@cursor/july 0.1.68 → 0.1.74
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 +17 -13
- package/README.md +23 -11
- package/dist/bin/agent-serve.js +10 -7
- package/dist/channels/github/api.d.ts +2 -0
- package/dist/channels/github/api.d.ts.map +1 -1
- package/dist/channels/github/api.js +2 -1
- package/dist/channels/github/binding.d.ts +7 -0
- package/dist/channels/github/binding.d.ts.map +1 -1
- package/dist/channels/github/binding.js +4 -0
- package/dist/channels/github/checks.d.ts +99 -0
- package/dist/channels/github/checks.d.ts.map +1 -0
- package/dist/channels/github/checks.js +108 -0
- package/dist/channels/github/cursor-account.d.ts +4 -4
- package/dist/channels/github/cursor-account.d.ts.map +1 -1
- package/dist/channels/github/cursor-account.js +7 -5
- package/dist/channels/github/index.d.ts +1 -0
- package/dist/channels/github/index.d.ts.map +1 -1
- package/dist/channels/github/index.js +1 -0
- package/dist/channels/github/types.d.ts +8 -0
- package/dist/channels/github/types.d.ts.map +1 -1
- package/dist/channels/slack/manifest.d.ts +2 -2
- package/dist/channels/slack/manifest.d.ts.map +1 -1
- package/dist/channels/slack/manifest.js +13 -11
- package/dist/channels/slack/types.d.ts +2 -2
- package/dist/channels/slack/types.d.ts.map +1 -1
- package/dist/connections.d.ts +17 -5
- package/dist/connections.d.ts.map +1 -1
- package/dist/connections.js +17 -5
- package/dist/docs/404.html +2 -2
- package/dist/docs/ab.html +3 -3
- package/dist/docs/assets/{app.C5XUTCw9.js → app.BETd-WqU.js} +1 -1
- package/dist/docs/assets/chunks/@localSearchIndexroot.DM5INS71.js +1 -0
- package/dist/docs/assets/chunks/{VPLocalSearchBox.CGDTAYHY.js → VPLocalSearchBox.wEaGEmV9.js} +1 -1
- package/dist/docs/assets/chunks/{theme.lPixh250.js → theme.DNDicFOP.js} +2 -2
- package/dist/docs/assets/{concepts.md.CqOsxbMU.js → concepts.md.BXAm6G-C.js} +1 -1
- package/dist/docs/assets/{guides_mcp-oauth.md.C7G7IykG.js → guides_mcp-oauth.md.CzEB6RaG.js} +1 -1
- package/dist/docs/assets/{reference_agent-config.md.DHkkvcEZ.js → reference_agent-config.md.BZnEKfEc.js} +3 -4
- package/dist/docs/assets/{reference_agent-config.md.DHkkvcEZ.lean.js → reference_agent-config.md.BZnEKfEc.lean.js} +1 -1
- package/dist/docs/assets/{reference_cli.md.Cl14Jfo3.js → reference_cli.md.TAaYU8br.js} +3 -3
- package/dist/docs/assets/{reference_cli.md.Cl14Jfo3.lean.js → reference_cli.md.TAaYU8br.lean.js} +1 -1
- package/dist/docs/assets/{reference_connections.md.Bwswbm6H.js → reference_connections.md.Cu3N-S3Q.js} +18 -11
- package/dist/docs/assets/{reference_connections.md.Bwswbm6H.lean.js → reference_connections.md.Cu3N-S3Q.lean.js} +1 -1
- package/dist/docs/assets/{reference_sessions.md.DBVFi2Sx.js → reference_sessions.md.B0DdlM-K.js} +1 -1
- package/dist/docs/assets/{reference_tools.md.Wmvb7Lob.js → reference_tools.md.DTg_kEsx.js} +1 -1
- package/dist/docs/assets/scaffolding-agents.md.CiGsJ1aw.js +1 -0
- package/dist/docs/assets/{scaffolding-agents.md.CrWSA0Ko.lean.js → scaffolding-agents.md.CiGsJ1aw.lean.js} +1 -1
- package/dist/docs/assets/troubleshooting.md.DQ-hYuZT.js +1 -0
- package/dist/docs/building-with-agents.html +3 -3
- package/dist/docs/concepts.html +5 -5
- package/dist/docs/deployment.html +3 -3
- package/dist/docs/evals.html +3 -3
- package/dist/docs/example-agents/approval-buddy.html +3 -3
- package/dist/docs/example-agents/benny.html +3 -3
- package/dist/docs/example-agents/bugbot.html +3 -3
- package/dist/docs/example-agents/codebase-wiki.html +3 -3
- package/dist/docs/example-agents/codeowners-review.html +3 -3
- package/dist/docs/example-agents/concierge.html +3 -3
- package/dist/docs/example-agents/fsd.html +3 -3
- package/dist/docs/example-agents/index.html +3 -3
- package/dist/docs/example-agents/knowledge-base.html +3 -3
- package/dist/docs/example-agents/oncall.html +3 -3
- package/dist/docs/example-agents/security-reviewer.html +3 -3
- package/dist/docs/example-agents/slack-agent.html +3 -3
- package/dist/docs/example-agents/weather-agent.html +3 -3
- package/dist/docs/guides/agent-to-agent.html +3 -3
- package/dist/docs/guides/cloud-runtime.html +3 -3
- package/dist/docs/guides/convert-automation.html +3 -3
- package/dist/docs/guides/github.html +3 -3
- package/dist/docs/guides/human-in-the-loop.html +3 -3
- package/dist/docs/guides/mcp-oauth.html +5 -5
- package/dist/docs/guides/opentelemetry.html +3 -3
- package/dist/docs/guides/slack.html +3 -3
- package/dist/docs/guides/webhooks.html +3 -3
- package/dist/docs/hashmap.json +1 -1
- package/dist/docs/hillclimbing.html +3 -3
- package/dist/docs/index.html +3 -3
- package/dist/docs/quickstart.html +3 -3
- package/dist/docs/reference/agent-config.html +5 -6
- package/dist/docs/reference/artifacts.html +3 -3
- package/dist/docs/reference/channels.html +3 -3
- package/dist/docs/reference/cli.html +6 -6
- package/dist/docs/reference/connections.html +20 -13
- package/dist/docs/reference/hooks.html +3 -3
- package/dist/docs/reference/http-api.html +3 -3
- package/dist/docs/reference/instructions.html +3 -3
- package/dist/docs/reference/playground.html +3 -3
- package/dist/docs/reference/project-layout.html +3 -3
- package/dist/docs/reference/prompt.html +3 -3
- package/dist/docs/reference/schedules.html +3 -3
- package/dist/docs/reference/sessions.html +5 -5
- package/dist/docs/reference/skills.html +3 -3
- package/dist/docs/reference/subagents.html +3 -3
- package/dist/docs/reference/tools.html +5 -5
- package/dist/docs/scaffolding-agents.html +5 -5
- package/dist/docs/storage.html +3 -3
- package/dist/docs/templates/agentic-owners.html +3 -3
- package/dist/docs/templates/demo.html +3 -3
- package/dist/docs/templates/pr-autofixer.html +3 -3
- package/dist/docs/templates/security-reviewer.html +3 -3
- package/dist/docs/templates/triage.html +3 -3
- package/dist/docs/troubleshooting.html +5 -5
- package/dist/internal/advertise-tools.d.ts +11 -6
- package/dist/internal/advertise-tools.d.ts.map +1 -1
- package/dist/internal/advertise-tools.js +63 -30
- package/dist/internal/cli-deploy.d.ts.map +1 -1
- package/dist/internal/cli-deploy.js +2 -4
- package/dist/internal/cli-skills.d.ts +4 -2
- package/dist/internal/cli-skills.d.ts.map +1 -1
- package/dist/internal/cli-skills.js +8 -3
- package/dist/internal/convert-automation/convert-workflow.d.ts.map +1 -1
- package/dist/internal/convert-automation/convert-workflow.js +2 -10
- package/dist/internal/cursor/account-mcp.d.ts +29 -3
- package/dist/internal/cursor/account-mcp.d.ts.map +1 -1
- package/dist/internal/cursor/account-mcp.js +147 -67
- package/dist/internal/cursor/backend-client.d.ts +11 -6
- package/dist/internal/cursor/backend-client.d.ts.map +1 -1
- package/dist/internal/cursor/backend-client.js +32 -10
- package/dist/internal/cursor-account-mcp-auth.d.ts +11 -0
- package/dist/internal/cursor-account-mcp-auth.d.ts.map +1 -1
- package/dist/internal/cursor-account-mcp-auth.js +69 -0
- package/dist/internal/deploy-client.d.ts +0 -7
- package/dist/internal/deploy-client.d.ts.map +1 -1
- package/dist/internal/deploy-client.js +2 -4
- package/dist/internal/deploy-manifest.d.ts +15 -24
- package/dist/internal/deploy-manifest.d.ts.map +1 -1
- package/dist/internal/deploy-manifest.js +38 -27
- package/dist/internal/deployment-scm-event-stream.d.ts +4 -1
- package/dist/internal/deployment-scm-event-stream.d.ts.map +1 -1
- package/dist/internal/deployment-scm-event-stream.js +15 -1
- package/dist/internal/discovery.d.ts.map +1 -1
- package/dist/internal/discovery.js +42 -10
- package/dist/internal/init-project.d.ts.map +1 -1
- package/dist/internal/init-project.js +7 -106
- package/dist/internal/init-scaffold.d.ts +8 -0
- package/dist/internal/init-scaffold.d.ts.map +1 -0
- package/dist/internal/init-scaffold.js +168 -0
- package/dist/internal/inline-stdio-mcp.d.ts +2 -0
- package/dist/internal/inline-stdio-mcp.d.ts.map +1 -1
- package/dist/internal/inline-stdio-mcp.js +10 -8
- package/dist/internal/install-cursor-skills.d.ts +71 -16
- package/dist/internal/install-cursor-skills.d.ts.map +1 -1
- package/dist/internal/install-cursor-skills.js +160 -48
- package/dist/internal/json-schema.d.ts +7 -0
- package/dist/internal/json-schema.d.ts.map +1 -1
- package/dist/internal/json-schema.js +18 -3
- package/dist/internal/mcp-endpoint.js +7 -7
- package/dist/internal/mcp-host.js +4 -2
- package/dist/internal/mcp-oauth.d.ts +22 -0
- package/dist/internal/mcp-oauth.d.ts.map +1 -1
- package/dist/internal/mcp-oauth.js +40 -1
- package/dist/internal/package-inline-stdio.d.ts.map +1 -1
- package/dist/internal/package-inline-stdio.js +5 -5
- package/dist/internal/review-comments.d.ts +97 -0
- package/dist/internal/review-comments.d.ts.map +1 -1
- package/dist/internal/review-comments.js +151 -0
- package/dist/internal/sanitize-mcp-tool-name.d.ts +20 -0
- package/dist/internal/sanitize-mcp-tool-name.d.ts.map +1 -0
- package/dist/internal/sanitize-mcp-tool-name.js +30 -0
- package/dist/internal/sdk-runner.d.ts.map +1 -1
- package/dist/internal/sdk-runner.js +6 -2
- package/dist/internal/session-engine.d.ts.map +1 -1
- package/dist/internal/session-engine.js +4 -6
- package/dist/internal/shallow-clone.d.ts +94 -39
- package/dist/internal/shallow-clone.d.ts.map +1 -1
- package/dist/internal/shallow-clone.js +188 -68
- package/dist/internal/terminal-style.d.ts +18 -0
- package/dist/internal/terminal-style.d.ts.map +1 -1
- package/dist/internal/terminal-style.js +46 -1
- package/dist/internal/workspace.d.ts +2 -0
- package/dist/internal/workspace.d.ts.map +1 -1
- package/dist/internal/workspace.js +5 -0
- package/dist/playground/assets/index-D_8I9TM0.js +85 -0
- package/dist/playground/assets/index-M3nSMc6_.css +1 -0
- package/dist/playground/index.html +2 -2
- package/dist/tools.d.ts +7 -0
- package/dist/tools.d.ts.map +1 -1
- package/dist/types.d.ts +28 -3
- package/dist/types.d.ts.map +1 -1
- package/docs/concepts.md +4 -4
- package/docs/guides/mcp-oauth.md +3 -1
- package/docs/reference/agent-config.md +11 -12
- package/docs/reference/cli.md +16 -8
- package/docs/reference/connections.md +44 -26
- package/docs/reference/sessions.md +2 -2
- package/docs/reference/tools.md +1 -1
- package/docs/scaffolding-agents.md +14 -6
- package/docs/troubleshooting.md +3 -2
- package/package.json +6 -1
- package/scripts/install-cursor-skills.mjs +36 -0
- package/skills/ab/SKILL.md +1 -1
- package/skills/create-agent/SKILL.md +13 -10
- package/skills/debug/SKILL.md +3 -2
- package/skills/evals/SKILL.md +1 -1
- package/skills/framework-map/SKILL.md +7 -7
- package/skills/github/SKILL.md +1 -1
- package/skills/hillclimb/SKILL.md +1 -1
- package/skills/mcp-auth/SKILL.md +9 -7
- package/skills/otel/SKILL.md +1 -1
- package/skills/setup-slack/SKILL.md +1 -1
- package/src/bin/agent-serve.ts +10 -7
- package/src/channels/github/api.ts +6 -1
- package/src/channels/github/binding.ts +21 -0
- package/src/channels/github/checks.ts +179 -0
- package/src/channels/github/cursor-account.ts +9 -6
- package/src/channels/github/index.ts +1 -0
- package/src/channels/github/types.ts +8 -0
- package/src/channels/slack/manifest.ts +8 -10
- package/src/channels/slack/types.ts +2 -2
- package/src/connections.ts +17 -5
- package/src/internal/advertise-tools.ts +72 -23
- package/src/internal/cli-deploy.ts +4 -15
- package/src/internal/cli-skills.ts +10 -2
- package/src/internal/convert-automation/convert-workflow.ts +2 -11
- package/src/internal/cursor/account-mcp.ts +208 -73
- package/src/internal/cursor/backend-client.ts +45 -11
- package/src/internal/cursor-account-mcp-auth.ts +83 -0
- package/src/internal/deploy-client.ts +0 -10
- package/src/internal/deploy-manifest.ts +33 -39
- package/src/internal/deployment-scm-event-stream.ts +17 -1
- package/src/internal/discovery.ts +47 -3
- package/src/internal/init-project.ts +7 -133
- package/src/internal/init-scaffold.ts +176 -0
- package/src/internal/inline-stdio-mcp.ts +13 -0
- package/src/internal/install-cursor-skills.ts +204 -49
- package/src/internal/json-schema.ts +24 -3
- package/src/internal/mcp-endpoint.ts +6 -0
- package/src/internal/mcp-host.ts +4 -0
- package/src/internal/mcp-oauth.ts +55 -1
- package/src/internal/package-inline-stdio.ts +5 -1
- package/src/internal/review-comments.ts +245 -0
- package/src/internal/sanitize-mcp-tool-name.ts +33 -0
- package/src/internal/sdk-runner.ts +6 -3
- package/src/internal/session-engine.ts +7 -0
- package/src/internal/shallow-clone.ts +293 -105
- package/src/internal/terminal-style.ts +67 -1
- package/src/internal/workspace.ts +6 -0
- package/src/tools.ts +7 -0
- package/src/types.ts +32 -4
- package/templates/agentic-owners/agent/agent.ts +3 -0
- package/templates/demo/agent/agent.ts +3 -0
- package/templates/security-reviewer/agent/agent.ts +3 -0
- package/templates/triage/agent/agent.ts +3 -0
- package/dist/docs/assets/chunks/@localSearchIndexroot.DvUR3lv9.js +0 -1
- package/dist/docs/assets/scaffolding-agents.md.CrWSA0Ko.js +0 -1
- package/dist/docs/assets/troubleshooting.md.CuVztCKs.js +0 -1
- package/dist/playground/assets/index-CoL7xCJl.css +0 -1
- package/dist/playground/assets/index-yxs1heea.js +0 -85
- /package/dist/docs/assets/{concepts.md.CqOsxbMU.lean.js → concepts.md.BXAm6G-C.lean.js} +0 -0
- /package/dist/docs/assets/{guides_mcp-oauth.md.C7G7IykG.lean.js → guides_mcp-oauth.md.CzEB6RaG.lean.js} +0 -0
- /package/dist/docs/assets/{reference_sessions.md.DBVFi2Sx.lean.js → reference_sessions.md.B0DdlM-K.lean.js} +0 -0
- /package/dist/docs/assets/{reference_tools.md.Wmvb7Lob.lean.js → reference_tools.md.DTg_kEsx.lean.js} +0 -0
- /package/dist/docs/assets/{troubleshooting.md.CuVztCKs.lean.js → troubleshooting.md.DQ-hYuZT.lean.js} +0 -0
|
@@ -9,6 +9,21 @@ export type ReviewCommentPostResult = {
|
|
|
9
9
|
mode: "review_with_inline_comments" | "review_body_only" | "skipped";
|
|
10
10
|
inlineCommentCount: number;
|
|
11
11
|
detail: string;
|
|
12
|
+
/**
|
|
13
|
+
* Ids of the inline comments this post created, when the publisher could
|
|
14
|
+
* read them back. Callers that later re-read a PR's comments use these as
|
|
15
|
+
* the provenance allowlist: a comment id we did not create is not ours,
|
|
16
|
+
* no matter what its body looks like. Empty when the publisher cannot
|
|
17
|
+
* resolve them (it never guesses).
|
|
18
|
+
*/
|
|
19
|
+
postedComments?: PostedReviewComment[];
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
/** One inline comment this agent created, as the SCM assigned it. */
|
|
23
|
+
export type PostedReviewComment = {
|
|
24
|
+
id: number;
|
|
25
|
+
file: string;
|
|
26
|
+
line: number;
|
|
12
27
|
};
|
|
13
28
|
|
|
14
29
|
export type ReviewInlineComment = {
|
|
@@ -41,6 +56,175 @@ export type ReviewCommentPublisherImplementation = {
|
|
|
41
56
|
postReview: (args: ReviewCommentPostArgs) => Promise<ReviewCommentPostResult>;
|
|
42
57
|
};
|
|
43
58
|
|
|
59
|
+
/**
|
|
60
|
+
* SCMs this module can read review comments back from. Same growth seam as
|
|
61
|
+
* `shallow-clone.ts`'s {@link import("./shallow-clone.js").ScmProvider}:
|
|
62
|
+
* adding GitLab/Bitbucket/Origin means a resolver case plus a reader
|
|
63
|
+
* implementation, and nothing above this line changes.
|
|
64
|
+
*/
|
|
65
|
+
export type ScmReviewProvider = "github";
|
|
66
|
+
|
|
67
|
+
/** Which SCM's PR to read review comments from. */
|
|
68
|
+
export type ScmReviewTarget = {
|
|
69
|
+
provider: ScmReviewProvider;
|
|
70
|
+
/** `owner/name`. */
|
|
71
|
+
repo: string;
|
|
72
|
+
prNumber: number;
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* One existing inline review comment, provider-neutral.
|
|
77
|
+
*
|
|
78
|
+
* Field names follow Bugbot's `ExistingInlineComment`
|
|
79
|
+
* (`backend/server/src/bugbot/review/applyBugbotPRReview.ts`), which is the
|
|
80
|
+
* shape its resolution judge consumes after normalizing each provider's
|
|
81
|
+
* `getPRComments` output — so the same review logic reads the same way here.
|
|
82
|
+
*/
|
|
83
|
+
export type ExistingReviewComment = {
|
|
84
|
+
id: number;
|
|
85
|
+
file: string;
|
|
86
|
+
startLine: number;
|
|
87
|
+
endLine: number;
|
|
88
|
+
body: string;
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
export type GetReviewCommentsArgs = {
|
|
92
|
+
target: ScmReviewTarget;
|
|
93
|
+
/** Comment ids to fetch; ids the SCM no longer has are omitted. */
|
|
94
|
+
commentIds: readonly number[];
|
|
95
|
+
signal?: AbortSignal;
|
|
96
|
+
};
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Read side of the review-comment seam, mirroring
|
|
100
|
+
* {@link ReviewCommentPublisherImplementation}. Bugbot's equivalent is
|
|
101
|
+
* `IGitProvider.getPRComments`.
|
|
102
|
+
*
|
|
103
|
+
* By id rather than by listing: callers only ever want comments they
|
|
104
|
+
* recorded creating, and a busy PR's comment list runs to thousands, where
|
|
105
|
+
* any page cap silently drops exactly the older comments a re-review needs.
|
|
106
|
+
*/
|
|
107
|
+
export type ReviewCommentReaderImplementation = {
|
|
108
|
+
getReviewComments: (
|
|
109
|
+
args: GetReviewCommentsArgs
|
|
110
|
+
) => Promise<ExistingReviewComment[]>;
|
|
111
|
+
};
|
|
112
|
+
|
|
113
|
+
/** Parse a PR URL into the SCM target to read comments from. */
|
|
114
|
+
export function resolveScmReviewTarget(
|
|
115
|
+
prUrl: string
|
|
116
|
+
): ScmReviewTarget | undefined {
|
|
117
|
+
const parsed = parseGithubPrUrl(prUrl);
|
|
118
|
+
return parsed.kind === "valid"
|
|
119
|
+
? {
|
|
120
|
+
provider: "github",
|
|
121
|
+
repo: parsed.value.repo,
|
|
122
|
+
prNumber: parsed.value.prNumber,
|
|
123
|
+
}
|
|
124
|
+
: undefined;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* Reader for a resolved target, mirroring Bugbot's `createPrGitProvider`
|
|
129
|
+
* dispatch. Returns undefined when the host cannot serve that provider (no
|
|
130
|
+
* GitHub client bound), so callers degrade instead of throwing.
|
|
131
|
+
*/
|
|
132
|
+
export function createReviewCommentReader(args: {
|
|
133
|
+
target: ScmReviewTarget;
|
|
134
|
+
github?: HostGitHubClient;
|
|
135
|
+
}): ReviewCommentReaderImplementation | undefined {
|
|
136
|
+
switch (args.target.provider) {
|
|
137
|
+
case "github":
|
|
138
|
+
return args.github === undefined
|
|
139
|
+
? undefined
|
|
140
|
+
: createHostGithubReviewCommentReader(args.github);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
/** Cap on pages pulled per PR; GitHub serves 100 comments per page. */
|
|
145
|
+
const REVIEW_COMMENTS_MAX_PAGES = 5;
|
|
146
|
+
const REVIEW_COMMENTS_PAGE_SIZE = 100;
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* Reads inline review comments through the host GitHub client (Cursor
|
|
150
|
+
* account lease, App installation token, or PAT).
|
|
151
|
+
*/
|
|
152
|
+
export function createHostGithubReviewCommentReader(
|
|
153
|
+
github: HostGitHubClient
|
|
154
|
+
): ReviewCommentReaderImplementation {
|
|
155
|
+
return {
|
|
156
|
+
async getReviewComments({ target, commentIds, signal }) {
|
|
157
|
+
const [owner, repo] = target.repo.split("/", 2);
|
|
158
|
+
if (owner === undefined || repo === undefined || repo === "") {
|
|
159
|
+
return [];
|
|
160
|
+
}
|
|
161
|
+
const octokit = await github.getOctokit();
|
|
162
|
+
const comments: ExistingReviewComment[] = [];
|
|
163
|
+
for (const commentId of commentIds) {
|
|
164
|
+
signal?.throwIfAborted();
|
|
165
|
+
try {
|
|
166
|
+
const response = await octokit.rest.pulls.getReviewComment({
|
|
167
|
+
owner,
|
|
168
|
+
repo,
|
|
169
|
+
comment_id: commentId,
|
|
170
|
+
});
|
|
171
|
+
const normalized = normalizeGithubReviewComment(response.data);
|
|
172
|
+
if (normalized !== undefined) {
|
|
173
|
+
comments.push(normalized);
|
|
174
|
+
}
|
|
175
|
+
} catch {
|
|
176
|
+
// Deleted or otherwise unreadable: that finding simply has no
|
|
177
|
+
// prior text to judge, which is the same as it not being there.
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
return comments;
|
|
181
|
+
},
|
|
182
|
+
};
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
type GithubReviewCommentLike = {
|
|
186
|
+
id: number;
|
|
187
|
+
path: string;
|
|
188
|
+
body: string;
|
|
189
|
+
line?: number | null;
|
|
190
|
+
start_line?: number | null;
|
|
191
|
+
original_line?: number | null;
|
|
192
|
+
original_start_line?: number | null;
|
|
193
|
+
};
|
|
194
|
+
|
|
195
|
+
/**
|
|
196
|
+
* GitHub review comment → {@link ExistingReviewComment}.
|
|
197
|
+
*
|
|
198
|
+
* Prefers the `original_*` fields — the path/lines/commit as of the review
|
|
199
|
+
* the comment belongs to. `line` drifts as the PR gains commits, so a
|
|
200
|
+
* caller correlating a comment with the review that produced it needs the
|
|
201
|
+
* original position, the same fields Bugbot carries on
|
|
202
|
+
* `PullRequestCommentOutput`.
|
|
203
|
+
*/
|
|
204
|
+
export function normalizeGithubReviewComment(
|
|
205
|
+
comment: GithubReviewCommentLike
|
|
206
|
+
): ExistingReviewComment | undefined {
|
|
207
|
+
// Take both lines from the same position set. Mixing them (original end
|
|
208
|
+
// line with the drifted current start line) would describe a range that
|
|
209
|
+
// never existed in either revision.
|
|
210
|
+
const original = comment.original_line ?? undefined;
|
|
211
|
+
const endLine = original ?? comment.line ?? undefined;
|
|
212
|
+
if (endLine === undefined || endLine === null) {
|
|
213
|
+
return undefined;
|
|
214
|
+
}
|
|
215
|
+
const startLine =
|
|
216
|
+
(original === undefined
|
|
217
|
+
? comment.start_line
|
|
218
|
+
: comment.original_start_line) ?? endLine;
|
|
219
|
+
return {
|
|
220
|
+
id: comment.id,
|
|
221
|
+
file: comment.path,
|
|
222
|
+
startLine,
|
|
223
|
+
endLine,
|
|
224
|
+
body: comment.body,
|
|
225
|
+
};
|
|
226
|
+
}
|
|
227
|
+
|
|
44
228
|
type ParsedGithubPrUrl = {
|
|
45
229
|
repo: string;
|
|
46
230
|
prNumber: number;
|
|
@@ -148,6 +332,15 @@ async function postReviewViaHostGithub(
|
|
|
148
332
|
detail: htmlUrl
|
|
149
333
|
? `posted via host GitHub: ${htmlUrl}`
|
|
150
334
|
: `posted via host GitHub with ${inlineCommentCount} inline comment(s)`,
|
|
335
|
+
postedComments: await readPostedComments({
|
|
336
|
+
octokit,
|
|
337
|
+
owner,
|
|
338
|
+
repo,
|
|
339
|
+
prNumber: request.prNumber,
|
|
340
|
+
reviewId: response.data.id,
|
|
341
|
+
expected: inlineCommentCount,
|
|
342
|
+
signal: args.signal,
|
|
343
|
+
}),
|
|
151
344
|
};
|
|
152
345
|
} catch (error) {
|
|
153
346
|
if (args.signal?.aborted) {
|
|
@@ -159,6 +352,58 @@ async function postReviewViaHostGithub(
|
|
|
159
352
|
}
|
|
160
353
|
}
|
|
161
354
|
|
|
355
|
+
/**
|
|
356
|
+
* Ids of the inline comments a just-created review owns.
|
|
357
|
+
*
|
|
358
|
+
* `pulls.createReview` returns the review, not its comments, so they come
|
|
359
|
+
* from the review-scoped listing. Scoping to the review matters: the
|
|
360
|
+
* PR-wide list is ordered oldest-first and runs to thousands on a busy PR,
|
|
361
|
+
* so the comments we just created are the ones a page cap would drop.
|
|
362
|
+
* Best-effort: any failure yields an empty list, which costs the next run
|
|
363
|
+
* its prior findings rather than risking a wrong id. Never throws — the
|
|
364
|
+
* review is already posted by this point.
|
|
365
|
+
*/
|
|
366
|
+
async function readPostedComments(args: {
|
|
367
|
+
octokit: Awaited<ReturnType<HostGitHubClient["getOctokit"]>>;
|
|
368
|
+
owner: string;
|
|
369
|
+
repo: string;
|
|
370
|
+
prNumber: number;
|
|
371
|
+
reviewId: number;
|
|
372
|
+
expected: number;
|
|
373
|
+
signal?: AbortSignal;
|
|
374
|
+
}): Promise<PostedReviewComment[]> {
|
|
375
|
+
if (args.expected === 0) {
|
|
376
|
+
return [];
|
|
377
|
+
}
|
|
378
|
+
try {
|
|
379
|
+
const posted: PostedReviewComment[] = [];
|
|
380
|
+
for (let page = 1; page <= REVIEW_COMMENTS_MAX_PAGES; page++) {
|
|
381
|
+
args.signal?.throwIfAborted();
|
|
382
|
+
const response = await args.octokit.rest.pulls.listCommentsForReview({
|
|
383
|
+
owner: args.owner,
|
|
384
|
+
repo: args.repo,
|
|
385
|
+
pull_number: args.prNumber,
|
|
386
|
+
review_id: args.reviewId,
|
|
387
|
+
per_page: REVIEW_COMMENTS_PAGE_SIZE,
|
|
388
|
+
page,
|
|
389
|
+
});
|
|
390
|
+
for (const comment of response.data) {
|
|
391
|
+
const line = comment.original_line ?? comment.line;
|
|
392
|
+
if (line === null || line === undefined) {
|
|
393
|
+
continue;
|
|
394
|
+
}
|
|
395
|
+
posted.push({ id: comment.id, file: comment.path, line });
|
|
396
|
+
}
|
|
397
|
+
if (response.data.length < REVIEW_COMMENTS_PAGE_SIZE) {
|
|
398
|
+
break;
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
return posted;
|
|
402
|
+
} catch {
|
|
403
|
+
return [];
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
|
|
162
407
|
async function postReviewViaLocalGh(
|
|
163
408
|
args: ReviewCommentPostArgs
|
|
164
409
|
): Promise<ReviewCommentPostResult> {
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MCP tool-name sanitization shared by the Cursor-account bridge
|
|
3
|
+
* (`account-mcp.ts`) and advertised connections (`advertise-tools.ts`).
|
|
4
|
+
*
|
|
5
|
+
* Connector display names — and the aggregate `/v1/agent/mcp` names minted
|
|
6
|
+
* from them (`<serverIdentifier>-<tool>`) — can contain spaces, dots, and
|
|
7
|
+
* other characters that are illegal as the tool name a model sees.
|
|
8
|
+
*
|
|
9
|
+
* Character class matches `packages/agent` `normalizeMcpToolName`
|
|
10
|
+
* (`[^a-zA-Z0-9_-]` → `_`). Length cap and the empty fallback match the
|
|
11
|
+
* account bridge (MCP clients commonly enforce `^[a-zA-Z0-9_-]{1,128}$`).
|
|
12
|
+
* Callers that talk to the backend keep the original advertised name.
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
/** MCP clients commonly enforce `^[a-zA-Z0-9_-]{1,128}$` for tool names. */
|
|
16
|
+
export const MAX_MCP_TOOL_NAME_LENGTH = 128;
|
|
17
|
+
|
|
18
|
+
/** Connector display names can contain anything (spaces, dots, emoji). */
|
|
19
|
+
export function sanitizeMcpToolName(name: string): string {
|
|
20
|
+
const cleaned = name
|
|
21
|
+
.replace(/[^a-zA-Z0-9_-]/g, "_")
|
|
22
|
+
.slice(0, MAX_MCP_TOOL_NAME_LENGTH);
|
|
23
|
+
return cleaned === "" ? "tool" : cleaned;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/** `base` for the first claimant, `base_2` / `base_3` … for colliders. */
|
|
27
|
+
export function suffixMcpToolName(base: string, index: number): string {
|
|
28
|
+
if (index === 0) {
|
|
29
|
+
return base;
|
|
30
|
+
}
|
|
31
|
+
const suffix = `_${index + 1}`;
|
|
32
|
+
return `${base.slice(0, MAX_MCP_TOOL_NAME_LENGTH - suffix.length)}${suffix}`;
|
|
33
|
+
}
|
|
@@ -14,12 +14,12 @@ import {
|
|
|
14
14
|
type CloudAgentOptions,
|
|
15
15
|
Cursor,
|
|
16
16
|
createAgentPlatform,
|
|
17
|
-
JsonlLocalAgentStore,
|
|
18
17
|
type LocalAgentStore,
|
|
19
18
|
type ModelSelection,
|
|
20
19
|
type RunResult,
|
|
21
20
|
type SDKAgent,
|
|
22
21
|
} from "@cursor/sdk";
|
|
22
|
+
import { SqliteLocalAgentStore } from "@cursor/sdk/sqlite";
|
|
23
23
|
import {
|
|
24
24
|
DEFAULT_MODEL,
|
|
25
25
|
type ModelSetting,
|
|
@@ -558,8 +558,11 @@ export class CursorSdkRunner implements AgentRunner {
|
|
|
558
558
|
private getStore(stateDir: string): Promise<LocalAgentStore> {
|
|
559
559
|
let storePromise = this.stores.get(stateDir);
|
|
560
560
|
if (storePromise === undefined) {
|
|
561
|
-
storePromise = mkdir(stateDir, { recursive: true }).then(
|
|
562
|
-
(
|
|
561
|
+
storePromise = mkdir(stateDir, { recursive: true }).then(() =>
|
|
562
|
+
SqliteLocalAgentStore.open({
|
|
563
|
+
stateRoot: stateDir,
|
|
564
|
+
workspaceRef: stateDir,
|
|
565
|
+
})
|
|
563
566
|
);
|
|
564
567
|
this.stores.set(stateDir, storePromise);
|
|
565
568
|
}
|
|
@@ -2327,6 +2327,13 @@ export class SessionEngine {
|
|
|
2327
2327
|
tools[tool.name] = {
|
|
2328
2328
|
description: tool.description,
|
|
2329
2329
|
inputSchema: tool.inputSchema as SDKCustomTool["inputSchema"],
|
|
2330
|
+
// `SDKCustomTool.outputSchema` ships in the next published
|
|
2331
|
+
// @cursor/sdk; the conditional spread carries the field through the
|
|
2332
|
+
// pinned SDK's type until the dependency bumps, at which point local
|
|
2333
|
+
// runs start advertising it.
|
|
2334
|
+
...(tool.outputSchema === undefined
|
|
2335
|
+
? {}
|
|
2336
|
+
: { outputSchema: tool.outputSchema }),
|
|
2330
2337
|
execute: async (args, context) => {
|
|
2331
2338
|
return this.executeServerTool({
|
|
2332
2339
|
tool,
|