@cursor/bdk 0.2.1 → 0.2.2
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/README.md +1 -6
- package/dist/artifacts.d.ts +5 -2
- package/dist/artifacts.d.ts.map +1 -1
- package/dist/artifacts.js +5 -2
- package/dist/channels/slack/manifest.d.ts.map +1 -1
- package/dist/channels/slack/manifest.js +3 -2
- package/dist/channels/slack/types.d.ts +6 -1
- package/dist/channels/slack/types.d.ts.map +1 -1
- package/dist/docs/404.html +2 -2
- package/dist/docs/assets/{app.JVQvbRO-.js → app.DtYVVVyK.js} +4 -4
- package/dist/docs/assets/chunks/@localSearchIndexroot.BgTA2tV1.js +1 -0
- package/dist/docs/assets/chunks/{VPLocalSearchBox.BkhY63uW.js → VPLocalSearchBox.D47xT7J4.js} +1 -1
- package/dist/docs/assets/chunks/{arc.Cc1unYd3.js → arc.CDJ6xzxR.js} +1 -1
- package/dist/docs/assets/chunks/{architectureDiagram-Q4EWVU46.CAY_TPVz.js → architectureDiagram-Q4EWVU46.l1Xnjd3N.js} +1 -1
- package/dist/docs/assets/chunks/{baseUniq.my2VD3Xm.js → baseUniq.x-finShZ.js} +1 -1
- package/dist/docs/assets/chunks/{blockDiagram-DXYQGD6D.CQXAOmqd.js → blockDiagram-DXYQGD6D.COC3qynH.js} +1 -1
- package/dist/docs/assets/chunks/{c4Diagram-AHTNJAMY.D0AsQFSX.js → c4Diagram-AHTNJAMY.DdQO850E.js} +1 -1
- package/dist/docs/assets/chunks/channel.B2nMEx82.js +1 -0
- package/dist/docs/assets/chunks/{chunk-4BX2VUAB.DZjhgNls.js → chunk-4BX2VUAB.Dpn8omLk.js} +1 -1
- package/dist/docs/assets/chunks/{chunk-4TB4RGXK.qdcp_qbo.js → chunk-4TB4RGXK.C0XWStUN.js} +1 -1
- package/dist/docs/assets/chunks/{chunk-55IACEB6.BHXoZhJ-.js → chunk-55IACEB6.DsKSZfIM.js} +1 -1
- package/dist/docs/assets/chunks/{chunk-EDXVE4YY.Cds_Vwj3.js → chunk-EDXVE4YY.dNU6JDu6.js} +1 -1
- package/dist/docs/assets/chunks/{chunk-FMBD7UC4.CSl0HknT.js → chunk-FMBD7UC4.DN41fxKE.js} +1 -1
- package/dist/docs/assets/chunks/{chunk-OYMX7WX6.DJMvAt5N.js → chunk-OYMX7WX6.COpKCZus.js} +1 -1
- package/dist/docs/assets/chunks/{chunk-QZHKN3VN.BYQzBK9D.js → chunk-QZHKN3VN.HDB-azx2.js} +1 -1
- package/dist/docs/assets/chunks/{chunk-YZCP3GAM.BAvw7N4o.js → chunk-YZCP3GAM.DEeX_a2j.js} +1 -1
- package/dist/docs/assets/chunks/classDiagram-6PBFFD2Q.D8iCH2ve.js +1 -0
- package/dist/docs/assets/chunks/classDiagram-v2-HSJHXN6E.D8iCH2ve.js +1 -0
- package/dist/docs/assets/chunks/clone.5XNLjby0.js +1 -0
- package/dist/docs/assets/chunks/{cose-bilkent-S5V4N54A.Buf3seya.js → cose-bilkent-S5V4N54A.C3yGL2A8.js} +1 -1
- package/dist/docs/assets/chunks/{dagre-KV5264BT.DMGGa3uA.js → dagre-KV5264BT.Bpl24en4.js} +1 -1
- package/dist/docs/assets/chunks/{diagram-5BDNPKRD.DDjnwRmY.js → diagram-5BDNPKRD.nFco6seU.js} +1 -1
- package/dist/docs/assets/chunks/{diagram-G4DWMVQ6.RwyrIr8Q.js → diagram-G4DWMVQ6.DXhA6DWR.js} +1 -1
- package/dist/docs/assets/chunks/{diagram-MMDJMWI5.DRvQV16Z.js → diagram-MMDJMWI5.8GoOYcwk.js} +1 -1
- package/dist/docs/assets/chunks/{diagram-TYMM5635.Dw8W9BTk.js → diagram-TYMM5635.DDBlqvlJ.js} +1 -1
- package/dist/docs/assets/chunks/{erDiagram-SMLLAGMA.DQT1Hnwf.js → erDiagram-SMLLAGMA.vl_N81P4.js} +1 -1
- package/dist/docs/assets/chunks/{flowDiagram-DWJPFMVM.6_Aky-ut.js → flowDiagram-DWJPFMVM.Cteg8g7I.js} +1 -1
- package/dist/docs/assets/chunks/{ganttDiagram-T4ZO3ILL.DHIwqnqN.js → ganttDiagram-T4ZO3ILL.D4aMhlMM.js} +1 -1
- package/dist/docs/assets/chunks/{gitGraphDiagram-UUTBAWPF.CGd_eJbn.js → gitGraphDiagram-UUTBAWPF.DF_J0D4q.js} +1 -1
- package/dist/docs/assets/chunks/{graph.ChMEylkh.js → graph.DJs0LDCf.js} +1 -1
- package/dist/docs/assets/chunks/{infoDiagram-42DDH7IO.Cd4gMyAz.js → infoDiagram-42DDH7IO.Bb-4RQwg.js} +1 -1
- package/dist/docs/assets/chunks/{ishikawaDiagram-UXIWVN3A.D1uw7MXq.js → ishikawaDiagram-UXIWVN3A.DEtQRSbc.js} +1 -1
- package/dist/docs/assets/chunks/{journeyDiagram-VCZTEJTY.AWLXtelc.js → journeyDiagram-VCZTEJTY.DhQQ75FA.js} +1 -1
- package/dist/docs/assets/chunks/{kanban-definition-6JOO6SKY.CagPhAn5.js → kanban-definition-6JOO6SKY.C4gEw3Rk.js} +1 -1
- package/dist/docs/assets/chunks/{layout.ClTBBkE_.js → layout.DT-PGlXa.js} +1 -1
- package/dist/docs/assets/chunks/{linear.SwS2rOLA.js → linear.BMMe__JW.js} +1 -1
- package/dist/docs/assets/chunks/{min.By_x-Btb.js → min.XyaU9K9Q.js} +1 -1
- package/dist/docs/assets/chunks/{mindmap-definition-QFDTVHPH.By_RAMaP.js → mindmap-definition-QFDTVHPH.CbBM6xZ-.js} +1 -1
- package/dist/docs/assets/chunks/{pieDiagram-DEJITSTG.DfAl9sy4.js → pieDiagram-DEJITSTG.DFJoIVou.js} +1 -1
- package/dist/docs/assets/chunks/{quadrantDiagram-34T5L4WZ.CNuqFRBj.js → quadrantDiagram-34T5L4WZ.CQjkDYqb.js} +1 -1
- package/dist/docs/assets/chunks/{requirementDiagram-MS252O5E.DJ5CmTCl.js → requirementDiagram-MS252O5E.D-mK-JQu.js} +1 -1
- package/dist/docs/assets/chunks/{sankeyDiagram-XADWPNL6.D-T_AKJj.js → sankeyDiagram-XADWPNL6.BStQInpd.js} +1 -1
- package/dist/docs/assets/chunks/{sequenceDiagram-FGHM5R23.BRn9WcrR.js → sequenceDiagram-FGHM5R23.CA_eooPJ.js} +1 -1
- package/dist/docs/assets/chunks/{stateDiagram-FHFEXIEX.F12urmm7.js → stateDiagram-FHFEXIEX.BXl-b7ad.js} +1 -1
- package/dist/docs/assets/chunks/stateDiagram-v2-QKLJ7IA2.yGM2uLZQ.js +1 -0
- package/dist/docs/assets/chunks/{theme.zK3OJa_C.js → theme.q37tOs4x.js} +2 -2
- package/dist/docs/assets/chunks/{timeline-definition-GMOUNBTQ.B7GiQBeC.js → timeline-definition-GMOUNBTQ.vjuaGOSe.js} +1 -1
- package/dist/docs/assets/chunks/{vennDiagram-DHZGUBPP.D0niwuY_.js → vennDiagram-DHZGUBPP.BxduJl-F.js} +1 -1
- package/dist/docs/assets/chunks/wardley-RL74JXVD.DKfyIejL.js +162 -0
- package/dist/docs/assets/chunks/{wardleyDiagram-NUSXRM2D.DKaqpT7K.js → wardleyDiagram-NUSXRM2D.D1z3ds0D.js} +1 -1
- package/dist/docs/assets/chunks/{xychartDiagram-5P7HB3ND.e8BPicch.js → xychartDiagram-5P7HB3ND.CRU5Ti9b.js} +1 -1
- package/dist/docs/assets/{reference_artifacts.md.IFFC5Zln.js → reference_artifacts.md.CFMNPreZ.js} +1 -1
- package/dist/docs/assets/{reference_hooks.md.Dg3dEugd.js → reference_hooks.md.DbthhtIR.js} +1 -1
- package/dist/docs/assets/{reference_sessions.md.BtpTjZmh.js → reference_sessions.md.DeRUItHD.js} +1 -1
- package/dist/docs/assets/{reference_skills.md.Cy00QMKS.js → reference_skills.md.CRFTxt9M.js} +3 -3
- package/dist/docs/assets/{reference_skills.md.Cy00QMKS.lean.js → reference_skills.md.CRFTxt9M.lean.js} +1 -1
- package/dist/docs/building-with-agents.html +35 -35
- package/dist/docs/deployment.html +35 -35
- package/dist/docs/evals.html +35 -35
- package/dist/docs/guides/agent-to-agent.html +35 -35
- package/dist/docs/guides/bitbucket.html +35 -35
- package/dist/docs/guides/cloud-agents.html +35 -35
- package/dist/docs/guides/convert-automation.html +35 -35
- package/dist/docs/guides/github.html +35 -35
- package/dist/docs/guides/gitlab.html +35 -35
- package/dist/docs/guides/grokbot-agents.html +35 -35
- package/dist/docs/guides/hooks.html +35 -35
- package/dist/docs/guides/improve.html +35 -35
- package/dist/docs/guides/jev.html +35 -35
- package/dist/docs/guides/mcp-oauth.html +35 -35
- package/dist/docs/guides/opentelemetry.html +35 -35
- package/dist/docs/guides/slack.html +35 -35
- package/dist/docs/guides/webhooks.html +35 -35
- package/dist/docs/hashmap.json +1 -1
- package/dist/docs/hillclimbing.html +35 -35
- package/dist/docs/index.html +35 -35
- package/dist/docs/llms-full.txt +8 -6
- package/dist/docs/quickstart.html +35 -35
- package/dist/docs/reference/agent-config.html +35 -35
- package/dist/docs/reference/artifacts.html +37 -37
- package/dist/docs/reference/artifacts.md +1 -1
- package/dist/docs/reference/channels.html +35 -35
- package/dist/docs/reference/cli.html +35 -35
- package/dist/docs/reference/connections.html +35 -35
- package/dist/docs/reference/evals.html +35 -35
- package/dist/docs/reference/extensions.html +35 -35
- package/dist/docs/reference/hooks.html +37 -37
- package/dist/docs/reference/hooks.md +3 -2
- package/dist/docs/reference/http-api.html +35 -35
- package/dist/docs/reference/instructions.html +35 -35
- package/dist/docs/reference/playground.html +35 -35
- package/dist/docs/reference/project-layout.html +35 -35
- package/dist/docs/reference/prompt.html +35 -35
- package/dist/docs/reference/schedules.html +35 -35
- package/dist/docs/reference/sessions.html +36 -36
- package/dist/docs/reference/sessions.md +4 -3
- package/dist/docs/reference/skills.html +38 -38
- package/dist/docs/reference/subagents.html +35 -35
- package/dist/docs/reference/tools.html +35 -35
- package/dist/docs/templates/agentic-owners.html +35 -35
- package/dist/docs/templates/security-reviewer.html +35 -35
- package/dist/docs/templates/thermo-quality-review.html +35 -35
- package/dist/docs/templates/thermo-review.html +35 -35
- package/dist/docs/templates/triage.html +35 -35
- package/dist/docs/troubleshooting.html +35 -35
- package/dist/extensions/cursor-cloud-agents/extension.d.ts +16 -4
- package/dist/extensions/cursor-cloud-agents/extension.d.ts.map +1 -1
- package/dist/extensions/cursor-cloud-agents/extension.js +7 -3
- package/dist/extensions/cursor-cloud-agents/lib/channels.d.ts +3 -0
- package/dist/extensions/cursor-cloud-agents/lib/channels.d.ts.map +1 -0
- package/dist/extensions/cursor-cloud-agents/lib/channels.js +7 -0
- package/dist/extensions/cursor-cloud-agents/lib/repos.d.ts +4 -2
- package/dist/extensions/cursor-cloud-agents/lib/repos.d.ts.map +1 -1
- package/dist/extensions/cursor-cloud-agents/lib/repos.js +21 -12
- package/dist/extensions/cursor-cloud-agents/tools/cancel.d.ts.map +1 -1
- package/dist/extensions/cursor-cloud-agents/tools/cancel.js +2 -0
- package/dist/extensions/cursor-cloud-agents/tools/launch.d.ts.map +1 -1
- package/dist/extensions/cursor-cloud-agents/tools/launch.js +3 -1
- package/dist/extensions/cursor-cloud-agents/tools/reply.d.ts.map +1 -1
- package/dist/extensions/cursor-cloud-agents/tools/reply.js +2 -0
- package/dist/files-backends/cursor-hosted.js +4 -4
- package/dist/internal/artifacts-store.d.ts +12 -2
- package/dist/internal/artifacts-store.d.ts.map +1 -1
- package/dist/internal/artifacts-store.js +8 -4
- package/dist/internal/event-mapper.d.ts +46 -4
- package/dist/internal/event-mapper.d.ts.map +1 -1
- package/dist/internal/event-mapper.js +316 -25
- package/dist/internal/hosted-delivery.js +1 -1
- package/dist/internal/session-engine.d.ts +1 -1
- package/dist/internal/session-engine.d.ts.map +1 -1
- package/dist/internal/session-engine.js +24 -3
- package/dist/playground/assets/index-6BbTPnaT.css +1 -0
- package/dist/playground/assets/{index-FFdUqTt_.js → index-CI7FAmOP.js} +43 -43
- package/dist/playground/index.html +2 -2
- package/dist/types.d.ts +39 -3
- package/dist/types.d.ts.map +1 -1
- package/docs/reference/artifacts.md +1 -1
- package/docs/reference/hooks.md +3 -2
- package/docs/reference/sessions.md +4 -3
- package/package.json +2 -2
- package/src/artifacts.ts +5 -2
- package/src/channels/slack/manifest.ts +2 -1
- package/src/channels/slack/types.ts +6 -1
- package/src/extensions/cursor-cloud-agents/extension.ts +23 -6
- package/src/extensions/cursor-cloud-agents/lib/channels.ts +11 -0
- package/src/extensions/cursor-cloud-agents/lib/repos.ts +19 -7
- package/src/extensions/cursor-cloud-agents/tools/cancel.ts +2 -0
- package/src/extensions/cursor-cloud-agents/tools/launch.ts +3 -1
- package/src/extensions/cursor-cloud-agents/tools/reply.ts +2 -0
- package/src/files-backends/cursor-hosted.ts +4 -4
- package/src/internal/artifacts-store.ts +14 -3
- package/src/internal/event-mapper.ts +367 -36
- package/src/internal/hosted-delivery.ts +1 -1
- package/src/internal/session-engine.ts +24 -8
- package/src/types.ts +45 -4
- package/dist/docs/assets/chunks/@localSearchIndexroot.Caw9W1pM.js +0 -1
- package/dist/docs/assets/chunks/channel.Sapo9HJZ.js +0 -1
- package/dist/docs/assets/chunks/classDiagram-6PBFFD2Q.NPiy3Hz7.js +0 -1
- package/dist/docs/assets/chunks/classDiagram-v2-HSJHXN6E.NPiy3Hz7.js +0 -1
- package/dist/docs/assets/chunks/clone.zl2qolPE.js +0 -1
- package/dist/docs/assets/chunks/stateDiagram-v2-QKLJ7IA2._auCa3fR.js +0 -1
- package/dist/docs/assets/chunks/wardley-RL74JXVD.1zhHNRsx.js +0 -162
- package/dist/playground/assets/index-BMV_IcEE.css +0 -1
- /package/dist/docs/assets/{reference_artifacts.md.IFFC5Zln.lean.js → reference_artifacts.md.CFMNPreZ.lean.js} +0 -0
- /package/dist/docs/assets/{reference_hooks.md.Dg3dEugd.lean.js → reference_hooks.md.DbthhtIR.lean.js} +0 -0
- /package/dist/docs/assets/{reference_sessions.md.BtpTjZmh.lean.js → reference_sessions.md.DeRUItHD.lean.js} +0 -0
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { defineTool } from "../../../tools.js";
|
|
2
2
|
import type { ToolDefinition } from "../../../types.js";
|
|
3
3
|
import { cloudAgentsBackend } from "../lib/backend.js";
|
|
4
|
+
import { assertWriteChannel } from "../lib/channels.js";
|
|
4
5
|
import { assertOwned } from "../lib/fleet.js";
|
|
5
6
|
import { agentRef } from "../lib/inputs.js";
|
|
6
7
|
|
|
@@ -10,6 +11,7 @@ const cancel: ToolDefinition = defineTool({
|
|
|
10
11
|
effect: "write",
|
|
11
12
|
inputSchema: agentRef,
|
|
12
13
|
async execute(input, ctx) {
|
|
14
|
+
assertWriteChannel(ctx);
|
|
13
15
|
await assertOwned(ctx, input.agent_id);
|
|
14
16
|
await cloudAgentsBackend().pause(input.agent_id);
|
|
15
17
|
return { agentId: input.agent_id, cancelled: true };
|
|
@@ -3,6 +3,7 @@ import { defineTool } from "../../../tools.js";
|
|
|
3
3
|
import type { ToolDefinition } from "../../../types.js";
|
|
4
4
|
import extension from "../extension.js";
|
|
5
5
|
import { cloudAgentsBackend } from "../lib/backend.js";
|
|
6
|
+
import { assertWriteChannel } from "../lib/channels.js";
|
|
6
7
|
import { recordLaunch } from "../lib/fleet.js";
|
|
7
8
|
import { launchRepos } from "../lib/repos.js";
|
|
8
9
|
|
|
@@ -21,7 +22,7 @@ const launch: ToolDefinition = defineTool({
|
|
|
21
22
|
.url()
|
|
22
23
|
.optional()
|
|
23
24
|
.describe(
|
|
24
|
-
"GitHub
|
|
25
|
+
"Repository clone URL (GitHub or Origin), one of the configured repositories. Defaults to the configured repository when there is exactly one.",
|
|
25
26
|
),
|
|
26
27
|
starting_ref: z
|
|
27
28
|
.string()
|
|
@@ -39,6 +40,7 @@ const launch: ToolDefinition = defineTool({
|
|
|
39
40
|
.describe("Display name; derived from the prompt when omitted."),
|
|
40
41
|
}),
|
|
41
42
|
async execute(input, ctx) {
|
|
43
|
+
assertWriteChannel(ctx);
|
|
42
44
|
const { cloud, model } = extension.config;
|
|
43
45
|
const launched = await cloudAgentsBackend().launch({
|
|
44
46
|
prompt: input.prompt,
|
|
@@ -3,6 +3,7 @@ import { defineTool } from "../../../tools.js";
|
|
|
3
3
|
import type { ToolDefinition } from "../../../types.js";
|
|
4
4
|
import extension from "../extension.js";
|
|
5
5
|
import { cloudAgentsBackend } from "../lib/backend.js";
|
|
6
|
+
import { assertWriteChannel } from "../lib/channels.js";
|
|
6
7
|
import { assertOwned } from "../lib/fleet.js";
|
|
7
8
|
import { agentRef } from "../lib/inputs.js";
|
|
8
9
|
|
|
@@ -21,6 +22,7 @@ const reply: ToolDefinition = defineTool({
|
|
|
21
22
|
),
|
|
22
23
|
}),
|
|
23
24
|
async execute(input, ctx) {
|
|
25
|
+
assertWriteChannel(ctx);
|
|
24
26
|
await assertOwned(ctx, input.agent_id);
|
|
25
27
|
const { runId } = await cloudAgentsBackend().followUp(
|
|
26
28
|
input.agent_id,
|
|
@@ -925,10 +925,10 @@ export function cursorHostedFiles(options: CursorHostedFilesOptions = {}): Hoste
|
|
|
925
925
|
if (files.wire !== "flush") {
|
|
926
926
|
return false;
|
|
927
927
|
}
|
|
928
|
-
//
|
|
929
|
-
//
|
|
930
|
-
// the
|
|
931
|
-
//
|
|
928
|
+
// With an observed etag the flush delete is If-Match on that version.
|
|
929
|
+
// Without one, the server tombstones whatever live object occupies
|
|
930
|
+
// the key (no directory walk here) and an absent key settles as
|
|
931
|
+
// `already_deleted`.
|
|
932
932
|
const cached = observedEtags.get(key);
|
|
933
933
|
const response = await flushPost<FlushWireResponse>(options, "/flush", {
|
|
934
934
|
store: files.store,
|
|
@@ -107,6 +107,12 @@ export interface CreateArtifactsStoreOptions {
|
|
|
107
107
|
config?: ArtifactsConfig;
|
|
108
108
|
/** Explicit sink override (tests). Omitted → hosted store or local disk. */
|
|
109
109
|
sink?: FileSink;
|
|
110
|
+
/**
|
|
111
|
+
* Whether `tag` enforces {@link ArtifactsConfig.max} by listing and
|
|
112
|
+
* deleting. Default true. Hosted architecture v2 passes false: the
|
|
113
|
+
* installation store is allowed to grow, and a tag must not list the prefix.
|
|
114
|
+
*/
|
|
115
|
+
enforceCap?: () => boolean;
|
|
110
116
|
}
|
|
111
117
|
|
|
112
118
|
/** Kind used by freeform tags when no kinds are declared. */
|
|
@@ -114,8 +120,11 @@ export const ARTIFACT_DEFAULT_KIND = "artifact";
|
|
|
114
120
|
|
|
115
121
|
/**
|
|
116
122
|
* Upsert + list semantics over one {@link ArtifactRowStore}: kind/schema
|
|
117
|
-
* validation, deterministic ids for keyed tags, and `max` eviction.
|
|
118
|
-
*
|
|
123
|
+
* validation, deterministic ids for keyed tags, and `max` eviction.
|
|
124
|
+
* Architecture v1 and self-hosted v2 evict. Hosted architecture v2 sets
|
|
125
|
+
* {@link CreateArtifactsStoreOptions.enforceCap} false and does not list
|
|
126
|
+
* or delete on tag. The engine wraps this into the per-context
|
|
127
|
+
* {@link ArtifactsApi} facades and
|
|
119
128
|
* owns the `artifact.tagged` event append.
|
|
120
129
|
*/
|
|
121
130
|
export class ArtifactsStore {
|
|
@@ -123,6 +132,7 @@ export class ArtifactsStore {
|
|
|
123
132
|
private readonly content: ArtifactContentStore;
|
|
124
133
|
private readonly config: ArtifactsConfig | undefined;
|
|
125
134
|
private readonly max: number;
|
|
135
|
+
private readonly enforceCap: () => boolean;
|
|
126
136
|
/** Serializes tags so read-modify-write upserts and eviction don't race. */
|
|
127
137
|
private tagChain: Promise<unknown> = Promise.resolve();
|
|
128
138
|
|
|
@@ -137,6 +147,7 @@ export class ArtifactsStore {
|
|
|
137
147
|
}
|
|
138
148
|
this.config = options.config;
|
|
139
149
|
this.max = resolveArtifactsMax(options.config);
|
|
150
|
+
this.enforceCap = options.enforceCap ?? (() => true);
|
|
140
151
|
}
|
|
141
152
|
|
|
142
153
|
tag(input: ArtifactTagInput): Promise<ArtifactRecord> {
|
|
@@ -181,7 +192,7 @@ export class ArtifactsStore {
|
|
|
181
192
|
}
|
|
182
193
|
}
|
|
183
194
|
await this.rows.put(record);
|
|
184
|
-
if (existing === undefined) {
|
|
195
|
+
if (existing === undefined && this.enforceCap()) {
|
|
185
196
|
await this.evictPastCap();
|
|
186
197
|
}
|
|
187
198
|
return record;
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
7
|
import type { InteractionUpdate as SdkInteractionUpdate, ToolCall } from "@cursor/sdk";
|
|
8
|
-
import type { SessionEventPayload, TurnUsage } from "../types.js";
|
|
8
|
+
import type { ActionCall, ActionResult, SessionEventPayload, TurnUsage } from "../types.js";
|
|
9
9
|
|
|
10
10
|
const CUSTOM_TOOLS_PROVIDER = "custom-user-tools";
|
|
11
11
|
/** Authored server tools on cloud turns; keep in sync with `SERVER_TOOLS_MCP_SERVER_NAME`. */
|
|
@@ -39,7 +39,8 @@ type NestedTaskUpdate =
|
|
|
39
39
|
modelCallId: string;
|
|
40
40
|
}
|
|
41
41
|
| { type: "step-started"; stepId: number }
|
|
42
|
-
| { type: "step-completed"; stepId: number; stepDurationMs: number }
|
|
42
|
+
| { type: "step-completed"; stepId: number; stepDurationMs: number }
|
|
43
|
+
| { type: "tool-requests-listed"; callCount: number };
|
|
43
44
|
|
|
44
45
|
type ToolCallDeltaUpdate = {
|
|
45
46
|
type: "tool-call-delta";
|
|
@@ -48,8 +49,13 @@ type ToolCallDeltaUpdate = {
|
|
|
48
49
|
taskUpdate: NestedTaskUpdate;
|
|
49
50
|
};
|
|
50
51
|
|
|
51
|
-
|
|
52
|
-
type
|
|
52
|
+
type ToolRequestsListedUpdate = {
|
|
53
|
+
type: "tool-requests-listed";
|
|
54
|
+
callCount: number;
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
/** SDK updates plus list-closed / nested task deltas ahead of `@cursor/sdk`. */
|
|
58
|
+
type InteractionUpdate = SdkInteractionUpdate | ToolCallDeltaUpdate | ToolRequestsListedUpdate;
|
|
53
59
|
|
|
54
60
|
function asToolCallDelta(update: InteractionUpdate): ToolCallDeltaUpdate | undefined {
|
|
55
61
|
if ((update as { type: string }).type !== "tool-call-delta") {
|
|
@@ -58,6 +64,12 @@ function asToolCallDelta(update: InteractionUpdate): ToolCallDeltaUpdate | undef
|
|
|
58
64
|
return update as ToolCallDeltaUpdate;
|
|
59
65
|
}
|
|
60
66
|
|
|
67
|
+
function modelCallIdOf(update: { modelCallId?: unknown }): string | undefined {
|
|
68
|
+
return typeof update.modelCallId === "string" && update.modelCallId !== ""
|
|
69
|
+
? update.modelCallId
|
|
70
|
+
: undefined;
|
|
71
|
+
}
|
|
72
|
+
|
|
61
73
|
export interface ToolCallDescription {
|
|
62
74
|
toolName: string;
|
|
63
75
|
args?: unknown;
|
|
@@ -74,6 +86,17 @@ interface NestedAccumulators {
|
|
|
74
86
|
reasoning: string;
|
|
75
87
|
}
|
|
76
88
|
|
|
89
|
+
type ToolWave = {
|
|
90
|
+
key: string;
|
|
91
|
+
modelCallId?: string;
|
|
92
|
+
parentCallId?: string;
|
|
93
|
+
calls: ActionCall[];
|
|
94
|
+
results: ActionResult[];
|
|
95
|
+
expectedCalls?: number;
|
|
96
|
+
requestedEmitted: boolean;
|
|
97
|
+
completedEmitted: boolean;
|
|
98
|
+
};
|
|
99
|
+
|
|
77
100
|
export class TurnEventMapper {
|
|
78
101
|
private textAccumulator = "";
|
|
79
102
|
private reasoningAccumulator = "";
|
|
@@ -82,6 +105,17 @@ export class TurnEventMapper {
|
|
|
82
105
|
private summaryTitle: string | undefined;
|
|
83
106
|
/** Per-parent-call accumulators for nested subagent streams. */
|
|
84
107
|
private readonly nested = new Map<string, NestedAccumulators>();
|
|
108
|
+
/** One wave per model step (or per call when the step id is missing). */
|
|
109
|
+
private readonly waves = new Map<string, ToolWave>();
|
|
110
|
+
/**
|
|
111
|
+
* Keys of waves that already emitted `actions.completed`, plus each
|
|
112
|
+
* finished call's singleton key. A late duplicate cannot reopen the
|
|
113
|
+
* batch or emit a second pair for the same callId. A new late callId
|
|
114
|
+
* still gets its own singleton.
|
|
115
|
+
*/
|
|
116
|
+
private readonly sealedWaveKeys = new Set<string>();
|
|
117
|
+
/** Listed-call count from `tool-requests-listed`, keyed by parentCallId. */
|
|
118
|
+
private readonly listedCounts = new Map<string, number>();
|
|
85
119
|
|
|
86
120
|
/**
|
|
87
121
|
* @param isStubbed Reports whether a finished tool call was answered by the
|
|
@@ -173,17 +207,25 @@ export class TurnEventMapper {
|
|
|
173
207
|
}
|
|
174
208
|
case "tool-call-started": {
|
|
175
209
|
this.flushAssistantText("tool_call");
|
|
176
|
-
this.
|
|
210
|
+
this.noteToolStarted(update.callId, update.toolCall, {
|
|
211
|
+
modelCallId: modelCallIdOf(update),
|
|
212
|
+
});
|
|
177
213
|
return;
|
|
178
214
|
}
|
|
179
215
|
case "tool-call-completed": {
|
|
180
|
-
this.
|
|
216
|
+
this.noteToolCompleted(update.callId, update.toolCall, {
|
|
217
|
+
modelCallId: modelCallIdOf(update),
|
|
218
|
+
});
|
|
181
219
|
return;
|
|
182
220
|
}
|
|
183
221
|
case "step-started": {
|
|
184
222
|
this.emit({ type: "step.started", data: { stepId: update.stepId } });
|
|
185
223
|
return;
|
|
186
224
|
}
|
|
225
|
+
case "tool-requests-listed": {
|
|
226
|
+
this.noteRequestsListed(undefined, update.callCount);
|
|
227
|
+
return;
|
|
228
|
+
}
|
|
187
229
|
case "step-completed": {
|
|
188
230
|
this.emit({
|
|
189
231
|
type: "step.completed",
|
|
@@ -223,6 +265,8 @@ export class TurnEventMapper {
|
|
|
223
265
|
|
|
224
266
|
/** Close out the turn: finalize any open assistant text block. */
|
|
225
267
|
finish(): void {
|
|
268
|
+
this.sealOpenRequests();
|
|
269
|
+
this.flushOpenResults();
|
|
226
270
|
this.flushAssistantText("stop");
|
|
227
271
|
for (const parentCallId of this.nested.keys()) {
|
|
228
272
|
this.flushNestedAssistantText(parentCallId, "stop");
|
|
@@ -273,15 +317,26 @@ export class TurnEventMapper {
|
|
|
273
317
|
}
|
|
274
318
|
case "tool-call-started": {
|
|
275
319
|
this.flushNestedAssistantText(parentCallId, "tool_call");
|
|
276
|
-
this.
|
|
320
|
+
this.noteToolStarted(update.callId, update.toolCall, {
|
|
321
|
+
parentCallId,
|
|
322
|
+
modelCallId: modelCallIdOf(update),
|
|
323
|
+
});
|
|
277
324
|
return;
|
|
278
325
|
}
|
|
279
326
|
case "tool-call-completed": {
|
|
280
|
-
this.
|
|
327
|
+
this.noteToolCompleted(update.callId, update.toolCall, {
|
|
328
|
+
parentCallId,
|
|
329
|
+
modelCallId: modelCallIdOf(update),
|
|
330
|
+
});
|
|
281
331
|
return;
|
|
282
332
|
}
|
|
283
333
|
case "partial-tool-call":
|
|
334
|
+
return;
|
|
284
335
|
case "step-started":
|
|
336
|
+
return;
|
|
337
|
+
case "tool-requests-listed":
|
|
338
|
+
this.noteRequestsListed(parentCallId, update.callCount);
|
|
339
|
+
return;
|
|
285
340
|
case "step-completed":
|
|
286
341
|
return;
|
|
287
342
|
default: {
|
|
@@ -290,22 +345,36 @@ export class TurnEventMapper {
|
|
|
290
345
|
}
|
|
291
346
|
}
|
|
292
347
|
|
|
293
|
-
private
|
|
348
|
+
private noteToolStarted(
|
|
349
|
+
callId: string,
|
|
350
|
+
toolCall: ToolCall,
|
|
351
|
+
ids?: { parentCallId?: string; modelCallId?: string },
|
|
352
|
+
): void {
|
|
353
|
+
const parentCallId = ids?.parentCallId;
|
|
354
|
+
const modelCallId = ids?.modelCallId;
|
|
294
355
|
const description = describeToolCall(toolCall);
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
},
|
|
305
|
-
],
|
|
356
|
+
const call: ActionCall = {
|
|
357
|
+
callId,
|
|
358
|
+
toolName: description.toolName,
|
|
359
|
+
args: description.args,
|
|
360
|
+
parentCallId,
|
|
361
|
+
modelCallId,
|
|
362
|
+
};
|
|
363
|
+
if (modelCallId !== undefined) {
|
|
364
|
+
this.sealOpenRequests({
|
|
306
365
|
parentCallId,
|
|
307
|
-
|
|
308
|
-
|
|
366
|
+
exceptModelCallId: modelCallId,
|
|
367
|
+
});
|
|
368
|
+
}
|
|
369
|
+
const wave = this.waveForStart({ parentCallId, modelCallId, callId });
|
|
370
|
+
if (wave === undefined) {
|
|
371
|
+
return;
|
|
372
|
+
}
|
|
373
|
+
if (wave.calls.every(existing => existing.callId !== callId)) {
|
|
374
|
+
wave.calls.push(call);
|
|
375
|
+
}
|
|
376
|
+
this.adoptSingletonResults(wave, parentCallId, callId);
|
|
377
|
+
this.maybeSealListedWave(wave);
|
|
309
378
|
// Subagent bookends only fire for the top-level task tool, not nested
|
|
310
379
|
// tools inside a subagent (nested subagents aren't supported).
|
|
311
380
|
if (description.subagent !== undefined && parentCallId === undefined) {
|
|
@@ -318,22 +387,44 @@ export class TurnEventMapper {
|
|
|
318
387
|
},
|
|
319
388
|
});
|
|
320
389
|
}
|
|
390
|
+
if (wave.modelCallId === undefined) {
|
|
391
|
+
this.sealWaveRequests(wave);
|
|
392
|
+
}
|
|
321
393
|
}
|
|
322
394
|
|
|
323
|
-
private
|
|
395
|
+
private noteToolCompleted(
|
|
396
|
+
callId: string,
|
|
397
|
+
toolCall: ToolCall,
|
|
398
|
+
ids?: { parentCallId?: string; modelCallId?: string },
|
|
399
|
+
): void {
|
|
400
|
+
const parentCallId = ids?.parentCallId;
|
|
401
|
+
const modelCallId = ids?.modelCallId;
|
|
324
402
|
const description = describeToolCall(toolCall);
|
|
325
403
|
const result = describeToolResult(toolCall);
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
404
|
+
const actionResult: ActionResult = {
|
|
405
|
+
callId,
|
|
406
|
+
toolName: description.toolName,
|
|
407
|
+
output: result.output,
|
|
408
|
+
isError: result.isError,
|
|
409
|
+
stubbed: this.isStubbed(callId) ? true : undefined,
|
|
410
|
+
parentCallId,
|
|
411
|
+
modelCallId,
|
|
412
|
+
};
|
|
413
|
+
const wave = this.waveForComplete({ parentCallId, modelCallId, callId });
|
|
414
|
+
if (wave === undefined) {
|
|
415
|
+
return;
|
|
416
|
+
}
|
|
417
|
+
const isNew = wave.results.every(existing => existing.callId !== callId);
|
|
418
|
+
if (isNew) {
|
|
419
|
+
wave.results.push(actionResult);
|
|
420
|
+
}
|
|
421
|
+
if (wave.requestedEmitted && isNew) {
|
|
422
|
+
this.emit({
|
|
423
|
+
type: "action.result",
|
|
424
|
+
data: actionResult,
|
|
425
|
+
});
|
|
426
|
+
this.maybeEmitActionsCompleted(wave);
|
|
427
|
+
}
|
|
337
428
|
if (description.subagent !== undefined && parentCallId === undefined) {
|
|
338
429
|
this.flushNestedAssistantText(callId, "stop");
|
|
339
430
|
this.nested.delete(callId);
|
|
@@ -344,6 +435,242 @@ export class TurnEventMapper {
|
|
|
344
435
|
}
|
|
345
436
|
}
|
|
346
437
|
|
|
438
|
+
private callBelongsToWave(wave: ToolWave, callId: string): boolean {
|
|
439
|
+
return (
|
|
440
|
+
wave.calls.some(existing => existing.callId === callId) ||
|
|
441
|
+
wave.results.some(existing => existing.callId === callId)
|
|
442
|
+
);
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
private singletonWave(parentCallId: string | undefined, callId: string): ToolWave | undefined {
|
|
446
|
+
const key = waveKey({ parentCallId, callId });
|
|
447
|
+
if (this.sealedWaveKeys.has(key) && !this.waves.has(key)) {
|
|
448
|
+
return undefined;
|
|
449
|
+
}
|
|
450
|
+
return this.ensureWave(key, { parentCallId });
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
/**
|
|
454
|
+
* Starts join the open model-step wave until `actions.requested` seals.
|
|
455
|
+
* A later start for that same step is its own singleton pair so completed
|
|
456
|
+
* cannot list tools the matching requested envelope never had.
|
|
457
|
+
*/
|
|
458
|
+
private waveForStart(ids: {
|
|
459
|
+
parentCallId?: string;
|
|
460
|
+
modelCallId?: string;
|
|
461
|
+
callId: string;
|
|
462
|
+
}): ToolWave | undefined {
|
|
463
|
+
const groupedKey = waveKey(ids);
|
|
464
|
+
const grouped = this.waves.get(groupedKey);
|
|
465
|
+
if (grouped !== undefined && !grouped.requestedEmitted) {
|
|
466
|
+
return grouped;
|
|
467
|
+
}
|
|
468
|
+
if (grouped !== undefined && this.callBelongsToWave(grouped, ids.callId)) {
|
|
469
|
+
return grouped;
|
|
470
|
+
}
|
|
471
|
+
if (grouped !== undefined && grouped.requestedEmitted) {
|
|
472
|
+
return this.singletonWave(ids.parentCallId, ids.callId);
|
|
473
|
+
}
|
|
474
|
+
if (this.sealedWaveKeys.has(groupedKey)) {
|
|
475
|
+
return this.singletonWave(ids.parentCallId, ids.callId);
|
|
476
|
+
}
|
|
477
|
+
return this.ensureWave(groupedKey, {
|
|
478
|
+
modelCallId: ids.modelCallId,
|
|
479
|
+
parentCallId: ids.parentCallId,
|
|
480
|
+
});
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
/**
|
|
484
|
+
* Completes join a model-step wave only when that call already started
|
|
485
|
+
* there. A start-less complete on an open sibling batch would flush with
|
|
486
|
+
* `actions.requested` and then block `actions.completed` forever.
|
|
487
|
+
*/
|
|
488
|
+
private waveForComplete(ids: {
|
|
489
|
+
parentCallId?: string;
|
|
490
|
+
modelCallId?: string;
|
|
491
|
+
callId: string;
|
|
492
|
+
}): ToolWave | undefined {
|
|
493
|
+
const groupedKey = waveKey(ids);
|
|
494
|
+
const grouped = this.waves.get(groupedKey);
|
|
495
|
+
if (grouped !== undefined && this.callBelongsToWave(grouped, ids.callId)) {
|
|
496
|
+
return grouped;
|
|
497
|
+
}
|
|
498
|
+
if (grouped !== undefined) {
|
|
499
|
+
return this.singletonWave(ids.parentCallId, ids.callId);
|
|
500
|
+
}
|
|
501
|
+
if (this.sealedWaveKeys.has(groupedKey)) {
|
|
502
|
+
return this.waves.get(waveKey({ parentCallId: ids.parentCallId, callId: ids.callId }));
|
|
503
|
+
}
|
|
504
|
+
return this.ensureWave(groupedKey, {
|
|
505
|
+
modelCallId: ids.modelCallId,
|
|
506
|
+
parentCallId: ids.parentCallId,
|
|
507
|
+
});
|
|
508
|
+
}
|
|
509
|
+
|
|
510
|
+
private adoptSingletonResults(
|
|
511
|
+
wave: ToolWave,
|
|
512
|
+
parentCallId: string | undefined,
|
|
513
|
+
callId: string,
|
|
514
|
+
): void {
|
|
515
|
+
const singletonKey = waveKey({ parentCallId, callId });
|
|
516
|
+
if (singletonKey === wave.key) {
|
|
517
|
+
return;
|
|
518
|
+
}
|
|
519
|
+
const singleton = this.waves.get(singletonKey);
|
|
520
|
+
if (singleton === undefined) {
|
|
521
|
+
return;
|
|
522
|
+
}
|
|
523
|
+
for (const result of singleton.results) {
|
|
524
|
+
if (wave.results.every(existing => existing.callId !== result.callId)) {
|
|
525
|
+
wave.results.push(result);
|
|
526
|
+
}
|
|
527
|
+
}
|
|
528
|
+
this.waves.delete(singletonKey);
|
|
529
|
+
}
|
|
530
|
+
|
|
531
|
+
private ensureWave(key: string, ids: { modelCallId?: string; parentCallId?: string }): ToolWave {
|
|
532
|
+
let wave = this.waves.get(key);
|
|
533
|
+
if (wave === undefined) {
|
|
534
|
+
const expectedCalls = this.listedCounts.get(ids.parentCallId ?? "");
|
|
535
|
+
wave = {
|
|
536
|
+
key,
|
|
537
|
+
modelCallId: ids.modelCallId,
|
|
538
|
+
parentCallId: ids.parentCallId,
|
|
539
|
+
expectedCalls,
|
|
540
|
+
calls: [],
|
|
541
|
+
results: [],
|
|
542
|
+
requestedEmitted: false,
|
|
543
|
+
completedEmitted: false,
|
|
544
|
+
};
|
|
545
|
+
this.waves.set(key, wave);
|
|
546
|
+
}
|
|
547
|
+
return wave;
|
|
548
|
+
}
|
|
549
|
+
|
|
550
|
+
private noteRequestsListed(parentCallId: string | undefined, callCount: number): void {
|
|
551
|
+
const listed = Math.max(0, callCount);
|
|
552
|
+
if (listed === 0) {
|
|
553
|
+
this.sealOpenRequests({ parentCallId });
|
|
554
|
+
this.listedCounts.delete(parentCallId ?? "");
|
|
555
|
+
return;
|
|
556
|
+
}
|
|
557
|
+
this.listedCounts.set(parentCallId ?? "", listed);
|
|
558
|
+
for (const wave of this.waves.values()) {
|
|
559
|
+
if (wave.parentCallId !== parentCallId || wave.requestedEmitted) {
|
|
560
|
+
continue;
|
|
561
|
+
}
|
|
562
|
+
wave.expectedCalls = listed;
|
|
563
|
+
this.maybeSealListedWave(wave);
|
|
564
|
+
}
|
|
565
|
+
}
|
|
566
|
+
|
|
567
|
+
private maybeSealListedWave(wave: ToolWave): void {
|
|
568
|
+
const expected = wave.expectedCalls ?? this.listedCounts.get(wave.parentCallId ?? "");
|
|
569
|
+
if (expected !== undefined && wave.calls.length >= expected) {
|
|
570
|
+
this.sealWaveRequests(wave);
|
|
571
|
+
}
|
|
572
|
+
}
|
|
573
|
+
|
|
574
|
+
private sealOpenRequests(ids?: { parentCallId?: string; exceptModelCallId?: string }): void {
|
|
575
|
+
const parentCallId = ids?.parentCallId;
|
|
576
|
+
const exceptModelCallId = ids?.exceptModelCallId;
|
|
577
|
+
for (const wave of this.waves.values()) {
|
|
578
|
+
if (wave.parentCallId !== parentCallId) {
|
|
579
|
+
continue;
|
|
580
|
+
}
|
|
581
|
+
if (exceptModelCallId !== undefined && wave.modelCallId === exceptModelCallId) {
|
|
582
|
+
continue;
|
|
583
|
+
}
|
|
584
|
+
this.sealWaveRequests(wave);
|
|
585
|
+
}
|
|
586
|
+
}
|
|
587
|
+
|
|
588
|
+
private sealWaveRequests(wave: ToolWave): void {
|
|
589
|
+
if (wave.requestedEmitted || wave.calls.length === 0) {
|
|
590
|
+
return;
|
|
591
|
+
}
|
|
592
|
+
wave.requestedEmitted = true;
|
|
593
|
+
this.listedCounts.delete(wave.parentCallId ?? "");
|
|
594
|
+
this.emit({
|
|
595
|
+
type: "actions.requested",
|
|
596
|
+
data: {
|
|
597
|
+
calls: wave.calls,
|
|
598
|
+
parentCallId: wave.parentCallId,
|
|
599
|
+
modelCallId: wave.modelCallId,
|
|
600
|
+
},
|
|
601
|
+
});
|
|
602
|
+
for (const result of wave.results) {
|
|
603
|
+
this.emit({
|
|
604
|
+
type: "action.result",
|
|
605
|
+
data: result,
|
|
606
|
+
});
|
|
607
|
+
}
|
|
608
|
+
this.maybeEmitActionsCompleted(wave);
|
|
609
|
+
}
|
|
610
|
+
|
|
611
|
+
private maybeEmitActionsCompleted(wave: ToolWave): void {
|
|
612
|
+
if (
|
|
613
|
+
wave.completedEmitted ||
|
|
614
|
+
!wave.requestedEmitted ||
|
|
615
|
+
wave.calls.length === 0 ||
|
|
616
|
+
wave.results.length < wave.calls.length
|
|
617
|
+
) {
|
|
618
|
+
return;
|
|
619
|
+
}
|
|
620
|
+
const callIds = new Set(wave.calls.map(call => call.callId));
|
|
621
|
+
if (!wave.results.every(result => callIds.has(result.callId))) {
|
|
622
|
+
return;
|
|
623
|
+
}
|
|
624
|
+
if (!wave.calls.every(call => wave.results.some(result => result.callId === call.callId))) {
|
|
625
|
+
return;
|
|
626
|
+
}
|
|
627
|
+
this.emitActionsCompleted(wave);
|
|
628
|
+
}
|
|
629
|
+
|
|
630
|
+
private emitActionsCompleted(wave: ToolWave): void {
|
|
631
|
+
wave.completedEmitted = true;
|
|
632
|
+
this.emit({
|
|
633
|
+
type: "actions.completed",
|
|
634
|
+
data: {
|
|
635
|
+
results: wave.results,
|
|
636
|
+
parentCallId: wave.parentCallId,
|
|
637
|
+
modelCallId: wave.modelCallId,
|
|
638
|
+
},
|
|
639
|
+
});
|
|
640
|
+
this.forgetWave(wave);
|
|
641
|
+
}
|
|
642
|
+
|
|
643
|
+
private forgetWave(wave: ToolWave): void {
|
|
644
|
+
this.waves.delete(wave.key);
|
|
645
|
+
this.sealedWaveKeys.add(wave.key);
|
|
646
|
+
for (const callId of new Set([
|
|
647
|
+
...wave.calls.map(call => call.callId),
|
|
648
|
+
...wave.results.map(result => result.callId),
|
|
649
|
+
])) {
|
|
650
|
+
this.sealedWaveKeys.add(waveKey({ parentCallId: wave.parentCallId, callId }));
|
|
651
|
+
}
|
|
652
|
+
wave.calls = [];
|
|
653
|
+
wave.results = [];
|
|
654
|
+
}
|
|
655
|
+
|
|
656
|
+
private flushOpenResults(): void {
|
|
657
|
+
for (const wave of [...this.waves.values()]) {
|
|
658
|
+
if (wave.calls.length === 0 && wave.results.length > 0) {
|
|
659
|
+
wave.calls = wave.results.map(result => ({
|
|
660
|
+
callId: result.callId,
|
|
661
|
+
toolName: result.toolName,
|
|
662
|
+
parentCallId: result.parentCallId,
|
|
663
|
+
modelCallId: result.modelCallId,
|
|
664
|
+
}));
|
|
665
|
+
}
|
|
666
|
+
this.sealWaveRequests(wave);
|
|
667
|
+
this.maybeEmitActionsCompleted(wave);
|
|
668
|
+
if (!wave.completedEmitted) {
|
|
669
|
+
this.forgetWave(wave);
|
|
670
|
+
}
|
|
671
|
+
}
|
|
672
|
+
}
|
|
673
|
+
|
|
347
674
|
private ensureNested(parentCallId: string): NestedAccumulators {
|
|
348
675
|
let acc = this.nested.get(parentCallId);
|
|
349
676
|
if (acc === undefined) {
|
|
@@ -415,10 +742,10 @@ export function describeToolCall(toolCall: ToolCall): ToolCallDescription {
|
|
|
415
742
|
toolName: "task",
|
|
416
743
|
args: {
|
|
417
744
|
description: toolCall.args.description,
|
|
418
|
-
|
|
745
|
+
subagentType: subagentName,
|
|
419
746
|
},
|
|
420
747
|
subagent: {
|
|
421
|
-
|
|
748
|
+
name: subagentName,
|
|
422
749
|
description: toolCall.args.description,
|
|
423
750
|
},
|
|
424
751
|
};
|
|
@@ -462,6 +789,10 @@ export function describeToolResult(toolCall: ToolCall): ToolResultDescription {
|
|
|
462
789
|
return { output: result.value, isError: false };
|
|
463
790
|
}
|
|
464
791
|
|
|
792
|
+
function waveKey(ids: { parentCallId?: string; modelCallId?: string; callId: string }): string {
|
|
793
|
+
return `${ids.parentCallId ?? ""}:${ids.modelCallId ?? `call:${ids.callId}`}`;
|
|
794
|
+
}
|
|
795
|
+
|
|
465
796
|
function addUsage(total: TurnUsage | undefined, usage: TurnUsage): TurnUsage {
|
|
466
797
|
if (total === undefined) {
|
|
467
798
|
return { ...usage };
|
|
@@ -615,7 +615,7 @@ export function registerHostedDeliveryRoute(input: {
|
|
|
615
615
|
}
|
|
616
616
|
};
|
|
617
617
|
|
|
618
|
-
// Hosted callers reach this only through
|
|
618
|
+
// Hosted callers reach this only through Anyrun's signed pod-port URL.
|
|
619
619
|
// The marker is a second, route-specific fence distinct from channel auth.
|
|
620
620
|
const auth: AuthPolicy = request => {
|
|
621
621
|
if (request.headers.get(HOSTED_DELIVERY_HEADER) !== "1") {
|