@mastra/factory 0.5.1-alpha.0 → 0.6.0-alpha.10
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 +211 -0
- package/dist/auth.d.ts +17 -0
- package/dist/auth.d.ts.map +1 -1
- package/dist/auth.js +19 -1
- package/dist/auth.js.map +1 -1
- package/dist/capabilities/intake.d.ts +1 -0
- package/dist/capabilities/intake.d.ts.map +1 -1
- package/dist/capabilities/version-control.d.ts +3 -0
- package/dist/capabilities/version-control.d.ts.map +1 -1
- package/dist/factory.d.ts +10 -0
- package/dist/factory.d.ts.map +1 -1
- package/dist/factory.js +17 -4
- package/dist/factory.js.map +1 -1
- package/dist/integrations/base.d.ts +6 -0
- package/dist/integrations/base.d.ts.map +1 -1
- package/dist/integrations/github/integration.d.ts +14 -1
- package/dist/integrations/github/integration.d.ts.map +1 -1
- package/dist/integrations/github/integration.js +61 -3
- package/dist/integrations/github/integration.js.map +1 -1
- package/dist/integrations/github/issue-reconciler.d.ts +24 -0
- package/dist/integrations/github/issue-reconciler.d.ts.map +1 -0
- package/dist/integrations/github/issue-reconciler.js +104 -0
- package/dist/integrations/github/issue-reconciler.js.map +1 -0
- package/dist/integrations/github/reconcile-worker.d.ts +8 -0
- package/dist/integrations/github/reconcile-worker.d.ts.map +1 -1
- package/dist/integrations/github/reconcile-worker.js +38 -1
- package/dist/integrations/github/reconcile-worker.js.map +1 -1
- package/dist/integrations/github/routes.d.ts.map +1 -1
- package/dist/integrations/github/routes.js +65 -52
- package/dist/integrations/github/routes.js.map +1 -1
- package/dist/integrations/github/rules.d.ts +37 -2
- package/dist/integrations/github/rules.d.ts.map +1 -1
- package/dist/integrations/github/rules.js +150 -14
- package/dist/integrations/github/rules.js.map +1 -1
- package/dist/integrations/github/sandbox-release.d.ts +16 -1
- package/dist/integrations/github/sandbox-release.d.ts.map +1 -1
- package/dist/integrations/github/sandbox-release.js +42 -1
- package/dist/integrations/github/sandbox-release.js.map +1 -1
- package/dist/integrations/github/sandbox.d.ts.map +1 -1
- package/dist/integrations/github/sandbox.js +74 -8
- 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 +16 -12
- package/dist/integrations/github/session-subscriptions.js.map +1 -1
- package/dist/integrations/issue-reconcile-worker.d.ts +19 -0
- package/dist/integrations/issue-reconcile-worker.d.ts.map +1 -0
- package/dist/integrations/issue-reconcile-worker.js +98 -0
- package/dist/integrations/issue-reconcile-worker.js.map +1 -0
- package/dist/integrations/issue-reconciler.d.ts +47 -0
- package/dist/integrations/issue-reconciler.d.ts.map +1 -0
- package/dist/integrations/issue-reconciler.js +104 -0
- package/dist/integrations/issue-reconciler.js.map +1 -0
- package/dist/integrations/linear/integration.d.ts +4 -0
- package/dist/integrations/linear/integration.d.ts.map +1 -1
- package/dist/integrations/linear/integration.js +19 -2
- package/dist/integrations/linear/integration.js.map +1 -1
- package/dist/integrations/linear/issue-reconciler.d.ts +6 -0
- package/dist/integrations/linear/issue-reconciler.d.ts.map +1 -0
- package/dist/integrations/linear/issue-reconciler.js +64 -0
- package/dist/integrations/linear/issue-reconciler.js.map +1 -0
- package/dist/integrations/linear/routes.d.ts.map +1 -1
- package/dist/integrations/linear/routes.js +1 -0
- package/dist/integrations/linear/routes.js.map +1 -1
- package/dist/integrations/linear/rules.d.ts +2 -0
- package/dist/integrations/linear/rules.d.ts.map +1 -1
- package/dist/integrations/linear/rules.js +5 -2
- package/dist/integrations/linear/rules.js.map +1 -1
- package/dist/integrations/platform/github/event-worker.d.ts +7 -0
- package/dist/integrations/platform/github/event-worker.d.ts.map +1 -1
- package/dist/integrations/platform/github/event-worker.js +24 -0
- package/dist/integrations/platform/github/event-worker.js.map +1 -1
- package/dist/integrations/platform/github/integration.d.ts +13 -3
- package/dist/integrations/platform/github/integration.d.ts.map +1 -1
- package/dist/integrations/platform/github/integration.js +42 -1
- package/dist/integrations/platform/github/integration.js.map +1 -1
- package/dist/integrations/platform/linear/event-worker.d.ts +105 -0
- package/dist/integrations/platform/linear/event-worker.d.ts.map +1 -0
- package/dist/integrations/platform/linear/event-worker.js +380 -0
- package/dist/integrations/platform/linear/event-worker.js.map +1 -0
- package/dist/integrations/platform/linear/integration.d.ts +9 -0
- package/dist/integrations/platform/linear/integration.d.ts.map +1 -1
- package/dist/integrations/platform/linear/integration.js +37 -1
- package/dist/integrations/platform/linear/integration.js.map +1 -1
- package/dist/integrations/slack/integration.d.ts.map +1 -1
- package/dist/integrations/slack/integration.js +3 -2
- package/dist/integrations/slack/integration.js.map +1 -1
- package/dist/integrations/slack/slack.d.ts +37 -110
- package/dist/integrations/slack/slack.d.ts.map +1 -1
- package/dist/integrations/slack/slack.js +49 -44
- package/dist/integrations/slack/slack.js.map +1 -1
- package/dist/routes/config.d.ts +25 -0
- package/dist/routes/config.d.ts.map +1 -1
- package/dist/routes/config.js +63 -1
- package/dist/routes/config.js.map +1 -1
- package/dist/routes/fs.d.ts +16 -2
- package/dist/routes/fs.d.ts.map +1 -1
- package/dist/routes/fs.js +47 -5
- package/dist/routes/fs.js.map +1 -1
- package/dist/routes/intake.d.ts.map +1 -1
- package/dist/routes/intake.js +13 -5
- package/dist/routes/intake.js.map +1 -1
- package/dist/routes/surface.d.ts +13 -1
- package/dist/routes/surface.d.ts.map +1 -1
- package/dist/routes/surface.js +20 -9
- package/dist/routes/surface.js.map +1 -1
- package/dist/rules/binding-context.d.ts +28 -1
- package/dist/rules/binding-context.d.ts.map +1 -1
- package/dist/rules/binding-context.js +68 -3
- package/dist/rules/binding-context.js.map +1 -1
- package/dist/rules/defaults.d.ts.map +1 -1
- package/dist/rules/defaults.js +71 -5
- package/dist/rules/defaults.js.map +1 -1
- package/dist/rules/start-coordinator.d.ts.map +1 -1
- package/dist/rules/start-coordinator.js +8 -27
- package/dist/rules/start-coordinator.js.map +1 -1
- package/dist/rules/tools.d.ts +2 -0
- package/dist/rules/tools.d.ts.map +1 -1
- package/dist/rules/tools.js +15 -6
- package/dist/rules/tools.js.map +1 -1
- package/dist/rules/types.d.ts +17 -2
- package/dist/rules/types.d.ts.map +1 -1
- package/dist/rules/types.js +2 -1
- package/dist/rules/types.js.map +1 -1
- package/dist/session/factory-session.d.ts +116 -0
- package/dist/session/factory-session.d.ts.map +1 -0
- package/dist/session/factory-session.js +162 -0
- package/dist/session/factory-session.js.map +1 -0
- package/dist/session/filesystem-capture.d.ts +26 -0
- package/dist/session/filesystem-capture.d.ts.map +1 -0
- package/dist/session/filesystem-capture.js +75 -0
- package/dist/session/filesystem-capture.js.map +1 -0
- package/dist/storage/domains/audit/domain.d.ts +9 -2
- package/dist/storage/domains/audit/domain.d.ts.map +1 -1
- package/dist/storage/domains/audit/domain.js +106 -4
- package/dist/storage/domains/audit/domain.js.map +1 -1
- package/dist/storage/domains/filesystem/base.d.ts +26 -0
- package/dist/storage/domains/filesystem/base.d.ts.map +1 -0
- package/dist/storage/domains/filesystem/base.js +74 -0
- package/dist/storage/domains/filesystem/base.js.map +1 -0
- package/dist/storage/domains/projects/base.d.ts +1 -0
- package/dist/storage/domains/projects/base.d.ts.map +1 -1
- package/dist/storage/domains/projects/base.js +3 -0
- package/dist/storage/domains/projects/base.js.map +1 -1
- package/dist/storage/domains/source-control/base.d.ts +2 -0
- package/dist/storage/domains/source-control/base.d.ts.map +1 -1
- package/dist/storage/domains/source-control/base.js +6 -0
- package/dist/storage/domains/source-control/base.js.map +1 -1
- package/dist/storage/domains/source-control/inmemory.d.ts.map +1 -1
- package/dist/storage/domains/source-control/inmemory.js +3 -0
- package/dist/storage/domains/source-control/inmemory.js.map +1 -1
- package/dist/storage/domains/work-items/base.d.ts +11 -0
- package/dist/storage/domains/work-items/base.d.ts.map +1 -1
- package/dist/storage/domains/work-items/base.js +28 -0
- package/dist/storage/domains/work-items/base.js.map +1 -1
- package/dist/workspace.d.ts.map +1 -1
- package/dist/workspace.js +99 -45
- package/dist/workspace.js.map +1 -1
- package/factory-skills/factory-triage/SKILL.md +45 -12
- package/package.json +6 -6
- package/dist/integrations/github/factory-session.d.ts +0 -12
- package/dist/integrations/github/factory-session.d.ts.map +0 -1
- package/dist/integrations/github/factory-session.js +0 -37
- package/dist/integrations/github/factory-session.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"start-coordinator.js","names":["#controller","#storage","#transitionService","#sourceControl","#memorySettings"],"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 { MemorySettingsRecord, MemorySettingsStorage } from '../storage/domains/memory-settings/base.js';\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 defaultModelId?: string;\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\nasync function applyMemorySettings(session: FactorySession, record: MemorySettingsRecord | null): Promise<void> {\n if (record?.observerModelId) await session.om.observer.switchModel({ modelId: record.observerModelId });\n if (record?.reflectorModelId) await session.om.reflector.switchModel({ modelId: record.reflectorModelId });\n\n const state = {\n ...(record?.observationThreshold != null ? { observationThreshold: record.observationThreshold } : {}),\n ...(record?.reflectionThreshold != null ? { reflectionThreshold: record.reflectionThreshold } : {}),\n ...(record?.observeAttachments != null ? { observeAttachments: record.observeAttachments } : {}),\n };\n if (Object.keys(state).length > 0) await session.state.set(state);\n}\n\nexport class FactoryStartCoordinator {\n readonly #controller: FactoryController;\n readonly #storage: WorkItemsStorage;\n readonly #transitionService?: Pick<FactoryTransitionService, 'transition'>;\n readonly #sourceControl?: SourceControlStorageHandle;\n readonly #memorySettings?: MemorySettingsStorage;\n\n constructor(\n controller: FactoryController,\n storage: WorkItemsStorage,\n transitionService?: Pick<FactoryTransitionService, 'transition'>,\n sourceControl?: SourceControlStorageHandle,\n memorySettings?: MemorySettingsStorage,\n ) {\n this.#controller = controller;\n this.#storage = storage;\n this.#transitionService = transitionService;\n this.#sourceControl = sourceControl;\n this.#memorySettings = memorySettings;\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 // Sessions kicked off against third-party content (a PR under review, or\n // any pull-request-sourced work item) get `untrustedCheckout` so the SDK\n // never ingests the checkout's AGENTS.md/CLAUDE.md into the system prompt\n // or reminders — those files are attacker-writable in a PR branch.\n const untrustedCheckout =\n request.workItem.input.externalSource?.type === 'pull-request' ||\n (request.invocation?.type === 'skill' && request.invocation.skillName === 'factory-review');\n // The trusted ref the SDK may serve project instruction files from on an\n // untrusted checkout (the PR's base branch). Prefer the session record's\n // base branch; fall back to the intake metadata captured from the PR.\n const metadataBaseBranch = request.workItem.input.metadata?.baseBranch;\n const baseRef =\n (sourceSession.baseBranch || undefined) ??\n (typeof metadataBaseBranch === 'string' && metadataBaseBranch ? metadataBaseBranch : undefined);\n const sessionTags = {\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: sessionTags,\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. `untrustedCheckout` is a\n // boolean so it rides only on state (tags are string-valued).\n await session.state.set({\n ...sessionTags,\n ...(untrustedCheckout ? { untrustedCheckout: true, ...(baseRef ? { baseRef } : {}) } : {}),\n });\n if (this.#memorySettings) {\n try {\n const record = await this.#memorySettings.get({ orgId: request.orgId, userId: request.userId });\n await applyMemorySettings(session, record);\n } catch (error) {\n console.warn('[Factory Start] Failed to apply observational-memory settings', {\n error: error instanceof Error ? error.message : String(error),\n });\n }\n }\n if (request.defaultModelId) {\n try {\n await session.model.switch({ modelId: request.defaultModelId });\n } catch (error) {\n console.warn('[Factory Start] Failed to apply factory default model', {\n modelId: request.defaultModelId,\n error: error instanceof Error ? error.message : String(error),\n });\n }\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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"}
|
|
1
|
+
{"version":3,"file":"start-coordinator.js","names":["#controller","#storage","#transitionService","#sourceControl","#memorySettings"],"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 { hydrateFactorySession } from '../session/factory-session.js';\nimport type { MemorySettingsStorage } from '../storage/domains/memory-settings/base.js';\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 defaultModelId?: string;\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 readonly #memorySettings?: MemorySettingsStorage;\n\n constructor(\n controller: FactoryController,\n storage: WorkItemsStorage,\n transitionService?: Pick<FactoryTransitionService, 'transition'>,\n sourceControl?: SourceControlStorageHandle,\n memorySettings?: MemorySettingsStorage,\n ) {\n this.#controller = controller;\n this.#storage = storage;\n this.#transitionService = transitionService;\n this.#sourceControl = sourceControl;\n this.#memorySettings = memorySettings;\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 (!requestContext.get('user')) {\n requestContext.set('user', { workosId: request.userId, organizationId: request.orgId });\n }\n // Sessions kicked off against third-party content (a PR under review, or\n // any pull-request-sourced work item) get `untrustedCheckout` so the SDK\n // never ingests the checkout's AGENTS.md/CLAUDE.md into the system prompt\n // or reminders — those files are attacker-writable in a PR branch.\n const untrustedCheckout =\n request.workItem.input.externalSource?.type === 'pull-request' ||\n (request.invocation?.type === 'skill' && request.invocation.skillName === 'factory-review');\n // The trusted ref the SDK may serve project instruction files from on an\n // untrusted checkout (the PR's base branch). Prefer the session record's\n // base branch; fall back to the intake metadata captured from the PR.\n const metadataBaseBranch = request.workItem.input.metadata?.baseBranch;\n const baseRef =\n (sourceSession.baseBranch || undefined) ??\n (typeof metadataBaseBranch === 'string' && metadataBaseBranch ? metadataBaseBranch : undefined);\n const sessionTags = {\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: sessionTags,\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. `untrustedCheckout` is a\n // boolean so it rides only on state (tags are string-valued).\n await session.state.set({\n ...sessionTags,\n ...(untrustedCheckout ? { untrustedCheckout: true, ...(baseRef ? { baseRef } : {}) } : {}),\n });\n await hydrateFactorySession(session, {\n orgId: request.orgId,\n userId: request.userId,\n defaultModelId: request.defaultModelId,\n memorySettings: this.#memorySettings,\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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"}
|
package/dist/rules/tools.d.ts
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import type { RequestContext } from '@mastra/core/request-context';
|
|
2
2
|
import type { IntegrationTools } from '../integrations/base.js';
|
|
3
3
|
import type { WorkItemsStorage } from '../storage/domains/work-items/base.js';
|
|
4
|
+
import type { FactorySessionSourceLookup } from './binding-context.js';
|
|
4
5
|
import type { FactoryTransitionService } from './transition-service.js';
|
|
5
6
|
export declare function createFactoryTransitionTools(options: {
|
|
6
7
|
requestContext: RequestContext;
|
|
7
8
|
storage: WorkItemsStorage;
|
|
8
9
|
transitionService: Pick<FactoryTransitionService, 'transition'>;
|
|
10
|
+
sessions?: FactorySessionSourceLookup;
|
|
9
11
|
}): Promise<IntegrationTools>;
|
|
10
12
|
//# sourceMappingURL=tools.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tools.d.ts","sourceRoot":"","sources":["../../src/rules/tools.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;AAInE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAChE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,uCAAuC,CAAC;
|
|
1
|
+
{"version":3,"file":"tools.d.ts","sourceRoot":"","sources":["../../src/rules/tools.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;AAInE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAChE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,uCAAuC,CAAC;AAC9E,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,sBAAsB,CAAC;AAEvE,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,yBAAyB,CAAC;AA0BxE,wBAAsB,4BAA4B,CAAC,OAAO,EAAE;IAC1D,cAAc,EAAE,cAAc,CAAC;IAC/B,OAAO,EAAE,gBAAgB,CAAC;IAC1B,iBAAiB,EAAE,IAAI,CAAC,wBAAwB,EAAE,YAAY,CAAC,CAAC;IAChE,QAAQ,CAAC,EAAE,0BAA0B,CAAC;CACvC,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAiD5B"}
|
package/dist/rules/tools.js
CHANGED
|
@@ -1,20 +1,25 @@
|
|
|
1
1
|
import { FACTORY_RULE_STAGES } from "./types.js";
|
|
2
|
-
import {
|
|
2
|
+
import { resolveFactorySessionAddress } from "./binding-context.js";
|
|
3
3
|
import { createTool } from "@mastra/core/tools";
|
|
4
4
|
import { z } from "zod";
|
|
5
5
|
//#region src/rules/tools.ts
|
|
6
|
+
const MAX_RATIONALE_LENGTH = 1e3;
|
|
6
7
|
const transitionInputSchema = z.object({
|
|
7
8
|
stage: z.enum(FACTORY_RULE_STAGES),
|
|
8
9
|
expectedRevision: z.number().int().positive(),
|
|
9
|
-
rationale: z.string().trim().min(1).
|
|
10
|
+
rationale: z.string().trim().min(1).transform((value) => value.length <= MAX_RATIONALE_LENGTH ? value : `${value.slice(0, MAX_RATIONALE_LENGTH - 1)}…`)
|
|
10
11
|
}).strict();
|
|
11
12
|
function boardForSource(type) {
|
|
12
13
|
return type === "pull-request" ? "review" : "work";
|
|
13
14
|
}
|
|
14
15
|
async function createFactoryTransitionTools(options) {
|
|
15
|
-
const
|
|
16
|
-
|
|
17
|
-
|
|
16
|
+
const resolution = await resolveFactorySessionAddress({
|
|
17
|
+
requestContext: options.requestContext,
|
|
18
|
+
storage: options.storage,
|
|
19
|
+
sessions: options.sessions
|
|
20
|
+
});
|
|
21
|
+
if (!resolution) return {};
|
|
22
|
+
const availableBinding = resolution.binding ?? await options.storage.findActiveRunBinding(resolution.address);
|
|
18
23
|
if (!availableBinding) return {};
|
|
19
24
|
return { factory_transition_work_item: createTool({
|
|
20
25
|
id: "factory_transition_work_item",
|
|
@@ -22,7 +27,11 @@ async function createFactoryTransitionTools(options) {
|
|
|
22
27
|
inputSchema: transitionInputSchema,
|
|
23
28
|
requireApproval: true,
|
|
24
29
|
execute: async ({ stage, expectedRevision, rationale }, execution) => {
|
|
25
|
-
const currentAddress =
|
|
30
|
+
const currentAddress = (await resolveFactorySessionAddress({
|
|
31
|
+
requestContext: execution.requestContext,
|
|
32
|
+
storage: options.storage,
|
|
33
|
+
sessions: options.sessions
|
|
34
|
+
}))?.address ?? null;
|
|
26
35
|
const toolCallId = execution.agent?.toolCallId;
|
|
27
36
|
if (!currentAddress || !toolCallId) throw new Error("Factory transitions require an authenticated bound agent tool call.");
|
|
28
37
|
const binding = await options.storage.findActiveRunBinding(currentAddress);
|
package/dist/rules/tools.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tools.js","names":[],"sources":["../../src/rules/tools.ts"],"sourcesContent":["import type { RequestContext } from '@mastra/core/request-context';\nimport { createTool } from '@mastra/core/tools';\nimport { z } from 'zod';\n\nimport type { IntegrationTools } from '../integrations/base.js';\nimport type { WorkItemsStorage } from '../storage/domains/work-items/base.js';\nimport {
|
|
1
|
+
{"version":3,"file":"tools.js","names":[],"sources":["../../src/rules/tools.ts"],"sourcesContent":["import type { RequestContext } from '@mastra/core/request-context';\nimport { createTool } from '@mastra/core/tools';\nimport { z } from 'zod';\n\nimport type { IntegrationTools } from '../integrations/base.js';\nimport type { WorkItemsStorage } from '../storage/domains/work-items/base.js';\nimport type { FactorySessionSourceLookup } from './binding-context.js';\nimport { resolveFactorySessionAddress } from './binding-context.js';\nimport type { FactoryTransitionService } from './transition-service.js';\nimport { FACTORY_RULE_STAGES } from './types.js';\nimport type { FactoryRuleBoard } from './types.js';\n\nconst MAX_RATIONALE_LENGTH = 1_000;\n\nconst transitionInputSchema = z\n .object({\n stage: z.enum(FACTORY_RULE_STAGES),\n expectedRevision: z.number().int().positive(),\n // Providers strip maxLength from the JSON schema and models can't count characters, so a\n // hard cap invites overshoot-retry loops at the end of every run. Accept and clamp instead.\n rationale: z\n .string()\n .trim()\n .min(1)\n .transform(value =>\n value.length <= MAX_RATIONALE_LENGTH ? value : `${value.slice(0, MAX_RATIONALE_LENGTH - 1)}…`,\n ),\n })\n .strict();\n\nfunction boardForSource(type: string | undefined): FactoryRuleBoard {\n return type === 'pull-request' ? 'review' : 'work';\n}\n\nexport async function createFactoryTransitionTools(options: {\n requestContext: RequestContext;\n storage: WorkItemsStorage;\n transitionService: Pick<FactoryTransitionService, 'transition'>;\n sessions?: FactorySessionSourceLookup;\n}): Promise<IntegrationTools> {\n const resolution = await resolveFactorySessionAddress({\n requestContext: options.requestContext,\n storage: options.storage,\n sessions: options.sessions,\n });\n if (!resolution) return {};\n const availableBinding = resolution.binding ?? (await options.storage.findActiveRunBinding(resolution.address));\n if (!availableBinding) return {};\n\n return {\n factory_transition_work_item: createTool({\n id: 'factory_transition_work_item',\n description:\n 'Request a governed stage transition for the Factory work item exactly bound to this thread. Use the current revision from the factory-phase signal and explain why the transition is appropriate.',\n inputSchema: transitionInputSchema,\n requireApproval: true,\n execute: async ({ stage, expectedRevision, rationale }, execution) => {\n const currentResolution = await resolveFactorySessionAddress({\n requestContext: execution.requestContext,\n storage: options.storage,\n sessions: options.sessions,\n });\n const currentAddress = currentResolution?.address ?? null;\n const toolCallId = execution.agent?.toolCallId;\n if (!currentAddress || !toolCallId) {\n throw new Error('Factory transitions require an authenticated bound agent tool call.');\n }\n const binding = await options.storage.findActiveRunBinding(currentAddress);\n if (!binding || binding.id !== availableBinding.id) {\n throw new Error('Factory agent binding is unavailable, revoked, or no longer matches this session.');\n }\n const item = await options.storage.get({ orgId: binding.orgId, id: binding.workItemId });\n if (!item) throw new Error('Bound Factory work item not found.');\n\n return options.transitionService.transition({\n orgId: binding.orgId,\n factoryProjectId: binding.factoryProjectId,\n workItemId: binding.workItemId,\n board: boardForSource(item.externalSource?.type),\n stage,\n expectedRevision,\n actor: { type: 'agent', bindingId: binding.id, role: binding.role },\n ingress: { type: 'agent', identity: `${binding.id}:${toolCallId}` },\n cause: rationale,\n });\n },\n }),\n };\n}\n"],"mappings":";;;;;AAYA,MAAM,uBAAuB;AAE7B,MAAM,wBAAwB,EAC3B,OAAO;CACN,OAAO,EAAE,KAAK,mBAAmB;CACjC,kBAAkB,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,SAAS;CAG5C,WAAW,EACR,OAAO,CAAC,CACR,KAAK,CAAC,CACN,IAAI,CAAC,CAAC,CACN,WAAU,UACT,MAAM,UAAU,uBAAuB,QAAQ,GAAG,MAAM,MAAM,GAAG,uBAAuB,CAAC,EAAE,EAC7F;AACJ,CAAC,CAAC,CACD,OAAO;AAEV,SAAS,eAAe,MAA4C;CAClE,OAAO,SAAS,iBAAiB,WAAW;AAC9C;AAEA,eAAsB,6BAA6B,SAKrB;CAC5B,MAAM,aAAa,MAAM,6BAA6B;EACpD,gBAAgB,QAAQ;EACxB,SAAS,QAAQ;EACjB,UAAU,QAAQ;CACpB,CAAC;CACD,IAAI,CAAC,YAAY,OAAO,CAAC;CACzB,MAAM,mBAAmB,WAAW,WAAY,MAAM,QAAQ,QAAQ,qBAAqB,WAAW,OAAO;CAC7G,IAAI,CAAC,kBAAkB,OAAO,CAAC;CAE/B,OAAO,EACL,8BAA8B,WAAW;EACvC,IAAI;EACJ,aACE;EACF,aAAa;EACb,iBAAiB;EACjB,SAAS,OAAO,EAAE,OAAO,kBAAkB,aAAa,cAAc;GAMpE,MAAM,kBAAiB,MALS,6BAA6B;IAC3D,gBAAgB,UAAU;IAC1B,SAAS,QAAQ;IACjB,UAAU,QAAQ;GACpB,CAAC,EAAA,EACyC,WAAW;GACrD,MAAM,aAAa,UAAU,OAAO;GACpC,IAAI,CAAC,kBAAkB,CAAC,YACtB,MAAM,IAAI,MAAM,qEAAqE;GAEvF,MAAM,UAAU,MAAM,QAAQ,QAAQ,qBAAqB,cAAc;GACzE,IAAI,CAAC,WAAW,QAAQ,OAAO,iBAAiB,IAC9C,MAAM,IAAI,MAAM,mFAAmF;GAErG,MAAM,OAAO,MAAM,QAAQ,QAAQ,IAAI;IAAE,OAAO,QAAQ;IAAO,IAAI,QAAQ;GAAW,CAAC;GACvF,IAAI,CAAC,MAAM,MAAM,IAAI,MAAM,oCAAoC;GAE/D,OAAO,QAAQ,kBAAkB,WAAW;IAC1C,OAAO,QAAQ;IACf,kBAAkB,QAAQ;IAC1B,YAAY,QAAQ;IACpB,OAAO,eAAe,KAAK,gBAAgB,IAAI;IAC/C;IACA;IACA,OAAO;KAAE,MAAM;KAAS,WAAW,QAAQ;KAAI,MAAM,QAAQ;IAAK;IAClE,SAAS;KAAE,MAAM;KAAS,UAAU,GAAG,QAAQ,GAAG,GAAG;IAAa;IAClE,OAAO;GACT,CAAC;EACH;CACF,CAAC,EACH;AACF"}
|
package/dist/rules/types.d.ts
CHANGED
|
@@ -5,9 +5,9 @@ export declare const FACTORY_RULE_BOARDS: readonly ["work", "review"];
|
|
|
5
5
|
export type FactoryRuleBoard = (typeof FACTORY_RULE_BOARDS)[number];
|
|
6
6
|
export declare const FACTORY_RULE_SOURCES: readonly ["issue", "pullRequest", "linearIssue", "manual"];
|
|
7
7
|
export type FactoryRuleSource = (typeof FACTORY_RULE_SOURCES)[number];
|
|
8
|
-
export declare const FACTORY_GITHUB_EVENTS: readonly ["issueOpened", "issueEdited", "issueCommentCreated", "issueCommentEdited", "issueCommentDeleted", "pullRequestOpened", "pullRequestUpdated", "pullRequestReviewRequested", "pullRequestMerged", "pullRequestClosed"];
|
|
8
|
+
export declare const FACTORY_GITHUB_EVENTS: readonly ["issueOpened", "issueEdited", "issueClosed", "issueCommentCreated", "issueCommentEdited", "issueCommentDeleted", "pullRequestOpened", "pullRequestUpdated", "pullRequestReviewRequested", "pullRequestMerged", "pullRequestClosed"];
|
|
9
9
|
export type FactoryGithubEventName = (typeof FACTORY_GITHUB_EVENTS)[number];
|
|
10
|
-
export declare const FACTORY_LINEAR_EVENTS: readonly ["issueObserved"];
|
|
10
|
+
export declare const FACTORY_LINEAR_EVENTS: readonly ["issueObserved", "issueClosed"];
|
|
11
11
|
export type FactoryLinearEventName = (typeof FACTORY_LINEAR_EVENTS)[number];
|
|
12
12
|
export type FactoryRuleJsonValue = null | boolean | number | string | FactoryRuleJsonValue[] | {
|
|
13
13
|
[key: string]: FactoryRuleJsonValue;
|
|
@@ -96,6 +96,11 @@ export interface FactoryGithubRuleContext extends FactoryRuleContextBase {
|
|
|
96
96
|
url: string;
|
|
97
97
|
createdAt?: string;
|
|
98
98
|
updatedAt?: string;
|
|
99
|
+
assignees?: string[];
|
|
100
|
+
labels?: string[];
|
|
101
|
+
state?: 'open' | 'closed';
|
|
102
|
+
/** GitHub close reason: `completed`, `not_planned`, or `duplicate`. */
|
|
103
|
+
stateReason?: string;
|
|
99
104
|
};
|
|
100
105
|
issueChange?: {
|
|
101
106
|
title: boolean;
|
|
@@ -116,10 +121,19 @@ export interface FactoryGithubRuleContext extends FactoryRuleContextBase {
|
|
|
116
121
|
url: string;
|
|
117
122
|
createdAt?: string;
|
|
118
123
|
state: 'open' | 'closed';
|
|
124
|
+
draft: boolean;
|
|
119
125
|
merged: boolean;
|
|
126
|
+
assignees?: string[];
|
|
127
|
+
requestedReviewers?: string[];
|
|
128
|
+
labels?: string[];
|
|
120
129
|
headBranch: string;
|
|
121
130
|
baseBranch: string;
|
|
122
131
|
};
|
|
132
|
+
/** Present on `pullRequestReviewRequested`: who review was (re-)requested from. */
|
|
133
|
+
reviewRequest?: {
|
|
134
|
+
reviewer: string;
|
|
135
|
+
factoryReviewer: boolean;
|
|
136
|
+
};
|
|
123
137
|
}
|
|
124
138
|
export interface FactoryLinearRuleContext extends FactoryRuleContextBase {
|
|
125
139
|
item?: FactoryRuleItemContext;
|
|
@@ -135,6 +149,7 @@ export interface FactoryLinearRuleContext extends FactoryRuleContextBase {
|
|
|
135
149
|
stateType: string;
|
|
136
150
|
priorityLabel: string;
|
|
137
151
|
assignee: string | null;
|
|
152
|
+
creator: string | null;
|
|
138
153
|
team: string | null;
|
|
139
154
|
labels: readonly string[];
|
|
140
155
|
createdAt: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/rules/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,cAAc,GAAG,cAAc,GAAG,WAAW,GAAG,cAAc,GAAG,QAAQ,CAAC;AAEtF,eAAO,MAAM,mBAAmB,oFAAqF,CAAC;AACtH,MAAM,MAAM,gBAAgB,GAAG,CAAC,OAAO,mBAAmB,CAAC,CAAC,MAAM,CAAC,CAAC;AAEpE,eAAO,MAAM,mBAAmB,6BAA8B,CAAC;AAC/D,MAAM,MAAM,gBAAgB,GAAG,CAAC,OAAO,mBAAmB,CAAC,CAAC,MAAM,CAAC,CAAC;AAEpE,eAAO,MAAM,oBAAoB,4DAA6D,CAAC;AAC/F,MAAM,MAAM,iBAAiB,GAAG,CAAC,OAAO,oBAAoB,CAAC,CAAC,MAAM,CAAC,CAAC;AAEtE,eAAO,MAAM,qBAAqB,
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/rules/types.ts"],"names":[],"mappings":"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"}
|
package/dist/rules/types.js
CHANGED
|
@@ -18,6 +18,7 @@ const FACTORY_RULE_SOURCES = [
|
|
|
18
18
|
const FACTORY_GITHUB_EVENTS = [
|
|
19
19
|
"issueOpened",
|
|
20
20
|
"issueEdited",
|
|
21
|
+
"issueClosed",
|
|
21
22
|
"issueCommentCreated",
|
|
22
23
|
"issueCommentEdited",
|
|
23
24
|
"issueCommentDeleted",
|
|
@@ -27,7 +28,7 @@ const FACTORY_GITHUB_EVENTS = [
|
|
|
27
28
|
"pullRequestMerged",
|
|
28
29
|
"pullRequestClosed"
|
|
29
30
|
];
|
|
30
|
-
const FACTORY_LINEAR_EVENTS = ["issueObserved"];
|
|
31
|
+
const FACTORY_LINEAR_EVENTS = ["issueObserved", "issueClosed"];
|
|
31
32
|
function factoryRuleSourceForWorkItem(source) {
|
|
32
33
|
switch (source) {
|
|
33
34
|
case "github-issue": return "issue";
|
package/dist/rules/types.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.js","names":[],"sources":["../../src/rules/types.ts"],"sourcesContent":["export type WorkItemSource = 'github-issue' | 'github-pr' | 'linear-issue' | 'manual';\n\nexport const FACTORY_RULE_STAGES = ['intake', 'triage', 'planning', 'execute', 'review', 'done', 'canceled'] as const;\nexport type FactoryRuleStage = (typeof FACTORY_RULE_STAGES)[number];\n\nexport const FACTORY_RULE_BOARDS = ['work', 'review'] as const;\nexport type FactoryRuleBoard = (typeof FACTORY_RULE_BOARDS)[number];\n\nexport const FACTORY_RULE_SOURCES = ['issue', 'pullRequest', 'linearIssue', 'manual'] as const;\nexport type FactoryRuleSource = (typeof FACTORY_RULE_SOURCES)[number];\n\nexport const FACTORY_GITHUB_EVENTS = [\n 'issueOpened',\n 'issueEdited',\n 'issueCommentCreated',\n 'issueCommentEdited',\n 'issueCommentDeleted',\n 'pullRequestOpened',\n 'pullRequestUpdated',\n 'pullRequestReviewRequested',\n 'pullRequestMerged',\n 'pullRequestClosed',\n] as const;\nexport type FactoryGithubEventName = (typeof FACTORY_GITHUB_EVENTS)[number];\n\nexport const FACTORY_LINEAR_EVENTS = ['issueObserved'] as const;\nexport type FactoryLinearEventName = (typeof FACTORY_LINEAR_EVENTS)[number];\n\nexport type FactoryRuleJsonValue =\n | null\n | boolean\n | number\n | string\n | FactoryRuleJsonValue[]\n | { [key: string]: FactoryRuleJsonValue };\n\nexport interface FactoryRuleItemContext {\n id: string;\n source: WorkItemSource;\n sourceKey: string | null;\n parentWorkItemId: string | null;\n title: string;\n url: string | null;\n stages: readonly string[];\n}\n\nexport type FactoryRuleActor =\n | { type: 'human'; id: string }\n | { type: 'agent'; bindingId: string; role: string }\n | { type: 'github'; login: string; trusted: boolean; factoryAuthored: boolean }\n | { type: 'system'; id: string };\n\nexport interface FactoryRuleIngressIdentity {\n type: 'human' | 'agent' | 'toolResult' | 'github' | 'linear' | 'rule';\n id: string;\n}\n\nexport interface FactoryRuleCausalEntry {\n ingressId: string;\n decisionType: FactoryCommitDecision['type'];\n}\n\nexport interface FactoryRuleContextBase {\n tenant: { orgId: string; projectId: string };\n actor: FactoryRuleActor;\n ingress: FactoryRuleIngressIdentity;\n cause: string;\n causalChain: readonly FactoryRuleCausalEntry[];\n ruleSetVersion: string;\n}\n\nexport interface FactoryBoundRuleContext extends FactoryRuleContextBase {\n item: FactoryRuleItemContext;\n board: FactoryRuleBoard;\n itemRevision: number;\n}\n\nexport interface FactoryStageRuleContext extends FactoryBoundRuleContext {\n source: FactoryRuleSource;\n stage: FactoryRuleStage;\n fromStage: FactoryRuleStage;\n toStage: FactoryRuleStage;\n}\n\nexport interface FactoryToolResultRuleContext extends FactoryBoundRuleContext {\n toolName: string;\n threadId: string;\n assistantMessageId: string;\n toolCallId: string;\n result: {\n status: 'success' | 'error';\n value: FactoryRuleJsonValue;\n };\n}\n\nexport interface FactoryGithubRuleContext extends FactoryRuleContextBase {\n item?: FactoryRuleItemContext;\n board?: FactoryRuleBoard;\n itemRevision?: number;\n event: FactoryGithubEventName;\n deliveryId: string;\n factory: { createdAt: string };\n repository: { id: number; fullName: string };\n issue?: {
|
|
1
|
+
{"version":3,"file":"types.js","names":[],"sources":["../../src/rules/types.ts"],"sourcesContent":["export type WorkItemSource = 'github-issue' | 'github-pr' | 'linear-issue' | 'manual';\n\nexport const FACTORY_RULE_STAGES = ['intake', 'triage', 'planning', 'execute', 'review', 'done', 'canceled'] as const;\nexport type FactoryRuleStage = (typeof FACTORY_RULE_STAGES)[number];\n\nexport const FACTORY_RULE_BOARDS = ['work', 'review'] as const;\nexport type FactoryRuleBoard = (typeof FACTORY_RULE_BOARDS)[number];\n\nexport const FACTORY_RULE_SOURCES = ['issue', 'pullRequest', 'linearIssue', 'manual'] as const;\nexport type FactoryRuleSource = (typeof FACTORY_RULE_SOURCES)[number];\n\nexport const FACTORY_GITHUB_EVENTS = [\n 'issueOpened',\n 'issueEdited',\n 'issueClosed',\n 'issueCommentCreated',\n 'issueCommentEdited',\n 'issueCommentDeleted',\n 'pullRequestOpened',\n 'pullRequestUpdated',\n 'pullRequestReviewRequested',\n 'pullRequestMerged',\n 'pullRequestClosed',\n] as const;\nexport type FactoryGithubEventName = (typeof FACTORY_GITHUB_EVENTS)[number];\n\nexport const FACTORY_LINEAR_EVENTS = ['issueObserved', 'issueClosed'] as const;\nexport type FactoryLinearEventName = (typeof FACTORY_LINEAR_EVENTS)[number];\n\nexport type FactoryRuleJsonValue =\n | null\n | boolean\n | number\n | string\n | FactoryRuleJsonValue[]\n | { [key: string]: FactoryRuleJsonValue };\n\nexport interface FactoryRuleItemContext {\n id: string;\n source: WorkItemSource;\n sourceKey: string | null;\n parentWorkItemId: string | null;\n title: string;\n url: string | null;\n stages: readonly string[];\n}\n\nexport type FactoryRuleActor =\n | { type: 'human'; id: string }\n | { type: 'agent'; bindingId: string; role: string }\n | { type: 'github'; login: string; trusted: boolean; factoryAuthored: boolean }\n | { type: 'system'; id: string };\n\nexport interface FactoryRuleIngressIdentity {\n type: 'human' | 'agent' | 'toolResult' | 'github' | 'linear' | 'rule';\n id: string;\n}\n\nexport interface FactoryRuleCausalEntry {\n ingressId: string;\n decisionType: FactoryCommitDecision['type'];\n}\n\nexport interface FactoryRuleContextBase {\n tenant: { orgId: string; projectId: string };\n actor: FactoryRuleActor;\n ingress: FactoryRuleIngressIdentity;\n cause: string;\n causalChain: readonly FactoryRuleCausalEntry[];\n ruleSetVersion: string;\n}\n\nexport interface FactoryBoundRuleContext extends FactoryRuleContextBase {\n item: FactoryRuleItemContext;\n board: FactoryRuleBoard;\n itemRevision: number;\n}\n\nexport interface FactoryStageRuleContext extends FactoryBoundRuleContext {\n source: FactoryRuleSource;\n stage: FactoryRuleStage;\n fromStage: FactoryRuleStage;\n toStage: FactoryRuleStage;\n}\n\nexport interface FactoryToolResultRuleContext extends FactoryBoundRuleContext {\n toolName: string;\n threadId: string;\n assistantMessageId: string;\n toolCallId: string;\n result: {\n status: 'success' | 'error';\n value: FactoryRuleJsonValue;\n };\n}\n\nexport interface FactoryGithubRuleContext extends FactoryRuleContextBase {\n item?: FactoryRuleItemContext;\n board?: FactoryRuleBoard;\n itemRevision?: number;\n event: FactoryGithubEventName;\n deliveryId: string;\n factory: { createdAt: string };\n repository: { id: number; fullName: string };\n issue?: {\n number: number;\n title: string;\n url: string;\n createdAt?: string;\n updatedAt?: string;\n assignees?: string[];\n labels?: string[];\n state?: 'open' | 'closed';\n /** GitHub close reason: `completed`, `not_planned`, or `duplicate`. */\n stateReason?: string;\n };\n issueChange?: { title: boolean; body: boolean };\n issueComment?: {\n id: number;\n body?: string;\n url?: string;\n author?: string;\n authorType?: string;\n createdAt?: string;\n updatedAt?: string;\n };\n pullRequest?: {\n number: number;\n title: string;\n url: string;\n createdAt?: string;\n state: 'open' | 'closed';\n draft: boolean;\n merged: boolean;\n assignees?: string[];\n requestedReviewers?: string[];\n labels?: string[];\n headBranch: string;\n baseBranch: string;\n };\n /** Present on `pullRequestReviewRequested`: who review was (re-)requested from. */\n reviewRequest?: { reviewer: string; factoryReviewer: boolean };\n}\n\nexport interface FactoryLinearRuleContext extends FactoryRuleContextBase {\n item?: FactoryRuleItemContext;\n board?: FactoryRuleBoard;\n itemRevision?: number;\n event: FactoryLinearEventName;\n issue: {\n id: string;\n identifier: string;\n title: string;\n url: string;\n state: string;\n stateType: string;\n priorityLabel: string;\n assignee: string | null;\n creator: string | null;\n team: string | null;\n labels: readonly string[];\n createdAt: string;\n updatedAt: string;\n };\n}\n\nexport type FactoryRuleHandler<TContext> = (\n context: Readonly<TContext>,\n) => FactoryRuleDecision | void | Promise<FactoryRuleDecision | void>;\n\nexport interface FactoryBoardRuleLeaf {\n onEnter?: FactoryRuleHandler<FactoryStageRuleContext>;\n onExit?: FactoryRuleHandler<FactoryStageRuleContext>;\n}\n\nexport interface FactoryToolRuleLeaf {\n onResult?: FactoryRuleHandler<FactoryToolResultRuleContext>;\n}\n\nexport interface FactoryGithubRuleLeaf {\n onEvent?: FactoryRuleHandler<FactoryGithubRuleContext>;\n}\n\nexport interface FactoryLinearRuleLeaf {\n onEvent?: FactoryRuleHandler<FactoryLinearRuleContext>;\n}\n\nexport type FactoryBoardRules = Partial<\n Record<FactoryRuleStage, Partial<Record<FactoryRuleSource, FactoryBoardRuleLeaf>>>\n>;\n\nexport interface FactoryRules {\n version: string;\n work: FactoryBoardRules;\n review: FactoryBoardRules;\n tools: Record<string, FactoryToolRuleLeaf>;\n github: Partial<Record<FactoryGithubEventName, FactoryGithubRuleLeaf>>;\n linear: Partial<Record<FactoryLinearEventName, FactoryLinearRuleLeaf>>;\n}\n\nexport interface FactoryRulesOverrides {\n work?: FactoryBoardRules;\n review?: FactoryBoardRules;\n tools?: Record<string, FactoryToolRuleLeaf>;\n github?: Partial<Record<FactoryGithubEventName, FactoryGithubRuleLeaf>>;\n linear?: Partial<Record<FactoryLinearEventName, FactoryLinearRuleLeaf>>;\n}\n\nexport type FactoryRuleRejectionCode =\n | 'forbidden'\n | 'invalid_transition'\n | 'missing_binding'\n | 'stale'\n | 'timeout'\n | 'rule_error'\n | 'causal_depth_exceeded'\n | 'repeated_transition';\n\nexport interface FactoryRuleRejectDecision {\n type: 'reject';\n code: FactoryRuleRejectionCode;\n reason: string;\n}\n\ninterface FactoryCommitDecisionBase {\n idempotencyKey: string;\n}\n\nexport interface FactoryTransitionDecision extends FactoryCommitDecisionBase {\n type: 'transition';\n board: FactoryRuleBoard;\n stage: FactoryRuleStage;\n /**\n * Delivered to the item's active session (waking it if idle) after the\n * transition commits. Skipped when the item has no active run binding, so\n * informational messages never fail the transition.\n */\n message?: { text: string; role?: string };\n}\n\nexport interface FactoryUpsertLinkedWorkItemDecision extends FactoryCommitDecisionBase {\n type: 'upsertLinkedWorkItem';\n board: FactoryRuleBoard;\n source: WorkItemSource;\n sourceKey: string;\n title: string;\n url: string | null;\n stage: FactoryRuleStage;\n metadata?: Record<string, FactoryRuleJsonValue>;\n}\n\nexport interface FactoryInvokeSkillDecision extends FactoryCommitDecisionBase {\n type: 'invokeSkill';\n role: string;\n skillName: string;\n arguments?: string;\n precedingMessage?: string;\n}\n\nexport interface FactorySendMessageDecision extends FactoryCommitDecisionBase {\n type: 'sendMessage';\n role: string;\n message: string;\n priority?: 'medium' | 'high' | 'urgent';\n idleBehavior?: 'persist' | 'wake';\n prepareBinding?: boolean;\n}\n\nexport interface FactoryNotifyDecision extends FactoryCommitDecisionBase {\n type: 'notify';\n title: string;\n body?: string;\n level?: 'info' | 'warning' | 'error';\n}\n\nexport type FactoryCommitDecision =\n | FactoryTransitionDecision\n | FactoryUpsertLinkedWorkItemDecision\n | FactoryInvokeSkillDecision\n | FactorySendMessageDecision\n | FactoryNotifyDecision;\n\nexport type FactoryRuleDecision = FactoryRuleRejectDecision | FactoryCommitDecision;\n\nexport interface FactoryTransitionResultAccepted {\n status: 'accepted';\n transitionId: string;\n itemId: string;\n revision: number;\n stage: FactoryRuleStage;\n decisions: FactoryCommitDecision[];\n}\n\nexport interface FactoryTransitionResultRejected {\n status: 'rejected';\n transitionId: string;\n itemId: string;\n code: FactoryRuleRejectionCode;\n reason: string;\n}\n\nexport type FactoryTransitionResult = FactoryTransitionResultAccepted | FactoryTransitionResultRejected;\n\nexport function factoryRuleSourceForWorkItem(source: WorkItemSource): FactoryRuleSource {\n switch (source) {\n case 'github-issue':\n return 'issue';\n case 'github-pr':\n return 'pullRequest';\n case 'linear-issue':\n return 'linearIssue';\n case 'manual':\n return 'manual';\n }\n}\n"],"mappings":";AAEA,MAAa,sBAAsB;CAAC;CAAU;CAAU;CAAY;CAAW;CAAU;CAAQ;AAAU;AAG3G,MAAa,sBAAsB,CAAC,QAAQ,QAAQ;AAGpD,MAAa,uBAAuB;CAAC;CAAS;CAAe;CAAe;AAAQ;AAGpF,MAAa,wBAAwB;CACnC;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;AACF;AAGA,MAAa,wBAAwB,CAAC,iBAAiB,aAAa;AAqRpE,SAAgB,6BAA6B,QAA2C;CACtF,QAAQ,QAAR;EACE,KAAK,gBACH,OAAO;EACT,KAAK,aACH,OAAO;EACT,KAAK,gBACH,OAAO;EACT,KAAK,UACH,OAAO;CACX;AACF"}
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import type { MastraCodeState } from '@mastra/code-sdk/schema';
|
|
2
|
+
import type { AgentController } from '@mastra/core/agent-controller';
|
|
3
|
+
import type { MemorySettingsStorage } from '../storage/domains/memory-settings/base.js';
|
|
4
|
+
import type { FactoryProjectsStorage } from '../storage/domains/projects/base.js';
|
|
5
|
+
import type { SourceControlStorageHandle } from '../storage/domains/source-control/base.js';
|
|
6
|
+
type FactorySession = Awaited<ReturnType<AgentController<MastraCodeState>['createSession']>>;
|
|
7
|
+
/**
|
|
8
|
+
* Read the factory project's default model. Best-effort: a missing project or an
|
|
9
|
+
* uninitialized storage domain means "no default", never a failed run.
|
|
10
|
+
*/
|
|
11
|
+
export declare function resolveFactoryDefaultModelId(projects: FactoryProjectsStorage | undefined, factoryProjectId: string | undefined): Promise<string | undefined>;
|
|
12
|
+
export interface EnsureFactorySourceSessionArgs {
|
|
13
|
+
/**
|
|
14
|
+
* Storage handle of the integration that owns source control. Nothing here is
|
|
15
|
+
* provider-specific: the connection is matched by the handle's own
|
|
16
|
+
* `integrationId`, so GitHub, Slack-on-behalf-of-GitHub, or any future owner
|
|
17
|
+
* all resolve through the same traversal.
|
|
18
|
+
*/
|
|
19
|
+
sourceControl: SourceControlStorageHandle;
|
|
20
|
+
orgId: string;
|
|
21
|
+
factoryProjectId: string;
|
|
22
|
+
branch: string;
|
|
23
|
+
/** Pick a specific linked repository by slug. Defaults to the first linked repository. */
|
|
24
|
+
repositorySlug?: string;
|
|
25
|
+
}
|
|
26
|
+
export interface EnsuredFactorySourceSession {
|
|
27
|
+
sessionId: string;
|
|
28
|
+
userId: string;
|
|
29
|
+
projectRepositoryId: string;
|
|
30
|
+
branch: string;
|
|
31
|
+
baseBranch: string;
|
|
32
|
+
}
|
|
33
|
+
export interface ResolvedFactorySourceRepository {
|
|
34
|
+
projectRepositoryId: string;
|
|
35
|
+
/** The repository's pinned branch, else its default branch. */
|
|
36
|
+
baseBranch: string;
|
|
37
|
+
/** Who connected the repository. The attribution for runs with no interactive user. */
|
|
38
|
+
connectedByUserId: string;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Outcome of {@link resolveFactorySourceRepository}. A miss carries which step
|
|
42
|
+
* failed: callers differ on whether that is an error (an autonomous run cannot
|
|
43
|
+
* proceed) or a routine fallback (a chat integration drops to a chat-only
|
|
44
|
+
* session), and the two steps fail for different reasons worth reporting apart.
|
|
45
|
+
*/
|
|
46
|
+
export type FactorySourceRepositoryResult = ({
|
|
47
|
+
found: true;
|
|
48
|
+
} & ResolvedFactorySourceRepository) | {
|
|
49
|
+
found: false;
|
|
50
|
+
reason: 'connection' | 'repository';
|
|
51
|
+
};
|
|
52
|
+
/**
|
|
53
|
+
* Resolve which repository a factory project's source-control runs act on: the
|
|
54
|
+
* owner's connection on the project, then one of its linked repositories.
|
|
55
|
+
*
|
|
56
|
+
* The owner is whichever integration owns source control, matched by the
|
|
57
|
+
* handle's own `integrationId` — nothing here is provider-specific.
|
|
58
|
+
*/
|
|
59
|
+
export declare function resolveFactorySourceRepository(args: {
|
|
60
|
+
sourceControl: SourceControlStorageHandle;
|
|
61
|
+
orgId: string;
|
|
62
|
+
factoryProjectId: string;
|
|
63
|
+
/** Pick a specific linked repository by slug. Defaults to the first linked repository. */
|
|
64
|
+
repositorySlug?: string;
|
|
65
|
+
}): Promise<FactorySourceRepositoryResult>;
|
|
66
|
+
/**
|
|
67
|
+
* Walk a Factory user-session id back to the project it belongs to.
|
|
68
|
+
*
|
|
69
|
+
* Repo-backed channel threads are keyed by their Factory session id, which is
|
|
70
|
+
* the only handle a session-start hook gets. This turns that id back into the
|
|
71
|
+
* project whose configuration the session should adopt. Durable by
|
|
72
|
+
* construction — it reads the same rows the session was created from, so it
|
|
73
|
+
* survives restarts without any in-memory mapping.
|
|
74
|
+
*/
|
|
75
|
+
export declare function resolveFactoryProjectForSession(args: {
|
|
76
|
+
sourceControl: SourceControlStorageHandle;
|
|
77
|
+
sessionId: string;
|
|
78
|
+
}): Promise<{
|
|
79
|
+
factoryProjectId: string;
|
|
80
|
+
orgId: string;
|
|
81
|
+
userId: string;
|
|
82
|
+
} | null>;
|
|
83
|
+
/**
|
|
84
|
+
* Create the source-control session a repo-backed factory run needs.
|
|
85
|
+
*
|
|
86
|
+
* `FactoryStartCoordinator.prepare` requires this record to already exist —
|
|
87
|
+
* `resolveSourceSession` throws `Factory session not found` otherwise — so every
|
|
88
|
+
* autonomous entry point has to produce one before it can start a run. This is
|
|
89
|
+
* that step, in one place: the owner's connection on the factory project, one of
|
|
90
|
+
* its linked repositories, and a session on the requested branch with the
|
|
91
|
+
* repository's pinned or default branch as the base.
|
|
92
|
+
*
|
|
93
|
+
* The run is attributed to whoever connected the repository
|
|
94
|
+
* (`connection.createdByUserId`), because an autonomous run has no interactive
|
|
95
|
+
* user of its own.
|
|
96
|
+
*/
|
|
97
|
+
export declare function ensureFactorySourceSession(args: EnsureFactorySourceSessionArgs): Promise<EnsuredFactorySourceSession>;
|
|
98
|
+
export interface HydrateFactorySessionArgs {
|
|
99
|
+
orgId: string;
|
|
100
|
+
userId: string;
|
|
101
|
+
/** The factory project's default model. Without it the session keeps the SDK's built-in mode default. */
|
|
102
|
+
defaultModelId?: string;
|
|
103
|
+
/** Omitted when the storage domain is unavailable, in which case the session runs on memory defaults. */
|
|
104
|
+
memorySettings?: MemorySettingsStorage;
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Apply a factory project's configuration to a freshly created session:
|
|
108
|
+
* observational-memory settings, then the project's default model.
|
|
109
|
+
*
|
|
110
|
+
* Both steps are best-effort. A retired model id or an unreachable settings row
|
|
111
|
+
* must not sink a run that is otherwise ready — the session simply keeps the
|
|
112
|
+
* default it was created with, and the reason is logged.
|
|
113
|
+
*/
|
|
114
|
+
export declare function hydrateFactorySession(session: FactorySession, args: HydrateFactorySessionArgs): Promise<void>;
|
|
115
|
+
export {};
|
|
116
|
+
//# sourceMappingURL=factory-session.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"factory-session.d.ts","sourceRoot":"","sources":["../../src/session/factory-session.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAC/D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;AAErE,OAAO,KAAK,EAAwB,qBAAqB,EAAE,MAAM,4CAA4C,CAAC;AAC9G,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,qCAAqC,CAAC;AAClF,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,2CAA2C,CAAC;AAE5F,KAAK,cAAc,GAAG,OAAO,CAAC,UAAU,CAAC,eAAe,CAAC,eAAe,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC;AAE7F;;;GAGG;AACH,wBAAsB,4BAA4B,CAChD,QAAQ,EAAE,sBAAsB,GAAG,SAAS,EAC5C,gBAAgB,EAAE,MAAM,GAAG,SAAS,GACnC,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAQ7B;AAED,MAAM,WAAW,8BAA8B;IAC7C;;;;;OAKG;IACH,aAAa,EAAE,0BAA0B,CAAC;IAC1C,KAAK,EAAE,MAAM,CAAC;IACd,gBAAgB,EAAE,MAAM,CAAC;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,0FAA0F;IAC1F,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,2BAA2B;IAC1C,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,mBAAmB,EAAE,MAAM,CAAC;IAC5B,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,+BAA+B;IAC9C,mBAAmB,EAAE,MAAM,CAAC;IAC5B,+DAA+D;IAC/D,UAAU,EAAE,MAAM,CAAC;IACnB,uFAAuF;IACvF,iBAAiB,EAAE,MAAM,CAAC;CAC3B;AAED;;;;;GAKG;AACH,MAAM,MAAM,6BAA6B,GACrC,CAAC;IAAE,KAAK,EAAE,IAAI,CAAA;CAAE,GAAG,+BAA+B,CAAC,GACnD;IAAE,KAAK,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,YAAY,GAAG,YAAY,CAAA;CAAE,CAAC;AAE1D;;;;;;GAMG;AACH,wBAAsB,8BAA8B,CAAC,IAAI,EAAE;IACzD,aAAa,EAAE,0BAA0B,CAAC;IAC1C,KAAK,EAAE,MAAM,CAAC;IACd,gBAAgB,EAAE,MAAM,CAAC;IACzB,0FAA0F;IAC1F,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB,GAAG,OAAO,CAAC,6BAA6B,CAAC,CAyBzC;AAED;;;;;;;;GAQG;AACH,wBAAsB,+BAA+B,CAAC,IAAI,EAAE;IAC1D,aAAa,EAAE,0BAA0B,CAAC;IAC1C,SAAS,EAAE,MAAM,CAAC;CACnB,GAAG,OAAO,CAAC;IAAE,gBAAgB,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAAC,CAc9E;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAsB,0BAA0B,CAC9C,IAAI,EAAE,8BAA8B,GACnC,OAAO,CAAC,2BAA2B,CAAC,CA4BtC;AAcD,MAAM,WAAW,yBAAyB;IACxC,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,yGAAyG;IACzG,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,yGAAyG;IACzG,cAAc,CAAC,EAAE,qBAAqB,CAAC;CACxC;AAED;;;;;;;GAOG;AACH,wBAAsB,qBAAqB,CAAC,OAAO,EAAE,cAAc,EAAE,IAAI,EAAE,yBAAyB,GAAG,OAAO,CAAC,IAAI,CAAC,CAqBnH"}
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
import { randomUUID } from "crypto";
|
|
2
|
+
//#region src/session/factory-session.ts
|
|
3
|
+
/**
|
|
4
|
+
* Read the factory project's default model. Best-effort: a missing project or an
|
|
5
|
+
* uninitialized storage domain means "no default", never a failed run.
|
|
6
|
+
*/
|
|
7
|
+
async function resolveFactoryDefaultModelId(projects, factoryProjectId) {
|
|
8
|
+
if (!projects || !factoryProjectId) return void 0;
|
|
9
|
+
try {
|
|
10
|
+
return (await projects.getById({ id: factoryProjectId }))?.defaultModelId ?? void 0;
|
|
11
|
+
} catch {
|
|
12
|
+
return;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Resolve which repository a factory project's source-control runs act on: the
|
|
17
|
+
* owner's connection on the project, then one of its linked repositories.
|
|
18
|
+
*
|
|
19
|
+
* The owner is whichever integration owns source control, matched by the
|
|
20
|
+
* handle's own `integrationId` — nothing here is provider-specific.
|
|
21
|
+
*/
|
|
22
|
+
async function resolveFactorySourceRepository(args) {
|
|
23
|
+
const { sourceControl, orgId, factoryProjectId, repositorySlug } = args;
|
|
24
|
+
const connection = (await sourceControl.connections.list({
|
|
25
|
+
orgId,
|
|
26
|
+
factoryProjectId
|
|
27
|
+
})).find((candidate) => candidate.integrationId === sourceControl.integrationId);
|
|
28
|
+
if (!connection) return {
|
|
29
|
+
found: false,
|
|
30
|
+
reason: "connection"
|
|
31
|
+
};
|
|
32
|
+
const projectRepositories = await sourceControl.projectRepositories.list({
|
|
33
|
+
orgId,
|
|
34
|
+
connectionId: connection.id
|
|
35
|
+
});
|
|
36
|
+
const resolved = (await Promise.all(projectRepositories.map(async (projectRepository) => ({
|
|
37
|
+
projectRepository,
|
|
38
|
+
repository: await sourceControl.repositories.get({
|
|
39
|
+
orgId,
|
|
40
|
+
id: projectRepository.repositoryId
|
|
41
|
+
})
|
|
42
|
+
})))).find((candidate) => candidate.repository && (!repositorySlug || candidate.repository.slug === repositorySlug));
|
|
43
|
+
if (!resolved?.repository) return {
|
|
44
|
+
found: false,
|
|
45
|
+
reason: "repository"
|
|
46
|
+
};
|
|
47
|
+
return {
|
|
48
|
+
found: true,
|
|
49
|
+
projectRepositoryId: resolved.projectRepository.id,
|
|
50
|
+
baseBranch: resolved.projectRepository.branch ?? resolved.repository.defaultBranch,
|
|
51
|
+
connectedByUserId: connection.createdByUserId
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Walk a Factory user-session id back to the project it belongs to.
|
|
56
|
+
*
|
|
57
|
+
* Repo-backed channel threads are keyed by their Factory session id, which is
|
|
58
|
+
* the only handle a session-start hook gets. This turns that id back into the
|
|
59
|
+
* project whose configuration the session should adopt. Durable by
|
|
60
|
+
* construction — it reads the same rows the session was created from, so it
|
|
61
|
+
* survives restarts without any in-memory mapping.
|
|
62
|
+
*/
|
|
63
|
+
async function resolveFactoryProjectForSession(args) {
|
|
64
|
+
const { sourceControl, sessionId } = args;
|
|
65
|
+
const session = await sourceControl.sessions.getBySessionId(sessionId);
|
|
66
|
+
if (!session) return null;
|
|
67
|
+
const projectRepository = await sourceControl.projectRepositories.get({
|
|
68
|
+
orgId: session.orgId,
|
|
69
|
+
id: session.projectRepositoryId
|
|
70
|
+
});
|
|
71
|
+
if (!projectRepository) return null;
|
|
72
|
+
const connection = await sourceControl.connections.get({
|
|
73
|
+
orgId: session.orgId,
|
|
74
|
+
id: projectRepository.connectionId
|
|
75
|
+
});
|
|
76
|
+
if (!connection) return null;
|
|
77
|
+
return {
|
|
78
|
+
factoryProjectId: connection.factoryProjectId,
|
|
79
|
+
orgId: session.orgId,
|
|
80
|
+
userId: session.userId
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Create the source-control session a repo-backed factory run needs.
|
|
85
|
+
*
|
|
86
|
+
* `FactoryStartCoordinator.prepare` requires this record to already exist —
|
|
87
|
+
* `resolveSourceSession` throws `Factory session not found` otherwise — so every
|
|
88
|
+
* autonomous entry point has to produce one before it can start a run. This is
|
|
89
|
+
* that step, in one place: the owner's connection on the factory project, one of
|
|
90
|
+
* its linked repositories, and a session on the requested branch with the
|
|
91
|
+
* repository's pinned or default branch as the base.
|
|
92
|
+
*
|
|
93
|
+
* The run is attributed to whoever connected the repository
|
|
94
|
+
* (`connection.createdByUserId`), because an autonomous run has no interactive
|
|
95
|
+
* user of its own.
|
|
96
|
+
*/
|
|
97
|
+
async function ensureFactorySourceSession(args) {
|
|
98
|
+
const { sourceControl, orgId, factoryProjectId, branch, repositorySlug } = args;
|
|
99
|
+
const resolved = await resolveFactorySourceRepository({
|
|
100
|
+
sourceControl,
|
|
101
|
+
orgId,
|
|
102
|
+
factoryProjectId,
|
|
103
|
+
repositorySlug
|
|
104
|
+
});
|
|
105
|
+
if (!resolved.found) throw new Error(resolved.reason === "connection" ? "Factory source-control connection not found." : "Factory source-control repository not found.");
|
|
106
|
+
const userId = resolved.connectedByUserId;
|
|
107
|
+
const session = await sourceControl.sessions.create({
|
|
108
|
+
sessionId: randomUUID(),
|
|
109
|
+
projectRepositoryId: resolved.projectRepositoryId,
|
|
110
|
+
orgId,
|
|
111
|
+
userId,
|
|
112
|
+
branch,
|
|
113
|
+
baseBranch: resolved.baseBranch
|
|
114
|
+
});
|
|
115
|
+
return {
|
|
116
|
+
sessionId: session.sessionId,
|
|
117
|
+
userId,
|
|
118
|
+
projectRepositoryId: resolved.projectRepositoryId,
|
|
119
|
+
branch: session.branch,
|
|
120
|
+
baseBranch: resolved.baseBranch
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
async function applyMemorySettings(session, record) {
|
|
124
|
+
if (record?.observerModelId) await session.om.observer.switchModel({ modelId: record.observerModelId });
|
|
125
|
+
if (record?.reflectorModelId) await session.om.reflector.switchModel({ modelId: record.reflectorModelId });
|
|
126
|
+
const state = {
|
|
127
|
+
...record?.observationThreshold != null ? { observationThreshold: record.observationThreshold } : {},
|
|
128
|
+
...record?.reflectionThreshold != null ? { reflectionThreshold: record.reflectionThreshold } : {},
|
|
129
|
+
...record?.observeAttachments != null ? { observeAttachments: record.observeAttachments } : {}
|
|
130
|
+
};
|
|
131
|
+
if (Object.keys(state).length > 0) await session.state.set(state);
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* Apply a factory project's configuration to a freshly created session:
|
|
135
|
+
* observational-memory settings, then the project's default model.
|
|
136
|
+
*
|
|
137
|
+
* Both steps are best-effort. A retired model id or an unreachable settings row
|
|
138
|
+
* must not sink a run that is otherwise ready — the session simply keeps the
|
|
139
|
+
* default it was created with, and the reason is logged.
|
|
140
|
+
*/
|
|
141
|
+
async function hydrateFactorySession(session, args) {
|
|
142
|
+
if (args.memorySettings) try {
|
|
143
|
+
await applyMemorySettings(session, await args.memorySettings.get({
|
|
144
|
+
orgId: args.orgId,
|
|
145
|
+
userId: args.userId
|
|
146
|
+
}));
|
|
147
|
+
} catch (error) {
|
|
148
|
+
console.warn("[Factory Start] Failed to apply observational-memory settings", { error: error instanceof Error ? error.message : String(error) });
|
|
149
|
+
}
|
|
150
|
+
if (args.defaultModelId) try {
|
|
151
|
+
await session.model.switch({ modelId: args.defaultModelId });
|
|
152
|
+
} catch (error) {
|
|
153
|
+
console.warn("[Factory Start] Failed to apply factory default model", {
|
|
154
|
+
modelId: args.defaultModelId,
|
|
155
|
+
error: error instanceof Error ? error.message : String(error)
|
|
156
|
+
});
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
//#endregion
|
|
160
|
+
export { ensureFactorySourceSession, hydrateFactorySession, resolveFactoryDefaultModelId, resolveFactoryProjectForSession, resolveFactorySourceRepository };
|
|
161
|
+
|
|
162
|
+
//# sourceMappingURL=factory-session.js.map
|