@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
|
@@ -0,0 +1,395 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Thin client for the Agent Serve deployment management API
|
|
3
|
+
* (`/internal/agent-serve/deployments` on the Cursor backend). Pure
|
|
4
|
+
* request/response + error mapping — no console I/O, no polling loops;
|
|
5
|
+
* rendering lives in `cli-deploy.ts`.
|
|
6
|
+
*
|
|
7
|
+
* Auth is the user API key sent directly as the bearer (the routes are
|
|
8
|
+
* `wrapUserApiRoute` on the backend); there is no token exchange here.
|
|
9
|
+
* The endpoints are gated on the `agent_serve_mvp` Statsig gate and 404
|
|
10
|
+
* when it is off — the error mapping says so instead of "not found".
|
|
11
|
+
*/
|
|
12
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
13
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
14
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
15
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
16
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
17
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
18
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
19
|
+
});
|
|
20
|
+
};
|
|
21
|
+
import { z } from "zod";
|
|
22
|
+
import { MAX_SECRET_VALUE_BYTES, MAX_SECRETS, validateEgressDomain, validateSettableSecretName, } from "./hosting.js";
|
|
23
|
+
export const TERMINAL_DEPLOY_STATUSES = new Set([
|
|
24
|
+
"running",
|
|
25
|
+
"degraded",
|
|
26
|
+
"failed",
|
|
27
|
+
"stopped",
|
|
28
|
+
]);
|
|
29
|
+
const SLUG_PATTERN = /^[a-z0-9_-]{1,64}$/;
|
|
30
|
+
/** Returns a human error message, or undefined when the slug is valid. */
|
|
31
|
+
export function validateDeploymentSlug(slug) {
|
|
32
|
+
if (SLUG_PATTERN.test(slug)) {
|
|
33
|
+
return undefined;
|
|
34
|
+
}
|
|
35
|
+
return `Invalid slug ${JSON.stringify(slug)}: use lowercase letters, digits, '-' or '_' (max 64 chars)`;
|
|
36
|
+
}
|
|
37
|
+
/** Derive a valid slug from a directory name, or undefined if impossible. */
|
|
38
|
+
export function slugFromDirectoryName(name) {
|
|
39
|
+
const slug = name
|
|
40
|
+
.toLowerCase()
|
|
41
|
+
.replace(/[^a-z0-9_-]+/g, "-")
|
|
42
|
+
.replace(/^-+|-+$/g, "")
|
|
43
|
+
.slice(0, 64);
|
|
44
|
+
return SLUG_PATTERN.test(slug) ? slug : undefined;
|
|
45
|
+
}
|
|
46
|
+
export class DeployApiError extends Error {
|
|
47
|
+
constructor(message, status,
|
|
48
|
+
/** Seconds to wait before retrying (from `Retry-After` on 429s). */
|
|
49
|
+
retryAfterSeconds) {
|
|
50
|
+
super(message);
|
|
51
|
+
this.status = status;
|
|
52
|
+
this.retryAfterSeconds = retryAfterSeconds;
|
|
53
|
+
this.name = "DeployApiError";
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
// All response schemas are `.passthrough()`: the backend keeps growing the
|
|
57
|
+
// deployment payload (serviceAccountId, egressAllowedDomains, secret
|
|
58
|
+
// metadata, ...) and unknown fields must flow through untouched — both so
|
|
59
|
+
// parsing never breaks on a newer backend and so `--json` output stays
|
|
60
|
+
// faithful to the API instead of silently dropping fields.
|
|
61
|
+
const deployAcceptedSchema = z
|
|
62
|
+
.object({
|
|
63
|
+
id: z.number(),
|
|
64
|
+
slug: z.string(),
|
|
65
|
+
teamId: z.number(),
|
|
66
|
+
status: z.string(),
|
|
67
|
+
generation: z.number(),
|
|
68
|
+
deploymentKind: z.string(),
|
|
69
|
+
engineAlias: z.string(),
|
|
70
|
+
aliasToken: z.string().optional(),
|
|
71
|
+
})
|
|
72
|
+
.passthrough();
|
|
73
|
+
const deploymentSchema = z.object({
|
|
74
|
+
id: z.number(),
|
|
75
|
+
slug: z.string(),
|
|
76
|
+
teamId: z.number(),
|
|
77
|
+
deploymentKind: z.string(),
|
|
78
|
+
gitRepoUrl: z.string().nullable().optional(),
|
|
79
|
+
gitRef: z.string().optional(),
|
|
80
|
+
agentPath: z.string().optional(),
|
|
81
|
+
desiredState: z.string().optional(),
|
|
82
|
+
status: z.enum([
|
|
83
|
+
"pending",
|
|
84
|
+
"deploying",
|
|
85
|
+
"running",
|
|
86
|
+
"degraded",
|
|
87
|
+
"failed",
|
|
88
|
+
"stopping",
|
|
89
|
+
"stopped",
|
|
90
|
+
]),
|
|
91
|
+
progress: z
|
|
92
|
+
.enum([
|
|
93
|
+
"queued",
|
|
94
|
+
"preparing",
|
|
95
|
+
"building",
|
|
96
|
+
"finalizing",
|
|
97
|
+
"running",
|
|
98
|
+
"failed",
|
|
99
|
+
"stopping",
|
|
100
|
+
"stopped",
|
|
101
|
+
"degraded",
|
|
102
|
+
])
|
|
103
|
+
.optional(),
|
|
104
|
+
generation: z.number(),
|
|
105
|
+
observedGeneration: z.number().nullable().optional(),
|
|
106
|
+
engineGeneration: z.number().nullable().optional(),
|
|
107
|
+
publicId: z.string().optional(),
|
|
108
|
+
engineUrl: z.string().nullable().optional(),
|
|
109
|
+
lastError: z.string().nullable().optional(),
|
|
110
|
+
engineAlias: z.string(),
|
|
111
|
+
desiredUpdatedAt: z.string().optional(),
|
|
112
|
+
lastReconciledAt: z.string().nullable().optional(),
|
|
113
|
+
cursorEventRepos: z.array(z.string()).optional(),
|
|
114
|
+
egressAllowedDomains: z.array(z.string()).optional(),
|
|
115
|
+
// String ids (`sa_…`) in prod; older mocks/fixtures used numbers. Null on
|
|
116
|
+
// legacy rows that predate service-account-backed deploys.
|
|
117
|
+
serviceAccountId: z.union([z.string(), z.number()]).nullable().optional(),
|
|
118
|
+
podCredentialMaskedKey: z.string().nullable().optional(),
|
|
119
|
+
secretNames: z.array(z.string()).optional(),
|
|
120
|
+
});
|
|
121
|
+
const deploymentListItemSchema = deploymentSchema.passthrough();
|
|
122
|
+
const deploymentDetailSchema = deploymentSchema
|
|
123
|
+
.extend({
|
|
124
|
+
engineAccess: z
|
|
125
|
+
.object({
|
|
126
|
+
url: z.string(),
|
|
127
|
+
headers: z.record(z.string()),
|
|
128
|
+
expiresAt: z.string(),
|
|
129
|
+
})
|
|
130
|
+
.nullable()
|
|
131
|
+
.optional(),
|
|
132
|
+
})
|
|
133
|
+
.passthrough();
|
|
134
|
+
const listResponseSchema = z.object({
|
|
135
|
+
deployments: z.array(deploymentListItemSchema),
|
|
136
|
+
});
|
|
137
|
+
const stopAcceptedSchema = z
|
|
138
|
+
.object({
|
|
139
|
+
id: z.number(),
|
|
140
|
+
status: z.string(),
|
|
141
|
+
})
|
|
142
|
+
.passthrough();
|
|
143
|
+
const rotateResponseSchema = z
|
|
144
|
+
.object({
|
|
145
|
+
aliasToken: z.string().min(1),
|
|
146
|
+
})
|
|
147
|
+
.passthrough();
|
|
148
|
+
const rotatePodCredentialResponseSchema = z
|
|
149
|
+
.object({
|
|
150
|
+
podCredentialMaskedKey: z.string().min(1),
|
|
151
|
+
})
|
|
152
|
+
.passthrough();
|
|
153
|
+
const setSecretsResponseSchema = z
|
|
154
|
+
.object({
|
|
155
|
+
secretNames: z.array(z.string()),
|
|
156
|
+
})
|
|
157
|
+
.passthrough();
|
|
158
|
+
const listSecretsResponseSchema = z
|
|
159
|
+
.object({
|
|
160
|
+
secrets: z.array(z.object({ name: z.string(), createdAt: z.string() }).passthrough()),
|
|
161
|
+
})
|
|
162
|
+
.passthrough();
|
|
163
|
+
export class AgentServeDeployClient {
|
|
164
|
+
constructor(options) {
|
|
165
|
+
var _a;
|
|
166
|
+
this.backendUrl = options.backendUrl.endsWith("/")
|
|
167
|
+
? options.backendUrl.slice(0, -1)
|
|
168
|
+
: options.backendUrl;
|
|
169
|
+
this.apiKey = options.apiKey;
|
|
170
|
+
this.fetchImpl = (_a = options.fetchImpl) !== null && _a !== void 0 ? _a : fetch;
|
|
171
|
+
}
|
|
172
|
+
/** Create or redeploy; 202 means accepted, not running (poll status). */
|
|
173
|
+
deploy(args) {
|
|
174
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
175
|
+
var _a;
|
|
176
|
+
const slugError = validateDeploymentSlug(args.slug);
|
|
177
|
+
if (slugError !== undefined) {
|
|
178
|
+
throw new DeployApiError(slugError, 400);
|
|
179
|
+
}
|
|
180
|
+
for (const domain of (_a = args.source.egressAllowedDomains) !== null && _a !== void 0 ? _a : []) {
|
|
181
|
+
const domainError = validateEgressDomain(domain);
|
|
182
|
+
if (domainError !== undefined) {
|
|
183
|
+
throw new DeployApiError(domainError, 400);
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
// Only the git-ref member exists today; a future artifact member would
|
|
187
|
+
// upload the build first and post a different body from this branch.
|
|
188
|
+
const body = Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({ teamId: args.teamId, slug: args.slug }, (args.source.gitRepoUrl === undefined
|
|
189
|
+
? {}
|
|
190
|
+
: { gitRepoUrl: args.source.gitRepoUrl })), (args.source.gitRef === undefined
|
|
191
|
+
? {}
|
|
192
|
+
: { gitRef: args.source.gitRef })), (args.source.agentPath === undefined
|
|
193
|
+
? {}
|
|
194
|
+
: { agentPath: args.source.agentPath })), (args.source.cursorEventRepos === undefined
|
|
195
|
+
? {}
|
|
196
|
+
: { cursorEventRepos: args.source.cursorEventRepos })), (args.source.egressAllowedDomains === undefined
|
|
197
|
+
? {}
|
|
198
|
+
: { egressAllowedDomains: args.source.egressAllowedDomains }));
|
|
199
|
+
const raw = yield this.request({
|
|
200
|
+
method: "POST",
|
|
201
|
+
path: "/internal/agent-serve/deployments",
|
|
202
|
+
body,
|
|
203
|
+
context: { verb: "deploy", slug: args.slug },
|
|
204
|
+
});
|
|
205
|
+
return deployAcceptedSchema.parse(raw);
|
|
206
|
+
});
|
|
207
|
+
}
|
|
208
|
+
listDeployments(args) {
|
|
209
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
210
|
+
const raw = yield this.request({
|
|
211
|
+
method: "GET",
|
|
212
|
+
path: `/internal/agent-serve/deployments?teamId=${args.teamId}`,
|
|
213
|
+
context: { verb: "list deployments" },
|
|
214
|
+
});
|
|
215
|
+
return listResponseSchema.parse(raw).deployments;
|
|
216
|
+
});
|
|
217
|
+
}
|
|
218
|
+
getDeployment(args) {
|
|
219
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
220
|
+
const raw = yield this.request({
|
|
221
|
+
method: "GET",
|
|
222
|
+
path: `/internal/agent-serve/deployments/${encodeURIComponent(args.slug)}?teamId=${args.teamId}`,
|
|
223
|
+
context: { verb: "get deployment", slug: args.slug },
|
|
224
|
+
});
|
|
225
|
+
return deploymentDetailSchema.parse(raw);
|
|
226
|
+
});
|
|
227
|
+
}
|
|
228
|
+
stopDeployment(args) {
|
|
229
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
230
|
+
const raw = yield this.request({
|
|
231
|
+
method: "POST",
|
|
232
|
+
path: `/internal/agent-serve/deployments/${encodeURIComponent(args.slug)}/stop?teamId=${args.teamId}`,
|
|
233
|
+
context: { verb: "stop", slug: args.slug },
|
|
234
|
+
});
|
|
235
|
+
return stopAcceptedSchema.parse(raw);
|
|
236
|
+
});
|
|
237
|
+
}
|
|
238
|
+
/** Returns the new alias token exactly once; the old one dies now. */
|
|
239
|
+
rotateAliasToken(args) {
|
|
240
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
241
|
+
const raw = yield this.request({
|
|
242
|
+
method: "POST",
|
|
243
|
+
path: `/internal/agent-serve/deployments/${encodeURIComponent(args.slug)}/rotate-alias-token?teamId=${args.teamId}`,
|
|
244
|
+
context: { verb: "rotate alias token", slug: args.slug },
|
|
245
|
+
});
|
|
246
|
+
return rotateResponseSchema.parse(raw).aliasToken;
|
|
247
|
+
});
|
|
248
|
+
}
|
|
249
|
+
/**
|
|
250
|
+
* Upsert secrets by name (unlisted names stay untouched). Returns the
|
|
251
|
+
* post-write union of secret names, sorted. Validates names and value
|
|
252
|
+
* sizes client-side with the backend's grammar before any network call.
|
|
253
|
+
*/
|
|
254
|
+
setSecrets(args) {
|
|
255
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
256
|
+
for (const { name, value } of args.secrets) {
|
|
257
|
+
const nameError = validateSettableSecretName(name);
|
|
258
|
+
if (nameError !== undefined) {
|
|
259
|
+
throw new DeployApiError(nameError, 400);
|
|
260
|
+
}
|
|
261
|
+
if (Buffer.byteLength(value, "utf8") > MAX_SECRET_VALUE_BYTES) {
|
|
262
|
+
throw new DeployApiError(`The value for ${name} is too large (max ${MAX_SECRET_VALUE_BYTES} bytes).`, 400);
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
if (args.secrets.length > MAX_SECRETS) {
|
|
266
|
+
throw new DeployApiError(`Too many secrets in one request (${args.secrets.length}); deployments hold at most ${MAX_SECRETS}.`, 400);
|
|
267
|
+
}
|
|
268
|
+
const raw = yield this.request({
|
|
269
|
+
method: "PUT",
|
|
270
|
+
path: `/internal/agent-serve/deployments/${encodeURIComponent(args.slug)}/secrets`,
|
|
271
|
+
body: { teamId: args.teamId, secrets: args.secrets },
|
|
272
|
+
context: { verb: "set secrets", slug: args.slug },
|
|
273
|
+
});
|
|
274
|
+
return setSecretsResponseSchema.parse(raw).secretNames;
|
|
275
|
+
});
|
|
276
|
+
}
|
|
277
|
+
/** Secret names + creation times; values are never returned. */
|
|
278
|
+
listSecrets(args) {
|
|
279
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
280
|
+
const raw = yield this.request({
|
|
281
|
+
method: "GET",
|
|
282
|
+
path: `/internal/agent-serve/deployments/${encodeURIComponent(args.slug)}/secrets?teamId=${args.teamId}`,
|
|
283
|
+
context: { verb: "list secrets", slug: args.slug },
|
|
284
|
+
});
|
|
285
|
+
return listSecretsResponseSchema.parse(raw).secrets;
|
|
286
|
+
});
|
|
287
|
+
}
|
|
288
|
+
/** Remove one secret by name; 404 when it is not set. */
|
|
289
|
+
deleteSecret(args) {
|
|
290
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
291
|
+
const nameError = validateSettableSecretName(args.name);
|
|
292
|
+
if (nameError !== undefined) {
|
|
293
|
+
throw new DeployApiError(nameError, 400);
|
|
294
|
+
}
|
|
295
|
+
yield this.request({
|
|
296
|
+
method: "DELETE",
|
|
297
|
+
path: `/internal/agent-serve/deployments/${encodeURIComponent(args.slug)}/secrets/${encodeURIComponent(args.name)}?teamId=${args.teamId}`,
|
|
298
|
+
context: { verb: "unset secret", slug: args.slug },
|
|
299
|
+
});
|
|
300
|
+
});
|
|
301
|
+
}
|
|
302
|
+
/**
|
|
303
|
+
* Rotate the deployment's pod credential. Returns the masked new key —
|
|
304
|
+
* the raw key is injected into the pod on the next deploy, never
|
|
305
|
+
* returned to clients.
|
|
306
|
+
*/
|
|
307
|
+
rotatePodCredential(args) {
|
|
308
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
309
|
+
const raw = yield this.request({
|
|
310
|
+
method: "POST",
|
|
311
|
+
path: `/internal/agent-serve/deployments/${encodeURIComponent(args.slug)}/rotate-pod-credential?teamId=${args.teamId}`,
|
|
312
|
+
context: { verb: "rotate pod credential", slug: args.slug },
|
|
313
|
+
});
|
|
314
|
+
return rotatePodCredentialResponseSchema.parse(raw).podCredentialMaskedKey;
|
|
315
|
+
});
|
|
316
|
+
}
|
|
317
|
+
/** Full URL of the stable engine alias for a deployment. */
|
|
318
|
+
aliasUrl(engineAlias) {
|
|
319
|
+
return `${this.backendUrl}${engineAlias}`;
|
|
320
|
+
}
|
|
321
|
+
request(args) {
|
|
322
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
323
|
+
let response;
|
|
324
|
+
try {
|
|
325
|
+
response = yield this.fetchImpl(`${this.backendUrl}${args.path}`, Object.assign(Object.assign({ method: args.method, headers: Object.assign({ accept: "application/json", authorization: `Bearer ${this.apiKey}` }, (args.body === undefined
|
|
326
|
+
? {}
|
|
327
|
+
: { "content-type": "application/json" })) }, (args.body === undefined ? {} : { body: JSON.stringify(args.body) })), { signal: AbortSignal.timeout(60000) }));
|
|
328
|
+
}
|
|
329
|
+
catch (error) {
|
|
330
|
+
throw new DeployApiError(`Could not reach the Cursor backend at ${this.backendUrl}: ${error instanceof Error ? error.message : String(error)}`, 0);
|
|
331
|
+
}
|
|
332
|
+
const text = yield response.text();
|
|
333
|
+
if (!response.ok) {
|
|
334
|
+
throw mapErrorResponse(response, text, args.context);
|
|
335
|
+
}
|
|
336
|
+
try {
|
|
337
|
+
return JSON.parse(text);
|
|
338
|
+
}
|
|
339
|
+
catch (_a) {
|
|
340
|
+
throw new DeployApiError(`The Cursor backend returned a non-JSON response to ${args.context.verb}.`, response.status);
|
|
341
|
+
}
|
|
342
|
+
});
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
// ============================================================================
|
|
346
|
+
// Error mapping (HTTP → actionable human messages)
|
|
347
|
+
// ============================================================================
|
|
348
|
+
function serverErrorText(bodyText) {
|
|
349
|
+
try {
|
|
350
|
+
const parsed = JSON.parse(bodyText);
|
|
351
|
+
if (typeof parsed.error === "string" && parsed.error !== "") {
|
|
352
|
+
return parsed.error;
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
catch (_a) {
|
|
356
|
+
// Non-JSON body — fall through.
|
|
357
|
+
}
|
|
358
|
+
return undefined;
|
|
359
|
+
}
|
|
360
|
+
function mapErrorResponse(response, bodyText, context) {
|
|
361
|
+
var _a;
|
|
362
|
+
const serverError = serverErrorText(bodyText);
|
|
363
|
+
const slugPart = context.slug === undefined ? "" : ` "${context.slug}"`;
|
|
364
|
+
switch (response.status) {
|
|
365
|
+
case 400:
|
|
366
|
+
return new DeployApiError(serverError !== null && serverError !== void 0 ? serverError : `The ${context.verb} request was rejected as invalid.`, 400);
|
|
367
|
+
case 401:
|
|
368
|
+
return new DeployApiError("The Cursor API key was rejected. Run `agentkit login` again or update CURSOR_API_KEY.", 401);
|
|
369
|
+
case 403:
|
|
370
|
+
return new DeployApiError(`${serverError !== null && serverError !== void 0 ? serverError : "Not authorized"} — deploying needs team-admin permission and the cloud-agent entitlement on that team.`, 403);
|
|
371
|
+
case 404: {
|
|
372
|
+
// Fastify's route-not-found envelope means we hit the wrong host
|
|
373
|
+
// (api2 vs api.cursor.com), not a missing deployment / closed gate.
|
|
374
|
+
if (/Route \S+ not found/i.test(bodyText)) {
|
|
375
|
+
return new DeployApiError(`Agent Serve deploy API not found on this host — use the default api.cursor.com (unset CURSOR_API_BASE_URL), or point CURSOR_API_BASE_URL at a backend that mounts /internal/agent-serve/*.`, 404);
|
|
376
|
+
}
|
|
377
|
+
return new DeployApiError(context.slug === undefined
|
|
378
|
+
? `Not found — the agent_serve_mvp feature gate may not be enabled for your team.`
|
|
379
|
+
: `Deployment${slugPart} was not found — check the slug and --team, or the agent_serve_mvp feature gate may not be enabled for your team.`, 404);
|
|
380
|
+
}
|
|
381
|
+
case 409:
|
|
382
|
+
return new DeployApiError(`A concurrent deploy or stop is changing deployment${slugPart}; retry in a moment.`, 409);
|
|
383
|
+
case 429: {
|
|
384
|
+
const retryAfterHeader = response.headers.get("retry-after");
|
|
385
|
+
const retryAfterSeconds = retryAfterHeader !== null && /^\d+$/.test(retryAfterHeader)
|
|
386
|
+
? Number(retryAfterHeader)
|
|
387
|
+
: undefined;
|
|
388
|
+
return new DeployApiError(`${serverError !== null && serverError !== void 0 ? serverError : "Rate limited"}${retryAfterSeconds === undefined
|
|
389
|
+
? ""
|
|
390
|
+
: ` — retry in ${retryAfterSeconds}s`}`, 429, retryAfterSeconds);
|
|
391
|
+
}
|
|
392
|
+
default:
|
|
393
|
+
return new DeployApiError(`The ${context.verb} request failed (${response.status}): ${(_a = serverError !== null && serverError !== void 0 ? serverError : bodyText.slice(0, 300)) !== null && _a !== void 0 ? _a : "(empty body)"}`, response.status);
|
|
394
|
+
}
|
|
395
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Infer `agentkit deploy` git source fields from a local checkout.
|
|
3
|
+
*
|
|
4
|
+
* From an agent directory inside a git repo with an `origin` remote, the
|
|
5
|
+
* CLI can fill `--repo` / `--ref` / `--path` so `agentkit deploy` (no
|
|
6
|
+
* flags) is enough. Explicit flags always win.
|
|
7
|
+
*/
|
|
8
|
+
/** Injectable git runner (cwd + args → stdout, or undefined on failure). */
|
|
9
|
+
export type GitRunner = (args: readonly string[], cwd: string) => Promise<string | undefined>;
|
|
10
|
+
export interface InferredDeploySource {
|
|
11
|
+
gitRepoUrl?: string;
|
|
12
|
+
gitRef?: string;
|
|
13
|
+
/** Agent directory relative to the repo root (posix). Omitted at root. */
|
|
14
|
+
agentPath?: string;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Normalize a git remote URL to the https form the control plane accepts
|
|
18
|
+
* (`https://host/owner/repo`, no `.git` suffix). Returns undefined for
|
|
19
|
+
* unrecognized shapes.
|
|
20
|
+
*/
|
|
21
|
+
export declare function httpsGitRepoUrlFromRemote(remote: string): string | undefined;
|
|
22
|
+
/**
|
|
23
|
+
* Path of `dir` relative to `gitRoot`, using `/` separators. Undefined when
|
|
24
|
+
* `dir` is outside the root; omitted (undefined) when `dir` *is* the root
|
|
25
|
+
* so the control plane treats the agent as living at the repo root.
|
|
26
|
+
*/
|
|
27
|
+
export declare function agentPathRelativeToGitRoot(dir: string, gitRoot: string): string | undefined;
|
|
28
|
+
/**
|
|
29
|
+
* Probe the git checkout containing `dir` for deploy source fields.
|
|
30
|
+
* Missing pieces stay undefined (static deploy / server defaults).
|
|
31
|
+
*/
|
|
32
|
+
export declare function inferDeployGitSource(dir: string, options?: {
|
|
33
|
+
git?: GitRunner;
|
|
34
|
+
}): Promise<InferredDeploySource>;
|
|
35
|
+
//# sourceMappingURL=deploy-source.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"deploy-source.d.ts","sourceRoot":"","sources":["../../src/internal/deploy-source.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAQH,4EAA4E;AAC5E,MAAM,MAAM,SAAS,GAAG,CACtB,IAAI,EAAE,SAAS,MAAM,EAAE,EACvB,GAAG,EAAE,MAAM,KACR,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAAC;AAEjC,MAAM,WAAW,oBAAoB;IACnC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,0EAA0E;IAC1E,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAYD;;;;GAIG;AACH,wBAAgB,yBAAyB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CA6B5E;AAED;;;;GAIG;AACH,wBAAgB,0BAA0B,CACxC,GAAG,EAAE,MAAM,EACX,OAAO,EAAE,MAAM,GACd,MAAM,GAAG,SAAS,CAYpB;AAED;;;GAGG;AACH,wBAAsB,oBAAoB,CACxC,GAAG,EAAE,MAAM,EACX,OAAO,CAAC,EAAE;IAAE,GAAG,CAAC,EAAE,SAAS,CAAA;CAAE,GAC5B,OAAO,CAAC,oBAAoB,CAAC,CA8B/B"}
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Infer `agentkit deploy` git source fields from a local checkout.
|
|
3
|
+
*
|
|
4
|
+
* From an agent directory inside a git repo with an `origin` remote, the
|
|
5
|
+
* CLI can fill `--repo` / `--ref` / `--path` so `agentkit deploy` (no
|
|
6
|
+
* flags) is enough. Explicit flags always win.
|
|
7
|
+
*/
|
|
8
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
9
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
10
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
11
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
12
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
13
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
14
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
15
|
+
});
|
|
16
|
+
};
|
|
17
|
+
import { execFile } from "node:child_process";
|
|
18
|
+
import { relative, resolve, sep } from "node:path";
|
|
19
|
+
import { promisify } from "node:util";
|
|
20
|
+
const execFileAsync = promisify(execFile);
|
|
21
|
+
const defaultGitRunner = (args, cwd) => __awaiter(void 0, void 0, void 0, function* () {
|
|
22
|
+
try {
|
|
23
|
+
const { stdout } = yield execFileAsync("git", [...args], { cwd });
|
|
24
|
+
const trimmed = stdout.trim();
|
|
25
|
+
return trimmed === "" ? undefined : trimmed;
|
|
26
|
+
}
|
|
27
|
+
catch (_a) {
|
|
28
|
+
return undefined;
|
|
29
|
+
}
|
|
30
|
+
});
|
|
31
|
+
/**
|
|
32
|
+
* Normalize a git remote URL to the https form the control plane accepts
|
|
33
|
+
* (`https://host/owner/repo`, no `.git` suffix). Returns undefined for
|
|
34
|
+
* unrecognized shapes.
|
|
35
|
+
*/
|
|
36
|
+
export function httpsGitRepoUrlFromRemote(remote) {
|
|
37
|
+
let url = remote.trim();
|
|
38
|
+
if (url === "") {
|
|
39
|
+
return undefined;
|
|
40
|
+
}
|
|
41
|
+
if (url.startsWith("git@")) {
|
|
42
|
+
// git@host:owner/repo.git → https://host/owner/repo.git
|
|
43
|
+
url = `https://${url.slice("git@".length).replace(":", "/")}`;
|
|
44
|
+
}
|
|
45
|
+
else if (url.startsWith("ssh://git@")) {
|
|
46
|
+
url = `https://${url.slice("ssh://git@".length)}`;
|
|
47
|
+
}
|
|
48
|
+
else if (!/^https?:\/\//i.test(url)) {
|
|
49
|
+
return undefined;
|
|
50
|
+
}
|
|
51
|
+
let parsed;
|
|
52
|
+
try {
|
|
53
|
+
parsed = new URL(url);
|
|
54
|
+
}
|
|
55
|
+
catch (_a) {
|
|
56
|
+
return undefined;
|
|
57
|
+
}
|
|
58
|
+
const path = parsed.pathname
|
|
59
|
+
.replace(/\.git$/i, "")
|
|
60
|
+
.replace(/\/+$/, "")
|
|
61
|
+
.replace(/^\/+/, "");
|
|
62
|
+
if (path === "" || !path.includes("/")) {
|
|
63
|
+
return undefined;
|
|
64
|
+
}
|
|
65
|
+
// Use hostname (not host) so ssh://git@github.com:22/… does not keep :22.
|
|
66
|
+
return `https://${parsed.hostname}/${path}`;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Path of `dir` relative to `gitRoot`, using `/` separators. Undefined when
|
|
70
|
+
* `dir` is outside the root; omitted (undefined) when `dir` *is* the root
|
|
71
|
+
* so the control plane treats the agent as living at the repo root.
|
|
72
|
+
*/
|
|
73
|
+
export function agentPathRelativeToGitRoot(dir, gitRoot) {
|
|
74
|
+
const absDir = resolve(dir);
|
|
75
|
+
const absRoot = resolve(gitRoot);
|
|
76
|
+
const rel = relative(absRoot, absDir);
|
|
77
|
+
if (rel === "") {
|
|
78
|
+
return undefined;
|
|
79
|
+
}
|
|
80
|
+
// Outside the repo (or a Windows drive mismatch) → cannot infer.
|
|
81
|
+
if (rel.startsWith("..") || rel.split(sep).includes("..")) {
|
|
82
|
+
return undefined;
|
|
83
|
+
}
|
|
84
|
+
return rel.split(sep).join("/");
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Probe the git checkout containing `dir` for deploy source fields.
|
|
88
|
+
* Missing pieces stay undefined (static deploy / server defaults).
|
|
89
|
+
*/
|
|
90
|
+
export function inferDeployGitSource(dir, options) {
|
|
91
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
92
|
+
var _a;
|
|
93
|
+
const git = (_a = options === null || options === void 0 ? void 0 : options.git) !== null && _a !== void 0 ? _a : defaultGitRunner;
|
|
94
|
+
const absDir = resolve(dir);
|
|
95
|
+
const gitRoot = yield git(["rev-parse", "--show-toplevel"], absDir);
|
|
96
|
+
if (gitRoot === undefined) {
|
|
97
|
+
return {};
|
|
98
|
+
}
|
|
99
|
+
const remote = yield git(["remote", "get-url", "origin"], gitRoot);
|
|
100
|
+
const gitRepoUrl = remote === undefined ? undefined : httpsGitRepoUrlFromRemote(remote);
|
|
101
|
+
const branch = yield git(["rev-parse", "--abbrev-ref", "HEAD"], gitRoot);
|
|
102
|
+
let gitRef;
|
|
103
|
+
if (branch !== undefined && branch !== "HEAD") {
|
|
104
|
+
gitRef = branch;
|
|
105
|
+
}
|
|
106
|
+
else {
|
|
107
|
+
// Detached HEAD — pin the exact commit so the control plane still
|
|
108
|
+
// has something concrete to build.
|
|
109
|
+
gitRef = yield git(["rev-parse", "HEAD"], gitRoot);
|
|
110
|
+
}
|
|
111
|
+
const agentPath = agentPathRelativeToGitRoot(absDir, gitRoot);
|
|
112
|
+
return {
|
|
113
|
+
gitRepoUrl,
|
|
114
|
+
gitRef,
|
|
115
|
+
agentPath,
|
|
116
|
+
};
|
|
117
|
+
});
|
|
118
|
+
}
|
|
@@ -16,6 +16,17 @@ export interface LoadAgentProjectOptions {
|
|
|
16
16
|
* inside it.
|
|
17
17
|
*/
|
|
18
18
|
export declare function isAgentProjectDir(dir: string): Promise<boolean>;
|
|
19
|
+
/** One immediate child agent directory under a multi-agent parent. */
|
|
20
|
+
export interface ChildAgentDir {
|
|
21
|
+
slug: string;
|
|
22
|
+
dir: string;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* List agent projects directly under `rootDir` (one level deep) without
|
|
26
|
+
* loading them. Empty when the path is missing or has no child agents.
|
|
27
|
+
* Slug rules match {@link loadAgentProjects} / multi-agent serve.
|
|
28
|
+
*/
|
|
29
|
+
export declare function listChildAgentDirs(rootDir: string): Promise<ChildAgentDir[]>;
|
|
19
30
|
/**
|
|
20
31
|
* Discover the agent projects directly under `rootDir` (one level deep):
|
|
21
32
|
* each immediate child directory that is itself an agent project becomes a
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"discovery.d.ts","sourceRoot":"","sources":["../../src/internal/discovery.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;
|
|
1
|
+
{"version":3,"file":"discovery.d.ts","sourceRoot":"","sources":["../../src/internal/discovery.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAgBH,OAAO,EAGL,KAAK,YAAY,EACjB,KAAK,gBAAgB,EAKrB,KAAK,UAAU,EAmBhB,MAAM,aAAa,CAAC;AAoBrB,MAAM,WAAW,uBAAuB;IACtC,sDAAsD;IACtD,YAAY,CAAC,EAAE,CAAC,YAAY,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;CAC3E;AAmBD;;;;GAIG;AACH,wBAAsB,iBAAiB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CASrE;AAED,sEAAsE;AACtE,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;CACb;AAED;;;;GAIG;AACH,wBAAsB,kBAAkB,CACtC,OAAO,EAAE,MAAM,GACd,OAAO,CAAC,aAAa,EAAE,CAAC,CA2B1B;AAED;;;;;;GAMG;AACH,wBAAsB,iBAAiB,CACrC,OAAO,EAAE,MAAM,EACf,OAAO,GAAE,uBAA4B,GACpC,OAAO,CAAC,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,YAAY,CAAA;CAAE,CAAC,CAAC,CAoBzD;AAED;;;;;;GAMG;AACH,wBAAsB,kBAAkB,CACtC,OAAO,EAAE,MAAM,EACf,OAAO,GAAE,uBAAuB,GAAG;IACjC,IAAI,CAAC,EAAE,QAAQ,GAAG,OAAO,CAAC;CACtB,GACL,OAAO,CAAC,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,YAAY,CAAA;CAAE,CAAC,CAAC,CAgBzD;AAWD,iFAAiF;AACjF,eAAO,MAAM,cAAc,EAAE,GAAG,CAAC,MAAM,CAIrC,CAAC;AAEH,wBAAsB,gBAAgB,CACpC,GAAG,EAAE,MAAM,EACX,OAAO,GAAE,uBAA4B,GACpC,OAAO,CAAC,YAAY,CAAC,CA8DvB;AAED,qEAAqE;AACrE,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAElE;AAED,wBAAgB,iBAAiB,CAAC,WAAW,EAAE,UAAU,EAAE,GAAG,MAAM,CAOnE;AAskBD;;;GAGG;AACH,wBAAgB,sBAAsB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAiB3E;AAukBD,wBAAgB,WAAW,CAAC,OAAO,EAAE,YAAY,GAAG,gBAAgB,CAkInE"}
|