@vascend/talos 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/README.md +202 -0
- package/dist/backend/asset-events.d.ts +31 -0
- package/dist/backend/asset-events.js +149 -0
- package/dist/backend/assets.d.ts +31 -0
- package/dist/backend/assets.js +210 -0
- package/dist/backend/auth.d.ts +18 -0
- package/dist/backend/auth.js +59 -0
- package/dist/backend/config.d.ts +14 -0
- package/dist/backend/config.js +41 -0
- package/dist/backend/conversations.d.ts +21 -0
- package/dist/backend/conversations.js +141 -0
- package/dist/backend/crypto.d.ts +9 -0
- package/dist/backend/crypto.js +68 -0
- package/dist/backend/engine.d.ts +13 -0
- package/dist/backend/engine.js +78 -0
- package/dist/backend/http.d.ts +25 -0
- package/dist/backend/http.js +112 -0
- package/dist/backend/index.d.ts +1 -0
- package/dist/backend/index.js +24 -0
- package/dist/backend/routes.d.ts +14 -0
- package/dist/backend/routes.js +169 -0
- package/dist/backend/sdk.d.ts +12 -0
- package/dist/backend/sdk.js +11 -0
- package/dist/backend/server.d.ts +12 -0
- package/dist/backend/server.js +91 -0
- package/dist/backend/temp-image-store.d.ts +46 -0
- package/dist/backend/temp-image-store.js +197 -0
- package/dist/backend/types.d.ts +103 -0
- package/dist/backend/types.js +29 -0
- package/dist/backend/users.d.ts +13 -0
- package/dist/backend/users.js +76 -0
- package/dist/backend/ws-handler.d.ts +14 -0
- package/dist/backend/ws-handler.js +72 -0
- package/dist/backend/ws.d.ts +19 -0
- package/dist/backend/ws.js +146 -0
- package/dist/core/agent.d.ts +56 -0
- package/dist/core/agent.js +1783 -0
- package/dist/core/background.d.ts +45 -0
- package/dist/core/background.js +140 -0
- package/dist/core/bootstrap.d.ts +45 -0
- package/dist/core/bootstrap.js +294 -0
- package/dist/core/cli-args.d.ts +41 -0
- package/dist/core/cli-args.js +282 -0
- package/dist/core/collapsible-output.d.ts +38 -0
- package/dist/core/collapsible-output.js +143 -0
- package/dist/core/compaction-checkpoint.d.ts +9 -0
- package/dist/core/compaction-checkpoint.js +58 -0
- package/dist/core/compaction.d.ts +42 -0
- package/dist/core/compaction.js +270 -0
- package/dist/core/config.d.ts +49 -0
- package/dist/core/config.js +417 -0
- package/dist/core/context-ledger.d.ts +99 -0
- package/dist/core/context-ledger.js +222 -0
- package/dist/core/context-policy.d.ts +17 -0
- package/dist/core/context-policy.js +81 -0
- package/dist/core/continuation-review.d.ts +23 -0
- package/dist/core/continuation-review.js +64 -0
- package/dist/core/crash-report.d.ts +3 -0
- package/dist/core/crash-report.js +27 -0
- package/dist/core/credentials.d.ts +11 -0
- package/dist/core/credentials.js +183 -0
- package/dist/core/doctor.d.ts +24 -0
- package/dist/core/doctor.js +125 -0
- package/dist/core/effort.d.ts +5 -0
- package/dist/core/effort.js +42 -0
- package/dist/core/env-paths.d.ts +3 -0
- package/dist/core/env-paths.js +38 -0
- package/dist/core/execution-guidance.d.ts +9 -0
- package/dist/core/execution-guidance.js +73 -0
- package/dist/core/execution-target.d.ts +41 -0
- package/dist/core/execution-target.js +69 -0
- package/dist/core/file-coordination.d.ts +66 -0
- package/dist/core/file-coordination.js +176 -0
- package/dist/core/file-lease-store.d.ts +14 -0
- package/dist/core/file-lease-store.js +89 -0
- package/dist/core/image-limits.d.ts +26 -0
- package/dist/core/image-limits.js +205 -0
- package/dist/core/interruptible-completion.d.ts +3 -0
- package/dist/core/interruptible-completion.js +42 -0
- package/dist/core/kingdoms-mode-state.d.ts +24 -0
- package/dist/core/kingdoms-mode-state.js +139 -0
- package/dist/core/licenza.d.ts +38 -0
- package/dist/core/licenza.js +125 -0
- package/dist/core/model-limits.d.ts +2 -0
- package/dist/core/model-limits.js +36 -0
- package/dist/core/output-lifecycle.d.ts +44 -0
- package/dist/core/output-lifecycle.js +190 -0
- package/dist/core/package-update.d.ts +15 -0
- package/dist/core/package-update.js +121 -0
- package/dist/core/permission-queue.d.ts +2 -0
- package/dist/core/permission-queue.js +20 -0
- package/dist/core/prompt-attachment.d.ts +21 -0
- package/dist/core/prompt-attachment.js +123 -0
- package/dist/core/request-plan.d.ts +16 -0
- package/dist/core/request-plan.js +36 -0
- package/dist/core/run-timing.d.ts +17 -0
- package/dist/core/run-timing.js +123 -0
- package/dist/core/self-update.d.ts +17 -0
- package/dist/core/self-update.js +54 -0
- package/dist/core/session-refs.d.ts +27 -0
- package/dist/core/session-refs.js +126 -0
- package/dist/core/session-storage.d.ts +4 -0
- package/dist/core/session-storage.js +48 -0
- package/dist/core/session-title.d.ts +1 -0
- package/dist/core/session-title.js +21 -0
- package/dist/core/session-usage.d.ts +17 -0
- package/dist/core/session-usage.js +74 -0
- package/dist/core/session.d.ts +58 -0
- package/dist/core/session.js +296 -0
- package/dist/core/settings.d.ts +17 -0
- package/dist/core/settings.js +107 -0
- package/dist/core/storage-retention.d.ts +21 -0
- package/dist/core/storage-retention.js +227 -0
- package/dist/core/text-sanitize.d.ts +1 -0
- package/dist/core/text-sanitize.js +35 -0
- package/dist/core/tool-artifacts.d.ts +6 -0
- package/dist/core/tool-artifacts.js +51 -0
- package/dist/core/tool-compress.d.ts +8 -0
- package/dist/core/tool-compress.js +111 -0
- package/dist/core/tool-executor.d.ts +16 -0
- package/dist/core/tool-executor.js +97 -0
- package/dist/core/tool-result-index.d.ts +52 -0
- package/dist/core/tool-result-index.js +327 -0
- package/dist/core/tool-result-store.d.ts +38 -0
- package/dist/core/tool-result-store.js +190 -0
- package/dist/core/tool-scheduler.d.ts +16 -0
- package/dist/core/tool-scheduler.js +35 -0
- package/dist/core/trust.d.ts +21 -0
- package/dist/core/trust.js +95 -0
- package/dist/core/types.d.ts +402 -0
- package/dist/core/types.js +1 -0
- package/dist/core/update-check.d.ts +26 -0
- package/dist/core/update-check.js +89 -0
- package/dist/core/update-process.d.ts +10 -0
- package/dist/core/update-process.js +31 -0
- package/dist/core/user-inbox.d.ts +23 -0
- package/dist/core/user-inbox.js +56 -0
- package/dist/core/user-input.d.ts +10 -0
- package/dist/core/user-input.js +35 -0
- package/dist/core/version.d.ts +1 -0
- package/dist/core/version.js +10 -0
- package/dist/core/vibe-modes.d.ts +38 -0
- package/dist/core/vibe-modes.js +383 -0
- package/dist/core/workspace-roots.d.ts +13 -0
- package/dist/core/workspace-roots.js +91 -0
- package/dist/core/workspace-sessions.d.ts +51 -0
- package/dist/core/workspace-sessions.js +243 -0
- package/dist/cowork/client.d.ts +29 -0
- package/dist/cowork/client.js +49 -0
- package/dist/cowork/engine-bridge.d.ts +22 -0
- package/dist/cowork/engine-bridge.js +98 -0
- package/dist/cowork/index.d.ts +11 -0
- package/dist/cowork/index.js +16 -0
- package/dist/cowork/ipc.d.ts +97 -0
- package/dist/cowork/ipc.js +96 -0
- package/dist/cowork/manager.d.ts +66 -0
- package/dist/cowork/manager.js +325 -0
- package/dist/cowork/store.d.ts +23 -0
- package/dist/cowork/store.js +182 -0
- package/dist/cowork/sync.d.ts +20 -0
- package/dist/cowork/sync.js +164 -0
- package/dist/cowork/types.d.ts +78 -0
- package/dist/cowork/types.js +21 -0
- package/dist/extensions/ext-tools.d.ts +3 -0
- package/dist/extensions/ext-tools.js +73 -0
- package/dist/extensions/loader.d.ts +91 -0
- package/dist/extensions/loader.js +474 -0
- package/dist/extensions/settings.d.ts +20 -0
- package/dist/extensions/settings.js +86 -0
- package/dist/extensions/types.d.ts +219 -0
- package/dist/extensions/types.js +1 -0
- package/dist/horizon/async-queue.d.ts +9 -0
- package/dist/horizon/async-queue.js +46 -0
- package/dist/horizon/engine.d.ts +85 -0
- package/dist/horizon/engine.js +603 -0
- package/dist/horizon/index.d.ts +4 -0
- package/dist/horizon/index.js +2 -0
- package/dist/horizon/main-team.d.ts +163 -0
- package/dist/horizon/main-team.js +774 -0
- package/dist/horizon/types.d.ts +233 -0
- package/dist/horizon/types.js +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +233 -0
- package/dist/mcp/protocol.d.ts +81 -0
- package/dist/mcp/protocol.js +122 -0
- package/dist/package.json +1 -0
- package/dist/packages/packages.d.ts +12 -0
- package/dist/packages/packages.js +323 -0
- package/dist/prompts/templates.d.ts +13 -0
- package/dist/prompts/templates.js +139 -0
- package/dist/providers/anthropic-oauth.d.ts +13 -0
- package/dist/providers/anthropic-oauth.js +124 -0
- package/dist/providers/anthropic.d.ts +27 -0
- package/dist/providers/anthropic.js +526 -0
- package/dist/providers/catalog.d.ts +15 -0
- package/dist/providers/catalog.js +166 -0
- package/dist/providers/effort.d.ts +12 -0
- package/dist/providers/effort.js +102 -0
- package/dist/providers/model-catalog.d.ts +43 -0
- package/dist/providers/model-catalog.js +70 -0
- package/dist/providers/model-effort.d.ts +5 -0
- package/dist/providers/model-effort.js +43 -0
- package/dist/providers/model-registry.d.ts +39 -0
- package/dist/providers/model-registry.js +142 -0
- package/dist/providers/models-dev.d.ts +9 -0
- package/dist/providers/models-dev.js +97 -0
- package/dist/providers/oauth-callback-server.d.ts +28 -0
- package/dist/providers/oauth-callback-server.js +184 -0
- package/dist/providers/oauth-orchestrator.d.ts +58 -0
- package/dist/providers/oauth-orchestrator.js +159 -0
- package/dist/providers/oauth-store.d.ts +12 -0
- package/dist/providers/oauth-store.js +139 -0
- package/dist/providers/open-browser.d.ts +20 -0
- package/dist/providers/open-browser.js +92 -0
- package/dist/providers/openai-compat.d.ts +14 -0
- package/dist/providers/openai-compat.js +523 -0
- package/dist/providers/openai-oauth.d.ts +15 -0
- package/dist/providers/openai-oauth.js +382 -0
- package/dist/providers/openrouter-auth.d.ts +73 -0
- package/dist/providers/openrouter-auth.js +321 -0
- package/dist/providers/openrouter-manual-fallback.d.ts +25 -0
- package/dist/providers/openrouter-manual-fallback.js +161 -0
- package/dist/providers/openrouter.d.ts +15 -0
- package/dist/providers/openrouter.js +107 -0
- package/dist/providers/plan-limits.d.ts +6 -0
- package/dist/providers/plan-limits.js +175 -0
- package/dist/providers/provider-reset.d.ts +4 -0
- package/dist/providers/provider-reset.js +83 -0
- package/dist/providers/quota-limits.d.ts +4 -0
- package/dist/providers/quota-limits.js +33 -0
- package/dist/providers/registry.d.ts +33 -0
- package/dist/providers/registry.js +213 -0
- package/dist/providers/retry.d.ts +37 -0
- package/dist/providers/retry.js +347 -0
- package/dist/rpc/server.d.ts +23 -0
- package/dist/rpc/server.js +222 -0
- package/dist/sdk.d.ts +67 -0
- package/dist/sdk.js +64 -0
- package/dist/skills/skills.d.ts +17 -0
- package/dist/skills/skills.js +155 -0
- package/dist/text-sanitize.js +28 -0
- package/dist/tools/ask-user.d.ts +2 -0
- package/dist/tools/ask-user.js +60 -0
- package/dist/tools/builtin.d.ts +48 -0
- package/dist/tools/builtin.js +2494 -0
- package/dist/tools/capabilities.d.ts +5 -0
- package/dist/tools/capabilities.js +55 -0
- package/dist/tools/computer-capture.d.ts +2 -0
- package/dist/tools/computer-capture.js +91 -0
- package/dist/tools/computer-posix.d.ts +5 -0
- package/dist/tools/computer-posix.js +136 -0
- package/dist/tools/computer-use.d.ts +14 -0
- package/dist/tools/computer-use.js +108 -0
- package/dist/tools/discovery.d.ts +12 -0
- package/dist/tools/discovery.js +205 -0
- package/dist/tools/execute.d.ts +2 -0
- package/dist/tools/execute.js +73 -0
- package/dist/tools/normalize-input.d.ts +17 -0
- package/dist/tools/normalize-input.js +174 -0
- package/dist/tools/output-artifact.d.ts +3 -0
- package/dist/tools/output-artifact.js +80 -0
- package/dist/tools/pagination.d.ts +15 -0
- package/dist/tools/pagination.js +93 -0
- package/dist/tools/plan-status.d.ts +2 -0
- package/dist/tools/plan-status.js +109 -0
- package/dist/tools/program-input.d.ts +3 -0
- package/dist/tools/program-input.js +19 -0
- package/dist/tools/program.d.ts +3 -0
- package/dist/tools/program.js +567 -0
- package/dist/tools/protocol-catalog.d.ts +12 -0
- package/dist/tools/protocol-catalog.js +46 -0
- package/dist/tools/ramification-tools.d.ts +12 -0
- package/dist/tools/ramification-tools.js +528 -0
- package/dist/tools/regex-compat.d.ts +9 -0
- package/dist/tools/regex-compat.js +96 -0
- package/dist/tools/registry.d.ts +51 -0
- package/dist/tools/registry.js +185 -0
- package/dist/tools/resolve.d.ts +2 -0
- package/dist/tools/resolve.js +107 -0
- package/dist/tools/shell-env.d.ts +2 -0
- package/dist/tools/shell-env.js +7 -0
- package/dist/tools/team-input.d.ts +3 -0
- package/dist/tools/team-input.js +129 -0
- package/dist/tools/team-tools.d.ts +7 -0
- package/dist/tools/team-tools.js +348 -0
- package/dist/tools/workspace-sessions.d.ts +2 -0
- package/dist/tools/workspace-sessions.js +35 -0
- package/dist/tui/account-entry.d.ts +1 -0
- package/dist/tui/account-entry.js +93 -0
- package/dist/tui/attachment-highlight.d.ts +1 -0
- package/dist/tui/attachment-highlight.js +24 -0
- package/dist/tui/attachment-refs.d.ts +2 -0
- package/dist/tui/attachment-refs.js +3 -0
- package/dist/tui/bottom-input.d.ts +219 -0
- package/dist/tui/bottom-input.js +1958 -0
- package/dist/tui/branding.d.ts +107 -0
- package/dist/tui/branding.js +750 -0
- package/dist/tui/clipboard-image.d.ts +10 -0
- package/dist/tui/clipboard-image.js +163 -0
- package/dist/tui/clipboard-text.d.ts +9 -0
- package/dist/tui/clipboard-text.js +51 -0
- package/dist/tui/clipboard-windows.d.ts +8 -0
- package/dist/tui/clipboard-windows.js +84 -0
- package/dist/tui/collapsible-command.d.ts +15 -0
- package/dist/tui/collapsible-command.js +48 -0
- package/dist/tui/command-feedback.d.ts +10 -0
- package/dist/tui/command-feedback.js +46 -0
- package/dist/tui/command-output-registry.d.ts +28 -0
- package/dist/tui/command-output-registry.js +103 -0
- package/dist/tui/command-transcript.d.ts +12 -0
- package/dist/tui/command-transcript.js +90 -0
- package/dist/tui/commands.d.ts +20 -0
- package/dist/tui/commands.js +131 -0
- package/dist/tui/context-bar.d.ts +4 -0
- package/dist/tui/context-bar.js +74 -0
- package/dist/tui/context-meter.d.ts +25 -0
- package/dist/tui/context-meter.js +81 -0
- package/dist/tui/cost-binding.d.ts +8 -0
- package/dist/tui/cost-binding.js +43 -0
- package/dist/tui/cost-tracker.d.ts +49 -0
- package/dist/tui/cost-tracker.js +122 -0
- package/dist/tui/diff.d.ts +9 -0
- package/dist/tui/diff.js +119 -0
- package/dist/tui/i18n-catalog.d.ts +5 -0
- package/dist/tui/i18n-catalog.js +184 -0
- package/dist/tui/i18n.d.ts +6 -0
- package/dist/tui/i18n.js +10 -0
- package/dist/tui/image-attachments.d.ts +46 -0
- package/dist/tui/image-attachments.js +167 -0
- package/dist/tui/images.d.ts +12 -0
- package/dist/tui/images.js +87 -0
- package/dist/tui/intro.d.ts +13 -0
- package/dist/tui/intro.js +109 -0
- package/dist/tui/language-preference.d.ts +6 -0
- package/dist/tui/language-preference.js +24 -0
- package/dist/tui/live-output.d.ts +2 -0
- package/dist/tui/live-output.js +18 -0
- package/dist/tui/locales.d.ts +19 -0
- package/dist/tui/locales.js +22 -0
- package/dist/tui/login-menu.d.ts +17 -0
- package/dist/tui/login-menu.js +58 -0
- package/dist/tui/logo.d.ts +8 -0
- package/dist/tui/logo.js +305 -0
- package/dist/tui/markdown-inline.d.ts +3 -0
- package/dist/tui/markdown-inline.js +99 -0
- package/dist/tui/markdown-table.d.ts +4 -0
- package/dist/tui/markdown-table.js +63 -0
- package/dist/tui/markdown.d.ts +11 -0
- package/dist/tui/markdown.js +257 -0
- package/dist/tui/mcp-transcript.d.ts +7 -0
- package/dist/tui/mcp-transcript.js +40 -0
- package/dist/tui/model-details.d.ts +2 -0
- package/dist/tui/model-details.js +21 -0
- package/dist/tui/model-selection.d.ts +7 -0
- package/dist/tui/model-selection.js +41 -0
- package/dist/tui/native-scrollback.d.ts +27 -0
- package/dist/tui/native-scrollback.js +134 -0
- package/dist/tui/onboarding.d.ts +72 -0
- package/dist/tui/onboarding.js +207 -0
- package/dist/tui/paste-collapse.d.ts +39 -0
- package/dist/tui/paste-collapse.js +117 -0
- package/dist/tui/perm-mode.d.ts +8 -0
- package/dist/tui/perm-mode.js +41 -0
- package/dist/tui/prompt-queue-store.d.ts +26 -0
- package/dist/tui/prompt-queue-store.js +87 -0
- package/dist/tui/prompt-queue.d.ts +47 -0
- package/dist/tui/prompt-queue.js +187 -0
- package/dist/tui/provider-menu.d.ts +33 -0
- package/dist/tui/provider-menu.js +175 -0
- package/dist/tui/question.d.ts +24 -0
- package/dist/tui/question.js +32 -0
- package/dist/tui/queue-screen.d.ts +25 -0
- package/dist/tui/queue-screen.js +152 -0
- package/dist/tui/queue-team.d.ts +3 -0
- package/dist/tui/queue-team.js +28 -0
- package/dist/tui/queued-questions.d.ts +20 -0
- package/dist/tui/queued-questions.js +163 -0
- package/dist/tui/quick-help.d.ts +1 -0
- package/dist/tui/quick-help.js +53 -0
- package/dist/tui/repl.d.ts +78 -0
- package/dist/tui/repl.js +4130 -0
- package/dist/tui/restore-queued-input.d.ts +3 -0
- package/dist/tui/restore-queued-input.js +20 -0
- package/dist/tui/review-detail.d.ts +6 -0
- package/dist/tui/review-detail.js +56 -0
- package/dist/tui/review-files.d.ts +3 -0
- package/dist/tui/review-files.js +22 -0
- package/dist/tui/review-render.d.ts +22 -0
- package/dist/tui/review-render.js +98 -0
- package/dist/tui/review-screen.d.ts +38 -0
- package/dist/tui/review-screen.js +358 -0
- package/dist/tui/review-store.d.ts +60 -0
- package/dist/tui/review-store.js +270 -0
- package/dist/tui/review-team.d.ts +2 -0
- package/dist/tui/review-team.js +27 -0
- package/dist/tui/selector-mouse.d.ts +26 -0
- package/dist/tui/selector-mouse.js +65 -0
- package/dist/tui/selector.d.ts +51 -0
- package/dist/tui/selector.js +299 -0
- package/dist/tui/session-replay.d.ts +10 -0
- package/dist/tui/session-replay.js +78 -0
- package/dist/tui/session-usage.d.ts +22 -0
- package/dist/tui/session-usage.js +55 -0
- package/dist/tui/skill-transcript.d.ts +5 -0
- package/dist/tui/skill-transcript.js +31 -0
- package/dist/tui/startup.d.ts +5 -0
- package/dist/tui/startup.js +61 -0
- package/dist/tui/status-line-loader.d.ts +8 -0
- package/dist/tui/status-line-loader.js +33 -0
- package/dist/tui/status-line.d.ts +38 -0
- package/dist/tui/status-line.js +213 -0
- package/dist/tui/system-language.d.ts +8 -0
- package/dist/tui/system-language.js +41 -0
- package/dist/tui/task-labels.d.ts +2 -0
- package/dist/tui/task-labels.js +7 -0
- package/dist/tui/term-bg.d.ts +4 -0
- package/dist/tui/term-bg.js +67 -0
- package/dist/tui/terminal-screen.d.ts +12 -0
- package/dist/tui/terminal-screen.js +1 -0
- package/dist/tui/terminal-text.d.ts +7 -0
- package/dist/tui/terminal-text.js +123 -0
- package/dist/tui/theme.d.ts +25 -0
- package/dist/tui/theme.js +383 -0
- package/dist/tui/tool-style.d.ts +7 -0
- package/dist/tui/tool-style.js +119 -0
- package/dist/tui/update-prompt.d.ts +14 -0
- package/dist/tui/update-prompt.js +104 -0
- package/dist/tui/usage-footer.d.ts +9 -0
- package/dist/tui/usage-footer.js +123 -0
- package/dist/tui/vascend-login.d.ts +68 -0
- package/dist/tui/vascend-login.js +355 -0
- package/dist/tui/web-login.d.ts +28 -0
- package/dist/tui/web-login.js +115 -0
- package/dist/vascend/activity-status.d.ts +12 -0
- package/dist/vascend/activity-status.js +68 -0
- package/dist/vascend/architecture-map.d.ts +73 -0
- package/dist/vascend/architecture-map.js +424 -0
- package/dist/vascend/attention-layout.d.ts +19 -0
- package/dist/vascend/attention-layout.js +141 -0
- package/dist/vascend/budget-allocator.d.ts +31 -0
- package/dist/vascend/budget-allocator.js +79 -0
- package/dist/vascend/candidate-collector.d.ts +20 -0
- package/dist/vascend/candidate-collector.js +220 -0
- package/dist/vascend/code-events.d.ts +24 -0
- package/dist/vascend/code-events.js +304 -0
- package/dist/vascend/code-graph-memory.d.ts +38 -0
- package/dist/vascend/code-graph-memory.js +334 -0
- package/dist/vascend/code-graph-runtime.d.ts +19 -0
- package/dist/vascend/code-graph-runtime.js +190 -0
- package/dist/vascend/code-graph-types.d.ts +58 -0
- package/dist/vascend/code-graph-types.js +50 -0
- package/dist/vascend/code-parser.d.ts +4 -0
- package/dist/vascend/code-parser.js +257 -0
- package/dist/vascend/competitor-knowledge.d.ts +53 -0
- package/dist/vascend/competitor-knowledge.js +262 -0
- package/dist/vascend/completeness.d.ts +16 -0
- package/dist/vascend/completeness.js +90 -0
- package/dist/vascend/context-autotuner.d.ts +45 -0
- package/dist/vascend/context-autotuner.js +231 -0
- package/dist/vascend/context-candidate.d.ts +45 -0
- package/dist/vascend/context-candidate.js +150 -0
- package/dist/vascend/context-capsule.d.ts +51 -0
- package/dist/vascend/context-capsule.js +133 -0
- package/dist/vascend/context-fabric.d.ts +108 -0
- package/dist/vascend/context-fabric.js +480 -0
- package/dist/vascend/context-feedback-loop.d.ts +56 -0
- package/dist/vascend/context-feedback-loop.js +204 -0
- package/dist/vascend/context-learning-identity.d.ts +4 -0
- package/dist/vascend/context-learning-identity.js +8 -0
- package/dist/vascend/context-links.d.ts +14 -0
- package/dist/vascend/context-links.js +83 -0
- package/dist/vascend/context-lint.d.ts +22 -0
- package/dist/vascend/context-lint.js +91 -0
- package/dist/vascend/context-market-selection.d.ts +17 -0
- package/dist/vascend/context-market-selection.js +50 -0
- package/dist/vascend/context-metrics.d.ts +25 -0
- package/dist/vascend/context-metrics.js +57 -0
- package/dist/vascend/context-pack-render.d.ts +16 -0
- package/dist/vascend/context-pack-render.js +52 -0
- package/dist/vascend/context-pareto.d.ts +33 -0
- package/dist/vascend/context-pareto.js +165 -0
- package/dist/vascend/context-pattern-explorer.d.ts +41 -0
- package/dist/vascend/context-pattern-explorer.js +276 -0
- package/dist/vascend/context-regret.d.ts +32 -0
- package/dist/vascend/context-regret.js +93 -0
- package/dist/vascend/context-retriever.d.ts +22 -0
- package/dist/vascend/context-retriever.js +243 -0
- package/dist/vascend/context-scope-index.d.ts +5 -0
- package/dist/vascend/context-scope-index.js +96 -0
- package/dist/vascend/context-scorer.d.ts +35 -0
- package/dist/vascend/context-scorer.js +162 -0
- package/dist/vascend/context-search-index.d.ts +12 -0
- package/dist/vascend/context-search-index.js +25 -0
- package/dist/vascend/context-snapshot.d.ts +22 -0
- package/dist/vascend/context-snapshot.js +135 -0
- package/dist/vascend/context-window-compiler.d.ts +42 -0
- package/dist/vascend/context-window-compiler.js +237 -0
- package/dist/vascend/contract-memory.d.ts +61 -0
- package/dist/vascend/contract-memory.js +435 -0
- package/dist/vascend/council.d.ts +58 -0
- package/dist/vascend/council.js +337 -0
- package/dist/vascend/decision-promotion.d.ts +48 -0
- package/dist/vascend/decision-promotion.js +410 -0
- package/dist/vascend/delta-context.d.ts +12 -0
- package/dist/vascend/delta-context.js +36 -0
- package/dist/vascend/dev-context-compiler.d.ts +27 -0
- package/dist/vascend/dev-context-compiler.js +133 -0
- package/dist/vascend/dev-context-layout.d.ts +30 -0
- package/dist/vascend/dev-context-layout.js +262 -0
- package/dist/vascend/evidence-slots.d.ts +14 -0
- package/dist/vascend/evidence-slots.js +55 -0
- package/dist/vascend/expansion-levels.d.ts +15 -0
- package/dist/vascend/expansion-levels.js +178 -0
- package/dist/vascend/file-lock.d.ts +7 -0
- package/dist/vascend/file-lock.js +95 -0
- package/dist/vascend/granular-kingdom.d.ts +25 -0
- package/dist/vascend/granular-kingdom.js +259 -0
- package/dist/vascend/granular-launcher.d.ts +48 -0
- package/dist/vascend/granular-launcher.js +202 -0
- package/dist/vascend/kingdom-bus.d.ts +25 -0
- package/dist/vascend/kingdom-bus.js +54 -0
- package/dist/vascend/kingdom-channel.d.ts +22 -0
- package/dist/vascend/kingdom-channel.js +180 -0
- package/dist/vascend/kingdom-kpi.d.ts +48 -0
- package/dist/vascend/kingdom-kpi.js +172 -0
- package/dist/vascend/kingdom-live.d.ts +28 -0
- package/dist/vascend/kingdom-live.js +61 -0
- package/dist/vascend/kingdom-run.d.ts +18 -0
- package/dist/vascend/kingdom-run.js +506 -0
- package/dist/vascend/kingdom-scribe.d.ts +20 -0
- package/dist/vascend/kingdom-scribe.js +52 -0
- package/dist/vascend/kingdom.d.ts +79 -0
- package/dist/vascend/kingdom.js +870 -0
- package/dist/vascend/lexical-index.d.ts +10 -0
- package/dist/vascend/lexical-index.js +99 -0
- package/dist/vascend/lexical-search.d.ts +29 -0
- package/dist/vascend/lexical-search.js +262 -0
- package/dist/vascend/long-term-context.d.ts +51 -0
- package/dist/vascend/long-term-context.js +194 -0
- package/dist/vascend/mandate.d.ts +33 -0
- package/dist/vascend/mandate.js +107 -0
- package/dist/vascend/memory-packet.d.ts +13 -0
- package/dist/vascend/memory-packet.js +155 -0
- package/dist/vascend/memory-status.d.ts +22 -0
- package/dist/vascend/memory-status.js +73 -0
- package/dist/vascend/memory-store.d.ts +62 -0
- package/dist/vascend/memory-store.js +273 -0
- package/dist/vascend/objective-revision.d.ts +69 -0
- package/dist/vascend/objective-revision.js +319 -0
- package/dist/vascend/patch-plan-store.d.ts +33 -0
- package/dist/vascend/patch-plan-store.js +240 -0
- package/dist/vascend/patch-plan.d.ts +97 -0
- package/dist/vascend/patch-plan.js +345 -0
- package/dist/vascend/plan-progress.d.ts +11 -0
- package/dist/vascend/plan-progress.js +68 -0
- package/dist/vascend/plan-store.d.ts +64 -0
- package/dist/vascend/plan-store.js +460 -0
- package/dist/vascend/proof-chains.d.ts +19 -0
- package/dist/vascend/proof-chains.js +120 -0
- package/dist/vascend/ramification-store.d.ts +25 -0
- package/dist/vascend/ramification-store.js +94 -0
- package/dist/vascend/ramification.d.ts +193 -0
- package/dist/vascend/ramification.js +583 -0
- package/dist/vascend/recall-planner.d.ts +17 -0
- package/dist/vascend/recall-planner.js +109 -0
- package/dist/vascend/requirements.d.ts +31 -0
- package/dist/vascend/requirements.js +151 -0
- package/dist/vascend/reviewer.d.ts +9 -0
- package/dist/vascend/reviewer.js +93 -0
- package/dist/vascend/room-graph.d.ts +29 -0
- package/dist/vascend/room-graph.js +242 -0
- package/dist/vascend/room-memory.d.ts +57 -0
- package/dist/vascend/room-memory.js +631 -0
- package/dist/vascend/runtime.d.ts +84 -0
- package/dist/vascend/runtime.js +286 -0
- package/dist/vascend/self-improve.d.ts +104 -0
- package/dist/vascend/self-improve.js +396 -0
- package/dist/vascend/session-search.d.ts +52 -0
- package/dist/vascend/session-search.js +349 -0
- package/dist/vascend/supersession-graph.d.ts +14 -0
- package/dist/vascend/supersession-graph.js +70 -0
- package/dist/vascend/team-areas.d.ts +9 -0
- package/dist/vascend/team-areas.js +28 -0
- package/dist/vascend/team-handoff.d.ts +24 -0
- package/dist/vascend/team-handoff.js +37 -0
- package/dist/vascend/team-scheduler.d.ts +13 -0
- package/dist/vascend/team-scheduler.js +74 -0
- package/dist/vascend/team-session.d.ts +42 -0
- package/dist/vascend/team-session.js +142 -0
- package/dist/vascend/test-failure-memory.d.ts +76 -0
- package/dist/vascend/test-failure-memory.js +354 -0
- package/dist/vascend/token-market.d.ts +42 -0
- package/dist/vascend/token-market.js +144 -0
- package/dist/vascend/tuner-baseline-store.d.ts +52 -0
- package/dist/vascend/tuner-baseline-store.js +446 -0
- package/dist/vascend/user-profile.d.ts +44 -0
- package/dist/vascend/user-profile.js +131 -0
- package/dist/vascend/vision.d.ts +94 -0
- package/dist/vascend/vision.js +375 -0
- package/dist/vascend/work-agent.d.ts +12 -0
- package/dist/vascend/work-agent.js +83 -0
- package/dist/vascend/work-queue.d.ts +62 -0
- package/dist/vascend/work-queue.js +255 -0
- package/dist/vascend/work-runner.d.ts +64 -0
- package/dist/vascend/work-runner.js +137 -0
- package/dist/vascend/worktree.d.ts +38 -0
- package/dist/vascend/worktree.js +206 -0
- package/dist/vendor/computer-use/README.md +7 -0
- package/dist/vendor/computer-use/computer-desktop.js +211 -0
- package/dist/vendor/computer-use/computer-observe.js +315 -0
- package/dist/vendor/computer-use/computer-scripts.js +1230 -0
- package/dist/vendor/computer-use/computer-tools.js +2136 -0
- package/dist/vendor/computer-use/package.json +1 -0
- package/dist/vendor/computer-use/rac/atomic-input.js +91 -0
- package/dist/vendor/computer-use/rac/grammatica.js +101 -0
- package/dist/vendor/computer-use/rac/parser.js +185 -0
- package/dist/vendor/computer-use/rac/protocol.js +136 -0
- package/install.ps1 +30 -0
- package/install.sh +50 -0
- package/package.json +56 -0
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import type { Message } from "../core/types.js";
|
|
2
|
+
import { RoomGraph, type RoomEdge, type RoomNeighbor } from "./room-graph.js";
|
|
3
|
+
export interface RoomRecord {
|
|
4
|
+
readonly room: string;
|
|
5
|
+
readonly level: number;
|
|
6
|
+
readonly title: string;
|
|
7
|
+
readonly terms: readonly string[];
|
|
8
|
+
readonly body: string;
|
|
9
|
+
readonly children: readonly string[];
|
|
10
|
+
readonly parent: string | null;
|
|
11
|
+
readonly createdAt: number;
|
|
12
|
+
readonly edges?: readonly RoomEdge[];
|
|
13
|
+
}
|
|
14
|
+
export interface RoomSearchHit {
|
|
15
|
+
readonly record: RoomRecord;
|
|
16
|
+
readonly score: number;
|
|
17
|
+
readonly viaGraph?: boolean;
|
|
18
|
+
readonly via?: readonly string[];
|
|
19
|
+
}
|
|
20
|
+
export declare const DEFAULT_FANOUT = 8;
|
|
21
|
+
export declare const DEFAULT_RECENT_KEEP = 2;
|
|
22
|
+
export declare class RoomMemory {
|
|
23
|
+
private readonly file;
|
|
24
|
+
private readonly fanout;
|
|
25
|
+
private readonly memory;
|
|
26
|
+
private records;
|
|
27
|
+
private synonyms;
|
|
28
|
+
private tokenCache;
|
|
29
|
+
private graphCache;
|
|
30
|
+
private readonly recentKeep;
|
|
31
|
+
private constructor();
|
|
32
|
+
withSynonyms(groups: readonly (readonly string[])[]): this;
|
|
33
|
+
private tokensFor;
|
|
34
|
+
private indexedDocs;
|
|
35
|
+
static open(sessionDir: string, sessionId: string, fanout?: number): RoomMemory;
|
|
36
|
+
count(): number;
|
|
37
|
+
all(): readonly RoomRecord[];
|
|
38
|
+
frontier(): readonly RoomRecord[];
|
|
39
|
+
nextId(level: number, ns?: string): string;
|
|
40
|
+
nextRoomId(ns?: string): string;
|
|
41
|
+
append(record: RoomRecord): void;
|
|
42
|
+
filePath(): string;
|
|
43
|
+
reloadFromDisk(): void;
|
|
44
|
+
appendRoomNamespaced(build: (id: string) => RoomRecord, ns: string | undefined): RoomRecord;
|
|
45
|
+
rollup(now: number): boolean;
|
|
46
|
+
byRooms(ids: readonly string[]): readonly RoomRecord[];
|
|
47
|
+
expandRooms(ids: readonly string[]): readonly RoomRecord[];
|
|
48
|
+
search(query: string, limit?: number): readonly RoomSearchHit[];
|
|
49
|
+
graph(): RoomGraph;
|
|
50
|
+
neighbors(room: string, limit?: number): readonly RoomNeighbor[];
|
|
51
|
+
searchGraph(query: string, limit?: number): readonly RoomSearchHit[];
|
|
52
|
+
indexBlock(): string;
|
|
53
|
+
private setParent;
|
|
54
|
+
private persistAll;
|
|
55
|
+
}
|
|
56
|
+
export declare function formatRoomRecord(room: string, messages: readonly Message[], createdAt: number): RoomRecord;
|
|
57
|
+
export declare function formatRollupRecord(id: string, level: number, children: readonly RoomRecord[], createdAt: number): RoomRecord;
|
|
@@ -0,0 +1,631 @@
|
|
|
1
|
+
import { appendFileSync, existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
2
|
+
import { dirname, join } from "node:path";
|
|
3
|
+
import { sanitizeText } from "../core/text-sanitize.js";
|
|
4
|
+
import { MemoryStore } from "./memory-store.js";
|
|
5
|
+
import { STOP, tokenize, buildSynonyms, expandQuery, bm25Score, } from "./lexical-search.js";
|
|
6
|
+
import { withLockSync } from "./file-lock.js";
|
|
7
|
+
import { RoomGraph, clusterByAffinity, clusterLabel, roomEdges, topTerms, } from "./room-graph.js";
|
|
8
|
+
// Peso di un vicino a 2 hop rispetto al seme che lo ha portato. Allineato al
|
|
9
|
+
// peso del link tipizzato in context-retriever.ts: stessa semantica, stesso
|
|
10
|
+
// numero, cosi' recall e compilazione del contesto non si contraddicono.
|
|
11
|
+
const GRAPH_HOP_WEIGHT = 0.68;
|
|
12
|
+
export const DEFAULT_FANOUT = 8;
|
|
13
|
+
const MAX_BODY = 4_000;
|
|
14
|
+
// Quante stanze recenti restano SEMPRE individuali in frontiera (mai assorbite
|
|
15
|
+
// da un rollup): sono il "dove eravamo rimasti" dell'agente. Limitata a
|
|
16
|
+
// fanout-1 perche' con fanout piccoli la gerarchia non si formerebbe mai.
|
|
17
|
+
export const DEFAULT_RECENT_KEEP = 2;
|
|
18
|
+
export class RoomMemory {
|
|
19
|
+
file;
|
|
20
|
+
fanout;
|
|
21
|
+
memory;
|
|
22
|
+
records = [];
|
|
23
|
+
// Indice sinonimi (default; configurabile via withSynonyms) per espandere le
|
|
24
|
+
// query verso forme equivalenti IT/EN.
|
|
25
|
+
synonyms = buildSynonyms();
|
|
26
|
+
// INDICE INVERTITO: i token di ogni record, calcolati una volta sola. Senza
|
|
27
|
+
// questa cache ogni recall ritokenizzava l'intero corpus (misurato: 38 ms su
|
|
28
|
+
// 569 record, crescita lineare). Il corpo di un record non cambia mai dopo la
|
|
29
|
+
// scrittura — solo `parent` viene riassegnato dal rollup, e non entra
|
|
30
|
+
// nell'indice — quindi la chiave e' l'id della stanza.
|
|
31
|
+
tokenCache = new Map();
|
|
32
|
+
// Grafo memoizzato: la firma e' il numero di record (i record esistenti non
|
|
33
|
+
// cambiano mai corpo ne' archi dopo la scrittura).
|
|
34
|
+
graphCache = null;
|
|
35
|
+
recentKeep;
|
|
36
|
+
constructor(file, fanout, memory) {
|
|
37
|
+
this.file = file;
|
|
38
|
+
this.fanout = fanout;
|
|
39
|
+
this.memory = memory;
|
|
40
|
+
this.recentKeep = Math.max(0, Math.min(this.fanout - 1, DEFAULT_RECENT_KEEP));
|
|
41
|
+
}
|
|
42
|
+
// Sostituisce la tabella sinonimi (es. per dominio specifico). Ritorna this
|
|
43
|
+
// per concatenare dopo open(). Deterministico.
|
|
44
|
+
withSynonyms(groups) {
|
|
45
|
+
this.synonyms = buildSynonyms(groups);
|
|
46
|
+
return this;
|
|
47
|
+
}
|
|
48
|
+
// Token indicizzati di un record (memoizzati per id).
|
|
49
|
+
tokensFor(record) {
|
|
50
|
+
const hit = this.tokenCache.get(record.room);
|
|
51
|
+
if (hit)
|
|
52
|
+
return hit;
|
|
53
|
+
const tokens = tokenize(`${record.terms.join(" ")} ${record.title} ${record.body}`);
|
|
54
|
+
this.tokenCache.set(record.room, tokens);
|
|
55
|
+
return tokens;
|
|
56
|
+
}
|
|
57
|
+
// Corpus indicizzato per la ricerca lessicale.
|
|
58
|
+
indexedDocs() {
|
|
59
|
+
return this.records.map((record) => ({ ref: record, tokens: this.tokensFor(record) }));
|
|
60
|
+
}
|
|
61
|
+
static open(sessionDir, sessionId, fanout = DEFAULT_FANOUT) {
|
|
62
|
+
const file = join(sessionDir, `${sessionId}.rooms.jsonl`);
|
|
63
|
+
const mem = new RoomMemory(file, Math.max(2, fanout), MemoryStore.open(sessionDir, sessionId));
|
|
64
|
+
if (existsSync(file)) {
|
|
65
|
+
const raw = readFileSync(file, "utf8");
|
|
66
|
+
for (const line of raw.split("\n")) {
|
|
67
|
+
if (!line.trim())
|
|
68
|
+
continue;
|
|
69
|
+
try {
|
|
70
|
+
mem.records.push(normalize(JSON.parse(line)));
|
|
71
|
+
}
|
|
72
|
+
catch {
|
|
73
|
+
// riga corrotta: ignorata
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
return mem;
|
|
78
|
+
}
|
|
79
|
+
count() {
|
|
80
|
+
return this.records.length;
|
|
81
|
+
}
|
|
82
|
+
all() {
|
|
83
|
+
return this.records;
|
|
84
|
+
}
|
|
85
|
+
// Frontiera: i nodi non ancora compattati in un livello superiore, in ordine.
|
|
86
|
+
frontier() {
|
|
87
|
+
return this.records.filter((r) => r.parent === null).slice().sort((a, b) => a.createdAt - b.createdAt);
|
|
88
|
+
}
|
|
89
|
+
// Prossimo id per un dato livello (R/C/K/L<n>). Con `ns` (slug castello) gli
|
|
90
|
+
// id sono namespaced (es. "auth-R1") e contati per-namespace: evita le
|
|
91
|
+
// collisioni quando piu' vassalli scrivono sullo stesso store del regno.
|
|
92
|
+
nextId(level, ns) {
|
|
93
|
+
const prefix = `${ns ? `${ns}-` : ""}${levelPrefix(level)}`;
|
|
94
|
+
const n = this.records.filter((r) => r.level === level && r.room.startsWith(prefix)).length + 1;
|
|
95
|
+
return `${prefix}${n}`;
|
|
96
|
+
}
|
|
97
|
+
nextRoomId(ns) {
|
|
98
|
+
return this.nextId(0, ns);
|
|
99
|
+
}
|
|
100
|
+
// Aggiunge una stanza (livello 0): fast path append, protetto da lock
|
|
101
|
+
// file-system cosi' due processi concorrenti non interlacciano le righe.
|
|
102
|
+
append(record) {
|
|
103
|
+
this.records.push(record);
|
|
104
|
+
mkdirSync(dirname(this.file), { recursive: true });
|
|
105
|
+
withLockSync(this.file, () => {
|
|
106
|
+
appendFileSync(this.file, JSON.stringify(record) + "\n", "utf8");
|
|
107
|
+
});
|
|
108
|
+
// Sink eventi: emette room.closed nel log append-only multi-dominio
|
|
109
|
+
// (Memory OS) per recall/packet/rollup. Non bloccante.
|
|
110
|
+
this.memory.append(roomEvent("room.closed", record));
|
|
111
|
+
}
|
|
112
|
+
// Percorso del file (per il writer unico/scribe che deve coordinare il lock).
|
|
113
|
+
filePath() {
|
|
114
|
+
return this.file;
|
|
115
|
+
}
|
|
116
|
+
// Ricarica lo stato dal disco (le righe scritte da altri writer da quando
|
|
117
|
+
// questa istanza ha aperto il file). Usato dal writer unico per assegnare id
|
|
118
|
+
// monotoni su una vista FRESCA prima di scrivere.
|
|
119
|
+
reloadFromDisk() {
|
|
120
|
+
// Vista sostituita per intero: gli indici memoizzati non sono piu'
|
|
121
|
+
// affidabili (un writer concorrente puo' aver riscritto lo store).
|
|
122
|
+
this.tokenCache.clear();
|
|
123
|
+
this.graphCache = null;
|
|
124
|
+
if (!existsSync(this.file)) {
|
|
125
|
+
this.records = [];
|
|
126
|
+
return;
|
|
127
|
+
}
|
|
128
|
+
const raw = readFileSync(this.file, "utf8");
|
|
129
|
+
const next = [];
|
|
130
|
+
for (const line of raw.split("\n")) {
|
|
131
|
+
if (!line.trim())
|
|
132
|
+
continue;
|
|
133
|
+
try {
|
|
134
|
+
next.push(normalize(JSON.parse(line)));
|
|
135
|
+
}
|
|
136
|
+
catch {
|
|
137
|
+
// riga corrotta: ignorata
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
this.records = next;
|
|
141
|
+
}
|
|
142
|
+
// WRITER UNICO sicuro: sotto lock cross-processo, ricarica la vista dal
|
|
143
|
+
// disco (ordine autoritativo), costruisce il record con un id MONOTONO
|
|
144
|
+
// calcolato sulla vista fresca (niente collisioni anche con piu' processi)
|
|
145
|
+
// e appende una sola riga atomica. Ritorna il record scritto.
|
|
146
|
+
appendRoomNamespaced(build, ns) {
|
|
147
|
+
mkdirSync(dirname(this.file), { recursive: true });
|
|
148
|
+
const record = withLockSync(this.file, () => {
|
|
149
|
+
this.reloadFromDisk();
|
|
150
|
+
const id = this.nextRoomId(ns);
|
|
151
|
+
const rec = build(id);
|
|
152
|
+
this.records.push(rec);
|
|
153
|
+
appendFileSync(this.file, JSON.stringify(rec) + "\n", "utf8");
|
|
154
|
+
return rec;
|
|
155
|
+
});
|
|
156
|
+
// Sink eventi anche per la scrittura del writer unico.
|
|
157
|
+
this.memory.append(roomEvent("room.closed", record));
|
|
158
|
+
return record;
|
|
159
|
+
}
|
|
160
|
+
// Compatta a cascata: quando un livello ha abbastanza nodi in frontiera, li
|
|
161
|
+
// chiude in nodi padre del livello superiore. Ritorna true se qualcosa e'
|
|
162
|
+
// stato compattato (e persiste l'intero store).
|
|
163
|
+
//
|
|
164
|
+
// Due proprieta' rispetto alla versione a fetta di tempo:
|
|
165
|
+
//
|
|
166
|
+
// AFFINITA' — il gruppo non e' "le prime N in ordine di arrivo" ma il
|
|
167
|
+
// grappolo piu' denso per termini e file condivisi. Un castello torna a
|
|
168
|
+
// essere un'unita' di senso: misurato su 48 stanze interlacciate, la
|
|
169
|
+
// purezza dei padri passa da 0.25 a 0.75 e il payload pertinente di un
|
|
170
|
+
// recall dal 25% al 75%, a parita' di token.
|
|
171
|
+
//
|
|
172
|
+
// RECENZA — le ultime `recentKeep` stanze non vengono mai assorbite:
|
|
173
|
+
// restano in frontiera, individuali e cronologiche. Senza, dopo un rollup
|
|
174
|
+
// il marcatore "TURNO PIU' RECENTE" finiva su un castello e "riprendi da
|
|
175
|
+
// dove eravamo" perdeva il suo aggancio.
|
|
176
|
+
rollup(now) {
|
|
177
|
+
let changed = false;
|
|
178
|
+
let level = 0;
|
|
179
|
+
const maxLevel = () => this.records.reduce((m, r) => Math.max(m, r.level), 0);
|
|
180
|
+
while (level <= maxLevel()) {
|
|
181
|
+
for (;;) {
|
|
182
|
+
const front = this.frontier().filter((r) => r.level === level);
|
|
183
|
+
// La finestra di recenza protegge solo le stanze: ai livelli superiori
|
|
184
|
+
// il dettaglio e' gia' archiviato e l'ordine cronologico non serve a
|
|
185
|
+
// riprendere il lavoro.
|
|
186
|
+
const keep = level === 0 ? this.recentKeep : 0;
|
|
187
|
+
const eligible = keep > 0 ? front.slice(0, Math.max(0, front.length - keep)) : front;
|
|
188
|
+
if (eligible.length < this.fanout)
|
|
189
|
+
break;
|
|
190
|
+
const groups = clusterByAffinity(eligible, this.fanout);
|
|
191
|
+
if (!groups.length)
|
|
192
|
+
break;
|
|
193
|
+
for (const group of groups) {
|
|
194
|
+
const parent = formatRollupRecord(this.nextId(level + 1), level + 1, group, now);
|
|
195
|
+
this.records.push(parent);
|
|
196
|
+
this.memory.append(roomEvent("rollup.created", parent, group));
|
|
197
|
+
for (const child of group)
|
|
198
|
+
this.setParent(child.room, parent.room);
|
|
199
|
+
changed = true;
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
level += 1;
|
|
203
|
+
}
|
|
204
|
+
if (changed)
|
|
205
|
+
this.persistAll();
|
|
206
|
+
return changed;
|
|
207
|
+
}
|
|
208
|
+
byRooms(ids) {
|
|
209
|
+
const want = new Set(ids.map((id) => id.toUpperCase()));
|
|
210
|
+
return this.records.filter((r) => want.has(r.room.toUpperCase()));
|
|
211
|
+
}
|
|
212
|
+
// Espande ricorsivamente nodi gerarchici (castelli/regni/livelli) nei figli,
|
|
213
|
+
// preservando il nodo richiesto come intestazione e deduplicando i discendenti.
|
|
214
|
+
expandRooms(ids) {
|
|
215
|
+
const out = [];
|
|
216
|
+
const seen = new Set();
|
|
217
|
+
const byId = new Map(this.records.map((r) => [r.room.toUpperCase(), r]));
|
|
218
|
+
const visit = (record) => {
|
|
219
|
+
const key = record.room.toUpperCase();
|
|
220
|
+
if (seen.has(key))
|
|
221
|
+
return;
|
|
222
|
+
seen.add(key);
|
|
223
|
+
out.push(record);
|
|
224
|
+
for (const childId of record.children) {
|
|
225
|
+
const child = byId.get(childId.toUpperCase());
|
|
226
|
+
if (child)
|
|
227
|
+
visit(child);
|
|
228
|
+
}
|
|
229
|
+
};
|
|
230
|
+
for (const record of this.byRooms(ids))
|
|
231
|
+
visit(record);
|
|
232
|
+
return out;
|
|
233
|
+
}
|
|
234
|
+
// Ricerca LESSICALE BM25 (offline, deterministica) su TUTTI i livelli: una
|
|
235
|
+
// query puo' colpire una stanza (dettaglio) o un castello/regno (indice ->
|
|
236
|
+
// figli da cui scendere). Aumenta il richiamo su parole non perfettamente
|
|
237
|
+
// coincidenti tramite normalizzazione (fold accenti + stemming), espansione
|
|
238
|
+
// sinonimi e prefix/fuzzy match (vedi lexical-search.ts). API invariata.
|
|
239
|
+
search(query, limit = 5) {
|
|
240
|
+
const qTokens = unique(tokenize(query));
|
|
241
|
+
if (!qTokens.length) {
|
|
242
|
+
return this.frontier().slice(-limit).reverse().map((record) => ({ record, score: 0 }));
|
|
243
|
+
}
|
|
244
|
+
const docs = this.indexedDocs();
|
|
245
|
+
const weighted = expandQuery(qTokens, this.synonyms);
|
|
246
|
+
const scored = bm25Score(docs, weighted);
|
|
247
|
+
// RECENCY BIAS (freshness): a parita' o quasi-parita' di rilevanza vince la
|
|
248
|
+
// stanza piu' RECENTE. Senza, il recall pescava task vecchi gia' risolti
|
|
249
|
+
// invece del turno precedente. Rank ordinale deterministico in [0,1]
|
|
250
|
+
// (0=piu' vecchio, 1=piu' recente) applicato come moltiplicatore lieve: una
|
|
251
|
+
// forte rilevanza testuale di una stanza vecchia puo' ancora prevalere.
|
|
252
|
+
const minT = this.records.reduce((m, r) => Math.min(m, r.createdAt), Infinity);
|
|
253
|
+
const maxT = this.records.reduce((m, r) => Math.max(m, r.createdAt), -Infinity);
|
|
254
|
+
const span = maxT - minT || 1;
|
|
255
|
+
const RECENCY_WEIGHT = 0.2;
|
|
256
|
+
// Posizione di append: tie-break finale quando i timestamp coincidono
|
|
257
|
+
// (append rapidi nello stesso ms) -> l'ultimo scritto e' il piu' recente.
|
|
258
|
+
const pos = new Map(this.records.map((r, i) => [r.room, i]));
|
|
259
|
+
return scored
|
|
260
|
+
.filter((h) => h.score > 0)
|
|
261
|
+
.map((h) => {
|
|
262
|
+
const rank = (h.ref.createdAt - minT) / span; // 0..1
|
|
263
|
+
return { record: h.ref, score: h.score * (1 + RECENCY_WEIGHT * rank) };
|
|
264
|
+
})
|
|
265
|
+
.sort((a, b) => b.score - a.score ||
|
|
266
|
+
b.record.createdAt - a.record.createdAt ||
|
|
267
|
+
(pos.get(b.record.room) ?? 0) - (pos.get(a.record.room) ?? 0))
|
|
268
|
+
.slice(0, limit);
|
|
269
|
+
}
|
|
270
|
+
// Grafo degli archi tipizzati (stanza -> file -> stanza). Memoizzato: il
|
|
271
|
+
// numero di record e' la firma, e i record esistenti non cambiano corpo.
|
|
272
|
+
graph() {
|
|
273
|
+
const cached = this.graphCache;
|
|
274
|
+
if (cached && cached.size === this.records.length)
|
|
275
|
+
return cached.graph;
|
|
276
|
+
const graph = RoomGraph.build(this.records);
|
|
277
|
+
this.graphCache = { size: this.records.length, graph };
|
|
278
|
+
return graph;
|
|
279
|
+
}
|
|
280
|
+
// Stanze vicine: hanno toccato almeno un file in comune con `room`.
|
|
281
|
+
neighbors(room, limit = 8) {
|
|
282
|
+
return this.graph().neighbors(room, limit);
|
|
283
|
+
}
|
|
284
|
+
// Ricerca lessicale + TRAVERSATA a un hop. I match diretti restano i piu'
|
|
285
|
+
// forti; i vicini entrano con peso ridotto e possono spodestare solo le code
|
|
286
|
+
// lessicali deboli. Risponde a "chi altro ha messo le mani qui", che la sola
|
|
287
|
+
// BM25 non puo' vedere: due stanze possono descrivere lo stesso file con
|
|
288
|
+
// parole completamente diverse.
|
|
289
|
+
searchGraph(query, limit = 5) {
|
|
290
|
+
const direct = this.search(query, limit);
|
|
291
|
+
if (!direct.length)
|
|
292
|
+
return direct;
|
|
293
|
+
const graph = this.graph();
|
|
294
|
+
const byId = new Map(this.records.map((r) => [r.room, r]));
|
|
295
|
+
const merged = new Map(direct.map((h) => [h.record.room, h]));
|
|
296
|
+
const seeds = direct.filter((h) => h.record.level === 0).slice(0, 3);
|
|
297
|
+
for (const seed of seeds) {
|
|
298
|
+
for (const neighbor of graph.neighbors(seed.record.room, limit)) {
|
|
299
|
+
if (merged.has(neighbor.room))
|
|
300
|
+
continue;
|
|
301
|
+
const record = byId.get(neighbor.room);
|
|
302
|
+
if (!record)
|
|
303
|
+
continue;
|
|
304
|
+
merged.set(neighbor.room, {
|
|
305
|
+
record,
|
|
306
|
+
score: seed.score * GRAPH_HOP_WEIGHT,
|
|
307
|
+
viaGraph: true,
|
|
308
|
+
via: neighbor.via,
|
|
309
|
+
});
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
return [...merged.values()]
|
|
313
|
+
.sort((a, b) => b.score - a.score ||
|
|
314
|
+
Number(Boolean(a.viaGraph)) - Number(Boolean(b.viaGraph)) ||
|
|
315
|
+
b.record.createdAt - a.record.createdAt ||
|
|
316
|
+
a.record.room.localeCompare(b.record.room))
|
|
317
|
+
.slice(0, limit);
|
|
318
|
+
}
|
|
319
|
+
// INDICE della frontiera: il blocco compatto iniettato nel contesto (diventa
|
|
320
|
+
// il riassunto di compattazione). Elenca i nodi di frontiera (stanze sciolte
|
|
321
|
+
// + castelli/regni gia' chiusi) e istruisce l'uso di recall per scendere.
|
|
322
|
+
indexBlock() {
|
|
323
|
+
const front = this.frontier(); // ordine cronologico: vecchio -> recente
|
|
324
|
+
if (!front.length)
|
|
325
|
+
return "";
|
|
326
|
+
const last = front.length - 1;
|
|
327
|
+
const rows = front
|
|
328
|
+
.map((r, i) => {
|
|
329
|
+
const marker = i === last ? " <- TURNO PIU' RECENTE" : "";
|
|
330
|
+
return `${i + 1}. @${levelLabel(r.level)}[${r.room}]: "${escapeValue(r.title)}" · termini=${r.terms.slice(0, 8).join(",")}${marker}`;
|
|
331
|
+
})
|
|
332
|
+
.join("\n");
|
|
333
|
+
return `ATTIVITA_ARCHIVIATE (ordine cronologico: prima le piu' vecchie, ultima la piu' recente)
|
|
334
|
+
Il lavoro precedente e' ARCHIVIATO fuori dal contesto vivo, in attivita raccolte
|
|
335
|
+
in gruppi e liste. Per recuperarne il dettaglio usa il tool "recall" (per query
|
|
336
|
+
o per id, anche scendendo da un gruppo alle sue attivita) invece di chiedere di
|
|
337
|
+
ripetere: il contesto resta compatto.
|
|
338
|
+
Per RIPRENDERE il lavoro appena svolto parti dalla voce piu' in basso (il turno
|
|
339
|
+
piu' recente, marcato), NON da quelle sopra: quelle sono turni gia' conclusi.
|
|
340
|
+
|
|
341
|
+
${rows}
|
|
342
|
+
|
|
343
|
+
OUTPUT: contesto compatto; dettaglio recuperabile a ogni livello via recall.`;
|
|
344
|
+
}
|
|
345
|
+
setParent(childId, parentId) {
|
|
346
|
+
const i = this.records.findIndex((r) => r.room === childId);
|
|
347
|
+
if (i >= 0)
|
|
348
|
+
this.records[i] = { ...this.records[i], parent: parentId };
|
|
349
|
+
}
|
|
350
|
+
persistAll() {
|
|
351
|
+
mkdirSync(dirname(this.file), { recursive: true });
|
|
352
|
+
withLockSync(this.file, () => {
|
|
353
|
+
writeFileSync(this.file, this.records.map((r) => JSON.stringify(r)).join("\n") + "\n", "utf8");
|
|
354
|
+
});
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
function roomEvent(type, record, children = []) {
|
|
358
|
+
return {
|
|
359
|
+
type,
|
|
360
|
+
domain: "rooms",
|
|
361
|
+
subject: record.room,
|
|
362
|
+
summary: record.title,
|
|
363
|
+
body: record.body,
|
|
364
|
+
terms: record.terms,
|
|
365
|
+
links: children.map((child) => ({ rel: "contains", target: child.room, domain: "rooms" })),
|
|
366
|
+
payload: { room: record },
|
|
367
|
+
createdAt: record.createdAt,
|
|
368
|
+
};
|
|
369
|
+
}
|
|
370
|
+
// Record Danilov compatto di una STANZA (livello 0) dai messaggi del turno.
|
|
371
|
+
export function formatRoomRecord(room, messages, createdAt) {
|
|
372
|
+
const title = roomTitle(messages);
|
|
373
|
+
const tools = collectToolCalls(messages);
|
|
374
|
+
const files = collectFiles(messages);
|
|
375
|
+
const output = lastAssistantText(messages);
|
|
376
|
+
const terms = cleanTerms([
|
|
377
|
+
...tokenize(title).slice(0, 6),
|
|
378
|
+
...tools.map((t) => t.name),
|
|
379
|
+
...files.map((f) => baseName(f)),
|
|
380
|
+
]).slice(0, 12);
|
|
381
|
+
const def = [
|
|
382
|
+
`@goal[${room}]: "${escapeValue(title)}"`,
|
|
383
|
+
...tools.slice(0, 12).map((t, i) => `@tool[${room}.${i + 1}]: ${t.name}(${escapeValue(t.arg)}) -> ${escapeValue(t.result)}`),
|
|
384
|
+
...files.slice(0, 12).map((f, i) => `@file[${room}.${i + 1}]: ${escapeValue(f)}`),
|
|
385
|
+
].join("\n");
|
|
386
|
+
const rel = tools.length
|
|
387
|
+
? `@R: ${room} -> ${tools.slice(0, 8).map((t) => t.name).join(" -> ")}`
|
|
388
|
+
: `@R: ${room} -> nessuno_strumento`;
|
|
389
|
+
// Archi tipizzati: i file e i tool del turno sono gia' estratti qui sopra,
|
|
390
|
+
// quindi il grafo costa zero a scrittura.
|
|
391
|
+
const edges = roomEdges(files, tools.map((t) => t.name));
|
|
392
|
+
const body = clampBody(`INDICE
|
|
393
|
+
${numberedIndex(terms)}
|
|
394
|
+
|
|
395
|
+
DEFINIZIONI
|
|
396
|
+
${def}
|
|
397
|
+
|
|
398
|
+
RELAZIONI
|
|
399
|
+
${rel}
|
|
400
|
+
|
|
401
|
+
OUTPUT: ${escapeValue(output) || "(nessun output testuale)"}`);
|
|
402
|
+
return { room, level: 0, title, terms, body, children: [], parent: null, createdAt, edges };
|
|
403
|
+
}
|
|
404
|
+
// Record di ROLLUP (castello/regno/...): indice sui figli che ha chiuso.
|
|
405
|
+
export function formatRollupRecord(id, level, children, createdAt) {
|
|
406
|
+
const label = levelLabel(level);
|
|
407
|
+
const childLabel = levelLabel(level - 1);
|
|
408
|
+
const childCountLabel = level === 1 ? "attivita" : level === 2 ? "gruppi" : "liste";
|
|
409
|
+
// Termini RICORRENTI nel gruppo, non l'unione piatta: descrivono il nodo
|
|
410
|
+
// padre invece di elencare tutto quello che c'e' sotto.
|
|
411
|
+
const recurring = topTerms(children, 16);
|
|
412
|
+
const terms = cleanTerms(recurring.length ? recurring : children.flatMap((c) => c.terms)).slice(0, 16);
|
|
413
|
+
// Titolo ONESTO: l'area comune + i termini ricorrenti. Prima era il titolo
|
|
414
|
+
// del PRIMO figlio con "… +7" in coda, quindi un castello si annunciava col
|
|
415
|
+
// nome di un ottavo del suo contenuto e sviava sia l'agente sia la ricerca.
|
|
416
|
+
const title = children.length > 1
|
|
417
|
+
? `${clusterLabel(children)} · ${children.length} ${childCountLabel}`.slice(0, 160)
|
|
418
|
+
: oneLine(children[0]?.title ?? "").slice(0, 120);
|
|
419
|
+
const rows = children
|
|
420
|
+
.map((c) => `@${childLabel}[${c.room}]: "${escapeValue(c.title)}" · termini=${c.terms.slice(0, 8).join(",")}`)
|
|
421
|
+
.join("\n");
|
|
422
|
+
const body = clampBody(`RIEPILOGO_${label.toUpperCase()} ${id}
|
|
423
|
+
Elementi archiviati: ${children.length}. Per il dettaglio
|
|
424
|
+
di un figlio usa recall(rooms:["${children[0]?.room ?? ""}", ...]) o una query.
|
|
425
|
+
|
|
426
|
+
INDICE
|
|
427
|
+
${numberedIndex(terms)}
|
|
428
|
+
|
|
429
|
+
${cap(childLabel)}
|
|
430
|
+
${rows}
|
|
431
|
+
|
|
432
|
+
OUTPUT: riepilogo delle attivita; apri i dettagli col tool recall.`);
|
|
433
|
+
return {
|
|
434
|
+
room: id,
|
|
435
|
+
level,
|
|
436
|
+
title: title || cap(label),
|
|
437
|
+
terms,
|
|
438
|
+
body,
|
|
439
|
+
children: children.map((c) => c.room),
|
|
440
|
+
parent: null,
|
|
441
|
+
// Il padre eredita il timestamp del figlio piu' recente: con i gruppi per
|
|
442
|
+
// affinita' l'istante del rollup non direbbe nulla, mentre cosi' la
|
|
443
|
+
// frontiera resta ordinata per "quanto e' recente il lavoro che contiene".
|
|
444
|
+
createdAt: children.reduce((max, c) => Math.max(max, c.createdAt), 0) || createdAt,
|
|
445
|
+
};
|
|
446
|
+
}
|
|
447
|
+
// --- livelli ---------------------------------------------------------------
|
|
448
|
+
function levelPrefix(level) {
|
|
449
|
+
if (level === 0)
|
|
450
|
+
return "R";
|
|
451
|
+
if (level === 1)
|
|
452
|
+
return "C";
|
|
453
|
+
if (level === 2)
|
|
454
|
+
return "K";
|
|
455
|
+
return `L${level}`;
|
|
456
|
+
}
|
|
457
|
+
function levelLabel(level) {
|
|
458
|
+
if (level <= 0)
|
|
459
|
+
return "attivita";
|
|
460
|
+
if (level === 1)
|
|
461
|
+
return "gruppo";
|
|
462
|
+
if (level === 2)
|
|
463
|
+
return "lista";
|
|
464
|
+
return `raccolta${level}`;
|
|
465
|
+
}
|
|
466
|
+
function cap(s) {
|
|
467
|
+
return s ? s[0].toUpperCase() + s.slice(1) : s;
|
|
468
|
+
}
|
|
469
|
+
// INDICE Danilov: vocabolario numerato (una voce per riga), come prescrive il
|
|
470
|
+
// metodo, invece di una lista piatta separata da virgole.
|
|
471
|
+
function numberedIndex(terms) {
|
|
472
|
+
if (!terms.length)
|
|
473
|
+
return "1 = (nessun termine)";
|
|
474
|
+
return terms.map((t, i) => `${i + 1} = ${t}`).join("\n");
|
|
475
|
+
}
|
|
476
|
+
function normalize(raw) {
|
|
477
|
+
const body = currentMemoryLabels(raw.body ?? "");
|
|
478
|
+
const title = raw.title ?? "";
|
|
479
|
+
return {
|
|
480
|
+
room: raw.room ?? "R?",
|
|
481
|
+
level: typeof raw.level === "number" ? raw.level : 0,
|
|
482
|
+
title: body === raw.body ? title : title.replace(/( · \d+) (stanza|castello|regno)$/, (_, count, label) => `${count} ${label === "stanza" ? "attivita" : label === "castello" ? "gruppi" : "liste"}`),
|
|
483
|
+
terms: Array.isArray(raw.terms) ? raw.terms : [],
|
|
484
|
+
body,
|
|
485
|
+
children: Array.isArray(raw.children) ? raw.children : [],
|
|
486
|
+
parent: raw.parent ?? null,
|
|
487
|
+
createdAt: typeof raw.createdAt === "number" ? raw.createdAt : 0,
|
|
488
|
+
...(Array.isArray(raw.edges) ? { edges: raw.edges.filter(isRoomEdge) } : {}),
|
|
489
|
+
};
|
|
490
|
+
}
|
|
491
|
+
// Aggiorna solo le etichette generate dei vecchi riepiloghi. Gli ID,
|
|
492
|
+
// le prove e il testo originale dell'utente restano quelli salvati.
|
|
493
|
+
function currentMemoryLabels(body) {
|
|
494
|
+
if (!/^INDICE_(?:CASTELLO|REGNO|LIVELLO\d+) \S+\r?\n/.test(body))
|
|
495
|
+
return body;
|
|
496
|
+
const labels = { stanza: "attivita", castello: "gruppo", regno: "lista" };
|
|
497
|
+
return body
|
|
498
|
+
.replace(/^INDICE_(CASTELLO|REGNO|LIVELLO\d+)/, (_, label) => `RIEPILOGO_${(labels[label.toLowerCase()] ?? label.replace("LIVELLO", "RACCOLTA")).toUpperCase()}`)
|
|
499
|
+
.replace(/^(?:Castello|Regno|Livello\d+) chiuso: (\d+) \w+ archiviati\./m, "Elementi archiviati: $1.")
|
|
500
|
+
.replace(/^@(stanza|castello|regno)(?=\[)/gm, (_, label) => `@${labels[label]}`)
|
|
501
|
+
.replace(/^(Stanza|Castello|Regno)\r?$/gm, (_, label) => cap(labels[label.toLowerCase()]))
|
|
502
|
+
.replace(/^OUTPUT: indice del (?:castello|regno|livello\d+);.*$/m, "OUTPUT: riepilogo delle attivita; apri i dettagli col tool recall.");
|
|
503
|
+
}
|
|
504
|
+
function isRoomEdge(value) {
|
|
505
|
+
const edge = value;
|
|
506
|
+
return Boolean(edge && typeof edge.target === "string" && edge.target && (edge.kind === "file" || edge.kind === "tool"));
|
|
507
|
+
}
|
|
508
|
+
// --- estrazione deterministica dai messaggi --------------------------------
|
|
509
|
+
function roomTitle(messages) {
|
|
510
|
+
const firstUser = messages.find((m) => m.role === "user");
|
|
511
|
+
const text = firstUser ? messageText(firstUser) : "";
|
|
512
|
+
// Collaboratore: il task reale e' appeso DOPO il preambolo di
|
|
513
|
+
// steering, sotto il marker OBIETTIVO_CASTELLO. Senza riconoscerlo, il titolo
|
|
514
|
+
// (e quindi i termini-indice e la ricerca) catturerebbe il boilerplate
|
|
515
|
+
// "[COLLABORATORE ...] INDICE 1 = ruolo 2 = dipendenze ..." IDENTICO per ogni
|
|
516
|
+
// stanza, rendendo indexBlock e recall inservibili: la causa per cui le
|
|
517
|
+
// stanze passate non si distinguono ne' si richiamano.
|
|
518
|
+
const objective = /OBIETTIVO_(?:ATTIVITA|CASTELLO)\s*\n([\s\S]*)$/.exec(text);
|
|
519
|
+
if (objective?.[1]?.trim())
|
|
520
|
+
return oneLine(objective[1]).slice(0, 160);
|
|
521
|
+
const input = /INPUT_UTENTE\n([\s\S]*)$/.exec(text);
|
|
522
|
+
if (input?.[1]?.trim())
|
|
523
|
+
return oneLine(input[1]).slice(0, 160);
|
|
524
|
+
const goal = /GOAL:\s*(.+)/.exec(text);
|
|
525
|
+
if (goal?.[1])
|
|
526
|
+
return oneLine(goal[1]).slice(0, 160);
|
|
527
|
+
return oneLine(text).slice(0, 160) || "attivita";
|
|
528
|
+
}
|
|
529
|
+
function collectToolCalls(messages) {
|
|
530
|
+
const calls = new Map();
|
|
531
|
+
const out = [];
|
|
532
|
+
for (const m of messages) {
|
|
533
|
+
for (const part of m.content) {
|
|
534
|
+
if (part.type === "tool_call") {
|
|
535
|
+
calls.set(part.id, { name: part.name, arg: firstArg(part.input) });
|
|
536
|
+
}
|
|
537
|
+
if (part.type === "tool_result") {
|
|
538
|
+
const call = calls.get(part.callId);
|
|
539
|
+
if (call)
|
|
540
|
+
out.push({ name: call.name, arg: call.arg, result: firstLine(part.output).slice(0, 100) });
|
|
541
|
+
}
|
|
542
|
+
}
|
|
543
|
+
}
|
|
544
|
+
for (const [, c] of calls) {
|
|
545
|
+
if (!out.some((o) => o.name === c.name && o.arg === c.arg))
|
|
546
|
+
out.push({ name: c.name, arg: c.arg, result: "" });
|
|
547
|
+
}
|
|
548
|
+
return out;
|
|
549
|
+
}
|
|
550
|
+
function collectFiles(messages) {
|
|
551
|
+
const files = new Set();
|
|
552
|
+
for (const m of messages) {
|
|
553
|
+
for (const part of m.content) {
|
|
554
|
+
if (part.type === "tool_call") {
|
|
555
|
+
const p = part.input["path"];
|
|
556
|
+
// Scarta i path "directory corrente" (".", "./") che non sono file utili.
|
|
557
|
+
if (typeof p === "string" && p && !/^\.\/?$/.test(p.trim()))
|
|
558
|
+
files.add(p);
|
|
559
|
+
}
|
|
560
|
+
}
|
|
561
|
+
}
|
|
562
|
+
return [...files];
|
|
563
|
+
}
|
|
564
|
+
function lastAssistantText(messages) {
|
|
565
|
+
for (let i = messages.length - 1; i >= 0; i -= 1) {
|
|
566
|
+
const m = messages[i];
|
|
567
|
+
if (m?.role === "assistant") {
|
|
568
|
+
const text = m.content.filter((p) => p.type === "text").map((p) => p.text).join(" ");
|
|
569
|
+
if (text.trim())
|
|
570
|
+
return oneLine(text).slice(0, 400);
|
|
571
|
+
}
|
|
572
|
+
}
|
|
573
|
+
return "";
|
|
574
|
+
}
|
|
575
|
+
function firstArg(input) {
|
|
576
|
+
const path = input["path"];
|
|
577
|
+
if (typeof path === "string")
|
|
578
|
+
return path;
|
|
579
|
+
const cmd = input["command"];
|
|
580
|
+
if (typeof cmd === "string")
|
|
581
|
+
return cmd.slice(0, 60);
|
|
582
|
+
const keys = Object.keys(input);
|
|
583
|
+
if (!keys.length)
|
|
584
|
+
return "";
|
|
585
|
+
const v = input[keys[0]];
|
|
586
|
+
return typeof v === "string" ? v.slice(0, 60) : JSON.stringify(v).slice(0, 60);
|
|
587
|
+
}
|
|
588
|
+
// --- util ------------------------------------------------------------------
|
|
589
|
+
function messageText(message) {
|
|
590
|
+
return message.content
|
|
591
|
+
.map((part) => {
|
|
592
|
+
if (part.type === "text")
|
|
593
|
+
return part.text;
|
|
594
|
+
if (part.type === "tool_call")
|
|
595
|
+
return `${part.name} ${JSON.stringify(part.input)}`;
|
|
596
|
+
if (part.type === "image")
|
|
597
|
+
return `[immagine ${part.mime}]`;
|
|
598
|
+
return part.output;
|
|
599
|
+
})
|
|
600
|
+
.join("\n");
|
|
601
|
+
}
|
|
602
|
+
function unique(values) {
|
|
603
|
+
return [...new Set(values.filter(Boolean))];
|
|
604
|
+
}
|
|
605
|
+
// Termini per l'INDICE: niente duplicati, niente STOP, niente rumore (deve
|
|
606
|
+
// contenere almeno una lettera -> scarta ".", numeri puri, punteggiatura).
|
|
607
|
+
function cleanTerms(values) {
|
|
608
|
+
return [...new Set(values
|
|
609
|
+
// Togli la punteggiatura ai BORDI (mantieni i punti interni: "prova.txt")
|
|
610
|
+
// cosi' "directory." -> "directory", "prosa." -> "prosa" (poi STOP filtra).
|
|
611
|
+
.map((t) => t.trim().toLowerCase().replace(/^[^a-z0-9]+|[^a-z0-9]+$/g, ""))
|
|
612
|
+
.filter((t) => t.length >= 2 && /[a-z]/.test(t) && !STOP.has(t)))];
|
|
613
|
+
}
|
|
614
|
+
function baseName(p) {
|
|
615
|
+
const parts = p.split(/[\\/]/).filter(Boolean);
|
|
616
|
+
return parts[parts.length - 1] ?? p;
|
|
617
|
+
}
|
|
618
|
+
function firstLine(s) {
|
|
619
|
+
return (s.split("\n")[0] ?? "").trim();
|
|
620
|
+
}
|
|
621
|
+
function oneLine(value) {
|
|
622
|
+
// Strip ANSI/byte di controllo PRIMA di collassare gli spazi: cosi' i
|
|
623
|
+
// "caratteri strani" da output di tool non entrano in title/body/output.
|
|
624
|
+
return sanitizeText(value).replace(/\s+/g, " ").trim();
|
|
625
|
+
}
|
|
626
|
+
function escapeValue(value) {
|
|
627
|
+
return oneLine(value).replace(/"/g, "'");
|
|
628
|
+
}
|
|
629
|
+
function clampBody(s) {
|
|
630
|
+
return s.length > MAX_BODY ? s.slice(0, MAX_BODY) + "\n...[troncato]" : s;
|
|
631
|
+
}
|