@copilotkit/channels 0.1.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.
- package/LICENSE +21 -0
- package/README.md +204 -0
- package/dist/action-registry.d.ts +59 -0
- package/dist/action-registry.d.ts.map +1 -0
- package/dist/action-registry.js +217 -0
- package/dist/action-registry.test.d.ts +2 -0
- package/dist/action-registry.test.d.ts.map +1 -0
- package/dist/action-registry.test.js +115 -0
- package/dist/action-store.d.ts +21 -0
- package/dist/action-store.d.ts.map +1 -0
- package/dist/action-store.js +23 -0
- package/dist/action-store.test.d.ts +2 -0
- package/dist/action-store.test.d.ts.map +1 -0
- package/dist/action-store.test.js +27 -0
- package/dist/codec.d.ts +25 -0
- package/dist/codec.d.ts.map +1 -0
- package/dist/codec.js +1 -0
- package/dist/commands.d.ts +73 -0
- package/dist/commands.d.ts.map +1 -0
- package/dist/commands.js +38 -0
- package/dist/commands.test.d.ts +2 -0
- package/dist/commands.test.d.ts.map +1 -0
- package/dist/commands.test.js +23 -0
- package/dist/create-bot.d.ts +171 -0
- package/dist/create-bot.d.ts.map +1 -0
- package/dist/create-bot.foundations.test.d.ts +2 -0
- package/dist/create-bot.foundations.test.d.ts.map +1 -0
- package/dist/create-bot.foundations.test.js +147 -0
- package/dist/create-bot.js +576 -0
- package/dist/create-bot.test.d.ts +2 -0
- package/dist/create-bot.test.d.ts.map +1 -0
- package/dist/create-bot.test.js +936 -0
- package/dist/index.d.ts +26 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +32 -0
- package/dist/mint-id.d.ts +3 -0
- package/dist/mint-id.d.ts.map +1 -0
- package/dist/mint-id.js +20 -0
- package/dist/mint-id.test.d.ts +2 -0
- package/dist/mint-id.test.d.ts.map +1 -0
- package/dist/mint-id.test.js +16 -0
- package/dist/modal-submit.test.d.ts +2 -0
- package/dist/modal-submit.test.d.ts.map +1 -0
- package/dist/modal-submit.test.js +68 -0
- package/dist/platform-adapter.d.ts +312 -0
- package/dist/platform-adapter.d.ts.map +1 -0
- package/dist/platform-adapter.js +1 -0
- package/dist/platform-adapter.test.d.ts +2 -0
- package/dist/platform-adapter.test.d.ts.map +1 -0
- package/dist/platform-adapter.test.js +40 -0
- package/dist/reactions.test.d.ts +2 -0
- package/dist/reactions.test.d.ts.map +1 -0
- package/dist/reactions.test.js +197 -0
- package/dist/run-loop.d.ts +41 -0
- package/dist/run-loop.d.ts.map +1 -0
- package/dist/run-loop.js +102 -0
- package/dist/run-loop.test.d.ts +2 -0
- package/dist/run-loop.test.d.ts.map +1 -0
- package/dist/run-loop.test.js +125 -0
- package/dist/standard-schema.d.ts +52 -0
- package/dist/standard-schema.d.ts.map +1 -0
- package/dist/standard-schema.js +66 -0
- package/dist/state/duration.d.ts +3 -0
- package/dist/state/duration.d.ts.map +1 -0
- package/dist/state/duration.js +16 -0
- package/dist/state/duration.test.d.ts +2 -0
- package/dist/state/duration.test.d.ts.map +1 -0
- package/dist/state/duration.test.js +13 -0
- package/dist/state/kv-action-store.d.ts +7 -0
- package/dist/state/kv-action-store.d.ts.map +1 -0
- package/dist/state/kv-action-store.js +9 -0
- package/dist/state/kv-action-store.test.d.ts +2 -0
- package/dist/state/kv-action-store.test.d.ts.map +1 -0
- package/dist/state/kv-action-store.test.js +21 -0
- package/dist/state/memory-store.d.ts +41 -0
- package/dist/state/memory-store.d.ts.map +1 -0
- package/dist/state/memory-store.js +110 -0
- package/dist/state/memory-store.test.d.ts +2 -0
- package/dist/state/memory-store.test.d.ts.map +1 -0
- package/dist/state/memory-store.test.js +22 -0
- package/dist/state/state-conversation-store.d.ts +14 -0
- package/dist/state/state-conversation-store.d.ts.map +1 -0
- package/dist/state/state-conversation-store.js +22 -0
- package/dist/state/state-conversation-store.test.d.ts +2 -0
- package/dist/state/state-conversation-store.test.d.ts.map +1 -0
- package/dist/state/state-conversation-store.test.js +58 -0
- package/dist/state/state-store.d.ts +63 -0
- package/dist/state/state-store.d.ts.map +1 -0
- package/dist/state/state-store.js +1 -0
- package/dist/telemetry/bot-telemetry.d.ts +31 -0
- package/dist/telemetry/bot-telemetry.d.ts.map +1 -0
- package/dist/telemetry/bot-telemetry.js +70 -0
- package/dist/telemetry/bot-telemetry.test.d.ts +2 -0
- package/dist/telemetry/bot-telemetry.test.d.ts.map +1 -0
- package/dist/telemetry/bot-telemetry.test.js +56 -0
- package/dist/telemetry/create-bot-telemetry.test.d.ts +2 -0
- package/dist/telemetry/create-bot-telemetry.test.d.ts.map +1 -0
- package/dist/telemetry/create-bot-telemetry.test.js +71 -0
- package/dist/telemetry/e2e-telemetry.test.d.ts +2 -0
- package/dist/telemetry/e2e-telemetry.test.d.ts.map +1 -0
- package/dist/telemetry/e2e-telemetry.test.js +56 -0
- package/dist/telemetry/events-catalog.test.d.ts +2 -0
- package/dist/telemetry/events-catalog.test.d.ts.map +1 -0
- package/dist/telemetry/events-catalog.test.js +8 -0
- package/dist/telemetry/install-id.d.ts +8 -0
- package/dist/telemetry/install-id.d.ts.map +1 -0
- package/dist/telemetry/install-id.js +43 -0
- package/dist/telemetry/install-id.test.d.ts +2 -0
- package/dist/telemetry/install-id.test.d.ts.map +1 -0
- package/dist/telemetry/install-id.test.js +43 -0
- package/dist/telemetry/platform-allowlist-coverage.test.d.ts +2 -0
- package/dist/telemetry/platform-allowlist-coverage.test.d.ts.map +1 -0
- package/dist/telemetry/platform-allowlist-coverage.test.js +45 -0
- package/dist/telemetry/sanitize-error.d.ts +3 -0
- package/dist/telemetry/sanitize-error.d.ts.map +1 -0
- package/dist/telemetry/sanitize-error.js +31 -0
- package/dist/telemetry/sanitize-error.test.d.ts +2 -0
- package/dist/telemetry/sanitize-error.test.d.ts.map +1 -0
- package/dist/telemetry/sanitize-error.test.js +33 -0
- package/dist/testing/fake-adapter.d.ts +137 -0
- package/dist/testing/fake-adapter.d.ts.map +1 -0
- package/dist/testing/fake-adapter.js +273 -0
- package/dist/testing/fake-agent.d.ts +28 -0
- package/dist/testing/fake-agent.d.ts.map +1 -0
- package/dist/testing/fake-agent.js +36 -0
- package/dist/testing/state-store-conformance.d.ts +4 -0
- package/dist/testing/state-store-conformance.d.ts.map +1 -0
- package/dist/testing/state-store-conformance.js +117 -0
- package/dist/thread-capabilities.test.d.ts +2 -0
- package/dist/thread-capabilities.test.d.ts.map +1 -0
- package/dist/thread-capabilities.test.js +77 -0
- package/dist/thread-ephemeral.test.d.ts +2 -0
- package/dist/thread-ephemeral.test.d.ts.map +1 -0
- package/dist/thread-ephemeral.test.js +45 -0
- package/dist/thread-reactions.test.d.ts +2 -0
- package/dist/thread-reactions.test.d.ts.map +1 -0
- package/dist/thread-reactions.test.js +38 -0
- package/dist/thread.d.ts +152 -0
- package/dist/thread.d.ts.map +1 -0
- package/dist/thread.js +329 -0
- package/dist/thread.test.d.ts +2 -0
- package/dist/thread.test.d.ts.map +1 -0
- package/dist/thread.test.js +83 -0
- package/dist/tools.d.ts +67 -0
- package/dist/tools.d.ts.map +1 -0
- package/dist/tools.js +38 -0
- package/dist/tools.test.d.ts +2 -0
- package/dist/tools.test.d.ts.map +1 -0
- package/dist/tools.test.js +31 -0
- package/dist/transcripts.d.ts +52 -0
- package/dist/transcripts.d.ts.map +1 -0
- package/dist/transcripts.js +67 -0
- package/dist/transcripts.test.d.ts +2 -0
- package/dist/transcripts.test.d.ts.map +1 -0
- package/dist/transcripts.test.js +108 -0
- package/package.json +72 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
export { createBot } from "./create-bot.js";
|
|
2
|
+
export type { Bot, CreateBotOptions, BotHandler, ThreadStartHandler, ReactionEvent, ReactionHandler, ModalSubmitEvent, ModalSubmitHandler, ModalCloseEvent, ModalCloseHandler, StoreConfig, LockConflictDecision, StatefulThread, BotComponent, } from "./create-bot.js";
|
|
3
|
+
export { Thread } from "./thread.js";
|
|
4
|
+
export type { ThreadDeps } from "./thread.js";
|
|
5
|
+
export type { PlatformAdapter, AdapterStartContext, RunRenderer, IngressSink, IncomingTurn, InteractionEvent, IncomingCommand, IncomingThreadStart, IncomingReaction, IncomingModalSubmit, IncomingModalClose, ModalSubmitResult, SurfaceCapabilities, ReplyTarget, ConversationStore, AgentSession, CapturedToolCall, CapturedInterrupt, UserQuery, NativePayload, } from "./platform-adapter.js";
|
|
6
|
+
export { defineBotCommand, normalizeCommandName, toCommandSpec, } from "./commands.js";
|
|
7
|
+
export type { BotCommand, CommandContext, CommandSpec } from "./commands.js";
|
|
8
|
+
export { InMemoryActionStore } from "./action-store.js";
|
|
9
|
+
export type { ActionStore, ActionSnapshot } from "./action-store.js";
|
|
10
|
+
export { ActionRegistry, ActionExpiredError } from "./action-registry.js";
|
|
11
|
+
export type { StateStore } from "./state/state-store.js";
|
|
12
|
+
export { MemoryStore } from "./state/memory-store.js";
|
|
13
|
+
export { parseDuration } from "./state/duration.js";
|
|
14
|
+
export { createStateBackedConversationStore } from "./state/state-conversation-store.js";
|
|
15
|
+
export { Transcripts } from "./transcripts.js";
|
|
16
|
+
export type { TranscriptEntry, Identity, TranscriptsConfig, } from "./transcripts.js";
|
|
17
|
+
export { toAgentToolDescriptors, parseToolArgs, stringifyHandlerResult, defineBotTool, } from "./tools.js";
|
|
18
|
+
export type { BotTool, ObjectSchema, BotToolContext, ContextEntry, AgentToolDescriptor, } from "./tools.js";
|
|
19
|
+
export { mintId, stableStringify } from "./mint-id.js";
|
|
20
|
+
export { runAgentLoop } from "./run-loop.js";
|
|
21
|
+
export type { RunLoopArgs } from "./run-loop.js";
|
|
22
|
+
export type { PlatformCodec } from "./codec.js";
|
|
23
|
+
export { FakeAdapter, makeFakeRunRenderer } from "./testing/fake-adapter.js";
|
|
24
|
+
export { FakeAgent } from "./testing/fake-agent.js";
|
|
25
|
+
export * from "@copilotkit/channels-ui";
|
|
26
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAC5C,YAAY,EACV,GAAG,EACH,gBAAgB,EAChB,UAAU,EACV,kBAAkB,EAClB,aAAa,EACb,eAAe,EACf,gBAAgB,EAChB,kBAAkB,EAClB,eAAe,EACf,iBAAiB,EACjB,WAAW,EACX,oBAAoB,EACpB,cAAc,EACd,YAAY,GACb,MAAM,iBAAiB,CAAC;AAGzB,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,YAAY,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAG9C,YAAY,EACV,eAAe,EACf,mBAAmB,EACnB,WAAW,EACX,WAAW,EACX,YAAY,EACZ,gBAAgB,EAChB,eAAe,EACf,mBAAmB,EACnB,gBAAgB,EAChB,mBAAmB,EACnB,kBAAkB,EAClB,iBAAiB,EACjB,mBAAmB,EACnB,WAAW,EACX,iBAAiB,EACjB,YAAY,EACZ,gBAAgB,EAChB,iBAAiB,EACjB,SAAS,EACT,aAAa,GACd,MAAM,uBAAuB,CAAC;AAG/B,OAAO,EACL,gBAAgB,EAChB,oBAAoB,EACpB,aAAa,GACd,MAAM,eAAe,CAAC;AACvB,YAAY,EAAE,UAAU,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAG7E,OAAO,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AACxD,YAAY,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAGrE,OAAO,EAAE,cAAc,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAG1E,YAAY,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AACzD,OAAO,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAMtD,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,kCAAkC,EAAE,MAAM,qCAAqC,CAAC;AAGzF,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC/C,YAAY,EACV,eAAe,EACf,QAAQ,EACR,iBAAiB,GAClB,MAAM,kBAAkB,CAAC;AAG1B,OAAO,EACL,sBAAsB,EACtB,aAAa,EACb,sBAAsB,EACtB,aAAa,GACd,MAAM,YAAY,CAAC;AACpB,YAAY,EACV,OAAO,EACP,YAAY,EACZ,cAAc,EACd,YAAY,EACZ,mBAAmB,GACpB,MAAM,YAAY,CAAC;AAGpB,OAAO,EAAE,MAAM,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAGvD,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAC7C,YAAY,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAKjD,YAAY,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAGhD,OAAO,EAAE,WAAW,EAAE,mBAAmB,EAAE,MAAM,2BAA2B,CAAC;AAC7E,OAAO,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAC;AAGpD,cAAc,yBAAyB,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
// Public API for @copilotkit/channels.
|
|
2
|
+
// Bot orchestration
|
|
3
|
+
export { createBot } from "./create-bot.js";
|
|
4
|
+
// Thread
|
|
5
|
+
export { Thread } from "./thread.js";
|
|
6
|
+
// Slash commands
|
|
7
|
+
export { defineBotCommand, normalizeCommandName, toCommandSpec, } from "./commands.js";
|
|
8
|
+
// Action store
|
|
9
|
+
export { InMemoryActionStore } from "./action-store.js";
|
|
10
|
+
// Action registry
|
|
11
|
+
export { ActionRegistry, ActionExpiredError } from "./action-registry.js";
|
|
12
|
+
export { MemoryStore } from "./state/memory-store.js";
|
|
13
|
+
// NOTE: `runStateStoreConformance` is intentionally NOT re-exported here. It
|
|
14
|
+
// pulls in `vitest`, so re-exporting it from the package entry would drag a
|
|
15
|
+
// test framework into every consumer's runtime module graph (a bare
|
|
16
|
+
// `import ... from "@copilotkit/channels"` would fail unless vitest is installed).
|
|
17
|
+
// It is published under the `@copilotkit/channels/testing` subpath instead.
|
|
18
|
+
export { parseDuration } from "./state/duration.js";
|
|
19
|
+
export { createStateBackedConversationStore } from "./state/state-conversation-store.js";
|
|
20
|
+
// Transcripts
|
|
21
|
+
export { Transcripts } from "./transcripts.js";
|
|
22
|
+
// Tools & context
|
|
23
|
+
export { toAgentToolDescriptors, parseToolArgs, stringifyHandlerResult, defineBotTool, } from "./tools.js";
|
|
24
|
+
// Id / serialization helpers
|
|
25
|
+
export { mintId, stableStringify } from "./mint-id.js";
|
|
26
|
+
// Run loop
|
|
27
|
+
export { runAgentLoop } from "./run-loop.js";
|
|
28
|
+
// Test utilities (also surfaces them for downstream adapter packages' tests).
|
|
29
|
+
export { FakeAdapter, makeFakeRunRenderer } from "./testing/fake-adapter.js";
|
|
30
|
+
export { FakeAgent } from "./testing/fake-agent.js";
|
|
31
|
+
// Re-export the bot-ui component vocabulary + types for convenience.
|
|
32
|
+
export * from "@copilotkit/channels-ui";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mint-id.d.ts","sourceRoot":"","sources":["../src/mint-id.ts"],"names":[],"mappings":"AAEA,wBAAgB,eAAe,CAAC,CAAC,EAAE,OAAO,GAAG,MAAM,CAYlD;AAED,wBAAgB,MAAM,CACpB,aAAa,EAAE,MAAM,EACrB,IAAI,EAAE,CAAC,MAAM,GAAG,MAAM,CAAC,EAAE,EACzB,KAAK,EAAE,OAAO,GACb,MAAM,CAKR"}
|
package/dist/mint-id.js
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
2
|
+
export function stableStringify(v) {
|
|
3
|
+
if (v === null || typeof v !== "object")
|
|
4
|
+
return JSON.stringify(v) ?? "null";
|
|
5
|
+
if (Array.isArray(v))
|
|
6
|
+
return "[" + v.map(stableStringify).join(",") + "]";
|
|
7
|
+
const obj = v;
|
|
8
|
+
const keys = Object.keys(obj).sort();
|
|
9
|
+
return ("{" +
|
|
10
|
+
keys
|
|
11
|
+
.map((k) => JSON.stringify(k) + ":" + stableStringify(obj[k]))
|
|
12
|
+
.join(",") +
|
|
13
|
+
"}");
|
|
14
|
+
}
|
|
15
|
+
export function mintId(componentName, path, props) {
|
|
16
|
+
const h = createHash("sha1")
|
|
17
|
+
.update(`${componentName}|${path.join(".")}|${stableStringify(props)}`)
|
|
18
|
+
.digest("hex");
|
|
19
|
+
return "ck:" + h.slice(0, 16);
|
|
20
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mint-id.test.d.ts","sourceRoot":"","sources":["../src/mint-id.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { describe, it, expect } from "vitest";
|
|
2
|
+
import { mintId, stableStringify } from "./mint-id.js";
|
|
3
|
+
describe("mintId", () => {
|
|
4
|
+
it("is content-stable for same component/path/props", () => {
|
|
5
|
+
const a = mintId("Flight", [0, "onClick"], { id: "f1" });
|
|
6
|
+
const b = mintId("Flight", [0, "onClick"], { id: "f1" });
|
|
7
|
+
expect(a).toBe(b);
|
|
8
|
+
expect(a.startsWith("ck:")).toBe(true);
|
|
9
|
+
});
|
|
10
|
+
it("differs when props differ", () => {
|
|
11
|
+
expect(mintId("Flight", [0], { id: "f1" })).not.toBe(mintId("Flight", [0], { id: "f2" }));
|
|
12
|
+
});
|
|
13
|
+
it("stableStringify sorts keys", () => {
|
|
14
|
+
expect(stableStringify({ b: 1, a: 2 })).toBe(stableStringify({ a: 2, b: 1 }));
|
|
15
|
+
});
|
|
16
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"modal-submit.test.d.ts","sourceRoot":"","sources":["../src/modal-submit.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
// packages/channels/src/modal-submit.test.ts
|
|
2
|
+
import { describe, it, expect } from "vitest";
|
|
3
|
+
import { createBot } from "./create-bot.js";
|
|
4
|
+
import { FakeAdapter } from "./testing/fake-adapter.js";
|
|
5
|
+
describe("bot.onModalSubmit / onModalClose", () => {
|
|
6
|
+
it("routes a submission by callbackId and parses values; thread present when conversation context exists", async () => {
|
|
7
|
+
const fake = new FakeAdapter();
|
|
8
|
+
const bot = createBot({ adapters: [fake] });
|
|
9
|
+
const seen = [];
|
|
10
|
+
bot.onModalSubmit("triage", (evt) => {
|
|
11
|
+
seen.push({
|
|
12
|
+
values: evt.values,
|
|
13
|
+
user: evt.user?.id,
|
|
14
|
+
cb: evt.callbackId,
|
|
15
|
+
hasThread: !!evt.thread,
|
|
16
|
+
});
|
|
17
|
+
});
|
|
18
|
+
await bot.start();
|
|
19
|
+
const res = await fake.emitModalSubmit({
|
|
20
|
+
callbackId: "triage",
|
|
21
|
+
values: { summary: "boom", prio: "high" },
|
|
22
|
+
user: { id: "U1" },
|
|
23
|
+
conversationKey: "c",
|
|
24
|
+
replyTarget: {},
|
|
25
|
+
});
|
|
26
|
+
expect(res).toBeUndefined(); // no errors → closes
|
|
27
|
+
expect(seen).toEqual([
|
|
28
|
+
{
|
|
29
|
+
values: { summary: "boom", prio: "high" },
|
|
30
|
+
user: "U1",
|
|
31
|
+
cb: "triage",
|
|
32
|
+
hasThread: true,
|
|
33
|
+
},
|
|
34
|
+
]);
|
|
35
|
+
});
|
|
36
|
+
it("returns the handler's field errors so the adapter can keep the modal open", async () => {
|
|
37
|
+
const fake = new FakeAdapter();
|
|
38
|
+
const bot = createBot({ adapters: [fake] });
|
|
39
|
+
bot.onModalSubmit("triage", (evt) => evt.values.summary ? undefined : { errors: { summary: "Required" } });
|
|
40
|
+
await bot.start();
|
|
41
|
+
const res = await fake.emitModalSubmit({
|
|
42
|
+
callbackId: "triage",
|
|
43
|
+
values: {},
|
|
44
|
+
});
|
|
45
|
+
expect(res).toEqual({ errors: { summary: "Required" } });
|
|
46
|
+
});
|
|
47
|
+
it("ignores submissions with no registered handler", async () => {
|
|
48
|
+
const fake = new FakeAdapter();
|
|
49
|
+
const bot = createBot({ adapters: [fake] });
|
|
50
|
+
await bot.start();
|
|
51
|
+
const res = await fake.emitModalSubmit({
|
|
52
|
+
callbackId: "unknown",
|
|
53
|
+
values: {},
|
|
54
|
+
});
|
|
55
|
+
expect(res).toBeUndefined();
|
|
56
|
+
});
|
|
57
|
+
it("routes a close by callbackId", async () => {
|
|
58
|
+
const fake = new FakeAdapter();
|
|
59
|
+
const bot = createBot({ adapters: [fake] });
|
|
60
|
+
const closed = [];
|
|
61
|
+
bot.onModalClose("triage", (evt) => {
|
|
62
|
+
closed.push(evt.callbackId);
|
|
63
|
+
});
|
|
64
|
+
await bot.start();
|
|
65
|
+
await fake.emitModalClose({ callbackId: "triage", user: { id: "U2" } });
|
|
66
|
+
expect(closed).toEqual(["triage"]);
|
|
67
|
+
});
|
|
68
|
+
});
|
|
@@ -0,0 +1,312 @@
|
|
|
1
|
+
import type { AgentSubscriber, AbstractAgent } from "@ag-ui/client";
|
|
2
|
+
import type { AgentContentPart, BotNode, EmojiValue, EphemeralResult, MessageRef, PlatformUser, ThreadMessage } from "@copilotkit/channels-ui";
|
|
3
|
+
import type { CommandSpec } from "./commands.js";
|
|
4
|
+
import type { StateStore } from "./state/state-store.js";
|
|
5
|
+
/** Opaque to the bot core — created by an adapter during ingress and passed back to post/createRunRenderer. */
|
|
6
|
+
export type ReplyTarget = unknown;
|
|
7
|
+
/** Opaque native payload produced by an adapter's render(). */
|
|
8
|
+
export type NativePayload = unknown;
|
|
9
|
+
export interface SurfaceCapabilities {
|
|
10
|
+
supportsModals: boolean;
|
|
11
|
+
supportsTyping: boolean;
|
|
12
|
+
supportsReactions: boolean;
|
|
13
|
+
supportsStreaming: boolean;
|
|
14
|
+
maxBlocksPerMessage?: number;
|
|
15
|
+
/** Pinned prompt chips on a conversation surface (Slack assistant pane). */
|
|
16
|
+
supportsSuggestedPrompts?: boolean;
|
|
17
|
+
/** Nameable conversations (Slack assistant-thread titles). */
|
|
18
|
+
supportsThreadTitle?: boolean;
|
|
19
|
+
/** Native ephemeral messages (Slack). When false, `postEphemeral` still works via DM fallback. */
|
|
20
|
+
supportsEphemeral?: boolean;
|
|
21
|
+
[k: string]: unknown;
|
|
22
|
+
}
|
|
23
|
+
export interface CapturedToolCall {
|
|
24
|
+
toolCallId: string;
|
|
25
|
+
toolCallName: string;
|
|
26
|
+
toolCallArgs: Record<string, unknown>;
|
|
27
|
+
}
|
|
28
|
+
export interface CapturedInterrupt {
|
|
29
|
+
eventName: string;
|
|
30
|
+
value: unknown;
|
|
31
|
+
}
|
|
32
|
+
/** A per-run handle: the AG-UI subscriber to stream into, plus capture accessors the run-loop reads after each runAgent. */
|
|
33
|
+
export interface RunRenderer {
|
|
34
|
+
subscriber: AgentSubscriber;
|
|
35
|
+
markInterrupted(): Promise<void>;
|
|
36
|
+
getCapturedToolCalls(): readonly CapturedToolCall[];
|
|
37
|
+
getPendingInterrupt(): CapturedInterrupt | undefined;
|
|
38
|
+
clearPendingInterrupt(): void;
|
|
39
|
+
/**
|
|
40
|
+
* Optional turn-end hook. Called once after the run-loop resolves normally
|
|
41
|
+
* (no more tool calls, or an interrupt was acked), so a renderer that keeps a
|
|
42
|
+
* turn-scoped resource open across `runAgent` iterations — e.g. a single
|
|
43
|
+
* native streaming message that interleaves text and tool-progress — can
|
|
44
|
+
* finalize it. Symmetric with {@link markInterrupted}; renderers whose
|
|
45
|
+
* streams self-terminate per message simply omit it. Must be a no-op if the
|
|
46
|
+
* run was already interrupted.
|
|
47
|
+
*/
|
|
48
|
+
finish?(): Promise<void>;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Fields shared by every ingress event routed through the {@link IngressSink}:
|
|
52
|
+
* the conversation it belongs to, the opaque target to reply on, and the user
|
|
53
|
+
* who triggered it (when the platform reports one).
|
|
54
|
+
*/
|
|
55
|
+
export interface IngressEventBase {
|
|
56
|
+
conversationKey: string;
|
|
57
|
+
replyTarget: ReplyTarget;
|
|
58
|
+
user?: PlatformUser;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Idempotency ids carried by turn/command/interaction ingress. Set on the
|
|
62
|
+
* managed (Intelligence-delivered) path; local adapters omit them.
|
|
63
|
+
*/
|
|
64
|
+
export interface IngressIds {
|
|
65
|
+
/** Stable platform event id for idempotency; omit if the platform provides none. */
|
|
66
|
+
eventId?: string;
|
|
67
|
+
/** Stable per-turn id (managed/Intelligence path); local adapters omit it. */
|
|
68
|
+
turnId?: string;
|
|
69
|
+
/** Lease/delivery id (managed/Intelligence path); local adapters omit it. */
|
|
70
|
+
deliveryId?: string;
|
|
71
|
+
}
|
|
72
|
+
export interface IncomingTurn extends IngressEventBase, IngressIds {
|
|
73
|
+
userText: string;
|
|
74
|
+
/**
|
|
75
|
+
* Optional multimodal content parts built by the adapter (e.g. inbound
|
|
76
|
+
* image/file attachments). Carried through to `IncomingMessage.contentParts`.
|
|
77
|
+
*/
|
|
78
|
+
contentParts?: AgentContentPart[];
|
|
79
|
+
platform: string;
|
|
80
|
+
}
|
|
81
|
+
export interface InteractionEvent extends IngressEventBase, IngressIds {
|
|
82
|
+
id: string;
|
|
83
|
+
value?: unknown;
|
|
84
|
+
/** The message the interaction occurred on (the picker), so handlers can update it in place. */
|
|
85
|
+
messageRef?: MessageRef;
|
|
86
|
+
/** Opaque platform trigger for opening a modal (Slack `trigger_id`; Discord interaction id). */
|
|
87
|
+
triggerId?: string;
|
|
88
|
+
}
|
|
89
|
+
/** A slash-command invocation normalized by an adapter. */
|
|
90
|
+
export interface IncomingCommand extends IngressEventBase, IngressIds {
|
|
91
|
+
/** Command name as invoked (a leading slash and case are normalized by the engine). */
|
|
92
|
+
command: string;
|
|
93
|
+
/** Raw argument string after the command name (the form text-only surfaces deliver). */
|
|
94
|
+
text: string;
|
|
95
|
+
/** Structured, pre-parsed options when the surface delivers them (e.g. Discord). */
|
|
96
|
+
rawOptions?: Record<string, unknown>;
|
|
97
|
+
platform: string;
|
|
98
|
+
/** Opaque platform trigger for opening a modal (Slack `trigger_id`; Discord interaction id). */
|
|
99
|
+
triggerId?: string;
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* A "conversation opened" lifecycle event (Slack: `assistant_thread_started`).
|
|
103
|
+
* Adapters without the concept never emit it.
|
|
104
|
+
*/
|
|
105
|
+
export interface IncomingThreadStart extends IngressEventBase {
|
|
106
|
+
platform: string;
|
|
107
|
+
}
|
|
108
|
+
/** A reaction added/removed on a message. Adapters that can't observe reactions never emit it. */
|
|
109
|
+
export interface IncomingReaction extends IngressEventBase {
|
|
110
|
+
/** Platform-native emoji token (Slack shortcode, Unicode, Discord custom). */
|
|
111
|
+
rawEmoji: string;
|
|
112
|
+
/** true = added, false = removed. */
|
|
113
|
+
added: boolean;
|
|
114
|
+
/** Id of the reacted-to message. */
|
|
115
|
+
messageId: string;
|
|
116
|
+
/**
|
|
117
|
+
* Update-capable ref to the reacted message (the platform-specific shape the
|
|
118
|
+
* adapter's `update`/`delete` accept). Lets a `<Message onReaction>` handler
|
|
119
|
+
* swap the message's UI in place. Adapters that can edit messages should set
|
|
120
|
+
* this; the engine falls back to `{ id: messageId }` when omitted.
|
|
121
|
+
*/
|
|
122
|
+
messageRef?: MessageRef;
|
|
123
|
+
/** Containing thread/conversation id, when distinct from the message. */
|
|
124
|
+
threadId?: string;
|
|
125
|
+
/** Native payload. */
|
|
126
|
+
raw: unknown;
|
|
127
|
+
}
|
|
128
|
+
/** A modal submission. Adapters without modals never emit it. */
|
|
129
|
+
export interface IncomingModalSubmit {
|
|
130
|
+
callbackId: string;
|
|
131
|
+
/** Field id → value (text string, selected option value, etc.). */
|
|
132
|
+
values: Record<string, unknown>;
|
|
133
|
+
user?: PlatformUser;
|
|
134
|
+
privateMetadata?: string;
|
|
135
|
+
/** Present when the submission carries a conversation context (so the engine can build a Thread). */
|
|
136
|
+
conversationKey?: string;
|
|
137
|
+
replyTarget?: ReplyTarget;
|
|
138
|
+
platform: string;
|
|
139
|
+
raw: unknown;
|
|
140
|
+
}
|
|
141
|
+
/** A modal dismissal (Slack `view_closed`; requires `notifyOnClose`). */
|
|
142
|
+
export interface IncomingModalClose {
|
|
143
|
+
callbackId: string;
|
|
144
|
+
user?: PlatformUser;
|
|
145
|
+
privateMetadata?: string;
|
|
146
|
+
/** Present when the dismissal carries a conversation context (so the engine can build a Thread). */
|
|
147
|
+
conversationKey?: string;
|
|
148
|
+
replyTarget?: ReplyTarget;
|
|
149
|
+
platform: string;
|
|
150
|
+
raw: unknown;
|
|
151
|
+
}
|
|
152
|
+
/** What a submit handler may return to keep the modal open with per-field errors. */
|
|
153
|
+
export interface ModalSubmitResult {
|
|
154
|
+
errors?: Record<string, string>;
|
|
155
|
+
}
|
|
156
|
+
export interface IngressSink {
|
|
157
|
+
onTurn(turn: IncomingTurn): void | Promise<void>;
|
|
158
|
+
onInteraction(evt: InteractionEvent): void | Promise<void>;
|
|
159
|
+
/** A slash command fired. Routed to the matching `bot.onCommand` handler (ignored if none). */
|
|
160
|
+
onCommand(cmd: IncomingCommand): void | Promise<void>;
|
|
161
|
+
/** A conversation surface opened. Adapters without the concept never call it. */
|
|
162
|
+
onThreadStarted(evt: IncomingThreadStart): void | Promise<void>;
|
|
163
|
+
/** A reaction was added/removed. Adapters that can't observe reactions never call it. */
|
|
164
|
+
onReaction(evt: IncomingReaction): void | Promise<void>;
|
|
165
|
+
/**
|
|
166
|
+
* A modal was submitted. Returns the handler's result so the adapter can ack
|
|
167
|
+
* with per-field errors (Slack `response_action: "errors"`). Adapters without
|
|
168
|
+
* modals never call it.
|
|
169
|
+
*/
|
|
170
|
+
onModalSubmit(evt: IncomingModalSubmit): Promise<ModalSubmitResult | void>;
|
|
171
|
+
/** A modal was dismissed. Adapters without `view_closed` never call it. */
|
|
172
|
+
onModalClose(evt: IncomingModalClose): void | Promise<void>;
|
|
173
|
+
}
|
|
174
|
+
export interface UserQuery {
|
|
175
|
+
query: string;
|
|
176
|
+
}
|
|
177
|
+
/** A resolved agent session for a conversation (the adapter may build the agent's history from its own state). */
|
|
178
|
+
export interface AgentSession {
|
|
179
|
+
agent: AbstractAgent;
|
|
180
|
+
}
|
|
181
|
+
/** Adapter-owned conversation state; the adapter resolves (or creates) the agent session for a conversation. */
|
|
182
|
+
export interface ConversationStore {
|
|
183
|
+
getOrCreate(conversationKey: string, replyTarget: ReplyTarget, makeAgent: (threadId: string) => AbstractAgent): Promise<AgentSession>;
|
|
184
|
+
}
|
|
185
|
+
/**
|
|
186
|
+
* Optional context bot core passes to {@link PlatformAdapter.start}. Carries
|
|
187
|
+
* the bot's declared identity so a transport that must announce itself (e.g.
|
|
188
|
+
* the managed Intelligence adapter's heartbeat) can do so without separate
|
|
189
|
+
* config. Local adapters ignore it.
|
|
190
|
+
*/
|
|
191
|
+
export interface AdapterStartContext {
|
|
192
|
+
/** The bot's declared name (`createBot({ name })`), when set. */
|
|
193
|
+
botName?: string;
|
|
194
|
+
}
|
|
195
|
+
export interface PlatformAdapter {
|
|
196
|
+
readonly platform: string;
|
|
197
|
+
readonly capabilities: SurfaceCapabilities;
|
|
198
|
+
readonly ackDeadlineMs: number;
|
|
199
|
+
start(sink: IngressSink, ctx?: AdapterStartContext): Promise<void>;
|
|
200
|
+
stop(): Promise<void>;
|
|
201
|
+
render(ir: BotNode[]): NativePayload;
|
|
202
|
+
post(target: ReplyTarget, ir: BotNode[]): Promise<MessageRef>;
|
|
203
|
+
update(ref: MessageRef, ir: BotNode[]): Promise<void>;
|
|
204
|
+
stream(target: ReplyTarget, chunks: AsyncIterable<string>): Promise<MessageRef>;
|
|
205
|
+
delete(ref: MessageRef): Promise<void>;
|
|
206
|
+
createRunRenderer(target: ReplyTarget): RunRenderer;
|
|
207
|
+
decodeInteraction(raw: unknown): InteractionEvent | undefined;
|
|
208
|
+
lookupUser(q: UserQuery): Promise<PlatformUser | undefined>;
|
|
209
|
+
readonly conversationStore: ConversationStore;
|
|
210
|
+
/**
|
|
211
|
+
* Optional persistence backend supplied by the adapter. `createBot` uses it
|
|
212
|
+
* only when no explicit `store.adapter` is configured; if more than one
|
|
213
|
+
* adapter provides one, `createBot` warns and uses the first. Distinct from
|
|
214
|
+
* {@link conversationStore}.
|
|
215
|
+
*/
|
|
216
|
+
readonly stateStore?: StateStore;
|
|
217
|
+
/** @internal Marks the managed adapter; bot core uses it for the V1 exclusivity guard. */
|
|
218
|
+
readonly __managed?: boolean;
|
|
219
|
+
/**
|
|
220
|
+
* When true, bot core skips its ingress dedup for events from this adapter.
|
|
221
|
+
* Set by at-least-once transports (managed delivery) that enforce
|
|
222
|
+
* idempotency at egress instead — dropping a redelivery at ingress would lose
|
|
223
|
+
* a legitimate retry.
|
|
224
|
+
*/
|
|
225
|
+
readonly skipIngressDedup?: boolean;
|
|
226
|
+
/**
|
|
227
|
+
* Optional conversation-history read. Backs the capability-gated
|
|
228
|
+
* `Thread.getMessages()`; adapters that can't read history simply omit this,
|
|
229
|
+
* and `Thread.getMessages()` returns `[]`.
|
|
230
|
+
*/
|
|
231
|
+
getMessages?(target: ReplyTarget): Promise<ThreadMessage[]>;
|
|
232
|
+
/**
|
|
233
|
+
* Optional platform file upload. Threads expose `postFile` unconditionally;
|
|
234
|
+
* adapters that can't upload simply omit this, and `Thread.postFile` returns
|
|
235
|
+
* a capability-gated `{ ok: false, error }`.
|
|
236
|
+
*/
|
|
237
|
+
postFile?(target: ReplyTarget, args: {
|
|
238
|
+
bytes: Uint8Array;
|
|
239
|
+
filename: string;
|
|
240
|
+
title?: string;
|
|
241
|
+
altText?: string;
|
|
242
|
+
}): Promise<{
|
|
243
|
+
ok: boolean;
|
|
244
|
+
fileId?: string;
|
|
245
|
+
error?: string;
|
|
246
|
+
}>;
|
|
247
|
+
/**
|
|
248
|
+
* Optional slash-command support. Called once on `start()` with the bot's
|
|
249
|
+
* declared commands, so a surface that registers commands up front (e.g.
|
|
250
|
+
* Discord's application-command API) can publish them. Surfaces that match
|
|
251
|
+
* commands dynamically (e.g. Slack, which forwards every `/command` to
|
|
252
|
+
* `sink.onCommand`) need not implement this; adapters that don't support
|
|
253
|
+
* commands at all simply omit it and command handlers never fire there.
|
|
254
|
+
*/
|
|
255
|
+
registerCommands?(commands: readonly CommandSpec[]): void | Promise<void>;
|
|
256
|
+
/**
|
|
257
|
+
* Optional: pin suggested prompts on a conversation surface (backs the
|
|
258
|
+
* capability-gated `Thread.setSuggestedPrompts`). Adapters without the
|
|
259
|
+
* concept omit this, and `Thread.setSuggestedPrompts` returns
|
|
260
|
+
* `{ ok: false, error }` without throwing.
|
|
261
|
+
*/
|
|
262
|
+
setSuggestedPrompts?(target: ReplyTarget, prompts: ReadonlyArray<{
|
|
263
|
+
title: string;
|
|
264
|
+
message: string;
|
|
265
|
+
}>, opts?: {
|
|
266
|
+
title?: string;
|
|
267
|
+
}): Promise<{
|
|
268
|
+
ok: boolean;
|
|
269
|
+
error?: string;
|
|
270
|
+
}>;
|
|
271
|
+
/**
|
|
272
|
+
* Optional: set the conversation's display title (backs `Thread.setTitle`).
|
|
273
|
+
* Adapters without the concept omit this, and `Thread.setTitle` returns
|
|
274
|
+
* `{ ok: false, error }` without throwing.
|
|
275
|
+
*/
|
|
276
|
+
setThreadTitle?(target: ReplyTarget, title: string): Promise<{
|
|
277
|
+
ok: boolean;
|
|
278
|
+
error?: string;
|
|
279
|
+
}>;
|
|
280
|
+
/**
|
|
281
|
+
* Optional reactions egress (backs `Thread.react`/`unreact`). Adapters without
|
|
282
|
+
* reactions omit these; the Thread methods then return `{ ok: false, error }`.
|
|
283
|
+
*/
|
|
284
|
+
addReaction?(target: ReplyTarget, messageRef: MessageRef, emoji: EmojiValue): Promise<{
|
|
285
|
+
ok: boolean;
|
|
286
|
+
error?: string;
|
|
287
|
+
}>;
|
|
288
|
+
removeReaction?(target: ReplyTarget, messageRef: MessageRef, emoji: EmojiValue): Promise<{
|
|
289
|
+
ok: boolean;
|
|
290
|
+
error?: string;
|
|
291
|
+
}>;
|
|
292
|
+
/**
|
|
293
|
+
* Optional ephemeral post (backs `Thread.postEphemeral`). The adapter decides
|
|
294
|
+
* native vs DM fallback based on `opts.fallbackToDM` and returns
|
|
295
|
+
* `{ ok, usedFallback }` or `null` (native unsupported and no fallback).
|
|
296
|
+
*/
|
|
297
|
+
postEphemeral?(target: ReplyTarget, user: PlatformUser | string, ir: BotNode[], opts: {
|
|
298
|
+
fallbackToDM: boolean;
|
|
299
|
+
}): Promise<EphemeralResult | null>;
|
|
300
|
+
/** Optional modal render (pure; backs `openModal`). Throws `ModalRenderError` on unsupported elements. */
|
|
301
|
+
renderModal?(ir: BotNode[]): NativePayload;
|
|
302
|
+
/**
|
|
303
|
+
* Optional modal open (backs context `openModal`). Renders `ir` and opens it
|
|
304
|
+
* against the platform `triggerId`. Returns `{ ok: false }` on failure
|
|
305
|
+
* (expired trigger, unsupported elements) — never throws.
|
|
306
|
+
*/
|
|
307
|
+
openModal?(target: ReplyTarget, triggerId: string, ir: BotNode[]): Promise<{
|
|
308
|
+
ok: boolean;
|
|
309
|
+
error?: string;
|
|
310
|
+
}>;
|
|
311
|
+
}
|
|
312
|
+
//# sourceMappingURL=platform-adapter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"platform-adapter.d.ts","sourceRoot":"","sources":["../src/platform-adapter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AACpE,OAAO,KAAK,EACV,gBAAgB,EAChB,OAAO,EACP,UAAU,EACV,eAAe,EACf,UAAU,EACV,YAAY,EACZ,aAAa,EACd,MAAM,yBAAyB,CAAC;AACjC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AACjD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AAEzD,+GAA+G;AAC/G,MAAM,MAAM,WAAW,GAAG,OAAO,CAAC;AAClC,+DAA+D;AAC/D,MAAM,MAAM,aAAa,GAAG,OAAO,CAAC;AAEpC,MAAM,WAAW,mBAAmB;IAClC,cAAc,EAAE,OAAO,CAAC;IACxB,cAAc,EAAE,OAAO,CAAC;IACxB,iBAAiB,EAAE,OAAO,CAAC;IAC3B,iBAAiB,EAAE,OAAO,CAAC;IAC3B,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,4EAA4E;IAC5E,wBAAwB,CAAC,EAAE,OAAO,CAAC;IACnC,8DAA8D;IAC9D,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B,kGAAkG;IAClG,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,CAAC,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;CACtB;AAED,MAAM,WAAW,gBAAgB;IAC/B,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACvC;AACD,MAAM,WAAW,iBAAiB;IAChC,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,OAAO,CAAC;CAChB;AAED,4HAA4H;AAC5H,MAAM,WAAW,WAAW;IAC1B,UAAU,EAAE,eAAe,CAAC;IAC5B,eAAe,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACjC,oBAAoB,IAAI,SAAS,gBAAgB,EAAE,CAAC;IACpD,mBAAmB,IAAI,iBAAiB,GAAG,SAAS,CAAC;IACrD,qBAAqB,IAAI,IAAI,CAAC;IAC9B;;;;;;;;OAQG;IACH,MAAM,CAAC,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CAC1B;AAED;;;;GAIG;AACH,MAAM,WAAW,gBAAgB;IAC/B,eAAe,EAAE,MAAM,CAAC;IACxB,WAAW,EAAE,WAAW,CAAC;IACzB,IAAI,CAAC,EAAE,YAAY,CAAC;CACrB;AAED;;;GAGG;AACH,MAAM,WAAW,UAAU;IACzB,oFAAoF;IACpF,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,8EAA8E;IAC9E,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,6EAA6E;IAC7E,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,YAAa,SAAQ,gBAAgB,EAAE,UAAU;IAChE,QAAQ,EAAE,MAAM,CAAC;IACjB;;;OAGG;IACH,YAAY,CAAC,EAAE,gBAAgB,EAAE,CAAC;IAClC,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,gBAAiB,SAAQ,gBAAgB,EAAE,UAAU;IACpE,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,gGAAgG;IAChG,UAAU,CAAC,EAAE,UAAU,CAAC;IACxB,gGAAgG;IAChG,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,2DAA2D;AAC3D,MAAM,WAAW,eAAgB,SAAQ,gBAAgB,EAAE,UAAU;IACnE,uFAAuF;IACvF,OAAO,EAAE,MAAM,CAAC;IAChB,wFAAwF;IACxF,IAAI,EAAE,MAAM,CAAC;IACb,oFAAoF;IACpF,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACrC,QAAQ,EAAE,MAAM,CAAC;IACjB,gGAAgG;IAChG,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;GAGG;AACH,MAAM,WAAW,mBAAoB,SAAQ,gBAAgB;IAC3D,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,kGAAkG;AAClG,MAAM,WAAW,gBAAiB,SAAQ,gBAAgB;IACxD,8EAA8E;IAC9E,QAAQ,EAAE,MAAM,CAAC;IACjB,qCAAqC;IACrC,KAAK,EAAE,OAAO,CAAC;IACf,oCAAoC;IACpC,SAAS,EAAE,MAAM,CAAC;IAClB;;;;;OAKG;IACH,UAAU,CAAC,EAAE,UAAU,CAAC;IACxB,yEAAyE;IACzE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,sBAAsB;IACtB,GAAG,EAAE,OAAO,CAAC;CACd;AAED,iEAAiE;AACjE,MAAM,WAAW,mBAAmB;IAClC,UAAU,EAAE,MAAM,CAAC;IACnB,mEAAmE;IACnE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAChC,IAAI,CAAC,EAAE,YAAY,CAAC;IACpB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,qGAAqG;IACrG,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B,QAAQ,EAAE,MAAM,CAAC;IACjB,GAAG,EAAE,OAAO,CAAC;CACd;AAED,yEAAyE;AACzE,MAAM,WAAW,kBAAkB;IACjC,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,YAAY,CAAC;IACpB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,oGAAoG;IACpG,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B,QAAQ,EAAE,MAAM,CAAC;IACjB,GAAG,EAAE,OAAO,CAAC;CACd;AAED,qFAAqF;AACrF,MAAM,WAAW,iBAAiB;IAChC,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACjC;AAED,MAAM,WAAW,WAAW;IAC1B,MAAM,CAAC,IAAI,EAAE,YAAY,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACjD,aAAa,CAAC,GAAG,EAAE,gBAAgB,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC3D,+FAA+F;IAC/F,SAAS,CAAC,GAAG,EAAE,eAAe,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACtD,iFAAiF;IACjF,eAAe,CAAC,GAAG,EAAE,mBAAmB,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAChE,yFAAyF;IACzF,UAAU,CAAC,GAAG,EAAE,gBAAgB,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACxD;;;;OAIG;IACH,aAAa,CAAC,GAAG,EAAE,mBAAmB,GAAG,OAAO,CAAC,iBAAiB,GAAG,IAAI,CAAC,CAAC;IAC3E,2EAA2E;IAC3E,YAAY,CAAC,GAAG,EAAE,kBAAkB,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC7D;AAED,MAAM,WAAW,SAAS;IACxB,KAAK,EAAE,MAAM,CAAC;CACf;AAED,kHAAkH;AAClH,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,aAAa,CAAC;CACtB;AAED,gHAAgH;AAChH,MAAM,WAAW,iBAAiB;IAChC,WAAW,CACT,eAAe,EAAE,MAAM,EACvB,WAAW,EAAE,WAAW,EACxB,SAAS,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,aAAa,GAC7C,OAAO,CAAC,YAAY,CAAC,CAAC;CAC1B;AAED;;;;;GAKG;AACH,MAAM,WAAW,mBAAmB;IAClC,iEAAiE;IACjE,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,YAAY,EAAE,mBAAmB,CAAC;IAC3C,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,KAAK,CAAC,IAAI,EAAE,WAAW,EAAE,GAAG,CAAC,EAAE,mBAAmB,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACnE,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACtB,MAAM,CAAC,EAAE,EAAE,OAAO,EAAE,GAAG,aAAa,CAAC;IACrC,IAAI,CAAC,MAAM,EAAE,WAAW,EAAE,EAAE,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;IAC9D,MAAM,CAAC,GAAG,EAAE,UAAU,EAAE,EAAE,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACtD,MAAM,CACJ,MAAM,EAAE,WAAW,EACnB,MAAM,EAAE,aAAa,CAAC,MAAM,CAAC,GAC5B,OAAO,CAAC,UAAU,CAAC,CAAC;IACvB,MAAM,CAAC,GAAG,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACvC,iBAAiB,CAAC,MAAM,EAAE,WAAW,GAAG,WAAW,CAAC;IACpD,iBAAiB,CAAC,GAAG,EAAE,OAAO,GAAG,gBAAgB,GAAG,SAAS,CAAC;IAC9D,UAAU,CAAC,CAAC,EAAE,SAAS,GAAG,OAAO,CAAC,YAAY,GAAG,SAAS,CAAC,CAAC;IAC5D,QAAQ,CAAC,iBAAiB,EAAE,iBAAiB,CAAC;IAC9C;;;;;OAKG;IACH,QAAQ,CAAC,UAAU,CAAC,EAAE,UAAU,CAAC;IACjC,0FAA0F;IAC1F,QAAQ,CAAC,SAAS,CAAC,EAAE,OAAO,CAAC;IAC7B;;;;;OAKG;IACH,QAAQ,CAAC,gBAAgB,CAAC,EAAE,OAAO,CAAC;IACpC;;;;OAIG;IACH,WAAW,CAAC,CAAC,MAAM,EAAE,WAAW,GAAG,OAAO,CAAC,aAAa,EAAE,CAAC,CAAC;IAC5D;;;;OAIG;IACH,QAAQ,CAAC,CACP,MAAM,EAAE,WAAW,EACnB,IAAI,EAAE;QACJ,KAAK,EAAE,UAAU,CAAC;QAClB,QAAQ,EAAE,MAAM,CAAC;QACjB,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,OAAO,CAAC,EAAE,MAAM,CAAC;KAClB,GACA,OAAO,CAAC;QAAE,EAAE,EAAE,OAAO,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC7D;;;;;;;OAOG;IACH,gBAAgB,CAAC,CAAC,QAAQ,EAAE,SAAS,WAAW,EAAE,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC1E;;;;;OAKG;IACH,mBAAmB,CAAC,CAClB,MAAM,EAAE,WAAW,EACnB,OAAO,EAAE,aAAa,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC,EAC1D,IAAI,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,GACxB,OAAO,CAAC;QAAE,EAAE,EAAE,OAAO,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC5C;;;;OAIG;IACH,cAAc,CAAC,CACb,MAAM,EAAE,WAAW,EACnB,KAAK,EAAE,MAAM,GACZ,OAAO,CAAC;QAAE,EAAE,EAAE,OAAO,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC5C;;;OAGG;IACH,WAAW,CAAC,CACV,MAAM,EAAE,WAAW,EACnB,UAAU,EAAE,UAAU,EACtB,KAAK,EAAE,UAAU,GAChB,OAAO,CAAC;QAAE,EAAE,EAAE,OAAO,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC5C,cAAc,CAAC,CACb,MAAM,EAAE,WAAW,EACnB,UAAU,EAAE,UAAU,EACtB,KAAK,EAAE,UAAU,GAChB,OAAO,CAAC;QAAE,EAAE,EAAE,OAAO,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC5C;;;;OAIG;IACH,aAAa,CAAC,CACZ,MAAM,EAAE,WAAW,EACnB,IAAI,EAAE,YAAY,GAAG,MAAM,EAC3B,EAAE,EAAE,OAAO,EAAE,EACb,IAAI,EAAE;QAAE,YAAY,EAAE,OAAO,CAAA;KAAE,GAC9B,OAAO,CAAC,eAAe,GAAG,IAAI,CAAC,CAAC;IACnC,0GAA0G;IAC1G,WAAW,CAAC,CAAC,EAAE,EAAE,OAAO,EAAE,GAAG,aAAa,CAAC;IAC3C;;;;OAIG;IACH,SAAS,CAAC,CACR,MAAM,EAAE,WAAW,EACnB,SAAS,EAAE,MAAM,EACjB,EAAE,EAAE,OAAO,EAAE,GACZ,OAAO,CAAC;QAAE,EAAE,EAAE,OAAO,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CAC7C"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"platform-adapter.test.d.ts","sourceRoot":"","sources":["../src/platform-adapter.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { describe, it, expect } from "vitest";
|
|
2
|
+
import { FakeAdapter } from "./testing/fake-adapter.js";
|
|
3
|
+
describe("FakeAdapter", () => {
|
|
4
|
+
it("records posts and drives ingress", async () => {
|
|
5
|
+
const a = new FakeAdapter();
|
|
6
|
+
let got;
|
|
7
|
+
await a.start({
|
|
8
|
+
onTurn: (t) => {
|
|
9
|
+
got = t.userText;
|
|
10
|
+
},
|
|
11
|
+
onInteraction: () => { },
|
|
12
|
+
onCommand: () => { },
|
|
13
|
+
onThreadStarted: () => { },
|
|
14
|
+
onReaction: () => { },
|
|
15
|
+
onModalSubmit: async () => { },
|
|
16
|
+
onModalClose: () => { },
|
|
17
|
+
});
|
|
18
|
+
a.emitTurn({ userText: "hi" });
|
|
19
|
+
expect(got).toBe("hi");
|
|
20
|
+
await a.post({}, [{ type: "text", props: { value: "x" } }]);
|
|
21
|
+
expect(a.posted.length).toBe(1);
|
|
22
|
+
});
|
|
23
|
+
it("delivers interactions to the sink", async () => {
|
|
24
|
+
const a = new FakeAdapter();
|
|
25
|
+
let id;
|
|
26
|
+
await a.start({
|
|
27
|
+
onTurn: () => { },
|
|
28
|
+
onInteraction: (e) => {
|
|
29
|
+
id = e.id;
|
|
30
|
+
},
|
|
31
|
+
onCommand: () => { },
|
|
32
|
+
onThreadStarted: () => { },
|
|
33
|
+
onReaction: () => { },
|
|
34
|
+
onModalSubmit: async () => { },
|
|
35
|
+
onModalClose: () => { },
|
|
36
|
+
});
|
|
37
|
+
a.emitInteraction({ id: "ck:abc" });
|
|
38
|
+
expect(id).toBe("ck:abc");
|
|
39
|
+
});
|
|
40
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reactions.test.d.ts","sourceRoot":"","sources":["../src/reactions.test.ts"],"names":[],"mappings":""}
|