@mastra/factory 0.26.0-alpha.0 → 0.26.0-alpha.2
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 +158 -57
- package/dist/auth.d.ts.map +1 -1
- package/dist/boards/card-facts.d.ts +5 -0
- package/dist/boards/card-facts.d.ts.map +1 -0
- package/dist/boards/card-facts.js +19 -0
- package/dist/boards/card-facts.js.map +1 -0
- package/dist/boards/define-board.d.ts +109 -13
- package/dist/boards/define-board.d.ts.map +1 -1
- package/dist/boards/define-board.js +163 -21
- package/dist/boards/define-board.js.map +1 -1
- package/dist/boards/index.d.ts +4 -3
- package/dist/boards/index.d.ts.map +1 -1
- package/dist/boards/index.js +3 -2
- package/dist/boards/index.js.map +1 -1
- package/dist/boards/legacy-plan-role.d.ts +14 -0
- package/dist/boards/legacy-plan-role.d.ts.map +1 -0
- package/dist/boards/legacy-plan-role.js +32 -0
- package/dist/boards/legacy-plan-role.js.map +1 -0
- package/dist/boards/phase-automation.d.ts +13 -0
- package/dist/boards/phase-automation.d.ts.map +1 -0
- package/dist/boards/phase-automation.js +25 -0
- package/dist/boards/phase-automation.js.map +1 -0
- package/dist/boards/phase-runner.d.ts +13 -0
- package/dist/boards/phase-runner.d.ts.map +1 -0
- package/dist/boards/phase-runner.js +44 -0
- package/dist/boards/phase-runner.js.map +1 -0
- package/dist/boards/relocate.d.ts.map +1 -1
- package/dist/boards/relocate.js +2 -0
- package/dist/boards/relocate.js.map +1 -1
- package/dist/boards/review.d.ts +1 -1
- package/dist/boards/review.d.ts.map +1 -1
- package/dist/boards/review.js +18 -18
- package/dist/boards/review.js.map +1 -1
- package/dist/boards/semantics.d.ts.map +1 -1
- package/dist/boards/semantics.js +11 -7
- package/dist/boards/semantics.js.map +1 -1
- package/dist/boards/transition-policy.d.ts +10 -10
- package/dist/boards/work-tool-rules.d.ts +3 -3
- package/dist/boards/work-tool-rules.d.ts.map +1 -1
- package/dist/boards/work-tool-rules.js +1 -1
- package/dist/boards/work-tool-rules.js.map +1 -1
- package/dist/boards/work.d.ts +3 -3
- package/dist/boards/work.d.ts.map +1 -1
- package/dist/boards/work.js +31 -29
- package/dist/boards/work.js.map +1 -1
- package/dist/environment/build-runner.d.ts +4 -4
- package/dist/environment/build-runner.d.ts.map +1 -1
- package/dist/environment/build-workflow.d.ts +6 -6
- package/dist/environment/build-workflow.js +1 -1
- package/dist/environment/build.d.ts +2 -2
- package/dist/environment/build.d.ts.map +1 -1
- package/dist/environment/build.js +2 -0
- package/dist/environment/build.js.map +1 -1
- package/dist/factory.d.ts +8 -0
- package/dist/factory.d.ts.map +1 -1
- package/dist/factory.js +8 -2
- package/dist/factory.js.map +1 -1
- package/dist/index.d.ts +3 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -2
- package/dist/integrations/github/app-identity.d.ts.map +1 -1
- package/dist/integrations/github/default-rules.d.ts +71 -71
- package/dist/integrations/github/default-rules.d.ts.map +1 -1
- package/dist/integrations/github/integration.d.ts +5 -4
- package/dist/integrations/github/integration.d.ts.map +1 -1
- package/dist/integrations/github/integration.js +10 -8
- package/dist/integrations/github/integration.js.map +1 -1
- package/dist/integrations/github/reconcile-worker.d.ts.map +1 -1
- package/dist/integrations/github/rules.d.ts.map +1 -1
- package/dist/integrations/github/sandbox.d.ts +2 -2
- package/dist/integrations/github/sandbox.d.ts.map +1 -1
- package/dist/integrations/github/sandbox.js +6 -1
- package/dist/integrations/github/sandbox.js.map +1 -1
- package/dist/integrations/gitlab/api.d.ts.map +1 -1
- package/dist/integrations/gitlab/default-rules.d.ts +38 -38
- package/dist/integrations/gitlab/default-rules.d.ts.map +1 -1
- package/dist/integrations/gitlab/integration.d.ts.map +1 -1
- package/dist/integrations/gitlab/rules.d.ts.map +1 -1
- package/dist/integrations/incidentio/api.d.ts.map +1 -1
- package/dist/integrations/incidentio/default-rules.d.ts +3 -3
- package/dist/integrations/incidentio/default-rules.d.ts.map +1 -1
- package/dist/integrations/incidentio/integration.d.ts.map +1 -1
- package/dist/integrations/incidentio/rules.d.ts.map +1 -1
- package/dist/integrations/issue-reconcile-worker.d.ts.map +1 -1
- package/dist/integrations/jira/api.d.ts +1 -1
- package/dist/integrations/jira/api.d.ts.map +1 -1
- package/dist/integrations/jira/default-rules.d.ts +3 -3
- package/dist/integrations/jira/default-rules.d.ts.map +1 -1
- package/dist/integrations/jira/integration.d.ts.map +1 -1
- package/dist/integrations/jira/rules.d.ts.map +1 -1
- package/dist/integrations/linear/default-rules.d.ts +8 -8
- package/dist/integrations/linear/default-rules.d.ts.map +1 -1
- package/dist/integrations/linear/integration.d.ts.map +1 -1
- package/dist/integrations/linear/rules.d.ts.map +1 -1
- package/dist/integrations/platform/api-client.d.ts.map +1 -1
- package/dist/integrations/platform/github/event-worker.d.ts.map +1 -1
- package/dist/integrations/platform/github/integration.d.ts +5 -0
- package/dist/integrations/platform/github/integration.d.ts.map +1 -1
- package/dist/integrations/platform/github/integration.js +7 -0
- package/dist/integrations/platform/github/integration.js.map +1 -1
- package/dist/integrations/platform/gitlab/event-worker.d.ts.map +1 -1
- package/dist/integrations/platform/gitlab/integration.d.ts.map +1 -1
- package/dist/integrations/platform/incidentio/integration.d.ts.map +1 -1
- package/dist/integrations/platform/jira/integration.d.ts.map +1 -1
- package/dist/integrations/platform/linear/event-worker.d.ts.map +1 -1
- package/dist/integrations/platform/linear/integration.d.ts.map +1 -1
- package/dist/integrations/slack/channel-reply-processor.d.ts.map +1 -1
- package/dist/integrations/slack/channel-session-link-processor.d.ts.map +1 -1
- package/dist/integrations/slack/feed-publisher.d.ts.map +1 -1
- package/dist/integrations/slack/integration.d.ts.map +1 -1
- package/dist/integrations/slack/reply-reminder-processor.d.ts.map +1 -1
- package/dist/integrations/slack/reply-tool.d.ts.map +1 -1
- package/dist/integrations/slack/slack.d.ts.map +1 -1
- package/dist/integrations/workos/integration.d.ts.map +1 -1
- package/dist/mcp/events.d.ts +3 -3
- package/dist/mcp/routes.js +1 -1
- package/dist/routes/attention-activity.d.ts +1 -1
- package/dist/routes/attention-activity.d.ts.map +1 -1
- package/dist/routes/attention-parked.d.ts +1 -1
- package/dist/routes/attention-parked.d.ts.map +1 -1
- package/dist/routes/attention-providers.d.ts +1 -1
- package/dist/routes/attention-providers.d.ts.map +1 -1
- package/dist/routes/automation-runs.d.ts.map +1 -1
- package/dist/routes/config.d.ts.map +1 -1
- package/dist/routes/contracts.d.ts +159 -136
- package/dist/routes/contracts.d.ts.map +1 -1
- package/dist/routes/contracts.js +23 -0
- package/dist/routes/contracts.js.map +1 -1
- package/dist/routes/fs.d.ts.map +1 -1
- package/dist/routes/fs.js +24 -0
- package/dist/routes/fs.js.map +1 -1
- package/dist/routes/intake.d.ts.map +1 -1
- package/dist/routes/knowledge.d.ts.map +1 -1
- package/dist/routes/oauth.d.ts.map +1 -1
- package/dist/routes/projects.d.ts.map +1 -1
- package/dist/routes/route.d.ts.map +1 -1
- package/dist/routes/skills.d.ts +3 -0
- package/dist/routes/skills.d.ts.map +1 -1
- package/dist/routes/skills.js +1 -1
- package/dist/routes/skills.js.map +1 -1
- package/dist/routes/surface.d.ts +3 -0
- package/dist/routes/surface.d.ts.map +1 -1
- package/dist/routes/surface.js +24 -22
- package/dist/routes/surface.js.map +1 -1
- package/dist/routes/telemetry.d.ts.map +1 -1
- package/dist/routes/tenant-credentials.d.ts.map +1 -1
- package/dist/routes/work-items.d.ts.map +1 -1
- package/dist/routes/work-items.js +19 -3
- package/dist/routes/work-items.js.map +1 -1
- package/dist/rules/decision-applicability.d.ts.map +1 -1
- package/dist/rules/decision-applicability.js +3 -1
- package/dist/rules/decision-applicability.js.map +1 -1
- package/dist/rules/dispatch-errors.d.ts.map +1 -1
- package/dist/rules/dispatch-errors.js +4 -0
- package/dist/rules/dispatch-errors.js.map +1 -1
- package/dist/rules/dispatcher.d.ts.map +1 -1
- package/dist/rules/dispatcher.js +17 -3
- package/dist/rules/dispatcher.js.map +1 -1
- package/dist/rules/processor.d.ts.map +1 -1
- package/dist/rules/processor.js +4 -2
- package/dist/rules/processor.js.map +1 -1
- package/dist/rules/rule-group.d.ts +29 -0
- package/dist/rules/rule-group.d.ts.map +1 -0
- package/dist/rules/rule-group.js +141 -0
- package/dist/rules/rule-group.js.map +1 -0
- package/dist/rules/start-coordinator.d.ts.map +1 -1
- package/dist/rules/terminal-cleanup.d.ts.map +1 -1
- package/dist/rules/tools.d.ts +1 -1
- package/dist/rules/tools.d.ts.map +1 -1
- package/dist/rules/transition-service.d.ts.map +1 -1
- package/dist/rules/transition-service.js +5 -3
- package/dist/rules/transition-service.js.map +1 -1
- package/dist/rules/types.d.ts +25 -14
- package/dist/rules/types.d.ts.map +1 -1
- package/dist/rules/types.js.map +1 -1
- package/dist/rules/validation.d.ts +2 -0
- package/dist/rules/validation.d.ts.map +1 -1
- package/dist/rules/validation.js +6 -3
- package/dist/rules/validation.js.map +1 -1
- package/dist/sandbox/callback-factory-sandbox.d.ts.map +1 -1
- package/dist/sandbox/local-factory-sandbox.d.ts +4 -1
- package/dist/sandbox/local-factory-sandbox.d.ts.map +1 -1
- package/dist/sandbox/local-factory-sandbox.js +1 -1
- package/dist/sandbox/local-factory-sandbox.js.map +1 -1
- package/dist/sandbox/session-retirement.d.ts.map +1 -1
- package/dist/session/environment-state-processor.d.ts.map +1 -1
- package/dist/session/factory-session.d.ts.map +1 -1
- package/dist/session/live-sessions.d.ts.map +1 -1
- package/dist/session/reply-credential-processor.d.ts.map +1 -1
- package/dist/session/run-audit.d.ts +1 -1
- package/dist/session/run-audit.d.ts.map +1 -1
- package/dist/skills/app-skills.d.ts +11 -0
- package/dist/skills/app-skills.d.ts.map +1 -0
- package/dist/skills/app-skills.js +37 -0
- package/dist/skills/app-skills.js.map +1 -0
- package/dist/skills/catalog.d.ts +9 -3
- package/dist/skills/catalog.d.ts.map +1 -1
- package/dist/skills/catalog.js +35 -19
- package/dist/skills/catalog.js.map +1 -1
- package/dist/skills/service.d.ts.map +1 -1
- package/dist/spa-static.d.ts.map +1 -1
- package/dist/storage/domains/audit/actions.d.ts +6 -6
- package/dist/storage/domains/audit/actions.d.ts.map +1 -1
- package/dist/storage/domains/audit/actors.d.ts +1 -1
- package/dist/storage/domains/audit/actors.d.ts.map +1 -1
- package/dist/storage/domains/audit/base.d.ts.map +1 -1
- package/dist/storage/domains/audit/domain.d.ts.map +1 -1
- package/dist/storage/domains/channel-identity/base.d.ts.map +1 -1
- package/dist/storage/domains/comments/base.d.ts.map +1 -1
- package/dist/storage/domains/comments/domain.d.ts.map +1 -1
- package/dist/storage/domains/comments/feed-context.d.ts.map +1 -1
- package/dist/storage/domains/credentials/base.d.ts.map +1 -1
- package/dist/storage/domains/custom-providers/base.d.ts.map +1 -1
- package/dist/storage/domains/filesystem/base.d.ts.map +1 -1
- package/dist/storage/domains/intake/base.d.ts.map +1 -1
- package/dist/storage/domains/integrations/base.d.ts.map +1 -1
- package/dist/storage/domains/memory-settings/base.d.ts.map +1 -1
- package/dist/storage/domains/model-defaults/base.d.ts.map +1 -1
- package/dist/storage/domains/projects/base.d.ts +1 -1
- package/dist/storage/domains/projects/base.d.ts.map +1 -1
- package/dist/storage/domains/queue-health/base.d.ts.map +1 -1
- package/dist/storage/domains/source-control/base.d.ts.map +1 -1
- package/dist/storage/domains/source-control/inmemory.d.ts +5 -5
- package/dist/storage/domains/source-control/inmemory.d.ts.map +1 -1
- package/dist/storage/domains/work-items/base.d.ts +2 -2
- package/dist/storage/domains/work-items/base.d.ts.map +1 -1
- package/dist/storage/domains/work-items/base.js +1 -0
- package/dist/storage/domains/work-items/base.js.map +1 -1
- package/dist/storage/domains/work-items/board-version.d.ts.map +1 -1
- package/dist/telemetry-types.d.ts +1 -1
- package/dist/telemetry-types.d.ts.map +1 -1
- package/dist/timing.d.ts.map +1 -1
- package/dist/tools/session-tools.d.ts.map +1 -1
- package/dist/tools/session-tools.js +3 -1
- package/dist/tools/session-tools.js.map +1 -1
- package/dist/tools/sessions-state-processor.d.ts.map +1 -1
- package/dist/tools/work-item-tools.js +1 -1
- package/dist/workspace.d.ts +15 -6
- package/dist/workspace.d.ts.map +1 -1
- package/dist/workspace.js +79 -18
- package/dist/workspace.js.map +1 -1
- package/package.json +9 -9
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"board-version.d.ts","sourceRoot":"","sources":["../../../../src/storage/domains/work-items/board-version.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,gBAAgB,EAAmB,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AAEjG;;;;GAIG;AACH,eAAO,MAAM,6BAA6B,EAAE,gBAU3C,CAAC;AAEF,sFAAsF;AACtF,MAAM,WAAW,UAAU;IACzB,KAAK,EAAE,MAAM,CAAC;IACd,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAkBD;;;GAGG;AACH,wBAAgB,gBAAgB,CAC9B,GAAG,EAAE,iBAAiB,EACtB,OAAO,EAAE,CAAC,KAAK,EAAE,UAAU,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,GACnD,iBAAiB,CA6CnB;AAED,6FAA6F;AAC7F,qBAAa,WAAW;;IAGtB,GAAG,
|
|
1
|
+
{"version":3,"file":"board-version.d.ts","sourceRoot":"","sources":["../../../../src/storage/domains/work-items/board-version.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,gBAAgB,EAAmB,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AAEjG;;;;GAIG;AACH,eAAO,MAAM,6BAA6B,EAAE,gBAU3C,CAAC;AAEF,sFAAsF;AACtF,MAAM,WAAW,UAAU;IACzB,KAAK,EAAE,MAAM,CAAC;IACd,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAkBD;;;GAGG;AACH,wBAAgB,gBAAgB,CAC9B,GAAG,EAAE,iBAAiB,EACtB,OAAO,EAAE,CAAC,KAAK,EAAE,UAAU,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,GACnD,iBAAiB,CA6CnB;AAED,6FAA6F;AAC7F,qBAAa,WAAW;;IAGtB,GAAG,UAAW,UAAU,KAAG,IAAI,CAE7B;IAEF,MAAM,IAAI,UAAU,EAAE,CAErB;CACF;AAED,wBAAsB,iBAAiB,CAAC,GAAG,EAAE,iBAAiB,EAAE,MAAM,EAAE,SAAS,UAAU,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAgB5G;AAED,wBAAsB,gBAAgB,CACpC,GAAG,EAAE,iBAAiB,EACtB,KAAK,EAAE,MAAM,EACb,gBAAgB,EAAE,MAAM,GACvB,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAM7B"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/** Browser-safe vocabulary: never send URLs, route parameters, or input contents. */
|
|
2
|
-
export declare const FACTORY_WEB_PAGES: readonly [
|
|
2
|
+
export declare const FACTORY_WEB_PAGES: readonly ['onboarding', 'work', 'review', 'overview', 'attention', 'activity', 'rules', 'audit', 'knowledge', 'settings', 'slack_connection', 'workspace', 'thread', 'new_session', 'new_factory'];
|
|
3
3
|
export interface FactoryWebActivity {
|
|
4
4
|
activity: 'page_view' | 'interaction';
|
|
5
5
|
page: (typeof FACTORY_WEB_PAGES)[number];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"telemetry-types.d.ts","sourceRoot":"","sources":["../src/telemetry-types.ts"],"names":[],"mappings":"AAAA,qFAAqF;AACrF,eAAO,MAAM,iBAAiB,
|
|
1
|
+
{"version":3,"file":"telemetry-types.d.ts","sourceRoot":"","sources":["../src/telemetry-types.ts"],"names":[],"mappings":"AAAA,qFAAqF;AACrF,eAAO,MAAM,iBAAiB,YAC5B,YAAY,EACZ,MAAM,EACN,QAAQ,EACR,UAAU,EACV,WAAW,EACX,UAAU,EACV,OAAO,EACP,OAAO,EACP,WAAW,EACX,UAAU,EACV,kBAAkB,EAClB,WAAW,EACX,QAAQ,EACR,aAAa,EACb,aAAa,CACL,CAAC;AAEX,MAAM,WAAW,kBAAkB;IACjC,QAAQ,EAAE,WAAW,GAAG,aAAa,CAAC;IACtC,IAAI,EAAE,CAAC,OAAO,iBAAiB,CAAC,CAAC,MAAM,CAAC,CAAC;CAC1C"}
|
package/dist/timing.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"timing.d.ts","sourceRoot":"","sources":["../src/timing.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AAEpC;;;GAGG;AACH,eAAO,MAAM,oBAAoB,SAA2D,CAAC;AAM7F,4EAA4E;AAC5E,wBAAsB,KAAK,CAAC,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAQ9E;AAED,kFAAkF;AAClF,wBAAgB,6BAA6B,
|
|
1
|
+
{"version":3,"file":"timing.d.ts","sourceRoot":"","sources":["../src/timing.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AAEpC;;;GAGG;AACH,eAAO,MAAM,oBAAoB,SAA2D,CAAC;AAM7F,4EAA4E;AAC5E,wBAAsB,KAAK,CAAC,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAQ9E;AAED,kFAAkF;AAClF,wBAAgB,6BAA6B,QAC1B,OAAO,QAAQ,MAAM,OAAO,CAAC,IAAI,CAAC,KAAG,OAAO,CAAC,IAAI,CAAC,CAQpE;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,CAAC,SAAS,MAAM,EAAE,MAAM,EAAE,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,SAAS,MAAM,EAAE,GAAG,CAAC,CAgB3G;AAmBD;;;;;;GAMG;AACH,wBAAgB,sBAAsB,CAAC,CAAC,SAAS,MAAM,EAAE,MAAM,EAAE,CAAC,EAAE,KAAK,EAAE,MAAM,GAAG,CAAC,CAyBpF;AAED,2EAA2E;AAC3E,wBAAsB,UAAU,CAAC,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAOnF;AAED;;;GAGG;AACH,wBAAsB,mBAAmB,CAAC,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAUjH"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"session-tools.d.ts","sourceRoot":"","sources":["../../src/tools/session-tools.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"session-tools.d.ts","sourceRoot":"","sources":["../../src/tools/session-tools.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAC3D,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAMhE,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,+BAA+B,CAAC;AAE7E,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,+BAA+B,CAAC;AAQhF,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oCAAoC,CAAC;AACxE,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,wCAAwC,CAAC;AACtF,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,6CAA6C,CAAC;AAC1F,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,mCAAmC,CAAC;AACvE,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AAEtF,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,qCAAqC,CAAC;AAElF,OAAO,KAAK,EAAe,gBAAgB,EAAE,MAAM,uCAAuC,CAAC;AAE3F,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAG7D,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAKnD,sGAAsG;AACtG,eAAO,MAAM,sBAAsB,QAAoD,CAAC;AAExF,MAAM,WAAW,8BAA8B;IAC7C,QAAQ,EAAE,IAAI,CAAC,0BAA0B,EAAE,gBAAgB,GAAG,6BAA6B,CAAC,CAAC;IAC7F,YAAY,EAAE;QACZ,QAAQ,EAAE,sBAAsB,CAAC;QACjC,aAAa,EAAE,oBAAoB,CAAC;QACpC;;;;WAIG;QACH,aAAa,CAAC,EAAE;YACd,WAAW,EAAE,IAAI,CAAC,uBAAuB,EAAE,iBAAiB,CAAC,CAAC;YAC9D,eAAe,CAAC,EAAE,IAAI,CAAC,sBAAsB,EAAE,aAAa,GAAG,MAAM,CAAC,CAAC;YACvE,mBAAmB,CAAC,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;SAC3C,CAAC;KACH,CAAC;IACF,wEAAwE;IACxE,SAAS,EAAE,MAAM,OAAO,CAAC,gBAAgB,GAAG,IAAI,CAAC,CAAC;IAClD,SAAS,EAAE,IAAI,CACb,gBAAgB,EACd,MAAM,GACN,eAAe,GACf,iBAAiB,GACjB,gCAAgC,GAChC,wBAAwB,GACxB,yBAAyB,GACzB,qBAAqB,GACrB,yBAAyB,GACzB,0BAA0B,GAC1B,yBAAyB,CAC5B,CAAC;IACF,MAAM,EAAE,aAAa,CAAC;IACtB,aAAa,EAAE,aAAa,CAAC;IAC7B,MAAM,CAAC,EAAE,IAAI,CAAC,aAAa,EAAE,WAAW,CAAC,CAAC;IAC1C,kFAAkF;IAClF,gBAAgB,EAAE,MAAM,IAAI,CAAC,uBAAuB,EAAE,SAAS,CAAC,GAAG,SAAS,CAAC;CAC9E;AA0BD,oGAAoG;AACpG,wBAAgB,yBAAyB,CACvC,KAAK,EAAE,gBAAgB,EACvB,IAAI,EAAE,8BAA8B,GACnC,gBAAgB,CA6clB"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { boardForWorkItem } from "../boards/semantics.js";
|
|
2
2
|
import "../boards/index.js";
|
|
3
|
+
import { workLaneForRole } from "../boards/legacy-plan-role.js";
|
|
3
4
|
import { primeTenantCredentialsForTenant } from "../routes/tenant-credentials.js";
|
|
4
5
|
import { effectiveModelScope } from "../storage/domains/projects/base.js";
|
|
5
6
|
import { ensureFactorySourceSession, hydrateFactorySession, resolveFactorySessionModel } from "../session/factory-session.js";
|
|
@@ -272,7 +273,8 @@ function createFactorySessionTools(scope, deps) {
|
|
|
272
273
|
const item = await findWorkItem(deps.workItems, scope, workItem);
|
|
273
274
|
if (!item) throw workItemNotFound(workItem);
|
|
274
275
|
const label = workItemLabel(item);
|
|
275
|
-
|
|
276
|
+
const board = deps.boards.get(boardForWorkItem(item));
|
|
277
|
+
if (!workLaneForRole(board, role) && !board?.phaseForRole(role)) throw new Error(`${label}'s board has no ${role} role.`);
|
|
276
278
|
const seated = item.sessions[role];
|
|
277
279
|
if (seated) throw new Error(`${label} already has a ${role} session ${seated.sessionId}; message it with factory_signal_session.`);
|
|
278
280
|
const parent = await deps.sessions.getBySessionId(scope.sessionId);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"session-tools.js","names":[],"sources":["../../src/tools/session-tools.ts"],"sourcesContent":["import { RequestContext } from '@mastra/core/request-context';\nimport { createTool } from '@mastra/core/tools';\nimport { z } from 'zod';\n\nimport { boardForWorkItem } from '../boards/index.js';\nimport type { BoardRegistry } from '../boards/registry.js';\nimport type { IntegrationTools } from '../integrations/base.js';\nimport { factorySessionUrl, factoryWorkItemUrl } from '../links.js';\nimport { buildModelCatalog, listSessionScopedCredentials } from '../routes/config.js';\nimport { USER_SESSION_BRANCH_PREFIX } from '../routes/source-control-sessions.js';\nimport { primeTenantCredentialsForTenant } from '../routes/tenant-credentials.js';\nimport { FactoryStartTransitionError, WorkItemRepositoryError } from '../rules/start-coordinator.js';\nimport type { FactoryStartCoordinator } from '../rules/start-coordinator.js';\nimport { resolveFactoryModelPolicy } from '../session/credential-policy.js';\nimport type { SourceControlSessionLookup } from '../session/factory-session.js';\nimport {\n ensureFactorySourceSession,\n hydrateFactorySession,\n resolveFactorySessionModel,\n} from '../session/factory-session.js';\nimport { recordSessionRunStart } from '../session/run-audit.js';\nimport { resolveWorkItemRepository } from '../session/work-item-repository.js';\nimport type { AuditRecorder } from '../storage/domains/audit/domain.js';\nimport type { ModelCredentialsStorage } from '../storage/domains/credentials/base.js';\nimport type { CustomProvidersStorage } from '../storage/domains/custom-providers/base.js';\nimport type { IntakeStorage } from '../storage/domains/intake/base.js';\nimport type { ModelDefaultsStorage } from '../storage/domains/model-defaults/base.js';\nimport { effectiveModelScope } from '../storage/domains/projects/base.js';\nimport type { FactoryProjectsStorage } from '../storage/domains/projects/base.js';\nimport type { SourceControlStorageHandle } from '../storage/domains/source-control/base.js';\nimport type { WorkItemRow, WorkItemsStorage } from '../storage/domains/work-items/base.js';\nimport { deliverFactorySessionNotification, resolveSessionThread } from './deliver.js';\nimport type { FactoryMessaging } from './messaging-tools.js';\nimport { findWorkItem, workItemNotFound, workItemNumber, workItemRefSchema } from './read-tools.js';\nimport { heartbeatOpenRunUntilEnd } from './run-watch.js';\nimport type { FactoryToolScope } from './scope.js';\nimport { sessionModel } from './side-sessions.js';\n\nconst TITLE_LENGTH = 120;\n\n/** Who renews the open-run entries this process writes; one id per process, like the dispatcher's. */\nexport const FACTORY_TOOLS_OWNER_ID = `factory-tools:${globalThis.crypto.randomUUID()}`;\n\nexport interface FactorySessionToolDependencies {\n sessions: Pick<SourceControlSessionLookup, 'getBySessionId' | 'getSourceControlBySessionId'>;\n sessionModel: {\n projects: FactoryProjectsStorage;\n modelDefaults: ModelDefaultsStorage;\n /**\n * Tenant credential stores, present when auth is on. Model switches then\n * check the target session's credential scope, like the Settings picker;\n * without them the server's own keys decide.\n */\n tenantCatalog?: {\n credentials: Pick<ModelCredentialsStorage, 'listCredentials'>;\n customProviders?: Pick<CustomProvidersStorage, 'ensureReady' | 'list'>;\n deploymentProviders?: ReadonlySet<string>;\n };\n };\n /** Resolved lazily: the controller only exists once the mount is up. */\n messaging: () => Promise<FactoryMessaging | null>;\n workItems: Pick<\n WorkItemsStorage,\n | 'list'\n | 'getForProject'\n | 'listRunBindings'\n | 'findActiveRunBindingForSession'\n | 'findRunBindingByThread'\n | 'hasRunBindingForSession'\n | 'subscribeToWorkItem'\n | 'unsubscribeFromWorkItem'\n | 'listSessionSubscriptions'\n | 'listWorkItemSubscribers'\n >;\n boards: BoardRegistry;\n auditRecorder: AuditRecorder;\n intake?: Pick<IntakeStorage, 'getConfig'>;\n /** The browser Start's coordinator; absent until the Factory runtime is ready. */\n startCoordinator: () => Pick<FactoryStartCoordinator, 'prepare'> | undefined;\n}\n\nconst LISTED_MODELS = 8;\n\nfunction ambiguousRepository(candidates: readonly string[]): string {\n return `This item has several repositories (${candidates.join(', ')}); v1 can't choose one.`;\n}\n\nfunction startErrorMessage(error: unknown): string | null {\n if (error instanceof WorkItemRepositoryError) {\n return error.code === 'repository_ambiguous' ? ambiguousRepository(error.candidates) : error.message;\n }\n if (error instanceof FactoryStartTransitionError) return `The start was refused: ${error.result.reason}`;\n return null;\n}\n\nfunction workItemLabel(item: WorkItemRow): string {\n const number = workItemNumber(item);\n return number === null ? `\"${item.title}\"` : `#${number}`;\n}\n\nfunction titleFrom(prompt: string): string {\n const firstLine = prompt.split('\\n').find(line => line.trim()) ?? prompt;\n return firstLine.trim().slice(0, TITLE_LENGTH);\n}\n\n/** Tools that start sessions on the caller's behalf, or switch their models. User sessions only. */\nexport function createFactorySessionTools(\n scope: FactoryToolScope,\n deps: FactorySessionToolDependencies,\n): IntegrationTools {\n /** The models a session can switch to, resolved from the target session's owner and project policy. */\n async function sessionModelCatalog(\n controller: FactoryMessaging['controller'],\n sessionId: string,\n threadId: string,\n resourceId: string,\n ): Promise<{ usable: string[]; known: Set<string>; scopeLabel: string }> {\n const models = await controller.listAvailableModels();\n const known = new Set(models.flatMap(model => (typeof model.id === 'string' ? [model.id] : [])));\n const tenantCatalog = deps.sessionModel.tenantCatalog;\n if (!tenantCatalog) {\n const usable = (await buildModelCatalog({ controller })).map(model => model.id);\n return { usable, known, scopeLabel: 'server' };\n }\n const requestContext = new RequestContext();\n requestContext.set('user', { id: scope.userId, organizationId: scope.orgId });\n requestContext.set('controller', { sessionId, resourceId, threadId });\n const policy = await resolveFactoryModelPolicy(requestContext, {\n projects: deps.sessionModel.projects,\n sourceControl: deps.sessions,\n workItems: deps.workItems,\n });\n if (!policy) throw new Error('Session model policy is unavailable.');\n const modelScope = policy.tenant.credentialScope ?? 'user';\n const orgId = policy.tenant.orgId ?? scope.orgId;\n const customProviders = tenantCatalog.customProviders;\n const usable = (\n await buildModelCatalog({\n controller,\n tenantCredentials: await listSessionScopedCredentials({\n credentials: tenantCatalog.credentials,\n orgId,\n userId: policy.tenant.userId,\n modelScope,\n }),\n deploymentProviders: tenantCatalog.deploymentProviders,\n listCustomProviders: customProviders\n ? async () => {\n await customProviders.ensureReady();\n return customProviders.list({ orgId });\n }\n : undefined,\n })\n ).map(model => model.id);\n for (const id of usable) known.add(id);\n return { usable, known, scopeLabel: modelScope === 'factory' ? 'Factory' : 'session owner' };\n }\n\n function unrunnableModelError(\n modelId: string,\n catalog: { usable: string[]; known: Set<string>; scopeLabel: string },\n ) {\n const options = catalog.usable.length\n ? ` Models available to it: ${catalog.usable.slice(0, LISTED_MODELS).join(', ')}${catalog.usable.length > LISTED_MODELS ? ', …' : ''}.`\n : ' No models are available to it; connect a provider credential first.';\n return new Error(\n catalog.known.has(modelId)\n ? `Model ${modelId} exists, but this session's credential scope (${catalog.scopeLabel}) has no credential for its provider.${options}`\n : `Unknown model ${modelId}.${options}`,\n );\n }\n\n const switchModel = createTool({\n id: 'factory_switch_session_model',\n description:\n 'Look up or switch the model of a session you own in this Factory (side, work item, or review session). When someone describes a model by purpose, family, or preference rather than an exact ID, call with sessionId alone first to list models the target session can actually use. Interpret their intent against that list, then call with the chosen exact modelId to switch; do not use their words as a guessed model ID. A running session switches immediately; a stopped one uses the model on its next run. User-scoped sessions use their owner credentials; Factory-scoped sessions use Factory credentials. Use a session ID from the Factory session or work item tools.',\n inputSchema: z\n .object({\n sessionId: z.string().trim().min(1).max(200),\n modelId: z.string().trim().min(1).max(200).optional().describe('Omit to list usable models without switching.'),\n })\n .strict(),\n execute: async ({ sessionId, modelId }) => {\n const row = await deps.sessions.getBySessionId(sessionId);\n if (\n !row ||\n row.orgId !== scope.orgId ||\n row.factoryProjectId !== scope.factoryProjectId ||\n row.userId !== scope.userId\n ) {\n throw new Error('Session not found or not owned by you in this Factory.');\n }\n // A turn nobody signed in started reaches only this session and the side sessions it started.\n if (!scope.interactive && sessionId !== scope.sessionId && row.originSessionId !== scope.sessionId) {\n throw new Error(\n 'Without a person in this turn, only this session and the side sessions it started can switch models.',\n );\n }\n const messaging = await deps.messaging();\n if (!messaging) throw new Error('Session model switching is not available on this server.');\n const threadId = await resolveSessionThread({\n controller: messaging.controller,\n sessions: deps.sessions,\n workItems: deps.workItems,\n sessionId,\n });\n if (!threadId) throw new Error('Session has no conversation thread yet.');\n // The thread's resource, not the session id: sessions share their Factory's or owner's resource.\n const resourceId = (await messaging.controller.queryThreadById({ threadId }))?.resourceId ?? sessionId;\n const catalog = await sessionModelCatalog(messaging.controller, sessionId, threadId, resourceId);\n if (modelId === undefined) return { sessionId, models: catalog.usable };\n if (!catalog.usable.includes(modelId)) throw unrunnableModelError(modelId, catalog);\n const { live } = await messaging.controller.setThreadModel({ resourceId, threadId, modelId });\n return { sessionId, threadId, modelId, live };\n },\n });\n\n const start = createTool({\n id: 'factory_start_session',\n description: [\n 'Start a side session in this Factory with a prompt. It runs on its own sandbox and branch as you, and reports back to this session with `factory-session` notifications.',\n 'A side session uses this session’s model. Pass `model` to start it on another model the session credentials can run.',\n 'Use it for self-contained investigations; when the result should land as a pull request, file a work item instead.',\n 'With `workItem` and `role` it starts that role on the work item instead, without moving the card, and this session follows the item.',\n \"A role that already has a session on the item (current or past) can't be started again from here: message that session with factory_signal_session, or ask the person to start it from a signed-in chat.\",\n ].join(' '),\n inputSchema: z\n .object({\n prompt: z.string().trim().min(1).max(8000).describe('The first message the new session receives.'),\n title: z.string().trim().min(1).max(TITLE_LENGTH).optional(),\n model: z\n .string()\n .trim()\n .min(1)\n .max(200)\n .optional()\n .describe(\n 'Model id for a side session. Omit it to inherit this session’s model. The session credentials must be able to run it.',\n ),\n workItem: workItemRefSchema.optional(),\n role: z.string().trim().min(1).max(64).optional(),\n })\n .strict()\n .refine(input => input.role === undefined || input.workItem !== undefined, {\n message: 'Pass workItem together with role.',\n path: ['role'],\n }),\n execute: async ({ prompt, title, model, workItem, role }) => {\n if (workItem !== undefined) {\n // A role start records a run as the person, so it waits for a turn the person started.\n if (!scope.interactive) {\n throw new Error(\n 'Starting a role on a work item needs a person in this turn; start a side session, or ask the person to ask for it in a signed-in chat.',\n );\n }\n return startWorkItemRole({ prompt, title, workItem, role });\n }\n\n const parent = await deps.sessions.getBySessionId(scope.sessionId);\n const sourceControl = await deps.sessions.getSourceControlBySessionId(scope.sessionId);\n if (!parent || !sourceControl) throw new Error('This session has no Factory session row to start from.');\n const messaging = await deps.messaging();\n if (!messaging) throw new Error('Starting sessions is not available on this server.');\n\n // The child runs with the same credentials as this session, so validate against those.\n const parentThreadId = await resolveSessionThread({\n controller: messaging.controller,\n sessions: deps.sessions,\n workItems: deps.workItems,\n sessionId: scope.sessionId,\n });\n const parentResourceId = parentThreadId\n ? ((await messaging.controller.queryThreadById({ threadId: parentThreadId }))?.resourceId ?? scope.sessionId)\n : scope.sessionId;\n const catalog = await sessionModelCatalog(\n messaging.controller,\n scope.sessionId,\n parentThreadId ?? scope.threadId,\n parentResourceId,\n );\n const inherited = model\n ? null\n : await sessionModel(messaging.controller, deps.sessions, deps.workItems, scope.sessionId);\n const requestedModel = model ?? (inherited && catalog.usable.includes(inherited) ? inherited : undefined);\n if (requestedModel && !catalog.usable.includes(requestedModel))\n throw unrunnableModelError(requestedModel, catalog);\n\n const sessionId = globalThis.crypto.randomUUID();\n const ensured = await ensureFactorySourceSession({\n sourceControl,\n orgId: scope.orgId,\n factoryProjectId: scope.factoryProjectId,\n sessionId,\n branch: `${USER_SESSION_BRANCH_PREFIX}${sessionId}`,\n // Bills the caller: the credential tenant follows the row's user.\n attributeToUserId: scope.userId,\n // Same repository as the session that started it.\n ...(parent.projectRepositoryId ? { projectRepositoryId: parent.projectRepositoryId } : {}),\n visibility: parent.visibility,\n origin: { sessionId: scope.sessionId, threadId: scope.threadId },\n });\n const resolvedModel = await resolveFactorySessionModel({\n ...deps.sessionModel,\n factoryProjectId: scope.factoryProjectId,\n orgId: scope.orgId,\n ownerUserId: scope.userId,\n // No work item, so an interactive session: a hybrid Factory bills it as one.\n context: 'session',\n });\n\n // Only the new row's owner as `user`. The tool call's context carries the\n // interactive marker and the parent's controller entry; neither may reach the child.\n const kickoffContext = new RequestContext();\n kickoffContext.set('user', { workosId: scope.userId, organizationId: scope.orgId });\n\n const tags = { factoryProjectId: scope.factoryProjectId, projectRepositoryId: ensured.projectRepositoryId };\n const session = await messaging.controller.createSession({\n id: ensured.sessionId,\n ownerId: scope.userId,\n // A side session works for the Factory, so it shares the Factory's memory\n // resource; a private one stays with its owner, like a Slack DM.\n resourceId: parent.visibility === 'private' ? scope.userId : scope.factoryProjectId,\n threadId: ensured.sessionId,\n requestContext: kickoffContext,\n tags,\n });\n await session.state.set(tags);\n await hydrateFactorySession(session, {\n orgId: scope.orgId,\n modelScope: resolvedModel.modelScope,\n ownerUserId: scope.userId,\n defaultModelId: requestedModel ?? resolvedModel.modelId,\n });\n\n const threadId = session.thread.requireId();\n const threadTitle = title ?? titleFrom(prompt);\n await session.thread.rename({ title: threadTitle, pin: false });\n // On the row too, so its run-end reports name it without waiting for the title mirror.\n await sourceControl.sessions.rename({ sessionId: ensured.sessionId, title: threadTitle });\n await session.thread.setSetting({ key: 'factorySessionId', value: ensured.sessionId });\n\n await primeTenantCredentialsForTenant({\n orgId: scope.orgId,\n userId: scope.userId,\n credentialScope: resolvedModel.modelScope,\n });\n // How its runs end reaches this session through the listener every Factory\n // session gets (`observeSessionRunReports`), which follows the row's origin.\n // `requireDelivery` makes `accepted` reject when the wake fails; the run itself is not awaited.\n await session.sendSignal(\n { id: globalThis.crypto.randomUUID(), type: 'user', tagName: 'user', contents: prompt },\n { requestContext: kickoffContext, requireDelivery: true },\n ).accepted;\n\n return {\n mode: 'side' as const,\n sessionId: ensured.sessionId,\n threadId,\n title: threadTitle,\n url:\n factorySessionUrl({ factoryProjectId: scope.factoryProjectId, sessionId: ensured.sessionId, threadId }) ??\n null,\n };\n },\n });\n\n async function startWorkItemRole({\n prompt,\n title,\n workItem,\n role,\n }: {\n prompt: string;\n title?: string;\n workItem: string;\n role?: string;\n }) {\n if (!role) throw new Error('Pass the role to start on the work item.');\n const coordinator = deps.startCoordinator();\n if (!coordinator) throw new Error(\"Factory sessions can't be started yet; try again shortly.\");\n const item = await findWorkItem(deps.workItems, scope, workItem);\n if (!item) throw workItemNotFound(workItem);\n const label = workItemLabel(item);\n const board = deps.boards.get(boardForWorkItem(item));\n if (!board?.phaseForRole(role)) throw new Error(`${label}'s board has no ${role} role.`);\n const seated = item.sessions[role];\n if (seated) {\n throw new Error(\n `${label} already has a ${role} session ${seated.sessionId}; message it with factory_signal_session.`,\n );\n }\n\n const parent = await deps.sessions.getBySessionId(scope.sessionId);\n const sourceControl = await deps.sessions.getSourceControlBySessionId(scope.sessionId);\n if (!parent || !sourceControl) throw new Error('This session has no Factory session row to start from.');\n const messaging = await deps.messaging();\n if (!messaging) throw new Error('Starting sessions is not available on this server.');\n const project = await deps.sessionModel.projects.get({ orgId: scope.orgId, id: scope.factoryProjectId });\n if (!project) throw new Error('This Factory no longer exists.');\n // A work-item start is a run, so a hybrid Factory uses the Factory's scope (as the Start route does).\n const modelScope = effectiveModelScope(project.modelScope, 'run');\n const projectRepositoryId = await resolveRepository(sourceControl, item);\n\n const sessionId = globalThis.crypto.randomUUID();\n const ensured = await ensureFactorySourceSession({\n sourceControl,\n orgId: scope.orgId,\n factoryProjectId: scope.factoryProjectId,\n sessionId,\n branch: `${USER_SESSION_BRANCH_PREFIX}${sessionId}`,\n projectRepositoryId,\n attributeToUserId: scope.userId,\n // A run works a shared card, so the org can open it and answer its approvals even when the session that\n // started it is private.\n visibility: 'org',\n });\n\n // Follow first, so a fast run's first report already has somewhere to go.\n const followScope = { orgId: scope.orgId, factoryProjectId: scope.factoryProjectId };\n const alreadyFollowing = (\n await deps.workItems.listSessionSubscriptions({ ...followScope, sessionId: scope.sessionId })\n ).some(subscription => subscription.workItemId === item.id);\n await deps.workItems.subscribeToWorkItem({\n ...followScope,\n workItemId: item.id,\n sessionId: scope.sessionId,\n threadId: scope.threadId,\n resourceId: scope.resourceId,\n userId: scope.userId,\n reason: 'started',\n });\n\n const startedAt = new Date();\n let prepared;\n try {\n prepared = await coordinator.prepare({\n orgId: scope.orgId,\n userId: scope.userId,\n factoryProjectId: scope.factoryProjectId,\n sessionId: ensured.sessionId,\n threadTitle: title ?? `${label} ${role}`,\n kickoffKey: globalThis.crypto.randomUUID(),\n modelScope,\n defaultModelId: modelScope === 'factory' ? (project.defaultModelId ?? undefined) : undefined,\n workItem: {\n id: item.id,\n role,\n input: {\n externalSource: item.externalSource,\n parentWorkItemId: item.parentWorkItemId,\n title: item.title,\n stages: item.stages,\n sessions: item.sessions,\n metadata: item.metadata,\n },\n },\n });\n } catch (error) {\n if (!alreadyFollowing) {\n await deps.workItems.unsubscribeFromWorkItem({\n orgId: scope.orgId,\n workItemId: item.id,\n sessionId: scope.sessionId,\n });\n }\n const message = startErrorMessage(error);\n if (message) throw new Error(message);\n throw error;\n }\n\n const bindings = await deps.workItems.listRunBindings(scope.orgId, scope.factoryProjectId, item.id);\n const replaced = bindings.find(\n binding =>\n binding.role === role &&\n binding.id !== prepared.bindingId &&\n binding.revokedAt !== null &&\n binding.revokedAt >= startedAt,\n );\n\n const session = await messaging.controller.getSession(prepared.sessionId);\n if (!session) {\n throw new Error(\n `The ${role} session ${prepared.sessionId} was bound but is not running; message it with factory_signal_session to wake it.`,\n );\n }\n const kickoffId = globalThis.crypto.randomUUID();\n // Heartbeat from before the kickoff so a fast run's end is seen; the open-run\n // entry and audit follow the accepted kickoff, as the dispatcher records them.\n // The run's end reaches this item's followers through the session's listener.\n const heartbeat = heartbeatOpenRunUntilEnd(session, kickoffId);\n const kickoffContext = new RequestContext();\n kickoffContext.set('user', { workosId: scope.userId, organizationId: scope.orgId });\n try {\n await session.sendSignal(\n { id: kickoffId, type: 'user', tagName: 'user', contents: prompt },\n { requestContext: kickoffContext, requireDelivery: true },\n ).accepted;\n } catch (error) {\n heartbeat.stop();\n throw error;\n }\n\n await recordSessionRunStart(session, {\n audit: deps.auditRecorder,\n actorType: 'human',\n observedEnd: heartbeat.endReason,\n run: {\n kickoffId,\n ownerId: FACTORY_TOOLS_OWNER_ID,\n heartbeatAt: Date.now(),\n bindingId: prepared.bindingId,\n role,\n startedBy: scope.userId,\n orgId: scope.orgId,\n factoryProjectId: scope.factoryProjectId,\n workItemId: item.id,\n workItemName: item.title,\n sessionId: prepared.sessionId,\n threadId: prepared.threadId,\n branch: prepared.branch,\n },\n });\n\n const number = workItemNumber(item);\n return {\n mode: 'work-item' as const,\n workItem: {\n id: item.id,\n ...(number === null ? {} : { number }),\n url:\n factoryWorkItemUrl({\n factoryProjectId: scope.factoryProjectId,\n board: boardForWorkItem(item),\n workItemId: item.id,\n }) ?? null,\n },\n role,\n sessionId: prepared.sessionId,\n threadId: prepared.threadId,\n url:\n factorySessionUrl({\n factoryProjectId: scope.factoryProjectId,\n sessionId: prepared.sessionId,\n threadId: prepared.threadId,\n }) ?? null,\n bindingId: prepared.bindingId,\n ...(replaced ? { replacedSessionId: replaced.sessionId } : {}),\n };\n }\n\n async function resolveRepository(sourceControl: SourceControlStorageHandle, item: WorkItemRow): Promise<string> {\n const intakeConfig = await deps.intake?.getConfig({ orgId: scope.orgId, integrationIds: ['linear'] });\n const repository = await resolveWorkItemRepository({\n sourceControl,\n orgId: scope.orgId,\n factoryProjectId: scope.factoryProjectId,\n item,\n linearRepositoryMap: intakeConfig?.linear?.repositoryByLinearProject,\n });\n if (repository.status === 'ambiguous') {\n throw new Error(ambiguousRepository(repository.candidates));\n }\n if (repository.status === 'unlinked') throw new Error(repository.hint);\n return repository.projectRepositoryId;\n }\n\n return { factory_start_session: start, factory_switch_session_model: switchModel };\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"session-tools.js","names":[],"sources":["../../src/tools/session-tools.ts"],"sourcesContent":["import { RequestContext } from '@mastra/core/request-context';\nimport { createTool } from '@mastra/core/tools';\nimport { z } from 'zod';\n\nimport { boardForWorkItem } from '../boards/index.js';\nimport { workLaneForRole } from '../boards/legacy-plan-role.js';\nimport type { BoardRegistry } from '../boards/registry.js';\nimport type { IntegrationTools } from '../integrations/base.js';\nimport { factorySessionUrl, factoryWorkItemUrl } from '../links.js';\nimport { buildModelCatalog, listSessionScopedCredentials } from '../routes/config.js';\nimport { USER_SESSION_BRANCH_PREFIX } from '../routes/source-control-sessions.js';\nimport { primeTenantCredentialsForTenant } from '../routes/tenant-credentials.js';\nimport { FactoryStartTransitionError, WorkItemRepositoryError } from '../rules/start-coordinator.js';\nimport type { FactoryStartCoordinator } from '../rules/start-coordinator.js';\nimport { resolveFactoryModelPolicy } from '../session/credential-policy.js';\nimport type { SourceControlSessionLookup } from '../session/factory-session.js';\nimport {\n ensureFactorySourceSession,\n hydrateFactorySession,\n resolveFactorySessionModel,\n} from '../session/factory-session.js';\nimport { recordSessionRunStart } from '../session/run-audit.js';\nimport { resolveWorkItemRepository } from '../session/work-item-repository.js';\nimport type { AuditRecorder } from '../storage/domains/audit/domain.js';\nimport type { ModelCredentialsStorage } from '../storage/domains/credentials/base.js';\nimport type { CustomProvidersStorage } from '../storage/domains/custom-providers/base.js';\nimport type { IntakeStorage } from '../storage/domains/intake/base.js';\nimport type { ModelDefaultsStorage } from '../storage/domains/model-defaults/base.js';\nimport { effectiveModelScope } from '../storage/domains/projects/base.js';\nimport type { FactoryProjectsStorage } from '../storage/domains/projects/base.js';\nimport type { SourceControlStorageHandle } from '../storage/domains/source-control/base.js';\nimport type { WorkItemRow, WorkItemsStorage } from '../storage/domains/work-items/base.js';\nimport { deliverFactorySessionNotification, resolveSessionThread } from './deliver.js';\nimport type { FactoryMessaging } from './messaging-tools.js';\nimport { findWorkItem, workItemNotFound, workItemNumber, workItemRefSchema } from './read-tools.js';\nimport { heartbeatOpenRunUntilEnd } from './run-watch.js';\nimport type { FactoryToolScope } from './scope.js';\nimport { sessionModel } from './side-sessions.js';\n\nconst TITLE_LENGTH = 120;\n\n/** Who renews the open-run entries this process writes; one id per process, like the dispatcher's. */\nexport const FACTORY_TOOLS_OWNER_ID = `factory-tools:${globalThis.crypto.randomUUID()}`;\n\nexport interface FactorySessionToolDependencies {\n sessions: Pick<SourceControlSessionLookup, 'getBySessionId' | 'getSourceControlBySessionId'>;\n sessionModel: {\n projects: FactoryProjectsStorage;\n modelDefaults: ModelDefaultsStorage;\n /**\n * Tenant credential stores, present when auth is on. Model switches then\n * check the target session's credential scope, like the Settings picker;\n * without them the server's own keys decide.\n */\n tenantCatalog?: {\n credentials: Pick<ModelCredentialsStorage, 'listCredentials'>;\n customProviders?: Pick<CustomProvidersStorage, 'ensureReady' | 'list'>;\n deploymentProviders?: ReadonlySet<string>;\n };\n };\n /** Resolved lazily: the controller only exists once the mount is up. */\n messaging: () => Promise<FactoryMessaging | null>;\n workItems: Pick<\n WorkItemsStorage,\n | 'list'\n | 'getForProject'\n | 'listRunBindings'\n | 'findActiveRunBindingForSession'\n | 'findRunBindingByThread'\n | 'hasRunBindingForSession'\n | 'subscribeToWorkItem'\n | 'unsubscribeFromWorkItem'\n | 'listSessionSubscriptions'\n | 'listWorkItemSubscribers'\n >;\n boards: BoardRegistry;\n auditRecorder: AuditRecorder;\n intake?: Pick<IntakeStorage, 'getConfig'>;\n /** The browser Start's coordinator; absent until the Factory runtime is ready. */\n startCoordinator: () => Pick<FactoryStartCoordinator, 'prepare'> | undefined;\n}\n\nconst LISTED_MODELS = 8;\n\nfunction ambiguousRepository(candidates: readonly string[]): string {\n return `This item has several repositories (${candidates.join(', ')}); v1 can't choose one.`;\n}\n\nfunction startErrorMessage(error: unknown): string | null {\n if (error instanceof WorkItemRepositoryError) {\n return error.code === 'repository_ambiguous' ? ambiguousRepository(error.candidates) : error.message;\n }\n if (error instanceof FactoryStartTransitionError) return `The start was refused: ${error.result.reason}`;\n return null;\n}\n\nfunction workItemLabel(item: WorkItemRow): string {\n const number = workItemNumber(item);\n return number === null ? `\"${item.title}\"` : `#${number}`;\n}\n\nfunction titleFrom(prompt: string): string {\n const firstLine = prompt.split('\\n').find(line => line.trim()) ?? prompt;\n return firstLine.trim().slice(0, TITLE_LENGTH);\n}\n\n/** Tools that start sessions on the caller's behalf, or switch their models. User sessions only. */\nexport function createFactorySessionTools(\n scope: FactoryToolScope,\n deps: FactorySessionToolDependencies,\n): IntegrationTools {\n /** The models a session can switch to, resolved from the target session's owner and project policy. */\n async function sessionModelCatalog(\n controller: FactoryMessaging['controller'],\n sessionId: string,\n threadId: string,\n resourceId: string,\n ): Promise<{ usable: string[]; known: Set<string>; scopeLabel: string }> {\n const models = await controller.listAvailableModels();\n const known = new Set(models.flatMap(model => (typeof model.id === 'string' ? [model.id] : [])));\n const tenantCatalog = deps.sessionModel.tenantCatalog;\n if (!tenantCatalog) {\n const usable = (await buildModelCatalog({ controller })).map(model => model.id);\n return { usable, known, scopeLabel: 'server' };\n }\n const requestContext = new RequestContext();\n requestContext.set('user', { id: scope.userId, organizationId: scope.orgId });\n requestContext.set('controller', { sessionId, resourceId, threadId });\n const policy = await resolveFactoryModelPolicy(requestContext, {\n projects: deps.sessionModel.projects,\n sourceControl: deps.sessions,\n workItems: deps.workItems,\n });\n if (!policy) throw new Error('Session model policy is unavailable.');\n const modelScope = policy.tenant.credentialScope ?? 'user';\n const orgId = policy.tenant.orgId ?? scope.orgId;\n const customProviders = tenantCatalog.customProviders;\n const usable = (\n await buildModelCatalog({\n controller,\n tenantCredentials: await listSessionScopedCredentials({\n credentials: tenantCatalog.credentials,\n orgId,\n userId: policy.tenant.userId,\n modelScope,\n }),\n deploymentProviders: tenantCatalog.deploymentProviders,\n listCustomProviders: customProviders\n ? async () => {\n await customProviders.ensureReady();\n return customProviders.list({ orgId });\n }\n : undefined,\n })\n ).map(model => model.id);\n for (const id of usable) known.add(id);\n return { usable, known, scopeLabel: modelScope === 'factory' ? 'Factory' : 'session owner' };\n }\n\n function unrunnableModelError(\n modelId: string,\n catalog: { usable: string[]; known: Set<string>; scopeLabel: string },\n ) {\n const options = catalog.usable.length\n ? ` Models available to it: ${catalog.usable.slice(0, LISTED_MODELS).join(', ')}${catalog.usable.length > LISTED_MODELS ? ', …' : ''}.`\n : ' No models are available to it; connect a provider credential first.';\n return new Error(\n catalog.known.has(modelId)\n ? `Model ${modelId} exists, but this session's credential scope (${catalog.scopeLabel}) has no credential for its provider.${options}`\n : `Unknown model ${modelId}.${options}`,\n );\n }\n\n const switchModel = createTool({\n id: 'factory_switch_session_model',\n description:\n 'Look up or switch the model of a session you own in this Factory (side, work item, or review session). When someone describes a model by purpose, family, or preference rather than an exact ID, call with sessionId alone first to list models the target session can actually use. Interpret their intent against that list, then call with the chosen exact modelId to switch; do not use their words as a guessed model ID. A running session switches immediately; a stopped one uses the model on its next run. User-scoped sessions use their owner credentials; Factory-scoped sessions use Factory credentials. Use a session ID from the Factory session or work item tools.',\n inputSchema: z\n .object({\n sessionId: z.string().trim().min(1).max(200),\n modelId: z.string().trim().min(1).max(200).optional().describe('Omit to list usable models without switching.'),\n })\n .strict(),\n execute: async ({ sessionId, modelId }) => {\n const row = await deps.sessions.getBySessionId(sessionId);\n if (\n !row ||\n row.orgId !== scope.orgId ||\n row.factoryProjectId !== scope.factoryProjectId ||\n row.userId !== scope.userId\n ) {\n throw new Error('Session not found or not owned by you in this Factory.');\n }\n // A turn nobody signed in started reaches only this session and the side sessions it started.\n if (!scope.interactive && sessionId !== scope.sessionId && row.originSessionId !== scope.sessionId) {\n throw new Error(\n 'Without a person in this turn, only this session and the side sessions it started can switch models.',\n );\n }\n const messaging = await deps.messaging();\n if (!messaging) throw new Error('Session model switching is not available on this server.');\n const threadId = await resolveSessionThread({\n controller: messaging.controller,\n sessions: deps.sessions,\n workItems: deps.workItems,\n sessionId,\n });\n if (!threadId) throw new Error('Session has no conversation thread yet.');\n // The thread's resource, not the session id: sessions share their Factory's or owner's resource.\n const resourceId = (await messaging.controller.queryThreadById({ threadId }))?.resourceId ?? sessionId;\n const catalog = await sessionModelCatalog(messaging.controller, sessionId, threadId, resourceId);\n if (modelId === undefined) return { sessionId, models: catalog.usable };\n if (!catalog.usable.includes(modelId)) throw unrunnableModelError(modelId, catalog);\n const { live } = await messaging.controller.setThreadModel({ resourceId, threadId, modelId });\n return { sessionId, threadId, modelId, live };\n },\n });\n\n const start = createTool({\n id: 'factory_start_session',\n description: [\n 'Start a side session in this Factory with a prompt. It runs on its own sandbox and branch as you, and reports back to this session with `factory-session` notifications.',\n 'A side session uses this session’s model. Pass `model` to start it on another model the session credentials can run.',\n 'Use it for self-contained investigations; when the result should land as a pull request, file a work item instead.',\n 'With `workItem` and `role` it starts that role on the work item instead, without moving the card, and this session follows the item.',\n \"A role that already has a session on the item (current or past) can't be started again from here: message that session with factory_signal_session, or ask the person to start it from a signed-in chat.\",\n ].join(' '),\n inputSchema: z\n .object({\n prompt: z.string().trim().min(1).max(8000).describe('The first message the new session receives.'),\n title: z.string().trim().min(1).max(TITLE_LENGTH).optional(),\n model: z\n .string()\n .trim()\n .min(1)\n .max(200)\n .optional()\n .describe(\n 'Model id for a side session. Omit it to inherit this session’s model. The session credentials must be able to run it.',\n ),\n workItem: workItemRefSchema.optional(),\n role: z.string().trim().min(1).max(64).optional(),\n })\n .strict()\n .refine(input => input.role === undefined || input.workItem !== undefined, {\n message: 'Pass workItem together with role.',\n path: ['role'],\n }),\n execute: async ({ prompt, title, model, workItem, role }) => {\n if (workItem !== undefined) {\n // A role start records a run as the person, so it waits for a turn the person started.\n if (!scope.interactive) {\n throw new Error(\n 'Starting a role on a work item needs a person in this turn; start a side session, or ask the person to ask for it in a signed-in chat.',\n );\n }\n return startWorkItemRole({ prompt, title, workItem, role });\n }\n\n const parent = await deps.sessions.getBySessionId(scope.sessionId);\n const sourceControl = await deps.sessions.getSourceControlBySessionId(scope.sessionId);\n if (!parent || !sourceControl) throw new Error('This session has no Factory session row to start from.');\n const messaging = await deps.messaging();\n if (!messaging) throw new Error('Starting sessions is not available on this server.');\n\n // The child runs with the same credentials as this session, so validate against those.\n const parentThreadId = await resolveSessionThread({\n controller: messaging.controller,\n sessions: deps.sessions,\n workItems: deps.workItems,\n sessionId: scope.sessionId,\n });\n const parentResourceId = parentThreadId\n ? ((await messaging.controller.queryThreadById({ threadId: parentThreadId }))?.resourceId ?? scope.sessionId)\n : scope.sessionId;\n const catalog = await sessionModelCatalog(\n messaging.controller,\n scope.sessionId,\n parentThreadId ?? scope.threadId,\n parentResourceId,\n );\n const inherited = model\n ? null\n : await sessionModel(messaging.controller, deps.sessions, deps.workItems, scope.sessionId);\n const requestedModel = model ?? (inherited && catalog.usable.includes(inherited) ? inherited : undefined);\n if (requestedModel && !catalog.usable.includes(requestedModel))\n throw unrunnableModelError(requestedModel, catalog);\n\n const sessionId = globalThis.crypto.randomUUID();\n const ensured = await ensureFactorySourceSession({\n sourceControl,\n orgId: scope.orgId,\n factoryProjectId: scope.factoryProjectId,\n sessionId,\n branch: `${USER_SESSION_BRANCH_PREFIX}${sessionId}`,\n // Bills the caller: the credential tenant follows the row's user.\n attributeToUserId: scope.userId,\n // Same repository as the session that started it.\n ...(parent.projectRepositoryId ? { projectRepositoryId: parent.projectRepositoryId } : {}),\n visibility: parent.visibility,\n origin: { sessionId: scope.sessionId, threadId: scope.threadId },\n });\n const resolvedModel = await resolveFactorySessionModel({\n ...deps.sessionModel,\n factoryProjectId: scope.factoryProjectId,\n orgId: scope.orgId,\n ownerUserId: scope.userId,\n // No work item, so an interactive session: a hybrid Factory bills it as one.\n context: 'session',\n });\n\n // Only the new row's owner as `user`. The tool call's context carries the\n // interactive marker and the parent's controller entry; neither may reach the child.\n const kickoffContext = new RequestContext();\n kickoffContext.set('user', { workosId: scope.userId, organizationId: scope.orgId });\n\n const tags = { factoryProjectId: scope.factoryProjectId, projectRepositoryId: ensured.projectRepositoryId };\n const session = await messaging.controller.createSession({\n id: ensured.sessionId,\n ownerId: scope.userId,\n // A side session works for the Factory, so it shares the Factory's memory\n // resource; a private one stays with its owner, like a Slack DM.\n resourceId: parent.visibility === 'private' ? scope.userId : scope.factoryProjectId,\n threadId: ensured.sessionId,\n requestContext: kickoffContext,\n tags,\n });\n await session.state.set(tags);\n await hydrateFactorySession(session, {\n orgId: scope.orgId,\n modelScope: resolvedModel.modelScope,\n ownerUserId: scope.userId,\n defaultModelId: requestedModel ?? resolvedModel.modelId,\n });\n\n const threadId = session.thread.requireId();\n const threadTitle = title ?? titleFrom(prompt);\n await session.thread.rename({ title: threadTitle, pin: false });\n // On the row too, so its run-end reports name it without waiting for the title mirror.\n await sourceControl.sessions.rename({ sessionId: ensured.sessionId, title: threadTitle });\n await session.thread.setSetting({ key: 'factorySessionId', value: ensured.sessionId });\n\n await primeTenantCredentialsForTenant({\n orgId: scope.orgId,\n userId: scope.userId,\n credentialScope: resolvedModel.modelScope,\n });\n // How its runs end reaches this session through the listener every Factory\n // session gets (`observeSessionRunReports`), which follows the row's origin.\n // `requireDelivery` makes `accepted` reject when the wake fails; the run itself is not awaited.\n await session.sendSignal(\n { id: globalThis.crypto.randomUUID(), type: 'user', tagName: 'user', contents: prompt },\n { requestContext: kickoffContext, requireDelivery: true },\n ).accepted;\n\n return {\n mode: 'side' as const,\n sessionId: ensured.sessionId,\n threadId,\n title: threadTitle,\n url:\n factorySessionUrl({ factoryProjectId: scope.factoryProjectId, sessionId: ensured.sessionId, threadId }) ??\n null,\n };\n },\n });\n\n async function startWorkItemRole({\n prompt,\n title,\n workItem,\n role,\n }: {\n prompt: string;\n title?: string;\n workItem: string;\n role?: string;\n }) {\n if (!role) throw new Error('Pass the role to start on the work item.');\n const coordinator = deps.startCoordinator();\n if (!coordinator) throw new Error(\"Factory sessions can't be started yet; try again shortly.\");\n const item = await findWorkItem(deps.workItems, scope, workItem);\n if (!item) throw workItemNotFound(workItem);\n const label = workItemLabel(item);\n const board = deps.boards.get(boardForWorkItem(item));\n // Work's old `plan` role still names Planning, though no phase runs in a `plan` context any more.\n if (!workLaneForRole(board, role) && !board?.phaseForRole(role)) {\n throw new Error(`${label}'s board has no ${role} role.`);\n }\n const seated = item.sessions[role];\n if (seated) {\n throw new Error(\n `${label} already has a ${role} session ${seated.sessionId}; message it with factory_signal_session.`,\n );\n }\n\n const parent = await deps.sessions.getBySessionId(scope.sessionId);\n const sourceControl = await deps.sessions.getSourceControlBySessionId(scope.sessionId);\n if (!parent || !sourceControl) throw new Error('This session has no Factory session row to start from.');\n const messaging = await deps.messaging();\n if (!messaging) throw new Error('Starting sessions is not available on this server.');\n const project = await deps.sessionModel.projects.get({ orgId: scope.orgId, id: scope.factoryProjectId });\n if (!project) throw new Error('This Factory no longer exists.');\n // A work-item start is a run, so a hybrid Factory uses the Factory's scope (as the Start route does).\n const modelScope = effectiveModelScope(project.modelScope, 'run');\n const projectRepositoryId = await resolveRepository(sourceControl, item);\n\n const sessionId = globalThis.crypto.randomUUID();\n const ensured = await ensureFactorySourceSession({\n sourceControl,\n orgId: scope.orgId,\n factoryProjectId: scope.factoryProjectId,\n sessionId,\n branch: `${USER_SESSION_BRANCH_PREFIX}${sessionId}`,\n projectRepositoryId,\n attributeToUserId: scope.userId,\n // A run works a shared card, so the org can open it and answer its approvals even when the session that\n // started it is private.\n visibility: 'org',\n });\n\n // Follow first, so a fast run's first report already has somewhere to go.\n const followScope = { orgId: scope.orgId, factoryProjectId: scope.factoryProjectId };\n const alreadyFollowing = (\n await deps.workItems.listSessionSubscriptions({ ...followScope, sessionId: scope.sessionId })\n ).some(subscription => subscription.workItemId === item.id);\n await deps.workItems.subscribeToWorkItem({\n ...followScope,\n workItemId: item.id,\n sessionId: scope.sessionId,\n threadId: scope.threadId,\n resourceId: scope.resourceId,\n userId: scope.userId,\n reason: 'started',\n });\n\n const startedAt = new Date();\n let prepared;\n try {\n prepared = await coordinator.prepare({\n orgId: scope.orgId,\n userId: scope.userId,\n factoryProjectId: scope.factoryProjectId,\n sessionId: ensured.sessionId,\n threadTitle: title ?? `${label} ${role}`,\n kickoffKey: globalThis.crypto.randomUUID(),\n modelScope,\n defaultModelId: modelScope === 'factory' ? (project.defaultModelId ?? undefined) : undefined,\n workItem: {\n id: item.id,\n role,\n input: {\n externalSource: item.externalSource,\n parentWorkItemId: item.parentWorkItemId,\n title: item.title,\n stages: item.stages,\n sessions: item.sessions,\n metadata: item.metadata,\n },\n },\n });\n } catch (error) {\n if (!alreadyFollowing) {\n await deps.workItems.unsubscribeFromWorkItem({\n orgId: scope.orgId,\n workItemId: item.id,\n sessionId: scope.sessionId,\n });\n }\n const message = startErrorMessage(error);\n if (message) throw new Error(message);\n throw error;\n }\n\n const bindings = await deps.workItems.listRunBindings(scope.orgId, scope.factoryProjectId, item.id);\n const replaced = bindings.find(\n binding =>\n binding.role === role &&\n binding.id !== prepared.bindingId &&\n binding.revokedAt !== null &&\n binding.revokedAt >= startedAt,\n );\n\n const session = await messaging.controller.getSession(prepared.sessionId);\n if (!session) {\n throw new Error(\n `The ${role} session ${prepared.sessionId} was bound but is not running; message it with factory_signal_session to wake it.`,\n );\n }\n const kickoffId = globalThis.crypto.randomUUID();\n // Heartbeat from before the kickoff so a fast run's end is seen; the open-run\n // entry and audit follow the accepted kickoff, as the dispatcher records them.\n // The run's end reaches this item's followers through the session's listener.\n const heartbeat = heartbeatOpenRunUntilEnd(session, kickoffId);\n const kickoffContext = new RequestContext();\n kickoffContext.set('user', { workosId: scope.userId, organizationId: scope.orgId });\n try {\n await session.sendSignal(\n { id: kickoffId, type: 'user', tagName: 'user', contents: prompt },\n { requestContext: kickoffContext, requireDelivery: true },\n ).accepted;\n } catch (error) {\n heartbeat.stop();\n throw error;\n }\n\n await recordSessionRunStart(session, {\n audit: deps.auditRecorder,\n actorType: 'human',\n observedEnd: heartbeat.endReason,\n run: {\n kickoffId,\n ownerId: FACTORY_TOOLS_OWNER_ID,\n heartbeatAt: Date.now(),\n bindingId: prepared.bindingId,\n role,\n startedBy: scope.userId,\n orgId: scope.orgId,\n factoryProjectId: scope.factoryProjectId,\n workItemId: item.id,\n workItemName: item.title,\n sessionId: prepared.sessionId,\n threadId: prepared.threadId,\n branch: prepared.branch,\n },\n });\n\n const number = workItemNumber(item);\n return {\n mode: 'work-item' as const,\n workItem: {\n id: item.id,\n ...(number === null ? {} : { number }),\n url:\n factoryWorkItemUrl({\n factoryProjectId: scope.factoryProjectId,\n board: boardForWorkItem(item),\n workItemId: item.id,\n }) ?? null,\n },\n role,\n sessionId: prepared.sessionId,\n threadId: prepared.threadId,\n url:\n factorySessionUrl({\n factoryProjectId: scope.factoryProjectId,\n sessionId: prepared.sessionId,\n threadId: prepared.threadId,\n }) ?? null,\n bindingId: prepared.bindingId,\n ...(replaced ? { replacedSessionId: replaced.sessionId } : {}),\n };\n }\n\n async function resolveRepository(sourceControl: SourceControlStorageHandle, item: WorkItemRow): Promise<string> {\n const intakeConfig = await deps.intake?.getConfig({ orgId: scope.orgId, integrationIds: ['linear'] });\n const repository = await resolveWorkItemRepository({\n sourceControl,\n orgId: scope.orgId,\n factoryProjectId: scope.factoryProjectId,\n item,\n linearRepositoryMap: intakeConfig?.linear?.repositoryByLinearProject,\n });\n if (repository.status === 'ambiguous') {\n throw new Error(ambiguousRepository(repository.candidates));\n }\n if (repository.status === 'unlinked') throw new Error(repository.hint);\n return repository.projectRepositoryId;\n }\n\n return { factory_start_session: start, factory_switch_session_model: switchModel };\n}\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sessions-state-processor.d.ts","sourceRoot":"","sources":["../../src/tools/sessions-state-processor.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,4BAA4B,CAAC;AACvE,OAAO,KAAK,EAAE,sBAAsB,EAAE,wBAAwB,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAC;AAG3G,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAC3D,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,+BAA+B,CAAC;AAChF,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,uCAAuC,CAAC;AAE9E,OAAO,KAAK,EAAoB,8BAA8B,EAAE,MAAM,YAAY,CAAC;AAWnF,+FAA+F;AAC/F,eAAO,MAAM,2BAA2B,QAAsB,CAAC;AAI/D,8GAA8G;AAC9G,eAAO,MAAM,yBAAyB,QAAiB,CAAC;AACxD,0DAA0D;AAC1D,eAAO,MAAM,yBAAyB,KAAK,CAAC;AAG5C,YAAY,EAAE,sBAAsB,EAAE,MAAM,oBAAoB,CAAC;AAEjE,MAAM,WAAW,gCAAgC;IAC/C,WAAW,EAAE,OAAO,CAAC;IACrB,QAAQ,EAAE,IAAI,CAAC,0BAA0B,EAAE,gBAAgB,GAAG,cAAc,CAAC,CAAC;IAC9E,QAAQ,EAAE,8BAA8B,CAAC,UAAU,CAAC,CAAC;IACrD,SAAS,EAAE,IAAI,CACb,gBAAgB,EACd,yBAAyB,GACzB,0BAA0B,GAC1B,eAAe,GACf,iBAAiB,GACjB,gCAAgC,GAChC,yBAAyB,CAC5B,CAAC;IACF,MAAM,EAAE,aAAa,CAAC;IACtB,8FAA8F;IAC9F,SAAS,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IACnD,+FAA+F;IAC/F,YAAY,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC,CAAC;IAC1D,aAAa,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,oBAAoB,EAAE,mBAAmB,CAAC,GAAG,IAAI,CAAC,CAAC;IACrF,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;CACpB;AAiCD;;;;;;GAMG;AACH,qBAAa,6BAA8B,YAAW,SAAS,CAAC,kBAAkB,CAAC;;IACjF,QAAQ,CAAC,EAAE,sBAAY;IACvB,QAAQ,CAAC,OAAO,sBAAY;
|
|
1
|
+
{"version":3,"file":"sessions-state-processor.d.ts","sourceRoot":"","sources":["../../src/tools/sessions-state-processor.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,4BAA4B,CAAC;AACvE,OAAO,KAAK,EAAE,sBAAsB,EAAE,wBAAwB,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAC;AAG3G,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAC3D,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,+BAA+B,CAAC;AAChF,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,uCAAuC,CAAC;AAE9E,OAAO,KAAK,EAAoB,8BAA8B,EAAE,MAAM,YAAY,CAAC;AAWnF,+FAA+F;AAC/F,eAAO,MAAM,2BAA2B,QAAsB,CAAC;AAI/D,8GAA8G;AAC9G,eAAO,MAAM,yBAAyB,QAAiB,CAAC;AACxD,0DAA0D;AAC1D,eAAO,MAAM,yBAAyB,KAAK,CAAC;AAG5C,YAAY,EAAE,sBAAsB,EAAE,MAAM,oBAAoB,CAAC;AAEjE,MAAM,WAAW,gCAAgC;IAC/C,WAAW,EAAE,OAAO,CAAC;IACrB,QAAQ,EAAE,IAAI,CAAC,0BAA0B,EAAE,gBAAgB,GAAG,cAAc,CAAC,CAAC;IAC9E,QAAQ,EAAE,8BAA8B,CAAC,UAAU,CAAC,CAAC;IACrD,SAAS,EAAE,IAAI,CACb,gBAAgB,EACd,yBAAyB,GACzB,0BAA0B,GAC1B,eAAe,GACf,iBAAiB,GACjB,gCAAgC,GAChC,yBAAyB,CAC5B,CAAC;IACF,MAAM,EAAE,aAAa,CAAC;IACtB,8FAA8F;IAC9F,SAAS,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IACnD,+FAA+F;IAC/F,YAAY,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC,CAAC;IAC1D,aAAa,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,oBAAoB,EAAE,mBAAmB,CAAC,GAAG,IAAI,CAAC,CAAC;IACrF,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;CACpB;AAiCD;;;;;;GAMG;AACH,qBAAa,6BAA8B,YAAW,SAAS,CAAC,kBAAkB,CAAC;;IACjF,QAAQ,CAAC,EAAE,sBAAY;IACvB,QAAQ,CAAC,OAAO,sBAAY;IAG5B,YAAY,IAAI,EAAE,gCAAgC,EAEjD;IAEK,kBAAkB,CAAC,IAAI,EAAE,sBAAsB,GAAG,OAAO,CAAC,wBAAwB,CAAC,CAyCxF;CAgKF"}
|
|
@@ -8,8 +8,8 @@ import { transitionBodySchema } from "../routes/contracts.js";
|
|
|
8
8
|
import { resolveWorkItemRepository } from "../session/work-item-repository.js";
|
|
9
9
|
import { createFactoryWorkItem } from "../work-items/create-work-item.js";
|
|
10
10
|
import { dismissFactoryDecision, resolveFactoryProposal, retryFactoryDecision } from "../work-items/decision-actions.js";
|
|
11
|
-
import { randomUUID } from "crypto";
|
|
12
11
|
import { z } from "zod";
|
|
12
|
+
import { randomUUID } from "crypto";
|
|
13
13
|
import { createTool } from "@mastra/core/tools";
|
|
14
14
|
// src/tools/work-item-tools.ts
|
|
15
15
|
/**
|
package/dist/workspace.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { SandboxFilesystem } from '@mastra/code-sdk/agents/sandbox-filesystem';
|
|
2
2
|
import type { getDynamicWorkspace } from '@mastra/code-sdk/agents/workspace';
|
|
3
|
+
import type { InlineSkill } from '@mastra/core/skills';
|
|
3
4
|
import { Workspace } from '@mastra/core/workspace';
|
|
4
5
|
import type { FactorySandbox, SkillSource, SkillSourceEntry, SkillSourceStat, WorkspaceSandbox } from '@mastra/core/workspace';
|
|
5
6
|
import type { RepositoryAccess, VersionControl } from './capabilities/version-control.js';
|
|
@@ -12,12 +13,14 @@ export declare const BUNDLED_FACTORY_SKILLS_PATH: string;
|
|
|
12
13
|
/**
|
|
13
14
|
* Resolve the consumer repo's local Factory skills root, if any. Checked in
|
|
14
15
|
* addition to the bundled skills so projects can add (or override) Factory
|
|
15
|
-
* skills without patching the installed package.
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
16
|
+
* skills without patching the installed package. Skills live in
|
|
17
|
+
* `src/mastra/factory-skills`; `src/mastra/public/factory-skills` is the older
|
|
18
|
+
* location and still works. Candidates cover the cwd variants the dev server
|
|
19
|
+
* runs with (`repo root`, `mastra dev` which runs with cwd `src/mastra/public`),
|
|
20
|
+
* then the platform build output when the server runs from its parent directory.
|
|
19
21
|
*/
|
|
20
22
|
export declare function resolveLocalFactorySkillsPath(cwd?: string): string | undefined;
|
|
23
|
+
export declare const FACTORY_SKILLS_MOUNT: string;
|
|
21
24
|
export declare const FACTORY_SKILL_NAMES: Set<string>;
|
|
22
25
|
/**
|
|
23
26
|
* Review skills only sessions with an active review run binding, or unbound
|
|
@@ -37,7 +40,9 @@ export declare class FactorySkillSource implements SkillSource {
|
|
|
37
40
|
readonly isReviewSession: () => Promise<boolean>;
|
|
38
41
|
constructor(fallback: SkillSource, fallbackSkillRoots: string[], localSkillsPath?: string | undefined,
|
|
39
42
|
/** Evaluated per call because a session's bound role changes across stages. */
|
|
40
|
-
isReviewSession?: () => Promise<boolean
|
|
43
|
+
isReviewSession?: () => Promise<boolean>,
|
|
44
|
+
/** Skills passed as `MastraFactory({ skills })`; they win over local and bundled skills of the same name. */
|
|
45
|
+
codeSkills?: readonly InlineSkill[]);
|
|
41
46
|
exists(skillPath: string): Promise<boolean>;
|
|
42
47
|
stat(skillPath: string): Promise<SkillSourceStat>;
|
|
43
48
|
readFile(skillPath: string): Promise<string | Buffer>;
|
|
@@ -78,6 +83,8 @@ export interface CreateWorkspaceFactoryOptions {
|
|
|
78
83
|
projects?: Pick<FactoryProjectsStorage, 'get'>;
|
|
79
84
|
/** Runtime workspace/token registrations invalidated when a session retires. */
|
|
80
85
|
workspaceRegistry?: FactoryWorkspaceRegistry;
|
|
86
|
+
/** App skills from `MastraFactory({ skills })`, served on the Factory skill mount. */
|
|
87
|
+
skills?: readonly InlineSkill[];
|
|
81
88
|
}
|
|
82
89
|
type WorkspaceUnregister = () => Promise<void> | void;
|
|
83
90
|
/** Tracks dynamic Factory workspaces by persisted session id for retirement. */
|
|
@@ -102,6 +109,8 @@ export interface SessionEnvironmentRepo {
|
|
|
102
109
|
}
|
|
103
110
|
/** The session's factory environment, resolved from the project and its `inEnvironment` links. */
|
|
104
111
|
export interface SessionEnvironment {
|
|
112
|
+
/** The factory's display name. */
|
|
113
|
+
factoryName: string;
|
|
105
114
|
repos: SessionEnvironmentRepo[];
|
|
106
115
|
workspaceSetupCommand: string | undefined;
|
|
107
116
|
/** Only an absolute root is passed on; the templates reject anything else. */
|
|
@@ -130,6 +139,6 @@ export declare function environmentSandboxContext(environment: SessionEnvironmen
|
|
|
130
139
|
}) => Promise<RepositoryAccess>;
|
|
131
140
|
resolveHead?: FactorySandboxContext['resolveHead'];
|
|
132
141
|
}): Omit<FactorySandboxContext, 'sessionId'>;
|
|
133
|
-
export declare function createWorkspaceFactory(options?: CreateWorkspaceFactoryOptions): (context: DynamicWorkspaceContext) => Promise<Workspace<import("@mastra/core/workspace").WorkspaceFilesystem | undefined, WorkspaceSandbox | undefined, undefined> |
|
|
142
|
+
export declare function createWorkspaceFactory(options?: CreateWorkspaceFactoryOptions): (context: DynamicWorkspaceContext) => Promise<Workspace<SandboxFilesystem, WorkspaceSandbox, undefined> | Workspace<import("@mastra/core/workspace").WorkspaceFilesystem | undefined, WorkspaceSandbox | undefined, undefined> | undefined>;
|
|
134
143
|
export {};
|
|
135
144
|
//# sourceMappingURL=workspace.d.ts.map
|
package/dist/workspace.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"workspace.d.ts","sourceRoot":"","sources":["../src/workspace.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,iBAAiB,EAAE,MAAM,4CAA4C,CAAC;AAE/E,OAAO,KAAK,EAAE,mBAAmB,EAA2B,MAAM,mCAAmC,CAAC;
|
|
1
|
+
{"version":3,"file":"workspace.d.ts","sourceRoot":"","sources":["../src/workspace.ts"],"names":[],"mappings":"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"}
|
package/dist/workspace.js
CHANGED
|
@@ -10,12 +10,13 @@ import { repositoryDirectoryName } from "./sandbox/workdir.js";
|
|
|
10
10
|
import { createEnvironmentSetupHook, createSessionSetupHook, evictSessionSandbox, getSessionSandbox, hasFailedSetupCommand, recordFailedSetupCommand, resolveSessionWorkdir } from "./sandbox/session-sandbox.js";
|
|
11
11
|
import { clearSessionEnvironment, recordSessionEnvironment, setSessionEnvironmentNote } from "./session/environment-state-processor.js";
|
|
12
12
|
import { LocalSkillSource, Workspace } from "@mastra/core/workspace";
|
|
13
|
+
import { DEFAULT_CONFIG_DIR } from "@mastra/code-sdk/constants";
|
|
13
14
|
import { existsSync } from "fs";
|
|
14
15
|
import path, { dirname, join } from "path";
|
|
15
16
|
import { fileURLToPath } from "url";
|
|
16
17
|
import { SandboxFilesystem } from "@mastra/code-sdk/agents/sandbox-filesystem";
|
|
17
18
|
import { MASTRACODE_WORKSPACE_TOOLS } from "@mastra/code-sdk/agents/tool-availability";
|
|
18
|
-
import {
|
|
19
|
+
import { InlineSkillSource } from "@mastra/core/skills";
|
|
19
20
|
// src/workspace.ts
|
|
20
21
|
const WORKSPACE_ID_PREFIX = "mfw";
|
|
21
22
|
const bundleDirectory = dirname(fileURLToPath(import.meta.url));
|
|
@@ -24,14 +25,17 @@ const BUNDLED_FACTORY_SKILLS_PATH = [bundledFactorySkillsPath, join(bundleDirect
|
|
|
24
25
|
/**
|
|
25
26
|
* Resolve the consumer repo's local Factory skills root, if any. Checked in
|
|
26
27
|
* addition to the bundled skills so projects can add (or override) Factory
|
|
27
|
-
* skills without patching the installed package.
|
|
28
|
-
*
|
|
29
|
-
*
|
|
30
|
-
*
|
|
28
|
+
* skills without patching the installed package. Skills live in
|
|
29
|
+
* `src/mastra/factory-skills`; `src/mastra/public/factory-skills` is the older
|
|
30
|
+
* location and still works. Candidates cover the cwd variants the dev server
|
|
31
|
+
* runs with (`repo root`, `mastra dev` which runs with cwd `src/mastra/public`),
|
|
32
|
+
* then the platform build output when the server runs from its parent directory.
|
|
31
33
|
*/
|
|
32
34
|
function resolveLocalFactorySkillsPath(cwd = process.cwd()) {
|
|
33
35
|
return [
|
|
36
|
+
join(cwd, "src", "mastra", "factory-skills"),
|
|
34
37
|
join(cwd, "src", "mastra", "public", "factory-skills"),
|
|
38
|
+
...path.basename(cwd) === "public" ? [join(cwd, "..", "factory-skills")] : [],
|
|
35
39
|
join(cwd, "public", "factory-skills"),
|
|
36
40
|
join(cwd, "factory-skills"),
|
|
37
41
|
join(cwd, "output", "factory-skills")
|
|
@@ -76,18 +80,57 @@ async function rescanFactorySkills(skills) {
|
|
|
76
80
|
rescannedOutsideResolver.set(skills, pending.catch(() => {}));
|
|
77
81
|
await pending;
|
|
78
82
|
}
|
|
83
|
+
/**
|
|
84
|
+
* Serves `createSkill()` skills under mount-relative paths (`<name>/SKILL.md`),
|
|
85
|
+
* the layout the other Factory skill layers use.
|
|
86
|
+
*/
|
|
87
|
+
var CodeSkillSource = class {
|
|
88
|
+
#inline;
|
|
89
|
+
#names;
|
|
90
|
+
constructor(skills) {
|
|
91
|
+
this.#inline = new InlineSkillSource([...skills]);
|
|
92
|
+
this.#names = skills.map((skill) => skill.name);
|
|
93
|
+
}
|
|
94
|
+
#inlinePath(relativePath) {
|
|
95
|
+
return `inline/${relativePath.split(path.sep).join("/")}`;
|
|
96
|
+
}
|
|
97
|
+
async exists(relativePath) {
|
|
98
|
+
if (relativePath === "") return this.#names.length > 0;
|
|
99
|
+
return this.#inline.exists(this.#inlinePath(relativePath));
|
|
100
|
+
}
|
|
101
|
+
stat(relativePath) {
|
|
102
|
+
return this.#inline.stat(this.#inlinePath(relativePath));
|
|
103
|
+
}
|
|
104
|
+
readFile(relativePath) {
|
|
105
|
+
return this.#inline.readFile(this.#inlinePath(relativePath));
|
|
106
|
+
}
|
|
107
|
+
async readdir(relativePath) {
|
|
108
|
+
if (relativePath === "") return this.#names.map((name) => ({
|
|
109
|
+
name,
|
|
110
|
+
type: "directory"
|
|
111
|
+
}));
|
|
112
|
+
return this.#inline.readdir(this.#inlinePath(relativePath));
|
|
113
|
+
}
|
|
114
|
+
};
|
|
79
115
|
var FactorySkillSource = class {
|
|
80
116
|
fallback;
|
|
81
117
|
isReviewSession;
|
|
82
118
|
#bundledSource = new LocalSkillSource({ basePath: BUNDLED_FACTORY_SKILLS_PATH });
|
|
83
119
|
#localSource;
|
|
120
|
+
#codeSource;
|
|
84
121
|
#fallbackSkillRoots;
|
|
85
|
-
constructor(fallback, fallbackSkillRoots, localSkillsPath = resolveLocalFactorySkillsPath(), isReviewSession = () => Promise.resolve(true)) {
|
|
122
|
+
constructor(fallback, fallbackSkillRoots, localSkillsPath = resolveLocalFactorySkillsPath(), isReviewSession = () => Promise.resolve(true), codeSkills = []) {
|
|
86
123
|
this.fallback = fallback;
|
|
87
124
|
this.isReviewSession = isReviewSession;
|
|
88
125
|
this.#localSource = localSkillsPath ? new LocalSkillSource({ basePath: localSkillsPath }) : void 0;
|
|
126
|
+
this.#codeSource = codeSkills.length > 0 ? new CodeSkillSource(codeSkills) : void 0;
|
|
89
127
|
this.#fallbackSkillRoots = new Set(fallbackSkillRoots.map((skillPath) => path.normalize(skillPath)));
|
|
90
128
|
}
|
|
129
|
+
/** A code skill owns its whole directory, so a same-named folder skill never mixes in files. */
|
|
130
|
+
async #ownedByCode(relativePath) {
|
|
131
|
+
const skillName = relativePath.split(path.sep)[0];
|
|
132
|
+
return !!skillName && !!this.#codeSource && await this.#codeSource.exists(skillName);
|
|
133
|
+
}
|
|
91
134
|
#isFactoryPath(skillPath) {
|
|
92
135
|
const normalized = path.normalize(skillPath);
|
|
93
136
|
return normalized === FACTORY_SKILLS_MOUNT || normalized.startsWith(`${FACTORY_SKILLS_MOUNT}${path.sep}`);
|
|
@@ -101,8 +144,9 @@ var FactorySkillSource = class {
|
|
|
101
144
|
if (!skillName || !REVIEW_ONLY_FACTORY_SKILLS.has(skillName)) return false;
|
|
102
145
|
return !await this.isReviewSession();
|
|
103
146
|
}
|
|
104
|
-
/** Pick the layer serving this mount-relative path:
|
|
147
|
+
/** Pick the layer serving this mount-relative path: code skills, then local entries, then bundled. */
|
|
105
148
|
async #layerFor(relativePath) {
|
|
149
|
+
if (await this.#ownedByCode(relativePath)) return this.#codeSource;
|
|
106
150
|
if (this.#localSource && await this.#localSource.exists(relativePath)) return this.#localSource;
|
|
107
151
|
return this.#bundledSource;
|
|
108
152
|
}
|
|
@@ -110,6 +154,7 @@ var FactorySkillSource = class {
|
|
|
110
154
|
if (!this.#isFactoryPath(skillPath)) return this.fallback.exists(skillPath);
|
|
111
155
|
const relative = this.#factoryPath(skillPath);
|
|
112
156
|
if (await this.#isHiddenReviewPath(relative)) return false;
|
|
157
|
+
if (await this.#ownedByCode(relative)) return this.#codeSource.exists(relative);
|
|
113
158
|
if (this.#localSource && await this.#localSource.exists(relative)) return true;
|
|
114
159
|
return this.#bundledSource.exists(relative);
|
|
115
160
|
}
|
|
@@ -129,12 +174,18 @@ var FactorySkillSource = class {
|
|
|
129
174
|
if (this.#isFactoryPath(skillPath)) {
|
|
130
175
|
const relative = this.#factoryPath(skillPath);
|
|
131
176
|
if (await this.#isHiddenReviewPath(relative)) throw skillSourceEnoent(skillPath);
|
|
177
|
+
if (relative !== "" && await this.#ownedByCode(relative)) return this.#codeSource.readdir(relative);
|
|
132
178
|
const [bundledExists, localExists] = await Promise.all([this.#bundledSource.exists(relative), this.#localSource?.exists(relative) ?? Promise.resolve(false)]);
|
|
133
|
-
if (!bundledExists && !localExists) throw skillSourceEnoent(skillPath);
|
|
134
|
-
const [bundledEntries, localEntries] = await Promise.all([
|
|
179
|
+
if (!bundledExists && !localExists && !(relative === "" && this.#codeSource)) throw skillSourceEnoent(skillPath);
|
|
180
|
+
const [bundledEntries, localEntries, codeEntries] = await Promise.all([
|
|
181
|
+
bundledExists ? this.#bundledSource.readdir(relative) : [],
|
|
182
|
+
localExists ? this.#localSource.readdir(relative) : [],
|
|
183
|
+
relative === "" && this.#codeSource ? this.#codeSource.readdir("") : []
|
|
184
|
+
]);
|
|
135
185
|
const merged = /* @__PURE__ */ new Map();
|
|
136
186
|
for (const entry of bundledEntries) merged.set(entry.name, entry);
|
|
137
187
|
for (const entry of localEntries) merged.set(entry.name, entry);
|
|
188
|
+
for (const entry of codeEntries) merged.set(entry.name, entry);
|
|
138
189
|
const entries = [...merged.values()];
|
|
139
190
|
if (relative !== "" || await this.isReviewSession()) return entries;
|
|
140
191
|
return entries.filter((entry) => !REVIEW_ONLY_FACTORY_SKILLS.has(entry.name));
|
|
@@ -147,12 +198,13 @@ var FactorySkillSource = class {
|
|
|
147
198
|
return entries;
|
|
148
199
|
}
|
|
149
200
|
/**
|
|
150
|
-
* Names the Factory mount serves: bundled skills plus the app's local skills.
|
|
201
|
+
* Names the Factory mount serves: bundled skills plus the app's code and local skills.
|
|
151
202
|
* Repository skills with these names are hidden so they cannot collide with
|
|
152
203
|
* Factory's copy. Recomputed per scan so skill refreshes pick up local changes.
|
|
153
204
|
*/
|
|
154
205
|
async #reservedNames() {
|
|
155
206
|
const reserved = new Set(FACTORY_SKILL_NAMES);
|
|
207
|
+
for (const entry of await this.#codeSource?.readdir("") ?? []) reserved.add(entry.name);
|
|
156
208
|
if (!this.#localSource) return reserved;
|
|
157
209
|
try {
|
|
158
210
|
for (const entry of await this.#localSource.readdir("")) if (entry.type === "directory") reserved.add(entry.name);
|
|
@@ -206,11 +258,11 @@ var UnmaterializedAwareSkillSource = class {
|
|
|
206
258
|
return this.fallback.realpath ? this.fallback.realpath(skillPath) : Promise.resolve(skillPath);
|
|
207
259
|
}
|
|
208
260
|
};
|
|
209
|
-
function createFactorySkillExtension(isReviewSession) {
|
|
261
|
+
function createFactorySkillExtension(isReviewSession, codeSkills) {
|
|
210
262
|
return {
|
|
211
263
|
id: "web-factory",
|
|
212
264
|
paths: [FACTORY_SKILLS_MOUNT],
|
|
213
|
-
createSource: (fallback, fallbackSkillRoots) => new FactorySkillSource(fallback, fallbackSkillRoots, resolveLocalFactorySkillsPath(), isReviewSession)
|
|
265
|
+
createSource: (fallback, fallbackSkillRoots) => new FactorySkillSource(fallback, fallbackSkillRoots, resolveLocalFactorySkillsPath(), isReviewSession, codeSkills)
|
|
214
266
|
};
|
|
215
267
|
}
|
|
216
268
|
function isActiveReviewBinding(runBinding, orgId) {
|
|
@@ -320,6 +372,7 @@ async function resolveProjectEnvironment(storage, project) {
|
|
|
320
372
|
}
|
|
321
373
|
const workdir = project.sandboxWorkingDirectory?.trim();
|
|
322
374
|
return {
|
|
375
|
+
factoryName: project.name,
|
|
323
376
|
repos,
|
|
324
377
|
workspaceSetupCommand: project.workspaceSetupCommand?.trim() || void 0,
|
|
325
378
|
workingDirectory: workdir?.startsWith("/") ? workdir : void 0,
|
|
@@ -488,6 +541,8 @@ function createWorkspaceFactory(options = {}) {
|
|
|
488
541
|
const constructSessionEntry = () => getSessionSandbox(session.id, repoFullName, () => {
|
|
489
542
|
const sandbox = instrumentMethods(factorySandbox.create({
|
|
490
543
|
sessionId: session.id,
|
|
544
|
+
...session.factoryProjectId ? { factoryId: session.factoryProjectId } : {},
|
|
545
|
+
...resolvedEnvironment ? { factoryName: resolvedEnvironment.factoryName } : {},
|
|
491
546
|
sandboxId: session.sandboxId ?? void 0,
|
|
492
547
|
repoFullName,
|
|
493
548
|
...environment ? environmentSandboxContext(environment, {
|
|
@@ -507,10 +562,16 @@ function createWorkspaceFactory(options = {}) {
|
|
|
507
562
|
"reconnect"
|
|
508
563
|
]);
|
|
509
564
|
sandbox.setOnStart((previous) => async (args) => {
|
|
510
|
-
|
|
511
|
-
await
|
|
512
|
-
|
|
513
|
-
|
|
565
|
+
try {
|
|
566
|
+
await timedPhase(`workspace.onStart(${args.outcome})`, async () => {
|
|
567
|
+
await setupHook(args);
|
|
568
|
+
});
|
|
569
|
+
await previous?.(args);
|
|
570
|
+
} catch (error) {
|
|
571
|
+
const physicalId = args.sandbox.sandboxId;
|
|
572
|
+
if (physicalId && error instanceof Error) error.message += ` (provider sandbox ${physicalId})`;
|
|
573
|
+
throw error;
|
|
574
|
+
}
|
|
514
575
|
});
|
|
515
576
|
startEagerly = eagerSandboxStart;
|
|
516
577
|
return sandbox;
|
|
@@ -558,7 +619,7 @@ function createWorkspaceFactory(options = {}) {
|
|
|
558
619
|
return false;
|
|
559
620
|
}
|
|
560
621
|
};
|
|
561
|
-
const effectiveSkillExtension = skillExtension ?? createFactorySkillExtension(() => (skillReviewChecks.get(workspaceId) ?? isReviewSession)());
|
|
622
|
+
const effectiveSkillExtension = skillExtension ?? createFactorySkillExtension(() => (skillReviewChecks.get(workspaceId) ?? isReviewSession)(), options.skills ?? []);
|
|
562
623
|
const extensionId = effectiveSkillExtension ? `-${effectiveSkillExtension.id}` : "";
|
|
563
624
|
const workspaceId = `${WORKSPACE_ID_PREFIX}-${projectRepository.id}-${session.id}${extensionId}`;
|
|
564
625
|
const workspaceGeneration = workspaceRegistry.generation(session.sessionId);
|
|
@@ -1007,6 +1068,6 @@ function createWorkspaceFactory(options = {}) {
|
|
|
1007
1068
|
};
|
|
1008
1069
|
return (context) => timed("workspace.resolve", () => resolve(context));
|
|
1009
1070
|
}
|
|
1010
|
-
export { BUNDLED_FACTORY_SKILLS_PATH, FACTORY_SKILL_NAMES, FactorySkillSource, FactoryWorkspaceRegistry, REVIEW_ONLY_FACTORY_SKILLS, createWorkspaceFactory, environmentSandboxContext, rescanFactorySkills, resolveLocalFactorySkillsPath, resolveProjectEnvironment };
|
|
1071
|
+
export { BUNDLED_FACTORY_SKILLS_PATH, FACTORY_SKILLS_MOUNT, FACTORY_SKILL_NAMES, FactorySkillSource, FactoryWorkspaceRegistry, REVIEW_ONLY_FACTORY_SKILLS, createWorkspaceFactory, environmentSandboxContext, rescanFactorySkills, resolveLocalFactorySkillsPath, resolveProjectEnvironment };
|
|
1011
1072
|
|
|
1012
1073
|
//# sourceMappingURL=workspace.js.map
|