@mastra/factory 0.1.0-alpha.6 → 0.1.0-alpha.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +7 -0
- package/dist/factory.d.ts.map +1 -1
- package/dist/factory.js +140 -8
- package/dist/factory.js.map +1 -1
- package/dist/index.js +140 -8
- package/dist/index.js.map +1 -1
- package/dist/integrations/github/integration.js +108 -1
- package/dist/integrations/github/integration.js.map +1 -1
- package/dist/integrations/github/pat.d.ts +38 -0
- package/dist/integrations/github/pat.d.ts.map +1 -0
- package/dist/integrations/github/pat.js +48 -0
- package/dist/integrations/github/pat.js.map +1 -0
- package/dist/integrations/github/provenance.js.map +1 -1
- package/dist/integrations/github/routes.d.ts.map +1 -1
- package/dist/integrations/github/routes.js +94 -1
- package/dist/integrations/github/routes.js.map +1 -1
- package/dist/integrations/github/session-subscriptions.d.ts.map +1 -1
- package/dist/integrations/github/session-subscriptions.js +30 -0
- package/dist/integrations/github/session-subscriptions.js.map +1 -1
- package/dist/integrations/github/token-refresh.d.ts +6 -0
- package/dist/integrations/github/token-refresh.d.ts.map +1 -1
- package/dist/integrations/github/token-refresh.js +10 -0
- package/dist/integrations/github/token-refresh.js.map +1 -1
- package/dist/integrations/platform/github/integration.d.ts.map +1 -1
- package/dist/integrations/platform/github/integration.js +110 -2
- package/dist/integrations/platform/github/integration.js.map +1 -1
- package/dist/routes/surface.js +7 -1
- package/dist/routes/surface.js.map +1 -1
- package/dist/routes/work-items.js.map +1 -1
- package/dist/rules/start-coordinator.d.ts.map +1 -1
- package/dist/rules/start-coordinator.js +7 -1
- package/dist/rules/start-coordinator.js.map +1 -1
- package/dist/workspace.d.ts +5 -0
- package/dist/workspace.d.ts.map +1 -1
- package/dist/workspace.js +64 -5
- package/dist/workspace.js.map +1 -1
- package/package.json +6 -6
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"start-coordinator.d.ts","sourceRoot":"","sources":["../../src/rules/start-coordinator.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAC/D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;AACrE,OAAO,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;AAG9D,OAAO,KAAK,EAAwB,0BAA0B,EAAE,MAAM,2CAA2C,CAAC;AAClH,OAAO,KAAK,EAAE,mBAAmB,EAAE,gBAAgB,EAAE,MAAM,uCAAuC,CAAC;AACnG,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,yBAAyB,CAAC;AACxE,OAAO,KAAK,EAAE,gBAAgB,EAAE,uBAAuB,EAAE,MAAM,YAAY,CAAC;AAE5E,MAAM,WAAW,mBAAmB;IAClC,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,gBAAgB,EAAE,MAAM,CAAC;IACzB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACpC,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE;QAAE,IAAI,EAAE,QAAQ,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,GAAG;QAAE,IAAI,EAAE,OAAO,CAAC;QAAC,SAAS,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,CAAC;IAC1G,gBAAgB,EAAE,gBAAgB,CAAC;IACnC,QAAQ,EAAE;QACR,EAAE,CAAC,EAAE,MAAM,CAAC;QACZ,IAAI,EAAE,MAAM,CAAC;QACb,KAAK,EAAE,mBAAmB,CAAC;KAC5B,CAAC;IACF,cAAc,CAAC,EAAE,cAAc,CAAC;CACjC;AAED,qBAAa,2BAA4B,SAAQ,KAAK;IACpD,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC,uBAAuB,EAAE;QAAE,MAAM,EAAE,UAAU,CAAA;KAAE,CAAC,CAAC;gBAE9D,MAAM,EAAE,OAAO,CAAC,uBAAuB,EAAE;QAAE,MAAM,EAAE,UAAU,CAAA;KAAE,CAAC;CAK7E;AAED,MAAM,WAAW,0BAA0B;IACzC,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,aAAa,EAAE,SAAS,GAAG,QAAQ,GAAG,OAAO,GAAG,MAAM,GAAG,QAAQ,CAAC;IAClE,QAAQ,EAAE,OAAO,CAAC;CACnB;AAED,KAAK,iBAAiB,GAAG,eAAe,CAAC,eAAe,CAAC,CAAC;AAqD1D,qBAAa,uBAAuB;;gBAOhC,UAAU,EAAE,iBAAiB,EAC7B,OAAO,EAAE,gBAAgB,EACzB,iBAAiB,CAAC,EAAE,IAAI,CAAC,wBAAwB,EAAE,YAAY,CAAC,EAChE,aAAa,CAAC,EAAE,0BAA0B;IAQtC,OAAO,CAAC,OAAO,EAAE,mBAAmB,GAAG,OAAO,CAAC,0BAA0B,CAAC;
|
|
1
|
+
{"version":3,"file":"start-coordinator.d.ts","sourceRoot":"","sources":["../../src/rules/start-coordinator.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAC/D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;AACrE,OAAO,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;AAG9D,OAAO,KAAK,EAAwB,0BAA0B,EAAE,MAAM,2CAA2C,CAAC;AAClH,OAAO,KAAK,EAAE,mBAAmB,EAAE,gBAAgB,EAAE,MAAM,uCAAuC,CAAC;AACnG,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,yBAAyB,CAAC;AACxE,OAAO,KAAK,EAAE,gBAAgB,EAAE,uBAAuB,EAAE,MAAM,YAAY,CAAC;AAE5E,MAAM,WAAW,mBAAmB;IAClC,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,gBAAgB,EAAE,MAAM,CAAC;IACzB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACpC,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE;QAAE,IAAI,EAAE,QAAQ,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,GAAG;QAAE,IAAI,EAAE,OAAO,CAAC;QAAC,SAAS,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,CAAC;IAC1G,gBAAgB,EAAE,gBAAgB,CAAC;IACnC,QAAQ,EAAE;QACR,EAAE,CAAC,EAAE,MAAM,CAAC;QACZ,IAAI,EAAE,MAAM,CAAC;QACb,KAAK,EAAE,mBAAmB,CAAC;KAC5B,CAAC;IACF,cAAc,CAAC,EAAE,cAAc,CAAC;CACjC;AAED,qBAAa,2BAA4B,SAAQ,KAAK;IACpD,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC,uBAAuB,EAAE;QAAE,MAAM,EAAE,UAAU,CAAA;KAAE,CAAC,CAAC;gBAE9D,MAAM,EAAE,OAAO,CAAC,uBAAuB,EAAE;QAAE,MAAM,EAAE,UAAU,CAAA;KAAE,CAAC;CAK7E;AAED,MAAM,WAAW,0BAA0B;IACzC,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,aAAa,EAAE,SAAS,GAAG,QAAQ,GAAG,OAAO,GAAG,MAAM,GAAG,QAAQ,CAAC;IAClE,QAAQ,EAAE,OAAO,CAAC;CACnB;AAED,KAAK,iBAAiB,GAAG,eAAe,CAAC,eAAe,CAAC,CAAC;AAqD1D,qBAAa,uBAAuB;;gBAOhC,UAAU,EAAE,iBAAiB,EAC7B,OAAO,EAAE,gBAAgB,EACzB,iBAAiB,CAAC,EAAE,IAAI,CAAC,wBAAwB,EAAE,YAAY,CAAC,EAChE,aAAa,CAAC,EAAE,0BAA0B;IAQtC,OAAO,CAAC,OAAO,EAAE,mBAAmB,GAAG,OAAO,CAAC,0BAA0B,CAAC;CAgFjF"}
|
|
@@ -71,13 +71,19 @@ var FactoryStartCoordinator = class {
|
|
|
71
71
|
if (!request.requestContext) {
|
|
72
72
|
requestContext.set("user", { workosId: request.userId, organizationId: request.orgId });
|
|
73
73
|
}
|
|
74
|
+
const sessionState = {
|
|
75
|
+
factoryProjectId: request.factoryProjectId,
|
|
76
|
+
projectRepositoryId: sourceSession.projectRepositoryId
|
|
77
|
+
};
|
|
74
78
|
const session = await this.#controller.createSession({
|
|
75
79
|
id: sourceSession.sessionId,
|
|
76
80
|
ownerId: request.userId,
|
|
77
81
|
resourceId: sourceSession.sessionId,
|
|
78
82
|
threadId: sourceSession.sessionId,
|
|
79
|
-
requestContext
|
|
83
|
+
requestContext,
|
|
84
|
+
tags: sessionState
|
|
80
85
|
});
|
|
86
|
+
await session.state.set(sessionState);
|
|
81
87
|
const threadId = await configureThread(session, request);
|
|
82
88
|
const kickoffMessage = await resolveKickoffMessage(session, request.invocation);
|
|
83
89
|
const prepared = await storage.prepareRunStart({
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/rules/start-coordinator.ts"],"sourcesContent":["import type { MastraCodeState } from '@mastra/code-sdk/schema';\nimport type { AgentController } from '@mastra/core/agent-controller';\nimport { RequestContext } from '@mastra/core/request-context';\nimport { formatSkillActivation } from '@mastra/core/workspace';\n\nimport type { SourceControlSession, SourceControlStorageHandle } from '../storage/domains/source-control/base.js';\nimport type { CreateWorkItemInput, WorkItemsStorage } from '../storage/domains/work-items/base.js';\nimport type { FactoryTransitionService } from './transition-service.js';\nimport type { FactoryRuleStage, FactoryTransitionResult } from './types.js';\n\nexport interface FactoryStartRequest {\n orgId: string;\n userId: string;\n factoryProjectId: string;\n sessionId: string;\n threadTitle: string;\n threadTags?: Record<string, string>;\n kickoffKey: string;\n invocation?: { type: 'prompt'; prompt: string } | { type: 'skill'; skillName: string; arguments: string };\n destinationStage: FactoryRuleStage;\n workItem: {\n id?: string;\n role: string;\n input: CreateWorkItemInput;\n };\n requestContext?: RequestContext;\n}\n\nexport class FactoryStartTransitionError extends Error {\n readonly result: Extract<FactoryTransitionResult, { status: 'rejected' }>;\n\n constructor(result: Extract<FactoryTransitionResult, { status: 'rejected' }>) {\n super(result.reason);\n this.name = 'FactoryStartTransitionError';\n this.result = result;\n }\n}\n\nexport interface FactoryStartPreparedResult {\n workItemId: string;\n bindingId: string;\n threadId: string;\n resourceId: string;\n sessionId: string;\n branch: string;\n revision: number;\n kickoffStatus: 'pending' | 'leased' | 'retry' | 'sent' | 'failed';\n replayed: boolean;\n}\n\ntype FactoryController = AgentController<MastraCodeState>;\ntype FactorySession = Awaited<ReturnType<FactoryController['createSession']>>;\n\nfunction escapeSkillBoundary(value: string): string {\n return value.replaceAll('</skill>', '</skill>');\n}\n\nasync function resolveKickoffMessage(\n session: FactorySession,\n invocation: FactoryStartRequest['invocation'],\n): Promise<string | null> {\n if (!invocation) return null;\n if (invocation.type === 'prompt') return invocation.prompt;\n\n const skills = session.getWorkspace().skills;\n await skills?.maybeRefresh();\n const skill = await skills?.get(invocation.skillName);\n if (!skill || skill['user-invocable'] === false) {\n throw new Error(`Skill not found: ${invocation.skillName}.`);\n }\n const args = invocation.arguments.trim();\n const content = `${formatSkillActivation(skill)}${args ? `\\n\\nARGUMENTS: ${args}` : ''}`.trim();\n return `<skill name=\"${skill.name}\">\\n${escapeSkillBoundary(content)}\\n</skill>`;\n}\n\nasync function resolveSourceSession(\n storage: SourceControlStorageHandle,\n request: FactoryStartRequest,\n): Promise<SourceControlSession> {\n const session = await storage.sessions.getBySessionId(request.sessionId);\n if (!session || session.orgId !== request.orgId || session.userId !== request.userId) {\n throw new Error('Factory session not found');\n }\n const projectRepository = await storage.projectRepositories.get({\n orgId: request.orgId,\n id: session.projectRepositoryId,\n });\n if (!projectRepository) throw new Error('Factory session repository not found');\n const connection = await storage.connections.get({ orgId: request.orgId, id: projectRepository.connectionId });\n if (!connection || connection.factoryProjectId !== request.factoryProjectId) {\n throw new Error('Factory session does not belong to this project');\n }\n return session;\n}\n\nasync function configureThread(session: FactorySession, request: FactoryStartRequest): Promise<string> {\n const threadId = session.thread.requireId();\n await session.thread.rename({ title: request.threadTitle });\n const settings = { ...(request.threadTags ?? {}), factorySessionId: request.sessionId };\n await Promise.all(Object.entries(settings).map(([key, value]) => session.thread.setSetting({ key, value })));\n return threadId;\n}\n\nexport class FactoryStartCoordinator {\n readonly #controller: FactoryController;\n readonly #storage: WorkItemsStorage;\n readonly #transitionService?: Pick<FactoryTransitionService, 'transition'>;\n readonly #sourceControl?: SourceControlStorageHandle;\n\n constructor(\n controller: FactoryController,\n storage: WorkItemsStorage,\n transitionService?: Pick<FactoryTransitionService, 'transition'>,\n sourceControl?: SourceControlStorageHandle,\n ) {\n this.#controller = controller;\n this.#storage = storage;\n this.#transitionService = transitionService;\n this.#sourceControl = sourceControl;\n }\n\n async prepare(request: FactoryStartRequest): Promise<FactoryStartPreparedResult> {\n const storage = this.#storage;\n if (!this.#sourceControl) throw new Error('Factory source control storage is unavailable');\n const sourceSession = await resolveSourceSession(this.#sourceControl, request);\n const requestContext = request.requestContext ?? new RequestContext();\n if (!request.requestContext) {\n requestContext.set('user', { workosId: request.userId, organizationId: request.orgId });\n }\n const session = await this.#controller.createSession({\n id: sourceSession.sessionId,\n ownerId: request.userId,\n resourceId: sourceSession.sessionId,\n threadId: sourceSession.sessionId,\n requestContext,\n });\n const threadId = await configureThread(session, request);\n const kickoffMessage = await resolveKickoffMessage(session, request.invocation);\n const prepared = await storage.prepareRunStart({\n orgId: request.orgId,\n userId: request.userId,\n factoryProjectId: request.factoryProjectId,\n workItem: { id: request.workItem.id, input: request.workItem.input },\n role: request.workItem.role,\n session: { sessionId: sourceSession.sessionId, branch: sourceSession.branch, threadId },\n resourceId: sourceSession.sessionId,\n kickoffKey: request.kickoffKey,\n kickoffMessage,\n });\n await session.thread.setSetting({ key: 'factoryWorkItemId', value: prepared.item.id });\n\n let revision = prepared.item.revision;\n if (prepared.item.stages.length !== 1 || prepared.item.stages[0] !== request.destinationStage) {\n if (!this.#transitionService) throw new Error('Factory transition service is unavailable.');\n const transition = await this.#transitionService.transition({\n orgId: request.orgId,\n factoryProjectId: request.factoryProjectId,\n workItemId: prepared.item.id,\n board: prepared.item.externalSource?.type === 'pull-request' ? 'review' : 'work',\n stage: request.destinationStage,\n expectedRevision: prepared.item.revision,\n actor: { type: 'human', id: request.userId },\n ingress: { type: 'human', identity: `start:${request.kickoffKey}:transition` },\n cause: 'run_start',\n });\n if (transition.status === 'rejected') {\n await storage.markPendingStart(prepared.binding.id, 'failed', transition.reason);\n throw new FactoryStartTransitionError(transition);\n }\n revision = transition.revision;\n }\n\n if (kickoffMessage === null) {\n await storage.markPendingStart(prepared.binding.id, 'sent');\n prepared.pendingStart.status = 'sent';\n }\n\n return {\n workItemId: prepared.item.id,\n bindingId: prepared.binding.id,\n threadId,\n resourceId: sourceSession.sessionId,\n sessionId: sourceSession.sessionId,\n branch: sourceSession.branch,\n revision,\n kickoffStatus: prepared.pendingStart.status,\n replayed: prepared.replayed,\n };\n }\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../src/rules/start-coordinator.ts"],"sourcesContent":["import type { MastraCodeState } from '@mastra/code-sdk/schema';\nimport type { AgentController } from '@mastra/core/agent-controller';\nimport { RequestContext } from '@mastra/core/request-context';\nimport { formatSkillActivation } from '@mastra/core/workspace';\n\nimport type { SourceControlSession, SourceControlStorageHandle } from '../storage/domains/source-control/base.js';\nimport type { CreateWorkItemInput, WorkItemsStorage } from '../storage/domains/work-items/base.js';\nimport type { FactoryTransitionService } from './transition-service.js';\nimport type { FactoryRuleStage, FactoryTransitionResult } from './types.js';\n\nexport interface FactoryStartRequest {\n orgId: string;\n userId: string;\n factoryProjectId: string;\n sessionId: string;\n threadTitle: string;\n threadTags?: Record<string, string>;\n kickoffKey: string;\n invocation?: { type: 'prompt'; prompt: string } | { type: 'skill'; skillName: string; arguments: string };\n destinationStage: FactoryRuleStage;\n workItem: {\n id?: string;\n role: string;\n input: CreateWorkItemInput;\n };\n requestContext?: RequestContext;\n}\n\nexport class FactoryStartTransitionError extends Error {\n readonly result: Extract<FactoryTransitionResult, { status: 'rejected' }>;\n\n constructor(result: Extract<FactoryTransitionResult, { status: 'rejected' }>) {\n super(result.reason);\n this.name = 'FactoryStartTransitionError';\n this.result = result;\n }\n}\n\nexport interface FactoryStartPreparedResult {\n workItemId: string;\n bindingId: string;\n threadId: string;\n resourceId: string;\n sessionId: string;\n branch: string;\n revision: number;\n kickoffStatus: 'pending' | 'leased' | 'retry' | 'sent' | 'failed';\n replayed: boolean;\n}\n\ntype FactoryController = AgentController<MastraCodeState>;\ntype FactorySession = Awaited<ReturnType<FactoryController['createSession']>>;\n\nfunction escapeSkillBoundary(value: string): string {\n return value.replaceAll('</skill>', '</skill>');\n}\n\nasync function resolveKickoffMessage(\n session: FactorySession,\n invocation: FactoryStartRequest['invocation'],\n): Promise<string | null> {\n if (!invocation) return null;\n if (invocation.type === 'prompt') return invocation.prompt;\n\n const skills = session.getWorkspace().skills;\n await skills?.maybeRefresh();\n const skill = await skills?.get(invocation.skillName);\n if (!skill || skill['user-invocable'] === false) {\n throw new Error(`Skill not found: ${invocation.skillName}.`);\n }\n const args = invocation.arguments.trim();\n const content = `${formatSkillActivation(skill)}${args ? `\\n\\nARGUMENTS: ${args}` : ''}`.trim();\n return `<skill name=\"${skill.name}\">\\n${escapeSkillBoundary(content)}\\n</skill>`;\n}\n\nasync function resolveSourceSession(\n storage: SourceControlStorageHandle,\n request: FactoryStartRequest,\n): Promise<SourceControlSession> {\n const session = await storage.sessions.getBySessionId(request.sessionId);\n if (!session || session.orgId !== request.orgId || session.userId !== request.userId) {\n throw new Error('Factory session not found');\n }\n const projectRepository = await storage.projectRepositories.get({\n orgId: request.orgId,\n id: session.projectRepositoryId,\n });\n if (!projectRepository) throw new Error('Factory session repository not found');\n const connection = await storage.connections.get({ orgId: request.orgId, id: projectRepository.connectionId });\n if (!connection || connection.factoryProjectId !== request.factoryProjectId) {\n throw new Error('Factory session does not belong to this project');\n }\n return session;\n}\n\nasync function configureThread(session: FactorySession, request: FactoryStartRequest): Promise<string> {\n const threadId = session.thread.requireId();\n await session.thread.rename({ title: request.threadTitle });\n const settings = { ...(request.threadTags ?? {}), factorySessionId: request.sessionId };\n await Promise.all(Object.entries(settings).map(([key, value]) => session.thread.setSetting({ key, value })));\n return threadId;\n}\n\nexport class FactoryStartCoordinator {\n readonly #controller: FactoryController;\n readonly #storage: WorkItemsStorage;\n readonly #transitionService?: Pick<FactoryTransitionService, 'transition'>;\n readonly #sourceControl?: SourceControlStorageHandle;\n\n constructor(\n controller: FactoryController,\n storage: WorkItemsStorage,\n transitionService?: Pick<FactoryTransitionService, 'transition'>,\n sourceControl?: SourceControlStorageHandle,\n ) {\n this.#controller = controller;\n this.#storage = storage;\n this.#transitionService = transitionService;\n this.#sourceControl = sourceControl;\n }\n\n async prepare(request: FactoryStartRequest): Promise<FactoryStartPreparedResult> {\n const storage = this.#storage;\n if (!this.#sourceControl) throw new Error('Factory source control storage is unavailable');\n const sourceSession = await resolveSourceSession(this.#sourceControl, request);\n const requestContext = request.requestContext ?? new RequestContext();\n if (!request.requestContext) {\n requestContext.set('user', { workosId: request.userId, organizationId: request.orgId });\n }\n const sessionState = {\n factoryProjectId: request.factoryProjectId,\n projectRepositoryId: sourceSession.projectRepositoryId,\n };\n const session = await this.#controller.createSession({\n id: sourceSession.sessionId,\n ownerId: request.userId,\n resourceId: sourceSession.sessionId,\n threadId: sourceSession.sessionId,\n requestContext,\n tags: sessionState,\n });\n // Bound-agent authority gates (the transition tool, the factory-phase\n // processor, workspace token selection) resolve the session address from\n // controller state. Seed it server-side — `tags` covers fresh creation,\n // the explicit setState covers get-or-create returning a session another\n // caller created without them — so autonomous runs never depend on a\n // browser connecting to populate the state.\n await session.state.set(sessionState);\n const threadId = await configureThread(session, request);\n const kickoffMessage = await resolveKickoffMessage(session, request.invocation);\n const prepared = await storage.prepareRunStart({\n orgId: request.orgId,\n userId: request.userId,\n factoryProjectId: request.factoryProjectId,\n workItem: { id: request.workItem.id, input: request.workItem.input },\n role: request.workItem.role,\n session: { sessionId: sourceSession.sessionId, branch: sourceSession.branch, threadId },\n resourceId: sourceSession.sessionId,\n kickoffKey: request.kickoffKey,\n kickoffMessage,\n });\n await session.thread.setSetting({ key: 'factoryWorkItemId', value: prepared.item.id });\n\n let revision = prepared.item.revision;\n if (prepared.item.stages.length !== 1 || prepared.item.stages[0] !== request.destinationStage) {\n if (!this.#transitionService) throw new Error('Factory transition service is unavailable.');\n const transition = await this.#transitionService.transition({\n orgId: request.orgId,\n factoryProjectId: request.factoryProjectId,\n workItemId: prepared.item.id,\n board: prepared.item.externalSource?.type === 'pull-request' ? 'review' : 'work',\n stage: request.destinationStage,\n expectedRevision: prepared.item.revision,\n actor: { type: 'human', id: request.userId },\n ingress: { type: 'human', identity: `start:${request.kickoffKey}:transition` },\n cause: 'run_start',\n });\n if (transition.status === 'rejected') {\n await storage.markPendingStart(prepared.binding.id, 'failed', transition.reason);\n throw new FactoryStartTransitionError(transition);\n }\n revision = transition.revision;\n }\n\n if (kickoffMessage === null) {\n await storage.markPendingStart(prepared.binding.id, 'sent');\n prepared.pendingStart.status = 'sent';\n }\n\n return {\n workItemId: prepared.item.id,\n bindingId: prepared.binding.id,\n threadId,\n resourceId: sourceSession.sessionId,\n sessionId: sourceSession.sessionId,\n branch: sourceSession.branch,\n revision,\n kickoffStatus: prepared.pendingStart.status,\n replayed: prepared.replayed,\n };\n }\n}\n"],"mappings":"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","names":[]}
|
package/dist/workspace.d.ts
CHANGED
|
@@ -4,6 +4,7 @@ import { LocalSandbox, Workspace } from '@mastra/core/workspace';
|
|
|
4
4
|
import type { MastraFactorySandboxConfig } from './factory.js';
|
|
5
5
|
import type { GithubIntegration } from './integrations/github/integration.js';
|
|
6
6
|
import type { SandboxFleet } from './sandbox/fleet.js';
|
|
7
|
+
import type { WorkItemsStorage } from './storage/domains/work-items/base.js';
|
|
7
8
|
export declare function checkpointNameForSession(sessionId: string): string;
|
|
8
9
|
type DynamicWorkspaceContext = Parameters<typeof getDynamicWorkspace>[0];
|
|
9
10
|
export interface CreateWorkspaceFactoryOptions {
|
|
@@ -13,6 +14,10 @@ export interface CreateWorkspaceFactoryOptions {
|
|
|
13
14
|
github?: GithubIntegration;
|
|
14
15
|
/** Fleet the per-session sandboxes are provisioned/reattached through. */
|
|
15
16
|
fleet?: SandboxFleet;
|
|
17
|
+
/** Work-items storage used to resolve the session's run-binding role, so
|
|
18
|
+
* review-board sessions get the reviewer PAT as `GH_TOKEN`. Optional —
|
|
19
|
+
* without it every session uses the default (worker) PAT. */
|
|
20
|
+
workItems?: Pick<WorkItemsStorage, 'findRunBindingBySession'>;
|
|
16
21
|
}
|
|
17
22
|
export declare function createWorkspaceFactory(options?: CreateWorkspaceFactoryOptions): ({ requestContext, mastra, skillExtension }: DynamicWorkspaceContext) => Promise<Workspace<import("@mastra/core/workspace").WorkspaceFilesystem | undefined, import("@mastra/core/workspace").WorkspaceSandbox | undefined, undefined> | Workspace<import("@mastra/core/workspace").LocalFilesystem, LocalSandbox, undefined> | Workspace<SandboxFilesystem, import("@mastra/core/workspace").WorkspaceSandbox, undefined>>;
|
|
18
23
|
export declare const getFactoryWorkspace: ({ requestContext, mastra, skillExtension }: DynamicWorkspaceContext) => Promise<Workspace<import("@mastra/core/workspace").WorkspaceFilesystem | undefined, import("@mastra/core/workspace").WorkspaceSandbox | undefined, undefined> | Workspace<import("@mastra/core/workspace").LocalFilesystem, LocalSandbox, undefined> | Workspace<SandboxFilesystem, import("@mastra/core/workspace").WorkspaceSandbox, undefined>>;
|
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,EAAE,mBAAmB,EAAE,MAAM,mCAAmC,CAAC;AAKxE,OAAO,EAAE,YAAY,EAAoB,SAAS,EAAE,MAAM,wBAAwB,CAAC;AAInF,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,cAAc,CAAC;AAC/D,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,sCAAsC,CAAC;
|
|
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,EAAE,mBAAmB,EAAE,MAAM,mCAAmC,CAAC;AAKxE,OAAO,EAAE,YAAY,EAAoB,SAAS,EAAE,MAAM,wBAAwB,CAAC;AAInF,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,cAAc,CAAC;AAC/D,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,sCAAsC,CAAC;AAM9E,OAAO,KAAK,EAAuB,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAC5E,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,sCAAsC,CAAC;AAK7E,wBAAgB,wBAAwB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAElE;AA+ED,KAAK,uBAAuB,GAAG,UAAU,CAAC,OAAO,mBAAmB,CAAC,CAAC,CAAC,CAAC,CAAC;AAEzE,MAAM,WAAW,6BAA6B;IAC5C,wEAAwE;IACxE,OAAO,CAAC,EAAE,0BAA0B,CAAC;IACrC,gFAAgF;IAChF,MAAM,CAAC,EAAE,iBAAiB,CAAC;IAC3B,0EAA0E;IAC1E,KAAK,CAAC,EAAE,YAAY,CAAC;IACrB;;iEAE6D;IAC7D,SAAS,CAAC,EAAE,IAAI,CAAC,gBAAgB,EAAE,yBAAyB,CAAC,CAAC;CAC/D;AAED,wBAAgB,sBAAsB,CAAC,OAAO,GAAE,6BAAkC,IAKlE,4CAA4C,uBAAuB,wVA2IlF;AAED,eAAO,MAAM,mBAAmB,+CA7I4B,uBAAuB,uVA6IxB,CAAC"}
|
package/dist/workspace.js
CHANGED
|
@@ -21,6 +21,25 @@ import {
|
|
|
21
21
|
function getFactoryAuthUserId(user) {
|
|
22
22
|
return user?.workosId ?? user?.id;
|
|
23
23
|
}
|
|
24
|
+
function getFactoryAuthOrgId(user) {
|
|
25
|
+
return user?.organizationId;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
// src/integrations/github/pat.ts
|
|
29
|
+
var PAT_SETTINGS_USER_ID = "__github_org_settings__";
|
|
30
|
+
function asToken(value) {
|
|
31
|
+
return typeof value === "string" && value.length > 0 ? value : null;
|
|
32
|
+
}
|
|
33
|
+
async function getGithubPat(getStorage, orgId, kind = "default") {
|
|
34
|
+
try {
|
|
35
|
+
const settings = await getStorage().settings.get(orgId, PAT_SETTINGS_USER_ID);
|
|
36
|
+
if (!settings) return null;
|
|
37
|
+
if (kind === "reviewer") return asToken(settings.reviewerPat) ?? asToken(settings.pat);
|
|
38
|
+
return asToken(settings.pat);
|
|
39
|
+
} catch {
|
|
40
|
+
return null;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
24
43
|
|
|
25
44
|
// src/integrations/github/sandbox.ts
|
|
26
45
|
import { createHash } from "crypto";
|
|
@@ -195,9 +214,35 @@ async function runWorktreeSetup(sandbox, worktreePath, command) {
|
|
|
195
214
|
|
|
196
215
|
// src/integrations/github/token-refresh.ts
|
|
197
216
|
var GITHUB_TOKEN_INJECTOR_CONTEXT_KEY = "factoryGithubTokenInjector";
|
|
217
|
+
var GITHUB_PAT_KIND_CONTEXT_KEY = "factoryGithubPatKind";
|
|
198
218
|
function registerGithubTokenInjector(requestContext, injector) {
|
|
199
219
|
requestContext.set(GITHUB_TOKEN_INJECTOR_CONTEXT_KEY, injector);
|
|
200
220
|
}
|
|
221
|
+
function registerGithubPatKind(requestContext, kind) {
|
|
222
|
+
requestContext.set(GITHUB_PAT_KIND_CONTEXT_KEY, kind);
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
// src/rules/binding-context.ts
|
|
226
|
+
function getFactorySessionCoordinates(requestContext) {
|
|
227
|
+
if (!requestContext || typeof requestContext.get !== "function") return null;
|
|
228
|
+
const context = requestContext.get("controller");
|
|
229
|
+
const factoryProjectId = context?.getState().factoryProjectId;
|
|
230
|
+
if (!context?.threadId || !context.resourceId || !factoryProjectId) return null;
|
|
231
|
+
return {
|
|
232
|
+
factoryProjectId,
|
|
233
|
+
threadId: context.threadId,
|
|
234
|
+
resourceId: context.resourceId,
|
|
235
|
+
sessionId: context.resourceId
|
|
236
|
+
};
|
|
237
|
+
}
|
|
238
|
+
function getFactorySessionAddress(requestContext) {
|
|
239
|
+
const coordinates = getFactorySessionCoordinates(requestContext);
|
|
240
|
+
if (!coordinates || !requestContext || typeof requestContext.get !== "function") return null;
|
|
241
|
+
const user = requestContext.get("user");
|
|
242
|
+
const orgId = getFactoryAuthOrgId(user);
|
|
243
|
+
if (!orgId) return null;
|
|
244
|
+
return { orgId, ...coordinates };
|
|
245
|
+
}
|
|
201
246
|
|
|
202
247
|
// src/workspace.ts
|
|
203
248
|
var WORKSPACE_ID_PREFIX = "mfw";
|
|
@@ -264,7 +309,7 @@ var factorySkillExtension = {
|
|
|
264
309
|
createSource: (fallback, fallbackSkillRoots) => new FactorySkillSource(fallback, fallbackSkillRoots)
|
|
265
310
|
};
|
|
266
311
|
function createWorkspaceFactory(options = {}) {
|
|
267
|
-
const { sandbox: sandboxConfig, github, fleet } = options;
|
|
312
|
+
const { sandbox: sandboxConfig, github, fleet, workItems } = options;
|
|
268
313
|
const isLocalSandbox = sandboxConfig?.machine instanceof LocalSandbox;
|
|
269
314
|
const githubTokenInjectors = /* @__PURE__ */ new Map();
|
|
270
315
|
return async ({ requestContext, mastra, skillExtension }) => {
|
|
@@ -318,8 +363,11 @@ function createWorkspaceFactory(options = {}) {
|
|
|
318
363
|
const existing = mastra?.getWorkspaceById(workspaceId);
|
|
319
364
|
if (existing) {
|
|
320
365
|
existing.setToolsConfig(MASTRACODE_WORKSPACE_TOOLS);
|
|
321
|
-
const
|
|
322
|
-
if (
|
|
366
|
+
const registered = githubTokenInjectors.get(workspaceId);
|
|
367
|
+
if (registered) {
|
|
368
|
+
registerGithubTokenInjector(requestContext, registered.inject);
|
|
369
|
+
registerGithubPatKind(requestContext, registered.patKind);
|
|
370
|
+
}
|
|
323
371
|
return existing;
|
|
324
372
|
}
|
|
325
373
|
} catch {
|
|
@@ -330,9 +378,19 @@ function createWorkspaceFactory(options = {}) {
|
|
|
330
378
|
});
|
|
331
379
|
const token = access.authorization?.token;
|
|
332
380
|
if (!token) throw new Error("Repository access did not include a bearer token for the Factory session");
|
|
381
|
+
let patKind = "default";
|
|
382
|
+
if (workItems) {
|
|
383
|
+
try {
|
|
384
|
+
const address = getFactorySessionAddress(requestContext);
|
|
385
|
+
const runBinding = address ? await workItems.findRunBindingBySession(address) : null;
|
|
386
|
+
if (runBinding?.role === "review" && runBinding.orgId === session.orgId) patKind = "reviewer";
|
|
387
|
+
} catch {
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
const ghCliToken = await getGithubPat(() => github.integrationStorage, session.orgId, patKind) ?? token;
|
|
333
391
|
const sandbox = await fleet.ensureSandbox(
|
|
334
392
|
binding,
|
|
335
|
-
{ GH_TOKEN:
|
|
393
|
+
{ GH_TOKEN: ghCliToken },
|
|
336
394
|
void 0,
|
|
337
395
|
isLocalSandbox ? { workingDirectory: workdir } : {}
|
|
338
396
|
);
|
|
@@ -356,8 +414,9 @@ function createWorkspaceFactory(options = {}) {
|
|
|
356
414
|
}
|
|
357
415
|
sandbox.setEnvironmentVariable("GH_TOKEN", freshToken);
|
|
358
416
|
};
|
|
359
|
-
githubTokenInjectors.set(workspaceId, injectGithubToken);
|
|
417
|
+
githubTokenInjectors.set(workspaceId, { inject: injectGithubToken, patKind });
|
|
360
418
|
registerGithubTokenInjector(requestContext, injectGithubToken);
|
|
419
|
+
registerGithubPatKind(requestContext, patKind);
|
|
361
420
|
const filesystem = new SandboxFilesystem({ sandbox, workdir });
|
|
362
421
|
const projectSkillPaths = [path2.join(configDir, "skills"), ".claude/skills", ".agents/skills"];
|
|
363
422
|
const skillPaths = [...effectiveSkillExtension?.paths ?? [], ...projectSkillPaths];
|