@cursor/july 0.1.33 → 0.1.35

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 (171) hide show
  1. package/README.md +1 -1
  2. package/dist/artifacts.d.ts.map +1 -1
  3. package/dist/artifacts.js +0 -5
  4. package/dist/bin/agent-serve.d.ts +1 -0
  5. package/dist/bin/agent-serve.d.ts.map +1 -1
  6. package/dist/bin/agent-serve.js +32 -2
  7. package/dist/channels/github/types.d.ts +10 -7
  8. package/dist/channels/github/types.d.ts.map +1 -1
  9. package/dist/docs/404.html +2 -2
  10. package/dist/docs/ab.html +3 -3
  11. package/dist/docs/assets/{app.CgZqLyWL.js → app.D5Mv1T0U.js} +1 -1
  12. package/dist/docs/assets/chunks/@localSearchIndexroot.Cu7b6o1D.js +1 -0
  13. package/dist/docs/assets/chunks/{VPLocalSearchBox.C4KigoQn.js → VPLocalSearchBox.CMq_BQce.js} +1 -1
  14. package/dist/docs/assets/chunks/{theme.C_Ty4yT7.js → theme.C6D9UPLK.js} +2 -2
  15. package/dist/docs/assets/{example-agents_weather-agent.md.Dmrcphhl.js → example-agents_weather-agent.md.BADkPqxQ.js} +6 -4
  16. package/dist/docs/assets/example-agents_weather-agent.md.BADkPqxQ.lean.js +1 -0
  17. package/dist/docs/assets/guides_cloud-runtime.md.CDJGvVC4.js +9 -0
  18. package/dist/docs/assets/guides_cloud-runtime.md.CDJGvVC4.lean.js +1 -0
  19. package/dist/docs/building-with-agents.html +3 -3
  20. package/dist/docs/concepts.html +3 -3
  21. package/dist/docs/deployment.html +3 -3
  22. package/dist/docs/evals.html +3 -3
  23. package/dist/docs/example-agents/approval-buddy.html +3 -3
  24. package/dist/docs/example-agents/benny.html +3 -3
  25. package/dist/docs/example-agents/bugbot.html +3 -3
  26. package/dist/docs/example-agents/codebase-wiki.html +3 -3
  27. package/dist/docs/example-agents/codeowners-review.html +3 -3
  28. package/dist/docs/example-agents/concierge.html +3 -3
  29. package/dist/docs/example-agents/fsd.html +3 -3
  30. package/dist/docs/example-agents/index.html +3 -3
  31. package/dist/docs/example-agents/knowledge-base.html +3 -3
  32. package/dist/docs/example-agents/oncall.html +3 -3
  33. package/dist/docs/example-agents/security-reviewer.html +3 -3
  34. package/dist/docs/example-agents/slack-agent.html +3 -3
  35. package/dist/docs/example-agents/weather-agent.html +10 -8
  36. package/dist/docs/guides/agent-to-agent.html +3 -3
  37. package/dist/docs/guides/cloud-runtime.html +5 -5
  38. package/dist/docs/guides/github.html +3 -3
  39. package/dist/docs/guides/human-in-the-loop.html +3 -3
  40. package/dist/docs/guides/mcp-oauth.html +3 -3
  41. package/dist/docs/guides/slack.html +3 -3
  42. package/dist/docs/guides/webhooks.html +3 -3
  43. package/dist/docs/hashmap.json +1 -1
  44. package/dist/docs/hillclimbing.html +3 -3
  45. package/dist/docs/index.html +3 -3
  46. package/dist/docs/quickstart.html +3 -3
  47. package/dist/docs/reference/agent-config.html +3 -3
  48. package/dist/docs/reference/channels.html +3 -3
  49. package/dist/docs/reference/cli.html +3 -3
  50. package/dist/docs/reference/connections.html +3 -3
  51. package/dist/docs/reference/hooks.html +3 -3
  52. package/dist/docs/reference/http-api.html +3 -3
  53. package/dist/docs/reference/instructions.html +3 -3
  54. package/dist/docs/reference/playground.html +3 -3
  55. package/dist/docs/reference/project-layout.html +3 -3
  56. package/dist/docs/reference/prompt.html +3 -3
  57. package/dist/docs/reference/schedules.html +3 -3
  58. package/dist/docs/reference/sessions.html +3 -3
  59. package/dist/docs/reference/skills.html +3 -3
  60. package/dist/docs/reference/subagents.html +3 -3
  61. package/dist/docs/reference/tools.html +3 -3
  62. package/dist/docs/scaffolding-agents.html +3 -3
  63. package/dist/docs/storage.html +3 -3
  64. package/dist/docs/troubleshooting.html +3 -3
  65. package/dist/files-backends/agent-store-presigned-url.d.ts +3 -11
  66. package/dist/files.d.ts +20 -0
  67. package/dist/files.d.ts.map +1 -1
  68. package/dist/files.js +20 -0
  69. package/dist/index.d.ts +2 -2
  70. package/dist/index.d.ts.map +1 -1
  71. package/dist/index.js +2 -2
  72. package/dist/internal/artifacts-store.d.ts +14 -6
  73. package/dist/internal/artifacts-store.d.ts.map +1 -1
  74. package/dist/internal/artifacts-store.js +160 -16
  75. package/dist/internal/cli-convert-automation.d.ts +39 -0
  76. package/dist/internal/cli-convert-automation.d.ts.map +1 -0
  77. package/dist/internal/cli-convert-automation.js +280 -0
  78. package/dist/internal/cli-deploy.d.ts +2 -0
  79. package/dist/internal/cli-deploy.d.ts.map +1 -1
  80. package/dist/internal/cli-deploy.js +1 -1
  81. package/dist/internal/cli-mcp-oauth.d.ts +23 -0
  82. package/dist/internal/cli-mcp-oauth.d.ts.map +1 -1
  83. package/dist/internal/cli-mcp-oauth.js +57 -33
  84. package/dist/internal/convert-automation/convert-workflow.d.ts +10 -0
  85. package/dist/internal/convert-automation/convert-workflow.d.ts.map +1 -0
  86. package/dist/internal/convert-automation/convert-workflow.js +998 -0
  87. package/dist/internal/convert-automation/index.d.ts +3 -0
  88. package/dist/internal/convert-automation/index.d.ts.map +1 -0
  89. package/dist/internal/convert-automation/index.js +1 -0
  90. package/dist/internal/convert-automation/slug.d.ts +11 -0
  91. package/dist/internal/convert-automation/slug.d.ts.map +1 -0
  92. package/dist/internal/convert-automation/slug.js +36 -0
  93. package/dist/internal/convert-automation/types.d.ts +191 -0
  94. package/dist/internal/convert-automation/types.d.ts.map +1 -0
  95. package/dist/internal/convert-automation/types.js +13 -0
  96. package/dist/internal/deploy-client.d.ts +31 -0
  97. package/dist/internal/deploy-client.d.ts.map +1 -1
  98. package/dist/internal/deploy-client.js +48 -0
  99. package/dist/internal/discovery.d.ts.map +1 -1
  100. package/dist/internal/discovery.js +3 -32
  101. package/dist/internal/host-kv.d.ts +6 -2
  102. package/dist/internal/host-kv.d.ts.map +1 -1
  103. package/dist/internal/init-project.d.ts +1 -0
  104. package/dist/internal/init-project.d.ts.map +1 -1
  105. package/dist/internal/init-project.js +1 -1
  106. package/dist/internal/mcp-endpoint.d.ts +6 -0
  107. package/dist/internal/mcp-endpoint.d.ts.map +1 -1
  108. package/dist/internal/mcp-endpoint.js +168 -0
  109. package/dist/internal/resolved-connections.d.ts +15 -0
  110. package/dist/internal/resolved-connections.d.ts.map +1 -1
  111. package/dist/internal/resolved-connections.js +12 -5
  112. package/dist/internal/server.d.ts.map +1 -1
  113. package/dist/internal/server.js +75 -7
  114. package/dist/internal/session-engine.d.ts +56 -3
  115. package/dist/internal/session-engine.d.ts.map +1 -1
  116. package/dist/internal/session-engine.js +262 -84
  117. package/dist/internal/storage-coordinator.d.ts +9 -16
  118. package/dist/internal/storage-coordinator.d.ts.map +1 -1
  119. package/dist/internal/storage-coordinator.js +7 -52
  120. package/dist/internal/storage-roles.d.ts +78 -0
  121. package/dist/internal/storage-roles.d.ts.map +1 -0
  122. package/dist/internal/storage-roles.js +24 -0
  123. package/dist/internal/workspace.d.ts +36 -5
  124. package/dist/internal/workspace.d.ts.map +1 -1
  125. package/dist/internal/workspace.js +66 -0
  126. package/dist/memory.d.ts +22 -6
  127. package/dist/memory.d.ts.map +1 -1
  128. package/dist/memory.js +100 -8
  129. package/dist/playground/assets/{index-CVlCAcUx.js → index-D7OV8B_H.js} +50 -50
  130. package/dist/playground/assets/index-DOb96C0M.css +1 -0
  131. package/dist/playground/index.html +2 -2
  132. package/dist/storage.d.ts +0 -4
  133. package/dist/storage.d.ts.map +1 -1
  134. package/dist/storage.js +0 -4
  135. package/dist/types.d.ts +18 -0
  136. package/dist/types.d.ts.map +1 -1
  137. package/docs/example-agents/weather-agent.md +29 -11
  138. package/docs/guides/cloud-runtime.md +6 -4
  139. package/package.json +3 -1
  140. package/src/artifacts.ts +0 -6
  141. package/src/bin/agent-serve.ts +36 -2
  142. package/src/channels/github/types.ts +10 -7
  143. package/src/files.ts +27 -0
  144. package/src/index.ts +6 -1
  145. package/src/internal/artifacts-store.ts +185 -22
  146. package/src/internal/cli-convert-automation.ts +352 -0
  147. package/src/internal/cli-deploy.ts +1 -1
  148. package/src/internal/cli-mcp-oauth.ts +69 -31
  149. package/src/internal/convert-automation/convert-workflow.ts +1422 -0
  150. package/src/internal/convert-automation/index.ts +10 -0
  151. package/src/internal/convert-automation/slug.ts +38 -0
  152. package/src/internal/convert-automation/types.ts +199 -0
  153. package/src/internal/deploy-client.ts +78 -0
  154. package/src/internal/discovery.ts +3 -37
  155. package/src/internal/host-kv.ts +6 -2
  156. package/src/internal/init-project.ts +1 -1
  157. package/src/internal/mcp-endpoint.ts +243 -0
  158. package/src/internal/resolved-connections.ts +32 -6
  159. package/src/internal/server.ts +99 -1
  160. package/src/internal/session-engine.ts +345 -103
  161. package/src/internal/storage-coordinator.ts +15 -63
  162. package/src/internal/storage-roles.ts +86 -0
  163. package/src/internal/workspace.ts +81 -6
  164. package/src/memory.ts +126 -10
  165. package/src/storage.ts +0 -6
  166. package/src/types.ts +15 -0
  167. package/dist/docs/assets/chunks/@localSearchIndexroot.B1uHGxBZ.js +0 -1
  168. package/dist/docs/assets/example-agents_weather-agent.md.Dmrcphhl.lean.js +0 -1
  169. package/dist/docs/assets/guides_cloud-runtime.md.BZ2GA7Es.js +0 -9
  170. package/dist/docs/assets/guides_cloud-runtime.md.BZ2GA7Es.lean.js +0 -1
  171. package/dist/playground/assets/index-BRhBbnd4.css +0 -1
@@ -32,6 +32,7 @@ import { mergeABInstructions, resolveABMaxPlaygroundSessions, resolveABSplit, }
32
32
  import { slackThreadPermalink } from "../channels/slack/links.js";
33
33
  import { SlackAskDedupeStore, SlackNudgeStore, } from "../channels/slack/nudge-store.js";
34
34
  import { resolveDedicatedSlackHostBinding } from "../channels/slack/slack-channel.js";
35
+ import { isCursorHostedFilesAvailable } from "../files-backends/cursor-hosted.js";
35
36
  import { DEFAULT_MODEL, DIRECT_TOOL_CALL_CHANNEL_ID, isHostOauthConnectionTransport, isSymbolicConnectionTransport, } from "../types.js";
36
37
  import { ABCollector } from "./ab-collector.js";
37
38
  import { foldABStream } from "./ab-fold.js";
@@ -57,7 +58,7 @@ import { StorageCoordinator } from "./storage-coordinator.js";
57
58
  import { normalizeToolResult, toolCallErrorMessage } from "./tool-result.js";
58
59
  import { estimateTurnCostFromApi, roundCostUsd, } from "./turn-cost.js";
59
60
  import { TurnGovernor } from "./turn-governor.js";
60
- import { buildAgentsMdContent, isNestedInGitRepo, materializeWorkspace, writeWorkspaceFiles, } from "./workspace.js";
61
+ import { buildAgentsMdContent, buildCloudMemorySection, isNestedInGitRepo, materializeWorkspace, SERVER_TOOLS_MCP_SERVER_NAME, writeWorkspaceFiles, } from "./workspace.js";
61
62
  export const HTTP_CHANNEL_ID = "http";
62
63
  export { SCHEDULE_CHANNEL_PREFIX } from "./prompt-context.js";
63
64
  export class SessionBusyError extends Error {
@@ -124,6 +125,8 @@ export class SessionEngine {
124
125
  /** Sessions with a turn being admitted (before the run promise exists). */
125
126
  this.pendingTurns = new Set();
126
127
  this.activeTurns = new Map();
128
+ /** Context used by the cloud turn's HTTP MCP callbacks. */
129
+ this.activeToolContexts = new Map();
127
130
  /** Aborts the in-flight turn per session so a follow-up can preempt it. */
128
131
  this.turnAborts = new Map();
129
132
  /** Serializes turn admission per session (latest follow-up wins). */
@@ -176,7 +179,7 @@ export class SessionEngine {
176
179
  });
177
180
  this.artifactsStore = new ArtifactsStore({
178
181
  stateRoot: options.stateRoot,
179
- storage: this.storage,
182
+ agentName: options.project.name,
180
183
  config: options.project.artifacts,
181
184
  });
182
185
  this.abCollector = new ABCollector(options.project.abs, this.logger, (sessionId) => __awaiter(this, void 0, void 0, function* () { return (yield this.logs.get(sessionId)).snapshot(0); }),
@@ -219,6 +222,9 @@ export class SessionEngine {
219
222
  });
220
223
  }
221
224
  }
225
+ setCloudServerToolsConnection(connection) {
226
+ this.cloudServerToolsConnection = connection;
227
+ }
222
228
  /** Shared host services (MCP / GitHub / Slack / reminders / evals / kv / Slack nudges). */
223
229
  get host() {
224
230
  return {
@@ -933,7 +939,13 @@ export class SessionEngine {
933
939
  yield yieldEventLoop();
934
940
  }
935
941
  }), signal);
936
- outcome = yield this.runner.runTurn(request);
942
+ this.activeToolContexts.set(sessionId, { record, turnId, emit });
943
+ try {
944
+ outcome = yield this.runner.runTurn(request);
945
+ }
946
+ finally {
947
+ this.activeToolContexts.delete(sessionId);
948
+ }
937
949
  }
938
950
  catch (error) {
939
951
  this.approvals.cancelSession(sessionId, "deny");
@@ -1032,9 +1044,22 @@ export class SessionEngine {
1032
1044
  if (isFirstTurn) {
1033
1045
  if (runtime === "cloud") {
1034
1046
  // Cloud VMs have no materialized workspace: ship the full context,
1035
- // including agent tool script bodies.
1036
- const preamble = buildAgentsMdContent(agent, { includeScripts: true });
1037
- turnPrompt = `${preamble}\n\n${turnPrompt}`;
1047
+ // including agent tool script bodies. On hosted deployments the
1048
+ // shared memory journal is on the store mount — say where. When the
1049
+ // turn carries the session-bound server-tool MCP endpoint, the
1050
+ // preamble also catalogs server tools under that MCP server name;
1051
+ // without it a model told to "use <server tool>" finds no script
1052
+ // and improvises a local substitute instead of calling the host.
1053
+ const preamble = buildAgentsMdContent(agent, {
1054
+ includeScripts: true,
1055
+ serverToolsMcpName: this.cloudServerToolsConnection === undefined
1056
+ ? undefined
1057
+ : SERVER_TOOLS_MCP_SERVER_NAME,
1058
+ });
1059
+ const memorySection = isCursorHostedFilesAvailable()
1060
+ ? `\n\n${buildCloudMemorySection(this.project.name)}`
1061
+ : "";
1062
+ turnPrompt = `${preamble}${memorySection}\n\n${turnPrompt}`;
1038
1063
  }
1039
1064
  else if (instructionsInvisibleToHarness) {
1040
1065
  // Local workspace whose AGENTS.md the harness will not load. With a
@@ -1048,7 +1073,7 @@ export class SessionEngine {
1048
1073
  }
1049
1074
  return Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({ sessionId: record.sessionId }, (record.sdkAgentId === undefined
1050
1075
  ? {}
1051
- : { sdkAgentId: record.sdkAgentId })), { workspaceDir: this.harnessCwd(record), sandbox: ((_c = this.project.agent.local) === null || _c === void 0 ? void 0 : _c.sandbox) === true, runnerStateDir: join(this.stateRoot, "runner"), prompt: turnPrompt, isFirstTurn }), (agent.model === undefined ? {} : { model: agent.model })), { runtime }), (mergedCloud === undefined ? {} : { cloud: mergedCloud })), { customTools: runtime === "local" ? this.buildCustomTools(record, turnId, emit) : {}, mcpServers: this.buildMcpServers(runtime), subagents: buildRunnerSubagents(agent), onUpdate,
1076
+ : { sdkAgentId: record.sdkAgentId })), { workspaceDir: this.harnessCwd(record), sandbox: ((_c = this.project.agent.local) === null || _c === void 0 ? void 0 : _c.sandbox) === true, runnerStateDir: join(this.stateRoot, "runner"), prompt: turnPrompt, isFirstTurn }), (agent.model === undefined ? {} : { model: agent.model })), { runtime }), (mergedCloud === undefined ? {} : { cloud: mergedCloud })), { customTools: runtime === "local" ? this.buildCustomTools(record, turnId, emit) : {}, mcpServers: this.buildMcpServers(runtime, record.sessionId), subagents: buildRunnerSubagents(agent), onUpdate,
1052
1077
  signal,
1053
1078
  // Local follow-ups expire any lingering active run so a preempted turn
1054
1079
  // (or one orphaned by a crashed process) never blocks this send.
@@ -1068,17 +1093,85 @@ export class SessionEngine {
1068
1093
  }) });
1069
1094
  }
1070
1095
  /**
1071
- * Authored + resolved MCP servers for a turn; skips `hostOnly`, and skips
1072
- * host-OAuth connections on cloud turns (their tokens live on this host).
1096
+ * Connection names a cloud turn can only reach through the host connection
1097
+ * bridge on the tool MCP endpoint: filtered account connections without a
1098
+ * public bridge URL, and host-OAuth connections whose tokens live on this
1099
+ * host. `hostOnly` names are never bridged — that flag means the model
1100
+ * must not see the connection at all, on any runtime.
1073
1101
  */
1074
- buildMcpServers(runtime) {
1102
+ cloudBridgeableConnectionNames() {
1075
1103
  const hostOnlyNames = new Set(this.project.agent.connections
1076
1104
  .filter((connection) => connection.hostOnly === true)
1077
1105
  .map((connection) => connection.name));
1106
+ const names = [];
1107
+ for (const connection of this.project.agent.connections) {
1108
+ if (!hostOnlyNames.has(connection.name) &&
1109
+ isHostOauthConnectionTransport(connection.transport)) {
1110
+ names.push(connection.name);
1111
+ }
1112
+ }
1113
+ for (const resolved of this.resolvedConnections) {
1114
+ if (!hostOnlyNames.has(resolved.name) &&
1115
+ resolved.accountServersFilter !== undefined &&
1116
+ resolved.cloudUrl === undefined) {
1117
+ names.push(resolved.name);
1118
+ }
1119
+ }
1120
+ return names;
1121
+ }
1122
+ /**
1123
+ * True when cloud turns reach `name` through the host connection bridge —
1124
+ * the gate the tool MCP endpoint applies before forwarding a bridge
1125
+ * request to `host.mcp`, so `hostOnly` connections (and arbitrary names)
1126
+ * stay unreachable from a VM.
1127
+ */
1128
+ isCloudBridgedConnection(name) {
1129
+ if (this.cloudServerToolsConnection === undefined) {
1130
+ return false;
1131
+ }
1132
+ return this.cloudBridgeableConnectionNames().includes(name);
1133
+ }
1134
+ /**
1135
+ * Session-bound transport for one host-bridged connection: the tool MCP
1136
+ * endpoint with the connection named, so `tools/list` / `tools/call`
1137
+ * forward to the host-side client (`host.mcp`) where the credential —
1138
+ * account bridge secret or host OAuth token — actually lives.
1139
+ */
1140
+ cloudBridgeTransport(sessionId, connectionName) {
1141
+ const connection = this.cloudServerToolsConnection;
1142
+ if (connection === undefined || !("url" in connection)) {
1143
+ return undefined;
1144
+ }
1145
+ const url = new URL(connection.url);
1146
+ url.searchParams.set("agentkitSessionId", sessionId);
1147
+ url.searchParams.set("connection", connectionName);
1148
+ return Object.assign(Object.assign({}, connection), { url: url.toString() });
1149
+ }
1150
+ /**
1151
+ * Authored + resolved MCP servers for a turn. Skips `hostOnly`. On cloud
1152
+ * turns, connections whose credential lives on this host — filtered
1153
+ * account connections without a public bridge URL, host-OAuth servers —
1154
+ * mount as host connection bridges over the tool MCP endpoint instead of
1155
+ * being omitted or failing the turn closed.
1156
+ */
1157
+ buildMcpServers(runtime, sessionId) {
1158
+ const hostOnlyNames = new Set(this.project.agent.connections
1159
+ .filter((connection) => connection.hostOnly === true)
1160
+ .map((connection) => connection.name));
1161
+ const bridgedNames = new Set(runtime === "cloud" &&
1162
+ sessionId !== undefined &&
1163
+ this.cloudServerToolsConnection !== undefined &&
1164
+ "url" in this.cloudServerToolsConnection
1165
+ ? this.cloudBridgeableConnectionNames()
1166
+ : []);
1078
1167
  assertCloudCanHonorAccountServersFilters({
1079
1168
  runtime,
1080
1169
  resolvedConnections: this.resolvedConnections.filter((resolved) => !hostOnlyNames.has(resolved.name)),
1170
+ bridgedNames,
1081
1171
  });
1172
+ const bridgeTransport = (name) => sessionId === undefined || !bridgedNames.has(name)
1173
+ ? undefined
1174
+ : this.cloudBridgeTransport(sessionId, name);
1082
1175
  const servers = {};
1083
1176
  for (const connection of this.project.agent.connections) {
1084
1177
  if (hostOnlyNames.has(connection.name)) {
@@ -1089,10 +1182,15 @@ export class SessionEngine {
1089
1182
  }
1090
1183
  // A cloud VM cannot use a credential that lives on this host, and the
1091
1184
  // cloud API rejects the `oauth` key outright ("Unrecognized key(s) in
1092
- // object: 'oauth'"), which fails the whole turn. Omit it there; host
1093
- // tools (`ctx.host.mcp`) still reach the server over the host client.
1185
+ // object: 'oauth'"), which fails the whole turn. Mount the host
1186
+ // connection bridge instead when serve has a cloud tools URL; omit
1187
+ // otherwise (host tools via `ctx.host.mcp` still reach the server).
1094
1188
  if (runtime === "cloud" &&
1095
1189
  isHostOauthConnectionTransport(connection.transport)) {
1190
+ const bridged = bridgeTransport(connection.name);
1191
+ if (bridged !== undefined) {
1192
+ servers[connection.name] = bridged;
1193
+ }
1096
1194
  continue;
1097
1195
  }
1098
1196
  servers[connection.name] = connection.transport;
@@ -1103,6 +1201,13 @@ export class SessionEngine {
1103
1201
  }
1104
1202
  const url = runtime === "cloud" ? resolved.cloudUrl : resolved.localUrl;
1105
1203
  if (url === undefined) {
1204
+ // Filtered account connections bridge through the host so the
1205
+ // `servers` filter is honored; unfiltered ones keep their documented
1206
+ // fallback to the account's native connectors on the VM.
1207
+ const bridged = bridgeTransport(resolved.name);
1208
+ if (bridged !== undefined) {
1209
+ servers[resolved.name] = bridged;
1210
+ }
1106
1211
  continue;
1107
1212
  }
1108
1213
  servers[resolved.name] = {
@@ -1110,6 +1215,20 @@ export class SessionEngine {
1110
1215
  headers: resolved.headers,
1111
1216
  };
1112
1217
  }
1218
+ if (runtime === "cloud" &&
1219
+ sessionId !== undefined &&
1220
+ this.cloudServerToolsConnection !== undefined &&
1221
+ this.project.agent.tools.some((tool) => tool.execution === "server")) {
1222
+ if (servers[SERVER_TOOLS_MCP_SERVER_NAME] !== undefined) {
1223
+ throw new Error(`MCP connection name "${SERVER_TOOLS_MCP_SERVER_NAME}" is reserved for authored server tools on cloud turns.`);
1224
+ }
1225
+ const connection = this.cloudServerToolsConnection;
1226
+ if ("url" in connection) {
1227
+ const url = new URL(connection.url);
1228
+ url.searchParams.set("agentkitSessionId", sessionId);
1229
+ servers[SERVER_TOOLS_MCP_SERVER_NAME] = Object.assign(Object.assign({}, connection), { url: url.toString() });
1230
+ }
1231
+ }
1113
1232
  return servers;
1114
1233
  }
1115
1234
  buildCustomTools(record, turnId, emit) {
@@ -1126,81 +1245,105 @@ export class SessionEngine {
1126
1245
  description: tool.description,
1127
1246
  inputSchema: tool.inputSchema,
1128
1247
  execute: (args, context) => __awaiter(this, void 0, void 0, function* () {
1129
- var _a;
1130
- const validation = validateToolInput(tool.definition.inputSchema, args);
1131
- if (!validation.ok) {
1132
- return {
1133
- content: [
1134
- {
1135
- type: "text",
1136
- text: `Invalid input for tool "${tool.name}": ${validation.message}`,
1137
- },
1138
- ],
1139
- isError: true,
1140
- };
1141
- }
1142
- const toolCallId = (_a = context.toolCallId) !== null && _a !== void 0 ? _a : newToolCallId(tool.name);
1143
- const toolCtx = {
1144
- toolCallId,
1145
- session: this.sessionInfo(record),
1146
- workspaceDir: this.harnessCwd(record),
1147
- stateRoot: this.stateRoot,
1148
- host: this.hostForSession(record.sessionId),
1149
- artifacts: this.artifactsApi({
1150
- sessionId: record.sessionId,
1151
- turnId,
1152
- }),
1153
- send: (channelId, message, sendOptions = {}) => this.send(channelId, message, Object.assign(Object.assign({}, sendOptions), { auth: sendOptions.auth !== undefined
1154
- ? sendOptions.auth
1155
- : record.auth })),
1156
- getSession: (channelId, sessionId) => this.getChannelSession(channelId, sessionId),
1157
- };
1158
- try {
1159
- const needsGate = yield evaluateNeedsApproval(tool.definition.needsApproval, validation.value);
1160
- if (needsGate) {
1161
- const decision = yield this.parkForApproval({
1162
- sessionId: record.sessionId,
1163
- turnId,
1164
- callId: toolCallId,
1165
- toolName: tool.name,
1166
- args: validation.value,
1167
- emit,
1168
- });
1169
- if (decision === "deny") {
1170
- return {
1171
- content: [
1172
- {
1173
- type: "text",
1174
- text: `Tool "${tool.name}" was denied by a human approver.`,
1175
- },
1176
- ],
1177
- isError: true,
1178
- };
1179
- }
1180
- }
1181
- const started = Date.now();
1182
- this.logger(`[session] tool ${tool.name} start`);
1183
- const result = yield execute(validation.value, toolCtx);
1184
- this.logger(`[session] tool ${tool.name} done (${Date.now() - started}ms)`);
1185
- return normalizeToolResult(result);
1186
- }
1187
- catch (error) {
1188
- this.logger(`[session] tool ${tool.name} failed: ${describeError(error)}`);
1189
- return {
1190
- content: [
1191
- {
1192
- type: "text",
1193
- text: `Tool "${tool.name}" failed: ${describeError(error)}`,
1194
- },
1195
- ],
1196
- isError: true,
1197
- };
1198
- }
1248
+ return this.executeServerTool({
1249
+ tool,
1250
+ input: args,
1251
+ toolCallId: context.toolCallId,
1252
+ record,
1253
+ turnId,
1254
+ emit,
1255
+ });
1199
1256
  }),
1200
1257
  };
1201
1258
  }
1202
1259
  return tools;
1203
1260
  }
1261
+ /**
1262
+ * True while `sessionId` has a turn in flight. The host connection bridge
1263
+ * applies this before forwarding to `host.mcp` — the same window
1264
+ * {@link callActiveServerTool} enforces for authored server tools — so an
1265
+ * endpoint credential that outlives a turn (e.g. in a VM's MCP config)
1266
+ * cannot reach host-credentialed connectors between turns.
1267
+ */
1268
+ hasActiveTurn(sessionId) {
1269
+ return this.activeToolContexts.has(sessionId);
1270
+ }
1271
+ callActiveServerTool(sessionId, toolName, input) {
1272
+ return __awaiter(this, void 0, void 0, function* () {
1273
+ const active = this.activeToolContexts.get(sessionId);
1274
+ if (active === undefined) {
1275
+ return toolErrorResult(`Session ${sessionId} has no active turn for tool "${toolName}".`);
1276
+ }
1277
+ const tool = this.project.agent.tools.find((candidate) => candidate.name === toolName && candidate.execution === "server");
1278
+ if (tool === undefined) {
1279
+ return toolErrorResult(`Unknown server tool "${toolName}".`);
1280
+ }
1281
+ const toolCallId = newToolCallId(toolName);
1282
+ this.logger(`[session] cloud HTTP MCP tool ${toolName} dispatch (${sessionId}, ${toolCallId})`);
1283
+ const result = yield this.executeServerTool({
1284
+ tool,
1285
+ input,
1286
+ toolCallId,
1287
+ record: active.record,
1288
+ turnId: active.turnId,
1289
+ emit: active.emit,
1290
+ });
1291
+ this.logger(`[session] cloud HTTP MCP tool ${toolName} complete (${sessionId}, ${toolCallId}, isError=${isErrorEnvelope(result)})`);
1292
+ return result;
1293
+ });
1294
+ }
1295
+ executeServerTool(args) {
1296
+ return __awaiter(this, void 0, void 0, function* () {
1297
+ var _a;
1298
+ const execute = args.tool.definition.execute;
1299
+ if (args.tool.execution !== "server" || typeof execute !== "function") {
1300
+ return toolErrorResult(`Tool "${args.tool.name}" is not a server tool.`);
1301
+ }
1302
+ const validation = validateToolInput(args.tool.definition.inputSchema, args.input);
1303
+ if (!validation.ok) {
1304
+ return toolErrorResult(`Invalid input for tool "${args.tool.name}": ${validation.message}`);
1305
+ }
1306
+ const toolCallId = (_a = args.toolCallId) !== null && _a !== void 0 ? _a : newToolCallId(args.tool.name);
1307
+ const toolCtx = {
1308
+ toolCallId,
1309
+ session: this.sessionInfo(args.record),
1310
+ workspaceDir: this.harnessCwd(args.record),
1311
+ stateRoot: this.stateRoot,
1312
+ host: this.hostForSession(args.record.sessionId),
1313
+ artifacts: this.artifactsApi({
1314
+ sessionId: args.record.sessionId,
1315
+ turnId: args.turnId,
1316
+ }),
1317
+ send: (channelId, message, sendOptions = {}) => { var _a; return this.send(channelId, message, Object.assign(Object.assign({}, sendOptions), { auth: (_a = sendOptions.auth) !== null && _a !== void 0 ? _a : args.record.auth })); },
1318
+ getSession: (channelId, sessionId) => this.getChannelSession(channelId, sessionId),
1319
+ };
1320
+ try {
1321
+ const needsGate = yield evaluateNeedsApproval(args.tool.definition.needsApproval, validation.value);
1322
+ if (needsGate) {
1323
+ const decision = yield this.parkForApproval({
1324
+ sessionId: args.record.sessionId,
1325
+ turnId: args.turnId,
1326
+ callId: toolCallId,
1327
+ toolName: args.tool.name,
1328
+ args: validation.value,
1329
+ emit: args.emit,
1330
+ });
1331
+ if (decision === "deny") {
1332
+ return toolErrorResult(`Tool "${args.tool.name}" was denied by a human approver.`);
1333
+ }
1334
+ }
1335
+ const started = Date.now();
1336
+ this.logger(`[session] tool ${args.tool.name} start`);
1337
+ const result = yield execute(validation.value, toolCtx);
1338
+ this.logger(`[session] tool ${args.tool.name} done (${Date.now() - started}ms)`);
1339
+ return normalizeToolResult(result);
1340
+ }
1341
+ catch (error) {
1342
+ this.logger(`[session] tool ${args.tool.name} failed: ${describeError(error)}`);
1343
+ return toolErrorResult(`Tool "${args.tool.name}" failed: ${describeError(error)}`);
1344
+ }
1345
+ });
1346
+ }
1204
1347
  /**
1205
1348
  * Park a server-tool call until a human approves or denies. Emits
1206
1349
  * `action.approval_requested` / `action.approval_resolved` on the
@@ -1616,11 +1759,40 @@ export class SessionEngine {
1616
1759
  if ((options === null || options === void 0 ? void 0 : options.includeAll) === true) {
1617
1760
  return records;
1618
1761
  }
1762
+ const owned = yield this.ownedSessionIds(caller);
1763
+ return records.filter((record) => record.sessionId !== undefined && owned.has(record.sessionId));
1764
+ });
1765
+ }
1766
+ /**
1767
+ * One artifact's file/blob payload for `GET /v1/artifacts/:id/content`.
1768
+ * Same visibility rule as {@link listArtifacts}. Undefined when the
1769
+ * artifact is missing, invisible to the caller, or carries no payload.
1770
+ */
1771
+ getArtifactContent(caller, id, options) {
1772
+ return __awaiter(this, void 0, void 0, function* () {
1773
+ const record = yield this.artifactsStore.get(id);
1774
+ if (record === undefined || record.content === undefined) {
1775
+ return undefined;
1776
+ }
1777
+ if ((options === null || options === void 0 ? void 0 : options.includeAll) !== true) {
1778
+ if (record.sessionId === undefined) {
1779
+ return undefined;
1780
+ }
1781
+ const owned = yield this.ownedSessionIds(caller);
1782
+ if (!owned.has(record.sessionId)) {
1783
+ return undefined;
1784
+ }
1785
+ }
1786
+ const body = yield this.artifactsStore.getContent(id);
1787
+ return body === undefined ? undefined : { record, body };
1788
+ });
1789
+ }
1790
+ ownedSessionIds(caller) {
1791
+ return __awaiter(this, void 0, void 0, function* () {
1619
1792
  const sessions = yield this.sessions.list();
1620
- const owned = new Set(sessions
1793
+ return new Set(sessions
1621
1794
  .filter((record) => samePrincipal(record.auth, caller))
1622
1795
  .map((record) => record.sessionId));
1623
- return records.filter((record) => record.sessionId !== undefined && owned.has(record.sessionId));
1624
1796
  });
1625
1797
  }
1626
1798
  /**
@@ -2273,6 +2445,12 @@ function buildRunnerSubagents(agent) {
2273
2445
  function describeError(error) {
2274
2446
  return error instanceof Error ? error.message : String(error);
2275
2447
  }
2448
+ function toolErrorResult(message) {
2449
+ return {
2450
+ content: [{ type: "text", text: message }],
2451
+ isError: true,
2452
+ };
2453
+ }
2276
2454
  function defaultGetCloudUsage(sdkAgentId) {
2277
2455
  return __awaiter(this, void 0, void 0, function* () {
2278
2456
  try {
@@ -14,19 +14,27 @@
14
14
  * and A/B metrics go to their dedicated tables (`evals` / `abs`).
15
15
  * Reminder documents live on the control plane. Everything shares one
16
16
  * bounded, serialized queue.
17
+ *
18
+ * It does three unrelated jobs, declared separately as
19
+ * {@link FrameworkSessionStore}, {@link AuthorKvStore}, and
20
+ * {@link EvalAbStore} — see `storage-roles.ts` for why they differ and where
21
+ * each is headed. The queue stays shared: it is one bounded, serialized chain
22
+ * per agent, and splitting it would change backpressure behavior, which this
23
+ * seam deliberately does not touch.
17
24
  */
18
25
  import type { ABMetricSample } from "../ab.js";
19
26
  import { type ResolvedStoragePolicy, type StorageContext, type StorageDefinition } from "../storage.js";
20
27
  import type { JsonValue, SessionEvent, SessionRecord } from "../types.js";
21
28
  import type { ABSnapshot } from "./ab-snapshot.js";
22
29
  import type { EvalRunStorage } from "./eval-run-store.js";
30
+ import type { AuthorKvStore, EvalAbStore, FrameworkSessionStore } from "./storage-roles.js";
23
31
  export interface StorageCoordinatorOptions {
24
32
  definition: StorageDefinition;
25
33
  agentName: string;
26
34
  projectRoot: string;
27
35
  logger: (line: string) => void;
28
36
  }
29
- export declare class StorageCoordinator {
37
+ export declare class StorageCoordinator implements FrameworkSessionStore, AuthorKvStore, EvalAbStore {
30
38
  readonly policy: ResolvedStoragePolicy;
31
39
  private readonly definition;
32
40
  private readonly agentName;
@@ -130,21 +138,6 @@ export declare class StorageCoordinator {
130
138
  kvPut(authorKey: string, value: JsonValue): Promise<void>;
131
139
  /** Awaited author KV delete. No-op when the sink omits `delete`. */
132
140
  kvDelete(authorKey: string): Promise<void>;
133
- /**
134
- * Whether the sink can serve awaited artifact rows: `get` (upsert
135
- * read-back), `list` (listing + eviction), and `delete` (`max` cap
136
- * eviction) are all required — without `delete` the retention cap
137
- * could never evict, so rows fall back to the filesystem store.
138
- */
139
- get supportsArtifacts(): boolean;
140
- /** Awaited artifact-row read. Errors propagate (read-after-write). */
141
- artifactGet(id: string): Promise<JsonValue | undefined>;
142
- /** Awaited artifact-row write (straight to the sink, like author KV). */
143
- artifactPut(id: string, value: JsonValue): Promise<void>;
144
- /** Awaited artifact-row delete. Errors propagate (cap eviction). */
145
- artifactDelete(id: string): Promise<void>;
146
- /** All artifact-row values for this agent. Errors propagate. */
147
- artifactList(): Promise<JsonValue[]>;
148
141
  /**
149
142
  * Adapter over the sink's dedicated `evals` table for the playground
150
143
  * eval-run store. Undefined when the table is not configured — eval
@@ -1 +1 @@
1
- {"version":3,"file":"storage-coordinator.d.ts","sourceRoot":"","sources":["../../src/internal/storage-coordinator.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"storage-coordinator.d.ts","sourceRoot":"","sources":["../../src/internal/storage-coordinator.ts"],"names":[],"mappings":"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"}
@@ -14,6 +14,13 @@
14
14
  * and A/B metrics go to their dedicated tables (`evals` / `abs`).
15
15
  * Reminder documents live on the control plane. Everything shares one
16
16
  * bounded, serialized queue.
17
+ *
18
+ * It does three unrelated jobs, declared separately as
19
+ * {@link FrameworkSessionStore}, {@link AuthorKvStore}, and
20
+ * {@link EvalAbStore} — see `storage-roles.ts` for why they differ and where
21
+ * each is headed. The queue stays shared: it is one bounded, serialized chain
22
+ * per agent, and splitting it would change backpressure behavior, which this
23
+ * seam deliberately does not touch.
17
24
  */
18
25
  var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
19
26
  function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
@@ -364,58 +371,6 @@ export class StorageCoordinator {
364
371
  });
365
372
  }
366
373
  // ==========================================================================
367
- // Artifacts (`ctx.artifacts`)
368
- // ==========================================================================
369
- /**
370
- * Whether the sink can serve awaited artifact rows: `get` (upsert
371
- * read-back), `list` (listing + eviction), and `delete` (`max` cap
372
- * eviction) are all required — without `delete` the retention cap
373
- * could never evict, so rows fall back to the filesystem store.
374
- */
375
- get supportsArtifacts() {
376
- return (this.definition.get !== undefined &&
377
- this.definition.list !== undefined &&
378
- this.definition.delete !== undefined);
379
- }
380
- /** Awaited artifact-row read. Errors propagate (read-after-write). */
381
- artifactGet(id) {
382
- return __awaiter(this, void 0, void 0, function* () {
383
- const get = this.definition.get;
384
- if (get === undefined) {
385
- throw new Error("storage get is not configured");
386
- }
387
- const value = yield get(storageKeys.artifact(this.agentName, id), this.context("restore"));
388
- return value !== null && value !== void 0 ? value : undefined;
389
- });
390
- }
391
- /** Awaited artifact-row write (straight to the sink, like author KV). */
392
- artifactPut(id, value) {
393
- return __awaiter(this, void 0, void 0, function* () {
394
- yield this.definition.put(storageKeys.artifact(this.agentName, id), value, this.context("policy"));
395
- });
396
- }
397
- /** Awaited artifact-row delete. Errors propagate (cap eviction). */
398
- artifactDelete(id) {
399
- return __awaiter(this, void 0, void 0, function* () {
400
- const del = this.definition.delete;
401
- if (del === undefined) {
402
- throw new Error("storage delete is not configured");
403
- }
404
- yield del(storageKeys.artifact(this.agentName, id), this.context("policy"));
405
- });
406
- }
407
- /** All artifact-row values for this agent. Errors propagate. */
408
- artifactList() {
409
- return __awaiter(this, void 0, void 0, function* () {
410
- const list = this.definition.list;
411
- if (list === undefined) {
412
- throw new Error("storage list is not configured");
413
- }
414
- const entries = yield list(storageKeys.artifactPrefix(this.agentName), this.context("restore"));
415
- return Array.isArray(entries) ? entries.map((entry) => entry.value) : [];
416
- });
417
- }
418
- // ==========================================================================
419
374
  // Evals (dedicated `evals` table)
420
375
  // ==========================================================================
421
376
  /**