@copilotkit/channels-core 0.5.0 → 0.5.1-canary.1785633429

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 (82) hide show
  1. package/README.md +35 -14
  2. package/dist/action-registry.d.ts +15 -3
  3. package/dist/action-registry.d.ts.map +1 -1
  4. package/dist/action-registry.js +61 -9
  5. package/dist/action-registry.test.js +107 -2
  6. package/dist/action-store.d.ts +23 -0
  7. package/dist/action-store.d.ts.map +1 -1
  8. package/dist/action-store.js +11 -0
  9. package/dist/canonical-run-loop.test.js +6 -1
  10. package/dist/channel-identity.test.d.ts +2 -0
  11. package/dist/channel-identity.test.d.ts.map +1 -0
  12. package/dist/channel-identity.test.js +297 -0
  13. package/dist/channel-memory.test.d.ts +2 -0
  14. package/dist/channel-memory.test.d.ts.map +1 -0
  15. package/dist/channel-memory.test.js +199 -0
  16. package/dist/commands.d.ts +5 -3
  17. package/dist/commands.d.ts.map +1 -1
  18. package/dist/create-channel.d.ts +30 -56
  19. package/dist/create-channel.d.ts.map +1 -1
  20. package/dist/create-channel.foundations.test.js +30 -7
  21. package/dist/create-channel.js +209 -72
  22. package/dist/create-channel.test.js +293 -66
  23. package/dist/hitl-continuation.test.d.ts +2 -0
  24. package/dist/hitl-continuation.test.d.ts.map +1 -0
  25. package/dist/hitl-continuation.test.js +393 -0
  26. package/dist/identity.d.ts +51 -0
  27. package/dist/identity.d.ts.map +1 -0
  28. package/dist/identity.js +56 -0
  29. package/dist/identity.test.d.ts +2 -0
  30. package/dist/identity.test.d.ts.map +1 -0
  31. package/dist/identity.test.js +109 -0
  32. package/dist/index.d.ts +10 -5
  33. package/dist/index.d.ts.map +1 -1
  34. package/dist/index.js +5 -1
  35. package/dist/managed-v1-await-choice-guard.test.js +4 -1
  36. package/dist/memory.d.ts +23 -0
  37. package/dist/memory.d.ts.map +1 -0
  38. package/dist/memory.js +25 -0
  39. package/dist/modal-submit.test.js +21 -6
  40. package/dist/open-modal.test.js +16 -4
  41. package/dist/platform-adapter.d.ts +29 -6
  42. package/dist/platform-adapter.d.ts.map +1 -1
  43. package/dist/platform-adapter.test.js +2 -0
  44. package/dist/reactions.test.js +49 -11
  45. package/dist/run-loop.test.js +30 -5
  46. package/dist/sanitize-agent-events.test.js +2 -0
  47. package/dist/source-platform.test.js +24 -9
  48. package/dist/state/kv-action-store.d.ts.map +1 -1
  49. package/dist/state/kv-action-store.js +1 -0
  50. package/dist/state/kv-action-store.test.js +11 -0
  51. package/dist/state/memory-store.d.ts +1 -0
  52. package/dist/state/memory-store.d.ts.map +1 -1
  53. package/dist/state/memory-store.js +9 -0
  54. package/dist/state/state-store.d.ts +2 -0
  55. package/dist/state/state-store.d.ts.map +1 -1
  56. package/dist/telemetry/create-channel-telemetry.test.js +4 -2
  57. package/dist/telemetry/e2e-telemetry.test.js +1 -0
  58. package/dist/telemetry/install-id.test.js +5 -0
  59. package/dist/testing/fake-adapter.d.ts +26 -9
  60. package/dist/testing/fake-adapter.d.ts.map +1 -1
  61. package/dist/testing/fake-adapter.js +65 -21
  62. package/dist/testing/state-store-conformance.d.ts.map +1 -1
  63. package/dist/testing/state-store-conformance.js +16 -0
  64. package/dist/thread-capabilities.test.js +29 -9
  65. package/dist/thread-ephemeral.test.js +8 -5
  66. package/dist/thread-promise-contract.test.js +4 -0
  67. package/dist/thread-reactions.test.js +8 -2
  68. package/dist/thread.d.ts +50 -7
  69. package/dist/thread.d.ts.map +1 -1
  70. package/dist/thread.js +163 -17
  71. package/dist/thread.test.js +4 -0
  72. package/dist/tools.d.ts +5 -3
  73. package/dist/tools.d.ts.map +1 -1
  74. package/dist/tools.js +2 -1
  75. package/dist/transcripts.d.ts +6 -13
  76. package/dist/transcripts.d.ts.map +1 -1
  77. package/dist/transcripts.js +12 -12
  78. package/dist/transcripts.test.js +28 -29
  79. package/dist/welcome.test.d.ts +2 -0
  80. package/dist/welcome.test.d.ts.map +1 -0
  81. package/dist/welcome.test.js +53 -0
  82. package/package.json +5 -5
@@ -21,6 +21,7 @@ test("an ingress source platform reaches the text thread and its tool context",
21
21
  },
22
22
  ]);
23
23
  const channel = createChannel({
24
+ identifyUser: "platform",
24
25
  adapters: [adapter],
25
26
  agent: () => agent,
26
27
  tools: [
@@ -31,6 +32,8 @@ test("an ingress source platform reaches the text thread and its tool context",
31
32
  handler: (_args, ctx) => {
32
33
  observed.toolPlatform = ctx.platform;
33
34
  observed.toolThreadPlatform = ctx.thread.platform;
35
+ observed.toolUser = ctx.user?.id;
36
+ observed.toolActor = ctx.actor.id;
34
37
  return "captured";
35
38
  },
36
39
  },
@@ -47,30 +50,41 @@ test("an ingress source platform reaches the text thread and its tool context",
47
50
  replyTarget: {},
48
51
  userText: "hello",
49
52
  platform: "slack",
53
+ actor: { id: "U1", kind: "human", name: "Ada" },
54
+ identityContext: {
55
+ tenant: { id: "T1" },
56
+ installation: { id: "I1" },
57
+ conversation: { id: "conversation-1", kind: "channel" },
58
+ trigger: "message",
59
+ event: { id: "E1" },
60
+ raw: {},
61
+ },
50
62
  });
51
63
  expect(observed).toEqual({
52
64
  messagePlatform: "slack",
53
65
  threadPlatform: "slack",
54
66
  toolPlatform: "slack",
55
67
  toolThreadPlatform: "slack",
68
+ toolUser: "slack:T1:U1",
69
+ toolActor: "U1",
56
70
  });
57
71
  });
58
72
  test("an ingress source platform scopes identity resolution and event dedupe", async () => {
59
73
  const state = new MemoryStore();
60
74
  const dedupeSeen = vi.spyOn(state.dedup, "seen").mockResolvedValue(false);
61
- const identity = vi.fn(() => "person-1");
75
+ const identifyUser = vi.fn(() => ({ id: "person-1", name: "Person One" }));
62
76
  const adapter = new FakeAdapter({ platform: "intelligence" });
63
77
  const channel = createChannel({
64
78
  adapters: [adapter],
79
+ identifyUser,
65
80
  store: {
66
81
  adapter: state,
67
- identity,
68
82
  transcripts: {},
69
83
  },
70
84
  });
71
- let userKey;
85
+ let userId;
72
86
  channel.onMessage(({ message }) => {
73
- userKey = message.userKey;
87
+ userId = message.user?.id;
74
88
  });
75
89
  await channel.ɵruntime.start();
76
90
  await adapter.getSink().onTurn({
@@ -79,14 +93,14 @@ test("an ingress source platform scopes identity resolution and event dedupe", a
79
93
  userText: "hello",
80
94
  platform: "teams",
81
95
  eventId: "event-1",
82
- user: { id: "user-1" },
96
+ actor: { id: "user-1", kind: "human" },
83
97
  });
84
98
  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" }),
99
+ expect(identifyUser).toHaveBeenCalledWith(expect.objectContaining({
100
+ provider: "teams",
101
+ actor: expect.objectContaining({ id: "user-1" }),
88
102
  }));
89
- expect(userKey).toBe("person-1");
103
+ expect(userId).toBe("person-1");
90
104
  });
91
105
  test("non-text ingress keeps source platform in handler contexts and dedupe keys", async () => {
92
106
  const state = new MemoryStore();
@@ -94,6 +108,7 @@ test("non-text ingress keeps source platform in handler contexts and dedupe keys
94
108
  const adapter = new FakeAdapter({ platform: "intelligence" });
95
109
  const observed = {};
96
110
  const channel = createChannel({
111
+ identifyUser: "platform",
97
112
  adapters: [adapter],
98
113
  store: { adapter: state },
99
114
  });
@@ -1 +1 @@
1
- {"version":3,"file":"kv-action-store.d.ts","sourceRoot":"","sources":["../../src/state/kv-action-store.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAkB,MAAM,oBAAoB,CAAC;AACtE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAInD,uFAAuF;AACvF,wBAAgB,aAAa,CAC3B,KAAK,EAAE,UAAU,EACjB,IAAI,CAAC,EAAE;IAAE,YAAY,CAAC,EAAE,MAAM,CAAA;CAAE,GAC/B,WAAW,CAOb"}
1
+ {"version":3,"file":"kv-action-store.d.ts","sourceRoot":"","sources":["../../src/state/kv-action-store.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAkB,MAAM,oBAAoB,CAAC;AACtE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAInD,uFAAuF;AACvF,wBAAgB,aAAa,CAC3B,KAAK,EAAE,UAAU,EACjB,IAAI,CAAC,EAAE;IAAE,YAAY,CAAC,EAAE,MAAM,CAAA;CAAE,GAC/B,WAAW,CAQb"}
@@ -4,6 +4,7 @@ export function kvActionStore(state, opts) {
4
4
  return {
5
5
  put: (id, snap, ttlMs) => state.kv.set(key(id), snap, ttlMs ?? opts?.defaultTtlMs),
6
6
  get: (id) => state.kv.get(key(id)),
7
+ consume: (id) => state.kv.consume(key(id)),
7
8
  delete: (id) => state.kv.delete(key(id)),
8
9
  };
9
10
  }
@@ -18,4 +18,15 @@ describe("kvActionStore", () => {
18
18
  await store.delete("ck:abc");
19
19
  expect(await store.get("ck:abc")).toBeUndefined();
20
20
  });
21
+ it("consumes a snapshot once via state.kv", async () => {
22
+ const state = new MemoryStore();
23
+ const store = kvActionStore(state);
24
+ const snap = {
25
+ path: [0, "onClick"],
26
+ conversationKey: "c",
27
+ };
28
+ await store.put("ck:once", snap);
29
+ expect(await store.consume("ck:once")).toEqual(snap);
30
+ expect(await store.consume("ck:once")).toBeUndefined();
31
+ });
21
32
  });
@@ -8,6 +8,7 @@ export declare class MemoryStore implements StateStore {
8
8
  get: <T>(key: string) => Promise<T | undefined>;
9
9
  set: <T>(key: string, value: T, ttlMs?: number) => Promise<void>;
10
10
  delete: (key: string) => Promise<void>;
11
+ consume: <T>(key: string) => Promise<T | undefined>;
11
12
  };
12
13
  list: {
13
14
  append: <T>(key: string, value: T, opts?: {
@@ -1 +1 @@
1
- {"version":3,"file":"memory-store.d.ts","sourceRoot":"","sources":["../../src/state/memory-store.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAQnD,qBAAa,WAAY,YAAW,UAAU;IAC5C,OAAO,CAAC,KAAK,CAAwC;IACrD,OAAO,CAAC,KAAK,CAA0C;IACvD,OAAO,CAAC,KAAK,CAA4D;IACzE,OAAO,CAAC,MAAM,CAAgC;IAE9C,EAAE;cACY,CAAC,OAAO,MAAM,KAAG,OAAO,CAAC,CAAC,GAAG,SAAS,CAAC;cAQvC,CAAC,OAAO,MAAM,SAAS,CAAC,UAAU,MAAM,KAAG,OAAO,CAAC,IAAI,CAAC;sBAMhD,MAAM,KAAG,OAAO,CAAC,IAAI,CAAC;MAG1C;IAEF,IAAI;iBACa,CAAC,OACT,MAAM,SACJ,CAAC,SACD;YAAE,MAAM,CAAC,EAAE,MAAM,CAAC;YAAC,KAAK,CAAC,EAAE,MAAM,CAAA;SAAE,KACzC,OAAO,CAAC,MAAM,CAAC;gBAYJ,CAAC,OAAO,MAAM,yBAAoB,MAAM,KAAG,OAAO,CAAC,CAAC,EAAE,CAAC;oBASnD,MAAM,UAAU,MAAM,KAAG,OAAO,CAAC,IAAI,CAAC;sBAMpC,MAAM,KAAG,OAAO,CAAC,IAAI,CAAC;MAG1C;IAEF,IAAI;uBAEK,MAAM,SACJ;YAAE,KAAK,CAAC,EAAE,MAAM,CAAA;SAAE,KACxB,OAAO,CAAC;YAAE,KAAK,EAAE,MAAM,CAAA;SAAE,GAAG,IAAI,CAAC;uBAWf,MAAM,SAAS,MAAM,KAAG,OAAO,CAAC,IAAI,CAAC;MAI1D;IAEF,KAAK;oBACe,MAAM,SAAS,MAAM,KAAG,OAAO,CAAC,OAAO,CAAC;MAO1D;IAEF,KAAK;kBACa,CAAC,OACV,MAAM,SACJ,CAAC,SACD;YAAE,OAAO,CAAC,EAAE,MAAM,CAAC;YAAC,MAAM,CAAC,EAAE,aAAa,GAAG,aAAa,CAAA;SAAE,KAClE,OAAO,CAAC,MAAM,CAAC;kBAaF,CAAC,OAAO,MAAM,KAAG,OAAO,CAAC,CAAC,GAAG,SAAS,CAAC;qBAIpC,MAAM,KAAG,OAAO,CAAC,MAAM,CAAC;MAE3C;CACH"}
1
+ {"version":3,"file":"memory-store.d.ts","sourceRoot":"","sources":["../../src/state/memory-store.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAQnD,qBAAa,WAAY,YAAW,UAAU;IAC5C,OAAO,CAAC,KAAK,CAAwC;IACrD,OAAO,CAAC,KAAK,CAA0C;IACvD,OAAO,CAAC,KAAK,CAA4D;IACzE,OAAO,CAAC,MAAM,CAAgC;IAE9C,EAAE;cACY,CAAC,OAAO,MAAM,KAAG,OAAO,CAAC,CAAC,GAAG,SAAS,CAAC;cAQvC,CAAC,OAAO,MAAM,SAAS,CAAC,UAAU,MAAM,KAAG,OAAO,CAAC,IAAI,CAAC;sBAMhD,MAAM,KAAG,OAAO,CAAC,IAAI,CAAC;kBAG1B,CAAC,OAAO,MAAM,KAAG,OAAO,CAAC,CAAC,GAAG,SAAS,CAAC;MASvD;IAEF,IAAI;iBACa,CAAC,OACT,MAAM,SACJ,CAAC,SACD;YAAE,MAAM,CAAC,EAAE,MAAM,CAAC;YAAC,KAAK,CAAC,EAAE,MAAM,CAAA;SAAE,KACzC,OAAO,CAAC,MAAM,CAAC;gBAYJ,CAAC,OAAO,MAAM,yBAAoB,MAAM,KAAG,OAAO,CAAC,CAAC,EAAE,CAAC;oBASnD,MAAM,UAAU,MAAM,KAAG,OAAO,CAAC,IAAI,CAAC;sBAMpC,MAAM,KAAG,OAAO,CAAC,IAAI,CAAC;MAG1C;IAEF,IAAI;uBAEK,MAAM,SACJ;YAAE,KAAK,CAAC,EAAE,MAAM,CAAA;SAAE,KACxB,OAAO,CAAC;YAAE,KAAK,EAAE,MAAM,CAAA;SAAE,GAAG,IAAI,CAAC;uBAWf,MAAM,SAAS,MAAM,KAAG,OAAO,CAAC,IAAI,CAAC;MAI1D;IAEF,KAAK;oBACe,MAAM,SAAS,MAAM,KAAG,OAAO,CAAC,OAAO,CAAC;MAO1D;IAEF,KAAK;kBACa,CAAC,OACV,MAAM,SACJ,CAAC,SACD;YAAE,OAAO,CAAC,EAAE,MAAM,CAAC;YAAC,MAAM,CAAC,EAAE,aAAa,GAAG,aAAa,CAAA;SAAE,KAClE,OAAO,CAAC,MAAM,CAAC;kBAaF,CAAC,OAAO,MAAM,KAAG,OAAO,CAAC,CAAC,GAAG,SAAS,CAAC;qBAIpC,MAAM,KAAG,OAAO,CAAC,MAAM,CAAC;MAE3C;CACH"}
@@ -24,6 +24,15 @@ export class MemoryStore {
24
24
  delete: async (key) => {
25
25
  this.kvMap.delete(key);
26
26
  },
27
+ consume: async (key) => {
28
+ const e = this.kvMap.get(key);
29
+ if (!live(e)) {
30
+ this.kvMap.delete(key);
31
+ return undefined;
32
+ }
33
+ this.kvMap.delete(key);
34
+ return e.value;
35
+ },
27
36
  };
28
37
  list = {
29
38
  append: async (key, value, opts) => {
@@ -12,6 +12,8 @@ export interface StateStore {
12
12
  get<T>(key: string): Promise<T | undefined>;
13
13
  set<T>(key: string, value: T, ttlMs?: number): Promise<void>;
14
14
  delete(key: string): Promise<void>;
15
+ /** Atomically return and delete one live value. */
16
+ consume<T>(key: string): Promise<T | undefined>;
15
17
  };
16
18
  list: {
17
19
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"state-store.d.ts","sourceRoot":"","sources":["../../src/state/state-store.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,MAAM,WAAW,UAAU;IACzB,EAAE,EAAE;QACF,GAAG,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,GAAG,SAAS,CAAC,CAAC;QAC5C,GAAG,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;QAC7D,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;KACpC,CAAC;IACF,IAAI,EAAE;QACJ;;;;WAIG;QACH,MAAM,CAAC,CAAC,EACN,GAAG,EAAE,MAAM,EACX,KAAK,EAAE,CAAC,EACR,IAAI,CAAC,EAAE;YAAE,MAAM,CAAC,EAAE,MAAM,CAAC;YAAC,KAAK,CAAC,EAAE,MAAM,CAAA;SAAE,GACzC,OAAO,CAAC,MAAM,CAAC,CAAC;QACnB;;;;WAIG;QACH,KAAK,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,EAAE,CAAC,CAAC;QACnE,IAAI,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;QACjD,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;KACpC,CAAC;IACF,IAAI,EAAE;QACJ;;;;;WAKG;QACH,OAAO,CACL,GAAG,EAAE,MAAM,EACX,IAAI,CAAC,EAAE;YAAE,KAAK,CAAC,EAAE,MAAM,CAAA;SAAE,GACxB,OAAO,CAAC;YAAE,KAAK,EAAE,MAAM,CAAA;SAAE,GAAG,IAAI,CAAC,CAAC;QACrC,kDAAkD;QAClD,OAAO,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;KACpD,CAAC;IACF,KAAK,EAAE;QACL,+EAA+E;QAC/E,IAAI,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;KACpD,CAAC;IACF,KAAK,EAAE;QACL,OAAO,CAAC,CAAC,EACP,GAAG,EAAE,MAAM,EACX,KAAK,EAAE,CAAC,EACR,IAAI,CAAC,EAAE;YAAE,OAAO,CAAC,EAAE,MAAM,CAAC;YAAC,MAAM,CAAC,EAAE,aAAa,GAAG,aAAa,CAAA;SAAE,GAClE,OAAO,CAAC,MAAM,CAAC,CAAC;QACnB,OAAO,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,GAAG,SAAS,CAAC,CAAC;QAChD,KAAK,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;KACrC,CAAC;CACH"}
1
+ {"version":3,"file":"state-store.d.ts","sourceRoot":"","sources":["../../src/state/state-store.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,MAAM,WAAW,UAAU;IACzB,EAAE,EAAE;QACF,GAAG,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,GAAG,SAAS,CAAC,CAAC;QAC5C,GAAG,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;QAC7D,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;QACnC,mDAAmD;QACnD,OAAO,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,GAAG,SAAS,CAAC,CAAC;KACjD,CAAC;IACF,IAAI,EAAE;QACJ;;;;WAIG;QACH,MAAM,CAAC,CAAC,EACN,GAAG,EAAE,MAAM,EACX,KAAK,EAAE,CAAC,EACR,IAAI,CAAC,EAAE;YAAE,MAAM,CAAC,EAAE,MAAM,CAAC;YAAC,KAAK,CAAC,EAAE,MAAM,CAAA;SAAE,GACzC,OAAO,CAAC,MAAM,CAAC,CAAC;QACnB;;;;WAIG;QACH,KAAK,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,EAAE,CAAC,CAAC;QACnE,IAAI,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;QACjD,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;KACpC,CAAC;IACF,IAAI,EAAE;QACJ;;;;;WAKG;QACH,OAAO,CACL,GAAG,EAAE,MAAM,EACX,IAAI,CAAC,EAAE;YAAE,KAAK,CAAC,EAAE,MAAM,CAAA;SAAE,GACxB,OAAO,CAAC;YAAE,KAAK,EAAE,MAAM,CAAA;SAAE,GAAG,IAAI,CAAC,CAAC;QACrC,kDAAkD;QAClD,OAAO,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;KACpD,CAAC;IACF,KAAK,EAAE;QACL,+EAA+E;QAC/E,IAAI,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;KACpD,CAAC;IACF,KAAK,EAAE;QACL,OAAO,CAAC,CAAC,EACP,GAAG,EAAE,MAAM,EACX,KAAK,EAAE,CAAC,EACR,IAAI,CAAC,EAAE;YAAE,OAAO,CAAC,EAAE,MAAM,CAAC;YAAC,MAAM,CAAC,EAAE,aAAa,GAAG,aAAa,CAAA;SAAE,GAClE,OAAO,CAAC,MAAM,CAAC,CAAC;QACnB,OAAO,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,GAAG,SAAS,CAAC,CAAC;QAChD,KAAK,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;KACrC,CAAC;CACH"}
@@ -21,6 +21,7 @@ describe("createChannel telemetry wiring", () => {
21
21
  // telemetry) is resolved there, not at construction, so an adapter attached
22
22
  // via addAdapter can still provide the persistence backend.
23
23
  const channel = createChannel({
24
+ identifyUser: "platform",
24
25
  adapters: [new FakeAdapter()],
25
26
  components: [
26
27
  function Card() {
@@ -37,14 +38,14 @@ describe("createChannel telemetry wiring", () => {
37
38
  });
38
39
  it("emits oss.channel.started on start, start_failed (category only) on a throwing adapter", async () => {
39
40
  const ok = new FakeAdapter();
40
- const channel = createChannel({ adapters: [ok] });
41
+ const channel = createChannel({ identifyUser: "platform", adapters: [ok] });
41
42
  await channel.ɵruntime.start();
42
43
  expect(capture.mock.calls.find((c) => c[0] === "oss.channel.started")?.[1]
43
44
  .startedCount).toBe(1);
44
45
  capture.mockClear();
45
46
  const bad = new FakeAdapter();
46
47
  bad.start = () => Promise.reject(Object.assign(new Error("xoxb-SECRET token bad"), { code: "EAUTH" }));
47
- const bot2 = createChannel({ adapters: [bad] });
48
+ const bot2 = createChannel({ identifyUser: "platform", adapters: [bad] });
48
49
  // All adapters failed → start() rejects (the channel is dead; the runtime
49
50
  // reports status "error"). The start_failed telemetry is still captured
50
51
  // before the throw.
@@ -57,6 +58,7 @@ describe("createChannel telemetry wiring", () => {
57
58
  it("emits oss.channel.agent_run on a successful run", async () => {
58
59
  const fake = new FakeAdapter();
59
60
  const channel = createChannel({
61
+ identifyUser: "platform",
60
62
  adapters: [fake],
61
63
  agent: () => new FakeAgent(),
62
64
  });
@@ -34,6 +34,7 @@ describe("oss.channel.* end-to-end (real ChannelTelemetry, only network boundary
34
34
  it("flows configured -> started -> agent_run with anonymous_id + channel_session_id and no env config", async () => {
35
35
  const fake = new FakeAdapter();
36
36
  const channel = createChannel({
37
+ identifyUser: "platform",
37
38
  adapters: [fake],
38
39
  agent: () => new FakeAgent(),
39
40
  });
@@ -10,6 +10,11 @@ class FakeDurableStore {
10
10
  get: async (k) => this.map.get(k),
11
11
  set: async (k, v) => void this.map.set(k, v),
12
12
  delete: async (k) => void this.map.delete(k),
13
+ consume: async (k) => {
14
+ const value = this.map.get(k);
15
+ this.map.delete(k);
16
+ return value;
17
+ },
13
18
  };
14
19
  list = {};
15
20
  lock = {};
@@ -1,13 +1,31 @@
1
- import type { ChannelNode, MessageRef, PlatformUser, ThreadMessage } from "@copilotkit/channels-ui";
2
- import type { PlatformAdapter, SurfaceCapabilities, IngressSink, IncomingTurn, IncomingThreadStart, InteractionEvent, IncomingCommand, RunRenderer, ReplyTarget, NativePayload, UserQuery, ConversationStore, IncomingReaction, IncomingModalSubmit, IncomingModalClose, ModalSubmitResult } from "../platform-adapter.js";
1
+ import type { ChannelNode, MessageRef, ProviderActor, ThreadMessage } from "@copilotkit/channels-ui";
2
+ import type { PlatformAdapter, SurfaceCapabilities, IngressSink, IncomingTurn, IncomingThreadStart, IncomingWelcome, InteractionEvent, IncomingCommand, RunRenderer, ReplyTarget, NativePayload, UserQuery, ConversationStore, IncomingReaction, IncomingModalSubmit, IncomingModalClose, ModalSubmitResult } from "../platform-adapter.js";
3
3
  import type { CommandSpec } from "../commands.js";
4
4
  import type { StateStore } from "../state/state-store.js";
5
+ type OptionalIdentity<T extends {
6
+ actor: unknown;
7
+ identityContext: unknown;
8
+ }> = Omit<T, "actor" | "identityContext"> & Partial<Pick<T, "actor" | "identityContext">>;
9
+ type FakeIngressSink = {
10
+ onTurn(turn: OptionalIdentity<Omit<IncomingTurn, "operation">> & {
11
+ operation?: IncomingTurn["operation"];
12
+ }): void | Promise<void>;
13
+ onInteraction(event: OptionalIdentity<InteractionEvent>): void | Promise<void>;
14
+ onCommand(event: OptionalIdentity<IncomingCommand>): void | Promise<void>;
15
+ onThreadStarted(event: OptionalIdentity<IncomingThreadStart>): void | Promise<void>;
16
+ onWelcome(event: OptionalIdentity<IncomingWelcome>): void | Promise<void>;
17
+ onReaction(event: OptionalIdentity<IncomingReaction>): void | Promise<void>;
18
+ onModalSubmit(event: OptionalIdentity<IncomingModalSubmit>): Promise<ModalSubmitResult | void>;
19
+ onModalClose(event: OptionalIdentity<IncomingModalClose>): void | Promise<void>;
20
+ };
5
21
  /** A RunRenderer whose subscriber captures tool-call-end and custom (interrupt) events — used by run-loop tests. */
6
22
  export declare function makeFakeRunRenderer(): RunRenderer;
7
23
  export declare class FakeAdapter implements PlatformAdapter {
8
24
  platform: string;
9
25
  readonly capabilities: SurfaceCapabilities;
10
26
  readonly ackDeadlineMs = 3000;
27
+ supportsIntelligenceMemory?: boolean;
28
+ runAgentLifecycle?: PlatformAdapter["runAgentLifecycle"];
11
29
  /** When true, `start()` rejects (set via constructor `failStart`). */
12
30
  readonly failStart: boolean;
13
31
  /** When true, `registerCommands()` rejects (set via constructor `failRegisterCommands`). */
@@ -57,18 +75,15 @@ export declare class FakeAdapter implements PlatformAdapter {
57
75
  /** History returned by getMessages(); override in tests. */
58
76
  messages: ThreadMessage[];
59
77
  /** User returned by lookupUser(); override in tests. */
60
- user?: PlatformUser;
78
+ user?: ProviderActor;
61
79
  /** Optional persistence backend the adapter provides (test-only); exercises createChannel's store resolution. */
62
80
  stateStore?: StateStore;
63
81
  private sink?;
64
82
  private counter;
65
83
  private turnCounter;
66
84
  /** Expose the registered sink so tests can invoke onTurn() directly for overlap/lock tests. */
67
- getSink(): Omit<IngressSink, "onTurn"> & {
68
- onTurn(turn: Omit<IncomingTurn, "operation"> & {
69
- operation?: IncomingTurn["operation"];
70
- }): void | Promise<void>;
71
- };
85
+ getSink(): FakeIngressSink;
86
+ private withIdentity;
72
87
  start(sink: IngressSink): Promise<void>;
73
88
  stop(): Promise<void>;
74
89
  render(ir: ChannelNode[]): NativePayload;
@@ -78,7 +93,7 @@ export declare class FakeAdapter implements PlatformAdapter {
78
93
  delete(_ref: MessageRef): Promise<void>;
79
94
  createRunRenderer(_target: ReplyTarget): RunRenderer;
80
95
  decodeInteraction(raw: unknown): InteractionEvent | undefined;
81
- lookupUser(_q: UserQuery): Promise<PlatformUser | undefined>;
96
+ lookupUser(_q: UserQuery): Promise<ProviderActor | undefined>;
82
97
  getMessages(_target: ReplyTarget): Promise<ThreadMessage[]>;
83
98
  /** Suggested-prompt calls recorded by the capability-gated method (when present). */
84
99
  suggestedPromptsCalls: {
@@ -124,6 +139,7 @@ export declare class FakeAdapter implements PlatformAdapter {
124
139
  openModal?: PlatformAdapter["openModal"];
125
140
  emitTurn(partial: Partial<IncomingTurn>): void;
126
141
  emitThreadStarted(partial?: Partial<IncomingThreadStart>): Promise<void> | void;
142
+ emitWelcome(partial?: Partial<IncomingWelcome>): Promise<void> | void;
127
143
  emitInteraction(partial: Partial<InteractionEvent>): void;
128
144
  emitCommand(partial: Partial<IncomingCommand> & {
129
145
  command: string;
@@ -141,4 +157,5 @@ export declare class FakeAdapter implements PlatformAdapter {
141
157
  registeredCommands?: readonly CommandSpec[];
142
158
  registerCommands(commands: readonly CommandSpec[]): Promise<void>;
143
159
  }
160
+ export {};
144
161
  //# sourceMappingURL=fake-adapter.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"fake-adapter.d.ts","sourceRoot":"","sources":["../../src/testing/fake-adapter.ts"],"names":[],"mappings":"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"}
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,aAAa,EACb,aAAa,EACd,MAAM,yBAAyB,CAAC;AACjC,OAAO,KAAK,EACV,eAAe,EACf,mBAAmB,EACnB,WAAW,EACX,YAAY,EACZ,mBAAmB,EACnB,eAAe,EACf,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,KAAK,gBAAgB,CAAC,CAAC,SAAS;IAAE,KAAK,EAAE,OAAO,CAAC;IAAC,eAAe,EAAE,OAAO,CAAA;CAAE,IAC1E,IAAI,CAAC,CAAC,EAAE,OAAO,GAAG,iBAAiB,CAAC,GAClC,OAAO,CAAC,IAAI,CAAC,CAAC,EAAE,OAAO,GAAG,iBAAiB,CAAC,CAAC,CAAC;AAElD,KAAK,eAAe,GAAG;IACrB,MAAM,CACJ,IAAI,EAAE,gBAAgB,CAAC,IAAI,CAAC,YAAY,EAAE,WAAW,CAAC,CAAC,GAAG;QACxD,SAAS,CAAC,EAAE,YAAY,CAAC,WAAW,CAAC,CAAC;KACvC,GACA,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACxB,aAAa,CACX,KAAK,EAAE,gBAAgB,CAAC,gBAAgB,CAAC,GACxC,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACxB,SAAS,CAAC,KAAK,EAAE,gBAAgB,CAAC,eAAe,CAAC,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC1E,eAAe,CACb,KAAK,EAAE,gBAAgB,CAAC,mBAAmB,CAAC,GAC3C,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACxB,SAAS,CAAC,KAAK,EAAE,gBAAgB,CAAC,eAAe,CAAC,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC1E,UAAU,CAAC,KAAK,EAAE,gBAAgB,CAAC,gBAAgB,CAAC,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC5E,aAAa,CACX,KAAK,EAAE,gBAAgB,CAAC,mBAAmB,CAAC,GAC3C,OAAO,CAAC,iBAAiB,GAAG,IAAI,CAAC,CAAC;IACrC,YAAY,CACV,KAAK,EAAE,gBAAgB,CAAC,kBAAkB,CAAC,GAC1C,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACzB,CAAC;AAEF,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;IAC9B,0BAA0B,CAAC,EAAE,OAAO,CAAC;IACrC,iBAAiB,CAAC,EAAE,eAAe,CAAC,mBAAmB,CAAC,CAAC;IAEzD,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,wEAAwE;QACxE,aAAa,CAAC,EAAE,OAAO,CAAC;QACxB,+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;IAgER,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,aAAa,CAAC;IACrB,iHAAiH;IACjH,UAAU,CAAC,EAAE,UAAU,CAAC;IACxB,OAAO,CAAC,IAAI,CAAC,CAAc;IAC3B,OAAO,CAAC,OAAO,CAAK;IACpB,OAAO,CAAC,WAAW,CAAK;IAExB,+FAA+F;IAC/F,OAAO,IAAI,eAAe;IAoD1B,OAAO,CAAC,YAAY;IAyBd,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,aAAa,GAAG,SAAS,CAAC;IAG7D,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;IAgB9C,iBAAiB,CACf,OAAO,CAAC,EAAE,OAAO,CAAC,mBAAmB,CAAC,GACrC,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI;IAQvB,WAAW,CAAC,OAAO,CAAC,EAAE,OAAO,CAAC,eAAe,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI;IAarE,eAAe,CAAC,OAAO,EAAE,OAAO,CAAC,gBAAgB,CAAC,GAAG,IAAI;IAYzD,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;IAQvB,gGAAgG;IAChG,kBAAkB,CAAC,EAAE,SAAS,WAAW,EAAE,CAAC;IACtC,gBAAgB,CAAC,QAAQ,EAAE,SAAS,WAAW,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;CAKxE"}
@@ -37,6 +37,8 @@ export class FakeAdapter {
37
37
  platform = "fake";
38
38
  capabilities;
39
39
  ackDeadlineMs = 3000;
40
+ supportsIntelligenceMemory;
41
+ runAgentLifecycle;
40
42
  /** When true, `start()` rejects (set via constructor `failStart`). */
41
43
  failStart;
42
44
  /** When true, `registerCommands()` rejects (set via constructor `failRegisterCommands`). */
@@ -149,24 +151,54 @@ export class FakeAdapter {
149
151
  const adapter = this;
150
152
  return new Proxy(sink, {
151
153
  get(target, property, receiver) {
152
- if (property !== "onTurn") {
153
- return Reflect.get(target, property, receiver);
154
+ if (property === "onTurn") {
155
+ return (turn) => {
156
+ const syntheticId = turn.eventId ?? `fake-message-${++adapter.turnCounter}`;
157
+ return sink.onTurn(adapter.withIdentity({
158
+ ...turn,
159
+ operation: turn.operation ?? {
160
+ kind: "created",
161
+ logicalMessageId: syntheticId,
162
+ revisionId: syntheticId,
163
+ mentioned: true,
164
+ },
165
+ }, "message"));
166
+ };
154
167
  }
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
- });
168
+ const triggers = {
169
+ onInteraction: "interaction",
170
+ onCommand: "command",
171
+ onThreadStarted: "thread-start",
172
+ onWelcome: "welcome",
173
+ onReaction: "reaction",
174
+ onModalSubmit: "modal-submit",
175
+ onModalClose: "modal-close",
166
176
  };
177
+ const trigger = triggers[property];
178
+ if (trigger) {
179
+ return (event) => target[property](adapter.withIdentity(event, trigger));
180
+ }
181
+ return Reflect.get(target, property, receiver);
167
182
  },
168
183
  });
169
184
  }
185
+ withIdentity(event, trigger) {
186
+ const conversationKey = typeof event.conversationKey === "string" ? event.conversationKey : "c";
187
+ const actor = event.actor ??
188
+ { id: "", kind: "unknown" };
189
+ return {
190
+ ...event,
191
+ actor,
192
+ identityContext: event.identityContext ?? {
193
+ tenant: { id: "fake-tenant" },
194
+ installation: { id: "fake-installation" },
195
+ conversation: { id: conversationKey, kind: "test" },
196
+ trigger,
197
+ event: {},
198
+ raw: {},
199
+ },
200
+ };
201
+ }
170
202
  async start(sink) {
171
203
  if (this.failStart)
172
204
  throw new Error("fake-adapter: start failed");
@@ -230,7 +262,7 @@ export class FakeAdapter {
230
262
  // --- test helpers ---
231
263
  emitTurn(partial) {
232
264
  const syntheticId = partial.eventId ?? `fake-message-${++this.turnCounter}`;
233
- void this.sink?.onTurn({
265
+ void this.getSink().onTurn({
234
266
  conversationKey: "c",
235
267
  replyTarget: {},
236
268
  userText: "",
@@ -245,13 +277,21 @@ export class FakeAdapter {
245
277
  });
246
278
  }
247
279
  emitThreadStarted(partial) {
248
- return this.sink?.onThreadStarted({
280
+ return this.getSink().onThreadStarted({
249
281
  conversationKey: "c",
250
282
  replyTarget: {},
251
283
  platform: "fake",
252
284
  ...partial,
253
285
  });
254
286
  }
287
+ emitWelcome(partial) {
288
+ return this.getSink().onWelcome(this.withIdentity({
289
+ conversationKey: "c",
290
+ replyTarget: {},
291
+ platform: "fake",
292
+ ...partial,
293
+ }, "welcome"));
294
+ }
255
295
  emitInteraction(partial) {
256
296
  const evt = {
257
297
  id: "",
@@ -259,11 +299,11 @@ export class FakeAdapter {
259
299
  replyTarget: {},
260
300
  ...partial,
261
301
  };
262
- this.interactionsSeen.push(evt);
263
- void this.sink?.onInteraction(evt);
302
+ this.interactionsSeen.push(this.withIdentity(evt, "interaction"));
303
+ void this.getSink().onInteraction(evt);
264
304
  }
265
305
  emitCommand(partial) {
266
- return this.sink?.onCommand({
306
+ return this.getSink().onCommand({
267
307
  text: "",
268
308
  conversationKey: "c",
269
309
  replyTarget: {},
@@ -272,7 +312,7 @@ export class FakeAdapter {
272
312
  });
273
313
  }
274
314
  emitReaction(partial) {
275
- return this.sink?.onReaction({
315
+ return this.getSink().onReaction({
276
316
  added: true,
277
317
  conversationKey: "c",
278
318
  replyTarget: {},
@@ -282,7 +322,7 @@ export class FakeAdapter {
282
322
  });
283
323
  }
284
324
  emitModalSubmit(partial) {
285
- return this.sink?.onModalSubmit({
325
+ return this.getSink().onModalSubmit({
286
326
  values: {},
287
327
  platform: "fake",
288
328
  raw: {},
@@ -290,7 +330,11 @@ export class FakeAdapter {
290
330
  });
291
331
  }
292
332
  emitModalClose(partial) {
293
- return this.sink?.onModalClose({ platform: "fake", raw: {}, ...partial });
333
+ return this.getSink().onModalClose({
334
+ platform: "fake",
335
+ raw: {},
336
+ ...partial,
337
+ });
294
338
  }
295
339
  /** Commands handed to the adapter via `registerCommands`; asserts the capability hook fires. */
296
340
  registeredCommands;
@@ -1 +1 @@
1
- {"version":3,"file":"state-store-conformance.d.ts","sourceRoot":"","sources":["../../src/testing/state-store-conformance.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AAE1D,gFAAgF;AAChF,wBAAgB,wBAAwB,CACtC,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,UAAU,GAAG,OAAO,CAAC,UAAU,CAAC,EAC5C,QAAQ,CAAC,EAAE,CAAC,CAAC,EAAE,UAAU,KAAK,OAAO,CAAC,IAAI,CAAC,GAC1C,IAAI,CAwHN"}
1
+ {"version":3,"file":"state-store-conformance.d.ts","sourceRoot":"","sources":["../../src/testing/state-store-conformance.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AAE1D,gFAAgF;AAChF,wBAAgB,wBAAwB,CACtC,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,UAAU,GAAG,OAAO,CAAC,UAAU,CAAC,EAC5C,QAAQ,CAAC,EAAE,CAAC,CAAC,EAAE,UAAU,KAAK,OAAO,CAAC,IAAI,CAAC,GAC1C,IAAI,CAwIN"}
@@ -17,11 +17,27 @@ export function runStateStoreConformance(name, make, teardown) {
17
17
  expect(await s.kv.get("a")).toBeUndefined();
18
18
  });
19
19
  it("missing key is undefined", async () => expect(await s.kv.get("nope")).toBeUndefined());
20
+ it("atomically consumes one live value", async () => {
21
+ await s.kv.set("once", { n: 1 });
22
+ const results = await Promise.all([
23
+ s.kv.consume("once"),
24
+ s.kv.consume("once"),
25
+ ]);
26
+ expect(results.filter((value) => value !== undefined)).toEqual([
27
+ { n: 1 },
28
+ ]);
29
+ expect(await s.kv.get("once")).toBeUndefined();
30
+ });
20
31
  it("expires after ttl", async () => {
21
32
  await s.kv.set("t", 1, 30);
22
33
  await new Promise((r) => setTimeout(r, 60));
23
34
  expect(await s.kv.get("t")).toBeUndefined();
24
35
  });
36
+ it("does not return an expired value from consume", async () => {
37
+ await s.kv.set("expired-once", 1, 30);
38
+ await new Promise((r) => setTimeout(r, 60));
39
+ expect(await s.kv.consume("expired-once")).toBeUndefined();
40
+ });
25
41
  });
26
42
  describe("list", () => {
27
43
  it("appends oldest-first and ranges", async () => {
@@ -4,18 +4,29 @@ import { FakeAdapter } from "./testing/fake-adapter.js";
4
4
  describe("onThreadStarted routing", () => {
5
5
  it("invokes registered handlers with the thread and user", async () => {
6
6
  const fake = new FakeAdapter();
7
- const channel = createChannel({ adapters: [fake] });
7
+ const channel = createChannel({
8
+ adapters: [fake],
9
+ identifyUser: ({ actor }) => ({
10
+ id: actor.id,
11
+ name: actor.name ?? actor.id,
12
+ }),
13
+ });
8
14
  const seen = [];
9
- channel.onThreadStarted(({ thread, user }) => {
10
- seen.push({ user: user?.id, platform: thread.platform });
15
+ channel.onThreadStarted(({ thread, user, actor }) => {
16
+ seen.push({ user: user?.id, actor: actor.id, platform: thread.platform });
11
17
  });
12
18
  await channel.ɵruntime.start();
13
- await fake.emitThreadStarted({ user: { id: "U1", name: "Ada" } });
14
- expect(seen).toEqual([{ user: "U1", platform: "fake" }]);
19
+ await fake.emitThreadStarted({
20
+ actor: { id: "U1", kind: "human", name: "Ada" },
21
+ });
22
+ expect(seen).toEqual([{ user: "U1", actor: "U1", platform: "fake" }]);
15
23
  });
16
24
  it("invokes every registered handler in order", async () => {
17
25
  const fake = new FakeAdapter();
18
- const channel = createChannel({ adapters: [fake] });
26
+ const channel = createChannel({
27
+ identifyUser: "platform",
28
+ adapters: [fake],
29
+ });
19
30
  const order = [];
20
31
  channel.onThreadStarted(() => {
21
32
  order.push(1);
@@ -29,7 +40,10 @@ describe("onThreadStarted routing", () => {
29
40
  });
30
41
  it("is a no-op when no handler is registered", async () => {
31
42
  const fake = new FakeAdapter();
32
- const channel = createChannel({ adapters: [fake] });
43
+ const channel = createChannel({
44
+ identifyUser: "platform",
45
+ adapters: [fake],
46
+ });
33
47
  await channel.ɵruntime.start();
34
48
  // Should not throw.
35
49
  await expect(Promise.resolve(fake.emitThreadStarted())).resolves.toBeUndefined();
@@ -38,7 +52,10 @@ describe("onThreadStarted routing", () => {
38
52
  describe("Thread.setSuggestedPrompts / setTitle capability gating", () => {
39
53
  it("delegates to the adapter when supported", async () => {
40
54
  const fake = new FakeAdapter();
41
- const channel = createChannel({ adapters: [fake] });
55
+ const channel = createChannel({
56
+ identifyUser: "platform",
57
+ adapters: [fake],
58
+ });
42
59
  const results = [];
43
60
  channel.onThreadStarted(async ({ thread }) => {
44
61
  results.push(await thread.setSuggestedPrompts([{ title: "Triage", message: "Triage my issues" }], { title: "Try" }));
@@ -59,7 +76,10 @@ describe("Thread.setSuggestedPrompts / setTitle capability gating", () => {
59
76
  });
60
77
  it("returns { ok: false } without throwing when unsupported", async () => {
61
78
  const fake = new FakeAdapter({ paneMethods: false });
62
- const channel = createChannel({ adapters: [fake] });
79
+ const channel = createChannel({
80
+ identifyUser: "platform",
81
+ adapters: [fake],
82
+ });
63
83
  const results = [];
64
84
  channel.onThreadStarted(async ({ thread }) => {
65
85
  results.push(await thread.setSuggestedPrompts([]));
@@ -2,10 +2,13 @@ import { describe, it, expect } from "vitest";
2
2
  import { createChannel } from "./create-channel.js";
3
3
  import { FakeAdapter } from "./testing/fake-adapter.js";
4
4
  async function runOnMessage(fake, fn) {
5
- const channel = createChannel({ adapters: [fake] });
5
+ const channel = createChannel({ identifyUser: "platform", adapters: [fake] });
6
6
  channel.onMessage(fn);
7
7
  await channel.ɵruntime.start();
8
- fake.emitTurn({ userText: "hi", user: { id: "U1" } });
8
+ fake.emitTurn({
9
+ userText: "hi",
10
+ actor: { id: "U1", kind: "human" },
11
+ });
9
12
  await new Promise((r) => setTimeout(r, 0));
10
13
  }
11
14
  describe("Thread.postEphemeral", () => {
@@ -13,7 +16,7 @@ describe("Thread.postEphemeral", () => {
13
16
  const fake = new FakeAdapter({ nativeEphemeral: true });
14
17
  let res;
15
18
  await runOnMessage(fake, async ({ thread, message }) => {
16
- res = await thread.postEphemeral(message.user, "psst", {
19
+ res = await thread.postEphemeral(message.actor, "psst", {
17
20
  fallbackToDM: false,
18
21
  });
19
22
  });
@@ -26,7 +29,7 @@ describe("Thread.postEphemeral", () => {
26
29
  const fake = new FakeAdapter({ nativeEphemeral: false });
27
30
  let res;
28
31
  await runOnMessage(fake, async ({ thread, message }) => {
29
- res = await thread.postEphemeral(message.user, "psst", {
32
+ res = await thread.postEphemeral(message.actor, "psst", {
30
33
  fallbackToDM: true,
31
34
  });
32
35
  });
@@ -36,7 +39,7 @@ describe("Thread.postEphemeral", () => {
36
39
  const fake = new FakeAdapter({ nativeEphemeral: false });
37
40
  let res = "sentinel";
38
41
  await runOnMessage(fake, async ({ thread, message }) => {
39
- res = await thread.postEphemeral(message.user, "psst", {
42
+ res = await thread.postEphemeral(message.actor, "psst", {
40
43
  fallbackToDM: false,
41
44
  });
42
45
  });