@cursor/july 0.1.11 → 0.1.14
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/dist/bin/agent-serve.js +32 -9
- package/dist/channels/github/api.d.ts.map +1 -1
- package/dist/channels/github/api.js +11 -4
- package/dist/channels/github/cursor-account.d.ts +21 -1
- package/dist/channels/github/cursor-account.d.ts.map +1 -1
- package/dist/channels/github/cursor-account.js +29 -1
- package/dist/channels/github/github-channel.d.ts.map +1 -1
- package/dist/channels/github/github-channel.js +1 -1
- package/dist/channels/github/instrument.d.ts +20 -0
- package/dist/channels/github/instrument.d.ts.map +1 -0
- package/dist/channels/slack/api.d.ts +9 -0
- package/dist/channels/slack/api.d.ts.map +1 -1
- package/dist/channels/slack/api.js +40 -7
- package/dist/channels/slack/eval-directive.d.ts +3 -0
- package/dist/channels/slack/eval-directive.d.ts.map +1 -1
- package/dist/channels/slack/eval-directive.js +20 -1
- package/dist/docs/404.html +2 -2
- package/dist/docs/ab.html +3 -3
- package/dist/docs/assets/{app.BcXUGca7.js → app.CKFFLL4Z.js} +1 -1
- package/dist/docs/assets/chunks/@localSearchIndexroot.DGWkvXJc.js +1 -0
- package/dist/docs/assets/chunks/{VPLocalSearchBox.CWur6XGZ.js → VPLocalSearchBox.BXk19JBN.js} +1 -1
- package/dist/docs/assets/chunks/{theme.BnvulOX2.js → theme.BXSPBMyn.js} +2 -2
- package/dist/docs/assets/{evals.md.DAgEc_hL.js → evals.md.DYOjkRCX.js} +10 -4
- package/dist/docs/assets/{evals.md.DAgEc_hL.lean.js → evals.md.DYOjkRCX.lean.js} +1 -1
- package/dist/docs/assets/{reference_cli.md.B74NrVzb.js → reference_cli.md.DnYfr5V2.js} +4 -1
- package/dist/docs/assets/{reference_http-api.md.Dx_nmDG6.js → reference_http-api.md.BncLd3PZ.js} +2 -2
- package/dist/docs/assets/{reference_http-api.md.Dx_nmDG6.lean.js → reference_http-api.md.BncLd3PZ.lean.js} +1 -1
- package/dist/docs/building-with-agents.html +3 -3
- package/dist/docs/concepts.html +3 -3
- package/dist/docs/deployment.html +3 -3
- package/dist/docs/evals.html +13 -7
- 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/github.html +3 -3
- package/dist/docs/guides/human-in-the-loop.html +3 -3
- package/dist/docs/guides/mcp-oauth.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 +3 -3
- package/dist/docs/reference/channels.html +3 -3
- package/dist/docs/reference/cli.html +8 -5
- package/dist/docs/reference/connections.html +3 -3
- package/dist/docs/reference/hooks.html +3 -3
- package/dist/docs/reference/http-api.html +5 -5
- 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 +3 -3
- package/dist/docs/reference/skills.html +3 -3
- package/dist/docs/reference/subagents.html +3 -3
- package/dist/docs/reference/tools.html +3 -3
- package/dist/docs/scaffolding-agents.html +3 -3
- package/dist/docs/storage.html +3 -3
- package/dist/docs/troubleshooting.html +3 -3
- package/dist/evals.d.ts +41 -2
- package/dist/evals.d.ts.map +1 -1
- package/dist/evals.js +53 -16
- package/dist/internal/cli-ax.d.ts +4 -0
- package/dist/internal/cli-ax.d.ts.map +1 -1
- package/dist/internal/cli-ax.js +163 -33
- package/dist/internal/cli-deploy.d.ts +8 -0
- package/dist/internal/cli-deploy.d.ts.map +1 -1
- package/dist/internal/cli-deploy.js +92 -12
- package/dist/internal/cli-mcp-oauth.d.ts +14 -2
- package/dist/internal/cli-mcp-oauth.d.ts.map +1 -1
- package/dist/internal/cli-mcp-oauth.js +95 -2
- package/dist/internal/cursor/backend-client.d.ts +34 -0
- package/dist/internal/cursor/backend-client.d.ts.map +1 -1
- package/dist/internal/cursor/backend-client.js +73 -9
- package/dist/internal/cursor/credentials.d.ts +7 -1
- package/dist/internal/cursor/credentials.d.ts.map +1 -1
- package/dist/internal/cursor/credentials.js +9 -3
- package/dist/internal/cursor-account-mcp-auth.d.ts +55 -0
- package/dist/internal/cursor-account-mcp-auth.d.ts.map +1 -0
- package/dist/internal/cursor-account-mcp-auth.js +175 -0
- package/dist/internal/cursor-event-relay.d.ts +2 -0
- package/dist/internal/cursor-event-relay.d.ts.map +1 -1
- package/dist/internal/cursor-event-relay.js +3 -0
- package/dist/internal/deploy-client.d.ts +6 -0
- package/dist/internal/deploy-client.d.ts.map +1 -1
- package/dist/internal/deploy-client.js +13 -0
- package/dist/internal/eval-run-store.d.ts +15 -0
- package/dist/internal/eval-run-store.d.ts.map +1 -1
- package/dist/internal/eval-run-store.js +87 -8
- package/dist/internal/eval-runner.d.ts +12 -0
- package/dist/internal/eval-runner.d.ts.map +1 -1
- package/dist/internal/eval-runner.js +97 -22
- package/dist/internal/evals-client.d.ts +9 -1
- package/dist/internal/evals-client.d.ts.map +1 -1
- package/dist/internal/evals-client.js +43 -0
- package/dist/internal/http-channel.d.ts.map +1 -1
- package/dist/internal/http-channel.js +74 -7
- package/dist/internal/map-pool.d.ts +6 -1
- package/dist/internal/map-pool.d.ts.map +1 -1
- package/dist/internal/map-pool.js +8 -1
- package/dist/internal/mcp-host.d.ts +13 -0
- package/dist/internal/mcp-host.d.ts.map +1 -1
- package/dist/internal/mcp-host.js +68 -13
- package/dist/internal/run-client.d.ts +5 -1
- package/dist/internal/run-client.d.ts.map +1 -1
- package/dist/internal/run-client.js +26 -5
- package/dist/internal/server.d.ts.map +1 -1
- package/dist/internal/server.js +57 -4
- package/dist/internal/session-engine.d.ts +13 -0
- package/dist/internal/session-engine.d.ts.map +1 -1
- package/dist/internal/session-engine.js +49 -0
- package/dist/internal/storage-coordinator.d.ts +7 -0
- package/dist/internal/storage-coordinator.d.ts.map +1 -1
- package/dist/internal/storage-coordinator.js +29 -4
- package/dist/playground/assets/index-CuXb4j4V.css +1 -0
- package/dist/playground/assets/index-DeyYpOit.js +86 -0
- package/dist/playground/index.html +2 -2
- package/dist/types.d.ts +10 -0
- package/dist/types.d.ts.map +1 -1
- package/docs/evals.md +46 -11
- package/docs/reference/cli.md +3 -0
- package/docs/reference/http-api.md +2 -1
- package/package.json +1 -1
- package/src/bin/agent-serve.ts +38 -8
- package/src/channels/github/api.ts +12 -1
- package/src/channels/github/cursor-account.ts +51 -1
- package/src/channels/github/github-channel.ts +4 -1
- package/src/channels/slack/api.ts +57 -8
- package/src/channels/slack/eval-directive.ts +24 -1
- package/src/evals.ts +104 -25
- package/src/internal/cli-ax.ts +192 -16
- package/src/internal/cli-deploy.ts +140 -13
- package/src/internal/cli-mcp-oauth.ts +122 -3
- package/src/internal/cursor/backend-client.ts +104 -1
- package/src/internal/cursor/credentials.ts +10 -2
- package/src/internal/cursor-account-mcp-auth.ts +241 -0
- package/src/internal/cursor-event-relay.ts +5 -0
- package/src/internal/deploy-client.ts +16 -0
- package/src/internal/eval-run-store.ts +89 -6
- package/src/internal/eval-runner.ts +113 -18
- package/src/internal/evals-client.ts +81 -0
- package/src/internal/http-channel.ts +87 -6
- package/src/internal/map-pool.ts +8 -1
- package/src/internal/mcp-host.ts +74 -16
- package/src/internal/run-client.ts +32 -1
- package/src/internal/server.ts +69 -2
- package/src/internal/session-engine.ts +58 -0
- package/src/internal/storage-coordinator.ts +32 -6
- package/src/types.ts +10 -0
- package/dist/channels/slack/post-update-delivery.d.ts +0 -85
- package/dist/channels/slack/post-update-delivery.d.ts.map +0 -1
- package/dist/channels/slack/post-update-delivery.js +0 -318
- package/dist/docs/assets/chunks/@localSearchIndexroot.BIbvK8M1.js +0 -1
- package/dist/internal/corp-ca.d.ts +0 -9
- package/dist/internal/corp-ca.d.ts.map +0 -1
- package/dist/internal/corp-ca.js +0 -44
- package/dist/playground/assets/index-BIGLubwK.js +0 -86
- package/dist/playground/assets/index-C17ZQKDG.css +0 -1
- package/docs/.vitepress/cache/deps/package.json +0 -3
- /package/dist/docs/assets/{reference_cli.md.B74NrVzb.lean.js → reference_cli.md.DnYfr5V2.lean.js} +0 -0
package/src/internal/server.ts
CHANGED
|
@@ -21,6 +21,7 @@ import {
|
|
|
21
21
|
getGithubCursorAccountRuntime,
|
|
22
22
|
parseCursorGithubRepoScope,
|
|
23
23
|
resolveCursorGithubPermissions,
|
|
24
|
+
resolveCursorGithubProxyUrl,
|
|
24
25
|
} from "../channels/github/cursor-account.js";
|
|
25
26
|
import { findGitHubChannelTargets } from "../channels/github/forward.js";
|
|
26
27
|
import {
|
|
@@ -80,7 +81,9 @@ import {
|
|
|
80
81
|
import {
|
|
81
82
|
EvalRunConflictError,
|
|
82
83
|
EvalRunEmptyError,
|
|
84
|
+
EvalRunNotRunningError,
|
|
83
85
|
EvalRunStore,
|
|
86
|
+
EvalRunUnknownError,
|
|
84
87
|
} from "./eval-run-store.js";
|
|
85
88
|
import {
|
|
86
89
|
collectGitHubTriggerTargets,
|
|
@@ -251,8 +254,35 @@ export async function startServer(
|
|
|
251
254
|
logger,
|
|
252
255
|
});
|
|
253
256
|
cursorGithubCredentials = provider;
|
|
254
|
-
|
|
255
|
-
|
|
257
|
+
const githubProxyUrl =
|
|
258
|
+
options.cursorGithubProxy === true
|
|
259
|
+
? resolveCursorGithubProxyUrl(cursorEventsAuth.baseUrl)
|
|
260
|
+
: undefined;
|
|
261
|
+
if (githubProxyUrl !== undefined) {
|
|
262
|
+
// Proxy mode: channel Octokit calls carry the Cursor API key to the
|
|
263
|
+
// backend forwarder, which swaps in the installation token server-side
|
|
264
|
+
// and logs every call with per-deployment attribution. The provider
|
|
265
|
+
// still runs so child `gh` processes get a `GH_TOKEN` lease (v1).
|
|
266
|
+
const proxyTransport = {
|
|
267
|
+
apiBaseUrl: githubProxyUrl,
|
|
268
|
+
headers: {
|
|
269
|
+
"x-cursor-github-repos": cursorGithubConfig.scope.repos.join(","),
|
|
270
|
+
"x-cursor-github-permissions": cursorGithubConfig.scope.permissions,
|
|
271
|
+
},
|
|
272
|
+
};
|
|
273
|
+
for (const target of cursorGithubTargets) {
|
|
274
|
+
target.accountRuntime.credentials.bind(
|
|
275
|
+
async () => cursorEventsAuth.apiKey
|
|
276
|
+
);
|
|
277
|
+
target.accountRuntime.credentials.bindProxyTransport(proxyTransport);
|
|
278
|
+
}
|
|
279
|
+
logger(
|
|
280
|
+
`[agentkit] GitHub auth: channel API calls route through ${githubProxyUrl}`
|
|
281
|
+
);
|
|
282
|
+
} else {
|
|
283
|
+
for (const target of cursorGithubTargets) {
|
|
284
|
+
target.accountRuntime.credentials.bind(() => provider.getToken());
|
|
285
|
+
}
|
|
256
286
|
}
|
|
257
287
|
}
|
|
258
288
|
const resolvedCursorGithubCredentials = cursorGithubCredentials;
|
|
@@ -392,6 +422,7 @@ export async function startServer(
|
|
|
392
422
|
get: (runId) => evalRuns.get(runId),
|
|
393
423
|
listRunsWithActive: () => evalRuns.listRunsWithActive(),
|
|
394
424
|
start: (input) => evalRuns.start(input),
|
|
425
|
+
cancel: (runId) => evalRuns.cancel(runId),
|
|
395
426
|
});
|
|
396
427
|
const runtime: MountedRuntime = {
|
|
397
428
|
slug,
|
|
@@ -1171,6 +1202,42 @@ function mountAgentRoutes(
|
|
|
1171
1202
|
return jsonResponse(snap);
|
|
1172
1203
|
},
|
|
1173
1204
|
});
|
|
1205
|
+
router.add({
|
|
1206
|
+
method: "POST",
|
|
1207
|
+
pattern: `${base}/v1/dev/evals/runs/:runId/cancel`,
|
|
1208
|
+
auth: httpAuth,
|
|
1209
|
+
handler: async (_request, ctx) => {
|
|
1210
|
+
const runId = ctx.params.runId ?? "";
|
|
1211
|
+
try {
|
|
1212
|
+
const snap = await runtime.evalRuns.cancel(runId);
|
|
1213
|
+
return jsonResponse(snap);
|
|
1214
|
+
} catch (error) {
|
|
1215
|
+
if (error instanceof EvalRunUnknownError) {
|
|
1216
|
+
return jsonResponse(
|
|
1217
|
+
{ ok: false, error: "unknown_eval_run" },
|
|
1218
|
+
{ status: 404 }
|
|
1219
|
+
);
|
|
1220
|
+
}
|
|
1221
|
+
if (error instanceof EvalRunNotRunningError) {
|
|
1222
|
+
return jsonResponse(
|
|
1223
|
+
{
|
|
1224
|
+
ok: false,
|
|
1225
|
+
error: "eval_run_not_running",
|
|
1226
|
+
runId: error.runId,
|
|
1227
|
+
status: error.status,
|
|
1228
|
+
message: error.message,
|
|
1229
|
+
},
|
|
1230
|
+
{ status: 409 }
|
|
1231
|
+
);
|
|
1232
|
+
}
|
|
1233
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
1234
|
+
return jsonResponse(
|
|
1235
|
+
{ ok: false, error: "eval_cancel_failed", message },
|
|
1236
|
+
{ status: 400 }
|
|
1237
|
+
);
|
|
1238
|
+
}
|
|
1239
|
+
},
|
|
1240
|
+
});
|
|
1174
1241
|
|
|
1175
1242
|
if (dev) {
|
|
1176
1243
|
router.add({
|
|
@@ -2335,6 +2335,25 @@ export class SessionEngine {
|
|
|
2335
2335
|
}
|
|
2336
2336
|
}
|
|
2337
2337
|
|
|
2338
|
+
/**
|
|
2339
|
+
* Local session lookup with lazy restore by session id.
|
|
2340
|
+
*
|
|
2341
|
+
* `GET /v1/sessions` (cursor-hosted) can list durable rows that were not
|
|
2342
|
+
* bulk-restored into `--state-root` (restore caps, `restore: "off"`, or
|
|
2343
|
+
* eval Open-trace by id). Events/stream/follow-up must materialize that
|
|
2344
|
+
* one session before answering, or the playground shows an empty timeline
|
|
2345
|
+
* after redeploy.
|
|
2346
|
+
*/
|
|
2347
|
+
async getOrRestoreSession(
|
|
2348
|
+
sessionId: string
|
|
2349
|
+
): Promise<SessionRecord | undefined> {
|
|
2350
|
+
const local = await this.sessions.get(sessionId);
|
|
2351
|
+
if (local !== undefined) {
|
|
2352
|
+
return local;
|
|
2353
|
+
}
|
|
2354
|
+
return this.restoreSessionById(sessionId);
|
|
2355
|
+
}
|
|
2356
|
+
|
|
2338
2357
|
/**
|
|
2339
2358
|
* Lazy restore: a continuation lookup missed locally, so ask the sink
|
|
2340
2359
|
* for that one session and materialize it before resuming. Disk grows
|
|
@@ -2367,6 +2386,24 @@ export class SessionEngine {
|
|
|
2367
2386
|
return pending;
|
|
2368
2387
|
}
|
|
2369
2388
|
|
|
2389
|
+
private restoreSessionById(
|
|
2390
|
+
sessionId: string
|
|
2391
|
+
): Promise<SessionRecord | undefined> {
|
|
2392
|
+
const storage = this.storage;
|
|
2393
|
+
if (storage === undefined) {
|
|
2394
|
+
return Promise.resolve(undefined);
|
|
2395
|
+
}
|
|
2396
|
+
const key = `id\u0000${sessionId}`;
|
|
2397
|
+
let pending = this.restoreInFlight.get(key);
|
|
2398
|
+
if (pending === undefined) {
|
|
2399
|
+
pending = this.loadAndMaterializeById(storage, sessionId).finally(() =>
|
|
2400
|
+
this.restoreInFlight.delete(key)
|
|
2401
|
+
);
|
|
2402
|
+
this.restoreInFlight.set(key, pending);
|
|
2403
|
+
}
|
|
2404
|
+
return pending;
|
|
2405
|
+
}
|
|
2406
|
+
|
|
2370
2407
|
private async loadAndMaterializeByContinuation(
|
|
2371
2408
|
storage: StorageCoordinator,
|
|
2372
2409
|
channelId: string,
|
|
@@ -2380,10 +2417,31 @@ export class SessionEngine {
|
|
|
2380
2417
|
// Definitive miss: the caller starts a fresh session under this token.
|
|
2381
2418
|
return undefined;
|
|
2382
2419
|
}
|
|
2420
|
+
return this.materializeRestoredRecord(record);
|
|
2421
|
+
}
|
|
2422
|
+
|
|
2423
|
+
private async loadAndMaterializeById(
|
|
2424
|
+
storage: StorageCoordinator,
|
|
2425
|
+
sessionId: string
|
|
2426
|
+
): Promise<SessionRecord | undefined> {
|
|
2427
|
+
const record = await storage.getSessionById(sessionId);
|
|
2428
|
+
if (record === undefined) {
|
|
2429
|
+
return undefined;
|
|
2430
|
+
}
|
|
2431
|
+
return this.materializeRestoredRecord(record);
|
|
2432
|
+
}
|
|
2433
|
+
|
|
2434
|
+
private async materializeRestoredRecord(
|
|
2435
|
+
record: SessionRecord
|
|
2436
|
+
): Promise<SessionRecord> {
|
|
2383
2437
|
const local = await this.sessions.get(record.sessionId);
|
|
2384
2438
|
if (local !== undefined) {
|
|
2385
2439
|
return local;
|
|
2386
2440
|
}
|
|
2441
|
+
const storage = this.storage;
|
|
2442
|
+
if (storage === undefined) {
|
|
2443
|
+
return record;
|
|
2444
|
+
}
|
|
2387
2445
|
const events = await storage.listSessionEvents(record.sessionId);
|
|
2388
2446
|
await this.materializeSession(record, eventsNdjson(events));
|
|
2389
2447
|
this.logger(
|
|
@@ -329,6 +329,36 @@ export class StorageCoordinator {
|
|
|
329
329
|
return events;
|
|
330
330
|
}
|
|
331
331
|
|
|
332
|
+
/**
|
|
333
|
+
* One saved session by id (lazy restore for playground Open-trace /
|
|
334
|
+
* events / stream after a host replacement). Sink errors **propagate**
|
|
335
|
+
* — same posture as {@link getSessionByContinuation}. A definitive miss
|
|
336
|
+
* (no row, or a write-only sink without `get`) resolves undefined.
|
|
337
|
+
*/
|
|
338
|
+
async getSessionById(sessionId: string): Promise<SessionRecord | undefined> {
|
|
339
|
+
const get = this.definition.get;
|
|
340
|
+
if (get === undefined) {
|
|
341
|
+
return undefined;
|
|
342
|
+
}
|
|
343
|
+
if (typeof sessionId !== "string" || sessionId === "") {
|
|
344
|
+
return undefined;
|
|
345
|
+
}
|
|
346
|
+
const ctx = this.context("restore");
|
|
347
|
+
const record = (await get(
|
|
348
|
+
storageKeys.session(this.agentName, sessionId),
|
|
349
|
+
ctx
|
|
350
|
+
)) as SessionRecord | null | undefined;
|
|
351
|
+
if (record == null) {
|
|
352
|
+
return undefined;
|
|
353
|
+
}
|
|
354
|
+
if (record.sessionId !== sessionId) {
|
|
355
|
+
throw new Error(
|
|
356
|
+
`storage returned a session that does not match the requested id ${sessionId}`
|
|
357
|
+
);
|
|
358
|
+
}
|
|
359
|
+
return record;
|
|
360
|
+
}
|
|
361
|
+
|
|
332
362
|
/**
|
|
333
363
|
* One saved session by channel continuation key (lazy restore). Unlike
|
|
334
364
|
* the startup reads, sink errors **propagate**: a failing store must
|
|
@@ -363,11 +393,8 @@ export class StorageCoordinator {
|
|
|
363
393
|
`storage returned a malformed continuation entry for channel ${channelId}`
|
|
364
394
|
);
|
|
365
395
|
}
|
|
366
|
-
const record =
|
|
367
|
-
|
|
368
|
-
ctx
|
|
369
|
-
)) as SessionRecord | null | undefined;
|
|
370
|
-
if (record == null) {
|
|
396
|
+
const record = await this.getSessionById(sessionId);
|
|
397
|
+
if (record === undefined) {
|
|
371
398
|
// Index entry without its record (e.g. the record write was shed
|
|
372
399
|
// under at-most-once). The session is unrecoverable; treat as a miss
|
|
373
400
|
// so the conversation can continue rather than failing forever.
|
|
@@ -380,7 +407,6 @@ export class StorageCoordinator {
|
|
|
380
407
|
// mismatched row is a broken store, not a miss; treating it as a miss
|
|
381
408
|
// would fork the continuation token onto a new session.
|
|
382
409
|
if (
|
|
383
|
-
record.sessionId !== sessionId ||
|
|
384
410
|
record.channelId !== channelId ||
|
|
385
411
|
record.continuationKey !== continuationKey
|
|
386
412
|
) {
|
package/src/types.ts
CHANGED
|
@@ -1974,6 +1974,16 @@ export interface ServeOptions {
|
|
|
1974
1974
|
* SSO/Okta proxy in front of the host).
|
|
1975
1975
|
*/
|
|
1976
1976
|
allowAnonymousCursorGithub?: boolean;
|
|
1977
|
+
/**
|
|
1978
|
+
* Route `githubChannel({ cursorAccount })` API calls through the Cursor
|
|
1979
|
+
* backend's GitHub forwarder (`/v0/github-proxy`) instead of minting raw
|
|
1980
|
+
* installation tokens into this process. The backend logs and meters every
|
|
1981
|
+
* call with per-deployment attribution. `AGENT_SERVE_GITHUB_PROXY_URL`
|
|
1982
|
+
* overrides the forwarder base URL (default: the resolved Cursor API base
|
|
1983
|
+
* URL + `/v0/github-proxy`). Child `gh` processes still use a minted
|
|
1984
|
+
* `GH_TOKEN` lease (proxying `gh` is a follow-up).
|
|
1985
|
+
*/
|
|
1986
|
+
cursorGithubProxy?: boolean;
|
|
1977
1987
|
/**
|
|
1978
1988
|
* Allow {@link allowAnonymous} together with
|
|
1979
1989
|
* `defineConnection({ cursorAccount: true })`. Without this opt-in, `serve`
|
|
@@ -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"}
|
|
@@ -1,318 +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
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
18
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
19
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
20
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
21
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
22
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
23
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
24
|
-
});
|
|
25
|
-
};
|
|
26
|
-
import { appendChatStream, deleteMessage, postMessage, setThreadStatus, startChatStream, stopChatStream, updateMessage, } from "./api.js";
|
|
27
|
-
import { SLACK_POST_UPDATE_MIN_INTERVAL_MS } from "./constants.js";
|
|
28
|
-
import { computeStreamAppend } from "./stream.js";
|
|
29
|
-
function createPostUpdateStrategy(deps) {
|
|
30
|
-
const { botToken, getLog } = deps;
|
|
31
|
-
return {
|
|
32
|
-
inlineToolSteps: false,
|
|
33
|
-
start(_a) {
|
|
34
|
-
return __awaiter(this, arguments, void 0, function* ({ channel, channelId, threadTs, sessionId }) {
|
|
35
|
-
const log = getLog();
|
|
36
|
-
try {
|
|
37
|
-
const posted = yield postMessage({
|
|
38
|
-
botToken,
|
|
39
|
-
channel: channelId,
|
|
40
|
-
text: "…",
|
|
41
|
-
threadTs,
|
|
42
|
-
});
|
|
43
|
-
if (posted.ts !== "") {
|
|
44
|
-
channel.state.streamTs = posted.ts;
|
|
45
|
-
channel.state.streamChannelId = channelId;
|
|
46
|
-
channel.state.lastPostedText = "";
|
|
47
|
-
log.info("postMessage skeleton ok", {
|
|
48
|
-
channel: channelId,
|
|
49
|
-
message_ts: posted.ts,
|
|
50
|
-
session: sessionId,
|
|
51
|
-
});
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
catch (error) {
|
|
55
|
-
log.warn("postMessage skeleton failed", {
|
|
56
|
-
error: error instanceof Error ? error.message : String(error),
|
|
57
|
-
channel: channelId,
|
|
58
|
-
session: sessionId,
|
|
59
|
-
});
|
|
60
|
-
// Transient proxy/network failures must not permanently disable
|
|
61
|
-
// live delivery — only the stream path sets streamingUnavailable
|
|
62
|
-
// when Slack reports the feature unsupported.
|
|
63
|
-
}
|
|
64
|
-
});
|
|
65
|
-
},
|
|
66
|
-
append(_a) {
|
|
67
|
-
return __awaiter(this, arguments, void 0, function* ({ channel, channelId, streamTs, text, sessionId }) {
|
|
68
|
-
var _b;
|
|
69
|
-
const now = Date.now();
|
|
70
|
-
const isFirstUpdate = channel.state.lastPostedText === null ||
|
|
71
|
-
channel.state.lastPostedText === "";
|
|
72
|
-
const lastAt = (_b = channel.state.lastPostUpdateAtMs) !== null && _b !== void 0 ? _b : 0;
|
|
73
|
-
const due = isFirstUpdate || now - lastAt >= SLACK_POST_UPDATE_MIN_INTERVAL_MS;
|
|
74
|
-
if (!due) {
|
|
75
|
-
// Skip intermediate update; message.completed flushes full text.
|
|
76
|
-
return;
|
|
77
|
-
}
|
|
78
|
-
const result = yield updateMessage({
|
|
79
|
-
botToken,
|
|
80
|
-
channel: channelId,
|
|
81
|
-
ts: streamTs,
|
|
82
|
-
text,
|
|
83
|
-
});
|
|
84
|
-
if (!result.ok) {
|
|
85
|
-
getLog().warn("chat.update failed", {
|
|
86
|
-
error: result.error,
|
|
87
|
-
channel: channelId,
|
|
88
|
-
message_ts: streamTs,
|
|
89
|
-
session: sessionId,
|
|
90
|
-
});
|
|
91
|
-
return;
|
|
92
|
-
}
|
|
93
|
-
channel.state.lastPostUpdateAtMs = now;
|
|
94
|
-
channel.state.lastPostedText = text;
|
|
95
|
-
});
|
|
96
|
-
},
|
|
97
|
-
finalize(_a) {
|
|
98
|
-
return __awaiter(this, arguments, void 0, function* ({ channel, channelId, streamTs, text, sessionId }) {
|
|
99
|
-
const log = getLog();
|
|
100
|
-
const result = yield updateMessage({
|
|
101
|
-
botToken,
|
|
102
|
-
channel: channelId,
|
|
103
|
-
ts: streamTs,
|
|
104
|
-
text,
|
|
105
|
-
});
|
|
106
|
-
channel.state.streamTs = null;
|
|
107
|
-
if (result.ok) {
|
|
108
|
-
channel.state.lastPostedText = text;
|
|
109
|
-
log.info("reply delivered via chat.update", {
|
|
110
|
-
channel: channelId,
|
|
111
|
-
message_ts: streamTs,
|
|
112
|
-
session: sessionId,
|
|
113
|
-
chars: text.length,
|
|
114
|
-
});
|
|
115
|
-
return { delivered: true };
|
|
116
|
-
}
|
|
117
|
-
log.warn("chat.update finalize failed; falling back to postMessage", {
|
|
118
|
-
error: result.error,
|
|
119
|
-
channel: channelId,
|
|
120
|
-
message_ts: streamTs,
|
|
121
|
-
session: sessionId,
|
|
122
|
-
});
|
|
123
|
-
// Only suppress the fallback when the skeleton already holds the exact
|
|
124
|
-
// final text. Partial updates must not permanently truncate.
|
|
125
|
-
if (channel.state.lastPostedText === text) {
|
|
126
|
-
return { delivered: true };
|
|
127
|
-
}
|
|
128
|
-
// The skeleton still shows the placeholder or a stale partial and we're
|
|
129
|
-
// about to post the full reply as a fresh message. Best-effort delete the
|
|
130
|
-
// orphan so the thread doesn't show a duplicate.
|
|
131
|
-
yield deleteMessage({ botToken, channel: channelId, ts: streamTs });
|
|
132
|
-
return { delivered: false };
|
|
133
|
-
});
|
|
134
|
-
},
|
|
135
|
-
finalizeEmpty(_a) {
|
|
136
|
-
return __awaiter(this, arguments, void 0, function* ({ channelId, streamTs }) {
|
|
137
|
-
yield updateMessage({
|
|
138
|
-
botToken,
|
|
139
|
-
channel: channelId,
|
|
140
|
-
ts: streamTs,
|
|
141
|
-
text: " ",
|
|
142
|
-
});
|
|
143
|
-
});
|
|
144
|
-
},
|
|
145
|
-
cleanupOrphan(_a) {
|
|
146
|
-
return __awaiter(this, arguments, void 0, function* ({ channel }) {
|
|
147
|
-
var _b;
|
|
148
|
-
// A skeleton that was never finalized (e.g. an empty turn that produced
|
|
149
|
-
// no message.completed) would otherwise linger as a "…" placeholder
|
|
150
|
-
// forever. Best-effort delete it and clear typing.
|
|
151
|
-
const orphanTs = channel.state.streamTs;
|
|
152
|
-
if (orphanTs === null || orphanTs === "") {
|
|
153
|
-
return;
|
|
154
|
-
}
|
|
155
|
-
const orphanChannelId = (_b = channel.state.streamChannelId) !== null && _b !== void 0 ? _b : channel.state.channelId;
|
|
156
|
-
if (orphanChannelId !== null && orphanChannelId !== "") {
|
|
157
|
-
yield deleteMessage({
|
|
158
|
-
botToken,
|
|
159
|
-
channel: orphanChannelId,
|
|
160
|
-
ts: orphanTs,
|
|
161
|
-
});
|
|
162
|
-
}
|
|
163
|
-
channel.state.streamTs = null;
|
|
164
|
-
if (channel.state.channelId !== null && channel.state.threadTs !== null) {
|
|
165
|
-
yield setThreadStatus({
|
|
166
|
-
botToken,
|
|
167
|
-
channelId: channel.state.channelId,
|
|
168
|
-
threadTs: channel.state.threadTs,
|
|
169
|
-
status: "",
|
|
170
|
-
});
|
|
171
|
-
}
|
|
172
|
-
});
|
|
173
|
-
},
|
|
174
|
-
fail(_a) {
|
|
175
|
-
return __awaiter(this, arguments, void 0, function* ({ channel, channelId, streamTs, errorText }) {
|
|
176
|
-
const updated = yield updateMessage({
|
|
177
|
-
botToken,
|
|
178
|
-
channel: channelId,
|
|
179
|
-
ts: streamTs,
|
|
180
|
-
text: errorText,
|
|
181
|
-
});
|
|
182
|
-
channel.state.streamTs = null;
|
|
183
|
-
return { delivered: updated.ok };
|
|
184
|
-
});
|
|
185
|
-
},
|
|
186
|
-
};
|
|
187
|
-
}
|
|
188
|
-
function createStreamStrategy(deps) {
|
|
189
|
-
const { botToken, getLog } = deps;
|
|
190
|
-
return {
|
|
191
|
-
inlineToolSteps: true,
|
|
192
|
-
start(_a) {
|
|
193
|
-
return __awaiter(this, arguments, void 0, function* ({ channel, channelId, threadTs, sessionId }) {
|
|
194
|
-
const log = getLog();
|
|
195
|
-
const started = yield startChatStream({
|
|
196
|
-
botToken,
|
|
197
|
-
channel: channelId,
|
|
198
|
-
thread_ts: threadTs,
|
|
199
|
-
markdown_text: "",
|
|
200
|
-
});
|
|
201
|
-
if (!started.ok) {
|
|
202
|
-
log.warn("chat.startStream unavailable", {
|
|
203
|
-
error: started.error,
|
|
204
|
-
channel: channelId,
|
|
205
|
-
thread_ts: threadTs,
|
|
206
|
-
session: sessionId,
|
|
207
|
-
});
|
|
208
|
-
if (started.unsupported === true) {
|
|
209
|
-
channel.state.streamingUnavailable = true;
|
|
210
|
-
}
|
|
211
|
-
return;
|
|
212
|
-
}
|
|
213
|
-
channel.state.streamTs = started.ts;
|
|
214
|
-
channel.state.streamChannelId = started.channel;
|
|
215
|
-
channel.state.lastPostedText = "";
|
|
216
|
-
log.info("chat.startStream ok", {
|
|
217
|
-
channel: started.channel,
|
|
218
|
-
stream_ts: started.ts,
|
|
219
|
-
session: sessionId,
|
|
220
|
-
});
|
|
221
|
-
});
|
|
222
|
-
},
|
|
223
|
-
append(_a) {
|
|
224
|
-
return __awaiter(this, arguments, void 0, function* ({ channel, channelId, streamTs, text, sessionId }) {
|
|
225
|
-
const appendText = computeStreamAppend(channel.state.lastPostedText, text);
|
|
226
|
-
if (appendText === "") {
|
|
227
|
-
return;
|
|
228
|
-
}
|
|
229
|
-
const result = yield appendChatStream({
|
|
230
|
-
botToken,
|
|
231
|
-
channel: channelId,
|
|
232
|
-
ts: streamTs,
|
|
233
|
-
markdown_text: appendText,
|
|
234
|
-
});
|
|
235
|
-
if (!result.ok) {
|
|
236
|
-
getLog().warn("appendStream failed", {
|
|
237
|
-
error: result.error,
|
|
238
|
-
channel: channelId,
|
|
239
|
-
stream_ts: streamTs,
|
|
240
|
-
session: sessionId,
|
|
241
|
-
});
|
|
242
|
-
if (result.unsupported === true) {
|
|
243
|
-
channel.state.streamingUnavailable = true;
|
|
244
|
-
}
|
|
245
|
-
return;
|
|
246
|
-
}
|
|
247
|
-
channel.state.lastPostedText = text;
|
|
248
|
-
});
|
|
249
|
-
},
|
|
250
|
-
finalize(_a) {
|
|
251
|
-
return __awaiter(this, arguments, void 0, function* ({ channel, channelId, streamTs, text, sessionId }) {
|
|
252
|
-
const log = getLog();
|
|
253
|
-
// Only send the unsent suffix — full text was already appended.
|
|
254
|
-
const appendText = computeStreamAppend(channel.state.lastPostedText, text);
|
|
255
|
-
const stopped = yield stopChatStream({
|
|
256
|
-
botToken,
|
|
257
|
-
channel: channelId,
|
|
258
|
-
ts: streamTs,
|
|
259
|
-
markdown_text: appendText === "" ? undefined : appendText,
|
|
260
|
-
});
|
|
261
|
-
if (stopped.ok) {
|
|
262
|
-
channel.state.streamTs = null;
|
|
263
|
-
channel.state.lastPostedText = text;
|
|
264
|
-
log.info("reply delivered via stream", {
|
|
265
|
-
channel: channelId,
|
|
266
|
-
stream_ts: streamTs,
|
|
267
|
-
session: sessionId,
|
|
268
|
-
chars: text.length,
|
|
269
|
-
});
|
|
270
|
-
return { delivered: true };
|
|
271
|
-
}
|
|
272
|
-
log.warn("chat.stopStream failed; falling back to postMessage", {
|
|
273
|
-
error: stopped.error,
|
|
274
|
-
channel: channelId,
|
|
275
|
-
stream_ts: streamTs,
|
|
276
|
-
session: sessionId,
|
|
277
|
-
});
|
|
278
|
-
if (stopped.unsupported === true) {
|
|
279
|
-
channel.state.streamingUnavailable = true;
|
|
280
|
-
}
|
|
281
|
-
channel.state.streamTs = null;
|
|
282
|
-
// If we already streamed content, do not post the full reply again.
|
|
283
|
-
const alreadyStreamed = typeof channel.state.lastPostedText === "string" &&
|
|
284
|
-
channel.state.lastPostedText.length > 0;
|
|
285
|
-
return { delivered: alreadyStreamed };
|
|
286
|
-
});
|
|
287
|
-
},
|
|
288
|
-
finalizeEmpty(_a) {
|
|
289
|
-
return __awaiter(this, arguments, void 0, function* ({ channelId, streamTs }) {
|
|
290
|
-
yield stopChatStream({ botToken, channel: channelId, ts: streamTs });
|
|
291
|
-
});
|
|
292
|
-
},
|
|
293
|
-
cleanupOrphan() {
|
|
294
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
295
|
-
// The stream path closes its message in message.completed / turn.failed;
|
|
296
|
-
// there is nothing to clean up after turn.completed.
|
|
297
|
-
});
|
|
298
|
-
},
|
|
299
|
-
fail(_a) {
|
|
300
|
-
return __awaiter(this, arguments, void 0, function* ({ channel, channelId, streamTs, errorText }) {
|
|
301
|
-
const stopped = yield stopChatStream({
|
|
302
|
-
botToken,
|
|
303
|
-
channel: channelId,
|
|
304
|
-
ts: streamTs,
|
|
305
|
-
markdown_text: errorText,
|
|
306
|
-
});
|
|
307
|
-
channel.state.streamTs = null;
|
|
308
|
-
return { delivered: stopped.ok };
|
|
309
|
-
});
|
|
310
|
-
},
|
|
311
|
-
};
|
|
312
|
-
}
|
|
313
|
-
/** Pick the live-reply delivery strategy for a `buildDefaultEvents` instance. */
|
|
314
|
-
export function selectLiveDeliveryStrategy(deps, usePostUpdate) {
|
|
315
|
-
return usePostUpdate
|
|
316
|
-
? createPostUpdateStrategy(deps)
|
|
317
|
-
: createStreamStrategy(deps);
|
|
318
|
-
}
|