@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.
- package/README.md +1 -1
- package/dist/artifacts.d.ts.map +1 -1
- package/dist/artifacts.js +0 -5
- package/dist/bin/agent-serve.d.ts +1 -0
- package/dist/bin/agent-serve.d.ts.map +1 -1
- package/dist/bin/agent-serve.js +32 -2
- package/dist/channels/github/types.d.ts +10 -7
- package/dist/channels/github/types.d.ts.map +1 -1
- package/dist/docs/404.html +2 -2
- package/dist/docs/ab.html +3 -3
- package/dist/docs/assets/{app.CgZqLyWL.js → app.D5Mv1T0U.js} +1 -1
- package/dist/docs/assets/chunks/@localSearchIndexroot.Cu7b6o1D.js +1 -0
- package/dist/docs/assets/chunks/{VPLocalSearchBox.C4KigoQn.js → VPLocalSearchBox.CMq_BQce.js} +1 -1
- package/dist/docs/assets/chunks/{theme.C_Ty4yT7.js → theme.C6D9UPLK.js} +2 -2
- package/dist/docs/assets/{example-agents_weather-agent.md.Dmrcphhl.js → example-agents_weather-agent.md.BADkPqxQ.js} +6 -4
- package/dist/docs/assets/example-agents_weather-agent.md.BADkPqxQ.lean.js +1 -0
- package/dist/docs/assets/guides_cloud-runtime.md.CDJGvVC4.js +9 -0
- package/dist/docs/assets/guides_cloud-runtime.md.CDJGvVC4.lean.js +1 -0
- package/dist/docs/building-with-agents.html +3 -3
- package/dist/docs/concepts.html +3 -3
- package/dist/docs/deployment.html +3 -3
- package/dist/docs/evals.html +3 -3
- package/dist/docs/example-agents/approval-buddy.html +3 -3
- package/dist/docs/example-agents/benny.html +3 -3
- package/dist/docs/example-agents/bugbot.html +3 -3
- package/dist/docs/example-agents/codebase-wiki.html +3 -3
- package/dist/docs/example-agents/codeowners-review.html +3 -3
- package/dist/docs/example-agents/concierge.html +3 -3
- package/dist/docs/example-agents/fsd.html +3 -3
- package/dist/docs/example-agents/index.html +3 -3
- package/dist/docs/example-agents/knowledge-base.html +3 -3
- package/dist/docs/example-agents/oncall.html +3 -3
- package/dist/docs/example-agents/security-reviewer.html +3 -3
- package/dist/docs/example-agents/slack-agent.html +3 -3
- package/dist/docs/example-agents/weather-agent.html +10 -8
- package/dist/docs/guides/agent-to-agent.html +3 -3
- package/dist/docs/guides/cloud-runtime.html +5 -5
- package/dist/docs/guides/github.html +3 -3
- package/dist/docs/guides/human-in-the-loop.html +3 -3
- package/dist/docs/guides/mcp-oauth.html +3 -3
- package/dist/docs/guides/slack.html +3 -3
- package/dist/docs/guides/webhooks.html +3 -3
- package/dist/docs/hashmap.json +1 -1
- package/dist/docs/hillclimbing.html +3 -3
- package/dist/docs/index.html +3 -3
- package/dist/docs/quickstart.html +3 -3
- package/dist/docs/reference/agent-config.html +3 -3
- package/dist/docs/reference/channels.html +3 -3
- package/dist/docs/reference/cli.html +3 -3
- package/dist/docs/reference/connections.html +3 -3
- package/dist/docs/reference/hooks.html +3 -3
- package/dist/docs/reference/http-api.html +3 -3
- package/dist/docs/reference/instructions.html +3 -3
- package/dist/docs/reference/playground.html +3 -3
- package/dist/docs/reference/project-layout.html +3 -3
- package/dist/docs/reference/prompt.html +3 -3
- package/dist/docs/reference/schedules.html +3 -3
- package/dist/docs/reference/sessions.html +3 -3
- package/dist/docs/reference/skills.html +3 -3
- package/dist/docs/reference/subagents.html +3 -3
- package/dist/docs/reference/tools.html +3 -3
- package/dist/docs/scaffolding-agents.html +3 -3
- package/dist/docs/storage.html +3 -3
- package/dist/docs/troubleshooting.html +3 -3
- package/dist/files-backends/agent-store-presigned-url.d.ts +3 -11
- package/dist/files.d.ts +20 -0
- package/dist/files.d.ts.map +1 -1
- package/dist/files.js +20 -0
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -2
- package/dist/internal/artifacts-store.d.ts +14 -6
- package/dist/internal/artifacts-store.d.ts.map +1 -1
- package/dist/internal/artifacts-store.js +160 -16
- package/dist/internal/cli-convert-automation.d.ts +39 -0
- package/dist/internal/cli-convert-automation.d.ts.map +1 -0
- package/dist/internal/cli-convert-automation.js +280 -0
- package/dist/internal/cli-deploy.d.ts +2 -0
- package/dist/internal/cli-deploy.d.ts.map +1 -1
- package/dist/internal/cli-deploy.js +1 -1
- package/dist/internal/cli-mcp-oauth.d.ts +23 -0
- package/dist/internal/cli-mcp-oauth.d.ts.map +1 -1
- package/dist/internal/cli-mcp-oauth.js +57 -33
- package/dist/internal/convert-automation/convert-workflow.d.ts +10 -0
- package/dist/internal/convert-automation/convert-workflow.d.ts.map +1 -0
- package/dist/internal/convert-automation/convert-workflow.js +998 -0
- package/dist/internal/convert-automation/index.d.ts +3 -0
- package/dist/internal/convert-automation/index.d.ts.map +1 -0
- package/dist/internal/convert-automation/index.js +1 -0
- package/dist/internal/convert-automation/slug.d.ts +11 -0
- package/dist/internal/convert-automation/slug.d.ts.map +1 -0
- package/dist/internal/convert-automation/slug.js +36 -0
- package/dist/internal/convert-automation/types.d.ts +191 -0
- package/dist/internal/convert-automation/types.d.ts.map +1 -0
- package/dist/internal/convert-automation/types.js +13 -0
- package/dist/internal/deploy-client.d.ts +31 -0
- package/dist/internal/deploy-client.d.ts.map +1 -1
- package/dist/internal/deploy-client.js +48 -0
- package/dist/internal/discovery.d.ts.map +1 -1
- package/dist/internal/discovery.js +3 -32
- package/dist/internal/host-kv.d.ts +6 -2
- package/dist/internal/host-kv.d.ts.map +1 -1
- package/dist/internal/init-project.d.ts +1 -0
- package/dist/internal/init-project.d.ts.map +1 -1
- package/dist/internal/init-project.js +1 -1
- package/dist/internal/mcp-endpoint.d.ts +6 -0
- package/dist/internal/mcp-endpoint.d.ts.map +1 -1
- package/dist/internal/mcp-endpoint.js +168 -0
- package/dist/internal/resolved-connections.d.ts +15 -0
- package/dist/internal/resolved-connections.d.ts.map +1 -1
- package/dist/internal/resolved-connections.js +12 -5
- package/dist/internal/server.d.ts.map +1 -1
- package/dist/internal/server.js +75 -7
- package/dist/internal/session-engine.d.ts +56 -3
- package/dist/internal/session-engine.d.ts.map +1 -1
- package/dist/internal/session-engine.js +262 -84
- package/dist/internal/storage-coordinator.d.ts +9 -16
- package/dist/internal/storage-coordinator.d.ts.map +1 -1
- package/dist/internal/storage-coordinator.js +7 -52
- package/dist/internal/storage-roles.d.ts +78 -0
- package/dist/internal/storage-roles.d.ts.map +1 -0
- package/dist/internal/storage-roles.js +24 -0
- package/dist/internal/workspace.d.ts +36 -5
- package/dist/internal/workspace.d.ts.map +1 -1
- package/dist/internal/workspace.js +66 -0
- package/dist/memory.d.ts +22 -6
- package/dist/memory.d.ts.map +1 -1
- package/dist/memory.js +100 -8
- package/dist/playground/assets/{index-CVlCAcUx.js → index-D7OV8B_H.js} +50 -50
- package/dist/playground/assets/index-DOb96C0M.css +1 -0
- package/dist/playground/index.html +2 -2
- package/dist/storage.d.ts +0 -4
- package/dist/storage.d.ts.map +1 -1
- package/dist/storage.js +0 -4
- package/dist/types.d.ts +18 -0
- package/dist/types.d.ts.map +1 -1
- package/docs/example-agents/weather-agent.md +29 -11
- package/docs/guides/cloud-runtime.md +6 -4
- package/package.json +3 -1
- package/src/artifacts.ts +0 -6
- package/src/bin/agent-serve.ts +36 -2
- package/src/channels/github/types.ts +10 -7
- package/src/files.ts +27 -0
- package/src/index.ts +6 -1
- package/src/internal/artifacts-store.ts +185 -22
- package/src/internal/cli-convert-automation.ts +352 -0
- package/src/internal/cli-deploy.ts +1 -1
- package/src/internal/cli-mcp-oauth.ts +69 -31
- package/src/internal/convert-automation/convert-workflow.ts +1422 -0
- package/src/internal/convert-automation/index.ts +10 -0
- package/src/internal/convert-automation/slug.ts +38 -0
- package/src/internal/convert-automation/types.ts +199 -0
- package/src/internal/deploy-client.ts +78 -0
- package/src/internal/discovery.ts +3 -37
- package/src/internal/host-kv.ts +6 -2
- package/src/internal/init-project.ts +1 -1
- package/src/internal/mcp-endpoint.ts +243 -0
- package/src/internal/resolved-connections.ts +32 -6
- package/src/internal/server.ts +99 -1
- package/src/internal/session-engine.ts +345 -103
- package/src/internal/storage-coordinator.ts +15 -63
- package/src/internal/storage-roles.ts +86 -0
- package/src/internal/workspace.ts +81 -6
- package/src/memory.ts +126 -10
- package/src/storage.ts +0 -6
- package/src/types.ts +15 -0
- package/dist/docs/assets/chunks/@localSearchIndexroot.B1uHGxBZ.js +0 -1
- package/dist/docs/assets/example-agents_weather-agent.md.Dmrcphhl.lean.js +0 -1
- package/dist/docs/assets/guides_cloud-runtime.md.BZ2GA7Es.js +0 -9
- package/dist/docs/assets/guides_cloud-runtime.md.BZ2GA7Es.lean.js +0 -1
- 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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
1037
|
-
|
|
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
|
-
*
|
|
1072
|
-
*
|
|
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
|
-
|
|
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.
|
|
1093
|
-
//
|
|
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
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
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
|
-
|
|
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":"AAAA
|
|
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
|
/**
|