@cursor/july 0.1.87 → 0.1.88

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.
Files changed (49) hide show
  1. package/dist/bin/agent-serve.js +7 -0
  2. package/dist/internal/advertise-tools.d.ts.map +1 -1
  3. package/dist/internal/advertise-tools.js +4 -2
  4. package/dist/internal/cli-docs.js +11 -0
  5. package/dist/internal/cloud-merge.d.ts +3 -1
  6. package/dist/internal/cloud-merge.d.ts.map +1 -1
  7. package/dist/internal/cloud-merge.js +10 -2
  8. package/dist/internal/cursor/backend-client.d.ts +4 -0
  9. package/dist/internal/cursor/backend-client.d.ts.map +1 -1
  10. package/dist/internal/cursor/backend-client.js +4 -0
  11. package/dist/internal/discovery.d.ts.map +1 -1
  12. package/dist/internal/discovery.js +87 -11
  13. package/dist/internal/docs-site.d.ts +13 -2
  14. package/dist/internal/docs-site.d.ts.map +1 -1
  15. package/dist/internal/docs-site.js +76 -13
  16. package/dist/internal/grokbot/runner.d.ts +61 -0
  17. package/dist/internal/grokbot/runner.d.ts.map +1 -0
  18. package/dist/internal/grokbot/runner.js +278 -0
  19. package/dist/internal/mcp-endpoint.js +4 -2
  20. package/dist/internal/mcp-host.d.ts +14 -1
  21. package/dist/internal/mcp-host.d.ts.map +1 -1
  22. package/dist/internal/mcp-host.js +41 -2
  23. package/dist/internal/runtime-dispatch-runner.d.ts +30 -0
  24. package/dist/internal/runtime-dispatch-runner.d.ts.map +1 -0
  25. package/dist/internal/runtime-dispatch-runner.js +60 -0
  26. package/dist/internal/sdk-runner.d.ts.map +1 -1
  27. package/dist/internal/sdk-runner.js +7 -0
  28. package/dist/internal/server.d.ts.map +1 -1
  29. package/dist/internal/server.js +24 -1
  30. package/dist/internal/session-engine.d.ts.map +1 -1
  31. package/dist/internal/session-engine.js +36 -18
  32. package/dist/types.d.ts +64 -2
  33. package/dist/types.d.ts.map +1 -1
  34. package/package.json +1 -1
  35. package/src/bin/agent-serve.ts +8 -0
  36. package/src/internal/advertise-tools.ts +6 -0
  37. package/src/internal/cli-docs.ts +11 -0
  38. package/src/internal/cloud-merge.ts +12 -2
  39. package/src/internal/cursor/backend-client.ts +4 -0
  40. package/src/internal/discovery.ts +133 -13
  41. package/src/internal/docs-site.ts +83 -13
  42. package/src/internal/grokbot/runner.ts +361 -0
  43. package/src/internal/mcp-endpoint.ts +4 -0
  44. package/src/internal/mcp-host.ts +48 -0
  45. package/src/internal/runtime-dispatch-runner.ts +63 -0
  46. package/src/internal/sdk-runner.ts +9 -0
  47. package/src/internal/server.ts +32 -4
  48. package/src/internal/session-engine.ts +40 -15
  49. package/src/types.ts +65 -2
@@ -35,6 +35,7 @@ import {
35
35
  } from "../files-backends/cursor-hosted.js";
36
36
  import {
37
37
  type AgentProject,
38
+ type AgentRuntime,
38
39
  type ApprovalDecision,
39
40
  type ArtifactListFilter,
40
41
  type ArtifactRecord,
@@ -1916,28 +1917,29 @@ export class SessionEngine {
1916
1917
  agentRuntime: agent.runtime,
1917
1918
  cloudOverride: record.cloudOverride,
1918
1919
  });
1919
- // Fail closed: the SDK cannot enforce the built-in tool allowlist on
1920
- // cloud agents yet, and a restriction that silently does not apply is
1921
- // worse than a refused turn. Cloud-runtime agents already fail
1922
- // discovery; this guards hybrid agents' per-send cloud sessions.
1923
- if (runtime === "cloud" && agent.allowedTools !== undefined) {
1920
+ // Fail closed: only the local harness can enforce the built-in tool
1921
+ // allowlist, and a restriction that silently does not apply is worse
1922
+ // than a refused turn. Non-local agents already fail discovery; this
1923
+ // guards hybrid agents' per-send cloud sessions.
1924
+ if (runtime !== "local" && agent.allowedTools !== undefined) {
1924
1925
  throw new Error(
1925
- `Agent "${agent.name}" declares a built-in tool allowlist (tools), which cannot be enforced on cloud turns yet. Refusing the cloud session rather than running it unrestricted.`
1926
+ `Agent "${agent.name}" declares a built-in tool allowlist (tools), which cannot be enforced on ${runtime} turns. Refusing the session rather than running it unrestricted.`
1926
1927
  );
1927
1928
  }
1928
1929
  // Same fail-closed posture for per-session connection features:
1929
1930
  // advertised tools are server tools (in-process, local turns only) and
1930
- // per-session auth headers cannot reach a cloud VM's MCP config. A turn
1931
- // that silently runs without its per-session tools or identity is worse
1932
- // than a refused one. Cloud-runtime agents already fail discovery; this
1933
- // guards hybrid agents' per-send cloud sessions.
1931
+ // per-session auth headers cannot reach a cloud VM's (or the Grok Bot
1932
+ // harness's) MCP config. A turn that silently runs without its
1933
+ // per-session tools or identity is worse than a refused one. Non-local
1934
+ // agents already fail discovery; this guards hybrid agents' per-send
1935
+ // cloud sessions.
1934
1936
  const perSessionConnection = agent.connections.find(
1935
1937
  (connection) =>
1936
1938
  connection.advertiseTools === true || connection.auth !== undefined
1937
1939
  );
1938
- if (runtime === "cloud" && perSessionConnection !== undefined) {
1940
+ if (runtime !== "local" && perSessionConnection !== undefined) {
1939
1941
  throw new Error(
1940
- `Agent "${agent.name}" connection "${perSessionConnection.name}" uses advertiseTools/auth, which only run on local turns. Refusing the cloud session rather than running it without the connection's tools or identity.`
1942
+ `Agent "${agent.name}" connection "${perSessionConnection.name}" uses advertiseTools/auth, which only run on local turns. Refusing the session rather than running it without the connection's tools or identity.`
1941
1943
  );
1942
1944
  }
1943
1945
  const mergedCloud =
@@ -1986,11 +1988,13 @@ export class SessionEngine {
1986
1988
  ? `\n\n${buildCloudMemorySection(this.project.name)}`
1987
1989
  : "";
1988
1990
  turnPrompt = `${preamble}${memorySection}\n\n${turnPrompt}`;
1989
- } else if (instructionsInvisibleToHarness) {
1991
+ } else if (runtime === "local" && instructionsInvisibleToHarness) {
1990
1992
  // Local workspace whose AGENTS.md the harness will not load. With a
1991
1993
  // borrowed harness cwd, agent tool scripts live only in the durable
1992
1994
  // scaffold dir — embed bodies like cloud. Otherwise the catalog can
1993
- // reference on-disk paths under the harness cwd.
1995
+ // reference on-disk paths under the harness cwd. Grokbot turns are
1996
+ // excluded: their instructions ride the request's `instructions`
1997
+ // field into the Sand system prompt instead.
1994
1998
  const includeScripts = this.hasBorrowedWorkspace(record);
1995
1999
  const preamble = buildAgentsMdContent(agent, { includeScripts });
1996
2000
  turnPrompt = `${preamble}\n\n${turnPrompt}`;
@@ -2012,7 +2016,17 @@ export class SessionEngine {
2012
2016
  ...(images !== undefined && images.length > 0 ? { images } : {}),
2013
2017
  ...(agent.model === undefined ? {} : { model: agent.model }),
2014
2018
  runtime,
2019
+ agentName: agent.name,
2015
2020
  ...(mergedCloud === undefined ? {} : { cloud: mergedCloud }),
2021
+ // The hosted Grok Bot harness reads no workspace AGENTS.md: grokbot
2022
+ // turns carry the composed instructions into the hosted session,
2023
+ // which surfaces them in the Sand system prompt. The box never sees
2024
+ // the local session workspace, so agent-tool script bodies are
2025
+ // always embedded — same rule as the cloud first-prompt preamble.
2026
+ instructions:
2027
+ runtime === "grokbot"
2028
+ ? buildAgentsMdContent(agent, { includeScripts: true })
2029
+ : undefined,
2016
2030
  ...(runtime === "cloud" && !isCursorHostedFilesAvailable()
2017
2031
  ? { agentServeAgent: this.project.name }
2018
2032
  : {}),
@@ -2135,10 +2149,15 @@ export class SessionEngine {
2135
2149
  * being omitted or failing the turn closed.
2136
2150
  */
2137
2151
  private buildMcpServers(
2138
- runtime: "local" | "cloud",
2152
+ runtime: AgentRuntime,
2139
2153
  sessionId?: string,
2140
2154
  sessionAuth?: ReadonlyMap<string, Record<string, string>>
2141
2155
  ): Record<string, ConnectionTransport> {
2156
+ // The Grok Bot harness manages its own MCP surface; authored
2157
+ // connections are refused at discovery, so there is nothing to mount.
2158
+ if (runtime === "grokbot") {
2159
+ return {};
2160
+ }
2142
2161
  // Advertised connections surface as named server tools instead of an
2143
2162
  // attached MCP server (each tool appears exactly once), so they are
2144
2163
  // excluded here alongside hostOnly.
@@ -2326,6 +2345,12 @@ export class SessionEngine {
2326
2345
  ...(tool.outputSchema === undefined
2327
2346
  ? {}
2328
2347
  : { outputSchema: tool.outputSchema }),
2348
+ // Same pinned-SDK carry for `SDKCustomTool.annotations`: an advertised
2349
+ // MCP passthrough's server-declared hints (bounded at listing time)
2350
+ // ride into the harness listing once the dependency bumps.
2351
+ ...(tool.annotations === undefined
2352
+ ? {}
2353
+ : { annotations: tool.annotations }),
2329
2354
  execute: async (args, context) => {
2330
2355
  return this.executeServerTool({
2331
2356
  tool,
package/src/types.ts CHANGED
@@ -95,9 +95,14 @@ export const DEFAULT_MODEL: ModelSetting = {
95
95
 
96
96
  /**
97
97
  * Where turns execute. `"local"` (default) uses the Cursor SDK local
98
- * harness on this machine; `"cloud"` runs on Cursor cloud agents.
98
+ * harness on this machine; `"cloud"` runs on Cursor cloud agents;
99
+ * `"grokbot"` runs on Cursor's hosted Grok Bot (Sand) harness with the
100
+ * account's own computer (box) — the SDK is a thin client over the
101
+ * `/v0/grokbot` session API, and the user-visible reply is whatever the
102
+ * agent delivers through its SendToUser tool. The hosted harness picks
103
+ * the model; {@link AgentConfig.model} does not apply to grokbot turns.
99
104
  */
100
- export type AgentRuntime = "local" | "cloud";
105
+ export type AgentRuntime = "local" | "cloud" | "grokbot";
101
106
 
102
107
  /**
103
108
  * Cloud-only options forwarded to the Cursor SDK's `cloud` field on
@@ -473,11 +478,39 @@ export interface HostMcpRegistry {
473
478
  ): Promise<HostMcpCallResult>;
474
479
  }
475
480
 
481
+ /**
482
+ * MCP spec tool annotations (`Tool.annotations`, 2025-03-26 revision).
483
+ *
484
+ * A closed type on purpose: these are exactly the fields listing-time
485
+ * bounding keeps, so the type matches what a reader can ever see — and the
486
+ * hints are behavioral, so a misspelled or wrong-typed key must not
487
+ * masquerade as a declaration.
488
+ */
489
+ export interface McpToolAnnotations {
490
+ /** Human-readable display name for the tool, length-capped at listing. */
491
+ title?: string;
492
+ /** The tool does not modify its environment. */
493
+ readOnlyHint?: boolean;
494
+ /** The tool may perform destructive updates (meaningful when not read-only). */
495
+ destructiveHint?: boolean;
496
+ /** Repeated calls with the same arguments have no additional effect. */
497
+ idempotentHint?: boolean;
498
+ /** The tool may interact with an open world of external entities. */
499
+ openWorldHint?: boolean;
500
+ }
501
+
476
502
  export interface HostMcpToolInfo {
477
503
  name: string;
478
504
  description?: string;
479
505
  inputSchema?: JsonObject;
480
506
  outputSchema?: JsonObject;
507
+ /**
508
+ * MCP spec tool annotations, bounded at listing time to the
509
+ * {@link McpToolAnnotations} fields. Untrusted server hints — consumers
510
+ * that classify on them must fail closed when absent, and absent is
511
+ * exactly what a server that declares nothing produces.
512
+ */
513
+ annotations?: McpToolAnnotations;
481
514
  }
482
515
 
483
516
  export interface HostMcpCallResult {
@@ -2579,6 +2612,14 @@ export interface DiscoveredTool {
2579
2612
  * declares nothing, which a dry run treats as a write.
2580
2613
  */
2581
2614
  effect?: ToolEffect | "dynamic";
2615
+ /**
2616
+ * MCP spec tool annotations, present only on advertised MCP passthroughs
2617
+ * whose server declared them (see {@link HostMcpToolInfo.annotations}).
2618
+ * Authored tools declare {@link effect} instead. Untrusted hints,
2619
+ * propagated so the harness listing carries them and so effect
2620
+ * classification can read them; absent is the fail-closed state.
2621
+ */
2622
+ annotations?: McpToolAnnotations;
2582
2623
  /**
2583
2624
  * Agent tools: script body materialized under
2584
2625
  * `.agent-serve/tools/<name>.sh`.
@@ -2840,8 +2881,22 @@ export interface RunnerTurnRequest {
2840
2881
  images?: Array<{ data: string; mimeType: string }>;
2841
2882
  model?: ModelSetting;
2842
2883
  runtime: AgentRuntime;
2884
+ /**
2885
+ * The agent's display name. Grokbot turns address the caller's hosted
2886
+ * Grok Bot agent of this name: every SDK session of one agent forwards
2887
+ * into the same hosted agent and conversation.
2888
+ */
2889
+ agentName?: string;
2843
2890
  /** Cloud options when {@link runtime} is `"cloud"`. */
2844
2891
  cloud?: AgentCloudOptions;
2892
+ /**
2893
+ * Composed instructions ({@link ResolvedAgent.instructions}) for runtimes
2894
+ * whose harness cannot read the workspace `AGENTS.md` — grokbot turns
2895
+ * carry them into the hosted session so they reach the Sand system
2896
+ * prompt. Local turns read the materialized workspace instead and leave
2897
+ * this unset.
2898
+ */
2899
+ instructions?: string;
2845
2900
  /**
2846
2901
  * defineAgent directory slug for personal-key cloud creates. Injected
2847
2902
  * by the engine — not part of authored {@link AgentCloudOptions}.
@@ -2962,6 +3017,14 @@ export interface ServeOptions {
2962
3017
  * SSO/Okta proxy in front of the host).
2963
3018
  */
2964
3019
  allowAnonymousCursorGithub?: boolean;
3020
+ /**
3021
+ * Allow `--allow-anonymous` together with a `runtime: "grokbot"` mount.
3022
+ * Off by default: grokbot turns execute on the signed-in account's hosted
3023
+ * Grok Bot computer, so an anonymous caller could drive Shell and other
3024
+ * box tools there. Set it only when the network boundary already
3025
+ * authenticates callers (e.g. an SSO/Okta proxy in front of the host).
3026
+ */
3027
+ allowAnonymousGrokbot?: boolean;
2965
3028
  /**
2966
3029
  * Route `githubChannel({ cursorAccount })` API calls through the Cursor
2967
3030
  * backend's GitHub forwarder (`/v0/github-proxy`) instead of minting raw