@finalai/final-agent-provider 0.2.2 → 0.3.1

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 (29) hide show
  1. package/dist/modules/channel-factories.d.mts +3 -1
  2. package/dist/modules/channel-factories.mjs +32 -18
  3. package/dist/modules/channel-factories.mjs.map +2 -2
  4. package/dist/modules/channels/address-context.mjs +16 -53
  5. package/dist/modules/channels/address-context.mjs.map +3 -3
  6. package/dist/modules/channels/agent-events.d.mts +3 -29
  7. package/dist/modules/channels/agent-events.mjs +67 -146
  8. package/dist/modules/channels/agent-events.mjs.map +3 -3
  9. package/dist/modules/channels/agent-schedules.d.mts +1 -0
  10. package/dist/modules/channels/agent-schedules.mjs +18 -19
  11. package/dist/modules/channels/agent-schedules.mjs.map +2 -2
  12. package/dist/modules/channels/delivery.d.mts +1 -1
  13. package/dist/modules/channels/delivery.mjs +5 -23
  14. package/dist/modules/channels/delivery.mjs.map +2 -2
  15. package/dist/modules/channels/fake-platform.d.mts +6 -1
  16. package/dist/modules/channels/fake-platform.mjs +31 -12
  17. package/dist/modules/channels/fake-platform.mjs.map +2 -2
  18. package/dist/modules/channels/index.d.mts +1 -0
  19. package/dist/modules/channels/index.mjs +1 -0
  20. package/dist/modules/channels/index.mjs.map +2 -2
  21. package/dist/modules/channels/prompt.d.mts +19 -2
  22. package/dist/modules/channels/prompt.mjs +44 -17
  23. package/dist/modules/channels/prompt.mjs.map +2 -2
  24. package/dist/modules/channels/routing.mjs +1 -15
  25. package/dist/modules/channels/routing.mjs.map +2 -2
  26. package/dist/modules/channels/service-input.d.mts +22 -0
  27. package/dist/modules/channels/service-input.mjs +32 -0
  28. package/dist/modules/channels/service-input.mjs.map +7 -0
  29. package/package.json +5 -5
@@ -2,15 +2,13 @@ import {
2
2
  Delivery,
3
3
  ParticipantKind,
4
4
  RoutingMode,
5
- SystemParticipantKind,
6
5
  TurnPolicy
7
6
  } from "@finalai/agent-provider";
8
7
  import * as z from "zod";
9
8
  import {
10
9
  authorPrefixedContent,
11
- buildCatchUpBlock,
12
10
  buildPromptContent,
13
- CatchUpSince,
11
+ catchUpFor,
14
12
  excerpt,
15
13
  finalAuthorOf,
16
14
  finalContextOf,
@@ -23,10 +21,8 @@ import { MAX_AGENT_HOP_DEPTH } from "./routing.mjs";
23
21
  const thrownMessageSchema = z.object({ message: z.string() });
24
22
  const CONTEXT_WINDOW_MESSAGES = 50;
25
23
  const effectiveTurnPolicy = (args) => args.conversation === TurnPolicy.Queue ? TurnPolicy.Queue : args.channel;
26
- const humanAudience = (participants) => participants.filter(
27
- (participant) => !participant.left && (participant.kind === ParticipantKind.User || participant.systemKind === SystemParticipantKind.ApiKey)
28
- ).map((participant) => participant.id);
29
- const audienceFor = (author, participants) => author?.kind === ParticipantKind.User || author?.kind === ParticipantKind.System && author.systemKind === SystemParticipantKind.ApiKey ? [author.id] : humanAudience(participants);
24
+ const humanAudience = (participants) => participants.filter((participant) => !participant.left && participant.kind === ParticipantKind.User).map((participant) => participant.id);
25
+ const audienceFor = (author, participants) => author?.kind === ParticipantKind.User ? [author.id] : humanAudience(participants);
30
26
  const replyContextFor = async (args) => {
31
27
  const byId = new Map(args.earlier.map((message) => [message.messageId, message]));
32
28
  const referenced = [
@@ -57,18 +53,6 @@ const replyContextFor = async (args) => {
57
53
  })
58
54
  };
59
55
  };
60
- const catchUpFor = (args) => {
61
- const since = args.recipient.sessionId == null ? CatchUpSince.Start : args.recipient.routingMode === RoutingMode.Mention ? CatchUpSince.LastContact : null;
62
- if (since == null) {
63
- return null;
64
- }
65
- return buildCatchUpBlock({
66
- messages: args.earlier,
67
- participants: args.participants,
68
- agentParticipantId: args.recipient.id,
69
- since
70
- });
71
- };
72
56
  const deliveryIdempotencyKey = (messageId, participantId) => `${messageId}:${participantId}`;
73
57
  const deliverMessage = async (args) => {
74
58
  const { platform, conversation, message } = args;
@@ -110,7 +94,6 @@ const deliverMessage = async (args) => {
110
94
  displayName: "Someone",
111
95
  userId: null,
112
96
  definitionId: null,
113
- systemKind: null,
114
97
  routingMode: null,
115
98
  sessionId: null,
116
99
  supportsObserve: null,
@@ -196,7 +179,7 @@ const observeNotice = async (args) => {
196
179
  try {
197
180
  await args.platform.sessions.observe({
198
181
  participantId: recipient.id,
199
- content: [systemNoticeBlock({ text: args.text, participantId: args.sourceParticipantId })],
182
+ content: [systemNoticeBlock({ text: args.text })],
200
183
  idempotencyKey: `${args.idempotencyKey}:${recipient.id}`
201
184
  });
202
185
  delivered.push(recipient.id);
@@ -225,7 +208,6 @@ const reactionNotice = async (args) => {
225
208
  platform: args.platform,
226
209
  recipients: [author],
227
210
  text: `${reactor.displayName} reacted ${args.emoji} to ${target}`,
228
- sourceParticipantId: reactor.id,
229
211
  idempotencyKey: args.eventId == null ? reactionId : `${reactionId}:${args.eventId}`
230
212
  });
231
213
  };
@@ -243,7 +225,6 @@ const membershipNotice = async (args) => {
243
225
  platform: args.platform,
244
226
  recipients,
245
227
  text: `${args.subject.displayName} ${verb} the conversation`,
246
- sourceParticipantId: args.subject.id,
247
228
  idempotencyKey: args.idempotencyKey
248
229
  });
249
230
  };
@@ -254,6 +235,7 @@ export {
254
235
  deliverMessage,
255
236
  deliveryIdempotencyKey,
256
237
  effectiveTurnPolicy,
238
+ humanAudience,
257
239
  membershipNotice,
258
240
  observeNotice,
259
241
  reactionNotice
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../src/channels/delivery.ts"],
4
- "sourcesContent": ["import type { ContentBlock } from '@agentclientprotocol/sdk/experimental/v2';\nimport {\n Delivery,\n ParticipantKind,\n RoutingMode,\n SystemParticipantKind,\n TurnPolicy,\n type ChannelPlatformIface,\n type ConversationIface,\n type ConversationMessageIface,\n type ParticipantIface,\n type RouteArgsIface,\n type RouteDecisionIface,\n} from '@finalai/agent-provider';\nimport * as z from 'zod';\nimport {\n authorPrefixedContent,\n buildCatchUpBlock,\n buildPromptContent,\n CatchUpSince,\n excerpt,\n finalAuthorOf,\n finalContextOf,\n messageRefOf,\n messageSummary,\n renderReplyContext,\n systemNoticeBlock,\n type ReplyContextArgsIface,\n} from \"./prompt.mjs\";\nimport { MAX_AGENT_HOP_DEPTH } from \"./routing.mjs\";\n\n// How a channel hands a conversation message to its agents: route, then build\n// each recipient's ACP content and call prompt or observe. Prompt construction,\n// not orchestration.\n\nconst thrownMessageSchema = z.object({ message: z.string() });\n\nexport const CONTEXT_WINDOW_MESSAGES = 50;\n\nexport interface DeliveryOutcomeIface {\n participantId: string;\n delivery: Delivery;\n // What actually happened: an observe can fall back to a silent prompt, or be\n // skipped for an agent with no session yet (its first prompt catches up).\n sent: 'prompt' | 'observe' | 'silent-prompt' | 'skipped' | 'failed';\n messageId: string | null;\n error: string | null;\n}\n\nexport interface DeliverMessageArgsIface {\n platform: ChannelPlatformIface;\n // A channel's pure route(), or a bundle channel's run in its isolate.\n route: (args: RouteArgsIface) => RouteDecisionIface[] | Promise<RouteDecisionIface[]>;\n conversation: ConversationIface;\n message: ConversationMessageIface;\n participants?: ParticipantIface[];\n // The delivering channel's turnPolicy.\n turnPolicy: TurnPolicy;\n}\n\n// A channel's policy applies unless the conversation is set to\n// queue, the per-conversation override.\nexport const effectiveTurnPolicy = (args: {\n channel: TurnPolicy;\n conversation: TurnPolicy;\n}): TurnPolicy => (args.conversation === TurnPolicy.Queue ? TurnPolicy.Queue : args.channel);\n\nconst humanAudience = (participants: ParticipantIface[]): string[] =>\n participants\n .filter(\n (participant) =>\n !participant.left &&\n (participant.kind === ParticipantKind.User ||\n participant.systemKind === SystemParticipantKind.ApiKey),\n )\n .map((participant) => participant.id);\n\n// A user or API-key author answers its own prompt; other sources use the room\u2019s answering actors.\nexport const audienceFor = (\n author: ParticipantIface | null,\n participants: ParticipantIface[],\n): string[] =>\n author?.kind === ParticipantKind.User ||\n (author?.kind === ParticipantKind.System && author.systemKind === SystemParticipantKind.ApiKey)\n ? [author.id]\n : humanAudience(participants);\n\n// Reply, thread and quote context. A referenced message outside the\n// recent window is read by id, however old.\nconst replyContextFor = async (args: {\n platform: ChannelPlatformIface;\n message: ConversationMessageIface;\n earlier: ConversationMessageIface[];\n participants: ParticipantIface[];\n}): Promise<ReplyContextArgsIface> => {\n const byId = new Map(args.earlier.map((message) => [message.messageId, message]));\n const referenced = [\n args.message.replyToMessageId,\n args.message.threadRootId,\n ...args.message.quotedMessageIds,\n ].flatMap((id) => (id == null || byId.has(id) ? [] : [id]));\n if (referenced.length > 0) {\n const found = await args.platform.conversations.getMessages({\n conversationId: args.message.conversationId,\n messageIds: [...new Set(referenced)],\n });\n for (const message of found) byId.set(message.messageId, message);\n }\n const replyTo =\n args.message.replyToMessageId == null\n ? null\n : (byId.get(args.message.replyToMessageId) ?? null);\n const root =\n args.message.threadRootId == null ? null : (byId.get(args.message.threadRootId) ?? null);\n const rootAuthor =\n root == null\n ? null\n : args.participants.find((participant) => participant.id === root.authorParticipantId);\n return {\n replyTo:\n replyTo == null || replyTo.messageId === root?.messageId\n ? null\n : messageRefOf(replyTo, args.participants),\n thread:\n args.message.threadRootId == null\n ? null\n : {\n rootMessageId: args.message.threadRootId,\n rootExcerpt: root == null ? '' : excerpt(messageSummary(root.content)),\n rootAuthor: rootAuthor == null ? null : finalAuthorOf(rootAuthor),\n },\n quotes: args.message.quotedMessageIds.flatMap((id) => {\n const quoted = byId.get(id);\n return quoted == null ? [] : [messageRefOf(quoted, args.participants)];\n }),\n };\n};\n\nconst catchUpFor = (args: {\n recipient: ParticipantIface;\n earlier: ConversationMessageIface[];\n participants: ParticipantIface[];\n}): ContentBlock | null => {\n // A fresh session has seen nothing; a Mention agent sees only what it is\n // prompted with; everyone else has been observing.\n const since =\n args.recipient.sessionId == null\n ? CatchUpSince.Start\n : args.recipient.routingMode === RoutingMode.Mention\n ? CatchUpSince.LastContact\n : null;\n if (since == null) {\n return null;\n }\n return buildCatchUpBlock({\n messages: args.earlier,\n participants: args.participants,\n agentParticipantId: args.recipient.id,\n since,\n });\n};\n\nexport const deliveryIdempotencyKey = (messageId: string, participantId: string): string =>\n `${messageId}:${participantId}`;\n\nexport const deliverMessage = async (\n args: DeliverMessageArgsIface,\n): Promise<DeliveryOutcomeIface[]> => {\n const { platform, conversation, message } = args;\n const participants =\n args.participants ?? (await platform.conversations.participants(conversation.conversationId));\n const decisions = await args.route({ conversation, message, participants });\n const author =\n participants.find((participant) => participant.id === message.authorParticipantId) ?? null;\n for (const participant of participants) {\n if (participant.kind !== ParticipantKind.Agent) continue;\n const decision = decisions.find((candidate) => candidate.participantId === participant.id);\n platform.log('channel route decision', {\n observed_at: new Date().toISOString(),\n organization_id: conversation.organizationId,\n conversation_id: conversation.conversationId,\n conversation_kind: conversation.kind,\n message_id: message.messageId,\n author_kind: author?.kind ?? '',\n participant_id: participant.id,\n routing_mode: participant.routingMode ?? '',\n delivery: decision?.delivery ?? 'skipped',\n reason: participant.left\n ? 'left conversation'\n : participant.id === message.authorParticipantId\n ? 'author'\n : decision == null\n ? 'not selected by route'\n : 'selected by route',\n hop_depth: message.hopDepth,\n });\n }\n if (decisions.length === 0) return [];\n const earlier = await platform.conversations.recentMessages({\n conversationId: conversation.conversationId,\n limit: CONTEXT_WINDOW_MESSAGES,\n beforeSeq: message.seq,\n });\n const replyContext = await replyContextFor({ platform, message, earlier, participants });\n const turnPolicy = effectiveTurnPolicy({\n channel: args.turnPolicy,\n conversation: conversation.turnPolicy,\n });\n const audience = audienceFor(author, participants);\n const authorParticipant: ParticipantIface = author ?? {\n id: message.authorParticipantId,\n kind: ParticipantKind.User,\n displayName: 'Someone',\n userId: null,\n definitionId: null,\n systemKind: null,\n routingMode: null,\n sessionId: null,\n supportsObserve: null,\n rendersAuthorMeta: null,\n left: true,\n };\n\n const deliverOne = async (decision: RouteDecisionIface): Promise<DeliveryOutcomeIface> => {\n const recipient = participants.find((participant) => participant.id === decision.participantId);\n const base = { participantId: decision.participantId, delivery: decision.delivery };\n if (recipient == null) {\n return { ...base, sent: 'skipped', messageId: null, error: null };\n }\n const idempotencyKey = deliveryIdempotencyKey(message.messageId, recipient.id);\n const prompt = async (content: ContentBlock[], replyExpected: boolean): Promise<string> => {\n const result = await platform.sessions.prompt({\n participantId: recipient.id,\n content,\n turnPolicy,\n replyExpected,\n idempotencyKey,\n authorParticipantId: message.authorParticipantId,\n audienceParticipantIds: audience,\n sourceMessageId: message.messageId,\n });\n return result.messageId;\n };\n try {\n if (decision.delivery === Delivery.Prompt) {\n const content = buildPromptContent({\n message,\n author: authorParticipant,\n recipient,\n replyContext,\n catchUp: catchUpFor({ recipient, earlier, participants }),\n });\n return { ...base, sent: 'prompt', messageId: await prompt(content, true), error: null };\n }\n if (recipient.sessionId == null) {\n return { ...base, sent: 'skipped', messageId: null, error: null };\n }\n const contextBlock = renderReplyContext(replyContext);\n const content = [\n ...(contextBlock == null ? [] : [contextBlock]),\n ...authorPrefixedContent({\n content: message.content,\n author: finalAuthorOf(authorParticipant),\n rendersAuthorMeta: recipient.rendersAuthorMeta ?? false,\n context: finalContextOf(replyContext),\n }),\n ];\n if (recipient.supportsObserve === false) {\n if (message.hopDepth >= MAX_AGENT_HOP_DEPTH) {\n return { ...base, sent: 'skipped', messageId: null, error: null };\n }\n return {\n ...base,\n sent: 'silent-prompt',\n messageId: await prompt(content, false),\n error: null,\n };\n }\n await platform.sessions.observe({ participantId: recipient.id, content, idempotencyKey });\n return { ...base, sent: 'observe', messageId: null, error: null };\n } catch (error) {\n // JSON-RPC failures arrive as plain `{ code, message }` objects.\n const reason =\n error instanceof Error\n ? error.message\n : (thrownMessageSchema.safeParse(error).data?.message ?? String(error));\n platform.log('channel delivery failed', {\n conversationId: conversation.conversationId,\n messageId: message.messageId,\n participantId: recipient.id,\n delivery: decision.delivery,\n error: reason,\n });\n return { ...base, sent: 'failed', messageId: null, error: reason };\n }\n };\n\n return Promise.all(decisions.map(deliverOne));\n};\n\nexport interface ObserveNoticeArgsIface {\n platform: ChannelPlatformIface;\n recipients: ParticipantIface[];\n text: string;\n sourceParticipantId: string;\n idempotencyKey: string;\n}\n\n// System blocks with no model call. Agents without a session skip them (their\n// first prompt catches up); agents without observe support skip them too, since\n// a silent prompt per reaction is not worth a model call.\nexport const observeNotice = async (args: ObserveNoticeArgsIface): Promise<string[]> => {\n const delivered: string[] = [];\n for (const recipient of args.recipients) {\n if (recipient.sessionId == null || recipient.supportsObserve === false || recipient.left)\n continue;\n try {\n await args.platform.sessions.observe({\n participantId: recipient.id,\n content: [systemNoticeBlock({ text: args.text, participantId: args.sourceParticipantId })],\n idempotencyKey: `${args.idempotencyKey}:${recipient.id}`,\n });\n delivered.push(recipient.id);\n } catch (error) {\n args.platform.log('channel notice failed', {\n participantId: recipient.id,\n error: error instanceof Error ? error.message : String(error),\n });\n }\n }\n return delivered;\n};\n\nexport interface ReactionNoticeArgsIface {\n platform: ChannelPlatformIface;\n participants: ParticipantIface[];\n message: ConversationMessageIface;\n // Whether the reacted message is the agent's latest one.\n isLatestOfAuthor: boolean;\n reactorParticipantId: string;\n emoji: string;\n eventId?: string;\n}\n\n// Only the agent whose message was reacted to hears about it.\nexport const reactionNotice = async (args: ReactionNoticeArgsIface): Promise<string[]> => {\n const author = args.participants.find(\n (participant) => participant.id === args.message.authorParticipantId,\n );\n const reactor = args.participants.find(\n (participant) => participant.id === args.reactorParticipantId,\n );\n if (\n author == null ||\n author.kind !== ParticipantKind.Agent ||\n reactor == null ||\n reactor.id === author.id\n ) {\n return [];\n }\n const target = args.isLatestOfAuthor\n ? 'your last message'\n : `your message \"${excerpt(messageSummary(args.message.content), 120)}\"`;\n const reactionId = `reaction:${args.message.messageId}:${reactor.id}:${args.emoji}`;\n return observeNotice({\n platform: args.platform,\n recipients: [author],\n text: `${reactor.displayName} reacted ${args.emoji} to ${target}`,\n sourceParticipantId: reactor.id,\n idempotencyKey: args.eventId == null ? reactionId : `${reactionId}:${args.eventId}`,\n });\n};\n\nexport enum MembershipChange {\n Joined = 'joined',\n Left = 'left',\n}\n\nexport interface MembershipNoticeArgsIface {\n platform: ChannelPlatformIface;\n participants: ParticipantIface[];\n subject: ParticipantIface;\n change: MembershipChange;\n idempotencyKey: string;\n}\n\n// Membership changes reach agents that follow the whole conversation.\nexport const membershipNotice = async (args: MembershipNoticeArgsIface): Promise<string[]> => {\n const recipients = args.participants.filter(\n (participant) =>\n participant.kind === ParticipantKind.Agent &&\n participant.id !== args.subject.id &&\n (participant.routingMode === RoutingMode.All ||\n participant.routingMode === RoutingMode.Default),\n );\n const verb = args.change === MembershipChange.Joined ? 'joined' : 'left';\n return observeNotice({\n platform: args.platform,\n recipients,\n text: `${args.subject.displayName} ${verb} the conversation`,\n sourceParticipantId: args.subject.id,\n idempotencyKey: args.idempotencyKey,\n });\n};\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import type { ContentBlock } from '@agentclientprotocol/sdk/experimental/v2';\nimport {\n Delivery,\n ParticipantKind,\n RoutingMode,\n TurnPolicy,\n type ChannelPlatformIface,\n type ConversationIface,\n type ConversationMessageIface,\n type ParticipantIface,\n type RouteArgsIface,\n type RouteDecisionIface,\n} from '@finalai/agent-provider';\nimport * as z from 'zod';\nimport {\n authorPrefixedContent,\n buildPromptContent,\n catchUpFor,\n excerpt,\n finalAuthorOf,\n finalContextOf,\n messageRefOf,\n messageSummary,\n renderReplyContext,\n systemNoticeBlock,\n type ReplyContextArgsIface,\n} from \"./prompt.mjs\";\nimport { MAX_AGENT_HOP_DEPTH } from \"./routing.mjs\";\n\n// How a channel hands a conversation message to its agents: route, then build\n// each recipient's ACP content and call prompt or observe. Prompt construction,\n// not orchestration.\n\nconst thrownMessageSchema = z.object({ message: z.string() });\n\nexport const CONTEXT_WINDOW_MESSAGES = 50;\n\nexport interface DeliveryOutcomeIface {\n participantId: string;\n delivery: Delivery;\n // What actually happened: an observe can fall back to a silent prompt, or be\n // skipped for an agent with no session yet (its first prompt catches up).\n sent: 'prompt' | 'observe' | 'silent-prompt' | 'skipped' | 'failed';\n messageId: string | null;\n error: string | null;\n}\n\nexport interface DeliverMessageArgsIface {\n platform: ChannelPlatformIface;\n // A channel's pure route(), or a bundle channel's run in its isolate.\n route: (args: RouteArgsIface) => RouteDecisionIface[] | Promise<RouteDecisionIface[]>;\n conversation: ConversationIface;\n message: ConversationMessageIface;\n participants?: ParticipantIface[];\n // The delivering channel's turnPolicy.\n turnPolicy: TurnPolicy;\n}\n\n// A channel's policy applies unless the conversation is set to\n// queue, the per-conversation override.\nexport const effectiveTurnPolicy = (args: {\n channel: TurnPolicy;\n conversation: TurnPolicy;\n}): TurnPolicy => (args.conversation === TurnPolicy.Queue ? TurnPolicy.Queue : args.channel);\n\n// Every person in the room: who may answer what a turn no person prompted asks.\nexport const humanAudience = (participants: ParticipantIface[]): string[] =>\n participants\n .filter((participant) => !participant.left && participant.kind === ParticipantKind.User)\n .map((participant) => participant.id);\n\n// A person answers their own prompt; an agent's prompt is answered by the room's people.\nexport const audienceFor = (\n author: ParticipantIface | null,\n participants: ParticipantIface[],\n): string[] => (author?.kind === ParticipantKind.User ? [author.id] : humanAudience(participants));\n\n// Reply, thread and quote context. A referenced message outside the\n// recent window is read by id, however old.\nconst replyContextFor = async (args: {\n platform: ChannelPlatformIface;\n message: ConversationMessageIface;\n earlier: ConversationMessageIface[];\n participants: ParticipantIface[];\n}): Promise<ReplyContextArgsIface> => {\n const byId = new Map(args.earlier.map((message) => [message.messageId, message]));\n const referenced = [\n args.message.replyToMessageId,\n args.message.threadRootId,\n ...args.message.quotedMessageIds,\n ].flatMap((id) => (id == null || byId.has(id) ? [] : [id]));\n if (referenced.length > 0) {\n const found = await args.platform.conversations.getMessages({\n conversationId: args.message.conversationId,\n messageIds: [...new Set(referenced)],\n });\n for (const message of found) byId.set(message.messageId, message);\n }\n const replyTo =\n args.message.replyToMessageId == null\n ? null\n : (byId.get(args.message.replyToMessageId) ?? null);\n const root =\n args.message.threadRootId == null ? null : (byId.get(args.message.threadRootId) ?? null);\n const rootAuthor =\n root == null\n ? null\n : args.participants.find((participant) => participant.id === root.authorParticipantId);\n return {\n replyTo:\n replyTo == null || replyTo.messageId === root?.messageId\n ? null\n : messageRefOf(replyTo, args.participants),\n thread:\n args.message.threadRootId == null\n ? null\n : {\n rootMessageId: args.message.threadRootId,\n rootExcerpt: root == null ? '' : excerpt(messageSummary(root.content)),\n rootAuthor: rootAuthor == null ? null : finalAuthorOf(rootAuthor),\n },\n quotes: args.message.quotedMessageIds.flatMap((id) => {\n const quoted = byId.get(id);\n return quoted == null ? [] : [messageRefOf(quoted, args.participants)];\n }),\n };\n};\n\nexport const deliveryIdempotencyKey = (messageId: string, participantId: string): string =>\n `${messageId}:${participantId}`;\n\nexport const deliverMessage = async (\n args: DeliverMessageArgsIface,\n): Promise<DeliveryOutcomeIface[]> => {\n const { platform, conversation, message } = args;\n const participants =\n args.participants ?? (await platform.conversations.participants(conversation.conversationId));\n const decisions = await args.route({ conversation, message, participants });\n const author =\n participants.find((participant) => participant.id === message.authorParticipantId) ?? null;\n for (const participant of participants) {\n if (participant.kind !== ParticipantKind.Agent) continue;\n const decision = decisions.find((candidate) => candidate.participantId === participant.id);\n platform.log('channel route decision', {\n observed_at: new Date().toISOString(),\n organization_id: conversation.organizationId,\n conversation_id: conversation.conversationId,\n conversation_kind: conversation.kind,\n message_id: message.messageId,\n author_kind: author?.kind ?? '',\n participant_id: participant.id,\n routing_mode: participant.routingMode ?? '',\n delivery: decision?.delivery ?? 'skipped',\n reason: participant.left\n ? 'left conversation'\n : participant.id === message.authorParticipantId\n ? 'author'\n : decision == null\n ? 'not selected by route'\n : 'selected by route',\n hop_depth: message.hopDepth,\n });\n }\n if (decisions.length === 0) return [];\n const earlier = await platform.conversations.recentMessages({\n conversationId: conversation.conversationId,\n limit: CONTEXT_WINDOW_MESSAGES,\n beforeSeq: message.seq,\n });\n const replyContext = await replyContextFor({ platform, message, earlier, participants });\n const turnPolicy = effectiveTurnPolicy({\n channel: args.turnPolicy,\n conversation: conversation.turnPolicy,\n });\n const audience = audienceFor(author, participants);\n const authorParticipant: ParticipantIface = author ?? {\n id: message.authorParticipantId,\n kind: ParticipantKind.User,\n displayName: 'Someone',\n userId: null,\n definitionId: null,\n routingMode: null,\n sessionId: null,\n supportsObserve: null,\n rendersAuthorMeta: null,\n left: true,\n };\n\n const deliverOne = async (decision: RouteDecisionIface): Promise<DeliveryOutcomeIface> => {\n const recipient = participants.find((participant) => participant.id === decision.participantId);\n const base = { participantId: decision.participantId, delivery: decision.delivery };\n if (recipient == null) {\n return { ...base, sent: 'skipped', messageId: null, error: null };\n }\n const idempotencyKey = deliveryIdempotencyKey(message.messageId, recipient.id);\n const prompt = async (content: ContentBlock[], replyExpected: boolean): Promise<string> => {\n const result = await platform.sessions.prompt({\n participantId: recipient.id,\n content,\n turnPolicy,\n replyExpected,\n idempotencyKey,\n authorParticipantId: message.authorParticipantId,\n audienceParticipantIds: audience,\n sourceMessageId: message.messageId,\n });\n return result.messageId;\n };\n try {\n if (decision.delivery === Delivery.Prompt) {\n const content = buildPromptContent({\n message,\n author: authorParticipant,\n recipient,\n replyContext,\n catchUp: catchUpFor({ recipient, earlier, participants }),\n });\n return { ...base, sent: 'prompt', messageId: await prompt(content, true), error: null };\n }\n if (recipient.sessionId == null) {\n return { ...base, sent: 'skipped', messageId: null, error: null };\n }\n const contextBlock = renderReplyContext(replyContext);\n const content = [\n ...(contextBlock == null ? [] : [contextBlock]),\n ...authorPrefixedContent({\n content: message.content,\n author: finalAuthorOf(authorParticipant),\n rendersAuthorMeta: recipient.rendersAuthorMeta ?? false,\n context: finalContextOf(replyContext),\n }),\n ];\n if (recipient.supportsObserve === false) {\n if (message.hopDepth >= MAX_AGENT_HOP_DEPTH) {\n return { ...base, sent: 'skipped', messageId: null, error: null };\n }\n return {\n ...base,\n sent: 'silent-prompt',\n messageId: await prompt(content, false),\n error: null,\n };\n }\n await platform.sessions.observe({ participantId: recipient.id, content, idempotencyKey });\n return { ...base, sent: 'observe', messageId: null, error: null };\n } catch (error) {\n // JSON-RPC failures arrive as plain `{ code, message }` objects.\n const reason =\n error instanceof Error\n ? error.message\n : (thrownMessageSchema.safeParse(error).data?.message ?? String(error));\n platform.log('channel delivery failed', {\n conversationId: conversation.conversationId,\n messageId: message.messageId,\n participantId: recipient.id,\n delivery: decision.delivery,\n error: reason,\n });\n return { ...base, sent: 'failed', messageId: null, error: reason };\n }\n };\n\n return Promise.all(decisions.map(deliverOne));\n};\n\nexport interface ObserveNoticeArgsIface {\n platform: ChannelPlatformIface;\n recipients: ParticipantIface[];\n text: string;\n idempotencyKey: string;\n}\n\n// System blocks with no model call. Agents without a session skip them (their\n// first prompt catches up); agents without observe support skip them too, since\n// a silent prompt per reaction is not worth a model call.\nexport const observeNotice = async (args: ObserveNoticeArgsIface): Promise<string[]> => {\n const delivered: string[] = [];\n for (const recipient of args.recipients) {\n if (recipient.sessionId == null || recipient.supportsObserve === false || recipient.left)\n continue;\n try {\n await args.platform.sessions.observe({\n participantId: recipient.id,\n content: [systemNoticeBlock({ text: args.text })],\n idempotencyKey: `${args.idempotencyKey}:${recipient.id}`,\n });\n delivered.push(recipient.id);\n } catch (error) {\n args.platform.log('channel notice failed', {\n participantId: recipient.id,\n error: error instanceof Error ? error.message : String(error),\n });\n }\n }\n return delivered;\n};\n\nexport interface ReactionNoticeArgsIface {\n platform: ChannelPlatformIface;\n participants: ParticipantIface[];\n message: ConversationMessageIface;\n // Whether the reacted message is the agent's latest one.\n isLatestOfAuthor: boolean;\n reactorParticipantId: string;\n emoji: string;\n eventId?: string;\n}\n\n// Only the agent whose message was reacted to hears about it.\nexport const reactionNotice = async (args: ReactionNoticeArgsIface): Promise<string[]> => {\n const author = args.participants.find(\n (participant) => participant.id === args.message.authorParticipantId,\n );\n const reactor = args.participants.find(\n (participant) => participant.id === args.reactorParticipantId,\n );\n if (\n author == null ||\n author.kind !== ParticipantKind.Agent ||\n reactor == null ||\n reactor.id === author.id\n ) {\n return [];\n }\n const target = args.isLatestOfAuthor\n ? 'your last message'\n : `your message \"${excerpt(messageSummary(args.message.content), 120)}\"`;\n const reactionId = `reaction:${args.message.messageId}:${reactor.id}:${args.emoji}`;\n return observeNotice({\n platform: args.platform,\n recipients: [author],\n text: `${reactor.displayName} reacted ${args.emoji} to ${target}`,\n idempotencyKey: args.eventId == null ? reactionId : `${reactionId}:${args.eventId}`,\n });\n};\n\nexport enum MembershipChange {\n Joined = 'joined',\n Left = 'left',\n}\n\nexport interface MembershipNoticeArgsIface {\n platform: ChannelPlatformIface;\n participants: ParticipantIface[];\n subject: ParticipantIface;\n change: MembershipChange;\n idempotencyKey: string;\n}\n\n// Membership changes reach agents that follow the whole conversation.\nexport const membershipNotice = async (args: MembershipNoticeArgsIface): Promise<string[]> => {\n const recipients = args.participants.filter(\n (participant) =>\n participant.kind === ParticipantKind.Agent &&\n participant.id !== args.subject.id &&\n (participant.routingMode === RoutingMode.All ||\n participant.routingMode === RoutingMode.Default),\n );\n const verb = args.change === MembershipChange.Joined ? 'joined' : 'left';\n return observeNotice({\n platform: args.platform,\n recipients,\n text: `${args.subject.displayName} ${verb} the conversation`,\n idempotencyKey: args.idempotencyKey,\n });\n};\n"],
5
+ "mappings": "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",
6
6
  "names": ["content", "MembershipChange"]
7
7
  }
@@ -1,4 +1,8 @@
1
- import { ConversationKind, ParticipantKind, TurnPolicy, type ChannelPlatformIface, type ConversationIface, type ConversationMessageIface, type JsonObject, type ObserveArgsIface, type ParticipantIface, type PromptArgsIface } from '@finalai/agent-provider';
1
+ import { ConversationKind, ParticipantKind, TurnPolicy, type ChannelPlatformIface, type ChannelSendInputIface, type ChannelSessionTargetIface, type ConversationIface, type ConversationMessageIface, type JsonObject, type ObserveArgsIface, type ParticipantIface, type PromptArgsIface } from '@finalai/agent-provider';
2
+ export interface FakeInputIface {
3
+ target: ChannelSessionTargetIface;
4
+ input: ChannelSendInputIface;
5
+ }
2
6
  export interface FakeMessageIface extends ConversationMessageIface {
3
7
  final: boolean;
4
8
  updates: number;
@@ -21,6 +25,7 @@ export interface FakePlatformIface {
21
25
  cards: FakeCardIface[];
22
26
  prompts: PromptArgsIface[];
23
27
  observes: ObserveArgsIface[];
28
+ inputs: FakeInputIface[];
24
29
  logs: string[];
25
30
  getMessagesCalls: string[][];
26
31
  addConversation(args: {
@@ -15,6 +15,7 @@ const createFakePlatform = () => {
15
15
  const cards = [];
16
16
  const prompts = [];
17
17
  const observes = [];
18
+ const inputs = [];
18
19
  const logs = [];
19
20
  const getMessagesCalls = [];
20
21
  let nextId = 1;
@@ -36,7 +37,6 @@ const createFakePlatform = () => {
36
37
  displayName: partial.id,
37
38
  userId: null,
38
39
  definitionId: null,
39
- systemKind: null,
40
40
  routingMode: null,
41
41
  sessionId: partial.kind === ParticipantKind.Agent ? `session-${partial.id}` : null,
42
42
  supportsObserve: partial.kind === ParticipantKind.Agent ? true : null,
@@ -70,7 +70,36 @@ const createFakePlatform = () => {
70
70
  messages.push(message);
71
71
  return message;
72
72
  };
73
+ const unsupported = async () => {
74
+ throw new Error("not supported by the fake platform");
75
+ };
73
76
  const platform = {
77
+ channelSessions: {
78
+ send: async (target, input) => {
79
+ const prior = inputs.findIndex(
80
+ (entry) => entry.input.idempotencyKey === input.idempotencyKey
81
+ );
82
+ if (prior < 0) inputs.push({ target, input });
83
+ const agent = target.participantId == null ? null : (participants.get(target.conversationId ?? "") ?? []).find(
84
+ (participant) => participant.id === target.participantId
85
+ );
86
+ return {
87
+ inputId: `input-${prior < 0 ? inputs.length : prior + 1}`,
88
+ sessionId: agent?.sessionId ?? target.sessionId ?? `session-${target.address ?? "room"}`
89
+ };
90
+ },
91
+ inspect: unsupported,
92
+ resolve: unsupported,
93
+ respond: unsupported,
94
+ cancel: unsupported,
95
+ close: unsupported,
96
+ observe: unsupported,
97
+ setConfigOption: unsupported,
98
+ park: unsupported,
99
+ getState: unsupported,
100
+ setState: unsupported,
101
+ handoff: unsupported
102
+ },
74
103
  conversations: {
75
104
  dispatchMessage: async (input) => {
76
105
  const room = conversations.get(input.conversationId);
@@ -91,17 +120,6 @@ const createFakePlatform = () => {
91
120
  },
92
121
  boundTo: async () => null,
93
122
  participants: async (conversationId) => participants.get(conversationId) ?? [],
94
- systemParticipant: async (args) => {
95
- const existing = (participants.get(args.conversationId) ?? []).find(
96
- (participant) => participant.kind === ParticipantKind.System && participant.id === args.sourceRef
97
- );
98
- return existing ?? addParticipant(args.conversationId, {
99
- id: args.sourceRef,
100
- kind: ParticipantKind.System,
101
- systemKind: args.systemKind,
102
- displayName: args.displayName
103
- });
104
- },
105
123
  postMessage: async (args) => {
106
124
  if (args.clientMessageId != null) {
107
125
  const existing = messages.find(
@@ -173,6 +191,7 @@ const createFakePlatform = () => {
173
191
  cards,
174
192
  prompts,
175
193
  observes,
194
+ inputs,
176
195
  logs,
177
196
  getMessagesCalls,
178
197
  addConversation,
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../src/channels/fake-platform.ts"],
4
- "sourcesContent": ["import type { ContentBlock } from '@agentclientprotocol/sdk/experimental/v2';\nimport {\n ConversationKind,\n MessageKind,\n ParticipantKind,\n TurnPolicy,\n type CardArgsIface,\n type ChannelPlatformIface,\n type ConversationIface,\n type ConversationMessageIface,\n type JsonObject,\n type ObserveArgsIface,\n type ParticipantIface,\n type PromptArgsIface,\n} from '@finalai/agent-provider';\nimport { routeToOwner } from \"./agent-events.mjs\";\nimport { deliverMessage } from \"./delivery.mjs\";\nimport { messageSummary } from \"./prompt.mjs\";\nimport { routeMessage } from \"./routing.mjs\";\n\n// An in-memory ChannelPlatformIface for channel tests (not exported from the\n// package index). Records every prompt, observe and visible-message write.\n\nexport interface FakeMessageIface extends ConversationMessageIface {\n final: boolean;\n updates: number;\n source: { turnId: string; fromSeq: number; toSeq: number } | null;\n}\n\nexport interface FakeCardIface {\n messageId: string;\n pendingRequestId: string | null;\n state: JsonObject;\n}\n\nexport interface FakePlatformIface {\n platform: ChannelPlatformIface;\n conversations: Map<string, ConversationIface>;\n participants: Map<string, ParticipantIface[]>;\n messages: FakeMessageIface[];\n cards: FakeCardIface[];\n prompts: PromptArgsIface[];\n observes: ObserveArgsIface[];\n logs: string[];\n // The message ids of each getMessages call.\n getMessagesCalls: string[][];\n addConversation(args: {\n conversationId: string;\n kind: ConversationKind;\n turnPolicy?: TurnPolicy;\n }): ConversationIface;\n addParticipant(\n conversationId: string,\n participant: Partial<ParticipantIface> & { id: string; kind: ParticipantKind },\n ): ParticipantIface;\n}\n\nexport const createFakePlatform = (): FakePlatformIface => {\n const conversations = new Map<string, ConversationIface>();\n const participants = new Map<string, ParticipantIface[]>();\n const messages: FakeMessageIface[] = [];\n const cards: FakeCardIface[] = [];\n const prompts: PromptArgsIface[] = [];\n const observes: ObserveArgsIface[] = [];\n const logs: string[] = [];\n const getMessagesCalls: string[][] = [];\n let nextId = 1;\n\n const addConversation: FakePlatformIface['addConversation'] = (args) => {\n const conversation: ConversationIface = {\n conversationId: args.conversationId,\n organizationId: 'org',\n kind: args.kind,\n title: null,\n isHome: false,\n turnPolicy: args.turnPolicy ?? TurnPolicy.Steer,\n };\n conversations.set(args.conversationId, conversation);\n participants.set(args.conversationId, []);\n return conversation;\n };\n\n const addParticipant: FakePlatformIface['addParticipant'] = (conversationId, partial) => {\n const participant: ParticipantIface = {\n displayName: partial.id,\n userId: null,\n definitionId: null,\n systemKind: null,\n routingMode: null,\n sessionId: partial.kind === ParticipantKind.Agent ? `session-${partial.id}` : null,\n supportsObserve: partial.kind === ParticipantKind.Agent ? true : null,\n rendersAuthorMeta: partial.kind === ParticipantKind.Agent ? true : null,\n left: false,\n ...partial,\n };\n participants.get(conversationId)?.push(participant);\n return participant;\n };\n\n const nextSeq = (conversationId: string): number =>\n messages.filter((message) => message.conversationId === conversationId).length + 1;\n\n const insert = (args: {\n conversationId: string;\n authorParticipantId: string;\n kind: MessageKind;\n content: ContentBlock[];\n replyToMessageId?: string | null;\n threadRootId?: string | null;\n quotedMessageIds?: string[];\n mentionedParticipantIds?: string[];\n hopDepth?: number;\n source?: FakeMessageIface['source'];\n }): FakeMessageIface => {\n const message: FakeMessageIface = {\n messageId: `m${nextId++}`,\n seq: nextSeq(args.conversationId),\n conversationId: args.conversationId,\n authorParticipantId: args.authorParticipantId,\n kind: args.kind,\n body: messageSummary(args.content),\n content: args.content,\n replyToMessageId: args.replyToMessageId ?? null,\n threadRootId: args.threadRootId ?? null,\n quotedMessageIds: args.quotedMessageIds ?? [],\n mentionedParticipantIds: args.mentionedParticipantIds ?? [],\n hopDepth: args.hopDepth ?? 0,\n createdAt: new Date(0).toISOString(),\n final: args.source == null,\n updates: 0,\n source: args.source ?? null,\n };\n messages.push(message);\n return message;\n };\n\n const platform: ChannelPlatformIface = {\n conversations: {\n dispatchMessage: async (input) => {\n const room = conversations.get(input.conversationId);\n const message = messages.find((entry) => entry.messageId === input.messageId);\n if (room == null || message == null) throw new Error('dispatch source missing');\n await deliverMessage({\n platform,\n conversation: room,\n message,\n turnPolicy: room.turnPolicy,\n route: input.participantId == null ? routeMessage : routeToOwner(input.participantId),\n });\n },\n get: async (conversationId) => conversations.get(conversationId) ?? null,\n findOrCreateDirect: async (args) => {\n const id = `direct:${args.userId}:${args.definitionId}`;\n return (\n conversations.get(id) ??\n addConversation({ conversationId: id, kind: ConversationKind.Direct })\n );\n },\n boundTo: async () => null,\n participants: async (conversationId) => participants.get(conversationId) ?? [],\n systemParticipant: async (args) => {\n const existing = (participants.get(args.conversationId) ?? []).find(\n (participant) =>\n participant.kind === ParticipantKind.System && participant.id === args.sourceRef,\n );\n return (\n existing ??\n addParticipant(args.conversationId, {\n id: args.sourceRef,\n kind: ParticipantKind.System,\n systemKind: args.systemKind,\n displayName: args.displayName,\n })\n );\n },\n postMessage: async (args) => {\n if (args.clientMessageId != null) {\n const existing = messages.find(\n (message) =>\n message.conversationId === args.conversationId &&\n message.messageId === args.clientMessageId,\n );\n if (existing != null) return existing;\n }\n return insert({ ...args, kind: args.kind ?? MessageKind.Message });\n },\n updateMessage: async (args) => {\n const message = messages.find((candidate) => candidate.messageId === args.messageId);\n if (message == null) throw new Error(`no message ${args.messageId}`);\n message.content = args.content;\n message.body = messageSummary(args.content);\n message.final = args.final;\n message.updates += 1;\n },\n postCard: async (args: CardArgsIface) => {\n const message = insert({\n conversationId: args.conversationId,\n authorParticipantId: args.authorParticipantId,\n kind: MessageKind.Card,\n content: [],\n });\n cards.push({\n messageId: message.messageId,\n pendingRequestId: args.pendingRequestId,\n state: args.state,\n });\n return message;\n },\n updateCard: async (args) => {\n const card = cards.find(\n (candidate) =>\n candidate.messageId === args.messageId || candidate.pendingRequestId === args.messageId,\n );\n if (card == null) throw new Error(`no card ${args.messageId}`);\n card.state = { ...card.state, ...args.state };\n },\n recentMessages: async (args) =>\n messages\n .filter(\n (message) =>\n message.conversationId === args.conversationId &&\n (args.beforeSeq == null || message.seq < args.beforeSeq) &&\n (args.afterSeq == null || message.seq > args.afterSeq),\n )\n .slice(-args.limit),\n getMessages: async (args) => {\n getMessagesCalls.push(args.messageIds);\n return messages.filter(\n (message) =>\n message.conversationId === args.conversationId &&\n args.messageIds.includes(message.messageId),\n );\n },\n },\n sessions: {\n prompt: async (args) => {\n prompts.push(args);\n return { messageId: `acp-${prompts.length}` };\n },\n observe: async (args) => {\n observes.push(args);\n },\n cancel: async () => {},\n },\n log: (message) => {\n logs.push(message);\n },\n };\n\n return {\n platform,\n conversations,\n participants,\n messages,\n cards,\n prompts,\n observes,\n logs,\n getMessagesCalls,\n addConversation,\n addParticipant,\n };\n};\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import type { ContentBlock } from '@agentclientprotocol/sdk/experimental/v2';\nimport {\n ConversationKind,\n MessageKind,\n ParticipantKind,\n TurnPolicy,\n type CardArgsIface,\n type ChannelPlatformIface,\n type ChannelSendInputIface,\n type ChannelSessionTargetIface,\n type ConversationIface,\n type ConversationMessageIface,\n type JsonObject,\n type ObserveArgsIface,\n type ParticipantIface,\n type PromptArgsIface,\n} from '@finalai/agent-provider';\nimport { routeToOwner } from \"./agent-events.mjs\";\nimport { deliverMessage } from \"./delivery.mjs\";\nimport { messageSummary } from \"./prompt.mjs\";\nimport { routeMessage } from \"./routing.mjs\";\n\n// An in-memory ChannelPlatformIface for channel tests (not exported from the\n// package index). Records every prompt, observe, channel input and\n// visible-message write.\n\nexport interface FakeInputIface {\n target: ChannelSessionTargetIface;\n input: ChannelSendInputIface;\n}\n\nexport interface FakeMessageIface extends ConversationMessageIface {\n final: boolean;\n updates: number;\n source: { turnId: string; fromSeq: number; toSeq: number } | null;\n}\n\nexport interface FakeCardIface {\n messageId: string;\n pendingRequestId: string | null;\n state: JsonObject;\n}\n\nexport interface FakePlatformIface {\n platform: ChannelPlatformIface;\n conversations: Map<string, ConversationIface>;\n participants: Map<string, ParticipantIface[]>;\n messages: FakeMessageIface[];\n cards: FakeCardIface[];\n prompts: PromptArgsIface[];\n observes: ObserveArgsIface[];\n // Channel inputs sent (service input to a room's agent included), in order.\n inputs: FakeInputIface[];\n logs: string[];\n // The message ids of each getMessages call.\n getMessagesCalls: string[][];\n addConversation(args: {\n conversationId: string;\n kind: ConversationKind;\n turnPolicy?: TurnPolicy;\n }): ConversationIface;\n addParticipant(\n conversationId: string,\n participant: Partial<ParticipantIface> & { id: string; kind: ParticipantKind },\n ): ParticipantIface;\n}\n\nexport const createFakePlatform = (): FakePlatformIface => {\n const conversations = new Map<string, ConversationIface>();\n const participants = new Map<string, ParticipantIface[]>();\n const messages: FakeMessageIface[] = [];\n const cards: FakeCardIface[] = [];\n const prompts: PromptArgsIface[] = [];\n const observes: ObserveArgsIface[] = [];\n const inputs: FakeInputIface[] = [];\n const logs: string[] = [];\n const getMessagesCalls: string[][] = [];\n let nextId = 1;\n\n const addConversation: FakePlatformIface['addConversation'] = (args) => {\n const conversation: ConversationIface = {\n conversationId: args.conversationId,\n organizationId: 'org',\n kind: args.kind,\n title: null,\n isHome: false,\n turnPolicy: args.turnPolicy ?? TurnPolicy.Steer,\n };\n conversations.set(args.conversationId, conversation);\n participants.set(args.conversationId, []);\n return conversation;\n };\n\n const addParticipant: FakePlatformIface['addParticipant'] = (conversationId, partial) => {\n const participant: ParticipantIface = {\n displayName: partial.id,\n userId: null,\n definitionId: null,\n routingMode: null,\n sessionId: partial.kind === ParticipantKind.Agent ? `session-${partial.id}` : null,\n supportsObserve: partial.kind === ParticipantKind.Agent ? true : null,\n rendersAuthorMeta: partial.kind === ParticipantKind.Agent ? true : null,\n left: false,\n ...partial,\n };\n participants.get(conversationId)?.push(participant);\n return participant;\n };\n\n const nextSeq = (conversationId: string): number =>\n messages.filter((message) => message.conversationId === conversationId).length + 1;\n\n const insert = (args: {\n conversationId: string;\n authorParticipantId: string;\n kind: MessageKind;\n content: ContentBlock[];\n replyToMessageId?: string | null;\n threadRootId?: string | null;\n quotedMessageIds?: string[];\n mentionedParticipantIds?: string[];\n hopDepth?: number;\n source?: FakeMessageIface['source'];\n }): FakeMessageIface => {\n const message: FakeMessageIface = {\n messageId: `m${nextId++}`,\n seq: nextSeq(args.conversationId),\n conversationId: args.conversationId,\n authorParticipantId: args.authorParticipantId,\n kind: args.kind,\n body: messageSummary(args.content),\n content: args.content,\n replyToMessageId: args.replyToMessageId ?? null,\n threadRootId: args.threadRootId ?? null,\n quotedMessageIds: args.quotedMessageIds ?? [],\n mentionedParticipantIds: args.mentionedParticipantIds ?? [],\n hopDepth: args.hopDepth ?? 0,\n createdAt: new Date(0).toISOString(),\n final: args.source == null,\n updates: 0,\n source: args.source ?? null,\n };\n messages.push(message);\n return message;\n };\n\n const unsupported = async (): Promise<never> => {\n throw new Error('not supported by the fake platform');\n };\n const platform: ChannelPlatformIface = {\n channelSessions: {\n send: async (target, input) => {\n const prior = inputs.findIndex(\n (entry) => entry.input.idempotencyKey === input.idempotencyKey,\n );\n if (prior < 0) inputs.push({ target, input });\n const agent =\n target.participantId == null\n ? null\n : (participants.get(target.conversationId ?? '') ?? []).find(\n (participant) => participant.id === target.participantId,\n );\n return {\n inputId: `input-${prior < 0 ? inputs.length : prior + 1}`,\n sessionId: agent?.sessionId ?? target.sessionId ?? `session-${target.address ?? 'room'}`,\n };\n },\n inspect: unsupported,\n resolve: unsupported,\n respond: unsupported,\n cancel: unsupported,\n close: unsupported,\n observe: unsupported,\n setConfigOption: unsupported,\n park: unsupported,\n getState: unsupported,\n setState: unsupported,\n handoff: unsupported,\n },\n conversations: {\n dispatchMessage: async (input) => {\n const room = conversations.get(input.conversationId);\n const message = messages.find((entry) => entry.messageId === input.messageId);\n if (room == null || message == null) throw new Error('dispatch source missing');\n await deliverMessage({\n platform,\n conversation: room,\n message,\n turnPolicy: room.turnPolicy,\n route: input.participantId == null ? routeMessage : routeToOwner(input.participantId),\n });\n },\n get: async (conversationId) => conversations.get(conversationId) ?? null,\n findOrCreateDirect: async (args) => {\n const id = `direct:${args.userId}:${args.definitionId}`;\n return (\n conversations.get(id) ??\n addConversation({ conversationId: id, kind: ConversationKind.Direct })\n );\n },\n boundTo: async () => null,\n participants: async (conversationId) => participants.get(conversationId) ?? [],\n postMessage: async (args) => {\n if (args.clientMessageId != null) {\n const existing = messages.find(\n (message) =>\n message.conversationId === args.conversationId &&\n message.messageId === args.clientMessageId,\n );\n if (existing != null) return existing;\n }\n return insert({ ...args, kind: args.kind ?? MessageKind.Message });\n },\n updateMessage: async (args) => {\n const message = messages.find((candidate) => candidate.messageId === args.messageId);\n if (message == null) throw new Error(`no message ${args.messageId}`);\n message.content = args.content;\n message.body = messageSummary(args.content);\n message.final = args.final;\n message.updates += 1;\n },\n postCard: async (args: CardArgsIface) => {\n const message = insert({\n conversationId: args.conversationId,\n authorParticipantId: args.authorParticipantId,\n kind: MessageKind.Card,\n content: [],\n });\n cards.push({\n messageId: message.messageId,\n pendingRequestId: args.pendingRequestId,\n state: args.state,\n });\n return message;\n },\n updateCard: async (args) => {\n const card = cards.find(\n (candidate) =>\n candidate.messageId === args.messageId || candidate.pendingRequestId === args.messageId,\n );\n if (card == null) throw new Error(`no card ${args.messageId}`);\n card.state = { ...card.state, ...args.state };\n },\n recentMessages: async (args) =>\n messages\n .filter(\n (message) =>\n message.conversationId === args.conversationId &&\n (args.beforeSeq == null || message.seq < args.beforeSeq) &&\n (args.afterSeq == null || message.seq > args.afterSeq),\n )\n .slice(-args.limit),\n getMessages: async (args) => {\n getMessagesCalls.push(args.messageIds);\n return messages.filter(\n (message) =>\n message.conversationId === args.conversationId &&\n args.messageIds.includes(message.messageId),\n );\n },\n },\n sessions: {\n prompt: async (args) => {\n prompts.push(args);\n return { messageId: `acp-${prompts.length}` };\n },\n observe: async (args) => {\n observes.push(args);\n },\n cancel: async () => {},\n },\n log: (message) => {\n logs.push(message);\n },\n };\n\n return {\n platform,\n conversations,\n participants,\n messages,\n cards,\n prompts,\n observes,\n inputs,\n logs,\n getMessagesCalls,\n addConversation,\n addParticipant,\n };\n};\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -10,3 +10,4 @@ export * from "./pending.mjs";
10
10
  export * from "./projection.mjs";
11
11
  export * from "./prompt.mjs";
12
12
  export * from "./routing.mjs";
13
+ export * from "./service-input.mjs";
@@ -10,4 +10,5 @@ export * from "./pending.mjs";
10
10
  export * from "./projection.mjs";
11
11
  export * from "./prompt.mjs";
12
12
  export * from "./routing.mjs";
13
+ export * from "./service-input.mjs";
13
14
  //# sourceMappingURL=index.mjs.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../src/channels/index.ts"],
4
- "sourcesContent": ["export * from \"./agent-events.mjs\";\nexport * from \"./agent-schedules.mjs\";\nexport * from \"./content.mjs\";\nexport * from \"./delivery.mjs\";\nexport * from \"./direct-messaging.mjs\";\nexport * from \"./group-messaging.mjs\";\nexport * from \"./inbound.mjs\";\nexport * from \"./messaging-channel.mjs\";\nexport * from \"./pending.mjs\";\nexport * from \"./projection.mjs\";\nexport * from \"./prompt.mjs\";\nexport * from \"./routing.mjs\";\n"],
5
- "mappings": "AAAA,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;",
4
+ "sourcesContent": ["export * from \"./agent-events.mjs\";\nexport * from \"./agent-schedules.mjs\";\nexport * from \"./content.mjs\";\nexport * from \"./delivery.mjs\";\nexport * from \"./direct-messaging.mjs\";\nexport * from \"./group-messaging.mjs\";\nexport * from \"./inbound.mjs\";\nexport * from \"./messaging-channel.mjs\";\nexport * from \"./pending.mjs\";\nexport * from \"./projection.mjs\";\nexport * from \"./prompt.mjs\";\nexport * from \"./routing.mjs\";\nexport * from \"./service-input.mjs\";\n"],
5
+ "mappings": "AAAA,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;",
6
6
  "names": []
7
7
  }
@@ -1,6 +1,6 @@
1
1
  import type { ContentBlock } from '@agentclientprotocol/sdk/experimental/v2';
2
2
  import { type FinalAuthorIface, type FinalContextIface, type FinalMessageRefIface } from '@finalai/acp-session';
3
- import { type ConversationMessageIface, type ParticipantIface } from '@finalai/agent-provider/channel';
3
+ import { type ChannelAuthIface, type ConversationMessageIface, type ParticipantIface } from '@finalai/agent-provider/channel';
4
4
  export declare const EXCERPT_CHARS = 280;
5
5
  export declare const CATCH_UP_MAX_MESSAGES = 20;
6
6
  export declare const CATCH_UP_MAX_CHARS = 4000;
@@ -9,6 +9,10 @@ export declare const contentText: (content: ContentBlock[]) => string;
9
9
  export declare const messageSummary: (content: ContentBlock[]) => string;
10
10
  export declare const excerpt: (text: string, maxChars?: number) => string;
11
11
  export declare const finalAuthorOf: (participant: ParticipantIface) => FinalAuthorIface;
12
+ export declare const principalAuthorOf: (args: {
13
+ auth: ChannelAuthIface;
14
+ agent?: boolean;
15
+ }) => FinalAuthorIface;
12
16
  export interface AuthorPrefixedContentArgsIface {
13
17
  content: ContentBlock[];
14
18
  author: FinalAuthorIface;
@@ -43,8 +47,12 @@ export interface CatchUpArgsIface {
43
47
  export declare const buildCatchUpBlock: (args: CatchUpArgsIface) => ContentBlock | null;
44
48
  export declare const systemNoticeBlock: (args: {
45
49
  text: string;
46
- participantId: string;
47
50
  }) => ContentBlock;
51
+ export declare const catchUpFor: (args: {
52
+ recipient: ParticipantIface;
53
+ earlier: ConversationMessageIface[];
54
+ participants: ParticipantIface[];
55
+ }) => ContentBlock | null;
48
56
  export interface PromptContentArgsIface {
49
57
  message: ConversationMessageIface;
50
58
  author: ParticipantIface;
@@ -53,3 +61,12 @@ export interface PromptContentArgsIface {
53
61
  catchUp: ContentBlock | null;
54
62
  }
55
63
  export declare const buildPromptContent: (args: PromptContentArgsIface) => ContentBlock[];
64
+ export interface ServiceInputPromptArgsIface {
65
+ content: ContentBlock[];
66
+ context?: string[];
67
+ author: FinalAuthorIface;
68
+ recipient: ParticipantIface;
69
+ earlier: ConversationMessageIface[];
70
+ participants: ParticipantIface[];
71
+ }
72
+ export declare const buildServiceInputPrompt: (args: ServiceInputPromptArgsIface) => ContentBlock[];
@@ -6,8 +6,11 @@ import {
6
6
  withFinalMeta
7
7
  } from "@finalai/acp-session";
8
8
  import {
9
+ ChannelPrincipalType,
9
10
  MessageKind,
10
- ParticipantKind
11
+ ParticipantKind,
12
+ principalDisplayName,
13
+ RoutingMode
11
14
  } from "@finalai/agent-provider/channel";
12
15
  const EXCERPT_CHARS = 280;
13
16
  const CATCH_UP_MAX_MESSAGES = 20;
@@ -26,21 +29,20 @@ const excerpt = (text, maxChars = EXCERPT_CHARS) => {
26
29
  const normalized = text.replace(/\s+/gu, " ").trim();
27
30
  return normalized.length <= maxChars ? normalized : `${normalized.slice(0, maxChars - 1)}\u2026`;
28
31
  };
29
- const authorKindOf = (kind) => {
30
- switch (kind) {
31
- case ParticipantKind.Agent:
32
- return FinalAuthorKind.Agent;
33
- case ParticipantKind.System:
34
- return FinalAuthorKind.System;
35
- case ParticipantKind.User:
36
- return FinalAuthorKind.User;
37
- }
38
- };
39
32
  const finalAuthorOf = (participant) => ({
40
33
  participantId: participant.id,
41
- kind: authorKindOf(participant.kind),
34
+ kind: participant.kind === ParticipantKind.Agent ? FinalAuthorKind.Agent : FinalAuthorKind.User,
42
35
  displayName: participant.displayName
43
36
  });
37
+ const principalAuthorOf = (args) => ({
38
+ kind: args.agent === true ? FinalAuthorKind.Agent : args.auth.principalType === ChannelPrincipalType.User ? FinalAuthorKind.User : FinalAuthorKind.Service,
39
+ displayName: principalDisplayName(args.auth),
40
+ principal: {
41
+ principalId: args.auth.principalId,
42
+ principalType: args.auth.principalType,
43
+ authenticator: args.auth.authenticator
44
+ }
45
+ });
44
46
  const withContentRole = (block, context) => withFinalMeta(block, { role: FinalContentRole.Context, context });
45
47
  const authorPrefixedContent = (args) => {
46
48
  const blocks = args.rendersAuthorMeta ? args.content : promptTextWithAuthorPrefix(args.content, args.author.displayName);
@@ -140,12 +142,18 @@ const buildCatchUpBlock = (args) => {
140
142
  return withContentRole(textBlock([header, ...omittedLine, ...lines].join("\n")));
141
143
  };
142
144
  const systemNoticeBlock = (args) => withFinalMeta(textBlock(args.text), {
143
- author: {
144
- participantId: args.participantId,
145
- kind: FinalAuthorKind.System,
146
- displayName: "Final"
147
- }
145
+ author: { kind: FinalAuthorKind.Service, displayName: "Final" }
148
146
  });
147
+ const catchUpFor = (args) => {
148
+ const since = args.recipient.sessionId == null ? "start" /* Start */ : args.recipient.routingMode === RoutingMode.Mention ? "last-contact" /* LastContact */ : null;
149
+ if (since == null) return null;
150
+ return buildCatchUpBlock({
151
+ messages: args.earlier,
152
+ participants: args.participants,
153
+ agentParticipantId: args.recipient.id,
154
+ since
155
+ });
156
+ };
149
157
  const buildPromptContent = (args) => {
150
158
  const contextBlock = renderReplyContext(args.replyContext);
151
159
  const body = authorPrefixedContent({
@@ -160,6 +168,22 @@ const buildPromptContent = (args) => {
160
168
  ...body
161
169
  ];
162
170
  };
171
+ const buildServiceInputPrompt = (args) => {
172
+ const catchUp = catchUpFor({
173
+ recipient: args.recipient,
174
+ earlier: args.earlier,
175
+ participants: args.participants
176
+ });
177
+ return [
178
+ ...catchUp == null ? [] : [catchUp],
179
+ ...(args.context ?? []).map((text) => withContentRole(textBlock(text))),
180
+ ...authorPrefixedContent({
181
+ content: args.content,
182
+ author: args.author,
183
+ rendersAuthorMeta: args.recipient.rendersAuthorMeta ?? false
184
+ })
185
+ ];
186
+ };
163
187
  export {
164
188
  CATCH_UP_MAX_CHARS,
165
189
  CATCH_UP_MAX_MESSAGES,
@@ -168,12 +192,15 @@ export {
168
192
  authorPrefixedContent,
169
193
  buildCatchUpBlock,
170
194
  buildPromptContent,
195
+ buildServiceInputPrompt,
196
+ catchUpFor,
171
197
  contentText,
172
198
  excerpt,
173
199
  finalAuthorOf,
174
200
  finalContextOf,
175
201
  messageRefOf,
176
202
  messageSummary,
203
+ principalAuthorOf,
177
204
  renderReplyContext,
178
205
  systemNoticeBlock,
179
206
  textBlock
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../src/channels/prompt.ts"],
4
- "sourcesContent": ["import type { ContentBlock } from '@agentclientprotocol/sdk/experimental/v2';\nimport {\n FinalAuthorKind,\n FinalContentRole,\n promptTextWithAuthorPrefix,\n textOf,\n withFinalMeta,\n type FinalAuthorIface,\n type FinalContextIface,\n type FinalMessageRefIface,\n} from '@finalai/acp-session';\nimport {\n MessageKind,\n ParticipantKind,\n type ConversationMessageIface,\n type ParticipantIface,\n} from '@finalai/agent-provider/channel';\n\nexport const EXCERPT_CHARS = 280;\nexport const CATCH_UP_MAX_MESSAGES = 20;\nexport const CATCH_UP_MAX_CHARS = 4_000;\n\nexport const textBlock = (text: string): ContentBlock => ({ type: 'text', text });\n\nexport const contentText = (content: ContentBlock[]): string =>\n textOf(content, { separator: '\\n' }).trim();\n\n// A one-line description of a message for previews, excerpts and transcripts.\nexport const messageSummary = (content: ContentBlock[]): string => {\n const text = contentText(content);\n if (text.length > 0) {\n return text;\n }\n const attachments = content.filter((block) => block.type !== 'text').length;\n return attachments === 0 ? '' : `[${attachments} attachment${attachments === 1 ? '' : 's'}]`;\n};\n\nexport const excerpt = (text: string, maxChars: number = EXCERPT_CHARS): string => {\n const normalized = text.replace(/\\s+/gu, ' ').trim();\n return normalized.length <= maxChars ? normalized : `${normalized.slice(0, maxChars - 1)}\u2026`;\n};\n\nconst authorKindOf = (kind: ParticipantKind): FinalAuthorKind => {\n switch (kind) {\n case ParticipantKind.Agent:\n return FinalAuthorKind.Agent;\n case ParticipantKind.System:\n return FinalAuthorKind.System;\n case ParticipantKind.User:\n return FinalAuthorKind.User;\n }\n};\n\nexport const finalAuthorOf = (participant: ParticipantIface): FinalAuthorIface => ({\n participantId: participant.id,\n kind: authorKindOf(participant.kind),\n displayName: participant.displayName,\n});\n\nconst withContentRole = (block: ContentBlock, context?: FinalContextIface): ContentBlock =>\n withFinalMeta(block, { role: FinalContentRole.Context, context });\n\n// Attribution: `_meta[\"final.ai\"].author` on every block, plus a\n// `<name>: ` prefix for harnesses that do not render author meta.\nexport interface AuthorPrefixedContentArgsIface {\n content: ContentBlock[];\n author: FinalAuthorIface;\n rendersAuthorMeta: boolean;\n context?: FinalContextIface;\n}\n\nexport const authorPrefixedContent = (args: AuthorPrefixedContentArgsIface): ContentBlock[] => {\n const blocks: ContentBlock[] = args.rendersAuthorMeta\n ? args.content\n : promptTextWithAuthorPrefix(args.content, args.author.displayName);\n return blocks.map((block, index) =>\n withFinalMeta(block, { author: args.author, context: index === 0 ? args.context : undefined }),\n );\n};\n\nexport interface ReplyContextArgsIface {\n replyTo?: FinalMessageRefIface | null;\n thread?: {\n rootMessageId: string;\n rootExcerpt: string;\n rootAuthor?: FinalAuthorIface | null;\n } | null;\n quotes?: FinalMessageRefIface[];\n}\n\nexport const finalContextOf = (args: ReplyContextArgsIface): FinalContextIface | undefined => {\n const context: FinalContextIface = {};\n if (args.replyTo != null) context.replyTo = args.replyTo;\n if (args.thread != null) {\n context.thread = {\n rootMessageId: args.thread.rootMessageId,\n rootExcerpt: args.thread.rootExcerpt,\n };\n }\n if (args.quotes != null && args.quotes.length > 0) context.quotes = args.quotes;\n return Object.keys(context).length === 0 ? undefined : context;\n};\n\n// The rendered reply/thread/quote block, for harnesses that ignore\n// `_meta`. Null when the message has no context.\nexport const renderReplyContext = (args: ReplyContextArgsIface): ContentBlock | null => {\n const context = finalContextOf(args);\n if (context == null) {\n return null;\n }\n const lines: string[] = [];\n if (args.thread != null) {\n const by =\n args.thread.rootAuthor == null ? '' : ` started by ${args.thread.rootAuthor.displayName}`;\n lines.push(`In a thread${by}: \"${args.thread.rootExcerpt}\"`);\n }\n if (args.replyTo != null) {\n lines.push(\n `Replying to ${args.replyTo.author?.displayName ?? 'a message'}: \"${args.replyTo.excerpt}\"`,\n );\n }\n for (const quote of args.quotes ?? []) {\n lines.push(`Quoting ${quote.author?.displayName ?? 'a message'}: \"${quote.excerpt}\"`);\n }\n return withContentRole(textBlock(lines.join('\\n')), context);\n};\n\nexport const messageRefOf = (\n message: ConversationMessageIface,\n participants: ParticipantIface[],\n): FinalMessageRefIface => {\n const author = participants.find((participant) => participant.id === message.authorParticipantId);\n return {\n messageId: message.messageId,\n author: author == null ? null : finalAuthorOf(author),\n excerpt: excerpt(messageSummary(message.content)),\n };\n};\n\nconst transcriptLine = (\n message: ConversationMessageIface,\n participants: ParticipantIface[],\n): string => {\n const author = participants.find((participant) => participant.id === message.authorParticipantId);\n return `${author?.displayName ?? 'Someone'}: ${messageSummary(message.content)}`;\n};\n\nconst visibleForTranscript = (message: ConversationMessageIface): boolean =>\n message.kind !== MessageKind.Card && messageSummary(message.content).length > 0;\n\ninterface BoundedLinesArgsIface {\n messages: ConversationMessageIface[];\n participants: ParticipantIface[];\n maxMessages: number;\n maxChars: number;\n}\n\ninterface BoundedLinesIface {\n lines: string[];\n omitted: number;\n}\n\n// Lines from newest backwards until a bound is hit, returned oldest first.\nconst boundedLines = (args: BoundedLinesArgsIface): BoundedLinesIface => {\n const lines: string[] = [];\n let chars = 0;\n const ordered = [...args.messages].sort((left, right) => right.seq - left.seq);\n for (const message of ordered) {\n const line = transcriptLine(message, args.participants);\n if (lines.length >= args.maxMessages || chars + line.length > args.maxChars) {\n break;\n }\n lines.push(line);\n chars += line.length + 1;\n }\n return { lines: lines.reverse(), omitted: ordered.length - lines.length };\n};\n\nexport enum CatchUpSince {\n // A session that has never seen this conversation (new or reset).\n Start = 'start',\n // An agent that does not observe: since it last spoke or was mentioned.\n LastContact = 'last-contact',\n}\n\nexport interface CatchUpArgsIface {\n // Messages before the one being delivered, any order.\n messages: ConversationMessageIface[];\n participants: ParticipantIface[];\n agentParticipantId: string;\n since: CatchUpSince;\n maxMessages?: number;\n maxChars?: number;\n}\n\n// \"Earlier in this conversation, not previously shown: \u2026\", marked\n// as context. Null when there is nothing the agent has not seen.\nexport const buildCatchUpBlock = (args: CatchUpArgsIface): ContentBlock | null => {\n let unseen = args.messages.filter(\n (message) =>\n visibleForTranscript(message) && message.authorParticipantId !== args.agentParticipantId,\n );\n if (args.since === CatchUpSince.LastContact) {\n const lastContactSeq = args.messages.reduce(\n (latest, message) =>\n message.authorParticipantId === args.agentParticipantId ||\n message.mentionedParticipantIds.includes(args.agentParticipantId)\n ? Math.max(latest, message.seq)\n : latest,\n -1,\n );\n unseen = unseen.filter((message) => message.seq > lastContactSeq);\n }\n if (unseen.length === 0) {\n return null;\n }\n const { lines, omitted } = boundedLines({\n messages: unseen,\n participants: args.participants,\n maxMessages: args.maxMessages ?? CATCH_UP_MAX_MESSAGES,\n maxChars: args.maxChars ?? CATCH_UP_MAX_CHARS,\n });\n if (lines.length === 0) {\n return null;\n }\n const header = 'Earlier in this conversation, not previously shown:';\n const omittedLine =\n omitted > 0 ? [`(${omitted} earlier message${omitted === 1 ? '' : 's'} omitted)`] : [];\n return withContentRole(textBlock([header, ...omittedLine, ...lines].join('\\n')));\n};\n\n// A system-authored block delivered by observe: reactions, membership changes.\nexport const systemNoticeBlock = (args: { text: string; participantId: string }): ContentBlock =>\n withFinalMeta(textBlock(args.text), {\n author: {\n participantId: args.participantId,\n kind: FinalAuthorKind.System,\n displayName: 'Final',\n },\n });\n\nexport interface PromptContentArgsIface {\n message: ConversationMessageIface;\n author: ParticipantIface;\n recipient: ParticipantIface;\n replyContext: ReplyContextArgsIface;\n catchUp: ContentBlock | null;\n}\n\n// The ACP prompt one agent receives for a conversation message.\nexport const buildPromptContent = (args: PromptContentArgsIface): ContentBlock[] => {\n const contextBlock = renderReplyContext(args.replyContext);\n const body = authorPrefixedContent({\n content:\n args.message.content.length > 0 ? args.message.content : [textBlock(args.message.body)],\n author: finalAuthorOf(args.author),\n rendersAuthorMeta: args.recipient.rendersAuthorMeta ?? false,\n context: finalContextOf(args.replyContext),\n });\n return [\n ...(args.catchUp == null ? [] : [args.catchUp]),\n ...(contextBlock == null ? [] : [contextBlock]),\n ...body,\n ];\n};\n"],
5
- "mappings": "AACA;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OAIK;AACP;AAAA,EACE;AAAA,EACA;AAAA,OAGK;AAEA,MAAM,gBAAgB;AACtB,MAAM,wBAAwB;AAC9B,MAAM,qBAAqB;AAE3B,MAAM,YAAY,CAAC,UAAgC,EAAE,MAAM,QAAQ,KAAK;AAExE,MAAM,cAAc,CAAC,YAC1B,OAAO,SAAS,EAAE,WAAW,KAAK,CAAC,EAAE,KAAK;AAGrC,MAAM,iBAAiB,CAAC,YAAoC;AACjE,QAAM,OAAO,YAAY,OAAO;AAChC,MAAI,KAAK,SAAS,GAAG;AACnB,WAAO;AAAA,EACT;AACA,QAAM,cAAc,QAAQ,OAAO,CAAC,UAAU,MAAM,SAAS,MAAM,EAAE;AACrE,SAAO,gBAAgB,IAAI,KAAK,IAAI,WAAW,cAAc,gBAAgB,IAAI,KAAK,GAAG;AAC3F;AAEO,MAAM,UAAU,CAAC,MAAc,WAAmB,kBAA0B;AACjF,QAAM,aAAa,KAAK,QAAQ,SAAS,GAAG,EAAE,KAAK;AACnD,SAAO,WAAW,UAAU,WAAW,aAAa,GAAG,WAAW,MAAM,GAAG,WAAW,CAAC,CAAC;AAC1F;AAEA,MAAM,eAAe,CAAC,SAA2C;AAC/D,UAAQ,MAAM;AAAA,IACZ,KAAK,gBAAgB;AACnB,aAAO,gBAAgB;AAAA,IACzB,KAAK,gBAAgB;AACnB,aAAO,gBAAgB;AAAA,IACzB,KAAK,gBAAgB;AACnB,aAAO,gBAAgB;AAAA,EAC3B;AACF;AAEO,MAAM,gBAAgB,CAAC,iBAAqD;AAAA,EACjF,eAAe,YAAY;AAAA,EAC3B,MAAM,aAAa,YAAY,IAAI;AAAA,EACnC,aAAa,YAAY;AAC3B;AAEA,MAAM,kBAAkB,CAAC,OAAqB,YAC5C,cAAc,OAAO,EAAE,MAAM,iBAAiB,SAAS,QAAQ,CAAC;AAW3D,MAAM,wBAAwB,CAAC,SAAyD;AAC7F,QAAM,SAAyB,KAAK,oBAChC,KAAK,UACL,2BAA2B,KAAK,SAAS,KAAK,OAAO,WAAW;AACpE,SAAO,OAAO;AAAA,IAAI,CAAC,OAAO,UACxB,cAAc,OAAO,EAAE,QAAQ,KAAK,QAAQ,SAAS,UAAU,IAAI,KAAK,UAAU,OAAU,CAAC;AAAA,EAC/F;AACF;AAYO,MAAM,iBAAiB,CAAC,SAA+D;AAC5F,QAAM,UAA6B,CAAC;AACpC,MAAI,KAAK,WAAW,KAAM,SAAQ,UAAU,KAAK;AACjD,MAAI,KAAK,UAAU,MAAM;AACvB,YAAQ,SAAS;AAAA,MACf,eAAe,KAAK,OAAO;AAAA,MAC3B,aAAa,KAAK,OAAO;AAAA,IAC3B;AAAA,EACF;AACA,MAAI,KAAK,UAAU,QAAQ,KAAK,OAAO,SAAS,EAAG,SAAQ,SAAS,KAAK;AACzE,SAAO,OAAO,KAAK,OAAO,EAAE,WAAW,IAAI,SAAY;AACzD;AAIO,MAAM,qBAAqB,CAAC,SAAqD;AACtF,QAAM,UAAU,eAAe,IAAI;AACnC,MAAI,WAAW,MAAM;AACnB,WAAO;AAAA,EACT;AACA,QAAM,QAAkB,CAAC;AACzB,MAAI,KAAK,UAAU,MAAM;AACvB,UAAM,KACJ,KAAK,OAAO,cAAc,OAAO,KAAK,eAAe,KAAK,OAAO,WAAW,WAAW;AACzF,UAAM,KAAK,cAAc,EAAE,MAAM,KAAK,OAAO,WAAW,GAAG;AAAA,EAC7D;AACA,MAAI,KAAK,WAAW,MAAM;AACxB,UAAM;AAAA,MACJ,eAAe,KAAK,QAAQ,QAAQ,eAAe,WAAW,MAAM,KAAK,QAAQ,OAAO;AAAA,IAC1F;AAAA,EACF;AACA,aAAW,SAAS,KAAK,UAAU,CAAC,GAAG;AACrC,UAAM,KAAK,WAAW,MAAM,QAAQ,eAAe,WAAW,MAAM,MAAM,OAAO,GAAG;AAAA,EACtF;AACA,SAAO,gBAAgB,UAAU,MAAM,KAAK,IAAI,CAAC,GAAG,OAAO;AAC7D;AAEO,MAAM,eAAe,CAC1B,SACA,iBACyB;AACzB,QAAM,SAAS,aAAa,KAAK,CAAC,gBAAgB,YAAY,OAAO,QAAQ,mBAAmB;AAChG,SAAO;AAAA,IACL,WAAW,QAAQ;AAAA,IACnB,QAAQ,UAAU,OAAO,OAAO,cAAc,MAAM;AAAA,IACpD,SAAS,QAAQ,eAAe,QAAQ,OAAO,CAAC;AAAA,EAClD;AACF;AAEA,MAAM,iBAAiB,CACrB,SACA,iBACW;AACX,QAAM,SAAS,aAAa,KAAK,CAAC,gBAAgB,YAAY,OAAO,QAAQ,mBAAmB;AAChG,SAAO,GAAG,QAAQ,eAAe,SAAS,KAAK,eAAe,QAAQ,OAAO,CAAC;AAChF;AAEA,MAAM,uBAAuB,CAAC,YAC5B,QAAQ,SAAS,YAAY,QAAQ,eAAe,QAAQ,OAAO,EAAE,SAAS;AAehF,MAAM,eAAe,CAAC,SAAmD;AACvE,QAAM,QAAkB,CAAC;AACzB,MAAI,QAAQ;AACZ,QAAM,UAAU,CAAC,GAAG,KAAK,QAAQ,EAAE,KAAK,CAAC,MAAM,UAAU,MAAM,MAAM,KAAK,GAAG;AAC7E,aAAW,WAAW,SAAS;AAC7B,UAAM,OAAO,eAAe,SAAS,KAAK,YAAY;AACtD,QAAI,MAAM,UAAU,KAAK,eAAe,QAAQ,KAAK,SAAS,KAAK,UAAU;AAC3E;AAAA,IACF;AACA,UAAM,KAAK,IAAI;AACf,aAAS,KAAK,SAAS;AAAA,EACzB;AACA,SAAO,EAAE,OAAO,MAAM,QAAQ,GAAG,SAAS,QAAQ,SAAS,MAAM,OAAO;AAC1E;AAEO,IAAK,eAAL,kBAAKA,kBAAL;AAEL,EAAAA,cAAA,WAAQ;AAER,EAAAA,cAAA,iBAAc;AAJJ,SAAAA;AAAA,GAAA;AAmBL,MAAM,oBAAoB,CAAC,SAAgD;AAChF,MAAI,SAAS,KAAK,SAAS;AAAA,IACzB,CAAC,YACC,qBAAqB,OAAO,KAAK,QAAQ,wBAAwB,KAAK;AAAA,EAC1E;AACA,MAAI,KAAK,UAAU,kCAA0B;AAC3C,UAAM,iBAAiB,KAAK,SAAS;AAAA,MACnC,CAAC,QAAQ,YACP,QAAQ,wBAAwB,KAAK,sBACrC,QAAQ,wBAAwB,SAAS,KAAK,kBAAkB,IAC5D,KAAK,IAAI,QAAQ,QAAQ,GAAG,IAC5B;AAAA,MACN;AAAA,IACF;AACA,aAAS,OAAO,OAAO,CAAC,YAAY,QAAQ,MAAM,cAAc;AAAA,EAClE;AACA,MAAI,OAAO,WAAW,GAAG;AACvB,WAAO;AAAA,EACT;AACA,QAAM,EAAE,OAAO,QAAQ,IAAI,aAAa;AAAA,IACtC,UAAU;AAAA,IACV,cAAc,KAAK;AAAA,IACnB,aAAa,KAAK,eAAe;AAAA,IACjC,UAAU,KAAK,YAAY;AAAA,EAC7B,CAAC;AACD,MAAI,MAAM,WAAW,GAAG;AACtB,WAAO;AAAA,EACT;AACA,QAAM,SAAS;AACf,QAAM,cACJ,UAAU,IAAI,CAAC,IAAI,OAAO,mBAAmB,YAAY,IAAI,KAAK,GAAG,WAAW,IAAI,CAAC;AACvF,SAAO,gBAAgB,UAAU,CAAC,QAAQ,GAAG,aAAa,GAAG,KAAK,EAAE,KAAK,IAAI,CAAC,CAAC;AACjF;AAGO,MAAM,oBAAoB,CAAC,SAChC,cAAc,UAAU,KAAK,IAAI,GAAG;AAAA,EAClC,QAAQ;AAAA,IACN,eAAe,KAAK;AAAA,IACpB,MAAM,gBAAgB;AAAA,IACtB,aAAa;AAAA,EACf;AACF,CAAC;AAWI,MAAM,qBAAqB,CAAC,SAAiD;AAClF,QAAM,eAAe,mBAAmB,KAAK,YAAY;AACzD,QAAM,OAAO,sBAAsB;AAAA,IACjC,SACE,KAAK,QAAQ,QAAQ,SAAS,IAAI,KAAK,QAAQ,UAAU,CAAC,UAAU,KAAK,QAAQ,IAAI,CAAC;AAAA,IACxF,QAAQ,cAAc,KAAK,MAAM;AAAA,IACjC,mBAAmB,KAAK,UAAU,qBAAqB;AAAA,IACvD,SAAS,eAAe,KAAK,YAAY;AAAA,EAC3C,CAAC;AACD,SAAO;AAAA,IACL,GAAI,KAAK,WAAW,OAAO,CAAC,IAAI,CAAC,KAAK,OAAO;AAAA,IAC7C,GAAI,gBAAgB,OAAO,CAAC,IAAI,CAAC,YAAY;AAAA,IAC7C,GAAG;AAAA,EACL;AACF;",
4
+ "sourcesContent": ["import type { ContentBlock } from '@agentclientprotocol/sdk/experimental/v2';\nimport {\n FinalAuthorKind,\n FinalContentRole,\n promptTextWithAuthorPrefix,\n textOf,\n withFinalMeta,\n type FinalAuthorIface,\n type FinalContextIface,\n type FinalMessageRefIface,\n} from '@finalai/acp-session';\nimport {\n ChannelPrincipalType,\n MessageKind,\n ParticipantKind,\n principalDisplayName,\n RoutingMode,\n type ChannelAuthIface,\n type ConversationMessageIface,\n type ParticipantIface,\n} from '@finalai/agent-provider/channel';\n\nexport const EXCERPT_CHARS = 280;\nexport const CATCH_UP_MAX_MESSAGES = 20;\nexport const CATCH_UP_MAX_CHARS = 4_000;\n\nexport const textBlock = (text: string): ContentBlock => ({ type: 'text', text });\n\nexport const contentText = (content: ContentBlock[]): string =>\n textOf(content, { separator: '\\n' }).trim();\n\n// A one-line description of a message for previews, excerpts and transcripts.\nexport const messageSummary = (content: ContentBlock[]): string => {\n const text = contentText(content);\n if (text.length > 0) {\n return text;\n }\n const attachments = content.filter((block) => block.type !== 'text').length;\n return attachments === 0 ? '' : `[${attachments} attachment${attachments === 1 ? '' : 's'}]`;\n};\n\nexport const excerpt = (text: string, maxChars: number = EXCERPT_CHARS): string => {\n const normalized = text.replace(/\\s+/gu, ' ').trim();\n return normalized.length <= maxChars ? normalized : `${normalized.slice(0, maxChars - 1)}\u2026`;\n};\n\nexport const finalAuthorOf = (participant: ParticipantIface): FinalAuthorIface => ({\n participantId: participant.id,\n kind: participant.kind === ParticipantKind.Agent ? FinalAuthorKind.Agent : FinalAuthorKind.User,\n displayName: participant.displayName,\n});\n\n// The author an agent sees for channel input from no member: the principal the\n// channel authenticated, named as the channel named it. `agent` marks input an\n// agent wrote elsewhere (another chat), so the recipient knows it is not a person.\nexport const principalAuthorOf = (args: {\n auth: ChannelAuthIface;\n agent?: boolean;\n}): FinalAuthorIface => ({\n kind:\n args.agent === true\n ? FinalAuthorKind.Agent\n : args.auth.principalType === ChannelPrincipalType.User\n ? FinalAuthorKind.User\n : FinalAuthorKind.Service,\n displayName: principalDisplayName(args.auth),\n principal: {\n principalId: args.auth.principalId,\n principalType: args.auth.principalType,\n authenticator: args.auth.authenticator,\n },\n});\n\nconst withContentRole = (block: ContentBlock, context?: FinalContextIface): ContentBlock =>\n withFinalMeta(block, { role: FinalContentRole.Context, context });\n\n// Attribution: `_meta[\"final.ai\"].author` on every block, plus a\n// `<name>: ` prefix for harnesses that do not render author meta.\nexport interface AuthorPrefixedContentArgsIface {\n content: ContentBlock[];\n author: FinalAuthorIface;\n rendersAuthorMeta: boolean;\n context?: FinalContextIface;\n}\n\nexport const authorPrefixedContent = (args: AuthorPrefixedContentArgsIface): ContentBlock[] => {\n const blocks: ContentBlock[] = args.rendersAuthorMeta\n ? args.content\n : promptTextWithAuthorPrefix(args.content, args.author.displayName);\n return blocks.map((block, index) =>\n withFinalMeta(block, { author: args.author, context: index === 0 ? args.context : undefined }),\n );\n};\n\nexport interface ReplyContextArgsIface {\n replyTo?: FinalMessageRefIface | null;\n thread?: {\n rootMessageId: string;\n rootExcerpt: string;\n rootAuthor?: FinalAuthorIface | null;\n } | null;\n quotes?: FinalMessageRefIface[];\n}\n\nexport const finalContextOf = (args: ReplyContextArgsIface): FinalContextIface | undefined => {\n const context: FinalContextIface = {};\n if (args.replyTo != null) context.replyTo = args.replyTo;\n if (args.thread != null) {\n context.thread = {\n rootMessageId: args.thread.rootMessageId,\n rootExcerpt: args.thread.rootExcerpt,\n };\n }\n if (args.quotes != null && args.quotes.length > 0) context.quotes = args.quotes;\n return Object.keys(context).length === 0 ? undefined : context;\n};\n\n// The rendered reply/thread/quote block, for harnesses that ignore\n// `_meta`. Null when the message has no context.\nexport const renderReplyContext = (args: ReplyContextArgsIface): ContentBlock | null => {\n const context = finalContextOf(args);\n if (context == null) {\n return null;\n }\n const lines: string[] = [];\n if (args.thread != null) {\n const by =\n args.thread.rootAuthor == null ? '' : ` started by ${args.thread.rootAuthor.displayName}`;\n lines.push(`In a thread${by}: \"${args.thread.rootExcerpt}\"`);\n }\n if (args.replyTo != null) {\n lines.push(\n `Replying to ${args.replyTo.author?.displayName ?? 'a message'}: \"${args.replyTo.excerpt}\"`,\n );\n }\n for (const quote of args.quotes ?? []) {\n lines.push(`Quoting ${quote.author?.displayName ?? 'a message'}: \"${quote.excerpt}\"`);\n }\n return withContentRole(textBlock(lines.join('\\n')), context);\n};\n\nexport const messageRefOf = (\n message: ConversationMessageIface,\n participants: ParticipantIface[],\n): FinalMessageRefIface => {\n const author = participants.find((participant) => participant.id === message.authorParticipantId);\n return {\n messageId: message.messageId,\n author: author == null ? null : finalAuthorOf(author),\n excerpt: excerpt(messageSummary(message.content)),\n };\n};\n\nconst transcriptLine = (\n message: ConversationMessageIface,\n participants: ParticipantIface[],\n): string => {\n const author = participants.find((participant) => participant.id === message.authorParticipantId);\n return `${author?.displayName ?? 'Someone'}: ${messageSummary(message.content)}`;\n};\n\nconst visibleForTranscript = (message: ConversationMessageIface): boolean =>\n message.kind !== MessageKind.Card && messageSummary(message.content).length > 0;\n\ninterface BoundedLinesArgsIface {\n messages: ConversationMessageIface[];\n participants: ParticipantIface[];\n maxMessages: number;\n maxChars: number;\n}\n\ninterface BoundedLinesIface {\n lines: string[];\n omitted: number;\n}\n\n// Lines from newest backwards until a bound is hit, returned oldest first.\nconst boundedLines = (args: BoundedLinesArgsIface): BoundedLinesIface => {\n const lines: string[] = [];\n let chars = 0;\n const ordered = [...args.messages].sort((left, right) => right.seq - left.seq);\n for (const message of ordered) {\n const line = transcriptLine(message, args.participants);\n if (lines.length >= args.maxMessages || chars + line.length > args.maxChars) {\n break;\n }\n lines.push(line);\n chars += line.length + 1;\n }\n return { lines: lines.reverse(), omitted: ordered.length - lines.length };\n};\n\nexport enum CatchUpSince {\n // A session that has never seen this conversation (new or reset).\n Start = 'start',\n // An agent that does not observe: since it last spoke or was mentioned.\n LastContact = 'last-contact',\n}\n\nexport interface CatchUpArgsIface {\n // Messages before the one being delivered, any order.\n messages: ConversationMessageIface[];\n participants: ParticipantIface[];\n agentParticipantId: string;\n since: CatchUpSince;\n maxMessages?: number;\n maxChars?: number;\n}\n\n// \"Earlier in this conversation, not previously shown: \u2026\", marked\n// as context. Null when there is nothing the agent has not seen.\nexport const buildCatchUpBlock = (args: CatchUpArgsIface): ContentBlock | null => {\n let unseen = args.messages.filter(\n (message) =>\n visibleForTranscript(message) && message.authorParticipantId !== args.agentParticipantId,\n );\n if (args.since === CatchUpSince.LastContact) {\n const lastContactSeq = args.messages.reduce(\n (latest, message) =>\n message.authorParticipantId === args.agentParticipantId ||\n message.mentionedParticipantIds.includes(args.agentParticipantId)\n ? Math.max(latest, message.seq)\n : latest,\n -1,\n );\n unseen = unseen.filter((message) => message.seq > lastContactSeq);\n }\n if (unseen.length === 0) {\n return null;\n }\n const { lines, omitted } = boundedLines({\n messages: unseen,\n participants: args.participants,\n maxMessages: args.maxMessages ?? CATCH_UP_MAX_MESSAGES,\n maxChars: args.maxChars ?? CATCH_UP_MAX_CHARS,\n });\n if (lines.length === 0) {\n return null;\n }\n const header = 'Earlier in this conversation, not previously shown:';\n const omittedLine =\n omitted > 0 ? [`(${omitted} earlier message${omitted === 1 ? '' : 's'} omitted)`] : [];\n return withContentRole(textBlock([header, ...omittedLine, ...lines].join('\\n')));\n};\n\n// A notice from Final itself delivered by observe: reactions, membership changes.\nexport const systemNoticeBlock = (args: { text: string }): ContentBlock =>\n withFinalMeta(textBlock(args.text), {\n author: { kind: FinalAuthorKind.Service, displayName: 'Final' },\n });\n\n// What a recipient has not seen of its conversation before a prompt: a fresh\n// session has seen nothing; a Mention agent sees only what it is prompted\n// with; everyone else has been observing.\nexport const catchUpFor = (args: {\n recipient: ParticipantIface;\n earlier: ConversationMessageIface[];\n participants: ParticipantIface[];\n}): ContentBlock | null => {\n const since =\n args.recipient.sessionId == null\n ? CatchUpSince.Start\n : args.recipient.routingMode === RoutingMode.Mention\n ? CatchUpSince.LastContact\n : null;\n if (since == null) return null;\n return buildCatchUpBlock({\n messages: args.earlier,\n participants: args.participants,\n agentParticipantId: args.recipient.id,\n since,\n });\n};\n\nexport interface PromptContentArgsIface {\n message: ConversationMessageIface;\n author: ParticipantIface;\n recipient: ParticipantIface;\n replyContext: ReplyContextArgsIface;\n catchUp: ContentBlock | null;\n}\n\n// The ACP prompt one agent receives for a conversation message.\nexport const buildPromptContent = (args: PromptContentArgsIface): ContentBlock[] => {\n const contextBlock = renderReplyContext(args.replyContext);\n const body = authorPrefixedContent({\n content:\n args.message.content.length > 0 ? args.message.content : [textBlock(args.message.body)],\n author: finalAuthorOf(args.author),\n rendersAuthorMeta: args.recipient.rendersAuthorMeta ?? false,\n context: finalContextOf(args.replyContext),\n });\n return [\n ...(args.catchUp == null ? [] : [args.catchUp]),\n ...(contextBlock == null ? [] : [contextBlock]),\n ...body,\n ];\n};\n\nexport interface ServiceInputPromptArgsIface {\n content: ContentBlock[];\n // Channel-supplied context lines, marked as context before the input.\n context?: string[];\n author: FinalAuthorIface;\n recipient: ParticipantIface;\n // The room's latest messages when the input is delivered, any order.\n earlier: ConversationMessageIface[];\n participants: ParticipantIface[];\n}\n\n// The ACP prompt a room's agent receives for channel input: what it has not seen\n// of the room up to its latest message, then the input attributed to its principal.\nexport const buildServiceInputPrompt = (args: ServiceInputPromptArgsIface): ContentBlock[] => {\n const catchUp = catchUpFor({\n recipient: args.recipient,\n earlier: args.earlier,\n participants: args.participants,\n });\n return [\n ...(catchUp == null ? [] : [catchUp]),\n ...(args.context ?? []).map((text) => withContentRole(textBlock(text))),\n ...authorPrefixedContent({\n content: args.content,\n author: args.author,\n rendersAuthorMeta: args.recipient.rendersAuthorMeta ?? false,\n }),\n ];\n};\n"],
5
+ "mappings": "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",
6
6
  "names": ["CatchUpSince"]
7
7
  }