@cursor/july 0.1.94 → 0.1.96
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 +3 -4
- package/dist/channels/deployments/types.d.ts +1 -1
- package/dist/channels/deployments/types.d.ts.map +1 -1
- package/dist/channels/deployments/types.js +1 -0
- package/dist/channels/github/github-channel.d.ts.map +1 -1
- package/dist/channels/github/github-channel.js +14 -2
- package/dist/channels/github/types.d.ts +18 -3
- package/dist/channels/github/types.d.ts.map +1 -1
- package/dist/channels/origin/api.d.ts +59 -13
- package/dist/channels/origin/api.d.ts.map +1 -1
- package/dist/channels/origin/api.js +168 -27
- package/dist/channels/origin/binding.d.ts +2 -2
- package/dist/channels/origin/checks.d.ts +6 -6
- package/dist/channels/origin/checks.js +6 -6
- package/dist/channels/origin/cursor-account.d.ts +5 -3
- package/dist/channels/origin/cursor-account.d.ts.map +1 -1
- package/dist/channels/origin/cursor-account.js +5 -3
- package/dist/channels/origin/origin-channel.d.ts.map +1 -1
- package/dist/channels/origin/origin-channel.js +11 -3
- package/dist/channels/origin/origin-webhook.d.ts +11 -1
- package/dist/channels/origin/origin-webhook.d.ts.map +1 -1
- package/dist/channels/origin/origin-webhook.js +23 -3
- package/dist/channels/origin/types.d.ts +8 -0
- package/dist/channels/origin/types.d.ts.map +1 -1
- package/dist/channels/slack/api.d.ts +9 -0
- package/dist/channels/slack/api.d.ts.map +1 -1
- package/dist/channels/slack/api.js +36 -5
- package/dist/channels/slack/defaults.d.ts.map +1 -1
- package/dist/channels/slack/defaults.js +17 -46
- package/dist/channels/slack/dispatch.d.ts +7 -1
- package/dist/channels/slack/dispatch.d.ts.map +1 -1
- package/dist/channels/slack/dispatch.js +47 -23
- package/dist/channels/slack/inbound.d.ts +8 -0
- package/dist/channels/slack/inbound.d.ts.map +1 -1
- package/dist/channels/slack/inbound.js +32 -0
- package/dist/channels/slack/live-delivery.d.ts +26 -29
- package/dist/channels/slack/live-delivery.d.ts.map +1 -1
- package/dist/channels/slack/live-delivery.js +172 -73
- package/dist/channels/slack/manifest.d.ts.map +1 -1
- package/dist/channels/slack/manifest.js +5 -1
- package/dist/channels/slack/nudge-carrier.d.ts +2 -0
- package/dist/channels/slack/nudge-carrier.d.ts.map +1 -1
- package/dist/channels/slack/nudge-carrier.js +48 -1
- package/dist/channels/slack/pr-ref.d.ts +7 -1
- package/dist/channels/slack/pr-ref.d.ts.map +1 -1
- package/dist/channels/slack/pr-ref.js +42 -23
- package/dist/channels/slack/slack-channel.d.ts.map +1 -1
- package/dist/channels/slack/slack-channel.js +2 -2
- package/dist/docs/404.html +2 -2
- package/dist/docs/ab.html +4 -4
- package/dist/docs/assets/{app.CFDEas4I.js → app.jXleCmOc.js} +1 -1
- package/dist/docs/assets/chunks/@localSearchIndexroot.DFoGuETX.js +1 -0
- package/dist/docs/assets/chunks/{VPLocalSearchBox.B1IIYpYS.js → VPLocalSearchBox.8LhyglIT.js} +1 -1
- package/dist/docs/assets/chunks/{theme.Ct4NSiLm.js → theme.9ged-pr2.js} +2 -2
- package/dist/docs/assets/index.md.CI93Ltlb.js +5 -0
- package/dist/docs/assets/{index.md.DRakGHFe.lean.js → index.md.CI93Ltlb.lean.js} +1 -1
- package/dist/docs/assets/{reference_cli.md.Cw6_ICYG.js → reference_cli.md.CCnG-nJx.js} +4 -2
- package/dist/docs/assets/{reference_cli.md.Cw6_ICYG.lean.js → reference_cli.md.CCnG-nJx.lean.js} +1 -1
- package/dist/docs/assets/{reference_skills.md.8son6Hjm.js → reference_skills.md.BFW9retM.js} +3 -3
- package/dist/docs/assets/{templates_agentic-owners.md.DqtPdm6f.js → templates_agentic-owners.md.BZSH4N9z.js} +1 -1
- package/dist/docs/assets/templates_code-wiki.md.CDYZIBFN.js +2 -0
- package/dist/docs/assets/templates_code-wiki.md.CDYZIBFN.lean.js +1 -0
- package/dist/docs/assets/{templates_demo.md.DhFcWN6j.js → templates_demo.md.BeQX9V3H.js} +1 -1
- package/dist/docs/assets/{templates_pr-autofixer.md.DU7dQpor.js → templates_pr-autofixer.md.x5zl6-GT.js} +2 -2
- package/dist/docs/assets/{templates_pr-autofixer.md.DU7dQpor.lean.js → templates_pr-autofixer.md.x5zl6-GT.lean.js} +1 -1
- package/dist/docs/assets/templates_security-help.md.C3Ny_Qr2.js +4 -0
- package/dist/docs/assets/templates_security-help.md.C3Ny_Qr2.lean.js +1 -0
- package/dist/docs/assets/{templates_security-reviewer.md.CTa7u_l1.js → templates_security-reviewer.md.lshxbCLK.js} +2 -2
- package/dist/docs/assets/{templates_security-reviewer.md.CTa7u_l1.lean.js → templates_security-reviewer.md.lshxbCLK.lean.js} +1 -1
- package/dist/docs/assets/{templates_triage.md.CVlpctKS.js → templates_triage.md.Co4UNzkZ.js} +3 -3
- package/dist/docs/assets/{templates_triage.md.CVlpctKS.lean.js → templates_triage.md.Co4UNzkZ.lean.js} +1 -1
- 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/evals.html +4 -4
- package/dist/docs/guides/agent-to-agent.html +4 -4
- package/dist/docs/guides/cloud-runtime.html +4 -4
- package/dist/docs/guides/convert-automation.html +4 -4
- package/dist/docs/guides/github.html +4 -4
- 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 +4 -4
- 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 +5 -1
- package/dist/docs/llms-full.txt +189 -26
- package/dist/docs/llms.txt +2 -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 +4 -4
- package/dist/docs/reference/cli.html +8 -6
- package/dist/docs/reference/cli.md +4 -1
- package/dist/docs/reference/connections.html +4 -4
- 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/schedules.html +4 -4
- package/dist/docs/reference/sessions.html +4 -4
- package/dist/docs/reference/skills.html +7 -7
- 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/storage.html +4 -4
- package/dist/docs/templates/agentic-owners.html +7 -7
- package/dist/docs/templates/agentic-owners.md +1 -1
- package/dist/docs/templates/code-wiki.html +28 -0
- package/dist/docs/templates/code-wiki.md +91 -0
- package/dist/docs/templates/demo.html +6 -6
- package/dist/docs/templates/demo.md +3 -2
- package/dist/docs/templates/pr-autofixer.html +6 -6
- package/dist/docs/templates/pr-autofixer.md +7 -13
- package/dist/docs/templates/security-help.html +30 -0
- package/dist/docs/templates/security-help.md +65 -0
- package/dist/docs/templates/security-reviewer.html +6 -6
- package/dist/docs/templates/security-reviewer.md +1 -2
- package/dist/docs/templates/triage.html +7 -7
- package/dist/docs/templates/triage.md +2 -6
- package/dist/docs/troubleshooting.html +4 -4
- package/dist/files-backends/cursor-hosted.d.ts +26 -0
- package/dist/files-backends/cursor-hosted.d.ts.map +1 -1
- package/dist/files-backends/cursor-hosted.js +32 -4
- package/dist/files.d.ts +2 -0
- package/dist/files.d.ts.map +1 -1
- package/dist/files.js +5 -0
- package/dist/internal/advertise-tools.d.ts +2 -0
- package/dist/internal/advertise-tools.d.ts.map +1 -1
- package/dist/internal/advertise-tools.js +15 -1
- package/dist/internal/bounded.d.ts +7 -0
- package/dist/internal/bounded.d.ts.map +1 -0
- package/dist/internal/bounded.js +32 -0
- package/dist/internal/cli-deploy.d.ts.map +1 -1
- package/dist/internal/cli-deploy.js +142 -7
- package/dist/internal/conversation-mirror.d.ts +85 -0
- package/dist/internal/conversation-mirror.d.ts.map +1 -0
- package/dist/internal/conversation-mirror.js +312 -0
- package/dist/internal/cursor/backend-client.d.ts.map +1 -1
- package/dist/internal/cursor/backend-client.js +22 -48
- package/dist/internal/cursor/session-token.d.ts +45 -0
- package/dist/internal/cursor/session-token.d.ts.map +1 -0
- package/dist/internal/cursor/session-token.js +99 -0
- 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/deferred-channel-session.d.ts +20 -0
- package/dist/internal/deferred-channel-session.d.ts.map +1 -0
- package/dist/internal/deferred-channel-session.js +62 -0
- package/dist/internal/deploy-client.d.ts +13 -1
- package/dist/internal/deploy-client.d.ts.map +1 -1
- package/dist/internal/deploy-client.js +11 -1
- package/dist/internal/deploy-manifest.d.ts.map +1 -1
- package/dist/internal/deploy-manifest.js +11 -5
- package/dist/internal/discovery.d.ts.map +1 -1
- package/dist/internal/discovery.js +22 -2
- package/dist/internal/framework-file-storage.d.ts +61 -0
- package/dist/internal/framework-file-storage.d.ts.map +1 -0
- package/dist/internal/framework-file-storage.js +204 -0
- package/dist/internal/framework-storage-selection.d.ts +38 -16
- package/dist/internal/framework-storage-selection.d.ts.map +1 -1
- package/dist/internal/framework-storage-selection.js +78 -17
- package/dist/internal/hosted-admission-context.d.ts +20 -0
- package/dist/internal/hosted-admission-context.d.ts.map +1 -0
- package/dist/internal/hosted-admission-context.js +31 -0
- package/dist/internal/hosted-delivery-protocol.d.ts +5 -0
- package/dist/internal/hosted-delivery-protocol.d.ts.map +1 -1
- package/dist/internal/hosted-delivery-protocol.js +33 -1
- package/dist/internal/hosted-delivery.d.ts +11 -2
- package/dist/internal/hosted-delivery.d.ts.map +1 -1
- package/dist/internal/hosted-delivery.js +79 -35
- package/dist/internal/hosted-managed-automation.d.ts +30 -0
- package/dist/internal/hosted-managed-automation.d.ts.map +1 -0
- package/dist/internal/hosted-managed-automation.js +58 -0
- package/dist/internal/init-project.d.ts.map +1 -1
- package/dist/internal/init-project.js +2 -0
- package/dist/internal/install-cursor-skills.d.ts.map +1 -1
- package/dist/internal/install-cursor-skills.js +1 -3
- package/dist/internal/managed-delivery.d.ts +80 -0
- package/dist/internal/managed-delivery.d.ts.map +1 -0
- package/dist/internal/managed-delivery.js +86 -0
- package/dist/internal/review-comments.d.ts.map +1 -1
- package/dist/internal/review-comments.js +10 -98
- package/dist/internal/runtime-dispatch-runner.d.ts +5 -1
- package/dist/internal/runtime-dispatch-runner.d.ts.map +1 -1
- package/dist/internal/runtime-dispatch-runner.js +7 -0
- package/dist/internal/scm/pr-url.d.ts +14 -0
- package/dist/internal/scm/pr-url.d.ts.map +1 -0
- package/dist/internal/scm/pr-url.js +65 -0
- package/dist/internal/sdk-runner.d.ts +25 -0
- package/dist/internal/sdk-runner.d.ts.map +1 -1
- package/dist/internal/sdk-runner.js +70 -0
- package/dist/internal/server.d.ts.map +1 -1
- package/dist/internal/server.js +11 -2
- package/dist/internal/session-engine.d.ts +13 -0
- package/dist/internal/session-engine.d.ts.map +1 -1
- package/dist/internal/session-engine.js +71 -3
- package/dist/internal/steering.d.ts +15 -0
- package/dist/internal/steering.d.ts.map +1 -0
- package/dist/internal/steering.js +18 -0
- package/dist/playground/assets/index-B1DDvBeC.css +1 -0
- package/dist/playground/assets/{index-B3JCyigB.js → index-Cx9CclK_.js} +47 -47
- package/dist/playground/index.html +2 -2
- package/dist/storage-backends/cursor-hosted.d.ts +8 -0
- package/dist/storage-backends/cursor-hosted.d.ts.map +1 -1
- package/dist/storage-backends/cursor-hosted.js +4 -3
- package/dist/types.d.ts +2 -1
- package/dist/types.d.ts.map +1 -1
- package/docs/README.md +5 -1
- package/docs/reference/cli.md +4 -1
- package/docs/templates/agentic-owners.md +1 -1
- package/docs/templates/code-wiki.md +96 -0
- package/docs/templates/demo.md +3 -2
- package/docs/templates/pr-autofixer.md +7 -13
- package/docs/templates/security-help.md +70 -0
- package/docs/templates/security-reviewer.md +1 -2
- package/docs/templates/triage.md +2 -6
- package/package.json +2 -2
- package/skills/ab/SKILL.md +13 -97
- package/skills/create-agent/SKILL.md +123 -223
- package/skills/debug/SKILL.md +34 -68
- package/skills/evals/SKILL.md +55 -180
- package/skills/framework-map/SKILL.md +83 -145
- package/skills/github/SKILL.md +53 -111
- package/skills/hillclimb/SKILL.md +40 -163
- package/skills/mcp-auth/SKILL.md +48 -107
- package/skills/otel/SKILL.md +22 -68
- package/skills/setup-slack/SKILL.md +77 -208
- package/src/channels/deployments/types.ts +1 -0
- package/src/channels/github/github-channel.ts +23 -8
- package/src/channels/github/types.ts +19 -2
- package/src/channels/origin/api.ts +242 -30
- package/src/channels/origin/binding.ts +2 -2
- package/src/channels/origin/checks.ts +6 -6
- package/src/channels/origin/cursor-account.ts +5 -3
- package/src/channels/origin/origin-channel.ts +13 -1
- package/src/channels/origin/origin-webhook.ts +27 -3
- package/src/channels/origin/types.ts +8 -0
- package/src/channels/slack/api.ts +41 -5
- package/src/channels/slack/defaults.ts +15 -49
- package/src/channels/slack/dispatch.ts +56 -22
- package/src/channels/slack/inbound.ts +43 -0
- package/src/channels/slack/live-delivery.ts +235 -114
- package/src/channels/slack/manifest.ts +5 -1
- package/src/channels/slack/nudge-carrier.ts +48 -1
- package/src/channels/slack/pr-ref.ts +56 -25
- package/src/channels/slack/slack-channel.ts +2 -0
- package/src/files-backends/cursor-hosted.ts +41 -2
- package/src/files.ts +11 -0
- package/src/internal/advertise-tools.ts +18 -2
- package/src/internal/bounded.ts +28 -0
- package/src/internal/cli-deploy.ts +183 -7
- package/src/internal/conversation-mirror.ts +406 -0
- package/src/internal/cursor/backend-client.ts +34 -58
- package/src/internal/cursor/session-token.ts +115 -0
- package/src/internal/cursor-agent-template.ts +1 -0
- package/src/internal/deferred-channel-session.ts +61 -0
- package/src/internal/deploy-client.ts +24 -1
- package/src/internal/deploy-manifest.ts +10 -5
- package/src/internal/discovery.ts +25 -2
- package/src/internal/framework-file-storage.ts +222 -0
- package/src/internal/framework-storage-selection.ts +101 -19
- package/src/internal/hosted-admission-context.ts +37 -0
- package/src/internal/hosted-delivery-protocol.ts +44 -1
- package/src/internal/hosted-delivery.ts +105 -40
- package/src/internal/hosted-managed-automation.ts +72 -0
- package/src/internal/init-project.ts +2 -0
- package/src/internal/install-cursor-skills.ts +1 -4
- package/src/internal/managed-delivery.ts +125 -0
- package/src/internal/review-comments.ts +10 -113
- package/src/internal/runtime-dispatch-runner.ts +10 -0
- package/src/internal/scm/pr-url.ts +95 -0
- package/src/internal/sdk-runner.ts +103 -0
- package/src/internal/server.ts +12 -0
- package/src/internal/session-engine.ts +76 -4
- package/src/internal/steering.ts +17 -0
- package/src/storage-backends/cursor-hosted.ts +10 -1
- package/src/types.ts +2 -1
- package/templates/agentic-owners/README.md +1 -1
- package/templates/agentic-owners/agent/agent.ts +0 -10
- package/templates/agentic-owners/agent/channels/github.ts +5 -14
- package/templates/agentic-owners/agent/lib/config.ts +0 -8
- package/templates/agentic-owners/agent/lib/review.ts +2 -15
- package/templates/agentic-owners/agent/tools/record_review.ts +2 -4
- package/templates/code-wiki/README.md +34 -0
- package/templates/code-wiki/agent/agent.ts +8 -0
- package/templates/code-wiki/agent/channels/github.ts +144 -0
- package/templates/code-wiki/agent/instructions.md +39 -0
- package/templates/code-wiki/agent/lib/repos.ts +5 -0
- package/templates/code-wiki/agent/lib/wiki.ts +22 -0
- package/templates/code-wiki/agent/tools/apply_wiki.ts +219 -0
- package/templates/code-wiki/evals/evals.config.ts +5 -0
- package/templates/code-wiki/evals/wiki.eval.ts +132 -0
- package/templates/code-wiki/init.json +25 -0
- package/templates/code-wiki/package.json +18 -0
- package/templates/code-wiki/tsconfig.json +12 -0
- package/templates/demo/agent/agent.ts +0 -10
- package/templates/pr-autofixer/README.md +0 -2
- package/templates/pr-autofixer/agent/agent.ts +0 -11
- package/templates/pr-autofixer/agent/channels/slack.ts +0 -7
- package/templates/pr-autofixer/agent/lib/pr-state.ts +5 -17
- package/templates/pr-autofixer/agent/lib/repos.ts +0 -1
- package/templates/security-help/README.md +2 -2
- package/templates/security-help/agent/agent.ts +1 -2
- package/templates/security-help/agent/channels/slack.ts +0 -3
- package/templates/security-help/agent/instructions.md +9 -10
- package/templates/security-help/agent/skills/access-request.md +1 -1
- package/templates/security-help/agent/skills/faq.md +31 -0
- package/templates/security-help/agent/skills/security-playbooks.md +1 -1
- package/templates/security-help/package.json +1 -2
- package/templates/security-reviewer/agent/agent.ts +0 -10
- package/templates/triage/agent/agent.ts +0 -10
- package/templates/triage/agent/channels/queue.ts +1 -1
- package/templates/triage/agent/channels/webhook.ts +1 -3
- package/dist/docs/assets/chunks/@localSearchIndexroot.DU3U2Ij2.js +0 -1
- package/dist/docs/assets/index.md.DRakGHFe.js +0 -5
- package/dist/internal/deployment-scm-event-stream.d.ts +0 -116
- package/dist/internal/deployment-scm-event-stream.d.ts.map +0 -1
- package/dist/internal/deployment-scm-event-stream.js +0 -474
- package/dist/playground/assets/index-D9N7-q97.css +0 -1
- package/src/internal/deployment-scm-event-stream.ts +0 -593
- package/templates/security-help/agent/knowledge/faq/approvals.md +0 -5
- package/templates/security-help/agent/knowledge/faq/channels.md +0 -6
- package/templates/security-help/agent/knowledge/faq/phishing.md +0 -10
- package/templates/security-help/agent/skills/security-first-pass.md +0 -15
- /package/dist/docs/assets/{reference_skills.md.8son6Hjm.lean.js → reference_skills.md.BFW9retM.lean.js} +0 -0
- /package/dist/docs/assets/{templates_agentic-owners.md.DqtPdm6f.lean.js → templates_agentic-owners.md.BZSH4N9z.lean.js} +0 -0
- /package/dist/docs/assets/{templates_demo.md.DhFcWN6j.lean.js → templates_demo.md.BeQX9V3H.lean.js} +0 -0
|
@@ -27,7 +27,7 @@ import { authorizeCursorAccountConnectors } from "./cursor-account-mcp-auth.js";
|
|
|
27
27
|
import { readDeployTemplate } from "./cursor-agent-template.js";
|
|
28
28
|
import { AgentServeDeployClient, DeployApiError, deploymentServiceAccountId, slugFromDirectoryName, TERMINAL_AGENTKIT_DEPLOY_STATUSES, TERMINAL_DEPLOY_STATUSES, validateDeploymentSlug, } from "./deploy-client.js";
|
|
29
29
|
import { inferDeployGitSource } from "./deploy-source.js";
|
|
30
|
-
import { isAgentProjectDir, listChildAgentDirs, loadAgentProject, } from "./discovery.js";
|
|
30
|
+
import { formatDiagnostics, hasErrorDiagnostics, isAgentProjectDir, listChildAgentDirs, loadAgentProject, } from "./discovery.js";
|
|
31
31
|
import { CLI_COMMAND_NAME as CLI } from "./distribution.js";
|
|
32
32
|
import { isReservedSecretName, isValidCursorEventRepo, validateSettableSecretName, } from "./hosting.js";
|
|
33
33
|
import { deployProgressLabel, sanitizeCustomerError } from "./logs-client.js";
|
|
@@ -139,18 +139,34 @@ export function cmdDeploy(options) {
|
|
|
139
139
|
if (typeof targets === "number") {
|
|
140
140
|
return targets;
|
|
141
141
|
}
|
|
142
|
+
if (targets.length === 1) {
|
|
143
|
+
return deployOne(ctx, options, targets[0]);
|
|
144
|
+
}
|
|
145
|
+
// Multi-agent parent: when every child declares `architecture: "v2"`,
|
|
146
|
+
// the v2 control plane models sibling agents as release components of
|
|
147
|
+
// ONE application, so deploy them together (one app, one component per
|
|
148
|
+
// child) instead of minting a separate application per child. Mixed and
|
|
149
|
+
// v1 parents keep the per-child sequential deploys.
|
|
150
|
+
const manifests = [];
|
|
151
|
+
for (const target of targets) {
|
|
152
|
+
manifests.push(yield readDeployManifest(target.dir));
|
|
153
|
+
}
|
|
154
|
+
if (manifests.every((manifest) => manifest.architecture === "v2")) {
|
|
155
|
+
return deployAgentsdkApplication(ctx, options, targets);
|
|
156
|
+
}
|
|
157
|
+
if (!ctx.json &&
|
|
158
|
+
manifests.some((manifest) => manifest.architecture === "v2")) {
|
|
159
|
+
ctx.err(`warning: agents under this parent mix architectures; deploying each separately (v2 children become standalone single-component applications).\n`);
|
|
160
|
+
}
|
|
142
161
|
// --path is per-agent (relative to the repo root). When deploying several
|
|
143
162
|
// agents, ignore a shared --path so each target can infer its own path.
|
|
144
163
|
let deployOptions = options;
|
|
145
|
-
if (
|
|
164
|
+
if (options.path !== undefined) {
|
|
146
165
|
if (!ctx.json) {
|
|
147
166
|
ctx.err(`warning: ignoring --path ${JSON.stringify(options.path)} for a multi-agent deploy; each agent infers its own path from git.\n`);
|
|
148
167
|
}
|
|
149
168
|
deployOptions = Object.assign(Object.assign({}, options), { path: undefined });
|
|
150
169
|
}
|
|
151
|
-
if (targets.length === 1) {
|
|
152
|
-
return deployOne(ctx, deployOptions, targets[0]);
|
|
153
|
-
}
|
|
154
170
|
// Multi-agent batch: deploy sequentially; --json emits an array.
|
|
155
171
|
const jsonResults = [];
|
|
156
172
|
let failures = 0;
|
|
@@ -295,6 +311,16 @@ function resolveDeployTargets(options, ctx) {
|
|
|
295
311
|
}
|
|
296
312
|
return [match];
|
|
297
313
|
}
|
|
314
|
+
// An all-v2 parent deploys as ONE application (siblings are components
|
|
315
|
+
// of a single app on the v2 control plane), so "deploy the parent" is
|
|
316
|
+
// unambiguous and needs no picker or --all. A child that is v1 — or
|
|
317
|
+
// fails to load — keeps the interactive picker below.
|
|
318
|
+
if (yield allChildrenAreV2(children)) {
|
|
319
|
+
if (!ctx.json) {
|
|
320
|
+
ctx.err(`Deploying all ${children.length} v2 agents under ${basename(dir)} as one application (pass --slug <name> to deploy a single agent standalone).\n`);
|
|
321
|
+
}
|
|
322
|
+
return [...children];
|
|
323
|
+
}
|
|
298
324
|
const chooser = (_b = options.chooseTargets) !== null && _b !== void 0 ? _b : ((agents) => { var _a, _b; return promptChooseDeployTargets(agents, {
|
|
299
325
|
err: ctx.err,
|
|
300
326
|
stdin: (_a = options.stdin) !== null && _a !== void 0 ? _a : process.stdin,
|
|
@@ -319,6 +345,27 @@ function resolveDeployTargets(options, ctx) {
|
|
|
319
345
|
function formatAgentList(agents) {
|
|
320
346
|
return agents.map((agent, i) => ` ${i + 1}) ${agent.slug}\n`).join("");
|
|
321
347
|
}
|
|
348
|
+
/**
|
|
349
|
+
* True when every child agent project loads and declares
|
|
350
|
+
* `architecture: "v2"`. Broken projects count as not-v2 so target
|
|
351
|
+
* resolution falls back to the picker instead of failing the whole deploy
|
|
352
|
+
* on a child the user might not even select.
|
|
353
|
+
*/
|
|
354
|
+
function allChildrenAreV2(children) {
|
|
355
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
356
|
+
for (const child of children) {
|
|
357
|
+
try {
|
|
358
|
+
if ((yield readDeployManifest(child.dir)).architecture !== "v2") {
|
|
359
|
+
return false;
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
catch (_a) {
|
|
363
|
+
return false;
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
return true;
|
|
367
|
+
});
|
|
368
|
+
}
|
|
322
369
|
/**
|
|
323
370
|
* TTY picker for multi-agent parents. Non-interactive callers get `[]`
|
|
324
371
|
* so {@link resolveDeployTargets} can print the --slug/--all hint.
|
|
@@ -526,6 +573,76 @@ function deployOne(ctx, options, target, extras) {
|
|
|
526
573
|
return 0;
|
|
527
574
|
});
|
|
528
575
|
}
|
|
576
|
+
/**
|
|
577
|
+
* Multi-agent parent whose children all declare `architecture: "v2"`:
|
|
578
|
+
* deploy ONE application whose release carries a component per child. The
|
|
579
|
+
* application slug derives from the parent directory name; each component
|
|
580
|
+
* key is the child's slug and its path is the child directory relative to
|
|
581
|
+
* the repo root (a shared --path names the parent's directory in the repo).
|
|
582
|
+
*/
|
|
583
|
+
function deployAgentsdkApplication(ctx, options, targets) {
|
|
584
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
585
|
+
var _a, _b, _c, _d, _e;
|
|
586
|
+
const parentDir = resolve((_a = options.dir) !== null && _a !== void 0 ? _a : ".");
|
|
587
|
+
const slug = slugFromDirectoryName(basename(parentDir));
|
|
588
|
+
if (slug === undefined) {
|
|
589
|
+
ctx.err(`Could not derive an application slug from the parent directory name ${JSON.stringify(basename(parentDir))} — rename it (deploy slugs use lowercase letters, digits, '-' or '_').\n`);
|
|
590
|
+
return 1;
|
|
591
|
+
}
|
|
592
|
+
const needsGitInference = options.repo === undefined ||
|
|
593
|
+
options.ref === undefined ||
|
|
594
|
+
options.path === undefined;
|
|
595
|
+
const inferred = needsGitInference
|
|
596
|
+
? yield inferDeployGitSource(parentDir, Object.assign({}, (options.git === undefined ? {} : { git: options.git })))
|
|
597
|
+
: {};
|
|
598
|
+
const gitRepoUrl = (_b = options.repo) !== null && _b !== void 0 ? _b : inferred.gitRepoUrl;
|
|
599
|
+
const gitRef = (_c = options.ref) !== null && _c !== void 0 ? _c : inferred.gitRef;
|
|
600
|
+
const parentPath = (_d = options.path) !== null && _d !== void 0 ? _d : inferred.agentPath;
|
|
601
|
+
if (gitRepoUrl !== undefined && !gitRepoUrl.startsWith("https://")) {
|
|
602
|
+
ctx.err(`Invalid --repo: ${gitRepoUrl} (expected an https:// git repository URL)\n`);
|
|
603
|
+
return 1;
|
|
604
|
+
}
|
|
605
|
+
if (gitRepoUrl === undefined) {
|
|
606
|
+
ctx.err(`Could not resolve an https:// git repository URL for this deploy.\n` +
|
|
607
|
+
` Pass --repo https://github.com/<owner>/<repo> (inferred from origin when possible).\n`);
|
|
608
|
+
return 1;
|
|
609
|
+
}
|
|
610
|
+
for (const repo of (_e = options.cursorEventsRepos) !== null && _e !== void 0 ? _e : []) {
|
|
611
|
+
if (!isValidCursorEventRepo(repo)) {
|
|
612
|
+
ctx.err(`Invalid --cursor-events-repo: ${repo} (expected owner/name)\n`);
|
|
613
|
+
return 1;
|
|
614
|
+
}
|
|
615
|
+
}
|
|
616
|
+
const components = targets.map((target) => ({
|
|
617
|
+
componentKey: target.slug,
|
|
618
|
+
agentPath: [parentPath, basename(target.dir)]
|
|
619
|
+
.filter((part) => part !== undefined && part !== "")
|
|
620
|
+
.join("/"),
|
|
621
|
+
}));
|
|
622
|
+
if (!ctx.json) {
|
|
623
|
+
ctx.err(`Deploying "${slug}" as one v2 application with ${targets.length} components (slug from the parent directory name).\n` +
|
|
624
|
+
` architecture: v2\n` +
|
|
625
|
+
` source: ${gitRepoUrl}${gitRef === undefined ? "" : ` @ ${gitRef}`}\n` +
|
|
626
|
+
components
|
|
627
|
+
.map((component) => { var _a; return ` component: ${component.componentKey} (${(_a = component.agentPath) !== null && _a !== void 0 ? _a : "."})\n`; })
|
|
628
|
+
.join(""));
|
|
629
|
+
}
|
|
630
|
+
// Components bake sequentially on the control plane, so the default wait
|
|
631
|
+
// budget is per component; otherwise a 2+ component deploy routinely hits
|
|
632
|
+
// the client-side timeout while the server-side deploy is still fine. An
|
|
633
|
+
// explicitly passed timeout always wins.
|
|
634
|
+
const waitCtx = options.timeoutMs === undefined
|
|
635
|
+
? Object.assign(Object.assign({}, ctx), { timeoutMs: ctx.timeoutMs * targets.length }) : ctx;
|
|
636
|
+
return deployOneAgentsdk(waitCtx, undefined, {
|
|
637
|
+
slug,
|
|
638
|
+
gitRepoUrl,
|
|
639
|
+
gitRef,
|
|
640
|
+
agentPath: undefined,
|
|
641
|
+
components,
|
|
642
|
+
repositories: options.cursorEventsRepos,
|
|
643
|
+
});
|
|
644
|
+
});
|
|
645
|
+
}
|
|
529
646
|
/**
|
|
530
647
|
* `architecture: "v2"` deploy: POST `/internal/agentkit/deployments` and
|
|
531
648
|
* poll the matching GET. The v2 accept path starts freeze bake; it does
|
|
@@ -534,6 +651,11 @@ function deployOne(ctx, options, target, extras) {
|
|
|
534
651
|
function deployOneAgentsdk(ctx, extras, args) {
|
|
535
652
|
return __awaiter(this, void 0, void 0, function* () {
|
|
536
653
|
const { slug } = args;
|
|
654
|
+
const componentsLine = args.components === undefined
|
|
655
|
+
? ""
|
|
656
|
+
: ` components: ${args.components
|
|
657
|
+
.map((component) => component.componentKey)
|
|
658
|
+
.join(", ")}\n`;
|
|
537
659
|
let accepted;
|
|
538
660
|
try {
|
|
539
661
|
accepted = yield ctx.client.deployAgentkit({
|
|
@@ -542,6 +664,7 @@ function deployOneAgentsdk(ctx, extras, args) {
|
|
|
542
664
|
gitRepoUrl: args.gitRepoUrl,
|
|
543
665
|
gitRef: args.gitRef,
|
|
544
666
|
agentPath: args.agentPath,
|
|
667
|
+
components: args.components,
|
|
545
668
|
repositories: args.repositories,
|
|
546
669
|
});
|
|
547
670
|
}
|
|
@@ -558,7 +681,8 @@ function deployOneAgentsdk(ctx, extras, args) {
|
|
|
558
681
|
else {
|
|
559
682
|
ctx.out(`Deploy accepted: ${slug} (team ${ctx.teamId}, v2)\n` +
|
|
560
683
|
` application: ${accepted.applicationId}\n` +
|
|
561
|
-
` release: ${accepted.releaseId}\n`
|
|
684
|
+
` release: ${accepted.releaseId}\n` +
|
|
685
|
+
componentsLine);
|
|
562
686
|
}
|
|
563
687
|
return 0;
|
|
564
688
|
}
|
|
@@ -585,7 +709,12 @@ function deployOneAgentsdk(ctx, extras, args) {
|
|
|
585
709
|
` status: running\n` +
|
|
586
710
|
` architecture: v2\n` +
|
|
587
711
|
` application: ${detail.applicationId}\n` +
|
|
588
|
-
` release: ${detail.releaseId}\n`
|
|
712
|
+
` release: ${detail.releaseId}\n` +
|
|
713
|
+
(args.components === undefined
|
|
714
|
+
? ""
|
|
715
|
+
: ` components: ${args.components
|
|
716
|
+
.map((component) => component.componentKey)
|
|
717
|
+
.join(", ")}\n`));
|
|
589
718
|
return 0;
|
|
590
719
|
});
|
|
591
720
|
}
|
|
@@ -661,6 +790,12 @@ function readDeployManifest(dir) {
|
|
|
661
790
|
return __awaiter(this, void 0, void 0, function* () {
|
|
662
791
|
var _a;
|
|
663
792
|
const project = yield loadAgentProject(dir);
|
|
793
|
+
// Fail here, before anything is dispatched: a project with error
|
|
794
|
+
// diagnostics (e.g. agent/storage.ts on architecture v2) would only be
|
|
795
|
+
// refused later by `serve` inside the hosted build, wasting a bake.
|
|
796
|
+
if (hasErrorDiagnostics(project)) {
|
|
797
|
+
throw new Error(`Refusing to deploy ${project.name} — it has errors:\n${formatDiagnostics(project.diagnostics.filter((d) => d.severity === "error"))}`);
|
|
798
|
+
}
|
|
664
799
|
return {
|
|
665
800
|
hosting: project.agent.hosting,
|
|
666
801
|
architecture: project.agent.architecture,
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Durable mirror for the SDK runner's conversation store.
|
|
3
|
+
*
|
|
4
|
+
* The Cursor SDK keeps each local conversation in SQLite under the engine's
|
|
5
|
+
* state root (`runner/index.db` + `runner/agents/agent-<hash>/store.db`).
|
|
6
|
+
* That disk dies with the pod: on architecture v2, session **records** and
|
|
7
|
+
* event chunks survive replacement through the control-plane storage mirror
|
|
8
|
+
* (framework-storage-selection.ts), but the conversation itself was never
|
|
9
|
+
* hydrated anywhere — a replacement pod resumed every thread as a fresh
|
|
10
|
+
* conversation.
|
|
11
|
+
*
|
|
12
|
+
* This module mirrors the conversation through the SDK's own store APIs —
|
|
13
|
+
* the agent document (which carries `sdkMetadata.blobEncryptionKey`, without
|
|
14
|
+
* which the checkpoint blobs cannot be decrypted) plus its content-addressed
|
|
15
|
+
* checkpoint blobs — into the deployment's **framework-level** file store
|
|
16
|
+
* (`AGENT_SERVE_FRAMEWORK_STORE_SOURCE_ID`), alongside session records and
|
|
17
|
+
* transcripts and apart from the author-facing user store. The store is an
|
|
18
|
+
* Agent Store reached over `/v0/agent-serve-files` presigned URLs — **not
|
|
19
|
+
* mounted** as a filesystem in the engine VM (the FUSE mount at
|
|
20
|
+
* {@link DEPLOYMENT_STORE_MOUNT_PATH} exists only on cloud-runtime VMs) —
|
|
21
|
+
* so the mirror moves bytes through the {@link FileSink} contract instead.
|
|
22
|
+
*
|
|
23
|
+
* Going through the store APIs rather than copying `store.db` files sidesteps
|
|
24
|
+
* WAL consistency and the shared `index.db` (per-session raw copies would
|
|
25
|
+
* clobber other sessions' rows); checkpoint blobs are content-addressed, so
|
|
26
|
+
* repeat persists upload only what is new.
|
|
27
|
+
*
|
|
28
|
+
* Timing: the runner hydrates before `Agent.resume` (so a follow-up landing
|
|
29
|
+
* on a fresh pod — including a v2 hosted-execution delivery — finds the
|
|
30
|
+
* conversation before the turn runs) and persists after each local turn
|
|
31
|
+
* settles, **awaited**, because a hosted pod can be parked immediately after
|
|
32
|
+
* the execution reply.
|
|
33
|
+
*
|
|
34
|
+
* Run rows and run events are deliberately not mirrored: they are per-pod
|
|
35
|
+
* bookkeeping (turn numbers, stream offsets), and the durable session event
|
|
36
|
+
* stream already lives in the control-plane storage mirror.
|
|
37
|
+
*/
|
|
38
|
+
import type { LocalAgentStore } from "@cursor/sdk";
|
|
39
|
+
import { type FileSink } from "../files.js";
|
|
40
|
+
import type { AgentProject } from "../types.js";
|
|
41
|
+
/**
|
|
42
|
+
* Persist/restore one SDK conversation between a {@link LocalAgentStore} and
|
|
43
|
+
* durable file storage. Implemented by {@link createConversationMirror};
|
|
44
|
+
* consumed by the SDK runner.
|
|
45
|
+
*/
|
|
46
|
+
export interface ConversationMirror {
|
|
47
|
+
/**
|
|
48
|
+
* Restore `sdkAgentId`'s conversation into `store` when the store does not
|
|
49
|
+
* already hold it. Resolves `true` when a conversation was restored,
|
|
50
|
+
* `false` on a definitive miss (never persisted, or already local — the
|
|
51
|
+
* caller falls through to its fresh-conversation path). A sink **failure**
|
|
52
|
+
* propagates: an outage must fail the turn (retryable) rather than
|
|
53
|
+
* silently fork the thread onto a fresh conversation.
|
|
54
|
+
*/
|
|
55
|
+
hydrate(store: LocalAgentStore, sdkAgentId: string): Promise<boolean>;
|
|
56
|
+
/**
|
|
57
|
+
* Mirror `sdkAgentId`'s conversation from `store` to the sink
|
|
58
|
+
* (last write wins). No-op until the conversation has a checkpoint.
|
|
59
|
+
*/
|
|
60
|
+
persist(store: LocalAgentStore, sdkAgentId: string): Promise<void>;
|
|
61
|
+
}
|
|
62
|
+
export interface CreateConversationMirrorOptions {
|
|
63
|
+
sink: FileSink;
|
|
64
|
+
/** Agent name baked into every minted key. */
|
|
65
|
+
agentName: string;
|
|
66
|
+
logger?: (line: string) => void;
|
|
67
|
+
}
|
|
68
|
+
/** Build a {@link ConversationMirror} over a {@link FileSink}. */
|
|
69
|
+
export declare function createConversationMirror(options: CreateConversationMirrorOptions): ConversationMirror;
|
|
70
|
+
/**
|
|
71
|
+
* Whether (and over which sink) this serve process mirrors conversations.
|
|
72
|
+
*
|
|
73
|
+
* Selected for architecture-v2 agents on Cursor-managed hosting — the same
|
|
74
|
+
* generation signal as framework-storage-selection.ts, plus a provisioned
|
|
75
|
+
* **framework-level** file store: conversation state is engine-owned, so it
|
|
76
|
+
* lives with session records and transcripts, never on the author-facing
|
|
77
|
+
* user store. Self-hosted v2 keeps everything on the state root (the
|
|
78
|
+
* operator owns the disk), and v1 keeps today's behavior while it runs.
|
|
79
|
+
*/
|
|
80
|
+
export declare function selectConversationMirror(input: {
|
|
81
|
+
project: AgentProject;
|
|
82
|
+
logger?: (line: string) => void;
|
|
83
|
+
env?: Record<string, string | undefined>;
|
|
84
|
+
}): ConversationMirror | undefined;
|
|
85
|
+
//# sourceMappingURL=conversation-mirror.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"conversation-mirror.d.ts","sourceRoot":"","sources":["../../src/internal/conversation-mirror.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AAEH,OAAO,KAAK,EAAsB,eAAe,EAAE,MAAM,aAAa,CAAC;AACvE,OAAO,EAAkB,KAAK,QAAQ,EAAE,MAAM,aAAa,CAAC;AAK5D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAMhD;;;;GAIG;AACH,MAAM,WAAW,kBAAkB;IACjC;;;;;;;OAOG;IACH,OAAO,CAAC,KAAK,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IACtE;;;OAGG;IACH,OAAO,CAAC,KAAK,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACpE;AAYD,MAAM,WAAW,+BAA+B;IAC9C,IAAI,EAAE,QAAQ,CAAC;IACf,8CAA8C;IAC9C,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;CACjC;AAED,kEAAkE;AAClE,wBAAgB,wBAAwB,CACtC,OAAO,EAAE,+BAA+B,GACvC,kBAAkB,CAqMpB;AA6ED;;;;;;;;;GASG;AACH,wBAAgB,wBAAwB,CAAC,KAAK,EAAE;IAC9C,OAAO,EAAE,YAAY,CAAC;IACtB,MAAM,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAChC,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC;CAC1C,GAAG,kBAAkB,GAAG,SAAS,CAyBjC"}
|
|
@@ -0,0 +1,312 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Durable mirror for the SDK runner's conversation store.
|
|
3
|
+
*
|
|
4
|
+
* The Cursor SDK keeps each local conversation in SQLite under the engine's
|
|
5
|
+
* state root (`runner/index.db` + `runner/agents/agent-<hash>/store.db`).
|
|
6
|
+
* That disk dies with the pod: on architecture v2, session **records** and
|
|
7
|
+
* event chunks survive replacement through the control-plane storage mirror
|
|
8
|
+
* (framework-storage-selection.ts), but the conversation itself was never
|
|
9
|
+
* hydrated anywhere — a replacement pod resumed every thread as a fresh
|
|
10
|
+
* conversation.
|
|
11
|
+
*
|
|
12
|
+
* This module mirrors the conversation through the SDK's own store APIs —
|
|
13
|
+
* the agent document (which carries `sdkMetadata.blobEncryptionKey`, without
|
|
14
|
+
* which the checkpoint blobs cannot be decrypted) plus its content-addressed
|
|
15
|
+
* checkpoint blobs — into the deployment's **framework-level** file store
|
|
16
|
+
* (`AGENT_SERVE_FRAMEWORK_STORE_SOURCE_ID`), alongside session records and
|
|
17
|
+
* transcripts and apart from the author-facing user store. The store is an
|
|
18
|
+
* Agent Store reached over `/v0/agent-serve-files` presigned URLs — **not
|
|
19
|
+
* mounted** as a filesystem in the engine VM (the FUSE mount at
|
|
20
|
+
* {@link DEPLOYMENT_STORE_MOUNT_PATH} exists only on cloud-runtime VMs) —
|
|
21
|
+
* so the mirror moves bytes through the {@link FileSink} contract instead.
|
|
22
|
+
*
|
|
23
|
+
* Going through the store APIs rather than copying `store.db` files sidesteps
|
|
24
|
+
* WAL consistency and the shared `index.db` (per-session raw copies would
|
|
25
|
+
* clobber other sessions' rows); checkpoint blobs are content-addressed, so
|
|
26
|
+
* repeat persists upload only what is new.
|
|
27
|
+
*
|
|
28
|
+
* Timing: the runner hydrates before `Agent.resume` (so a follow-up landing
|
|
29
|
+
* on a fresh pod — including a v2 hosted-execution delivery — finds the
|
|
30
|
+
* conversation before the turn runs) and persists after each local turn
|
|
31
|
+
* settles, **awaited**, because a hosted pod can be parked immediately after
|
|
32
|
+
* the execution reply.
|
|
33
|
+
*
|
|
34
|
+
* Run rows and run events are deliberately not mirrored: they are per-pod
|
|
35
|
+
* bookkeeping (turn numbers, stream offsets), and the durable session event
|
|
36
|
+
* stream already lives in the control-plane storage mirror.
|
|
37
|
+
*/
|
|
38
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
39
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
40
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
41
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
42
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
43
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
44
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
45
|
+
});
|
|
46
|
+
};
|
|
47
|
+
import { agentStoreKeys } from "../files.js";
|
|
48
|
+
import { cursorFrameworkStoreSourceId, cursorHostedFiles, } from "../files-backends/cursor-hosted.js";
|
|
49
|
+
import { mapBounded } from "./bounded.js";
|
|
50
|
+
import { resolveApiKeySync } from "./cursor/credentials.js";
|
|
51
|
+
import { AGENT_SERVE_GENERATION_ENV_VAR } from "./cursor-relay-core.js";
|
|
52
|
+
import { describeError } from "./describe-error.js";
|
|
53
|
+
/** Build a {@link ConversationMirror} over a {@link FileSink}. */
|
|
54
|
+
export function createConversationMirror(options) {
|
|
55
|
+
var _a;
|
|
56
|
+
const { sink, agentName } = options;
|
|
57
|
+
const logger = (_a = options.logger) !== null && _a !== void 0 ? _a : (() => { });
|
|
58
|
+
/**
|
|
59
|
+
* Blob ids known to be in the sink, per SDK agent id (upload dedupe).
|
|
60
|
+
* Bounded oldest-out like the files backend's etag cache: a resident
|
|
61
|
+
* engine touches an unbounded number of conversations over its lifetime,
|
|
62
|
+
* and a miss costs one manifest read, never correctness.
|
|
63
|
+
*/
|
|
64
|
+
const mirrored = new Map();
|
|
65
|
+
const rememberMirrored = (sdkAgentId, blobIds) => {
|
|
66
|
+
if (!mirrored.has(sdkAgentId) &&
|
|
67
|
+
mirrored.size >= MAX_TRACKED_CONVERSATIONS) {
|
|
68
|
+
const oldest = mirrored.keys().next();
|
|
69
|
+
if (!oldest.done) {
|
|
70
|
+
mirrored.delete(oldest.value);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
mirrored.set(sdkAgentId, blobIds);
|
|
74
|
+
};
|
|
75
|
+
/**
|
|
76
|
+
* Per-conversation serialization so a persist cannot interleave with a
|
|
77
|
+
* hydrate (or another persist) for the same conversation. Entries are
|
|
78
|
+
* removed once their chain settles as the tail, so the map tracks only
|
|
79
|
+
* conversations with work in flight.
|
|
80
|
+
*/
|
|
81
|
+
const chains = new Map();
|
|
82
|
+
function serialize(sdkAgentId, run) {
|
|
83
|
+
var _a;
|
|
84
|
+
const previous = (_a = chains.get(sdkAgentId)) !== null && _a !== void 0 ? _a : Promise.resolve();
|
|
85
|
+
const next = previous.then(run, run);
|
|
86
|
+
const stored = next
|
|
87
|
+
.catch(() => { })
|
|
88
|
+
.then(() => {
|
|
89
|
+
if (chains.get(sdkAgentId) === stored) {
|
|
90
|
+
chains.delete(sdkAgentId);
|
|
91
|
+
}
|
|
92
|
+
});
|
|
93
|
+
chains.set(sdkAgentId, stored);
|
|
94
|
+
return next;
|
|
95
|
+
}
|
|
96
|
+
function mirroredBlobIds(sdkAgentId) {
|
|
97
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
98
|
+
const cached = mirrored.get(sdkAgentId);
|
|
99
|
+
if (cached !== undefined) {
|
|
100
|
+
return cached;
|
|
101
|
+
}
|
|
102
|
+
// Seed from the previous manifest so a fresh pod does not re-upload the
|
|
103
|
+
// whole history on its first persist. A miss, an unusable manifest, or
|
|
104
|
+
// a failed read seeds empty — re-uploading is wasteful, never wrong.
|
|
105
|
+
const seeded = new Set();
|
|
106
|
+
try {
|
|
107
|
+
const read = yield readManifest(sink, agentName, sdkAgentId);
|
|
108
|
+
if (read.outcome === "found") {
|
|
109
|
+
for (const blobId of read.manifest.blobIds) {
|
|
110
|
+
seeded.add(blobId);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
catch (error) {
|
|
115
|
+
logger(`[agent-sdk] conversation mirror: could not read the prior manifest for ${sdkAgentId} (${describeError(error)}); re-uploading blobs`);
|
|
116
|
+
}
|
|
117
|
+
rememberMirrored(sdkAgentId, seeded);
|
|
118
|
+
return seeded;
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
return {
|
|
122
|
+
persist(store, sdkAgentId) {
|
|
123
|
+
return serialize(sdkAgentId, () => __awaiter(this, void 0, void 0, function* () {
|
|
124
|
+
const document = yield store.agents.get({ agentId: sdkAgentId });
|
|
125
|
+
if (document === null || document.latestCheckpoint == null) {
|
|
126
|
+
// Nothing restorable yet (no conversation, or no checkpoint).
|
|
127
|
+
return;
|
|
128
|
+
}
|
|
129
|
+
const uploaded = yield mirroredBlobIds(sdkAgentId);
|
|
130
|
+
const blobIds = yield listCheckpointBlobIds(store, sdkAgentId);
|
|
131
|
+
for (const blobId of blobIds) {
|
|
132
|
+
if (uploaded.has(blobId)) {
|
|
133
|
+
continue;
|
|
134
|
+
}
|
|
135
|
+
const bytes = yield store.checkpoints.get({
|
|
136
|
+
agentId: sdkAgentId,
|
|
137
|
+
blobId,
|
|
138
|
+
});
|
|
139
|
+
if (bytes === null) {
|
|
140
|
+
continue;
|
|
141
|
+
}
|
|
142
|
+
yield sink.put(agentStoreKeys.conversationBlob(agentName, sdkAgentId, blobId), bytes);
|
|
143
|
+
// Content-addressed: once in the sink, never re-uploaded.
|
|
144
|
+
uploaded.add(blobId);
|
|
145
|
+
}
|
|
146
|
+
const manifest = {
|
|
147
|
+
v: 1,
|
|
148
|
+
// The referenced run is pod-local bookkeeping and is not mirrored;
|
|
149
|
+
// a hydrated store must not point at a run row it does not hold.
|
|
150
|
+
agent: Object.assign(Object.assign({}, document), { activeRunId: null }),
|
|
151
|
+
blobIds: blobIds.filter((blobId) => uploaded.has(blobId)),
|
|
152
|
+
persistedAtMs: Date.now(),
|
|
153
|
+
};
|
|
154
|
+
// Manifest last: it only ever references blobs already uploaded.
|
|
155
|
+
yield sink.put(agentStoreKeys.conversationManifest(agentName, sdkAgentId), new TextEncoder().encode(JSON.stringify(manifest)));
|
|
156
|
+
}));
|
|
157
|
+
},
|
|
158
|
+
hydrate(store, sdkAgentId) {
|
|
159
|
+
return serialize(sdkAgentId, () => __awaiter(this, void 0, void 0, function* () {
|
|
160
|
+
var _a;
|
|
161
|
+
const existing = yield store.agents.get({ agentId: sdkAgentId });
|
|
162
|
+
if (existing !== null) {
|
|
163
|
+
return false;
|
|
164
|
+
}
|
|
165
|
+
const read = yield readManifest(sink, agentName, sdkAgentId);
|
|
166
|
+
if (read.outcome === "miss") {
|
|
167
|
+
return false;
|
|
168
|
+
}
|
|
169
|
+
if (read.outcome === "unusable") {
|
|
170
|
+
// Definitive, non-transient state (a future manifest version
|
|
171
|
+
// during a rolling redeploy, or corruption): retrying would fail
|
|
172
|
+
// identically forever, so fall through to the caller's
|
|
173
|
+
// fresh-conversation path instead of wedging the session.
|
|
174
|
+
logger(`[agent-sdk] conversation mirror: the manifest for ${sdkAgentId} is unusable (${read.reason}); treating the conversation as unrestorable`);
|
|
175
|
+
return false;
|
|
176
|
+
}
|
|
177
|
+
const manifest = read.manifest;
|
|
178
|
+
const rootBlobId = (_a = manifest.agent.latestCheckpoint) === null || _a === void 0 ? void 0 : _a.rootBlobId;
|
|
179
|
+
if (rootBlobId === undefined ||
|
|
180
|
+
!manifest.blobIds.includes(rootBlobId)) {
|
|
181
|
+
logger(`[agent-sdk] conversation mirror: the manifest for ${sdkAgentId} does not list its root checkpoint blob; treating the conversation as unrestorable`);
|
|
182
|
+
return false;
|
|
183
|
+
}
|
|
184
|
+
// Bounded-parallel downloads: this sits on the resume critical path
|
|
185
|
+
// (a presign plus an object GET per blob against the hosted sink).
|
|
186
|
+
const bodies = yield mapBounded(manifest.blobIds, HYDRATE_DOWNLOAD_CONCURRENCY, (blobId) => __awaiter(this, void 0, void 0, function* () {
|
|
187
|
+
return ({
|
|
188
|
+
blobId,
|
|
189
|
+
body: yield sink.get(agentStoreKeys.conversationBlob(agentName, sdkAgentId, blobId)),
|
|
190
|
+
});
|
|
191
|
+
}));
|
|
192
|
+
const missing = bodies.filter((entry) => entry.body === undefined);
|
|
193
|
+
if (missing.length > 0) {
|
|
194
|
+
// The manifest lists exactly what a previous persist uploaded, so
|
|
195
|
+
// any definitive absence is store loss — and the checkpoint graph
|
|
196
|
+
// may reach any listed blob, not just the root. Restoring a
|
|
197
|
+
// partial graph would create an agent row whose resume succeeds
|
|
198
|
+
// and whose checkpoint walk then fails unrecoverably.
|
|
199
|
+
logger(`[agent-sdk] conversation mirror: ${missing.length} checkpoint blob(s) for ${sdkAgentId} are missing from the sink; treating the conversation as unrestorable`);
|
|
200
|
+
return false;
|
|
201
|
+
}
|
|
202
|
+
const restored = new Set();
|
|
203
|
+
for (const entry of bodies) {
|
|
204
|
+
const body = entry.body;
|
|
205
|
+
const bytes = body instanceof Uint8Array ? body : body.body;
|
|
206
|
+
if ((yield store.checkpoints.get({
|
|
207
|
+
agentId: sdkAgentId,
|
|
208
|
+
blobId: entry.blobId,
|
|
209
|
+
})) === null) {
|
|
210
|
+
yield store.checkpoints.create({
|
|
211
|
+
agentId: sdkAgentId,
|
|
212
|
+
blobId: entry.blobId,
|
|
213
|
+
data: bytes,
|
|
214
|
+
});
|
|
215
|
+
}
|
|
216
|
+
restored.add(entry.blobId);
|
|
217
|
+
}
|
|
218
|
+
yield store.agents.create({
|
|
219
|
+
agent: Object.assign(Object.assign({}, manifest.agent), { activeRunId: null }),
|
|
220
|
+
});
|
|
221
|
+
rememberMirrored(sdkAgentId, restored);
|
|
222
|
+
logger(`[agent-sdk] conversation mirror: restored the conversation for ${sdkAgentId} (${restored.size} checkpoint blob(s))`);
|
|
223
|
+
return true;
|
|
224
|
+
}));
|
|
225
|
+
},
|
|
226
|
+
};
|
|
227
|
+
}
|
|
228
|
+
/** Oldest-out cap on the per-conversation upload-dedupe cache. */
|
|
229
|
+
const MAX_TRACKED_CONVERSATIONS = 1000;
|
|
230
|
+
/** Parallel blob downloads during hydrate (resume critical path). */
|
|
231
|
+
const HYDRATE_DOWNLOAD_CONCURRENCY = 8;
|
|
232
|
+
/**
|
|
233
|
+
* Read the persisted manifest. Sink transport failures propagate (an
|
|
234
|
+
* outage must fail the follow-up, not fork the thread); everything the
|
|
235
|
+
* bytes themselves can be wrong about is reported as `unusable`.
|
|
236
|
+
*/
|
|
237
|
+
function readManifest(sink, agentName, sdkAgentId) {
|
|
238
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
239
|
+
const body = yield sink.get(agentStoreKeys.conversationManifest(agentName, sdkAgentId));
|
|
240
|
+
if (body === undefined) {
|
|
241
|
+
return { outcome: "miss" };
|
|
242
|
+
}
|
|
243
|
+
const bytes = body instanceof Uint8Array ? body : body.body;
|
|
244
|
+
let parsed;
|
|
245
|
+
try {
|
|
246
|
+
parsed = JSON.parse(new TextDecoder().decode(bytes));
|
|
247
|
+
}
|
|
248
|
+
catch (_a) {
|
|
249
|
+
return { outcome: "unusable", reason: "not JSON" };
|
|
250
|
+
}
|
|
251
|
+
if (parsed === null ||
|
|
252
|
+
typeof parsed !== "object" ||
|
|
253
|
+
parsed.v !== 1) {
|
|
254
|
+
return { outcome: "unusable", reason: "unsupported manifest version" };
|
|
255
|
+
}
|
|
256
|
+
const manifest = parsed;
|
|
257
|
+
if (manifest.agent === null ||
|
|
258
|
+
typeof manifest.agent !== "object" ||
|
|
259
|
+
manifest.agent.agentId !== sdkAgentId ||
|
|
260
|
+
!Array.isArray(manifest.blobIds)) {
|
|
261
|
+
return { outcome: "unusable", reason: "malformed manifest" };
|
|
262
|
+
}
|
|
263
|
+
return { outcome: "found", manifest };
|
|
264
|
+
});
|
|
265
|
+
}
|
|
266
|
+
function listCheckpointBlobIds(store, sdkAgentId) {
|
|
267
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
268
|
+
const blobIds = [];
|
|
269
|
+
let cursor;
|
|
270
|
+
do {
|
|
271
|
+
const page = yield store.checkpoints.list({
|
|
272
|
+
filter: { agentIds: [sdkAgentId], cursor },
|
|
273
|
+
});
|
|
274
|
+
blobIds.push(...page.items);
|
|
275
|
+
cursor = page.nextCursor;
|
|
276
|
+
} while (cursor !== undefined);
|
|
277
|
+
return blobIds;
|
|
278
|
+
});
|
|
279
|
+
}
|
|
280
|
+
/**
|
|
281
|
+
* Whether (and over which sink) this serve process mirrors conversations.
|
|
282
|
+
*
|
|
283
|
+
* Selected for architecture-v2 agents on Cursor-managed hosting — the same
|
|
284
|
+
* generation signal as framework-storage-selection.ts, plus a provisioned
|
|
285
|
+
* **framework-level** file store: conversation state is engine-owned, so it
|
|
286
|
+
* lives with session records and transcripts, never on the author-facing
|
|
287
|
+
* user store. Self-hosted v2 keeps everything on the state root (the
|
|
288
|
+
* operator owns the disk), and v1 keeps today's behavior while it runs.
|
|
289
|
+
*/
|
|
290
|
+
export function selectConversationMirror(input) {
|
|
291
|
+
var _a;
|
|
292
|
+
if (input.project.agent.architecture !== "v2") {
|
|
293
|
+
return undefined;
|
|
294
|
+
}
|
|
295
|
+
const env = (_a = input.env) !== null && _a !== void 0 ? _a : process.env;
|
|
296
|
+
const frameworkStoreId = cursorFrameworkStoreSourceId(env);
|
|
297
|
+
if (env[AGENT_SERVE_GENERATION_ENV_VAR] === undefined ||
|
|
298
|
+
frameworkStoreId === undefined) {
|
|
299
|
+
return undefined;
|
|
300
|
+
}
|
|
301
|
+
return createConversationMirror({
|
|
302
|
+
sink: cursorHostedFiles({
|
|
303
|
+
storeSourceId: frameworkStoreId,
|
|
304
|
+
// Full chain (env → key file → stored login): frozen engines listen
|
|
305
|
+
// unsigned and bind CURSOR_API_KEY_FILE at task time, after this sink
|
|
306
|
+
// is constructed.
|
|
307
|
+
resolveApiKey: () => { var _a; return (_a = resolveApiKeySync()) === null || _a === void 0 ? void 0 : _a.apiKey; },
|
|
308
|
+
}),
|
|
309
|
+
agentName: input.project.name,
|
|
310
|
+
logger: input.logger,
|
|
311
|
+
});
|
|
312
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"backend-client.d.ts","sourceRoot":"","sources":["../../../src/internal/cursor/backend-client.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAGH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"backend-client.d.ts","sourceRoot":"","sources":["../../../src/internal/cursor/backend-client.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAGH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AAezD,qBAAa,kBAAmB,SAAQ,KAAK;IAGzC,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM;IACxB,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM;IAHhC,YACE,OAAO,EAAE,MAAM,EACN,MAAM,CAAC,EAAE,MAAM,YAAA,EACf,YAAY,CAAC,EAAE,MAAM,YAAA,EAI/B;CACF;AAMD,QAAA,MAAM,mBAAmB,EAAE,CAAC,CAAC,SAAS,CACpC;IACE,MAAM,EAAE,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;IACnC,KAAK,EAAE,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;IAClC,SAAS,EAAE,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;IACtC,QAAQ,EAAE,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;IACrC,MAAM,EAAE,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;IACnC,QAAQ,EAAE,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;CACtC,EACD,OAAO,CAQP,CAAC;AACH,MAAM,MAAM,cAAc,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,mBAAmB,CAAC,CAAC;AAMjE,MAAM,WAAW,iBAAiB;IAChC,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;CACnB;AAiCD,kEAAkE;AAClE,MAAM,WAAW,kBAAkB;IACjC,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,YAAY,EAAE,OAAO,CAAC;IACtB,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAeD,+EAA+E;AAC/E,MAAM,WAAW,kBAAkB;IACjC,EAAE,EAAE,MAAM,CAAC;IACX,YAAY,EAAE,OAAO,CAAC;IACtB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAeD,MAAM,WAAW,cAAc;IAC7B,wEAAwE;IACxE,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,2EAA2E;IAC3E,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACrC;;;;OAIG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACvC;;;;;OAKG;IACH,WAAW,CAAC,EAAE,kBAAkB,CAAC;CAClC;AAED,MAAM,WAAW,gBAAgB;IAC/B,gBAAgB,EAAE,MAAM,CAAC;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,cAAc,EAAE,CAAC;CACzB;AAgDD,yEAAyE;AACzE,MAAM,WAAW,oBAAoB;IACnC,OAAO,EAAE,KAAK,CACV;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,GAC9B;QAAE,IAAI,EAAE,OAAO,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;KAAE,CACrD,CAAC;IACF,OAAO,EAAE,OAAO,CAAC;IACjB,iBAAiB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAC7C;AAkED,MAAM,WAAW,0BAA0B;IACzC,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;IACf;;;;OAIG;IACH,SAAS,CAAC,EAAE,MAAM,MAAM,CAAC;IACzB,MAAM,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAChC,2CAA2C;IAC3C,SAAS,CAAC,EAAE,OAAO,KAAK,CAAC;CAC1B;AAED,qBAAa,mBAAmB;IAC9B,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;IACpC,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAe;IAC7C,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAyB;IAChD,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAe;IACzC,OAAO,CAAC,KAAK,CAAqD;IAClE,OAAO,CAAC,aAAa,CAA8B;IACnD,OAAO,CAAC,mBAAmB,CAAqB;IAEhD,YAAY,OAAO,EAAE,0BAA0B,EAO9C;IAED,OAAO,CAAC,aAAa;IAIrB,gCAAgC;IAC1B,KAAK,IAAI,OAAO,CAAC,cAAc,CAAC,CAErC;IAED;;;;OAIG;IACG,mBAAmB,CACvB,iBAAiB,EAAE,SAAS,MAAM,EAAE,GACnC,OAAO,CAAC,gBAAgB,EAAE,CAAC,CAsB7B;IAED;;;;OAIG;IACG,qBAAqB,CAAC,IAAI,EAAE;QAChC,gBAAgB,EAAE,MAAM,CAAC;QACzB,QAAQ,EAAE,MAAM,CAAC;QACjB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;KAC/B,GAAG,OAAO,CAAC,oBAAoB,CAAC,CAahC;IAED;;;;OAIG;IACG,sBAAsB,CAAC,OAAO,CAAC,EAAE;QACrC,MAAM,CAAC,EAAE,MAAM,CAAC;KACjB,GAAG,OAAO,CAAC,kBAAkB,EAAE,CAAC,CAahC;IAED;;;;;OAKG;IACG,kBAAkB,CAAC,IAAI,EAAE;QAC7B,SAAS,EAAE,MAAM,EAAE,CAAC;QACpB,gBAAgB,EAAE,MAAM,CAAC;QACzB,gBAAgB,CAAC,EAAE,MAAM,CAAC;KAC3B,GAAG,OAAO,CAAC,kBAAkB,EAAE,CAAC,CAiBhC;IAED,4EAA4E;IACtE,cAAc,CAClB,KAAK,EAAE,SAAS,MAAM,EAAE,EACxB,OAAO,CAAC,EAAE;QAAE,WAAW,CAAC,EAAE,MAAM,GAAG,UAAU,GAAG,gBAAgB,CAAA;KAAE,GACjE,OAAO,CAAC,iBAAiB,CAAC,CAsC5B;YAEa,GAAG;IA+CjB;;;OAGG;IACH,OAAO,CAAC,cAAc;YA4BR,cAAc;CAoC7B;AAED;;;GAGG;AACH,wBAAsB,gCAAgC,CAAC,IAAI,EAAE;IAC3D,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,OAAO,KAAK,CAAC;CAC1B,GAAG,OAAO,CAAC,MAAM,CAAC,CAalB;AAqBD;;;;;;GAMG;AACH,wBAAsB,sBAAsB,CAAC,IAAI,EAAE;IACjD,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,sEAAsE;IACtE,MAAM,EAAE,MAAM,CAAC;IACf,uEAAuE;IACvE,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,OAAO,KAAK,CAAC;CAC1B,GAAG,OAAO,CAAC,IAAI,CAAC,CAmChB"}
|