@adonis-agora/agent 0.72.0 → 0.74.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +29 -0
- package/dist/configure.d.ts +5 -4
- package/dist/configure.d.ts.map +1 -1
- package/dist/configure.js +8 -4
- package/dist/configure.js.map +1 -1
- package/dist/providers/agent_provider.d.ts.map +1 -1
- package/dist/providers/agent_provider.js +15 -1
- package/dist/providers/agent_provider.js.map +1 -1
- package/dist/src/a2ui/adapter.d.ts.map +1 -1
- package/dist/src/a2ui/adapter.js +1 -0
- package/dist/src/a2ui/adapter.js.map +1 -1
- package/dist/src/a2ui/core.d.ts.map +1 -1
- package/dist/src/a2ui/core.js +11 -1
- package/dist/src/a2ui/core.js.map +1 -1
- package/dist/src/action-proposal-executor.d.ts.map +1 -1
- package/dist/src/action-proposal-executor.js +3 -0
- package/dist/src/action-proposal-executor.js.map +1 -1
- package/dist/src/ag-ui/adapter.d.ts.map +1 -1
- package/dist/src/ag-ui/adapter.js +2 -0
- package/dist/src/ag-ui/adapter.js.map +1 -1
- package/dist/src/ag-ui/core/encoder.d.ts.map +1 -1
- package/dist/src/ag-ui/core/encoder.js +3 -0
- package/dist/src/ag-ui/core/encoder.js.map +1 -1
- package/dist/src/agent-deps-factory.d.ts +3 -1
- package/dist/src/agent-deps-factory.d.ts.map +1 -1
- package/dist/src/agent-deps-factory.js +3 -0
- package/dist/src/agent-deps-factory.js.map +1 -1
- package/dist/src/agent-deps.d.ts +3 -1
- package/dist/src/agent-deps.d.ts.map +1 -1
- package/dist/src/agent-deps.js.map +1 -1
- package/dist/src/agent-loop.d.ts +7 -1
- package/dist/src/agent-loop.d.ts.map +1 -1
- package/dist/src/agent-loop.js +52 -2
- package/dist/src/agent-loop.js.map +1 -1
- package/dist/src/agent-service.d.ts +6 -0
- package/dist/src/agent-service.d.ts.map +1 -1
- package/dist/src/agent-service.js +5 -3
- package/dist/src/agent-service.js.map +1 -1
- package/dist/src/channels/adapters/evolution_api.d.ts.map +1 -1
- package/dist/src/channels/adapters/evolution_api.js +35 -0
- package/dist/src/channels/adapters/evolution_api.js.map +1 -1
- package/dist/src/channels/adapters/telegram.d.ts.map +1 -1
- package/dist/src/channels/adapters/telegram.js +25 -7
- package/dist/src/channels/adapters/telegram.js.map +1 -1
- package/dist/src/channels/adapters/whatsapp_cloud.d.ts.map +1 -1
- package/dist/src/channels/adapters/whatsapp_cloud.js +44 -0
- package/dist/src/channels/adapters/whatsapp_cloud.js.map +1 -1
- package/dist/src/channels/handler.d.ts +29 -1
- package/dist/src/channels/handler.d.ts.map +1 -1
- package/dist/src/channels/handler.js +231 -9
- package/dist/src/channels/handler.js.map +1 -1
- package/dist/src/channels/index.d.ts +2 -2
- package/dist/src/channels/index.d.ts.map +1 -1
- package/dist/src/channels/index.js.map +1 -1
- package/dist/src/channels/types.d.ts +40 -0
- package/dist/src/channels/types.d.ts.map +1 -1
- package/dist/src/genui/catalog.d.ts +12 -1
- package/dist/src/genui/catalog.d.ts.map +1 -1
- package/dist/src/genui/catalog.js +18 -1
- package/dist/src/genui/catalog.js.map +1 -1
- package/dist/src/genui/channels.d.ts +252 -0
- package/dist/src/genui/channels.d.ts.map +1 -0
- package/dist/src/genui/channels.js +516 -0
- package/dist/src/genui/channels.js.map +1 -0
- package/dist/src/genui/chart-image.d.ts +46 -0
- package/dist/src/genui/chart-image.d.ts.map +1 -0
- package/dist/src/genui/chart-image.js +155 -0
- package/dist/src/genui/chart-image.js.map +1 -0
- package/dist/src/genui/factory.d.ts +23 -1
- package/dist/src/genui/factory.d.ts.map +1 -1
- package/dist/src/genui/factory.js +13 -1
- package/dist/src/genui/factory.js.map +1 -1
- package/dist/src/genui/index.d.ts.map +1 -1
- package/dist/src/genui/index.js +64 -3
- package/dist/src/genui/index.js.map +1 -1
- package/dist/src/genui/kit/adonis.d.ts +4 -0
- package/dist/src/genui/kit/adonis.d.ts.map +1 -0
- package/dist/src/genui/kit/adonis.js +38 -0
- package/dist/src/genui/kit/adonis.js.map +1 -0
- package/dist/src/genui/kit/bundle.d.ts +25 -0
- package/dist/src/genui/kit/bundle.d.ts.map +1 -0
- package/dist/src/genui/kit/bundle.js +144 -0
- package/dist/src/genui/kit/bundle.js.map +1 -0
- package/dist/src/genui/kit/discover.d.ts +41 -0
- package/dist/src/genui/kit/discover.d.ts.map +1 -0
- package/dist/src/genui/kit/discover.js +100 -0
- package/dist/src/genui/kit/discover.js.map +1 -0
- package/dist/src/genui/kit/docs.d.ts +22 -0
- package/dist/src/genui/kit/docs.d.ts.map +1 -0
- package/dist/src/genui/kit/docs.js +237 -0
- package/dist/src/genui/kit/docs.js.map +1 -0
- package/dist/src/genui/kit/files.d.ts +27 -0
- package/dist/src/genui/kit/files.d.ts.map +1 -0
- package/dist/src/genui/kit/files.js +126 -0
- package/dist/src/genui/kit/files.js.map +1 -0
- package/dist/src/genui/kit/index.d.ts +12 -0
- package/dist/src/genui/kit/index.d.ts.map +1 -0
- package/dist/src/genui/kit/index.js +12 -0
- package/dist/src/genui/kit/index.js.map +1 -0
- package/dist/src/genui/kit/plugin.d.ts +52 -0
- package/dist/src/genui/kit/plugin.d.ts.map +1 -0
- package/dist/src/genui/kit/plugin.js +314 -0
- package/dist/src/genui/kit/plugin.js.map +1 -0
- package/dist/src/genui/kit/write.d.ts +14 -0
- package/dist/src/genui/kit/write.d.ts.map +1 -0
- package/dist/src/genui/kit/write.js +39 -0
- package/dist/src/genui/kit/write.js.map +1 -0
- package/dist/src/genui/public.d.ts +7 -3
- package/dist/src/genui/public.d.ts.map +1 -1
- package/dist/src/genui/public.js +5 -1
- package/dist/src/genui/public.js.map +1 -1
- package/dist/src/genui/sandbox-jsx.d.ts +29 -0
- package/dist/src/genui/sandbox-jsx.d.ts.map +1 -0
- package/dist/src/genui/sandbox-jsx.js +656 -0
- package/dist/src/genui/sandbox-jsx.js.map +1 -0
- package/dist/src/genui/sandbox-kit.d.ts +88 -0
- package/dist/src/genui/sandbox-kit.d.ts.map +1 -0
- package/dist/src/genui/sandbox-kit.js +89 -0
- package/dist/src/genui/sandbox-kit.js.map +1 -0
- package/dist/src/genui/sandbox-theme.d.ts +61 -0
- package/dist/src/genui/sandbox-theme.d.ts.map +1 -0
- package/dist/src/genui/sandbox-theme.js +255 -0
- package/dist/src/genui/sandbox-theme.js.map +1 -0
- package/dist/src/genui/sandbox.d.ts +73 -2
- package/dist/src/genui/sandbox.d.ts.map +1 -1
- package/dist/src/genui/sandbox.js +106 -16
- package/dist/src/genui/sandbox.js.map +1 -1
- package/dist/src/genui/text.d.ts.map +1 -1
- package/dist/src/genui/text.js +33 -1
- package/dist/src/genui/text.js.map +1 -1
- package/dist/src/genui/tools.d.ts +26 -0
- package/dist/src/genui/tools.d.ts.map +1 -1
- package/dist/src/genui/tools.js +94 -14
- package/dist/src/genui/tools.js.map +1 -1
- package/dist/src/genui/tree.d.ts +25 -2
- package/dist/src/genui/tree.d.ts.map +1 -1
- package/dist/src/genui/tree.js +161 -4
- package/dist/src/genui/tree.js.map +1 -1
- package/dist/src/hooks/genui_kit.d.ts +20 -0
- package/dist/src/hooks/genui_kit.d.ts.map +1 -0
- package/dist/src/hooks/genui_kit.js +55 -0
- package/dist/src/hooks/genui_kit.js.map +1 -0
- package/dist/src/index.d.ts +2 -2
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +2 -2
- package/dist/src/index.js.map +1 -1
- package/dist/src/negotiated-tool-ui.d.ts +27 -0
- package/dist/src/negotiated-tool-ui.d.ts.map +1 -1
- package/dist/src/negotiated-tool-ui.js +52 -0
- package/dist/src/negotiated-tool-ui.js.map +1 -1
- package/dist/src/react/core/genui/sandbox-assets.d.ts +32 -0
- package/dist/src/react/core/genui/sandbox-assets.d.ts.map +1 -0
- package/dist/src/react/core/genui/sandbox-assets.js +174 -0
- package/dist/src/react/core/genui/sandbox-assets.js.map +1 -0
- package/dist/src/react/core/genui/sandbox.d.ts +9 -0
- package/dist/src/react/core/genui/sandbox.d.ts.map +1 -1
- package/dist/src/react/core/genui/sandbox.js +119 -19
- package/dist/src/react/core/genui/sandbox.js.map +1 -1
- package/dist/src/react/core/index.d.ts +1 -1
- package/dist/src/react/core/index.d.ts.map +1 -1
- package/dist/src/react/core/index.js +1 -1
- package/dist/src/react/core/index.js.map +1 -1
- package/dist/src/react/core/presentation/phrasing.d.ts +3 -2
- package/dist/src/react/core/presentation/phrasing.d.ts.map +1 -1
- package/dist/src/react/core/presentation/phrasing.js +4 -27
- package/dist/src/react/core/presentation/phrasing.js.map +1 -1
- package/dist/src/react/core/presentation/tool-activity.d.ts +8 -0
- package/dist/src/react/core/presentation/tool-activity.d.ts.map +1 -1
- package/dist/src/react/core/presentation/tool-activity.js +28 -1
- package/dist/src/react/core/presentation/tool-activity.js.map +1 -1
- package/dist/src/react/core/transcript/model.d.ts +6 -0
- package/dist/src/react/core/transcript/model.d.ts.map +1 -1
- package/dist/src/react/core/transcript/model.js +6 -1
- package/dist/src/react/core/transcript/model.js.map +1 -1
- package/dist/src/react/core/transcript/use-chat-transcript.d.ts +5 -0
- package/dist/src/react/core/transcript/use-chat-transcript.d.ts.map +1 -1
- package/dist/src/react/core/transcript/use-chat-transcript.js +3 -0
- package/dist/src/react/core/transcript/use-chat-transcript.js.map +1 -1
- package/dist/src/spi/tool.d.ts +7 -0
- package/dist/src/spi/tool.d.ts.map +1 -1
- package/dist/src/tool-presentation.d.ts +15 -0
- package/dist/src/tool-presentation.d.ts.map +1 -1
- package/dist/src/tool-presentation.js +48 -0
- package/dist/src/tool-presentation.js.map +1 -1
- package/dist/src/tool-registry.d.ts.map +1 -1
- package/dist/src/tool-registry.js +2 -0
- package/dist/src/tool-registry.js.map +1 -1
- package/dist/src/types.d.ts +10 -0
- package/dist/src/types.d.ts.map +1 -1
- package/dist/src/vite/index.d.ts +24 -0
- package/dist/src/vite/index.d.ts.map +1 -0
- package/dist/src/vite/index.js +29 -0
- package/dist/src/vite/index.js.map +1 -0
- package/package.json +38 -2
- package/skills/agent-setup/SKILL.md +3 -1
- package/skills/agent-tools/SKILL.md +5 -3
|
@@ -2,6 +2,8 @@ import type { HttpContext } from '@adonisjs/core/http';
|
|
|
2
2
|
import { AgentService } from '../agent-service.js';
|
|
3
3
|
import type { AttachmentLimits } from '../attachment-limits.js';
|
|
4
4
|
import type { UiCapabilities } from '../genui/capabilities.js';
|
|
5
|
+
import type { Catalog } from '../genui/catalog.js';
|
|
6
|
+
import { type GenuiChannelBase, type GenuiChannels } from '../genui/channels.js';
|
|
5
7
|
import type { ActionProposal } from '../spi/action-proposal-store.js';
|
|
6
8
|
import type { AttachmentRef } from '../spi/attachment-staging.js';
|
|
7
9
|
import type { Actor, PageContext } from '../types.js';
|
|
@@ -248,9 +250,19 @@ export interface ChannelHandleOptions {
|
|
|
248
250
|
allowRemember?: boolean;
|
|
249
251
|
/**
|
|
250
252
|
* What the turn may draw. Default `{ components: [] }`: every component arrives as its
|
|
251
|
-
* `fallbackText`. Allow some with {@link renderComponent} to send them as files.
|
|
253
|
+
* `fallbackText`. Allow some with {@link renderComponent} to send them as files. With
|
|
254
|
+
* `genui({ channels })` configured for this channel ({@link ChannelAdapter.kind}, else `default`)
|
|
255
|
+
* the default is the channel's own: the components it can draw, delivered natively.
|
|
252
256
|
*/
|
|
253
257
|
uiCapabilities?: UiCapabilities;
|
|
258
|
+
/**
|
|
259
|
+
* The genui setup this channel draws with — default: the app's (`AgentGenui` from the container).
|
|
260
|
+
* With `channels` configured for this channel, components arrive natively (their `channels`
|
|
261
|
+
* conversion: text, reply buttons, lists, images; their text summary otherwise), and a pressed
|
|
262
|
+
* button is the user's next turn, as a UI action. `false` → never (every component as its text).
|
|
263
|
+
* With a `service` handed in, the container is not read: pass `genui` too.
|
|
264
|
+
*/
|
|
265
|
+
genui?: ChannelGenui | false;
|
|
254
266
|
/**
|
|
255
267
|
* A component the turn drew: what to send for it — a file (a chart as an image), text, several —
|
|
256
268
|
* or `null`/`undefined` for its `fallbackText`. Rendered components are sent when the turn ends (or
|
|
@@ -297,6 +309,12 @@ export interface ChannelHandleOptions {
|
|
|
297
309
|
/** A message whose handling failed (after its retries). Default: `console.error`. */
|
|
298
310
|
onError?(error: unknown, message: InboundMessage): void;
|
|
299
311
|
}
|
|
312
|
+
/** What a channel draws generative UI with — `AgentGenui` is one. */
|
|
313
|
+
export interface ChannelGenui {
|
|
314
|
+
catalog: Catalog;
|
|
315
|
+
channels?: GenuiChannels;
|
|
316
|
+
base?: GenuiChannelBase;
|
|
317
|
+
}
|
|
300
318
|
/** The route handler `channels.handle()` returns. */
|
|
301
319
|
export interface ChannelRouteHandler {
|
|
302
320
|
(ctx: HttpContext): Promise<void>;
|
|
@@ -321,6 +339,16 @@ export declare function proposalButtonIds(proposalId: string): {
|
|
|
321
339
|
export interface ChannelAddress {
|
|
322
340
|
name: string;
|
|
323
341
|
conversation: string;
|
|
342
|
+
/** The adapter's {@link ChannelAdapter.kind}, when it has one — what `turnChannel` reads first. */
|
|
343
|
+
kind?: string;
|
|
344
|
+
/**
|
|
345
|
+
* How many reply buttons and list rows the adapter shows (its capabilities): what a tool result's
|
|
346
|
+
* `delivered` describes choices by, the way the handler will send them.
|
|
347
|
+
*/
|
|
348
|
+
choices?: {
|
|
349
|
+
buttons: number;
|
|
350
|
+
lists: number;
|
|
351
|
+
};
|
|
324
352
|
}
|
|
325
353
|
/**
|
|
326
354
|
* The webhook route for one channel. Each request is verified (`401` when it is not the provider's),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"handler.d.ts","sourceRoot":"","sources":["../../../src/channels/handler.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"handler.d.ts","sourceRoot":"","sources":["../../../src/channels/handler.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAKvD,OAAO,EAAE,YAAY,EAAgD,MAAM,qBAAqB,CAAC;AACjG,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAIhE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAC/D,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,EAIL,KAAK,gBAAgB,EACrB,KAAK,aAAa,EAInB,MAAM,sBAAsB,CAAC;AAE9B,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iCAAiC,CAAC;AACtE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAElE,OAAO,KAAK,EAAE,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AACtD,OAAO,EAGL,KAAK,mBAAmB,EAExB,KAAK,qBAAqB,EAM3B,MAAM,eAAe,CAAC;AAKvB,OAAO,EAAE,KAAK,YAAY,EAA2C,MAAM,YAAY,CAAC;AACxF,OAAO,EACL,KAAK,gBAAgB,EACrB,KAAK,mBAAmB,EAExB,KAAK,YAAY,EACjB,KAAK,qBAAqB,EAG3B,MAAM,YAAY,CAAC;AACpB,OAAO,KAAK,EACV,cAAc,EAEd,gBAAgB,EAChB,cAAc,EACd,YAAY,EACZ,cAAc,EACd,aAAa,EACb,eAAe,EAChB,MAAM,YAAY,CAAC;AAEpB;;;;GAIG;AACH,MAAM,WAAW,kBACf,SAAQ,IAAI,CAAC,YAAY,EAAE,WAAW,GAAG,MAAM,GAAG,QAAQ,GAAG,qBAAqB,CAAC,EACjF,OAAO,CACL,IAAI,CACF,YAAY,EACV,sBAAsB,GACtB,qBAAqB,GACrB,0BAA0B,GAC1B,oBAAoB,GACpB,QAAQ,GACR,kBAAkB,GAClB,iBAAiB,GACjB,eAAe,GACf,OAAO,CACV,CACF;IACH;;;OAGG;IACH,IAAI,CAAC,GAAG,IAAI,EAAE,UAAU,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC,GAAG,UAAU,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC,CAAC;CACnF;AAED;;;;GAIG;AACH,MAAM,MAAM,YAAY,GACpB,MAAM,GACN;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,GAAG,CAAC,EAAE,OAAO,CAAA;CAAE,GAC/B;IACE,KAAK,EAAE,aAAa,CAAC;IACrB,0CAA0C;IAC1C,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,wEAAwE;IACxE,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB,CAAC;AAEN,4DAA4D;AAC5D,MAAM,MAAM,WAAW,GACnB,UAAU,GACV,MAAM,GACN,SAAS,GACT;IAAE,KAAK,EAAE,YAAY,CAAA;CAAE,GACvB;IAAE,OAAO,EAAE,YAAY,EAAE,CAAA;CAAE,CAAC;AAEhC,2DAA2D;AAC3D,MAAM,WAAW,kBAAkB;IACjC,0BAA0B;IAC1B,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,EAAE,MAAM,CAAC;IACrB,OAAO,EAAE,cAAc,CAAC;CACzB;AAED,yFAAyF;AACzF,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,EAAE,MAAM,CAAC;IACrB,yDAAyD;IACzD,QAAQ,EAAE,eAAe,CAAC;IAC1B;;;OAGG;IACH,IAAI,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,GAAG,UAAU,GAAG,MAAM,GAAG,QAAQ,CAAC;IACpE,wDAAwD;IACxD,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;IACpB,yGAAyG;IACzG,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,qDAAqD;IACrD,OAAO,EAAE,cAAc,GAAG,IAAI,CAAC;IAC/B,iEAAiE;IACjE,QAAQ,EAAE,cAAc,GAAG,IAAI,CAAC;CACjC;AAED,+EAA+E;AAC/E,MAAM,WAAW,mBAAmB;IAClC,OAAO,EAAE,MAAM,CAAC;IAChB;;;;;OAKG;IACH,MAAM,EACF,UAAU,GACV,WAAW,GACX,SAAS,GACT,cAAc,GACd,WAAW,GACX,oBAAoB,GACpB,QAAQ,CAAC;IACb,yFAAyF;IACzF,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,wDAAwD;IACxD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,0BAA0B;IAC1B,QAAQ,EAAE,MAAM,CAAC;IACjB,wDAAwD;IACxD,UAAU,EAAE,MAAM,CAAC;IACnB,sFAAsF;IACtF,QAAQ,EAAE,SAAS,cAAc,EAAE,CAAC;CACrC;AAED,uEAAuE;AACvE,MAAM,WAAW,kBAAkB;IACjC,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,KAAK,CAAC;IACb,OAAO,EAAE,cAAc,CAAC;IACxB,oFAAoF;IACpF,MAAM,EAAE,OAAO,CAAC;CACjB;AAED;;;;;;;;;;;;;;;GAeG;AACH,MAAM,MAAM,kBAAkB,GAC1B,SAAS,GACT,QAAQ,GACR,SAAS,GACT,SAAS,GACT,QAAQ,GACR,SAAS,GACT,SAAS,GACT,aAAa,CAAC;AAElB,yGAAyG;AACzG,MAAM,WAAW,gBAAgB;IAC/B,0BAA0B;IAC1B,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,EAAE,MAAM,CAAC;IACrB,mGAAmG;IACnG,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;IACpB,qGAAqG;IACrG,OAAO,EAAE,cAAc,GAAG,IAAI,CAAC;IAC/B,uDAAuD;IACvD,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,OAAO,EAAE,kBAAkB,CAAC;IAC5B,8EAA8E;IAC9E,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED,iFAAiF;AACjF,MAAM,MAAM,oBAAoB,GAC5B,SAAS;AACX,sDAAsD;GACpD;IAAE,IAAI,EAAE,gBAAgB,CAAA;CAAE;AAC5B,kGAAkG;GAChG;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE;AAClB,mDAAmD;GACjD;IAAE,MAAM,EAAE,mBAAmB,CAAA;CAAE,CAAC;AAEpC,sGAAsG;AACtG,MAAM,WAAW,cAAc;IAC7B,sDAAsD;IACtD,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,aAAa,EAAE,CAAC;CAC9B;AAED,MAAM,WAAW,oBAAoB;IACnC;;;;OAIG;IACH,KAAK,CAAC,OAAO,EAAE,cAAc,GAAG,KAAK,GAAG,IAAI,GAAG,OAAO,CAAC,KAAK,GAAG,IAAI,CAAC,CAAC;IACrE;;;OAGG;IACH,aAAa,CAAC,CACZ,OAAO,EAAE,cAAc,EACvB,OAAO,EAAE,kBAAkB,GAEzB,YAAY,GACZ,YAAY,EAAE,GACd,IAAI,GACJ,SAAS,GACT,OAAO,CAAC,YAAY,GAAG,YAAY,EAAE,GAAG,IAAI,GAAG,SAAS,CAAC,CAAC;IAC9D;;;;OAIG;IACH,UAAU,CAAC,CACT,OAAO,EAAE,cAAc,EACvB,KAAK,EAAE,KAAK,EACZ,OAAO,EAAE,kBAAkB,GAC1B,WAAW,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC;IACtC;;;OAGG;IACH,MAAM,CACJ,KAAK,EAAE,KAAK,EACZ,OAAO,EAAE,cAAc,GACtB,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC,CAAC;IAClE,sFAAsF;IACtF,eAAe,CAAC,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,cAAc,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAChG,+FAA+F;IAC/F,aAAa,CAAC,CAAC,IAAI,EAAE,kBAAkB,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC/D;;;;;;;;;OASG;IACH,WAAW,CAAC,CAAC,IAAI,EAAE,gBAAgB,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC3D;;;OAGG;IACH,UAAU,CAAC,CAAC,QAAQ,EAAE,eAAe,GAAG,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IACnE;;;OAGG;IACH,WAAW,CAAC,EAAE,WAAW,GAAG,CAAC,CAAC,OAAO,EAAE,cAAc,KAAK,WAAW,CAAC,CAAC;IACvE,kFAAkF;IAClF,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,qEAAqE;IACrE,OAAO,CAAC,EAAE,kBAAkB,CAAC;IAC7B;;;;OAIG;IACH,KAAK,CAAC,EAAE,YAAY,CAAC;IACrB;;;;;OAKG;IACH,OAAO,CAAC,EAAE,OAAO,GAAG,qBAAqB,CAAC;IAC1C,4DAA4D;IAC5D,KAAK,CAAC,EAAE,mBAAmB,CAAC;IAC5B,yFAAyF;IACzF,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,kFAAkF;IAClF,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;OAGG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,qGAAqG;IACrG,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B;;;;;OAKG;IACH,KAAK,CAAC,EACF,qBAAqB,GACrB,CAAC,CAAC,OAAO,EAAE;QACT,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;QACpB,OAAO,EAAE,cAAc,GAAG,IAAI,CAAC;QAC/B,QAAQ,CAAC,EAAE,cAAc,CAAC;KAC3B,KAAK,qBAAqB,GAAG,OAAO,CAAC,qBAAqB,CAAC,CAAC,CAAC;IAClE;;;OAGG;IACH,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB;;;;;OAKG;IACH,cAAc,CAAC,EAAE,cAAc,CAAC;IAChC;;;;;;OAMG;IACH,KAAK,CAAC,EAAE,YAAY,GAAG,KAAK,CAAC;IAC7B;;;;;OAKG;IACH,eAAe,CAAC,CACd,SAAS,EAAE,gBAAgB,EAC3B,OAAO,EAAE;QAAE,KAAK,EAAE,KAAK,CAAC;QAAC,YAAY,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,GAE9E,YAAY,GACZ,YAAY,EAAE,GACd,IAAI,GACJ,SAAS,GACT,OAAO,CAAC,YAAY,GAAG,YAAY,EAAE,GAAG,IAAI,GAAG,SAAS,CAAC,CAAC;IAC9D;;;OAGG;IACH,WAAW,CAAC,CAAC,MAAM,EAAE,gBAAgB,GAAG,IAAI,EAAE,KAAK,EAAE,YAAY,GAAG,gBAAgB,GAAG,IAAI,CAAC;IAC5F;;;OAGG;IACH,YAAY,CAAC,CACX,IAAI,EAAE,gBAAgB,EACtB,KAAK,EAAE,YAAY,EACnB,OAAO,EAAE,kBAAkB,GAAG;QAAE,KAAK,EAAE,KAAK,CAAA;KAAE,GAC7C,oBAAoB,GAAG,OAAO,CAAC,oBAAoB,CAAC,CAAC;IACxD;;;OAGG;IACH,gBAAgB,CAAC,CACf,OAAO,EAAE,cAAc,EACvB,OAAO,EAAE,kBAAkB,GAAG;QAAE,KAAK,EAAE,KAAK,CAAC;QAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,GACtE,cAAc,GAAG,OAAO,CAAC,cAAc,CAAC,CAAC;IAC5C;;;;OAIG;IACH,aAAa,CAAC,CACZ,QAAQ,EAAE,cAAc,EACxB,OAAO,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,YAAY,CAAA;KAAE,GAC7C,YAAY,EAAE,GAAG,IAAI,GAAG,SAAS,GAAG,OAAO,CAAC,YAAY,EAAE,GAAG,IAAI,GAAG,SAAS,CAAC,CAAC;IAClF,kGAAkG;IAClG,SAAS,CAAC,CAAC,KAAK,EAAE,mBAAmB,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7D,qFAAqF;IACrF,OAAO,CAAC,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,cAAc,GAAG,IAAI,CAAC;CACzD;AAED,qEAAqE;AACrE,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,OAAO,CAAC;IACjB,QAAQ,CAAC,EAAE,aAAa,CAAC;IACzB,IAAI,CAAC,EAAE,gBAAgB,CAAC;CACzB;AAED,qDAAqD;AACrD,MAAM,WAAW,mBAAmB;IAClC,CAAC,GAAG,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAClC;;;OAGG;IACH,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACvB,kEAAkE;IAClE,aAAa,CACX,OAAO,EAAE,cAAc,GACtB,OAAO,CAAC;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,OAAO,CAAC;QAAC,WAAW,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CACrE;AAsBD,iGAAiG;AACjG,wBAAgB,iBAAiB,CAAC,UAAU,EAAE,MAAM,GAAG;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAGzF;AAED,gGAAgG;AAChG,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,YAAY,EAAE,MAAM,CAAC;IACrB,mGAAmG;IACnG,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;;OAGG;IACH,OAAO,CAAC,EAAE;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;CAC9C;AAyID;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAAgB,aAAa,CAC3B,OAAO,EAAE,cAAc,EACvB,OAAO,EAAE,oBAAoB,GAC5B,mBAAmB,CA29CrB;AAmBD;;;;;;;;;;GAUG;AACH,wBAAsB,mBAAmB,CAAC,QAAQ,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,CAEjF;AAED,eAAO,MAAM,QAAQ;IACnB,iCAAiC;IACjC,MAAM;IACN,uCAAuC;IACvC,SAAS;IACT,iEAAiE;IACjE,cAAc,aAAa,cAAc,YAAY,kBAAkB;IAEvE,0EAA0E;IAC1E,OAAO,SAAS,MAAM,KAAG,cAAc,GAAG,SAAS;CACpD,CAAC"}
|
|
@@ -1,6 +1,10 @@
|
|
|
1
|
+
import { createHash } from 'node:crypto';
|
|
1
2
|
import { DEFAULT_TEXT_ACTION_PROPOSAL_VOCABULARY, parseTextActionProposalCommand, } from '../action-proposal-text.js';
|
|
2
3
|
import { AgentService, AttachmentRefusedError } from '../agent-service.js';
|
|
3
4
|
import { onAgentEngine, registeredAgentEngine } from '../durable/agent-run-context.js';
|
|
5
|
+
import { uiActionText } from '../genui/actions.js';
|
|
6
|
+
import { channelButtonAction, renderChannelMessages, resolveGenuiChannel, } from '../genui/channels.js';
|
|
7
|
+
import { AgentGenui } from '../genui/factory.js';
|
|
4
8
|
import { durableExecutor, inlineExecutor, jobId, registerChannelWorkflows, withRetries, } from './executor.js';
|
|
5
9
|
import { ChannelMediaTooLargeError } from './http.js';
|
|
6
10
|
import { toChannelMarkdown } from './markdown.js';
|
|
@@ -9,6 +13,11 @@ import { splitMessage } from './split.js';
|
|
|
9
13
|
import { InMemoryChannelStore, lucidChannelStore } from './store.js';
|
|
10
14
|
import { channelTextsFor, mergeTexts, } from './texts.js';
|
|
11
15
|
const BUTTON_ID = /^agora:(approve|reject):([^\s]+)$/;
|
|
16
|
+
/** A component's button (or list entry): `ui:<ref>`, short enough for Telegram's 64-byte callback data. */
|
|
17
|
+
const UI_BUTTON_ID = /^ui:([A-Za-z0-9_-]{6,32})$/;
|
|
18
|
+
/** How long a component's buttons stay pressable, and how many per conversation are remembered by label. */
|
|
19
|
+
const UI_BUTTON_TTL_MS = 7 * 24 * 60 * 60 * 1000;
|
|
20
|
+
const MAX_UI_BUTTONS = 40;
|
|
12
21
|
/** The tail of a proposal id a button carries — Telegram's `callback_data` holds 64 bytes. */
|
|
13
22
|
const BUTTON_REF_LENGTH = 32;
|
|
14
23
|
const OUTCOME_POLL_MS = 500;
|
|
@@ -59,6 +68,8 @@ function record(value) {
|
|
|
59
68
|
}
|
|
60
69
|
/** `image/jpeg` → `jpeg`, for a file that arrives without a name. */
|
|
61
70
|
const extensionOf = (contentType) => (contentType.split('/')[1] ?? 'bin').split(/[;+]/)[0] ?? 'bin';
|
|
71
|
+
/** Where a natively drawn component sits in a turn's text, until it is sent. */
|
|
72
|
+
const NATIVE_MARK = '\u0000agora-native\u0000';
|
|
62
73
|
const replyList = (value) => value === null || value === undefined ? [] : Array.isArray(value) ? value : [value];
|
|
63
74
|
/** The component a frame carries (a live one, or a replayed `ui` event), else `null`. */
|
|
64
75
|
function componentOf(frame, position) {
|
|
@@ -144,6 +155,36 @@ export function handleChannel(adapter, options) {
|
|
|
144
155
|
const { capabilities } = adapter;
|
|
145
156
|
const buttons = (capabilities.buttons ?? 0) >= 2;
|
|
146
157
|
const name = adapter.name;
|
|
158
|
+
/** What the channel is (`whatsapp`, `telegram`) — the turn's channel, whatever it is named. */
|
|
159
|
+
const kind = adapter.kind ?? adapter.name;
|
|
160
|
+
let resolvedGenui;
|
|
161
|
+
/** The genui setup, and this channel's options in it — `null` when it draws nothing natively. */
|
|
162
|
+
const genuiFor = () => {
|
|
163
|
+
resolvedGenui ??= (async () => {
|
|
164
|
+
if (options.genui === false)
|
|
165
|
+
return null;
|
|
166
|
+
if (options.genui !== undefined)
|
|
167
|
+
return options.genui;
|
|
168
|
+
// A service handed in (a test, another framework): no container to read the app's genui from.
|
|
169
|
+
if (options.service !== undefined)
|
|
170
|
+
return null;
|
|
171
|
+
try {
|
|
172
|
+
const { default: app } = await import('@adonisjs/core/services/app');
|
|
173
|
+
if (!app.container.hasBinding(AgentGenui))
|
|
174
|
+
return null;
|
|
175
|
+
return (await app.container.make(AgentGenui));
|
|
176
|
+
}
|
|
177
|
+
catch {
|
|
178
|
+
return null;
|
|
179
|
+
}
|
|
180
|
+
})();
|
|
181
|
+
return resolvedGenui.then((genui) => {
|
|
182
|
+
if (genui === null || genui.channels === undefined)
|
|
183
|
+
return null;
|
|
184
|
+
const channel = resolveGenuiChannel(genui.base ?? {}, genui.channels, kind);
|
|
185
|
+
return channel.configured ? { genui, channel } : null;
|
|
186
|
+
});
|
|
187
|
+
};
|
|
147
188
|
let resolvedService;
|
|
148
189
|
const serviceFor = (given) => {
|
|
149
190
|
if (options.service)
|
|
@@ -273,6 +314,125 @@ export function handleChannel(adapter, options) {
|
|
|
273
314
|
const saved = await store.get(cardsKey(conversation));
|
|
274
315
|
return new Set(saved === null ? [] : JSON.parse(saved));
|
|
275
316
|
};
|
|
317
|
+
const uiButtonKey = (ref) => `${name}:ui:${ref}`;
|
|
318
|
+
const uiButtonsKey = (conversation) => `${name}:uibuttons:${conversation}`;
|
|
319
|
+
/**
|
|
320
|
+
* Remember a component's buttons — by id for the press, and by label for a provider that forwards
|
|
321
|
+
* only the label (Whatsmiau). Each id is derived from the run, the component and its place, so a
|
|
322
|
+
* phase that runs again names the same buttons.
|
|
323
|
+
*/
|
|
324
|
+
const rememberUiButtons = async (store, conversation, seed, message, entries) => {
|
|
325
|
+
const ids = [];
|
|
326
|
+
const index = await store.get(uiButtonsKey(conversation));
|
|
327
|
+
const known = index === null ? [] : JSON.parse(index);
|
|
328
|
+
for (const [position, button] of entries.entries()) {
|
|
329
|
+
const ref = createHash('sha256')
|
|
330
|
+
.update(`${seed}:${position}`)
|
|
331
|
+
.digest('base64url')
|
|
332
|
+
.slice(0, 16);
|
|
333
|
+
const saved = {
|
|
334
|
+
conversation,
|
|
335
|
+
button,
|
|
336
|
+
...(message.componentId !== undefined ? { componentId: message.componentId } : {}),
|
|
337
|
+
...(message.title !== undefined ? { title: message.title } : {}),
|
|
338
|
+
};
|
|
339
|
+
await store.set(uiButtonKey(ref), JSON.stringify(saved), UI_BUTTON_TTL_MS);
|
|
340
|
+
ids.push(`ui:${ref}`);
|
|
341
|
+
known.push(ref);
|
|
342
|
+
}
|
|
343
|
+
await store.set(uiButtonsKey(conversation), JSON.stringify([...new Set(known)].slice(-MAX_UI_BUTTONS)), UI_BUTTON_TTL_MS);
|
|
344
|
+
return ids;
|
|
345
|
+
};
|
|
346
|
+
/** The component button a press (or, for a provider without ids, its label) names, if any. */
|
|
347
|
+
const pressedUiButton = async (store, message) => {
|
|
348
|
+
const match = message.buttonId === undefined ? null : UI_BUTTON_ID.exec(message.buttonId);
|
|
349
|
+
if (match !== null) {
|
|
350
|
+
const saved = await store.get(uiButtonKey(match[1] ?? ''));
|
|
351
|
+
const button = saved === null ? null : JSON.parse(saved);
|
|
352
|
+
return button !== null && button.conversation === message.conversation ? button : null;
|
|
353
|
+
}
|
|
354
|
+
if (message.buttonId !== undefined || message.buttonWithoutId !== true)
|
|
355
|
+
return null;
|
|
356
|
+
const index = await store.get(uiButtonsKey(message.conversation));
|
|
357
|
+
const label = foldLabel(message.text);
|
|
358
|
+
for (const ref of (index === null ? [] : JSON.parse(index)).reverse()) {
|
|
359
|
+
const saved = await store.get(uiButtonKey(ref));
|
|
360
|
+
const button = saved === null ? null : JSON.parse(saved);
|
|
361
|
+
if (button !== null && foldLabel(button.button.label) === label)
|
|
362
|
+
return button;
|
|
363
|
+
}
|
|
364
|
+
return null;
|
|
365
|
+
};
|
|
366
|
+
/**
|
|
367
|
+
* One natively drawn message out: an image with its caption, text with reply buttons, a list (as
|
|
368
|
+
* reply buttons when it fits and the channel has no lists, as numbered text when neither does), or
|
|
369
|
+
* text — in the channel's markdown and limits.
|
|
370
|
+
*/
|
|
371
|
+
const sendNative = async (store, out, conversation, seed, message) => {
|
|
372
|
+
const markdown = (text) => toChannelMarkdown(text, capabilities.markdown);
|
|
373
|
+
const text = message.text ?? '';
|
|
374
|
+
if (message.image !== undefined) {
|
|
375
|
+
const { image } = message;
|
|
376
|
+
await out.reply({
|
|
377
|
+
media: {
|
|
378
|
+
kind: 'image',
|
|
379
|
+
...(image.url !== undefined ? { url: image.url } : {}),
|
|
380
|
+
...(image.data !== undefined ? { data: Buffer.from(image.data) } : {}),
|
|
381
|
+
contentType: image.contentType ?? 'image/png',
|
|
382
|
+
},
|
|
383
|
+
caption: text,
|
|
384
|
+
fallbackText: text,
|
|
385
|
+
}, 'reply');
|
|
386
|
+
}
|
|
387
|
+
const choices = message.list?.items ?? message.buttons ?? [];
|
|
388
|
+
if (choices.length === 0) {
|
|
389
|
+
if (message.image === undefined && text.trim() !== '')
|
|
390
|
+
await out.text(text, 'reply');
|
|
391
|
+
return;
|
|
392
|
+
}
|
|
393
|
+
const body = message.image === undefined ? text : '';
|
|
394
|
+
const numbered = [
|
|
395
|
+
body,
|
|
396
|
+
...(message.list?.title !== undefined ? [`*${message.list.title}*`] : []),
|
|
397
|
+
choices
|
|
398
|
+
.map((choice, index) => `${index + 1}. ${choice.label}${choice.description ? ` — ${choice.description}` : ''}`)
|
|
399
|
+
.join('\n'),
|
|
400
|
+
]
|
|
401
|
+
.filter((part) => part.trim() !== '')
|
|
402
|
+
.join('\n\n');
|
|
403
|
+
const maxButtons = capabilities.buttons ?? 0;
|
|
404
|
+
const asButtons = message.list === undefined || (capabilities.lists ?? 0) === 0;
|
|
405
|
+
if (asButtons && choices.length <= maxButtons) {
|
|
406
|
+
const ids = await rememberUiButtons(store, conversation, seed, message, choices);
|
|
407
|
+
await out.send({
|
|
408
|
+
text: markdown(body.trim() === '' ? (message.title ?? '…') : body).slice(0, capabilities.maxLength),
|
|
409
|
+
buttons: choices.map((choice, index) => ({ id: ids[index] ?? '', label: choice.label })),
|
|
410
|
+
fallbackText: markdown(numbered).slice(0, capabilities.maxLength),
|
|
411
|
+
}, 'reply');
|
|
412
|
+
return;
|
|
413
|
+
}
|
|
414
|
+
const maxRows = capabilities.lists ?? 0;
|
|
415
|
+
if (maxRows > 0) {
|
|
416
|
+
const rows = choices.slice(0, maxRows);
|
|
417
|
+
const ids = await rememberUiButtons(store, conversation, seed, message, rows);
|
|
418
|
+
await out.send({
|
|
419
|
+
text: markdown(body.trim() === '' ? (message.title ?? '…') : body).slice(0, capabilities.maxLength),
|
|
420
|
+
list: {
|
|
421
|
+
button: message.list?.button ?? 'Options',
|
|
422
|
+
...(message.list?.title !== undefined ? { title: message.list.title } : {}),
|
|
423
|
+
rows: rows.map((row, index) => ({
|
|
424
|
+
id: ids[index] ?? '',
|
|
425
|
+
title: row.label,
|
|
426
|
+
...(row.description !== undefined ? { description: row.description } : {}),
|
|
427
|
+
})),
|
|
428
|
+
},
|
|
429
|
+
fallbackText: markdown(numbered).slice(0, capabilities.maxLength),
|
|
430
|
+
}, 'reply');
|
|
431
|
+
return;
|
|
432
|
+
}
|
|
433
|
+
// Neither buttons nor lists: the choices as numbered text.
|
|
434
|
+
await out.text(numbered, 'reply');
|
|
435
|
+
};
|
|
276
436
|
const sendProposal = async (service, store, texts, out, conversation, proposal, withId) => {
|
|
277
437
|
const summary = texts.proposal(proposal);
|
|
278
438
|
const footer = typeof texts.footer === 'function' ? texts.footer(proposal) : texts.footer;
|
|
@@ -606,6 +766,9 @@ export function handleChannel(adapter, options) {
|
|
|
606
766
|
const proposals = new Map();
|
|
607
767
|
/** Components rendered as files, by id (a later one replaces), sent before the text. */
|
|
608
768
|
const rendered = new Map();
|
|
769
|
+
/** Components drawn natively (genui channels), by id, sent where they came in the text. */
|
|
770
|
+
const natives = new Map();
|
|
771
|
+
const native = await genuiFor();
|
|
609
772
|
const asText = new Set();
|
|
610
773
|
let wroteText = false;
|
|
611
774
|
let failed = false;
|
|
@@ -620,10 +783,20 @@ export function handleChannel(adapter, options) {
|
|
|
620
783
|
for (const { replies } of batch)
|
|
621
784
|
for (const reply of replies)
|
|
622
785
|
await out.reply(reply, 'reply');
|
|
623
|
-
|
|
786
|
+
// Text and natively drawn components, in the order the turn produced them.
|
|
787
|
+
const segments = parts.join('').split(NATIVE_MARK);
|
|
624
788
|
parts.length = 0;
|
|
625
|
-
|
|
626
|
-
|
|
789
|
+
for (const [index, segment] of segments.entries()) {
|
|
790
|
+
if (index % 2 === 0) {
|
|
791
|
+
if (segment.trim() !== '')
|
|
792
|
+
await out.text(segment.trim(), 'reply');
|
|
793
|
+
continue;
|
|
794
|
+
}
|
|
795
|
+
const messages = natives.get(segment) ?? [];
|
|
796
|
+
for (const [position, message] of messages.entries())
|
|
797
|
+
await sendNative(store, out, conversation, `${runId}:${segment}:${position}`, message);
|
|
798
|
+
}
|
|
799
|
+
natives.clear();
|
|
627
800
|
if (end && !wroteText && batch.length > 0) {
|
|
628
801
|
const after = texts.componentsOnly?.(batch.map(({ component }) => component));
|
|
629
802
|
if (after !== undefined && after !== '')
|
|
@@ -650,7 +823,33 @@ export function handleChannel(adapter, options) {
|
|
|
650
823
|
break;
|
|
651
824
|
const frame = next.value;
|
|
652
825
|
const component = componentOf(frame, position++);
|
|
653
|
-
if (component !== null) {
|
|
826
|
+
if (component !== null && native !== null) {
|
|
827
|
+
// A genui channel: the component as this channel draws it, where it came in the text.
|
|
828
|
+
const replies = options.renderComponent
|
|
829
|
+
? replyList(await options.renderComponent(component, {
|
|
830
|
+
actor,
|
|
831
|
+
conversation,
|
|
832
|
+
runId,
|
|
833
|
+
rendered: rendered.size,
|
|
834
|
+
}))
|
|
835
|
+
: [];
|
|
836
|
+
if (replies.length > 0) {
|
|
837
|
+
rendered.set(component.id, { component, replies });
|
|
838
|
+
continue;
|
|
839
|
+
}
|
|
840
|
+
const drawn = await renderChannelMessages(native.genui.catalog, {
|
|
841
|
+
id: component.id,
|
|
842
|
+
name: component.name,
|
|
843
|
+
props: (component.data ?? {}),
|
|
844
|
+
}, native.channel);
|
|
845
|
+
if (drawn.length === 0)
|
|
846
|
+
continue;
|
|
847
|
+
wroteText = true;
|
|
848
|
+
if (!natives.has(component.id))
|
|
849
|
+
parts.push(`${NATIVE_MARK}${component.id}${NATIVE_MARK}`);
|
|
850
|
+
natives.set(component.id, drawn);
|
|
851
|
+
}
|
|
852
|
+
else if (component !== null) {
|
|
654
853
|
const replies = options.renderComponent
|
|
655
854
|
? replyList(await options.renderComponent(component, {
|
|
656
855
|
actor,
|
|
@@ -753,6 +952,7 @@ export function handleChannel(adapter, options) {
|
|
|
753
952
|
failed = true;
|
|
754
953
|
// A failed turn shows none of what it drew before failing.
|
|
755
954
|
rendered.clear();
|
|
955
|
+
natives.clear();
|
|
756
956
|
}
|
|
757
957
|
}
|
|
758
958
|
}
|
|
@@ -848,10 +1048,22 @@ export function handleChannel(adapter, options) {
|
|
|
848
1048
|
}
|
|
849
1049
|
if (await pressButton(service, out, actor, threadId, message))
|
|
850
1050
|
return done(null);
|
|
851
|
-
|
|
1051
|
+
// A component's button (or list entry): the user's next turn, as a UI action — the same thing a
|
|
1052
|
+
// sandbox's `agent.send` and an A2UI button become.
|
|
1053
|
+
const uiButton = await pressedUiButton(store, message);
|
|
1054
|
+
const media = uiButton === null ? await attachMedia(service, texts, out, actor, message) : null;
|
|
852
1055
|
let inbound = {
|
|
853
|
-
text:
|
|
854
|
-
|
|
1056
|
+
text: uiButton !== null
|
|
1057
|
+
? uiActionText(channelButtonAction(uiButton.button, {
|
|
1058
|
+
...(uiButton.componentId !== undefined
|
|
1059
|
+
? { componentId: uiButton.componentId }
|
|
1060
|
+
: {}),
|
|
1061
|
+
...(uiButton.title !== undefined ? { title: uiButton.title } : {}),
|
|
1062
|
+
}))
|
|
1063
|
+
: [message.text, ...(media?.extra ?? [])]
|
|
1064
|
+
.filter((part) => part.trim() !== '')
|
|
1065
|
+
.join('\n\n'),
|
|
1066
|
+
attachments: media?.refs ?? [],
|
|
855
1067
|
};
|
|
856
1068
|
if (options.transformInbound)
|
|
857
1069
|
inbound = await options.transformInbound(inbound, {
|
|
@@ -873,7 +1085,15 @@ export function handleChannel(adapter, options) {
|
|
|
873
1085
|
const pageContext = typeof options.pageContext === 'function'
|
|
874
1086
|
? options.pageContext(message)
|
|
875
1087
|
: (options.pageContext ?? { kind: name });
|
|
876
|
-
const channel = {
|
|
1088
|
+
const channel = {
|
|
1089
|
+
name,
|
|
1090
|
+
conversation: message.conversation,
|
|
1091
|
+
...(adapter.kind !== undefined ? { kind: adapter.kind } : {}),
|
|
1092
|
+
choices: { buttons: capabilities.buttons ?? 0, lists: capabilities.lists ?? 0 },
|
|
1093
|
+
};
|
|
1094
|
+
// A channel genui draws for: the turn may push whatever this channel can draw (the tools are
|
|
1095
|
+
// narrowed to it), and the components arrive whole, for the history and for native delivery.
|
|
1096
|
+
const drawsNatively = options.uiCapabilities === undefined && (await genuiFor()) !== null;
|
|
877
1097
|
const sendOptions = { textDecisions: false };
|
|
878
1098
|
let sent;
|
|
879
1099
|
try {
|
|
@@ -883,7 +1103,9 @@ export function handleChannel(adapter, options) {
|
|
|
883
1103
|
...(threadId !== null ? { threadId } : {}),
|
|
884
1104
|
...(options.agentName !== undefined ? { agentName: options.agentName } : {}),
|
|
885
1105
|
...(inbound.attachments.length > 0 ? { attachments: inbound.attachments } : {}),
|
|
886
|
-
|
|
1106
|
+
...(drawsNatively
|
|
1107
|
+
? {}
|
|
1108
|
+
: { uiCapabilities: options.uiCapabilities ?? { components: [] } }),
|
|
887
1109
|
pageContext: { ...pageContext, channel },
|
|
888
1110
|
hostContext: {
|
|
889
1111
|
channel: name,
|