@cursor/july 0.1.103 → 0.1.105
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/channels/change-monitors/change-monitors-channel.d.ts +5 -0
- package/dist/channels/change-monitors/change-monitors-channel.d.ts.map +1 -0
- package/dist/channels/change-monitors/change-monitors-channel.js +41 -0
- package/dist/channels/change-monitors/index.d.ts +4 -0
- package/dist/channels/change-monitors/index.d.ts.map +1 -0
- package/dist/channels/change-monitors/index.js +2 -0
- package/dist/channels/change-monitors/types.d.ts +39 -0
- package/dist/channels/change-monitors/types.d.ts.map +1 -0
- package/dist/channels/change-monitors/types.js +1 -0
- package/dist/channels/deployments/deployments-channel.d.ts.map +1 -1
- package/dist/channels/deployments/deployments-channel.js +1 -0
- package/dist/channels/deployments/types.d.ts +2 -0
- package/dist/channels/deployments/types.d.ts.map +1 -1
- package/dist/channels/github/defaults.d.ts.map +1 -1
- package/dist/channels/github/defaults.js +4 -0
- package/dist/channels/github/progress.d.ts +22 -0
- package/dist/channels/github/progress.d.ts.map +1 -1
- package/dist/channels/github/progress.js +32 -5
- package/dist/channels/issues/index.d.ts +4 -0
- package/dist/channels/issues/index.d.ts.map +1 -0
- package/dist/channels/issues/index.js +2 -0
- package/dist/channels/issues/issues-channel.d.ts +5 -0
- package/dist/channels/issues/issues-channel.d.ts.map +1 -0
- package/dist/channels/issues/issues-channel.js +37 -0
- package/dist/channels/issues/types.d.ts +33 -0
- package/dist/channels/issues/types.d.ts.map +1 -0
- package/dist/channels/issues/types.js +1 -0
- package/dist/docs/404.html +2 -2
- package/dist/docs/ab.html +4 -4
- package/dist/docs/assets/{app.DW9pXkpL.js → app.BVwaffdK.js} +1 -1
- package/dist/docs/assets/chunks/@localSearchIndexroot.CJxMklAy.js +1 -0
- package/dist/docs/assets/chunks/{VPLocalSearchBox.CdEIUwDg.js → VPLocalSearchBox.WuWTZ1x8.js} +1 -1
- package/dist/docs/assets/chunks/{theme.YZMHgPgg.js → theme.BYdI_6sF.js} +2 -2
- package/dist/docs/assets/{guides_github.md.DKYiT9do.js → guides_github.md.c0gdGJ-D.js} +1 -1
- package/dist/docs/assets/{guides_github.md.DKYiT9do.lean.js → guides_github.md.c0gdGJ-D.lean.js} +1 -1
- package/dist/docs/assets/guides_grokbot-agents.md.DVqdhBKb.js +9 -0
- package/dist/docs/assets/guides_grokbot-agents.md.DVqdhBKb.lean.js +1 -0
- package/dist/docs/assets/index.md.BW_6tOgR.js +5 -0
- package/dist/docs/assets/index.md.BW_6tOgR.lean.js +1 -0
- package/dist/docs/assets/{reference_channels.md.Dz8Cnudp.js → reference_channels.md.DBGcaB7m.js} +2 -2
- package/dist/docs/assets/{reference_channels.md.Dz8Cnudp.lean.js → reference_channels.md.DBGcaB7m.lean.js} +1 -1
- package/dist/docs/assets/{reference_cli.md.CJNc_xYK.js → reference_cli.md.C6Lo8SEd.js} +2 -1
- package/dist/docs/assets/{reference_extensions.md.DykHW3qL.js → reference_extensions.md.CGmMLblt.js} +1 -1
- package/dist/docs/assets/templates_grokbot-agents.md.c1s6Flp9.js +3 -0
- package/dist/docs/assets/templates_grokbot-agents.md.c1s6Flp9.lean.js +1 -0
- package/dist/docs/building-with-agents.html +4 -4
- package/dist/docs/concepts.html +4 -4
- package/dist/docs/deployment.html +4 -4
- package/dist/docs/design/filesystem.md +376 -0
- package/dist/docs/evals.html +4 -4
- package/dist/docs/guides/agent-to-agent.html +4 -4
- package/dist/docs/guides/cloud-agents.html +5 -5
- package/dist/docs/guides/convert-automation.html +4 -4
- package/dist/docs/guides/github.html +6 -6
- package/dist/docs/guides/github.md +5 -0
- package/dist/docs/guides/grokbot-agents.html +35 -0
- package/dist/docs/guides/grokbot-agents.md +88 -0
- package/dist/docs/guides/human-in-the-loop.html +4 -4
- package/dist/docs/guides/mcp-oauth.html +4 -4
- package/dist/docs/guides/opentelemetry.html +5 -5
- package/dist/docs/guides/slack.html +4 -4
- package/dist/docs/guides/webhooks.html +4 -4
- package/dist/docs/hashmap.json +1 -1
- package/dist/docs/hillclimbing.html +4 -4
- package/dist/docs/index.html +6 -6
- package/dist/docs/index.md +6 -1
- package/dist/docs/llms-full.txt +562 -2
- package/dist/docs/llms.txt +3 -0
- package/dist/docs/quickstart.html +4 -4
- package/dist/docs/reference/agent-config.html +4 -4
- package/dist/docs/reference/artifacts.html +4 -4
- package/dist/docs/reference/channels.html +6 -6
- package/dist/docs/reference/channels.md +20 -0
- package/dist/docs/reference/cli.html +7 -6
- package/dist/docs/reference/cli.md +2 -1
- package/dist/docs/reference/connections.html +4 -4
- package/dist/docs/reference/extensions.html +6 -6
- package/dist/docs/reference/extensions.md +2 -0
- package/dist/docs/reference/hooks.html +4 -4
- package/dist/docs/reference/http-api.html +4 -4
- package/dist/docs/reference/instructions.html +4 -4
- package/dist/docs/reference/playground.html +4 -4
- package/dist/docs/reference/project-layout.html +4 -4
- package/dist/docs/reference/prompt.html +4 -4
- package/dist/docs/reference/result.html +4 -4
- package/dist/docs/reference/schedules.html +4 -4
- package/dist/docs/reference/sessions.html +4 -4
- package/dist/docs/reference/skills.html +4 -4
- package/dist/docs/reference/subagents.html +4 -4
- package/dist/docs/reference/tools.html +4 -4
- package/dist/docs/scaffolding-agents.html +4 -4
- package/dist/docs/skills/ab.html +4 -4
- package/dist/docs/skills/create-agent.html +4 -4
- package/dist/docs/skills/debug.html +4 -4
- package/dist/docs/skills/evals.html +4 -4
- package/dist/docs/skills/framework-map.html +4 -4
- package/dist/docs/skills/github.html +4 -4
- package/dist/docs/skills/hillclimb.html +4 -4
- package/dist/docs/skills/index.html +4 -4
- package/dist/docs/skills/mcp-auth.html +4 -4
- package/dist/docs/skills/otel.html +4 -4
- package/dist/docs/skills/setup-slack.html +4 -4
- package/dist/docs/storage.html +4 -4
- package/dist/docs/templates/agentic-owners.html +4 -4
- package/dist/docs/templates/agents-md.html +4 -4
- package/dist/docs/templates/code-wiki.html +5 -5
- package/dist/docs/templates/demo.html +5 -5
- package/dist/docs/templates/grokbot-agents.html +29 -0
- package/dist/docs/templates/grokbot-agents.md +48 -0
- package/dist/docs/templates/pr-autofixer.html +4 -4
- package/dist/docs/templates/security-help.html +4 -4
- package/dist/docs/templates/security-reviewer.html +4 -4
- package/dist/docs/templates/triage.html +4 -4
- package/dist/docs/troubleshooting.html +4 -4
- package/dist/files.d.ts +7 -2
- package/dist/files.d.ts.map +1 -1
- package/dist/files.js +7 -2
- package/dist/filesystem.d.ts +440 -0
- package/dist/filesystem.d.ts.map +1 -0
- package/dist/filesystem.js +1694 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/internal/continuation-channel.d.ts +4 -2
- package/dist/internal/continuation-channel.d.ts.map +1 -1
- package/dist/internal/continuation-channel.js +21 -12
- package/dist/internal/continuation-identity.d.ts +13 -5
- package/dist/internal/continuation-identity.d.ts.map +1 -1
- package/dist/internal/continuation-identity.js +74 -35
- package/dist/internal/cursor-agent-template.d.ts +1 -1
- package/dist/internal/cursor-agent-template.d.ts.map +1 -1
- package/dist/internal/cursor-agent-template.js +1 -0
- package/dist/internal/discovery/agent.d.ts.map +1 -1
- package/dist/internal/discovery/agent.js +80 -8
- package/dist/internal/discovery/info.d.ts.map +1 -1
- package/dist/internal/discovery/info.js +3 -0
- package/dist/internal/factory-resource-channel.d.ts +33 -0
- package/dist/internal/factory-resource-channel.d.ts.map +1 -0
- package/dist/internal/factory-resource-channel.js +77 -0
- package/dist/internal/filesystem/errors.d.ts +64 -0
- package/dist/internal/filesystem/errors.d.ts.map +1 -0
- package/dist/internal/filesystem/errors.js +175 -0
- package/dist/internal/filesystem/format.d.ts +28 -0
- package/dist/internal/filesystem/format.d.ts.map +1 -0
- package/dist/internal/filesystem/format.js +213 -0
- package/dist/internal/filesystem/merge.d.ts +34 -0
- package/dist/internal/filesystem/merge.d.ts.map +1 -0
- package/dist/internal/filesystem/merge.js +196 -0
- package/dist/internal/filesystem/scratch.d.ts +59 -0
- package/dist/internal/filesystem/scratch.d.ts.map +1 -0
- package/dist/internal/filesystem/scratch.js +212 -0
- package/dist/internal/filesystem/sdk-schemas.d.ts +29 -0
- package/dist/internal/filesystem/sdk-schemas.d.ts.map +1 -0
- package/dist/internal/filesystem/sdk-schemas.js +153 -0
- package/dist/internal/filesystem/tools.d.ts +42 -0
- package/dist/internal/filesystem/tools.d.ts.map +1 -0
- package/dist/internal/filesystem/tools.js +618 -0
- package/dist/internal/filesystem/walk.d.ts +74 -0
- package/dist/internal/filesystem/walk.d.ts.map +1 -0
- package/dist/internal/filesystem/walk.js +339 -0
- package/dist/internal/framework-file-storage.d.ts +3 -1
- package/dist/internal/framework-file-storage.d.ts.map +1 -1
- package/dist/internal/framework-file-storage.js +3 -1
- package/dist/internal/guest-network.d.ts +5 -2
- package/dist/internal/guest-network.d.ts.map +1 -1
- package/dist/internal/guest-network.js +7 -2
- package/dist/internal/hosted-delivery.d.ts +7 -0
- package/dist/internal/hosted-delivery.d.ts.map +1 -1
- package/dist/internal/hosted-delivery.js +41 -3
- package/dist/internal/hosted-managed-automation.d.ts.map +1 -1
- package/dist/internal/hosted-managed-automation.js +27 -2
- package/dist/internal/init-project.d.ts.map +1 -1
- package/dist/internal/init-project.js +4 -1
- package/dist/internal/sdk-runner.d.ts +13 -1
- package/dist/internal/sdk-runner.d.ts.map +1 -1
- package/dist/internal/sdk-runner.js +21 -1
- package/dist/internal/server.d.ts.map +1 -1
- package/dist/internal/server.js +11 -3
- package/dist/internal/session-engine.d.ts +30 -0
- package/dist/internal/session-engine.d.ts.map +1 -1
- package/dist/internal/session-engine.js +484 -82
- package/dist/internal/store-mirror.d.ts +2 -2
- package/dist/internal/store-mirror.js +2 -2
- package/dist/internal/tenant-slack/relay.d.ts +2 -0
- package/dist/internal/tenant-slack/relay.d.ts.map +1 -1
- package/dist/internal/tenant-slack/relay.js +18 -8
- package/dist/internal/testing/factory-resource-fixtures.d.ts +48 -0
- package/dist/internal/testing/factory-resource-fixtures.d.ts.map +1 -0
- package/dist/internal/testing/factory-resource-fixtures.js +41 -0
- package/dist/internal/workspace-sync.d.ts +31 -6
- package/dist/internal/workspace-sync.d.ts.map +1 -1
- package/dist/internal/workspace-sync.js +67 -12
- package/dist/internal/workspace.d.ts +9 -0
- package/dist/internal/workspace.d.ts.map +1 -1
- package/dist/internal/workspace.js +16 -0
- package/dist/playground/assets/{index-59KvgREd.js → index-BaQzjaNK.js} +40 -40
- package/dist/playground/assets/index-CceqnLTX.css +1 -0
- package/dist/playground/index.html +2 -2
- package/dist/types.d.ts +60 -11
- package/dist/types.d.ts.map +1 -1
- package/docs/README.md +6 -1
- package/docs/design/filesystem.md +376 -0
- package/docs/guides/github.md +5 -0
- package/docs/guides/grokbot-agents.md +93 -0
- package/docs/reference/channels.md +20 -0
- package/docs/reference/cli.md +2 -1
- package/docs/reference/extensions.md +2 -0
- package/docs/templates/grokbot-agents.md +53 -0
- package/package.json +25 -2
- package/src/channels/change-monitors/change-monitors-channel.ts +62 -0
- package/src/channels/change-monitors/index.ts +8 -0
- package/src/channels/change-monitors/types.ts +44 -0
- package/src/channels/deployments/deployments-channel.ts +1 -0
- package/src/channels/deployments/types.ts +2 -0
- package/src/channels/github/defaults.ts +4 -0
- package/src/channels/github/progress.ts +76 -10
- package/src/channels/issues/index.ts +9 -0
- package/src/channels/issues/issues-channel.ts +51 -0
- package/src/channels/issues/types.ts +41 -0
- package/src/files.ts +9 -2
- package/src/filesystem.ts +2074 -0
- package/src/index.ts +28 -0
- package/src/internal/continuation-channel.ts +29 -12
- package/src/internal/continuation-identity.ts +122 -37
- package/src/internal/cursor-agent-template.ts +1 -0
- package/src/internal/discovery/agent.ts +87 -1
- package/src/internal/discovery/info.ts +3 -0
- package/src/internal/factory-resource-channel.ts +122 -0
- package/src/internal/filesystem/errors.ts +220 -0
- package/src/internal/filesystem/format.ts +276 -0
- package/src/internal/filesystem/merge.ts +195 -0
- package/src/internal/filesystem/scratch.ts +255 -0
- package/src/internal/filesystem/sdk-schemas.ts +204 -0
- package/src/internal/filesystem/tools.ts +821 -0
- package/src/internal/filesystem/walk.ts +369 -0
- package/src/internal/framework-file-storage.ts +3 -1
- package/src/internal/guest-network.ts +8 -2
- package/src/internal/hosted-delivery.ts +71 -2
- package/src/internal/hosted-managed-automation.ts +49 -5
- package/src/internal/init-project.ts +4 -1
- package/src/internal/sdk-runner.ts +23 -0
- package/src/internal/server.ts +16 -0
- package/src/internal/session-engine.ts +595 -73
- package/src/internal/store-mirror.ts +2 -2
- package/src/internal/tenant-slack/relay.ts +28 -4
- package/src/internal/testing/factory-resource-fixtures.ts +85 -0
- package/src/internal/workspace-sync.ts +84 -12
- package/src/internal/workspace.ts +20 -0
- package/src/types.ts +58 -11
- package/templates/grokbot-agents/README.md +26 -0
- package/templates/grokbot-agents/agent/agent.ts +6 -0
- package/templates/grokbot-agents/agent/extensions/grokbot.ts +5 -0
- package/templates/grokbot-agents/agent/instructions.md +7 -0
- package/templates/grokbot-agents/evals/evals.config.ts +5 -0
- package/templates/grokbot-agents/evals/grokbot-agents.eval.ts +18 -0
- package/templates/grokbot-agents/init.json +18 -0
- package/templates/grokbot-agents/package.json +17 -0
- package/templates/grokbot-agents/tsconfig.json +12 -0
- package/dist/docs/assets/chunks/@localSearchIndexroot.nrl1ifBq.js +0 -1
- package/dist/docs/assets/index.md.D75GWhPl.js +0 -5
- package/dist/docs/assets/index.md.D75GWhPl.lean.js +0 -1
- package/dist/playground/assets/index-MbMxXg-y.css +0 -1
- /package/dist/docs/assets/{reference_cli.md.CJNc_xYK.lean.js → reference_cli.md.C6Lo8SEd.lean.js} +0 -0
- /package/dist/docs/assets/{reference_extensions.md.DykHW3qL.lean.js → reference_extensions.md.CGmMLblt.lean.js} +0 -0
|
@@ -25,6 +25,7 @@ import { SlackAskDedupeStore, SlackNudgeStore, } from "../channels/slack/nudge-s
|
|
|
25
25
|
import { resolveDedicatedSlackHostBinding } from "../channels/slack/slack-channel.js";
|
|
26
26
|
import { AGENT_SERVE_USER_STORE_FILES_SOURCE_ID, agentStoreKeys, DEPLOYMENT_STORE_MOUNT_PATH, USER_STORE_MOUNT_PATH, } from "../files.js";
|
|
27
27
|
import { cursorHostedFiles, isCursorHostedFilesAvailable, isCursorUserStoreFilesAvailable, } from "../files-backends/cursor-hosted.js";
|
|
28
|
+
import { isFileSystemToolAlias, isMutatingFileSystemTool, localFileSystem, resolveFileSystemTools, resolveHostHarnessToolOptions, tempFs, unionFs, writeWorkspaceFilesToRoot, } from "../filesystem.js";
|
|
28
29
|
import { storageKeysForArchitecture } from "../storage.js";
|
|
29
30
|
import { DEFAULT_MODEL, DIRECT_TOOL_CALL_CHANNEL_ID, isCursorAccountTransport, isHostOauthConnectionTransport, isSymbolicConnectionTransport, } from "../types.js";
|
|
30
31
|
import { ABCollector } from "./ab-collector.js";
|
|
@@ -43,6 +44,8 @@ import { describeError } from "./describe-error.js";
|
|
|
43
44
|
import { isDevMode } from "./dev-mode.js";
|
|
44
45
|
import { EventLogStore } from "./event-log.js";
|
|
45
46
|
import { TurnEventMapper } from "./event-mapper.js";
|
|
47
|
+
import { applyWebScratchUpdate, ingestHostAgentToolsScratch, remapScratchPaths, } from "./filesystem/scratch.js";
|
|
48
|
+
import { fileSystemTool, hostFileToolsFromAuthored, rootFileToolsFromAuthored, synthesizeFileSystemTools, } from "./filesystem/tools.js";
|
|
46
49
|
import { selectFrameworkStorageDefinition } from "./framework-storage-selection.js";
|
|
47
50
|
import { createHostFilesApi } from "./host-files.js";
|
|
48
51
|
import { createHostKvApi } from "./host-kv.js";
|
|
@@ -69,8 +72,8 @@ import { TurnGovernor } from "./turn-governor.js";
|
|
|
69
72
|
import { TurnLeaseStore } from "./turn-lease-store.js";
|
|
70
73
|
import { TurnOutbox } from "./turn-outbox.js";
|
|
71
74
|
import { resolveAgentV2Hosting } from "./v2-hosting.js";
|
|
72
|
-
import { buildAgentsMdContent, buildCloudMemorySection, buildCloudWorkspaceSection, ensureOwnGitRoot, isNestedInGitRepo, materializeWorkspace, SERVER_TOOLS_MCP_SERVER_NAME,
|
|
73
|
-
import { syncWorkspaceToStore } from "./workspace-sync.js";
|
|
75
|
+
import { buildAgentsMdContent, buildCloudMemorySection, buildCloudSessionWorkspaceSection, buildCloudWorkspaceSection, ensureOwnGitRoot, isNestedInGitRepo, materializeWorkspace, SERVER_TOOLS_MCP_SERVER_NAME, } from "./workspace.js";
|
|
76
|
+
import { syncSessionWorkspaceFiles, syncWorkspaceToStore, WorkspaceFileRefusal, wipeSessionWorkspace, } from "./workspace-sync.js";
|
|
74
77
|
export const HTTP_CHANNEL_ID = "http";
|
|
75
78
|
export { SCHEDULE_CHANNEL_PREFIX } from "./prompt-context.js";
|
|
76
79
|
export class SessionBusyError extends Error {
|
|
@@ -218,6 +221,12 @@ export class SessionEngine {
|
|
|
218
221
|
this.cloudCostBackfillDone = new Set();
|
|
219
222
|
/** Deduped in-flight cloud cost backfills, keyed by session id. */
|
|
220
223
|
this.cloudCostBackfill = new Map();
|
|
224
|
+
/** Per-session FileSystem handle cache (not a tree snapshot). */
|
|
225
|
+
this.sessionRoots = new Map();
|
|
226
|
+
/** In-flight factory resolves, so the first turn and a racing callTool share one handle. */
|
|
227
|
+
this.sessionRootInflight = new Map();
|
|
228
|
+
/** Per-turn `unionFs({ "/": authored, "/tmp": tempFs() })`. Dropped at end of turn. */
|
|
229
|
+
this.turnRoots = new Map();
|
|
221
230
|
this.project = options.project;
|
|
222
231
|
applyAgentContinuationDefaults(this.project);
|
|
223
232
|
this.stateRoot = options.stateRoot;
|
|
@@ -1252,6 +1261,224 @@ export class SessionEngine {
|
|
|
1252
1261
|
return this.interrupt(existing.sessionId);
|
|
1253
1262
|
});
|
|
1254
1263
|
}
|
|
1264
|
+
hasRootOverride() {
|
|
1265
|
+
return this.project.agent.root !== undefined;
|
|
1266
|
+
}
|
|
1267
|
+
/**
|
|
1268
|
+
* FileSystem for this turn or `callTool`. Authored `root` (static or
|
|
1269
|
+
* factory) is cached per session when `cache` is set; unscoped
|
|
1270
|
+
* `callTool` passes the invocation id and does not cache, so factories
|
|
1271
|
+
* cannot share one tree across callers. A static handle is used as
|
|
1272
|
+
* authored — every session sees that same object. Host-default agents
|
|
1273
|
+
* get `localFileSystem` against the harness cwd — same path verbs as
|
|
1274
|
+
* the Cursor SDK natives, always through the synthesized tools.
|
|
1275
|
+
*/
|
|
1276
|
+
resolveFileSystem(options) {
|
|
1277
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
1278
|
+
const authored = this.project.agent.root;
|
|
1279
|
+
if (authored === undefined) {
|
|
1280
|
+
return localFileSystem({ cwd: options.cwd });
|
|
1281
|
+
}
|
|
1282
|
+
const authoredRoot = yield this.resolveAuthoredFileSystem(options);
|
|
1283
|
+
if (options.cache) {
|
|
1284
|
+
const existing = this.turnRoots.get(options.sessionId);
|
|
1285
|
+
if (existing !== undefined) {
|
|
1286
|
+
return existing.root;
|
|
1287
|
+
}
|
|
1288
|
+
}
|
|
1289
|
+
const root = unionFs({
|
|
1290
|
+
"/": authoredRoot,
|
|
1291
|
+
"/tmp": tempFs(),
|
|
1292
|
+
});
|
|
1293
|
+
if (options.cache && this.isTurnRunning(options.sessionId)) {
|
|
1294
|
+
this.turnRoots.set(options.sessionId, { root, cwd: options.cwd });
|
|
1295
|
+
}
|
|
1296
|
+
return root;
|
|
1297
|
+
});
|
|
1298
|
+
}
|
|
1299
|
+
resolveAuthoredFileSystem(options) {
|
|
1300
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
1301
|
+
const authored = this.project.agent.root;
|
|
1302
|
+
if (authored === undefined) {
|
|
1303
|
+
throw new Error("resolveAuthoredFileSystem requires an authored root");
|
|
1304
|
+
}
|
|
1305
|
+
if (options.cache) {
|
|
1306
|
+
const cached = this.sessionRoots.get(options.sessionId);
|
|
1307
|
+
if (cached !== undefined) {
|
|
1308
|
+
return cached;
|
|
1309
|
+
}
|
|
1310
|
+
const inflight = this.sessionRootInflight.get(options.sessionId);
|
|
1311
|
+
if (inflight !== undefined) {
|
|
1312
|
+
return inflight;
|
|
1313
|
+
}
|
|
1314
|
+
}
|
|
1315
|
+
const resolve = () => __awaiter(this, void 0, void 0, function* () {
|
|
1316
|
+
if (typeof authored !== "function") {
|
|
1317
|
+
return authored;
|
|
1318
|
+
}
|
|
1319
|
+
const host = this.hostForSession(options.cache ? options.sessionId : undefined);
|
|
1320
|
+
const ctx = Object.assign(Object.assign({ sessionId: options.sessionId, agentName: this.project.agent.name }, (options.continuationKey === undefined
|
|
1321
|
+
? {}
|
|
1322
|
+
: { continuationKey: options.continuationKey })), { host: { files: host.files, reminders: host.reminders } });
|
|
1323
|
+
return yield authored(ctx);
|
|
1324
|
+
});
|
|
1325
|
+
if (!options.cache) {
|
|
1326
|
+
return resolve();
|
|
1327
|
+
}
|
|
1328
|
+
const pending = resolve();
|
|
1329
|
+
this.sessionRootInflight.set(options.sessionId, pending);
|
|
1330
|
+
try {
|
|
1331
|
+
const resolved = yield pending;
|
|
1332
|
+
this.sessionRoots.set(options.sessionId, resolved);
|
|
1333
|
+
return resolved;
|
|
1334
|
+
}
|
|
1335
|
+
finally {
|
|
1336
|
+
this.sessionRootInflight.delete(options.sessionId);
|
|
1337
|
+
}
|
|
1338
|
+
});
|
|
1339
|
+
}
|
|
1340
|
+
dropTurnFileSystem(sessionId) {
|
|
1341
|
+
this.turnRoots.delete(sessionId);
|
|
1342
|
+
}
|
|
1343
|
+
prepareScratchToolInput(options) {
|
|
1344
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
1345
|
+
if (options.sessionId === undefined) {
|
|
1346
|
+
return options.input;
|
|
1347
|
+
}
|
|
1348
|
+
const turn = this.turnRoots.get(options.sessionId);
|
|
1349
|
+
if (turn === undefined) {
|
|
1350
|
+
return options.input;
|
|
1351
|
+
}
|
|
1352
|
+
yield ingestHostAgentToolsScratch({
|
|
1353
|
+
cwd: turn.cwd,
|
|
1354
|
+
root: turn.root,
|
|
1355
|
+
});
|
|
1356
|
+
return remapScratchPaths(options.input, turn.cwd);
|
|
1357
|
+
});
|
|
1358
|
+
}
|
|
1359
|
+
withTurnScratchTools(tools, sessionId) {
|
|
1360
|
+
const turn = this.turnRoots.get(sessionId);
|
|
1361
|
+
if (turn === undefined) {
|
|
1362
|
+
return tools;
|
|
1363
|
+
}
|
|
1364
|
+
return tools.map((tool) => {
|
|
1365
|
+
const execute = tool.definition.execute;
|
|
1366
|
+
if (typeof execute !== "function") {
|
|
1367
|
+
return tool;
|
|
1368
|
+
}
|
|
1369
|
+
return Object.assign(Object.assign({}, tool), { definition: Object.assign(Object.assign({}, tool.definition), { execute: (input, ctx) => __awaiter(this, void 0, void 0, function* () {
|
|
1370
|
+
const remapped = yield this.prepareScratchToolInput({
|
|
1371
|
+
sessionId,
|
|
1372
|
+
input: input !== null &&
|
|
1373
|
+
typeof input === "object" &&
|
|
1374
|
+
!Array.isArray(input)
|
|
1375
|
+
? input
|
|
1376
|
+
: {},
|
|
1377
|
+
});
|
|
1378
|
+
return execute(remapped, ctx);
|
|
1379
|
+
}) }) });
|
|
1380
|
+
});
|
|
1381
|
+
}
|
|
1382
|
+
nativeFileSystemOutcome(options) {
|
|
1383
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
1384
|
+
var _a;
|
|
1385
|
+
const { toolName, input, callId } = options;
|
|
1386
|
+
if (!isFileSystemToolAlias(toolName)) {
|
|
1387
|
+
return undefined;
|
|
1388
|
+
}
|
|
1389
|
+
// Same policy the authored callTool path asks: a dry-run write is
|
|
1390
|
+
// answered by the host. Native edit/delete used to return before
|
|
1391
|
+
// decideToolCall and persist through the FileSystem.
|
|
1392
|
+
const decision = decideToolCall({
|
|
1393
|
+
dryRun: options.dryRun === true,
|
|
1394
|
+
effect: isMutatingFileSystemTool(toolName) ? "write" : "read",
|
|
1395
|
+
input,
|
|
1396
|
+
});
|
|
1397
|
+
if (decision.kind === "answer") {
|
|
1398
|
+
return {
|
|
1399
|
+
callId,
|
|
1400
|
+
toolName,
|
|
1401
|
+
isError: false,
|
|
1402
|
+
result: decision.result,
|
|
1403
|
+
durationMs: 0,
|
|
1404
|
+
sessionId: options.sessionId,
|
|
1405
|
+
};
|
|
1406
|
+
}
|
|
1407
|
+
const root = yield this.resolveFileSystem({
|
|
1408
|
+
sessionId: (_a = options.sessionId) !== null && _a !== void 0 ? _a : callId,
|
|
1409
|
+
continuationKey: options.continuationKey,
|
|
1410
|
+
cache: options.sessionId !== undefined,
|
|
1411
|
+
cwd: options.cwd,
|
|
1412
|
+
});
|
|
1413
|
+
const rawArgs = input !== null && typeof input === "object" && !Array.isArray(input)
|
|
1414
|
+
? input
|
|
1415
|
+
: {};
|
|
1416
|
+
const args = yield this.prepareScratchToolInput({
|
|
1417
|
+
sessionId: options.sessionId,
|
|
1418
|
+
input: rawArgs,
|
|
1419
|
+
});
|
|
1420
|
+
const tool = fileSystemTool(root, toolName, args);
|
|
1421
|
+
const execute = tool === null || tool === void 0 ? void 0 : tool.definition.execute;
|
|
1422
|
+
if (tool === undefined || typeof execute !== "function") {
|
|
1423
|
+
// A resolved root owns this native name. Falling through would let
|
|
1424
|
+
// an authored lookalike run, or surface UnknownToolError after we
|
|
1425
|
+
// already advertised the FileSystem tool.
|
|
1426
|
+
return {
|
|
1427
|
+
callId,
|
|
1428
|
+
toolName,
|
|
1429
|
+
isError: true,
|
|
1430
|
+
result: {
|
|
1431
|
+
status: "error",
|
|
1432
|
+
error: { message: `FileSystem cannot handle ${toolName}` },
|
|
1433
|
+
},
|
|
1434
|
+
durationMs: 0,
|
|
1435
|
+
sessionId: options.sessionId,
|
|
1436
|
+
errorMessage: `FileSystem cannot handle ${toolName}`,
|
|
1437
|
+
};
|
|
1438
|
+
}
|
|
1439
|
+
const validation = validateToolInput(tool.definition.inputSchema, args);
|
|
1440
|
+
if (!validation.ok) {
|
|
1441
|
+
return {
|
|
1442
|
+
callId,
|
|
1443
|
+
toolName,
|
|
1444
|
+
isError: true,
|
|
1445
|
+
result: {
|
|
1446
|
+
status: "error",
|
|
1447
|
+
error: { message: validation.message },
|
|
1448
|
+
},
|
|
1449
|
+
durationMs: 0,
|
|
1450
|
+
sessionId: options.sessionId,
|
|
1451
|
+
errorMessage: validation.message,
|
|
1452
|
+
};
|
|
1453
|
+
}
|
|
1454
|
+
try {
|
|
1455
|
+
const value = yield execute(validation.value, {
|
|
1456
|
+
toolCallId: callId,
|
|
1457
|
+
workspaceDir: options.cwd,
|
|
1458
|
+
});
|
|
1459
|
+
return {
|
|
1460
|
+
callId,
|
|
1461
|
+
toolName,
|
|
1462
|
+
isError: false,
|
|
1463
|
+
result: normalizeToolResult(value),
|
|
1464
|
+
durationMs: 0,
|
|
1465
|
+
sessionId: options.sessionId,
|
|
1466
|
+
};
|
|
1467
|
+
}
|
|
1468
|
+
catch (error) {
|
|
1469
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
1470
|
+
return {
|
|
1471
|
+
callId,
|
|
1472
|
+
toolName,
|
|
1473
|
+
isError: true,
|
|
1474
|
+
result: { status: "error", error: { message } },
|
|
1475
|
+
durationMs: 0,
|
|
1476
|
+
sessionId: options.sessionId,
|
|
1477
|
+
errorMessage: message,
|
|
1478
|
+
};
|
|
1479
|
+
}
|
|
1480
|
+
});
|
|
1481
|
+
}
|
|
1255
1482
|
/**
|
|
1256
1483
|
* Local harness cwd for a session: per-send override, else the shared
|
|
1257
1484
|
* `agent.local.workspaceDir`, else `<agent.local.cwd>/<sessionId>`, else
|
|
@@ -1298,14 +1525,16 @@ export class SessionEngine {
|
|
|
1298
1525
|
const workspaceDir = (_a = agent.local) === null || _a === void 0 ? void 0 : _a.workspaceDir;
|
|
1299
1526
|
if (workspaceDir === undefined ||
|
|
1300
1527
|
agent.runtime !== "local" ||
|
|
1528
|
+
this.hasRootOverride() ||
|
|
1301
1529
|
this.runner.prewarm === undefined) {
|
|
1302
1530
|
return;
|
|
1303
1531
|
}
|
|
1304
1532
|
const startedAt = Date.now();
|
|
1305
1533
|
try {
|
|
1306
|
-
const
|
|
1534
|
+
const harness = resolveHostHarnessToolOptions(agent.allowedTools);
|
|
1535
|
+
const outcome = yield this.runner.prewarm(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({ workspaceDir, runnerStateDir: join(this.stateRoot, "runner"), sandbox: ((_b = agent.local) === null || _b === void 0 ? void 0 : _b.sandbox) === true }, (harness.tools === undefined ? {} : { tools: harness.tools })), (harness.disallowedTools === undefined
|
|
1307
1536
|
? {}
|
|
1308
|
-
: {
|
|
1537
|
+
: { disallowedTools: harness.disallowedTools })), {
|
|
1309
1538
|
// No session yet, so auth'd connections are omitted rather than
|
|
1310
1539
|
// warmed without an identity; the per-send flag still has to match
|
|
1311
1540
|
// the turns' requests or the warmed executor is one no turn asks for.
|
|
@@ -1333,7 +1562,7 @@ export class SessionEngine {
|
|
|
1333
1562
|
}
|
|
1334
1563
|
executeTurn(record, turnId, message, isFirstTurn, signal) {
|
|
1335
1564
|
return __awaiter(this, void 0, void 0, function* () {
|
|
1336
|
-
var _a, _b, _c, _d, _e, _f, _g;
|
|
1565
|
+
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
1337
1566
|
const sessionId = record.sessionId;
|
|
1338
1567
|
const workspaceDir = this.scaffoldDir(record);
|
|
1339
1568
|
const harnessCwd = this.harnessCwd(record);
|
|
@@ -1380,35 +1609,48 @@ export class SessionEngine {
|
|
|
1380
1609
|
// cwd is overridden (e.g. a PR worktree). A/B variant instruction
|
|
1381
1610
|
// overlays are applied via agentForSession.
|
|
1382
1611
|
const agent = this.agentForSession(record);
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
|
|
1390
|
-
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
|
|
1396
|
-
|
|
1612
|
+
if (!this.hasRootOverride()) {
|
|
1613
|
+
yield materializeWorkspace({
|
|
1614
|
+
agent,
|
|
1615
|
+
workspaceDir,
|
|
1616
|
+
seed: isFirstTurn,
|
|
1617
|
+
stateRoot: this.stateRoot,
|
|
1618
|
+
});
|
|
1619
|
+
this.materializedWorkspaces.add(sessionId);
|
|
1620
|
+
// Must precede the carrier: the harness resolves rules, skills,
|
|
1621
|
+
// `mcp.json` and hooks from its git root, so a workspace nested in an
|
|
1622
|
+
// outer repo would load that repo's hooks instead of the ones written
|
|
1623
|
+
// just below. Only for directories this session owns — a borrowed
|
|
1624
|
+
// checkout or worktree keeps its own root.
|
|
1625
|
+
if (!this.hasBorrowedWorkspace(record)) {
|
|
1626
|
+
yield ensureOwnGitRoot(harnessCwd);
|
|
1627
|
+
}
|
|
1628
|
+
yield this.materializeNudgeCarrier(record, harnessCwd);
|
|
1397
1629
|
}
|
|
1398
|
-
yield this.materializeNudgeCarrier(record, harnessCwd);
|
|
1399
1630
|
// Baseline before the agent can run, so a follow-up that arrives and
|
|
1400
1631
|
// drains before the first tool boundary still counts as an increase.
|
|
1401
1632
|
yield this.baselineDeliveredNudges(record);
|
|
1402
1633
|
const pendingFiles = record.pendingWorkspaceFiles;
|
|
1403
1634
|
const pendingImages = record.pendingImages;
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
|
|
1635
|
+
const runtime = resolveSessionRuntime({
|
|
1636
|
+
agentRuntime: agent.runtime,
|
|
1637
|
+
cloudOverride: record.cloudOverride,
|
|
1638
|
+
});
|
|
1639
|
+
const hasPendingFiles = pendingFiles !== undefined && Object.keys(pendingFiles).length > 0;
|
|
1640
|
+
if (hasPendingFiles && runtime !== "cloud") {
|
|
1641
|
+
const root = yield this.resolveFileSystem({
|
|
1642
|
+
sessionId,
|
|
1643
|
+
continuationKey: (_a = record.continuationKey) !== null && _a !== void 0 ? _a : undefined,
|
|
1644
|
+
cache: true,
|
|
1645
|
+
cwd: harnessCwd,
|
|
1646
|
+
});
|
|
1647
|
+
yield writeWorkspaceFilesToRoot(root, pendingFiles);
|
|
1407
1648
|
}
|
|
1408
|
-
if ((
|
|
1409
|
-
Object.keys(pendingFiles).length > 0) ||
|
|
1649
|
+
if ((hasPendingFiles && runtime !== "cloud") ||
|
|
1410
1650
|
(pendingImages !== undefined && pendingImages.length > 0)) {
|
|
1411
|
-
yield this.updateRecord(sessionId, (current) => (Object.assign(Object.assign({}, current), { pendingWorkspaceFiles:
|
|
1651
|
+
yield this.updateRecord(sessionId, (current) => (Object.assign(Object.assign({}, current), { pendingWorkspaceFiles: hasPendingFiles &&
|
|
1652
|
+
runtime !== "cloud" &&
|
|
1653
|
+
current.pendingWorkspaceFiles === pendingFiles
|
|
1412
1654
|
? undefined
|
|
1413
1655
|
: current.pendingWorkspaceFiles, pendingImages: current.pendingImages === pendingImages
|
|
1414
1656
|
? undefined
|
|
@@ -1423,6 +1665,14 @@ export class SessionEngine {
|
|
|
1423
1665
|
(this.hasBorrowedWorkspace(record) ||
|
|
1424
1666
|
(yield isNestedInGitRepo(harnessCwd)));
|
|
1425
1667
|
const request = yield this.buildTurnRequest(record, agent, turnId, message, isFirstTurn, instructionsInvisibleToHarness, emit, (update) => __awaiter(this, void 0, void 0, function* () {
|
|
1668
|
+
const turn = this.turnRoots.get(sessionId);
|
|
1669
|
+
if (turn !== undefined) {
|
|
1670
|
+
update = yield applyWebScratchUpdate({
|
|
1671
|
+
cwd: turn.cwd,
|
|
1672
|
+
root: turn.root,
|
|
1673
|
+
update,
|
|
1674
|
+
});
|
|
1675
|
+
}
|
|
1426
1676
|
mapper.handleUpdate(update);
|
|
1427
1677
|
// Yield so the HTTP NDJSON writer can flush tool start/result
|
|
1428
1678
|
// events while sibling parallel tools are still executing.
|
|
@@ -1454,6 +1704,7 @@ export class SessionEngine {
|
|
|
1454
1704
|
}
|
|
1455
1705
|
finally {
|
|
1456
1706
|
permit.release();
|
|
1707
|
+
this.dropTurnFileSystem(sessionId);
|
|
1457
1708
|
this.approvals.cancelSession(sessionId, "deny");
|
|
1458
1709
|
this.auths.cancelSession(sessionId, "deny");
|
|
1459
1710
|
yield this.clearPendingApprovals(sessionId);
|
|
@@ -1468,15 +1719,15 @@ export class SessionEngine {
|
|
|
1468
1719
|
const title = mapper.title;
|
|
1469
1720
|
yield this.updateRecord(sessionId, (current) => (Object.assign(Object.assign({}, current), { title })));
|
|
1470
1721
|
}
|
|
1471
|
-
const finalResult = (
|
|
1472
|
-
const finalUsage = (
|
|
1722
|
+
const finalResult = (_b = outcome.result) !== null && _b !== void 0 ? _b : mapper.finalText;
|
|
1723
|
+
const finalUsage = (_c = outcome.usage) !== null && _c !== void 0 ? _c : mapper.usage;
|
|
1473
1724
|
const finalCost = finalUsage === undefined
|
|
1474
1725
|
? undefined
|
|
1475
1726
|
: yield this.estimateTurnCost({
|
|
1476
|
-
model: (
|
|
1727
|
+
model: (_d = this.project.agent.model) !== null && _d !== void 0 ? _d : DEFAULT_MODEL,
|
|
1477
1728
|
usage: finalUsage,
|
|
1478
1729
|
agentId: record.sdkAgentId,
|
|
1479
|
-
conversationId: (
|
|
1730
|
+
conversationId: (_e = record.sdkAgentId) !== null && _e !== void 0 ? _e : sessionId,
|
|
1480
1731
|
});
|
|
1481
1732
|
if (finalCost !== undefined) {
|
|
1482
1733
|
outcome = Object.assign(Object.assign({}, outcome), { cost: finalCost });
|
|
@@ -1524,22 +1775,23 @@ export class SessionEngine {
|
|
|
1524
1775
|
data: {
|
|
1525
1776
|
message: interrupted
|
|
1526
1777
|
? "turn interrupted"
|
|
1527
|
-
: ((
|
|
1778
|
+
: ((_f = outcome.errorMessage) !== null && _f !== void 0 ? _f : (outcome.status === "cancelled"
|
|
1528
1779
|
? "turn cancelled"
|
|
1529
1780
|
: "turn failed")),
|
|
1530
1781
|
},
|
|
1531
1782
|
});
|
|
1532
1783
|
}
|
|
1533
1784
|
const current = yield this.sessions.get(sessionId);
|
|
1534
|
-
const mode = (
|
|
1785
|
+
const mode = (_g = current === null || current === void 0 ? void 0 : current.mode) !== null && _g !== void 0 ? _g : record.mode;
|
|
1535
1786
|
if (mode === "task") {
|
|
1536
1787
|
yield this.appendEvent(sessionId, outcome.status === "finished"
|
|
1537
1788
|
? { type: "session.completed", turnId, data: {} }
|
|
1538
1789
|
: {
|
|
1539
1790
|
type: "session.failed",
|
|
1540
1791
|
turnId,
|
|
1541
|
-
data: { message: (
|
|
1792
|
+
data: { message: (_h = outcome.errorMessage) !== null && _h !== void 0 ? _h : "task failed" },
|
|
1542
1793
|
});
|
|
1794
|
+
yield this.wipeCloudSessionWorkspace(sessionId);
|
|
1543
1795
|
}
|
|
1544
1796
|
else {
|
|
1545
1797
|
yield this.appendEvent(sessionId, {
|
|
@@ -1582,6 +1834,58 @@ export class SessionEngine {
|
|
|
1582
1834
|
workspacePrefix: store.workspacePrefix,
|
|
1583
1835
|
}));
|
|
1584
1836
|
}
|
|
1837
|
+
/**
|
|
1838
|
+
* Replace this session's store prefix with the pending `workspaceFiles`.
|
|
1839
|
+
* Undefined when the write did not land; the prompt must not name the
|
|
1840
|
+
* mount, matching ensureCloudWorkspaceSynced.
|
|
1841
|
+
*/
|
|
1842
|
+
syncCloudSessionWorkspaceFiles(store, sessionId, files) {
|
|
1843
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
1844
|
+
const workspacePrefix = store.sessionWorkspacePrefix(sessionId);
|
|
1845
|
+
try {
|
|
1846
|
+
const relPaths = yield syncSessionWorkspaceFiles({
|
|
1847
|
+
sink: store.sink,
|
|
1848
|
+
files,
|
|
1849
|
+
workspacePrefix,
|
|
1850
|
+
});
|
|
1851
|
+
return {
|
|
1852
|
+
dir: `${store.mountPath}/${workspacePrefix}`,
|
|
1853
|
+
relPaths,
|
|
1854
|
+
};
|
|
1855
|
+
}
|
|
1856
|
+
catch (error) {
|
|
1857
|
+
this.logger(`[workspace] ${store.label} session files sync failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
1858
|
+
if (error instanceof WorkspaceFileRefusal) {
|
|
1859
|
+
yield this.clearPendingWorkspaceFiles(sessionId, files);
|
|
1860
|
+
}
|
|
1861
|
+
return undefined;
|
|
1862
|
+
}
|
|
1863
|
+
});
|
|
1864
|
+
}
|
|
1865
|
+
wipeCloudSessionWorkspace(sessionId) {
|
|
1866
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
1867
|
+
const store = this.cloudStore();
|
|
1868
|
+
if (store === undefined) {
|
|
1869
|
+
return;
|
|
1870
|
+
}
|
|
1871
|
+
try {
|
|
1872
|
+
yield wipeSessionWorkspace({
|
|
1873
|
+
sink: store.sink,
|
|
1874
|
+
workspacePrefix: store.sessionWorkspacePrefix(sessionId),
|
|
1875
|
+
});
|
|
1876
|
+
}
|
|
1877
|
+
catch (error) {
|
|
1878
|
+
this.logger(`[workspace] ${store.label} session files wipe failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
1879
|
+
}
|
|
1880
|
+
});
|
|
1881
|
+
}
|
|
1882
|
+
clearPendingWorkspaceFiles(sessionId, pending) {
|
|
1883
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
1884
|
+
yield this.updateRecord(sessionId, (current) => (Object.assign(Object.assign({}, current), { pendingWorkspaceFiles: current.pendingWorkspaceFiles === pending
|
|
1885
|
+
? undefined
|
|
1886
|
+
: current.pendingWorkspaceFiles })));
|
|
1887
|
+
});
|
|
1888
|
+
}
|
|
1585
1889
|
/**
|
|
1586
1890
|
* With files authored, every first cloud turn re-copies the authored
|
|
1587
1891
|
* bytes and the memo only dedupes concurrent first turns. The mount is
|
|
@@ -1623,6 +1927,7 @@ export class SessionEngine {
|
|
|
1623
1927
|
mountPath: DEPLOYMENT_STORE_MOUNT_PATH,
|
|
1624
1928
|
skillsPrefix: agentStoreKeys.skillsPrefix(),
|
|
1625
1929
|
workspacePrefix: agentStoreKeys.workspacePrefix(),
|
|
1930
|
+
sessionWorkspacePrefix: (sessionId) => agentStoreKeys.sessionWorkspacePrefix(sessionId),
|
|
1626
1931
|
label: "deployment store",
|
|
1627
1932
|
};
|
|
1628
1933
|
if (v2Hosting.kind === "cursor-managed") {
|
|
@@ -1641,6 +1946,7 @@ export class SessionEngine {
|
|
|
1641
1946
|
mountPath: USER_STORE_MOUNT_PATH,
|
|
1642
1947
|
skillsPrefix: agentStoreKeys.userSkillsPrefix(this.project.name),
|
|
1643
1948
|
workspacePrefix: agentStoreKeys.userWorkspacePrefix(this.project.name),
|
|
1949
|
+
sessionWorkspacePrefix: (sessionId) => agentStoreKeys.userSessionWorkspacePrefix(this.project.name, sessionId),
|
|
1644
1950
|
label: "user store",
|
|
1645
1951
|
};
|
|
1646
1952
|
}
|
|
@@ -1649,6 +1955,7 @@ export class SessionEngine {
|
|
|
1649
1955
|
buildTurnRequest(record, agent, turnId, prompt, isFirstTurn, instructionsInvisibleToHarness, emit, onUpdate, signal, images) {
|
|
1650
1956
|
return __awaiter(this, void 0, void 0, function* () {
|
|
1651
1957
|
var _a, _b, _c;
|
|
1958
|
+
var _d;
|
|
1652
1959
|
// Per-session cloud attach (channel/tool handoff) forces cloud runtime
|
|
1653
1960
|
// even when the agent defaults to local for chat server tools.
|
|
1654
1961
|
const runtime = resolveSessionRuntime({
|
|
@@ -1659,6 +1966,15 @@ export class SessionEngine {
|
|
|
1659
1966
|
// allowlist, and a restriction that silently does not apply is worse
|
|
1660
1967
|
// than a refused turn. Non-local agents already fail discovery; this
|
|
1661
1968
|
// guards hybrid agents' per-send cloud sessions.
|
|
1969
|
+
//
|
|
1970
|
+
// Factory roots omit `allowedTools` at discovery (the live handle is
|
|
1971
|
+
// resolved per session). The allowlist guard below therefore never
|
|
1972
|
+
// fires for `defineAgent({ root: (ctx) => … })` with omitted `tools`,
|
|
1973
|
+
// and a per-send `cloud` attach would skip the virtual-root allowlist
|
|
1974
|
+
// and run unrestricted on a VM. Any authored root refuses non-local turns.
|
|
1975
|
+
if (runtime !== "local" && this.hasRootOverride()) {
|
|
1976
|
+
throw new Error(`Agent "${agent.name}" declares root, which cannot be served on ${runtime} turns. Refusing the session rather than running it against the host VM.`);
|
|
1977
|
+
}
|
|
1662
1978
|
if (runtime !== "local" && agent.allowedTools !== undefined) {
|
|
1663
1979
|
throw new Error(`Agent "${agent.name}" declares a built-in tool allowlist (tools), which cannot be enforced on ${runtime} turns. Refusing the session rather than running it unrestricted.`);
|
|
1664
1980
|
}
|
|
@@ -1679,6 +1995,38 @@ export class SessionEngine {
|
|
|
1679
1995
|
override: record.cloudOverride,
|
|
1680
1996
|
})
|
|
1681
1997
|
: undefined;
|
|
1998
|
+
const authoredRoot = this.hasRootOverride();
|
|
1999
|
+
const root = runtime === "local"
|
|
2000
|
+
? yield this.resolveFileSystem({
|
|
2001
|
+
sessionId: record.sessionId,
|
|
2002
|
+
continuationKey: (_d = record.continuationKey) !== null && _d !== void 0 ? _d : undefined,
|
|
2003
|
+
cache: true,
|
|
2004
|
+
cwd: this.harnessCwd(record),
|
|
2005
|
+
})
|
|
2006
|
+
: undefined;
|
|
2007
|
+
const harnessTools = runtime === "local" && root !== undefined
|
|
2008
|
+
? authoredRoot
|
|
2009
|
+
? {
|
|
2010
|
+
tools: resolveFileSystemTools({
|
|
2011
|
+
root,
|
|
2012
|
+
tools: agent.allowedTools,
|
|
2013
|
+
}),
|
|
2014
|
+
}
|
|
2015
|
+
: resolveHostHarnessToolOptions(agent.allowedTools)
|
|
2016
|
+
: undefined;
|
|
2017
|
+
const fileTools = root === undefined
|
|
2018
|
+
? []
|
|
2019
|
+
: synthesizeFileSystemTools(root, authoredRoot
|
|
2020
|
+
? rootFileToolsFromAuthored(agent.allowedTools)
|
|
2021
|
+
: hostFileToolsFromAuthored(agent.allowedTools));
|
|
2022
|
+
// Host-default keeps native SemanticSearch (the host index).
|
|
2023
|
+
// `localFileSystem.search` is empty, so synthesizing would
|
|
2024
|
+
// replace a working index with an empty custom tool.
|
|
2025
|
+
const synthesized = root === undefined
|
|
2026
|
+
? []
|
|
2027
|
+
: this.withTurnScratchTools(authoredRoot
|
|
2028
|
+
? fileTools
|
|
2029
|
+
: fileTools.filter((tool) => tool.name !== "SemanticSearch"), record.sessionId);
|
|
1682
2030
|
let turnPrompt = prompt;
|
|
1683
2031
|
if (isFirstTurn) {
|
|
1684
2032
|
const contextBlock = buildSessionContextBlock({
|
|
@@ -1690,32 +2038,37 @@ export class SessionEngine {
|
|
|
1690
2038
|
});
|
|
1691
2039
|
turnPrompt = `${contextBlock}\n\n${prompt}`;
|
|
1692
2040
|
}
|
|
1693
|
-
if (
|
|
1694
|
-
|
|
1695
|
-
|
|
1696
|
-
|
|
1697
|
-
|
|
1698
|
-
|
|
1699
|
-
|
|
1700
|
-
|
|
1701
|
-
|
|
1702
|
-
|
|
1703
|
-
|
|
1704
|
-
|
|
2041
|
+
if (runtime === "cloud") {
|
|
2042
|
+
// Cloud VMs have no materialized workspace: ship the full context,
|
|
2043
|
+
// including agent tool script bodies. Authored skills and workspace
|
|
2044
|
+
// seeds land on the store mount (skills for native discovery, seeds
|
|
2045
|
+
// for the model's file tools), per-turn workspaceFiles land under
|
|
2046
|
+
// the session prefix, and on hosted deployments the shared memory
|
|
2047
|
+
// journal is on that mount too — say where. When the turn carries
|
|
2048
|
+
// the session-bound server-tool MCP endpoint, the preamble catalogs
|
|
2049
|
+
// server tools under that MCP server name *before* the agent-tool
|
|
2050
|
+
// "write the script if missing" recipe, so a model told to "use
|
|
2051
|
+
// <server tool>" calls MCP instead of inventing a .sh.
|
|
2052
|
+
const hosted = isCursorHostedFilesAvailable();
|
|
2053
|
+
const store = hosted || isCursorUserStoreFilesAvailable()
|
|
2054
|
+
? this.cloudStore()
|
|
2055
|
+
: undefined;
|
|
2056
|
+
let preamble = "";
|
|
2057
|
+
const sections = [];
|
|
2058
|
+
const pending = record.pendingWorkspaceFiles;
|
|
2059
|
+
if (isFirstTurn) {
|
|
2060
|
+
preamble = buildAgentsMdContent(agent, {
|
|
1705
2061
|
includeScripts: true,
|
|
1706
2062
|
serverToolsMcpName: this.cloudServerToolsConnection === undefined
|
|
1707
2063
|
? undefined
|
|
1708
2064
|
: SERVER_TOOLS_MCP_SERVER_NAME,
|
|
1709
2065
|
});
|
|
1710
|
-
|
|
1711
|
-
|
|
1712
|
-
|
|
1713
|
-
|
|
1714
|
-
|
|
1715
|
-
|
|
1716
|
-
: undefined;
|
|
1717
|
-
let sections = "";
|
|
1718
|
-
if (store !== undefined) {
|
|
2066
|
+
}
|
|
2067
|
+
if (store !== undefined) {
|
|
2068
|
+
if (isFirstTurn) {
|
|
2069
|
+
// Synced whenever a store is reachable, not just when skills or
|
|
2070
|
+
// seeds exist: removing the last one has to delete its store copies
|
|
2071
|
+
// too.
|
|
1719
2072
|
const [, seedsSynced] = yield Promise.all([
|
|
1720
2073
|
this.ensureCloudSkillsSynced(store),
|
|
1721
2074
|
this.ensureCloudWorkspaceSynced(store),
|
|
@@ -1723,32 +2076,62 @@ export class SessionEngine {
|
|
|
1723
2076
|
// Only name the mount when the bytes landed; a failed sync must
|
|
1724
2077
|
// not send the model looking for files that are not there.
|
|
1725
2078
|
if (seedsSynced && agent.seedFiles.length > 0) {
|
|
1726
|
-
|
|
1727
|
-
sections += `\n\n${buildCloudWorkspaceSection(dir)}`;
|
|
2079
|
+
sections.push(buildCloudWorkspaceSection(`${store.mountPath}/${store.workspacePrefix}`));
|
|
1728
2080
|
}
|
|
1729
2081
|
}
|
|
1730
|
-
if (
|
|
1731
|
-
|
|
2082
|
+
if (pending !== undefined && Object.keys(pending).length > 0) {
|
|
2083
|
+
const synced = yield this.syncCloudSessionWorkspaceFiles(store, record.sessionId, pending);
|
|
2084
|
+
if (synced !== undefined) {
|
|
2085
|
+
sections.push(buildCloudSessionWorkspaceSection(synced.dir, synced.relPaths));
|
|
2086
|
+
yield this.clearPendingWorkspaceFiles(record.sessionId, pending);
|
|
2087
|
+
}
|
|
1732
2088
|
}
|
|
1733
|
-
turnPrompt = `${preamble}${sections}\n\n${turnPrompt}`;
|
|
1734
2089
|
}
|
|
1735
|
-
else if (
|
|
1736
|
-
|
|
1737
|
-
|
|
1738
|
-
|
|
1739
|
-
|
|
1740
|
-
|
|
1741
|
-
|
|
1742
|
-
|
|
1743
|
-
|
|
1744
|
-
|
|
2090
|
+
else if (pending !== undefined && Object.keys(pending).length > 0) {
|
|
2091
|
+
yield this.clearPendingWorkspaceFiles(record.sessionId, pending);
|
|
2092
|
+
}
|
|
2093
|
+
if (isFirstTurn && hosted) {
|
|
2094
|
+
sections.push(buildCloudMemorySection(this.project.name));
|
|
2095
|
+
}
|
|
2096
|
+
if (preamble !== "" || sections.length > 0) {
|
|
2097
|
+
turnPrompt = [preamble, ...sections, turnPrompt]
|
|
2098
|
+
.filter((part) => part !== "")
|
|
2099
|
+
.join("\n\n");
|
|
1745
2100
|
}
|
|
1746
2101
|
}
|
|
2102
|
+
else if (isFirstTurn && runtime === "local" && authoredRoot) {
|
|
2103
|
+
// Virtual roots skip materialize, so AGENTS.md never lands on disk.
|
|
2104
|
+
// Ship the same preamble the borrowed-cwd local path uses.
|
|
2105
|
+
const preamble = buildAgentsMdContent(Object.assign(Object.assign({}, agent), { tools: [...agent.tools, ...synthesized] }), { includeScripts: true });
|
|
2106
|
+
const workspaceInfo = `<user_info>\nWorkspace Path: /\n</user_info>`;
|
|
2107
|
+
turnPrompt =
|
|
2108
|
+
preamble === ""
|
|
2109
|
+
? `${workspaceInfo}\n\n${turnPrompt}`
|
|
2110
|
+
: `${workspaceInfo}\n\n${preamble}\n\n${turnPrompt}`;
|
|
2111
|
+
}
|
|
2112
|
+
else if (isFirstTurn &&
|
|
2113
|
+
runtime === "local" &&
|
|
2114
|
+
instructionsInvisibleToHarness) {
|
|
2115
|
+
// Local workspace whose AGENTS.md the harness will not load. With a
|
|
2116
|
+
// borrowed harness cwd, agent tool scripts live only in the durable
|
|
2117
|
+
// scaffold dir — embed bodies like cloud. Otherwise the catalog can
|
|
2118
|
+
// reference on-disk paths under the harness cwd. Grokbot turns are
|
|
2119
|
+
// excluded: their instructions ride the request's `instructions`
|
|
2120
|
+
// field into the Sand system prompt instead.
|
|
2121
|
+
const includeScripts = this.hasBorrowedWorkspace(record);
|
|
2122
|
+
const preamble = buildAgentsMdContent(agent, { includeScripts });
|
|
2123
|
+
turnPrompt = `${preamble}\n\n${turnPrompt}`;
|
|
2124
|
+
}
|
|
1747
2125
|
return Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({ sessionId: record.sessionId }, (record.sdkAgentId === undefined
|
|
1748
2126
|
? {}
|
|
1749
|
-
: { sdkAgentId: record.sdkAgentId })), { workspaceDir: this.harnessCwd(record), sandbox:
|
|
1750
|
-
|
|
1751
|
-
|
|
2127
|
+
: { sdkAgentId: record.sdkAgentId })), { workspaceDir: this.harnessCwd(record), sandbox: authoredRoot
|
|
2128
|
+
? false
|
|
2129
|
+
: ((_c = this.project.agent.local) === null || _c === void 0 ? void 0 : _c.sandbox) === true }), (runtime === "local" && harnessTools !== undefined
|
|
2130
|
+
? Object.assign(Object.assign({}, (harnessTools.tools === undefined
|
|
2131
|
+
? {}
|
|
2132
|
+
: { tools: harnessTools.tools })), (harnessTools.disallowedTools === undefined
|
|
2133
|
+
? {}
|
|
2134
|
+
: { disallowedTools: harnessTools.disallowedTools })) : {})), { runnerStateDir: join(this.stateRoot, "runner"), prompt: turnPrompt, isFirstTurn }), (images !== undefined && images.length > 0 ? { images } : {})), (agent.model === undefined ? {} : { model: agent.model })), { runtime, agentName: agent.name }), (mergedCloud === undefined ? {} : { cloud: mergedCloud })), {
|
|
1752
2135
|
// The hosted Grok Bot harness reads no workspace AGENTS.md: grokbot
|
|
1753
2136
|
// turns carry the composed instructions into the hosted session,
|
|
1754
2137
|
// which surfaces them in the Sand system prompt. The box never sees
|
|
@@ -1759,7 +2142,7 @@ export class SessionEngine {
|
|
|
1759
2142
|
: undefined }), (runtime === "cloud" && !isCursorHostedFilesAvailable()
|
|
1760
2143
|
? { agentServeAgent: this.project.name }
|
|
1761
2144
|
: {})), { customTools: runtime === "local"
|
|
1762
|
-
? yield this.buildCustomTools(record, agent, turnId, emit)
|
|
2145
|
+
? yield this.buildCustomTools(record, agent, turnId, emit, synthesized)
|
|
1763
2146
|
: {}, mcpServers: this.buildMcpServers(runtime, record.sessionId, yield this.evaluateConnectionAuth(record)) }), (runtime === "local" && this.hasAttachedAuthedConnections()
|
|
1764
2147
|
? { perSendMcpServers: true }
|
|
1765
2148
|
: {})), { subagents: buildRunnerSubagents(agent), onUpdate,
|
|
@@ -1982,8 +2365,8 @@ export class SessionEngine {
|
|
|
1982
2365
|
return evaluated;
|
|
1983
2366
|
});
|
|
1984
2367
|
}
|
|
1985
|
-
buildCustomTools(
|
|
1986
|
-
return __awaiter(this,
|
|
2368
|
+
buildCustomTools(record_1, agent_1, turnId_1, emit_1) {
|
|
2369
|
+
return __awaiter(this, arguments, void 0, function* (record, agent, turnId, emit, extraTools = []) {
|
|
1987
2370
|
const tools = {};
|
|
1988
2371
|
const register = (tool) => {
|
|
1989
2372
|
tools[tool.name] = Object.assign(Object.assign(Object.assign({ description: tool.description, inputSchema: tool.inputSchema }, (tool.outputSchema === undefined
|
|
@@ -2003,7 +2386,7 @@ export class SessionEngine {
|
|
|
2003
2386
|
});
|
|
2004
2387
|
}) });
|
|
2005
2388
|
};
|
|
2006
|
-
for (const tool of agent.tools) {
|
|
2389
|
+
for (const tool of [...agent.tools, ...extraTools]) {
|
|
2007
2390
|
if (tool.execution !== "server") {
|
|
2008
2391
|
continue;
|
|
2009
2392
|
}
|
|
@@ -2672,6 +3055,7 @@ export class SessionEngine {
|
|
|
2672
3055
|
callTool(toolName_1) {
|
|
2673
3056
|
return __awaiter(this, arguments, void 0, function* (toolName, input = {}, options = {}) {
|
|
2674
3057
|
var _a;
|
|
3058
|
+
var _b, _c;
|
|
2675
3059
|
const callId = newToolCallId(toolName);
|
|
2676
3060
|
// Identity resolves before the tool lookup: advertised connection tools
|
|
2677
3061
|
// only exist relative to a session (per-session auth), so finding them
|
|
@@ -2681,6 +3065,24 @@ export class SessionEngine {
|
|
|
2681
3065
|
const session = identity.session;
|
|
2682
3066
|
let workspaceDir = identity.workspaceDir;
|
|
2683
3067
|
let scratchDir = identity.scratchDir;
|
|
3068
|
+
if (isFileSystemToolAlias(toolName) &&
|
|
3069
|
+
identity.busy &&
|
|
3070
|
+
record !== undefined &&
|
|
3071
|
+
isMutatingFileSystemTool(toolName)) {
|
|
3072
|
+
throw new SessionBusyError(record.sessionId);
|
|
3073
|
+
}
|
|
3074
|
+
const native = yield this.nativeFileSystemOutcome({
|
|
3075
|
+
toolName,
|
|
3076
|
+
input,
|
|
3077
|
+
callId,
|
|
3078
|
+
sessionId: record === null || record === void 0 ? void 0 : record.sessionId,
|
|
3079
|
+
continuationKey: (_c = (_b = record === null || record === void 0 ? void 0 : record.continuationKey) !== null && _b !== void 0 ? _b : session.continuationKey) !== null && _c !== void 0 ? _c : undefined,
|
|
3080
|
+
cwd: workspaceDir,
|
|
3081
|
+
dryRun: (record === null || record === void 0 ? void 0 : record.dryRun) === true,
|
|
3082
|
+
});
|
|
3083
|
+
if (native !== undefined) {
|
|
3084
|
+
return native;
|
|
3085
|
+
}
|
|
2684
3086
|
let tool = this.project.agent.tools.find((t) => t.name === toolName);
|
|
2685
3087
|
if (tool === undefined &&
|
|
2686
3088
|
this.project.agent.connections.some((c) => c.advertiseTools === true)) {
|
|
@@ -2769,7 +3171,8 @@ export class SessionEngine {
|
|
|
2769
3171
|
const turnMaterialized = record !== undefined &&
|
|
2770
3172
|
identity.busy &&
|
|
2771
3173
|
this.materializedWorkspaces.has(record.sessionId);
|
|
2772
|
-
if (
|
|
3174
|
+
if (!this.hasRootOverride() &&
|
|
3175
|
+
(record === undefined || workspaceUnavailable || !turnMaterialized)) {
|
|
2773
3176
|
yield materializeWorkspace({
|
|
2774
3177
|
agent: this.project.agent,
|
|
2775
3178
|
workspaceDir: record === undefined || workspaceUnavailable
|
|
@@ -3548,7 +3951,8 @@ export class SessionEngine {
|
|
|
3548
3951
|
}
|
|
3549
3952
|
runCloudTurnCostBackfill(sessionId) {
|
|
3550
3953
|
return __awaiter(this, void 0, void 0, function* () {
|
|
3551
|
-
var _a
|
|
3954
|
+
var _a;
|
|
3955
|
+
var _b, _c;
|
|
3552
3956
|
const log = yield this.logs.get(sessionId);
|
|
3553
3957
|
const events = yield log.snapshot(0);
|
|
3554
3958
|
if (!events.some((event) => isUnpricedCompletedTurn(event))) {
|
|
@@ -3559,9 +3963,7 @@ export class SessionEngine {
|
|
|
3559
3963
|
return;
|
|
3560
3964
|
}
|
|
3561
3965
|
const record = yield this.sessions.get(sessionId);
|
|
3562
|
-
const sdkAgentId = (
|
|
3563
|
-
? record.sdkAgentId
|
|
3564
|
-
: undefined)) !== null && _a !== void 0 ? _a : cloudSdkAgentIdFromEvents(events);
|
|
3966
|
+
const sdkAgentId = (_b = (((_a = record === null || record === void 0 ? void 0 : record.sdkAgentId) === null || _a === void 0 ? void 0 : _a.startsWith("bc-")) ? record.sdkAgentId : undefined)) !== null && _b !== void 0 ? _b : cloudSdkAgentIdFromEvents(events);
|
|
3565
3967
|
if (sdkAgentId === undefined) {
|
|
3566
3968
|
return;
|
|
3567
3969
|
}
|
|
@@ -3569,7 +3971,7 @@ export class SessionEngine {
|
|
|
3569
3971
|
if (billed === undefined) {
|
|
3570
3972
|
return;
|
|
3571
3973
|
}
|
|
3572
|
-
const model = (
|
|
3974
|
+
const model = (_c = this.project.agent.model) !== null && _c !== void 0 ? _c : DEFAULT_MODEL;
|
|
3573
3975
|
const patched = applyCloudUsageToEvents(events, billed, model);
|
|
3574
3976
|
if (patched === undefined) {
|
|
3575
3977
|
return;
|