@mastra/factory 0.25.0-alpha.4 → 0.25.0-alpha.6
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 +3 -1
- package/dist/auth.js +1 -2
- package/dist/boards/define-board.js +1 -2
- package/dist/boards/index.js +1 -2
- package/dist/boards/registry.js +1 -2
- package/dist/boards/relocate.js +1 -2
- package/dist/boards/review.js +1 -2
- package/dist/boards/semantics.js +1 -2
- package/dist/boards/transition-policy.js +1 -2
- package/dist/boards/work-tool-rules.js +1 -2
- package/dist/boards/work-transition-policy.js +1 -2
- package/dist/boards/work.js +1 -2
- package/dist/default-thinking-level.d.ts +3 -0
- package/dist/default-thinking-level.d.ts.map +1 -0
- package/dist/default-thinking-level.js +5 -0
- package/dist/default-thinking-level.js.map +1 -0
- package/dist/environment/build-runner.js +1 -2
- package/dist/environment/build-schedule.js +1 -2
- package/dist/environment/build-workflow.js +1 -2
- package/dist/environment/build.js +1 -2
- package/dist/environment/heads.js +1 -2
- package/dist/factory.d.ts +4 -2
- package/dist/factory.d.ts.map +1 -1
- package/dist/factory.js +62 -21
- package/dist/factory.js.map +1 -1
- package/dist/feed-events.js +1 -2
- package/dist/index.js +2 -2
- package/dist/integrations/channel-thread-announcements.d.ts +8 -0
- package/dist/integrations/channel-thread-announcements.d.ts.map +1 -0
- package/dist/integrations/channel-thread-announcements.js +16 -0
- package/dist/integrations/channel-thread-announcements.js.map +1 -0
- package/dist/integrations/github/acceptance-labels.js +1 -2
- package/dist/integrations/github/app-identity.js +1 -2
- package/dist/integrations/github/commits.js +1 -2
- package/dist/integrations/github/config.js +1 -2
- package/dist/integrations/github/default-rules.js +2 -3
- package/dist/integrations/github/integration.js +3 -4
- package/dist/integrations/github/issue-reconciler.js +1 -2
- package/dist/integrations/github/pat.js +1 -2
- package/dist/integrations/github/provenance.d.ts.map +1 -1
- package/dist/integrations/github/provenance.js +2 -5
- package/dist/integrations/github/provenance.js.map +1 -1
- package/dist/integrations/github/reconcile-worker.js +1 -2
- package/dist/integrations/github/reconciliation-config.js +1 -2
- package/dist/integrations/github/routes.js +4 -5
- package/dist/integrations/github/rules.d.ts.map +1 -1
- package/dist/integrations/github/rules.js +14 -3
- package/dist/integrations/github/rules.js.map +1 -1
- package/dist/integrations/github/sandbox-release.js +1 -2
- package/dist/integrations/github/sandbox.js +1 -2
- package/dist/integrations/github/session-subscriptions.js +1 -2
- package/dist/integrations/github/settle-or-abort.js +1 -2
- package/dist/integrations/github/stale-reviews.js +1 -2
- package/dist/integrations/github/subscriptions.js +1 -2
- package/dist/integrations/github/token-refresh.js +1 -2
- package/dist/integrations/github/webhook.d.ts.map +1 -1
- package/dist/integrations/github/webhook.js +17 -3
- package/dist/integrations/github/webhook.js.map +1 -1
- package/dist/integrations/gitlab/agent-tools.js +1 -2
- package/dist/integrations/gitlab/api.js +1 -2
- package/dist/integrations/gitlab/default-rules.js +1 -2
- package/dist/integrations/gitlab/integration.d.ts +4 -0
- package/dist/integrations/gitlab/integration.d.ts.map +1 -1
- package/dist/integrations/gitlab/integration.js +12 -4
- package/dist/integrations/gitlab/integration.js.map +1 -1
- package/dist/integrations/gitlab/issue-reconciler.js +1 -2
- package/dist/integrations/gitlab/merge-request-reconciler.js +1 -2
- package/dist/integrations/gitlab/reconciler.js +1 -2
- package/dist/integrations/gitlab/reconciliation-config.js +1 -2
- package/dist/integrations/gitlab/routes.d.ts +6 -0
- package/dist/integrations/gitlab/routes.d.ts.map +1 -1
- package/dist/integrations/gitlab/routes.js +154 -3
- package/dist/integrations/gitlab/routes.js.map +1 -1
- package/dist/integrations/gitlab/rules.d.ts.map +1 -1
- package/dist/integrations/gitlab/rules.js +5 -3
- package/dist/integrations/gitlab/rules.js.map +1 -1
- package/dist/integrations/gitlab/session-subscriptions.js +1 -2
- package/dist/integrations/gitlab/subscriptions.js +1 -2
- package/dist/integrations/gitlab/version-control.js +1 -2
- package/dist/integrations/gitlab/webhook-dispatch.js +1 -2
- package/dist/integrations/gitlab/webhook.js +1 -2
- package/dist/integrations/incidentio/agent-tools.js +1 -2
- package/dist/integrations/incidentio/api.js +1 -2
- package/dist/integrations/incidentio/claim.js +1 -2
- package/dist/integrations/incidentio/default-rules.js +1 -2
- package/dist/integrations/incidentio/intake.js +1 -2
- package/dist/integrations/incidentio/integration.js +1 -2
- package/dist/integrations/incidentio/issue-reconciler.js +1 -2
- package/dist/integrations/incidentio/reconciliation-config.js +1 -2
- package/dist/integrations/incidentio/routes.js +1 -2
- package/dist/integrations/incidentio/rules.js +1 -2
- package/dist/integrations/issue-reconcile-worker.js +1 -2
- package/dist/integrations/issue-reconciler.js +1 -2
- package/dist/integrations/jira/adf.js +1 -2
- package/dist/integrations/jira/agent-tools.js +1 -2
- package/dist/integrations/jira/api.d.ts +1 -1
- package/dist/integrations/jira/api.d.ts.map +1 -1
- package/dist/integrations/jira/api.js +2 -3
- package/dist/integrations/jira/api.js.map +1 -1
- package/dist/integrations/jira/claim.js +1 -2
- package/dist/integrations/jira/default-rules.js +1 -2
- package/dist/integrations/jira/integration.d.ts +3 -1
- package/dist/integrations/jira/integration.d.ts.map +1 -1
- package/dist/integrations/jira/integration.js +18 -4
- package/dist/integrations/jira/integration.js.map +1 -1
- package/dist/integrations/jira/issue-reconciler.js +1 -2
- package/dist/integrations/jira/reconciliation-config.js +1 -2
- package/dist/integrations/jira/routes.js +1 -2
- package/dist/integrations/jira/rules.js +1 -2
- package/dist/integrations/linear/agent-tools.d.ts +1 -1
- package/dist/integrations/linear/agent-tools.d.ts.map +1 -1
- package/dist/integrations/linear/agent-tools.js +5 -5
- package/dist/integrations/linear/agent-tools.js.map +1 -1
- package/dist/integrations/linear/claim.js +1 -2
- package/dist/integrations/linear/default-rules.js +1 -2
- package/dist/integrations/linear/integration.d.ts +2 -0
- package/dist/integrations/linear/integration.d.ts.map +1 -1
- package/dist/integrations/linear/integration.js +2 -2
- package/dist/integrations/linear/integration.js.map +1 -1
- package/dist/integrations/linear/issue-reconciler.js +1 -2
- package/dist/integrations/linear/reconciliation-config.js +1 -2
- package/dist/integrations/linear/routes.js +1 -2
- package/dist/integrations/linear/rules.js +1 -2
- package/dist/integrations/platform/api-client.js +1 -2
- package/dist/integrations/platform/connect/routes.js +1 -2
- package/dist/integrations/platform/github/event-worker.js +6 -2
- package/dist/integrations/platform/github/event-worker.js.map +1 -1
- package/dist/integrations/platform/github/integration.js +1 -2
- package/dist/integrations/platform/gitlab/event-worker.js +1 -2
- package/dist/integrations/platform/gitlab/integration.js +1 -2
- package/dist/integrations/platform/incidentio/integration.js +1 -2
- package/dist/integrations/platform/jira/agent-tools.js +1 -2
- package/dist/integrations/platform/jira/integration.js +1 -2
- package/dist/integrations/platform/jira/routes.js +1 -2
- package/dist/integrations/platform/linear/event-worker.js +1 -2
- package/dist/integrations/platform/linear/integration.d.ts.map +1 -1
- package/dist/integrations/platform/linear/integration.js +2 -2
- package/dist/integrations/platform/linear/integration.js.map +1 -1
- package/dist/integrations/pull-request-head.d.ts +1 -0
- package/dist/integrations/pull-request-head.d.ts.map +1 -1
- package/dist/integrations/pull-request-head.js +3 -3
- package/dist/integrations/pull-request-head.js.map +1 -1
- package/dist/integrations/reconciliation-config.js +1 -2
- package/dist/integrations/slack/channel-reply-processor.d.ts +1 -0
- package/dist/integrations/slack/channel-reply-processor.d.ts.map +1 -1
- package/dist/integrations/slack/channel-reply-processor.js +16 -6
- package/dist/integrations/slack/channel-reply-processor.js.map +1 -1
- package/dist/integrations/slack/channel-session-link-processor.d.ts +1 -0
- package/dist/integrations/slack/channel-session-link-processor.d.ts.map +1 -1
- package/dist/integrations/slack/channel-session-link-processor.js +2 -3
- package/dist/integrations/slack/channel-session-link-processor.js.map +1 -1
- package/dist/integrations/slack/connect-route.js +1 -2
- package/dist/integrations/slack/emoji-shortcodes.generated.js +1 -2
- package/dist/integrations/slack/emoji.js +1 -2
- package/dist/integrations/slack/feed-publisher.js +1 -2
- package/dist/integrations/slack/integration.d.ts +5 -0
- package/dist/integrations/slack/integration.d.ts.map +1 -1
- package/dist/integrations/slack/integration.js +13 -2
- package/dist/integrations/slack/integration.js.map +1 -1
- package/dist/integrations/slack/reply-reminder-processor.js +1 -2
- package/dist/integrations/slack/reply-tool.d.ts.map +1 -1
- package/dist/integrations/slack/reply-tool.js +4 -13
- package/dist/integrations/slack/reply-tool.js.map +1 -1
- package/dist/integrations/slack/run-error-card.d.ts +3 -0
- package/dist/integrations/slack/run-error-card.d.ts.map +1 -0
- package/dist/integrations/slack/run-error-card.js +44 -0
- package/dist/integrations/slack/run-error-card.js.map +1 -0
- package/dist/integrations/slack/share-file-tool.js +1 -2
- package/dist/integrations/slack/slack.d.ts.map +1 -1
- package/dist/integrations/slack/slack.js +7 -4
- package/dist/integrations/slack/slack.js.map +1 -1
- package/dist/integrations/subscription-session.js +1 -2
- package/dist/integrations/workos/integration.js +1 -2
- package/dist/mcp/disconnect.js +1 -2
- package/dist/mcp/events.js +2 -3
- package/dist/mcp/routes.js +1 -2
- package/dist/packages/_internals/workspace/dist/index.js +1 -2
- package/dist/packages/_internals/workspace/dist/index.js.map +1 -1
- package/dist/platform-auth-host.js +1 -2
- package/dist/provider-display-name.js +1 -2
- package/dist/review-verdict.d.ts +1 -0
- package/dist/review-verdict.d.ts.map +1 -1
- package/dist/review-verdict.js +9 -3
- package/dist/review-verdict.js.map +1 -1
- package/dist/routes/attention-activity.js +1 -2
- package/dist/routes/attention-parked.js +1 -2
- package/dist/routes/attention-proposed.js +1 -2
- package/dist/routes/attention-providers.js +1 -2
- package/dist/routes/attention.js +1 -2
- package/dist/routes/automation-runs.js +1 -2
- package/dist/routes/config.d.ts +7 -0
- package/dist/routes/config.d.ts.map +1 -1
- package/dist/routes/config.js +29 -3
- package/dist/routes/config.js.map +1 -1
- package/dist/routes/contracts.js +1 -2
- package/dist/routes/custom-provider-source.js +1 -2
- package/dist/routes/fs.js +1 -2
- package/dist/routes/intake.js +6 -4
- package/dist/routes/intake.js.map +1 -1
- package/dist/routes/knowledge.js +1 -2
- package/dist/routes/oauth.js +1 -2
- package/dist/routes/projects.js +1 -2
- package/dist/routes/provider-credentials.js +1 -2
- package/dist/routes/route.js +1 -2
- package/dist/routes/session-access.js +1 -2
- package/dist/routes/skills.js +1 -2
- package/dist/routes/source-control-sessions.js +5 -6
- package/dist/routes/source-control-settings.js +1 -2
- package/dist/routes/surface.js +3 -4
- package/dist/routes/surface.js.map +1 -1
- package/dist/routes/telemetry.js +1 -2
- package/dist/routes/tenant-credentials.js +1 -2
- package/dist/routes/work-items.js +2 -3
- package/dist/rules/binding-context.js +1 -2
- package/dist/rules/decision-applicability.js +1 -2
- package/dist/rules/dispatch-errors.js +1 -2
- package/dist/rules/dispatcher.d.ts.map +1 -1
- package/dist/rules/dispatcher.js +9 -3
- package/dist/rules/dispatcher.js.map +1 -1
- package/dist/rules/event-rules.js +1 -2
- package/dist/rules/processor.js +1 -2
- package/dist/rules/resolve.js +1 -2
- package/dist/rules/review-source-tool.js +1 -2
- package/dist/rules/start-coordinator.js +1 -2
- package/dist/rules/terminal-cleanup.js +1 -2
- package/dist/rules/tools.js +1 -2
- package/dist/rules/transition-service.js +1 -2
- package/dist/rules/types.d.ts +4 -1
- package/dist/rules/types.d.ts.map +1 -1
- package/dist/rules/types.js +1 -2
- package/dist/rules/types.js.map +1 -1
- package/dist/rules/validation.js +1 -2
- package/dist/run-error.d.ts +13 -0
- package/dist/run-error.d.ts.map +1 -0
- package/dist/run-error.js +81 -0
- package/dist/run-error.js.map +1 -0
- package/dist/sandbox/callback-factory-sandbox.js +1 -2
- package/dist/sandbox/git-ref.js +1 -2
- package/dist/sandbox/local-factory-sandbox.d.ts +12 -4
- package/dist/sandbox/local-factory-sandbox.d.ts.map +1 -1
- package/dist/sandbox/local-factory-sandbox.js +32 -7
- package/dist/sandbox/local-factory-sandbox.js.map +1 -1
- package/dist/sandbox/materialization.js +1 -2
- package/dist/sandbox/session-retirement.js +1 -2
- package/dist/sandbox/session-sandbox.js +1 -2
- package/dist/sandbox/workdir.js +1 -2
- package/dist/secret-encryption.js +1 -2
- package/dist/server-error.js +1 -2
- package/dist/session/credential-policy.js +1 -2
- package/dist/session/default-model-hydration.js +1 -2
- package/dist/session/environment-repositories.js +1 -2
- package/dist/session/environment-state-processor.d.ts +0 -1
- package/dist/session/environment-state-processor.d.ts.map +1 -1
- package/dist/session/environment-state-processor.js +2 -3
- package/dist/session/environment-state-processor.js.map +1 -1
- package/dist/session/factory-session.js +1 -2
- package/dist/session/filesystem-capture.js +2 -3
- package/dist/session/filesystem-capture.js.map +1 -1
- package/dist/session/first-exec-capture.js +2 -3
- package/dist/session/first-exec-capture.js.map +1 -1
- package/dist/session/first-message-capture.js +1 -2
- package/dist/session/live-sessions.js +1 -2
- package/dist/session/memory-settings-hydration.js +1 -2
- package/dist/session/org-seed.js +1 -2
- package/dist/session/reply-credential-processor.js +1 -2
- package/dist/session/resource-migration.js +1 -2
- package/dist/session/run-audit.js +1 -2
- package/dist/session/session-threads.js +1 -2
- package/dist/session/session-title.js +1 -2
- package/dist/session/shell-commands.js +1 -2
- package/dist/session/source-control-tools.js +2 -3
- package/dist/session/thinking-default.d.ts +1 -1
- package/dist/session/thinking-default.d.ts.map +1 -1
- package/dist/session/thinking-default.js +11 -13
- package/dist/session/thinking-default.js.map +1 -1
- package/dist/session/thread-session-stamp.js +1 -2
- package/dist/session/thread-title-mirror.js +1 -2
- package/dist/session/thread-title-mirror.js.map +1 -1
- package/dist/session/work-item-repository.js +1 -2
- package/dist/session-owner-signal.js +1 -2
- package/dist/skills/catalog.js +1 -2
- package/dist/skills/service.js +1 -2
- package/dist/spa-static.js +1 -2
- package/dist/state-signing.js +1 -2
- package/dist/storage/domains/audit/actions.js +1 -2
- package/dist/storage/domains/audit/actors.js +1 -2
- package/dist/storage/domains/audit/agent-audit.js +1 -2
- package/dist/storage/domains/audit/base.js +1 -2
- package/dist/storage/domains/audit/domain.js +1 -2
- package/dist/storage/domains/audit/wire.js +1 -2
- package/dist/storage/domains/channel-identity/base.js +1 -2
- package/dist/storage/domains/comments/activity.js +1 -2
- package/dist/storage/domains/comments/actor.js +1 -2
- package/dist/storage/domains/comments/base.js +1 -2
- package/dist/storage/domains/comments/domain.js +1 -2
- package/dist/storage/domains/comments/feed-context.js +1 -2
- package/dist/storage/domains/comments/parse.js +1 -2
- package/dist/storage/domains/comments/routes.js +1 -2
- package/dist/storage/domains/comments/schema.js +1 -2
- package/dist/storage/domains/comments/wire.js +1 -2
- package/dist/storage/domains/credentials/base.d.ts +4 -1
- package/dist/storage/domains/credentials/base.d.ts.map +1 -1
- package/dist/storage/domains/credentials/base.js +40 -44
- package/dist/storage/domains/credentials/base.js.map +1 -1
- package/dist/storage/domains/custom-providers/base.js +1 -2
- package/dist/storage/domains/filesystem/base.js +1 -2
- package/dist/storage/domains/intake/base.d.ts +5 -0
- package/dist/storage/domains/intake/base.d.ts.map +1 -1
- package/dist/storage/domains/intake/base.js +10 -2
- package/dist/storage/domains/intake/base.js.map +1 -1
- package/dist/storage/domains/integrations/base.js +1 -2
- package/dist/storage/domains/memory-settings/base.js +1 -2
- package/dist/storage/domains/model-defaults/base.js +1 -2
- package/dist/storage/domains/projects/base.d.ts +0 -1
- package/dist/storage/domains/projects/base.d.ts.map +1 -1
- package/dist/storage/domains/projects/base.js +5 -6
- package/dist/storage/domains/projects/base.js.map +1 -1
- package/dist/storage/domains/queue-health/base.js +1 -2
- package/dist/storage/domains/source-control/base.js +1 -2
- package/dist/storage/domains/source-control/inmemory.js +1 -2
- package/dist/storage/domains/work-items/base.js +1 -2
- package/dist/storage/domains/work-items/board-version.js +1 -2
- package/dist/storage/domains/work-items/metrics.js +1 -2
- package/dist/telemetry-types.js +1 -2
- package/dist/telemetry.js +1 -2
- package/dist/timing.js +1 -2
- package/dist/tools/annotations.js +1 -2
- package/dist/tools/approval-tools.js +1 -2
- package/dist/tools/deliver.js +2 -3
- package/dist/tools/index.js +1 -2
- package/dist/tools/messaging-tools.js +1 -2
- package/dist/tools/permissions.js +1 -2
- package/dist/tools/read-tools.js +1 -2
- package/dist/tools/reports.js +1 -2
- package/dist/tools/run-watch.d.ts +0 -2
- package/dist/tools/run-watch.d.ts.map +1 -1
- package/dist/tools/run-watch.js +4 -44
- package/dist/tools/run-watch.js.map +1 -1
- package/dist/tools/sandbox-tools.js +1 -2
- package/dist/tools/scope.js +2 -3
- package/dist/tools/session-tools.js +1 -2
- package/dist/tools/sessions-state-processor.js +1 -2
- package/dist/tools/side-sessions.js +1 -2
- package/dist/tools/work-item-tools.js +1 -2
- package/dist/work-item-branch.js +1 -2
- package/dist/work-item-branch.js.map +1 -1
- package/dist/work-items/create-work-item.js +1 -2
- package/dist/work-items/decision-actions.js +1 -2
- package/dist/workspace.d.ts.map +1 -1
- package/dist/workspace.js +1 -3
- package/dist/workspace.js.map +1 -1
- package/factory-skills/factory-gitlab-review/SKILL.md +1 -1
- package/factory-skills/factory-plan/SKILL.md +1 -1
- package/factory-skills/factory-rereview/SKILL.md +14 -3
- package/factory-skills/factory-review/SKILL.md +14 -3
- package/factory-skills/factory-self-review/SKILL.md +1 -1
- package/factory-skills/factory-triage/SKILL.md +52 -29
- package/package.json +19 -17
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"base.js","names":[],"sources":["../../../../src/storage/domains/projects/base.ts"],"sourcesContent":["import { isThinkingLevelSetting } from '@mastra/code-sdk/thinking';\nimport type { ThinkingLevelSetting } from '@mastra/code-sdk/thinking';\nimport { FactoryStorageDomain } from '@mastra/core/storage';\nimport type { CollectionSchema, FactoryStorageOps } from '@mastra/core/storage';\n\nexport const DEFAULT_BUILD_PUSH_DEBOUNCE_MINUTES = 10;\nexport const DEFAULT_FACTORY_THINKING_LEVEL: ThinkingLevelSetting = 'medium';\nexport const FACTORY_MODEL_SCOPES = ['factory', 'user', 'hybrid'] as const;\nexport type FactoryModelScope = (typeof FACTORY_MODEL_SCOPES)[number];\n/** The single credential scope one session or run resolves from; `hybrid` is never effective. */\nexport type EffectiveModelScope = Exclude<FactoryModelScope, 'hybrid'>;\n\n/**\n * Resolve the scope one context runs under. `hybrid` splits by context: work-item runs use the\n * Factory's model and credentials, interactive sessions use the session owner's.\n */\nexport function effectiveModelScope(scope: FactoryModelScope, context: 'run' | 'session'): EffectiveModelScope {\n if (scope === 'hybrid') return context === 'run' ? 'factory' : 'user';\n return scope;\n}\n\nexport interface FactoryProject {\n id: string;\n orgId: string;\n createdBy: string;\n name: string;\n description: string | null;\n /** Default model for sessions/runs started under this Factory (null = harness default). */\n defaultModelId: string | null;\n /**\n * Whose model and credentials sessions and runs use: the Factory's, the session owner's, or\n * `hybrid` (owner's for interactive sessions, the Factory's for work-item runs).\n */\n modelScope: FactoryModelScope;\n /** Thinking level for this Factory's sessions and runs that have not picked their own. */\n defaultThinkingLevel: ThinkingLevelSetting;\n /** Whether rules may start agent runs on their own; off, a run waits for approval on its card. */\n autoRunEnabled: boolean;\n /** Whether the Factory answers a run's plan itself instead of waiting for a person. */\n autoApprovePlans: boolean;\n /** Workspace root in the sandbox; linked repositories are checked out beneath it. */\n sandboxWorkingDirectory: string | null;\n /** Provider settings document validated by the configured FactorySandbox. Only keys the user set. */\n sandboxSettings: Record<string, unknown> | null;\n /** Command run once in the workspace root after every repository's own setup. */\n workspaceSetupCommand: string | null;\n /** Template id of the environment's current build, written by the build path. */\n activeTemplateId: string | null;\n /** Repository slug → commit the active template was built at. */\n activeTemplateHeads: Record<string, string> | null;\n /** Provider build id of the most recent build attempt; its status is read live from the provider. */\n lastBuildId: string | null;\n /** Repository slug → commit the most recent build attempt pinned, so its status can be read back. */\n lastBuildHeads: Record<string, string> | null;\n /** Fingerprint of the settings, repositories and setup commands the most recent build attempt used. */\n lastBuildInputs: string | null;\n /** When the most recent build attempt started, whatever triggered it. */\n lastBuildAttemptedAt: Date | null;\n /** When a push last started a build: the leading edge of the push debounce window. */\n lastPushBuildAt: Date | null;\n /**\n * A run's build-start lease lapsed, so a build it may have started is not\n * on record. Cleared once a run reconciles it with a provider that lists builds.\n */\n buildStartUncertain: boolean;\n /** Whether a push to an environment repository's default branch starts a build. */\n buildOnPushEnabled: boolean;\n /** Minutes after a push-triggered attempt during which further pushes do not build. */\n buildPushDebounceMinutes: number;\n /** Whether Review agents publish their test results as a commit check. Defaults to off. */\n reviewTestChecksEnabled: boolean;\n /** Whether Work items get an independent self-review before the change request opens. Defaults to off. */\n selfReviewEnabled: boolean;\n createdAt: Date;\n updatedAt: Date;\n}\n\nexport interface CreateFactoryProjectInput {\n name: string;\n description?: string | null;\n defaultModelId?: string | null;\n modelScope?: FactoryModelScope;\n}\n\nexport interface UpdateFactoryProjectInput {\n name?: string;\n description?: string | null;\n defaultModelId?: string | null;\n modelScope?: FactoryModelScope;\n defaultThinkingLevel?: ThinkingLevelSetting;\n autoRunEnabled?: boolean;\n autoApprovePlans?: boolean;\n sandboxWorkingDirectory?: string | null;\n sandboxSettings?: Record<string, unknown> | null;\n workspaceSetupCommand?: string | null;\n activeTemplateId?: string | null;\n activeTemplateHeads?: Record<string, string> | null;\n lastBuildId?: string | null;\n lastBuildHeads?: Record<string, string> | null;\n lastBuildInputs?: string | null;\n lastBuildAttemptedAt?: Date | null;\n buildOnPushEnabled?: boolean;\n buildPushDebounceMinutes?: number;\n reviewTestChecksEnabled?: boolean;\n selfReviewEnabled?: boolean;\n}\n\nexport const FACTORY_PROJECTS_SCHEMA: CollectionSchema = {\n name: 'factory_projects',\n columns: {\n id: { type: 'uuid-pk' },\n org_id: { type: 'text' },\n created_by: { type: 'text' },\n name: { type: 'text' },\n description: { type: 'text', nullable: true },\n default_model_id: { type: 'text', nullable: true },\n model_scope: { type: 'text', default: 'hybrid' },\n default_thinking_level: { type: 'text', default: DEFAULT_FACTORY_THINKING_LEVEL },\n // Deprecated: no longer read or written. Kept so existing databases need no\n // migration. Old rows may still hold `true`, so never read it to bring Slack\n // work items back. Drop it in a later migration.\n slack_work_items_enabled: { type: 'boolean', default: false },\n auto_run_enabled: { type: 'boolean', default: false },\n auto_approve_plans: { type: 'boolean', default: false },\n sandbox_working_directory: { type: 'text', nullable: true },\n sandbox_settings: { type: 'json', nullable: true },\n workspace_setup_command: { type: 'text', nullable: true },\n active_template_id: { type: 'text', nullable: true },\n active_template_heads: { type: 'json', nullable: true },\n last_build_id: { type: 'text', nullable: true },\n last_build_heads: { type: 'json', nullable: true },\n last_build_inputs: { type: 'text', nullable: true },\n last_build_attempted_at: { type: 'timestamp', nullable: true },\n last_push_build_at: { type: 'timestamp', nullable: true },\n build_start_uncertain: { type: 'boolean', default: false },\n build_start_claim: { type: 'text', nullable: true },\n build_start_claim_expires_at: { type: 'timestamp', nullable: true },\n build_on_push_enabled: { type: 'boolean', default: false },\n build_push_debounce_minutes: { type: 'integer', default: DEFAULT_BUILD_PUSH_DEBOUNCE_MINUTES },\n review_test_checks_enabled: { type: 'boolean', default: false },\n self_review_enabled: { type: 'boolean', default: false },\n /** Set once the source-control domain has backfilled repository positions and environment membership. */\n environment_backfilled_at: { type: 'timestamp', nullable: true },\n created_at: { type: 'timestamp' },\n updated_at: { type: 'timestamp' },\n },\n indexes: [{ name: 'factory_projects_org_updated_at_idx', columns: ['org_id', 'updated_at'] }],\n};\n\ninterface FactoryProjectDbRow extends Record<string, unknown> {\n id: string;\n org_id: string;\n created_by: string;\n name: string;\n description: string | null;\n default_model_id: string | null;\n model_scope: string;\n default_thinking_level: string | null;\n auto_run_enabled: boolean;\n auto_approve_plans: boolean;\n sandbox_working_directory: string | null;\n sandbox_settings: Record<string, unknown> | null;\n workspace_setup_command: string | null;\n active_template_id: string | null;\n active_template_heads: Record<string, string> | null;\n last_build_id: string | null;\n last_build_heads: Record<string, string> | null;\n last_build_inputs: string | null;\n last_build_attempted_at: Date | null;\n last_push_build_at: Date | null;\n build_start_uncertain: boolean | null;\n build_start_claim: string | null;\n build_start_claim_expires_at: Date | null;\n build_on_push_enabled: boolean | null;\n build_push_debounce_minutes: number | null;\n review_test_checks_enabled: boolean | null;\n self_review_enabled: boolean | null;\n environment_backfilled_at: Date | null;\n created_at: Date;\n updated_at: Date;\n}\n\nfunction toFactoryProject(row: FactoryProjectDbRow): FactoryProject {\n return {\n id: row.id,\n orgId: row.org_id,\n createdBy: row.created_by,\n name: row.name,\n description: row.description,\n defaultModelId: row.default_model_id,\n modelScope: row.model_scope === 'factory' || row.model_scope === 'user' ? row.model_scope : 'hybrid',\n defaultThinkingLevel: isThinkingLevelSetting(row.default_thinking_level)\n ? row.default_thinking_level\n : DEFAULT_FACTORY_THINKING_LEVEL,\n autoRunEnabled: row.auto_run_enabled,\n autoApprovePlans: row.auto_approve_plans ?? false,\n sandboxWorkingDirectory: row.sandbox_working_directory ?? null,\n sandboxSettings: row.sandbox_settings ?? null,\n workspaceSetupCommand: row.workspace_setup_command ?? null,\n activeTemplateId: row.active_template_id ?? null,\n activeTemplateHeads: row.active_template_heads ?? null,\n lastBuildId: row.last_build_id ?? null,\n lastBuildHeads: row.last_build_heads ?? null,\n lastBuildInputs: row.last_build_inputs ?? null,\n lastBuildAttemptedAt: row.last_build_attempted_at ?? null,\n lastPushBuildAt: row.last_push_build_at ?? null,\n buildStartUncertain: row.build_start_uncertain ?? false,\n buildOnPushEnabled: row.build_on_push_enabled ?? false,\n buildPushDebounceMinutes: row.build_push_debounce_minutes ?? DEFAULT_BUILD_PUSH_DEBOUNCE_MINUTES,\n reviewTestChecksEnabled: row.review_test_checks_enabled ?? false,\n selfReviewEnabled: row.self_review_enabled ?? false,\n createdAt: row.created_at,\n updatedAt: row.updated_at,\n };\n}\n\nexport class FactoryProjectsStorage extends FactoryStorageDomain {\n constructor() {\n super('projects');\n }\n\n async init(): Promise<void> {\n await this.ensureCollections([FACTORY_PROJECTS_SCHEMA]);\n }\n\n async dangerouslyClearAll(): Promise<void> {\n await this.ops.deleteMany('factory_projects', {});\n }\n\n get #db(): FactoryStorageOps {\n return this.ops;\n }\n\n async create({\n orgId,\n userId,\n input,\n }: {\n orgId: string;\n userId: string;\n input: CreateFactoryProjectInput;\n }): Promise<FactoryProject> {\n const now = new Date();\n const row = await this.#db.insertOne<FactoryProjectDbRow>('factory_projects', {\n org_id: orgId,\n created_by: userId,\n name: input.name,\n description: input.description ?? null,\n default_model_id: input.defaultModelId ?? null,\n model_scope: input.modelScope ?? 'hybrid',\n auto_run_enabled: false,\n auto_approve_plans: false,\n created_at: now,\n updated_at: now,\n });\n return toFactoryProject(row);\n }\n\n async list({ orgId }: { orgId: string }): Promise<FactoryProject[]> {\n const rows = await this.#db.findMany<FactoryProjectDbRow>(\n 'factory_projects',\n { org_id: orgId },\n { orderBy: [['updated_at', 'desc']] },\n );\n return rows.map(toFactoryProject);\n }\n\n async listAll(): Promise<FactoryProject[]> {\n const rows = await this.#db.findMany<FactoryProjectDbRow>(\n 'factory_projects',\n {},\n { orderBy: [['updated_at', 'desc']] },\n );\n return rows.map(toFactoryProject);\n }\n\n async get({ orgId, id }: { orgId: string; id: string }): Promise<FactoryProject | null> {\n const row = await this.#db.findOne<FactoryProjectDbRow>('factory_projects', { org_id: orgId, id });\n return row ? toFactoryProject(row) : null;\n }\n\n async getById({ id }: { id: string }): Promise<FactoryProject | null> {\n const row = await this.#db.findOne<FactoryProjectDbRow>('factory_projects', { id });\n return row ? toFactoryProject(row) : null;\n }\n\n async update({\n orgId,\n id,\n input,\n }: {\n orgId: string;\n id: string;\n /** A function input runs in a transaction; writes through its `ops` commit or roll back with the project. */\n input:\n | UpdateFactoryProjectInput\n | ((current: FactoryProject, ops: FactoryStorageOps) => Promise<UpdateFactoryProjectInput | null>);\n }): Promise<FactoryProject | null> {\n const update = (ops: FactoryStorageOps) =>\n ops.updateAtomic<FactoryProjectDbRow>('factory_projects', { org_id: orgId, id }, async current => {\n const changes = typeof input === 'function' ? await input(toFactoryProject(current), ops) : input;\n if (changes === null) return null;\n return {\n ...(changes.name !== undefined ? { name: changes.name } : {}),\n ...(changes.description !== undefined ? { description: changes.description } : {}),\n ...(changes.defaultModelId !== undefined ? { default_model_id: changes.defaultModelId } : {}),\n ...(changes.modelScope !== undefined ? { model_scope: changes.modelScope } : {}),\n ...(changes.defaultThinkingLevel !== undefined\n ? { default_thinking_level: changes.defaultThinkingLevel }\n : {}),\n ...(changes.autoRunEnabled !== undefined ? { auto_run_enabled: changes.autoRunEnabled } : {}),\n ...(changes.autoApprovePlans !== undefined ? { auto_approve_plans: changes.autoApprovePlans } : {}),\n ...(changes.sandboxWorkingDirectory !== undefined\n ? { sandbox_working_directory: changes.sandboxWorkingDirectory }\n : {}),\n ...(changes.sandboxSettings !== undefined ? { sandbox_settings: changes.sandboxSettings } : {}),\n ...(changes.workspaceSetupCommand !== undefined\n ? { workspace_setup_command: changes.workspaceSetupCommand }\n : {}),\n ...(changes.activeTemplateId !== undefined ? { active_template_id: changes.activeTemplateId } : {}),\n ...(changes.activeTemplateHeads !== undefined ? { active_template_heads: changes.activeTemplateHeads } : {}),\n ...(changes.lastBuildId !== undefined ? { last_build_id: changes.lastBuildId } : {}),\n ...(changes.lastBuildHeads !== undefined ? { last_build_heads: changes.lastBuildHeads } : {}),\n ...(changes.lastBuildInputs !== undefined ? { last_build_inputs: changes.lastBuildInputs } : {}),\n ...(changes.lastBuildAttemptedAt !== undefined\n ? { last_build_attempted_at: changes.lastBuildAttemptedAt }\n : {}),\n ...(changes.buildOnPushEnabled !== undefined ? { build_on_push_enabled: changes.buildOnPushEnabled } : {}),\n ...(changes.buildPushDebounceMinutes !== undefined\n ? { build_push_debounce_minutes: changes.buildPushDebounceMinutes }\n : {}),\n ...(changes.reviewTestChecksEnabled !== undefined\n ? { review_test_checks_enabled: changes.reviewTestChecksEnabled }\n : {}),\n ...(changes.selfReviewEnabled !== undefined ? { self_review_enabled: changes.selfReviewEnabled } : {}),\n updated_at: new Date(),\n };\n });\n // LibSQL's standalone updateAtomic only serializes one client; a transaction\n // also protects a read-dependent update against other database connections.\n const row = typeof input === 'function' ? await this.storage.withTransaction(update) : await update(this.#db);\n return row ? toFactoryProject(row) : null;\n }\n\n /**\n * Leading-edge debounce for push-triggered builds: stamps\n * `last_push_build_at = now` and resolves true when no push started a build\n * within the last `debounceMinutes`, else writes nothing and resolves\n * false. Taken right before the provider start, so a push that skips\n * (another run starting, a build in progress) never closes the window. The read and the write run in one transaction, so two concurrent\n * webhooks never both win, even on different database connections.\n */\n async claimBuildAttempt({\n id,\n debounceMinutes,\n now = new Date(),\n }: {\n id: string;\n debounceMinutes: number;\n now?: Date;\n }): Promise<boolean> {\n let claimed = false;\n await this.storage.withTransaction(ops =>\n ops.updateAtomic<FactoryProjectDbRow>('factory_projects', { id }, current => {\n const last = current.last_push_build_at;\n if (last && now.getTime() - last.getTime() < debounceMinutes * 60_000) return null;\n claimed = true;\n return { last_push_build_at: now, updated_at: now };\n }),\n );\n return claimed;\n }\n\n /**\n * Takes the project's build-start lease for `token`. Every trigger (manual,\n * schedule, push) takes it before reading build state and holds it through\n * `builds.start` and recording the result, so two runs never both start a\n * build. `claimed` is false while another run holds an unexpired lease. The\n * holder renews the lease while it works (`renewBuildStart`), so a lease\n * only expires when its run died or stalled. Taking over an expired lease\n * marks the start uncertain (that run's build may have reached the provider\n * unrecorded), and the mark stays until a release resolves it; `uncertain`\n * reports it. Only the claim is transactional; provider calls run outside it.\n */\n async claimBuildStart({\n id,\n token,\n leaseMs,\n now = new Date(),\n }: {\n id: string;\n token: string;\n leaseMs: number;\n now?: Date;\n }): Promise<{ claimed: boolean; uncertain: boolean }> {\n const result = { claimed: false, uncertain: false };\n await this.storage.withTransaction(ops =>\n ops.updateAtomic<FactoryProjectDbRow>('factory_projects', { id }, current => {\n const expiresAt = current.build_start_claim_expires_at;\n if (current.build_start_claim && expiresAt && expiresAt.getTime() > now.getTime()) return null;\n result.claimed = true;\n result.uncertain = Boolean(current.build_start_claim) || current.build_start_uncertain === true;\n return {\n build_start_claim: token,\n build_start_claim_expires_at: new Date(now.getTime() + leaseMs),\n ...(result.uncertain ? { build_start_uncertain: true } : {}),\n updated_at: now,\n };\n }),\n );\n return result;\n }\n\n /**\n * Extends the build-start lease held by `token` to `now + leaseMs`. Resolves\n * false, writing nothing, when `token` no longer holds it.\n */\n async renewBuildStart({\n id,\n token,\n leaseMs,\n now = new Date(),\n }: {\n id: string;\n token: string;\n leaseMs: number;\n now?: Date;\n }): Promise<boolean> {\n let renewed = false;\n await this.storage.withTransaction(ops =>\n ops.updateAtomic<FactoryProjectDbRow>('factory_projects', { id }, current => {\n if (current.build_start_claim !== token) return null;\n renewed = true;\n return { build_start_claim_expires_at: new Date(now.getTime() + leaseMs), updated_at: now };\n }),\n );\n return renewed;\n }\n\n /**\n * Releases the build-start lease taken with `token` and writes `changes` in\n * the same transaction, but only while `token` still holds the lease. A run\n * whose lease expired and was taken by a newer run writes nothing, so it\n * never clears or overwrites that run's build. `resolved` clears an\n * uncertain start. Resolves false when skipped.\n */\n async releaseBuildStart({\n id,\n token,\n changes = {},\n resolved = false,\n now = new Date(),\n }: {\n id: string;\n token: string;\n resolved?: boolean;\n changes?: Pick<\n UpdateFactoryProjectInput,\n 'lastBuildId' | 'lastBuildHeads' | 'lastBuildInputs' | 'lastBuildAttemptedAt'\n >;\n now?: Date;\n }): Promise<boolean> {\n let released = false;\n await this.storage.withTransaction(ops =>\n ops.updateAtomic<FactoryProjectDbRow>('factory_projects', { id }, current => {\n if (current.build_start_claim !== token) return null;\n released = true;\n return {\n ...(changes.lastBuildId !== undefined ? { last_build_id: changes.lastBuildId } : {}),\n ...(changes.lastBuildHeads !== undefined ? { last_build_heads: changes.lastBuildHeads } : {}),\n ...(changes.lastBuildInputs !== undefined ? { last_build_inputs: changes.lastBuildInputs } : {}),\n ...(changes.lastBuildAttemptedAt !== undefined\n ? { last_build_attempted_at: changes.lastBuildAttemptedAt }\n : {}),\n ...(resolved ? { build_start_uncertain: false } : {}),\n build_start_claim: null,\n build_start_claim_expires_at: null,\n updated_at: now,\n };\n }),\n );\n return released;\n }\n\n /**\n * Pins the active template to a finished build, but only while that build is\n * still the project's last one. Overlapping runs (Build now during a push\n * build) can finish out of order; the write and the `last_build_id` check\n * run in one transaction so a stale run never overwrites a newer build's\n * pin. Resolves false when the pin was skipped.\n */\n async pinActiveTemplate({\n id,\n buildId,\n templateId,\n heads,\n now = new Date(),\n }: {\n id: string;\n buildId: string;\n templateId: string;\n heads: Record<string, string>;\n now?: Date;\n }): Promise<boolean> {\n let pinned = false;\n await this.storage.withTransaction(ops =>\n ops.updateAtomic<FactoryProjectDbRow>('factory_projects', { id }, current => {\n if (current.last_build_id !== buildId) return null;\n pinned = true;\n return { active_template_id: templateId, active_template_heads: heads, updated_at: now };\n }),\n );\n return pinned;\n }\n\n async delete({ orgId, id }: { orgId: string; id: string }): Promise<FactoryProject | null> {\n const project = await this.get({ orgId, id });\n if (!project) return null;\n const deleted = await this.#db.deleteMany('factory_projects', { org_id: orgId, id });\n return deleted > 0 ? project : null;\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"base.js","names":[],"sources":["../../../../src/storage/domains/projects/base.ts"],"sourcesContent":["import { isThinkingLevelSetting } from '@mastra/code-sdk/thinking';\nimport type { ThinkingLevelSetting } from '@mastra/code-sdk/thinking';\nimport { FactoryStorageDomain } from '@mastra/core/storage';\nimport type { CollectionSchema, FactoryStorageOps } from '@mastra/core/storage';\n\nimport { DEFAULT_THINKING_LEVEL } from '../../../default-thinking-level.js';\n\nexport const DEFAULT_BUILD_PUSH_DEBOUNCE_MINUTES = 10;\nexport const FACTORY_MODEL_SCOPES = ['factory', 'user', 'hybrid'] as const;\nexport type FactoryModelScope = (typeof FACTORY_MODEL_SCOPES)[number];\n/** The single credential scope one session or run resolves from; `hybrid` is never effective. */\nexport type EffectiveModelScope = Exclude<FactoryModelScope, 'hybrid'>;\n\n/**\n * Resolve the scope one context runs under. `hybrid` splits by context: work-item runs use the\n * Factory's model and credentials, interactive sessions use the session owner's.\n */\nexport function effectiveModelScope(scope: FactoryModelScope, context: 'run' | 'session'): EffectiveModelScope {\n if (scope === 'hybrid') return context === 'run' ? 'factory' : 'user';\n return scope;\n}\n\nexport interface FactoryProject {\n id: string;\n orgId: string;\n createdBy: string;\n name: string;\n description: string | null;\n /** Default model for sessions/runs started under this Factory (null = harness default). */\n defaultModelId: string | null;\n /**\n * Whose model and credentials sessions and runs use: the Factory's, the session owner's, or\n * `hybrid` (owner's for interactive sessions, the Factory's for work-item runs).\n */\n modelScope: FactoryModelScope;\n /** Thinking level for this Factory's sessions and runs that have not picked their own. */\n defaultThinkingLevel: ThinkingLevelSetting;\n /** Whether rules may start agent runs on their own; off, a run waits for approval on its card. */\n autoRunEnabled: boolean;\n /** Whether the Factory answers a run's plan itself instead of waiting for a person. */\n autoApprovePlans: boolean;\n /** Workspace root in the sandbox; linked repositories are checked out beneath it. */\n sandboxWorkingDirectory: string | null;\n /** Provider settings document validated by the configured FactorySandbox. Only keys the user set. */\n sandboxSettings: Record<string, unknown> | null;\n /** Command run once in the workspace root after every repository's own setup. */\n workspaceSetupCommand: string | null;\n /** Template id of the environment's current build, written by the build path. */\n activeTemplateId: string | null;\n /** Repository slug → commit the active template was built at. */\n activeTemplateHeads: Record<string, string> | null;\n /** Provider build id of the most recent build attempt; its status is read live from the provider. */\n lastBuildId: string | null;\n /** Repository slug → commit the most recent build attempt pinned, so its status can be read back. */\n lastBuildHeads: Record<string, string> | null;\n /** Fingerprint of the settings, repositories and setup commands the most recent build attempt used. */\n lastBuildInputs: string | null;\n /** When the most recent build attempt started, whatever triggered it. */\n lastBuildAttemptedAt: Date | null;\n /** When a push last started a build: the leading edge of the push debounce window. */\n lastPushBuildAt: Date | null;\n /**\n * A run's build-start lease lapsed, so a build it may have started is not\n * on record. Cleared once a run reconciles it with a provider that lists builds.\n */\n buildStartUncertain: boolean;\n /** Whether a push to an environment repository's default branch starts a build. */\n buildOnPushEnabled: boolean;\n /** Minutes after a push-triggered attempt during which further pushes do not build. */\n buildPushDebounceMinutes: number;\n /** Whether Review agents publish their test results as a commit check. Defaults to off. */\n reviewTestChecksEnabled: boolean;\n /** Whether Work items get an independent self-review before the change request opens. Defaults to off. */\n selfReviewEnabled: boolean;\n createdAt: Date;\n updatedAt: Date;\n}\n\nexport interface CreateFactoryProjectInput {\n name: string;\n description?: string | null;\n defaultModelId?: string | null;\n modelScope?: FactoryModelScope;\n}\n\nexport interface UpdateFactoryProjectInput {\n name?: string;\n description?: string | null;\n defaultModelId?: string | null;\n modelScope?: FactoryModelScope;\n defaultThinkingLevel?: ThinkingLevelSetting;\n autoRunEnabled?: boolean;\n autoApprovePlans?: boolean;\n sandboxWorkingDirectory?: string | null;\n sandboxSettings?: Record<string, unknown> | null;\n workspaceSetupCommand?: string | null;\n activeTemplateId?: string | null;\n activeTemplateHeads?: Record<string, string> | null;\n lastBuildId?: string | null;\n lastBuildHeads?: Record<string, string> | null;\n lastBuildInputs?: string | null;\n lastBuildAttemptedAt?: Date | null;\n buildOnPushEnabled?: boolean;\n buildPushDebounceMinutes?: number;\n reviewTestChecksEnabled?: boolean;\n selfReviewEnabled?: boolean;\n}\n\nexport const FACTORY_PROJECTS_SCHEMA: CollectionSchema = {\n name: 'factory_projects',\n columns: {\n id: { type: 'uuid-pk' },\n org_id: { type: 'text' },\n created_by: { type: 'text' },\n name: { type: 'text' },\n description: { type: 'text', nullable: true },\n default_model_id: { type: 'text', nullable: true },\n model_scope: { type: 'text', default: 'hybrid' },\n default_thinking_level: { type: 'text', default: DEFAULT_THINKING_LEVEL },\n // Deprecated: no longer read or written. Kept so existing databases need no\n // migration. Old rows may still hold `true`, so never read it to bring Slack\n // work items back. Drop it in a later migration.\n slack_work_items_enabled: { type: 'boolean', default: false },\n auto_run_enabled: { type: 'boolean', default: false },\n auto_approve_plans: { type: 'boolean', default: false },\n sandbox_working_directory: { type: 'text', nullable: true },\n sandbox_settings: { type: 'json', nullable: true },\n workspace_setup_command: { type: 'text', nullable: true },\n active_template_id: { type: 'text', nullable: true },\n active_template_heads: { type: 'json', nullable: true },\n last_build_id: { type: 'text', nullable: true },\n last_build_heads: { type: 'json', nullable: true },\n last_build_inputs: { type: 'text', nullable: true },\n last_build_attempted_at: { type: 'timestamp', nullable: true },\n last_push_build_at: { type: 'timestamp', nullable: true },\n build_start_uncertain: { type: 'boolean', default: false },\n build_start_claim: { type: 'text', nullable: true },\n build_start_claim_expires_at: { type: 'timestamp', nullable: true },\n build_on_push_enabled: { type: 'boolean', default: false },\n build_push_debounce_minutes: { type: 'integer', default: DEFAULT_BUILD_PUSH_DEBOUNCE_MINUTES },\n review_test_checks_enabled: { type: 'boolean', default: false },\n self_review_enabled: { type: 'boolean', default: false },\n /** Set once the source-control domain has backfilled repository positions and environment membership. */\n environment_backfilled_at: { type: 'timestamp', nullable: true },\n created_at: { type: 'timestamp' },\n updated_at: { type: 'timestamp' },\n },\n indexes: [{ name: 'factory_projects_org_updated_at_idx', columns: ['org_id', 'updated_at'] }],\n};\n\ninterface FactoryProjectDbRow extends Record<string, unknown> {\n id: string;\n org_id: string;\n created_by: string;\n name: string;\n description: string | null;\n default_model_id: string | null;\n model_scope: string;\n default_thinking_level: string | null;\n auto_run_enabled: boolean;\n auto_approve_plans: boolean;\n sandbox_working_directory: string | null;\n sandbox_settings: Record<string, unknown> | null;\n workspace_setup_command: string | null;\n active_template_id: string | null;\n active_template_heads: Record<string, string> | null;\n last_build_id: string | null;\n last_build_heads: Record<string, string> | null;\n last_build_inputs: string | null;\n last_build_attempted_at: Date | null;\n last_push_build_at: Date | null;\n build_start_uncertain: boolean | null;\n build_start_claim: string | null;\n build_start_claim_expires_at: Date | null;\n build_on_push_enabled: boolean | null;\n build_push_debounce_minutes: number | null;\n review_test_checks_enabled: boolean | null;\n self_review_enabled: boolean | null;\n environment_backfilled_at: Date | null;\n created_at: Date;\n updated_at: Date;\n}\n\nfunction toFactoryProject(row: FactoryProjectDbRow): FactoryProject {\n return {\n id: row.id,\n orgId: row.org_id,\n createdBy: row.created_by,\n name: row.name,\n description: row.description,\n defaultModelId: row.default_model_id,\n modelScope: row.model_scope === 'factory' || row.model_scope === 'user' ? row.model_scope : 'hybrid',\n defaultThinkingLevel: isThinkingLevelSetting(row.default_thinking_level)\n ? row.default_thinking_level\n : DEFAULT_THINKING_LEVEL,\n autoRunEnabled: row.auto_run_enabled,\n autoApprovePlans: row.auto_approve_plans ?? false,\n sandboxWorkingDirectory: row.sandbox_working_directory ?? null,\n sandboxSettings: row.sandbox_settings ?? null,\n workspaceSetupCommand: row.workspace_setup_command ?? null,\n activeTemplateId: row.active_template_id ?? null,\n activeTemplateHeads: row.active_template_heads ?? null,\n lastBuildId: row.last_build_id ?? null,\n lastBuildHeads: row.last_build_heads ?? null,\n lastBuildInputs: row.last_build_inputs ?? null,\n lastBuildAttemptedAt: row.last_build_attempted_at ?? null,\n lastPushBuildAt: row.last_push_build_at ?? null,\n buildStartUncertain: row.build_start_uncertain ?? false,\n buildOnPushEnabled: row.build_on_push_enabled ?? false,\n buildPushDebounceMinutes: row.build_push_debounce_minutes ?? DEFAULT_BUILD_PUSH_DEBOUNCE_MINUTES,\n reviewTestChecksEnabled: row.review_test_checks_enabled ?? false,\n selfReviewEnabled: row.self_review_enabled ?? false,\n createdAt: row.created_at,\n updatedAt: row.updated_at,\n };\n}\n\nexport class FactoryProjectsStorage extends FactoryStorageDomain {\n constructor() {\n super('projects');\n }\n\n async init(): Promise<void> {\n await this.ensureCollections([FACTORY_PROJECTS_SCHEMA]);\n }\n\n async dangerouslyClearAll(): Promise<void> {\n await this.ops.deleteMany('factory_projects', {});\n }\n\n get #db(): FactoryStorageOps {\n return this.ops;\n }\n\n async create({\n orgId,\n userId,\n input,\n }: {\n orgId: string;\n userId: string;\n input: CreateFactoryProjectInput;\n }): Promise<FactoryProject> {\n const now = new Date();\n const row = await this.#db.insertOne<FactoryProjectDbRow>('factory_projects', {\n org_id: orgId,\n created_by: userId,\n name: input.name,\n description: input.description ?? null,\n default_model_id: input.defaultModelId ?? null,\n model_scope: input.modelScope ?? 'hybrid',\n auto_run_enabled: false,\n auto_approve_plans: false,\n created_at: now,\n updated_at: now,\n });\n return toFactoryProject(row);\n }\n\n async list({ orgId }: { orgId: string }): Promise<FactoryProject[]> {\n const rows = await this.#db.findMany<FactoryProjectDbRow>(\n 'factory_projects',\n { org_id: orgId },\n { orderBy: [['updated_at', 'desc']] },\n );\n return rows.map(toFactoryProject);\n }\n\n async listAll(): Promise<FactoryProject[]> {\n const rows = await this.#db.findMany<FactoryProjectDbRow>(\n 'factory_projects',\n {},\n { orderBy: [['updated_at', 'desc']] },\n );\n return rows.map(toFactoryProject);\n }\n\n async get({ orgId, id }: { orgId: string; id: string }): Promise<FactoryProject | null> {\n const row = await this.#db.findOne<FactoryProjectDbRow>('factory_projects', { org_id: orgId, id });\n return row ? toFactoryProject(row) : null;\n }\n\n async getById({ id }: { id: string }): Promise<FactoryProject | null> {\n const row = await this.#db.findOne<FactoryProjectDbRow>('factory_projects', { id });\n return row ? toFactoryProject(row) : null;\n }\n\n async update({\n orgId,\n id,\n input,\n }: {\n orgId: string;\n id: string;\n /** A function input runs in a transaction; writes through its `ops` commit or roll back with the project. */\n input:\n | UpdateFactoryProjectInput\n | ((current: FactoryProject, ops: FactoryStorageOps) => Promise<UpdateFactoryProjectInput | null>);\n }): Promise<FactoryProject | null> {\n const update = (ops: FactoryStorageOps) =>\n ops.updateAtomic<FactoryProjectDbRow>('factory_projects', { org_id: orgId, id }, async current => {\n const changes = typeof input === 'function' ? await input(toFactoryProject(current), ops) : input;\n if (changes === null) return null;\n return {\n ...(changes.name !== undefined ? { name: changes.name } : {}),\n ...(changes.description !== undefined ? { description: changes.description } : {}),\n ...(changes.defaultModelId !== undefined ? { default_model_id: changes.defaultModelId } : {}),\n ...(changes.modelScope !== undefined ? { model_scope: changes.modelScope } : {}),\n ...(changes.defaultThinkingLevel !== undefined\n ? { default_thinking_level: changes.defaultThinkingLevel }\n : {}),\n ...(changes.autoRunEnabled !== undefined ? { auto_run_enabled: changes.autoRunEnabled } : {}),\n ...(changes.autoApprovePlans !== undefined ? { auto_approve_plans: changes.autoApprovePlans } : {}),\n ...(changes.sandboxWorkingDirectory !== undefined\n ? { sandbox_working_directory: changes.sandboxWorkingDirectory }\n : {}),\n ...(changes.sandboxSettings !== undefined ? { sandbox_settings: changes.sandboxSettings } : {}),\n ...(changes.workspaceSetupCommand !== undefined\n ? { workspace_setup_command: changes.workspaceSetupCommand }\n : {}),\n ...(changes.activeTemplateId !== undefined ? { active_template_id: changes.activeTemplateId } : {}),\n ...(changes.activeTemplateHeads !== undefined ? { active_template_heads: changes.activeTemplateHeads } : {}),\n ...(changes.lastBuildId !== undefined ? { last_build_id: changes.lastBuildId } : {}),\n ...(changes.lastBuildHeads !== undefined ? { last_build_heads: changes.lastBuildHeads } : {}),\n ...(changes.lastBuildInputs !== undefined ? { last_build_inputs: changes.lastBuildInputs } : {}),\n ...(changes.lastBuildAttemptedAt !== undefined\n ? { last_build_attempted_at: changes.lastBuildAttemptedAt }\n : {}),\n ...(changes.buildOnPushEnabled !== undefined ? { build_on_push_enabled: changes.buildOnPushEnabled } : {}),\n ...(changes.buildPushDebounceMinutes !== undefined\n ? { build_push_debounce_minutes: changes.buildPushDebounceMinutes }\n : {}),\n ...(changes.reviewTestChecksEnabled !== undefined\n ? { review_test_checks_enabled: changes.reviewTestChecksEnabled }\n : {}),\n ...(changes.selfReviewEnabled !== undefined ? { self_review_enabled: changes.selfReviewEnabled } : {}),\n updated_at: new Date(),\n };\n });\n // LibSQL's standalone updateAtomic only serializes one client; a transaction\n // also protects a read-dependent update against other database connections.\n const row = typeof input === 'function' ? await this.storage.withTransaction(update) : await update(this.#db);\n return row ? toFactoryProject(row) : null;\n }\n\n /**\n * Leading-edge debounce for push-triggered builds: stamps\n * `last_push_build_at = now` and resolves true when no push started a build\n * within the last `debounceMinutes`, else writes nothing and resolves\n * false. Taken right before the provider start, so a push that skips\n * (another run starting, a build in progress) never closes the window. The read and the write run in one transaction, so two concurrent\n * webhooks never both win, even on different database connections.\n */\n async claimBuildAttempt({\n id,\n debounceMinutes,\n now = new Date(),\n }: {\n id: string;\n debounceMinutes: number;\n now?: Date;\n }): Promise<boolean> {\n let claimed = false;\n await this.storage.withTransaction(ops =>\n ops.updateAtomic<FactoryProjectDbRow>('factory_projects', { id }, current => {\n const last = current.last_push_build_at;\n if (last && now.getTime() - last.getTime() < debounceMinutes * 60_000) return null;\n claimed = true;\n return { last_push_build_at: now, updated_at: now };\n }),\n );\n return claimed;\n }\n\n /**\n * Takes the project's build-start lease for `token`. Every trigger (manual,\n * schedule, push) takes it before reading build state and holds it through\n * `builds.start` and recording the result, so two runs never both start a\n * build. `claimed` is false while another run holds an unexpired lease. The\n * holder renews the lease while it works (`renewBuildStart`), so a lease\n * only expires when its run died or stalled. Taking over an expired lease\n * marks the start uncertain (that run's build may have reached the provider\n * unrecorded), and the mark stays until a release resolves it; `uncertain`\n * reports it. Only the claim is transactional; provider calls run outside it.\n */\n async claimBuildStart({\n id,\n token,\n leaseMs,\n now = new Date(),\n }: {\n id: string;\n token: string;\n leaseMs: number;\n now?: Date;\n }): Promise<{ claimed: boolean; uncertain: boolean }> {\n const result = { claimed: false, uncertain: false };\n await this.storage.withTransaction(ops =>\n ops.updateAtomic<FactoryProjectDbRow>('factory_projects', { id }, current => {\n const expiresAt = current.build_start_claim_expires_at;\n if (current.build_start_claim && expiresAt && expiresAt.getTime() > now.getTime()) return null;\n result.claimed = true;\n result.uncertain = Boolean(current.build_start_claim) || current.build_start_uncertain === true;\n return {\n build_start_claim: token,\n build_start_claim_expires_at: new Date(now.getTime() + leaseMs),\n ...(result.uncertain ? { build_start_uncertain: true } : {}),\n updated_at: now,\n };\n }),\n );\n return result;\n }\n\n /**\n * Extends the build-start lease held by `token` to `now + leaseMs`. Resolves\n * false, writing nothing, when `token` no longer holds it.\n */\n async renewBuildStart({\n id,\n token,\n leaseMs,\n now = new Date(),\n }: {\n id: string;\n token: string;\n leaseMs: number;\n now?: Date;\n }): Promise<boolean> {\n let renewed = false;\n await this.storage.withTransaction(ops =>\n ops.updateAtomic<FactoryProjectDbRow>('factory_projects', { id }, current => {\n if (current.build_start_claim !== token) return null;\n renewed = true;\n return { build_start_claim_expires_at: new Date(now.getTime() + leaseMs), updated_at: now };\n }),\n );\n return renewed;\n }\n\n /**\n * Releases the build-start lease taken with `token` and writes `changes` in\n * the same transaction, but only while `token` still holds the lease. A run\n * whose lease expired and was taken by a newer run writes nothing, so it\n * never clears or overwrites that run's build. `resolved` clears an\n * uncertain start. Resolves false when skipped.\n */\n async releaseBuildStart({\n id,\n token,\n changes = {},\n resolved = false,\n now = new Date(),\n }: {\n id: string;\n token: string;\n resolved?: boolean;\n changes?: Pick<\n UpdateFactoryProjectInput,\n 'lastBuildId' | 'lastBuildHeads' | 'lastBuildInputs' | 'lastBuildAttemptedAt'\n >;\n now?: Date;\n }): Promise<boolean> {\n let released = false;\n await this.storage.withTransaction(ops =>\n ops.updateAtomic<FactoryProjectDbRow>('factory_projects', { id }, current => {\n if (current.build_start_claim !== token) return null;\n released = true;\n return {\n ...(changes.lastBuildId !== undefined ? { last_build_id: changes.lastBuildId } : {}),\n ...(changes.lastBuildHeads !== undefined ? { last_build_heads: changes.lastBuildHeads } : {}),\n ...(changes.lastBuildInputs !== undefined ? { last_build_inputs: changes.lastBuildInputs } : {}),\n ...(changes.lastBuildAttemptedAt !== undefined\n ? { last_build_attempted_at: changes.lastBuildAttemptedAt }\n : {}),\n ...(resolved ? { build_start_uncertain: false } : {}),\n build_start_claim: null,\n build_start_claim_expires_at: null,\n updated_at: now,\n };\n }),\n );\n return released;\n }\n\n /**\n * Pins the active template to a finished build, but only while that build is\n * still the project's last one. Overlapping runs (Build now during a push\n * build) can finish out of order; the write and the `last_build_id` check\n * run in one transaction so a stale run never overwrites a newer build's\n * pin. Resolves false when the pin was skipped.\n */\n async pinActiveTemplate({\n id,\n buildId,\n templateId,\n heads,\n now = new Date(),\n }: {\n id: string;\n buildId: string;\n templateId: string;\n heads: Record<string, string>;\n now?: Date;\n }): Promise<boolean> {\n let pinned = false;\n await this.storage.withTransaction(ops =>\n ops.updateAtomic<FactoryProjectDbRow>('factory_projects', { id }, current => {\n if (current.last_build_id !== buildId) return null;\n pinned = true;\n return { active_template_id: templateId, active_template_heads: heads, updated_at: now };\n }),\n );\n return pinned;\n }\n\n async delete({ orgId, id }: { orgId: string; id: string }): Promise<FactoryProject | null> {\n const project = await this.get({ orgId, id });\n if (!project) return null;\n const deleted = await this.#db.deleteMany('factory_projects', { org_id: orgId, id });\n return deleted > 0 ? project : null;\n }\n}\n"],"mappings":"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"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { FactoryStorageDomain, UniqueViolationError } from "@mastra/core/storage";
|
|
2
|
-
|
|
2
|
+
// src/storage/domains/queue-health/base.ts
|
|
3
3
|
/**
|
|
4
4
|
* Queue-health threshold configuration domain: per-project age buckets for the
|
|
5
5
|
* Factory Overview queue-health chart.
|
|
@@ -116,7 +116,6 @@ var QueueHealthStorage = class extends FactoryStorageDomain {
|
|
|
116
116
|
}
|
|
117
117
|
}
|
|
118
118
|
};
|
|
119
|
-
//#endregion
|
|
120
119
|
export { DEFAULT_QUEUE_HEALTH_CONFIG, QUEUE_HEALTH_SETTINGS_SCHEMA, QueueHealthStorage, assertValidThresholds, parseQueueHealthConfig, thresholdsOrDefault };
|
|
121
120
|
|
|
122
121
|
//# sourceMappingURL=base.js.map
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { FACTORY_PROJECTS_SCHEMA } from "../projects/base.js";
|
|
2
2
|
import { FactoryStorageDomain, UniqueViolationError } from "@mastra/core/storage";
|
|
3
|
-
|
|
3
|
+
// src/storage/domains/source-control/base.ts
|
|
4
4
|
const FACTORY_PROJECTS = "factory_projects";
|
|
5
5
|
const INSTALLATIONS = "source_control_installations";
|
|
6
6
|
const REPOSITORIES = "source_control_repositories";
|
|
@@ -1249,7 +1249,6 @@ var SourceControlStorage = class extends FactoryStorageDomain {
|
|
|
1249
1249
|
};
|
|
1250
1250
|
}
|
|
1251
1251
|
};
|
|
1252
|
-
//#endregion
|
|
1253
1252
|
export { SOURCE_CONTROL_SCHEMAS, SessionBranchHeldError, SessionOwnershipMismatchError, SourceControlConnectionNotFoundError, SourceControlStorage };
|
|
1254
1253
|
|
|
1255
1254
|
//# sourceMappingURL=base.js.map
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { UniqueViolationError } from "@mastra/core/storage";
|
|
2
|
-
|
|
2
|
+
// src/storage/domains/source-control/inmemory.ts
|
|
3
3
|
/** In-memory provider-scoped source-control handle for route tests. */
|
|
4
4
|
var SourceControlStorageInMemory = class {
|
|
5
5
|
integrationId;
|
|
@@ -457,7 +457,6 @@ var SourceControlStorageInMemory = class {
|
|
|
457
457
|
listBySession: async ({ sessionId }) => this.sessionRepositoriesRows.filter((row) => row.sessionId === sessionId)
|
|
458
458
|
};
|
|
459
459
|
};
|
|
460
|
-
//#endregion
|
|
461
460
|
export { SourceControlStorageInMemory };
|
|
462
461
|
|
|
463
462
|
//# sourceMappingURL=inmemory.js.map
|
|
@@ -4,7 +4,7 @@ import { WORK_ITEM_ACTIVITY_SCHEMA, WORK_ITEM_COMMENTS_SCHEMA, WORK_ITEM_COMMENT
|
|
|
4
4
|
import { BoardScopes, FACTORY_BOARD_VERSIONS_SCHEMA, bumpBoardVersions, readBoardVersion, trackBoardWrites } from "./board-version.js";
|
|
5
5
|
import { createHash } from "crypto";
|
|
6
6
|
import { FactoryStorageDomain, UniqueViolationError } from "@mastra/core/storage";
|
|
7
|
-
|
|
7
|
+
// src/storage/domains/work-items/base.ts
|
|
8
8
|
/**
|
|
9
9
|
* Factory work-items storage domain.
|
|
10
10
|
*
|
|
@@ -2742,7 +2742,6 @@ var WorkItemsStorage = class extends FactoryStorageDomain {
|
|
|
2742
2742
|
return removed;
|
|
2743
2743
|
}
|
|
2744
2744
|
};
|
|
2745
|
-
//#endregion
|
|
2746
2745
|
export { ACTIVE_RUN_BINDING_STAGES, FACTORY_PULL_REQUEST_RECONCILIATION_KEY, FACTORY_RULE_MATERIALIZATION_KEY, FACTORY_WORK_ITEM_SUBSCRIPTIONS_SCHEMA, WORK_ITEMS_SCHEMA, WorkItemClaimConflictError, WorkItemRelationError, WorkItemUpdateConflictError, WorkItemsStorage, applyStageTransition, externalSourceKey, factoryActivityAttentionIdentity, factoryAgentWaitingAttentionIdentity, factoryAttentionKey, factoryDecisionAttentionIdentity, factoryDecisionHash, factoryMentionAttentionIdentity, factoryProposalAttentionIdentity, isAgentActor, stampSessions, validateParentRelation };
|
|
2747
2746
|
|
|
2748
2747
|
//# sourceMappingURL=base.js.map
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { randomUUID } from "crypto";
|
|
2
|
-
|
|
2
|
+
// src/storage/domains/work-items/board-version.ts
|
|
3
3
|
/**
|
|
4
4
|
* One row per project whose `version` is replaced after every committed write to that project's
|
|
5
5
|
* `work_items`. Readers of the full card list compare it against the version their snapshot was
|
|
@@ -104,7 +104,6 @@ async function readBoardVersion(ops, orgId, factoryProjectId) {
|
|
|
104
104
|
factory_project_id: factoryProjectId
|
|
105
105
|
}))?.version;
|
|
106
106
|
}
|
|
107
|
-
//#endregion
|
|
108
107
|
export { BoardScopes, FACTORY_BOARD_VERSIONS_SCHEMA, bumpBoardVersions, readBoardVersion, trackBoardWrites };
|
|
109
108
|
|
|
110
109
|
//# sourceMappingURL=board-version.js.map
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { isAgentActor } from "./base.js";
|
|
2
|
-
|
|
2
|
+
// src/storage/domains/work-items/metrics.ts
|
|
3
3
|
/**
|
|
4
4
|
* Aggregation math for the Factory Overview page.
|
|
5
5
|
*
|
|
@@ -220,7 +220,6 @@ function computeFactoryMetrics(boardItems, window) {
|
|
|
220
220
|
agentCoverage: agentCoverage(items, window)
|
|
221
221
|
};
|
|
222
222
|
}
|
|
223
|
-
//#endregion
|
|
224
223
|
export { DEFAULT_METRICS_WINDOW, MAX_METRICS_WINDOW, computeFactoryMetrics, parseMetricsRange };
|
|
225
224
|
|
|
226
225
|
//# sourceMappingURL=metrics.js.map
|
package/dist/telemetry-types.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
|
|
1
|
+
// src/telemetry-types.ts
|
|
2
2
|
/** Browser-safe vocabulary: never send URLs, route parameters, or input contents. */
|
|
3
3
|
const FACTORY_WEB_PAGES = [
|
|
4
4
|
"onboarding",
|
|
@@ -17,7 +17,6 @@ const FACTORY_WEB_PAGES = [
|
|
|
17
17
|
"new_session",
|
|
18
18
|
"new_factory"
|
|
19
19
|
];
|
|
20
|
-
//#endregion
|
|
21
20
|
export { FACTORY_WEB_PAGES };
|
|
22
21
|
|
|
23
22
|
//# sourceMappingURL=telemetry-types.js.map
|
package/dist/telemetry.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { PostHog } from "posthog-node";
|
|
2
|
-
|
|
2
|
+
// src/telemetry.ts
|
|
3
3
|
let client;
|
|
4
4
|
/** Start with the default platform auth provider; custom identity authorities are separate work. */
|
|
5
5
|
function isFactoryTelemetryEnabled(providerName) {
|
|
@@ -41,7 +41,6 @@ function captureFactoryWebActivity(activity, actor) {
|
|
|
41
41
|
});
|
|
42
42
|
} catch {}
|
|
43
43
|
}
|
|
44
|
-
//#endregion
|
|
45
44
|
export { captureFactoryWebActivity, isFactoryTelemetryEnabled };
|
|
46
45
|
|
|
47
46
|
//# sourceMappingURL=telemetry.js.map
|
package/dist/timing.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
|
|
1
|
+
// src/timing.ts
|
|
2
2
|
/**
|
|
3
3
|
* Verbose per-operation timing (HTTP requests, storage calls, sandbox
|
|
4
4
|
* commands). Off by default; enable per deployment with `FACTORY_TIMING=1`.
|
|
@@ -107,7 +107,6 @@ async function timedAboveThreshold(phase, thresholdMs, fn) {
|
|
|
107
107
|
if (elapsed > thresholdMs) process.stderr.write(`[factory:timing] slow ${phase} ${Math.round(elapsed)}ms\n`);
|
|
108
108
|
}
|
|
109
109
|
}
|
|
110
|
-
//#endregion
|
|
111
110
|
export { createRequestTimingMiddleware, factoryTimingEnabled, instrumentAsyncMethods, instrumentMethods, timed, timedAboveThreshold, timedPhase };
|
|
112
111
|
|
|
113
112
|
//# sourceMappingURL=timing.js.map
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
|
|
1
|
+
// src/tools/annotations.ts
|
|
2
2
|
const read = {
|
|
3
3
|
readOnlyHint: true,
|
|
4
4
|
destructiveHint: false,
|
|
@@ -96,7 +96,6 @@ const FACTORY_TOOL_ANNOTATIONS = {
|
|
|
96
96
|
title: "Fetch a work item"
|
|
97
97
|
}
|
|
98
98
|
};
|
|
99
|
-
//#endregion
|
|
100
99
|
export { FACTORY_TOOL_ANNOTATIONS };
|
|
101
100
|
|
|
102
101
|
//# sourceMappingURL=annotations.js.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { requirePerson } from "./scope.js";
|
|
2
2
|
import { z } from "zod";
|
|
3
3
|
import { createTool } from "@mastra/core/tools";
|
|
4
|
-
|
|
4
|
+
// src/tools/approval-tools.ts
|
|
5
5
|
/** Answers a tool call another session holds for approval. Only a signed-in person's turn may answer. */
|
|
6
6
|
function createFactoryApprovalTools(scope, deps) {
|
|
7
7
|
return { factory_answer_approval: createTool({
|
|
@@ -73,7 +73,6 @@ function createFactoryApprovalTools(scope, deps) {
|
|
|
73
73
|
}
|
|
74
74
|
}) };
|
|
75
75
|
}
|
|
76
|
-
//#endregion
|
|
77
76
|
export { createFactoryApprovalTools };
|
|
78
77
|
|
|
79
78
|
//# sourceMappingURL=approval-tools.js.map
|
package/dist/tools/deliver.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { listFactorySessionThreads, sessionMemoryResourceId, sessionStampCounts } from "../session/session-threads.js";
|
|
2
1
|
import { createSessionAsRowOwner } from "../integrations/subscription-session.js";
|
|
3
|
-
|
|
2
|
+
import { listFactorySessionThreads, sessionMemoryResourceId, sessionStampCounts } from "../session/session-threads.js";
|
|
3
|
+
// src/tools/deliver.ts
|
|
4
4
|
/** Notifications between Factory sessions all carry this source. */
|
|
5
5
|
const FACTORY_SESSION_NOTIFICATION_SOURCE = "factory-session";
|
|
6
6
|
/**
|
|
@@ -123,7 +123,6 @@ async function isSessionThread(controller, runs, thread, sessionId, loadRow) {
|
|
|
123
123
|
if (thread.id !== sessionId && !sessionStampCounts(row, thread.resourceId)) return false;
|
|
124
124
|
return thread.resourceId === await sessionMemoryResourceId(controller, row, runs);
|
|
125
125
|
}
|
|
126
|
-
//#endregion
|
|
127
126
|
export { FACTORY_SESSION_NOTIFICATION_SOURCE, deliverFactorySessionNotification, resolveSessionThread, sessionActivity };
|
|
128
127
|
|
|
129
128
|
//# sourceMappingURL=deliver.js.map
|
package/dist/tools/index.js
CHANGED
|
@@ -6,7 +6,7 @@ import { createFactoryMessagingTools } from "./messaging-tools.js";
|
|
|
6
6
|
import { createFactorySessionTools } from "./session-tools.js";
|
|
7
7
|
import { createFactoryWorkItemTools } from "./work-item-tools.js";
|
|
8
8
|
import { FACTORY_TOOLS_WITHOUT_APPROVAL, applyFactoryToolPermissions } from "./permissions.js";
|
|
9
|
-
|
|
9
|
+
// src/tools/index.ts
|
|
10
10
|
/**
|
|
11
11
|
* The Factory toolset for a resolved scope. Tools take scope and storage by
|
|
12
12
|
* closure and never read the request context, so a non-session transport
|
|
@@ -30,7 +30,6 @@ function createFactoryTools({ scope, deps }) {
|
|
|
30
30
|
...createFactoryApprovalTools(scope, deps)
|
|
31
31
|
};
|
|
32
32
|
}
|
|
33
|
-
//#endregion
|
|
34
33
|
export { FACTORY_INTERACTIVE_KEY, FACTORY_TOOLS_WITHOUT_APPROVAL, applyFactoryToolPermissions, createFactoryTools, resolveFactoryToolScope };
|
|
35
34
|
|
|
36
35
|
//# sourceMappingURL=index.js.map
|
|
@@ -5,7 +5,7 @@ import { reportNotification, workItemReportAttributes, workItemReportRecipients
|
|
|
5
5
|
import { listSideSessions, sessionModel } from "./side-sessions.js";
|
|
6
6
|
import { z } from "zod";
|
|
7
7
|
import { createTool } from "@mastra/core/tools";
|
|
8
|
-
|
|
8
|
+
// src/tools/messaging-tools.ts
|
|
9
9
|
/** Messages plus replies, per sender session, per target thread, per window. */
|
|
10
10
|
const SIGNAL_RATE_LIMIT = 10;
|
|
11
11
|
const SIGNAL_RATE_WINDOW_MS = 6e5;
|
|
@@ -518,7 +518,6 @@ function createFactoryMessagingTools(scope, deps) {
|
|
|
518
518
|
factory_subscribe_session: subscribe
|
|
519
519
|
};
|
|
520
520
|
}
|
|
521
|
-
//#endregion
|
|
522
521
|
export { SIGNAL_RATE_LIMIT, SIGNAL_RATE_WINDOW_MS, createFactoryMessagingTools };
|
|
523
522
|
|
|
524
523
|
//# sourceMappingURL=messaging-tools.js.map
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
|
|
1
|
+
// src/tools/permissions.ts
|
|
2
2
|
/**
|
|
3
3
|
* Factory tools that run without asking. Factory tools fall into the SDK's
|
|
4
4
|
* `mcp` category, whose default policy is `ask`, so each of these needs an
|
|
@@ -43,7 +43,6 @@ async function applyFactoryToolPermissions(session, { sessions }, toolNames = FA
|
|
|
43
43
|
});
|
|
44
44
|
}
|
|
45
45
|
}
|
|
46
|
-
//#endregion
|
|
47
46
|
export { FACTORY_TOOLS_WITHOUT_APPROVAL, applyFactoryToolPermissions };
|
|
48
47
|
|
|
49
48
|
//# sourceMappingURL=permissions.js.map
|
package/dist/tools/read-tools.js
CHANGED
|
@@ -5,7 +5,7 @@ import { sessionActivity } from "./deliver.js";
|
|
|
5
5
|
import { decisionRetryable, overtakenDecisionIds } from "../rules/decision-applicability.js";
|
|
6
6
|
import { z } from "zod";
|
|
7
7
|
import { createTool } from "@mastra/core/tools";
|
|
8
|
-
|
|
8
|
+
// src/tools/read-tools.ts
|
|
9
9
|
const MAX_TEXT = 600;
|
|
10
10
|
const MAX_ERROR = 400;
|
|
11
11
|
const MAX_LIST = 50;
|
|
@@ -287,7 +287,6 @@ function createFactoryReadTools(scope, deps) {
|
|
|
287
287
|
})
|
|
288
288
|
};
|
|
289
289
|
}
|
|
290
|
-
//#endregion
|
|
291
290
|
export { MAX_ERROR, MAX_LIST, MAX_TEXT, createFactoryReadTools, findWorkItem, truncate, workItemNotFound, workItemNumber, workItemRefSchema, workItemStage };
|
|
292
291
|
|
|
293
292
|
//# sourceMappingURL=read-tools.js.map
|
package/dist/tools/reports.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { FACTORY_SESSION_NOTIFICATION_SOURCE } from "./deliver.js";
|
|
2
2
|
import { workItemNumber } from "./read-tools.js";
|
|
3
|
-
|
|
3
|
+
// src/tools/reports.ts
|
|
4
4
|
/** How each report status travels. Final reports never coalesce, so a later report can't overwrite them. */
|
|
5
5
|
const FACTORY_REPORT_FORMS = {
|
|
6
6
|
failed: {
|
|
@@ -403,7 +403,6 @@ function createSessionApprovalNotifier(deps) {
|
|
|
403
403
|
for (const recipient of recipients) await resolved.deliver(recipient, notification);
|
|
404
404
|
};
|
|
405
405
|
}
|
|
406
|
-
//#endregion
|
|
407
406
|
export { FACTORY_REPORT_FORMS, createSessionApprovalNotifier, createSessionRunEndReporter, createStageChangeNotifier, createWorkItemRunEndReporter, hasFinalReport, repeatsLastFailure, reportNotification, sendRunEndReport, workItemReportAttributes, workItemReportRecipients };
|
|
408
407
|
|
|
409
408
|
//# sourceMappingURL=reports.js.map
|
|
@@ -21,8 +21,6 @@ export type SessionApprovalReport = (request: {
|
|
|
21
21
|
toolCallId: string;
|
|
22
22
|
args: unknown;
|
|
23
23
|
}) => Promise<void>;
|
|
24
|
-
/** The provider's own usage-limit text, when the error chain carries one. Status text alone is not enough. */
|
|
25
|
-
export declare function usageLimitReason(error: unknown): string | undefined;
|
|
26
24
|
/**
|
|
27
25
|
* Report every run end of a session, however the run started: the board, a
|
|
28
26
|
* typed message, a wake, or a run after a restart. Attached to each Factory
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"run-watch.d.ts","sourceRoot":"","sources":["../../src/tools/run-watch.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,+BAA+B,CAAC;
|
|
1
|
+
{"version":3,"file":"run-watch.d.ts","sourceRoot":"","sources":["../../src/tools/run-watch.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,+BAA+B,CAAC;AAI1E,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,yBAAyB,CAAC;AACpE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAEtD,KAAK,YAAY,GAAG,OAAO,CAAC,oBAAoB,EAAE;IAAE,IAAI,EAAE,WAAW,CAAA;CAAE,CAAC,CAAC,QAAQ,CAAC,CAAC;AAEnF,wFAAwF;AACxF,MAAM,WAAW,UAAU;IACzB,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,OAAO,CAAC;CACnB;AAED,MAAM,WAAW,gBAAgB;IAC/B,SAAS,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,oBAAoB,KAAK,IAAI,GAAG,MAAM,IAAI,CAAC;CACxE;AAED,wFAAwF;AACxF,MAAM,MAAM,mBAAmB,GAAG,CAAC,OAAO,EAAE,iBAAiB,EAAE,KAAK,EAAE,IAAI,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;AAE7F,sFAAsF;AACtF,MAAM,MAAM,qBAAqB,GAAG,CAAC,OAAO,EAAE;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,OAAO,CAAA;CAAE,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;AAKxH;;;;;;GAMG;AACH,wBAAgB,wBAAwB,CACtC,OAAO,EAAE,gBAAgB,EACzB,MAAM,EAAE,mBAAmB,EAC3B,EAAE,mBAAmB,EAAE,GAAE;IAAE,mBAAmB,CAAC,EAAE,qBAAqB,CAAA;CAAO,GAC5E,MAAM,IAAI,CAwCZ;AAED;;;;GAIG;AACH,wBAAgB,wBAAwB,CACtC,OAAO,EAAE,oBAAoB,EAC7B,SAAS,EAAE,MAAM,GAChB;IAAE,SAAS,EAAE,MAAM,YAAY,CAAC;IAAC,IAAI,EAAE,MAAM,IAAI,CAAA;CAAE,CAqBrD;AAED,yFAAyF;AACzF,wBAAgB,UAAU,CACxB,MAAM,EAAE,YAAY,EACpB,MAAM,EAAE,IAAI,CAAC,UAAU,EAAE,UAAU,GAAG,UAAU,CAAC,GAAG,SAAS,EAC7D,YAAY,CAAC,EAAE,MAAM,GACpB,iBAAiB,GAAG,IAAI,CAqB1B"}
|
package/dist/tools/run-watch.js
CHANGED
|
@@ -1,48 +1,9 @@
|
|
|
1
1
|
import { FACTORY_OPEN_RUN_STALE_MS, heartbeatSessionOpenRun } from "../session/run-audit.js";
|
|
2
|
-
|
|
2
|
+
import { toPersistedErrorIdentity } from "@mastra/core/error";
|
|
3
|
+
// src/tools/run-watch.ts
|
|
3
4
|
/** How much of a run's error message a `failed` report quotes. */
|
|
4
5
|
const ERROR_MESSAGE_LENGTH = 400;
|
|
5
6
|
/**
|
|
6
|
-
* A usage or quota rejection, not a rate limit or a request-size limit. The
|
|
7
|
-
* wording is the same set account rotation uses, so a provider that reports
|
|
8
|
-
* the cap as a plain 400 still counts.
|
|
9
|
-
*/
|
|
10
|
-
const USAGE_LIMIT_MESSAGE_PATTERN = /usage limit|usage cap|insufficient_quota|quota exceeded|quota exhausted|quota reached|exceeded your current quota|insufficient balance|insufficient credits|credits exhausted|rate limit exceeded|rate limit reached|weekly limit|monthly limit/i;
|
|
11
|
-
const ERROR_CHAIN_DEPTH = 5;
|
|
12
|
-
function isRecord(value) {
|
|
13
|
-
return typeof value === "object" && value !== null;
|
|
14
|
-
}
|
|
15
|
-
/** The provider's own usage-limit text, when the error chain carries one. Status text alone is not enough. */
|
|
16
|
-
function usageLimitReason(error) {
|
|
17
|
-
const visited = /* @__PURE__ */ new Set();
|
|
18
|
-
const found = [];
|
|
19
|
-
const add = (value) => {
|
|
20
|
-
if (typeof value !== "string") return;
|
|
21
|
-
const text = value.trim();
|
|
22
|
-
if (text && USAGE_LIMIT_MESSAGE_PATTERN.test(text)) found.push(text);
|
|
23
|
-
};
|
|
24
|
-
function walk(value, depth) {
|
|
25
|
-
if (depth > ERROR_CHAIN_DEPTH || !isRecord(value) || visited.has(value)) return;
|
|
26
|
-
visited.add(value);
|
|
27
|
-
add(value.message);
|
|
28
|
-
if (typeof value.responseBody === "string") try {
|
|
29
|
-
const body = JSON.parse(value.responseBody);
|
|
30
|
-
if (isRecord(body)) {
|
|
31
|
-
add(body.message);
|
|
32
|
-
add(body.detail);
|
|
33
|
-
if (isRecord(body.error)) add(body.error.message);
|
|
34
|
-
else add(body.error);
|
|
35
|
-
}
|
|
36
|
-
} catch {}
|
|
37
|
-
if (value.cause !== void 0) walk(value.cause, depth + 1);
|
|
38
|
-
if (value.error !== void 0) walk(value.error, depth + 1);
|
|
39
|
-
}
|
|
40
|
-
try {
|
|
41
|
-
walk(error, 0);
|
|
42
|
-
} catch {}
|
|
43
|
-
return (found.find((text) => text !== "Bad Request") ?? found[0])?.slice(0, ERROR_MESSAGE_LENGTH);
|
|
44
|
-
}
|
|
45
|
-
/**
|
|
46
7
|
* Report every run end of a session, however the run started: the board, a
|
|
47
8
|
* typed message, a wake, or a run after a restart. Attached to each Factory
|
|
48
9
|
* session when it is created, so it outlives any one start. A run someone
|
|
@@ -71,7 +32,7 @@ function observeSessionRunReports(session, report, { onApprovalRequested } = {})
|
|
|
71
32
|
return;
|
|
72
33
|
}
|
|
73
34
|
if (event.type === "error") {
|
|
74
|
-
lastError =
|
|
35
|
+
lastError = toPersistedErrorIdentity(event.error).reason ?? event.error?.message;
|
|
75
36
|
return;
|
|
76
37
|
}
|
|
77
38
|
if (event.type === "tool_suspension_cancelled" && parked?.toolCallId === event.toolCallId) {
|
|
@@ -136,7 +97,6 @@ function runOutcome(reason, parked, errorMessage) {
|
|
|
136
97
|
default: return { status: "done" };
|
|
137
98
|
}
|
|
138
99
|
}
|
|
139
|
-
|
|
140
|
-
export { heartbeatOpenRunUntilEnd, observeSessionRunReports, runOutcome, usageLimitReason };
|
|
100
|
+
export { heartbeatOpenRunUntilEnd, observeSessionRunReports, runOutcome };
|
|
141
101
|
|
|
142
102
|
//# sourceMappingURL=run-watch.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"run-watch.js","names":[],"sources":["../../src/tools/run-watch.ts"],"sourcesContent":["import type { AgentControllerEvent } from '@mastra/core/agent-controller';\n\nimport { FACTORY_OPEN_RUN_STALE_MS, heartbeatSessionOpenRun } from '../session/run-audit.js';\nimport type { RunEndCaptureSession } from '../session/run-audit.js';\nimport type { FactoryRunOutcome } from './reports.js';\n\ntype RunEndReason = Extract<AgentControllerEvent, { type: 'agent_end' }>['reason'];\n\n/** What a run stopped on: a tool waiting for an answer, or one waiting for approval. */\nexport interface ParkedTool {\n toolName: string;\n toolCallId: string;\n approval: boolean;\n}\n\nexport interface RunReportSession {\n subscribe(listener: (event: AgentControllerEvent) => void): () => void;\n}\n\n/** Reports one run's end; `since` is when the run's window opened. Should not throw. */\nexport type SessionRunEndReport = (outcome: FactoryRunOutcome, since: Date) => Promise<void>;\n\n/** Told when the run holds a tool call for approval; the run stays open meanwhile. */\nexport type SessionApprovalReport = (request: { toolName: string; toolCallId: string; args: unknown }) => Promise<void>;\n\n/** How much of a run's error message a `failed` report quotes. */\nconst ERROR_MESSAGE_LENGTH = 400;\n\n/**\n *
|
|
1
|
+
{"version":3,"file":"run-watch.js","names":[],"sources":["../../src/tools/run-watch.ts"],"sourcesContent":["import type { AgentControllerEvent } from '@mastra/core/agent-controller';\nimport { toPersistedErrorIdentity } from '@mastra/core/error';\n\nimport { FACTORY_OPEN_RUN_STALE_MS, heartbeatSessionOpenRun } from '../session/run-audit.js';\nimport type { RunEndCaptureSession } from '../session/run-audit.js';\nimport type { FactoryRunOutcome } from './reports.js';\n\ntype RunEndReason = Extract<AgentControllerEvent, { type: 'agent_end' }>['reason'];\n\n/** What a run stopped on: a tool waiting for an answer, or one waiting for approval. */\nexport interface ParkedTool {\n toolName: string;\n toolCallId: string;\n approval: boolean;\n}\n\nexport interface RunReportSession {\n subscribe(listener: (event: AgentControllerEvent) => void): () => void;\n}\n\n/** Reports one run's end; `since` is when the run's window opened. Should not throw. */\nexport type SessionRunEndReport = (outcome: FactoryRunOutcome, since: Date) => Promise<void>;\n\n/** Told when the run holds a tool call for approval; the run stays open meanwhile. */\nexport type SessionApprovalReport = (request: { toolName: string; toolCallId: string; args: unknown }) => Promise<void>;\n\n/** How much of a run's error message a `failed` report quotes. */\nconst ERROR_MESSAGE_LENGTH = 400;\n\n/**\n * Report every run end of a session, however the run started: the board, a\n * typed message, a wake, or a run after a restart. Attached to each Factory\n * session when it is created, so it outlives any one start. A run someone\n * stopped or steered says nothing, and its window carries into the next run,\n * so reports the agent made in it still count.\n */\nexport function observeSessionRunReports(\n session: RunReportSession,\n report: SessionRunEndReport,\n { onApprovalRequested }: { onApprovalRequested?: SessionApprovalReport } = {},\n): () => void {\n let parked: ParkedTool | undefined;\n let lastError: string | undefined;\n let since = new Date();\n const settle = (work: Promise<void>) =>\n void work.catch(error => {\n console.warn('[Factory reports] Unable to report on a session run.', error);\n });\n return session.subscribe(event => {\n if (event.type === 'tool_suspended' || event.type === 'tool_approval_required') {\n parked = {\n toolName: event.toolName,\n toolCallId: event.toolCallId,\n approval: event.type === 'tool_approval_required',\n };\n // An approval gate holds the run open, so it is announced now, not at the run's end.\n if (event.type === 'tool_approval_required' && onApprovalRequested) {\n settle(onApprovalRequested({ toolName: event.toolName, toolCallId: event.toolCallId, args: event.args }));\n }\n return;\n }\n if (event.type === 'error') {\n lastError = toPersistedErrorIdentity(event.error).reason ?? event.error?.message;\n return;\n }\n if (event.type === 'tool_suspension_cancelled' && parked?.toolCallId === event.toolCallId) {\n parked = undefined;\n return;\n }\n if (event.type !== 'agent_end') return;\n const outcome = runOutcome(event.reason, parked, lastError);\n parked = undefined;\n lastError = undefined;\n if (!outcome) return;\n // Move the window now, so a run that starts before this report settles is judged on its own;\n // reports made up to the end, including its last millisecond, belong to the run that ended.\n const runSince = since;\n since = new Date(Date.now() + 1);\n settle(report(outcome, runSince));\n });\n}\n\n/**\n * Renew a kicked-off run's open-run entry until the run ends, like the\n * dispatcher's heartbeat, so no dispatcher starts the role again meanwhile.\n * `endReason` is how that run ended, once it has; `stop` is for a kickoff that fails.\n */\nexport function heartbeatOpenRunUntilEnd(\n session: RunEndCaptureSession,\n kickoffId: string,\n): { endReason: () => RunEndReason; stop: () => void } {\n let endReason: RunEndReason;\n let unsubscribe = () => {};\n const timer = setInterval(\n () => void heartbeatSessionOpenRun(session, kickoffId),\n Math.floor(FACTORY_OPEN_RUN_STALE_MS / 3),\n );\n timer.unref?.();\n let stopped = false;\n const stop = () => {\n if (stopped) return;\n stopped = true;\n clearInterval(timer);\n unsubscribe();\n };\n unsubscribe = session.subscribe(event => {\n if (event.type !== 'agent_end') return;\n endReason ??= event.reason;\n stop();\n });\n return { endReason: () => endReason, stop };\n}\n\n/** `null` for an aborted run: someone stopped or steered it, which is not an outcome. */\nexport function runOutcome(\n reason: RunEndReason,\n parked: Pick<ParkedTool, 'toolName' | 'approval'> | undefined,\n errorMessage?: string,\n): FactoryRunOutcome | null {\n switch (reason) {\n case 'error': {\n const message = errorMessage?.trim();\n return {\n status: 'failed',\n reason: message\n ? `the run ended in error: ${message.slice(0, ERROR_MESSAGE_LENGTH)}`\n : 'the run ended in error.',\n };\n }\n case 'aborted':\n return null;\n case 'suspended':\n return {\n status: 'blocked',\n ...(parked ? { toolName: parked.toolName, ...(parked.approval ? { approval: true } : {}) } : {}),\n };\n default:\n return { status: 'done' };\n }\n}\n"],"mappings":";;;;AA2BA,MAAM,uBAAuB;;;;;;;;AAS7B,SAAgB,yBACd,SACA,QACA,EAAE,wBAAyE,CAAC,GAChE;CACZ,IAAI;CACJ,IAAI;CACJ,IAAI,wBAAQ,IAAI,KAAK;CACrB,MAAM,UAAU,SACd,KAAK,KAAK,OAAM,UAAS;EACvB,QAAQ,KAAK,wDAAwD,KAAK;CAC5E,CAAC;CACH,OAAO,QAAQ,WAAU,UAAS;EAChC,IAAI,MAAM,SAAS,oBAAoB,MAAM,SAAS,0BAA0B;GAC9E,SAAS;IACP,UAAU,MAAM;IAChB,YAAY,MAAM;IAClB,UAAU,MAAM,SAAS;GAC3B;GAEA,IAAI,MAAM,SAAS,4BAA4B,qBAC7C,OAAO,oBAAoB;IAAE,UAAU,MAAM;IAAU,YAAY,MAAM;IAAY,MAAM,MAAM;GAAK,CAAC,CAAC;GAE1G;EACF;EACA,IAAI,MAAM,SAAS,SAAS;GAC1B,YAAY,yBAAyB,MAAM,KAAK,CAAC,CAAC,UAAU,MAAM,OAAO;GACzE;EACF;EACA,IAAI,MAAM,SAAS,+BAA+B,QAAQ,eAAe,MAAM,YAAY;GACzF,SAAS,KAAA;GACT;EACF;EACA,IAAI,MAAM,SAAS,aAAa;EAChC,MAAM,UAAU,WAAW,MAAM,QAAQ,QAAQ,SAAS;EAC1D,SAAS,KAAA;EACT,YAAY,KAAA;EACZ,IAAI,CAAC,SAAS;EAGd,MAAM,WAAW;EACjB,QAAQ,IAAI,KAAK,KAAK,IAAI,IAAI,CAAC;EAC/B,OAAO,OAAO,SAAS,QAAQ,CAAC;CAClC,CAAC;AACH;;;;;;AAOA,SAAgB,yBACd,SACA,WACqD;CACrD,IAAI;CACJ,IAAI,oBAAoB,CAAC;CACzB,MAAM,QAAQ,kBACN,KAAK,wBAAwB,SAAS,SAAS,GACrD,KAAK,MAAM,4BAA4B,CAAC,CAC1C;CACA,MAAM,QAAQ;CACd,IAAI,UAAU;CACd,MAAM,aAAa;EACjB,IAAI,SAAS;EACb,UAAU;EACV,cAAc,KAAK;EACnB,YAAY;CACd;CACA,cAAc,QAAQ,WAAU,UAAS;EACvC,IAAI,MAAM,SAAS,aAAa;EAChC,cAAc,MAAM;EACpB,KAAK;CACP,CAAC;CACD,OAAO;EAAE,iBAAiB;EAAW;CAAK;AAC5C;;AAGA,SAAgB,WACd,QACA,QACA,cAC0B;CAC1B,QAAQ,QAAR;EACE,KAAK,SAAS;GACZ,MAAM,UAAU,cAAc,KAAK;GACnC,OAAO;IACL,QAAQ;IACR,QAAQ,UACJ,2BAA2B,QAAQ,MAAM,GAAG,oBAAoB,MAChE;GACN;EACF;EACA,KAAK,WACH,OAAO;EACT,KAAK,aACH,OAAO;GACL,QAAQ;GACR,GAAI,SAAS;IAAE,UAAU,OAAO;IAAU,GAAI,OAAO,WAAW,EAAE,UAAU,KAAK,IAAI,CAAC;GAAG,IAAI,CAAC;EAChG;EACF,SACE,OAAO,EAAE,QAAQ,OAAO;CAC5B;AACF"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
2
|
import { createTool } from "@mastra/core/tools";
|
|
3
|
-
|
|
3
|
+
// src/tools/sandbox-tools.ts
|
|
4
4
|
/** Tools a session uses on its own sandbox. Every session with a sandbox gets them. */
|
|
5
5
|
function createFactorySandboxTools(scope, deps) {
|
|
6
6
|
return { factory_recreate_sandbox: createTool({
|
|
@@ -34,7 +34,6 @@ function createFactorySandboxTools(scope, deps) {
|
|
|
34
34
|
}
|
|
35
35
|
}) };
|
|
36
36
|
}
|
|
37
|
-
//#endregion
|
|
38
37
|
export { createFactorySandboxTools };
|
|
39
38
|
|
|
40
39
|
//# sourceMappingURL=sandbox-tools.js.map
|
package/dist/tools/scope.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { FACTORY_INTERACTIVE_KEY, factoryUserOrgId, getFactoryAuthUserFromContext, getFactoryAuthUserId } from "../auth.js";
|
|
2
|
-
import { isWorkerSession } from "../session/session-threads.js";
|
|
3
2
|
import { auditActorProfile } from "../storage/domains/audit/base.js";
|
|
4
|
-
|
|
3
|
+
import { isWorkerSession } from "../session/session-threads.js";
|
|
4
|
+
// src/tools/scope.ts
|
|
5
5
|
/** Linked Slack sender, separate from the session owner's model-credential identity. */
|
|
6
6
|
const FACTORY_SLACK_SENDER_KEY = "mastra__factorySlackSender";
|
|
7
7
|
/**
|
|
@@ -78,7 +78,6 @@ function requirePerson(scope, action) {
|
|
|
78
78
|
if (scope.interactive) return;
|
|
79
79
|
throw new Error(`Only a person can ${action}. Nobody signed in started this turn (it came from a notification, webhook or rule); ask the person to do it from the board or by messaging this session.`);
|
|
80
80
|
}
|
|
81
|
-
//#endregion
|
|
82
81
|
export { FACTORY_INTERACTIVE_KEY, FACTORY_SLACK_SENDER_KEY, requirePerson, resolveFactoryToolScope };
|
|
83
82
|
|
|
84
83
|
//# sourceMappingURL=scope.js.map
|
|
@@ -16,7 +16,7 @@ import { heartbeatOpenRunUntilEnd } from "./run-watch.js";
|
|
|
16
16
|
import { RequestContext } from "@mastra/core/request-context";
|
|
17
17
|
import { z } from "zod";
|
|
18
18
|
import { createTool } from "@mastra/core/tools";
|
|
19
|
-
|
|
19
|
+
// src/tools/session-tools.ts
|
|
20
20
|
const TITLE_LENGTH = 120;
|
|
21
21
|
/** Who renews the open-run entries this process writes; one id per process, like the dispatcher's. */
|
|
22
22
|
const FACTORY_TOOLS_OWNER_ID = `factory-tools:${globalThis.crypto.randomUUID()}`;
|
|
@@ -423,7 +423,6 @@ function createFactorySessionTools(scope, deps) {
|
|
|
423
423
|
factory_switch_session_model: switchModel
|
|
424
424
|
};
|
|
425
425
|
}
|
|
426
|
-
//#endregion
|
|
427
426
|
export { FACTORY_TOOLS_OWNER_ID, createFactorySessionTools };
|
|
428
427
|
|
|
429
428
|
//# sourceMappingURL=session-tools.js.map
|