@mastra/code-sdk 0.0.0-fix-workflow-step-timing-and-parallel-status-20260715180716
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +285 -0
- package/LICENSE.md +30 -0
- package/README.md +50 -0
- package/dist/acp/agent.d.ts +35 -0
- package/dist/acp/agent.d.ts.map +1 -0
- package/dist/acp/agent.js +173 -0
- package/dist/acp/agent.js.map +1 -0
- package/dist/acp/event-mapper.d.ts +22 -0
- package/dist/acp/event-mapper.d.ts.map +1 -0
- package/dist/acp/event-mapper.js +166 -0
- package/dist/acp/event-mapper.js.map +1 -0
- package/dist/acp/index.d.ts +8 -0
- package/dist/acp/index.d.ts.map +1 -0
- package/dist/acp/index.js +54 -0
- package/dist/acp/index.js.map +1 -0
- package/dist/acp/server.d.ts +7 -0
- package/dist/acp/server.d.ts.map +1 -0
- package/dist/acp/server.js +34 -0
- package/dist/acp/server.js.map +1 -0
- package/dist/acp.d.ts +2 -0
- package/dist/acp.d.ts.map +1 -0
- package/dist/acp.js +5 -0
- package/dist/acp.js.map +1 -0
- package/dist/agents/instructions.d.ts +6 -0
- package/dist/agents/instructions.d.ts.map +1 -0
- package/dist/agents/instructions.js +41 -0
- package/dist/agents/instructions.js.map +1 -0
- package/dist/agents/mastracode-gateway.d.ts +67 -0
- package/dist/agents/mastracode-gateway.d.ts.map +1 -0
- package/dist/agents/mastracode-gateway.js +446 -0
- package/dist/agents/mastracode-gateway.js.map +1 -0
- package/dist/agents/memory.d.ts +13 -0
- package/dist/agents/memory.d.ts.map +1 -0
- package/dist/agents/memory.js +107 -0
- package/dist/agents/memory.js.map +1 -0
- package/dist/agents/model.d.ts +55 -0
- package/dist/agents/model.d.ts.map +1 -0
- package/dist/agents/model.js +115 -0
- package/dist/agents/model.js.map +1 -0
- package/dist/agents/modes/build.d.ts +10 -0
- package/dist/agents/modes/build.d.ts.map +1 -0
- package/dist/agents/modes/build.js +45 -0
- package/dist/agents/modes/build.js.map +1 -0
- package/dist/agents/modes/explore.d.ts +10 -0
- package/dist/agents/modes/explore.d.ts.map +1 -0
- package/dist/agents/modes/explore.js +38 -0
- package/dist/agents/modes/explore.js.map +1 -0
- package/dist/agents/modes/plan.d.ts +6 -0
- package/dist/agents/modes/plan.d.ts.map +1 -0
- package/dist/agents/modes/plan.js +38 -0
- package/dist/agents/modes/plan.js.map +1 -0
- package/dist/agents/prompts/agent-instructions.d.ts +20 -0
- package/dist/agents/prompts/agent-instructions.d.ts.map +1 -0
- package/dist/agents/prompts/agent-instructions.js +82 -0
- package/dist/agents/prompts/agent-instructions.js.map +1 -0
- package/dist/agents/prompts/build.d.ts +12 -0
- package/dist/agents/prompts/build.d.ts.map +1 -0
- package/dist/agents/prompts/build.js +73 -0
- package/dist/agents/prompts/build.js.map +1 -0
- package/dist/agents/prompts/fast.d.ts +5 -0
- package/dist/agents/prompts/fast.d.ts.map +1 -0
- package/dist/agents/prompts/fast.js +22 -0
- package/dist/agents/prompts/fast.js.map +1 -0
- package/dist/agents/prompts/index.d.ts +19 -0
- package/dist/agents/prompts/index.d.ts.map +1 -0
- package/dist/agents/prompts/index.js +57 -0
- package/dist/agents/prompts/index.js.map +1 -0
- package/dist/agents/prompts/model.d.ts +5 -0
- package/dist/agents/prompts/model.d.ts.map +1 -0
- package/dist/agents/prompts/model.js +22 -0
- package/dist/agents/prompts/model.js.map +1 -0
- package/dist/agents/prompts/plan.d.ts +6 -0
- package/dist/agents/prompts/plan.d.ts.map +1 -0
- package/dist/agents/prompts/plan.js +107 -0
- package/dist/agents/prompts/plan.js.map +1 -0
- package/dist/agents/prompts/tool-guidance.d.ts +13 -0
- package/dist/agents/prompts/tool-guidance.d.ts.map +1 -0
- package/dist/agents/prompts/tool-guidance.js +181 -0
- package/dist/agents/prompts/tool-guidance.js.map +1 -0
- package/dist/agents/sandbox-filesystem.d.ts +89 -0
- package/dist/agents/sandbox-filesystem.d.ts.map +1 -0
- package/dist/agents/sandbox-filesystem.js +268 -0
- package/dist/agents/sandbox-filesystem.js.map +1 -0
- package/dist/agents/sandbox-reattach.d.ts +19 -0
- package/dist/agents/sandbox-reattach.d.ts.map +1 -0
- package/dist/agents/sandbox-reattach.js +17 -0
- package/dist/agents/sandbox-reattach.js.map +1 -0
- package/dist/agents/thread-caveman-state.d.ts +17 -0
- package/dist/agents/thread-caveman-state.d.ts.map +1 -0
- package/dist/agents/thread-caveman-state.js +96 -0
- package/dist/agents/thread-caveman-state.js.map +1 -0
- package/dist/agents/tool-availability.d.ts +10 -0
- package/dist/agents/tool-availability.d.ts.map +1 -0
- package/dist/agents/tool-availability.js +105 -0
- package/dist/agents/tool-availability.js.map +1 -0
- package/dist/agents/tools.d.ts +19 -0
- package/dist/agents/tools.d.ts.map +1 -0
- package/dist/agents/tools.js +145 -0
- package/dist/agents/tools.js.map +1 -0
- package/dist/agents/workspace.d.ts +22 -0
- package/dist/agents/workspace.d.ts.map +1 -0
- package/dist/agents/workspace.js +226 -0
- package/dist/agents/workspace.js.map +1 -0
- package/dist/analytics.d.ts +18 -0
- package/dist/analytics.d.ts.map +1 -0
- package/dist/analytics.js +152 -0
- package/dist/analytics.js.map +1 -0
- package/dist/auth/index.d.ts +9 -0
- package/dist/auth/index.d.ts.map +1 -0
- package/dist/auth/index.js +11 -0
- package/dist/auth/index.js.map +1 -0
- package/dist/auth/pkce.d.ts +13 -0
- package/dist/auth/pkce.d.ts.map +1 -0
- package/dist/auth/pkce.js +21 -0
- package/dist/auth/pkce.js.map +1 -0
- package/dist/auth/providers/anthropic.d.ts +17 -0
- package/dist/auth/providers/anthropic.d.ts.map +1 -0
- package/dist/auth/providers/anthropic.js +94 -0
- package/dist/auth/providers/anthropic.js.map +1 -0
- package/dist/auth/providers/github-copilot.d.ts +100 -0
- package/dist/auth/providers/github-copilot.d.ts.map +1 -0
- package/dist/auth/providers/github-copilot.js +302 -0
- package/dist/auth/providers/github-copilot.js.map +1 -0
- package/dist/auth/providers/openai-codex.d.ts +95 -0
- package/dist/auth/providers/openai-codex.d.ts.map +1 -0
- package/dist/auth/providers/openai-codex.js +527 -0
- package/dist/auth/providers/openai-codex.js.map +1 -0
- package/dist/auth/storage.d.ts +91 -0
- package/dist/auth/storage.d.ts.map +1 -0
- package/dist/auth/storage.js +187 -0
- package/dist/auth/storage.js.map +1 -0
- package/dist/auth/types.d.ts +68 -0
- package/dist/auth/types.d.ts.map +1 -0
- package/dist/auth/types.js +1 -0
- package/dist/auth/types.js.map +1 -0
- package/dist/clipboard/index.d.ts +26 -0
- package/dist/clipboard/index.d.ts.map +1 -0
- package/dist/clipboard/index.js +192 -0
- package/dist/clipboard/index.js.map +1 -0
- package/dist/constants.d.ts +10 -0
- package/dist/constants.d.ts.map +1 -0
- package/dist/constants.js +23 -0
- package/dist/constants.js.map +1 -0
- package/dist/error-classification.d.ts +10 -0
- package/dist/error-classification.d.ts.map +1 -0
- package/dist/error-classification.js +14 -0
- package/dist/error-classification.js.map +1 -0
- package/dist/evals/context-builder.d.ts +41 -0
- package/dist/evals/context-builder.d.ts.map +1 -0
- package/dist/evals/context-builder.js +120 -0
- package/dist/evals/context-builder.js.map +1 -0
- package/dist/evals/index.d.ts +4 -0
- package/dist/evals/index.d.ts.map +1 -0
- package/dist/evals/index.js +8 -0
- package/dist/evals/index.js.map +1 -0
- package/dist/evals/scorers/classify-command.d.ts +31 -0
- package/dist/evals/scorers/classify-command.d.ts.map +1 -0
- package/dist/evals/scorers/classify-command.js +52 -0
- package/dist/evals/scorers/classify-command.js.map +1 -0
- package/dist/evals/scorers/efficiency.d.ts +44 -0
- package/dist/evals/scorers/efficiency.d.ts.map +1 -0
- package/dist/evals/scorers/efficiency.js +201 -0
- package/dist/evals/scorers/efficiency.js.map +1 -0
- package/dist/evals/scorers/extract-tools.d.ts +25 -0
- package/dist/evals/scorers/extract-tools.d.ts.map +1 -0
- package/dist/evals/scorers/extract-tools.js +56 -0
- package/dist/evals/scorers/extract-tools.js.map +1 -0
- package/dist/evals/scorers/index.d.ts +3 -0
- package/dist/evals/scorers/index.d.ts.map +1 -0
- package/dist/evals/scorers/index.js +7 -0
- package/dist/evals/scorers/index.js.map +1 -0
- package/dist/evals/scorers/outcome.d.ts +49 -0
- package/dist/evals/scorers/outcome.d.ts.map +1 -0
- package/dist/evals/scorers/outcome.js +238 -0
- package/dist/evals/scorers/outcome.js.map +1 -0
- package/dist/headless/cli.d.ts +42 -0
- package/dist/headless/cli.d.ts.map +1 -0
- package/dist/headless/cli.js +196 -0
- package/dist/headless/cli.js.map +1 -0
- package/dist/headless/flags.d.ts +33 -0
- package/dist/headless/flags.d.ts.map +1 -0
- package/dist/headless/flags.js +188 -0
- package/dist/headless/flags.js.map +1 -0
- package/dist/headless/format.d.ts +38 -0
- package/dist/headless/format.d.ts.map +1 -0
- package/dist/headless/format.js +85 -0
- package/dist/headless/format.js.map +1 -0
- package/dist/headless/index.d.ts +25 -0
- package/dist/headless/index.d.ts.map +1 -0
- package/dist/headless/index.js +32 -0
- package/dist/headless/index.js.map +1 -0
- package/dist/headless/policy.d.ts +17 -0
- package/dist/headless/policy.d.ts.map +1 -0
- package/dist/headless/policy.js +38 -0
- package/dist/headless/policy.js.map +1 -0
- package/dist/headless/run-mc.d.ts +7 -0
- package/dist/headless/run-mc.d.ts.map +1 -0
- package/dist/headless/run-mc.js +296 -0
- package/dist/headless/run-mc.js.map +1 -0
- package/dist/headless/types.d.ts +134 -0
- package/dist/headless/types.d.ts.map +1 -0
- package/dist/headless/types.js +9 -0
- package/dist/headless/types.js.map +1 -0
- package/dist/hooks/config.d.ts +11 -0
- package/dist/hooks/config.d.ts.map +1 -0
- package/dist/hooks/config.js +78 -0
- package/dist/hooks/config.js.map +1 -0
- package/dist/hooks/executor.d.ts +13 -0
- package/dist/hooks/executor.d.ts.map +1 -0
- package/dist/hooks/executor.js +125 -0
- package/dist/hooks/executor.js.map +1 -0
- package/dist/hooks/index.d.ts +6 -0
- package/dist/hooks/index.d.ts.map +1 -0
- package/dist/hooks/index.js +16 -0
- package/dist/hooks/index.js.map +1 -0
- package/dist/hooks/manager.d.ts +47 -0
- package/dist/hooks/manager.d.ts.map +1 -0
- package/dist/hooks/manager.js +284 -0
- package/dist/hooks/manager.js.map +1 -0
- package/dist/hooks/types.d.ts +152 -0
- package/dist/hooks/types.d.ts.map +1 -0
- package/dist/hooks/types.js +7 -0
- package/dist/hooks/types.js.map +1 -0
- package/dist/index.d.ts +243 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +730 -0
- package/dist/index.js.map +1 -0
- package/dist/ipc/ipc-reporter.d.ts +14 -0
- package/dist/ipc/ipc-reporter.d.ts.map +1 -0
- package/dist/ipc/ipc-reporter.js +24 -0
- package/dist/ipc/ipc-reporter.js.map +1 -0
- package/dist/lsp/client.d.ts +56 -0
- package/dist/lsp/client.d.ts.map +1 -0
- package/dist/lsp/client.js +309 -0
- package/dist/lsp/client.js.map +1 -0
- package/dist/lsp/index.d.ts +4 -0
- package/dist/lsp/index.d.ts.map +1 -0
- package/dist/lsp/index.js +9 -0
- package/dist/lsp/index.js.map +1 -0
- package/dist/lsp/language.d.ts +9 -0
- package/dist/lsp/language.d.ts.map +1 -0
- package/dist/lsp/language.js +48 -0
- package/dist/lsp/language.js.map +1 -0
- package/dist/lsp/manager.d.ts +34 -0
- package/dist/lsp/manager.d.ts.map +1 -0
- package/dist/lsp/manager.js +97 -0
- package/dist/lsp/manager.js.map +1 -0
- package/dist/lsp/server.d.ts +27 -0
- package/dist/lsp/server.d.ts.map +1 -0
- package/dist/lsp/server.js +128 -0
- package/dist/lsp/server.js.map +1 -0
- package/dist/lsp/workspace.d.ts +9 -0
- package/dist/lsp/workspace.d.ts.map +1 -0
- package/dist/lsp/workspace.js +52 -0
- package/dist/lsp/workspace.js.map +1 -0
- package/dist/mcp/config.d.ts +34 -0
- package/dist/mcp/config.d.ts.map +1 -0
- package/dist/mcp/config.js +205 -0
- package/dist/mcp/config.js.map +1 -0
- package/dist/mcp/index.d.ts +5 -0
- package/dist/mcp/index.d.ts.map +1 -0
- package/dist/mcp/index.js +10 -0
- package/dist/mcp/index.js.map +1 -0
- package/dist/mcp/manager.d.ts +49 -0
- package/dist/mcp/manager.d.ts.map +1 -0
- package/dist/mcp/manager.js +374 -0
- package/dist/mcp/manager.js.map +1 -0
- package/dist/mcp/types.d.ts +85 -0
- package/dist/mcp/types.d.ts.map +1 -0
- package/dist/mcp/types.js +1 -0
- package/dist/mcp/types.js.map +1 -0
- package/dist/onboarding/custom-packs.d.ts +7 -0
- package/dist/onboarding/custom-packs.d.ts.map +1 -0
- package/dist/onboarding/custom-packs.js +20 -0
- package/dist/onboarding/custom-packs.js.map +1 -0
- package/dist/onboarding/custom-providers.d.ts +4 -0
- package/dist/onboarding/custom-providers.d.ts.map +1 -0
- package/dist/onboarding/custom-providers.js +28 -0
- package/dist/onboarding/custom-providers.js.map +1 -0
- package/dist/onboarding/index.d.ts +5 -0
- package/dist/onboarding/index.d.ts.map +1 -0
- package/dist/onboarding/index.js +21 -0
- package/dist/onboarding/index.js.map +1 -0
- package/dist/onboarding/om-settings.d.ts +20 -0
- package/dist/onboarding/om-settings.d.ts.map +1 -0
- package/dist/onboarding/om-settings.js +26 -0
- package/dist/onboarding/om-settings.js.map +1 -0
- package/dist/onboarding/packs.d.ts +48 -0
- package/dist/onboarding/packs.d.ts.map +1 -0
- package/dist/onboarding/packs.js +111 -0
- package/dist/onboarding/packs.js.map +1 -0
- package/dist/onboarding/settings.d.ts +327 -0
- package/dist/onboarding/settings.d.ts.map +1 -0
- package/dist/onboarding/settings.js +598 -0
- package/dist/onboarding/settings.js.map +1 -0
- package/dist/permissions.d.ts +55 -0
- package/dist/permissions.d.ts.map +1 -0
- package/dist/permissions.js +119 -0
- package/dist/permissions.js.map +1 -0
- package/dist/plugin.d.ts +81 -0
- package/dist/plugin.d.ts.map +1 -0
- package/dist/plugin.js +30 -0
- package/dist/plugin.js.map +1 -0
- package/dist/plugins/dependencies.d.ts +9 -0
- package/dist/plugins/dependencies.d.ts.map +1 -0
- package/dist/plugins/dependencies.js +111 -0
- package/dist/plugins/dependencies.js.map +1 -0
- package/dist/plugins/install.d.ts +21 -0
- package/dist/plugins/install.d.ts.map +1 -0
- package/dist/plugins/install.js +200 -0
- package/dist/plugins/install.js.map +1 -0
- package/dist/plugins/loader.d.ts +15 -0
- package/dist/plugins/loader.d.ts.map +1 -0
- package/dist/plugins/loader.js +221 -0
- package/dist/plugins/loader.js.map +1 -0
- package/dist/plugins/manager.d.ts +60 -0
- package/dist/plugins/manager.d.ts.map +1 -0
- package/dist/plugins/manager.js +378 -0
- package/dist/plugins/manager.js.map +1 -0
- package/dist/plugins/manifest.d.ts +14 -0
- package/dist/plugins/manifest.d.ts.map +1 -0
- package/dist/plugins/manifest.js +75 -0
- package/dist/plugins/manifest.js.map +1 -0
- package/dist/plugins/package-link.d.ts +3 -0
- package/dist/plugins/package-link.d.ts.map +1 -0
- package/dist/plugins/package-link.js +77 -0
- package/dist/plugins/package-link.js.map +1 -0
- package/dist/plugins/paths.d.ts +10 -0
- package/dist/plugins/paths.d.ts.map +1 -0
- package/dist/plugins/paths.js +26 -0
- package/dist/plugins/paths.js.map +1 -0
- package/dist/plugins/registry.d.ts +8 -0
- package/dist/plugins/registry.d.ts.map +1 -0
- package/dist/plugins/registry.js +96 -0
- package/dist/plugins/registry.js.map +1 -0
- package/dist/plugins/scaffold.d.ts +10 -0
- package/dist/plugins/scaffold.d.ts.map +1 -0
- package/dist/plugins/scaffold.js +152 -0
- package/dist/plugins/scaffold.js.map +1 -0
- package/dist/plugins/types.d.ts +45 -0
- package/dist/plugins/types.d.ts.map +1 -0
- package/dist/plugins/types.js +1 -0
- package/dist/plugins/types.js.map +1 -0
- package/dist/processors/plan-rejection-abort.d.ts +12 -0
- package/dist/processors/plan-rejection-abort.d.ts.map +1 -0
- package/dist/processors/plan-rejection-abort.js +53 -0
- package/dist/processors/plan-rejection-abort.js.map +1 -0
- package/dist/providers/amazon-bedrock-gateway.d.ts +40 -0
- package/dist/providers/amazon-bedrock-gateway.d.ts.map +1 -0
- package/dist/providers/amazon-bedrock-gateway.js +79 -0
- package/dist/providers/amazon-bedrock-gateway.js.map +1 -0
- package/dist/providers/amazon-bedrock.d.ts +28 -0
- package/dist/providers/amazon-bedrock.d.ts.map +1 -0
- package/dist/providers/amazon-bedrock.js +62 -0
- package/dist/providers/amazon-bedrock.js.map +1 -0
- package/dist/providers/claude-max.d.ts +50 -0
- package/dist/providers/claude-max.d.ts.map +1 -0
- package/dist/providers/claude-max.js +151 -0
- package/dist/providers/claude-max.js.map +1 -0
- package/dist/providers/github-copilot.d.ts +58 -0
- package/dist/providers/github-copilot.d.ts.map +1 -0
- package/dist/providers/github-copilot.js +263 -0
- package/dist/providers/github-copilot.js.map +1 -0
- package/dist/providers/openai-codex.d.ts +70 -0
- package/dist/providers/openai-codex.d.ts.map +1 -0
- package/dist/providers/openai-codex.js +291 -0
- package/dist/providers/openai-codex.js.map +1 -0
- package/dist/schema.d.ts +167 -0
- package/dist/schema.d.ts.map +1 -0
- package/dist/schema.js +92 -0
- package/dist/schema.js.map +1 -0
- package/dist/theme-palette.d.ts +17 -0
- package/dist/theme-palette.d.ts.map +1 -0
- package/dist/theme-palette.js +17 -0
- package/dist/theme-palette.js.map +1 -0
- package/dist/tool-names.d.ts +73 -0
- package/dist/tool-names.d.ts.map +1 -0
- package/dist/tool-names.js +43 -0
- package/dist/tool-names.js.map +1 -0
- package/dist/tools/index.d.ts +6 -0
- package/dist/tools/index.d.ts.map +1 -0
- package/dist/tools/index.js +9 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/tools/request-sandbox-access.d.ts +6 -0
- package/dist/tools/request-sandbox-access.d.ts.map +1 -0
- package/dist/tools/request-sandbox-access.js +88 -0
- package/dist/tools/request-sandbox-access.js.map +1 -0
- package/dist/tools/utils.d.ts +20 -0
- package/dist/tools/utils.d.ts.map +1 -0
- package/dist/tools/utils.js +22 -0
- package/dist/tools/utils.js.map +1 -0
- package/dist/tools/web-search.d.ts +35 -0
- package/dist/tools/web-search.d.ts.map +1 -0
- package/dist/tools/web-search.js +65 -0
- package/dist/tools/web-search.js.map +1 -0
- package/dist/utils/binaries.d.ts +7 -0
- package/dist/utils/binaries.d.ts.map +1 -0
- package/dist/utils/binaries.js +74 -0
- package/dist/utils/binaries.js.map +1 -0
- package/dist/utils/debug-log.d.ts +12 -0
- package/dist/utils/debug-log.d.ts.map +1 -0
- package/dist/utils/debug-log.js +55 -0
- package/dist/utils/debug-log.js.map +1 -0
- package/dist/utils/errors.d.ts +36 -0
- package/dist/utils/errors.d.ts.map +1 -0
- package/dist/utils/errors.js +207 -0
- package/dist/utils/errors.js.map +1 -0
- package/dist/utils/gateway-sync.d.ts +26 -0
- package/dist/utils/gateway-sync.d.ts.map +1 -0
- package/dist/utils/gateway-sync.js +49 -0
- package/dist/utils/gateway-sync.js.map +1 -0
- package/dist/utils/path-security.d.ts +2 -0
- package/dist/utils/path-security.d.ts.map +1 -0
- package/dist/utils/path-security.js +9 -0
- package/dist/utils/path-security.js.map +1 -0
- package/dist/utils/plan-diff.d.ts +25 -0
- package/dist/utils/plan-diff.d.ts.map +1 -0
- package/dist/utils/plan-diff.js +43 -0
- package/dist/utils/plan-diff.js.map +1 -0
- package/dist/utils/plans.d.ts +56 -0
- package/dist/utils/plans.d.ts.map +1 -0
- package/dist/utils/plans.js +99 -0
- package/dist/utils/plans.js.map +1 -0
- package/dist/utils/project.d.ts +160 -0
- package/dist/utils/project.d.ts.map +1 -0
- package/dist/utils/project.js +302 -0
- package/dist/utils/project.js.map +1 -0
- package/dist/utils/signals-pubsub.d.ts +41 -0
- package/dist/utils/signals-pubsub.d.ts.map +1 -0
- package/dist/utils/signals-pubsub.js +104 -0
- package/dist/utils/signals-pubsub.js.map +1 -0
- package/dist/utils/slash-command-loader.d.ts +52 -0
- package/dist/utils/slash-command-loader.d.ts.map +1 -0
- package/dist/utils/slash-command-loader.js +177 -0
- package/dist/utils/slash-command-loader.js.map +1 -0
- package/dist/utils/slash-command-processor.d.ts +14 -0
- package/dist/utils/slash-command-processor.d.ts.map +1 -0
- package/dist/utils/slash-command-processor.js +96 -0
- package/dist/utils/slash-command-processor.js.map +1 -0
- package/dist/utils/stdin-pipe.d.ts +33 -0
- package/dist/utils/stdin-pipe.d.ts.map +1 -0
- package/dist/utils/stdin-pipe.js +72 -0
- package/dist/utils/stdin-pipe.js.map +1 -0
- package/dist/utils/storage-factory.d.ts +50 -0
- package/dist/utils/storage-factory.d.ts.map +1 -0
- package/dist/utils/storage-factory.js +101 -0
- package/dist/utils/storage-factory.js.map +1 -0
- package/dist/utils/storage-maintenance.d.ts +103 -0
- package/dist/utils/storage-maintenance.d.ts.map +1 -0
- package/dist/utils/storage-maintenance.js +236 -0
- package/dist/utils/storage-maintenance.js.map +1 -0
- package/dist/utils/thread-lock.d.ts +26 -0
- package/dist/utils/thread-lock.d.ts.map +1 -0
- package/dist/utils/thread-lock.js +108 -0
- package/dist/utils/thread-lock.js.map +1 -0
- package/dist/utils/token-estimator.d.ts +3 -0
- package/dist/utils/token-estimator.d.ts.map +1 -0
- package/dist/utils/token-estimator.js +21 -0
- package/dist/utils/token-estimator.js.map +1 -0
- package/dist/utils/update-check.d.ts +52 -0
- package/dist/utils/update-check.d.ts.map +1 -0
- package/dist/utils/update-check.js +177 -0
- package/dist/utils/update-check.js.map +1 -0
- package/dist/voice/stt-registry.d.ts +64 -0
- package/dist/voice/stt-registry.d.ts.map +1 -0
- package/dist/voice/stt-registry.js +126 -0
- package/dist/voice/stt-registry.js.map +1 -0
- package/package.json +94 -0
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Clean up raw piped output so the agent sees readable text, not terminal
|
|
3
|
+
* control noise.
|
|
4
|
+
*
|
|
5
|
+
* 1. Strip all ANSI escape sequences (colors, cursor movement, line clears).
|
|
6
|
+
* 2. Simulate carriage-return overwrites: for each line, split on `\r` and
|
|
7
|
+
* keep only the last segment — this is what the terminal would display
|
|
8
|
+
* after a spinner/progress bar finishes.
|
|
9
|
+
* 3. Collapse runs of blank lines.
|
|
10
|
+
*/
|
|
11
|
+
export declare function sanitizePipedOutput(raw: string): string;
|
|
12
|
+
/**
|
|
13
|
+
* If stdin is a pipe (not a TTY), read **all** data until EOF and return it as
|
|
14
|
+
* a string. The returned promise only resolves once the write end of the pipe
|
|
15
|
+
* is closed — i.e. the sending process has fully exited — so callers are
|
|
16
|
+
* guaranteed to receive the complete output, not a partial snapshot from a
|
|
17
|
+
* program that writes progressively.
|
|
18
|
+
*
|
|
19
|
+
* Returns `null` when:
|
|
20
|
+
* - stdin is a TTY (interactive terminal)
|
|
21
|
+
* - the pipe was empty or contained only whitespace
|
|
22
|
+
*/
|
|
23
|
+
export declare function drainPipedStdin(): Promise<string | null>;
|
|
24
|
+
/**
|
|
25
|
+
* Reopen `/dev/tty` (or `CON` on Windows) as `process.stdin` so that the
|
|
26
|
+
* interactive TUI can read keyboard input after the original piped stdin has
|
|
27
|
+
* been consumed.
|
|
28
|
+
*
|
|
29
|
+
* @returns `true` if the swap succeeded, `false` if a TTY could not be opened
|
|
30
|
+
* (e.g. running in a headless CI container with no controlling terminal).
|
|
31
|
+
*/
|
|
32
|
+
export declare function reopenStdinFromTTY(): boolean;
|
|
33
|
+
//# sourceMappingURL=stdin-pipe.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stdin-pipe.d.ts","sourceRoot":"","sources":["../../src/utils/stdin-pipe.ts"],"names":[],"mappings":"AAYA;;;;;;;;;GASG;AACH,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CA0BvD;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,eAAe,IAAI,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CA2C9D;AAED;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,IAAI,OAAO,CAmB5C"}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import * as fs from "node:fs";
|
|
2
|
+
import * as tty from "node:tty";
|
|
3
|
+
const MAX_PIPE_BYTES = 1024 * 1024;
|
|
4
|
+
const ANSI_RE = /\x1b(?:\[[0-9;?]*[A-Za-z]|\][^\x07\x1b]*(?:\x07|\x1b\\)?|\([A-Z])/g;
|
|
5
|
+
function sanitizePipedOutput(raw) {
|
|
6
|
+
let text = raw.replace(ANSI_RE, "");
|
|
7
|
+
text = text.replace(/[\x00-\x08\x0B\x0C\x0E-\x1F\x7F]/g, "");
|
|
8
|
+
text = text.split("\n").map((line) => {
|
|
9
|
+
if (!line.includes("\r")) return line;
|
|
10
|
+
const segments = line.split("\r");
|
|
11
|
+
for (let i = segments.length - 1; i >= 0; i--) {
|
|
12
|
+
if (segments[i].length > 0) return segments[i];
|
|
13
|
+
}
|
|
14
|
+
return "";
|
|
15
|
+
}).join("\n");
|
|
16
|
+
text = text.replace(/\n{3,}/g, "\n\n");
|
|
17
|
+
return text.trim();
|
|
18
|
+
}
|
|
19
|
+
async function drainPipedStdin() {
|
|
20
|
+
if (process.stdin.isTTY) return null;
|
|
21
|
+
const chunks = [];
|
|
22
|
+
let totalBytes = 0;
|
|
23
|
+
let truncated = false;
|
|
24
|
+
for await (const chunk of process.stdin) {
|
|
25
|
+
const buf = chunk;
|
|
26
|
+
if (totalBytes + buf.length > MAX_PIPE_BYTES) {
|
|
27
|
+
const remaining = MAX_PIPE_BYTES - totalBytes;
|
|
28
|
+
if (remaining > 0) {
|
|
29
|
+
chunks.push(Buffer.from(buf.subarray(0, remaining)));
|
|
30
|
+
}
|
|
31
|
+
buf.fill(0);
|
|
32
|
+
totalBytes = MAX_PIPE_BYTES;
|
|
33
|
+
truncated = true;
|
|
34
|
+
continue;
|
|
35
|
+
}
|
|
36
|
+
chunks.push(buf);
|
|
37
|
+
totalBytes += buf.length;
|
|
38
|
+
}
|
|
39
|
+
if (truncated) {
|
|
40
|
+
process.stderr.write(`Warning: Piped input exceeded ${MAX_PIPE_BYTES / 1024 / 1024}MB and was truncated.
|
|
41
|
+
`);
|
|
42
|
+
}
|
|
43
|
+
const raw = Buffer.concat(chunks).toString("utf-8");
|
|
44
|
+
for (const buf of chunks) {
|
|
45
|
+
buf.fill(0);
|
|
46
|
+
}
|
|
47
|
+
chunks.length = 0;
|
|
48
|
+
const content = sanitizePipedOutput(raw);
|
|
49
|
+
return content.length > 0 ? content : null;
|
|
50
|
+
}
|
|
51
|
+
function reopenStdinFromTTY() {
|
|
52
|
+
const ttyPath = process.platform === "win32" ? "CON" : "/dev/tty";
|
|
53
|
+
let fd;
|
|
54
|
+
try {
|
|
55
|
+
fd = fs.openSync(ttyPath, "r");
|
|
56
|
+
} catch {
|
|
57
|
+
return false;
|
|
58
|
+
}
|
|
59
|
+
const ttyStream = new tty.ReadStream(fd);
|
|
60
|
+
Object.defineProperty(process, "stdin", {
|
|
61
|
+
value: ttyStream,
|
|
62
|
+
writable: true,
|
|
63
|
+
configurable: true
|
|
64
|
+
});
|
|
65
|
+
return true;
|
|
66
|
+
}
|
|
67
|
+
export {
|
|
68
|
+
drainPipedStdin,
|
|
69
|
+
reopenStdinFromTTY,
|
|
70
|
+
sanitizePipedOutput
|
|
71
|
+
};
|
|
72
|
+
//# sourceMappingURL=stdin-pipe.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/utils/stdin-pipe.ts"],"sourcesContent":["import * as fs from 'node:fs';\nimport * as tty from 'node:tty';\n\n/** Maximum piped input size (1 MB). Content beyond this is truncated. */\nconst MAX_PIPE_BYTES = 1024 * 1024;\n\n/**\n * Matches all ANSI escape sequences — SGR (colors), cursor movement, line\n * clears, scrolling, window titles, etc.\n */\nconst ANSI_RE = /\\x1b(?:\\[[0-9;?]*[A-Za-z]|\\][^\\x07\\x1b]*(?:\\x07|\\x1b\\\\)?|\\([A-Z])/g;\n\n/**\n * Clean up raw piped output so the agent sees readable text, not terminal\n * control noise.\n *\n * 1. Strip all ANSI escape sequences (colors, cursor movement, line clears).\n * 2. Simulate carriage-return overwrites: for each line, split on `\\r` and\n * keep only the last segment — this is what the terminal would display\n * after a spinner/progress bar finishes.\n * 3. Collapse runs of blank lines.\n */\nexport function sanitizePipedOutput(raw: string): string {\n // Strip ANSI escapes first\n let text = raw.replace(ANSI_RE, '');\n\n // Strip binary control characters (everything below 0x20 except \\t, \\n, \\r)\n text = text.replace(/[\\x00-\\x08\\x0B\\x0C\\x0E-\\x1F\\x7F]/g, '');\n\n // Simulate \\r overwrites: for each line, the last \\r-segment wins\n text = text\n .split('\\n')\n .map(line => {\n if (!line.includes('\\r')) return line;\n const segments = line.split('\\r');\n // Walk backwards to find the last non-empty segment — a trailing \\r\n // produces an empty final segment that would otherwise discard visible text.\n for (let i = segments.length - 1; i >= 0; i--) {\n if (segments[i]!.length > 0) return segments[i]!;\n }\n return '';\n })\n .join('\\n');\n\n // Collapse 3+ consecutive blank lines into 2\n text = text.replace(/\\n{3,}/g, '\\n\\n');\n\n return text.trim();\n}\n\n/**\n * If stdin is a pipe (not a TTY), read **all** data until EOF and return it as\n * a string. The returned promise only resolves once the write end of the pipe\n * is closed — i.e. the sending process has fully exited — so callers are\n * guaranteed to receive the complete output, not a partial snapshot from a\n * program that writes progressively.\n *\n * Returns `null` when:\n * - stdin is a TTY (interactive terminal)\n * - the pipe was empty or contained only whitespace\n */\nexport async function drainPipedStdin(): Promise<string | null> {\n if (process.stdin.isTTY) return null;\n\n const chunks: Buffer[] = [];\n let totalBytes = 0;\n let truncated = false;\n\n for await (const chunk of process.stdin) {\n const buf = chunk as Buffer;\n\n if (totalBytes + buf.length > MAX_PIPE_BYTES) {\n // Take only what fits under the cap — copy so we don't retain the\n // original backing buffer, then zero the source.\n const remaining = MAX_PIPE_BYTES - totalBytes;\n if (remaining > 0) {\n chunks.push(Buffer.from(buf.subarray(0, remaining)));\n }\n buf.fill(0);\n totalBytes = MAX_PIPE_BYTES;\n truncated = true;\n // Keep draining so we don't leave unread data in the pipe, but don't\n // store it — we still need to wait for EOF.\n continue;\n }\n\n chunks.push(buf);\n totalBytes += buf.length;\n }\n\n if (truncated) {\n process.stderr.write(`Warning: Piped input exceeded ${MAX_PIPE_BYTES / 1024 / 1024}MB and was truncated.\\n`);\n }\n\n const raw = Buffer.concat(chunks).toString('utf-8');\n\n // Zero out raw buffers so piped secrets don't linger in memory\n for (const buf of chunks) {\n buf.fill(0);\n }\n chunks.length = 0;\n\n const content = sanitizePipedOutput(raw);\n return content.length > 0 ? content : null;\n}\n\n/**\n * Reopen `/dev/tty` (or `CON` on Windows) as `process.stdin` so that the\n * interactive TUI can read keyboard input after the original piped stdin has\n * been consumed.\n *\n * @returns `true` if the swap succeeded, `false` if a TTY could not be opened\n * (e.g. running in a headless CI container with no controlling terminal).\n */\nexport function reopenStdinFromTTY(): boolean {\n const ttyPath = process.platform === 'win32' ? 'CON' : '/dev/tty';\n\n let fd: number;\n try {\n fd = fs.openSync(ttyPath, 'r');\n } catch {\n return false;\n }\n\n const ttyStream = new tty.ReadStream(fd);\n\n Object.defineProperty(process, 'stdin', {\n value: ttyStream,\n writable: true,\n configurable: true,\n });\n\n return true;\n}\n"],"mappings":"AAAA,YAAY,QAAQ;AACpB,YAAY,SAAS;AAGrB,MAAM,iBAAiB,OAAO;AAM9B,MAAM,UAAU;AAYT,SAAS,oBAAoB,KAAqB;AAEvD,MAAI,OAAO,IAAI,QAAQ,SAAS,EAAE;AAGlC,SAAO,KAAK,QAAQ,qCAAqC,EAAE;AAG3D,SAAO,KACJ,MAAM,IAAI,EACV,IAAI,UAAQ;AACX,QAAI,CAAC,KAAK,SAAS,IAAI,EAAG,QAAO;AACjC,UAAM,WAAW,KAAK,MAAM,IAAI;AAGhC,aAAS,IAAI,SAAS,SAAS,GAAG,KAAK,GAAG,KAAK;AAC7C,UAAI,SAAS,CAAC,EAAG,SAAS,EAAG,QAAO,SAAS,CAAC;AAAA,IAChD;AACA,WAAO;AAAA,EACT,CAAC,EACA,KAAK,IAAI;AAGZ,SAAO,KAAK,QAAQ,WAAW,MAAM;AAErC,SAAO,KAAK,KAAK;AACnB;AAaA,eAAsB,kBAA0C;AAC9D,MAAI,QAAQ,MAAM,MAAO,QAAO;AAEhC,QAAM,SAAmB,CAAC;AAC1B,MAAI,aAAa;AACjB,MAAI,YAAY;AAEhB,mBAAiB,SAAS,QAAQ,OAAO;AACvC,UAAM,MAAM;AAEZ,QAAI,aAAa,IAAI,SAAS,gBAAgB;AAG5C,YAAM,YAAY,iBAAiB;AACnC,UAAI,YAAY,GAAG;AACjB,eAAO,KAAK,OAAO,KAAK,IAAI,SAAS,GAAG,SAAS,CAAC,CAAC;AAAA,MACrD;AACA,UAAI,KAAK,CAAC;AACV,mBAAa;AACb,kBAAY;AAGZ;AAAA,IACF;AAEA,WAAO,KAAK,GAAG;AACf,kBAAc,IAAI;AAAA,EACpB;AAEA,MAAI,WAAW;AACb,YAAQ,OAAO,MAAM,iCAAiC,iBAAiB,OAAO,IAAI;AAAA,CAAyB;AAAA,EAC7G;AAEA,QAAM,MAAM,OAAO,OAAO,MAAM,EAAE,SAAS,OAAO;AAGlD,aAAW,OAAO,QAAQ;AACxB,QAAI,KAAK,CAAC;AAAA,EACZ;AACA,SAAO,SAAS;AAEhB,QAAM,UAAU,oBAAoB,GAAG;AACvC,SAAO,QAAQ,SAAS,IAAI,UAAU;AACxC;AAUO,SAAS,qBAA8B;AAC5C,QAAM,UAAU,QAAQ,aAAa,UAAU,QAAQ;AAEvD,MAAI;AACJ,MAAI;AACF,SAAK,GAAG,SAAS,SAAS,GAAG;AAAA,EAC/B,QAAQ;AACN,WAAO;AAAA,EACT;AAEA,QAAM,YAAY,IAAI,IAAI,WAAW,EAAE;AAEvC,SAAO,eAAe,SAAS,SAAS;AAAA,IACtC,OAAO;AAAA,IACP,UAAU;AAAA,IACV,cAAc;AAAA,EAChB,CAAC;AAED,SAAO;AACT;","names":[]}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Storage factory — creates the appropriate storage backend based on resolved config.
|
|
3
|
+
*
|
|
4
|
+
* If PG is selected but fails to connect, falls back to LibSQL so the TUI
|
|
5
|
+
* can start and the user can fix the connection via /settings.
|
|
6
|
+
*/
|
|
7
|
+
import type { MastraCompositeStore, RetentionConfig } from '@mastra/core/storage';
|
|
8
|
+
import type { MastraVector } from '@mastra/core/vector';
|
|
9
|
+
import type { StorageConfig } from './project.js';
|
|
10
|
+
export declare const MASTRA_CODE_LOCAL_PRAGMAS: {
|
|
11
|
+
cacheSize: number;
|
|
12
|
+
mmapSize: number;
|
|
13
|
+
};
|
|
14
|
+
/**
|
|
15
|
+
* Construct a LibSQL store for an arbitrary url/authToken, applying the same
|
|
16
|
+
* local pragmas the default factory uses.
|
|
17
|
+
*/
|
|
18
|
+
export declare function buildLibSQLStore(opts: {
|
|
19
|
+
id?: string;
|
|
20
|
+
url: string;
|
|
21
|
+
authToken?: string;
|
|
22
|
+
retention?: RetentionConfig;
|
|
23
|
+
}): MastraCompositeStore;
|
|
24
|
+
/** Construct a LibSQL vector store for an arbitrary url/authToken. */
|
|
25
|
+
export declare function buildLibSQLVector(opts: {
|
|
26
|
+
id?: string;
|
|
27
|
+
url: string;
|
|
28
|
+
authToken?: string;
|
|
29
|
+
}): MastraVector;
|
|
30
|
+
export interface StorageResult {
|
|
31
|
+
storage: MastraCompositeStore;
|
|
32
|
+
/** The effective backend after any fallback logic has run. */
|
|
33
|
+
backend: 'libsql' | 'pg';
|
|
34
|
+
/** Non-null when PG was requested but failed — contains a user-facing warning. */
|
|
35
|
+
warning?: string;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Create a storage instance from the resolved config.
|
|
39
|
+
*
|
|
40
|
+
* - `libsql` backend → LibSQLStore (always available)
|
|
41
|
+
* - `pg` backend → PostgresStore, falls back to LibSQL on connection failure
|
|
42
|
+
*/
|
|
43
|
+
export declare function createStorage(config: StorageConfig): Promise<StorageResult>;
|
|
44
|
+
/**
|
|
45
|
+
* Create a vector store for recall search.
|
|
46
|
+
* Uses a separate LibSQL file to avoid bloating the main storage DB with embedding data.
|
|
47
|
+
* For PG backends, reuses the same connection (PG handles the extra tables fine).
|
|
48
|
+
*/
|
|
49
|
+
export declare function createVectorStore(config: StorageConfig, effectiveBackend?: 'libsql' | 'pg'): Promise<MastraVector | undefined>;
|
|
50
|
+
//# sourceMappingURL=storage-factory.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"storage-factory.d.ts","sourceRoot":"","sources":["../../src/utils/storage-factory.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,oBAAoB,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAClF,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAIxD,OAAO,KAAK,EAAE,aAAa,EAAmB,MAAM,cAAc,CAAC;AAInE,eAAO,MAAM,yBAAyB;;;CAGrC,CAAC;AAEF;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE;IACrC,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC;IACZ,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,eAAe,CAAC;CAC7B,GAAG,oBAAoB,CAQvB;AAED,sEAAsE;AACtE,wBAAgB,iBAAiB,CAAC,IAAI,EAAE;IAAE,EAAE,CAAC,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,YAAY,CAMtG;AAED,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,oBAAoB,CAAC;IAC9B,8DAA8D;IAC9D,OAAO,EAAE,QAAQ,GAAG,IAAI,CAAC;IACzB,kFAAkF;IAClF,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAMD;;;;;GAKG;AACH,wBAAsB,aAAa,CAAC,MAAM,EAAE,aAAa,GAAG,OAAO,CAAC,aAAa,CAAC,CAUjF;AAyDD;;;;GAIG;AACH,wBAAsB,iBAAiB,CACrC,MAAM,EAAE,aAAa,EACrB,gBAAgB,GAAE,QAAQ,GAAG,IAAqB,GACjD,OAAO,CAAC,YAAY,GAAG,SAAS,CAAC,CAuBnC"}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import { LibSQLStore, LibSQLVector } from "@mastra/libsql";
|
|
2
|
+
import { PostgresStore } from "@mastra/pg";
|
|
3
|
+
import { getDatabasePath, getVectorDatabasePath } from "./project.js";
|
|
4
|
+
import { DEFAULT_RETENTION } from "./storage-maintenance.js";
|
|
5
|
+
const MASTRA_CODE_LOCAL_PRAGMAS = {
|
|
6
|
+
cacheSize: -128e3,
|
|
7
|
+
mmapSize: 536870912
|
|
8
|
+
};
|
|
9
|
+
function buildLibSQLStore(opts) {
|
|
10
|
+
return new LibSQLStore({
|
|
11
|
+
id: opts.id ?? "mastra-code-storage",
|
|
12
|
+
url: opts.url,
|
|
13
|
+
...opts.authToken ? { authToken: opts.authToken } : {},
|
|
14
|
+
...opts.retention ? { retention: opts.retention } : {},
|
|
15
|
+
localPragmas: MASTRA_CODE_LOCAL_PRAGMAS
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
function buildLibSQLVector(opts) {
|
|
19
|
+
return new LibSQLVector({
|
|
20
|
+
id: opts.id ?? "mastra-code-vectors",
|
|
21
|
+
url: opts.url,
|
|
22
|
+
...opts.authToken ? { authToken: opts.authToken } : {}
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
function createFallbackLibSQL() {
|
|
26
|
+
return buildLibSQLStore({ url: `file:${getDatabasePath()}`, retention: DEFAULT_RETENTION });
|
|
27
|
+
}
|
|
28
|
+
async function createStorage(config) {
|
|
29
|
+
if (config.backend === "pg") {
|
|
30
|
+
return createPgStorage(config);
|
|
31
|
+
}
|
|
32
|
+
return {
|
|
33
|
+
storage: buildLibSQLStore({ url: config.url, authToken: config.authToken, retention: DEFAULT_RETENTION }),
|
|
34
|
+
backend: "libsql"
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
async function createPgStorage(config) {
|
|
38
|
+
if (!config.connectionString && !config.host) {
|
|
39
|
+
return {
|
|
40
|
+
storage: createFallbackLibSQL(),
|
|
41
|
+
backend: "libsql",
|
|
42
|
+
warning: "PostgreSQL backend selected but no connection info configured. Using LibSQL fallback. Set a connection string via /settings."
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
const base = {
|
|
46
|
+
id: "mastra-code-storage",
|
|
47
|
+
retention: DEFAULT_RETENTION,
|
|
48
|
+
...config.schemaName ? { schemaName: config.schemaName } : {},
|
|
49
|
+
...config.disableInit ? { disableInit: config.disableInit } : {},
|
|
50
|
+
...config.skipDefaultIndexes ? { skipDefaultIndexes: config.skipDefaultIndexes } : {}
|
|
51
|
+
};
|
|
52
|
+
const store = config.connectionString ? new PostgresStore({ ...base, connectionString: config.connectionString }) : new PostgresStore({
|
|
53
|
+
...base,
|
|
54
|
+
host: config.host,
|
|
55
|
+
port: config.port,
|
|
56
|
+
database: config.database,
|
|
57
|
+
user: config.user,
|
|
58
|
+
password: config.password
|
|
59
|
+
});
|
|
60
|
+
try {
|
|
61
|
+
await store.init();
|
|
62
|
+
} catch (err) {
|
|
63
|
+
const msg = err?.message ?? String(err);
|
|
64
|
+
const target = config.connectionString ?? `${config.host}:${config.port ?? 5432}`;
|
|
65
|
+
try {
|
|
66
|
+
await store.close();
|
|
67
|
+
} catch {
|
|
68
|
+
}
|
|
69
|
+
return {
|
|
70
|
+
storage: createFallbackLibSQL(),
|
|
71
|
+
backend: "libsql",
|
|
72
|
+
warning: `Failed to connect to PostgreSQL at ${target}: ${msg}
|
|
73
|
+
Using LibSQL fallback. Fix the connection via /settings.`
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
return { storage: store, backend: "pg" };
|
|
77
|
+
}
|
|
78
|
+
async function createVectorStore(config, effectiveBackend = config.backend) {
|
|
79
|
+
if (effectiveBackend === "pg") {
|
|
80
|
+
const pgConfig = config;
|
|
81
|
+
if (!pgConfig.connectionString && !pgConfig.host) return void 0;
|
|
82
|
+
const { PgVector } = await import("@mastra/pg");
|
|
83
|
+
return new PgVector({
|
|
84
|
+
id: "mastra-code-vectors",
|
|
85
|
+
connectionString: pgConfig.connectionString ?? `postgresql://${pgConfig.user}:${pgConfig.password}@${pgConfig.host}:${pgConfig.port ?? 5432}/${pgConfig.database}`
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
const libsqlConfig = config;
|
|
89
|
+
return buildLibSQLVector({
|
|
90
|
+
url: libsqlConfig.vectorUrl ?? `file:${getVectorDatabasePath()}`,
|
|
91
|
+
authToken: libsqlConfig.vectorAuthToken
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
export {
|
|
95
|
+
MASTRA_CODE_LOCAL_PRAGMAS,
|
|
96
|
+
buildLibSQLStore,
|
|
97
|
+
buildLibSQLVector,
|
|
98
|
+
createStorage,
|
|
99
|
+
createVectorStore
|
|
100
|
+
};
|
|
101
|
+
//# sourceMappingURL=storage-factory.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/utils/storage-factory.ts"],"sourcesContent":["/**\n * Storage factory — creates the appropriate storage backend based on resolved config.\n *\n * If PG is selected but fails to connect, falls back to LibSQL so the TUI\n * can start and the user can fix the connection via /settings.\n */\n\nimport type { MastraCompositeStore, RetentionConfig } from '@mastra/core/storage';\nimport type { MastraVector } from '@mastra/core/vector';\nimport { LibSQLStore, LibSQLVector } from '@mastra/libsql';\nimport { PostgresStore } from '@mastra/pg';\n\nimport type { StorageConfig, PgStorageConfig } from './project.js';\nimport { getDatabasePath, getVectorDatabasePath } from './project.js';\nimport { DEFAULT_RETENTION } from './storage-maintenance.js';\n\nexport const MASTRA_CODE_LOCAL_PRAGMAS = {\n cacheSize: -128000,\n mmapSize: 536870912,\n};\n\n/**\n * Construct a LibSQL store for an arbitrary url/authToken, applying the same\n * local pragmas the default factory uses.\n */\nexport function buildLibSQLStore(opts: {\n id?: string;\n url: string;\n authToken?: string;\n retention?: RetentionConfig;\n}): MastraCompositeStore {\n return new LibSQLStore({\n id: opts.id ?? 'mastra-code-storage',\n url: opts.url,\n ...(opts.authToken ? { authToken: opts.authToken } : {}),\n ...(opts.retention ? { retention: opts.retention } : {}),\n localPragmas: MASTRA_CODE_LOCAL_PRAGMAS,\n });\n}\n\n/** Construct a LibSQL vector store for an arbitrary url/authToken. */\nexport function buildLibSQLVector(opts: { id?: string; url: string; authToken?: string }): MastraVector {\n return new LibSQLVector({\n id: opts.id ?? 'mastra-code-vectors',\n url: opts.url,\n ...(opts.authToken ? { authToken: opts.authToken } : {}),\n });\n}\n\nexport interface StorageResult {\n storage: MastraCompositeStore;\n /** The effective backend after any fallback logic has run. */\n backend: 'libsql' | 'pg';\n /** Non-null when PG was requested but failed — contains a user-facing warning. */\n warning?: string;\n}\n\nfunction createFallbackLibSQL(): MastraCompositeStore {\n return buildLibSQLStore({ url: `file:${getDatabasePath()}`, retention: DEFAULT_RETENTION });\n}\n\n/**\n * Create a storage instance from the resolved config.\n *\n * - `libsql` backend → LibSQLStore (always available)\n * - `pg` backend → PostgresStore, falls back to LibSQL on connection failure\n */\nexport async function createStorage(config: StorageConfig): Promise<StorageResult> {\n if (config.backend === 'pg') {\n return createPgStorage(config);\n }\n\n // Default: LibSQL\n return {\n storage: buildLibSQLStore({ url: config.url, authToken: config.authToken, retention: DEFAULT_RETENTION }),\n backend: 'libsql',\n };\n}\n\nasync function createPgStorage(config: PgStorageConfig): Promise<StorageResult> {\n // No connection info → fall back with guidance\n if (!config.connectionString && !config.host) {\n return {\n storage: createFallbackLibSQL(),\n backend: 'libsql',\n warning:\n 'PostgreSQL backend selected but no connection info configured. ' +\n 'Using LibSQL fallback. Set a connection string via /settings.',\n };\n }\n\n const base = {\n id: 'mastra-code-storage' as const,\n retention: DEFAULT_RETENTION,\n ...(config.schemaName ? { schemaName: config.schemaName } : {}),\n ...(config.disableInit ? { disableInit: config.disableInit } : {}),\n ...(config.skipDefaultIndexes ? { skipDefaultIndexes: config.skipDefaultIndexes } : {}),\n };\n\n const store = config.connectionString\n ? new PostgresStore({ ...base, connectionString: config.connectionString })\n : new PostgresStore({\n ...base,\n host: config.host!,\n port: config.port,\n database: config.database,\n user: config.user,\n password: config.password,\n });\n\n // Test the connection before committing — if it fails, fall back to LibSQL\n // so the user can fix the config via /settings.\n try {\n await store.init();\n } catch (err: any) {\n const msg = err?.message ?? String(err);\n const target = config.connectionString ?? `${config.host}:${config.port ?? 5432}`;\n try {\n await store.close();\n } catch {\n // ignore cleanup errors\n }\n return {\n storage: createFallbackLibSQL(),\n backend: 'libsql',\n warning:\n `Failed to connect to PostgreSQL at ${target}: ${msg}\\n` +\n 'Using LibSQL fallback. Fix the connection via /settings.',\n };\n }\n\n return { storage: store, backend: 'pg' };\n}\n\n/**\n * Create a vector store for recall search.\n * Uses a separate LibSQL file to avoid bloating the main storage DB with embedding data.\n * For PG backends, reuses the same connection (PG handles the extra tables fine).\n */\nexport async function createVectorStore(\n config: StorageConfig,\n effectiveBackend: 'libsql' | 'pg' = config.backend,\n): Promise<MastraVector | undefined> {\n if (effectiveBackend === 'pg') {\n // PG can handle vector tables in the same database\n const pgConfig = config as PgStorageConfig;\n if (!pgConfig.connectionString && !pgConfig.host) return undefined;\n\n const { PgVector } = await import('@mastra/pg');\n return new PgVector({\n id: 'mastra-code-vectors',\n connectionString:\n pgConfig.connectionString ??\n `postgresql://${pgConfig.user}:${pgConfig.password}@${pgConfig.host}:${pgConfig.port ?? 5432}/${pgConfig.database}`,\n });\n }\n\n // LibSQL: separate file for vectors. Per-tenant configs supply an explicit\n // vectorUrl so each tenant's recall vectors are isolated; otherwise use the\n // shared default file.\n const libsqlConfig = config as { vectorUrl?: string; vectorAuthToken?: string };\n return buildLibSQLVector({\n url: libsqlConfig.vectorUrl ?? `file:${getVectorDatabasePath()}`,\n authToken: libsqlConfig.vectorAuthToken,\n });\n}\n"],"mappings":"AASA,SAAS,aAAa,oBAAoB;AAC1C,SAAS,qBAAqB;AAG9B,SAAS,iBAAiB,6BAA6B;AACvD,SAAS,yBAAyB;AAE3B,MAAM,4BAA4B;AAAA,EACvC,WAAW;AAAA,EACX,UAAU;AACZ;AAMO,SAAS,iBAAiB,MAKR;AACvB,SAAO,IAAI,YAAY;AAAA,IACrB,IAAI,KAAK,MAAM;AAAA,IACf,KAAK,KAAK;AAAA,IACV,GAAI,KAAK,YAAY,EAAE,WAAW,KAAK,UAAU,IAAI,CAAC;AAAA,IACtD,GAAI,KAAK,YAAY,EAAE,WAAW,KAAK,UAAU,IAAI,CAAC;AAAA,IACtD,cAAc;AAAA,EAChB,CAAC;AACH;AAGO,SAAS,kBAAkB,MAAsE;AACtG,SAAO,IAAI,aAAa;AAAA,IACtB,IAAI,KAAK,MAAM;AAAA,IACf,KAAK,KAAK;AAAA,IACV,GAAI,KAAK,YAAY,EAAE,WAAW,KAAK,UAAU,IAAI,CAAC;AAAA,EACxD,CAAC;AACH;AAUA,SAAS,uBAA6C;AACpD,SAAO,iBAAiB,EAAE,KAAK,QAAQ,gBAAgB,CAAC,IAAI,WAAW,kBAAkB,CAAC;AAC5F;AAQA,eAAsB,cAAc,QAA+C;AACjF,MAAI,OAAO,YAAY,MAAM;AAC3B,WAAO,gBAAgB,MAAM;AAAA,EAC/B;AAGA,SAAO;AAAA,IACL,SAAS,iBAAiB,EAAE,KAAK,OAAO,KAAK,WAAW,OAAO,WAAW,WAAW,kBAAkB,CAAC;AAAA,IACxG,SAAS;AAAA,EACX;AACF;AAEA,eAAe,gBAAgB,QAAiD;AAE9E,MAAI,CAAC,OAAO,oBAAoB,CAAC,OAAO,MAAM;AAC5C,WAAO;AAAA,MACL,SAAS,qBAAqB;AAAA,MAC9B,SAAS;AAAA,MACT,SACE;AAAA,IAEJ;AAAA,EACF;AAEA,QAAM,OAAO;AAAA,IACX,IAAI;AAAA,IACJ,WAAW;AAAA,IACX,GAAI,OAAO,aAAa,EAAE,YAAY,OAAO,WAAW,IAAI,CAAC;AAAA,IAC7D,GAAI,OAAO,cAAc,EAAE,aAAa,OAAO,YAAY,IAAI,CAAC;AAAA,IAChE,GAAI,OAAO,qBAAqB,EAAE,oBAAoB,OAAO,mBAAmB,IAAI,CAAC;AAAA,EACvF;AAEA,QAAM,QAAQ,OAAO,mBACjB,IAAI,cAAc,EAAE,GAAG,MAAM,kBAAkB,OAAO,iBAAiB,CAAC,IACxE,IAAI,cAAc;AAAA,IAChB,GAAG;AAAA,IACH,MAAM,OAAO;AAAA,IACb,MAAM,OAAO;AAAA,IACb,UAAU,OAAO;AAAA,IACjB,MAAM,OAAO;AAAA,IACb,UAAU,OAAO;AAAA,EACnB,CAAC;AAIL,MAAI;AACF,UAAM,MAAM,KAAK;AAAA,EACnB,SAAS,KAAU;AACjB,UAAM,MAAM,KAAK,WAAW,OAAO,GAAG;AACtC,UAAM,SAAS,OAAO,oBAAoB,GAAG,OAAO,IAAI,IAAI,OAAO,QAAQ,IAAI;AAC/E,QAAI;AACF,YAAM,MAAM,MAAM;AAAA,IACpB,QAAQ;AAAA,IAER;AACA,WAAO;AAAA,MACL,SAAS,qBAAqB;AAAA,MAC9B,SAAS;AAAA,MACT,SACE,sCAAsC,MAAM,KAAK,GAAG;AAAA;AAAA,IAExD;AAAA,EACF;AAEA,SAAO,EAAE,SAAS,OAAO,SAAS,KAAK;AACzC;AAOA,eAAsB,kBACpB,QACA,mBAAoC,OAAO,SACR;AACnC,MAAI,qBAAqB,MAAM;AAE7B,UAAM,WAAW;AACjB,QAAI,CAAC,SAAS,oBAAoB,CAAC,SAAS,KAAM,QAAO;AAEzD,UAAM,EAAE,SAAS,IAAI,MAAM,OAAO,YAAY;AAC9C,WAAO,IAAI,SAAS;AAAA,MAClB,IAAI;AAAA,MACJ,kBACE,SAAS,oBACT,gBAAgB,SAAS,IAAI,IAAI,SAAS,QAAQ,IAAI,SAAS,IAAI,IAAI,SAAS,QAAQ,IAAI,IAAI,SAAS,QAAQ;AAAA,IACrH,CAAC;AAAA,EACH;AAKA,QAAM,eAAe;AACrB,SAAO,kBAAkB;AAAA,IACvB,KAAK,aAAa,aAAa,QAAQ,sBAAsB,CAAC;AAAA,IAC9D,WAAW,aAAa;AAAA,EAC1B,CAAC;AACH;","names":[]}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Storage maintenance — retention defaults and disk reclamation for mastracode.
|
|
3
|
+
*
|
|
4
|
+
* Retention (`DEFAULT_RETENTION`) is wired into the inner store by the storage
|
|
5
|
+
* factory so `storage.prune()` can delete aged rows across every domain,
|
|
6
|
+
* including the legacy libsql observability spans table.
|
|
7
|
+
*
|
|
8
|
+
* `prune()` only deletes rows — SQLite keeps the freed pages inside the file.
|
|
9
|
+
* `reclaimLibSQLDisk()` returns that space to the OS by streaming a
|
|
10
|
+
* `VACUUM INTO` copy of each file and swapping it into place. It requires all
|
|
11
|
+
* connections to be closed first, so it only runs from the post-TUI
|
|
12
|
+
* maintenance flow. We deliberately do NOT expose VACUUM as a public API on
|
|
13
|
+
* LibSQLStore.
|
|
14
|
+
*/
|
|
15
|
+
import type { MastraCompositeStore, PruneOptions, PruneResult, RetentionConfig } from '@mastra/core/storage';
|
|
16
|
+
import type { StorageConfig } from './project.js';
|
|
17
|
+
/**
|
|
18
|
+
* Default retention for mastracode's own storage. Tables not listed are kept
|
|
19
|
+
* forever. Ages chosen for a local dev tool where observability data dwarfs
|
|
20
|
+
* everything else (spans have been observed at 17+ GB):
|
|
21
|
+
* - spans/logs: short-lived debugging telemetry → 14d
|
|
22
|
+
* - scorer results & workflow snapshots: medium-lived run records → 30d
|
|
23
|
+
* - chat history (messages/threads): long-lived, user-visible → 90d
|
|
24
|
+
*/
|
|
25
|
+
export declare const DEFAULT_RETENTION: RetentionConfig;
|
|
26
|
+
/** Result of reclaiming disk for one database file (sizes include the WAL). */
|
|
27
|
+
export interface ReclaimResult {
|
|
28
|
+
file: string;
|
|
29
|
+
bytesBefore: number;
|
|
30
|
+
bytesAfter: number;
|
|
31
|
+
}
|
|
32
|
+
/** Handle the TUI uses to run storage maintenance without reaching into store internals. */
|
|
33
|
+
export interface StorageMaintenance {
|
|
34
|
+
backend: 'libsql' | 'pg';
|
|
35
|
+
/** Retention policies in effect (for display in /prune output). */
|
|
36
|
+
retention: RetentionConfig;
|
|
37
|
+
/** Delete rows older than the retention policies. Safe to re-run; batched and cancellable. `options.retention` replaces the standing policies for this call only. */
|
|
38
|
+
prune: (options?: PruneOptions) => Promise<PruneResult[]>;
|
|
39
|
+
/** Close the long-lived storage connection (checkpoints WAL for local libsql). Nothing can use the store afterwards. */
|
|
40
|
+
closeStorage?: () => Promise<void>;
|
|
41
|
+
/** Compact local libsql files (VACUUM INTO + swap) to return freed pages to the OS. Only set for local libsql backends. */
|
|
42
|
+
reclaimDisk?: (onFileStart?: (file: string, bytesBefore: number, liveBytes: number) => void) => Promise<ReclaimResult[]>;
|
|
43
|
+
}
|
|
44
|
+
/** Free bytes required before compacting: the compacted copy plus 20% + 256 MB headroom. */
|
|
45
|
+
export declare function requiredFreeBytes(liveBytes: number): number;
|
|
46
|
+
/**
|
|
47
|
+
* Compact each local libsql db file by streaming a `VACUUM INTO` copy next to
|
|
48
|
+
* it, then swapping the copy into place. Reports before/after sizes.
|
|
49
|
+
*
|
|
50
|
+
* Deliberately NOT an in-place `VACUUM`: that copies all live content into a
|
|
51
|
+
* temp store (held in memory by libsql builds with `temp_store=MEMORY`) and
|
|
52
|
+
* then rewrites the entire database back through the WAL — on multi-GB
|
|
53
|
+
* databases that has frozen whole machines via memory/IO exhaustion.
|
|
54
|
+
* `VACUUM INTO` reads the logical database once and writes the compacted copy
|
|
55
|
+
* sequentially with bounded memory, and the WAL never grows.
|
|
56
|
+
*
|
|
57
|
+
* Each file is preflighted: live bytes are estimated from
|
|
58
|
+
* `page_count - freelist_count` and the copy is refused unless the volume has
|
|
59
|
+
* `requiredFreeBytes()` available.
|
|
60
|
+
*
|
|
61
|
+
* MUST run with every connection to these files closed (the swap replaces the
|
|
62
|
+
* inode — a surviving connection would keep writing to the unlinked old file).
|
|
63
|
+
* `runStorageMaintenance()` closes storage before calling this.
|
|
64
|
+
*/
|
|
65
|
+
export declare function reclaimLibSQLDisk(dbFiles: string[], onFileStart?: (file: string, bytesBefore: number, liveBytes: number) => void): Promise<ReclaimResult[]>;
|
|
66
|
+
/**
|
|
67
|
+
* Resolve the local libsql db files eligible for checkpoint + VACUUM.
|
|
68
|
+
* Returns [] for remote (turso) urls and PG backends. When PG was requested
|
|
69
|
+
* but the factory fell back to libsql, the fallback uses the default files.
|
|
70
|
+
*/
|
|
71
|
+
export declare function resolveLocalDbFiles(config: StorageConfig, effectiveBackend: 'libsql' | 'pg'): string[];
|
|
72
|
+
/**
|
|
73
|
+
* Build the maintenance handle for the effective storage backend.
|
|
74
|
+
* `localDbFiles` are the local libsql file paths eligible for VACUUM;
|
|
75
|
+
* pass an empty array for remote (turso) or PG backends.
|
|
76
|
+
*/
|
|
77
|
+
export declare function createStorageMaintenance(opts: {
|
|
78
|
+
storage: MastraCompositeStore;
|
|
79
|
+
backend: 'libsql' | 'pg';
|
|
80
|
+
retention: RetentionConfig;
|
|
81
|
+
localDbFiles: string[];
|
|
82
|
+
/** Closes the vector store's connection; required for local libsql so the compaction swap isn't blocked by our own handle. */
|
|
83
|
+
closeVector?: () => Promise<void>;
|
|
84
|
+
}): StorageMaintenance;
|
|
85
|
+
export declare function formatBytes(bytes: number): string;
|
|
86
|
+
/**
|
|
87
|
+
* Run storage maintenance with exclusive access to the database, reporting
|
|
88
|
+
* progress through `log` (one line per pass so large deletes are visible).
|
|
89
|
+
*
|
|
90
|
+
* Must run AFTER the TUI is stopped and background writers are quiesced —
|
|
91
|
+
* batched deletes and VACUUM contend with live writes (SQLITE_BUSY) and can
|
|
92
|
+
* starve the event loop that renders the TUI. The storage connection is
|
|
93
|
+
* closed at the end (checkpointing the WAL for local libsql), so the process
|
|
94
|
+
* must exit afterwards.
|
|
95
|
+
*/
|
|
96
|
+
export declare function runStorageMaintenance(opts: {
|
|
97
|
+
maintenance: StorageMaintenance;
|
|
98
|
+
vacuum: boolean;
|
|
99
|
+
/** Skip the memory domain (messages/threads) so chat history is preserved. */
|
|
100
|
+
keepMemory?: boolean;
|
|
101
|
+
log: (line: string) => void;
|
|
102
|
+
}): Promise<void>;
|
|
103
|
+
//# sourceMappingURL=storage-maintenance.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"storage-maintenance.d.ts","sourceRoot":"","sources":["../../src/utils/storage-maintenance.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAKH,OAAO,KAAK,EAAE,oBAAoB,EAAE,YAAY,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAQ7G,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAGlD;;;;;;;GAOG;AACH,eAAO,MAAM,iBAAiB,EAAE,eAe/B,CAAC;AAEF,+EAA+E;AAC/E,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,4FAA4F;AAC5F,MAAM,WAAW,kBAAkB;IACjC,OAAO,EAAE,QAAQ,GAAG,IAAI,CAAC;IACzB,mEAAmE;IACnE,SAAS,EAAE,eAAe,CAAC;IAC3B,qKAAqK;IACrK,KAAK,EAAE,CAAC,OAAO,CAAC,EAAE,YAAY,KAAK,OAAO,CAAC,WAAW,EAAE,CAAC,CAAC;IAC1D,wHAAwH;IACxH,YAAY,CAAC,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IACnC,2HAA2H;IAC3H,WAAW,CAAC,EAAE,CACZ,WAAW,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,KAAK,IAAI,KACzE,OAAO,CAAC,aAAa,EAAE,CAAC,CAAC;CAC/B;AAeD,4FAA4F;AAC5F,wBAAgB,iBAAiB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAE3D;AA0BD;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAsB,iBAAiB,CACrC,OAAO,EAAE,MAAM,EAAE,EACjB,WAAW,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,KAAK,IAAI,GAC3E,OAAO,CAAC,aAAa,EAAE,CAAC,CA0G1B;AAQD;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,aAAa,EAAE,gBAAgB,EAAE,QAAQ,GAAG,IAAI,GAAG,MAAM,EAAE,CAatG;AAED;;;;GAIG;AACH,wBAAgB,wBAAwB,CAAC,IAAI,EAAE;IAC7C,OAAO,EAAE,oBAAoB,CAAC;IAC9B,OAAO,EAAE,QAAQ,GAAG,IAAI,CAAC;IACzB,SAAS,EAAE,eAAe,CAAC;IAC3B,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,8HAA8H;IAC9H,WAAW,CAAC,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CACnC,GAAG,kBAAkB,CAiBrB;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAWjD;AAKD;;;;;;;;;GASG;AACH,wBAAsB,qBAAqB,CAAC,IAAI,EAAE;IAChD,WAAW,EAAE,kBAAkB,CAAC;IAChC,MAAM,EAAE,OAAO,CAAC;IAChB,8EAA8E;IAC9E,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,GAAG,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;CAC7B,GAAG,OAAO,CAAC,IAAI,CAAC,CA2EhB"}
|
|
@@ -0,0 +1,236 @@
|
|
|
1
|
+
import { closeSync, existsSync, openSync, readSync, renameSync, rmSync, statSync, statfsSync } from "node:fs";
|
|
2
|
+
import { dirname } from "node:path";
|
|
3
|
+
import Database from "libsql";
|
|
4
|
+
import { getDatabasePath, getVectorDatabasePath } from "./project.js";
|
|
5
|
+
const DEFAULT_RETENTION = {
|
|
6
|
+
memory: {
|
|
7
|
+
messages: { maxAge: "90d" },
|
|
8
|
+
threads: { maxAge: "90d" }
|
|
9
|
+
},
|
|
10
|
+
observability: {
|
|
11
|
+
spans: { maxAge: "14d" },
|
|
12
|
+
logs: { maxAge: "14d" }
|
|
13
|
+
},
|
|
14
|
+
scores: {
|
|
15
|
+
scorers: { maxAge: "30d" }
|
|
16
|
+
},
|
|
17
|
+
workflows: {
|
|
18
|
+
workflowSnapshot: { maxAge: "30d" }
|
|
19
|
+
}
|
|
20
|
+
};
|
|
21
|
+
function fileSizeWithWal(dbFile) {
|
|
22
|
+
let total = 0;
|
|
23
|
+
for (const candidate of [dbFile, `${dbFile}-wal`]) {
|
|
24
|
+
try {
|
|
25
|
+
total += statSync(candidate).size;
|
|
26
|
+
} catch {
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
return total;
|
|
30
|
+
}
|
|
31
|
+
function requiredFreeBytes(liveBytes) {
|
|
32
|
+
return Math.ceil(liveBytes * 1.2) + 256 * 1024 * 1024;
|
|
33
|
+
}
|
|
34
|
+
function pragmaNumber(db, pragma) {
|
|
35
|
+
const rows = db.pragma(pragma);
|
|
36
|
+
const row = rows?.[0];
|
|
37
|
+
return row ? Number(Object.values(row)[0]) : 0;
|
|
38
|
+
}
|
|
39
|
+
function journalModeFromHeader(file) {
|
|
40
|
+
const fd = openSync(file, "r");
|
|
41
|
+
try {
|
|
42
|
+
const buf = Buffer.alloc(2);
|
|
43
|
+
if (readSync(fd, buf, 0, 2, 18) !== 2) return "unknown";
|
|
44
|
+
if (buf[0] === 2 && buf[1] === 2) return "wal";
|
|
45
|
+
if (buf[0] === 1 && buf[1] === 1) return "delete";
|
|
46
|
+
return "unknown";
|
|
47
|
+
} finally {
|
|
48
|
+
closeSync(fd);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
async function reclaimLibSQLDisk(dbFiles, onFileStart) {
|
|
52
|
+
const results = [];
|
|
53
|
+
for (const file of dbFiles) {
|
|
54
|
+
if (!existsSync(file) || statSync(file).size < 100) continue;
|
|
55
|
+
const bytesBefore = fileSizeWithWal(file);
|
|
56
|
+
const tmp = `${file}.vacuum-tmp`;
|
|
57
|
+
rmSync(tmp, { force: true });
|
|
58
|
+
const probe = new Database(file);
|
|
59
|
+
try {
|
|
60
|
+
probe.exec("PRAGMA busy_timeout = 2000");
|
|
61
|
+
probe.exec("PRAGMA journal_mode = WAL");
|
|
62
|
+
probe.exec("PRAGMA journal_mode = DELETE");
|
|
63
|
+
} catch {
|
|
64
|
+
} finally {
|
|
65
|
+
probe.close();
|
|
66
|
+
}
|
|
67
|
+
if (journalModeFromHeader(file) !== "delete") {
|
|
68
|
+
throw new Error(
|
|
69
|
+
`${file} is in use by another process \u2014 is another Mastra Code session running? Close other sessions and run /prune vacuum again.`
|
|
70
|
+
);
|
|
71
|
+
}
|
|
72
|
+
const db = new Database(file);
|
|
73
|
+
try {
|
|
74
|
+
db.exec("PRAGMA busy_timeout = 2000");
|
|
75
|
+
const pageSize = pragmaNumber(db, "page_size");
|
|
76
|
+
const pageCount = pragmaNumber(db, "page_count");
|
|
77
|
+
const freelistCount = pragmaNumber(db, "freelist_count");
|
|
78
|
+
const liveBytes = Math.max(0, pageCount - freelistCount) * pageSize;
|
|
79
|
+
const { bsize, bavail } = statfsSync(dirname(file));
|
|
80
|
+
const freeBytes = bsize * bavail;
|
|
81
|
+
if (freeBytes < requiredFreeBytes(liveBytes)) {
|
|
82
|
+
throw new Error(
|
|
83
|
+
`Not enough free disk space to compact ${file}: need ${formatBytes(requiredFreeBytes(liveBytes))} for a ${formatBytes(liveBytes)} compacted copy, but only ${formatBytes(freeBytes)} is free.`
|
|
84
|
+
);
|
|
85
|
+
}
|
|
86
|
+
onFileStart?.(file, bytesBefore, liveBytes);
|
|
87
|
+
db.exec(`VACUUM INTO '${tmp.replace(/'/g, "''")}'`);
|
|
88
|
+
} catch (err) {
|
|
89
|
+
rmSync(tmp, { force: true });
|
|
90
|
+
throw err;
|
|
91
|
+
} finally {
|
|
92
|
+
db.close();
|
|
93
|
+
}
|
|
94
|
+
if (journalModeFromHeader(file) !== "delete") {
|
|
95
|
+
rmSync(tmp, { force: true });
|
|
96
|
+
throw new Error(
|
|
97
|
+
`${file} was opened by another process during compaction \u2014 is another Mastra Code session running? Close other sessions and run /prune vacuum again.`
|
|
98
|
+
);
|
|
99
|
+
}
|
|
100
|
+
renameSync(file, `${file}.old`);
|
|
101
|
+
try {
|
|
102
|
+
rmSync(`${file}-wal`, { force: true });
|
|
103
|
+
rmSync(`${file}-shm`, { force: true });
|
|
104
|
+
renameSync(tmp, file);
|
|
105
|
+
} catch (err) {
|
|
106
|
+
try {
|
|
107
|
+
renameSync(`${file}.old`, file);
|
|
108
|
+
} catch {
|
|
109
|
+
throw new Error(
|
|
110
|
+
`Failed to swap compacted copy into place AND failed to restore the original \u2014 your data is intact at ${file}.old; rename it back to ${file} manually. Original error: ${err instanceof Error ? err.message : String(err)}`
|
|
111
|
+
);
|
|
112
|
+
}
|
|
113
|
+
rmSync(tmp, { force: true });
|
|
114
|
+
throw err;
|
|
115
|
+
}
|
|
116
|
+
rmSync(`${file}.old`, { force: true });
|
|
117
|
+
results.push({ file, bytesBefore, bytesAfter: fileSizeWithWal(file) });
|
|
118
|
+
}
|
|
119
|
+
return results;
|
|
120
|
+
}
|
|
121
|
+
function fileUrlToPath(url) {
|
|
122
|
+
if (!url.startsWith("file:")) return void 0;
|
|
123
|
+
return url.replace(/^file:\/\//, "").replace(/^file:/, "");
|
|
124
|
+
}
|
|
125
|
+
function resolveLocalDbFiles(config, effectiveBackend) {
|
|
126
|
+
if (effectiveBackend !== "libsql") return [];
|
|
127
|
+
if (config.backend === "pg") {
|
|
128
|
+
return [getDatabasePath(), getVectorDatabasePath()];
|
|
129
|
+
}
|
|
130
|
+
if (config.isRemote) return [];
|
|
131
|
+
const files = [];
|
|
132
|
+
const main = fileUrlToPath(config.url);
|
|
133
|
+
if (main) files.push(main);
|
|
134
|
+
const vector = config.vectorUrl ? fileUrlToPath(config.vectorUrl) : getVectorDatabasePath();
|
|
135
|
+
if (vector) files.push(vector);
|
|
136
|
+
return files;
|
|
137
|
+
}
|
|
138
|
+
function createStorageMaintenance(opts) {
|
|
139
|
+
const { storage, backend, retention, localDbFiles, closeVector } = opts;
|
|
140
|
+
return {
|
|
141
|
+
backend,
|
|
142
|
+
retention,
|
|
143
|
+
prune: (options) => storage.prune(options),
|
|
144
|
+
closeStorage: async () => {
|
|
145
|
+
await storage.close?.();
|
|
146
|
+
await closeVector?.();
|
|
147
|
+
},
|
|
148
|
+
...backend === "libsql" && localDbFiles.length > 0 ? {
|
|
149
|
+
reclaimDisk: (onFileStart) => reclaimLibSQLDisk(localDbFiles, onFileStart)
|
|
150
|
+
} : {}
|
|
151
|
+
};
|
|
152
|
+
}
|
|
153
|
+
function formatBytes(bytes) {
|
|
154
|
+
if (bytes < 1024) return `${bytes} B`;
|
|
155
|
+
const units = ["KB", "MB", "GB", "TB"];
|
|
156
|
+
let value = bytes;
|
|
157
|
+
let unit = "B";
|
|
158
|
+
for (const next of units) {
|
|
159
|
+
if (value < 1024) break;
|
|
160
|
+
value /= 1024;
|
|
161
|
+
unit = next;
|
|
162
|
+
}
|
|
163
|
+
return `${value.toFixed(1)} ${unit}`;
|
|
164
|
+
}
|
|
165
|
+
const PASS_MAX_BATCHES = 20;
|
|
166
|
+
async function runStorageMaintenance(opts) {
|
|
167
|
+
const { maintenance, vacuum, keepMemory = false, log } = opts;
|
|
168
|
+
const { memory: _memory, ...withoutMemory } = maintenance.retention;
|
|
169
|
+
const retentionForRun = keepMemory ? { retention: withoutMemory } : {};
|
|
170
|
+
log("Pruning rows older than the retention policies:");
|
|
171
|
+
for (const [domain, tables] of Object.entries(maintenance.retention)) {
|
|
172
|
+
for (const [table, policy] of Object.entries(tables ?? {})) {
|
|
173
|
+
const kept = keepMemory && domain === "memory";
|
|
174
|
+
log(` ${domain}.${table}: ${kept ? "kept (keep-memory)" : policy.maxAge}`);
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
const totals = /* @__PURE__ */ new Map();
|
|
178
|
+
for (; ; ) {
|
|
179
|
+
const results = await maintenance.prune({ maxBatches: PASS_MAX_BATCHES, ...retentionForRun });
|
|
180
|
+
if (results.length === 0) break;
|
|
181
|
+
let remaining = false;
|
|
182
|
+
let deletedThisPass = 0;
|
|
183
|
+
for (const r of results) {
|
|
184
|
+
const key = `${r.domain}.${r.table}`;
|
|
185
|
+
totals.set(key, (totals.get(key) ?? 0) + r.deleted);
|
|
186
|
+
deletedThisPass += r.deleted;
|
|
187
|
+
if (!r.done) remaining = true;
|
|
188
|
+
if (r.deleted > 0) {
|
|
189
|
+
log(` ${key}: ${totals.get(key)} rows deleted${r.done ? "" : " so far\u2026"}`);
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
if (!remaining) break;
|
|
193
|
+
if (deletedThisPass === 0) {
|
|
194
|
+
log(" stopping: no progress in the last pass.");
|
|
195
|
+
break;
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
const totalDeleted = [...totals.values()].reduce((sum, n) => sum + n, 0);
|
|
199
|
+
log(
|
|
200
|
+
totalDeleted === 0 ? "Nothing to prune \u2014 no retention-eligible rows found." : `Prune complete: ${totalDeleted} rows deleted.`
|
|
201
|
+
);
|
|
202
|
+
await maintenance.closeStorage?.();
|
|
203
|
+
if (!vacuum) {
|
|
204
|
+
if (maintenance.reclaimDisk) {
|
|
205
|
+
log("Deleted rows free pages inside the db file but not on disk. Run /prune vacuum to reclaim disk space.");
|
|
206
|
+
}
|
|
207
|
+
return;
|
|
208
|
+
}
|
|
209
|
+
if (!maintenance.reclaimDisk) {
|
|
210
|
+
log("Disk reclamation (VACUUM) is only available for local libsql storage.");
|
|
211
|
+
return;
|
|
212
|
+
}
|
|
213
|
+
log("Reclaiming disk (compacting database files)\u2026 this can take several minutes on large databases.");
|
|
214
|
+
const reclaimed = await maintenance.reclaimDisk((file, bytesBefore, liveBytes) => {
|
|
215
|
+
log(` vacuuming ${file} (${formatBytes(bytesBefore)}, ~${formatBytes(liveBytes)} live)\u2026`);
|
|
216
|
+
});
|
|
217
|
+
if (reclaimed.length === 0) {
|
|
218
|
+
log("No local database files found to vacuum.");
|
|
219
|
+
return;
|
|
220
|
+
}
|
|
221
|
+
for (const r of reclaimed) {
|
|
222
|
+
log(` ${r.file}: ${formatBytes(r.bytesBefore)} \u2192 ${formatBytes(r.bytesAfter)}`);
|
|
223
|
+
}
|
|
224
|
+
const saved = reclaimed.reduce((sum, r) => sum + Math.max(0, r.bytesBefore - r.bytesAfter), 0);
|
|
225
|
+
log(`Reclaimed ${formatBytes(saved)}.`);
|
|
226
|
+
}
|
|
227
|
+
export {
|
|
228
|
+
DEFAULT_RETENTION,
|
|
229
|
+
createStorageMaintenance,
|
|
230
|
+
formatBytes,
|
|
231
|
+
reclaimLibSQLDisk,
|
|
232
|
+
requiredFreeBytes,
|
|
233
|
+
resolveLocalDbFiles,
|
|
234
|
+
runStorageMaintenance
|
|
235
|
+
};
|
|
236
|
+
//# sourceMappingURL=storage-maintenance.js.map
|