@cursor/july 0.1.32 → 0.1.33

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 (84) hide show
  1. package/dist/bin/agent-serve.js +0 -0
  2. package/dist/docs/404.html +1 -1
  3. package/dist/docs/ab.html +2 -2
  4. package/dist/docs/assets/{app.C2aVczmo.js → app.CgZqLyWL.js} +1 -1
  5. package/dist/docs/assets/chunks/@localSearchIndexroot.B1uHGxBZ.js +1 -0
  6. package/dist/docs/assets/chunks/{VPLocalSearchBox.DLEzetbD.js → VPLocalSearchBox.C4KigoQn.js} +1 -1
  7. package/dist/docs/assets/chunks/{theme.BkOH1oMp.js → theme.C_Ty4yT7.js} +2 -2
  8. package/dist/docs/building-with-agents.html +2 -2
  9. package/dist/docs/concepts.html +2 -2
  10. package/dist/docs/deployment.html +2 -2
  11. package/dist/docs/evals.html +2 -2
  12. package/dist/docs/example-agents/approval-buddy.html +2 -2
  13. package/dist/docs/example-agents/benny.html +2 -2
  14. package/dist/docs/example-agents/bugbot.html +2 -2
  15. package/dist/docs/example-agents/codebase-wiki.html +2 -2
  16. package/dist/docs/example-agents/codeowners-review.html +2 -2
  17. package/dist/docs/example-agents/concierge.html +2 -2
  18. package/dist/docs/example-agents/fsd.html +2 -2
  19. package/dist/docs/example-agents/index.html +2 -2
  20. package/dist/docs/example-agents/knowledge-base.html +2 -2
  21. package/dist/docs/example-agents/oncall.html +2 -2
  22. package/dist/docs/example-agents/security-reviewer.html +2 -2
  23. package/dist/docs/example-agents/slack-agent.html +2 -2
  24. package/dist/docs/example-agents/weather-agent.html +2 -2
  25. package/dist/docs/guides/agent-to-agent.html +2 -2
  26. package/dist/docs/guides/cloud-runtime.html +2 -2
  27. package/dist/docs/guides/github.html +2 -2
  28. package/dist/docs/guides/human-in-the-loop.html +2 -2
  29. package/dist/docs/guides/mcp-oauth.html +2 -2
  30. package/dist/docs/guides/slack.html +2 -2
  31. package/dist/docs/guides/webhooks.html +2 -2
  32. package/dist/docs/hillclimbing.html +2 -2
  33. package/dist/docs/index.html +2 -2
  34. package/dist/docs/quickstart.html +2 -2
  35. package/dist/docs/reference/agent-config.html +2 -2
  36. package/dist/docs/reference/channels.html +2 -2
  37. package/dist/docs/reference/cli.html +2 -2
  38. package/dist/docs/reference/connections.html +2 -2
  39. package/dist/docs/reference/hooks.html +2 -2
  40. package/dist/docs/reference/http-api.html +2 -2
  41. package/dist/docs/reference/instructions.html +2 -2
  42. package/dist/docs/reference/playground.html +2 -2
  43. package/dist/docs/reference/project-layout.html +2 -2
  44. package/dist/docs/reference/prompt.html +2 -2
  45. package/dist/docs/reference/schedules.html +2 -2
  46. package/dist/docs/reference/sessions.html +2 -2
  47. package/dist/docs/reference/skills.html +2 -2
  48. package/dist/docs/reference/subagents.html +2 -2
  49. package/dist/docs/reference/tools.html +2 -2
  50. package/dist/docs/scaffolding-agents.html +2 -2
  51. package/dist/docs/storage.html +2 -2
  52. package/dist/docs/troubleshooting.html +2 -2
  53. package/dist/files-backends/agent-store-presigned-url.d.ts +11 -3
  54. package/dist/files-backends/agent-store-presigned-url.d.ts.map +1 -1
  55. package/dist/files-backends/agent-store-presigned-url.js +19 -810
  56. package/dist/internal/cursor-relay-core.d.ts +12 -0
  57. package/dist/internal/cursor-relay-core.d.ts.map +1 -1
  58. package/dist/internal/cursor-relay-core.js +42 -8
  59. package/dist/internal/review-comments.d.ts +9 -1
  60. package/dist/internal/review-comments.d.ts.map +1 -1
  61. package/dist/internal/review-comments.js +76 -0
  62. package/dist/internal/server.js +8 -1
  63. package/dist/playground/assets/index-BRhBbnd4.css +1 -0
  64. package/dist/playground/assets/index-CVlCAcUx.js +85 -0
  65. package/dist/playground/index.html +2 -2
  66. package/package.json +1 -22
  67. package/src/files-backends/agent-store-presigned-url.ts +7 -5
  68. package/src/internal/cursor-relay-core.ts +62 -3
  69. package/src/internal/review-comments.ts +102 -2
  70. package/src/internal/server.ts +9 -1
  71. package/dist/channels/slack/post-update-delivery.d.ts +0 -85
  72. package/dist/channels/slack/post-update-delivery.d.ts.map +0 -1
  73. package/dist/docs/assets/chunks/@localSearchIndexroot.xgMnlUSO.js +0 -1
  74. package/dist/internal/json-dir-store.d.ts +0 -32
  75. package/dist/internal/json-dir-store.d.ts.map +0 -1
  76. package/dist/internal/persistence-coordinator.d.ts +0 -127
  77. package/dist/internal/persistence-coordinator.d.ts.map +0 -1
  78. package/dist/multi-tenant.d.ts +0 -80
  79. package/dist/multi-tenant.d.ts.map +0 -1
  80. package/dist/multi-tenant.js +0 -69
  81. package/dist/persistence.d.ts +0 -184
  82. package/dist/persistence.d.ts.map +0 -1
  83. package/dist/playground/assets/index-50PKeJlG.css +0 -1
  84. package/dist/playground/assets/index-C0f2Wl1q.js +0 -85
@@ -8,8 +8,8 @@
8
8
  />
9
9
  <meta name="viewport" content="width=device-width, initial-scale=1" />
10
10
  <title>agent-serve playground</title>
11
- <script type="module" crossorigin src="./assets/index-C0f2Wl1q.js"></script>
12
- <link rel="stylesheet" crossorigin href="./assets/index-50PKeJlG.css">
11
+ <script type="module" crossorigin src="./assets/index-CVlCAcUx.js"></script>
12
+ <link rel="stylesheet" crossorigin href="./assets/index-BRhBbnd4.css">
13
13
  </head>
14
14
  <body>
15
15
  <div id="root"></div>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cursor/july",
3
- "version": "0.1.32",
3
+ "version": "0.1.33",
4
4
  "description": "(early alpha) Filesystem-first framework for defining Cursor agents as markdown and TypeScript and serving them over channels with the Cursor SDK.",
5
5
  "license": "SEE LICENSE IN LICENSE.md",
6
6
  "repository": {
@@ -39,147 +39,126 @@
39
39
  "exports": {
40
40
  ".": {
41
41
  "anysphere-source": "./src/index.ts",
42
- "bun": "./src/index.ts",
43
42
  "types": "./dist/index.d.ts",
44
43
  "import": "./dist/index.js",
45
44
  "default": "./dist/index.js"
46
45
  },
47
46
  "./tools": {
48
47
  "anysphere-source": "./src/tools.ts",
49
- "bun": "./src/tools.ts",
50
48
  "types": "./dist/tools.d.ts",
51
49
  "import": "./dist/tools.js",
52
50
  "default": "./dist/tools.js"
53
51
  },
54
52
  "./channels": {
55
53
  "anysphere-source": "./src/channels.ts",
56
- "bun": "./src/channels.ts",
57
54
  "types": "./dist/channels.d.ts",
58
55
  "import": "./dist/channels.js",
59
56
  "default": "./dist/channels.js"
60
57
  },
61
58
  "./channels/slack": {
62
59
  "anysphere-source": "./src/channels/slack/index.ts",
63
- "bun": "./src/channels/slack/index.ts",
64
60
  "types": "./dist/channels/slack/index.d.ts",
65
61
  "import": "./dist/channels/slack/index.js",
66
62
  "default": "./dist/channels/slack/index.js"
67
63
  },
68
64
  "./channels/github": {
69
65
  "anysphere-source": "./src/channels/github/index.ts",
70
- "bun": "./src/channels/github/index.ts",
71
66
  "types": "./dist/channels/github/index.d.ts",
72
67
  "import": "./dist/channels/github/index.js",
73
68
  "default": "./dist/channels/github/index.js"
74
69
  },
75
70
  "./skills": {
76
71
  "anysphere-source": "./src/skills.ts",
77
- "bun": "./src/skills.ts",
78
72
  "types": "./dist/skills.d.ts",
79
73
  "import": "./dist/skills.js",
80
74
  "default": "./dist/skills.js"
81
75
  },
82
76
  "./schedules": {
83
77
  "anysphere-source": "./src/schedules.ts",
84
- "bun": "./src/schedules.ts",
85
78
  "types": "./dist/schedules.d.ts",
86
79
  "import": "./dist/schedules.js",
87
80
  "default": "./dist/schedules.js"
88
81
  },
89
82
  "./reminders": {
90
83
  "anysphere-source": "./src/reminders.ts",
91
- "bun": "./src/reminders.ts",
92
84
  "types": "./dist/reminders.d.ts",
93
85
  "import": "./dist/reminders.js",
94
86
  "default": "./dist/reminders.js"
95
87
  },
96
88
  "./connections": {
97
89
  "anysphere-source": "./src/connections.ts",
98
- "bun": "./src/connections.ts",
99
90
  "types": "./dist/connections.d.ts",
100
91
  "import": "./dist/connections.js",
101
92
  "default": "./dist/connections.js"
102
93
  },
103
94
  "./hooks": {
104
95
  "anysphere-source": "./src/hooks.ts",
105
- "bun": "./src/hooks.ts",
106
96
  "types": "./dist/hooks.d.ts",
107
97
  "import": "./dist/hooks.js",
108
98
  "default": "./dist/hooks.js"
109
99
  },
110
100
  "./memory": {
111
101
  "anysphere-source": "./src/memory.ts",
112
- "bun": "./src/memory.ts",
113
102
  "types": "./dist/memory.d.ts",
114
103
  "import": "./dist/memory.js",
115
104
  "default": "./dist/memory.js"
116
105
  },
117
106
  "./prompt": {
118
107
  "anysphere-source": "./src/prompt.ts",
119
- "bun": "./src/prompt.ts",
120
108
  "types": "./dist/prompt.d.ts",
121
109
  "import": "./dist/prompt.js",
122
110
  "default": "./dist/prompt.js"
123
111
  },
124
112
  "./evals": {
125
113
  "anysphere-source": "./src/evals.ts",
126
- "bun": "./src/evals.ts",
127
114
  "types": "./dist/evals.d.ts",
128
115
  "import": "./dist/evals.js",
129
116
  "default": "./dist/evals.js"
130
117
  },
131
118
  "./evals/reporters": {
132
119
  "anysphere-source": "./src/evals/reporters.ts",
133
- "bun": "./src/evals/reporters.ts",
134
120
  "types": "./dist/evals/reporters.d.ts",
135
121
  "import": "./dist/evals/reporters.js",
136
122
  "default": "./dist/evals/reporters.js"
137
123
  },
138
124
  "./evals/loaders": {
139
125
  "anysphere-source": "./src/evals/loaders.ts",
140
- "bun": "./src/evals/loaders.ts",
141
126
  "types": "./dist/evals/loaders.d.ts",
142
127
  "import": "./dist/evals/loaders.js",
143
128
  "default": "./dist/evals/loaders.js"
144
129
  },
145
130
  "./ab": {
146
131
  "anysphere-source": "./src/ab.ts",
147
- "bun": "./src/ab.ts",
148
132
  "types": "./dist/ab.d.ts",
149
133
  "import": "./dist/ab.js",
150
134
  "default": "./dist/ab.js"
151
135
  },
152
136
  "./artifacts": {
153
137
  "anysphere-source": "./src/artifacts.ts",
154
- "bun": "./src/artifacts.ts",
155
138
  "types": "./dist/artifacts.d.ts",
156
139
  "import": "./dist/artifacts.js",
157
140
  "default": "./dist/artifacts.js"
158
141
  },
159
142
  "./storage": {
160
143
  "anysphere-source": "./src/storage.ts",
161
- "bun": "./src/storage.ts",
162
144
  "types": "./dist/storage.d.ts",
163
145
  "import": "./dist/storage.js",
164
146
  "default": "./dist/storage.js"
165
147
  },
166
148
  "./storage/file-kv": {
167
149
  "anysphere-source": "./src/storage-backends/file-kv.ts",
168
- "bun": "./src/storage-backends/file-kv.ts",
169
150
  "types": "./dist/storage-backends/file-kv.d.ts",
170
151
  "import": "./dist/storage-backends/file-kv.js",
171
152
  "default": "./dist/storage-backends/file-kv.js"
172
153
  },
173
154
  "./storage/postgres-kv": {
174
155
  "anysphere-source": "./src/storage-backends/postgres-kv.ts",
175
- "bun": "./src/storage-backends/postgres-kv.ts",
176
156
  "types": "./dist/storage-backends/postgres-kv.d.ts",
177
157
  "import": "./dist/storage-backends/postgres-kv.js",
178
158
  "default": "./dist/storage-backends/postgres-kv.js"
179
159
  },
180
160
  "./storage/cursor-hosted": {
181
161
  "anysphere-source": "./src/storage-backends/cursor-hosted.ts",
182
- "bun": "./src/storage-backends/cursor-hosted.ts",
183
162
  "types": "./dist/storage-backends/cursor-hosted.d.ts",
184
163
  "import": "./dist/storage-backends/cursor-hosted.js",
185
164
  "default": "./dist/storage-backends/cursor-hosted.js"
@@ -1,8 +1,10 @@
1
1
  /**
2
- * Re-export the agent-store SSRF pin used by `cursorHostedFiles`.
2
+ * Re-export bundled into dist by `scripts/bundle-publish-shims.mjs`.
3
3
  *
4
- * Source keeps a single dependency on `@anysphere/agent-store-sync` (dev-only
5
- * for publish). The build overwrites the emitted `dist` copy with an esbuild
6
- * bundle so the npm tarball does not need that private package at runtime.
4
+ * Imports the `presigned-url` entry point rather than the package root: the
5
+ * root is a barrel over the whole library, and bundling through it inlines
6
+ * every module the barrel can reach (sync engine, local sqlite index, secure
7
+ * open) into the published tarball. This module has no imports of its own, so
8
+ * the bundle stays limited to the validator.
7
9
  */
8
- export { createAgentStorePresignedUrlValidatorForBackend } from "@anysphere/agent-store-sync";
10
+ export { createAgentStorePresignedUrlValidatorForBackend } from "@anysphere/agent-store-sync/presigned-url";
@@ -151,6 +151,42 @@ export interface CursorRelayCoreOptions<TEvent extends { offset: string }> {
151
151
  fetchImpl?: typeof fetch;
152
152
  /** Test seam: override long-poll wait (default 25s). */
153
153
  pollWaitMs?: number;
154
+ /**
155
+ * Desired-revision generation for hosted engines. Sent as
156
+ * `x-agent-serve-generation` so the control plane can fence zombies after
157
+ * a redeploy. Defaults to `process.env.AGENT_SERVE_GENERATION` when set.
158
+ */
159
+ deploymentGeneration?: number;
160
+ }
161
+
162
+ /** Must match server-shared `AGENT_SERVE_GENERATION_HEADER`. */
163
+ export const AGENT_SERVE_GENERATION_HEADER = "x-agent-serve-generation";
164
+
165
+ /** Must match server-shared `AGENT_SERVE_GENERATION_ENV_VAR`. */
166
+ export const AGENT_SERVE_GENERATION_ENV_VAR = "AGENT_SERVE_GENERATION";
167
+
168
+ export function resolveAgentServeDeploymentGeneration(
169
+ explicit?: number
170
+ ): number | undefined {
171
+ if (
172
+ explicit !== undefined &&
173
+ Number.isSafeInteger(explicit) &&
174
+ explicit > 0
175
+ ) {
176
+ return explicit;
177
+ }
178
+ const raw = process.env[AGENT_SERVE_GENERATION_ENV_VAR]?.trim();
179
+ if (raw === undefined || raw.length === 0) {
180
+ return undefined;
181
+ }
182
+ if (!/^\d+$/.test(raw)) {
183
+ return undefined;
184
+ }
185
+ const parsed = Number(raw);
186
+ if (!Number.isSafeInteger(parsed) || parsed <= 0) {
187
+ return undefined;
188
+ }
189
+ return parsed;
154
190
  }
155
191
 
156
192
  export class CursorRelayCore<TEvent extends { offset: string }> {
@@ -160,6 +196,7 @@ export class CursorRelayCore<TEvent extends { offset: string }> {
160
196
  private consumePromise: Promise<void> | undefined;
161
197
  private readonly offsetStore: RelayOffsetStore;
162
198
  private readonly fetchImpl: typeof fetch;
199
+ private readonly deploymentGeneration: number | undefined;
163
200
  private consumerId = "";
164
201
  /** undefined until the first registration, so a clean first success logs. */
165
202
  private lastRegistrationLog: string | undefined;
@@ -175,6 +212,9 @@ export class CursorRelayCore<TEvent extends { offset: string }> {
175
212
  constructor(private readonly options: CursorRelayCoreOptions<TEvent>) {
176
213
  this.offsetStore = new RelayOffsetStore(options.stateDir);
177
214
  this.fetchImpl = options.fetchImpl ?? fetch;
215
+ this.deploymentGeneration = resolveAgentServeDeploymentGeneration(
216
+ options.deploymentGeneration
217
+ );
178
218
  }
179
219
 
180
220
  start(): void {
@@ -285,6 +325,13 @@ export class CursorRelayCore<TEvent extends { offset: string }> {
285
325
  headers: {
286
326
  authorization: `Bearer ${this.options.apiKey}`,
287
327
  "content-type": "application/json",
328
+ ...(this.deploymentGeneration === undefined
329
+ ? {}
330
+ : {
331
+ [AGENT_SERVE_GENERATION_HEADER]: String(
332
+ this.deploymentGeneration
333
+ ),
334
+ }),
288
335
  },
289
336
  body: JSON.stringify(adapter.buildDeregistrationBody(this.consumerId)),
290
337
  signal: controller.signal,
@@ -322,6 +369,13 @@ export class CursorRelayCore<TEvent extends { offset: string }> {
322
369
  headers: {
323
370
  authorization: `Bearer ${this.options.apiKey}`,
324
371
  ...(body === undefined ? {} : { "content-type": "application/json" }),
372
+ ...(this.deploymentGeneration === undefined
373
+ ? {}
374
+ : {
375
+ [AGENT_SERVE_GENERATION_HEADER]: String(
376
+ this.deploymentGeneration
377
+ ),
378
+ }),
325
379
  },
326
380
  ...(body === undefined ? {} : { body: JSON.stringify(body) }),
327
381
  ...(this.abort === undefined ? {} : { signal: this.abort.signal }),
@@ -514,14 +568,19 @@ export class CursorRelayCore<TEvent extends { offset: string }> {
514
568
  response: Response,
515
569
  backoffMs: number
516
570
  ): Promise<number> {
517
- const isAuthFailure = response.status === 401 || response.status === 403;
518
- const sleepMs = isAuthFailure ? AUTH_FAILURE_BACKOFF_MS : backoffMs;
571
+ // 409 = generation fence (stale resident after redeploy). Same long
572
+ // backoff as auth: retrying every second cannot heal a wrong generation.
573
+ const isAuthOrFenceFailure =
574
+ response.status === 401 ||
575
+ response.status === 403 ||
576
+ response.status === 409;
577
+ const sleepMs = isAuthOrFenceFailure ? AUTH_FAILURE_BACKOFF_MS : backoffMs;
519
578
  const text = await response.text().catch(() => "");
520
579
  this.log(
521
580
  `poll failed: ${response.status} ${text.slice(0, 300)} (retrying in ${Math.round(sleepMs / 1000)}s)`
522
581
  );
523
582
  await this.sleep(sleepMs);
524
- return isAuthFailure
583
+ return isAuthOrFenceFailure
525
584
  ? AUTH_FAILURE_BACKOFF_MS
526
585
  : Math.min(backoffMs * 2, MAX_BACKOFF_MS);
527
586
  }
@@ -1,6 +1,7 @@
1
1
  import { spawn } from "node:child_process";
2
+ import type { HostGitHubClient } from "../types.js";
2
3
 
3
- export type ReviewCommentPublisher = "local_gh";
4
+ export type ReviewCommentPublisher = "local_gh" | "host_github";
4
5
 
5
6
  export type ReviewCommentPostResult = {
6
7
  posted: boolean;
@@ -84,6 +85,80 @@ export function createLocalGhReviewPublisher(): ReviewCommentPublisherImplementa
84
85
  };
85
86
  }
86
87
 
88
+ /**
89
+ * Posts a PR review through the host GitHub client (Cursor account lease,
90
+ * App installation token, or PAT). Prefer this on Cursor-deployed agents —
91
+ * no separate GitHub write secret is required when `githubChannel({
92
+ * cursorAccount })` is bound.
93
+ */
94
+ export function createHostGithubReviewPublisher(
95
+ github: HostGitHubClient
96
+ ): ReviewCommentPublisherImplementation {
97
+ return {
98
+ async postReview(args) {
99
+ return postReviewViaHostGithub(github, args);
100
+ },
101
+ };
102
+ }
103
+
104
+ async function postReviewViaHostGithub(
105
+ github: HostGitHubClient,
106
+ args: ReviewCommentPostArgs
107
+ ): Promise<ReviewCommentPostResult> {
108
+ const prepared = prepareReviewCommentsRequest(args);
109
+ if (prepared.kind === "skipped") {
110
+ return {
111
+ ...prepared.result,
112
+ publisher: "host_github",
113
+ };
114
+ }
115
+
116
+ const { request } = prepared;
117
+ const [owner, repo] = request.repo.split("/", 2);
118
+ if (owner === undefined || repo === undefined || repo === "") {
119
+ return skippedHost("unparseable owner/repo from PR URL");
120
+ }
121
+
122
+ try {
123
+ args.signal?.throwIfAborted();
124
+ const octokit = await github.getOctokit();
125
+ args.signal?.throwIfAborted();
126
+ const response = await octokit.rest.pulls.createReview({
127
+ owner,
128
+ repo,
129
+ pull_number: request.prNumber,
130
+ commit_id: request.headSha,
131
+ body: request.message,
132
+ event: "COMMENT",
133
+ comments: request.comments.map(toGithubPullRequestReviewComment),
134
+ });
135
+ const htmlUrl =
136
+ typeof response.data.html_url === "string"
137
+ ? response.data.html_url
138
+ : undefined;
139
+ const inlineCommentCount = request.comments.length;
140
+ return {
141
+ posted: true,
142
+ publisher: "host_github",
143
+ mode:
144
+ inlineCommentCount > 0
145
+ ? "review_with_inline_comments"
146
+ : "review_body_only",
147
+ inlineCommentCount,
148
+ detail: htmlUrl
149
+ ? `posted via host GitHub: ${htmlUrl}`
150
+ : `posted via host GitHub with ${inlineCommentCount} inline comment(s)`,
151
+ };
152
+ } catch (error) {
153
+ if (args.signal?.aborted) {
154
+ throw error;
155
+ }
156
+ return skippedHost(
157
+ `host GitHub review post failed: ${error instanceof Error ? error.message : String(error)}`
158
+ );
159
+ }
160
+ }
161
+
87
162
  async function postReviewViaLocalGh(
88
163
  args: ReviewCommentPostArgs
89
164
  ): Promise<ReviewCommentPostResult> {
@@ -129,10 +204,25 @@ async function postReviewViaLocalGh(
129
204
  }
130
205
  }
131
206
 
207
+ type GithubPullRequestReviewComment = {
208
+ path: string;
209
+ body: string;
210
+ line: number;
211
+ side: "RIGHT";
212
+ start_line?: number;
213
+ start_side?: "RIGHT";
214
+ };
215
+
132
216
  function toGithubReviewComment(
133
217
  comment: ReviewInlineComment
134
218
  ): Record<string, string | number> {
135
- const body: Record<string, string | number> = {
219
+ return toGithubPullRequestReviewComment(comment);
220
+ }
221
+
222
+ function toGithubPullRequestReviewComment(
223
+ comment: ReviewInlineComment
224
+ ): GithubPullRequestReviewComment {
225
+ const body: GithubPullRequestReviewComment = {
136
226
  path: comment.file,
137
227
  body: comment.body,
138
228
  line: comment.line,
@@ -159,6 +249,16 @@ function skipped(detail: string): ReviewCommentPostResult {
159
249
  };
160
250
  }
161
251
 
252
+ function skippedHost(detail: string): ReviewCommentPostResult {
253
+ return {
254
+ posted: false,
255
+ publisher: "host_github",
256
+ mode: "skipped",
257
+ inlineCommentCount: 0,
258
+ detail,
259
+ };
260
+ }
261
+
162
262
  function parseGithubPrUrl(
163
263
  prUrl: string
164
264
  ):
@@ -959,7 +959,15 @@ function mountAgentRoutes(
959
959
  method: "GET",
960
960
  pattern: `${base}/v1/health`,
961
961
  auth: "none",
962
- handler: () => jsonResponse({ ok: true, name: project.name }),
962
+ // Temporal consumes this response before promoting a newly deployed pod.
963
+ // Include the framework build there so deploy observability gets the
964
+ // version from the process that will serve turns, with no second request.
965
+ handler: () =>
966
+ jsonResponse({
967
+ ok: true,
968
+ name: project.name,
969
+ version: packageVersion(),
970
+ }),
963
971
  });
964
972
 
965
973
  // Bootstrap the SPA can't derive from its own URL (agent name, dev mode, and
@@ -1,85 +0,0 @@
1
- /**
2
- * Live-reply delivery strategies for the Slack default handlers.
3
- *
4
- * A single strategy owns how an in-progress reply is opened, updated,
5
- * finalized, and cleaned up so the handlers in `defaults.ts` don't fork on the
6
- * delivery mode at every event:
7
- *
8
- * - `stream`: Slack chat.startStream / appendStream / stopStream.
9
- * - `post-update`: a chat.postMessage skeleton edited with chat.update. This is
10
- * the only path that preserves Cursor-account identity pinning (which only
11
- * covers postMessage).
12
- *
13
- * `buildDefaultEvents` selects one via {@link selectLiveDeliveryStrategy} up
14
- * front and calls into it. All calls keep the same soft-fail / log behavior as
15
- * the inlined logic they replaced.
16
- */
17
- import type { ChannelEventContext } from "../../types.js";
18
- import type { SlackLog } from "./log.js";
19
- import type { SlackBotToken, SlackChannelState } from "./types.js";
20
- type SlackChannel = ChannelEventContext<SlackChannelState>;
21
- export interface LiveDeliveryDeps {
22
- botToken: SlackBotToken | undefined;
23
- getLog: () => SlackLog;
24
- }
25
- /**
26
- * How the default handlers deliver an in-progress reply. Methods write live
27
- * delivery state (`streamTs`, `streamChannelId`, `lastPostedText`,
28
- * `lastPostUpdateAtMs`, `streamingUnavailable`) on `channel.state` directly.
29
- */
30
- export interface LiveDeliveryStrategy {
31
- /** True when tool-call thinking steps can be appended to the live message. */
32
- readonly inlineToolSteps: boolean;
33
- /** Open the live message (skeleton post / stream start). */
34
- start(args: {
35
- channel: SlackChannel;
36
- channelId: string;
37
- threadTs: string;
38
- sessionId: string;
39
- }): Promise<void>;
40
- /** Push the latest cumulative text to the live message (throttled). */
41
- append(args: {
42
- channel: SlackChannel;
43
- channelId: string;
44
- streamTs: string;
45
- text: string;
46
- sessionId: string;
47
- }): Promise<void>;
48
- /**
49
- * Flush the final reply text. `delivered` is false only when the caller must
50
- * post the full reply as a fresh message (finalize failed on partial text).
51
- */
52
- finalize(args: {
53
- channel: SlackChannel;
54
- channelId: string;
55
- streamTs: string;
56
- text: string;
57
- sessionId: string;
58
- }): Promise<{
59
- delivered: boolean;
60
- }>;
61
- /** Close the live message when the turn produced no final text. */
62
- finalizeEmpty(args: {
63
- channel: SlackChannel;
64
- channelId: string;
65
- streamTs: string;
66
- }): Promise<void>;
67
- /** Best-effort remove a live message left open after the turn ended. */
68
- cleanupOrphan(args: {
69
- channel: SlackChannel;
70
- }): Promise<void>;
71
- /** Deliver the error text into the live message; `delivered` gates a fallback post. */
72
- fail(args: {
73
- channel: SlackChannel;
74
- channelId: string;
75
- streamTs: string;
76
- errorText: string;
77
- sessionId: string;
78
- }): Promise<{
79
- delivered: boolean;
80
- }>;
81
- }
82
- /** Pick the live-reply delivery strategy for a `buildDefaultEvents` instance. */
83
- export declare function selectLiveDeliveryStrategy(deps: LiveDeliveryDeps, usePostUpdate: boolean): LiveDeliveryStrategy;
84
- export {};
85
- //# sourceMappingURL=post-update-delivery.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"post-update-delivery.d.ts","sourceRoot":"","sources":["../../../src/channels/slack/post-update-delivery.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AAW1D,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AAEzC,OAAO,KAAK,EAAE,aAAa,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAEnE,KAAK,YAAY,GAAG,mBAAmB,CAAC,iBAAiB,CAAC,CAAC;AAE3D,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,EAAE,aAAa,GAAG,SAAS,CAAC;IACpC,MAAM,EAAE,MAAM,QAAQ,CAAC;CACxB;AAED;;;;GAIG;AACH,MAAM,WAAW,oBAAoB;IACnC,8EAA8E;IAC9E,QAAQ,CAAC,eAAe,EAAE,OAAO,CAAC;IAClC,4DAA4D;IAC5D,KAAK,CAAC,IAAI,EAAE;QACV,OAAO,EAAE,YAAY,CAAC;QACtB,SAAS,EAAE,MAAM,CAAC;QAClB,QAAQ,EAAE,MAAM,CAAC;QACjB,SAAS,EAAE,MAAM,CAAC;KACnB,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAClB,uEAAuE;IACvE,MAAM,CAAC,IAAI,EAAE;QACX,OAAO,EAAE,YAAY,CAAC;QACtB,SAAS,EAAE,MAAM,CAAC;QAClB,QAAQ,EAAE,MAAM,CAAC;QACjB,IAAI,EAAE,MAAM,CAAC;QACb,SAAS,EAAE,MAAM,CAAC;KACnB,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAClB;;;OAGG;IACH,QAAQ,CAAC,IAAI,EAAE;QACb,OAAO,EAAE,YAAY,CAAC;QACtB,SAAS,EAAE,MAAM,CAAC;QAClB,QAAQ,EAAE,MAAM,CAAC;QACjB,IAAI,EAAE,MAAM,CAAC;QACb,SAAS,EAAE,MAAM,CAAC;KACnB,GAAG,OAAO,CAAC;QAAE,SAAS,EAAE,OAAO,CAAA;KAAE,CAAC,CAAC;IACpC,mEAAmE;IACnE,aAAa,CAAC,IAAI,EAAE;QAClB,OAAO,EAAE,YAAY,CAAC;QACtB,SAAS,EAAE,MAAM,CAAC;QAClB,QAAQ,EAAE,MAAM,CAAC;KAClB,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAClB,wEAAwE;IACxE,aAAa,CAAC,IAAI,EAAE;QAAE,OAAO,EAAE,YAAY,CAAA;KAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC9D,uFAAuF;IACvF,IAAI,CAAC,IAAI,EAAE;QACT,OAAO,EAAE,YAAY,CAAC;QACtB,SAAS,EAAE,MAAM,CAAC;QAClB,QAAQ,EAAE,MAAM,CAAC;QACjB,SAAS,EAAE,MAAM,CAAC;QAClB,SAAS,EAAE,MAAM,CAAC;KACnB,GAAG,OAAO,CAAC;QAAE,SAAS,EAAE,OAAO,CAAA;KAAE,CAAC,CAAC;CACrC;AA6RD,iFAAiF;AACjF,wBAAgB,0BAA0B,CACxC,IAAI,EAAE,gBAAgB,EACtB,aAAa,EAAE,OAAO,GACrB,oBAAoB,CAItB"}