@cursor/july 0.1.9 → 0.1.11

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 (200) hide show
  1. package/AGENTS.md +1 -0
  2. package/dist/bin/agent-serve.js +26 -3
  3. package/dist/channels/github/github-channel.d.ts.map +1 -1
  4. package/dist/channels/github/github-channel.js +2 -1
  5. package/dist/channels/github/types.d.ts +4 -0
  6. package/dist/channels/github/types.d.ts.map +1 -1
  7. package/dist/channels/slack/cursor-account.d.ts.map +1 -1
  8. package/dist/channels/slack/cursor-account.js +1 -1
  9. package/dist/channels/slack/dispatch.d.ts +13 -0
  10. package/dist/channels/slack/dispatch.d.ts.map +1 -1
  11. package/dist/channels/slack/dispatch.js +36 -11
  12. package/dist/channels/slack/eval-directive.d.ts +63 -0
  13. package/dist/channels/slack/eval-directive.d.ts.map +1 -0
  14. package/dist/channels/slack/eval-directive.js +283 -0
  15. package/dist/channels/slack/index.d.ts +1 -0
  16. package/dist/channels/slack/index.d.ts.map +1 -1
  17. package/dist/channels/slack/index.js +1 -0
  18. package/dist/channels/slack/slack-channel.d.ts.map +1 -1
  19. package/dist/channels/slack/slack-channel.js +4 -2
  20. package/dist/channels/slack/types.d.ts +7 -0
  21. package/dist/channels/slack/types.d.ts.map +1 -1
  22. package/dist/connections.d.ts +10 -5
  23. package/dist/connections.d.ts.map +1 -1
  24. package/dist/connections.js +10 -5
  25. package/dist/docs/404.html +2 -2
  26. package/dist/docs/ab.html +4 -4
  27. package/dist/docs/assets/{app.Ciosf24M.js → app.BcXUGca7.js} +1 -1
  28. package/dist/docs/assets/chunks/@localSearchIndexroot.BIbvK8M1.js +1 -0
  29. package/dist/docs/assets/chunks/{VPLocalSearchBox.BcRDly7n.js → VPLocalSearchBox.CWur6XGZ.js} +1 -1
  30. package/dist/docs/assets/chunks/{theme.CMpbjdfx.js → theme.BnvulOX2.js} +2 -2
  31. package/dist/docs/assets/{deployment.md.DC5-ImcM.js → deployment.md.TecHo0_2.js} +3 -3
  32. package/dist/docs/assets/{deployment.md.DC5-ImcM.lean.js → deployment.md.TecHo0_2.lean.js} +1 -1
  33. package/dist/docs/assets/guides_mcp-oauth.md.DqmEOQY1.js +29 -0
  34. package/dist/docs/assets/guides_mcp-oauth.md.DqmEOQY1.lean.js +1 -0
  35. package/dist/docs/assets/{index.md.COiu-1jL.js → index.md.t0TM2Qzz.js} +3 -3
  36. package/dist/docs/assets/{index.md.COiu-1jL.lean.js → index.md.t0TM2Qzz.lean.js} +1 -1
  37. package/dist/docs/assets/{reference_cli.md.D189RBCH.js → reference_cli.md.B74NrVzb.js} +5 -4
  38. package/dist/docs/assets/{reference_cli.md.D189RBCH.lean.js → reference_cli.md.B74NrVzb.lean.js} +1 -1
  39. package/dist/docs/assets/{reference_connections.md.zaEYCLHT.js → reference_connections.md.CsSr3rDz.js} +9 -4
  40. package/dist/docs/assets/{reference_connections.md.zaEYCLHT.lean.js → reference_connections.md.CsSr3rDz.lean.js} +1 -1
  41. package/dist/docs/assets/reference_prompt.md.BaiweQxE.js +1 -0
  42. package/dist/docs/assets/reference_prompt.md.BaiweQxE.lean.js +1 -0
  43. package/dist/docs/assets/{reference_tools.md.CqgJroI0.js → reference_tools.md.BRSDnTbN.js} +16 -3
  44. package/dist/docs/assets/{reference_tools.md.CqgJroI0.lean.js → reference_tools.md.BRSDnTbN.lean.js} +1 -1
  45. package/dist/docs/assets/{troubleshooting.md.DkovjS7h.js → troubleshooting.md.CmQkmnzC.js} +1 -1
  46. package/dist/docs/assets/{troubleshooting.md.DkovjS7h.lean.js → troubleshooting.md.CmQkmnzC.lean.js} +1 -1
  47. package/dist/docs/building-with-agents.html +4 -4
  48. package/dist/docs/concepts.html +4 -4
  49. package/dist/docs/deployment.html +7 -7
  50. package/dist/docs/evals.html +4 -4
  51. package/dist/docs/example-agents/approval-buddy.html +4 -4
  52. package/dist/docs/example-agents/benny.html +4 -4
  53. package/dist/docs/example-agents/bugbot.html +4 -4
  54. package/dist/docs/example-agents/codebase-wiki.html +4 -4
  55. package/dist/docs/example-agents/codeowners-review.html +4 -4
  56. package/dist/docs/example-agents/concierge.html +4 -4
  57. package/dist/docs/example-agents/fsd.html +4 -4
  58. package/dist/docs/example-agents/index.html +4 -4
  59. package/dist/docs/example-agents/knowledge-base.html +4 -4
  60. package/dist/docs/example-agents/oncall.html +4 -4
  61. package/dist/docs/example-agents/security-reviewer.html +4 -4
  62. package/dist/docs/example-agents/slack-agent.html +4 -4
  63. package/dist/docs/example-agents/weather-agent.html +4 -4
  64. package/dist/docs/guides/agent-to-agent.html +4 -4
  65. package/dist/docs/guides/cloud-runtime.html +4 -4
  66. package/dist/docs/guides/github.html +4 -4
  67. package/dist/docs/guides/human-in-the-loop.html +4 -4
  68. package/dist/docs/guides/mcp-oauth.html +53 -0
  69. package/dist/docs/guides/slack.html +4 -4
  70. package/dist/docs/guides/webhooks.html +4 -4
  71. package/dist/docs/hashmap.json +1 -1
  72. package/dist/docs/hillclimbing.html +4 -4
  73. package/dist/docs/index.html +6 -6
  74. package/dist/docs/quickstart.html +4 -4
  75. package/dist/docs/reference/agent-config.html +4 -4
  76. package/dist/docs/reference/channels.html +4 -4
  77. package/dist/docs/reference/cli.html +8 -7
  78. package/dist/docs/reference/connections.html +13 -8
  79. package/dist/docs/reference/hooks.html +4 -4
  80. package/dist/docs/reference/http-api.html +4 -4
  81. package/dist/docs/reference/instructions.html +4 -4
  82. package/dist/docs/reference/playground.html +4 -4
  83. package/dist/docs/reference/project-layout.html +4 -4
  84. package/dist/docs/reference/prompt.html +33 -0
  85. package/dist/docs/reference/schedules.html +4 -4
  86. package/dist/docs/reference/sessions.html +4 -4
  87. package/dist/docs/reference/skills.html +5 -5
  88. package/dist/docs/reference/subagents.html +4 -4
  89. package/dist/docs/reference/tools.html +20 -7
  90. package/dist/docs/scaffolding-agents.html +4 -4
  91. package/dist/docs/storage.html +4 -4
  92. package/dist/docs/troubleshooting.html +5 -5
  93. package/dist/evals.d.ts +39 -0
  94. package/dist/evals.d.ts.map +1 -1
  95. package/dist/index.d.ts +3 -1
  96. package/dist/index.d.ts.map +1 -1
  97. package/dist/index.js +2 -1
  98. package/dist/internal/cli-ax.d.ts.map +1 -1
  99. package/dist/internal/cli-ax.js +7 -4
  100. package/dist/internal/cli-mcp-oauth.d.ts +16 -0
  101. package/dist/internal/cli-mcp-oauth.d.ts.map +1 -0
  102. package/dist/internal/cli-mcp-oauth.js +194 -0
  103. package/dist/internal/cli-mcp.d.ts +4 -1
  104. package/dist/internal/cli-mcp.d.ts.map +1 -1
  105. package/dist/internal/cli-mcp.js +19 -1
  106. package/dist/internal/corp-ca.d.ts +9 -0
  107. package/dist/internal/corp-ca.d.ts.map +1 -0
  108. package/dist/internal/corp-ca.js +44 -0
  109. package/dist/internal/cursor/account-mcp.d.ts +17 -4
  110. package/dist/internal/cursor/account-mcp.d.ts.map +1 -1
  111. package/dist/internal/cursor/account-mcp.js +105 -17
  112. package/dist/internal/discovery.d.ts.map +1 -1
  113. package/dist/internal/discovery.js +64 -10
  114. package/dist/internal/distribution.d.ts.map +1 -1
  115. package/dist/internal/distribution.js +1 -0
  116. package/dist/internal/logs-client.js +1 -1
  117. package/dist/internal/mcp-host.d.ts.map +1 -1
  118. package/dist/internal/mcp-host.js +49 -26
  119. package/dist/internal/mcp-oauth.d.ts +88 -0
  120. package/dist/internal/mcp-oauth.d.ts.map +1 -0
  121. package/dist/internal/mcp-oauth.js +385 -0
  122. package/dist/internal/resolved-connections.d.ts +6 -0
  123. package/dist/internal/resolved-connections.d.ts.map +1 -1
  124. package/dist/internal/resolved-connections.js +10 -3
  125. package/dist/internal/sdk-runner.d.ts +9 -0
  126. package/dist/internal/sdk-runner.d.ts.map +1 -1
  127. package/dist/internal/sdk-runner.js +28 -2
  128. package/dist/internal/server.d.ts.map +1 -1
  129. package/dist/internal/server.js +24 -6
  130. package/dist/internal/session-engine.d.ts +30 -10
  131. package/dist/internal/session-engine.d.ts.map +1 -1
  132. package/dist/internal/session-engine.js +166 -74
  133. package/dist/internal/sessions-client.d.ts +16 -2
  134. package/dist/internal/sessions-client.d.ts.map +1 -1
  135. package/dist/internal/sessions-client.js +30 -13
  136. package/dist/internal/storage-coordinator.d.ts +11 -0
  137. package/dist/internal/storage-coordinator.d.ts.map +1 -1
  138. package/dist/internal/storage-coordinator.js +30 -0
  139. package/dist/internal/stream-progress.d.ts.map +1 -1
  140. package/dist/internal/stream-progress.js +8 -4
  141. package/dist/internal/turn-governor.d.ts +54 -0
  142. package/dist/internal/turn-governor.d.ts.map +1 -0
  143. package/dist/internal/turn-governor.js +111 -0
  144. package/dist/playground/assets/{index-C0-QEG4O.js → index-BIGLubwK.js} +46 -46
  145. package/dist/playground/assets/{index-z3JY9O2x.css → index-C17ZQKDG.css} +1 -1
  146. package/dist/playground/index.html +2 -2
  147. package/dist/prompt.d.ts +39 -0
  148. package/dist/prompt.d.ts.map +1 -0
  149. package/dist/prompt.js +70 -0
  150. package/dist/storage-backends/cursor-hosted.d.ts +10 -0
  151. package/dist/storage-backends/cursor-hosted.d.ts.map +1 -1
  152. package/dist/storage-backends/cursor-hosted.js +14 -0
  153. package/dist/types.d.ts +93 -5
  154. package/dist/types.d.ts.map +1 -1
  155. package/dist/types.js +6 -0
  156. package/docs/README.md +4 -0
  157. package/docs/deployment.md +6 -1
  158. package/docs/guides/mcp-oauth.md +157 -0
  159. package/docs/reference/cli.md +30 -0
  160. package/docs/reference/connections.md +32 -2
  161. package/docs/reference/prompt.md +47 -0
  162. package/docs/reference/tools.md +21 -0
  163. package/docs/troubleshooting.md +11 -0
  164. package/package.json +9 -2
  165. package/skills/create-agent/SKILL.md +7 -3
  166. package/skills/framework-map/SKILL.md +1 -0
  167. package/skills/mcp-auth/SKILL.md +138 -0
  168. package/src/bin/agent-serve.ts +30 -3
  169. package/src/channels/github/github-channel.ts +2 -0
  170. package/src/channels/github/types.ts +4 -0
  171. package/src/channels/slack/cursor-account.ts +2 -0
  172. package/src/channels/slack/dispatch.ts +49 -0
  173. package/src/channels/slack/eval-directive.ts +348 -0
  174. package/src/channels/slack/index.ts +1 -0
  175. package/src/channels/slack/slack-channel.ts +3 -0
  176. package/src/channels/slack/types.ts +7 -0
  177. package/src/connections.ts +10 -5
  178. package/src/evals.ts +43 -0
  179. package/src/index.ts +3 -0
  180. package/src/internal/cli-ax.ts +10 -4
  181. package/src/internal/cli-mcp-oauth.ts +254 -0
  182. package/src/internal/cli-mcp.ts +25 -2
  183. package/src/internal/cursor/account-mcp.ts +153 -41
  184. package/src/internal/discovery.ts +70 -8
  185. package/src/internal/distribution.ts +1 -0
  186. package/src/internal/logs-client.ts +1 -1
  187. package/src/internal/mcp-host.ts +33 -9
  188. package/src/internal/mcp-oauth.ts +496 -0
  189. package/src/internal/resolved-connections.ts +20 -5
  190. package/src/internal/sdk-runner.ts +37 -1
  191. package/src/internal/server.ts +28 -6
  192. package/src/internal/session-engine.ts +192 -76
  193. package/src/internal/sessions-client.ts +51 -15
  194. package/src/internal/storage-coordinator.ts +36 -0
  195. package/src/internal/stream-progress.ts +8 -0
  196. package/src/internal/turn-governor.ts +145 -0
  197. package/src/prompt.ts +83 -0
  198. package/src/storage-backends/cursor-hosted.ts +21 -0
  199. package/src/types.ts +92 -6
  200. package/dist/docs/assets/chunks/@localSearchIndexroot.D154Detj.js +0 -1
@@ -0,0 +1,145 @@
1
+ /**
2
+ * FIFO admission of model turns under `concurrency.maxRunningTurns`
3
+ * (see {@link AgentConcurrencyOptions}). One governor per session engine:
4
+ * every turn acquires a slot before its SDK run starts and releases it when
5
+ * the run settles, so at most `maxRunningTurns` turns execute at once and
6
+ * the rest wait in arrival order instead of failing.
7
+ *
8
+ * Waiting is cancellable: the engine passes the turn's abort signal, so a
9
+ * follow-up that preempts a queued turn (or an explicit `interrupt()`)
10
+ * removes the waiter without ever running it.
11
+ */
12
+
13
+ import type { AgentConcurrencyOptions } from "../types.js";
14
+
15
+ export interface TurnPermit {
16
+ /** Return the slot. Idempotent; wakes the oldest waiter, if any. */
17
+ release(): void;
18
+ }
19
+
20
+ export interface AcquireTurnSlotArgs {
21
+ sessionId: string;
22
+ /** Abort waiting (preemption / interrupt). Ignored once a slot is held. */
23
+ signal?: AbortSignal;
24
+ /**
25
+ * Called synchronously when the turn must wait, with its 1-based
26
+ * position among waiting turns at enqueue time.
27
+ */
28
+ onQueued?: (position: number) => void;
29
+ }
30
+
31
+ interface TurnWaiter {
32
+ sessionId: string;
33
+ grant: (permit: TurnPermit) => void;
34
+ cancel: () => void;
35
+ cleanup: () => void;
36
+ }
37
+
38
+ export class TurnGovernor {
39
+ /** The configured ceiling, or undefined for unlimited. */
40
+ readonly maxRunningTurns: number | undefined;
41
+ private running = 0;
42
+ private readonly waiters: TurnWaiter[] = [];
43
+ /** Sessions currently waiting for a slot (at most one turn per session). */
44
+ private readonly queuedSessions = new Set<string>();
45
+
46
+ constructor(concurrency: AgentConcurrencyOptions | undefined) {
47
+ this.maxRunningTurns = concurrency?.maxRunningTurns;
48
+ }
49
+
50
+ /** True when a `maxRunningTurns` ceiling is configured. */
51
+ get limited(): boolean {
52
+ return this.maxRunningTurns !== undefined;
53
+ }
54
+
55
+ /** True while `sessionId` has a turn waiting for a slot. */
56
+ isQueued(sessionId: string): boolean {
57
+ return this.queuedSessions.has(sessionId);
58
+ }
59
+
60
+ /** Turns currently waiting for a slot. */
61
+ get queuedCount(): number {
62
+ return this.waiters.length;
63
+ }
64
+
65
+ /** Turns currently holding a slot. */
66
+ get runningCount(): number {
67
+ return this.running;
68
+ }
69
+
70
+ /**
71
+ * Acquire a turn slot. Resolves with a permit once a slot is free (FIFO
72
+ * behind earlier waiters), or with `undefined` when the abort signal
73
+ * fires while waiting — the turn must then settle as cancelled without
74
+ * running. Unlimited governors grant immediately.
75
+ */
76
+ acquire(args: AcquireTurnSlotArgs): Promise<TurnPermit | undefined> {
77
+ const limit = this.maxRunningTurns;
78
+ if (limit === undefined) {
79
+ return Promise.resolve(NO_OP_PERMIT);
80
+ }
81
+ if (this.running < limit && this.waiters.length === 0) {
82
+ return Promise.resolve(this.grantSlot());
83
+ }
84
+ // Saturated. A turn that is already preempted never enqueues.
85
+ if (args.signal?.aborted === true) {
86
+ return Promise.resolve(undefined);
87
+ }
88
+ return new Promise<TurnPermit | undefined>((resolve) => {
89
+ const waiter: TurnWaiter = {
90
+ sessionId: args.sessionId,
91
+ grant: (permit) => resolve(permit),
92
+ cancel: () => resolve(undefined),
93
+ cleanup: () => {
94
+ this.queuedSessions.delete(args.sessionId);
95
+ args.signal?.removeEventListener("abort", onAbort);
96
+ },
97
+ };
98
+ const onAbort = (): void => {
99
+ const index = this.waiters.indexOf(waiter);
100
+ if (index === -1) {
101
+ return;
102
+ }
103
+ this.waiters.splice(index, 1);
104
+ waiter.cleanup();
105
+ waiter.cancel();
106
+ };
107
+ this.waiters.push(waiter);
108
+ this.queuedSessions.add(args.sessionId);
109
+ args.signal?.addEventListener("abort", onAbort, { once: true });
110
+ args.onQueued?.(this.waiters.length);
111
+ });
112
+ }
113
+
114
+ /** Take a slot and build its (idempotent) release handle. */
115
+ private grantSlot(): TurnPermit {
116
+ this.running += 1;
117
+ let released = false;
118
+ return {
119
+ release: () => {
120
+ if (released) {
121
+ return;
122
+ }
123
+ released = true;
124
+ this.running -= 1;
125
+ this.wakeNextWaiter();
126
+ },
127
+ };
128
+ }
129
+
130
+ private wakeNextWaiter(): void {
131
+ const limit = this.maxRunningTurns;
132
+ if (limit === undefined || this.running >= limit) {
133
+ return;
134
+ }
135
+ const waiter = this.waiters.shift();
136
+ if (waiter === undefined) {
137
+ return;
138
+ }
139
+ waiter.cleanup();
140
+ waiter.grant(this.grantSlot());
141
+ }
142
+ }
143
+
144
+ /** Permit handed out by unlimited governors. */
145
+ const NO_OP_PERMIT: TurnPermit = { release: () => {} };
package/src/prompt.ts ADDED
@@ -0,0 +1,83 @@
1
+ /**
2
+ * Dedented multi-line strings for prompts, errors, and tool descriptions.
3
+ *
4
+ * Indent the body to match surrounding TypeScript; the common leading
5
+ * whitespace is stripped. A leading newline after `` prompt` `` is dropped so
6
+ * the usual multiline form stays flush in source.
7
+ *
8
+ * ```ts
9
+ * import { prompt } from "@cursor/july";
10
+ *
11
+ * export default defineTool({
12
+ * description: prompt`
13
+ * Deploy Anyship services for a merged PR.
14
+ * Enforces HITL outside business hours.
15
+ * `,
16
+ * // ...
17
+ * });
18
+ *
19
+ * throw new Error(prompt`
20
+ * It is outside business hours.
21
+ * Use request_author_approval.
22
+ * `);
23
+ *
24
+ * // GitHub channel `context` wants string[]:
25
+ * context: prompt.lines`
26
+ * Merged PR detected: ${url}.
27
+ *
28
+ * Run the deploy flow.
29
+ * `
30
+ * ```
31
+ */
32
+
33
+ function dedentLines(
34
+ strings: TemplateStringsArray,
35
+ values: readonly unknown[]
36
+ ): string[] {
37
+ let text = "";
38
+ for (let i = 0; i < strings.length; i++) {
39
+ text += strings[i] ?? "";
40
+ if (i < values.length) {
41
+ text += String(values[i]);
42
+ }
43
+ }
44
+ // Common form is prompt`\n …\n`; drop the opening newline only.
45
+ if (text.startsWith("\n")) {
46
+ text = text.slice(1);
47
+ }
48
+ text = text.replace(/(?:\n[ \t]*)+$/u, "");
49
+
50
+ const lines = text.split("\n");
51
+ let minIndent = Number.POSITIVE_INFINITY;
52
+ for (const line of lines) {
53
+ if (line.trim() === "") {
54
+ continue;
55
+ }
56
+ const indent = /^[ \t]*/u.exec(line)?.[0]?.length ?? 0;
57
+ if (indent < minIndent) {
58
+ minIndent = indent;
59
+ }
60
+ }
61
+ if (!Number.isFinite(minIndent)) {
62
+ minIndent = 0;
63
+ }
64
+ return lines.map((line) => (line.trim() === "" ? "" : line.slice(minIndent)));
65
+ }
66
+
67
+ export type PromptTag = {
68
+ (strings: TemplateStringsArray, ...values: unknown[]): string;
69
+ /** Same as {@link prompt}, but as separate lines (e.g. GitHub `context`). */
70
+ lines(strings: TemplateStringsArray, ...values: unknown[]): string[];
71
+ };
72
+
73
+ /** Dedented multi-line string (blank lines preserved). */
74
+ export const prompt: PromptTag = Object.assign(
75
+ function prompt(strings: TemplateStringsArray, ...values: unknown[]): string {
76
+ return dedentLines(strings, values).join("\n");
77
+ },
78
+ {
79
+ lines(strings: TemplateStringsArray, ...values: unknown[]): string[] {
80
+ return dedentLines(strings, values);
81
+ },
82
+ }
83
+ );
@@ -80,9 +80,29 @@ export interface CursorHostedStorageOptions {
80
80
  fetch?: typeof fetch;
81
81
  }
82
82
 
83
+ /**
84
+ * Marker stamped on {@link cursorHostedStorage} so the engine can prefer
85
+ * durable Bugbot rows for `GET /v1/sessions` (survives `defineStorage` spread).
86
+ * Explicit `unique symbol` annotation required for `--isolatedDeclarations`
87
+ * (TS9010).
88
+ */
89
+ export const CURSOR_HOSTED_STORAGE: unique symbol = Symbol.for(
90
+ "@cursor/july.storage.cursor-hosted"
91
+ );
92
+
93
+ /** True when `value` is (or was built from) {@link cursorHostedStorage}. */
94
+ export function isCursorHostedStorage(value: unknown): boolean {
95
+ return (
96
+ typeof value === "object" &&
97
+ value !== null &&
98
+ (value as Record<symbol, unknown>)[CURSOR_HOSTED_STORAGE] === true
99
+ );
100
+ }
101
+
83
102
  type CursorHostedStorageMethods = Required<
84
103
  Pick<StorageConfig, "put" | "get" | "delete" | "list">
85
104
  > & {
105
+ readonly [CURSOR_HOSTED_STORAGE]: true;
86
106
  evals: StorageEvalsTable;
87
107
  abs: StorageABTable;
88
108
  };
@@ -155,6 +175,7 @@ export function cursorHostedStorage(
155
175
  options: CursorHostedStorageOptions = {}
156
176
  ): CursorHostedStorageMethods {
157
177
  return {
178
+ [CURSOR_HOSTED_STORAGE]: true,
158
179
  async put(key, value): Promise<void> {
159
180
  await storageRpc(options, "/internal/agent-serve/storage/kv/put", {
160
181
  key,
package/src/types.ts CHANGED
@@ -194,8 +194,45 @@ export interface AgentConfig {
194
194
  * it and sends it with the deployment request. Ignored by local serving.
195
195
  */
196
196
  hosting?: AgentHostingOptions;
197
+ /**
198
+ * Engine-wide turn admission limits. See {@link AgentConcurrencyOptions}.
199
+ */
200
+ concurrency?: AgentConcurrencyOptions;
201
+ }
202
+
203
+ /**
204
+ * Turn admission limits on {@link AgentConfig.concurrency}.
205
+ *
206
+ * ```ts
207
+ * export default defineAgent({
208
+ * // At most 3 sessions run a model turn at once; the rest queue FIFO.
209
+ * concurrency: { maxRunningTurns: 3 },
210
+ * });
211
+ * ```
212
+ */
213
+ export interface AgentConcurrencyOptions {
214
+ /**
215
+ * Max model turns running at once across **all** of this agent's
216
+ * sessions. When every slot is busy, newly admitted turns queue FIFO
217
+ * (surfaced as a durable `turn.queued` event and `queued: true` on
218
+ * `GET /v1/sessions`) instead of failing; each queued turn starts as
219
+ * soon as a slot frees. Positive integer, hard-capped at
220
+ * {@link MAX_RUNNING_TURNS_LIMIT}. Omit for unlimited.
221
+ *
222
+ * A queued turn still counts as `running` for busy semantics
223
+ * (follow-ups preempt it; direct tool calls get `SessionBusyError`),
224
+ * and a follow-up that preempts a queued turn re-queues at the back.
225
+ */
226
+ maxRunningTurns?: number;
197
227
  }
198
228
 
229
+ /**
230
+ * Hard ceiling for {@link AgentConcurrencyOptions.maxRunningTurns}.
231
+ * Matches the eval harness ceiling: each running turn issues model
232
+ * provider requests, so unbounded parallelism is never meaningful.
233
+ */
234
+ export const MAX_RUNNING_TURNS_LIMIT = 200;
235
+
199
236
  /**
200
237
  * Managed-hosting block on {@link AgentConfig.hosting}.
201
238
  */
@@ -367,6 +404,12 @@ export interface HostContext {
367
404
  * Slack follow-ups coalesce and drain at turn boundaries.
368
405
  */
369
406
  slackNudges?: SlackNudgeHostApi;
407
+ /**
408
+ * Playground eval batches (`/v1/dev/evals*`). Present once the serve host
409
+ * has attached an {@link import("./evals.js").HostEvalsApi}. Used by the
410
+ * built-in Slack `eval` directive and available to tools/handlers.
411
+ */
412
+ evals?: import("./evals.js").HostEvalsApi;
370
413
  /**
371
414
  * Author-facing durable JSON KV (`agentkit/v1/{agent}/kv/…`). Backed by
372
415
  * `agent/storage.ts` (`defineStorage`) when authored; otherwise files
@@ -531,6 +574,8 @@ export type ConnectionTransport =
531
574
  type?: "http" | "sse";
532
575
  url: string;
533
576
  headers?: Record<string, string>;
577
+ /** Host PKCE OAuth; `agentkit mcp oauth <name>`. No Authorization header. */
578
+ oauth?: true;
534
579
  }
535
580
  | {
536
581
  /** Slug of a peer agent mounted on the same serve host. */
@@ -578,13 +623,18 @@ export function isSymbolicConnectionTransport(
578
623
  export type ConnectionConfig = ConnectionTransport & {
579
624
  /** Documentation only; shown in `info` output. */
580
625
  description?: string;
626
+ /**
627
+ * Omit from SDK `mcpServers` (model never sees it). Still available on
628
+ * `host.mcp` for server tools / channel handlers. Does not affect
629
+ * cloud-native account connectors provisioned by the platform.
630
+ */
631
+ hostOnly?: boolean;
581
632
  };
582
633
 
583
634
  /**
584
- * An MCP connection is always available in three places:
585
- * - the Cursor agent (SDK `mcpServers`, local or cloud)
586
- * - the agent-serve host (`ctx.host.mcp` on in-process tools)
587
- * - channel / schedule handlers (`args.host.mcp`)
635
+ * An MCP connection is available to the agent (SDK `mcpServers`), host
636
+ * (`ctx.host.mcp`), and channel/schedule handlers unless `hostOnly`,
637
+ * which keeps it off the model surface only.
588
638
  */
589
639
  export type ConnectionDefinition = ConnectionConfig &
590
640
  BrandedDefinition<"connection">;
@@ -671,6 +721,15 @@ export type SessionEventPayload =
671
721
  data: { sdkAgentId: string; url?: string };
672
722
  }
673
723
  | { type: "message.received"; data: { text: string } }
724
+ | {
725
+ /**
726
+ * The turn was admitted while every {@link AgentConcurrencyOptions.maxRunningTurns}
727
+ * slot was busy; it waits FIFO and `turn.started` follows once a slot
728
+ * frees. `position` is 1-based among waiting turns at enqueue time.
729
+ */
730
+ type: "turn.queued";
731
+ data: { position: number; maxRunningTurns: number };
732
+ }
674
733
  | { type: "turn.started"; data: Record<string, never> }
675
734
  | { type: "step.started"; data: { stepId: number } }
676
735
  | { type: "step.completed"; data: { stepId: number; durationMs: number } }
@@ -872,8 +931,14 @@ export interface SessionSummary {
872
931
  mode: SessionMode;
873
932
  title?: string;
874
933
  turnCount: number;
875
- /** True while a turn is executing right now. */
934
+ /** True while a turn is executing right now (including queued turns). */
876
935
  running: boolean;
936
+ /**
937
+ * True while the session's admitted turn is waiting for a
938
+ * {@link AgentConcurrencyOptions.maxRunningTurns} slot (subset of
939
+ * {@link running}). Omitted when the agent has no turn limit.
940
+ */
941
+ queued?: boolean;
877
942
  createdAt: string;
878
943
  updatedAt: string;
879
944
  /** `<channelId>:<key>` wire token, or null when not addressable. */
@@ -886,6 +951,13 @@ export interface SessionSummary {
886
951
  externalUrl?: string;
887
952
  }
888
953
 
954
+ /**
955
+ * Where `GET /v1/sessions` loaded rows from.
956
+ * - `cursor-hosted` — durable Bugbot `agent_serve_kv` via `cursorHostedStorage`
957
+ * - `local` — the serve process `--state-root` session store
958
+ */
959
+ export type SessionListSource = "cursor-hosted" | "local";
960
+
889
961
  /**
890
962
  * A session handle scoped to the channel that owns it. This is what channel
891
963
  * route handlers get back from `send()` / `getSession()`.
@@ -1622,6 +1694,7 @@ export interface DiscoveredConnection {
1622
1694
  name: string;
1623
1695
  transport: ConnectionTransport;
1624
1696
  description?: string;
1697
+ hostOnly?: boolean;
1625
1698
  }
1626
1699
 
1627
1700
  export interface DiscoveredChannel {
@@ -1676,6 +1749,8 @@ export interface ResolvedAgent {
1676
1749
  local?: AgentLocalOptions;
1677
1750
  /** Managed-hosting declarations from {@link AgentConfig.hosting}. */
1678
1751
  hosting?: AgentHostingOptions;
1752
+ /** Validated turn admission limits from {@link AgentConfig.concurrency}. */
1753
+ concurrency?: AgentConcurrencyOptions;
1679
1754
  tools: DiscoveredTool[];
1680
1755
  skills: DiscoveredSkill[];
1681
1756
  connections: DiscoveredConnection[];
@@ -1727,6 +1802,8 @@ export interface AgentProjectInfo {
1727
1802
  local?: { cwd?: string };
1728
1803
  /** Managed-hosting declarations when authored (egress allowlist, expected secrets). */
1729
1804
  hosting?: { egressDomains?: string[]; secretNames?: string[] };
1805
+ /** Turn admission limits when authored (`concurrency` on `agent.ts`). */
1806
+ concurrency?: { maxRunningTurns?: number };
1730
1807
  /**
1731
1808
  * The agent's own MCP surface (mounted at `<base>/v1/mcp`): other agents
1732
1809
  * and MCP clients delegate to this agent through these tools.
@@ -1741,7 +1818,7 @@ export interface AgentProjectInfo {
1741
1818
  inputSchema: JsonSchemaObject;
1742
1819
  }>;
1743
1820
  skills: Array<{ name: string; description: string }>;
1744
- connections: Array<{ name: string; transport: string }>;
1821
+ connections: Array<{ name: string; transport: string; hostOnly?: boolean }>;
1745
1822
  subagents: Array<{
1746
1823
  name: string;
1747
1824
  description?: string;
@@ -1897,6 +1974,15 @@ export interface ServeOptions {
1897
1974
  * SSO/Okta proxy in front of the host).
1898
1975
  */
1899
1976
  allowAnonymousCursorGithub?: boolean;
1977
+ /**
1978
+ * Allow {@link allowAnonymous} together with
1979
+ * `defineConnection({ cursorAccount: true })`. Without this opt-in, `serve`
1980
+ * refuses to start because every admitted anonymous caller could drive the
1981
+ * signed-in account's MCP connectors. Set it only when the network boundary
1982
+ * already authenticates callers (e.g. an SSO/Okta proxy, or the hosted
1983
+ * agent-serve alias token).
1984
+ */
1985
+ allowAnonymousCursorAccountMcp?: boolean;
1900
1986
  /**
1901
1987
  * Public base URL where this server is reachable from outside the host
1902
1988
  * (e.g. `https://agents.example.com`). Used to resolve peer