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,527 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* PORTO FEDELE di AVM/mobile/src/lib/research/researchRun.ts (492 righe, 11/09/2026).
|
|
3
|
+
*
|
|
4
|
+
* Un giro di ricerca che può essere ucciso e ripreso.
|
|
5
|
+
*
|
|
6
|
+
* Questo è R-1, e la specifica lo mette per primo per una ragione che
|
|
7
|
+
* sopravvive al contatto con la piattaforma: su un telefono il processo VERRÀ
|
|
8
|
+
* ucciso. Doze lo ferma a schermo spento, i servizi in primo piano `dataSync`
|
|
9
|
+
* hanno sei ore ogni ventiquattro e poi qualche secondo di preavviso, e il
|
|
10
|
+
* produttore di questo dispositivo — OnePlus, oggi su ColorOS — è documentato
|
|
11
|
+
* come uno dei più aggressivi sul mercato nell'uccidere il lavoro in secondo
|
|
12
|
+
* piano, coi permessi che l'utente concede azzerati dagli aggiornamenti di
|
|
13
|
+
* firmware.
|
|
14
|
+
*
|
|
15
|
+
* Quindi essere interrotti non è una modalità di guasto qui. È il caso normale,
|
|
16
|
+
* e tutto quello che sta sotto ne prende la forma.
|
|
17
|
+
*
|
|
18
|
+
* La forma è quella su cui il campo si è assestato per l'esecuzione durevole:
|
|
19
|
+
* un giornale a sola aggiunta di quello che È SUCCESSO, con lo stato corrente
|
|
20
|
+
* ricavato rigiocandolo — non un oggetto mutabile salvato sopra sé stesso. La
|
|
21
|
+
* differenza si vede esattamente quando conta: uno stato sovrascritto sul posto
|
|
22
|
+
* ti dice cosa crede sia vero adesso, e un giornale ti dice che un passo era
|
|
23
|
+
* finito prima che il processo morisse, che è la differenza fra pagare una
|
|
24
|
+
* ricerca una volta e pagarla due.
|
|
25
|
+
*
|
|
26
|
+
* Compra anche tre cose gratis, ed è la ragione per cui vale più di una colonna
|
|
27
|
+
* `status`: il giro si può biforcare, si può controllare, e un giro registrato
|
|
28
|
+
* si può rigiocare come test.
|
|
29
|
+
*
|
|
30
|
+
* Quello che fa la concorrenza qui vale la pena nominarlo, perché è il «+1».
|
|
31
|
+
* Fermare un giro di Deep Research su ChatGPT vuol dire ricominciarlo da zero;
|
|
32
|
+
* i suoi forum sono pieni di giri bloccati su «Researching…» senza alcun
|
|
33
|
+
* recupero. Loro se lo possono permettere: girano su un server. Noi no, e il
|
|
34
|
+
* vincolo è quello che produce la capacità.
|
|
35
|
+
*
|
|
36
|
+
* Niente in questo file tocca Android, la rete, un database o un modello. È
|
|
37
|
+
* aritmetica su una lista, che è ciò che lo rende provabile senza un
|
|
38
|
+
* dispositivo — e ciò che permette allo stesso giro di migrare più tardi su un
|
|
39
|
+
* server (R1b), visto che uno stato che si serializza è uno stato che si può
|
|
40
|
+
* spostare.
|
|
41
|
+
*/
|
|
42
|
+
|
|
43
|
+
/** @typedef {'quick' | 'deep' | 'exhaustive'} TalosResearchDepth */
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* `pause_requested` e `paused` sono due stati, non uno, e la ragione è il
|
|
47
|
+
* denaro.
|
|
48
|
+
*
|
|
49
|
+
* Una pausa può arrivare mentre un passo è IN VOLO e già pagato. Buttare via
|
|
50
|
+
* quella risposta per onorare subito la parola «pausa» spenderebbe il denaro
|
|
51
|
+
* dell'utente per niente, quindi il motore drena il passo che ha cominciato, lo
|
|
52
|
+
* mette a registro, e solo allora riposa — la ricerca del 2026-08-03 lo chiama
|
|
53
|
+
* «drain then checkpoint». `pause_requested` è l'intervallo in mezzo:
|
|
54
|
+
* l'intenzione è registrata e nessun passo nuovo verrà prenotato, ma il punto
|
|
55
|
+
* sicuro non è ancora stato raggiunto. Collassare i due farebbe mentire lo
|
|
56
|
+
* schermo in una direzione o nell'altra.
|
|
57
|
+
*
|
|
58
|
+
* `paused` NON è `cancelled`. Cancellato è terminale — il WorkManager di
|
|
59
|
+
* Android non ha uno stato PAUSED e il suo CANCELLED non si può riprendere —
|
|
60
|
+
* quindi scriverne uno quando la persona ha chiesto l'altro butterebbe via una
|
|
61
|
+
* ricerca che aveva pagato.
|
|
62
|
+
*
|
|
63
|
+
* @typedef {'planning' | 'awaiting_plan_approval' | 'collecting' | 'synthesising' | 'verifying' | 'pause_requested' | 'paused' | 'done' | 'cancelled' | 'failed'} TalosResearchStatus
|
|
64
|
+
*/
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Gli stati da cui non succederà mai più niente.
|
|
68
|
+
*
|
|
69
|
+
* @type {readonly TalosResearchStatus[]}
|
|
70
|
+
*/
|
|
71
|
+
export const TALOS_RESEARCH_TERMINAL = Object.freeze([
|
|
72
|
+
'done', 'cancelled', 'failed',
|
|
73
|
+
]);
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* @param {TalosResearchStatus} status
|
|
77
|
+
* @returns {boolean}
|
|
78
|
+
*/
|
|
79
|
+
export function talosResearchIsTerminal(status) {
|
|
80
|
+
return TALOS_RESEARCH_TERMINAL.includes(status);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Fermo, ma con del lavoro ancora dovuto: il motore non deve prenotare, il giro
|
|
85
|
+
* si può riprendere.
|
|
86
|
+
*
|
|
87
|
+
* @param {TalosResearchStatus} status
|
|
88
|
+
* @returns {boolean}
|
|
89
|
+
*/
|
|
90
|
+
export function talosResearchIsResting(status) {
|
|
91
|
+
return status === 'paused' || status === 'pause_requested';
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Dove il giro sta girando. Tutto il punto di R1b è che questo può cambiare.
|
|
96
|
+
*
|
|
97
|
+
* @typedef {'device' | 'cloud'} TalosResearchEngine
|
|
98
|
+
*/
|
|
99
|
+
|
|
100
|
+
/** @typedef {'search' | 'read' | 'synthesise' | 'verify'} TalosResearchStepKind */
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* `interrupted` non è la stessa cosa di `failed`, e la distinzione È la
|
|
104
|
+
* funzione.
|
|
105
|
+
*
|
|
106
|
+
* Un passo fallito ha provato e non ce l'ha fatta; uno interrotto stava ancora
|
|
107
|
+
* girando quando il processo è stato ucciso, quindi nessuno sa se sia finito.
|
|
108
|
+
* Il primo è un risultato, il secondo è una domanda — e solo il secondo vale la
|
|
109
|
+
* pena di riprovare.
|
|
110
|
+
*
|
|
111
|
+
* @typedef {'pending' | 'running' | 'done' | 'failed' | 'interrupted'} TalosResearchStepState
|
|
112
|
+
*/
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* Solo e soltanto quello che è stato davvero osservato. Le stime vivono sul ramo.
|
|
116
|
+
*
|
|
117
|
+
* @typedef {object} TalosResearchSpend
|
|
118
|
+
* @property {number} tokens
|
|
119
|
+
* @property {number} searches
|
|
120
|
+
* @property {number} pages
|
|
121
|
+
*/
|
|
122
|
+
|
|
123
|
+
/** @type {TalosResearchSpend} */
|
|
124
|
+
export const TALOS_RESEARCH_NO_SPEND = Object.freeze({
|
|
125
|
+
tokens: 0,
|
|
126
|
+
searches: 0,
|
|
127
|
+
pages: 0,
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* @typedef {object} TalosResearchBranch
|
|
132
|
+
* @property {string} id
|
|
133
|
+
* @property {string} question
|
|
134
|
+
* @property {TalosResearchSpend} estimate Quello che il pianificatore ha INDOVINATO. Mai confuso con quello che è stato speso.
|
|
135
|
+
*/
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* @typedef {object} TalosResearchStep
|
|
139
|
+
* @property {string} id
|
|
140
|
+
* @property {string} branchId
|
|
141
|
+
* @property {TalosResearchStepKind} kind
|
|
142
|
+
* @property {TalosResearchStepState} state
|
|
143
|
+
* @property {number} attempts Quante volte questo passo è stato avviato. Prova, non identità.
|
|
144
|
+
* @property {string | null} startedAt
|
|
145
|
+
* @property {string | null} finishedAt
|
|
146
|
+
* @property {TalosResearchSpend} spend
|
|
147
|
+
* @property {string | null} resultRef
|
|
148
|
+
* Dove vive il carico — mai il carico. Un giornale che porta cento kilobyte
|
|
149
|
+
* di testo di pagina per riga è un giornale che nessuno può rigiocare su un
|
|
150
|
+
* telefono, e il testo appartiene al caveau con tutto il resto che l'app
|
|
151
|
+
* conserva.
|
|
152
|
+
* @property {string | null} error
|
|
153
|
+
*/
|
|
154
|
+
|
|
155
|
+
/**
|
|
156
|
+
* @typedef {object} TalosResearchRun
|
|
157
|
+
* @property {string} id
|
|
158
|
+
* @property {string} sessionId
|
|
159
|
+
* @property {string} question
|
|
160
|
+
* @property {TalosResearchDepth} depth
|
|
161
|
+
* @property {TalosResearchEngine} engine
|
|
162
|
+
* @property {TalosResearchStatus} status
|
|
163
|
+
* @property {string | null} title
|
|
164
|
+
* L'etichetta che la lista mostra, quando qualcuno ne ha scelta una. `null`
|
|
165
|
+
* vuol dire «usa la domanda» — che è il default onesto, perché la domanda È
|
|
166
|
+
* il nome di una ricerca finché una persona non decide altrimenti.
|
|
167
|
+
* @property {readonly TalosResearchBranch[]} plan
|
|
168
|
+
* @property {readonly TalosResearchStep[]} steps
|
|
169
|
+
* @property {string} startedAt
|
|
170
|
+
* @property {string} updatedAt
|
|
171
|
+
*/
|
|
172
|
+
|
|
173
|
+
/**
|
|
174
|
+
* Gli undici eventi del giornale.
|
|
175
|
+
*
|
|
176
|
+
* @typedef {{kind:'run_started', at:string, id:string, sessionId:string, question:string, depth:TalosResearchDepth, engine:TalosResearchEngine}
|
|
177
|
+
* | {kind:'plan_proposed', at:string, branches:readonly TalosResearchBranch[]}
|
|
178
|
+
* | {kind:'plan_approved', at:string, branches:readonly TalosResearchBranch[]}
|
|
179
|
+
* | {kind:'step_started', at:string, stepId:string, branchId:string, stepKind:TalosResearchStepKind}
|
|
180
|
+
* | {kind:'step_finished', at:string, stepId:string, spend:TalosResearchSpend, resultRef:string|null}
|
|
181
|
+
* | {kind:'step_failed', at:string, stepId:string, error:string}
|
|
182
|
+
* | {kind:'run_pause_requested', at:string}
|
|
183
|
+
* | {kind:'run_paused', at:string}
|
|
184
|
+
* | {kind:'run_resumed', at:string}
|
|
185
|
+
* | {kind:'run_renamed', at:string, title:string|null}
|
|
186
|
+
* | {kind:'run_cancelled', at:string}
|
|
187
|
+
* | {kind:'run_finished', at:string}} TalosResearchEvent
|
|
188
|
+
*/
|
|
189
|
+
|
|
190
|
+
/**
|
|
191
|
+
* Il nome a cui un passo risponde, attraverso ogni tentativo.
|
|
192
|
+
*
|
|
193
|
+
* La letteratura lo ricava da giro + attività + NUMERO DI TENTATIVO. Il
|
|
194
|
+
* tentativo è lasciato fuori di proposito qui, perché i due contesti vogliono
|
|
195
|
+
* cose opposte. Là la chiave separa i tentativi proprio perché il secondo giri.
|
|
196
|
+
* Qui l'utente paga di tasca sua — ogni ricerca è denaro — quindi due tentativi
|
|
197
|
+
* dello stesso passo logico devono essere riconoscibili come LO STESSO, e un
|
|
198
|
+
* fornitore che sa deduplicare dev'essere messo in condizione di farlo. Il
|
|
199
|
+
* conteggio dei tentativi è registrato accanto al passo come prova, mai piegato
|
|
200
|
+
* dentro il suo nome.
|
|
201
|
+
*
|
|
202
|
+
* @param {string} runId
|
|
203
|
+
* @param {string} stepId
|
|
204
|
+
* @returns {string}
|
|
205
|
+
*/
|
|
206
|
+
export function talosResearchIdempotencyKey(runId, stepId) {
|
|
207
|
+
return `${runId}:${stepId}`;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
/**
|
|
211
|
+
* @param {TalosResearchSpend} left
|
|
212
|
+
* @param {TalosResearchSpend} right
|
|
213
|
+
* @returns {TalosResearchSpend}
|
|
214
|
+
*/
|
|
215
|
+
function addSpend(left, right) {
|
|
216
|
+
return {
|
|
217
|
+
tokens: left.tokens + right.tokens,
|
|
218
|
+
searches: left.searches + right.searches,
|
|
219
|
+
pages: left.pages + right.pages,
|
|
220
|
+
};
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
/**
|
|
224
|
+
* Quanto il giro è davvero costato finora, sommato dai passi che sono girati.
|
|
225
|
+
*
|
|
226
|
+
* @param {TalosResearchRun} run
|
|
227
|
+
* @returns {TalosResearchSpend}
|
|
228
|
+
*/
|
|
229
|
+
export function talosResearchSpent(run) {
|
|
230
|
+
return run.steps.reduce((total, step) => addSpend(total, step.spend), TALOS_RESEARCH_NO_SPEND);
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
/**
|
|
234
|
+
* @param {readonly TalosResearchStep[]} steps
|
|
235
|
+
* @param {string} stepId
|
|
236
|
+
* @param {(step: TalosResearchStep) => TalosResearchStep} change
|
|
237
|
+
* @returns {readonly TalosResearchStep[]}
|
|
238
|
+
*/
|
|
239
|
+
function replaceStep(steps, stepId, change) {
|
|
240
|
+
return steps.map((step) => (step.id === stepId ? change(step) : step));
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
/**
|
|
244
|
+
* Un evento, ripiegato dentro lo stato.
|
|
245
|
+
*
|
|
246
|
+
* Gli eventi che non hanno senso contro lo stato a cui arrivano vengono
|
|
247
|
+
* IGNORATI invece di lanciare. Un giornale si legge dal magazzino dopo
|
|
248
|
+
* un'uccisione, e l'unica cosa che non deve fare mai è rifiutarsi di caricare:
|
|
249
|
+
* un giro che non si può rigiocare è un giro il cui lavoro pagato è perso, che
|
|
250
|
+
* è esattamente il guasto per cui questo disegno esiste. I duplicati sono il
|
|
251
|
+
* caso comune — un'aggiunta scritta due volte perché il processo è morto fra la
|
|
252
|
+
* scrittura e la conferma — e contarne uno due volte riporterebbe denaro che
|
|
253
|
+
* non è mai stato speso.
|
|
254
|
+
*
|
|
255
|
+
* @param {TalosResearchRun | null} run
|
|
256
|
+
* @param {TalosResearchEvent} event
|
|
257
|
+
* @returns {TalosResearchRun | null}
|
|
258
|
+
*/
|
|
259
|
+
export function talosResearchApply(run, event) {
|
|
260
|
+
if (event.kind === 'run_started') {
|
|
261
|
+
// Solo il primo. Un avvio ripetuto azzererebbe un giro che ha già speso
|
|
262
|
+
// denaro.
|
|
263
|
+
if (run) return run;
|
|
264
|
+
return {
|
|
265
|
+
id: event.id,
|
|
266
|
+
sessionId: event.sessionId,
|
|
267
|
+
question: event.question,
|
|
268
|
+
depth: event.depth,
|
|
269
|
+
engine: event.engine,
|
|
270
|
+
status: 'planning',
|
|
271
|
+
title: null,
|
|
272
|
+
plan: [],
|
|
273
|
+
steps: [],
|
|
274
|
+
startedAt: event.at,
|
|
275
|
+
updatedAt: event.at,
|
|
276
|
+
};
|
|
277
|
+
}
|
|
278
|
+
if (!run) return null;
|
|
279
|
+
|
|
280
|
+
/**
|
|
281
|
+
* @param {Partial<TalosResearchRun>} next
|
|
282
|
+
* @returns {TalosResearchRun}
|
|
283
|
+
*/
|
|
284
|
+
const touched = (next) => ({
|
|
285
|
+
...run,
|
|
286
|
+
...next,
|
|
287
|
+
updatedAt: event.at,
|
|
288
|
+
});
|
|
289
|
+
|
|
290
|
+
switch (event.kind) {
|
|
291
|
+
case 'plan_proposed':
|
|
292
|
+
return touched({ plan: event.branches, status: 'awaiting_plan_approval' });
|
|
293
|
+
|
|
294
|
+
case 'plan_approved':
|
|
295
|
+
// I rami APPROVATI, non quelli proposti: l'utente ha il permesso di
|
|
296
|
+
// togliere, aggiungere e riformulare, e quello che ha approvato è quello
|
|
297
|
+
// che gira.
|
|
298
|
+
return touched({ plan: event.branches, status: 'collecting' });
|
|
299
|
+
|
|
300
|
+
case 'step_started': {
|
|
301
|
+
const existing = run.steps.find((step) => step.id === event.stepId);
|
|
302
|
+
if (existing?.state === 'done') {
|
|
303
|
+
// Già pagato. Ricominciarlo è l'errore che tutto questo file esiste per
|
|
304
|
+
// rendere impossibile.
|
|
305
|
+
return run;
|
|
306
|
+
}
|
|
307
|
+
if (existing) {
|
|
308
|
+
return touched({
|
|
309
|
+
steps: replaceStep(run.steps, event.stepId, (step) => ({
|
|
310
|
+
...step,
|
|
311
|
+
state: 'running',
|
|
312
|
+
attempts: step.attempts + 1,
|
|
313
|
+
startedAt: event.at,
|
|
314
|
+
error: null,
|
|
315
|
+
})),
|
|
316
|
+
});
|
|
317
|
+
}
|
|
318
|
+
return touched({
|
|
319
|
+
steps: [...run.steps, {
|
|
320
|
+
id: event.stepId,
|
|
321
|
+
branchId: event.branchId,
|
|
322
|
+
kind: event.stepKind,
|
|
323
|
+
state: 'running',
|
|
324
|
+
attempts: 1,
|
|
325
|
+
startedAt: event.at,
|
|
326
|
+
finishedAt: null,
|
|
327
|
+
spend: TALOS_RESEARCH_NO_SPEND,
|
|
328
|
+
resultRef: null,
|
|
329
|
+
error: null,
|
|
330
|
+
}],
|
|
331
|
+
});
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
case 'step_finished': {
|
|
335
|
+
const existing = run.steps.find((step) => step.id === event.stepId);
|
|
336
|
+
if (!existing || existing.state === 'done') return run;
|
|
337
|
+
return touched({
|
|
338
|
+
steps: replaceStep(run.steps, event.stepId, (step) => ({
|
|
339
|
+
...step,
|
|
340
|
+
state: 'done',
|
|
341
|
+
finishedAt: event.at,
|
|
342
|
+
// Registrato una volta, sulla transizione. Sommarlo alla cifra
|
|
343
|
+
// precedente conterebbe due volte un passo riprovato che aveva già
|
|
344
|
+
// riportato una parte del suo costo.
|
|
345
|
+
spend: event.spend,
|
|
346
|
+
resultRef: event.resultRef,
|
|
347
|
+
error: null,
|
|
348
|
+
})),
|
|
349
|
+
});
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
case 'step_failed': {
|
|
353
|
+
const existing = run.steps.find((step) => step.id === event.stepId);
|
|
354
|
+
if (!existing || existing.state === 'done') return run;
|
|
355
|
+
return touched({
|
|
356
|
+
steps: replaceStep(run.steps, event.stepId, (step) => ({
|
|
357
|
+
...step,
|
|
358
|
+
state: 'failed',
|
|
359
|
+
finishedAt: event.at,
|
|
360
|
+
error: event.error,
|
|
361
|
+
})),
|
|
362
|
+
});
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
/*
|
|
366
|
+
* Chiedere due volte non è chiedere più forte: la seconda richiesta non
|
|
367
|
+
* deve riportare a «mi sto fermando» un giro che ha già raggiunto il punto
|
|
368
|
+
* sicuro. E un giro che è finito non è affatto mettibile in pausa — il
|
|
369
|
+
* giornale si legge dopo un'uccisione, e una richiesta vecchia che arriva
|
|
370
|
+
* in ritardo non deve resuscitare un giro terminale.
|
|
371
|
+
*/
|
|
372
|
+
case 'run_pause_requested':
|
|
373
|
+
if (talosResearchIsTerminal(run.status) || run.status === 'paused') return run;
|
|
374
|
+
return touched({ status: 'pause_requested' });
|
|
375
|
+
|
|
376
|
+
case 'run_paused':
|
|
377
|
+
if (talosResearchIsTerminal(run.status)) return run;
|
|
378
|
+
return touched({ status: 'paused' });
|
|
379
|
+
|
|
380
|
+
/*
|
|
381
|
+
* Di nuovo a raccogliere, che è dove vive il punto di ripresa. Rifiutato da
|
|
382
|
+
* uno stato terminale per lo stesso motivo: cancellato vuol dire
|
|
383
|
+
* cancellato, e una ripresa che lo riaprisse spenderebbe denaro su un giro
|
|
384
|
+
* che la persona ha chiuso.
|
|
385
|
+
*/
|
|
386
|
+
case 'run_resumed':
|
|
387
|
+
if (talosResearchIsTerminal(run.status)) return run;
|
|
388
|
+
return touched({ status: 'collecting' });
|
|
389
|
+
|
|
390
|
+
case 'run_renamed': {
|
|
391
|
+
// Lo spazio bianco non è un titolo. Vuoto ripristina la domanda, che è
|
|
392
|
+
// anche quello che scrive «Ripristina il titolo originale».
|
|
393
|
+
const title = event.title === null ? null : event.title.trim();
|
|
394
|
+
return touched({ title: title === null || title.length === 0 ? null : title });
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
case 'run_cancelled':
|
|
398
|
+
return touched({ status: 'cancelled' });
|
|
399
|
+
|
|
400
|
+
case 'run_finished':
|
|
401
|
+
return touched({ status: 'done' });
|
|
402
|
+
|
|
403
|
+
default:
|
|
404
|
+
return run;
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
/**
|
|
409
|
+
* Lo stato di un giro, da tutta la sua storia. Deterministico per costruzione.
|
|
410
|
+
*
|
|
411
|
+
* @param {readonly TalosResearchEvent[]} events
|
|
412
|
+
* @returns {TalosResearchRun | null}
|
|
413
|
+
*/
|
|
414
|
+
export function talosResearchReplay(events) {
|
|
415
|
+
return events.reduce(talosResearchApply, /** @type {TalosResearchRun | null} */ (null));
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
/**
|
|
419
|
+
* Quello che il processo non ha potuto dirci, ricavato sulla via del ritorno.
|
|
420
|
+
*
|
|
421
|
+
* Un passo lasciato `running` era in volo quando il processo è stato ucciso.
|
|
422
|
+
* Nessuno l'ha scritto, perché la cosa che l'avrebbe scritto è quella che è
|
|
423
|
+
* morta — quindi si deduce qui, nell'unico momento in cui qualcuno può: il
|
|
424
|
+
* prossimo avvio. È per questo che non esiste un evento `process_died`; un
|
|
425
|
+
* evento che nessuno è vivo per aggiungere è una bugia nel giornale.
|
|
426
|
+
*
|
|
427
|
+
* @param {TalosResearchRun} run
|
|
428
|
+
* @param {string} at
|
|
429
|
+
* @returns {TalosResearchRun}
|
|
430
|
+
*/
|
|
431
|
+
export function talosResearchRecover(run, at) {
|
|
432
|
+
if (!run.steps.some((step) => step.state === 'running')) return run;
|
|
433
|
+
return {
|
|
434
|
+
...run,
|
|
435
|
+
steps: run.steps.map((step) => (
|
|
436
|
+
step.state === 'running' ? { ...step, state: 'interrupted' } : step
|
|
437
|
+
)),
|
|
438
|
+
updatedAt: at,
|
|
439
|
+
};
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
/**
|
|
443
|
+
* Il passo da fare dopo, o niente.
|
|
444
|
+
*
|
|
445
|
+
* I passi interrotti vengono prima di quelli intatti: finire quello che era
|
|
446
|
+
* stato cominciato mantiene l'ordine del giro, ed è il passo che più
|
|
447
|
+
* probabilmente è già stato pagato in parte.
|
|
448
|
+
*
|
|
449
|
+
* @param {TalosResearchRun} run
|
|
450
|
+
* @returns {TalosResearchStep | null}
|
|
451
|
+
*/
|
|
452
|
+
export function talosResearchNextStep(run) {
|
|
453
|
+
if (talosResearchIsTerminal(run.status)) return null;
|
|
454
|
+
// La pausa si fa rispettare QUI, nell'unica funzione che decide cosa fare
|
|
455
|
+
// dopo, invece che a ogni punto di chiamata che potrebbe dimenticarsene.
|
|
456
|
+
// «Nessun passo nuovo viene prenotato» non è un consiglio al motore — è il
|
|
457
|
+
// motore che non ha niente da prenotare.
|
|
458
|
+
if (talosResearchIsResting(run.status)) return null;
|
|
459
|
+
return run.steps.find((step) => step.state === 'interrupted')
|
|
460
|
+
?? run.steps.find((step) => step.state === 'pending')
|
|
461
|
+
?? null;
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
/**
|
|
465
|
+
* Quanto è avanti un giro — una definizione sola, così niente può essere in
|
|
466
|
+
* disaccordo con sé stesso.
|
|
467
|
+
*
|
|
468
|
+
* La sintesi è un passo come gli altri e conta fra quelli finiti, quindi un
|
|
469
|
+
* totale preso dal solo piano annunciava «3 di 2» nel momento in cui il
|
|
470
|
+
* rapporto veniva scritto. Si aggiunge al totale una volta che il giro ha
|
|
471
|
+
* davvero un passo del genere, e non prima: un denominatore che conta lavoro
|
|
472
|
+
* che potrebbe non essere mai tentato è la stessa bugia nell'altra direzione.
|
|
473
|
+
*
|
|
474
|
+
* @param {TalosResearchRun} run
|
|
475
|
+
* @returns {{done: number, total: number}}
|
|
476
|
+
*/
|
|
477
|
+
export function talosResearchProgressOf(run) {
|
|
478
|
+
return {
|
|
479
|
+
done: run.steps.filter((step) => step.state === 'done').length,
|
|
480
|
+
total: run.plan.length + (run.steps.some((step) => step.kind === 'synthesise') ? 1 : 0),
|
|
481
|
+
};
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
/**
|
|
485
|
+
* Il nome a cui risponde il passo di un ramo. Derivato, mai inventato.
|
|
486
|
+
*
|
|
487
|
+
* Un id di passo che venisse da un contatore o da una sorgente casuale sarebbe
|
|
488
|
+
* un nome nuovo a ogni tentativo, e un nome nuovo è un passo che nessuno può
|
|
489
|
+
* riconoscere come già fatto — che è il modo in cui un giro ripreso paga due
|
|
490
|
+
* volte la stessa ricerca.
|
|
491
|
+
*
|
|
492
|
+
* @param {string} branchId
|
|
493
|
+
* @param {TalosResearchStepKind} kind
|
|
494
|
+
* @returns {string}
|
|
495
|
+
*/
|
|
496
|
+
export function talosResearchStepIdFor(branchId, kind) {
|
|
497
|
+
return `${branchId}:${kind}`;
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
/**
|
|
501
|
+
* Quello che deve ancora succedere, dal PIANO invece che dal giornale.
|
|
502
|
+
*
|
|
503
|
+
* I due rispondono a domande diverse e servono entrambi. Il giornale registra
|
|
504
|
+
* quello che è successo; solo il piano sa quello che avrebbe dovuto succedere.
|
|
505
|
+
* Un giro ucciso prima che il suo terzo ramo partisse non ha niente nel
|
|
506
|
+
* giornale su quel ramo — il lavoro manca, non è registrato come mancante —
|
|
507
|
+
* quindi chiedere al solo giornale chiamerebbe il giro finito.
|
|
508
|
+
*
|
|
509
|
+
* Un ramo è in sospeso quando il suo passo è assente, interrotto o fallito.
|
|
510
|
+
* Fatto è fatto: non viene mai offerto di nuovo, qualunque cosa sia successa
|
|
511
|
+
* dopo.
|
|
512
|
+
*
|
|
513
|
+
* @param {TalosResearchRun} run
|
|
514
|
+
* @param {TalosResearchStepKind} [kind='search']
|
|
515
|
+
* @returns {readonly TalosResearchBranch[]}
|
|
516
|
+
*/
|
|
517
|
+
export function talosResearchWorkLeft(run, kind = 'search') {
|
|
518
|
+
// Solo terminale. Un giro in pausa DEVE ancora questo lavoro — dire il
|
|
519
|
+
// contrario disegnerebbe un piano vuoto per una cosa che la persona sta per
|
|
520
|
+
// riprendere, ed è la domanda opposta rispetto a «cosa dovrebbe fare il
|
|
521
|
+
// motore proprio adesso».
|
|
522
|
+
if (talosResearchIsTerminal(run.status)) return [];
|
|
523
|
+
return run.plan.filter((branch) => {
|
|
524
|
+
const step = run.steps.find((candidate) => candidate.id === talosResearchStepIdFor(branch.id, kind));
|
|
525
|
+
return !step || step.state !== 'done';
|
|
526
|
+
});
|
|
527
|
+
}
|