@mastra/factory 0.21.1-alpha.3 → 0.22.0-alpha.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (174) hide show
  1. package/dist/capabilities/version-control.d.ts +13 -8
  2. package/dist/capabilities/version-control.d.ts.map +1 -1
  3. package/dist/environment/build-runner.d.ts +72 -0
  4. package/dist/environment/build-runner.d.ts.map +1 -0
  5. package/dist/environment/build-runner.js +131 -0
  6. package/dist/environment/build-runner.js.map +1 -0
  7. package/dist/environment/build-schedule.d.ts +40 -0
  8. package/dist/environment/build-schedule.d.ts.map +1 -0
  9. package/dist/environment/build-schedule.js +94 -0
  10. package/dist/environment/build-schedule.js.map +1 -0
  11. package/dist/environment/build-workflow.d.ts +62 -0
  12. package/dist/environment/build-workflow.d.ts.map +1 -0
  13. package/dist/environment/build-workflow.js +149 -0
  14. package/dist/environment/build-workflow.js.map +1 -0
  15. package/dist/environment/build.d.ts +111 -0
  16. package/dist/environment/build.d.ts.map +1 -0
  17. package/dist/environment/build.js +344 -0
  18. package/dist/environment/build.js.map +1 -0
  19. package/dist/environment/heads.d.ts +36 -0
  20. package/dist/environment/heads.d.ts.map +1 -0
  21. package/dist/environment/heads.js +60 -0
  22. package/dist/environment/heads.js.map +1 -0
  23. package/dist/factory.d.ts +18 -4
  24. package/dist/factory.d.ts.map +1 -1
  25. package/dist/factory.js +89 -15
  26. package/dist/factory.js.map +1 -1
  27. package/dist/index.d.ts +2 -1
  28. package/dist/index.d.ts.map +1 -1
  29. package/dist/index.js +3 -2
  30. package/dist/integrations/base.d.ts +17 -2
  31. package/dist/integrations/base.d.ts.map +1 -1
  32. package/dist/integrations/github/commits.d.ts +11 -0
  33. package/dist/integrations/github/commits.d.ts.map +1 -1
  34. package/dist/integrations/github/commits.js +20 -1
  35. package/dist/integrations/github/commits.js.map +1 -1
  36. package/dist/integrations/github/config.d.ts +3 -3
  37. package/dist/integrations/github/config.d.ts.map +1 -1
  38. package/dist/integrations/github/config.js +1 -1
  39. package/dist/integrations/github/config.js.map +1 -1
  40. package/dist/integrations/github/routes.d.ts +2 -2
  41. package/dist/integrations/github/routes.d.ts.map +1 -1
  42. package/dist/integrations/github/routes.js +6 -5
  43. package/dist/integrations/github/routes.js.map +1 -1
  44. package/dist/integrations/github/rules.d.ts +3 -1
  45. package/dist/integrations/github/rules.d.ts.map +1 -1
  46. package/dist/integrations/github/rules.js +31 -1
  47. package/dist/integrations/github/rules.js.map +1 -1
  48. package/dist/integrations/github/sandbox.d.ts +35 -0
  49. package/dist/integrations/github/sandbox.d.ts.map +1 -1
  50. package/dist/integrations/github/sandbox.js +203 -2
  51. package/dist/integrations/github/sandbox.js.map +1 -1
  52. package/dist/integrations/github/session-subscriptions.d.ts.map +1 -1
  53. package/dist/integrations/github/session-subscriptions.js +117 -62
  54. package/dist/integrations/github/session-subscriptions.js.map +1 -1
  55. package/dist/integrations/github/token-refresh.d.ts +7 -0
  56. package/dist/integrations/github/token-refresh.d.ts.map +1 -1
  57. package/dist/integrations/github/token-refresh.js.map +1 -1
  58. package/dist/integrations/github/webhook.js.map +1 -1
  59. package/dist/integrations/gitlab/agent-tools.js +1 -1
  60. package/dist/integrations/gitlab/routes.d.ts +2 -2
  61. package/dist/integrations/gitlab/routes.d.ts.map +1 -1
  62. package/dist/integrations/gitlab/routes.js.map +1 -1
  63. package/dist/integrations/gitlab/session-subscriptions.d.ts.map +1 -1
  64. package/dist/integrations/gitlab/session-subscriptions.js +8 -7
  65. package/dist/integrations/gitlab/session-subscriptions.js.map +1 -1
  66. package/dist/integrations/incidentio/agent-tools.js +1 -1
  67. package/dist/integrations/jira/agent-tools.js +1 -1
  68. package/dist/integrations/linear/agent-tools.js +1 -1
  69. package/dist/integrations/platform/github/integration.d.ts.map +1 -1
  70. package/dist/integrations/platform/github/integration.js +46 -2
  71. package/dist/integrations/platform/github/integration.js.map +1 -1
  72. package/dist/integrations/platform/jira/agent-tools.js +1 -1
  73. package/dist/integrations/slack/slack.d.ts.map +1 -1
  74. package/dist/integrations/slack/slack.js +15 -16
  75. package/dist/integrations/slack/slack.js.map +1 -1
  76. package/dist/integrations/subscription-session.js +1 -1
  77. package/dist/packages/_internals/workspace/dist/index.js +21 -1
  78. package/dist/packages/_internals/workspace/dist/index.js.map +1 -1
  79. package/dist/routes/contracts.d.ts +386 -2
  80. package/dist/routes/contracts.d.ts.map +1 -1
  81. package/dist/routes/contracts.js +166 -1
  82. package/dist/routes/contracts.js.map +1 -1
  83. package/dist/routes/fs.d.ts +25 -0
  84. package/dist/routes/fs.d.ts.map +1 -1
  85. package/dist/routes/fs.js +142 -46
  86. package/dist/routes/fs.js.map +1 -1
  87. package/dist/routes/projects.d.ts +6 -0
  88. package/dist/routes/projects.d.ts.map +1 -1
  89. package/dist/routes/projects.js +344 -1
  90. package/dist/routes/projects.js.map +1 -1
  91. package/dist/routes/source-control-sessions.d.ts +2 -0
  92. package/dist/routes/source-control-sessions.d.ts.map +1 -1
  93. package/dist/routes/source-control-sessions.js +36 -1
  94. package/dist/routes/source-control-sessions.js.map +1 -1
  95. package/dist/routes/supervisor.js +1 -1
  96. package/dist/routes/surface.d.ts +6 -3
  97. package/dist/routes/surface.d.ts.map +1 -1
  98. package/dist/routes/surface.js +21 -34
  99. package/dist/routes/surface.js.map +1 -1
  100. package/dist/rules/binding-context.d.ts +1 -1
  101. package/dist/rules/binding-context.d.ts.map +1 -1
  102. package/dist/rules/binding-context.js +1 -1
  103. package/dist/rules/binding-context.js.map +1 -1
  104. package/dist/rules/review-source-tool.js +1 -1
  105. package/dist/rules/start-coordinator.d.ts.map +1 -1
  106. package/dist/rules/start-coordinator.js +7 -2
  107. package/dist/rules/start-coordinator.js.map +1 -1
  108. package/dist/rules/tools.js +1 -1
  109. package/dist/sandbox/callback-factory-sandbox.d.ts +15 -0
  110. package/dist/sandbox/callback-factory-sandbox.d.ts.map +1 -0
  111. package/dist/sandbox/callback-factory-sandbox.js +22 -0
  112. package/dist/sandbox/callback-factory-sandbox.js.map +1 -0
  113. package/dist/sandbox/local-factory-sandbox.d.ts +20 -0
  114. package/dist/sandbox/local-factory-sandbox.d.ts.map +1 -0
  115. package/dist/sandbox/local-factory-sandbox.js +27 -0
  116. package/dist/sandbox/local-factory-sandbox.js.map +1 -0
  117. package/dist/sandbox/session-retirement.d.ts.map +1 -1
  118. package/dist/sandbox/session-retirement.js +23 -3
  119. package/dist/sandbox/session-retirement.js.map +1 -1
  120. package/dist/sandbox/session-sandbox.d.ts +82 -40
  121. package/dist/sandbox/session-sandbox.d.ts.map +1 -1
  122. package/dist/sandbox/session-sandbox.js +130 -13
  123. package/dist/sandbox/session-sandbox.js.map +1 -1
  124. package/dist/sandbox/workdir.d.ts +10 -0
  125. package/dist/sandbox/workdir.d.ts.map +1 -1
  126. package/dist/sandbox/workdir.js +10 -1
  127. package/dist/sandbox/workdir.js.map +1 -1
  128. package/dist/session/environment-repositories.d.ts +31 -0
  129. package/dist/session/environment-repositories.d.ts.map +1 -0
  130. package/dist/session/environment-repositories.js +89 -0
  131. package/dist/session/environment-repositories.js.map +1 -0
  132. package/dist/session/environment-state-processor.d.ts +59 -0
  133. package/dist/session/environment-state-processor.d.ts.map +1 -0
  134. package/dist/session/environment-state-processor.js +105 -0
  135. package/dist/session/environment-state-processor.js.map +1 -0
  136. package/dist/session/factory-session.d.ts +26 -35
  137. package/dist/session/factory-session.d.ts.map +1 -1
  138. package/dist/session/factory-session.js +34 -71
  139. package/dist/session/factory-session.js.map +1 -1
  140. package/dist/session/filesystem-capture.d.ts +13 -0
  141. package/dist/session/filesystem-capture.d.ts.map +1 -1
  142. package/dist/session/filesystem-capture.js +73 -14
  143. package/dist/session/filesystem-capture.js.map +1 -1
  144. package/dist/session/source-control-tools.d.ts +1 -1
  145. package/dist/session/source-control-tools.d.ts.map +1 -1
  146. package/dist/session/source-control-tools.js +144 -71
  147. package/dist/session/source-control-tools.js.map +1 -1
  148. package/dist/spa-static.js +2 -2
  149. package/dist/storage/domains/audit/agent-audit.d.ts +6 -1
  150. package/dist/storage/domains/audit/agent-audit.d.ts.map +1 -1
  151. package/dist/storage/domains/audit/agent-audit.js +31 -13
  152. package/dist/storage/domains/audit/agent-audit.js.map +1 -1
  153. package/dist/storage/domains/projects/base.d.ts +115 -2
  154. package/dist/storage/domains/projects/base.d.ts.map +1 -1
  155. package/dist/storage/domains/projects/base.js +219 -12
  156. package/dist/storage/domains/projects/base.js.map +1 -1
  157. package/dist/storage/domains/source-control/base.d.ts +123 -7
  158. package/dist/storage/domains/source-control/base.d.ts.map +1 -1
  159. package/dist/storage/domains/source-control/base.js +406 -33
  160. package/dist/storage/domains/source-control/base.js.map +1 -1
  161. package/dist/storage/domains/source-control/inmemory.d.ts +19 -6
  162. package/dist/storage/domains/source-control/inmemory.d.ts.map +1 -1
  163. package/dist/storage/domains/source-control/inmemory.js +90 -2
  164. package/dist/storage/domains/source-control/inmemory.js.map +1 -1
  165. package/dist/storage/domains/work-items/base.d.ts.map +1 -1
  166. package/dist/storage/domains/work-items/base.js +12 -5
  167. package/dist/storage/domains/work-items/base.js.map +1 -1
  168. package/dist/supervisor/read-tools.js +1 -1
  169. package/dist/supervisor/write-tools.js +1 -1
  170. package/dist/workspace.d.ts +50 -7
  171. package/dist/workspace.d.ts.map +1 -1
  172. package/dist/workspace.js +344 -24
  173. package/dist/workspace.js.map +1 -1
  174. package/package.json +7 -7
@@ -1,10 +1,12 @@
1
1
  import { getFactoryAuthOrgId, getFactoryAuthUserFromContext, getFactoryAuthUserId } from "../auth.js";
2
2
  import { mergeRequestNumberFromBranch } from "../work-item-branch.js";
3
- import { normalizedVerdictLine } from "../review-verdict.js";
3
+ import { ensureLocalBranch, isCheckoutOf, pushRepositoryBranch, refreshMergeRequestCheckout } from "../integrations/github/sandbox.js";
4
4
  import { resolveSessionWorkdir } from "../sandbox/session-sandbox.js";
5
- import { pushRepositoryBranch, refreshMergeRequestCheckout } from "../integrations/github/sandbox.js";
6
- import { createTool } from "@mastra/core/tools";
5
+ import { updateSessionEnvironmentRepository } from "./environment-state-processor.js";
6
+ import { environmentSlugs, findEnvironmentRepository, resolveSessionRepositories } from "./environment-repositories.js";
7
+ import { normalizedVerdictLine } from "../review-verdict.js";
7
8
  import { z } from "zod";
9
+ import { createTool } from "@mastra/core/tools";
8
10
  //#region src/session/source-control-tools.ts
9
11
  /** Returns why a review's leading `Verdict:` line contradicts the submitted event, if it does. */
10
12
  function verdictEventMismatch(event, body) {
@@ -34,45 +36,93 @@ function authIdentity(requestContext) {
34
36
  userId: getFactoryAuthUserId(user)
35
37
  };
36
38
  }
37
- async function resolveSessionTarget(requestContext, providers) {
38
- const context = requestContext.get("controller");
39
- const { orgId, userId } = authIdentity(requestContext);
40
- if (!context?.resourceId || !orgId || !userId) throw new Error("Source-control tools require an authenticated repository session.");
39
+ async function resolveProviderSession(resourceId, providers) {
41
40
  const matches = (await Promise.all(providers.map(async (provider) => ({
42
41
  provider,
43
- session: await provider.storage.sessions.getBySessionId(context.resourceId)
42
+ session: await provider.storage.sessions.getBySessionId(resourceId)
44
43
  })))).filter((match) => match.session !== null);
45
44
  if (matches.length !== 1) throw new Error(matches.length === 0 ? "The active session is not backed by a source-control repository." : "The active session is ambiguous across source-control providers.");
46
- const { provider, session } = matches[0];
45
+ return matches[0];
46
+ }
47
+ async function resolveSessionTarget(requestContext, providers, options = {}) {
48
+ const context = requestContext.get("controller");
49
+ const { orgId, userId } = authIdentity(requestContext);
50
+ if (!context?.resourceId || !orgId || !userId) throw new Error("Source-control tools require an authenticated repository session.");
51
+ const { provider, session } = await resolveProviderSession(context.resourceId, providers);
47
52
  if (session.orgId !== orgId || session.visibility === "private" && session.userId !== userId) throw new Error("The active source-control session is not available to the authenticated user.");
48
- const projectRepository = await provider.storage.projectRepositories.get({
53
+ const ownRepository = session.projectRepositoryId ? await provider.storage.projectRepositories.get({
49
54
  orgId,
50
55
  id: session.projectRepositoryId
51
- });
52
- if (!projectRepository) throw new Error("The active project repository was not found.");
56
+ }) : null;
57
+ if (!ownRepository) throw new Error("The active project repository was not found.");
53
58
  const state = context.getState();
54
- if (state.projectRepositoryId && state.projectRepositoryId !== projectRepository.id) throw new Error("The active source-control session does not match its controller repository.");
55
- const connection = await provider.storage.connections.get({
59
+ if (state.projectRepositoryId && state.projectRepositoryId !== ownRepository.id) throw new Error("The active source-control session does not match its controller repository.");
60
+ const ownConnection = await provider.storage.connections.get({
56
61
  orgId,
57
- id: projectRepository.connectionId
62
+ id: ownRepository.connectionId
58
63
  });
59
- if (!connection) throw new Error("The active source-control connection was not found.");
60
- if (state.factoryProjectId && state.factoryProjectId !== connection.factoryProjectId) throw new Error("The active source-control session does not match its Factory project.");
64
+ if (!ownConnection) throw new Error("The active source-control connection was not found.");
65
+ if (state.factoryProjectId && state.factoryProjectId !== ownConnection.factoryProjectId) throw new Error("The active source-control session does not match its Factory project.");
66
+ if (options.repository !== void 0) {
67
+ const candidates = await resolveSessionRepositories({
68
+ sourceControl: provider.storage,
69
+ session
70
+ });
71
+ const match = findEnvironmentRepository(candidates, options.repository);
72
+ if (!match) throw new Error(`Repository '${options.repository}' is not in this Factory's environment. Valid repositories: ${environmentSlugs(candidates).join(", ")}.`);
73
+ return {
74
+ context,
75
+ provider,
76
+ session,
77
+ projectRepository: match.link,
78
+ repository: match.repository,
79
+ orgId,
80
+ userId,
81
+ ownRepository: match.link.id === ownRepository.id
82
+ };
83
+ }
61
84
  const repository = await provider.storage.repositories.get({
62
85
  orgId,
63
- id: projectRepository.repositoryId
86
+ id: ownRepository.repositoryId
64
87
  });
65
88
  if (!repository) throw new Error("The active source-control repository was not found.");
66
89
  return {
67
90
  context,
68
91
  provider,
69
92
  session,
70
- projectRepository,
93
+ projectRepository: ownRepository,
71
94
  repository,
72
95
  orgId,
73
- userId
96
+ userId,
97
+ ownRepository: true
74
98
  };
75
99
  }
100
+ /**
101
+ * The slugs a session may target and the one it is filed under, for the tool
102
+ * descriptions. `undefined` when the session cannot be resolved; the tools
103
+ * then describe the default without naming it.
104
+ */
105
+ async function describeSessionRepositories(resourceId, providers) {
106
+ try {
107
+ const { provider, session } = await resolveProviderSession(resourceId, providers);
108
+ const repositories = await resolveSessionRepositories({
109
+ sourceControl: provider.storage,
110
+ session
111
+ });
112
+ const own = repositories.find((candidate) => candidate.link.id === session.projectRepositoryId);
113
+ return {
114
+ slugs: environmentSlugs(repositories),
115
+ own: own?.repository.slug
116
+ };
117
+ } catch {
118
+ return;
119
+ }
120
+ }
121
+ function repositoryArgumentDescription(described) {
122
+ if (!described || described.slugs.length === 0) return "Optional `repository` (owner/name) selects another repository of this Factory's environment; defaults to this session's repository.";
123
+ const fallback = described.own ? `${described.own}, this session's repository` : "this session's repository";
124
+ return `Optional \`repository\` (owner/name) selects one of this Factory's environment repositories: ${described.slugs.join(", ")}. Defaults to ${fallback}.`;
125
+ }
76
126
  function changeRequestId(value) {
77
127
  return String(value);
78
128
  }
@@ -94,13 +144,16 @@ async function emitAgentAudit(audit, requestContext, input) {
94
144
  });
95
145
  }
96
146
  }
97
- const changeRequestSchema = z.object({ changeRequestId: z.union([z.string().trim().min(1), z.number().int().positive()]) });
98
- function createSourceControlTools({ requestContext, providers, audit }) {
147
+ const repositorySchema = z.object({ repository: z.string().trim().min(1).optional() });
148
+ const changeRequestSchema = repositorySchema.extend({ changeRequestId: z.union([z.string().trim().min(1), z.number().int().positive()]) });
149
+ async function createSourceControlTools({ requestContext, providers, audit }) {
99
150
  if (!requestContext || typeof requestContext.get !== "function") return {};
100
151
  const controller = requestContext.get("controller");
101
152
  const identity = authIdentity(requestContext);
102
153
  if (!controller?.resourceId || !identity.orgId || !identity.userId || providers.length === 0) return {};
103
- const withTarget = () => resolveSessionTarget(requestContext, providers);
154
+ const repositoryArgument = repositoryArgumentDescription(await describeSessionRepositories(controller.resourceId, providers));
155
+ const withTarget = (options) => resolveSessionTarget(requestContext, providers, options);
156
+ const targetFor = (input) => withTarget(input.repository !== void 0 ? { repository: input.repository } : void 0);
104
157
  const reference = async (target) => ({
105
158
  ...await target.provider.versionControl.getRepositoryTarget({
106
159
  orgId: target.orgId,
@@ -139,17 +192,26 @@ function createSourceControlTools({ requestContext, providers, audit }) {
139
192
  }),
140
193
  source_control_push_branch: createTool({
141
194
  id: "source_control_push_branch",
142
- description: "Push the active Factory session branch to its connected source-control provider. Credentials are resolved and scrubbed server-side; this tool takes no token, repository, remote, or branch arguments.",
143
- inputSchema: z.object({}),
144
- execute: async (_input, { workspace }) => {
145
- const target = await withTarget();
195
+ description: `Push the active Factory session branch to its connected source-control provider. Credentials are resolved and scrubbed server-side; this tool takes no token, remote, or branch arguments. ${repositoryArgument}`,
196
+ inputSchema: repositorySchema,
197
+ execute: async (input, { workspace }) => {
198
+ const target = await targetFor(input);
146
199
  const sandbox = executableSandbox(workspace?.sandbox);
147
200
  const workdir = await resolveSessionWorkdir(target.session.id, sandbox, target.repository.slug);
148
201
  const access = await target.provider.versionControl.getRepositoryAccess({
149
202
  orgId: target.orgId,
150
203
  repositoryId: target.repository.id
151
204
  });
152
- await pushRepositoryBranch(sandbox, workdir, target.session.branch, access, target.repository.slug);
205
+ if (!target.ownRepository && !await isCheckoutOf(sandbox, workdir, access.cloneUrl)) throw new Error(`There is no checkout of ${target.repository.slug} in this session.`);
206
+ const branch = target.session.branch;
207
+ await ensureLocalBranch(sandbox, workdir, branch);
208
+ await pushRepositoryBranch(sandbox, workdir, branch, access, target.repository.slug);
209
+ await target.provider.storage.sessionRepositories.upsert({
210
+ sessionId: target.session.sessionId,
211
+ projectRepositoryId: target.projectRepository.id,
212
+ branch
213
+ });
214
+ updateSessionEnvironmentRepository(target.session.sessionId, target.repository.slug, { branch });
153
215
  await emitAgentAudit(audit, requestContext, {
154
216
  action: "factory.agent.push",
155
217
  targets: [{
@@ -157,23 +219,24 @@ function createSourceControlTools({ requestContext, providers, audit }) {
157
219
  id: target.repository.slug
158
220
  }],
159
221
  metadata: {
160
- branch: target.session.branch,
161
- provider: target.provider.id
222
+ branch,
223
+ provider: target.provider.id,
224
+ repository: target.repository.slug
162
225
  }
163
226
  });
164
227
  return {
165
228
  pushed: true,
166
- branch: target.session.branch,
229
+ branch,
167
230
  repository: target.repository.slug
168
231
  };
169
232
  }
170
233
  }),
171
234
  source_control_get_change_request: createTool({
172
235
  id: "source_control_get_change_request",
173
- description: "Read a pull request or merge request in the active Factory repository by its numeric repository-local ID.",
236
+ description: `Read a pull request or merge request in the active Factory repository by its numeric repository-local ID. ${repositoryArgument}`,
174
237
  inputSchema: changeRequestSchema,
175
238
  execute: async (input) => {
176
- const target = await withTarget();
239
+ const target = await targetFor(input);
177
240
  return target.provider.versionControl.getPullRequest({
178
241
  ...await reference(target),
179
242
  pullRequestId: changeRequestId(input.changeRequestId)
@@ -182,10 +245,10 @@ function createSourceControlTools({ requestContext, providers, audit }) {
182
245
  }),
183
246
  source_control_list_change_request_reviews: createTool({
184
247
  id: "source_control_list_change_request_reviews",
185
- description: "List submitted reviews and approvals on a pull request or merge request in the active repository.",
248
+ description: `List submitted reviews and approvals on a pull request or merge request in the active repository. ${repositoryArgument}`,
186
249
  inputSchema: changeRequestSchema.extend({ cursor: z.string().trim().min(1).optional() }),
187
250
  execute: async (input) => {
188
- const target = await withTarget();
251
+ const target = await targetFor(input);
189
252
  return target.provider.versionControl.listReviews({
190
253
  ...await reference(target),
191
254
  pullRequestId: changeRequestId(input.changeRequestId),
@@ -195,22 +258,31 @@ function createSourceControlTools({ requestContext, providers, audit }) {
195
258
  }),
196
259
  source_control_create_change_request: createTool({
197
260
  id: "source_control_create_change_request",
198
- description: "Open a pull request or merge request from the active Factory session branch into its persisted base branch. Push the branch with source_control_push_branch first.",
199
- inputSchema: z.object({
261
+ description: `Open a pull request or merge request from the active Factory session branch into the repository's base branch (the session's persisted base branch in its own repository, the linked or default branch elsewhere). Push the branch with source_control_push_branch first. ${repositoryArgument}`,
262
+ inputSchema: repositorySchema.extend({
200
263
  title: z.string().trim().min(1),
201
264
  body: z.string().optional(),
202
265
  draft: z.boolean().optional()
203
266
  }),
204
267
  execute: async (input) => {
205
- const target = await withTarget();
268
+ const target = await targetFor(input);
269
+ const baseBranch = target.ownRepository ? target.session.baseBranch : target.projectRepository.branch ?? target.repository.defaultBranch;
206
270
  const created = await target.provider.versionControl.createPullRequest({
207
271
  ...await reference(target),
208
272
  title: input.title,
209
273
  ...input.body !== void 0 ? { body: input.body } : {},
210
- baseBranch: target.session.baseBranch,
274
+ baseBranch,
211
275
  headBranch: target.session.branch,
212
276
  ...input.draft !== void 0 ? { draft: input.draft } : {}
213
277
  });
278
+ await target.provider.storage.sessionRepositories.upsert({
279
+ sessionId: target.session.sessionId,
280
+ projectRepositoryId: target.projectRepository.id,
281
+ fallbackBranch: target.session.branch,
282
+ changeRequestId: changeRequestId(created.id),
283
+ changeRequestUrl: created.url
284
+ });
285
+ updateSessionEnvironmentRepository(target.session.sessionId, target.repository.slug, { changeRequestUrl: created.url });
214
286
  await emitAgentAudit(audit, requestContext, {
215
287
  action: "factory.agent.pr_opened",
216
288
  targets: [{
@@ -222,7 +294,8 @@ function createSourceControlTools({ requestContext, providers, audit }) {
222
294
  }],
223
295
  metadata: {
224
296
  url: created.url,
225
- provider: target.provider.id
297
+ provider: target.provider.id,
298
+ repository: target.repository.slug
226
299
  }
227
300
  });
228
301
  return created;
@@ -230,7 +303,7 @@ function createSourceControlTools({ requestContext, providers, audit }) {
230
303
  }),
231
304
  source_control_update_change_request: createTool({
232
305
  id: "source_control_update_change_request",
233
- description: "Update the title, body, target branch, or open/closed state of a change request.",
306
+ description: `Update the title, body, target branch, or open/closed state of a change request. ${repositoryArgument}`,
234
307
  inputSchema: changeRequestSchema.extend({
235
308
  title: z.string().trim().min(1).optional(),
236
309
  body: z.string().nullable().optional(),
@@ -238,7 +311,7 @@ function createSourceControlTools({ requestContext, providers, audit }) {
238
311
  state: z.enum(["open", "closed"]).optional()
239
312
  }),
240
313
  execute: async (input) => {
241
- const target = await withTarget();
314
+ const target = await targetFor(input);
242
315
  return target.provider.versionControl.updatePullRequest({
243
316
  ...await reference(target),
244
317
  pullRequestId: changeRequestId(input.changeRequestId),
@@ -251,10 +324,10 @@ function createSourceControlTools({ requestContext, providers, audit }) {
251
324
  }),
252
325
  source_control_comment_change_request: createTool({
253
326
  id: "source_control_comment_change_request",
254
- description: "Add a top-level comment to a pull request or merge request in the active repository.",
327
+ description: `Add a top-level comment to a pull request or merge request in the active repository. ${repositoryArgument}`,
255
328
  inputSchema: changeRequestSchema.extend({ body: z.string().trim().min(1) }),
256
329
  execute: async (input) => {
257
- const target = await withTarget();
330
+ const target = await targetFor(input);
258
331
  return target.provider.versionControl.createComment({
259
332
  ...await reference(target),
260
333
  pullRequestId: changeRequestId(input.changeRequestId),
@@ -264,10 +337,10 @@ function createSourceControlTools({ requestContext, providers, audit }) {
264
337
  }),
265
338
  source_control_list_change_request_comments: createTool({
266
339
  id: "source_control_list_change_request_comments",
267
- description: "List top-level comments on a pull request or merge request in the active repository.",
340
+ description: `List top-level comments on a pull request or merge request in the active repository. ${repositoryArgument}`,
268
341
  inputSchema: changeRequestSchema.extend({ cursor: z.string().trim().min(1).optional() }),
269
342
  execute: async (input) => {
270
- const target = await withTarget();
343
+ const target = await targetFor(input);
271
344
  return target.provider.versionControl.listComments({
272
345
  ...await reference(target),
273
346
  pullRequestId: changeRequestId(input.changeRequestId),
@@ -277,13 +350,13 @@ function createSourceControlTools({ requestContext, providers, audit }) {
277
350
  }),
278
351
  source_control_update_change_request_comment: createTool({
279
352
  id: "source_control_update_change_request_comment",
280
- description: "Edit a top-level pull-request or merge-request comment in the active repository.",
281
- inputSchema: z.object({
353
+ description: `Edit a top-level pull-request or merge-request comment in the active repository. ${repositoryArgument}`,
354
+ inputSchema: repositorySchema.extend({
282
355
  commentId: z.string().trim().min(1),
283
356
  body: z.string().trim().min(1)
284
357
  }),
285
358
  execute: async (input) => {
286
- const target = await withTarget();
359
+ const target = await targetFor(input);
287
360
  return target.provider.versionControl.updateComment({
288
361
  ...await reference(target),
289
362
  commentId: input.commentId,
@@ -293,10 +366,10 @@ function createSourceControlTools({ requestContext, providers, audit }) {
293
366
  }),
294
367
  source_control_delete_change_request_comment: createTool({
295
368
  id: "source_control_delete_change_request_comment",
296
- description: "Delete a top-level pull-request or merge-request comment in the active repository.",
297
- inputSchema: z.object({ commentId: z.string().trim().min(1) }),
369
+ description: `Delete a top-level pull-request or merge-request comment in the active repository. ${repositoryArgument}`,
370
+ inputSchema: repositorySchema.extend({ commentId: z.string().trim().min(1) }),
298
371
  execute: async (input) => {
299
- const target = await withTarget();
372
+ const target = await targetFor(input);
300
373
  await target.provider.versionControl.deleteComment({
301
374
  ...await reference(target),
302
375
  commentId: input.commentId
@@ -306,10 +379,10 @@ function createSourceControlTools({ requestContext, providers, audit }) {
306
379
  }),
307
380
  source_control_list_diff_comments: createTool({
308
381
  id: "source_control_list_diff_comments",
309
- description: "List line-anchored review comments and discussion replies on a pull request or merge request in the active repository.",
382
+ description: `List line-anchored review comments and discussion replies on a pull request or merge request in the active repository. ${repositoryArgument}`,
310
383
  inputSchema: changeRequestSchema.extend({ cursor: z.string().trim().min(1).optional() }),
311
384
  execute: async (input) => {
312
- const target = await withTarget();
385
+ const target = await targetFor(input);
313
386
  return target.provider.versionControl.listReviewComments({
314
387
  ...await reference(target),
315
388
  pullRequestId: changeRequestId(input.changeRequestId),
@@ -319,7 +392,7 @@ function createSourceControlTools({ requestContext, providers, audit }) {
319
392
  }),
320
393
  source_control_create_diff_comment: createTool({
321
394
  id: "source_control_create_diff_comment",
322
- description: "Create a line-anchored review comment or reply to an existing diff discussion. Use replyToId alone for a reply; otherwise provide commitId, path, line, and side.",
395
+ description: `Create a line-anchored review comment or reply to an existing diff discussion. Use replyToId alone for a reply; otherwise provide commitId, path, line, and side. ${repositoryArgument}`,
323
396
  inputSchema: changeRequestSchema.extend({
324
397
  body: z.string().trim().min(1),
325
398
  replyToId: z.string().trim().min(1).optional(),
@@ -340,7 +413,7 @@ function createSourceControlTools({ requestContext, providers, audit }) {
340
413
  return (input.replyToId !== void 0 ? anchorFields.every((field) => field === void 0) : anchor) && input.startLine === void 0 === (input.startSide === void 0);
341
414
  }, { message: "Provide replyToId alone to reply to a diff thread, or commitId, path, line, and side to start one. startLine and startSide must be provided together." }),
342
415
  execute: async (input) => {
343
- const target = await withTarget();
416
+ const target = await targetFor(input);
344
417
  const base = {
345
418
  ...await reference(target),
346
419
  pullRequestId: changeRequestId(input.changeRequestId),
@@ -366,13 +439,13 @@ function createSourceControlTools({ requestContext, providers, audit }) {
366
439
  }),
367
440
  source_control_update_diff_comment: createTool({
368
441
  id: "source_control_update_diff_comment",
369
- description: "Edit a line-anchored review comment or discussion reply in the active repository.",
370
- inputSchema: z.object({
442
+ description: `Edit a line-anchored review comment or discussion reply in the active repository. ${repositoryArgument}`,
443
+ inputSchema: repositorySchema.extend({
371
444
  commentId: z.string().trim().min(1),
372
445
  body: z.string().trim().min(1)
373
446
  }),
374
447
  execute: async (input) => {
375
- const target = await withTarget();
448
+ const target = await targetFor(input);
376
449
  return target.provider.versionControl.updateReviewComment({
377
450
  ...await reference(target),
378
451
  commentId: input.commentId,
@@ -382,10 +455,10 @@ function createSourceControlTools({ requestContext, providers, audit }) {
382
455
  }),
383
456
  source_control_delete_diff_comment: createTool({
384
457
  id: "source_control_delete_diff_comment",
385
- description: "Delete a line-anchored review comment or discussion reply in the active repository.",
386
- inputSchema: z.object({ commentId: z.string().trim().min(1) }),
458
+ description: `Delete a line-anchored review comment or discussion reply in the active repository. ${repositoryArgument}`,
459
+ inputSchema: repositorySchema.extend({ commentId: z.string().trim().min(1) }),
387
460
  execute: async (input) => {
388
- const target = await withTarget();
461
+ const target = await targetFor(input);
389
462
  await target.provider.versionControl.deleteReviewComment({
390
463
  ...await reference(target),
391
464
  commentId: input.commentId
@@ -395,13 +468,13 @@ function createSourceControlTools({ requestContext, providers, audit }) {
395
468
  }),
396
469
  source_control_resolve_diff_thread: createTool({
397
470
  id: "source_control_resolve_diff_thread",
398
- description: "Resolve or reopen the review thread containing a diff comment. Providers without resolvable threads return an explicit limitation.",
399
- inputSchema: z.object({
471
+ description: `Resolve or reopen the review thread containing a diff comment. Providers without resolvable threads return an explicit limitation. ${repositoryArgument}`,
472
+ inputSchema: repositorySchema.extend({
400
473
  commentId: z.string().trim().min(1),
401
474
  resolved: z.boolean().default(true)
402
475
  }),
403
476
  execute: async (input) => {
404
- const target = await withTarget();
477
+ const target = await targetFor(input);
405
478
  const resolveReviewThread = target.provider.versionControl.resolveReviewThread;
406
479
  if (!resolveReviewThread) throw new Error(`${target.provider.id} does not support resolving review threads.`);
407
480
  await resolveReviewThread({
@@ -414,7 +487,7 @@ function createSourceControlTools({ requestContext, providers, audit }) {
414
487
  }),
415
488
  source_control_review_change_request: createTool({
416
489
  id: "source_control_review_change_request",
417
- description: "Submit an approve, request-changes, or comment review to a change request. Provider limitations are returned explicitly.",
490
+ description: `Submit an approve, request-changes, or comment review to a change request. Provider limitations are returned explicitly. ${repositoryArgument}`,
418
491
  inputSchema: changeRequestSchema.extend({
419
492
  event: z.enum([
420
493
  "approve",
@@ -446,7 +519,7 @@ function createSourceControlTools({ requestContext, providers, audit }) {
446
519
  });
447
520
  }),
448
521
  execute: async (input) => {
449
- const target = await withTarget();
522
+ const target = await targetFor(input);
450
523
  const reviewedHead = reviewedHeadFromBody(input.body);
451
524
  if (reviewedHead) {
452
525
  const pullRequest = await target.provider.versionControl.getPullRequest({
@@ -475,13 +548,13 @@ function createSourceControlTools({ requestContext, providers, audit }) {
475
548
  }),
476
549
  source_control_request_reviewers: createTool({
477
550
  id: "source_control_request_reviewers",
478
- description: "Request individual or team reviewers on a pull request or merge request. Provider limitations are returned explicitly.",
551
+ description: `Request individual or team reviewers on a pull request or merge request. Provider limitations are returned explicitly. ${repositoryArgument}`,
479
552
  inputSchema: changeRequestSchema.extend({
480
553
  users: z.array(z.string().trim().min(1)).default([]),
481
554
  teams: z.array(z.string().trim().min(1)).default([])
482
555
  }),
483
556
  execute: async (input) => {
484
- const target = await withTarget();
557
+ const target = await targetFor(input);
485
558
  return target.provider.versionControl.requestReviewers({
486
559
  ...await reference(target),
487
560
  pullRequestId: changeRequestId(input.changeRequestId),
@@ -492,7 +565,7 @@ function createSourceControlTools({ requestContext, providers, audit }) {
492
565
  }),
493
566
  source_control_merge_change_request: createTool({
494
567
  id: "source_control_merge_change_request",
495
- description: "Merge a pull request or merge request using the requested provider-supported merge method.",
568
+ description: `Merge a pull request or merge request using the requested provider-supported merge method. ${repositoryArgument}`,
496
569
  inputSchema: changeRequestSchema.extend({
497
570
  method: z.enum([
498
571
  "merge",
@@ -503,7 +576,7 @@ function createSourceControlTools({ requestContext, providers, audit }) {
503
576
  commitMessage: z.string().optional()
504
577
  }),
505
578
  execute: async (input) => {
506
- const target = await withTarget();
579
+ const target = await targetFor(input);
507
580
  return target.provider.versionControl.mergePullRequest({
508
581
  ...await reference(target),
509
582
  pullRequestId: changeRequestId(input.changeRequestId),