@copilotkit/channels-core 0.4.1-canary.perfall1 → 0.5.0

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 (47) hide show
  1. package/README.md +7 -8
  2. package/dist/canonical-run-loop.test.d.ts +2 -0
  3. package/dist/canonical-run-loop.test.d.ts.map +1 -0
  4. package/dist/canonical-run-loop.test.js +453 -0
  5. package/dist/codec.d.ts +2 -3
  6. package/dist/codec.d.ts.map +1 -1
  7. package/dist/create-channel.d.ts +110 -4
  8. package/dist/create-channel.d.ts.map +1 -1
  9. package/dist/create-channel.js +258 -92
  10. package/dist/create-channel.test.js +552 -29
  11. package/dist/delivery-error.d.ts +17 -0
  12. package/dist/delivery-error.d.ts.map +1 -0
  13. package/dist/delivery-error.js +22 -0
  14. package/dist/index.d.ts +6 -2
  15. package/dist/index.d.ts.map +1 -1
  16. package/dist/index.js +8 -0
  17. package/dist/managed-v1-await-choice-guard.test.d.ts +2 -0
  18. package/dist/managed-v1-await-choice-guard.test.d.ts.map +1 -0
  19. package/dist/managed-v1-await-choice-guard.test.js +52 -0
  20. package/dist/platform-adapter.d.ts +74 -11
  21. package/dist/platform-adapter.d.ts.map +1 -1
  22. package/dist/run-loop.d.ts +25 -6
  23. package/dist/run-loop.d.ts.map +1 -1
  24. package/dist/run-loop.js +289 -39
  25. package/dist/run-loop.test.js +37 -0
  26. package/dist/sanitize-agent-events.d.ts +24 -0
  27. package/dist/sanitize-agent-events.d.ts.map +1 -0
  28. package/dist/sanitize-agent-events.js +88 -0
  29. package/dist/sanitize-agent-events.test.d.ts +2 -0
  30. package/dist/sanitize-agent-events.test.d.ts.map +1 -0
  31. package/dist/sanitize-agent-events.test.js +194 -0
  32. package/dist/source-platform.test.d.ts +2 -0
  33. package/dist/source-platform.test.d.ts.map +1 -0
  34. package/dist/source-platform.test.js +149 -0
  35. package/dist/testing/fake-adapter.d.ts +8 -1
  36. package/dist/testing/fake-adapter.d.ts.map +1 -1
  37. package/dist/testing/fake-adapter.js +30 -1
  38. package/dist/testing/fake-agent.d.ts +5 -0
  39. package/dist/testing/fake-agent.d.ts.map +1 -1
  40. package/dist/testing/fake-agent.js +12 -0
  41. package/dist/thread-promise-contract.test.d.ts +2 -0
  42. package/dist/thread-promise-contract.test.d.ts.map +1 -0
  43. package/dist/thread-promise-contract.test.js +37 -0
  44. package/dist/thread.d.ts +5 -0
  45. package/dist/thread.d.ts.map +1 -1
  46. package/dist/thread.js +338 -243
  47. package/package.json +4 -4
@@ -0,0 +1,194 @@
1
+ import { describe, it, expect } from "vitest";
2
+ import { HttpAgent } from "@ag-ui/client";
3
+ import { sanitizeAgentEventStream } from "./sanitize-agent-events.js";
4
+ import { createChannel } from "./create-channel.js";
5
+ import { FakeAdapter } from "./testing/fake-adapter.js";
6
+ import { FakeAgent } from "./testing/fake-agent.js";
7
+ const tick = () => new Promise((r) => setTimeout(r, 0));
8
+ const encoder = new TextEncoder();
9
+ /** Serialize an AG-UI event as one SSE frame. */
10
+ const frame = (event) => `data: ${JSON.stringify(event)}\n\n`;
11
+ /** A Response whose body streams `chunks` verbatim, one enqueue per chunk. */
12
+ function streamResponse(chunks, contentType = "text/event-stream") {
13
+ const body = new ReadableStream({
14
+ start(c) {
15
+ for (const chunk of chunks)
16
+ c.enqueue(encoder.encode(chunk));
17
+ c.close();
18
+ },
19
+ });
20
+ return new Response(body, {
21
+ status: 200,
22
+ headers: { "content-type": contentType },
23
+ });
24
+ }
25
+ /**
26
+ * A run whose `TOOL_CALL_START` carries `parentMessageId: null` — the shape
27
+ * `@ag-ui/langgraph` emits for the tool call that triggers an interrupt, and
28
+ * the one `EventSchemas.parse` rejects with "Expected string, received null".
29
+ */
30
+ const nullParentRun = () => [
31
+ frame({ type: "RUN_STARTED", threadId: "t1", runId: "r1" }),
32
+ frame({
33
+ type: "TOOL_CALL_START",
34
+ toolCallId: "tc1",
35
+ toolCallName: "ask_human",
36
+ parentMessageId: null,
37
+ }),
38
+ frame({ type: "TOOL_CALL_ARGS", toolCallId: "tc1", delta: "{}" }),
39
+ frame({ type: "TOOL_CALL_END", toolCallId: "tc1" }),
40
+ frame({ type: "RUN_FINISHED", threadId: "t1", runId: "r1" }),
41
+ ];
42
+ /** An `HttpAgent` whose transport replays `chunks` instead of hitting a server. */
43
+ function agentServing(chunks, contentType) {
44
+ return new HttpAgent({
45
+ url: "http://agent.test/run",
46
+ fetch: (async () => streamResponse(chunks, contentType)),
47
+ });
48
+ }
49
+ /** Read a wrapped transport's response body back as text. */
50
+ async function bodyText(agent) {
51
+ const res = await agent.fetch("http://agent.test/run", {});
52
+ return await res.text();
53
+ }
54
+ describe("sanitizeAgentEventStream", () => {
55
+ it("lets a run carrying a null parentMessageId reach RUN_FINISHED", async () => {
56
+ const agent = sanitizeAgentEventStream(agentServing(nullParentRun()));
57
+ const started = [];
58
+ await agent.runAgent({}, {
59
+ onToolCallStartEvent: ({ event }) => void started.push(event.toolCallName),
60
+ });
61
+ expect(started).toEqual(["ask_human"]);
62
+ });
63
+ it("aborts that same run when the sanitizer is not applied", async () => {
64
+ const agent = agentServing(nullParentRun());
65
+ await expect(agent.runAgent({})).rejects.toThrow(/parentMessageId|received null/);
66
+ });
67
+ it("coerces the null to an empty string and leaves every other byte alone", async () => {
68
+ const agent = sanitizeAgentEventStream(agentServing([
69
+ ": keep-alive\n\n",
70
+ frame({
71
+ type: "TOOL_CALL_START",
72
+ toolCallId: "tc1",
73
+ toolCallName: "ask_human",
74
+ parentMessageId: null,
75
+ }),
76
+ frame({
77
+ type: "TOOL_CALL_START",
78
+ toolCallId: "tc2",
79
+ toolCallName: "other",
80
+ parentMessageId: "msg-1",
81
+ }),
82
+ ]));
83
+ expect(await bodyText(agent)).toBe(": keep-alive\n\n" +
84
+ `data: {"type":"TOOL_CALL_START","toolCallId":"tc1","toolCallName":"ask_human","parentMessageId":""}\n\n` +
85
+ `data: {"type":"TOOL_CALL_START","toolCallId":"tc2","toolCallName":"other","parentMessageId":"msg-1"}\n\n`);
86
+ });
87
+ it("coerces a null split across two transport chunks", async () => {
88
+ const whole = frame({
89
+ type: "TOOL_CALL_START",
90
+ toolCallId: "tc1",
91
+ toolCallName: "ask_human",
92
+ parentMessageId: null,
93
+ });
94
+ const split = whole.indexOf("null") + 2;
95
+ const agent = sanitizeAgentEventStream(agentServing([whole.slice(0, split), whole.slice(split)]));
96
+ expect(await bodyText(agent)).toContain(`"parentMessageId":""`);
97
+ });
98
+ it("still converts a mid-stream abort into RUN_ERROR rather than failing the run", async () => {
99
+ // The stock transform turns an AbortError into a synthetic RUN_ERROR and
100
+ // completes the stream. Replacing the transform (as SanitizingHttpAgent
101
+ // does) forfeits that; wrapping the transport must not.
102
+ const abort = Object.assign(new Error("aborted"), { name: "AbortError" });
103
+ const body = new ReadableStream({
104
+ start(c) {
105
+ c.enqueue(encoder.encode(frame({ type: "RUN_STARTED", threadId: "t1", runId: "r1" })));
106
+ c.error(abort);
107
+ },
108
+ });
109
+ const agent = sanitizeAgentEventStream(new HttpAgent({
110
+ url: "http://agent.test/run",
111
+ fetch: (async () => new Response(body, {
112
+ status: 200,
113
+ headers: { "content-type": "text/event-stream" },
114
+ })),
115
+ }));
116
+ const errors = [];
117
+ await agent.runAgent({}, { onRunErrorEvent: ({ event }) => void errors.push(event.code ?? "") });
118
+ expect(errors).toEqual(["abort"]);
119
+ });
120
+ it("passes a non-SSE body through untouched so protobuf still negotiates", async () => {
121
+ const proto = '\u0000\u0001"parentMessageId":null';
122
+ const agent = sanitizeAgentEventStream(agentServing([proto], "application/vnd.ag-ui+proto"));
123
+ expect(await bodyText(agent)).toBe(proto);
124
+ });
125
+ it("does not re-wrap a transport it has already wrapped", () => {
126
+ const agent = sanitizeAgentEventStream(agentServing(nullParentRun()));
127
+ const wrapped = agent.fetch;
128
+ sanitizeAgentEventStream(agent);
129
+ expect(agent.fetch).toBe(wrapped);
130
+ });
131
+ it("leaves an agent that has no HTTP transport alone", () => {
132
+ const agent = new FakeAgent();
133
+ expect(sanitizeAgentEventStream(agent)).toBe(agent);
134
+ expect("fetch" in agent).toBe(false);
135
+ });
136
+ });
137
+ describe("createChannel({ sanitizeAgentEvents })", () => {
138
+ /** Run one turn through a channel backed by `agent`; resolve the run's error, if any. */
139
+ async function runTurn(agent, opts) {
140
+ const fake = new FakeAdapter();
141
+ const channel = createChannel({
142
+ adapters: [fake],
143
+ agent: () => agent,
144
+ ...opts,
145
+ });
146
+ let failure;
147
+ channel.onMention(async ({ thread }) => {
148
+ try {
149
+ await thread.runAgent();
150
+ }
151
+ catch (err) {
152
+ failure = err;
153
+ }
154
+ });
155
+ await channel.ɵruntime.start();
156
+ fake.emitTurn({ userText: "yo", conversationKey: "c1" });
157
+ await tick();
158
+ await tick();
159
+ return failure;
160
+ }
161
+ it("sanitizes a null parentMessageId by default", async () => {
162
+ expect(await runTurn(agentServing(nullParentRun()))).toBeUndefined();
163
+ });
164
+ it("survives the per-run clone of a singleton agent", async () => {
165
+ // A singleton `agent` is cloned per turn (isolateAgentInstance). HttpAgent's
166
+ // clone() copies the transport but not own-property overrides of run(), so
167
+ // sanitizing has to live on the transport to reach the cloned instance.
168
+ const fake = new FakeAdapter();
169
+ const channel = createChannel({
170
+ adapters: [fake],
171
+ agent: agentServing(nullParentRun()),
172
+ });
173
+ let failure;
174
+ channel.onMention(async ({ thread }) => {
175
+ try {
176
+ await thread.runAgent();
177
+ }
178
+ catch (err) {
179
+ failure = err;
180
+ }
181
+ });
182
+ await channel.ɵruntime.start();
183
+ fake.emitTurn({ userText: "yo", conversationKey: "c1" });
184
+ await tick();
185
+ await tick();
186
+ expect(failure).toBeUndefined();
187
+ });
188
+ it("lets the run abort when sanitizing is disabled", async () => {
189
+ const failure = await runTurn(agentServing(nullParentRun()), {
190
+ sanitizeAgentEvents: false,
191
+ });
192
+ expect(String(failure)).toMatch(/parentMessageId|received null/);
193
+ });
194
+ });
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=source-platform.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"source-platform.test.d.ts","sourceRoot":"","sources":["../src/source-platform.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,149 @@
1
+ import { z } from "zod";
2
+ import { expect, test, vi } from "vitest";
3
+ import { createChannel } from "./create-channel.js";
4
+ import { MemoryStore } from "./state/memory-store.js";
5
+ import { FakeAdapter } from "./testing/fake-adapter.js";
6
+ import { FakeAgent } from "./testing/fake-agent.js";
7
+ test("an ingress source platform reaches the text thread and its tool context", async () => {
8
+ const observed = {};
9
+ const adapter = new FakeAdapter({ platform: "intelligence" });
10
+ const agent = new FakeAgent([
11
+ (subscriber) => {
12
+ subscriber.onToolCallEndEvent?.({
13
+ event: { toolCallId: "tool-call-1" },
14
+ toolCallName: "capture_platform",
15
+ toolCallArgs: {},
16
+ });
17
+ subscriber.onRunFinishedEvent?.({ event: {} });
18
+ },
19
+ (subscriber) => {
20
+ subscriber.onRunFinishedEvent?.({ event: {} });
21
+ },
22
+ ]);
23
+ const channel = createChannel({
24
+ adapters: [adapter],
25
+ agent: () => agent,
26
+ tools: [
27
+ {
28
+ name: "capture_platform",
29
+ description: "Capture the handler platform",
30
+ parameters: z.object({}),
31
+ handler: (_args, ctx) => {
32
+ observed.toolPlatform = ctx.platform;
33
+ observed.toolThreadPlatform = ctx.thread.platform;
34
+ return "captured";
35
+ },
36
+ },
37
+ ],
38
+ });
39
+ channel.onMessage(async ({ message, thread }) => {
40
+ observed.messagePlatform = message.platform;
41
+ observed.threadPlatform = thread.platform;
42
+ await thread.runAgent();
43
+ });
44
+ await channel.ɵruntime.start();
45
+ await adapter.getSink().onTurn({
46
+ conversationKey: "conversation-1",
47
+ replyTarget: {},
48
+ userText: "hello",
49
+ platform: "slack",
50
+ });
51
+ expect(observed).toEqual({
52
+ messagePlatform: "slack",
53
+ threadPlatform: "slack",
54
+ toolPlatform: "slack",
55
+ toolThreadPlatform: "slack",
56
+ });
57
+ });
58
+ test("an ingress source platform scopes identity resolution and event dedupe", async () => {
59
+ const state = new MemoryStore();
60
+ const dedupeSeen = vi.spyOn(state.dedup, "seen").mockResolvedValue(false);
61
+ const identity = vi.fn(() => "person-1");
62
+ const adapter = new FakeAdapter({ platform: "intelligence" });
63
+ const channel = createChannel({
64
+ adapters: [adapter],
65
+ store: {
66
+ adapter: state,
67
+ identity,
68
+ transcripts: {},
69
+ },
70
+ });
71
+ let userKey;
72
+ channel.onMessage(({ message }) => {
73
+ userKey = message.userKey;
74
+ });
75
+ await channel.ɵruntime.start();
76
+ await adapter.getSink().onTurn({
77
+ conversationKey: "conversation-1",
78
+ replyTarget: {},
79
+ userText: "hello",
80
+ platform: "teams",
81
+ eventId: "event-1",
82
+ user: { id: "user-1" },
83
+ });
84
+ expect(dedupeSeen).toHaveBeenCalledWith("message:teams:created:event-1:event-1", 300_000);
85
+ expect(identity).toHaveBeenCalledWith(expect.objectContaining({
86
+ adapter: "teams",
87
+ message: expect.objectContaining({ platform: "teams" }),
88
+ }));
89
+ expect(userKey).toBe("person-1");
90
+ });
91
+ test("non-text ingress keeps source platform in handler contexts and dedupe keys", async () => {
92
+ const state = new MemoryStore();
93
+ const dedupeSeen = vi.spyOn(state.dedup, "seen").mockResolvedValue(false);
94
+ const adapter = new FakeAdapter({ platform: "intelligence" });
95
+ const observed = {};
96
+ const channel = createChannel({
97
+ adapters: [adapter],
98
+ store: { adapter: state },
99
+ });
100
+ channel.onCommand("triage", ({ platform, thread }) => {
101
+ observed.commandPlatform = platform;
102
+ observed.commandThreadPlatform = thread.platform;
103
+ });
104
+ channel.onInteraction("approve", ({ message, platform, thread }) => {
105
+ observed.interactionMessagePlatform = message.platform;
106
+ observed.interactionPlatform = platform;
107
+ observed.interactionThreadPlatform = thread.platform;
108
+ });
109
+ channel.onReaction(({ thread }) => {
110
+ observed.reactionThreadPlatform = thread.platform;
111
+ });
112
+ await channel.ɵruntime.start();
113
+ const sink = adapter.getSink();
114
+ await sink.onCommand({
115
+ command: "triage",
116
+ conversationKey: "command-conversation",
117
+ eventId: "command-event",
118
+ platform: "teams",
119
+ replyTarget: {},
120
+ text: "",
121
+ });
122
+ const interaction = {
123
+ id: "approve",
124
+ conversationKey: "interaction-conversation",
125
+ eventId: "interaction-event",
126
+ platform: "slack",
127
+ replyTarget: {},
128
+ };
129
+ await sink.onInteraction(interaction);
130
+ await sink.onReaction({
131
+ added: true,
132
+ conversationKey: "reaction-conversation",
133
+ messageId: "message-1",
134
+ platform: "teams",
135
+ raw: {},
136
+ rawEmoji: "👍",
137
+ replyTarget: {},
138
+ });
139
+ expect(observed).toEqual({
140
+ commandPlatform: "teams",
141
+ commandThreadPlatform: "teams",
142
+ interactionMessagePlatform: "slack",
143
+ interactionPlatform: "slack",
144
+ interactionThreadPlatform: "slack",
145
+ reactionThreadPlatform: "teams",
146
+ });
147
+ expect(dedupeSeen).toHaveBeenCalledWith("evt:teams:command-event", 300_000);
148
+ expect(dedupeSeen).toHaveBeenCalledWith("evt:slack:interaction-event", 300_000);
149
+ });
@@ -35,6 +35,8 @@ export declare class FakeAdapter implements PlatformAdapter {
35
35
  reactions?: boolean;
36
36
  nativeEphemeral?: boolean;
37
37
  modals?: boolean;
38
+ /** When true, activation requires an onMention or onMessage handler. */
39
+ messageEvents?: boolean;
38
40
  /** Platform name override (defaults to "fake"); useful when a test needs distinct adapters. */
39
41
  platform?: string;
40
42
  /** When true, `start()` rejects — simulates an adapter that fails to come up. */
@@ -60,8 +62,13 @@ export declare class FakeAdapter implements PlatformAdapter {
60
62
  stateStore?: StateStore;
61
63
  private sink?;
62
64
  private counter;
65
+ private turnCounter;
63
66
  /** Expose the registered sink so tests can invoke onTurn() directly for overlap/lock tests. */
64
- getSink(): IngressSink;
67
+ getSink(): Omit<IngressSink, "onTurn"> & {
68
+ onTurn(turn: Omit<IncomingTurn, "operation"> & {
69
+ operation?: IncomingTurn["operation"];
70
+ }): void | Promise<void>;
71
+ };
65
72
  start(sink: IngressSink): Promise<void>;
66
73
  stop(): Promise<void>;
67
74
  render(ir: ChannelNode[]): NativePayload;
@@ -1 +1 @@
1
- {"version":3,"file":"fake-adapter.d.ts","sourceRoot":"","sources":["../../src/testing/fake-adapter.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,WAAW,EACX,UAAU,EACV,YAAY,EACZ,aAAa,EACd,MAAM,yBAAyB,CAAC;AACjC,OAAO,KAAK,EACV,eAAe,EACf,mBAAmB,EACnB,WAAW,EACX,YAAY,EACZ,mBAAmB,EACnB,gBAAgB,EAChB,eAAe,EACf,WAAW,EAGX,WAAW,EACX,aAAa,EACb,SAAS,EACT,iBAAiB,EACjB,gBAAgB,EAChB,mBAAmB,EACnB,kBAAkB,EAClB,iBAAiB,EAClB,MAAM,wBAAwB,CAAC;AAChC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAClD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AAE1D,oHAAoH;AACpH,wBAAgB,mBAAmB,IAAI,WAAW,CAgCjD;AAED,qBAAa,WAAY,YAAW,eAAe;IACjD,QAAQ,SAAU;IAClB,QAAQ,CAAC,YAAY,EAAE,mBAAmB,CAAC;IAC3C,QAAQ,CAAC,aAAa,QAAQ;IAE9B,sEAAsE;IACtE,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;IAC5B,4FAA4F;IAC5F,QAAQ,CAAC,oBAAoB,EAAE,OAAO,CAAC;IACvC,oEAAoE;IACpE,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;IAC3B,mGAAmG;IACnG,OAAO,UAAS;IAEhB;;;;;;;;;;;;;OAaG;gBAED,QAAQ,GAAE;QACR,WAAW,CAAC,EAAE,OAAO,CAAC;QACtB,SAAS,CAAC,EAAE,OAAO,CAAC;QACpB,eAAe,CAAC,EAAE,OAAO,CAAC;QAC1B,MAAM,CAAC,EAAE,OAAO,CAAC;QACjB,+FAA+F;QAC/F,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,iFAAiF;QACjF,SAAS,CAAC,EAAE,OAAO,CAAC;QACpB,0FAA0F;QAC1F,oBAAoB,CAAC,EAAE,OAAO,CAAC;QAC/B,kEAAkE;QAClE,QAAQ,CAAC,EAAE,OAAO,CAAC;KACf;IA+DR,QAAQ,CAAC,iBAAiB,EAAE,iBAAiB,CAI3C;IAEF,MAAM,EAAE,WAAW,EAAE,EAAE,CAAM;IAC7B,OAAO,EAAE;QAAE,GAAG,EAAE,UAAU,CAAC;QAAC,EAAE,EAAE,WAAW,EAAE,CAAA;KAAE,EAAE,CAAM;IACvD,gBAAgB,EAAE,gBAAgB,EAAE,CAAM;IAC1C,eAAe,CAAC,EAAE,WAAW,CAAC;IAC9B,4DAA4D;IAC5D,QAAQ,EAAE,aAAa,EAAE,CAAM;IAC/B,wDAAwD;IACxD,IAAI,CAAC,EAAE,YAAY,CAAC;IACpB,iHAAiH;IACjH,UAAU,CAAC,EAAE,UAAU,CAAC;IACxB,OAAO,CAAC,IAAI,CAAC,CAAc;IAC3B,OAAO,CAAC,OAAO,CAAK;IAEpB,+FAA+F;IAC/F,OAAO,IAAI,WAAW;IAQhB,KAAK,CAAC,IAAI,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC;IAKvC,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAI3B,MAAM,CAAC,EAAE,EAAE,WAAW,EAAE,GAAG,aAAa;IAGlC,IAAI,CAAC,OAAO,EAAE,WAAW,EAAE,EAAE,EAAE,WAAW,EAAE,GAAG,OAAO,CAAC,UAAU,CAAC;IAIlE,MAAM,CAAC,GAAG,EAAE,UAAU,EAAE,EAAE,EAAE,WAAW,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAGzD,MAAM,CACV,OAAO,EAAE,WAAW,EACpB,MAAM,EAAE,aAAa,CAAC,MAAM,CAAC,GAC5B,OAAO,CAAC,UAAU,CAAC;IAMhB,MAAM,CAAC,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC;IAE7C,iBAAiB,CAAC,OAAO,EAAE,WAAW,GAAG,WAAW;IAKpD,iBAAiB,CAAC,GAAG,EAAE,OAAO,GAAG,gBAAgB,GAAG,SAAS;IAGvD,UAAU,CAAC,EAAE,EAAE,SAAS,GAAG,OAAO,CAAC,YAAY,GAAG,SAAS,CAAC;IAG5D,WAAW,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,aAAa,EAAE,CAAC;IAIjE,qFAAqF;IACrF,qBAAqB,EAAE;QACrB,MAAM,EAAE,WAAW,CAAC;QACpB,OAAO,EAAE,aAAa,CAAC;YAAE,KAAK,EAAE,MAAM,CAAC;YAAC,OAAO,EAAE,MAAM,CAAA;SAAE,CAAC,CAAC;QAC3D,IAAI,CAAC,EAAE;YAAE,KAAK,CAAC,EAAE,MAAM,CAAA;SAAE,CAAC;KAC3B,EAAE,CAAM;IACT,mBAAmB,CAAC,EAAE,eAAe,CAAC,qBAAqB,CAAC,CAAC;IAE7D,iFAAiF;IACjF,gBAAgB,EAAE;QAAE,MAAM,EAAE,WAAW,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,EAAE,CAAM;IAChE,cAAc,CAAC,EAAE,eAAe,CAAC,gBAAgB,CAAC,CAAC;IAGnD,cAAc,EAAE;QAAE,GAAG,EAAE,UAAU,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,EAAE,CAAM;IAC1D,gBAAgB,EAAE;QAAE,GAAG,EAAE,UAAU,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,EAAE,CAAM;IAC5D,WAAW,CAAC,EAAE,eAAe,CAAC,aAAa,CAAC,CAAC;IAC7C,cAAc,CAAC,EAAE,eAAe,CAAC,gBAAgB,CAAC,CAAC;IAGnD,cAAc,EAAE;QACd,IAAI,EAAE,OAAO,CAAC;QACd,EAAE,EAAE,WAAW,EAAE,CAAC;QAClB,IAAI,EAAE;YAAE,YAAY,EAAE,OAAO,CAAA;SAAE,CAAC;KACjC,EAAE,CAAM;IACT,aAAa,CAAC,EAAE,eAAe,CAAC,eAAe,CAAC,CAAC;IAGjD,YAAY,EAAE;QAAE,SAAS,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,WAAW,EAAE,CAAA;KAAE,EAAE,CAAM;IAC9D,WAAW,CAAC,EAAE,eAAe,CAAC,aAAa,CAAC,CAAC;IAC7C,SAAS,CAAC,EAAE,eAAe,CAAC,WAAW,CAAC,CAAC;IAGzC,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC,YAAY,CAAC,GAAG,IAAI;IAS9C,iBAAiB,CACf,OAAO,CAAC,EAAE,OAAO,CAAC,mBAAmB,CAAC,GACrC,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI;IAQvB,eAAe,CAAC,OAAO,EAAE,OAAO,CAAC,gBAAgB,CAAC,GAAG,IAAI;IAUzD,WAAW,CACT,OAAO,EAAE,OAAO,CAAC,eAAe,CAAC,GAAG;QAAE,OAAO,EAAE,MAAM,CAAA;KAAE,GACtD,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI;IASvB,YAAY,CACV,OAAO,EAAE,OAAO,CAAC,gBAAgB,CAAC,GAAG;QAAE,QAAQ,EAAE,MAAM,CAAA;KAAE,GACxD,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI;IAUvB,eAAe,CACb,OAAO,EAAE,OAAO,CAAC,mBAAmB,CAAC,GAAG;QAAE,UAAU,EAAE,MAAM,CAAA;KAAE,GAC7D,OAAO,CAAC,iBAAiB,GAAG,IAAI,CAAC,GAAG,SAAS;IAQhD,cAAc,CACZ,OAAO,EAAE,OAAO,CAAC,kBAAkB,CAAC,GAAG;QAAE,UAAU,EAAE,MAAM,CAAA;KAAE,GAC5D,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI;IAIvB,gGAAgG;IAChG,kBAAkB,CAAC,EAAE,SAAS,WAAW,EAAE,CAAC;IACtC,gBAAgB,CAAC,QAAQ,EAAE,SAAS,WAAW,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;CAKxE"}
1
+ {"version":3,"file":"fake-adapter.d.ts","sourceRoot":"","sources":["../../src/testing/fake-adapter.ts"],"names":[],"mappings":"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"}
@@ -71,6 +71,7 @@ export class FakeAdapter {
71
71
  supportsTyping: false,
72
72
  supportsReactions: fakeOpts.reactions !== false,
73
73
  supportsStreaming: true,
74
+ supportsMessageEvents: fakeOpts.messageEvents === true,
74
75
  supportsSuggestedPrompts: paneMethods,
75
76
  supportsThreadTitle: paneMethods,
76
77
  supportsEphemeral: fakeOpts.nativeEphemeral === true,
@@ -139,11 +140,32 @@ export class FakeAdapter {
139
140
  stateStore;
140
141
  sink;
141
142
  counter = 0;
143
+ turnCounter = 0;
142
144
  /** Expose the registered sink so tests can invoke onTurn() directly for overlap/lock tests. */
143
145
  getSink() {
144
146
  if (!this.sink)
145
147
  throw new Error("FakeAdapter: sink not set — start the channel (channel.ɵruntime.start()) first");
146
- return this.sink;
148
+ const sink = this.sink;
149
+ const adapter = this;
150
+ return new Proxy(sink, {
151
+ get(target, property, receiver) {
152
+ if (property !== "onTurn") {
153
+ return Reflect.get(target, property, receiver);
154
+ }
155
+ return (turn) => {
156
+ const syntheticId = turn.eventId ?? `fake-message-${++adapter.turnCounter}`;
157
+ return sink.onTurn({
158
+ ...turn,
159
+ operation: turn.operation ?? {
160
+ kind: "created",
161
+ logicalMessageId: syntheticId,
162
+ revisionId: syntheticId,
163
+ mentioned: true,
164
+ },
165
+ });
166
+ };
167
+ },
168
+ });
147
169
  }
148
170
  async start(sink) {
149
171
  if (this.failStart)
@@ -207,12 +229,19 @@ export class FakeAdapter {
207
229
  openModal;
208
230
  // --- test helpers ---
209
231
  emitTurn(partial) {
232
+ const syntheticId = partial.eventId ?? `fake-message-${++this.turnCounter}`;
210
233
  void this.sink?.onTurn({
211
234
  conversationKey: "c",
212
235
  replyTarget: {},
213
236
  userText: "",
214
237
  platform: "fake",
215
238
  ...partial,
239
+ operation: partial.operation ?? {
240
+ kind: "created",
241
+ logicalMessageId: syntheticId,
242
+ revisionId: syntheticId,
243
+ mentioned: true,
244
+ },
216
245
  });
217
246
  }
218
247
  emitThreadStarted(partial) {
@@ -24,5 +24,10 @@ export declare class FakeAgent extends AbstractAgent {
24
24
  run(_input: RunAgentInput): ReturnType<AbstractAgent["run"]>;
25
25
  runAgent(_parameters?: RunAgentParameters, subscriber?: AgentSubscriber): Promise<RunAgentResult>;
26
26
  abortRun(): void;
27
+ /**
28
+ * Distinct instance for concurrent channel turns (singleton agent isolation).
29
+ * Copies the remaining script so both prototype and clone can still drive steps.
30
+ */
31
+ clone(): FakeAgent;
27
32
  }
28
33
  //# sourceMappingURL=fake-agent.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"fake-agent.d.ts","sourceRoot":"","sources":["../../src/testing/fake-agent.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAC9C,OAAO,KAAK,EACV,eAAe,EACf,kBAAkB,EAClB,cAAc,EACf,MAAM,eAAe,CAAC;AACvB,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAEjD;;;;;GAKG;AACH,MAAM,MAAM,mBAAmB,GAAG,CAChC,UAAU,EAAE,eAAe,KACxB,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;AAE1B;;;;GAIG;AACH,qBAAa,SAAU,SAAQ,aAAa;IAC1C,OAAO,CAAC,MAAM,CAAwB;IACtC,kFAAkF;IAClF,aAAa,SAAK;IAClB,uCAAuC;IACvC,OAAO,UAAS;gBAEJ,MAAM,GAAE,mBAAmB,EAAO;IAK9C,SAAS,CAAC,MAAM,EAAE,mBAAmB,EAAE,GAAG,IAAI;IAM9C,GAAG,CAAC,MAAM,EAAE,aAAa,GAAG,UAAU,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;IAI7C,QAAQ,CACrB,WAAW,CAAC,EAAE,kBAAkB,EAChC,UAAU,CAAC,EAAE,eAAe,GAC3B,OAAO,CAAC,cAAc,CAAC;IASjB,QAAQ,IAAI,IAAI;CAG1B"}
1
+ {"version":3,"file":"fake-agent.d.ts","sourceRoot":"","sources":["../../src/testing/fake-agent.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAC9C,OAAO,KAAK,EACV,eAAe,EACf,kBAAkB,EAClB,cAAc,EACf,MAAM,eAAe,CAAC;AACvB,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAEjD;;;;;GAKG;AACH,MAAM,MAAM,mBAAmB,GAAG,CAChC,UAAU,EAAE,eAAe,KACxB,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;AAE1B;;;;GAIG;AACH,qBAAa,SAAU,SAAQ,aAAa;IAC1C,OAAO,CAAC,MAAM,CAAwB;IACtC,kFAAkF;IAClF,aAAa,SAAK;IAClB,uCAAuC;IACvC,OAAO,UAAS;gBAEJ,MAAM,GAAE,mBAAmB,EAAO;IAK9C,SAAS,CAAC,MAAM,EAAE,mBAAmB,EAAE,GAAG,IAAI;IAM9C,GAAG,CAAC,MAAM,EAAE,aAAa,GAAG,UAAU,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;IAI7C,QAAQ,CACrB,WAAW,CAAC,EAAE,kBAAkB,EAChC,UAAU,CAAC,EAAE,eAAe,GAC3B,OAAO,CAAC,cAAc,CAAC;IASjB,QAAQ,IAAI,IAAI;IAIzB;;;OAGG;IACM,KAAK,IAAI,SAAS;CAQ5B"}
@@ -33,4 +33,16 @@ export class FakeAgent extends AbstractAgent {
33
33
  abortRun() {
34
34
  this.aborted = true;
35
35
  }
36
+ /**
37
+ * Distinct instance for concurrent channel turns (singleton agent isolation).
38
+ * Copies the remaining script so both prototype and clone can still drive steps.
39
+ */
40
+ clone() {
41
+ const cloned = new FakeAgent(this.script);
42
+ cloned.threadId = this.threadId;
43
+ cloned.agentId = this.agentId;
44
+ cloned.messages = structuredClone(this.messages);
45
+ cloned.state = structuredClone(this.state);
46
+ return cloned;
47
+ }
36
48
  }
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=thread-promise-contract.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"thread-promise-contract.test.d.ts","sourceRoot":"","sources":["../src/thread-promise-contract.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,37 @@
1
+ import { expect, test } from "vitest";
2
+ import { ActionRegistry } from "./action-registry.js";
3
+ import { InMemoryActionStore } from "./action-store.js";
4
+ import { MemoryStore } from "./state/memory-store.js";
5
+ import { FakeAdapter } from "./testing/fake-adapter.js";
6
+ import { Thread } from "./thread.js";
7
+ function setupThreadWithSyncDeleteFailure(failure) {
8
+ const adapter = new FakeAdapter();
9
+ adapter.delete = () => {
10
+ throw failure;
11
+ };
12
+ const deps = {
13
+ adapter,
14
+ replyTarget: {},
15
+ conversationKey: "thread-promise-contract",
16
+ registry: new ActionRegistry({ store: new InMemoryActionStore() }),
17
+ agentFactory: (threadId) => {
18
+ throw new Error(`agentFactory not needed in this test: ${threadId}`);
19
+ },
20
+ tools: new Map(),
21
+ toolDescriptors: [],
22
+ context: [],
23
+ registerWaiter: () => undefined,
24
+ interruptHandlers: new Map(),
25
+ state: new MemoryStore(),
26
+ };
27
+ return new Thread(deps);
28
+ }
29
+ test("a synchronous non-managed adapter failure returns a rejected Promise", async () => {
30
+ const failure = new Error("adapter delete failed synchronously");
31
+ const thread = setupThreadWithSyncDeleteFailure(failure);
32
+ let deletion;
33
+ expect(() => {
34
+ deletion = thread.delete({ id: "message-1" });
35
+ }).not.toThrow();
36
+ await expect(deletion).rejects.toBe(failure);
37
+ });
package/dist/thread.d.ts CHANGED
@@ -8,6 +8,8 @@ import type { StateStore } from "./state/state-store.js";
8
8
  import type { StandardSchemaV1 } from "./standard-schema.js";
9
9
  export interface ThreadDeps {
10
10
  adapter: PlatformAdapter;
11
+ /** Source provider for this ingress event; falls back to the adapter identity. */
12
+ platform?: string;
11
13
  replyTarget: ReplyTarget;
12
14
  conversationKey: string;
13
15
  registry: ActionRegistry;
@@ -50,8 +52,10 @@ export declare class Thread implements ThreadInterface {
50
52
  /** Mirrors the adapter's `supportsBlockingChoice` capability (see SurfaceCapabilities). */
51
53
  readonly supportsBlockingChoice?: boolean;
52
54
  private readonly store;
55
+ private implicitInboundConsumed;
53
56
  constructor(deps: ThreadDeps);
54
57
  private bindForPost;
58
+ private trackOperation;
55
59
  /**
56
60
  * Wire a posted message's `onReaction` to its returned id: cache it for this
57
61
  * process and, when it came from a component, persist a durable snapshot so a
@@ -70,6 +74,7 @@ export declare class Thread implements ThreadInterface {
70
74
  }): Promise<{
71
75
  ok: boolean;
72
76
  fileId?: string;
77
+ assetId?: string;
73
78
  error?: string;
74
79
  }>;
75
80
  /** Pin suggested prompts (returns `{ ok: false }` on surfaces without support). */
@@ -1 +1 @@
1
- {"version":3,"file":"thread.d.ts","sourceRoot":"","sources":["../src/thread.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"thread.d.ts","sourceRoot":"","sources":["../src/thread.ts"],"names":[],"mappings":"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"}