@mastra/factory 0.22.1-alpha.0 → 0.23.0-alpha.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/factory.d.ts.map +1 -1
- package/dist/factory.js +16 -6
- package/dist/factory.js.map +1 -1
- package/dist/index.js +1 -1
- package/dist/integrations/github/integration.d.ts +7 -2
- package/dist/integrations/github/integration.d.ts.map +1 -1
- package/dist/integrations/github/integration.js +5 -2
- package/dist/integrations/github/integration.js.map +1 -1
- package/dist/integrations/github/routes.d.ts.map +1 -1
- package/dist/integrations/github/routes.js +9 -1
- package/dist/integrations/github/routes.js.map +1 -1
- package/dist/integrations/platform/github/integration.d.ts +3 -1
- package/dist/integrations/platform/github/integration.d.ts.map +1 -1
- package/dist/integrations/platform/github/integration.js +2 -2
- package/dist/integrations/platform/github/integration.js.map +1 -1
- package/dist/integrations/slack/slack.d.ts +2 -2
- package/dist/integrations/slack/slack.d.ts.map +1 -1
- package/dist/integrations/slack/slack.js +28 -57
- package/dist/integrations/slack/slack.js.map +1 -1
- package/dist/integrations/subscription-session.js +1 -1
- package/dist/routes/config.d.ts +2 -7
- package/dist/routes/config.d.ts.map +1 -1
- package/dist/routes/config.js +8 -26
- package/dist/routes/config.js.map +1 -1
- package/dist/routes/projects.d.ts.map +1 -1
- package/dist/routes/projects.js +4 -0
- package/dist/routes/projects.js.map +1 -1
- package/dist/routes/provider-credentials.d.ts +5 -4
- package/dist/routes/provider-credentials.d.ts.map +1 -1
- package/dist/routes/provider-credentials.js +1 -8
- package/dist/routes/provider-credentials.js.map +1 -1
- package/dist/routes/source-control-sessions.d.ts.map +1 -1
- package/dist/routes/source-control-sessions.js +11 -15
- package/dist/routes/source-control-sessions.js.map +1 -1
- package/dist/routes/surface.d.ts.map +1 -1
- package/dist/routes/surface.js +11 -4
- package/dist/routes/surface.js.map +1 -1
- package/dist/routes/tenant-credentials.d.ts +12 -11
- package/dist/routes/tenant-credentials.d.ts.map +1 -1
- package/dist/routes/tenant-credentials.js +42 -28
- package/dist/routes/tenant-credentials.js.map +1 -1
- package/dist/routes/work-items.d.ts.map +1 -1
- package/dist/routes/work-items.js +5 -3
- package/dist/routes/work-items.js.map +1 -1
- package/dist/rules/dispatcher.d.ts.map +1 -1
- package/dist/rules/dispatcher.js +0 -2
- package/dist/rules/dispatcher.js.map +1 -1
- package/dist/rules/processor.js +1 -1
- package/dist/rules/processor.js.map +1 -1
- package/dist/rules/start-coordinator.d.ts +7 -1
- package/dist/rules/start-coordinator.d.ts.map +1 -1
- package/dist/rules/start-coordinator.js +29 -10
- package/dist/rules/start-coordinator.js.map +1 -1
- package/dist/session/credential-policy.d.ts +12 -0
- package/dist/session/credential-policy.d.ts.map +1 -0
- package/dist/session/credential-policy.js +46 -0
- package/dist/session/credential-policy.js.map +1 -0
- package/dist/session/default-model-hydration.d.ts +9 -8
- package/dist/session/default-model-hydration.d.ts.map +1 -1
- package/dist/session/default-model-hydration.js +51 -12
- package/dist/session/default-model-hydration.js.map +1 -1
- package/dist/session/factory-session.d.ts +17 -9
- package/dist/session/factory-session.d.ts.map +1 -1
- package/dist/session/factory-session.js +55 -37
- package/dist/session/factory-session.js.map +1 -1
- package/dist/session/run-audit.d.ts +1 -5
- package/dist/session/run-audit.d.ts.map +1 -1
- package/dist/session/run-audit.js +2 -8
- package/dist/session/run-audit.js.map +1 -1
- package/dist/storage/domains/audit/base.d.ts +0 -1
- package/dist/storage/domains/audit/base.d.ts.map +1 -1
- package/dist/storage/domains/audit/base.js +1 -4
- package/dist/storage/domains/audit/base.js.map +1 -1
- package/dist/storage/domains/audit/domain.d.ts.map +1 -1
- package/dist/storage/domains/audit/domain.js +1 -3
- package/dist/storage/domains/audit/domain.js.map +1 -1
- package/dist/storage/domains/credentials/base.d.ts +4 -8
- package/dist/storage/domains/credentials/base.d.ts.map +1 -1
- package/dist/storage/domains/credentials/base.js +3 -7
- package/dist/storage/domains/credentials/base.js.map +1 -1
- package/dist/storage/domains/work-items/base.d.ts +1 -0
- package/dist/storage/domains/work-items/base.d.ts.map +1 -1
- package/dist/storage/domains/work-items/base.js +3 -1
- package/dist/storage/domains/work-items/base.js.map +1 -1
- package/dist/supervisor/session.d.ts +3 -1
- package/dist/supervisor/session.d.ts.map +1 -1
- package/dist/supervisor/session.js +20 -3
- package/dist/supervisor/session.js.map +1 -1
- package/package.json +7 -6
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { primeTenantCredentialsForTenant } from "../routes/tenant-credentials.js";
|
|
1
2
|
//#region src/session/default-model-hydration.ts
|
|
2
3
|
async function applyDefaultModel(session, modelId) {
|
|
3
4
|
await session.model.switch(modelId);
|
|
@@ -10,13 +11,49 @@ async function applyDefaultModel(session, modelId) {
|
|
|
10
11
|
agentType
|
|
11
12
|
});
|
|
12
13
|
}
|
|
13
|
-
/** Seed
|
|
14
|
-
async function hydrateSessionDefaultModel(session, { sourceControl, workItems, modelDefaults }) {
|
|
14
|
+
/** Seed a new chat's scoped default model; a chat with a user message keeps its model. */
|
|
15
|
+
async function hydrateSessionDefaultModel(session, { sourceControl, projects, workItems, modelDefaults }) {
|
|
15
16
|
const resourceId = session.identity.getResourceId();
|
|
16
|
-
|
|
17
|
+
const initialState = session.state.get() ?? {};
|
|
18
|
+
if (initialState.factoryProjectId || typeof session.thread.firstUserMessage !== "function") return;
|
|
19
|
+
const hadFactoryIdentity = initialState.factoryModelScope === "factory" || initialState.factoryModelScope === "user";
|
|
20
|
+
const clearFactoryIdentity = () => session.state.set({
|
|
21
|
+
factoryOrgId: void 0,
|
|
22
|
+
factoryModelScope: void 0,
|
|
23
|
+
factoryOwnerUserId: void 0
|
|
24
|
+
});
|
|
25
|
+
const failClosedWithoutIdentity = () => session.state.set({
|
|
26
|
+
factoryModelScope: "user",
|
|
27
|
+
factoryOwnerUserId: void 0
|
|
28
|
+
});
|
|
29
|
+
let identityResolved = false;
|
|
17
30
|
try {
|
|
18
|
-
const sourceSession = await sourceControl.
|
|
19
|
-
if (!sourceSession)
|
|
31
|
+
const sourceSession = await sourceControl.getBySessionId(resourceId);
|
|
32
|
+
if (!sourceSession) {
|
|
33
|
+
await clearFactoryIdentity();
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
if (!sourceSession.factoryProjectId) {
|
|
37
|
+
await clearFactoryIdentity();
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
const project = await projects.getById({ id: sourceSession.factoryProjectId });
|
|
41
|
+
if (!project) {
|
|
42
|
+
await clearFactoryIdentity();
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
const modelScope = project.modelScope === "user" ? "user" : "factory";
|
|
46
|
+
await session.state.set({
|
|
47
|
+
factoryOrgId: sourceSession.orgId,
|
|
48
|
+
factoryModelScope: modelScope,
|
|
49
|
+
factoryOwnerUserId: sourceSession.userId
|
|
50
|
+
});
|
|
51
|
+
identityResolved = true;
|
|
52
|
+
await primeTenantCredentialsForTenant({
|
|
53
|
+
orgId: sourceSession.orgId,
|
|
54
|
+
userId: sourceSession.userId,
|
|
55
|
+
credentialScope: modelScope
|
|
56
|
+
});
|
|
20
57
|
const threadId = session.thread.getId();
|
|
21
58
|
if (threadId && await workItems.findActiveRunBindingByThread({
|
|
22
59
|
orgId: sourceSession.orgId,
|
|
@@ -24,19 +61,21 @@ async function hydrateSessionDefaultModel(session, { sourceControl, workItems, m
|
|
|
24
61
|
resourceId,
|
|
25
62
|
sessionId: resourceId
|
|
26
63
|
})) return;
|
|
27
|
-
if (
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
])).some((setting) => typeof setting === "string")) return;
|
|
64
|
+
if (threadId && await session.thread.firstUserMessage({ threadId })) return;
|
|
65
|
+
if (modelScope === "factory") {
|
|
66
|
+
if (project.defaultModelId) await applyDefaultModel(session, project.defaultModelId);
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
33
69
|
const modelDefault = await modelDefaults.get({
|
|
34
70
|
orgId: sourceSession.orgId,
|
|
35
71
|
userId: sourceSession.userId
|
|
36
72
|
});
|
|
37
73
|
if (modelDefault) await applyDefaultModel(session, modelDefault.modelId);
|
|
38
74
|
} catch (error) {
|
|
39
|
-
|
|
75
|
+
if (!identityResolved && !hadFactoryIdentity) try {
|
|
76
|
+
await failClosedWithoutIdentity();
|
|
77
|
+
} catch {}
|
|
78
|
+
console.warn("[Factory default-model hydration] Unable to apply the scoped default model.", error);
|
|
40
79
|
}
|
|
41
80
|
}
|
|
42
81
|
//#endregion
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"default-model-hydration.js","names":[],"sources":["../../src/session/default-model-hydration.ts"],"sourcesContent":["import type { ModelDefaultsStorage } from '../storage/domains/model-defaults/base.js';\nimport type {
|
|
1
|
+
{"version":3,"file":"default-model-hydration.js","names":[],"sources":["../../src/session/default-model-hydration.ts"],"sourcesContent":["import { primeTenantCredentialsForTenant } from '../routes/tenant-credentials.js';\nimport type { ModelDefaultsStorage } from '../storage/domains/model-defaults/base.js';\nimport type { FactoryProjectsStorage } from '../storage/domains/projects/base.js';\nimport type { WorkItemsStorage } from '../storage/domains/work-items/base.js';\nimport type { SourceControlSessionLookup } from './factory-session.js';\n\nexport interface DefaultModelApplicableSession {\n model: { switch(modelId: string): Promise<unknown> };\n subagents: { model: { set(args: { modelId: string; agentType: string }): Promise<unknown> } };\n}\n\nexport interface DefaultModelHydrationSession extends DefaultModelApplicableSession {\n readonly identity: { getResourceId(): string };\n state: {\n get(): Record<string, unknown> | undefined;\n set(updates: Record<string, unknown>): Promise<unknown>;\n };\n thread: {\n getId(): string | null | undefined;\n firstUserMessage(args: { threadId: string }): Promise<unknown>;\n };\n}\n\nasync function applyDefaultModel(session: DefaultModelApplicableSession, modelId: string): Promise<void> {\n await session.model.switch(modelId);\n\n for (const agentType of ['explore', 'plan', 'execute']) {\n await session.subagents.model.set({ modelId, agentType });\n }\n}\n\nexport interface DefaultModelHydrationDependencies {\n sourceControl: Pick<SourceControlSessionLookup, 'getBySessionId'>;\n projects: Pick<FactoryProjectsStorage, 'getById'>;\n workItems: Pick<WorkItemsStorage, 'findActiveRunBindingByThread'>;\n modelDefaults: Pick<ModelDefaultsStorage, 'get'>;\n}\n\n/** Seed a new chat's scoped default model; a chat with a user message keeps its model. */\nexport async function hydrateSessionDefaultModel(\n session: DefaultModelHydrationSession,\n { sourceControl, projects, workItems, modelDefaults }: DefaultModelHydrationDependencies,\n): Promise<void> {\n const resourceId = session.identity.getResourceId();\n const initialState = session.state.get() ?? {};\n if (initialState.factoryProjectId || typeof session.thread.firstUserMessage !== 'function') return;\n const hadFactoryIdentity = initialState.factoryModelScope === 'factory' || initialState.factoryModelScope === 'user';\n const clearFactoryIdentity = () =>\n session.state.set({ factoryOrgId: undefined, factoryModelScope: undefined, factoryOwnerUserId: undefined });\n const failClosedWithoutIdentity = () =>\n session.state.set({ factoryModelScope: 'user', factoryOwnerUserId: undefined });\n let identityResolved = false;\n try {\n const sourceSession = await sourceControl.getBySessionId(resourceId);\n if (!sourceSession) {\n await clearFactoryIdentity();\n return;\n }\n if (!sourceSession.factoryProjectId) {\n await clearFactoryIdentity();\n return;\n }\n const project = await projects.getById({ id: sourceSession.factoryProjectId });\n if (!project) {\n await clearFactoryIdentity();\n return;\n }\n\n const modelScope = project.modelScope === 'user' ? 'user' : 'factory';\n await session.state.set({\n factoryOrgId: sourceSession.orgId,\n factoryModelScope: modelScope,\n factoryOwnerUserId: sourceSession.userId,\n });\n identityResolved = true;\n await primeTenantCredentialsForTenant({\n orgId: sourceSession.orgId,\n userId: sourceSession.userId,\n credentialScope: modelScope,\n });\n\n const threadId = session.thread.getId();\n if (\n threadId &&\n (await workItems.findActiveRunBindingByThread({\n orgId: sourceSession.orgId,\n threadId,\n resourceId,\n sessionId: resourceId,\n }))\n ) {\n return;\n }\n if (threadId && (await session.thread.firstUserMessage({ threadId }))) return;\n\n if (modelScope === 'factory') {\n if (project.defaultModelId) await applyDefaultModel(session, project.defaultModelId);\n return;\n }\n\n const modelDefault = await modelDefaults.get({ orgId: sourceSession.orgId, userId: sourceSession.userId });\n if (modelDefault) await applyDefaultModel(session, modelDefault.modelId);\n } catch (error) {\n if (!identityResolved && !hadFactoryIdentity) {\n try {\n await failClosedWithoutIdentity();\n } catch {}\n }\n console.warn('[Factory default-model hydration] Unable to apply the scoped default model.', error);\n }\n}\n"],"mappings":";;AAuBA,eAAe,kBAAkB,SAAwC,SAAgC;CACvG,MAAM,QAAQ,MAAM,OAAO,OAAO;CAElC,KAAK,MAAM,aAAa;EAAC;EAAW;EAAQ;CAAS,GACnD,MAAM,QAAQ,UAAU,MAAM,IAAI;EAAE;EAAS;CAAU,CAAC;AAE5D;;AAUA,eAAsB,2BACpB,SACA,EAAE,eAAe,UAAU,WAAW,iBACvB;CACf,MAAM,aAAa,QAAQ,SAAS,cAAc;CAClD,MAAM,eAAe,QAAQ,MAAM,IAAI,KAAK,CAAC;CAC7C,IAAI,aAAa,oBAAoB,OAAO,QAAQ,OAAO,qBAAqB,YAAY;CAC5F,MAAM,qBAAqB,aAAa,sBAAsB,aAAa,aAAa,sBAAsB;CAC9G,MAAM,6BACJ,QAAQ,MAAM,IAAI;EAAE,cAAc,KAAA;EAAW,mBAAmB,KAAA;EAAW,oBAAoB,KAAA;CAAU,CAAC;CAC5G,MAAM,kCACJ,QAAQ,MAAM,IAAI;EAAE,mBAAmB;EAAQ,oBAAoB,KAAA;CAAU,CAAC;CAChF,IAAI,mBAAmB;CACvB,IAAI;EACF,MAAM,gBAAgB,MAAM,cAAc,eAAe,UAAU;EACnE,IAAI,CAAC,eAAe;GAClB,MAAM,qBAAqB;GAC3B;EACF;EACA,IAAI,CAAC,cAAc,kBAAkB;GACnC,MAAM,qBAAqB;GAC3B;EACF;EACA,MAAM,UAAU,MAAM,SAAS,QAAQ,EAAE,IAAI,cAAc,iBAAiB,CAAC;EAC7E,IAAI,CAAC,SAAS;GACZ,MAAM,qBAAqB;GAC3B;EACF;EAEA,MAAM,aAAa,QAAQ,eAAe,SAAS,SAAS;EAC5D,MAAM,QAAQ,MAAM,IAAI;GACtB,cAAc,cAAc;GAC5B,mBAAmB;GACnB,oBAAoB,cAAc;EACpC,CAAC;EACD,mBAAmB;EACnB,MAAM,gCAAgC;GACpC,OAAO,cAAc;GACrB,QAAQ,cAAc;GACtB,iBAAiB;EACnB,CAAC;EAED,MAAM,WAAW,QAAQ,OAAO,MAAM;EACtC,IACE,YACC,MAAM,UAAU,6BAA6B;GAC5C,OAAO,cAAc;GACrB;GACA;GACA,WAAW;EACb,CAAC,GAED;EAEF,IAAI,YAAa,MAAM,QAAQ,OAAO,iBAAiB,EAAE,SAAS,CAAC,GAAI;EAEvE,IAAI,eAAe,WAAW;GAC5B,IAAI,QAAQ,gBAAgB,MAAM,kBAAkB,SAAS,QAAQ,cAAc;GACnF;EACF;EAEA,MAAM,eAAe,MAAM,cAAc,IAAI;GAAE,OAAO,cAAc;GAAO,QAAQ,cAAc;EAAO,CAAC;EACzG,IAAI,cAAc,MAAM,kBAAkB,SAAS,aAAa,OAAO;CACzE,SAAS,OAAO;EACd,IAAI,CAAC,oBAAoB,CAAC,oBACxB,IAAI;GACF,MAAM,0BAA0B;EAClC,QAAQ,CAAC;EAEX,QAAQ,KAAK,+EAA+E,KAAK;CACnG;AACF"}
|
|
@@ -1,15 +1,22 @@
|
|
|
1
1
|
import type { MastraCodeState } from '@mastra/code-sdk/schema';
|
|
2
2
|
import type { AgentController } from '@mastra/core/agent-controller';
|
|
3
|
-
import type {
|
|
3
|
+
import type { ModelDefaultsStorage } from '../storage/domains/model-defaults/base.js';
|
|
4
|
+
import type { FactoryModelScope, FactoryProjectsStorage } from '../storage/domains/projects/base.js';
|
|
4
5
|
import { type SourceControlSession, type SourceControlStorageHandle } from '../storage/domains/source-control/base.js';
|
|
5
6
|
type FactorySession = Awaited<ReturnType<AgentController<MastraCodeState>['createSession']>>;
|
|
6
7
|
export declare class FactorySourceControlConflictError extends Error {
|
|
7
8
|
}
|
|
8
|
-
/**
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
9
|
+
/** Resolve the model and exclusive credential scope for a Factory session. */
|
|
10
|
+
export declare function resolveFactorySessionModel(args: {
|
|
11
|
+
projects: FactoryProjectsStorage | undefined;
|
|
12
|
+
modelDefaults: ModelDefaultsStorage | undefined;
|
|
13
|
+
factoryProjectId: string | undefined;
|
|
14
|
+
orgId: string;
|
|
15
|
+
ownerUserId: string;
|
|
16
|
+
}): Promise<{
|
|
17
|
+
modelScope: FactoryModelScope;
|
|
18
|
+
modelId?: string;
|
|
19
|
+
}>;
|
|
13
20
|
export interface SourceControlSessionLookup {
|
|
14
21
|
getBySessionId(sessionId: string): Promise<SourceControlSession | null>;
|
|
15
22
|
getSourceControlBySessionId(sessionId: string): Promise<SourceControlStorageHandle | null>;
|
|
@@ -133,15 +140,16 @@ export declare function resolvePrimaryEnvironmentRepository(args: {
|
|
|
133
140
|
export declare function ensureFactorySourceSession(args: EnsureFactorySourceSessionArgs): Promise<EnsuredFactorySourceSession>;
|
|
134
141
|
export interface HydrateFactorySessionArgs {
|
|
135
142
|
orgId: string;
|
|
136
|
-
|
|
143
|
+
modelScope: FactoryModelScope;
|
|
144
|
+
ownerUserId: string;
|
|
145
|
+
/** The model selected by the Factory scope. Without it the SDK mode default is applied. */
|
|
137
146
|
defaultModelId?: string;
|
|
138
147
|
}
|
|
139
148
|
/**
|
|
140
149
|
* Apply a factory project's main model to a session on every run.
|
|
141
150
|
*
|
|
142
151
|
* The model switch is best-effort. A retired model id must not sink a run that
|
|
143
|
-
* is otherwise ready
|
|
144
|
-
* and the reason is logged. Observational-memory settings are resolved from the
|
|
152
|
+
* is otherwise ready, and the reason is logged. Observational-memory settings are resolved from the
|
|
145
153
|
* authoritative row per invocation before memory processors run.
|
|
146
154
|
*/
|
|
147
155
|
export declare function hydrateFactorySession(session: FactorySession, args: HydrateFactorySessionArgs): Promise<void>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"factory-session.d.ts","sourceRoot":"","sources":["../../src/session/factory-session.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAC/D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;AAErE,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,qCAAqC,CAAC;
|
|
1
|
+
{"version":3,"file":"factory-session.d.ts","sourceRoot":"","sources":["../../src/session/factory-session.ts"],"names":[],"mappings":"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"}
|
|
@@ -3,16 +3,31 @@ import { resolveEnvironmentRepositories } from "./environment-repositories.js";
|
|
|
3
3
|
import { seedSessionOrg } from "./org-seed.js";
|
|
4
4
|
//#region src/session/factory-session.ts
|
|
5
5
|
var FactorySourceControlConflictError = class extends Error {};
|
|
6
|
-
/**
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
if (
|
|
6
|
+
/** Resolve the model and exclusive credential scope for a Factory session. */
|
|
7
|
+
async function resolveFactorySessionModel(args) {
|
|
8
|
+
if (!args.projects || !args.factoryProjectId) throw new Error("Factory model policy is unavailable.");
|
|
9
|
+
const project = await args.projects.getById({ id: args.factoryProjectId });
|
|
10
|
+
if (!project || project.orgId !== args.orgId) throw new Error("Factory model policy is unavailable.");
|
|
11
|
+
if (project.modelScope !== "user") return {
|
|
12
|
+
modelScope: "factory",
|
|
13
|
+
...project.defaultModelId ? { modelId: project.defaultModelId } : {}
|
|
14
|
+
};
|
|
12
15
|
try {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
+
const userDefault = await args.modelDefaults?.get({
|
|
17
|
+
orgId: args.orgId,
|
|
18
|
+
userId: args.ownerUserId
|
|
19
|
+
});
|
|
20
|
+
return {
|
|
21
|
+
modelScope: "user",
|
|
22
|
+
...userDefault?.modelId ? { modelId: userDefault.modelId } : {}
|
|
23
|
+
};
|
|
24
|
+
} catch (error) {
|
|
25
|
+
console.warn("[Factory] Owner default model lookup failed; using the mode default model", {
|
|
26
|
+
orgId: args.orgId,
|
|
27
|
+
ownerUserId: args.ownerUserId,
|
|
28
|
+
error: error instanceof Error ? error.message : String(error)
|
|
29
|
+
});
|
|
30
|
+
return { modelScope: "user" };
|
|
16
31
|
}
|
|
17
32
|
}
|
|
18
33
|
/**
|
|
@@ -168,40 +183,43 @@ async function ensureFactorySourceSession(args) {
|
|
|
168
183
|
* Apply a factory project's main model to a session on every run.
|
|
169
184
|
*
|
|
170
185
|
* The model switch is best-effort. A retired model id must not sink a run that
|
|
171
|
-
* is otherwise ready
|
|
172
|
-
* and the reason is logged. Observational-memory settings are resolved from the
|
|
186
|
+
* is otherwise ready, and the reason is logged. Observational-memory settings are resolved from the
|
|
173
187
|
* authoritative row per invocation before memory processors run.
|
|
174
188
|
*/
|
|
175
189
|
async function hydrateFactorySession(session, args) {
|
|
176
190
|
await seedSessionOrg(session, args.orgId);
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
191
|
+
await session.state.set({
|
|
192
|
+
factoryModelScope: args.modelScope,
|
|
193
|
+
factoryOwnerUserId: args.ownerUserId
|
|
194
|
+
});
|
|
195
|
+
const selectedModelId = args.defaultModelId ?? session.mode.resolve().defaultModelId;
|
|
196
|
+
if (!selectedModelId) return;
|
|
197
|
+
try {
|
|
198
|
+
await session.model.switch(selectedModelId);
|
|
199
|
+
} catch (error) {
|
|
200
|
+
console.warn("[Factory Start] Failed to apply scoped default model", {
|
|
201
|
+
modelId: selectedModelId,
|
|
202
|
+
error: error instanceof Error ? error.message : String(error)
|
|
203
|
+
});
|
|
204
|
+
}
|
|
205
|
+
for (const agentType of [
|
|
206
|
+
"explore",
|
|
207
|
+
"plan",
|
|
208
|
+
"execute"
|
|
209
|
+
]) try {
|
|
210
|
+
await session.subagents.model.set({
|
|
211
|
+
modelId: selectedModelId,
|
|
212
|
+
agentType
|
|
213
|
+
});
|
|
214
|
+
} catch (error) {
|
|
215
|
+
console.warn("[Factory Start] Failed to apply scoped default subagent model", {
|
|
216
|
+
agentType,
|
|
217
|
+
modelId: selectedModelId,
|
|
218
|
+
error: error instanceof Error ? error.message : String(error)
|
|
219
|
+
});
|
|
202
220
|
}
|
|
203
221
|
}
|
|
204
222
|
//#endregion
|
|
205
|
-
export { FactorySourceControlConflictError, FactorySourceSessionResolutionError, createSourceControlSessionLookup, ensureFactorySourceSession, hydrateFactorySession,
|
|
223
|
+
export { FactorySourceControlConflictError, FactorySourceSessionResolutionError, createSourceControlSessionLookup, ensureFactorySourceSession, hydrateFactorySession, resolveFactorySessionModel, resolveFactorySourceControl, resolvePrimaryEnvironmentRepository };
|
|
206
224
|
|
|
207
225
|
//# sourceMappingURL=factory-session.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"factory-session.js","names":[],"sources":["../../src/session/factory-session.ts"],"sourcesContent":["import type { MastraCodeState } from '@mastra/code-sdk/schema';\nimport type { AgentController } from '@mastra/core/agent-controller';\n\nimport type { FactoryProjectsStorage } from '../storage/domains/projects/base.js';\nimport {\n SourceControlConnectionNotFoundError,\n type SourceControlSession,\n type SourceControlStorageHandle,\n} from '../storage/domains/source-control/base.js';\nimport { resolveEnvironmentRepositories } from './environment-repositories.js';\nimport { seedSessionOrg } from './org-seed.js';\n\ntype FactorySession = Awaited<ReturnType<AgentController<MastraCodeState>['createSession']>>;\n\nexport class FactorySourceControlConflictError extends Error {}\n\n/**\n * Read the factory project's default model. Best-effort: a missing project or an\n * uninitialized storage domain means \"no default\", never a failed run.\n */\nexport async function resolveFactoryDefaultModelId(\n projects: FactoryProjectsStorage | undefined,\n factoryProjectId: string | undefined,\n): Promise<string | undefined> {\n if (!projects || !factoryProjectId) return undefined;\n try {\n const project = await projects.getById({ id: factoryProjectId });\n return project?.defaultModelId ?? undefined;\n } catch {\n return undefined;\n }\n}\n\nexport interface SourceControlSessionLookup {\n getBySessionId(sessionId: string): Promise<SourceControlSession | null>;\n getSourceControlBySessionId(sessionId: string): Promise<SourceControlStorageHandle | null>;\n rename(args: { sessionId: string; title: string }): Promise<void>;\n markFirstMessage(args: { sessionId: string }): Promise<void>;\n markFirstMeaningfulExec(args: { sessionId: string }): Promise<void>;\n}\n\n/**\n * Read or update a session across every registered source-control partition.\n * Session ids are globally generated, so more than one match is invalid and\n * fails closed instead of mutating an arbitrary provider.\n */\nexport function createSourceControlSessionLookup(\n sourceControls: readonly SourceControlStorageHandle[],\n): SourceControlSessionLookup {\n const resolve = async (\n sessionId: string,\n ): Promise<{ sourceControl: SourceControlStorageHandle; session: SourceControlSession } | null> => {\n const matches = (\n await Promise.all(\n sourceControls.map(async sourceControl => ({\n sourceControl,\n session: await sourceControl.sessions.getBySessionId(sessionId),\n })),\n )\n ).filter(\n (match): match is { sourceControl: SourceControlStorageHandle; session: SourceControlSession } =>\n match.session !== null,\n );\n if (matches.length > 1) throw new Error('Factory session exists in multiple source-control providers.');\n return matches[0] ?? null;\n };\n\n return {\n getBySessionId: async sessionId => (await resolve(sessionId))?.session ?? null,\n getSourceControlBySessionId: async sessionId => (await resolve(sessionId))?.sourceControl ?? null,\n rename: async args => (await resolve(args.sessionId))?.sourceControl.sessions.rename(args),\n markFirstMessage: async args => (await resolve(args.sessionId))?.sourceControl.sessions.markFirstMessage(args),\n markFirstMeaningfulExec: async args =>\n (await resolve(args.sessionId))?.sourceControl.sessions.markFirstMeaningfulExec(args),\n };\n}\n\n/**\n * Resolve the source-control provider from durable Factory repository links,\n * never from the issue tracker that happened to create the work item.\n */\nexport async function resolveFactorySourceControl(args: {\n sourceControls: readonly SourceControlStorageHandle[];\n orgId: string;\n factoryProjectId: string;\n sessionId?: string;\n}): Promise<SourceControlStorageHandle | undefined> {\n if (args.sessionId) {\n const sessionMatches = (\n await Promise.all(\n args.sourceControls.map(async sourceControl => ({\n sourceControl,\n session: await sourceControl.sessions.getBySessionId(args.sessionId!),\n })),\n )\n ).filter(match => match.session !== null);\n if (sessionMatches.length > 1) throw new Error('Factory session exists in multiple source-control providers.');\n if (sessionMatches[0]) return sessionMatches[0].sourceControl;\n }\n\n const linked = [];\n for (const sourceControl of args.sourceControls) {\n const connections = await sourceControl.connections.list({\n orgId: args.orgId,\n factoryProjectId: args.factoryProjectId,\n });\n let hasLinkedRepository = false;\n for (const connection of connections) {\n try {\n if (\n (await sourceControl.projectRepositories.list({ orgId: args.orgId, connectionId: connection.id })).length > 0\n ) {\n hasLinkedRepository = true;\n break;\n }\n } catch (error) {\n if (!(error instanceof SourceControlConnectionNotFoundError)) throw error;\n }\n }\n if (hasLinkedRepository) linked.push(sourceControl);\n }\n if (linked.length > 1)\n throw new FactorySourceControlConflictError(\n 'Factory project has repositories linked through multiple source-control providers.',\n );\n return linked[0];\n}\n\nexport interface EnsureFactorySourceSessionArgs {\n /**\n * Storage handle of the integration that owns source control. Nothing here is\n * provider-specific: the connection is matched by the handle's own\n * `integrationId`, so GitHub, Slack-on-behalf-of-GitHub, or any future owner\n * all resolve through the same traversal.\n */\n sourceControl: SourceControlStorageHandle;\n orgId: string;\n factoryProjectId: string;\n branch: string;\n /**\n * The repository link the session is filed under: the one a work item\n * targets. Defaults to the factory's position-1 environment link (D1), for\n * callers where nothing names a repository (chat threads, user sessions).\n */\n projectRepositoryId?: string;\n /**\n * Attribute the run to this user instead of the repo connector. Set when the\n * run has an interactive user — e.g. the person who approved a proposed run.\n */\n attributeToUserId?: string;\n}\n\nexport interface EnsuredFactorySourceSession {\n sessionId: string;\n userId: string;\n projectRepositoryId: string;\n branch: string;\n baseBranch: string;\n}\n\nexport class FactorySourceSessionResolutionError extends Error {\n constructor(readonly reason: 'connection' | 'repository') {\n super(\n reason === 'connection'\n ? 'Factory source-control connection not found.'\n : 'Factory source-control repository not found.',\n );\n this.name = 'FactorySourceSessionResolutionError';\n }\n}\n\nexport interface ResolvedFactorySourceRepository {\n projectRepositoryId: string;\n /** The repository's pinned branch, else its default branch. */\n baseBranch: string;\n /** Who connected the repository. The attribution for runs with no interactive user. */\n connectedByUserId: string;\n}\n\n/**\n * Outcome of {@link resolvePrimaryEnvironmentRepository}. A miss carries which\n * step failed: callers differ on whether that is an error (an autonomous run\n * cannot proceed) or a routine fallback (a chat integration drops to a\n * chat-only session), and the two steps fail for different reasons worth\n * reporting apart.\n */\nexport type FactorySourceRepositoryResult =\n | ({ found: true } & ResolvedFactorySourceRepository)\n | { found: false; reason: 'connection' | 'repository' };\n\n/**\n * The repository link a new session is filed under. By default the position-1\n * `inEnvironment` link of the factory (decision D1); a work item that targets\n * a repository names its link through `projectRepositoryId`, which must be an\n * environment link of the same factory. Session start no longer picks a\n * repository to work in, the sandbox holds every environment repository. The\n * PR tools default to this link, and subscriptions, audit and the work item's\n * repository check still read it; moving them to the per-repository\n * `sessionRepositories` rows is a follow-up.\n *\n * The owner is whichever integration owns source control, matched by the\n * handle's own `integrationId` — nothing here is provider-specific.\n */\nexport async function resolvePrimaryEnvironmentRepository(args: {\n sourceControl: SourceControlStorageHandle;\n orgId: string;\n factoryProjectId: string;\n projectRepositoryId?: string;\n}): Promise<FactorySourceRepositoryResult> {\n const { sourceControl, orgId, factoryProjectId, projectRepositoryId } = args;\n const connections = await sourceControl.connections.list({ orgId, factoryProjectId });\n if (!connections.some(candidate => candidate.integrationId === sourceControl.integrationId)) {\n return { found: false, reason: 'connection' };\n }\n const repositories = await resolveEnvironmentRepositories({ sourceControl, orgId, factoryProjectId });\n const primary = repositories.find(\n candidate => projectRepositoryId === undefined || candidate.link.id === projectRepositoryId,\n );\n if (!primary) return { found: false, reason: 'repository' };\n return {\n found: true,\n projectRepositoryId: primary.link.id,\n baseBranch: primary.link.branch ?? primary.repository.defaultBranch,\n connectedByUserId: primary.connection.createdByUserId,\n };\n}\n\n/**\n * Create the source-control session a repo-backed factory run needs.\n *\n * `FactoryStartCoordinator.prepare` requires this record to already exist —\n * `resolveSourceSession` throws `Factory session not found` otherwise — so every\n * autonomous entry point has to produce one before it can start a run. This is\n * that step, in one place: the owner's connection on the factory project, the\n * work item's repository link (else the position-1 environment link, D1) as\n * the session's link, and a session on the requested branch with that\n * repository's pinned or default branch as the base. The sandbox itself boots\n * every environment repository.\n *\n * The run is attributed to `attributeToUserId` when the caller has an\n * interactive user (e.g. the approver of a proposed run), and otherwise falls\n * back to whoever connected the repository (`connection.createdByUserId`),\n * because a genuinely autonomous run has no interactive user of its own.\n */\nexport async function ensureFactorySourceSession(\n args: EnsureFactorySourceSessionArgs,\n): Promise<EnsuredFactorySourceSession> {\n const { sourceControl, orgId, factoryProjectId, branch, projectRepositoryId } = args;\n\n const resolved = await resolvePrimaryEnvironmentRepository({\n sourceControl,\n orgId,\n factoryProjectId,\n projectRepositoryId,\n });\n if (!resolved.found) throw new FactorySourceSessionResolutionError(resolved.reason);\n\n const userId = args.attributeToUserId ?? resolved.connectedByUserId;\n const session = await sourceControl.sessions.create({\n sessionId: globalThis.crypto.randomUUID(),\n projectRepositoryId: resolved.projectRepositoryId,\n factoryProjectId,\n orgId,\n userId,\n branch,\n baseBranch: resolved.baseBranch,\n visibility: 'org',\n });\n return {\n sessionId: session.sessionId,\n userId,\n projectRepositoryId: resolved.projectRepositoryId,\n branch: session.branch,\n baseBranch: resolved.baseBranch,\n };\n}\n\nexport interface HydrateFactorySessionArgs {\n orgId: string;\n /** The factory project's default model. Without it the session keeps the SDK's built-in mode default. */\n defaultModelId?: string;\n}\n\n/**\n * Apply a factory project's main model to a session on every run.\n *\n * The model switch is best-effort. A retired model id must not sink a run that\n * is otherwise ready — the session simply keeps the default it was created with,\n * and the reason is logged. Observational-memory settings are resolved from the\n * authoritative row per invocation before memory processors run.\n */\nexport async function hydrateFactorySession(session: FactorySession, args: HydrateFactorySessionArgs): Promise<void> {\n // The org rung knowledge curation scopes on. Seeded first so it lands even if\n // a later best-effort step fails; an empty org marks the session unresolved.\n await seedSessionOrg(session, args.orgId);\n\n if (args.defaultModelId) {\n try {\n await session.model.switch(args.defaultModelId);\n } catch (error) {\n console.warn('[Factory Start] Failed to apply factory default model', {\n modelId: args.defaultModelId,\n error: error instanceof Error ? error.message : String(error),\n });\n }\n // Subagents otherwise keep the server-wide settings (or the SDK's built-in\n // default), which may name a provider this factory has no credentials for.\n // Each role is independent, so one failure doesn't strand the others.\n for (const agentType of ['explore', 'plan', 'execute']) {\n try {\n await session.subagents.model.set({ modelId: args.defaultModelId, agentType });\n } catch (error) {\n console.warn('[Factory Start] Failed to apply factory default subagent model', {\n agentType,\n modelId: args.defaultModelId,\n error: error instanceof Error ? error.message : String(error),\n });\n }\n }\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"factory-session.js","names":[],"sources":["../../src/session/factory-session.ts"],"sourcesContent":["import type { MastraCodeState } from '@mastra/code-sdk/schema';\nimport type { AgentController } from '@mastra/core/agent-controller';\n\nimport type { ModelDefaultsStorage } from '../storage/domains/model-defaults/base.js';\nimport type { FactoryModelScope, FactoryProjectsStorage } from '../storage/domains/projects/base.js';\nimport {\n SourceControlConnectionNotFoundError,\n type SourceControlSession,\n type SourceControlStorageHandle,\n} from '../storage/domains/source-control/base.js';\nimport { resolveEnvironmentRepositories } from './environment-repositories.js';\nimport { seedSessionOrg } from './org-seed.js';\n\ntype FactorySession = Awaited<ReturnType<AgentController<MastraCodeState>['createSession']>>;\n\nexport class FactorySourceControlConflictError extends Error {}\n\n/** Resolve the model and exclusive credential scope for a Factory session. */\nexport async function resolveFactorySessionModel(args: {\n projects: FactoryProjectsStorage | undefined;\n modelDefaults: ModelDefaultsStorage | undefined;\n factoryProjectId: string | undefined;\n orgId: string;\n ownerUserId: string;\n}): Promise<{ modelScope: FactoryModelScope; modelId?: string }> {\n if (!args.projects || !args.factoryProjectId) throw new Error('Factory model policy is unavailable.');\n\n const project = await args.projects.getById({ id: args.factoryProjectId });\n if (!project || project.orgId !== args.orgId) throw new Error('Factory model policy is unavailable.');\n if (project.modelScope !== 'user') {\n return { modelScope: 'factory', ...(project.defaultModelId ? { modelId: project.defaultModelId } : {}) };\n }\n\n try {\n const userDefault = await args.modelDefaults?.get({ orgId: args.orgId, userId: args.ownerUserId });\n return { modelScope: 'user', ...(userDefault?.modelId ? { modelId: userDefault.modelId } : {}) };\n } catch (error) {\n console.warn('[Factory] Owner default model lookup failed; using the mode default model', {\n orgId: args.orgId,\n ownerUserId: args.ownerUserId,\n error: error instanceof Error ? error.message : String(error),\n });\n return { modelScope: 'user' };\n }\n}\n\nexport interface SourceControlSessionLookup {\n getBySessionId(sessionId: string): Promise<SourceControlSession | null>;\n getSourceControlBySessionId(sessionId: string): Promise<SourceControlStorageHandle | null>;\n rename(args: { sessionId: string; title: string }): Promise<void>;\n markFirstMessage(args: { sessionId: string }): Promise<void>;\n markFirstMeaningfulExec(args: { sessionId: string }): Promise<void>;\n}\n\n/**\n * Read or update a session across every registered source-control partition.\n * Session ids are globally generated, so more than one match is invalid and\n * fails closed instead of mutating an arbitrary provider.\n */\nexport function createSourceControlSessionLookup(\n sourceControls: readonly SourceControlStorageHandle[],\n): SourceControlSessionLookup {\n const resolve = async (\n sessionId: string,\n ): Promise<{ sourceControl: SourceControlStorageHandle; session: SourceControlSession } | null> => {\n const matches = (\n await Promise.all(\n sourceControls.map(async sourceControl => ({\n sourceControl,\n session: await sourceControl.sessions.getBySessionId(sessionId),\n })),\n )\n ).filter(\n (match): match is { sourceControl: SourceControlStorageHandle; session: SourceControlSession } =>\n match.session !== null,\n );\n if (matches.length > 1) throw new Error('Factory session exists in multiple source-control providers.');\n return matches[0] ?? null;\n };\n\n return {\n getBySessionId: async sessionId => (await resolve(sessionId))?.session ?? null,\n getSourceControlBySessionId: async sessionId => (await resolve(sessionId))?.sourceControl ?? null,\n rename: async args => (await resolve(args.sessionId))?.sourceControl.sessions.rename(args),\n markFirstMessage: async args => (await resolve(args.sessionId))?.sourceControl.sessions.markFirstMessage(args),\n markFirstMeaningfulExec: async args =>\n (await resolve(args.sessionId))?.sourceControl.sessions.markFirstMeaningfulExec(args),\n };\n}\n\n/**\n * Resolve the source-control provider from durable Factory repository links,\n * never from the issue tracker that happened to create the work item.\n */\nexport async function resolveFactorySourceControl(args: {\n sourceControls: readonly SourceControlStorageHandle[];\n orgId: string;\n factoryProjectId: string;\n sessionId?: string;\n}): Promise<SourceControlStorageHandle | undefined> {\n if (args.sessionId) {\n const sessionMatches = (\n await Promise.all(\n args.sourceControls.map(async sourceControl => ({\n sourceControl,\n session: await sourceControl.sessions.getBySessionId(args.sessionId!),\n })),\n )\n ).filter(match => match.session !== null);\n if (sessionMatches.length > 1) throw new Error('Factory session exists in multiple source-control providers.');\n if (sessionMatches[0]) return sessionMatches[0].sourceControl;\n }\n\n const linked = [];\n for (const sourceControl of args.sourceControls) {\n const connections = await sourceControl.connections.list({\n orgId: args.orgId,\n factoryProjectId: args.factoryProjectId,\n });\n let hasLinkedRepository = false;\n for (const connection of connections) {\n try {\n if (\n (await sourceControl.projectRepositories.list({ orgId: args.orgId, connectionId: connection.id })).length > 0\n ) {\n hasLinkedRepository = true;\n break;\n }\n } catch (error) {\n if (!(error instanceof SourceControlConnectionNotFoundError)) throw error;\n }\n }\n if (hasLinkedRepository) linked.push(sourceControl);\n }\n if (linked.length > 1)\n throw new FactorySourceControlConflictError(\n 'Factory project has repositories linked through multiple source-control providers.',\n );\n return linked[0];\n}\n\nexport interface EnsureFactorySourceSessionArgs {\n /**\n * Storage handle of the integration that owns source control. Nothing here is\n * provider-specific: the connection is matched by the handle's own\n * `integrationId`, so GitHub, Slack-on-behalf-of-GitHub, or any future owner\n * all resolve through the same traversal.\n */\n sourceControl: SourceControlStorageHandle;\n orgId: string;\n factoryProjectId: string;\n branch: string;\n /**\n * The repository link the session is filed under: the one a work item\n * targets. Defaults to the factory's position-1 environment link (D1), for\n * callers where nothing names a repository (chat threads, user sessions).\n */\n projectRepositoryId?: string;\n /**\n * Attribute the run to this user instead of the repo connector. Set when the\n * run has an interactive user — e.g. the person who approved a proposed run.\n */\n attributeToUserId?: string;\n}\n\nexport interface EnsuredFactorySourceSession {\n sessionId: string;\n userId: string;\n projectRepositoryId: string;\n branch: string;\n baseBranch: string;\n}\n\nexport class FactorySourceSessionResolutionError extends Error {\n constructor(readonly reason: 'connection' | 'repository') {\n super(\n reason === 'connection'\n ? 'Factory source-control connection not found.'\n : 'Factory source-control repository not found.',\n );\n this.name = 'FactorySourceSessionResolutionError';\n }\n}\n\nexport interface ResolvedFactorySourceRepository {\n projectRepositoryId: string;\n /** The repository's pinned branch, else its default branch. */\n baseBranch: string;\n /** Who connected the repository. The attribution for runs with no interactive user. */\n connectedByUserId: string;\n}\n\n/**\n * Outcome of {@link resolvePrimaryEnvironmentRepository}. A miss carries which\n * step failed: callers differ on whether that is an error (an autonomous run\n * cannot proceed) or a routine fallback (a chat integration drops to a\n * chat-only session), and the two steps fail for different reasons worth\n * reporting apart.\n */\nexport type FactorySourceRepositoryResult =\n | ({ found: true } & ResolvedFactorySourceRepository)\n | { found: false; reason: 'connection' | 'repository' };\n\n/**\n * The repository link a new session is filed under. By default the position-1\n * `inEnvironment` link of the factory (decision D1); a work item that targets\n * a repository names its link through `projectRepositoryId`, which must be an\n * environment link of the same factory. Session start no longer picks a\n * repository to work in, the sandbox holds every environment repository. The\n * PR tools default to this link, and subscriptions, audit and the work item's\n * repository check still read it; moving them to the per-repository\n * `sessionRepositories` rows is a follow-up.\n *\n * The owner is whichever integration owns source control, matched by the\n * handle's own `integrationId` — nothing here is provider-specific.\n */\nexport async function resolvePrimaryEnvironmentRepository(args: {\n sourceControl: SourceControlStorageHandle;\n orgId: string;\n factoryProjectId: string;\n projectRepositoryId?: string;\n}): Promise<FactorySourceRepositoryResult> {\n const { sourceControl, orgId, factoryProjectId, projectRepositoryId } = args;\n const connections = await sourceControl.connections.list({ orgId, factoryProjectId });\n if (!connections.some(candidate => candidate.integrationId === sourceControl.integrationId)) {\n return { found: false, reason: 'connection' };\n }\n const repositories = await resolveEnvironmentRepositories({ sourceControl, orgId, factoryProjectId });\n const primary = repositories.find(\n candidate => projectRepositoryId === undefined || candidate.link.id === projectRepositoryId,\n );\n if (!primary) return { found: false, reason: 'repository' };\n return {\n found: true,\n projectRepositoryId: primary.link.id,\n baseBranch: primary.link.branch ?? primary.repository.defaultBranch,\n connectedByUserId: primary.connection.createdByUserId,\n };\n}\n\n/**\n * Create the source-control session a repo-backed factory run needs.\n *\n * `FactoryStartCoordinator.prepare` requires this record to already exist —\n * `resolveSourceSession` throws `Factory session not found` otherwise — so every\n * autonomous entry point has to produce one before it can start a run. This is\n * that step, in one place: the owner's connection on the factory project, the\n * work item's repository link (else the position-1 environment link, D1) as\n * the session's link, and a session on the requested branch with that\n * repository's pinned or default branch as the base. The sandbox itself boots\n * every environment repository.\n *\n * The run is attributed to `attributeToUserId` when the caller has an\n * interactive user (e.g. the approver of a proposed run), and otherwise falls\n * back to whoever connected the repository (`connection.createdByUserId`),\n * because a genuinely autonomous run has no interactive user of its own.\n */\nexport async function ensureFactorySourceSession(\n args: EnsureFactorySourceSessionArgs,\n): Promise<EnsuredFactorySourceSession> {\n const { sourceControl, orgId, factoryProjectId, branch, projectRepositoryId } = args;\n\n const resolved = await resolvePrimaryEnvironmentRepository({\n sourceControl,\n orgId,\n factoryProjectId,\n projectRepositoryId,\n });\n if (!resolved.found) throw new FactorySourceSessionResolutionError(resolved.reason);\n\n const userId = args.attributeToUserId ?? resolved.connectedByUserId;\n const session = await sourceControl.sessions.create({\n sessionId: globalThis.crypto.randomUUID(),\n projectRepositoryId: resolved.projectRepositoryId,\n factoryProjectId,\n orgId,\n userId,\n branch,\n baseBranch: resolved.baseBranch,\n visibility: 'org',\n });\n return {\n sessionId: session.sessionId,\n userId,\n projectRepositoryId: resolved.projectRepositoryId,\n branch: session.branch,\n baseBranch: resolved.baseBranch,\n };\n}\n\nexport interface HydrateFactorySessionArgs {\n orgId: string;\n modelScope: FactoryModelScope;\n ownerUserId: string;\n /** The model selected by the Factory scope. Without it the SDK mode default is applied. */\n defaultModelId?: string;\n}\n\n/**\n * Apply a factory project's main model to a session on every run.\n *\n * The model switch is best-effort. A retired model id must not sink a run that\n * is otherwise ready, and the reason is logged. Observational-memory settings are resolved from the\n * authoritative row per invocation before memory processors run.\n */\nexport async function hydrateFactorySession(session: FactorySession, args: HydrateFactorySessionArgs): Promise<void> {\n // The org rung knowledge curation scopes on. Seeded first so it lands even if\n // a later best-effort step fails; an empty org marks the session unresolved.\n await seedSessionOrg(session, args.orgId);\n await session.state.set({\n factoryModelScope: args.modelScope,\n factoryOwnerUserId: args.ownerUserId,\n });\n\n const selectedModelId = args.defaultModelId ?? session.mode.resolve().defaultModelId;\n if (!selectedModelId) return;\n\n try {\n await session.model.switch(selectedModelId);\n } catch (error) {\n console.warn('[Factory Start] Failed to apply scoped default model', {\n modelId: selectedModelId,\n error: error instanceof Error ? error.message : String(error),\n });\n }\n // Subagents otherwise keep the server-wide settings (or the SDK's built-in\n // default), which may name a provider this factory has no credentials for.\n // Each role is independent, so one failure doesn't strand the others.\n for (const agentType of ['explore', 'plan', 'execute']) {\n try {\n await session.subagents.model.set({ modelId: selectedModelId, agentType });\n } catch (error) {\n console.warn('[Factory Start] Failed to apply scoped default subagent model', {\n agentType,\n modelId: selectedModelId,\n error: error instanceof Error ? error.message : String(error),\n });\n }\n }\n}\n"],"mappings":"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"}
|
|
@@ -15,7 +15,6 @@ declare const factoryOpenRunSchema: z.ZodObject<{
|
|
|
15
15
|
sessionId: z.ZodString;
|
|
16
16
|
threadId: z.ZodString;
|
|
17
17
|
branch: z.ZodString;
|
|
18
|
-
agentName: z.ZodString;
|
|
19
18
|
ownerId: z.ZodOptional<z.ZodString>;
|
|
20
19
|
heartbeatAt: z.ZodOptional<z.ZodNumber>;
|
|
21
20
|
}, z.core.$strip>;
|
|
@@ -33,9 +32,6 @@ export interface RunEndCaptureSession {
|
|
|
33
32
|
value: unknown;
|
|
34
33
|
}): Promise<void>;
|
|
35
34
|
};
|
|
36
|
-
readonly mode: {
|
|
37
|
-
get(): string;
|
|
38
|
-
};
|
|
39
35
|
subscribe(listener: (event: AgentControllerEvent) => void): () => void;
|
|
40
36
|
}
|
|
41
37
|
type RunEndReason = Extract<AgentControllerEvent, {
|
|
@@ -45,7 +41,7 @@ export declare function listSessionOpenRuns(session: RunEndCaptureSession): Prom
|
|
|
45
41
|
export declare function waitForSessionRunAudit(session: RunEndCaptureSession): Promise<void>;
|
|
46
42
|
export declare function recordSessionRunStart(session: RunEndCaptureSession, { audit, run, actorType, observedEnd, }: {
|
|
47
43
|
audit: AuditRecorder;
|
|
48
|
-
run:
|
|
44
|
+
run: FactoryOpenRun;
|
|
49
45
|
actorType: AuditActorType;
|
|
50
46
|
observedEnd: () => RunEndReason;
|
|
51
47
|
}): Promise<void>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"run-audit.d.ts","sourceRoot":"","sources":["../../src/session/run-audit.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,+BAA+B,CAAC;AAC1E,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;
|
|
1
|
+
{"version":3,"file":"run-audit.d.ts","sourceRoot":"","sources":["../../src/session/run-audit.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,+BAA+B,CAAC;AAC1E,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,kCAAkC,CAAC;AACvE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oCAAoC,CAAC;AAExE,eAAO,MAAM,yBAAyB,oBAAoB,CAAC;AAE3D,QAAA,MAAM,oBAAoB;;;;;;;;;;;;;;iBAqBxB,CAAC;AAEH,MAAM,MAAM,cAAc,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oBAAoB,CAAC,CAAC;AAElE,6GAA6G;AAC7G,eAAO,MAAM,yBAAyB,QAAS,CAAC;AAEhD,wBAAgB,sBAAsB,CAAC,GAAG,EAAE,cAAc,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,SAAa,GAAG,OAAO,CAOtG;AAED,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,MAAM,EAAE;QACf,UAAU,CAAC,IAAI,EAAE;YAAE,GAAG,EAAE,MAAM,CAAA;SAAE,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;QACpD,UAAU,CAAC,IAAI,EAAE;YAAE,GAAG,EAAE,MAAM,CAAC;YAAC,KAAK,EAAE,OAAO,CAAA;SAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;KAClE,CAAC;IACF,SAAS,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,oBAAoB,KAAK,IAAI,GAAG,MAAM,IAAI,CAAC;CACxE;AAED,KAAK,YAAY,GAAG,OAAO,CAAC,oBAAoB,EAAE;IAAE,IAAI,EAAE,WAAW,CAAA;CAAE,CAAC,CAAC,QAAQ,CAAC,CAAC;AAWnF,wBAAsB,mBAAmB,CAAC,OAAO,EAAE,oBAAoB,GAAG,OAAO,CAAC,cAAc,EAAE,CAAC,CAGlG;AAED,wBAAsB,sBAAsB,CAAC,OAAO,EAAE,oBAAoB,GAAG,OAAO,CAAC,IAAI,CAAC,CAEzF;AA4CD,wBAAgB,qBAAqB,CACnC,OAAO,EAAE,oBAAoB,EAC7B,EACE,KAAK,EACL,GAAG,EACH,SAAS,EACT,WAAW,GACZ,EAAE;IACD,KAAK,EAAE,aAAa,CAAC;IACrB,GAAG,EAAE,cAAc,CAAC;IACpB,SAAS,EAAE,cAAc,CAAC;IAC1B,WAAW,EAAE,MAAM,YAAY,CAAC;CACjC,GACA,OAAO,CAAC,IAAI,CAAC,CAcf;AAED,4FAA4F;AAC5F,wBAAgB,uBAAuB,CACrC,OAAO,EAAE,oBAAoB,EAC7B,SAAS,EAAE,MAAM,EACjB,EAAE,SAAa,GACd,OAAO,CAAC,IAAI,CAAC,CASf;AAED,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,oBAAoB,EAAE,EAAE,KAAK,EAAE,EAAE;IAAE,KAAK,EAAE,aAAa,CAAA;CAAE,GAAG,MAAM,IAAI,CAKnH"}
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { auditAgentName } from "../storage/domains/audit/base.js";
|
|
2
1
|
import { z } from "zod";
|
|
3
2
|
//#region src/session/run-audit.ts
|
|
4
3
|
const FACTORY_OPEN_RUNS_SETTING = "factoryOpenRuns";
|
|
@@ -14,7 +13,6 @@ const factoryOpenRunSchema = z.object({
|
|
|
14
13
|
sessionId: z.string(),
|
|
15
14
|
threadId: z.string(),
|
|
16
15
|
branch: z.string(),
|
|
17
|
-
agentName: z.string(),
|
|
18
16
|
/**
|
|
19
17
|
* Which dispatcher process is watching this run, and when it last said so
|
|
20
18
|
* (epoch ms). The ledger is a thread setting shared by every replica, so a
|
|
@@ -85,18 +83,14 @@ async function recordRunEnds(session, audit, reason, kickoffId) {
|
|
|
85
83
|
});
|
|
86
84
|
}
|
|
87
85
|
function recordSessionRunStart(session, { audit, run, actorType, observedEnd }) {
|
|
88
|
-
const openRun = {
|
|
89
|
-
...run,
|
|
90
|
-
agentName: auditAgentName(session.mode.get())
|
|
91
|
-
};
|
|
92
86
|
return serializeRunAudit(session, async () => {
|
|
93
87
|
const runs = await listSessionOpenRuns(session);
|
|
94
88
|
if (!runs.some((existing) => existing.kickoffId === run.kickoffId)) await session.thread.setSetting({
|
|
95
89
|
key: FACTORY_OPEN_RUNS_SETTING,
|
|
96
|
-
value: [...runs,
|
|
90
|
+
value: [...runs, run]
|
|
97
91
|
});
|
|
98
92
|
await audit.record({
|
|
99
|
-
...runAuditInput(
|
|
93
|
+
...runAuditInput(run),
|
|
100
94
|
actorId: run.startedBy,
|
|
101
95
|
actorType,
|
|
102
96
|
action: "factory.run.started"
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"run-audit.js","names":[],"sources":["../../src/session/run-audit.ts"],"sourcesContent":["import type { AgentControllerEvent } from '@mastra/core/agent-controller';\nimport { z } from 'zod';\n\nimport
|
|
1
|
+
{"version":3,"file":"run-audit.js","names":[],"sources":["../../src/session/run-audit.ts"],"sourcesContent":["import type { AgentControllerEvent } from '@mastra/core/agent-controller';\nimport { z } from 'zod';\n\nimport type { AuditActorType } from '../storage/domains/audit/base.js';\nimport type { AuditRecorder } from '../storage/domains/audit/domain.js';\n\nexport const FACTORY_OPEN_RUNS_SETTING = 'factoryOpenRuns';\n\nconst factoryOpenRunSchema = z.object({\n kickoffId: z.string(),\n bindingId: z.string(),\n role: z.string(),\n startedBy: z.string(),\n orgId: z.string(),\n factoryProjectId: z.string(),\n workItemId: z.string(),\n workItemName: z.string().optional(),\n sessionId: z.string(),\n threadId: z.string(),\n branch: z.string(),\n /**\n * Which dispatcher process is watching this run, and when it last said so\n * (epoch ms). The ledger is a thread setting shared by every replica, so a\n * remote reader needs these to tell a run that is live elsewhere from one\n * that died with its process. Absent on entries written before ownership\n * was recorded; those read as stale.\n */\n ownerId: z.string().optional(),\n heartbeatAt: z.number().optional(),\n});\n\nexport type FactoryOpenRun = z.infer<typeof factoryOpenRunSchema>;\n\n/** A heartbeat older than this means the owner is gone; nothing renews it once the run's dispatcher dies. */\nexport const FACTORY_OPEN_RUN_STALE_MS = 30_000;\n\nexport function isOpenRunLiveElsewhere(run: FactoryOpenRun, ownerId: string, now = Date.now()): boolean {\n return (\n run.ownerId !== undefined &&\n run.ownerId !== ownerId &&\n run.heartbeatAt !== undefined &&\n now - run.heartbeatAt < FACTORY_OPEN_RUN_STALE_MS\n );\n}\n\nexport interface RunEndCaptureSession {\n readonly thread: {\n getSetting(args: { key: string }): Promise<unknown>;\n setSetting(args: { key: string; value: unknown }): Promise<void>;\n };\n subscribe(listener: (event: AgentControllerEvent) => void): () => void;\n}\n\ntype RunEndReason = Extract<AgentControllerEvent, { type: 'agent_end' }>['reason'];\nconst pendingWrites = new WeakMap<RunEndCaptureSession, Promise<void>>();\n\nfunction serializeRunAudit(session: RunEndCaptureSession, write: () => Promise<void>): Promise<void> {\n const pending = (pendingWrites.get(session) ?? Promise.resolve())\n .then(write)\n .catch(error => console.warn('[Factory run audit] Unable to record run lifecycle.', error));\n pendingWrites.set(session, pending);\n return pending;\n}\n\nexport async function listSessionOpenRuns(session: RunEndCaptureSession): Promise<FactoryOpenRun[]> {\n const stored = await session.thread.getSetting({ key: FACTORY_OPEN_RUNS_SETTING });\n return z.array(factoryOpenRunSchema).parse(stored ?? []);\n}\n\nexport async function waitForSessionRunAudit(session: RunEndCaptureSession): Promise<void> {\n await (pendingWrites.get(session) ?? Promise.resolve());\n}\n\nfunction runAuditInput(run: FactoryOpenRun) {\n // Ownership fields are dispatcher bookkeeping, not part of the run's audit record.\n const { orgId, factoryProjectId, workItemId, workItemName, ownerId, heartbeatAt, ...metadata } = run;\n void ownerId;\n void heartbeatAt;\n return {\n orgId,\n factoryProjectId,\n idempotencyKey: run.kickoffId,\n targets: [{ type: 'work_item', id: workItemId, ...(workItemName ? { name: workItemName } : {}) }],\n metadata,\n };\n}\n\nasync function recordRunEnds(\n session: RunEndCaptureSession,\n audit: AuditRecorder,\n reason: RunEndReason,\n kickoffId?: string,\n): Promise<void> {\n if (!reason || reason === 'suspended') return;\n const runs = await listSessionOpenRuns(session);\n if (runs.length === 0) return;\n const remaining = [];\n for (const run of runs) {\n if (kickoffId && run.kickoffId !== kickoffId) {\n remaining.push(run);\n continue;\n }\n const input = runAuditInput(run);\n const recorded = await audit.record({\n ...input,\n actorId: `agent:${run.threadId}`,\n actorType: 'agent',\n action: 'factory.run.ended',\n metadata: { ...input.metadata, reason },\n });\n if (!recorded) remaining.push(run);\n }\n await session.thread.setSetting({ key: FACTORY_OPEN_RUNS_SETTING, value: remaining });\n}\n\nexport function recordSessionRunStart(\n session: RunEndCaptureSession,\n {\n audit,\n run,\n actorType,\n observedEnd,\n }: {\n audit: AuditRecorder;\n run: FactoryOpenRun;\n actorType: AuditActorType;\n observedEnd: () => RunEndReason;\n },\n): Promise<void> {\n return serializeRunAudit(session, async () => {\n const runs = await listSessionOpenRuns(session);\n if (!runs.some(existing => existing.kickoffId === run.kickoffId)) {\n await session.thread.setSetting({ key: FACTORY_OPEN_RUNS_SETTING, value: [...runs, run] });\n }\n await audit.record({\n ...runAuditInput(run),\n actorId: run.startedBy,\n actorType,\n action: 'factory.run.started',\n });\n await recordRunEnds(session, audit, observedEnd(), run.kickoffId);\n });\n}\n\n/** Renew this process's claim on an open run so other replicas keep treating it as live. */\nexport function heartbeatSessionOpenRun(\n session: RunEndCaptureSession,\n kickoffId: string,\n at = Date.now(),\n): Promise<void> {\n return serializeRunAudit(session, async () => {\n const runs = await listSessionOpenRuns(session);\n if (!runs.some(run => run.kickoffId === kickoffId)) return;\n await session.thread.setSetting({\n key: FACTORY_OPEN_RUNS_SETTING,\n value: runs.map(run => (run.kickoffId === kickoffId ? { ...run, heartbeatAt: at } : run)),\n });\n });\n}\n\nexport function observeSessionRunEnd(session: RunEndCaptureSession, { audit }: { audit: AuditRecorder }): () => void {\n return session.subscribe(event => {\n if (event.type !== 'agent_end' || !event.reason || event.reason === 'suspended') return;\n void serializeRunAudit(session, () => recordRunEnds(session, audit, event.reason));\n });\n}\n"],"mappings":"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"}
|
|
@@ -32,7 +32,6 @@ export interface AuditActorProfileInput {
|
|
|
32
32
|
avatarUrl?: string;
|
|
33
33
|
}
|
|
34
34
|
export declare const ACTOR_PROFILE_METADATA_KEY = "__actorProfile";
|
|
35
|
-
export declare function auditAgentName(modeId: string): string;
|
|
36
35
|
export declare function auditActorProfile(user: {
|
|
37
36
|
name?: string;
|
|
38
37
|
email?: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"base.d.ts","sourceRoot":"","sources":["../../../../src/storage/domains/audit/base.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,EAAE,oBAAoB,EAAwB,MAAM,sBAAsB,CAAC;AAClF,OAAO,KAAK,EAAE,gBAAgB,EAAsC,MAAM,sBAAsB,CAAC;AAEjG,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAElD,qEAAqE;AACrE,MAAM,WAAW,WAAW;IAC1B,0EAA0E;IAC1E,IAAI,EAAE,MAAM,CAAC;IACb,8EAA8E;IAC9E,EAAE,EAAE,MAAM,CAAC;IACX,8DAA8D;IAC9D,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,YAAY,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAElD,4HAA4H;AAC5H,MAAM,WAAW,sBAAsB;IACrC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,eAAO,MAAM,0BAA0B,mBAAmB,CAAC;AAE3D,wBAAgB,
|
|
1
|
+
{"version":3,"file":"base.d.ts","sourceRoot":"","sources":["../../../../src/storage/domains/audit/base.ts"],"names":[],"mappings":"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"}
|
|
@@ -16,9 +16,6 @@ import { FactoryStorageDomain, UniqueViolationError } from "@mastra/core/storage
|
|
|
16
16
|
* whose message drove the run. Rule-driven events carry `actor_type = 'system'`.
|
|
17
17
|
*/
|
|
18
18
|
const ACTOR_PROFILE_METADATA_KEY = "__actorProfile";
|
|
19
|
-
function auditAgentName(modeId) {
|
|
20
|
-
return `${modeId} agent`;
|
|
21
|
-
}
|
|
22
19
|
function auditActorProfile(user) {
|
|
23
20
|
const name = user?.name?.trim() || user?.email?.trim();
|
|
24
21
|
const avatarUrl = user?.avatarUrl?.trim();
|
|
@@ -204,6 +201,6 @@ var AuditStorage = class extends FactoryStorageDomain {
|
|
|
204
201
|
}
|
|
205
202
|
};
|
|
206
203
|
//#endregion
|
|
207
|
-
export { ACTOR_PROFILE_METADATA_KEY, AUDIT_EVENTS_SCHEMA, AuditStorage, auditActorProfile,
|
|
204
|
+
export { ACTOR_PROFILE_METADATA_KEY, AUDIT_EVENTS_SCHEMA, AuditStorage, auditActorProfile, boundAuditMetadata, clampAuditLimit, decodeAuditCursor, encodeAuditCursor };
|
|
208
205
|
|
|
209
206
|
//# sourceMappingURL=base.js.map
|