@finalai/final-agent-provider 0.4.4 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/modules/channel-factories.d.mts +3 -3
- package/dist/modules/channel-factories.mjs +7 -7
- package/dist/modules/channel-factories.mjs.map +2 -2
- package/dist/modules/channels/agent-events.mjs +1 -1
- package/dist/modules/channels/agent-events.mjs.map +1 -1
- package/dist/modules/channels/fake-platform.d.mts +1 -1
- package/dist/modules/channels/fake-platform.mjs +2 -2
- package/dist/modules/channels/fake-platform.mjs.map +2 -2
- package/dist/modules/channels/index.d.mts +0 -1
- package/dist/modules/channels/index.mjs +0 -1
- package/dist/modules/channels/index.mjs.map +2 -2
- package/dist/modules/channels/messaging-channel.mjs +1 -4
- package/dist/modules/channels/messaging-channel.mjs.map +2 -2
- package/package.json +4 -4
- package/dist/modules/channels/pending.d.mts +0 -14
- package/dist/modules/channels/pending.mjs +0 -155
- package/dist/modules/channels/pending.mjs.map +0 -7
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { SessionUpdate } from '@agentclientprotocol/sdk/experimental/v2';
|
|
2
|
-
import { TurnPolicy, type ChannelAddressContextIface, type ChannelAuthIface, type ChannelDefinitionIface, type ChannelInputReceiptIface, type ChannelInputResponseIface, type ChannelMessageCompletedDataIface, type ChannelMessageDeltaDataIface, type ChannelReceiveContextIface, type ChannelTurnEventDataIface, type ChannelTurnStateIface, type ConversationMessageIface, type
|
|
2
|
+
import { TurnPolicy, type ChannelAddressContextIface, type ChannelAuthIface, type ChannelDefinitionIface, type ChannelInputReceiptIface, type ChannelInputResponseIface, type ChannelMessageCompletedDataIface, type ChannelMessageDeltaDataIface, type ChannelReceiveContextIface, type ChannelTurnEventDataIface, type ChannelTurnStateIface, type ConversationMessageIface, type DecisionCreatedDataIface, type DecisionResolvedDataIface, type JsonValue } from '@finalai/agent-provider';
|
|
3
3
|
import { type ServiceInputArgsIface } from "./channels/service-input.mjs";
|
|
4
4
|
export declare const FINAL_CHANNEL_SPECIFIER = "@finalai/final-agent-provider/channels/final";
|
|
5
5
|
export { ChannelPrincipalType, type ChannelAuthIface } from '@finalai/agent-provider';
|
|
@@ -28,8 +28,8 @@ export interface FinalChannelEventHandlersIface {
|
|
|
28
28
|
'message.completed'?: FinalChannelEventHandler<ChannelMessageCompletedDataIface>;
|
|
29
29
|
'turn.started'?: FinalChannelEventHandler<ChannelTurnEventDataIface>;
|
|
30
30
|
'turn.completed'?: FinalChannelEventHandler<ChannelTurnEventDataIface>;
|
|
31
|
-
'
|
|
32
|
-
'
|
|
31
|
+
'decision.created'?: FinalChannelEventHandler<DecisionCreatedDataIface>;
|
|
32
|
+
'decision.resolved'?: FinalChannelEventHandler<DecisionResolvedDataIface>;
|
|
33
33
|
}
|
|
34
34
|
export interface FinalChannelOptionsIface {
|
|
35
35
|
turnPolicy?: TurnPolicy | `${TurnPolicy}`;
|
|
@@ -5,11 +5,11 @@ import {
|
|
|
5
5
|
channelAccessors,
|
|
6
6
|
channelAuthSchema,
|
|
7
7
|
channelMessageCompletedSchema,
|
|
8
|
+
decisionCreatedDataSchema,
|
|
9
|
+
decisionResolvedDataSchema,
|
|
8
10
|
defineChannel,
|
|
9
11
|
jsonObjectSchema,
|
|
10
|
-
packageRef
|
|
11
|
-
pendingCreatedDataSchema,
|
|
12
|
-
pendingResolvedDataSchema
|
|
12
|
+
packageRef
|
|
13
13
|
} from "@finalai/agent-provider";
|
|
14
14
|
import * as z from "zod";
|
|
15
15
|
import { finalAddressContext } from "./channels/address-context.mjs";
|
|
@@ -73,8 +73,8 @@ const finalChannel = (inputOptions = {}) => {
|
|
|
73
73
|
"message.completed",
|
|
74
74
|
"turn.started",
|
|
75
75
|
"turn.completed",
|
|
76
|
-
"
|
|
77
|
-
"
|
|
76
|
+
"decision.created",
|
|
77
|
+
"decision.resolved"
|
|
78
78
|
]);
|
|
79
79
|
for (const kind of Object.keys(options.events ?? {}))
|
|
80
80
|
if (!supportedEvents.has(kind)) throw new Error(`unsupported Final channel event: ${kind}`);
|
|
@@ -196,8 +196,8 @@ const finalChannel = (inputOptions = {}) => {
|
|
|
196
196
|
z.object({ turnId: z.string(), stopReason: z.string().nullable() }),
|
|
197
197
|
options.events?.["turn.completed"]
|
|
198
198
|
),
|
|
199
|
-
"
|
|
200
|
-
"
|
|
199
|
+
"decision.created": wrap(decisionCreatedDataSchema, options.events?.["decision.created"]),
|
|
200
|
+
"decision.resolved": wrap(decisionResolvedDataSchema, options.events?.["decision.resolved"])
|
|
201
201
|
};
|
|
202
202
|
const events = { ...base.events };
|
|
203
203
|
for (const [kind, handler] of Object.entries(authoredEvents))
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/channel-factories.ts"],
|
|
4
|
-
"sourcesContent": ["import type { ContentBlock, SessionUpdate } from '@agentclientprotocol/sdk/experimental/v2';\nimport {\n ChannelPrincipalType,\n SemanticChannelEventKind,\n TurnPolicy,\n channelAccessors,\n channelAuthSchema,\n channelMessageCompletedSchema,\n defineChannel,\n jsonObjectSchema,\n packageRef,\n pendingCreatedDataSchema,\n pendingResolvedDataSchema,\n type ChannelAddressContextIface,\n type ChannelAuthIface,\n type ChannelDefinitionIface,\n type ChannelEventHandler,\n type ChannelInputReceiptIface,\n type ChannelInputResponseIface,\n type ChannelMessageCompletedDataIface,\n type ChannelMessageDeltaDataIface,\n type ChannelReceiveContextIface,\n type ChannelTurnEventDataIface,\n type ChannelTurnStateIface,\n type ConversationMessageIface,\n type JsonValue,\n type PendingCreatedDataIface,\n type PendingResolvedDataIface,\n type ProjectionContextIface,\n} from '@finalai/agent-provider';\nimport * as z from 'zod';\nimport { finalAddressContext } from \"./channels/address-context.mjs\";\nimport { contentBlocksOf } from \"./channels/content.mjs\";\nimport { conversationEventInboundSchema, messageInboundSchema } from \"./channels/inbound.mjs\";\nimport { createMessagingChannel } from \"./channels/messaging-channel.mjs\";\nimport { sendServiceInput, type ServiceInputArgsIface } from \"./channels/service-input.mjs\";\n\nexport const FINAL_CHANNEL_SPECIFIER = '@finalai/final-agent-provider/channels/final';\n\nexport { ChannelPrincipalType, type ChannelAuthIface } from '@finalai/agent-provider';\n\nexport interface ChannelAdmissionIface {\n auth: ChannelAuthIface | null;\n context?: string[];\n title?: string;\n}\n\nexport interface FinalMessageContextIface\n extends ChannelReceiveContextIface, ChannelAddressContextIface {\n defaultAuth: ChannelAuthIface | null;\n}\n\nexport interface FinalChannelContextIface extends ChannelAddressContextIface {\n final: {\n post(message: ChannelMessageCompletedDataIface['message']): Promise<ConversationMessageIface>;\n // Input to a room's agent from a principal that is no member of the room.\n sendServiceInput(args: ServiceInputArgsIface): Promise<ChannelInputReceiptIface>;\n };\n}\nexport interface FinalSessionContextIface {\n sessionId: string | null;\n turnId: string;\n state: ChannelTurnStateIface<JsonValue>;\n}\nexport type FinalChannelEventHandler<Data> = (\n data: Data,\n channel: FinalChannelContextIface,\n ctx: FinalSessionContextIface,\n) => void | Promise<void>;\nexport interface FinalChannelEventHandlersIface {\n 'message.delta'?: FinalChannelEventHandler<ChannelMessageDeltaDataIface>;\n 'message.completed'?: FinalChannelEventHandler<ChannelMessageCompletedDataIface>;\n 'turn.started'?: FinalChannelEventHandler<ChannelTurnEventDataIface>;\n 'turn.completed'?: FinalChannelEventHandler<ChannelTurnEventDataIface>;\n 'pending.created'?: FinalChannelEventHandler<PendingCreatedDataIface>;\n 'pending.resolved'?: FinalChannelEventHandler<PendingResolvedDataIface>;\n}\n\nexport interface FinalChannelOptionsIface {\n turnPolicy?: TurnPolicy | `${TurnPolicy}`;\n updateIntervalMs?: number;\n route?: ChannelDefinitionIface<JsonValue, JsonValue>['route'];\n onMessage?: (\n ctx: FinalMessageContextIface,\n message: ConversationMessageIface,\n ) => ChannelAdmissionIface | null | Promise<ChannelAdmissionIface | null>;\n onInputResponse?: (\n ctx: FinalMessageContextIface,\n response: ChannelInputResponseIface,\n ) => ChannelAdmissionIface | null | Promise<ChannelAdmissionIface | null>;\n events?: FinalChannelEventHandlersIface;\n renderer?: (\n update: SessionUpdate,\n channel: FinalChannelContextIface,\n ctx: FinalSessionContextIface,\n next: () => Promise<void>,\n ) => void | Promise<void>;\n}\n\nconst admissionSchema = z.object({\n auth: channelAuthSchema.nullable(),\n context: z.array(z.string()).optional(),\n title: z.string().optional(),\n});\n\nconst optionsSchema = z.object({\n turnPolicy: z.nativeEnum(TurnPolicy).default(TurnPolicy.Steer),\n updateIntervalMs: z.number().finite().nonnegative().optional(),\n});\n\n// A room member as a principal: a person by user id, an agent by definition id.\nconst defaultAuthOf = (\n author: import('@finalai/agent-provider').ParticipantIface | undefined,\n): ChannelAuthIface | null => {\n if (author == null) return null;\n return {\n principalId: author.userId ?? author.definitionId ?? author.id,\n principalType: author.userId == null ? ChannelPrincipalType.Service : ChannelPrincipalType.User,\n authenticator: 'final',\n displayName: author.displayName,\n attributes: { participant_id: author.id },\n };\n};\n\n// A handoff from another of the agent's channels (`ctx.to('final', target)`).\nconst handoffSchema = z.object({\n target: z.object({\n conversationId: z.string().min(1),\n participantId: z.string().min(1).optional(),\n }),\n content: z.array(jsonObjectSchema).min(1),\n idempotencyKey: z.string().min(1),\n auth: channelAuthSchema,\n context: z.array(z.string()).optional(),\n title: z.string().optional(),\n actingUserId: z.string().min(1).optional(),\n originTurnId: z.string().min(1).optional(),\n source: z.object({ label: z.string().min(1) }).optional(),\n turnPolicy: z.nativeEnum(TurnPolicy).optional(),\n});\n\nexport const finalChannel = (\n inputOptions: FinalChannelOptionsIface = {},\n): ChannelDefinitionIface<JsonValue, JsonValue> => {\n const options = {\n ...inputOptions,\n events: inputOptions.events == null ? undefined : { ...inputOptions.events },\n };\n const callbacks = {\n onMessage: options.onMessage,\n onInputResponse: options.onInputResponse,\n renderer: options.renderer,\n route: options.route,\n ...options.events,\n };\n for (const [name, callback] of Object.entries(callbacks))\n if (callback != null && !z.function().safeParse(callback).success)\n throw new Error(`Final channel ${name} must be a function`);\n const supportedEvents = new Set([\n 'message.delta',\n 'message.completed',\n 'turn.started',\n 'turn.completed',\n 'pending.created',\n 'pending.resolved',\n ]);\n for (const kind of Object.keys(options.events ?? {}))\n if (!supportedEvents.has(kind)) throw new Error(`unsupported Final channel event: ${kind}`);\n const config = optionsSchema.parse(options);\n const base = createMessagingChannel({ ...config, route: options.route });\n const receive: typeof base.receive = async (input, ctx) => {\n if (conversationEventInboundSchema.safeParse(input).success) return base.receive(input, ctx);\n const handoff = handoffSchema.safeParse(input);\n if (handoff.success) {\n if (ctx.platform.channelSessions == null)\n throw new Error('channel session operations are unavailable');\n const { target, ...rest } = handoff.data;\n await ctx.platform.channelSessions.send(target, {\n ...rest,\n content: contentBlocksOf(rest.content),\n source: rest.source,\n // The sender's policy, else the receiving channel's.\n turnPolicy: rest.turnPolicy ?? config.turnPolicy,\n });\n return { conversationId: target.conversationId };\n }\n const parsed = messageInboundSchema.parse(input);\n const participants =\n ctx.participants ?? (await ctx.platform.conversations.participants(parsed.conversationId));\n const author = participants.find(\n (participant) => participant.id === parsed.authorParticipantId,\n );\n const message =\n ctx.message ??\n (await ctx.platform.conversations.postMessage({\n ...parsed,\n content: contentBlocksOf(parsed.content),\n }));\n if (ctx.definitionId == null) throw new Error('Final channel has no agent definition');\n const messageContext: FinalMessageContextIface = {\n ...ctx,\n ...finalAddressContext({\n platform: ctx.platform,\n definitionId: ctx.definitionId,\n turnPolicy: config.turnPolicy,\n }),\n defaultAuth: defaultAuthOf(author),\n };\n const accepted =\n options.onMessage == null\n ? { auth: messageContext.defaultAuth }\n : await options.onMessage(messageContext, message);\n const admission = accepted == null ? null : admissionSchema.parse(accepted);\n if (admission == null) return { conversationId: parsed.conversationId };\n const context = admission.context ?? [];\n const injected: ContentBlock[] = context.map((text) => ({ type: 'text', text }));\n return base.receive(\n {\n ...parsed,\n content: [...context.map((text) => ({ type: 'text', text })), ...parsed.content],\n },\n {\n ...ctx,\n platform: {\n ...ctx.platform,\n sessions: {\n ...ctx.platform.sessions,\n prompt: (args) =>\n ctx.platform.sessions.prompt({\n ...args,\n auth: admission.auth,\n title: admission.title,\n }),\n },\n },\n message: { ...message, content: [...injected, ...message.content] },\n },\n );\n };\n const channelContext = (ctx: ProjectionContextIface): FinalChannelContextIface => {\n const { conversation, agentParticipant } = ctx;\n if (conversation == null || agentParticipant == null || agentParticipant.definitionId == null)\n throw new Error('Final platform context requires a Final conversation');\n return {\n ...finalAddressContext({\n platform: ctx.platform,\n definitionId: agentParticipant.definitionId,\n turnPolicy: config.turnPolicy,\n }),\n final: {\n post: async (message) => {\n if (ctx.platform.conversations.dispatchMessage == null)\n throw new Error('channel dispatch is unavailable');\n const posted = await ctx.platform.conversations.postMessage({\n conversationId: conversation.conversationId,\n authorParticipantId: agentParticipant.id,\n content: contentBlocksOf(message.content),\n clientMessageId: `channel:${ctx.turn.id}:${message.id}`,\n originTurnId: ctx.turn.id,\n });\n await ctx.platform.conversations.dispatchMessage({\n conversationId: posted.conversationId,\n messageId: posted.messageId,\n });\n return posted;\n },\n sendServiceInput: (input) => sendServiceInput(ctx.platform, input),\n },\n };\n };\n const sessionContext = (ctx: ProjectionContextIface): FinalSessionContextIface => ({\n sessionId: ctx.sessionId ?? null,\n turnId: ctx.turn.id,\n state: ctx.state,\n });\n const wrap = <Data>(\n schema: z.ZodType<Data>,\n handler: FinalChannelEventHandler<Data> | undefined,\n ): ChannelEventHandler | undefined =>\n handler == null\n ? undefined\n : async (event, ctx) =>\n handler(schema.parse(event.data), channelContext(ctx), sessionContext(ctx));\n const authoredEvents = {\n [SemanticChannelEventKind.MessageCompleted]: wrap(\n channelMessageCompletedSchema,\n options.events?.['message.completed'],\n ),\n [SemanticChannelEventKind.MessageDelta]: wrap(\n z.object({ messageId: z.string(), delta: jsonObjectSchema }),\n options.events?.['message.delta'],\n ),\n [SemanticChannelEventKind.TurnStarted]: wrap(\n z.object({ turnId: z.string() }),\n options.events?.['turn.started'],\n ),\n [SemanticChannelEventKind.TurnCompleted]: wrap(\n z.object({ turnId: z.string(), stopReason: z.string().nullable() }),\n options.events?.['turn.completed'],\n ),\n 'pending.created': wrap(pendingCreatedDataSchema, options.events?.['pending.created']),\n 'pending.resolved': wrap(pendingResolvedDataSchema, options.events?.['pending.resolved']),\n };\n const events = { ...base.events };\n for (const [kind, handler] of Object.entries(authoredEvents))\n if (handler != null) events[kind] = handler;\n return Object.freeze(\n defineChannel({\n ...base,\n config: jsonObjectSchema.parse(config),\n installed:\n options.onMessage == null &&\n options.onInputResponse == null &&\n options.events == null &&\n options.renderer == null &&\n options.route == null\n ? packageRef(FINAL_CHANNEL_SPECIFIER)\n : undefined,\n configure: (next) =>\n finalChannel({ ...options, ...optionsSchema.parse({ ...config, ...next }) }),\n receive,\n respond: async (input, ctx) => {\n const conversation = z.string().min(1).parse(ctx.conversationId);\n const participants = await ctx.platform.conversations.participants(conversation);\n const author = participants.find(\n (participant) => participant.id === input.actorParticipantId,\n );\n const defaultAuth = defaultAuthOf(author);\n let admission: ChannelAdmissionIface = { auth: defaultAuth };\n if (options.onInputResponse != null) {\n const accepted = await options.onInputResponse(\n { ...ctx, ...channelAccessors(ctx.platform), defaultAuth },\n input,\n );\n if (accepted == null) return { resolved: false };\n admission = admissionSchema.parse(accepted);\n }\n if (ctx.platform.sessions.respond == null)\n throw new Error('response submission is unavailable');\n return ctx.platform.sessions.respond({ ...input, auth: admission.auth });\n },\n cancel: async (ctx) => {\n if (ctx.agentParticipantId == null) return { accepted: false };\n const conversation = z.string().min(1).parse(ctx.conversationId);\n const participants = await ctx.platform.conversations.participants(conversation);\n const agent = participants.find((participant) => participant.id === ctx.agentParticipantId);\n if (agent?.sessionId == null) return { accepted: false };\n await ctx.platform.sessions.cancel({\n participantId: agent.id,\n reason: ctx.cancelReason,\n throughMessageSeq: ctx.cancelThroughMessageSeq,\n });\n return { accepted: true };\n },\n project: async (update, ctx) => {\n const next = () =>\n options.events?.['message.completed'] == null\n ? base.project(update, ctx)\n : Promise.resolve();\n if (options.renderer != null) {\n await options.renderer(update, channelContext(ctx), sessionContext(ctx), next);\n return;\n }\n await next();\n },\n events: Object.freeze(events),\n }),\n );\n};\n"],
|
|
5
|
-
"mappings": "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
|
|
4
|
+
"sourcesContent": ["import type { ContentBlock, SessionUpdate } from '@agentclientprotocol/sdk/experimental/v2';\nimport {\n ChannelPrincipalType,\n SemanticChannelEventKind,\n TurnPolicy,\n channelAccessors,\n channelAuthSchema,\n channelMessageCompletedSchema,\n decisionCreatedDataSchema,\n decisionResolvedDataSchema,\n defineChannel,\n jsonObjectSchema,\n packageRef,\n type ChannelAddressContextIface,\n type ChannelAuthIface,\n type ChannelDefinitionIface,\n type ChannelEventHandler,\n type ChannelInputReceiptIface,\n type ChannelInputResponseIface,\n type ChannelMessageCompletedDataIface,\n type ChannelMessageDeltaDataIface,\n type ChannelReceiveContextIface,\n type ChannelTurnEventDataIface,\n type ChannelTurnStateIface,\n type ConversationMessageIface,\n type DecisionCreatedDataIface,\n type DecisionResolvedDataIface,\n type JsonValue,\n type ProjectionContextIface,\n} from '@finalai/agent-provider';\nimport * as z from 'zod';\nimport { finalAddressContext } from \"./channels/address-context.mjs\";\nimport { contentBlocksOf } from \"./channels/content.mjs\";\nimport { conversationEventInboundSchema, messageInboundSchema } from \"./channels/inbound.mjs\";\nimport { createMessagingChannel } from \"./channels/messaging-channel.mjs\";\nimport { sendServiceInput, type ServiceInputArgsIface } from \"./channels/service-input.mjs\";\n\nexport const FINAL_CHANNEL_SPECIFIER = '@finalai/final-agent-provider/channels/final';\n\nexport { ChannelPrincipalType, type ChannelAuthIface } from '@finalai/agent-provider';\n\nexport interface ChannelAdmissionIface {\n auth: ChannelAuthIface | null;\n context?: string[];\n title?: string;\n}\n\nexport interface FinalMessageContextIface\n extends ChannelReceiveContextIface, ChannelAddressContextIface {\n defaultAuth: ChannelAuthIface | null;\n}\n\nexport interface FinalChannelContextIface extends ChannelAddressContextIface {\n final: {\n post(message: ChannelMessageCompletedDataIface['message']): Promise<ConversationMessageIface>;\n // Input to a room's agent from a principal that is no member of the room.\n sendServiceInput(args: ServiceInputArgsIface): Promise<ChannelInputReceiptIface>;\n };\n}\nexport interface FinalSessionContextIface {\n sessionId: string | null;\n turnId: string;\n state: ChannelTurnStateIface<JsonValue>;\n}\nexport type FinalChannelEventHandler<Data> = (\n data: Data,\n channel: FinalChannelContextIface,\n ctx: FinalSessionContextIface,\n) => void | Promise<void>;\nexport interface FinalChannelEventHandlersIface {\n 'message.delta'?: FinalChannelEventHandler<ChannelMessageDeltaDataIface>;\n 'message.completed'?: FinalChannelEventHandler<ChannelMessageCompletedDataIface>;\n 'turn.started'?: FinalChannelEventHandler<ChannelTurnEventDataIface>;\n 'turn.completed'?: FinalChannelEventHandler<ChannelTurnEventDataIface>;\n 'decision.created'?: FinalChannelEventHandler<DecisionCreatedDataIface>;\n 'decision.resolved'?: FinalChannelEventHandler<DecisionResolvedDataIface>;\n}\n\nexport interface FinalChannelOptionsIface {\n turnPolicy?: TurnPolicy | `${TurnPolicy}`;\n updateIntervalMs?: number;\n route?: ChannelDefinitionIface<JsonValue, JsonValue>['route'];\n onMessage?: (\n ctx: FinalMessageContextIface,\n message: ConversationMessageIface,\n ) => ChannelAdmissionIface | null | Promise<ChannelAdmissionIface | null>;\n onInputResponse?: (\n ctx: FinalMessageContextIface,\n response: ChannelInputResponseIface,\n ) => ChannelAdmissionIface | null | Promise<ChannelAdmissionIface | null>;\n events?: FinalChannelEventHandlersIface;\n renderer?: (\n update: SessionUpdate,\n channel: FinalChannelContextIface,\n ctx: FinalSessionContextIface,\n next: () => Promise<void>,\n ) => void | Promise<void>;\n}\n\nconst admissionSchema = z.object({\n auth: channelAuthSchema.nullable(),\n context: z.array(z.string()).optional(),\n title: z.string().optional(),\n});\n\nconst optionsSchema = z.object({\n turnPolicy: z.nativeEnum(TurnPolicy).default(TurnPolicy.Steer),\n updateIntervalMs: z.number().finite().nonnegative().optional(),\n});\n\n// A room member as a principal: a person by user id, an agent by definition id.\nconst defaultAuthOf = (\n author: import('@finalai/agent-provider').ParticipantIface | undefined,\n): ChannelAuthIface | null => {\n if (author == null) return null;\n return {\n principalId: author.userId ?? author.definitionId ?? author.id,\n principalType: author.userId == null ? ChannelPrincipalType.Service : ChannelPrincipalType.User,\n authenticator: 'final',\n displayName: author.displayName,\n attributes: { participant_id: author.id },\n };\n};\n\n// A handoff from another of the agent's channels (`ctx.to('final', target)`).\nconst handoffSchema = z.object({\n target: z.object({\n conversationId: z.string().min(1),\n participantId: z.string().min(1).optional(),\n }),\n content: z.array(jsonObjectSchema).min(1),\n idempotencyKey: z.string().min(1),\n auth: channelAuthSchema,\n context: z.array(z.string()).optional(),\n title: z.string().optional(),\n actingUserId: z.string().min(1).optional(),\n originTurnId: z.string().min(1).optional(),\n source: z.object({ label: z.string().min(1) }).optional(),\n turnPolicy: z.nativeEnum(TurnPolicy).optional(),\n});\n\nexport const finalChannel = (\n inputOptions: FinalChannelOptionsIface = {},\n): ChannelDefinitionIface<JsonValue, JsonValue> => {\n const options = {\n ...inputOptions,\n events: inputOptions.events == null ? undefined : { ...inputOptions.events },\n };\n const callbacks = {\n onMessage: options.onMessage,\n onInputResponse: options.onInputResponse,\n renderer: options.renderer,\n route: options.route,\n ...options.events,\n };\n for (const [name, callback] of Object.entries(callbacks))\n if (callback != null && !z.function().safeParse(callback).success)\n throw new Error(`Final channel ${name} must be a function`);\n const supportedEvents = new Set([\n 'message.delta',\n 'message.completed',\n 'turn.started',\n 'turn.completed',\n 'decision.created',\n 'decision.resolved',\n ]);\n for (const kind of Object.keys(options.events ?? {}))\n if (!supportedEvents.has(kind)) throw new Error(`unsupported Final channel event: ${kind}`);\n const config = optionsSchema.parse(options);\n const base = createMessagingChannel({ ...config, route: options.route });\n const receive: typeof base.receive = async (input, ctx) => {\n if (conversationEventInboundSchema.safeParse(input).success) return base.receive(input, ctx);\n const handoff = handoffSchema.safeParse(input);\n if (handoff.success) {\n if (ctx.platform.channelSessions == null)\n throw new Error('channel session operations are unavailable');\n const { target, ...rest } = handoff.data;\n await ctx.platform.channelSessions.send(target, {\n ...rest,\n content: contentBlocksOf(rest.content),\n source: rest.source,\n // The sender's policy, else the receiving channel's.\n turnPolicy: rest.turnPolicy ?? config.turnPolicy,\n });\n return { conversationId: target.conversationId };\n }\n const parsed = messageInboundSchema.parse(input);\n const participants =\n ctx.participants ?? (await ctx.platform.conversations.participants(parsed.conversationId));\n const author = participants.find(\n (participant) => participant.id === parsed.authorParticipantId,\n );\n const message =\n ctx.message ??\n (await ctx.platform.conversations.postMessage({\n ...parsed,\n content: contentBlocksOf(parsed.content),\n }));\n if (ctx.definitionId == null) throw new Error('Final channel has no agent definition');\n const messageContext: FinalMessageContextIface = {\n ...ctx,\n ...finalAddressContext({\n platform: ctx.platform,\n definitionId: ctx.definitionId,\n turnPolicy: config.turnPolicy,\n }),\n defaultAuth: defaultAuthOf(author),\n };\n const accepted =\n options.onMessage == null\n ? { auth: messageContext.defaultAuth }\n : await options.onMessage(messageContext, message);\n const admission = accepted == null ? null : admissionSchema.parse(accepted);\n if (admission == null) return { conversationId: parsed.conversationId };\n const context = admission.context ?? [];\n const injected: ContentBlock[] = context.map((text) => ({ type: 'text', text }));\n return base.receive(\n {\n ...parsed,\n content: [...context.map((text) => ({ type: 'text', text })), ...parsed.content],\n },\n {\n ...ctx,\n platform: {\n ...ctx.platform,\n sessions: {\n ...ctx.platform.sessions,\n prompt: (args) =>\n ctx.platform.sessions.prompt({\n ...args,\n auth: admission.auth,\n title: admission.title,\n }),\n },\n },\n message: { ...message, content: [...injected, ...message.content] },\n },\n );\n };\n const channelContext = (ctx: ProjectionContextIface): FinalChannelContextIface => {\n const { conversation, agentParticipant } = ctx;\n if (conversation == null || agentParticipant == null || agentParticipant.definitionId == null)\n throw new Error('Final platform context requires a Final conversation');\n return {\n ...finalAddressContext({\n platform: ctx.platform,\n definitionId: agentParticipant.definitionId,\n turnPolicy: config.turnPolicy,\n }),\n final: {\n post: async (message) => {\n if (ctx.platform.conversations.dispatchMessage == null)\n throw new Error('channel dispatch is unavailable');\n const posted = await ctx.platform.conversations.postMessage({\n conversationId: conversation.conversationId,\n authorParticipantId: agentParticipant.id,\n content: contentBlocksOf(message.content),\n clientMessageId: `channel:${ctx.turn.id}:${message.id}`,\n originTurnId: ctx.turn.id,\n });\n await ctx.platform.conversations.dispatchMessage({\n conversationId: posted.conversationId,\n messageId: posted.messageId,\n });\n return posted;\n },\n sendServiceInput: (input) => sendServiceInput(ctx.platform, input),\n },\n };\n };\n const sessionContext = (ctx: ProjectionContextIface): FinalSessionContextIface => ({\n sessionId: ctx.sessionId ?? null,\n turnId: ctx.turn.id,\n state: ctx.state,\n });\n const wrap = <Data>(\n schema: z.ZodType<Data>,\n handler: FinalChannelEventHandler<Data> | undefined,\n ): ChannelEventHandler | undefined =>\n handler == null\n ? undefined\n : async (event, ctx) =>\n handler(schema.parse(event.data), channelContext(ctx), sessionContext(ctx));\n const authoredEvents = {\n [SemanticChannelEventKind.MessageCompleted]: wrap(\n channelMessageCompletedSchema,\n options.events?.['message.completed'],\n ),\n [SemanticChannelEventKind.MessageDelta]: wrap(\n z.object({ messageId: z.string(), delta: jsonObjectSchema }),\n options.events?.['message.delta'],\n ),\n [SemanticChannelEventKind.TurnStarted]: wrap(\n z.object({ turnId: z.string() }),\n options.events?.['turn.started'],\n ),\n [SemanticChannelEventKind.TurnCompleted]: wrap(\n z.object({ turnId: z.string(), stopReason: z.string().nullable() }),\n options.events?.['turn.completed'],\n ),\n 'decision.created': wrap(decisionCreatedDataSchema, options.events?.['decision.created']),\n 'decision.resolved': wrap(decisionResolvedDataSchema, options.events?.['decision.resolved']),\n };\n const events = { ...base.events };\n for (const [kind, handler] of Object.entries(authoredEvents))\n if (handler != null) events[kind] = handler;\n return Object.freeze(\n defineChannel({\n ...base,\n config: jsonObjectSchema.parse(config),\n installed:\n options.onMessage == null &&\n options.onInputResponse == null &&\n options.events == null &&\n options.renderer == null &&\n options.route == null\n ? packageRef(FINAL_CHANNEL_SPECIFIER)\n : undefined,\n configure: (next) =>\n finalChannel({ ...options, ...optionsSchema.parse({ ...config, ...next }) }),\n receive,\n respond: async (input, ctx) => {\n const conversation = z.string().min(1).parse(ctx.conversationId);\n const participants = await ctx.platform.conversations.participants(conversation);\n const author = participants.find(\n (participant) => participant.id === input.actorParticipantId,\n );\n const defaultAuth = defaultAuthOf(author);\n let admission: ChannelAdmissionIface = { auth: defaultAuth };\n if (options.onInputResponse != null) {\n const accepted = await options.onInputResponse(\n { ...ctx, ...channelAccessors(ctx.platform), defaultAuth },\n input,\n );\n if (accepted == null) return { resolved: false };\n admission = admissionSchema.parse(accepted);\n }\n if (ctx.platform.sessions.respond == null)\n throw new Error('response submission is unavailable');\n return ctx.platform.sessions.respond({ ...input, auth: admission.auth });\n },\n cancel: async (ctx) => {\n if (ctx.agentParticipantId == null) return { accepted: false };\n const conversation = z.string().min(1).parse(ctx.conversationId);\n const participants = await ctx.platform.conversations.participants(conversation);\n const agent = participants.find((participant) => participant.id === ctx.agentParticipantId);\n if (agent?.sessionId == null) return { accepted: false };\n await ctx.platform.sessions.cancel({\n participantId: agent.id,\n reason: ctx.cancelReason,\n throughMessageSeq: ctx.cancelThroughMessageSeq,\n });\n return { accepted: true };\n },\n project: async (update, ctx) => {\n const next = () =>\n options.events?.['message.completed'] == null\n ? base.project(update, ctx)\n : Promise.resolve();\n if (options.renderer != null) {\n await options.renderer(update, channelContext(ctx), sessionContext(ctx), next);\n return;\n }\n await next();\n },\n events: Object.freeze(events),\n }),\n );\n};\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["ChannelPrincipalType"]
|
|
7
7
|
}
|
|
@@ -51,7 +51,7 @@ const linkedConversationEventSchema = z.object({
|
|
|
51
51
|
event: z.nativeEnum(LinkedConversationEvent),
|
|
52
52
|
// The reply (Replied) or what the agent asks for (WaitingForPerson).
|
|
53
53
|
text: z.string().nullish(),
|
|
54
|
-
// Makes a redelivered event post once (the turn or
|
|
54
|
+
// Makes a redelivered event post once (the turn or decision).
|
|
55
55
|
eventId: z.string().min(1),
|
|
56
56
|
originTurnId: z.string().nullish()
|
|
57
57
|
});
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../../src/channels/agent-events.ts"],
|
|
4
|
-
"sourcesContent": ["import type { ContentBlock } from '@agentclientprotocol/sdk/experimental/v2';\nimport {\n defineChannel,\n Delivery,\n jsonObjectSchema,\n jsonValueSchema,\n ParticipantKind,\n SandboxEventKind,\n TurnPolicy,\n type ChannelDefinitionIface,\n type ChannelReceiveContextIface,\n type ConversationIface,\n type ConversationRefIface,\n type JsonValue,\n type RouteArgsIface,\n type RouteDecisionIface,\n type RouteDefinitionIface,\n} from '@finalai/agent-provider';\nimport * as z from 'zod';\nimport { contentBlocksOf } from \"./content.mjs\";\nimport { textBlock } from \"./prompt.mjs\";\nimport { routeMessage } from \"./routing.mjs\";\nimport { sendServiceInput, type ServiceInputArgsIface } from \"./service-input.mjs\";\n\nexport const AGENT_EVENTS_SPECIFIER = '@finalai/final-agent-provider/channels/agent-events';\nexport const AGENT_EVENTS_TURN_POLICY = TurnPolicy.Steer;\n\n// The binding secret the webhook route verifies with (the binding's\n// `webhook_secret_ref`, resolved by the session service's secrets seam).\nexport const WEBHOOK_SECRET_NAME = 'webhook';\nexport const WEBHOOK_BODY_MAX_CHARS = 8_000;\n\nexport enum AgentEventKind {\n Webhook = 'webhook',\n LinkedConversation = 'linked-conversation',\n // A sandbox's result that arrives after the turn that started the work.\n Sandbox = 'sandbox',\n}\n\nexport { SandboxEventKind } from '@finalai/agent-provider';\n\nexport const SYSTEM_EVENT_TEXT_MAX_CHARS = 4_000;\n\n// What happened in a linked conversation (one a conversation handed work to).\nexport enum LinkedConversationEvent {\n // Its agent ended a turn with a reply.\n Replied = 'replied',\n // Its agent asked for a permission or an answer.\n WaitingForPerson = 'waiting_for_person',\n // Its agent's turn ended without a reply because it failed.\n Failed = 'failed',\n}\n\nexport const LINKED_CONVERSATION_TEXT_MAX_CHARS = 4_000;\n\nconst webhookEventSchema = z.object({\n kind: z.literal(AgentEventKind.Webhook),\n body: z.string(),\n contentType: z.string().nullish(),\n // A provider event name when the sender gives one (`x-github-event`).\n event: z.string().nullish(),\n deliveryId: z.string().nullish(),\n});\n\n// Input to the conversation that linked another, from the link, so the agent\n// there hears about work it handed off.\nconst linkedConversationEventSchema = z.object({\n kind: z.literal(AgentEventKind.LinkedConversation),\n // The conversation that linked the other: where its agent is prompted.\n conversationId: z.string().min(1),\n // The agent that handed the work off; the Default agent when absent.\n participantId: z.string().min(1).nullish(),\n linkId: z.string().min(1),\n linkedConversationId: z.string().min(1),\n linkedTitle: z.string().nullish(),\n event: z.nativeEnum(LinkedConversationEvent),\n // The reply (Replied) or what the agent asks for (WaitingForPerson).\n text: z.string().nullish(),\n // Makes a redelivered event post once (the turn or pending request).\n eventId: z.string().min(1),\n originTurnId: z.string().nullish(),\n});\n\n// Input from the sandbox binding to the agent whose session started the process.\nconst sandboxEventSchema = z.object({\n kind: z.literal(AgentEventKind.Sandbox),\n conversationId: z.string().min(1),\n // The agent participant whose session started the process: the only one told.\n participantId: z.string().min(1).nullish(),\n bindingId: z.string().min(1),\n sandboxName: z.string().nullish(),\n event: z.nativeEnum(SandboxEventKind),\n processId: z.string().min(1),\n command: z.string(),\n // Null when the sandbox could not report one (the process was lost).\n exitCode: z.number().int().nullable(),\n // The end of the process's output.\n stdout: z.string().nullish(),\n stderr: z.string().nullish(),\n // Makes a redelivered event post once (per binding).\n eventId: z.string().min(1),\n});\n\nexport const agentEventInboundSchema = z.discriminatedUnion('kind', [\n webhookEventSchema,\n linkedConversationEventSchema,\n sandboxEventSchema,\n]);\n\nexport type SandboxEventInboundIface = z.infer<typeof sandboxEventSchema>;\n\nexport type AgentEventInboundIface = z.infer<typeof agentEventInboundSchema>;\n\nexport enum ReceiveTargetKind {\n // The conversation the channel binding is attached to.\n BoundConversation = 'bound-conversation',\n // The agent owner's direct conversation with the agent.\n OwnerDirect = 'owner-direct',\n}\n\n// What a channel route hands to the default `receive`: content for the\n// binding's agent in a target conversation, as input from the binding.\nexport const targetedInboundSchema = z.object({\n target: z.object({ kind: z.nativeEnum(ReceiveTargetKind) }),\n content: z.array(jsonObjectSchema).min(1),\n // Makes a redelivered input count once.\n deliveryId: z.string().min(1).nullish(),\n});\n\nexport type TargetedInboundIface = z.infer<typeof targetedInboundSchema>;\n\nconst configSchema = z.looseObject({\n displayName: z.string().min(1).nullish(),\n // Owner direct conversation when the binding is attached to none; null for\n // organization-owned agents, whose webhooks need a bound conversation.\n ownerUserId: z.string().min(1).nullish(),\n});\n\nconst renderBody = (body: string, contentType: string | null): string => {\n let rendered = body;\n if (contentType?.includes('json') === true) {\n try {\n rendered = JSON.stringify(jsonValueSchema.parse(JSON.parse(body)), null, 2);\n } catch {\n rendered = body;\n }\n }\n return rendered.length <= WEBHOOK_BODY_MAX_CHARS\n ? rendered\n : `${rendered.slice(0, WEBHOOK_BODY_MAX_CHARS)}\\n\u2026 (truncated)`;\n};\n\nconst boundConversation = async (\n ctx: ChannelReceiveContextIface,\n): Promise<ConversationIface | null> =>\n ctx.bindingId == null ? null : ctx.platform.conversations.boundTo(ctx.bindingId);\n\nconst ownerDirectConversation = async (\n ctx: ChannelReceiveContextIface,\n): Promise<ConversationIface> => {\n const config = configSchema.parse(ctx.config);\n if (config.ownerUserId == null || ctx.definitionId == null) {\n throw new Error(\n `channel binding ${ctx.bindingId ?? '(none)'} is attached to no conversation and its agent has no owner to post to`,\n );\n }\n return ctx.platform.conversations.findOrCreateDirect({\n organizationId: ctx.organizationId,\n userId: config.ownerUserId,\n definitionId: ctx.definitionId,\n });\n};\n\nconst webhookConversation = async (ctx: ChannelReceiveContextIface): Promise<ConversationIface> =>\n (await boundConversation(ctx)) ?? ownerDirectConversation(ctx);\n\nconst targetConversation = async (\n target: ReceiveTargetKind,\n ctx: ChannelReceiveContextIface,\n): Promise<ConversationIface> => {\n if (target === ReceiveTargetKind.OwnerDirect) return ownerDirectConversation(ctx);\n const bound = await boundConversation(ctx);\n if (bound == null) {\n throw new Error(`channel binding ${ctx.bindingId ?? '(none)'} is attached to no conversation`);\n }\n return bound;\n};\n\n// The binding's own agent in the conversation its input goes to.\nconst bindingAgent = async (\n conversation: ConversationIface,\n ctx: ChannelReceiveContextIface,\n): Promise<string> => {\n const agent = (await ctx.platform.conversations.participants(conversation.conversationId)).find(\n (participant) =>\n participant.kind === ParticipantKind.Agent &&\n !participant.left &&\n participant.definitionId === ctx.definitionId,\n );\n if (agent == null) {\n throw new Error(\n `channel binding ${ctx.bindingId ?? '(none)'} has no agent in conversation ${conversation.conversationId}`,\n );\n }\n return agent.id;\n};\n\n// Input from the binding (a webhook or an authored route) to its agent.\nconst sendBindingInput = async (args: {\n ctx: ChannelReceiveContextIface;\n conversation: ConversationIface;\n content: ContentBlock[];\n deliveryKey: string | null;\n turnPolicy?: TurnPolicy;\n}): Promise<ConversationRefIface> => {\n const binding = args.ctx.bindingId ?? 'none';\n const name = configSchema.parse(args.ctx.config).displayName ?? 'Webhook';\n await sendServiceInput(args.ctx.platform, {\n room: args.conversation.conversationId,\n participantId: await bindingAgent(args.conversation, args.ctx),\n content: args.content,\n principal: { principalId: `binding:${binding}`, authenticator: 'final' },\n displayName: name,\n idempotencyKey: `webhook:${binding}:${args.deliveryKey ?? crypto.randomUUID()}`,\n label: `From ${name}`,\n turnPolicy: args.turnPolicy,\n });\n return { conversationId: args.conversation.conversationId };\n};\n\nexport type ChannelReceiveIface = (\n input: JsonValue,\n ctx: ChannelReceiveContextIface,\n) => Promise<ConversationRefIface>;\n\n// The receive of a custom channel that authors none: targeted content\n// (`{target, content}`), input to the binding's agent there under the\n// channel's turnPolicy.\nexport const createTargetedInputReceive =\n (turnPolicy: TurnPolicy = TurnPolicy.Steer): ChannelReceiveIface =>\n async (input, ctx) => {\n const targeted = targetedInboundSchema.parse(input);\n return sendBindingInput({\n ctx,\n conversation: await targetConversation(targeted.target.kind, ctx),\n content: contentBlocksOf(targeted.content),\n deliveryKey: targeted.deliveryId ?? null,\n turnPolicy,\n });\n };\n\nconst receiveTargetedInput = createTargetedInputReceive(AGENT_EVENTS_TURN_POLICY);\n\nconst clip = (text: string): string =>\n text.length <= LINKED_CONVERSATION_TEXT_MAX_CHARS\n ? text\n : `${text.slice(0, LINKED_CONVERSATION_TEXT_MAX_CHARS)}\\n\u2026 (truncated)`;\n\nexport const renderLinkedConversationEvent = (\n event: Pick<z.infer<typeof linkedConversationEventSchema>, 'linkedTitle' | 'event' | 'text'>,\n): string => {\n const title = event.linkedTitle?.trim() ?? '';\n const name = title.length === 0 ? 'A linked conversation' : `\"${title}\"`;\n const text = event.text?.trim() ?? '';\n switch (event.event) {\n case LinkedConversationEvent.Replied:\n return text.length === 0 ? `${name} replied.` : `${name} replied:\\n\\n${clip(text)}`;\n case LinkedConversationEvent.WaitingForPerson:\n return text.length === 0\n ? `${name} is waiting for a person.`\n : `${name} is waiting for a person: ${clip(text)}`;\n case LinkedConversationEvent.Failed:\n return text.length === 0\n ? `${name} stopped with an error.`\n : `${name} stopped with an error.\\n\\n${clip(text)}`;\n }\n};\n\n// Input from the link (the result of work handed off) to the agent that handed it off.\nconst receiveLinkedConversationEvent = async (\n event: z.infer<typeof linkedConversationEventSchema>,\n ctx: ChannelReceiveContextIface,\n): Promise<ConversationRefIface> => {\n const title = event.linkedTitle?.trim() ?? '';\n await sendServiceInput(ctx.platform, {\n room: event.conversationId,\n participantId: event.participantId ?? undefined,\n content: [textBlock(renderLinkedConversationEvent(event))],\n principal: { principalId: `link:${event.linkId}`, authenticator: 'final' },\n displayName: title.length === 0 ? 'Linked conversation' : title,\n originTurnId: event.originTurnId ?? undefined,\n idempotencyKey: `link:${event.linkId}:${event.eventId}`,\n label: title.length === 0 ? 'From a linked conversation' : `From \u201C${title}\u201D`,\n });\n return { conversationId: event.conversationId };\n};\n\nconst clipEnd = (text: string): string =>\n text.length <= SYSTEM_EVENT_TEXT_MAX_CHARS\n ? text\n : `\u2026 (truncated)\\n${text.slice(text.length - SYSTEM_EVENT_TEXT_MAX_CHARS)}`;\n\nconst outputSection = (label: string, output: string | null | undefined): string[] => {\n const text = output?.trimEnd() ?? '';\n return text.length === 0 ? [] : [`${label}:\\n\\`\\`\\`\\n${clipEnd(text)}\\n\\`\\`\\``];\n};\n\nexport const renderSandboxEvent = (\n event: Pick<SandboxEventInboundIface, 'processId' | 'command' | 'exitCode' | 'stdout' | 'stderr'>,\n): string => {\n const outcome =\n event.exitCode == null ? 'stopped without an exit code' : `exited with code ${event.exitCode}`;\n return [\n `Background process ${event.processId} (\\`${event.command}\\`) ${outcome}.`,\n ...outputSection('stdout', event.stdout),\n ...outputSection('stderr', event.stderr),\n ].join('\\n\\n');\n};\n\n// A result belongs to the session that produced it: that agent is prompted and\n// nobody observes it, so one agent's process output never reaches another\n// agent's history (a group's Default or All agents included).\nexport const routeToOwner =\n (participantId: string) =>\n (args: RouteArgsIface): RouteDecisionIface[] =>\n args.participants.some(\n (participant) =>\n participant.id === participantId &&\n participant.kind === ParticipantKind.Agent &&\n !participant.left,\n )\n ? [{ participantId, delivery: Delivery.Prompt }]\n : [];\n\nconst nonEmptyOr = (value: string | null | undefined, fallback: string): string => {\n const trimmed = value?.trim() ?? '';\n return trimmed.length === 0 ? fallback : trimmed;\n};\n\nconst receiveSandboxEvent = async (\n event: SandboxEventInboundIface,\n ctx: ChannelReceiveContextIface,\n): Promise<ConversationRefIface> => {\n const name = nonEmptyOr(event.sandboxName, 'Sandbox');\n const args: ServiceInputArgsIface = {\n room: event.conversationId,\n participantId: event.participantId ?? undefined,\n content: [textBlock(renderSandboxEvent(event))],\n principal: { principalId: `sandbox:${event.bindingId}`, authenticator: 'final' },\n displayName: name,\n idempotencyKey: `sandbox:${event.bindingId}:${event.eventId}`,\n label: `After a process in ${name} finished`,\n };\n await sendServiceInput(ctx.platform, args);\n return { conversationId: event.conversationId };\n};\n\n// agent-events' receive: a webhook, a linked conversation's event, a sandbox\n// result, or targeted content, each input to one agent. Outside systems\n// (Final's Goals among them) post conversation events through the public API instead.\nexport const receiveAgentEvent: ChannelReceiveIface = async (input, ctx) => {\n if (targetedInboundSchema.safeParse(input).success) return receiveTargetedInput(input, ctx);\n const event = agentEventInboundSchema.parse(input);\n if (event.kind === AgentEventKind.Webhook) {\n const name = configSchema.parse(ctx.config).displayName ?? 'Webhook';\n const heading = event.event == null ? `${name} event` : `${name} event: ${event.event}`;\n return sendBindingInput({\n ctx,\n conversation: await webhookConversation(ctx),\n content: [textBlock(`${heading}\\n\\n${renderBody(event.body, event.contentType ?? null)}`)],\n deliveryKey: event.deliveryId ?? null,\n });\n }\n if (event.kind === AgentEventKind.LinkedConversation) {\n return receiveLinkedConversationEvent(event, ctx);\n }\n return receiveSandboxEvent(event, ctx);\n};\n\nconst hex = (bytes: ArrayBuffer): string =>\n [...new Uint8Array(bytes)].map((byte) => byte.toString(16).padStart(2, '0')).join('');\n\nconst constantTimeEqual = (left: string, right: string): boolean => {\n if (left.length !== right.length) return false;\n let difference = 0;\n for (let index = 0; index < left.length; index += 1) {\n difference |= left.charCodeAt(index) ^ right.charCodeAt(index);\n }\n return difference === 0;\n};\n\nexport const hmacSha256Hex = async (secret: string, body: string): Promise<string> => {\n const encoder = new TextEncoder();\n const key = await crypto.subtle.importKey(\n 'raw',\n encoder.encode(secret),\n { name: 'HMAC', hash: 'SHA-256' },\n false,\n ['sign'],\n );\n return hex(await crypto.subtle.sign('HMAC', key, encoder.encode(body)));\n};\n\n// `sha256=<hex>` in `x-final-signature` or GitHub's `x-hub-signature-256`.\nexport const verifyWebhookSignature = async (args: {\n secret: string;\n body: string;\n headers: Headers;\n}): Promise<boolean> => {\n const header = args.headers.get('x-final-signature') ?? args.headers.get('x-hub-signature-256');\n if (header == null) return false;\n const provided = header.startsWith('sha256=') ? header.slice('sha256='.length) : header;\n return constantTimeEqual(provided.toLowerCase(), await hmacSha256Hex(args.secret, args.body));\n};\n\nconst webhookRoute: RouteDefinitionIface = {\n method: 'POST',\n path: '/',\n handler: async ({ request, secrets, receive }) => {\n const secret = await secrets.get(WEBHOOK_SECRET_NAME);\n if (secret == null) {\n return Response.json({ error: 'webhook secret is not configured' }, { status: 503 });\n }\n const body = await request.text();\n if (!(await verifyWebhookSignature({ secret, body, headers: request.headers }))) {\n return Response.json({ error: 'invalid signature' }, { status: 401 });\n }\n const ref = await receive({\n kind: AgentEventKind.Webhook,\n body,\n contentType: request.headers.get('content-type'),\n event: request.headers.get('x-github-event') ?? request.headers.get('x-final-event'),\n deliveryId:\n request.headers.get('x-github-delivery') ?? request.headers.get('x-final-delivery'),\n });\n if (ref == null || !('conversationId' in ref))\n throw new Error('agent event channel returned no conversation');\n return Response.json({ ok: true, conversationId: ref.conversationId }, { status: 202 });\n },\n};\n\n// Its inputs go to agents in conversations whose own channel (direct or\n// group messaging) projects the replies, so this channel projects nothing.\nexport const createAgentEventsChannel = (): ChannelDefinitionIface<JsonValue, JsonValue> =>\n defineChannel<JsonValue, JsonValue>({\n routes: [webhookRoute],\n receive: receiveAgentEvent,\n route: routeMessage,\n turnPolicy: AGENT_EVENTS_TURN_POLICY,\n project: async () => {},\n });\n"],
|
|
4
|
+
"sourcesContent": ["import type { ContentBlock } from '@agentclientprotocol/sdk/experimental/v2';\nimport {\n defineChannel,\n Delivery,\n jsonObjectSchema,\n jsonValueSchema,\n ParticipantKind,\n SandboxEventKind,\n TurnPolicy,\n type ChannelDefinitionIface,\n type ChannelReceiveContextIface,\n type ConversationIface,\n type ConversationRefIface,\n type JsonValue,\n type RouteArgsIface,\n type RouteDecisionIface,\n type RouteDefinitionIface,\n} from '@finalai/agent-provider';\nimport * as z from 'zod';\nimport { contentBlocksOf } from \"./content.mjs\";\nimport { textBlock } from \"./prompt.mjs\";\nimport { routeMessage } from \"./routing.mjs\";\nimport { sendServiceInput, type ServiceInputArgsIface } from \"./service-input.mjs\";\n\nexport const AGENT_EVENTS_SPECIFIER = '@finalai/final-agent-provider/channels/agent-events';\nexport const AGENT_EVENTS_TURN_POLICY = TurnPolicy.Steer;\n\n// The binding secret the webhook route verifies with (the binding's\n// `webhook_secret_ref`, resolved by the session service's secrets seam).\nexport const WEBHOOK_SECRET_NAME = 'webhook';\nexport const WEBHOOK_BODY_MAX_CHARS = 8_000;\n\nexport enum AgentEventKind {\n Webhook = 'webhook',\n LinkedConversation = 'linked-conversation',\n // A sandbox's result that arrives after the turn that started the work.\n Sandbox = 'sandbox',\n}\n\nexport { SandboxEventKind } from '@finalai/agent-provider';\n\nexport const SYSTEM_EVENT_TEXT_MAX_CHARS = 4_000;\n\n// What happened in a linked conversation (one a conversation handed work to).\nexport enum LinkedConversationEvent {\n // Its agent ended a turn with a reply.\n Replied = 'replied',\n // Its agent asked for a permission or an answer.\n WaitingForPerson = 'waiting_for_person',\n // Its agent's turn ended without a reply because it failed.\n Failed = 'failed',\n}\n\nexport const LINKED_CONVERSATION_TEXT_MAX_CHARS = 4_000;\n\nconst webhookEventSchema = z.object({\n kind: z.literal(AgentEventKind.Webhook),\n body: z.string(),\n contentType: z.string().nullish(),\n // A provider event name when the sender gives one (`x-github-event`).\n event: z.string().nullish(),\n deliveryId: z.string().nullish(),\n});\n\n// Input to the conversation that linked another, from the link, so the agent\n// there hears about work it handed off.\nconst linkedConversationEventSchema = z.object({\n kind: z.literal(AgentEventKind.LinkedConversation),\n // The conversation that linked the other: where its agent is prompted.\n conversationId: z.string().min(1),\n // The agent that handed the work off; the Default agent when absent.\n participantId: z.string().min(1).nullish(),\n linkId: z.string().min(1),\n linkedConversationId: z.string().min(1),\n linkedTitle: z.string().nullish(),\n event: z.nativeEnum(LinkedConversationEvent),\n // The reply (Replied) or what the agent asks for (WaitingForPerson).\n text: z.string().nullish(),\n // Makes a redelivered event post once (the turn or decision).\n eventId: z.string().min(1),\n originTurnId: z.string().nullish(),\n});\n\n// Input from the sandbox binding to the agent whose session started the process.\nconst sandboxEventSchema = z.object({\n kind: z.literal(AgentEventKind.Sandbox),\n conversationId: z.string().min(1),\n // The agent participant whose session started the process: the only one told.\n participantId: z.string().min(1).nullish(),\n bindingId: z.string().min(1),\n sandboxName: z.string().nullish(),\n event: z.nativeEnum(SandboxEventKind),\n processId: z.string().min(1),\n command: z.string(),\n // Null when the sandbox could not report one (the process was lost).\n exitCode: z.number().int().nullable(),\n // The end of the process's output.\n stdout: z.string().nullish(),\n stderr: z.string().nullish(),\n // Makes a redelivered event post once (per binding).\n eventId: z.string().min(1),\n});\n\nexport const agentEventInboundSchema = z.discriminatedUnion('kind', [\n webhookEventSchema,\n linkedConversationEventSchema,\n sandboxEventSchema,\n]);\n\nexport type SandboxEventInboundIface = z.infer<typeof sandboxEventSchema>;\n\nexport type AgentEventInboundIface = z.infer<typeof agentEventInboundSchema>;\n\nexport enum ReceiveTargetKind {\n // The conversation the channel binding is attached to.\n BoundConversation = 'bound-conversation',\n // The agent owner's direct conversation with the agent.\n OwnerDirect = 'owner-direct',\n}\n\n// What a channel route hands to the default `receive`: content for the\n// binding's agent in a target conversation, as input from the binding.\nexport const targetedInboundSchema = z.object({\n target: z.object({ kind: z.nativeEnum(ReceiveTargetKind) }),\n content: z.array(jsonObjectSchema).min(1),\n // Makes a redelivered input count once.\n deliveryId: z.string().min(1).nullish(),\n});\n\nexport type TargetedInboundIface = z.infer<typeof targetedInboundSchema>;\n\nconst configSchema = z.looseObject({\n displayName: z.string().min(1).nullish(),\n // Owner direct conversation when the binding is attached to none; null for\n // organization-owned agents, whose webhooks need a bound conversation.\n ownerUserId: z.string().min(1).nullish(),\n});\n\nconst renderBody = (body: string, contentType: string | null): string => {\n let rendered = body;\n if (contentType?.includes('json') === true) {\n try {\n rendered = JSON.stringify(jsonValueSchema.parse(JSON.parse(body)), null, 2);\n } catch {\n rendered = body;\n }\n }\n return rendered.length <= WEBHOOK_BODY_MAX_CHARS\n ? rendered\n : `${rendered.slice(0, WEBHOOK_BODY_MAX_CHARS)}\\n\u2026 (truncated)`;\n};\n\nconst boundConversation = async (\n ctx: ChannelReceiveContextIface,\n): Promise<ConversationIface | null> =>\n ctx.bindingId == null ? null : ctx.platform.conversations.boundTo(ctx.bindingId);\n\nconst ownerDirectConversation = async (\n ctx: ChannelReceiveContextIface,\n): Promise<ConversationIface> => {\n const config = configSchema.parse(ctx.config);\n if (config.ownerUserId == null || ctx.definitionId == null) {\n throw new Error(\n `channel binding ${ctx.bindingId ?? '(none)'} is attached to no conversation and its agent has no owner to post to`,\n );\n }\n return ctx.platform.conversations.findOrCreateDirect({\n organizationId: ctx.organizationId,\n userId: config.ownerUserId,\n definitionId: ctx.definitionId,\n });\n};\n\nconst webhookConversation = async (ctx: ChannelReceiveContextIface): Promise<ConversationIface> =>\n (await boundConversation(ctx)) ?? ownerDirectConversation(ctx);\n\nconst targetConversation = async (\n target: ReceiveTargetKind,\n ctx: ChannelReceiveContextIface,\n): Promise<ConversationIface> => {\n if (target === ReceiveTargetKind.OwnerDirect) return ownerDirectConversation(ctx);\n const bound = await boundConversation(ctx);\n if (bound == null) {\n throw new Error(`channel binding ${ctx.bindingId ?? '(none)'} is attached to no conversation`);\n }\n return bound;\n};\n\n// The binding's own agent in the conversation its input goes to.\nconst bindingAgent = async (\n conversation: ConversationIface,\n ctx: ChannelReceiveContextIface,\n): Promise<string> => {\n const agent = (await ctx.platform.conversations.participants(conversation.conversationId)).find(\n (participant) =>\n participant.kind === ParticipantKind.Agent &&\n !participant.left &&\n participant.definitionId === ctx.definitionId,\n );\n if (agent == null) {\n throw new Error(\n `channel binding ${ctx.bindingId ?? '(none)'} has no agent in conversation ${conversation.conversationId}`,\n );\n }\n return agent.id;\n};\n\n// Input from the binding (a webhook or an authored route) to its agent.\nconst sendBindingInput = async (args: {\n ctx: ChannelReceiveContextIface;\n conversation: ConversationIface;\n content: ContentBlock[];\n deliveryKey: string | null;\n turnPolicy?: TurnPolicy;\n}): Promise<ConversationRefIface> => {\n const binding = args.ctx.bindingId ?? 'none';\n const name = configSchema.parse(args.ctx.config).displayName ?? 'Webhook';\n await sendServiceInput(args.ctx.platform, {\n room: args.conversation.conversationId,\n participantId: await bindingAgent(args.conversation, args.ctx),\n content: args.content,\n principal: { principalId: `binding:${binding}`, authenticator: 'final' },\n displayName: name,\n idempotencyKey: `webhook:${binding}:${args.deliveryKey ?? crypto.randomUUID()}`,\n label: `From ${name}`,\n turnPolicy: args.turnPolicy,\n });\n return { conversationId: args.conversation.conversationId };\n};\n\nexport type ChannelReceiveIface = (\n input: JsonValue,\n ctx: ChannelReceiveContextIface,\n) => Promise<ConversationRefIface>;\n\n// The receive of a custom channel that authors none: targeted content\n// (`{target, content}`), input to the binding's agent there under the\n// channel's turnPolicy.\nexport const createTargetedInputReceive =\n (turnPolicy: TurnPolicy = TurnPolicy.Steer): ChannelReceiveIface =>\n async (input, ctx) => {\n const targeted = targetedInboundSchema.parse(input);\n return sendBindingInput({\n ctx,\n conversation: await targetConversation(targeted.target.kind, ctx),\n content: contentBlocksOf(targeted.content),\n deliveryKey: targeted.deliveryId ?? null,\n turnPolicy,\n });\n };\n\nconst receiveTargetedInput = createTargetedInputReceive(AGENT_EVENTS_TURN_POLICY);\n\nconst clip = (text: string): string =>\n text.length <= LINKED_CONVERSATION_TEXT_MAX_CHARS\n ? text\n : `${text.slice(0, LINKED_CONVERSATION_TEXT_MAX_CHARS)}\\n\u2026 (truncated)`;\n\nexport const renderLinkedConversationEvent = (\n event: Pick<z.infer<typeof linkedConversationEventSchema>, 'linkedTitle' | 'event' | 'text'>,\n): string => {\n const title = event.linkedTitle?.trim() ?? '';\n const name = title.length === 0 ? 'A linked conversation' : `\"${title}\"`;\n const text = event.text?.trim() ?? '';\n switch (event.event) {\n case LinkedConversationEvent.Replied:\n return text.length === 0 ? `${name} replied.` : `${name} replied:\\n\\n${clip(text)}`;\n case LinkedConversationEvent.WaitingForPerson:\n return text.length === 0\n ? `${name} is waiting for a person.`\n : `${name} is waiting for a person: ${clip(text)}`;\n case LinkedConversationEvent.Failed:\n return text.length === 0\n ? `${name} stopped with an error.`\n : `${name} stopped with an error.\\n\\n${clip(text)}`;\n }\n};\n\n// Input from the link (the result of work handed off) to the agent that handed it off.\nconst receiveLinkedConversationEvent = async (\n event: z.infer<typeof linkedConversationEventSchema>,\n ctx: ChannelReceiveContextIface,\n): Promise<ConversationRefIface> => {\n const title = event.linkedTitle?.trim() ?? '';\n await sendServiceInput(ctx.platform, {\n room: event.conversationId,\n participantId: event.participantId ?? undefined,\n content: [textBlock(renderLinkedConversationEvent(event))],\n principal: { principalId: `link:${event.linkId}`, authenticator: 'final' },\n displayName: title.length === 0 ? 'Linked conversation' : title,\n originTurnId: event.originTurnId ?? undefined,\n idempotencyKey: `link:${event.linkId}:${event.eventId}`,\n label: title.length === 0 ? 'From a linked conversation' : `From \u201C${title}\u201D`,\n });\n return { conversationId: event.conversationId };\n};\n\nconst clipEnd = (text: string): string =>\n text.length <= SYSTEM_EVENT_TEXT_MAX_CHARS\n ? text\n : `\u2026 (truncated)\\n${text.slice(text.length - SYSTEM_EVENT_TEXT_MAX_CHARS)}`;\n\nconst outputSection = (label: string, output: string | null | undefined): string[] => {\n const text = output?.trimEnd() ?? '';\n return text.length === 0 ? [] : [`${label}:\\n\\`\\`\\`\\n${clipEnd(text)}\\n\\`\\`\\``];\n};\n\nexport const renderSandboxEvent = (\n event: Pick<SandboxEventInboundIface, 'processId' | 'command' | 'exitCode' | 'stdout' | 'stderr'>,\n): string => {\n const outcome =\n event.exitCode == null ? 'stopped without an exit code' : `exited with code ${event.exitCode}`;\n return [\n `Background process ${event.processId} (\\`${event.command}\\`) ${outcome}.`,\n ...outputSection('stdout', event.stdout),\n ...outputSection('stderr', event.stderr),\n ].join('\\n\\n');\n};\n\n// A result belongs to the session that produced it: that agent is prompted and\n// nobody observes it, so one agent's process output never reaches another\n// agent's history (a group's Default or All agents included).\nexport const routeToOwner =\n (participantId: string) =>\n (args: RouteArgsIface): RouteDecisionIface[] =>\n args.participants.some(\n (participant) =>\n participant.id === participantId &&\n participant.kind === ParticipantKind.Agent &&\n !participant.left,\n )\n ? [{ participantId, delivery: Delivery.Prompt }]\n : [];\n\nconst nonEmptyOr = (value: string | null | undefined, fallback: string): string => {\n const trimmed = value?.trim() ?? '';\n return trimmed.length === 0 ? fallback : trimmed;\n};\n\nconst receiveSandboxEvent = async (\n event: SandboxEventInboundIface,\n ctx: ChannelReceiveContextIface,\n): Promise<ConversationRefIface> => {\n const name = nonEmptyOr(event.sandboxName, 'Sandbox');\n const args: ServiceInputArgsIface = {\n room: event.conversationId,\n participantId: event.participantId ?? undefined,\n content: [textBlock(renderSandboxEvent(event))],\n principal: { principalId: `sandbox:${event.bindingId}`, authenticator: 'final' },\n displayName: name,\n idempotencyKey: `sandbox:${event.bindingId}:${event.eventId}`,\n label: `After a process in ${name} finished`,\n };\n await sendServiceInput(ctx.platform, args);\n return { conversationId: event.conversationId };\n};\n\n// agent-events' receive: a webhook, a linked conversation's event, a sandbox\n// result, or targeted content, each input to one agent. Outside systems\n// (Final's Goals among them) post conversation events through the public API instead.\nexport const receiveAgentEvent: ChannelReceiveIface = async (input, ctx) => {\n if (targetedInboundSchema.safeParse(input).success) return receiveTargetedInput(input, ctx);\n const event = agentEventInboundSchema.parse(input);\n if (event.kind === AgentEventKind.Webhook) {\n const name = configSchema.parse(ctx.config).displayName ?? 'Webhook';\n const heading = event.event == null ? `${name} event` : `${name} event: ${event.event}`;\n return sendBindingInput({\n ctx,\n conversation: await webhookConversation(ctx),\n content: [textBlock(`${heading}\\n\\n${renderBody(event.body, event.contentType ?? null)}`)],\n deliveryKey: event.deliveryId ?? null,\n });\n }\n if (event.kind === AgentEventKind.LinkedConversation) {\n return receiveLinkedConversationEvent(event, ctx);\n }\n return receiveSandboxEvent(event, ctx);\n};\n\nconst hex = (bytes: ArrayBuffer): string =>\n [...new Uint8Array(bytes)].map((byte) => byte.toString(16).padStart(2, '0')).join('');\n\nconst constantTimeEqual = (left: string, right: string): boolean => {\n if (left.length !== right.length) return false;\n let difference = 0;\n for (let index = 0; index < left.length; index += 1) {\n difference |= left.charCodeAt(index) ^ right.charCodeAt(index);\n }\n return difference === 0;\n};\n\nexport const hmacSha256Hex = async (secret: string, body: string): Promise<string> => {\n const encoder = new TextEncoder();\n const key = await crypto.subtle.importKey(\n 'raw',\n encoder.encode(secret),\n { name: 'HMAC', hash: 'SHA-256' },\n false,\n ['sign'],\n );\n return hex(await crypto.subtle.sign('HMAC', key, encoder.encode(body)));\n};\n\n// `sha256=<hex>` in `x-final-signature` or GitHub's `x-hub-signature-256`.\nexport const verifyWebhookSignature = async (args: {\n secret: string;\n body: string;\n headers: Headers;\n}): Promise<boolean> => {\n const header = args.headers.get('x-final-signature') ?? args.headers.get('x-hub-signature-256');\n if (header == null) return false;\n const provided = header.startsWith('sha256=') ? header.slice('sha256='.length) : header;\n return constantTimeEqual(provided.toLowerCase(), await hmacSha256Hex(args.secret, args.body));\n};\n\nconst webhookRoute: RouteDefinitionIface = {\n method: 'POST',\n path: '/',\n handler: async ({ request, secrets, receive }) => {\n const secret = await secrets.get(WEBHOOK_SECRET_NAME);\n if (secret == null) {\n return Response.json({ error: 'webhook secret is not configured' }, { status: 503 });\n }\n const body = await request.text();\n if (!(await verifyWebhookSignature({ secret, body, headers: request.headers }))) {\n return Response.json({ error: 'invalid signature' }, { status: 401 });\n }\n const ref = await receive({\n kind: AgentEventKind.Webhook,\n body,\n contentType: request.headers.get('content-type'),\n event: request.headers.get('x-github-event') ?? request.headers.get('x-final-event'),\n deliveryId:\n request.headers.get('x-github-delivery') ?? request.headers.get('x-final-delivery'),\n });\n if (ref == null || !('conversationId' in ref))\n throw new Error('agent event channel returned no conversation');\n return Response.json({ ok: true, conversationId: ref.conversationId }, { status: 202 });\n },\n};\n\n// Its inputs go to agents in conversations whose own channel (direct or\n// group messaging) projects the replies, so this channel projects nothing.\nexport const createAgentEventsChannel = (): ChannelDefinitionIface<JsonValue, JsonValue> =>\n defineChannel<JsonValue, JsonValue>({\n routes: [webhookRoute],\n receive: receiveAgentEvent,\n route: routeMessage,\n turnPolicy: AGENT_EVENTS_TURN_POLICY,\n project: async () => {},\n });\n"],
|
|
5
5
|
"mappings": "AACA;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OASK;AACP,YAAY,OAAO;AACnB,SAAS,uBAAuB;AAChC,SAAS,iBAAiB;AAC1B,SAAS,oBAAoB;AAC7B,SAAS,wBAAoD;AAEtD,MAAM,yBAAyB;AAC/B,MAAM,2BAA2B,WAAW;AAI5C,MAAM,sBAAsB;AAC5B,MAAM,yBAAyB;AAE/B,IAAK,iBAAL,kBAAKA,oBAAL;AACL,EAAAA,gBAAA,aAAU;AACV,EAAAA,gBAAA,wBAAqB;AAErB,EAAAA,gBAAA,aAAU;AAJA,SAAAA;AAAA,GAAA;AAOZ,SAAS,oBAAAC,yBAAwB;AAE1B,MAAM,8BAA8B;AAGpC,IAAK,0BAAL,kBAAKC,6BAAL;AAEL,EAAAA,yBAAA,aAAU;AAEV,EAAAA,yBAAA,sBAAmB;AAEnB,EAAAA,yBAAA,YAAS;AANC,SAAAA;AAAA,GAAA;AASL,MAAM,qCAAqC;AAElD,MAAM,qBAAqB,EAAE,OAAO;AAAA,EAClC,MAAM,EAAE,QAAQ,uBAAsB;AAAA,EACtC,MAAM,EAAE,OAAO;AAAA,EACf,aAAa,EAAE,OAAO,EAAE,QAAQ;AAAA;AAAA,EAEhC,OAAO,EAAE,OAAO,EAAE,QAAQ;AAAA,EAC1B,YAAY,EAAE,OAAO,EAAE,QAAQ;AACjC,CAAC;AAID,MAAM,gCAAgC,EAAE,OAAO;AAAA,EAC7C,MAAM,EAAE,QAAQ,8CAAiC;AAAA;AAAA,EAEjD,gBAAgB,EAAE,OAAO,EAAE,IAAI,CAAC;AAAA;AAAA,EAEhC,eAAe,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE,QAAQ;AAAA,EACzC,QAAQ,EAAE,OAAO,EAAE,IAAI,CAAC;AAAA,EACxB,sBAAsB,EAAE,OAAO,EAAE,IAAI,CAAC;AAAA,EACtC,aAAa,EAAE,OAAO,EAAE,QAAQ;AAAA,EAChC,OAAO,EAAE,WAAW,uBAAuB;AAAA;AAAA,EAE3C,MAAM,EAAE,OAAO,EAAE,QAAQ;AAAA;AAAA,EAEzB,SAAS,EAAE,OAAO,EAAE,IAAI,CAAC;AAAA,EACzB,cAAc,EAAE,OAAO,EAAE,QAAQ;AACnC,CAAC;AAGD,MAAM,qBAAqB,EAAE,OAAO;AAAA,EAClC,MAAM,EAAE,QAAQ,uBAAsB;AAAA,EACtC,gBAAgB,EAAE,OAAO,EAAE,IAAI,CAAC;AAAA;AAAA,EAEhC,eAAe,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE,QAAQ;AAAA,EACzC,WAAW,EAAE,OAAO,EAAE,IAAI,CAAC;AAAA,EAC3B,aAAa,EAAE,OAAO,EAAE,QAAQ;AAAA,EAChC,OAAO,EAAE,WAAW,gBAAgB;AAAA,EACpC,WAAW,EAAE,OAAO,EAAE,IAAI,CAAC;AAAA,EAC3B,SAAS,EAAE,OAAO;AAAA;AAAA,EAElB,UAAU,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS;AAAA;AAAA,EAEpC,QAAQ,EAAE,OAAO,EAAE,QAAQ;AAAA,EAC3B,QAAQ,EAAE,OAAO,EAAE,QAAQ;AAAA;AAAA,EAE3B,SAAS,EAAE,OAAO,EAAE,IAAI,CAAC;AAC3B,CAAC;AAEM,MAAM,0BAA0B,EAAE,mBAAmB,QAAQ;AAAA,EAClE;AAAA,EACA;AAAA,EACA;AACF,CAAC;AAMM,IAAK,oBAAL,kBAAKC,uBAAL;AAEL,EAAAA,mBAAA,uBAAoB;AAEpB,EAAAA,mBAAA,iBAAc;AAJJ,SAAAA;AAAA,GAAA;AASL,MAAM,wBAAwB,EAAE,OAAO;AAAA,EAC5C,QAAQ,EAAE,OAAO,EAAE,MAAM,EAAE,WAAW,iBAAiB,EAAE,CAAC;AAAA,EAC1D,SAAS,EAAE,MAAM,gBAAgB,EAAE,IAAI,CAAC;AAAA;AAAA,EAExC,YAAY,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE,QAAQ;AACxC,CAAC;AAID,MAAM,eAAe,EAAE,YAAY;AAAA,EACjC,aAAa,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE,QAAQ;AAAA;AAAA;AAAA,EAGvC,aAAa,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE,QAAQ;AACzC,CAAC;AAED,MAAM,aAAa,CAAC,MAAc,gBAAuC;AACvE,MAAI,WAAW;AACf,MAAI,aAAa,SAAS,MAAM,MAAM,MAAM;AAC1C,QAAI;AACF,iBAAW,KAAK,UAAU,gBAAgB,MAAM,KAAK,MAAM,IAAI,CAAC,GAAG,MAAM,CAAC;AAAA,IAC5E,QAAQ;AACN,iBAAW;AAAA,IACb;AAAA,EACF;AACA,SAAO,SAAS,UAAU,yBACtB,WACA,GAAG,SAAS,MAAM,GAAG,sBAAsB,CAAC;AAAA;AAClD;AAEA,MAAM,oBAAoB,OACxB,QAEA,IAAI,aAAa,OAAO,OAAO,IAAI,SAAS,cAAc,QAAQ,IAAI,SAAS;AAEjF,MAAM,0BAA0B,OAC9B,QAC+B;AAC/B,QAAM,SAAS,aAAa,MAAM,IAAI,MAAM;AAC5C,MAAI,OAAO,eAAe,QAAQ,IAAI,gBAAgB,MAAM;AAC1D,UAAM,IAAI;AAAA,MACR,mBAAmB,IAAI,aAAa,QAAQ;AAAA,IAC9C;AAAA,EACF;AACA,SAAO,IAAI,SAAS,cAAc,mBAAmB;AAAA,IACnD,gBAAgB,IAAI;AAAA,IACpB,QAAQ,OAAO;AAAA,IACf,cAAc,IAAI;AAAA,EACpB,CAAC;AACH;AAEA,MAAM,sBAAsB,OAAO,QAChC,MAAM,kBAAkB,GAAG,KAAM,wBAAwB,GAAG;AAE/D,MAAM,qBAAqB,OACzB,QACA,QAC+B;AAC/B,MAAI,WAAW,iCAA+B,QAAO,wBAAwB,GAAG;AAChF,QAAM,QAAQ,MAAM,kBAAkB,GAAG;AACzC,MAAI,SAAS,MAAM;AACjB,UAAM,IAAI,MAAM,mBAAmB,IAAI,aAAa,QAAQ,iCAAiC;AAAA,EAC/F;AACA,SAAO;AACT;AAGA,MAAM,eAAe,OACnB,cACA,QACoB;AACpB,QAAM,SAAS,MAAM,IAAI,SAAS,cAAc,aAAa,aAAa,cAAc,GAAG;AAAA,IACzF,CAAC,gBACC,YAAY,SAAS,gBAAgB,SACrC,CAAC,YAAY,QACb,YAAY,iBAAiB,IAAI;AAAA,EACrC;AACA,MAAI,SAAS,MAAM;AACjB,UAAM,IAAI;AAAA,MACR,mBAAmB,IAAI,aAAa,QAAQ,iCAAiC,aAAa,cAAc;AAAA,IAC1G;AAAA,EACF;AACA,SAAO,MAAM;AACf;AAGA,MAAM,mBAAmB,OAAO,SAMK;AACnC,QAAM,UAAU,KAAK,IAAI,aAAa;AACtC,QAAM,OAAO,aAAa,MAAM,KAAK,IAAI,MAAM,EAAE,eAAe;AAChE,QAAM,iBAAiB,KAAK,IAAI,UAAU;AAAA,IACxC,MAAM,KAAK,aAAa;AAAA,IACxB,eAAe,MAAM,aAAa,KAAK,cAAc,KAAK,GAAG;AAAA,IAC7D,SAAS,KAAK;AAAA,IACd,WAAW,EAAE,aAAa,WAAW,OAAO,IAAI,eAAe,QAAQ;AAAA,IACvE,aAAa;AAAA,IACb,gBAAgB,WAAW,OAAO,IAAI,KAAK,eAAe,OAAO,WAAW,CAAC;AAAA,IAC7E,OAAO,QAAQ,IAAI;AAAA,IACnB,YAAY,KAAK;AAAA,EACnB,CAAC;AACD,SAAO,EAAE,gBAAgB,KAAK,aAAa,eAAe;AAC5D;AAUO,MAAM,6BACX,CAAC,aAAyB,WAAW,UACrC,OAAO,OAAO,QAAQ;AACpB,QAAM,WAAW,sBAAsB,MAAM,KAAK;AAClD,SAAO,iBAAiB;AAAA,IACtB;AAAA,IACA,cAAc,MAAM,mBAAmB,SAAS,OAAO,MAAM,GAAG;AAAA,IAChE,SAAS,gBAAgB,SAAS,OAAO;AAAA,IACzC,aAAa,SAAS,cAAc;AAAA,IACpC;AAAA,EACF,CAAC;AACH;AAEF,MAAM,uBAAuB,2BAA2B,wBAAwB;AAEhF,MAAM,OAAO,CAAC,SACZ,KAAK,UAAU,qCACX,OACA,GAAG,KAAK,MAAM,GAAG,kCAAkC,CAAC;AAAA;AAEnD,MAAM,gCAAgC,CAC3C,UACW;AACX,QAAM,QAAQ,MAAM,aAAa,KAAK,KAAK;AAC3C,QAAM,OAAO,MAAM,WAAW,IAAI,0BAA0B,IAAI,KAAK;AACrE,QAAM,OAAO,MAAM,MAAM,KAAK,KAAK;AACnC,UAAQ,MAAM,OAAO;AAAA,IACnB,KAAK;AACH,aAAO,KAAK,WAAW,IAAI,GAAG,IAAI,cAAc,GAAG,IAAI;AAAA;AAAA,EAAgB,KAAK,IAAI,CAAC;AAAA,IACnF,KAAK;AACH,aAAO,KAAK,WAAW,IACnB,GAAG,IAAI,8BACP,GAAG,IAAI,6BAA6B,KAAK,IAAI,CAAC;AAAA,IACpD,KAAK;AACH,aAAO,KAAK,WAAW,IACnB,GAAG,IAAI,4BACP,GAAG,IAAI;AAAA;AAAA,EAA8B,KAAK,IAAI,CAAC;AAAA,EACvD;AACF;AAGA,MAAM,iCAAiC,OACrC,OACA,QACkC;AAClC,QAAM,QAAQ,MAAM,aAAa,KAAK,KAAK;AAC3C,QAAM,iBAAiB,IAAI,UAAU;AAAA,IACnC,MAAM,MAAM;AAAA,IACZ,eAAe,MAAM,iBAAiB;AAAA,IACtC,SAAS,CAAC,UAAU,8BAA8B,KAAK,CAAC,CAAC;AAAA,IACzD,WAAW,EAAE,aAAa,QAAQ,MAAM,MAAM,IAAI,eAAe,QAAQ;AAAA,IACzE,aAAa,MAAM,WAAW,IAAI,wBAAwB;AAAA,IAC1D,cAAc,MAAM,gBAAgB;AAAA,IACpC,gBAAgB,QAAQ,MAAM,MAAM,IAAI,MAAM,OAAO;AAAA,IACrD,OAAO,MAAM,WAAW,IAAI,+BAA+B,cAAS,KAAK;AAAA,EAC3E,CAAC;AACD,SAAO,EAAE,gBAAgB,MAAM,eAAe;AAChD;AAEA,MAAM,UAAU,CAAC,SACf,KAAK,UAAU,8BACX,OACA;AAAA,EAAkB,KAAK,MAAM,KAAK,SAAS,2BAA2B,CAAC;AAE7E,MAAM,gBAAgB,CAAC,OAAe,WAAgD;AACpF,QAAM,OAAO,QAAQ,QAAQ,KAAK;AAClC,SAAO,KAAK,WAAW,IAAI,CAAC,IAAI,CAAC,GAAG,KAAK;AAAA;AAAA,EAAc,QAAQ,IAAI,CAAC;AAAA,OAAU;AAChF;AAEO,MAAM,qBAAqB,CAChC,UACW;AACX,QAAM,UACJ,MAAM,YAAY,OAAO,iCAAiC,oBAAoB,MAAM,QAAQ;AAC9F,SAAO;AAAA,IACL,sBAAsB,MAAM,SAAS,OAAO,MAAM,OAAO,OAAO,OAAO;AAAA,IACvE,GAAG,cAAc,UAAU,MAAM,MAAM;AAAA,IACvC,GAAG,cAAc,UAAU,MAAM,MAAM;AAAA,EACzC,EAAE,KAAK,MAAM;AACf;AAKO,MAAM,eACX,CAAC,kBACD,CAAC,SACC,KAAK,aAAa;AAAA,EAChB,CAAC,gBACC,YAAY,OAAO,iBACnB,YAAY,SAAS,gBAAgB,SACrC,CAAC,YAAY;AACjB,IACI,CAAC,EAAE,eAAe,UAAU,SAAS,OAAO,CAAC,IAC7C,CAAC;AAET,MAAM,aAAa,CAAC,OAAkC,aAA6B;AACjF,QAAM,UAAU,OAAO,KAAK,KAAK;AACjC,SAAO,QAAQ,WAAW,IAAI,WAAW;AAC3C;AAEA,MAAM,sBAAsB,OAC1B,OACA,QACkC;AAClC,QAAM,OAAO,WAAW,MAAM,aAAa,SAAS;AACpD,QAAM,OAA8B;AAAA,IAClC,MAAM,MAAM;AAAA,IACZ,eAAe,MAAM,iBAAiB;AAAA,IACtC,SAAS,CAAC,UAAU,mBAAmB,KAAK,CAAC,CAAC;AAAA,IAC9C,WAAW,EAAE,aAAa,WAAW,MAAM,SAAS,IAAI,eAAe,QAAQ;AAAA,IAC/E,aAAa;AAAA,IACb,gBAAgB,WAAW,MAAM,SAAS,IAAI,MAAM,OAAO;AAAA,IAC3D,OAAO,sBAAsB,IAAI;AAAA,EACnC;AACA,QAAM,iBAAiB,IAAI,UAAU,IAAI;AACzC,SAAO,EAAE,gBAAgB,MAAM,eAAe;AAChD;AAKO,MAAM,oBAAyC,OAAO,OAAO,QAAQ;AAC1E,MAAI,sBAAsB,UAAU,KAAK,EAAE,QAAS,QAAO,qBAAqB,OAAO,GAAG;AAC1F,QAAM,QAAQ,wBAAwB,MAAM,KAAK;AACjD,MAAI,MAAM,SAAS,yBAAwB;AACzC,UAAM,OAAO,aAAa,MAAM,IAAI,MAAM,EAAE,eAAe;AAC3D,UAAM,UAAU,MAAM,SAAS,OAAO,GAAG,IAAI,WAAW,GAAG,IAAI,WAAW,MAAM,KAAK;AACrF,WAAO,iBAAiB;AAAA,MACtB;AAAA,MACA,cAAc,MAAM,oBAAoB,GAAG;AAAA,MAC3C,SAAS,CAAC,UAAU,GAAG,OAAO;AAAA;AAAA,EAAO,WAAW,MAAM,MAAM,MAAM,eAAe,IAAI,CAAC,EAAE,CAAC;AAAA,MACzF,aAAa,MAAM,cAAc;AAAA,IACnC,CAAC;AAAA,EACH;AACA,MAAI,MAAM,SAAS,gDAAmC;AACpD,WAAO,+BAA+B,OAAO,GAAG;AAAA,EAClD;AACA,SAAO,oBAAoB,OAAO,GAAG;AACvC;AAEA,MAAM,MAAM,CAAC,UACX,CAAC,GAAG,IAAI,WAAW,KAAK,CAAC,EAAE,IAAI,CAAC,SAAS,KAAK,SAAS,EAAE,EAAE,SAAS,GAAG,GAAG,CAAC,EAAE,KAAK,EAAE;AAEtF,MAAM,oBAAoB,CAAC,MAAc,UAA2B;AAClE,MAAI,KAAK,WAAW,MAAM,OAAQ,QAAO;AACzC,MAAI,aAAa;AACjB,WAAS,QAAQ,GAAG,QAAQ,KAAK,QAAQ,SAAS,GAAG;AACnD,kBAAc,KAAK,WAAW,KAAK,IAAI,MAAM,WAAW,KAAK;AAAA,EAC/D;AACA,SAAO,eAAe;AACxB;AAEO,MAAM,gBAAgB,OAAO,QAAgB,SAAkC;AACpF,QAAM,UAAU,IAAI,YAAY;AAChC,QAAM,MAAM,MAAM,OAAO,OAAO;AAAA,IAC9B;AAAA,IACA,QAAQ,OAAO,MAAM;AAAA,IACrB,EAAE,MAAM,QAAQ,MAAM,UAAU;AAAA,IAChC;AAAA,IACA,CAAC,MAAM;AAAA,EACT;AACA,SAAO,IAAI,MAAM,OAAO,OAAO,KAAK,QAAQ,KAAK,QAAQ,OAAO,IAAI,CAAC,CAAC;AACxE;AAGO,MAAM,yBAAyB,OAAO,SAIrB;AACtB,QAAM,SAAS,KAAK,QAAQ,IAAI,mBAAmB,KAAK,KAAK,QAAQ,IAAI,qBAAqB;AAC9F,MAAI,UAAU,KAAM,QAAO;AAC3B,QAAM,WAAW,OAAO,WAAW,SAAS,IAAI,OAAO,MAAM,UAAU,MAAM,IAAI;AACjF,SAAO,kBAAkB,SAAS,YAAY,GAAG,MAAM,cAAc,KAAK,QAAQ,KAAK,IAAI,CAAC;AAC9F;AAEA,MAAM,eAAqC;AAAA,EACzC,QAAQ;AAAA,EACR,MAAM;AAAA,EACN,SAAS,OAAO,EAAE,SAAS,SAAS,QAAQ,MAAM;AAChD,UAAM,SAAS,MAAM,QAAQ,IAAI,mBAAmB;AACpD,QAAI,UAAU,MAAM;AAClB,aAAO,SAAS,KAAK,EAAE,OAAO,mCAAmC,GAAG,EAAE,QAAQ,IAAI,CAAC;AAAA,IACrF;AACA,UAAM,OAAO,MAAM,QAAQ,KAAK;AAChC,QAAI,CAAE,MAAM,uBAAuB,EAAE,QAAQ,MAAM,SAAS,QAAQ,QAAQ,CAAC,GAAI;AAC/E,aAAO,SAAS,KAAK,EAAE,OAAO,oBAAoB,GAAG,EAAE,QAAQ,IAAI,CAAC;AAAA,IACtE;AACA,UAAM,MAAM,MAAM,QAAQ;AAAA,MACxB,MAAM;AAAA,MACN;AAAA,MACA,aAAa,QAAQ,QAAQ,IAAI,cAAc;AAAA,MAC/C,OAAO,QAAQ,QAAQ,IAAI,gBAAgB,KAAK,QAAQ,QAAQ,IAAI,eAAe;AAAA,MACnF,YACE,QAAQ,QAAQ,IAAI,mBAAmB,KAAK,QAAQ,QAAQ,IAAI,kBAAkB;AAAA,IACtF,CAAC;AACD,QAAI,OAAO,QAAQ,EAAE,oBAAoB;AACvC,YAAM,IAAI,MAAM,8CAA8C;AAChE,WAAO,SAAS,KAAK,EAAE,IAAI,MAAM,gBAAgB,IAAI,eAAe,GAAG,EAAE,QAAQ,IAAI,CAAC;AAAA,EACxF;AACF;AAIO,MAAM,2BAA2B,MACtC,cAAoC;AAAA,EAClC,QAAQ,CAAC,YAAY;AAAA,EACrB,SAAS;AAAA,EACT,OAAO;AAAA,EACP,YAAY;AAAA,EACZ,SAAS,YAAY;AAAA,EAAC;AACxB,CAAC;",
|
|
6
6
|
"names": ["AgentEventKind", "SandboxEventKind", "LinkedConversationEvent", "ReceiveTargetKind"]
|
|
7
7
|
}
|
|
@@ -14,7 +14,7 @@ export interface FakeMessageIface extends ConversationMessageIface {
|
|
|
14
14
|
}
|
|
15
15
|
export interface FakeCardIface {
|
|
16
16
|
messageId: string;
|
|
17
|
-
|
|
17
|
+
decisionId: string | null;
|
|
18
18
|
state: JsonObject;
|
|
19
19
|
}
|
|
20
20
|
export interface FakePlatformIface {
|
|
@@ -146,14 +146,14 @@ const createFakePlatform = () => {
|
|
|
146
146
|
});
|
|
147
147
|
cards.push({
|
|
148
148
|
messageId: message.messageId,
|
|
149
|
-
|
|
149
|
+
decisionId: args.decisionId,
|
|
150
150
|
state: args.state
|
|
151
151
|
});
|
|
152
152
|
return message;
|
|
153
153
|
},
|
|
154
154
|
updateCard: async (args) => {
|
|
155
155
|
const card = cards.find(
|
|
156
|
-
(candidate) => candidate.messageId === args.messageId || candidate.
|
|
156
|
+
(candidate) => candidate.messageId === args.messageId || candidate.decisionId === args.messageId
|
|
157
157
|
);
|
|
158
158
|
if (card == null) throw new Error(`no card ${args.messageId}`);
|
|
159
159
|
card.state = { ...card.state, ...args.state };
|
|
@@ -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 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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
|
|
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 decisionId: 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 decisionId: args.decisionId,\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.decisionId === 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
|
}
|
|
@@ -6,7 +6,6 @@ export * from "./direct-messaging.mjs";
|
|
|
6
6
|
export * from "./group-messaging.mjs";
|
|
7
7
|
export * from "./inbound.mjs";
|
|
8
8
|
export * from "./messaging-channel.mjs";
|
|
9
|
-
export * from "./pending.mjs";
|
|
10
9
|
export * from "./projection.mjs";
|
|
11
10
|
export * from "./prompt.mjs";
|
|
12
11
|
export * from "./routing.mjs";
|
|
@@ -6,7 +6,6 @@ export * from "./direct-messaging.mjs";
|
|
|
6
6
|
export * from "./group-messaging.mjs";
|
|
7
7
|
export * from "./inbound.mjs";
|
|
8
8
|
export * from "./messaging-channel.mjs";
|
|
9
|
-
export * from "./pending.mjs";
|
|
10
9
|
export * from "./projection.mjs";
|
|
11
10
|
export * from "./prompt.mjs";
|
|
12
11
|
export * from "./routing.mjs";
|
|
@@ -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 \"./
|
|
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 \"./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;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -9,7 +9,6 @@ import {
|
|
|
9
9
|
ConversationEventKind,
|
|
10
10
|
messageInboundSchema
|
|
11
11
|
} from "./inbound.mjs";
|
|
12
|
-
import { createPendingCards } from "./pending.mjs";
|
|
13
12
|
import { createProjector } from "./projection.mjs";
|
|
14
13
|
import { routeMessage } from "./routing.mjs";
|
|
15
14
|
const receiveConversationEvent = async (event, ctx) => {
|
|
@@ -86,13 +85,11 @@ const createConversationReceive = (turnPolicy, route = routeMessage) => async (i
|
|
|
86
85
|
const createMessagingChannel = (config = {}) => {
|
|
87
86
|
const turnPolicy = config.turnPolicy ?? TurnPolicy.Steer;
|
|
88
87
|
const projector = createProjector({ ...config, turnPolicy });
|
|
89
|
-
const cards = createPendingCards();
|
|
90
88
|
return defineChannel({
|
|
91
89
|
receive: createConversationReceive(turnPolicy, config.route),
|
|
92
90
|
route: config.route ?? routeMessage,
|
|
93
91
|
turnPolicy,
|
|
94
|
-
project: projector.project
|
|
95
|
-
events: cards.events
|
|
92
|
+
project: projector.project
|
|
96
93
|
});
|
|
97
94
|
};
|
|
98
95
|
export {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../../src/channels/messaging-channel.ts"],
|
|
4
|
-
"sourcesContent": ["import {\n defineChannel,\n TurnPolicy,\n type ChannelDefinitionIface,\n type ChannelReceiveContextIface,\n type ConversationRefIface,\n type JsonValue,\n type RouteArgsIface,\n type RouteDecisionIface,\n} from '@finalai/agent-provider';\nimport { contentBlocksOf } from \"./content.mjs\";\nimport { deliverMessage, membershipNotice, reactionNotice } from \"./delivery.mjs\";\nimport {\n conversationEventInboundSchema,\n ConversationEventKind,\n messageInboundSchema,\n type ConversationEventInboundIface,\n} from \"./inbound.mjs\";\nimport {
|
|
5
|
-
"mappings": "AAAA;AAAA,EACE;AAAA,EACA;AAAA,OAOK;AACP,SAAS,uBAAuB;AAChC,SAAS,gBAAgB,kBAAkB,sBAAsB;AACjE;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,OAEK;AACP,SAAS,
|
|
4
|
+
"sourcesContent": ["import {\n defineChannel,\n TurnPolicy,\n type ChannelDefinitionIface,\n type ChannelReceiveContextIface,\n type ConversationRefIface,\n type JsonValue,\n type RouteArgsIface,\n type RouteDecisionIface,\n} from '@finalai/agent-provider';\nimport { contentBlocksOf } from \"./content.mjs\";\nimport { deliverMessage, membershipNotice, reactionNotice } from \"./delivery.mjs\";\nimport {\n conversationEventInboundSchema,\n ConversationEventKind,\n messageInboundSchema,\n type ConversationEventInboundIface,\n} from \"./inbound.mjs\";\nimport { createProjector, type ProjectorConfigIface } from \"./projection.mjs\";\nimport { routeMessage } from \"./routing.mjs\";\n\n// `turnPolicy` (ProjectorConfigIface): steer unless configured; a conversation\n// set to queue overrides it.\nexport interface MessagingChannelConfigIface extends ProjectorConfigIface {\n route?: (args: RouteArgsIface) => RouteDecisionIface[] | Promise<RouteDecisionIface[]>;\n}\n\nconst receiveConversationEvent = async (\n event: ConversationEventInboundIface,\n ctx: ChannelReceiveContextIface,\n): Promise<ConversationRefIface> => {\n const participants = await ctx.platform.conversations.participants(event.conversationId);\n if (event.event === ConversationEventKind.Membership) {\n const subject = participants.find((participant) => participant.id === event.participantId);\n if (subject != null) {\n await membershipNotice({\n platform: ctx.platform,\n participants: participants.filter(\n (participant) =>\n !participant.left &&\n (participant.kind !== 'agent' ||\n ctx.agentParticipantId == null ||\n participant.id === ctx.agentParticipantId),\n ),\n subject,\n change: event.change,\n idempotencyKey: `membership:${event.participantId}:${event.eventId}`,\n });\n }\n return { conversationId: event.conversationId };\n }\n const [message] = (\n await ctx.platform.conversations.recentMessages({\n conversationId: event.conversationId,\n beforeSeq: event.messageSeq + 1,\n limit: 1,\n })\n ).filter((candidate) => candidate.messageId === event.messageId);\n if (\n message != null &&\n (ctx.agentParticipantId == null || message.authorParticipantId === ctx.agentParticipantId)\n ) {\n await reactionNotice({\n platform: ctx.platform,\n participants,\n message,\n isLatestOfAuthor: event.latestOfAuthor,\n reactorParticipantId: event.reactorParticipantId,\n emoji: event.emoji,\n eventId: event.eventId,\n });\n }\n return { conversationId: event.conversationId };\n};\n\n// Persists the message before routing and delivering it to sessions,\n// using the channel's turnPolicy.\nexport const createConversationReceive =\n (\n turnPolicy: TurnPolicy,\n route: NonNullable<MessagingChannelConfigIface['route']> = routeMessage,\n ) =>\n async (input: JsonValue, ctx: ChannelReceiveContextIface): Promise<ConversationRefIface> => {\n const event = conversationEventInboundSchema.safeParse(input);\n if (event.success) {\n return receiveConversationEvent(event.data, ctx);\n }\n const inbound = messageInboundSchema.parse(input);\n const conversation =\n ctx.conversation ?? (await ctx.platform.conversations.get(inbound.conversationId));\n if (conversation == null) {\n throw new Error(`conversation ${inbound.conversationId} not found`);\n }\n const message =\n ctx.message ??\n (await ctx.platform.conversations.postMessage({\n conversationId: inbound.conversationId,\n authorParticipantId: inbound.authorParticipantId,\n kind: inbound.kind,\n content: contentBlocksOf(inbound.content),\n clientMessageId: inbound.clientMessageId ?? null,\n replyToMessageId: inbound.replyToMessageId ?? null,\n threadRootId: inbound.threadRootId ?? null,\n quotedMessageIds: inbound.quotedMessageIds,\n mentionedParticipantIds: inbound.mentionedParticipantIds,\n }));\n await deliverMessage({\n platform: ctx.platform,\n route: async (args) => {\n const requested =\n ctx.requestedDelivery != null && ctx.agentParticipantId != null && route === routeMessage\n ? [{ participantId: ctx.agentParticipantId, delivery: ctx.requestedDelivery }]\n : await route({ ...args, agentParticipantId: ctx.agentParticipantId });\n return requested.filter(\n (decision) =>\n ctx.agentParticipantId == null || decision.participantId === ctx.agentParticipantId,\n );\n },\n conversation,\n message,\n participants: ctx.participants == null ? undefined : [...ctx.participants],\n turnPolicy,\n });\n return { conversationId: conversation.conversationId };\n };\n\n// The shared body of direct-messaging and group-messaging: one routing table\n// and one projection; the conversation kind selects the rules.\nexport const createMessagingChannel = (\n config: MessagingChannelConfigIface = {},\n): ChannelDefinitionIface<JsonValue, JsonValue> => {\n const turnPolicy = config.turnPolicy ?? TurnPolicy.Steer;\n const projector = createProjector({ ...config, turnPolicy });\n return defineChannel<JsonValue, JsonValue>({\n receive: createConversationReceive(turnPolicy, config.route),\n route: config.route ?? routeMessage,\n turnPolicy,\n project: projector.project,\n });\n};\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@finalai/final-agent-provider",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.0",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "Final's provider package: serverless, remote and local harnesses; the computer and device sandboxes; the messaging, schedule and event channels.",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -220,13 +220,13 @@
|
|
|
220
220
|
"dependencies": {
|
|
221
221
|
"@agentclientprotocol/sdk": "1.8.0",
|
|
222
222
|
"@finalai/acp-session": "0.1.10",
|
|
223
|
-
"@finalai/agent-protocol": "0.
|
|
224
|
-
"@finalai/agent-provider": "0.
|
|
223
|
+
"@finalai/agent-protocol": "0.5.0",
|
|
224
|
+
"@finalai/agent-provider": "0.5.0",
|
|
225
225
|
"@finalai/computers": "0.2.0",
|
|
226
226
|
"@finalai/websockets": "0.1.6",
|
|
227
227
|
"ws": "^8.21.3",
|
|
228
228
|
"zod": "4.6.5",
|
|
229
|
-
"@finalai/agent-definition": "0.
|
|
229
|
+
"@finalai/agent-definition": "0.5.0"
|
|
230
230
|
},
|
|
231
231
|
"engines": {
|
|
232
232
|
"node": ">=26"
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
import { PendingEventKind, type CardArgsIface, type ChannelEventHandler, type JsonObject, type JsonValue, type PendingCreatedDataIface } from '@finalai/agent-provider';
|
|
2
|
-
export declare enum PendingCardStatus {
|
|
3
|
-
Open = "open",
|
|
4
|
-
Answered = "answered",
|
|
5
|
-
Cancelled = "cancelled",
|
|
6
|
-
Expired = "expired"
|
|
7
|
-
}
|
|
8
|
-
export declare const pendingEntityLinks: (pending: PendingCreatedDataIface) => CardArgsIface["entityLinks"];
|
|
9
|
-
export declare const pendingCardState: (pending: PendingCreatedDataIface) => JsonObject;
|
|
10
|
-
export declare const pendingStatusOfOutcome: (outcome: JsonValue) => PendingCardStatus;
|
|
11
|
-
export interface PendingCardsIface {
|
|
12
|
-
events: Record<`${PendingEventKind}`, ChannelEventHandler>;
|
|
13
|
-
}
|
|
14
|
-
export declare const createPendingCards: () => PendingCardsIface;
|
|
@@ -1,155 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
CardKind,
|
|
3
|
-
jsonObjectSchema,
|
|
4
|
-
jsonValueSchema,
|
|
5
|
-
pendingCreatedDataSchema,
|
|
6
|
-
PendingEventKind,
|
|
7
|
-
PendingKind,
|
|
8
|
-
pendingResolvedDataSchema
|
|
9
|
-
} from "@finalai/agent-provider";
|
|
10
|
-
import * as z from "zod";
|
|
11
|
-
var PendingCardStatus = /* @__PURE__ */ ((PendingCardStatus2) => {
|
|
12
|
-
PendingCardStatus2["Open"] = "open";
|
|
13
|
-
PendingCardStatus2["Answered"] = "answered";
|
|
14
|
-
PendingCardStatus2["Cancelled"] = "cancelled";
|
|
15
|
-
PendingCardStatus2["Expired"] = "expired";
|
|
16
|
-
return PendingCardStatus2;
|
|
17
|
-
})(PendingCardStatus || {});
|
|
18
|
-
const permissionRequestSchema = z.looseObject({
|
|
19
|
-
title: z.string().nullish(),
|
|
20
|
-
description: z.string().nullish(),
|
|
21
|
-
options: z.array(z.looseObject({ optionId: z.string(), name: z.string(), kind: z.string() })).default([]),
|
|
22
|
-
toolCall: jsonValueSchema.optional(),
|
|
23
|
-
subject: jsonValueSchema.optional()
|
|
24
|
-
});
|
|
25
|
-
const elicitationRequestSchema = z.looseObject({
|
|
26
|
-
message: z.string().default(""),
|
|
27
|
-
mode: z.string().default("form"),
|
|
28
|
-
requestedSchema: jsonObjectSchema.optional(),
|
|
29
|
-
url: z.string().optional(),
|
|
30
|
-
elicitationId: z.string().optional()
|
|
31
|
-
});
|
|
32
|
-
const entityLinksSchema = z.looseObject({
|
|
33
|
-
_meta: z.looseObject({
|
|
34
|
-
"final.ai": z.looseObject({
|
|
35
|
-
entityLinks: z.array(
|
|
36
|
-
z.looseObject({
|
|
37
|
-
kind: z.string(),
|
|
38
|
-
id: z.string(),
|
|
39
|
-
title: z.string().nullish(),
|
|
40
|
-
url: z.string().nullish(),
|
|
41
|
-
description: z.string().nullish(),
|
|
42
|
-
imageUrl: z.string().nullish()
|
|
43
|
-
})
|
|
44
|
-
)
|
|
45
|
-
})
|
|
46
|
-
})
|
|
47
|
-
});
|
|
48
|
-
const pendingEntityLinks = (pending) => {
|
|
49
|
-
if (pending.kind !== PendingKind.Elicitation) return [];
|
|
50
|
-
const parsed = entityLinksSchema.safeParse(pending.request);
|
|
51
|
-
if (!parsed.success) return [];
|
|
52
|
-
return parsed.data._meta["final.ai"].entityLinks.map((link) => {
|
|
53
|
-
const entityLink = { kind: link.kind, id: link.id };
|
|
54
|
-
if (link.title != null) entityLink.title = link.title;
|
|
55
|
-
if (link.url != null) entityLink.url = link.url;
|
|
56
|
-
if (link.description != null) entityLink.description = link.description;
|
|
57
|
-
if (link.imageUrl != null) entityLink.imageUrl = link.imageUrl;
|
|
58
|
-
return entityLink;
|
|
59
|
-
});
|
|
60
|
-
};
|
|
61
|
-
const cardSchema = z.looseObject({
|
|
62
|
-
_meta: z.looseObject({
|
|
63
|
-
"final.ai": z.looseObject({
|
|
64
|
-
card: z.looseObject({ title: z.string(), spec: jsonObjectSchema })
|
|
65
|
-
})
|
|
66
|
-
})
|
|
67
|
-
});
|
|
68
|
-
const pendingCardState = (pending) => {
|
|
69
|
-
const base = {
|
|
70
|
-
status: "open" /* Open */,
|
|
71
|
-
pendingRequestId: pending.pendingRequestId,
|
|
72
|
-
audienceParticipantIds: pending.audienceParticipantIds
|
|
73
|
-
};
|
|
74
|
-
if (pending.kind === PendingKind.Permission) {
|
|
75
|
-
const parsed2 = permissionRequestSchema.safeParse(pending.request);
|
|
76
|
-
const request2 = parsed2.success ? parsed2.data : { title: null, description: null, options: [] };
|
|
77
|
-
return {
|
|
78
|
-
...base,
|
|
79
|
-
title: request2.title ?? "Permission requested",
|
|
80
|
-
description: request2.description ?? null,
|
|
81
|
-
options: request2.options.map((option) => ({
|
|
82
|
-
optionId: option.optionId,
|
|
83
|
-
name: option.name,
|
|
84
|
-
kind: option.kind
|
|
85
|
-
}))
|
|
86
|
-
};
|
|
87
|
-
}
|
|
88
|
-
const card = cardSchema.safeParse(pending.request).data?._meta["final.ai"].card;
|
|
89
|
-
if (card != null) base.spec = card.spec;
|
|
90
|
-
const parsed = elicitationRequestSchema.safeParse(pending.request);
|
|
91
|
-
const request = parsed.success ? parsed.data : { message: "", mode: "form" };
|
|
92
|
-
const title = card?.title ?? request.message;
|
|
93
|
-
if (request.mode === "url") {
|
|
94
|
-
return {
|
|
95
|
-
...base,
|
|
96
|
-
title,
|
|
97
|
-
mode: "url",
|
|
98
|
-
url: request.url ?? null,
|
|
99
|
-
elicitationId: request.elicitationId ?? null
|
|
100
|
-
};
|
|
101
|
-
}
|
|
102
|
-
return {
|
|
103
|
-
...base,
|
|
104
|
-
title,
|
|
105
|
-
mode: "form",
|
|
106
|
-
requestedSchema: request.requestedSchema ?? {}
|
|
107
|
-
};
|
|
108
|
-
};
|
|
109
|
-
const outcomeLabelSchema = z.union([
|
|
110
|
-
z.looseObject({ outcome: z.looseObject({ outcome: z.string() }) }).transform((value) => value.outcome.outcome),
|
|
111
|
-
z.looseObject({ outcome: z.string() }).transform((value) => value.outcome),
|
|
112
|
-
z.looseObject({ action: z.string() }).transform((value) => value.action)
|
|
113
|
-
]);
|
|
114
|
-
const pendingStatusOfOutcome = (outcome) => {
|
|
115
|
-
const label = outcomeLabelSchema.safeParse(outcome).data;
|
|
116
|
-
if (label === "cancelled" || label === "cancel") return "cancelled" /* Cancelled */;
|
|
117
|
-
if (label === "expired") return "expired" /* Expired */;
|
|
118
|
-
return "answered" /* Answered */;
|
|
119
|
-
};
|
|
120
|
-
const createPendingCards = () => {
|
|
121
|
-
const created = async (event, ctx) => {
|
|
122
|
-
if (ctx.conversation == null || ctx.agentParticipant == null)
|
|
123
|
-
throw new Error("Final cards require a Final conversation");
|
|
124
|
-
const pending = pendingCreatedDataSchema.parse(event.data);
|
|
125
|
-
await ctx.platform.conversations.postCard({
|
|
126
|
-
conversationId: ctx.conversation.conversationId,
|
|
127
|
-
authorParticipantId: ctx.agentParticipant.id,
|
|
128
|
-
kind: pending.kind === PendingKind.Permission ? CardKind.Permission : CardKind.Elicitation,
|
|
129
|
-
pendingRequestId: pending.pendingRequestId,
|
|
130
|
-
state: pendingCardState(pending),
|
|
131
|
-
entityLinks: pendingEntityLinks(pending)
|
|
132
|
-
});
|
|
133
|
-
};
|
|
134
|
-
const resolved = async (event, ctx) => {
|
|
135
|
-
const resolution = pendingResolvedDataSchema.parse(event.data);
|
|
136
|
-
await ctx.platform.conversations.updateCard({
|
|
137
|
-
messageId: resolution.pendingRequestId,
|
|
138
|
-
state: {
|
|
139
|
-
status: pendingStatusOfOutcome(resolution.outcome),
|
|
140
|
-
outcome: resolution.outcome
|
|
141
|
-
}
|
|
142
|
-
});
|
|
143
|
-
};
|
|
144
|
-
return {
|
|
145
|
-
events: { [PendingEventKind.Created]: created, [PendingEventKind.Resolved]: resolved }
|
|
146
|
-
};
|
|
147
|
-
};
|
|
148
|
-
export {
|
|
149
|
-
PendingCardStatus,
|
|
150
|
-
createPendingCards,
|
|
151
|
-
pendingCardState,
|
|
152
|
-
pendingEntityLinks,
|
|
153
|
-
pendingStatusOfOutcome
|
|
154
|
-
};
|
|
155
|
-
//# sourceMappingURL=pending.mjs.map
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../../../../../src/channels/pending.ts"],
|
|
4
|
-
"sourcesContent": ["import {\n CardKind,\n jsonObjectSchema,\n jsonValueSchema,\n pendingCreatedDataSchema,\n PendingEventKind,\n PendingKind,\n pendingResolvedDataSchema,\n type CardArgsIface,\n type ChannelEventHandler,\n type JsonObject,\n type JsonValue,\n type PendingCreatedDataIface,\n} from '@finalai/agent-provider';\nimport * as z from 'zod';\n\n// Pending ACP requests become generic cards for their audience,\n// through the channel's `pending.created` and `pending.resolved` events:\n// a permission card carries the title and options, an elicitation card the\n// form schema or the URL. The card's state is the client's whole model of it.\n\nexport enum PendingCardStatus {\n Open = 'open',\n Answered = 'answered',\n Cancelled = 'cancelled',\n Expired = 'expired',\n}\n\nconst permissionRequestSchema = z.looseObject({\n title: z.string().nullish(),\n description: z.string().nullish(),\n options: z\n .array(z.looseObject({ optionId: z.string(), name: z.string(), kind: z.string() }))\n .default([]),\n toolCall: jsonValueSchema.optional(),\n subject: jsonValueSchema.optional(),\n});\n\nconst elicitationRequestSchema = z.looseObject({\n message: z.string().default(''),\n mode: z.string().default('form'),\n requestedSchema: jsonObjectSchema.optional(),\n url: z.string().optional(),\n elicitationId: z.string().optional(),\n});\n\n// An elicitation may link the entities it is about (a Goal it asks to accept)\n// in `_meta[\"final.ai\"].entityLinks`; the card carries them.\nconst entityLinksSchema = z.looseObject({\n _meta: z.looseObject({\n 'final.ai': z.looseObject({\n entityLinks: z.array(\n z.looseObject({\n kind: z.string(),\n id: z.string(),\n title: z.string().nullish(),\n url: z.string().nullish(),\n description: z.string().nullish(),\n imageUrl: z.string().nullish(),\n }),\n ),\n }),\n }),\n});\n\nexport const pendingEntityLinks = (\n pending: PendingCreatedDataIface,\n): CardArgsIface['entityLinks'] => {\n if (pending.kind !== PendingKind.Elicitation) return [];\n const parsed = entityLinksSchema.safeParse(pending.request);\n if (!parsed.success) return [];\n return parsed.data._meta['final.ai'].entityLinks.map((link) => {\n const entityLink: CardArgsIface['entityLinks'][number] = { kind: link.kind, id: link.id };\n if (link.title != null) entityLink.title = link.title;\n if (link.url != null) entityLink.url = link.url;\n if (link.description != null) entityLink.description = link.description;\n if (link.imageUrl != null) entityLink.imageUrl = link.imageUrl;\n return entityLink;\n });\n};\n\n// The generative card an elicitation asks with: its title names the card and\n// its spec is the card's contents. The session plane validates the spec.\nconst cardSchema = z.looseObject({\n _meta: z.looseObject({\n 'final.ai': z.looseObject({\n card: z.looseObject({ title: z.string(), spec: jsonObjectSchema }),\n }),\n }),\n});\n\nexport const pendingCardState = (pending: PendingCreatedDataIface): JsonObject => {\n const base: JsonObject = {\n status: PendingCardStatus.Open,\n pendingRequestId: pending.pendingRequestId,\n audienceParticipantIds: pending.audienceParticipantIds,\n };\n if (pending.kind === PendingKind.Permission) {\n const parsed = permissionRequestSchema.safeParse(pending.request);\n const request = parsed.success ? parsed.data : { title: null, description: null, options: [] };\n return {\n ...base,\n title: request.title ?? 'Permission requested',\n description: request.description ?? null,\n options: request.options.map((option) => ({\n optionId: option.optionId,\n name: option.name,\n kind: option.kind,\n })),\n };\n }\n const card = cardSchema.safeParse(pending.request).data?._meta['final.ai'].card;\n if (card != null) base.spec = card.spec;\n const parsed = elicitationRequestSchema.safeParse(pending.request);\n const request = parsed.success ? parsed.data : { message: '', mode: 'form' };\n const title = card?.title ?? request.message;\n if (request.mode === 'url') {\n return {\n ...base,\n title,\n mode: 'url',\n url: request.url ?? null,\n elicitationId: request.elicitationId ?? null,\n };\n }\n return {\n ...base,\n title,\n mode: 'form',\n requestedSchema: request.requestedSchema ?? {},\n };\n};\n\n// `{outcome: {outcome}}` (a RequestPermissionResponse), `{outcome}` (its\n// outcome) or `{action}` (an elicitation response).\nconst outcomeLabelSchema = z.union([\n z\n .looseObject({ outcome: z.looseObject({ outcome: z.string() }) })\n .transform((value) => value.outcome.outcome),\n z.looseObject({ outcome: z.string() }).transform((value) => value.outcome),\n z.looseObject({ action: z.string() }).transform((value) => value.action),\n]);\n\nexport const pendingStatusOfOutcome = (outcome: JsonValue): PendingCardStatus => {\n const label = outcomeLabelSchema.safeParse(outcome).data;\n if (label === 'cancelled' || label === 'cancel') return PendingCardStatus.Cancelled;\n if (label === 'expired') return PendingCardStatus.Expired;\n return PendingCardStatus.Answered;\n};\n\nexport interface PendingCardsIface {\n events: Record<`${PendingEventKind}`, ChannelEventHandler>;\n}\n\nexport const createPendingCards = (): PendingCardsIface => {\n const created: ChannelEventHandler = async (event, ctx) => {\n if (ctx.conversation == null || ctx.agentParticipant == null)\n throw new Error('Final cards require a Final conversation');\n const pending = pendingCreatedDataSchema.parse(event.data);\n await ctx.platform.conversations.postCard({\n conversationId: ctx.conversation.conversationId,\n authorParticipantId: ctx.agentParticipant.id,\n kind: pending.kind === PendingKind.Permission ? CardKind.Permission : CardKind.Elicitation,\n pendingRequestId: pending.pendingRequestId,\n state: pendingCardState(pending),\n entityLinks: pendingEntityLinks(pending),\n });\n };\n\n // The platform resolves a card by its pending request id.\n const resolved: ChannelEventHandler = async (event, ctx) => {\n const resolution = pendingResolvedDataSchema.parse(event.data);\n await ctx.platform.conversations.updateCard({\n messageId: resolution.pendingRequestId,\n state: {\n status: pendingStatusOfOutcome(resolution.outcome),\n outcome: resolution.outcome,\n },\n });\n };\n\n return {\n events: { [PendingEventKind.Created]: created, [PendingEventKind.Resolved]: resolved },\n };\n};\n"],
|
|
5
|
-
"mappings": "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",
|
|
6
|
-
"names": ["PendingCardStatus", "parsed", "request"]
|
|
7
|
-
}
|