@cursor/july 0.1.1 → 0.1.3
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/AGENTS.md +40 -7
- package/README.md +33 -24
- package/dist/bin/agent-serve.d.ts +3 -1
- package/dist/bin/agent-serve.d.ts.map +1 -1
- package/dist/bin/agent-serve.js +466 -140
- package/dist/channels/github/api.d.ts.map +1 -1
- package/dist/channels/github/api.js +31 -14
- package/dist/channels/github/cursor-account.d.ts +43 -0
- package/dist/channels/github/cursor-account.d.ts.map +1 -0
- package/dist/channels/github/cursor-account.js +95 -0
- package/dist/channels/github/github-channel.d.ts.map +1 -1
- package/dist/channels/github/github-channel.js +46 -9
- package/dist/channels/github/index.d.ts +2 -2
- package/dist/channels/github/index.js +2 -2
- package/dist/channels/github/types.d.ts +17 -0
- package/dist/channels/github/types.d.ts.map +1 -1
- package/dist/channels/slack/slack-channel.d.ts +8 -2
- package/dist/channels/slack/slack-channel.d.ts.map +1 -1
- package/dist/channels/slack/slack-channel.js +8 -0
- package/dist/channels/slack/types.d.ts +24 -3
- package/dist/channels/slack/types.d.ts.map +1 -1
- package/dist/channels/slack/types.js +15 -1
- package/dist/docs/404.html +2 -2
- package/dist/docs/ab.html +8 -8
- package/dist/docs/assets/{ab.md.COdXkces.js → ab.md.BMCZ6Hd7.js} +3 -3
- package/dist/docs/assets/{ab.md.COdXkces.lean.js → ab.md.BMCZ6Hd7.lean.js} +1 -1
- package/dist/docs/assets/{app.DqfFEmJd.js → app.BR0RbIdx.js} +1 -1
- package/dist/docs/assets/chunks/@localSearchIndexroot.DtIOQzGj.js +1 -0
- package/dist/docs/assets/chunks/{VPLocalSearchBox.BaLEdS15.js → VPLocalSearchBox.qjsVTneI.js} +1 -1
- package/dist/docs/assets/chunks/{theme.CZRvu_0q.js → theme.2Kg8jIp_.js} +2 -2
- package/dist/docs/assets/{deployment.md.Dx1TYNk5.js → deployment.md.DTKwE15Z.js} +3 -3
- package/dist/docs/assets/{deployment.md.Dx1TYNk5.lean.js → deployment.md.DTKwE15Z.lean.js} +1 -1
- package/dist/docs/assets/{evals.md.DPZ_MAnI.js → evals.md.DAgEc_hL.js} +3 -3
- package/dist/docs/assets/{guides_agent-to-agent.md.CrtrsySy.js → guides_agent-to-agent.md.Bpzgq2Pq.js} +1 -1
- package/dist/docs/assets/{guides_cloud-runtime.md.CYlNMTNp.js → guides_cloud-runtime.md.gVzabdQL.js} +1 -1
- package/dist/docs/assets/{guides_github.md.DwbKhCeS.js → guides_github.md.DOOCpqsW.js} +11 -4
- package/dist/docs/assets/{guides_github.md.DwbKhCeS.lean.js → guides_github.md.DOOCpqsW.lean.js} +1 -1
- package/dist/docs/assets/{guides_human-in-the-loop.md.Dvuctx7s.js → guides_human-in-the-loop.md.DlUqsp1S.js} +2 -2
- package/dist/docs/assets/{guides_slack.md.bv41fHfW.js → guides_slack.md.CCwqHvSV.js} +4 -4
- package/dist/docs/assets/{guides_slack.md.bv41fHfW.lean.js → guides_slack.md.CCwqHvSV.lean.js} +1 -1
- package/dist/docs/assets/{guides_webhooks.md.hFTik3lf.js → guides_webhooks.md.B1EswtUu.js} +2 -2
- package/dist/docs/assets/index.md.m81y7TY7.js +20 -0
- package/dist/docs/assets/{index.md.BPKcj5AI.lean.js → index.md.m81y7TY7.lean.js} +1 -1
- package/dist/docs/assets/quickstart.md.BU6Iwi_9.js +204 -0
- package/dist/docs/assets/quickstart.md.BU6Iwi_9.lean.js +1 -0
- package/dist/docs/assets/{reference_agent-config.md.Bpd7HQwf.js → reference_agent-config.md.DrW2JUM8.js} +4 -4
- package/dist/docs/assets/{reference_agent-config.md.Bpd7HQwf.lean.js → reference_agent-config.md.DrW2JUM8.lean.js} +1 -1
- package/dist/docs/assets/{reference_channels.md.D7JTR03W.js → reference_channels.md.DdmiKgqf.js} +4 -4
- package/dist/docs/assets/{reference_channels.md.D7JTR03W.lean.js → reference_channels.md.DdmiKgqf.lean.js} +1 -1
- package/dist/docs/assets/{reference_cli.md.DA730zCu.js → reference_cli.md.Bv6pOxcF.js} +11 -6
- package/dist/docs/assets/{reference_cli.md.DA730zCu.lean.js → reference_cli.md.Bv6pOxcF.lean.js} +1 -1
- package/dist/docs/assets/{reference_connections.md.C3vNH_DE.js → reference_connections.md.zaEYCLHT.js} +1 -1
- package/dist/docs/assets/{reference_hooks.md.BCEc3MyM.js → reference_hooks.md.DyLVfE1O.js} +1 -1
- package/dist/docs/assets/{reference_hooks.md.BCEc3MyM.lean.js → reference_hooks.md.DyLVfE1O.lean.js} +1 -1
- package/dist/docs/assets/{reference_http-api.md.DBAahtdz.js → reference_http-api.md.Dx_nmDG6.js} +1 -1
- package/dist/docs/assets/{reference_instructions.md.BC05LEQ8.js → reference_instructions.md.CgoV-YEb.js} +9 -7
- package/dist/docs/assets/{reference_instructions.md.BC05LEQ8.lean.js → reference_instructions.md.CgoV-YEb.lean.js} +1 -1
- package/dist/docs/assets/{reference_schedules.md.D7qijxLk.js → reference_schedules.md.w_F2mXB6.js} +2 -2
- package/dist/docs/assets/{reference_skills.md.VQnlBT3Q.js → reference_skills.md.B_jHN7JL.js} +3 -3
- package/dist/docs/assets/{reference_skills.md.VQnlBT3Q.lean.js → reference_skills.md.B_jHN7JL.lean.js} +1 -1
- package/dist/docs/assets/{reference_subagents.md.CIRAVcPK.js → reference_subagents.md.zWAMNfi1.js} +1 -1
- package/dist/docs/assets/{reference_tools.md.DF5kwlt0.js → reference_tools.md.CqgJroI0.js} +2 -2
- package/dist/docs/assets/scaffolding-agents.md.C3pTrmoE.js +1 -0
- package/dist/docs/assets/scaffolding-agents.md.C3pTrmoE.lean.js +1 -0
- package/dist/docs/assets/storage.md.CVnInNiN.js +17 -0
- package/dist/docs/assets/storage.md.CVnInNiN.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 +7 -7
- package/dist/docs/evals.html +7 -7
- package/dist/docs/guides/agent-to-agent.html +6 -6
- package/dist/docs/guides/cloud-runtime.html +5 -5
- package/dist/docs/guides/github.html +14 -7
- package/dist/docs/guides/human-in-the-loop.html +6 -6
- package/dist/docs/guides/slack.html +8 -8
- package/dist/docs/guides/webhooks.html +6 -6
- package/dist/docs/hashmap.json +1 -1
- package/dist/docs/hillclimbing.html +5 -5
- package/dist/docs/index.html +7 -7
- package/dist/docs/quickstart.html +195 -26
- package/dist/docs/reference/agent-config.html +7 -7
- package/dist/docs/reference/channels.html +8 -8
- package/dist/docs/reference/cli.html +14 -9
- package/dist/docs/reference/connections.html +5 -5
- package/dist/docs/reference/hooks.html +5 -5
- package/dist/docs/reference/http-api.html +6 -6
- package/dist/docs/reference/instructions.html +13 -11
- package/dist/docs/reference/playground.html +4 -4
- package/dist/docs/reference/project-layout.html +4 -4
- package/dist/docs/reference/schedules.html +7 -7
- package/dist/docs/reference/sessions.html +4 -4
- package/dist/docs/reference/skills.html +6 -6
- package/dist/docs/reference/subagents.html +6 -6
- package/dist/docs/reference/tools.html +7 -7
- package/dist/docs/scaffolding-agents.html +5 -5
- package/dist/docs/storage.html +41 -0
- package/dist/docs/troubleshooting.html +4 -4
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/internal/chat-client.d.ts +29 -3
- package/dist/internal/chat-client.d.ts.map +1 -1
- package/dist/internal/chat-client.js +180 -27
- package/dist/internal/cli-ax.d.ts +75 -2
- package/dist/internal/cli-ax.d.ts.map +1 -1
- package/dist/internal/cli-ax.js +600 -52
- package/dist/internal/cli-cursor.d.ts.map +1 -1
- package/dist/internal/cli-cursor.js +8 -36
- package/dist/internal/cli-deploy.d.ts +108 -0
- package/dist/internal/cli-deploy.d.ts.map +1 -0
- package/dist/internal/cli-deploy.js +1009 -0
- package/dist/internal/cursor/backend-client.d.ts +10 -1
- package/dist/internal/cursor/backend-client.d.ts.map +1 -1
- package/dist/internal/cursor/backend-client.js +79 -1
- package/dist/internal/cursor/credentials.d.ts +9 -0
- package/dist/internal/cursor/credentials.d.ts.map +1 -1
- package/dist/internal/cursor/credentials.js +12 -0
- package/dist/internal/cursor/github-credentials.d.ts +44 -0
- package/dist/internal/cursor/github-credentials.d.ts.map +1 -0
- package/dist/internal/cursor/github-credentials.js +195 -0
- package/dist/internal/deploy-client.d.ts +184 -0
- package/dist/internal/deploy-client.d.ts.map +1 -0
- package/dist/internal/deploy-client.js +395 -0
- package/dist/internal/deploy-source.d.ts +35 -0
- package/dist/internal/deploy-source.d.ts.map +1 -0
- package/dist/internal/deploy-source.js +118 -0
- package/dist/internal/discovery.d.ts +11 -0
- package/dist/internal/discovery.d.ts.map +1 -1
- package/dist/internal/discovery.js +116 -19
- package/dist/internal/distribution.d.ts.map +1 -1
- package/dist/internal/distribution.js +1 -0
- package/dist/internal/eval-run-store.d.ts +22 -3
- package/dist/internal/eval-run-store.d.ts.map +1 -1
- package/dist/internal/eval-run-store.js +39 -20
- package/dist/internal/eval-runner.d.ts +2 -0
- package/dist/internal/eval-runner.d.ts.map +1 -1
- package/dist/internal/eval-runner.js +2 -0
- package/dist/internal/event-mapper.d.ts +54 -1
- package/dist/internal/event-mapper.d.ts.map +1 -1
- package/dist/internal/event-mapper.js +151 -41
- package/dist/internal/handleAgentServeTrigger.d.ts.map +1 -1
- package/dist/internal/handleAgentServeTrigger.js +10 -12
- package/dist/internal/host-platforms.d.ts +7 -2
- package/dist/internal/host-platforms.d.ts.map +1 -1
- package/dist/internal/host-platforms.js +15 -10
- package/dist/internal/hosting.d.ts +37 -0
- package/dist/internal/hosting.d.ts.map +1 -0
- package/dist/internal/hosting.js +67 -0
- package/dist/internal/init-project.d.ts +88 -1
- package/dist/internal/init-project.d.ts.map +1 -1
- package/dist/internal/init-project.js +221 -31
- package/dist/internal/install-cursor-skills.d.ts +64 -0
- package/dist/internal/install-cursor-skills.d.ts.map +1 -0
- package/dist/internal/install-cursor-skills.js +274 -0
- package/dist/internal/logs-client.d.ts +60 -0
- package/dist/internal/logs-client.d.ts.map +1 -0
- package/dist/internal/logs-client.js +311 -0
- package/dist/internal/open-browser.d.ts +5 -0
- package/dist/internal/open-browser.d.ts.map +1 -0
- package/dist/internal/open-browser.js +34 -0
- package/dist/internal/playground/toolchain.d.ts.map +1 -1
- package/dist/internal/playground/toolchain.js +16 -11
- package/dist/internal/playground-proxy.d.ts +69 -0
- package/dist/internal/playground-proxy.d.ts.map +1 -0
- package/dist/internal/playground-proxy.js +468 -0
- package/dist/internal/prompt-context.d.ts +35 -0
- package/dist/internal/prompt-context.d.ts.map +1 -0
- package/dist/internal/prompt-context.js +71 -0
- package/dist/internal/reminder-runner.d.ts +7 -0
- package/dist/internal/reminder-runner.d.ts.map +1 -1
- package/dist/internal/reminder-runner.js +50 -6
- package/dist/internal/reminder-store.d.ts +2 -0
- package/dist/internal/reminder-store.d.ts.map +1 -1
- package/dist/internal/reminder-store.js +18 -0
- package/dist/internal/request-headers.d.ts +11 -0
- package/dist/internal/request-headers.d.ts.map +1 -0
- package/dist/internal/request-headers.js +14 -0
- package/dist/internal/resolve-prod-target.d.ts +42 -0
- package/dist/internal/resolve-prod-target.d.ts.map +1 -0
- package/dist/internal/resolve-prod-target.js +111 -0
- package/dist/internal/run-client.d.ts +2 -2
- package/dist/internal/run-client.d.ts.map +1 -1
- package/dist/internal/run-client.js +38 -23
- package/dist/internal/server.d.ts.map +1 -1
- package/dist/internal/server.js +182 -45
- package/dist/internal/session-engine.d.ts +50 -1
- package/dist/internal/session-engine.d.ts.map +1 -1
- package/dist/internal/session-engine.js +267 -23
- package/dist/internal/sessions-client.d.ts +21 -0
- package/dist/internal/sessions-client.d.ts.map +1 -0
- package/dist/internal/sessions-client.js +168 -0
- package/dist/internal/storage-coordinator.d.ts +139 -0
- package/dist/internal/storage-coordinator.d.ts.map +1 -0
- package/dist/internal/storage-coordinator.js +499 -0
- package/dist/internal/stream-progress.d.ts.map +1 -1
- package/dist/internal/stream-progress.js +31 -3
- package/dist/internal/terminal-style.d.ts +22 -0
- package/dist/internal/terminal-style.d.ts.map +1 -0
- package/dist/internal/terminal-style.js +49 -0
- package/dist/internal/trajectory.d.ts +10 -5
- package/dist/internal/trajectory.d.ts.map +1 -1
- package/dist/internal/trajectory.js +82 -10
- package/dist/internal/workspace.d.ts +11 -0
- package/dist/internal/workspace.d.ts.map +1 -1
- package/dist/internal/workspace.js +38 -4
- package/dist/playground/assets/cursor-icons-outline-BxTT_FVJ.woff2 +0 -0
- package/dist/playground/assets/index-D-vo2lV_.css +1 -0
- package/dist/playground/assets/index-x60b9q2j.js +312 -0
- package/dist/playground/index.html +2 -2
- package/dist/storage.d.ts +204 -0
- package/dist/storage.d.ts.map +1 -0
- package/dist/storage.js +153 -0
- package/dist/types.d.ts +70 -4
- package/dist/types.d.ts.map +1 -1
- package/docs/README.md +3 -2
- package/docs/guides/github.md +43 -8
- package/docs/guides/slack.md +1 -1
- package/docs/quickstart.md +350 -57
- package/docs/reference/cli.md +51 -3
- package/docs/reference/instructions.md +8 -6
- package/docs/scaffolding-agents.md +1 -1
- package/docs/storage.md +98 -0
- package/package.json +10 -1
- package/skills/ab/SKILL.md +8 -8
- package/skills/create-agent/SKILL.md +28 -22
- package/skills/debug/SKILL.md +11 -11
- package/skills/evals/SKILL.md +16 -16
- package/skills/framework-map/SKILL.md +6 -6
- package/skills/github/SKILL.md +22 -14
- package/skills/hillclimb/SKILL.md +10 -10
- package/skills/setup-slack/SKILL.md +13 -13
- package/src/bin/agent-serve.ts +552 -179
- package/src/channels/github/api.ts +42 -23
- package/src/channels/github/cursor-account.ts +165 -0
- package/src/channels/github/github-channel.ts +66 -6
- package/src/channels/github/index.ts +2 -2
- package/src/channels/github/types.ts +19 -0
- package/src/channels/slack/slack-channel.ts +17 -3
- package/src/channels/slack/types.ts +44 -3
- package/src/index.ts +13 -0
- package/src/internal/chat-client.ts +252 -37
- package/src/internal/cli-ax.ts +722 -72
- package/src/internal/cli-cursor.ts +14 -42
- package/src/internal/cli-deploy.ts +1319 -0
- package/src/internal/cursor/backend-client.ts +103 -1
- package/src/internal/cursor/credentials.ts +14 -0
- package/src/internal/cursor/github-credentials.ts +248 -0
- package/src/internal/deploy-client.ts +632 -0
- package/src/internal/deploy-source.ts +133 -0
- package/src/internal/discovery.ts +141 -17
- package/src/internal/distribution.ts +1 -0
- package/src/internal/eval-run-store.ts +50 -20
- package/src/internal/eval-runner.ts +5 -0
- package/src/internal/event-mapper.ts +222 -42
- package/src/internal/handleAgentServeTrigger.ts +10 -12
- package/src/internal/host-platforms.ts +28 -11
- package/src/internal/hosting.ts +77 -0
- package/src/internal/init-project.ts +333 -51
- package/src/internal/install-cursor-skills.ts +327 -0
- package/src/internal/logs-client.ts +442 -0
- package/src/internal/open-browser.ts +41 -0
- package/src/internal/playground/toolchain.ts +15 -13
- package/src/internal/playground-proxy.ts +576 -0
- package/src/internal/prompt-context.ts +95 -0
- package/src/internal/reminder-runner.ts +50 -6
- package/src/internal/reminder-store.ts +21 -0
- package/src/internal/request-headers.ts +23 -0
- package/src/internal/resolve-prod-target.ts +150 -0
- package/src/internal/run-client.ts +39 -36
- package/src/internal/server.ts +223 -28
- package/src/internal/session-engine.ts +307 -10
- package/src/internal/sessions-client.ts +182 -0
- package/src/internal/storage-coordinator.ts +615 -0
- package/src/internal/stream-progress.ts +36 -2
- package/src/internal/terminal-style.ts +74 -0
- package/src/internal/trajectory.ts +91 -13
- package/src/internal/workspace.ts +42 -4
- package/src/storage.ts +325 -0
- package/src/types.ts +82 -8
- package/dist/docs/assets/chunks/@localSearchIndexroot.CcVk1uKq.js +0 -1
- package/dist/docs/assets/index.md.BPKcj5AI.js +0 -20
- package/dist/docs/assets/quickstart.md.tVPiGK_L.js +0 -35
- package/dist/docs/assets/quickstart.md.tVPiGK_L.lean.js +0 -1
- package/dist/docs/assets/scaffolding-agents.md.CyYfWGdc.js +0 -1
- package/dist/docs/assets/scaffolding-agents.md.CyYfWGdc.lean.js +0 -1
- package/dist/playground/assets/cursor-icons-outline-oY2V_mvK.woff2 +0 -0
- package/dist/playground/assets/index-1K-hG-7p.css +0 -1
- package/dist/playground/assets/index-FlWjhg3x.js +0 -79
- /package/dist/docs/assets/{evals.md.DPZ_MAnI.lean.js → evals.md.DAgEc_hL.lean.js} +0 -0
- /package/dist/docs/assets/{guides_agent-to-agent.md.CrtrsySy.lean.js → guides_agent-to-agent.md.Bpzgq2Pq.lean.js} +0 -0
- /package/dist/docs/assets/{guides_cloud-runtime.md.CYlNMTNp.lean.js → guides_cloud-runtime.md.gVzabdQL.lean.js} +0 -0
- /package/dist/docs/assets/{guides_human-in-the-loop.md.Dvuctx7s.lean.js → guides_human-in-the-loop.md.DlUqsp1S.lean.js} +0 -0
- /package/dist/docs/assets/{guides_webhooks.md.hFTik3lf.lean.js → guides_webhooks.md.B1EswtUu.lean.js} +0 -0
- /package/dist/docs/assets/{reference_connections.md.C3vNH_DE.lean.js → reference_connections.md.zaEYCLHT.lean.js} +0 -0
- /package/dist/docs/assets/{reference_http-api.md.DBAahtdz.lean.js → reference_http-api.md.Dx_nmDG6.lean.js} +0 -0
- /package/dist/docs/assets/{reference_schedules.md.D7qijxLk.lean.js → reference_schedules.md.w_F2mXB6.lean.js} +0 -0
- /package/dist/docs/assets/{reference_subagents.md.CIRAVcPK.lean.js → reference_subagents.md.zWAMNfi1.lean.js} +0 -0
- /package/dist/docs/assets/{reference_tools.md.DF5kwlt0.lean.js → reference_tools.md.CqgJroI0.lean.js} +0 -0
|
@@ -26,8 +26,8 @@ var __rest = (this && this.__rest) || function (s, e) {
|
|
|
26
26
|
}
|
|
27
27
|
return t;
|
|
28
28
|
};
|
|
29
|
-
import { mkdir, rm } from "node:fs/promises";
|
|
30
|
-
import { join } from "node:path";
|
|
29
|
+
import { mkdir, rm, writeFile } from "node:fs/promises";
|
|
30
|
+
import { dirname, join } from "node:path";
|
|
31
31
|
import { mergeABInstructions, resolveABMaxPlaygroundSessions, resolveABSplit, } from "../ab.js";
|
|
32
32
|
import { slackThreadPermalink } from "../channels/slack/links.js";
|
|
33
33
|
import { DIRECT_TOOL_CALL_CHANNEL_ID, isSymbolicConnectionTransport, } from "../types.js";
|
|
@@ -37,18 +37,21 @@ import { buildABSnapshot } from "./ab-snapshot.js";
|
|
|
37
37
|
import { ApprovalGate } from "./approval-gate.js";
|
|
38
38
|
import { samePrincipal } from "./auth.js";
|
|
39
39
|
import { mergeCloudOptions, resolveSessionRuntime } from "./cloud-merge.js";
|
|
40
|
+
import { isDevMode } from "./dev-mode.js";
|
|
40
41
|
import { EventLogStore } from "./event-log.js";
|
|
41
42
|
import { TurnEventMapper } from "./event-mapper.js";
|
|
42
43
|
import { createHostPlatforms } from "./host-platforms.js";
|
|
43
44
|
import { formatContinuationToken, newContinuationKey, newSessionId, newToolCallId, } from "./ids.js";
|
|
44
45
|
import { validateToolInput } from "./json-schema.js";
|
|
45
46
|
import { McpHost } from "./mcp-host.js";
|
|
47
|
+
import { buildIdentitySection, buildSessionContextBlock, SCHEDULE_CHANNEL_PREFIX, } from "./prompt-context.js";
|
|
46
48
|
import { assertCloudCanHonorAccountServersFilters } from "./resolved-connections.js";
|
|
47
49
|
import { SessionStore } from "./session-store.js";
|
|
50
|
+
import { StorageCoordinator } from "./storage-coordinator.js";
|
|
48
51
|
import { normalizeToolResult, toolCallErrorMessage } from "./tool-result.js";
|
|
49
52
|
import { buildAgentToolsCatalog, materializeWorkspace, writeWorkspaceFiles, } from "./workspace.js";
|
|
50
53
|
export const HTTP_CHANNEL_ID = "http";
|
|
51
|
-
export
|
|
54
|
+
export { SCHEDULE_CHANNEL_PREFIX } from "./prompt-context.js";
|
|
52
55
|
export class SessionBusyError extends Error {
|
|
53
56
|
constructor(sessionId) {
|
|
54
57
|
super(`Session ${sessionId} already has a running turn; wait for session.waiting before sending a follow-up`);
|
|
@@ -106,8 +109,10 @@ export class ApprovalInterruptedError extends Error {
|
|
|
106
109
|
}
|
|
107
110
|
export class SessionEngine {
|
|
108
111
|
constructor(options) {
|
|
109
|
-
var _a;
|
|
110
|
-
var
|
|
112
|
+
var _a, _b;
|
|
113
|
+
var _c, _d, _e;
|
|
114
|
+
/** In-flight lazy restores, deduped per channel + continuation key. */
|
|
115
|
+
this.restoreInFlight = new Map();
|
|
111
116
|
this.channelsById = new Map();
|
|
112
117
|
/** Sessions with a turn being admitted (before the run promise exists). */
|
|
113
118
|
this.pendingTurns = new Set();
|
|
@@ -126,17 +131,29 @@ export class SessionEngine {
|
|
|
126
131
|
this.project = options.project;
|
|
127
132
|
this.stateRoot = options.stateRoot;
|
|
128
133
|
this.runner = options.runner;
|
|
129
|
-
this.logger = (
|
|
134
|
+
this.logger = (_c = options.logger) !== null && _c !== void 0 ? _c : (() => { });
|
|
130
135
|
this.sessions = new SessionStore(join(options.stateRoot, "sessions"));
|
|
131
136
|
this.logs = new EventLogStore((sessionId) => this.sessions.eventFilePath(sessionId), (sessionId, error) => this.logger(`[agent-serve] failed to persist events for ${sessionId}: ${describeError(error)}`));
|
|
132
|
-
this.
|
|
133
|
-
|
|
134
|
-
|
|
137
|
+
this.storage =
|
|
138
|
+
options.project.storage === undefined
|
|
139
|
+
? undefined
|
|
140
|
+
: new StorageCoordinator({
|
|
141
|
+
definition: options.project.storage,
|
|
142
|
+
agentName: options.project.name,
|
|
143
|
+
projectRoot: options.project.rootDir,
|
|
144
|
+
logger: this.logger,
|
|
145
|
+
});
|
|
146
|
+
// Domain-specific hooks win; the defineStorage sink is the fallback.
|
|
147
|
+
const persistSamples = (_d = (_a = options.project.abConfig) === null || _a === void 0 ? void 0 : _a.persistSamples) !== null && _d !== void 0 ? _d : (_b = this.storage) === null || _b === void 0 ? void 0 : _b.asABSamplePersistence();
|
|
148
|
+
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); }), {
|
|
149
|
+
projectRoot: options.project.rootDir,
|
|
150
|
+
persistSamples,
|
|
151
|
+
});
|
|
135
152
|
// Peer and Cursor-account transports are symbolic until the serve host
|
|
136
153
|
// resolves them; the host-side MCP registry starts with the concrete
|
|
137
154
|
// connections and gains the rest via setResolvedConnections.
|
|
138
155
|
this.mcpHost = new McpHost(options.project.agent.connections.filter((connection) => !isSymbolicConnectionTransport(connection.transport)));
|
|
139
|
-
this.platforms = createHostPlatforms();
|
|
156
|
+
this.platforms = (_e = options.platforms) !== null && _e !== void 0 ? _e : createHostPlatforms();
|
|
140
157
|
for (const channel of options.project.channels) {
|
|
141
158
|
this.channelsById.set(channel.id, channel.definition);
|
|
142
159
|
}
|
|
@@ -181,11 +198,17 @@ export class SessionEngine {
|
|
|
181
198
|
*/
|
|
182
199
|
send(channelId_1, message_1) {
|
|
183
200
|
return __awaiter(this, arguments, void 0, function* (channelId, message, options = {}) {
|
|
184
|
-
var _a
|
|
185
|
-
|
|
186
|
-
const
|
|
201
|
+
var _a;
|
|
202
|
+
var _b, _c, _d;
|
|
203
|
+
const auth = (_b = options.auth) !== null && _b !== void 0 ? _b : null;
|
|
204
|
+
let existing = options.continuationToken === undefined
|
|
187
205
|
? undefined
|
|
188
206
|
: yield this.sessions.findByContinuation(channelId, options.continuationToken);
|
|
207
|
+
if (existing === undefined && options.continuationToken !== undefined) {
|
|
208
|
+
// Local miss: the session may live only in the storage sink (it
|
|
209
|
+
// fell outside the startup restore window, or restore is lazy-only).
|
|
210
|
+
existing = yield this.restoreSessionByContinuation(channelId, options.continuationToken);
|
|
211
|
+
}
|
|
189
212
|
if (existing !== undefined) {
|
|
190
213
|
if (!samePrincipal(existing.auth, auth)) {
|
|
191
214
|
throw new SessionAuthError(existing.sessionId);
|
|
@@ -209,9 +232,9 @@ export class SessionEngine {
|
|
|
209
232
|
let record = {
|
|
210
233
|
sessionId: newSessionId(),
|
|
211
234
|
channelId,
|
|
212
|
-
mode: (
|
|
235
|
+
mode: (_c = options.mode) !== null && _c !== void 0 ? _c : "chat",
|
|
213
236
|
purpose,
|
|
214
|
-
continuationKey: (
|
|
237
|
+
continuationKey: (_d = options.continuationToken) !== null && _d !== void 0 ? _d : newContinuationKey(),
|
|
215
238
|
auth,
|
|
216
239
|
title: options.title,
|
|
217
240
|
channelState,
|
|
@@ -224,6 +247,7 @@ export class SessionEngine {
|
|
|
224
247
|
updatedAt: now,
|
|
225
248
|
};
|
|
226
249
|
yield this.sessions.save(record);
|
|
250
|
+
(_a = this.storage) === null || _a === void 0 ? void 0 : _a.sessionRecord(record);
|
|
227
251
|
yield this.appendEvent(record.sessionId, {
|
|
228
252
|
type: "session.started",
|
|
229
253
|
data: { channelId },
|
|
@@ -515,7 +539,10 @@ export class SessionEngine {
|
|
|
515
539
|
// Yield so the HTTP NDJSON writer can flush tool start/result
|
|
516
540
|
// events while sibling parallel tools are still executing.
|
|
517
541
|
if (update.type === "tool-call-started" ||
|
|
518
|
-
update.type === "tool-call-completed"
|
|
542
|
+
update.type === "tool-call-completed" ||
|
|
543
|
+
// Nested subagent progress (newer SDKs); string check keeps
|
|
544
|
+
// typecheck green against older published `@cursor/sdk` pins.
|
|
545
|
+
update.type === "tool-call-delta") {
|
|
519
546
|
yield yieldEventLoop();
|
|
520
547
|
}
|
|
521
548
|
}), signal);
|
|
@@ -579,8 +606,8 @@ export class SessionEngine {
|
|
|
579
606
|
});
|
|
580
607
|
}
|
|
581
608
|
buildTurnRequest(record, agent, turnId, prompt, isFirstTurn, emit, onUpdate, signal) {
|
|
582
|
-
var _a;
|
|
583
|
-
var
|
|
609
|
+
var _a, _b, _c;
|
|
610
|
+
var _d;
|
|
584
611
|
// Per-session cloud attach (channel/tool handoff) forces cloud runtime
|
|
585
612
|
// even when the agent defaults to local for chat server tools.
|
|
586
613
|
const runtime = resolveSessionRuntime({
|
|
@@ -594,14 +621,24 @@ export class SessionEngine {
|
|
|
594
621
|
})
|
|
595
622
|
: undefined;
|
|
596
623
|
let turnPrompt = prompt;
|
|
624
|
+
if (isFirstTurn) {
|
|
625
|
+
const contextBlock = buildSessionContextBlock({
|
|
626
|
+
sessionId: record.sessionId,
|
|
627
|
+
channelId: record.channelId,
|
|
628
|
+
channelKind: (_b = (_a = this.channelsById.get(record.channelId)) === null || _a === void 0 ? void 0 : _a.meta) === null || _b === void 0 ? void 0 : _b.kind,
|
|
629
|
+
environment: isDevMode() ? "local dev server" : "hosted deployment",
|
|
630
|
+
});
|
|
631
|
+
turnPrompt = `${contextBlock}\n\n${prompt}`;
|
|
632
|
+
}
|
|
597
633
|
if (runtime === "cloud" && isFirstTurn) {
|
|
598
634
|
const preamble = [
|
|
599
|
-
(
|
|
635
|
+
(_d = (_c = agent.instructions) === null || _c === void 0 ? void 0 : _c.trim()) !== null && _d !== void 0 ? _d : "",
|
|
636
|
+
buildIdentitySection(agent),
|
|
600
637
|
buildAgentToolsCatalog(agent.tools, { includeScripts: true }),
|
|
601
638
|
]
|
|
602
639
|
.filter((part) => part !== "")
|
|
603
640
|
.join("\n\n");
|
|
604
|
-
turnPrompt =
|
|
641
|
+
turnPrompt = `${preamble}\n\n${turnPrompt}`;
|
|
605
642
|
}
|
|
606
643
|
return Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({ sessionId: record.sessionId }, (record.sdkAgentId === undefined
|
|
607
644
|
? {}
|
|
@@ -996,11 +1033,22 @@ export class SessionEngine {
|
|
|
996
1033
|
}
|
|
997
1034
|
queueDispatch(sessionId, event) {
|
|
998
1035
|
var _a;
|
|
999
|
-
|
|
1036
|
+
var _b;
|
|
1037
|
+
// Single funnel for both append paths (appendEvent + the held-log emit),
|
|
1038
|
+
// so the storage sink sees every durable event exactly once.
|
|
1039
|
+
(_a = this.storage) === null || _a === void 0 ? void 0 : _a.event(event);
|
|
1040
|
+
const chain = (_b = this.dispatchChains.get(sessionId)) !== null && _b !== void 0 ? _b : Promise.resolve();
|
|
1000
1041
|
const next = chain
|
|
1001
1042
|
.then(() => this.dispatchEvent(sessionId, event))
|
|
1002
1043
|
.catch((error) => {
|
|
1003
1044
|
this.logger(`[agent-serve] event dispatch failed for ${sessionId}: ${describeError(error)}`);
|
|
1045
|
+
})
|
|
1046
|
+
.then(() => {
|
|
1047
|
+
var _a;
|
|
1048
|
+
// Turn-end flush happens here — after the boundary event's handlers
|
|
1049
|
+
// and their record updates settled — so the persisted record carries
|
|
1050
|
+
// the turn's final channel state and continuation token.
|
|
1051
|
+
(_a = this.storage) === null || _a === void 0 ? void 0 : _a.eventDispatched(event);
|
|
1004
1052
|
});
|
|
1005
1053
|
this.dispatchChains.set(sessionId, next);
|
|
1006
1054
|
}
|
|
@@ -1127,10 +1175,29 @@ export class SessionEngine {
|
|
|
1127
1175
|
*/
|
|
1128
1176
|
abSnapshot(caller, options) {
|
|
1129
1177
|
return __awaiter(this, void 0, void 0, function* () {
|
|
1178
|
+
var _a;
|
|
1179
|
+
var _b;
|
|
1130
1180
|
const sessions = yield this.listSessions(caller, options);
|
|
1131
1181
|
const abConfig = this.project.abConfig;
|
|
1132
1182
|
const maxPlaygroundSessions = resolveABMaxPlaygroundSessions(abConfig === null || abConfig === void 0 ? void 0 : abConfig.maxPlaygroundSessions);
|
|
1133
1183
|
const foldedSessions = sessions.slice(0, maxPlaygroundSessions);
|
|
1184
|
+
// Backfill for a replacement host with nothing local to fold (e.g.
|
|
1185
|
+
// lazy-only restore before any session resumed): serve the persisted
|
|
1186
|
+
// aggregate instead of an empty surface. Gated on the host having no
|
|
1187
|
+
// sessions AT ALL — the persisted snapshot spans every principal, so a
|
|
1188
|
+
// caller who merely owns no sessions must not see it. Loaded once per
|
|
1189
|
+
// process (playground polls this route ~every 4s); skip the persist
|
|
1190
|
+
// side effect below — re-saving a restored snapshot would echo stale
|
|
1191
|
+
// data back into the store.
|
|
1192
|
+
if (foldedSessions.length === 0 &&
|
|
1193
|
+
this.storage !== undefined &&
|
|
1194
|
+
(yield this.sessions.list()).length === 0) {
|
|
1195
|
+
(_b = this.restoredAbSnapshot) !== null && _b !== void 0 ? _b : (this.restoredAbSnapshot = this.storage.getLatestAbSnapshot());
|
|
1196
|
+
const restoredSnapshot = yield this.restoredAbSnapshot;
|
|
1197
|
+
if (restoredSnapshot !== undefined) {
|
|
1198
|
+
return restoredSnapshot;
|
|
1199
|
+
}
|
|
1200
|
+
}
|
|
1134
1201
|
const snapshot = yield buildABSnapshot({
|
|
1135
1202
|
experiments: this.project.abs,
|
|
1136
1203
|
agentName: this.project.name,
|
|
@@ -1158,6 +1225,10 @@ export class SessionEngine {
|
|
|
1158
1225
|
this.logger(`[agent-serve] ab persistSnapshots.save threw: ${describeError(error)}`);
|
|
1159
1226
|
}
|
|
1160
1227
|
}
|
|
1228
|
+
else {
|
|
1229
|
+
// defineStorage fallback (throttled inside the coordinator).
|
|
1230
|
+
(_a = this.storage) === null || _a === void 0 ? void 0 : _a.abSnapshot(snapshot);
|
|
1231
|
+
}
|
|
1161
1232
|
return snapshot;
|
|
1162
1233
|
});
|
|
1163
1234
|
}
|
|
@@ -1275,12 +1346,14 @@ export class SessionEngine {
|
|
|
1275
1346
|
var _a;
|
|
1276
1347
|
const chain = (_a = this.updateChains.get(sessionId)) !== null && _a !== void 0 ? _a : Promise.resolve();
|
|
1277
1348
|
const next = chain.then(() => __awaiter(this, void 0, void 0, function* () {
|
|
1349
|
+
var _a;
|
|
1278
1350
|
const current = yield this.sessions.get(sessionId);
|
|
1279
1351
|
if (current === undefined) {
|
|
1280
1352
|
throw new Error(`Session ${sessionId} not found`);
|
|
1281
1353
|
}
|
|
1282
1354
|
const updated = Object.assign(Object.assign({}, updater(current)), { updatedAt: new Date().toISOString() });
|
|
1283
1355
|
yield this.sessions.save(updated);
|
|
1356
|
+
(_a = this.storage) === null || _a === void 0 ? void 0 : _a.sessionRecord(updated);
|
|
1284
1357
|
return updated;
|
|
1285
1358
|
}));
|
|
1286
1359
|
this.updateChains.set(sessionId, next.catch(() => { }));
|
|
@@ -1289,6 +1362,167 @@ export class SessionEngine {
|
|
|
1289
1362
|
// ==========================================================================
|
|
1290
1363
|
// Lifecycle
|
|
1291
1364
|
// ==========================================================================
|
|
1365
|
+
/**
|
|
1366
|
+
* Restore sessions from the authored storage sink. Called once at
|
|
1367
|
+
* serve start, before channels accept traffic: any persisted session
|
|
1368
|
+
* missing from the local `--state-root` is materialized there — events
|
|
1369
|
+
* as `events.ndjson`, record as `session.json` — after which every
|
|
1370
|
+
* existing read path (continuation lookup, event replay/streams, A/B
|
|
1371
|
+
* fold hydration) works unchanged. Local state always wins over the
|
|
1372
|
+
* sink, so restarts on the same host are no-ops.
|
|
1373
|
+
*
|
|
1374
|
+
* Failures are logged and skipped; a broken store (including rows that
|
|
1375
|
+
* violate the SessionRecord shape) never blocks serve start.
|
|
1376
|
+
*/
|
|
1377
|
+
restoreStoredSessions() {
|
|
1378
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
1379
|
+
const storage = this.storage;
|
|
1380
|
+
if (storage === undefined || !storage.canBulkRestore) {
|
|
1381
|
+
return;
|
|
1382
|
+
}
|
|
1383
|
+
const policy = storage.policy.restore;
|
|
1384
|
+
if (policy === "off") {
|
|
1385
|
+
return;
|
|
1386
|
+
}
|
|
1387
|
+
try {
|
|
1388
|
+
yield this.runBulkRestore(storage, policy);
|
|
1389
|
+
}
|
|
1390
|
+
catch (error) {
|
|
1391
|
+
this.logger(`[agent-serve] session restore failed: ${describeError(error)}`);
|
|
1392
|
+
}
|
|
1393
|
+
});
|
|
1394
|
+
}
|
|
1395
|
+
runBulkRestore(storage, policy) {
|
|
1396
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
1397
|
+
const loaded = yield storage.listSessions();
|
|
1398
|
+
// Guardrails on whatever the sink returned: drop invalid rows and
|
|
1399
|
+
// sessions older than the age window, then restore newest-first under
|
|
1400
|
+
// the count cap. Anything filtered out here stays reachable through
|
|
1401
|
+
// the lazy continuation-lookup path.
|
|
1402
|
+
const cutoff = Date.now() - policy.maxAgeMs;
|
|
1403
|
+
const candidates = loaded
|
|
1404
|
+
.map((record) => ({
|
|
1405
|
+
record,
|
|
1406
|
+
// Numeric timestamp for both the age filter and the sort; a
|
|
1407
|
+
// non-string updatedAt (e.g. a raw DB Date from an untyped sink)
|
|
1408
|
+
// parses to NaN and is dropped instead of crashing serve start.
|
|
1409
|
+
updatedAt: typeof (record === null || record === void 0 ? void 0 : record.updatedAt) === "string"
|
|
1410
|
+
? Date.parse(record.updatedAt)
|
|
1411
|
+
: Number.NaN,
|
|
1412
|
+
}))
|
|
1413
|
+
.filter(({ record, updatedAt }) => typeof (record === null || record === void 0 ? void 0 : record.sessionId) === "string" &&
|
|
1414
|
+
record.sessionId !== "" &&
|
|
1415
|
+
updatedAt >= cutoff)
|
|
1416
|
+
.sort((a, b) => b.updatedAt - a.updatedAt)
|
|
1417
|
+
.slice(0, policy.maxSessions)
|
|
1418
|
+
.map(({ record }) => record);
|
|
1419
|
+
let restored = 0;
|
|
1420
|
+
let budget = policy.maxTotalBytes;
|
|
1421
|
+
// Sink round trips dominate restore latency, so event streams are
|
|
1422
|
+
// fetched with bounded parallelism; writes stay sequential, newest
|
|
1423
|
+
// first, so the byte budget is enforced deterministically.
|
|
1424
|
+
outer: for (let i = 0; i < candidates.length; i += RESTORE_FETCH_CONCURRENCY) {
|
|
1425
|
+
const chunk = candidates.slice(i, i + RESTORE_FETCH_CONCURRENCY);
|
|
1426
|
+
const fetched = yield Promise.all(chunk.map((record) => __awaiter(this, void 0, void 0, function* () {
|
|
1427
|
+
try {
|
|
1428
|
+
// Local state always wins over the sink.
|
|
1429
|
+
if ((yield this.sessions.get(record.sessionId)) !== undefined) {
|
|
1430
|
+
return undefined;
|
|
1431
|
+
}
|
|
1432
|
+
const events = yield storage.listSessionEvents(record.sessionId);
|
|
1433
|
+
return { record, events };
|
|
1434
|
+
}
|
|
1435
|
+
catch (error) {
|
|
1436
|
+
this.logger(`[agent-serve] failed to restore session ${record.sessionId}: ${describeError(error)}`);
|
|
1437
|
+
return undefined;
|
|
1438
|
+
}
|
|
1439
|
+
})));
|
|
1440
|
+
for (const item of fetched) {
|
|
1441
|
+
if (item === undefined) {
|
|
1442
|
+
continue;
|
|
1443
|
+
}
|
|
1444
|
+
const ndjson = eventsNdjson(item.events);
|
|
1445
|
+
// Budget is checked BEFORE anything is written: one oversized
|
|
1446
|
+
// session cannot blow past maxTotalBytes on disk. Skipped sessions
|
|
1447
|
+
// stay reachable through the lazy path.
|
|
1448
|
+
const bytes = Buffer.byteLength(JSON.stringify(item.record), "utf8") +
|
|
1449
|
+
(ndjson === undefined ? 0 : Buffer.byteLength(ndjson, "utf8"));
|
|
1450
|
+
if (bytes > budget) {
|
|
1451
|
+
this.logger(`[agent-serve] session restore stopped at the ${policy.maxTotalBytes}-byte budget after ${restored} session(s); remaining sessions restore lazily on resume`);
|
|
1452
|
+
break outer;
|
|
1453
|
+
}
|
|
1454
|
+
try {
|
|
1455
|
+
yield this.materializeSession(item.record, ndjson);
|
|
1456
|
+
budget -= bytes;
|
|
1457
|
+
restored += 1;
|
|
1458
|
+
}
|
|
1459
|
+
catch (error) {
|
|
1460
|
+
this.logger(`[agent-serve] failed to restore session ${item.record.sessionId}: ${describeError(error)}`);
|
|
1461
|
+
}
|
|
1462
|
+
}
|
|
1463
|
+
}
|
|
1464
|
+
if (restored > 0) {
|
|
1465
|
+
this.logger(`[agent-serve] restored ${restored} session(s) from storage`);
|
|
1466
|
+
}
|
|
1467
|
+
});
|
|
1468
|
+
}
|
|
1469
|
+
/**
|
|
1470
|
+
* Lazy restore: a continuation lookup missed locally, so ask the sink
|
|
1471
|
+
* for that one session and materialize it before resuming. Disk grows
|
|
1472
|
+
* with sessions that are actually resumed, not with history.
|
|
1473
|
+
*
|
|
1474
|
+
* Concurrent misses for the same key (webhook redeliveries, retries)
|
|
1475
|
+
* share one in-flight restore — a second materialization racing the
|
|
1476
|
+
* first resumed turn could truncate events the turn already appended.
|
|
1477
|
+
* Sink errors propagate and fail the send (see
|
|
1478
|
+
* {@link StorageCoordinator.getSessionByContinuation}).
|
|
1479
|
+
*/
|
|
1480
|
+
restoreSessionByContinuation(channelId, continuationKey) {
|
|
1481
|
+
const storage = this.storage;
|
|
1482
|
+
if (storage === undefined) {
|
|
1483
|
+
return Promise.resolve(undefined);
|
|
1484
|
+
}
|
|
1485
|
+
const key = `${channelId}\u0000${continuationKey}`;
|
|
1486
|
+
let pending = this.restoreInFlight.get(key);
|
|
1487
|
+
if (pending === undefined) {
|
|
1488
|
+
pending = this.loadAndMaterializeByContinuation(storage, channelId, continuationKey).finally(() => this.restoreInFlight.delete(key));
|
|
1489
|
+
this.restoreInFlight.set(key, pending);
|
|
1490
|
+
}
|
|
1491
|
+
return pending;
|
|
1492
|
+
}
|
|
1493
|
+
loadAndMaterializeByContinuation(storage, channelId, continuationKey) {
|
|
1494
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
1495
|
+
const record = yield storage.getSessionByContinuation(channelId, continuationKey);
|
|
1496
|
+
if (record === undefined) {
|
|
1497
|
+
// Definitive miss: the caller starts a fresh session under this token.
|
|
1498
|
+
return undefined;
|
|
1499
|
+
}
|
|
1500
|
+
const local = yield this.sessions.get(record.sessionId);
|
|
1501
|
+
if (local !== undefined) {
|
|
1502
|
+
return local;
|
|
1503
|
+
}
|
|
1504
|
+
const events = yield storage.listSessionEvents(record.sessionId);
|
|
1505
|
+
yield this.materializeSession(record, eventsNdjson(events));
|
|
1506
|
+
this.logger(`[agent-serve] lazily restored session ${record.sessionId} from storage`);
|
|
1507
|
+
return record;
|
|
1508
|
+
});
|
|
1509
|
+
}
|
|
1510
|
+
/**
|
|
1511
|
+
* Write one restored session to the local state root. Events land on
|
|
1512
|
+
* disk before the record: a session becomes visible (and addressable via
|
|
1513
|
+
* its continuation key) only with its full stream in place, and the
|
|
1514
|
+
* lazily opened event log hydrates from this file.
|
|
1515
|
+
*/
|
|
1516
|
+
materializeSession(record, eventsNdjson) {
|
|
1517
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
1518
|
+
if (eventsNdjson !== undefined) {
|
|
1519
|
+
const filePath = this.sessions.eventFilePath(record.sessionId);
|
|
1520
|
+
yield mkdir(dirname(filePath), { recursive: true });
|
|
1521
|
+
yield writeFile(filePath, eventsNdjson, "utf8");
|
|
1522
|
+
}
|
|
1523
|
+
yield this.sessions.save(record);
|
|
1524
|
+
});
|
|
1525
|
+
}
|
|
1292
1526
|
trackBackground(promise) {
|
|
1293
1527
|
this.backgroundWork.add(promise);
|
|
1294
1528
|
void promise
|
|
@@ -1300,18 +1534,28 @@ export class SessionEngine {
|
|
|
1300
1534
|
/** Drain running turns, dispatches, and pending writes, then dispose. */
|
|
1301
1535
|
close() {
|
|
1302
1536
|
return __awaiter(this, void 0, void 0, function* () {
|
|
1303
|
-
var _a, _b;
|
|
1537
|
+
var _a, _b, _c;
|
|
1304
1538
|
this.approvals.cancelAll("deny");
|
|
1305
1539
|
yield Promise.allSettled([...this.activeTurns.values()]);
|
|
1306
1540
|
yield Promise.allSettled([...this.backgroundWork]);
|
|
1307
1541
|
yield Promise.allSettled([...this.dispatchChains.values()]);
|
|
1308
1542
|
yield Promise.allSettled([...this.updateChains.values()]);
|
|
1309
1543
|
yield this.logs.flushAll();
|
|
1544
|
+
yield (_a = this.storage) === null || _a === void 0 ? void 0 : _a.close();
|
|
1310
1545
|
yield this.mcpHost.close();
|
|
1311
|
-
yield (
|
|
1546
|
+
yield (_c = (_b = this.runner).dispose) === null || _c === void 0 ? void 0 : _c.call(_b);
|
|
1312
1547
|
});
|
|
1313
1548
|
}
|
|
1314
1549
|
}
|
|
1550
|
+
/** Parallel event-stream loads during the startup bulk restore. */
|
|
1551
|
+
const RESTORE_FETCH_CONCURRENCY = 8;
|
|
1552
|
+
/** NDJSON payload for a restored event stream; undefined when empty. */
|
|
1553
|
+
function eventsNdjson(events) {
|
|
1554
|
+
if (events.length === 0) {
|
|
1555
|
+
return undefined;
|
|
1556
|
+
}
|
|
1557
|
+
return `${events.map((event) => JSON.stringify(event)).join("\n")}\n`;
|
|
1558
|
+
}
|
|
1315
1559
|
function subagentPrompt(subagent) {
|
|
1316
1560
|
var _a;
|
|
1317
1561
|
if (subagent.instructions !== undefined && subagent.instructions !== "") {
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Session list / event fetch for CLI (`sessions`, `session`, chat reattach).
|
|
3
|
+
*
|
|
4
|
+
* Customer-facing errors never include hosting URLs or infra jargon.
|
|
5
|
+
*/
|
|
6
|
+
import type { SessionEvent, SessionSummary } from "../types.js";
|
|
7
|
+
import { type RequestAuth } from "./request-headers.js";
|
|
8
|
+
export declare function listSessions(args: {
|
|
9
|
+
baseUrl: string;
|
|
10
|
+
auth?: RequestAuth;
|
|
11
|
+
fetchImpl?: typeof fetch;
|
|
12
|
+
}): Promise<SessionSummary[]>;
|
|
13
|
+
export declare function fetchSessionEvents(args: {
|
|
14
|
+
baseUrl: string;
|
|
15
|
+
sessionId: string;
|
|
16
|
+
auth?: RequestAuth;
|
|
17
|
+
fetchImpl?: typeof fetch;
|
|
18
|
+
}): Promise<SessionEvent[]>;
|
|
19
|
+
/** Format a sessions table (id, channel, mode, turns, running, updated). */
|
|
20
|
+
export declare function formatSessionsTable(sessions: SessionSummary[]): string;
|
|
21
|
+
//# sourceMappingURL=sessions-client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sessions-client.d.ts","sourceRoot":"","sources":["../../src/internal/sessions-client.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAEhE,OAAO,EAAuB,KAAK,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAE7E,wBAAsB,YAAY,CAAC,IAAI,EAAE;IACvC,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,WAAW,CAAC;IACnB,SAAS,CAAC,EAAE,OAAO,KAAK,CAAC;CAC1B,GAAG,OAAO,CAAC,cAAc,EAAE,CAAC,CA8B5B;AAED,wBAAsB,kBAAkB,CAAC,IAAI,EAAE;IAC7C,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,WAAW,CAAC;IACnB,SAAS,CAAC,EAAE,OAAO,KAAK,CAAC;CAC1B,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC,CAuE1B;AAgCD,4EAA4E;AAC5E,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,cAAc,EAAE,GAAG,MAAM,CActE"}
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Session list / event fetch for CLI (`sessions`, `session`, chat reattach).
|
|
3
|
+
*
|
|
4
|
+
* Customer-facing errors never include hosting URLs or infra jargon.
|
|
5
|
+
*/
|
|
6
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
7
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
8
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
9
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
10
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
11
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
12
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
13
|
+
});
|
|
14
|
+
};
|
|
15
|
+
import { sanitizeCustomerError } from "./logs-client.js";
|
|
16
|
+
import { mergeRequestHeaders } from "./request-headers.js";
|
|
17
|
+
export function listSessions(args) {
|
|
18
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
19
|
+
var _a;
|
|
20
|
+
const baseUrl = args.baseUrl.replace(/\/$/, "");
|
|
21
|
+
const fetchImpl = (_a = args.fetchImpl) !== null && _a !== void 0 ? _a : fetch;
|
|
22
|
+
let resp;
|
|
23
|
+
try {
|
|
24
|
+
resp = yield fetchImpl(`${baseUrl}/v1/sessions`, {
|
|
25
|
+
headers: mergeRequestHeaders(args.auth),
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
catch (error) {
|
|
29
|
+
throw new Error(sanitizeCustomerError(error instanceof Error ? error.message : "Could not list sessions."));
|
|
30
|
+
}
|
|
31
|
+
if (!resp.ok) {
|
|
32
|
+
throw new Error(`Could not list sessions (HTTP ${resp.status}).`);
|
|
33
|
+
}
|
|
34
|
+
const body = (yield resp.json());
|
|
35
|
+
if (!Array.isArray(body.sessions)) {
|
|
36
|
+
return [];
|
|
37
|
+
}
|
|
38
|
+
const out = [];
|
|
39
|
+
for (const row of body.sessions) {
|
|
40
|
+
const parsed = parseSessionSummary(row);
|
|
41
|
+
if (parsed !== undefined) {
|
|
42
|
+
out.push(parsed);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
return out;
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
export function fetchSessionEvents(args) {
|
|
49
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
50
|
+
var _a;
|
|
51
|
+
const baseUrl = args.baseUrl.replace(/\/$/, "");
|
|
52
|
+
const fetchImpl = (_a = args.fetchImpl) !== null && _a !== void 0 ? _a : fetch;
|
|
53
|
+
const path = `/v1/session/${encodeURIComponent(args.sessionId)}/events`;
|
|
54
|
+
try {
|
|
55
|
+
const jsonResp = yield fetchImpl(`${baseUrl}${path}?format=json`, {
|
|
56
|
+
headers: mergeRequestHeaders(args.auth),
|
|
57
|
+
});
|
|
58
|
+
if (jsonResp.ok) {
|
|
59
|
+
const body = (yield jsonResp.json());
|
|
60
|
+
if (Array.isArray(body.events)) {
|
|
61
|
+
return body.events;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
else if (jsonResp.status === 404) {
|
|
65
|
+
throw new Error(`Session ${args.sessionId} not found.`);
|
|
66
|
+
}
|
|
67
|
+
else if (jsonResp.status === 403) {
|
|
68
|
+
throw new Error(`Session ${args.sessionId} is not readable by this caller.`);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
catch (error) {
|
|
72
|
+
if (error instanceof Error && error.message.startsWith("Session ")) {
|
|
73
|
+
throw error;
|
|
74
|
+
}
|
|
75
|
+
// Fall through to NDJSON.
|
|
76
|
+
}
|
|
77
|
+
try {
|
|
78
|
+
const resp = yield fetchImpl(`${baseUrl}${path}`, {
|
|
79
|
+
headers: mergeRequestHeaders(args.auth),
|
|
80
|
+
});
|
|
81
|
+
if (resp.status === 404) {
|
|
82
|
+
throw new Error(`Session ${args.sessionId} not found.`);
|
|
83
|
+
}
|
|
84
|
+
if (resp.status === 403) {
|
|
85
|
+
throw new Error(`Session ${args.sessionId} is not readable by this caller.`);
|
|
86
|
+
}
|
|
87
|
+
if (!resp.ok) {
|
|
88
|
+
throw new Error(`Could not fetch session events (HTTP ${resp.status}).`);
|
|
89
|
+
}
|
|
90
|
+
const text = yield resp.text();
|
|
91
|
+
const events = [];
|
|
92
|
+
for (const line of text.split("\n")) {
|
|
93
|
+
if (line.trim() === "") {
|
|
94
|
+
continue;
|
|
95
|
+
}
|
|
96
|
+
try {
|
|
97
|
+
events.push(JSON.parse(line));
|
|
98
|
+
}
|
|
99
|
+
catch (_b) {
|
|
100
|
+
// skip malformed lines
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
return events;
|
|
104
|
+
}
|
|
105
|
+
catch (error) {
|
|
106
|
+
if (error instanceof Error && error.message.startsWith("Session ")) {
|
|
107
|
+
throw error;
|
|
108
|
+
}
|
|
109
|
+
if (error instanceof Error && error.message.startsWith("Could not fetch")) {
|
|
110
|
+
throw new Error(sanitizeCustomerError(error.message));
|
|
111
|
+
}
|
|
112
|
+
throw new Error(sanitizeCustomerError(error instanceof Error
|
|
113
|
+
? error.message
|
|
114
|
+
: "Could not fetch session events."));
|
|
115
|
+
}
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
/** Lenient parse so partial stubs / older servers still list by sessionId. */
|
|
119
|
+
function parseSessionSummary(value) {
|
|
120
|
+
if (typeof value !== "object" || value === null) {
|
|
121
|
+
return undefined;
|
|
122
|
+
}
|
|
123
|
+
const row = value;
|
|
124
|
+
if (typeof row.sessionId !== "string" || row.sessionId === "") {
|
|
125
|
+
return undefined;
|
|
126
|
+
}
|
|
127
|
+
const continuationToken = typeof row.continuationToken === "string"
|
|
128
|
+
? row.continuationToken
|
|
129
|
+
: row.continuationToken === null
|
|
130
|
+
? null
|
|
131
|
+
: null;
|
|
132
|
+
return {
|
|
133
|
+
sessionId: row.sessionId,
|
|
134
|
+
channelId: typeof row.channelId === "string" ? row.channelId : "",
|
|
135
|
+
mode: row.mode === "task" ? "task" : "chat",
|
|
136
|
+
title: typeof row.title === "string" ? row.title : undefined,
|
|
137
|
+
turnCount: typeof row.turnCount === "number" ? row.turnCount : 0,
|
|
138
|
+
running: row.running === true,
|
|
139
|
+
createdAt: typeof row.createdAt === "string" ? row.createdAt : "",
|
|
140
|
+
updatedAt: typeof row.updatedAt === "string" ? row.updatedAt : "",
|
|
141
|
+
continuationToken,
|
|
142
|
+
externalUrl: typeof row.externalUrl === "string" ? row.externalUrl : undefined,
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
/** Format a sessions table (id, channel, mode, turns, running, updated). */
|
|
146
|
+
export function formatSessionsTable(sessions) {
|
|
147
|
+
if (sessions.length === 0) {
|
|
148
|
+
return "No sessions.\n";
|
|
149
|
+
}
|
|
150
|
+
const header = ["SESSION", "CHANNEL", "MODE", "TURNS", "RUNNING", "UPDATED"];
|
|
151
|
+
const rows = sessions.map((s) => [
|
|
152
|
+
s.sessionId,
|
|
153
|
+
s.channelId,
|
|
154
|
+
s.mode,
|
|
155
|
+
String(s.turnCount),
|
|
156
|
+
s.running ? "yes" : "no",
|
|
157
|
+
s.updatedAt,
|
|
158
|
+
]);
|
|
159
|
+
return `${renderTable(header, rows)}\n`;
|
|
160
|
+
}
|
|
161
|
+
function renderTable(header, rows) {
|
|
162
|
+
const widths = header.map((h, i) => Math.max(h.length, ...rows.map((row) => { var _a; return ((_a = row[i]) !== null && _a !== void 0 ? _a : "").length; })));
|
|
163
|
+
const renderRow = (row) => row
|
|
164
|
+
.map((cell, i) => { var _a; return cell.padEnd((_a = widths[i]) !== null && _a !== void 0 ? _a : 0); })
|
|
165
|
+
.join(" ")
|
|
166
|
+
.trimEnd();
|
|
167
|
+
return [renderRow(header), ...rows.map(renderRow)].join("\n");
|
|
168
|
+
}
|