@mastra/factory 0.21.1-alpha.2 → 0.22.0-alpha.4
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/dist/capabilities/version-control.d.ts +13 -8
- package/dist/capabilities/version-control.d.ts.map +1 -1
- package/dist/environment/build-runner.d.ts +72 -0
- package/dist/environment/build-runner.d.ts.map +1 -0
- package/dist/environment/build-runner.js +131 -0
- package/dist/environment/build-runner.js.map +1 -0
- package/dist/environment/build-schedule.d.ts +40 -0
- package/dist/environment/build-schedule.d.ts.map +1 -0
- package/dist/environment/build-schedule.js +94 -0
- package/dist/environment/build-schedule.js.map +1 -0
- package/dist/environment/build-workflow.d.ts +62 -0
- package/dist/environment/build-workflow.d.ts.map +1 -0
- package/dist/environment/build-workflow.js +149 -0
- package/dist/environment/build-workflow.js.map +1 -0
- package/dist/environment/build.d.ts +111 -0
- package/dist/environment/build.d.ts.map +1 -0
- package/dist/environment/build.js +344 -0
- package/dist/environment/build.js.map +1 -0
- package/dist/environment/heads.d.ts +36 -0
- package/dist/environment/heads.d.ts.map +1 -0
- package/dist/environment/heads.js +60 -0
- package/dist/environment/heads.js.map +1 -0
- package/dist/factory.d.ts +18 -4
- package/dist/factory.d.ts.map +1 -1
- package/dist/factory.js +89 -15
- package/dist/factory.js.map +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -2
- package/dist/integrations/base.d.ts +17 -2
- package/dist/integrations/base.d.ts.map +1 -1
- package/dist/integrations/github/commits.d.ts +11 -0
- package/dist/integrations/github/commits.d.ts.map +1 -1
- package/dist/integrations/github/commits.js +20 -1
- package/dist/integrations/github/commits.js.map +1 -1
- package/dist/integrations/github/config.d.ts +3 -3
- package/dist/integrations/github/config.d.ts.map +1 -1
- package/dist/integrations/github/config.js +1 -1
- package/dist/integrations/github/config.js.map +1 -1
- package/dist/integrations/github/routes.d.ts +2 -2
- package/dist/integrations/github/routes.d.ts.map +1 -1
- package/dist/integrations/github/routes.js +6 -5
- package/dist/integrations/github/routes.js.map +1 -1
- package/dist/integrations/github/rules.d.ts +3 -1
- package/dist/integrations/github/rules.d.ts.map +1 -1
- package/dist/integrations/github/rules.js +31 -1
- package/dist/integrations/github/rules.js.map +1 -1
- package/dist/integrations/github/sandbox.d.ts +35 -0
- package/dist/integrations/github/sandbox.d.ts.map +1 -1
- package/dist/integrations/github/sandbox.js +203 -2
- package/dist/integrations/github/sandbox.js.map +1 -1
- package/dist/integrations/github/session-subscriptions.d.ts.map +1 -1
- package/dist/integrations/github/session-subscriptions.js +117 -62
- package/dist/integrations/github/session-subscriptions.js.map +1 -1
- package/dist/integrations/github/token-refresh.d.ts +7 -0
- package/dist/integrations/github/token-refresh.d.ts.map +1 -1
- package/dist/integrations/github/token-refresh.js.map +1 -1
- package/dist/integrations/github/webhook.js.map +1 -1
- package/dist/integrations/gitlab/agent-tools.js +1 -1
- package/dist/integrations/gitlab/routes.d.ts +2 -2
- package/dist/integrations/gitlab/routes.d.ts.map +1 -1
- package/dist/integrations/gitlab/routes.js.map +1 -1
- package/dist/integrations/gitlab/session-subscriptions.d.ts.map +1 -1
- package/dist/integrations/gitlab/session-subscriptions.js +8 -7
- package/dist/integrations/gitlab/session-subscriptions.js.map +1 -1
- package/dist/integrations/incidentio/agent-tools.js +1 -1
- package/dist/integrations/jira/agent-tools.js +1 -1
- package/dist/integrations/linear/agent-tools.js +1 -1
- package/dist/integrations/platform/github/integration.d.ts.map +1 -1
- package/dist/integrations/platform/github/integration.js +46 -2
- package/dist/integrations/platform/github/integration.js.map +1 -1
- package/dist/integrations/platform/jira/agent-tools.js +1 -1
- package/dist/integrations/slack/slack.d.ts.map +1 -1
- package/dist/integrations/slack/slack.js +15 -16
- package/dist/integrations/slack/slack.js.map +1 -1
- package/dist/integrations/subscription-session.js +1 -1
- package/dist/packages/_internals/workspace/dist/index.js +21 -1
- package/dist/packages/_internals/workspace/dist/index.js.map +1 -1
- package/dist/routes/contracts.d.ts +386 -2
- package/dist/routes/contracts.d.ts.map +1 -1
- package/dist/routes/contracts.js +166 -1
- package/dist/routes/contracts.js.map +1 -1
- package/dist/routes/fs.d.ts +25 -0
- package/dist/routes/fs.d.ts.map +1 -1
- package/dist/routes/fs.js +142 -46
- package/dist/routes/fs.js.map +1 -1
- package/dist/routes/projects.d.ts +6 -0
- package/dist/routes/projects.d.ts.map +1 -1
- package/dist/routes/projects.js +344 -1
- package/dist/routes/projects.js.map +1 -1
- package/dist/routes/source-control-sessions.d.ts +2 -0
- package/dist/routes/source-control-sessions.d.ts.map +1 -1
- package/dist/routes/source-control-sessions.js +36 -1
- package/dist/routes/source-control-sessions.js.map +1 -1
- package/dist/routes/supervisor.js +1 -1
- package/dist/routes/surface.d.ts +6 -3
- package/dist/routes/surface.d.ts.map +1 -1
- package/dist/routes/surface.js +21 -34
- package/dist/routes/surface.js.map +1 -1
- package/dist/rules/binding-context.d.ts +1 -1
- package/dist/rules/binding-context.d.ts.map +1 -1
- package/dist/rules/binding-context.js +1 -1
- package/dist/rules/binding-context.js.map +1 -1
- package/dist/rules/review-source-tool.js +1 -1
- package/dist/rules/start-coordinator.d.ts.map +1 -1
- package/dist/rules/start-coordinator.js +7 -2
- package/dist/rules/start-coordinator.js.map +1 -1
- package/dist/rules/tools.js +1 -1
- package/dist/sandbox/callback-factory-sandbox.d.ts +15 -0
- package/dist/sandbox/callback-factory-sandbox.d.ts.map +1 -0
- package/dist/sandbox/callback-factory-sandbox.js +22 -0
- package/dist/sandbox/callback-factory-sandbox.js.map +1 -0
- package/dist/sandbox/local-factory-sandbox.d.ts +20 -0
- package/dist/sandbox/local-factory-sandbox.d.ts.map +1 -0
- package/dist/sandbox/local-factory-sandbox.js +27 -0
- package/dist/sandbox/local-factory-sandbox.js.map +1 -0
- package/dist/sandbox/session-retirement.d.ts.map +1 -1
- package/dist/sandbox/session-retirement.js +23 -3
- package/dist/sandbox/session-retirement.js.map +1 -1
- package/dist/sandbox/session-sandbox.d.ts +82 -40
- package/dist/sandbox/session-sandbox.d.ts.map +1 -1
- package/dist/sandbox/session-sandbox.js +130 -13
- package/dist/sandbox/session-sandbox.js.map +1 -1
- package/dist/sandbox/workdir.d.ts +10 -0
- package/dist/sandbox/workdir.d.ts.map +1 -1
- package/dist/sandbox/workdir.js +10 -1
- package/dist/sandbox/workdir.js.map +1 -1
- package/dist/secret-encryption.d.ts.map +1 -1
- package/dist/secret-encryption.js +12 -1
- package/dist/secret-encryption.js.map +1 -1
- package/dist/session/environment-repositories.d.ts +31 -0
- package/dist/session/environment-repositories.d.ts.map +1 -0
- package/dist/session/environment-repositories.js +89 -0
- package/dist/session/environment-repositories.js.map +1 -0
- package/dist/session/environment-state-processor.d.ts +59 -0
- package/dist/session/environment-state-processor.d.ts.map +1 -0
- package/dist/session/environment-state-processor.js +105 -0
- package/dist/session/environment-state-processor.js.map +1 -0
- package/dist/session/factory-session.d.ts +26 -35
- package/dist/session/factory-session.d.ts.map +1 -1
- package/dist/session/factory-session.js +34 -71
- package/dist/session/factory-session.js.map +1 -1
- package/dist/session/filesystem-capture.d.ts +13 -0
- package/dist/session/filesystem-capture.d.ts.map +1 -1
- package/dist/session/filesystem-capture.js +73 -14
- package/dist/session/filesystem-capture.js.map +1 -1
- package/dist/session/source-control-tools.d.ts +1 -1
- package/dist/session/source-control-tools.d.ts.map +1 -1
- package/dist/session/source-control-tools.js +144 -71
- package/dist/session/source-control-tools.js.map +1 -1
- package/dist/spa-static.js +2 -2
- package/dist/storage/domains/audit/agent-audit.d.ts +6 -1
- package/dist/storage/domains/audit/agent-audit.d.ts.map +1 -1
- package/dist/storage/domains/audit/agent-audit.js +31 -13
- package/dist/storage/domains/audit/agent-audit.js.map +1 -1
- package/dist/storage/domains/custom-providers/base.d.ts.map +1 -1
- package/dist/storage/domains/custom-providers/base.js +13 -2
- package/dist/storage/domains/custom-providers/base.js.map +1 -1
- package/dist/storage/domains/projects/base.d.ts +115 -2
- package/dist/storage/domains/projects/base.d.ts.map +1 -1
- package/dist/storage/domains/projects/base.js +219 -12
- package/dist/storage/domains/projects/base.js.map +1 -1
- package/dist/storage/domains/source-control/base.d.ts +123 -7
- package/dist/storage/domains/source-control/base.d.ts.map +1 -1
- package/dist/storage/domains/source-control/base.js +406 -33
- package/dist/storage/domains/source-control/base.js.map +1 -1
- package/dist/storage/domains/source-control/inmemory.d.ts +19 -6
- package/dist/storage/domains/source-control/inmemory.d.ts.map +1 -1
- package/dist/storage/domains/source-control/inmemory.js +90 -2
- package/dist/storage/domains/source-control/inmemory.js.map +1 -1
- package/dist/storage/domains/work-items/base.d.ts.map +1 -1
- package/dist/storage/domains/work-items/base.js +12 -5
- package/dist/storage/domains/work-items/base.js.map +1 -1
- package/dist/supervisor/read-tools.js +1 -1
- package/dist/supervisor/write-tools.js +1 -1
- package/dist/workspace.d.ts +50 -7
- package/dist/workspace.d.ts.map +1 -1
- package/dist/workspace.js +344 -24
- package/dist/workspace.js.map +1 -1
- package/package.json +7 -7
|
@@ -2,8 +2,8 @@ import { FACTORY_RULE_STAGES, factoryRuleStage } from "../rules/types.js";
|
|
|
2
2
|
import { factoryDispatchFailureMetadata } from "../rules/dispatch-errors.js";
|
|
3
3
|
import { decisionRetryable, overtakenDecisionIds } from "../rules/decision-applicability.js";
|
|
4
4
|
import { runFactoryHealthCheck } from "./health.js";
|
|
5
|
-
import { createTool } from "@mastra/core/tools";
|
|
6
5
|
import { z } from "zod";
|
|
6
|
+
import { createTool } from "@mastra/core/tools";
|
|
7
7
|
//#region src/supervisor/read-tools.ts
|
|
8
8
|
const MAX_TEXT = 600;
|
|
9
9
|
const MAX_ERROR = 400;
|
|
@@ -3,8 +3,8 @@ import { boardForWorkItem } from "../boards/semantics.js";
|
|
|
3
3
|
import "../boards/index.js";
|
|
4
4
|
import { factoryDispatchFailureMetadata } from "../rules/dispatch-errors.js";
|
|
5
5
|
import { overtakenDecisionIds } from "../rules/decision-applicability.js";
|
|
6
|
-
import { createTool } from "@mastra/core/tools";
|
|
7
6
|
import { z } from "zod";
|
|
7
|
+
import { createTool } from "@mastra/core/tools";
|
|
8
8
|
//#region src/supervisor/write-tools.ts
|
|
9
9
|
function createFactorySupervisorWriteTools(deps) {
|
|
10
10
|
const now = deps.now ?? (() => /* @__PURE__ */ new Date());
|
package/dist/workspace.d.ts
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { SandboxFilesystem } from '@mastra/code-sdk/agents/sandbox-filesystem';
|
|
2
2
|
import type { getDynamicWorkspace } from '@mastra/code-sdk/agents/workspace';
|
|
3
3
|
import { Workspace } from '@mastra/core/workspace';
|
|
4
|
-
import type { SkillSource, SkillSourceEntry, SkillSourceStat, WorkspaceSandbox } from '@mastra/core/workspace';
|
|
5
|
-
import type { VersionControl } from './capabilities/version-control.js';
|
|
6
|
-
import type { MastraFactorySandboxConfig } from './factory.js';
|
|
4
|
+
import type { FactorySandbox, SkillSource, SkillSourceEntry, SkillSourceStat, WorkspaceSandbox } from '@mastra/core/workspace';
|
|
5
|
+
import type { RepositoryAccess, VersionControl } from './capabilities/version-control.js';
|
|
7
6
|
import type { GithubIntegration } from './integrations/github/integration.js';
|
|
8
|
-
import type {
|
|
7
|
+
import type { FactorySandboxContext } from './sandbox/session-sandbox.js';
|
|
8
|
+
import type { FactoryProject, FactoryProjectsStorage } from './storage/domains/projects/base.js';
|
|
9
9
|
import type { SourceControlStorageHandle } from './storage/domains/source-control/base.js';
|
|
10
10
|
import type { WorkItemsStorage } from './storage/domains/work-items/base.js';
|
|
11
11
|
export declare const BUNDLED_FACTORY_SKILLS_PATH: string;
|
|
@@ -51,15 +51,15 @@ export interface WorkspaceSourceControlProvider {
|
|
|
51
51
|
/** Stable integration id used to select the provider-owned storage partition. */
|
|
52
52
|
id: string;
|
|
53
53
|
/** Provider capability used to resolve fresh repository credentials. */
|
|
54
|
-
versionControl: Pick<VersionControl, 'getRepositoryAccess'>;
|
|
54
|
+
versionControl: Pick<VersionControl, 'getRepositoryAccess' | 'getRepositoriesAccess'>;
|
|
55
55
|
/** Provider-owned source-control rows, including Factory sessions. */
|
|
56
56
|
storage: SourceControlStorageHandle;
|
|
57
57
|
/** Present only for GitHub, whose CLI PAT rotation has additional semantics. */
|
|
58
58
|
github?: GithubIntegration;
|
|
59
59
|
}
|
|
60
60
|
export interface CreateWorkspaceFactoryOptions {
|
|
61
|
-
/**
|
|
62
|
-
sandbox?:
|
|
61
|
+
/** The normalized factory sandbox constructing one sandbox per session. */
|
|
62
|
+
sandbox?: FactorySandbox;
|
|
63
63
|
/** Defaults to `'lazy'`. */
|
|
64
64
|
sandboxStart?: FactorySandboxStart;
|
|
65
65
|
/** Source-control providers whose repositories may back Factory sessions. */
|
|
@@ -83,6 +83,49 @@ export declare class FactoryWorkspaceRegistry {
|
|
|
83
83
|
register(sessionId: string, workspaceId: string, generation: number, unregister: WorkspaceUnregister): Promise<boolean>;
|
|
84
84
|
invalidateSession(sessionId: string): Promise<void>;
|
|
85
85
|
}
|
|
86
|
+
/** One environment repository as the sandbox context and the boot need it, in position order. */
|
|
87
|
+
export interface SessionEnvironmentRepo {
|
|
88
|
+
projectRepositoryId: string;
|
|
89
|
+
repositoryId: string;
|
|
90
|
+
slug: string;
|
|
91
|
+
/** The session's base branch: the link's branch when set, else the repository default. */
|
|
92
|
+
defaultBranch: string;
|
|
93
|
+
/** The repository's own default branch, which the template image clones and pins. */
|
|
94
|
+
templateBranch: string;
|
|
95
|
+
position: number;
|
|
96
|
+
setupCommand: string | undefined;
|
|
97
|
+
teardownCommand: string | undefined;
|
|
98
|
+
}
|
|
99
|
+
/** The session's factory environment, resolved from the project and its `inEnvironment` links. */
|
|
100
|
+
export interface SessionEnvironment {
|
|
101
|
+
repos: SessionEnvironmentRepo[];
|
|
102
|
+
workspaceSetupCommand: string | undefined;
|
|
103
|
+
/** Only an absolute root is passed on; the templates reject anything else. */
|
|
104
|
+
workingDirectory: string | undefined;
|
|
105
|
+
/** The project's stored provider settings document, `{}` when nothing was set. */
|
|
106
|
+
settings: Record<string, unknown>;
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* The project's environment as a session (or an environment build) sees it:
|
|
110
|
+
* every `inEnvironment` link under this source-control integration in
|
|
111
|
+
* position order, plus the project's settings, setup command and workdir.
|
|
112
|
+
*/
|
|
113
|
+
export declare function resolveProjectEnvironment(storage: Pick<SourceControlStorageHandle, 'projectRepositories' | 'repositories'>, project: FactoryProject): Promise<SessionEnvironment>;
|
|
114
|
+
/**
|
|
115
|
+
* The context fields the list form of the repo templates needs: one entry per
|
|
116
|
+
* environment repository, each minting its own token at build time, with
|
|
117
|
+
* `getRepositoryAccess` present but undefined (the two are mutually exclusive
|
|
118
|
+
* for the template). Shared by session boot and environment builds so both
|
|
119
|
+
* resolve the same template identity; `resolveHead` is only set when given.
|
|
120
|
+
*/
|
|
121
|
+
export declare function environmentSandboxContext(environment: SessionEnvironment, options: {
|
|
122
|
+
orgId: string;
|
|
123
|
+
getRepositoryAccess: (args: {
|
|
124
|
+
orgId: string;
|
|
125
|
+
repositoryId: string;
|
|
126
|
+
}) => Promise<RepositoryAccess>;
|
|
127
|
+
resolveHead?: FactorySandboxContext['resolveHead'];
|
|
128
|
+
}): Omit<FactorySandboxContext, 'sessionId'>;
|
|
86
129
|
export declare function createWorkspaceFactory(options?: CreateWorkspaceFactoryOptions): ({ requestContext, mastra, skillExtension }: DynamicWorkspaceContext) => Promise<Workspace<import("@mastra/core/workspace").WorkspaceFilesystem | undefined, WorkspaceSandbox | undefined, undefined> | Workspace<SandboxFilesystem, WorkspaceSandbox, undefined> | undefined>;
|
|
87
130
|
export {};
|
|
88
131
|
//# 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;AAItG,OAAO,EAAoB,SAAS,EAAE,MAAM,wBAAwB,CAAC;AACrE,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"workspace.d.ts","sourceRoot":"","sources":["../src/workspace.ts"],"names":[],"mappings":"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"}
|
package/dist/workspace.js
CHANGED
|
@@ -1,17 +1,20 @@
|
|
|
1
1
|
import { timedPhase } from "./timing.js";
|
|
2
2
|
import { getFactoryAuthOrgId, getFactoryAuthUserFromContext, getFactoryAuthUserId } from "./auth.js";
|
|
3
3
|
import { mergeRequestNumberFromBranch, pullRequestNumberFromBranch } from "./work-item-branch.js";
|
|
4
|
+
import { redactCredentials } from "./environment/build.js";
|
|
4
5
|
import { getGithubPat } from "./integrations/github/pat.js";
|
|
6
|
+
import { DEFAULT_COMMAND_TIMEOUT_MS, SetupCommandError, checkoutSessionBranch, materializeRepo, runSetupCommand, runTeardownCommand, syncEnvironmentRepository } from "./integrations/github/sandbox.js";
|
|
5
7
|
import { registerGithubPatKind, registerGithubRefreshTarget, registerGithubTokenInjector, registerGithubTokenInjectorResolver } from "./integrations/github/token-refresh.js";
|
|
6
8
|
import { requireExec } from "./sandbox/materialization.js";
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
+
import { repositoryDirectoryName } from "./sandbox/workdir.js";
|
|
10
|
+
import { createEnvironmentSetupHook, createSessionSetupHook, evictSessionSandbox, getSessionSandbox, hasFailedSetupCommand, recordFailedSetupCommand, resolveSessionWorkdir } from "./sandbox/session-sandbox.js";
|
|
11
|
+
import { clearSessionEnvironment, recordSessionEnvironment, setSessionEnvironmentNote } from "./session/environment-state-processor.js";
|
|
9
12
|
import { parseSupervisorResourceId } from "./supervisor/session.js";
|
|
10
|
-
import path, { dirname, join } from "path";
|
|
11
13
|
import { LocalSkillSource, Workspace } from "@mastra/core/workspace";
|
|
12
|
-
import { SandboxFilesystem } from "@mastra/code-sdk/agents/sandbox-filesystem";
|
|
13
14
|
import { existsSync } from "fs";
|
|
15
|
+
import path, { dirname, join } from "path";
|
|
14
16
|
import { fileURLToPath } from "url";
|
|
17
|
+
import { SandboxFilesystem } from "@mastra/code-sdk/agents/sandbox-filesystem";
|
|
15
18
|
import { MASTRACODE_WORKSPACE_TOOLS } from "@mastra/code-sdk/agents/tool-availability";
|
|
16
19
|
import { DEFAULT_CONFIG_DIR } from "@mastra/code-sdk/constants";
|
|
17
20
|
//#region src/workspace.ts
|
|
@@ -241,6 +244,106 @@ async function resolveSourceControlSession(providers, sessionId) {
|
|
|
241
244
|
if (matches.length > 1) throw new Error(`Factory session ${sessionId} is ambiguous across source-control providers`);
|
|
242
245
|
return matches[0] ?? null;
|
|
243
246
|
}
|
|
247
|
+
/**
|
|
248
|
+
* Resolve the factory environment a session boots from: the project's
|
|
249
|
+
* settings plus every `inEnvironment` link of the project under this
|
|
250
|
+
* source-control integration, ordered by position. `undefined` when the
|
|
251
|
+
* session carries no factory or the project is gone. With no link in the
|
|
252
|
+
* environment `repos` is empty and the session keeps the single-repository
|
|
253
|
+
* sandbox of its own link, still booted with the project's settings. A link
|
|
254
|
+
* whose repository row is missing is skipped with a warning rather than
|
|
255
|
+
* failing every start of the session.
|
|
256
|
+
*/
|
|
257
|
+
async function resolveSessionEnvironment(projects, storage, session) {
|
|
258
|
+
if (!projects || !session.factoryProjectId) return void 0;
|
|
259
|
+
const project = await projects.get({
|
|
260
|
+
orgId: session.orgId,
|
|
261
|
+
id: session.factoryProjectId
|
|
262
|
+
});
|
|
263
|
+
if (!project) return void 0;
|
|
264
|
+
return resolveProjectEnvironment(storage, project);
|
|
265
|
+
}
|
|
266
|
+
/**
|
|
267
|
+
* The project's environment as a session (or an environment build) sees it:
|
|
268
|
+
* every `inEnvironment` link under this source-control integration in
|
|
269
|
+
* position order, plus the project's settings, setup command and workdir.
|
|
270
|
+
*/
|
|
271
|
+
async function resolveProjectEnvironment(storage, project) {
|
|
272
|
+
const orgId = project.orgId;
|
|
273
|
+
const links = (await storage.projectRepositories.listByProject({
|
|
274
|
+
orgId,
|
|
275
|
+
factoryProjectId: project.id
|
|
276
|
+
})).filter((link) => link.inEnvironment).sort((a, b) => a.position - b.position || a.createdAt.getTime() - b.createdAt.getTime());
|
|
277
|
+
const repos = [];
|
|
278
|
+
const directories = /* @__PURE__ */ new Set();
|
|
279
|
+
for (const link of links) {
|
|
280
|
+
const repository = await storage.repositories.get({
|
|
281
|
+
orgId,
|
|
282
|
+
id: link.repositoryId
|
|
283
|
+
});
|
|
284
|
+
if (!repository) {
|
|
285
|
+
console.warn("[Mastra Factory] Environment repository link has no repository row; skipping it", {
|
|
286
|
+
orgId,
|
|
287
|
+
factoryProjectId: project.id,
|
|
288
|
+
projectRepositoryId: link.id
|
|
289
|
+
});
|
|
290
|
+
continue;
|
|
291
|
+
}
|
|
292
|
+
const directory = repositoryDirectoryName(repository.slug);
|
|
293
|
+
if (directories.has(directory)) {
|
|
294
|
+
console.warn("[Mastra Factory] Environment repository shares its directory name with an earlier one; skipping it", {
|
|
295
|
+
orgId,
|
|
296
|
+
factoryProjectId: project.id,
|
|
297
|
+
projectRepositoryId: link.id,
|
|
298
|
+
slug: repository.slug,
|
|
299
|
+
directory
|
|
300
|
+
});
|
|
301
|
+
continue;
|
|
302
|
+
}
|
|
303
|
+
directories.add(directory);
|
|
304
|
+
repos.push({
|
|
305
|
+
projectRepositoryId: link.id,
|
|
306
|
+
repositoryId: repository.id,
|
|
307
|
+
slug: repository.slug,
|
|
308
|
+
defaultBranch: link.branch || repository.defaultBranch,
|
|
309
|
+
templateBranch: repository.defaultBranch,
|
|
310
|
+
position: link.position,
|
|
311
|
+
setupCommand: link.setupCommand ?? void 0,
|
|
312
|
+
teardownCommand: link.teardownCommand ?? void 0
|
|
313
|
+
});
|
|
314
|
+
}
|
|
315
|
+
const workdir = project.sandboxWorkingDirectory?.trim();
|
|
316
|
+
return {
|
|
317
|
+
repos,
|
|
318
|
+
workspaceSetupCommand: project.workspaceSetupCommand?.trim() || void 0,
|
|
319
|
+
workingDirectory: workdir?.startsWith("/") ? workdir : void 0,
|
|
320
|
+
settings: project.sandboxSettings ?? {}
|
|
321
|
+
};
|
|
322
|
+
}
|
|
323
|
+
/**
|
|
324
|
+
* The context fields the list form of the repo templates needs: one entry per
|
|
325
|
+
* environment repository, each minting its own token at build time, with
|
|
326
|
+
* `getRepositoryAccess` present but undefined (the two are mutually exclusive
|
|
327
|
+
* for the template). Shared by session boot and environment builds so both
|
|
328
|
+
* resolve the same template identity; `resolveHead` is only set when given.
|
|
329
|
+
*/
|
|
330
|
+
function environmentSandboxContext(environment, options) {
|
|
331
|
+
return {
|
|
332
|
+
setupCommand: void 0,
|
|
333
|
+
getRepositoryAccess: void 0,
|
|
334
|
+
repos: environment.repos.map((repo) => ({
|
|
335
|
+
getRepositoryAccess: () => options.getRepositoryAccess({
|
|
336
|
+
orgId: options.orgId,
|
|
337
|
+
repositoryId: repo.repositoryId
|
|
338
|
+
}),
|
|
339
|
+
...repo.setupCommand ? { setupCommand: repo.setupCommand } : {}
|
|
340
|
+
})),
|
|
341
|
+
...environment.workspaceSetupCommand ? { workspaceSetupCommand: environment.workspaceSetupCommand } : {},
|
|
342
|
+
continueOnSetupFailure: true,
|
|
343
|
+
...environment.workingDirectory ? { workingDirectory: environment.workingDirectory } : {},
|
|
344
|
+
...options.resolveHead ? { resolveHead: options.resolveHead } : {}
|
|
345
|
+
};
|
|
346
|
+
}
|
|
244
347
|
function createWorkspaceFactory(options = {}) {
|
|
245
348
|
const { sandbox: sandboxConfig, github, projects, workItems } = options;
|
|
246
349
|
const sourceControls = options.sourceControls ?? (github ? [{
|
|
@@ -276,14 +379,14 @@ function createWorkspaceFactory(options = {}) {
|
|
|
276
379
|
const userId = getFactoryAuthUserId(user);
|
|
277
380
|
if (!user?.organizationId || !userId) throw new Error(`Factory session ${session.sessionId} was resolved without a caller identity`);
|
|
278
381
|
if (user.organizationId !== session.orgId || session.visibility === "private" && userId !== session.userId) throw new Error(`Factory session ${session.sessionId} is not available to the current user`);
|
|
279
|
-
if (!sandboxConfig) throw new Error("A sandbox
|
|
280
|
-
const
|
|
382
|
+
if (!sandboxConfig) throw new Error("A sandbox is required to create a Factory session workspace");
|
|
383
|
+
const factorySandbox = sandboxConfig;
|
|
281
384
|
const githubProvider = sourceControl.github;
|
|
282
385
|
const storage = sourceControl.storage;
|
|
283
|
-
const projectRepository = await storage.projectRepositories.get({
|
|
386
|
+
const projectRepository = session.projectRepositoryId ? await storage.projectRepositories.get({
|
|
284
387
|
orgId: session.orgId,
|
|
285
388
|
id: session.projectRepositoryId
|
|
286
|
-
});
|
|
389
|
+
}) : null;
|
|
287
390
|
if (!projectRepository) throw new Error(`Repository link ${session.projectRepositoryId} was not found`);
|
|
288
391
|
const [connection, repository] = await Promise.all([storage.connections.get({
|
|
289
392
|
orgId: session.orgId,
|
|
@@ -298,12 +401,24 @@ function createWorkspaceFactory(options = {}) {
|
|
|
298
401
|
id: connection.installationId
|
|
299
402
|
})) throw new Error(`${sourceControl.id} installation ${connection.installationId} was not found`);
|
|
300
403
|
const repoFullName = repository.slug;
|
|
404
|
+
const resolvedEnvironment = await resolveSessionEnvironment(projects, storage, session);
|
|
405
|
+
const sandboxSettings = resolvedEnvironment?.settings ?? {};
|
|
406
|
+
const environment = resolvedEnvironment?.repos.some((repo) => repo.projectRepositoryId === projectRepository.id) ? resolvedEnvironment : void 0;
|
|
407
|
+
const tokenRepositoryIds = environment ? [repository.id, ...environment.repos.map((repo) => repo.repositoryId).filter((id) => id !== repository.id)] : [repository.id];
|
|
301
408
|
if (githubProvider) registerGithubRefreshTarget(requestContext, {
|
|
302
409
|
orgId: session.orgId,
|
|
303
|
-
repositoryId: repository.id
|
|
410
|
+
repositoryId: repository.id,
|
|
411
|
+
...tokenRepositoryIds.length > 1 ? { mint: () => getRepositoryToken() } : {}
|
|
304
412
|
});
|
|
305
413
|
const runSetupOn = (target, workdir, gate) => runSessionSetup(requireExec(target), workdir, gate);
|
|
306
|
-
const
|
|
414
|
+
const runEnvironmentSetupOn = (target, gate) => runSessionEnvironmentSetup(requireExec(target), gate);
|
|
415
|
+
const guardedSetup = environment ? createEnvironmentSetupHook(runEnvironmentSetupOn, session.id, repoFullName, {
|
|
416
|
+
repos: environment.repos.map((repo) => ({
|
|
417
|
+
slug: repo.slug,
|
|
418
|
+
...repo.setupCommand ? { setupCommand: repo.setupCommand } : {}
|
|
419
|
+
})),
|
|
420
|
+
...environment.workspaceSetupCommand ? { workspaceSetupCommand: environment.workspaceSetupCommand } : {}
|
|
421
|
+
}) : createSessionSetupHook(runSetupOn, session.id, repoFullName, projectRepository.setupCommand ?? void 0);
|
|
307
422
|
const setupHook = async (args) => {
|
|
308
423
|
if (workspaceRegistry.generation(session.sessionId) !== workspaceGeneration) throw retiredError();
|
|
309
424
|
let setupError;
|
|
@@ -319,7 +434,7 @@ function createWorkspaceFactory(options = {}) {
|
|
|
319
434
|
await storage.sessions.setSandbox({
|
|
320
435
|
id: session.id,
|
|
321
436
|
sandboxId: target.sandboxId ?? null,
|
|
322
|
-
sandboxWorkdir: sessionEntry.workdir ?? ""
|
|
437
|
+
sandboxWorkdir: sessionWorkdir(sessionEntry.workdir) ?? ""
|
|
323
438
|
});
|
|
324
439
|
constructedWorkspaces.get(workspaceId)?.skills?.refresh().catch(() => {});
|
|
325
440
|
};
|
|
@@ -370,16 +485,21 @@ function createWorkspaceFactory(options = {}) {
|
|
|
370
485
|
await finishStart();
|
|
371
486
|
};
|
|
372
487
|
const constructSessionEntry = () => getSessionSandbox(session.id, repoFullName, () => {
|
|
373
|
-
const sandbox =
|
|
488
|
+
const sandbox = factorySandbox.create({
|
|
374
489
|
sessionId: session.id,
|
|
375
490
|
sandboxId: session.sandboxId ?? void 0,
|
|
376
491
|
repoFullName,
|
|
377
|
-
|
|
378
|
-
getRepositoryAccess: () => sourceControl.versionControl.getRepositoryAccess({
|
|
492
|
+
...environment ? environmentSandboxContext(environment, {
|
|
379
493
|
orgId: session.orgId,
|
|
380
|
-
|
|
381
|
-
})
|
|
382
|
-
|
|
494
|
+
getRepositoryAccess: (args) => sourceControl.versionControl.getRepositoryAccess(args)
|
|
495
|
+
}) : {
|
|
496
|
+
setupCommand: projectRepository.setupCommand ?? void 0,
|
|
497
|
+
getRepositoryAccess: () => sourceControl.versionControl.getRepositoryAccess({
|
|
498
|
+
orgId: session.orgId,
|
|
499
|
+
repositoryId: repository.id
|
|
500
|
+
})
|
|
501
|
+
}
|
|
502
|
+
}, sandboxSettings);
|
|
383
503
|
sandbox.setOnStart((previous) => async (args) => {
|
|
384
504
|
await timedPhase(`workspace.onStart(${args.outcome})`, async () => {
|
|
385
505
|
await setupHook(args);
|
|
@@ -388,7 +508,7 @@ function createWorkspaceFactory(options = {}) {
|
|
|
388
508
|
});
|
|
389
509
|
startEagerly = eagerSandboxStart;
|
|
390
510
|
return sandbox;
|
|
391
|
-
});
|
|
511
|
+
}, environment?.repos.map((repo) => repo.slug) ?? []);
|
|
392
512
|
let startEagerly = false;
|
|
393
513
|
const fireEagerStart = () => {
|
|
394
514
|
if (!startEagerly) return;
|
|
@@ -398,11 +518,15 @@ function createWorkspaceFactory(options = {}) {
|
|
|
398
518
|
});
|
|
399
519
|
};
|
|
400
520
|
const sessionEntry = constructSessionEntry();
|
|
401
|
-
const
|
|
521
|
+
const multiRepo = (environment?.repos.length ?? 0) > 1;
|
|
522
|
+
const sessionWorkdir = (checkout) => checkout === void 0 ? void 0 : multiRepo ? path.posix.dirname(checkout) : checkout;
|
|
523
|
+
const workdir = sessionWorkdir(sessionEntry.workdir);
|
|
402
524
|
sessionEntry.sandbox.provider;
|
|
403
|
-
|
|
525
|
+
const checkoutDirs = environment && multiRepo ? [repositoryDirectoryName(repoFullName), ...environment.repos.filter((repo) => repo.slug.toLowerCase() !== repoFullName.toLowerCase()).map((repo) => repositoryDirectoryName(repo.slug))] : void 0;
|
|
526
|
+
if (ctx && workdir && (ctx.getState()?.projectPath !== workdir || ctx.getState()?.instructionRoots?.join("\n") !== checkoutDirs?.join("\n"))) await ctx.setState({
|
|
404
527
|
projectPath: workdir,
|
|
405
|
-
projectName: repoFullName
|
|
528
|
+
projectName: repoFullName,
|
|
529
|
+
instructionRoots: checkoutDirs
|
|
406
530
|
});
|
|
407
531
|
const findSessionBinding = async () => {
|
|
408
532
|
const binding = await workItems.findActiveRunBindingForSession({
|
|
@@ -431,7 +555,34 @@ function createWorkspaceFactory(options = {}) {
|
|
|
431
555
|
orgId: session.orgId,
|
|
432
556
|
repositoryId: repository.id
|
|
433
557
|
});
|
|
558
|
+
let tokenScopeWarned = false;
|
|
434
559
|
const getRepositoryToken = async () => {
|
|
560
|
+
if (tokenRepositoryIds.length > 1) {
|
|
561
|
+
let reason = "provider mints per-repository tokens only";
|
|
562
|
+
let wide;
|
|
563
|
+
if (sourceControl.versionControl.getRepositoriesAccess) try {
|
|
564
|
+
wide = await sourceControl.versionControl.getRepositoriesAccess({
|
|
565
|
+
orgId: session.orgId,
|
|
566
|
+
repositoryIds: tokenRepositoryIds
|
|
567
|
+
});
|
|
568
|
+
reason = "provider cannot mint one token for this repository set";
|
|
569
|
+
} catch (error) {
|
|
570
|
+
reason = `provider failed to mint one token for this repository set (${error instanceof Error ? error.name : "error"})`;
|
|
571
|
+
}
|
|
572
|
+
if (wide?.authorization?.token) {
|
|
573
|
+
setSessionEnvironmentNote(session.sessionId, null);
|
|
574
|
+
return wide.authorization.token;
|
|
575
|
+
}
|
|
576
|
+
if (!tokenScopeWarned) {
|
|
577
|
+
tokenScopeWarned = true;
|
|
578
|
+
console.warn("[Mastra Factory] GH_TOKEN covers the session repository only", {
|
|
579
|
+
sessionId: session.sessionId,
|
|
580
|
+
repositories: environment?.repos.map((repo) => repo.slug) ?? [repoFullName],
|
|
581
|
+
reason
|
|
582
|
+
});
|
|
583
|
+
}
|
|
584
|
+
setSessionEnvironmentNote(session.sessionId, `GH_TOKEN covers ${repoFullName} only; use the source_control_* tools for other repositories.`);
|
|
585
|
+
}
|
|
435
586
|
const token = (await getRepositoryAccess()).authorization?.token;
|
|
436
587
|
if (!token) throw new Error("Repository access did not include a bearer token for the Factory session");
|
|
437
588
|
return token;
|
|
@@ -634,17 +785,185 @@ function createWorkspaceFactory(options = {}) {
|
|
|
634
785
|
}
|
|
635
786
|
}
|
|
636
787
|
};
|
|
788
|
+
const runSessionEnvironmentSetup = async (target, gate) => {
|
|
789
|
+
const repos = environment.repos;
|
|
790
|
+
const primaryDir = `${gate.root}/${repositoryDirectoryName(repoFullName)}`;
|
|
791
|
+
const states = [];
|
|
792
|
+
const failures = /* @__PURE__ */ new Map();
|
|
793
|
+
const repeated = /* @__PURE__ */ new Set();
|
|
794
|
+
let primaryError;
|
|
795
|
+
const record = () => {
|
|
796
|
+
if (workspaceRegistry.generation(session.sessionId) !== workspaceGeneration) return;
|
|
797
|
+
recordSessionEnvironment(session.sessionId, {
|
|
798
|
+
workingDirectory: gate.root,
|
|
799
|
+
repositories: states
|
|
800
|
+
}, states.flatMap((state) => {
|
|
801
|
+
const command = repos.find((repo) => repo.slug === state.slug)?.teardownCommand;
|
|
802
|
+
return command ? [{
|
|
803
|
+
slug: state.slug,
|
|
804
|
+
dir: state.dir,
|
|
805
|
+
command
|
|
806
|
+
}] : [];
|
|
807
|
+
}));
|
|
808
|
+
};
|
|
809
|
+
let inFlight;
|
|
810
|
+
try {
|
|
811
|
+
for (const repo of repos) {
|
|
812
|
+
inFlight = repo.slug;
|
|
813
|
+
const entry = gate.repos.find((candidate) => candidate.slug === repo.slug);
|
|
814
|
+
if (!entry) continue;
|
|
815
|
+
const isPrimary = repo.projectRepositoryId === session.projectRepositoryId;
|
|
816
|
+
const state = {
|
|
817
|
+
slug: repo.slug,
|
|
818
|
+
dir: entry.dir,
|
|
819
|
+
branch: null,
|
|
820
|
+
defaultBranch: repo.defaultBranch,
|
|
821
|
+
position: repo.position,
|
|
822
|
+
setupStatus: repo.setupCommand ? "ok" : "skipped"
|
|
823
|
+
};
|
|
824
|
+
states.push(state);
|
|
825
|
+
if (isPrimary) {
|
|
826
|
+
try {
|
|
827
|
+
await runSessionSetup(target, primaryDir, entry.gate);
|
|
828
|
+
state.branch = session.branch;
|
|
829
|
+
if (repo.setupCommand && hasFailedSetupCommand(session.id, repo.setupCommand)) {
|
|
830
|
+
state.setupStatus = "failed";
|
|
831
|
+
repeated.add(repo.slug);
|
|
832
|
+
}
|
|
833
|
+
} catch (error) {
|
|
834
|
+
if (!(error instanceof SetupCommandError)) throw error;
|
|
835
|
+
state.branch = session.branch;
|
|
836
|
+
state.setupStatus = "failed";
|
|
837
|
+
failures.set(repo.slug, error.message);
|
|
838
|
+
primaryError = error;
|
|
839
|
+
}
|
|
840
|
+
continue;
|
|
841
|
+
}
|
|
842
|
+
try {
|
|
843
|
+
const access = await sourceControl.versionControl.getRepositoryAccess({
|
|
844
|
+
orgId: session.orgId,
|
|
845
|
+
repositoryId: repo.repositoryId
|
|
846
|
+
});
|
|
847
|
+
const token = access.authorization?.token;
|
|
848
|
+
if (!token) throw new Error(`Repository access for ${repo.slug} did not include a bearer token`);
|
|
849
|
+
await materializeRepo({
|
|
850
|
+
row: {
|
|
851
|
+
id: session.id,
|
|
852
|
+
sandboxWorkdir: entry.dir,
|
|
853
|
+
materializedAt: null
|
|
854
|
+
},
|
|
855
|
+
repoInfo: {
|
|
856
|
+
repoFullName: repo.slug,
|
|
857
|
+
defaultBranch: repo.defaultBranch,
|
|
858
|
+
cloneUrl: access.cloneUrl,
|
|
859
|
+
authUsername: access.authorization?.username
|
|
860
|
+
},
|
|
861
|
+
sandbox: target,
|
|
862
|
+
token,
|
|
863
|
+
storage: { markMaterialized: async () => {} }
|
|
864
|
+
});
|
|
865
|
+
state.branch = (await timedPhase(`workspace.sync(${repo.slug})`, () => syncEnvironmentRepository(target, entry.dir, {
|
|
866
|
+
branch: session.branch,
|
|
867
|
+
defaultBranch: repo.defaultBranch,
|
|
868
|
+
token,
|
|
869
|
+
repoFullName: repo.slug,
|
|
870
|
+
cloneUrl: access.cloneUrl,
|
|
871
|
+
authUsername: access.authorization?.username
|
|
872
|
+
}))).branch;
|
|
873
|
+
} catch (error) {
|
|
874
|
+
console.warn("[Mastra Factory] Environment repository could not be synced; continuing the boot", {
|
|
875
|
+
orgId: session.orgId,
|
|
876
|
+
sessionId: session.sessionId,
|
|
877
|
+
projectRepositoryId: repo.projectRepositoryId,
|
|
878
|
+
error: error instanceof Error ? error.message.slice(-2e3) : String(error)
|
|
879
|
+
});
|
|
880
|
+
state.setupStatus = "failed";
|
|
881
|
+
failures.set(repo.slug, error instanceof Error ? error.message : String(error));
|
|
882
|
+
continue;
|
|
883
|
+
}
|
|
884
|
+
if (!repo.setupCommand || entry.gate.setupDone) continue;
|
|
885
|
+
if (hasFailedSetupCommand(session.id, `${repo.slug}:${repo.setupCommand}`)) {
|
|
886
|
+
state.setupStatus = "failed";
|
|
887
|
+
repeated.add(repo.slug);
|
|
888
|
+
continue;
|
|
889
|
+
}
|
|
890
|
+
try {
|
|
891
|
+
await timedPhase(`workspace.setup(${repo.slug})`, () => runSetupCommand(target, entry.dir, repo.setupCommand));
|
|
892
|
+
await entry.gate.markSetupDone();
|
|
893
|
+
} catch (error) {
|
|
894
|
+
if (!(error instanceof SetupCommandError)) throw error;
|
|
895
|
+
recordFailedSetupCommand(session.id, `${repo.slug}:${repo.setupCommand}`);
|
|
896
|
+
state.setupStatus = "failed";
|
|
897
|
+
failures.set(repo.slug, error.message);
|
|
898
|
+
console.warn("[Mastra Factory] Environment repository setup command failed; continuing the boot", {
|
|
899
|
+
orgId: session.orgId,
|
|
900
|
+
sessionId: session.sessionId,
|
|
901
|
+
projectRepositoryId: repo.projectRepositoryId,
|
|
902
|
+
error: error.message.slice(-2e3)
|
|
903
|
+
});
|
|
904
|
+
}
|
|
905
|
+
}
|
|
906
|
+
inFlight = void 0;
|
|
907
|
+
const workspaceCommand = environment.workspaceSetupCommand;
|
|
908
|
+
if (workspaceCommand && !gate.workspace.setupDone) if (hasFailedSetupCommand(session.id, `workspace:${workspaceCommand}`)) console.warn("[Mastra Factory] Skipping workspace setup command that already failed this session", {
|
|
909
|
+
orgId: session.orgId,
|
|
910
|
+
sessionId: session.sessionId
|
|
911
|
+
});
|
|
912
|
+
else try {
|
|
913
|
+
await timedPhase("workspace.setup(workspace)", () => runSetupCommand(target, gate.root, workspaceCommand));
|
|
914
|
+
await gate.workspace.markSetupDone();
|
|
915
|
+
} catch (error) {
|
|
916
|
+
if (!(error instanceof SetupCommandError)) throw error;
|
|
917
|
+
recordFailedSetupCommand(session.id, `workspace:${workspaceCommand}`);
|
|
918
|
+
throw new SetupCommandError(`${error.message}. The sandbox stays usable: the workspace setup command is skipped for the rest of the session. Retry your command, then fix it in the environment settings or run it manually.`, error.code);
|
|
919
|
+
}
|
|
920
|
+
} finally {
|
|
921
|
+
record();
|
|
922
|
+
await recordSetupResults(repos, states, failures, inFlight, repeated);
|
|
923
|
+
}
|
|
924
|
+
if (primaryError) throw primaryError;
|
|
925
|
+
};
|
|
926
|
+
const recordSetupResults = async (repos, states, failures, inFlight, repeated) => {
|
|
927
|
+
const builtAt = /* @__PURE__ */ new Date();
|
|
928
|
+
try {
|
|
929
|
+
for (const state of states) {
|
|
930
|
+
if (state.setupStatus === "skipped") continue;
|
|
931
|
+
if (state.slug === inFlight && state.setupStatus !== "failed") continue;
|
|
932
|
+
if (repeated.has(state.slug)) continue;
|
|
933
|
+
const repo = repos.find((candidate) => candidate.slug === state.slug);
|
|
934
|
+
if (!repo) continue;
|
|
935
|
+
const error = failures.get(state.slug);
|
|
936
|
+
await storage.projectRepositories.setBuildStatus({
|
|
937
|
+
orgId: session.orgId,
|
|
938
|
+
id: repo.projectRepositoryId,
|
|
939
|
+
status: state.setupStatus === "failed" ? "failed" : "configured",
|
|
940
|
+
error: error === void 0 ? null : redactCredentials(error).slice(-2e3),
|
|
941
|
+
builtAt
|
|
942
|
+
});
|
|
943
|
+
}
|
|
944
|
+
} catch (error) {
|
|
945
|
+
console.warn("[Mastra Factory] Could not record environment setup results", {
|
|
946
|
+
orgId: session.orgId,
|
|
947
|
+
sessionId: session.sessionId,
|
|
948
|
+
error: error instanceof Error ? error.message : String(error)
|
|
949
|
+
});
|
|
950
|
+
}
|
|
951
|
+
};
|
|
637
952
|
const sessionSandbox = requireExec(sessionEntry.sandbox);
|
|
638
953
|
const filesystem = new SandboxFilesystem({
|
|
639
954
|
id: `sandbox-fs:${workspaceId}`,
|
|
640
955
|
sandbox: sessionSandbox,
|
|
641
|
-
workdir: () =>
|
|
956
|
+
workdir: async () => {
|
|
957
|
+
const checkout = await resolveSessionWorkdir(session.id, sessionEntry.sandbox, repoFullName);
|
|
958
|
+
return sessionWorkdir(checkout) ?? checkout;
|
|
959
|
+
}
|
|
642
960
|
});
|
|
643
|
-
const
|
|
961
|
+
const skillRoots = [
|
|
644
962
|
path.join(configDir, "skills"),
|
|
645
963
|
".claude/skills",
|
|
646
964
|
".agents/skills"
|
|
647
965
|
];
|
|
966
|
+
const projectSkillPaths = checkoutDirs ? checkoutDirs.flatMap((dir) => skillRoots.map((skillPath) => path.posix.join(dir, skillPath))) : skillRoots;
|
|
648
967
|
const guardedSkillFallback = new UnmaterializedAwareSkillSource(filesystem, () => sessionEntry.sandbox.status === "running");
|
|
649
968
|
const workspace = new Workspace({
|
|
650
969
|
id: workspaceId,
|
|
@@ -663,6 +982,7 @@ function createWorkspaceFactory(options = {}) {
|
|
|
663
982
|
skillCacheReviewState.delete(workspaceId);
|
|
664
983
|
skillReviewChecks.delete(workspaceId);
|
|
665
984
|
evictSessionSandbox(session.id);
|
|
985
|
+
clearSessionEnvironment(session.sessionId);
|
|
666
986
|
await mastra?.removeWorkspace?.(workspaceId);
|
|
667
987
|
})) throw new Error(`Factory session ${session.sessionId} was retired during workspace materialization`);
|
|
668
988
|
fireEagerStart();
|
|
@@ -670,6 +990,6 @@ function createWorkspaceFactory(options = {}) {
|
|
|
670
990
|
};
|
|
671
991
|
}
|
|
672
992
|
//#endregion
|
|
673
|
-
export { BUNDLED_FACTORY_SKILLS_PATH, FACTORY_SKILL_NAMES, FactorySkillSource, FactoryWorkspaceRegistry, REVIEW_ONLY_FACTORY_SKILLS, createWorkspaceFactory, rescanFactorySkills, resolveLocalFactorySkillsPath };
|
|
993
|
+
export { BUNDLED_FACTORY_SKILLS_PATH, FACTORY_SKILL_NAMES, FactorySkillSource, FactoryWorkspaceRegistry, REVIEW_ONLY_FACTORY_SKILLS, createWorkspaceFactory, environmentSandboxContext, rescanFactorySkills, resolveLocalFactorySkillsPath, resolveProjectEnvironment };
|
|
674
994
|
|
|
675
995
|
//# sourceMappingURL=workspace.js.map
|