talos-code 0.0.1 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +661 -0
- package/README.md +111 -3
- package/THIRD_PARTY_NOTICES.md +40 -0
- package/dist/archive/zip.js +73 -0
- package/dist/args.js +97 -0
- package/dist/automations/history-store.js +34 -0
- package/dist/automations/policy-store.js +43 -0
- package/dist/automations/runner.js +107 -0
- package/dist/automations/schedule.js +85 -0
- package/dist/automations/windows-task.js +53 -0
- package/dist/commands/advanced-cli.js +233 -0
- package/dist/commands/checkpoint-cli.js +45 -0
- package/dist/commands/config-cli.js +107 -0
- package/dist/commands/context.js +17 -0
- package/dist/commands/extensions-cli.js +207 -0
- package/dist/commands/project-cli.js +74 -0
- package/dist/commands/project-commands.js +143 -0
- package/dist/commands/provider-cli.js +185 -0
- package/dist/commands/services-cli.js +248 -0
- package/dist/commands/session-cli.js +171 -0
- package/dist/commands/system-cli.js +405 -0
- package/dist/config/commands.js +60 -0
- package/dist/config/load.js +382 -0
- package/dist/config/migrations.js +48 -0
- package/dist/config/types.js +11 -0
- package/dist/diagnostics/development-log.js +154 -0
- package/dist/diagnostics/doctor.js +104 -0
- package/dist/diagnostics/redact.js +80 -0
- package/dist/diagnostics/zip.js +52 -0
- package/dist/errors.js +156 -0
- package/dist/events/bridge.js +130 -0
- package/dist/extensions/installer.js +178 -0
- package/dist/extensions/package-schema.js +24 -0
- package/dist/headless/result.js +84 -0
- package/dist/headless/run.js +230 -0
- package/dist/i18n/en/approval.js +43 -0
- package/dist/i18n/en/common.js +9 -0
- package/dist/i18n/en/credentials.js +82 -0
- package/dist/i18n/en/errors.js +246 -0
- package/dist/i18n/en/firstrun.js +89 -0
- package/dist/i18n/en/providers.js +37 -0
- package/dist/i18n/en/screen.js +736 -0
- package/dist/i18n/en/tools.js +127 -0
- package/dist/i18n/en.js +14 -0
- package/dist/i18n/error-view.js +307 -0
- package/dist/i18n/index.js +19 -0
- package/dist/i18n/kernel-map.js +139 -0
- package/dist/io.js +45 -0
- package/dist/main.js +330 -0
- package/dist/paths.js +41 -0
- package/dist/protocol/v2/codec.js +9 -0
- package/dist/protocol/v2/events.js +555 -0
- package/dist/protocol/v2/index.js +4 -0
- package/dist/protocol/v2/replay.js +28 -0
- package/dist/protocol/v2/types.js +1 -0
- package/dist/provider/control-plane.js +135 -0
- package/dist/provider/environment-keys.js +275 -0
- package/dist/provider/health.js +110 -0
- package/dist/provider/missing-key.js +48 -0
- package/dist/provider/model-catalog.js +168 -0
- package/dist/provider/provider-text.js +13 -0
- package/dist/provider/store.js +95 -0
- package/dist/provider/system-keyring.js +214 -0
- package/dist/runtime/active-run.js +63 -0
- package/dist/runtime/agent-tree.js +74 -0
- package/dist/runtime/attachments.js +84 -0
- package/dist/runtime/brokered-executor.js +395 -0
- package/dist/runtime/context-status.js +76 -0
- package/dist/runtime/create-runtime.js +111 -0
- package/dist/runtime/model-profile.js +361 -0
- package/dist/runtime/output-store.js +137 -0
- package/dist/runtime/provider-attempts.js +185 -0
- package/dist/runtime/replay-buffer.js +153 -0
- package/dist/runtime/repo.js +95 -0
- package/dist/runtime/session-facade.js +135 -0
- package/dist/runtime/session-summary.js +125 -0
- package/dist/runtime/supervisor.js +262 -0
- package/dist/runtime/talos-composition.js +1006 -0
- package/dist/runtime/types.js +5 -0
- package/dist/runtime/usage-snapshot.js +82 -0
- package/dist/security/auto-classifier.js +38 -0
- package/dist/security/credential-free-environment.js +54 -0
- package/dist/security/evaluate.js +243 -0
- package/dist/security/execution-backends.js +236 -0
- package/dist/security/execution-broker.js +102 -0
- package/dist/security/forge-scan.js +74 -0
- package/dist/security/from-approval.js +39 -0
- package/dist/security/mxc-execution-backend.js +281 -0
- package/dist/security/permission-engine.js +138 -0
- package/dist/security/permission-explanation.js +54 -0
- package/dist/security/persist.js +179 -0
- package/dist/security/plugin-guard.js +230 -0
- package/dist/security/process-tree-evidence-store.js +74 -0
- package/dist/security/process-tree-probe.js +554 -0
- package/dist/security/project-resource-inventory.js +186 -0
- package/dist/security/project-trust-gate.js +38 -0
- package/dist/security/project-trust.js +367 -0
- package/dist/security/rule-parser.js +201 -0
- package/dist/security/shell-segmentation.js +68 -0
- package/dist/security/trust-authority.js +324 -0
- package/dist/security/types.js +1 -0
- package/dist/security/workspace-identity.js +102 -0
- package/dist/services/automation-facade.js +59 -0
- package/dist/services/forge-facade.js +77 -0
- package/dist/services/hook-facade.js +240 -0
- package/dist/services/index.js +16 -0
- package/dist/services/library-facade.js +174 -0
- package/dist/services/mcp-facade.js +348 -0
- package/dist/services/memory-facade.js +126 -0
- package/dist/services/notes-facade.js +157 -0
- package/dist/services/plugin-facade.js +308 -0
- package/dist/services/research-facade.js +110 -0
- package/dist/services/task-board-facade.js +236 -0
- package/dist/services/workflow-catalog.js +246 -0
- package/dist/sessions/export-format.js +98 -0
- package/dist/sessions/metadata-store.js +160 -0
- package/dist/sessions/share.js +122 -0
- package/dist/sessions/transfer.js +16 -0
- package/dist/subcommands.js +62 -0
- package/dist/tui/agent-roster.js +36 -0
- package/dist/tui/app.js +3761 -0
- package/dist/tui/approval.js +36 -0
- package/dist/tui/boot/boot-sequence.js +76 -0
- package/dist/tui/boot/cinematic.js +243 -0
- package/dist/tui/boot/desktop-logo.js +82 -0
- package/dist/tui/boot.js +3 -0
- package/dist/tui/busy-input.js +58 -0
- package/dist/tui/catalog-service.js +559 -0
- package/dist/tui/components/assistant-stream.js +1 -0
- package/dist/tui/components/command-menu.js +68 -0
- package/dist/tui/components/composer.js +219 -0
- package/dist/tui/components/diff.js +35 -0
- package/dist/tui/components/footer.js +48 -0
- package/dist/tui/components/header.js +6 -0
- package/dist/tui/components/markdown.js +305 -0
- package/dist/tui/components/status-indicator.js +32 -0
- package/dist/tui/components/terminal-shell.js +205 -0
- package/dist/tui/components/thinking-row.js +19 -0
- package/dist/tui/components/tool-row.js +97 -0
- package/dist/tui/components/transcript-virtualizer.js +165 -0
- package/dist/tui/components/transcript.js +43 -0
- package/dist/tui/diff-model.js +77 -0
- package/dist/tui/editor-history.js +21 -0
- package/dist/tui/editor.js +210 -0
- package/dist/tui/event-adapter.js +436 -0
- package/dist/tui/exit-output.js +58 -0
- package/dist/tui/external-editor.js +53 -0
- package/dist/tui/file-completion.js +89 -0
- package/dist/tui/focus-manager.js +5 -0
- package/dist/tui/highlight.js +30 -0
- package/dist/tui/input-router.js +18 -0
- package/dist/tui/interrupt.js +99 -0
- package/dist/tui/keybindings.js +194 -0
- package/dist/tui/keymap-resolver.js +91 -0
- package/dist/tui/launch-state.js +139 -0
- package/dist/tui/line-diff.js +57 -0
- package/dist/tui/live-activity.js +45 -0
- package/dist/tui/metrics.js +123 -0
- package/dist/tui/onboarding.js +36 -0
- package/dist/tui/overlays/agent-tree.js +39 -0
- package/dist/tui/overlays/approval-dialog.js +640 -0
- package/dist/tui/overlays/automation-center.js +51 -0
- package/dist/tui/overlays/checkpoint-picker.js +47 -0
- package/dist/tui/overlays/context-inspector.js +36 -0
- package/dist/tui/overlays/effort-line.js +110 -0
- package/dist/tui/overlays/forge-center.js +46 -0
- package/dist/tui/overlays/help-dialog.js +16 -0
- package/dist/tui/overlays/history-picker.js +37 -0
- package/dist/tui/overlays/hook-center.js +70 -0
- package/dist/tui/overlays/library-center.js +55 -0
- package/dist/tui/overlays/mcp-center.js +60 -0
- package/dist/tui/overlays/memory-center.js +63 -0
- package/dist/tui/overlays/model-picker.js +72 -0
- package/dist/tui/overlays/notes-center.js +53 -0
- package/dist/tui/overlays/overlay-host.js +8 -0
- package/dist/tui/overlays/plugin-center.js +76 -0
- package/dist/tui/overlays/provider-picker.js +145 -0
- package/dist/tui/overlays/queue-editor.js +32 -0
- package/dist/tui/overlays/research-center.js +59 -0
- package/dist/tui/overlays/scroll-window.js +234 -0
- package/dist/tui/overlays/session-picker.js +115 -0
- package/dist/tui/overlays/tasks-center.js +83 -0
- package/dist/tui/overlays/theme-picker.js +21 -0
- package/dist/tui/overlays/transcript-search.js +58 -0
- package/dist/tui/overlays/trust-center.js +29 -0
- package/dist/tui/overlays/workflow-center.js +46 -0
- package/dist/tui/project-file-index.js +214 -0
- package/dist/tui/project-references.js +85 -0
- package/dist/tui/project-trust-prompt.js +287 -0
- package/dist/tui/prompt-history-store.js +116 -0
- package/dist/tui/queue-store.js +110 -0
- package/dist/tui/regions/budget.js +59 -0
- package/dist/tui/regions/views.js +96 -0
- package/dist/tui/render-coordinator.js +148 -0
- package/dist/tui/render-scheduler.js +4 -0
- package/dist/tui/run.js +69 -0
- package/dist/tui/selection-list.js +29 -0
- package/dist/tui/session-controller.js +778 -0
- package/dist/tui/session-export.js +54 -0
- package/dist/tui/shell-input.js +35 -0
- package/dist/tui/shell-layout.js +48 -0
- package/dist/tui/shell-model.js +98 -0
- package/dist/tui/slash-commands.js +80 -0
- package/dist/tui/state.js +151 -0
- package/dist/tui/status-bar.js +125 -0
- package/dist/tui/status-view.js +40 -0
- package/dist/tui/terminal-capabilities.js +9 -0
- package/dist/tui/terminal-session.js +11 -0
- package/dist/tui/text-width.js +66 -0
- package/dist/tui/theme-catalog.js +25 -0
- package/dist/tui/theme-store.js +23 -0
- package/dist/tui/theme.js +23 -0
- package/dist/tui/tool-display.js +135 -0
- package/dist/tui/tool-facts.js +1 -0
- package/dist/tui/tools/bash-renderer.js +32 -0
- package/dist/tui/tools/change.js +61 -0
- package/dist/tui/tools/edit-renderer.js +17 -0
- package/dist/tui/tools/generic-renderer.js +13 -0
- package/dist/tui/tools/list-renderer.js +14 -0
- package/dist/tui/tools/read-renderer.js +13 -0
- package/dist/tui/tools/registry.js +20 -0
- package/dist/tui/tools/row-format.js +187 -0
- package/dist/tui/tools/search-renderer.js +38 -0
- package/dist/tui/tools/shared.js +97 -0
- package/dist/tui/tools/write-renderer.js +15 -0
- package/dist/tui/transcript-model.js +441 -0
- package/dist/tui/ui-preferences.js +79 -0
- package/dist/tui/usage-view.js +77 -0
- package/dist/tui/vim-mode.js +99 -0
- package/dist/update/check.js +15 -0
- package/dist/update/npm.js +51 -0
- package/dist/update/run.js +129 -0
- package/dist/version.js +2 -0
- package/dist/workspace/checkpoint-store.js +210 -0
- package/dist/workspace/checkpoint.js +413 -0
- package/dist/workspace/restore.js +232 -0
- package/package.json +63 -5
- package/vendor/context-engine/package.json +11 -0
- package/vendor/context-engine/src/compaction-planner.mjs +57 -0
- package/vendor/context-engine/src/contracts.mjs +48 -0
- package/vendor/context-engine/src/engine.mjs +445 -0
- package/vendor/context-engine/src/node/context-export.mjs +164 -0
- package/vendor/context-engine/src/node/legacy-import.mjs +92 -0
- package/vendor/context-engine/src/node/migrations/001-context.sql +126 -0
- package/vendor/context-engine/src/node/sqlite-store.mjs +85 -0
- package/vendor/context-engine/src/node/sqlite-worker.mjs +559 -0
- package/vendor/context-engine/src/profiles.mjs +10 -0
- package/vendor/context-engine/src/retrieval.mjs +104 -0
- package/vendor/context-engine/src/summary.mjs +97 -0
- package/vendor/context-engine/src/usage.mjs +34 -0
- package/vendor/harness-ui/package.json +38 -0
- package/vendor/harness-ui/src/acp-agent.mjs +350 -0
- package/vendor/harness-ui/src/agent-service.mjs +2188 -0
- package/vendor/harness-ui/src/agui-events.mjs +452 -0
- package/vendor/harness-ui/src/ambiente-solo-server.mjs +121 -0
- package/vendor/harness-ui/src/artifact-store.mjs +39 -0
- package/vendor/harness-ui/src/assistenza.mjs +123 -0
- package/vendor/harness-ui/src/automation-scheduler.mjs +69 -0
- package/vendor/harness-ui/src/automation-store.mjs +145 -0
- package/vendor/harness-ui/src/browser-annota.mjs +639 -0
- package/vendor/harness-ui/src/browser-frame.mjs +211 -0
- package/vendor/harness-ui/src/browser-proxy-universale.mjs +519 -0
- package/vendor/harness-ui/src/browser-proxy.mjs +87 -0
- package/vendor/harness-ui/src/browser-sessione-viva.mjs +329 -0
- package/vendor/harness-ui/src/browser-stream.mjs +445 -0
- package/vendor/harness-ui/src/browser-vivo.mjs +694 -0
- package/vendor/harness-ui/src/chat-image-attachments.mjs +72 -0
- package/vendor/harness-ui/src/config.mjs +697 -0
- package/vendor/harness-ui/src/contesto-del-progetto.mjs +385 -0
- package/vendor/harness-ui/src/context-asset-adapter.mjs +72 -0
- package/vendor/harness-ui/src/context-desktop-service.mjs +253 -0
- package/vendor/harness-ui/src/context-embedding-runtime.mjs +252 -0
- package/vendor/harness-ui/src/context-inference-scheduler.mjs +81 -0
- package/vendor/harness-ui/src/context-native-compaction.mjs +75 -0
- package/vendor/harness-ui/src/context-provider-adapter.mjs +141 -0
- package/vendor/harness-ui/src/context-runtime.mjs +118 -0
- package/vendor/harness-ui/src/context-token-counters.mjs +184 -0
- package/vendor/harness-ui/src/context-tool-catalog.mjs +86 -0
- package/vendor/harness-ui/src/context-tool-output.mjs +72 -0
- package/vendor/harness-ui/src/costo-elenco.mjs +252 -0
- package/vendor/harness-ui/src/custom-task.mjs +171 -0
- package/vendor/harness-ui/src/doctor.mjs +142 -0
- package/vendor/harness-ui/src/document-filename.mjs +97 -0
- package/vendor/harness-ui/src/document-generator.mjs +493 -0
- package/vendor/harness-ui/src/document-report.mjs +331 -0
- package/vendor/harness-ui/src/duckduckgo-search.mjs +155 -0
- package/vendor/harness-ui/src/elenco-profondo.mjs +337 -0
- package/vendor/harness-ui/src/favicon-proxy.mjs +113 -0
- package/vendor/harness-ui/src/forge-contract.mjs +221 -0
- package/vendor/harness-ui/src/frequent-dirs.mjs +134 -0
- package/vendor/harness-ui/src/generated-image-store.mjs +147 -0
- package/vendor/harness-ui/src/generation-idle.mjs +332 -0
- package/vendor/harness-ui/src/gguf-header.mjs +207 -0
- package/vendor/harness-ui/src/git-service.mjs +626 -0
- package/vendor/harness-ui/src/gitignore-elenco.mjs +604 -0
- package/vendor/harness-ui/src/harness-receipt-keypair.mjs +207 -0
- package/vendor/harness-ui/src/hf-direct-transfer.mjs +170 -0
- package/vendor/harness-ui/src/hf-hub-client.mjs +106 -0
- package/vendor/harness-ui/src/hf-image-proxy.mjs +105 -0
- package/vendor/harness-ui/src/hf-model-transfer.mjs +245 -0
- package/vendor/harness-ui/src/hook-registry.mjs +186 -0
- package/vendor/harness-ui/src/http-app.mjs +6259 -0
- package/vendor/harness-ui/src/http-lifecycle.mjs +132 -0
- package/vendor/harness-ui/src/id-archivio.mjs +27 -0
- package/vendor/harness-ui/src/image-generator.mjs +143 -0
- package/vendor/harness-ui/src/istruzioni-di-progetto.mjs +234 -0
- package/vendor/harness-ui/src/kernel/dist/kernelPerIlBanco.js +518 -0
- package/vendor/harness-ui/src/kernel/talosHarness.mjs +10437 -0
- package/vendor/harness-ui/src/library-policy-store.mjs +175 -0
- package/vendor/harness-ui/src/library-store.mjs +652 -0
- package/vendor/harness-ui/src/llama-server-supervisor.mjs +629 -0
- package/vendor/harness-ui/src/local-model-store.mjs +339 -0
- package/vendor/harness-ui/src/local-runtime-contract.mjs +66 -0
- package/vendor/harness-ui/src/local-runtime-events.mjs +44 -0
- package/vendor/harness-ui/src/local-runtime-llama-server.mjs +244 -0
- package/vendor/harness-ui/src/local-runtime-probe.mjs +401 -0
- package/vendor/harness-ui/src/machine-capacity.mjs +66 -0
- package/vendor/harness-ui/src/mappa-cartelle.mjs +491 -0
- package/vendor/harness-ui/src/mcp-client.mjs +98 -0
- package/vendor/harness-ui/src/mcp-registry.mjs +157 -0
- package/vendor/harness-ui/src/mcp-session.mjs +177 -0
- package/vendor/harness-ui/src/memory-store.mjs +227 -0
- package/vendor/harness-ui/src/model-catalog-models-dev.mjs +276 -0
- package/vendor/harness-ui/src/model-catalog.mjs +129 -0
- package/vendor/harness-ui/src/model-destination.mjs +189 -0
- package/vendor/harness-ui/src/modifica-ancorata.mjs +177 -0
- package/vendor/harness-ui/src/native-provider-adapter.mjs +205 -0
- package/vendor/harness-ui/src/notes-store.mjs +250 -0
- package/vendor/harness-ui/src/openai-compatible-runtime.mjs +428 -0
- package/vendor/harness-ui/src/openrouter-oauth.mjs +339 -0
- package/vendor/harness-ui/src/path-policy.mjs +442 -0
- package/vendor/harness-ui/src/plugin-registry.mjs +780 -0
- package/vendor/harness-ui/src/plugin-session.mjs +180 -0
- package/vendor/harness-ui/src/process-policy.mjs +345 -0
- package/vendor/harness-ui/src/prompt-enhancer-provider.mjs +94 -0
- package/vendor/harness-ui/src/provider-auth-cloud.mjs +95 -0
- package/vendor/harness-ui/src/provider-credential-store.mjs +541 -0
- package/vendor/harness-ui/src/provider-probe.mjs +582 -0
- package/vendor/harness-ui/src/provider-registry.mjs +1633 -0
- package/vendor/harness-ui/src/pty-terminal.mjs +312 -0
- package/vendor/harness-ui/src/public-problem.mjs +109 -0
- package/vendor/harness-ui/src/research/card.mjs +235 -0
- package/vendor/harness-ui/src/research/citations.mjs +142 -0
- package/vendor/harness-ui/src/research/collector.mjs +275 -0
- package/vendor/harness-ui/src/research/deposito-a-pezzi.mjs +139 -0
- package/vendor/harness-ui/src/research/dossier.mjs +114 -0
- package/vendor/harness-ui/src/research/esportazioni.mjs +560 -0
- package/vendor/harness-ui/src/research/fetch-cache.mjs +465 -0
- package/vendor/harness-ui/src/research/fidelity.mjs +122 -0
- package/vendor/harness-ui/src/research/independence.mjs +159 -0
- package/vendor/harness-ui/src/research/ledger.mjs +166 -0
- package/vendor/harness-ui/src/research/markdown-server.mjs +565 -0
- package/vendor/harness-ui/src/research/narration.mjs +181 -0
- package/vendor/harness-ui/src/research/open-cards.mjs +131 -0
- package/vendor/harness-ui/src/research/opposing.mjs +305 -0
- package/vendor/harness-ui/src/research/outline.mjs +111 -0
- package/vendor/harness-ui/src/research/page-budget.mjs +209 -0
- package/vendor/harness-ui/src/research/pdf.mjs +291 -0
- package/vendor/harness-ui/src/research/plan.mjs +301 -0
- package/vendor/harness-ui/src/research/raccolta-viva.mjs +452 -0
- package/vendor/harness-ui/src/research/recheck-document.mjs +69 -0
- package/vendor/harness-ui/src/research/recheck-history.mjs +192 -0
- package/vendor/harness-ui/src/research/recheck.mjs +194 -0
- package/vendor/harness-ui/src/research/report.mjs +203 -0
- package/vendor/harness-ui/src/research/run.mjs +527 -0
- package/vendor/harness-ui/src/research/synthesis.mjs +318 -0
- package/vendor/harness-ui/src/research/verification.mjs +572 -0
- package/vendor/harness-ui/src/research-orchestrator.mjs +2679 -0
- package/vendor/harness-ui/src/research-store.mjs +1133 -0
- package/vendor/harness-ui/src/runtime-build-manifest.mjs +26 -0
- package/vendor/harness-ui/src/runtime-contract.mjs +59 -0
- package/vendor/harness-ui/src/runtime-owner-adapter.mjs +1348 -0
- package/vendor/harness-ui/src/runtime-owner-contract.mjs +32 -0
- package/vendor/harness-ui/src/scheda-di-lavoro.mjs +249 -0
- package/vendor/harness-ui/src/search-source-store.mjs +172 -0
- package/vendor/harness-ui/src/session-registry.mjs +6095 -0
- package/vendor/harness-ui/src/session-store.mjs +220 -0
- package/vendor/harness-ui/src/sessione-pronta.mjs +73 -0
- package/vendor/harness-ui/src/setup-stato.mjs +31 -0
- package/vendor/harness-ui/src/sezioni-istruzioni.mjs +204 -0
- package/vendor/harness-ui/src/skill-registry.mjs +120 -0
- package/vendor/harness-ui/src/sse-replay-coalescente.mjs +0 -0
- package/vendor/harness-ui/src/static-files.mjs +96 -0
- package/vendor/harness-ui/src/stream-partition.mjs +123 -0
- package/vendor/harness-ui/src/subagent-orchestrator.mjs +453 -0
- package/vendor/harness-ui/src/task-catalog.mjs +65 -0
- package/vendor/harness-ui/src/tasks-store.mjs +220 -0
- package/vendor/harness-ui/src/terminal-registry.mjs +312 -0
- package/vendor/harness-ui/src/terminal-ws.mjs +170 -0
- package/vendor/harness-ui/src/tool-forge-store.mjs +299 -0
- package/vendor/harness-ui/src/tool-schema-normalize.mjs +100 -0
- package/vendor/harness-ui/src/usage-cache.mjs +315 -0
- package/vendor/harness-ui/src/workspace-browser.mjs +213 -0
- package/vendor/harness-ui/src/workspace-context.mjs +124 -0
- package/vendor/harness-ui/src/workspace-disk.mjs +62 -0
- package/vendor/harness-ui/src/workspace-files.mjs +589 -0
- package/vendor/harness-ui/src/workspace-info.mjs +189 -0
- package/vendor/harness-ui/src/workspace-launch-store.mjs +150 -0
- package/vendor/harness-ui/src/workspace-tree.mjs +67 -0
- package/vendor/harness-ui/src/workspace-watcher.mjs +161 -0
- package/vendor/manifest.json +170 -0
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/* R5a (Q-R5-17, gate finding 15): `beforeDeny` hears the engine's own refusal before the kernel is answered, so whoever shows
|
|
2
|
+
the row can say who refused before the kernel's receipt of the "no" arrives. */
|
|
3
|
+
export function createApprovalCoordinator({ engine, answer, interactive, mode, beforeDeny }) { const pending = new Map(); return { async request(sessionId, talosRequestId, action) { const currentMode = typeof mode === 'function' ? mode() : mode; const d = await engine.decide(action, { interactive, mode: currentMode }); if (d.kind === 'allow') {
|
|
4
|
+
await answer(sessionId, talosRequestId, true);
|
|
5
|
+
return { pending: false, allowed: true, source: d.source };
|
|
6
|
+
} if (d.kind === 'deny') {
|
|
7
|
+
try {
|
|
8
|
+
beforeDeny?.(talosRequestId, { code: d.code, message: d.message });
|
|
9
|
+
}
|
|
10
|
+
catch { /* a listener never changes the answer */ }
|
|
11
|
+
await answer(sessionId, talosRequestId, false);
|
|
12
|
+
return { pending: false, allowed: false, code: d.code, message: d.message };
|
|
13
|
+
} pending.set(talosRequestId, { engineId: d.requestId, sessionId }); return { pending: true, allowed: false, action: d.action, reason: d.reason, ...(d.rule ? { rule: d.rule } : {}) }; }, async resolve(talosRequestId, choice) { const p = pending.get(talosRequestId); if (!p)
|
|
14
|
+
throw new Error('APPROVAL_NOT_PENDING'); pending.delete(talosRequestId); await engine.resolve(p.engineId, choice); await answer(p.sessionId, talosRequestId, choice.startsWith('allow-')); } }; }
|
|
15
|
+
/*
|
|
16
|
+
* R3 gate E4, owner decision Q-R3-3: why a tool was allowed to run. The engine's allow `source` (permission-engine.ts:38-42)
|
|
17
|
+
* names it: a session grant, an allow rule (its text), accept-edits, bypassPermissions (Full access), the auto classifier.
|
|
18
|
+
* `rule` without a text is the built-in allowance for reads inside the project and documented read-only commands: no
|
|
19
|
+
* approval was involved, so nothing is said. The person's answer names the rest; a denied tool did not run.
|
|
20
|
+
*/
|
|
21
|
+
export function decisionFromSource(source) {
|
|
22
|
+
if (source === 'session')
|
|
23
|
+
return { kind: 'session' };
|
|
24
|
+
if (source === 'acceptEdits')
|
|
25
|
+
return { kind: 'accept-edits' };
|
|
26
|
+
if (source === 'bypassPermissions')
|
|
27
|
+
return { kind: 'full-access' };
|
|
28
|
+
if (source === 'auto')
|
|
29
|
+
return { kind: 'auto' };
|
|
30
|
+
if (source === 'rule' || !source)
|
|
31
|
+
return null;
|
|
32
|
+
return { kind: 'rule', rule: source };
|
|
33
|
+
}
|
|
34
|
+
export function decisionFromChoice(choice) {
|
|
35
|
+
return choice === 'allow-once' ? { kind: 'once' } : choice === 'allow-session' ? { kind: 'session' } : choice === 'allow-always' ? { kind: 'always' } : null;
|
|
36
|
+
}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { t } from "../../i18n/index.js";
|
|
2
|
+
import { DESKTOP_LOGO_SOURCE, TALOS_ASCII_FRAMES } from "./desktop-logo.js";
|
|
3
|
+
import { renderCinematicBoot, rowsToSegments, TALOS_BOOT_DURATION_MS, TALOS_GOLD_PALETTE } from "./cinematic.js";
|
|
4
|
+
/*
|
|
5
|
+
* R4 Q-R4-4 (owner, 2026-09-24): how long the boot holds the screen when nobody presses a key.
|
|
6
|
+
* - full, with motion: the whole cinematic reveal (7.2 s), on the first launch and after an update only;
|
|
7
|
+
* - full, without motion (reduced motion, or no colour and so no logo): a static frame for at most 1 s — before R4 these
|
|
8
|
+
* terminals waited the whole 7.2 s for an animation they never showed (measured 8,440 ms and 8,600 ms to the composer);
|
|
9
|
+
* - short (every other launch): the final frame for at most 600 ms.
|
|
10
|
+
* The sequence that draws the boot owns this length: it signals the end with `onComplete`, and the state functions below
|
|
11
|
+
* follow that signal instead of re-reading the 7.2 s constant, so lane N passes only `mode` (the R4 contract).
|
|
12
|
+
*/
|
|
13
|
+
export const SHORT_BOOT_MS = 600;
|
|
14
|
+
export const STATIC_BOOT_MS = 1000;
|
|
15
|
+
export function bootRevealMs({ mode, motion }) { return mode === 'short' ? SHORT_BOOT_MS : motion ? TALOS_BOOT_DURATION_MS : STATIC_BOOT_MS; }
|
|
16
|
+
export function createBootState(startedAt) { return { phase: 'revealing', startedAt, skipped: false, runtimeReady: false }; }
|
|
17
|
+
/* R4: a runtime that becomes ready after the reveal ended (`waiting`, whatever its length) opens the composer at once. */
|
|
18
|
+
export function markBootReady(state, now) { if (state.phase === 'error')
|
|
19
|
+
return state; const elapsed = Math.max(0, now - state.startedAt); const ready = state.skipped || state.phase === 'waiting' || elapsed >= TALOS_BOOT_DURATION_MS; return { ...state, runtimeReady: true, phase: ready ? 'ready' : state.phase }; }
|
|
20
|
+
export function markBootError(state) { return { ...state, phase: 'error' }; }
|
|
21
|
+
export function skipBoot(state) { return { ...state, skipped: true, phase: state.runtimeReady ? 'ready' : state.phase }; }
|
|
22
|
+
/* R4: `completeBoot` is the sequence's own signal that its reveal is over (BootSequence calls it only when its clock says so,
|
|
23
|
+
re-reading Date.now(), B1 slice 20); the reveal can be 600 ms, 1 s or 7.2 s, so the 7.2 s constant is no longer re-checked. */
|
|
24
|
+
export function completeBoot(state, _now) { if (state.phase === 'error' || state.phase === 'ready')
|
|
25
|
+
return state; return { ...state, phase: state.runtimeReady ? 'ready' : 'waiting' }; }
|
|
26
|
+
export function bootPhaseAt(state, now) { if (state.phase === 'ready' || state.phase === 'error' || state.phase === 'waiting')
|
|
27
|
+
return state.phase; const elapsed = Math.max(0, now - state.startedAt); if (state.runtimeReady && (state.skipped || elapsed >= TALOS_BOOT_DURATION_MS))
|
|
28
|
+
return 'ready'; if (state.skipped || elapsed >= TALOS_BOOT_DURATION_MS)
|
|
29
|
+
return 'waiting'; return 'revealing'; }
|
|
30
|
+
export function bootFrameAt(state, now, motion) { const last = TALOS_ASCII_FRAMES.length - 1; if (!motion || state.skipped || state.phase === 'ready' || state.phase === 'error')
|
|
31
|
+
return last; const elapsed = Math.max(0, now - state.startedAt); return Math.min(last, Math.floor(elapsed / TALOS_BOOT_DURATION_MS * Math.max(1, last))); }
|
|
32
|
+
export function bootLinesAt(state, now, { motion, unicode, width = 100 }) { const final = !motion || state.skipped || state.phase === 'ready' || state.phase === 'error'; return renderCinematicBoot(Math.max(0, now - state.startedAt), width, unicode, final).lines; }
|
|
33
|
+
export function shouldRenderBootLogo(capabilities) { return capabilities.interactive && capabilities.color; }
|
|
34
|
+
export function createBootSequenceComponent(React, Ink) {
|
|
35
|
+
// `logo:false` draws the plain "starting" line and keeps only the timer that ends the boot: without it, a terminal
|
|
36
|
+
// that gets no logo (no colour) had nothing to call `completeBoot`, and a runtime ready early waited for a key.
|
|
37
|
+
/* R4 CONTRACT (owner: lane F; lane N passes them from app.ts): `mode` from launch-state.ts bootPlan (Q-R4-4, full or
|
|
38
|
+
short), `hint` the skip line to draw (dictionary id firstrun.boot.skipHint).
|
|
39
|
+
R4 lane F: the hint defaults to the dictionary line, so the boot says a key skips it (s01 D-09) whether or not the caller
|
|
40
|
+
passes it; an empty string draws no hint. It takes the place of the dim stage label, which repeated the stage name the
|
|
41
|
+
frame already shows (`[SIGNAL ACQUISITION]` twice, gate §2.1). The short boot is the final frame without the counter. */
|
|
42
|
+
return function BootSequence({ state, logo = true, motion, unicode, width = 100, accentColor, mutedColor, onComplete, mode = 'full', hint = t('firstrun.boot.skipHint') }) {
|
|
43
|
+
const [now, setNow] = React.useState(() => Date.now());
|
|
44
|
+
// B1 slice 20: the animation stops with its last frame. Past the reveal every tick redrew an identical logo, 30
|
|
45
|
+
// times a second, for as long as the runtime kept the boot on screen — an idle render loop.
|
|
46
|
+
const animated = logo && motion && mode === 'full';
|
|
47
|
+
const revealMs = bootRevealMs({ mode, motion: animated });
|
|
48
|
+
React.useEffect(() => { if (!animated || state.phase === 'ready' || state.phase === 'error' || state.skipped)
|
|
49
|
+
return; const timer = setInterval(() => { const at = Date.now(); setNow(at); if (at - state.startedAt >= TALOS_BOOT_DURATION_MS)
|
|
50
|
+
clearInterval(timer); }, 33); return () => clearInterval(timer); }, [animated, state.startedAt, state.phase, state.skipped]);
|
|
51
|
+
/*
|
|
52
|
+
* B1 slice 20. The logo leaves when this timer says the reveal is over, so the timer must agree with the clock
|
|
53
|
+
* `completeBoot` reads. Node runs timers on its own loop clock and promises no exact timing: seen through
|
|
54
|
+
* Date.now() a 7,115 ms timer fired after 7,114, `completeBoot` found the reveal unfinished and returned the same
|
|
55
|
+
* state, React skipped the render, nothing re-armed, and the logo waited for a key. ⇒ Re-read Date.now() when
|
|
56
|
+
* the timer fires and re-arm for whatever is left.
|
|
57
|
+
* ⛔ Only while `revealing`: in `waiting` the end is already signalled, and signalling again made a new state
|
|
58
|
+
* object, a new `onComplete`, this effect again — a render loop for as long as the runtime was not ready.
|
|
59
|
+
*/
|
|
60
|
+
React.useEffect(() => { if (state.phase !== 'revealing' || state.skipped)
|
|
61
|
+
return; let timer; const settle = () => { timer = undefined; const remaining = revealMs - Math.max(0, Date.now() - state.startedAt); if (remaining > 0) {
|
|
62
|
+
timer = setTimeout(settle, remaining);
|
|
63
|
+
return;
|
|
64
|
+
} onComplete?.(); }; settle(); return () => { if (timer !== undefined)
|
|
65
|
+
clearTimeout(timer); }; }, [state.startedAt, state.phase, state.skipped, onComplete, revealMs]);
|
|
66
|
+
const phase = bootPhaseAt(state, now);
|
|
67
|
+
const label = phase === 'error' ? t('firstrun.boot.failed') : phase === 'waiting' ? t('firstrun.boot.waiting') : hint;
|
|
68
|
+
const labelText = label ? React.createElement(Ink.Text, { dimColor: true, color: mutedColor }, label) : null;
|
|
69
|
+
if (!logo)
|
|
70
|
+
return labelText ? React.createElement(Ink.Box, { flexDirection: 'column' }, React.createElement(Ink.Text, { color: accentColor }, 'starting'), labelText) : React.createElement(Ink.Text, { color: accentColor }, 'starting');
|
|
71
|
+
const final = !animated || state.skipped || state.phase === 'ready' || state.phase === 'error';
|
|
72
|
+
const frame = renderCinematicBoot(Math.max(0, now - state.startedAt), width, unicode, final, { counter: mode === 'full' });
|
|
73
|
+
const rows = rowsToSegments(frame);
|
|
74
|
+
return React.createElement(Ink.Box, { flexDirection: 'column' }, ...rows.map((segments, rowIndex) => React.createElement(Ink.Text, { key: rowIndex, color: accentColor }, ...segments.map((segment, index) => React.createElement(Ink.Text, { key: index, color: segment.level < 0 ? undefined : (TALOS_GOLD_PALETTE[segment.level] ?? accentColor) }, segment.text)))), ...(labelText ? [labelText] : []));
|
|
75
|
+
};
|
|
76
|
+
}
|
|
@@ -0,0 +1,243 @@
|
|
|
1
|
+
export const TALOS_GOLD_PALETTE = ['#604A12', '#9D7F24', '#D4AF37', '#F7D774', '#FFF4C2'];
|
|
2
|
+
export const TALOS_BOOT_DURATION_MS = 7200;
|
|
3
|
+
const LOGO_FULL = [
|
|
4
|
+
'████████╗ █████╗ ██╗ ██████╗ ███████╗',
|
|
5
|
+
'╚══██╔══╝██╔══██╗██║ ██╔═══██╗██╔════╝',
|
|
6
|
+
' ██║ ███████║██║ ██║ ██║███████╗',
|
|
7
|
+
' ██║ ██╔══██║██║ ██║ ██║╚════██║',
|
|
8
|
+
' ██║ ██║ ██║███████╗╚██████╔╝███████║',
|
|
9
|
+
' ╚═╝ ╚═╝ ╚═╝╚══════╝ ╚═════╝ ╚══════╝',
|
|
10
|
+
];
|
|
11
|
+
const LOGO_COMPACT = ['╔╦╗╔═╗╦ ╔═╗╔═╗', ' ║ ╠═╣║ ║ ║╚═╗', ' ╩ ╩ ╩╩═╝╚═╝╚═╝'];
|
|
12
|
+
const ASCII_MAP = {
|
|
13
|
+
'█': '#', '▓': '#', '▒': '+', '░': '.', '╔': '+', '╗': '+', '╚': '+', '╝': '+', '╦': '+', '╩': '+', '╠': '+', '╣': '+', '═': '-', '║': '|', '╲': '\\', '╱': '/', '◇': 'o', '◆': 'O', '◈': 'O', '●': 'o', '•': '.', '·': '.', '━': '=', '─': '-', '│': '|',
|
|
14
|
+
};
|
|
15
|
+
function clamp(value, min, max) { return Math.max(min, Math.min(max, value)); }
|
|
16
|
+
function easeOutCubic(t) { const v = clamp(t, 0, 1); return 1 - Math.pow(1 - v, 3); }
|
|
17
|
+
function easeInOutSine(t) { const v = clamp(t, 0, 1); return -(Math.cos(Math.PI * v) - 1) / 2; }
|
|
18
|
+
function triangleWave(t) { let x = t % 2; if (x < 0)
|
|
19
|
+
x += 2; return x <= 1 ? x : 2 - x; }
|
|
20
|
+
function layoutForWidth(terminalWidth) {
|
|
21
|
+
const tw = Math.max(32, Math.trunc(terminalWidth || 80));
|
|
22
|
+
const mode = tw < 48 ? 'micro' : tw < 72 ? 'compact' : tw < 100 ? 'medium' : 'full';
|
|
23
|
+
const width = Math.min(112, Math.max(30, tw - 2));
|
|
24
|
+
const height = mode === 'micro' ? 16 : mode === 'compact' ? 22 : mode === 'medium' ? 26 : 28;
|
|
25
|
+
const cx = Math.floor(width / 2);
|
|
26
|
+
const cy = Math.floor(Math.min(height - 8, height * 0.36));
|
|
27
|
+
return { mode, width, height, cx, cy };
|
|
28
|
+
}
|
|
29
|
+
function mulberry32(seed) { let a = seed >>> 0; return () => { a = (a + 0x6D2B79F5) >>> 0; let t = a; t = Math.imul(t ^ (t >>> 15), t | 1); t ^= t + Math.imul(t ^ (t >>> 7), t | 61); return ((t ^ (t >>> 14)) >>> 0) / 4294967296; }; }
|
|
30
|
+
const rand = mulberry32(1413565519);
|
|
31
|
+
const PARTICLES = Array.from({ length: 64 }, () => ({ x: rand(), y: rand(), vx: (rand() - .5) * .055, vy: (rand() - .5) * .035, phase: rand() * Math.PI * 2, tier: Math.floor(rand() * 3) }));
|
|
32
|
+
function newCanvas(layout) { return Array.from({ length: layout.height }, () => Array.from({ length: layout.width }, () => ({ char: ' ', level: -1 }))); }
|
|
33
|
+
function setCell(canvas, layout, x, y, char, level = 2) { if (x < 0 || y < 0 || x >= layout.width || y >= layout.height)
|
|
34
|
+
return; const cell = canvas[y][x]; if (char === ' ' && cell.char !== ' ')
|
|
35
|
+
return; if (level >= cell.level) {
|
|
36
|
+
cell.char = char;
|
|
37
|
+
cell.level = level;
|
|
38
|
+
} }
|
|
39
|
+
function putText(canvas, layout, x, y, text, level = 2) { for (const [i, ch] of Array.from(text).entries())
|
|
40
|
+
setCell(canvas, layout, x + i, y, ch, level); }
|
|
41
|
+
function putCentered(canvas, layout, y, text, level = 2) { putText(canvas, layout, Math.floor((layout.width - Array.from(text).length) / 2), y, text, level); }
|
|
42
|
+
function drawPartialLine(canvas, layout, x0, y0, x1, y1, progress, char, level = 1) { const dx = x1 - x0, dy = y1 - y0, steps = Math.max(Math.abs(dx), Math.abs(dy)); if (steps <= 0) {
|
|
43
|
+
setCell(canvas, layout, x0, y0, char, level);
|
|
44
|
+
return;
|
|
45
|
+
} const count = Math.floor(steps * clamp(progress, 0, 1)); for (let s = 0; s <= count; s++) {
|
|
46
|
+
const t = s / steps;
|
|
47
|
+
setCell(canvas, layout, Math.round(x0 + dx * t), Math.round(y0 + dy * t), char, level);
|
|
48
|
+
} }
|
|
49
|
+
function stageInfo(elapsed) {
|
|
50
|
+
if (elapsed < 1)
|
|
51
|
+
return { name: 'SIGNAL ACQUISITION', progress: elapsed, id: 0 };
|
|
52
|
+
if (elapsed < 2.2)
|
|
53
|
+
return { name: 'NETWORK CONVERGENCE', progress: (elapsed - 1) / 1.2, id: 1 };
|
|
54
|
+
if (elapsed < 3.4)
|
|
55
|
+
return { name: 'CORE IGNITION', progress: (elapsed - 2.2) / 1.2, id: 2 };
|
|
56
|
+
if (elapsed < 4.6)
|
|
57
|
+
return { name: 'SYNCHRONIZATION BUS', progress: (elapsed - 3.4) / 1.2, id: 3 };
|
|
58
|
+
if (elapsed < 5.8)
|
|
59
|
+
return { name: 'TALOS ASSEMBLY', progress: (elapsed - 4.6) / 1.2, id: 4 };
|
|
60
|
+
if (elapsed < 6.7)
|
|
61
|
+
return { name: 'ENERGY SHIMMER', progress: (elapsed - 5.8) / .9, id: 5 };
|
|
62
|
+
return { name: 'SYSTEM ONLINE', progress: clamp((elapsed - 6.7) / .5, 0, 1), id: 6 };
|
|
63
|
+
}
|
|
64
|
+
function drawParticles(canvas, layout, elapsed, visibility) { if (layout.mode === 'micro')
|
|
65
|
+
return; const limit = layout.mode === 'compact' ? 26 : layout.mode === 'medium' ? 42 : 64; const glyphs = ['·', '•', '+']; for (let i = 0; i < limit; i++) {
|
|
66
|
+
const p = PARTICLES[i];
|
|
67
|
+
let nx = (p.x + p.vx * elapsed) % 1, ny = (p.y + p.vy * elapsed) % 1;
|
|
68
|
+
if (nx < 0)
|
|
69
|
+
nx += 1;
|
|
70
|
+
if (ny < 0)
|
|
71
|
+
ny += 1;
|
|
72
|
+
const pulse = .5 + .5 * Math.sin(elapsed * 2.4 + p.phase);
|
|
73
|
+
if (pulse > 1 - visibility) {
|
|
74
|
+
const x = 1 + Math.floor(nx * Math.max(1, layout.width - 2));
|
|
75
|
+
const y = 2 + Math.floor(ny * Math.max(1, layout.height - 6));
|
|
76
|
+
setCell(canvas, layout, x, y, glyphs[Math.min(glyphs.length - 1, p.tier)], p.tier);
|
|
77
|
+
}
|
|
78
|
+
} }
|
|
79
|
+
function drawNetwork(canvas, layout, progress) { if (layout.mode === 'micro')
|
|
80
|
+
return; const { width: w, height: h, cx, cy } = layout, p = easeOutCubic(progress); const points = [[2, 3], [w - 3, 3], [2, Math.max(5, cy - 1)], [w - 3, Math.max(5, cy - 1)], [4, Math.min(h - 6, cy + 5)], [w - 5, Math.min(h - 6, cy + 5)]]; if (layout.mode === 'full') {
|
|
81
|
+
points.push([Math.floor(w * .18), h - 6], [Math.floor(w * .82), h - 6]);
|
|
82
|
+
} for (const [x, y] of points) {
|
|
83
|
+
drawPartialLine(canvas, layout, x, y, cx, cy, p, '·', 0);
|
|
84
|
+
setCell(canvas, layout, x, y, '◇', 2);
|
|
85
|
+
} if (p > .45) {
|
|
86
|
+
const inner = (p - .45) / .55;
|
|
87
|
+
drawPartialLine(canvas, layout, cx - 18, cy, cx + 18, cy, inner, '─', 1);
|
|
88
|
+
drawPartialLine(canvas, layout, cx, cy - 6, cx, cy + 6, inner, '│', 1);
|
|
89
|
+
} }
|
|
90
|
+
function drawDiamond(canvas, layout, rx, ry, level) { const { cx, cy } = layout; drawPartialLine(canvas, layout, cx, cy - ry, cx + rx, cy, 1, '╲', level); drawPartialLine(canvas, layout, cx + rx, cy, cx, cy + ry, 1, '╱', level); drawPartialLine(canvas, layout, cx, cy + ry, cx - rx, cy, 1, '╲', level); drawPartialLine(canvas, layout, cx - rx, cy, cx, cy - ry, 1, '╱', level); }
|
|
91
|
+
function drawCore(canvas, layout, progress, elapsed) { const p = easeInOutSine(progress); const maxRx = layout.mode === 'full' ? 15 : layout.mode === 'medium' ? 12 : 8; const maxRy = layout.mode === 'full' ? 6 : layout.mode === 'medium' ? 5 : 4; const rx = Math.max(2, Math.round(maxRx * p)), ry = Math.max(1, Math.round(maxRy * p)); if (p > .05)
|
|
92
|
+
drawDiamond(canvas, layout, rx, ry, 2); if (p > .28)
|
|
93
|
+
drawDiamond(canvas, layout, Math.max(2, Math.floor(rx * .56)), Math.max(1, Math.floor(ry * .56)), 3); const pulse = .5 + .5 * Math.sin(elapsed * 8); setCell(canvas, layout, layout.cx, layout.cy, p < .33 ? '·' : p < .66 ? '◇' : pulse > .45 ? '◆' : '◈', 4); if (p > .55) {
|
|
94
|
+
setCell(canvas, layout, layout.cx - Math.floor(rx * .56), layout.cy, '●', 3);
|
|
95
|
+
setCell(canvas, layout, layout.cx + Math.floor(rx * .56), layout.cy, '●', 3);
|
|
96
|
+
setCell(canvas, layout, layout.cx, layout.cy - Math.floor(ry * .56), '●', 3);
|
|
97
|
+
setCell(canvas, layout, layout.cx, layout.cy + Math.floor(ry * .56), '●', 3);
|
|
98
|
+
} }
|
|
99
|
+
function drawScanner(canvas, layout, elapsed, visibility) { if (visibility <= 0)
|
|
100
|
+
return; const span = layout.mode === 'full' ? Math.min(44, layout.width - 10) : layout.mode === 'medium' ? Math.min(36, layout.width - 8) : Math.min(24, layout.width - 6); const left = layout.cx - Math.floor(span / 2), right = left + span - 1, head = left + Math.round((span - 1) * triangleWave(elapsed * .78 + .12)); for (let x = left; x <= right; x++) {
|
|
101
|
+
const dist = Math.abs(head - x);
|
|
102
|
+
if (dist === 0)
|
|
103
|
+
setCell(canvas, layout, x, layout.cy, '◆', 4);
|
|
104
|
+
else if (dist === 1)
|
|
105
|
+
setCell(canvas, layout, x, layout.cy, '━', 3);
|
|
106
|
+
else if (dist <= 3)
|
|
107
|
+
setCell(canvas, layout, x, layout.cy, '═', 2);
|
|
108
|
+
else if (dist <= 6)
|
|
109
|
+
setCell(canvas, layout, x, layout.cy, '─', 1);
|
|
110
|
+
else if ((x - left) % 3 === 0)
|
|
111
|
+
setCell(canvas, layout, x, layout.cy, '·', 0);
|
|
112
|
+
} }
|
|
113
|
+
function logoForMode(mode) { return mode === 'full' || mode === 'medium' ? LOGO_FULL : LOGO_COMPACT; }
|
|
114
|
+
function drawLogoReveal(canvas, layout, progress, final = false) { const logo = logoForMode(layout.mode), logoHeight = logo.length, logoWidth = Math.max(...logo.map(line => Array.from(line).length)); let startY = layout.mode === 'micro' ? Math.max(6, layout.height - logoHeight - 4) : Math.max(layout.cy + 7, layout.height - logoHeight - 4); if (startY + logoHeight >= layout.height)
|
|
115
|
+
startY = Math.max(2, layout.height - logoHeight - 3); const startX = Math.floor((layout.width - logoWidth) / 2), p = final ? 1 : easeOutCubic(progress), front = Math.round((logoWidth + 8) * p) - 4; for (let row = 0; row < logoHeight; row++) {
|
|
116
|
+
const chars = Array.from(logo[row]);
|
|
117
|
+
const localFront = front - Math.round(row * 1.35);
|
|
118
|
+
for (let col = 0; col < chars.length; col++) {
|
|
119
|
+
const ch = chars[col];
|
|
120
|
+
if (ch === ' ')
|
|
121
|
+
continue;
|
|
122
|
+
if (col <= localFront)
|
|
123
|
+
setCell(canvas, layout, startX + col, startY + row, ch, 2);
|
|
124
|
+
else if (col - localFront <= 2 && !final)
|
|
125
|
+
setCell(canvas, layout, startX + col, startY + row, (col + row) % 2 === 0 ? '▒' : '░', (col + row) % 2 === 0 ? 1 : 0);
|
|
126
|
+
}
|
|
127
|
+
} return { x: startX, y: startY, width: logoWidth, height: logoHeight }; }
|
|
128
|
+
function applyShimmer(canvas, layout, bounds, elapsed, final) { const shimmerX = final ? bounds.x + Math.floor(bounds.width * .58) : bounds.x - 7 + Math.round((bounds.width + 14) * clamp((elapsed - 5.8) / .9, 0, 1)); for (let y = bounds.y; y < bounds.y + bounds.height; y++) {
|
|
129
|
+
for (let x = bounds.x; x < bounds.x + bounds.width; x++) {
|
|
130
|
+
const cell = canvas[y]?.[x];
|
|
131
|
+
if (!cell || cell.char === ' ')
|
|
132
|
+
continue;
|
|
133
|
+
const d = Math.abs(x - shimmerX);
|
|
134
|
+
if (d <= 1)
|
|
135
|
+
cell.level = 4;
|
|
136
|
+
else if (d <= 3)
|
|
137
|
+
cell.level = Math.max(cell.level, 3);
|
|
138
|
+
else if (d <= 6)
|
|
139
|
+
cell.level = Math.max(cell.level, 2);
|
|
140
|
+
}
|
|
141
|
+
} }
|
|
142
|
+
function toAscii(char) { return ASCII_MAP[char] ?? (/[\x00-\x7F]/u.test(char) ? char : '#'); }
|
|
143
|
+
function canvasToFrame(canvas, layout, stage, unicode) { const lines = [], levels = []; for (const row of canvas) {
|
|
144
|
+
const chars = [], ls = [];
|
|
145
|
+
for (const cell of row) {
|
|
146
|
+
chars.push(unicode ? cell.char : toAscii(cell.char));
|
|
147
|
+
ls.push(cell.level);
|
|
148
|
+
}
|
|
149
|
+
lines.push(chars.join('').replace(/\s+$/u, ''));
|
|
150
|
+
levels.push(ls);
|
|
151
|
+
} return { lines, levels, stage: stage.name, mode: layout.mode }; }
|
|
152
|
+
/* R4 Q-R4-4: the short boot is the final frame without the `BOOT nnn%` counter (`counter:false`): a counter that says 100% on
|
|
153
|
+
every launch is a progress bar with nothing in progress, and s09 recognises a replayed full boot by it. */
|
|
154
|
+
export function renderCinematicBoot(elapsedMs, terminalWidth, unicode = true, final = false, { counter = true } = {}) {
|
|
155
|
+
const layout = layoutForWidth(terminalWidth);
|
|
156
|
+
const elapsed = final ? TALOS_BOOT_DURATION_MS / 1000 : clamp(elapsedMs / 1000, 0, TALOS_BOOT_DURATION_MS / 1000);
|
|
157
|
+
const geometryElapsed = Math.floor(elapsed * 15) / 15, particleElapsed = Math.floor(elapsed * 12) / 12;
|
|
158
|
+
let stage = stageInfo(geometryElapsed);
|
|
159
|
+
let canvas = newCanvas(layout);
|
|
160
|
+
let logoBounds;
|
|
161
|
+
if (layout.mode !== 'micro') {
|
|
162
|
+
putText(canvas, layout, 2, 0, 'TALOS // AUTONOMOUS TERMINAL', 2);
|
|
163
|
+
if (counter) {
|
|
164
|
+
const right = `BOOT ${String(Math.min(100, Math.floor(elapsed / 7.2 * 100))).padStart(3, '0')}%`;
|
|
165
|
+
putText(canvas, layout, Math.max(2, layout.width - Array.from(right).length - 2), 0, right, 2);
|
|
166
|
+
}
|
|
167
|
+
for (let x = 2; x < layout.width - 2; x++)
|
|
168
|
+
if (x % 7 !== 0)
|
|
169
|
+
setCell(canvas, layout, x, 1, '─', 0);
|
|
170
|
+
}
|
|
171
|
+
if (stage.id === 0)
|
|
172
|
+
drawParticles(canvas, layout, particleElapsed, .25 + .75 * stage.progress);
|
|
173
|
+
else if (stage.id === 1) {
|
|
174
|
+
drawParticles(canvas, layout, particleElapsed, 1 - .35 * stage.progress);
|
|
175
|
+
drawNetwork(canvas, layout, stage.progress);
|
|
176
|
+
}
|
|
177
|
+
else if (stage.id === 2) {
|
|
178
|
+
drawParticles(canvas, layout, particleElapsed, .45);
|
|
179
|
+
drawNetwork(canvas, layout, 1);
|
|
180
|
+
drawCore(canvas, layout, stage.progress, geometryElapsed);
|
|
181
|
+
}
|
|
182
|
+
else if (stage.id === 3) {
|
|
183
|
+
drawParticles(canvas, layout, particleElapsed, .24);
|
|
184
|
+
drawNetwork(canvas, layout, 1);
|
|
185
|
+
drawCore(canvas, layout, 1, geometryElapsed);
|
|
186
|
+
drawScanner(canvas, layout, geometryElapsed, stage.progress);
|
|
187
|
+
}
|
|
188
|
+
else if (stage.id === 4) {
|
|
189
|
+
drawNetwork(canvas, layout, 1 - .45 * stage.progress);
|
|
190
|
+
drawCore(canvas, layout, 1, geometryElapsed);
|
|
191
|
+
drawScanner(canvas, layout, geometryElapsed, 1 - .35 * stage.progress);
|
|
192
|
+
logoBounds = drawLogoReveal(canvas, layout, stage.progress);
|
|
193
|
+
}
|
|
194
|
+
else {
|
|
195
|
+
drawCore(canvas, layout, 1, geometryElapsed);
|
|
196
|
+
logoBounds = drawLogoReveal(canvas, layout, 1, true);
|
|
197
|
+
}
|
|
198
|
+
if (final) {
|
|
199
|
+
stage = { name: 'SYSTEM ONLINE', progress: 1, id: 6 };
|
|
200
|
+
canvas = newCanvas(layout);
|
|
201
|
+
if (layout.mode !== 'micro') {
|
|
202
|
+
putText(canvas, layout, 2, 0, 'TALOS // AUTONOMOUS TERMINAL', 2);
|
|
203
|
+
if (counter)
|
|
204
|
+
putText(canvas, layout, Math.max(2, layout.width - 11), 0, 'BOOT 100%', 2);
|
|
205
|
+
for (let x = 2; x < layout.width - 2; x++)
|
|
206
|
+
if (x % 7 !== 0)
|
|
207
|
+
setCell(canvas, layout, x, 1, '─', 0);
|
|
208
|
+
}
|
|
209
|
+
drawCore(canvas, layout, 1, geometryElapsed);
|
|
210
|
+
logoBounds = drawLogoReveal(canvas, layout, 1, true);
|
|
211
|
+
}
|
|
212
|
+
if (logoBounds && (stage.id >= 5 || final))
|
|
213
|
+
applyShimmer(canvas, layout, logoBounds, elapsed, final);
|
|
214
|
+
const statusY = layout.height - 2;
|
|
215
|
+
if (layout.mode === 'micro')
|
|
216
|
+
putCentered(canvas, layout, statusY, '[ TALOS // READY ]', 3);
|
|
217
|
+
else {
|
|
218
|
+
putText(canvas, layout, 2, statusY, `[${stage.name}]`, stage.id >= 6 ? 3 : 2);
|
|
219
|
+
const right = stage.id >= 6 || final ? 'CORE ● BUS ● READY ●' : 'CORE ◇ BUS ◇ LINK ◇';
|
|
220
|
+
putText(canvas, layout, Math.max(2, layout.width - Array.from(right).length - 2), statusY, right, stage.id >= 6 ? 3 : 1);
|
|
221
|
+
}
|
|
222
|
+
if (stage.id >= 6) {
|
|
223
|
+
const pulse = .5 + .5 * Math.sin(elapsed * 4);
|
|
224
|
+
if (pulse > .72)
|
|
225
|
+
for (let y = layout.cy - 1; y <= layout.cy + 1; y++)
|
|
226
|
+
for (let x = layout.cx - 1; x <= layout.cx + 1; x++) {
|
|
227
|
+
const cell = canvas[y]?.[x];
|
|
228
|
+
if (cell && cell.char !== ' ')
|
|
229
|
+
cell.level = 4;
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
return canvasToFrame(canvas, layout, stage, unicode);
|
|
233
|
+
}
|
|
234
|
+
export function rowsToSegments(frame) {
|
|
235
|
+
return frame.lines.map((line, rowIndex) => { const chars = Array.from(line), levels = frame.levels[rowIndex] ?? []; const out = []; for (let i = 0; i < chars.length; i++) {
|
|
236
|
+
const level = levels[i] ?? -1;
|
|
237
|
+
const previous = out.at(-1);
|
|
238
|
+
if (previous && previous.level === level)
|
|
239
|
+
previous.text += chars[i];
|
|
240
|
+
else
|
|
241
|
+
out.push({ text: chars[i], level });
|
|
242
|
+
} return out; });
|
|
243
|
+
}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Source of truth: TALOS Desktop 0.1.7 @ 0c432153a288f64237e98403869d02d20d8fabc7
|
|
3
|
+
* - resources/harness-ui/public/talos/brand/logo-short.svg
|
|
4
|
+
* - resources/harness-ui/public/index.html boot layers
|
|
5
|
+
* - resources/harness-ui/public/avvio.js reveal timing
|
|
6
|
+
*
|
|
7
|
+
* These frames are manually curated fixed-width terminal interpretations of the
|
|
8
|
+
* Desktop graph mark. They are checked in; startup never rasterizes SVG assets.
|
|
9
|
+
*/
|
|
10
|
+
export const DESKTOP_LOGO_SOURCE = {
|
|
11
|
+
commit: '0c432153a288f64237e98403869d02d20d8fabc7',
|
|
12
|
+
svg: 'resources/harness-ui/public/talos/brand/logo-short.svg',
|
|
13
|
+
markup: 'resources/harness-ui/public/index.html',
|
|
14
|
+
script: 'resources/harness-ui/public/avvio.js',
|
|
15
|
+
nominalRevealMs: 7200,
|
|
16
|
+
};
|
|
17
|
+
export const TALOS_ASCII_FRAMES = Object.freeze([
|
|
18
|
+
Object.freeze([
|
|
19
|
+
' ',
|
|
20
|
+
' ',
|
|
21
|
+
' ╱ ╲ ',
|
|
22
|
+
' ╱ ╲ ',
|
|
23
|
+
' │ │ ',
|
|
24
|
+
' │ │ ',
|
|
25
|
+
' ╲ ╱ ',
|
|
26
|
+
' ╲___╱ ',
|
|
27
|
+
]),
|
|
28
|
+
Object.freeze([
|
|
29
|
+
' ● ',
|
|
30
|
+
' ',
|
|
31
|
+
' ╱ ╲ ',
|
|
32
|
+
' ╱ ╲ ',
|
|
33
|
+
' │ │ ',
|
|
34
|
+
' │ │ ',
|
|
35
|
+
' ╲ ╱ ',
|
|
36
|
+
' ╲___╱ ',
|
|
37
|
+
]),
|
|
38
|
+
Object.freeze([
|
|
39
|
+
' ● ',
|
|
40
|
+
' │ ',
|
|
41
|
+
' ╱ ╲ ',
|
|
42
|
+
' ╱ ╲ ',
|
|
43
|
+
' │ │ ',
|
|
44
|
+
' │ │ ',
|
|
45
|
+
' ╲ ╱ ',
|
|
46
|
+
' ╲___╱ ',
|
|
47
|
+
]),
|
|
48
|
+
Object.freeze([
|
|
49
|
+
' ● ',
|
|
50
|
+
' │ ',
|
|
51
|
+
' ╱ ╲ ',
|
|
52
|
+
' ╱ ● ╲ ',
|
|
53
|
+
' │ │ ',
|
|
54
|
+
' │ │ ',
|
|
55
|
+
' ╲ ╱ ',
|
|
56
|
+
' ╲___╱ ',
|
|
57
|
+
]),
|
|
58
|
+
Object.freeze([
|
|
59
|
+
' ● ',
|
|
60
|
+
' │ ',
|
|
61
|
+
' ╱ ╲ ',
|
|
62
|
+
' ╱ ● ╲ ',
|
|
63
|
+
' │ ╱│╲ │ ',
|
|
64
|
+
' │ │ │ ',
|
|
65
|
+
' ╲ ╱ ',
|
|
66
|
+
' ╲___╱ ',
|
|
67
|
+
]),
|
|
68
|
+
Object.freeze([
|
|
69
|
+
' ● ',
|
|
70
|
+
' │ ',
|
|
71
|
+
' ╱ ╲ ',
|
|
72
|
+
' ╱ ● ╲ ',
|
|
73
|
+
' │ ╱│╲ │ ',
|
|
74
|
+
' │ ● │ ● │ ',
|
|
75
|
+
' ╲ ● ╱ ',
|
|
76
|
+
' ╲___╱ ',
|
|
77
|
+
]),
|
|
78
|
+
]);
|
|
79
|
+
export function asciiLogoFrame(index) {
|
|
80
|
+
const frame = TALOS_ASCII_FRAMES[Math.max(0, Math.min(TALOS_ASCII_FRAMES.length - 1, Math.trunc(index)))];
|
|
81
|
+
return frame.map(line => line.replaceAll('●', 'o').replaceAll('│', '|').replaceAll('╱', '/').replaceAll('╲', '\\'));
|
|
82
|
+
}
|
package/dist/tui/boot.js
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import { TALOS_ASCII_FRAMES } from "./boot/desktop-logo.js";
|
|
2
|
+
export const BOOT_FRAMES = Object.freeze(TALOS_ASCII_FRAMES.map((_, index) => String(index)));
|
|
3
|
+
export function bootLabel(_frame, phase, detail = '') { const mark = phase === 'loading' ? '…' : phase === 'ready' ? '✓' : '!'; const status = phase === 'loading' ? 'starting' : phase; return `TALOS ${mark} ${status}${detail ? ` · ${detail}` : ''}`; }
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* R5a lane S — S5, what Enter does while TALOS works (owner decisions Q-R5-7 and Q-R5-8; gate E8; owner 2026-09-16).
|
|
3
|
+
*
|
|
4
|
+
* Three named modes (Hermes `/busy queue|steer|interrupt`, `hermes_cli/config_defaults.py:808`, 2026-09-24;
|
|
5
|
+
* `ui-tui/src/app/useConfigSync.ts:45-64`, 2026-09-02), config `ui.busyInput`, default `queue` (today's behaviour):
|
|
6
|
+
* - queue: Enter keeps the message and sends it when the turn ends;
|
|
7
|
+
* - steer: Enter steers the running turn (what Alt+S does);
|
|
8
|
+
* - interrupt: Enter stops the turn, then sends the message.
|
|
9
|
+
* In every mode `Alt+S` steers and Esc interrupts (E8); a `!` command typed during a turn is queued whatever the mode
|
|
10
|
+
* (owner 2026-09-16: never runs beside the agent). Slash commands follow Q-R5-8: the views run at once, the commands that
|
|
11
|
+
* change the session wait for the turn to end; every other command keeps today's behaviour (it runs at once).
|
|
12
|
+
* Pure: app.ts carries the decision out.
|
|
13
|
+
*/
|
|
14
|
+
import { t } from "../i18n/index.js";
|
|
15
|
+
export const BUSY_INPUT_MODES = Object.freeze(['queue', 'steer', 'interrupt']);
|
|
16
|
+
export const DEFAULT_BUSY_INPUT = 'queue';
|
|
17
|
+
export function parseBusyInput(value) { return typeof value === 'string' && BUSY_INPUT_MODES.includes(value) ? value : null; }
|
|
18
|
+
/* Q-R5-8 (a), as the owner decided it: views run at once; these change the session and wait for the turn. `/busy` is not
|
|
19
|
+
one of them (owner 2026-09-24): it changes what Enter does now, a screen preference, so it runs at once like Hermes's
|
|
20
|
+
(no busy guard, ui-tui/src/app/slash/commands/session.ts:622). */
|
|
21
|
+
export const SLASH_VIEWS = new Set(['help', 'status', 'context', 'queue', 'usage']);
|
|
22
|
+
export const SLASH_AFTER_TURN = new Set(['model', 'effort', 'provider', 'compact', 'clear', 'resume', 'fork', 'permissions']);
|
|
23
|
+
export function slashTiming(name) { return SLASH_AFTER_TURN.has(name) ? 'after-turn' : 'now'; }
|
|
24
|
+
/** What Enter does with `text` now. `running` is whether a turn is open. */
|
|
25
|
+
export function busyEnterAction({ text, running, mode }) {
|
|
26
|
+
const trimmed = String(text ?? '').trim();
|
|
27
|
+
if (trimmed.startsWith('/')) {
|
|
28
|
+
const name = trimmed.slice(1).split(/\s+/u)[0] ?? '';
|
|
29
|
+
return running && slashTiming(name) === 'after-turn' ? 'slash-after-turn' : 'slash-now';
|
|
30
|
+
}
|
|
31
|
+
if (!running)
|
|
32
|
+
return 'send';
|
|
33
|
+
if (trimmed.startsWith('!'))
|
|
34
|
+
return 'queue';
|
|
35
|
+
return mode === 'steer' ? 'steer' : mode === 'interrupt' ? 'interrupt-and-send' : 'queue';
|
|
36
|
+
}
|
|
37
|
+
/** The fixed line while a turn runs: what Enter, Alt+S and Esc do in this mode (Q-R5-7). */
|
|
38
|
+
export function busyLine(mode) { return t(`screen.busyLine.${mode}`); }
|
|
39
|
+
export function busyEffect(mode) { return t(`screen.busyInput.effect.${mode}`); }
|
|
40
|
+
/** The one-time tip, the first time Enter is pressed while TALOS works (Hermes `cli.md:430`, 2026-09-23). */
|
|
41
|
+
export function busyTip(mode) { return t('screen.busyInput.tip', { effect: busyEffect(mode) }); }
|
|
42
|
+
export function busySlash(args) {
|
|
43
|
+
if (args.length === 0)
|
|
44
|
+
return { kind: 'show' };
|
|
45
|
+
const mode = args.length === 1 ? parseBusyInput(args[0].toLowerCase()) : null;
|
|
46
|
+
return mode ? { kind: 'set', mode } : { kind: 'usage' };
|
|
47
|
+
}
|
|
48
|
+
export function busyShowText(mode) { return t('screen.busyInput.show', { mode, effect: busyEffect(mode) }); }
|
|
49
|
+
export function busySetText(mode) { return t('screen.busyInput.set', { mode, effect: busyEffect(mode) }); }
|
|
50
|
+
/** `/busy [mode]`: the line to show and, for a valid mode, the mode to adopt (and remember). */
|
|
51
|
+
export function busyCommand(args, current) {
|
|
52
|
+
const choice = busySlash(args);
|
|
53
|
+
if (choice.kind === 'set')
|
|
54
|
+
return { text: busySetText(choice.mode), mode: choice.mode };
|
|
55
|
+
return { text: choice.kind === 'show' ? busyShowText(current) : t('screen.usage.busy'), mode: null };
|
|
56
|
+
}
|
|
57
|
+
/** The Enter actions that earn the one-time tip: a message or a `!` command typed while TALOS works. */
|
|
58
|
+
export function tipsOnEnter(action) { return action === 'queue' || action === 'steer' || action === 'interrupt-and-send'; }
|