@agentskit/chat 0.1.0 → 0.2.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/README.md CHANGED
@@ -26,6 +26,6 @@ formatSemanticFallback(fallback)
26
26
 
27
27
  Custom application UI is declared through `defineComponentManifest`. The first schema-backed component is `ChoiceListComponent`; untrusted frames must pass `resolveComponentFrame` before rendering.
28
28
 
29
- Shared Ask-service hosts use `createAskAdapter` and `createAskSessionMemory`. The adapter owns the validated NDJSON boundary and ordered text/source projection; memory composes `@agentskit/memory/web-storage` rather than implementing another message store. See [`docs/protocol/ask-service.md`](../../docs/protocol/ask-service.md).
29
+ Shared Ask-service hosts use `createAskAdapter` and `createAskSessionMemory`. The adapter owns the validated NDJSON boundary and ordered text/source projection; memory composes `@agentskit/memory/web-storage` rather than implementing another message store. A resumed application session is forwarded through the additive Ask request, and deterministic escalations contribute bounded low-confidence context. Trusted site/corpus authority remains server-side. See [`docs/protocol/ask-service.md`](../../docs/protocol/ask-service.md).
30
30
 
31
31
  To answer exact local facts before Ask or another backend, verify the artifact and compose `createDeterministicAnswerAdapter({ artifact, expectedContentHash, expectedSiteId, fallbackMode, fallback })`. Wire its `resolveChoiceSubmission` into `definition.choiceSubmission` so only adapter-projected, single-use choices can submit their visible alias. One exact match renders locally, ambiguity exposes visible unique choices across all seven renderers, disabled fallback never calls the backend, and bounded successful backend streams receive the same answer envelope on completion. The contract is accepted in ADR-0024; see [`docs/protocol/deterministic-answers.md`](../../docs/protocol/deterministic-answers.md).
package/dist/index.cjs CHANGED
@@ -340,101 +340,111 @@ var encodeText = function* (encode, text) {
340
340
  }
341
341
  };
342
342
  function createAskAdapter(options = {}) {
343
- return {
344
- capabilities: { streaming: true, structuredOutput: true },
345
- createSource(request) {
346
- const controller = new AbortController();
347
- return {
348
- abort: () => controller.abort(),
349
- async *stream() {
350
- const encode = createBoundedAssistantEncoder();
343
+ const createSourceForSession = (request, sessionId) => {
344
+ const controller = new AbortController();
345
+ const escalation2 = import_chat_protocol.AnswerResponseSchema.safeParse(request.context?.metadata?.["agentskit.chat.escalation"]);
346
+ const deterministic = escalation2.success && escalation2.data.outcome === "escalation" ? escalation2.data : void 0;
347
+ return {
348
+ abort: () => controller.abort(),
349
+ async *stream() {
350
+ const encode = createBoundedAssistantEncoder();
351
+ try {
352
+ const connection = new AbortController();
353
+ const timeout = setTimeout(() => connection.abort(), DEFAULT_CONNECTION_TIMEOUT_MS);
354
+ let response;
351
355
  try {
352
- const connection = new AbortController();
353
- const timeout = setTimeout(() => connection.abort(), DEFAULT_CONNECTION_TIMEOUT_MS);
354
- let response;
355
- try {
356
- response = await fetch(endpointWithParams(options), {
357
- method: "POST",
358
- signal: AbortSignal.any([controller.signal, connection.signal]),
359
- headers: { "content-type": "application/json" },
360
- body: JSON.stringify({ messages: projectAskMessages(request.messages) })
361
- });
362
- } finally {
363
- clearTimeout(timeout);
364
- }
365
- if (!response.ok || response.body === null) throw new Error(`Ask request failed (${response.status}).`);
366
- const reader = response.body.getReader();
367
- const decoder = new TextDecoder();
368
- let buffer = "";
369
- const contentType = response.headers.get("content-type")?.toLowerCase() ?? "";
370
- let mode = contentType.includes("text/plain") ? "text" : contentType.includes("ndjson") ? "ndjson" : "unknown";
371
- let discardingOversizedLine = false;
372
- while (true) {
373
- const result = await reader.read();
374
- let incoming = decoder.decode(result.value, { stream: !result.done });
375
- if (discardingOversizedLine) {
376
- const lineEnd = incoming.indexOf("\n");
377
- if (lineEnd < 0) {
378
- if (result.done) break;
379
- continue;
380
- }
381
- incoming = incoming.slice(lineEnd + 1);
382
- discardingOversizedLine = false;
383
- }
384
- buffer += incoming;
385
- if (mode === "unknown" && buffer.trimStart() !== "") {
386
- if (!buffer.trimStart().startsWith("{")) mode = "text";
387
- else {
388
- const lineEnd = buffer.indexOf("\n");
389
- if (lineEnd >= 0 || result.done) {
390
- const firstLine = lineEnd >= 0 ? buffer.slice(0, lineEnd + 1) : `${buffer}
391
- `;
392
- mode = (0, import_chat_protocol.decodeAskEvents)(firstLine).events.length > 0 ? "ndjson" : "text";
393
- } else if (new TextEncoder().encode(buffer).byteLength > import_chat_protocol.ASK_EVENT_MAX_BYTES) {
394
- buffer = "";
395
- discardingOversizedLine = true;
396
- }
397
- }
398
- }
399
- if (mode === "unknown" && !result.done) continue;
400
- if (mode === "text") {
401
- yield* encodeText(encode, buffer);
402
- buffer = "";
356
+ response = await fetch(endpointWithParams(options), {
357
+ method: "POST",
358
+ signal: AbortSignal.any([controller.signal, connection.signal]),
359
+ headers: { "content-type": "application/json" },
360
+ body: JSON.stringify({
361
+ protocol: "agentskit.chat.ask",
362
+ version: 1,
363
+ ...sessionId === "unscoped" ? {} : { sessionId },
364
+ messages: projectAskMessages(request.messages),
365
+ ...deterministic === void 0 ? {} : { deterministic }
366
+ })
367
+ });
368
+ } finally {
369
+ clearTimeout(timeout);
370
+ }
371
+ if (!response.ok || response.body === null) throw new Error(`Ask request failed (${response.status}).`);
372
+ const reader = response.body.getReader();
373
+ const decoder = new TextDecoder();
374
+ let buffer = "";
375
+ const contentType = response.headers.get("content-type")?.toLowerCase() ?? "";
376
+ let mode = contentType.includes("ndjson") ? "ndjson" : "unknown";
377
+ let discardingOversizedLine = false;
378
+ while (true) {
379
+ const result = await reader.read();
380
+ let incoming = decoder.decode(result.value, { stream: !result.done });
381
+ if (discardingOversizedLine) {
382
+ const lineEnd = incoming.indexOf("\n");
383
+ if (lineEnd < 0) {
403
384
  if (result.done) break;
404
385
  continue;
405
386
  }
406
- const decoded = (0, import_chat_protocol.decodeAskEvents)(result.done ? `${buffer}
407
- ` : buffer);
408
- buffer = decoded.rest;
409
- discardingOversizedLine = decoded.discardedPartial;
410
- for (const event of decoded.events) {
411
- const projected = projectAskEvent(event, options.projectTool);
412
- if (projected?.kind === "error") {
413
- void reader.cancel().catch(() => void 0);
414
- yield { type: "error", content: projected.message };
415
- return;
416
- }
417
- if (projected?.kind === "done") {
418
- void reader.cancel().catch(() => void 0);
419
- yield { type: "done" };
420
- return;
421
- }
422
- if (projected?.kind === "text") yield* encodeText(encode, projected.text);
423
- if (projected?.kind === "component") {
424
- yield { type: "text", content: encode({ kind: "component", frame: projected.frame }) };
387
+ incoming = incoming.slice(lineEnd + 1);
388
+ discardingOversizedLine = false;
389
+ }
390
+ buffer += incoming;
391
+ if (mode === "unknown" && buffer.trimStart() !== "") {
392
+ if (!buffer.trimStart().startsWith("{")) mode = "text";
393
+ else {
394
+ const lineEnd = buffer.indexOf("\n");
395
+ if (lineEnd >= 0 || result.done) {
396
+ const firstLine = lineEnd >= 0 ? buffer.slice(0, lineEnd + 1) : `${buffer}
397
+ `;
398
+ mode = (0, import_chat_protocol.decodeAskEvents)(firstLine).events.length > 0 ? "ndjson" : "text";
399
+ } else if (new TextEncoder().encode(buffer).byteLength > import_chat_protocol.ASK_EVENT_MAX_BYTES) {
400
+ buffer = "";
401
+ discardingOversizedLine = true;
425
402
  }
426
403
  }
404
+ }
405
+ if (mode === "unknown" && !result.done) continue;
406
+ if (mode === "text") {
407
+ yield* encodeText(encode, buffer);
408
+ buffer = "";
427
409
  if (result.done) break;
410
+ continue;
428
411
  }
429
- yield { type: "done" };
430
- } catch (cause) {
431
- if (!controller.signal.aborted) {
432
- yield { type: "error", content: cause instanceof Error ? cause.message : "Ask request failed." };
412
+ const decoded = (0, import_chat_protocol.decodeAskEvents)(result.done ? `${buffer}
413
+ ` : buffer);
414
+ buffer = decoded.rest;
415
+ discardingOversizedLine = decoded.discardedPartial;
416
+ for (const event of decoded.events) {
417
+ const projected = projectAskEvent(event, options.projectTool);
418
+ if (projected?.kind === "error") {
419
+ void reader.cancel().catch(() => void 0);
420
+ yield { type: "error", content: projected.message };
421
+ return;
422
+ }
423
+ if (projected?.kind === "done") {
424
+ void reader.cancel().catch(() => void 0);
425
+ yield { type: "done" };
426
+ return;
427
+ }
428
+ if (projected?.kind === "text") yield* encodeText(encode, projected.text);
429
+ if (projected?.kind === "component") {
430
+ yield { type: "text", content: encode({ kind: "component", frame: projected.frame }) };
431
+ }
433
432
  }
433
+ if (result.done) break;
434
+ }
435
+ yield { type: "done" };
436
+ } catch (cause) {
437
+ if (!controller.signal.aborted) {
438
+ yield { type: "error", content: cause instanceof Error ? cause.message : "Ask request failed." };
434
439
  }
435
440
  }
436
- };
437
- }
441
+ }
442
+ };
443
+ };
444
+ return {
445
+ capabilities: { streaming: true, structuredOutput: true },
446
+ createSource: (request) => createSourceForSession(request, "unscoped"),
447
+ createSourceForSession
438
448
  };
439
449
  }
440
450
  var legacyContent = (record, projectTool) => {
package/dist/index.d.cts CHANGED
@@ -1,7 +1,7 @@
1
1
  import * as _agentskit_chat_protocol from '@agentskit/chat-protocol';
2
2
  import { AskToolEvent, ComponentRenderFrame, AskEvent, VerifiedLocalKnowledgeArtifact, DeterministicSiteConfig, AnswerResponse, SessionConfirmation, SessionSnapshot, ComponentInteractionEvent, ComponentSelectionEvent } from '@agentskit/chat-protocol';
3
3
  export { AskEvent, AskEventSchema, AskToolEvent, decodeAskEvents } from '@agentskit/chat-protocol';
4
- import { AdapterFactory, ChatMemory, Message, AdapterRequest, StreamSource, ChatReturn, ToolAuthorizer, ChatConfig } from '@agentskit/core';
4
+ import { AdapterFactory, AdapterRequest, StreamSource, ChatMemory, Message, ChatReturn, ToolAuthorizer, ChatConfig } from '@agentskit/core';
5
5
  import { z } from 'zod';
6
6
  import { WebStorageLike } from '@agentskit/memory/web-storage';
7
7
 
@@ -342,6 +342,9 @@ interface AskMemoryOptions {
342
342
  readonly getStorage?: () => WebStorageLike | undefined;
343
343
  readonly projectTool?: AskToolProjector;
344
344
  }
345
+ interface AskAdapter extends AdapterFactory {
346
+ readonly createSourceForSession: (request: AdapterRequest, sessionId: string) => StreamSource;
347
+ }
345
348
 
346
349
  /** Projects a validated Ask wire event into canonical ordered assistant content. */
347
350
  declare function projectAskEvent(event: AskEvent, projectTool?: AskToolProjector): AskProjection | undefined;
@@ -350,7 +353,7 @@ declare function projectAskMessages(messages: readonly Message[]): Array<{
350
353
  readonly content: string;
351
354
  }>;
352
355
  /** Creates the shared Ask adapter without replacing the AgentsKit controller or message model. */
353
- declare function createAskAdapter(options?: AskAdapterOptions): AdapterFactory;
356
+ declare function createAskAdapter(options?: AskAdapterOptions): AskAdapter;
354
357
  /** Composes Ask legacy migration over the released, validated Web Storage ChatMemory. */
355
358
  declare function createAskSessionMemory({ key, legacyKeys, maxMessages, maxRecordBytes, getStorage, projectTool, }: AskMemoryOptions): ChatMemory;
356
359
 
@@ -615,4 +618,4 @@ type SemanticFallback = z.infer<typeof SemanticFallbackSchema>;
615
618
  declare const parseSemanticFallback: (input: unknown) => SemanticFallback;
616
619
  declare const formatSemanticFallback: (fallback: SemanticFallback) => string;
617
620
 
618
- export { type ActionConfirmation, type ActionConfirmationCoordinator, type ActionConfirmationOptions, type ActionConfirmationStatus, type ActionPolicy, type ActionPolicyReason, type ActionPolicyTrace, ApprovalRequestComponent, ApprovalRequestPropsSchema, type AskAdapterOptions, type AskMemoryOptions, type AskProjection, type AskToolProjector, ButtonGroupComponent, ButtonGroupPropsSchema, CHOICE_LIST_COMPONENT_KEY, type CapabilityPolicyOptions, type ChatDefinition, type ChatMessagePresentation, type ChatSession, type ChatSessionOptions, type ChatTheme, type ChatThemeInput, ChatThemeSchema, type ChoiceAction, ChoiceListComponent, type ChoiceListProps, ChoiceListPropsSchema, type ChoiceSubmissionReservation, type ChoiceSubmissionUnavailable, type ComponentAccessibilityDefinition, type ComponentCapability, type ComponentDefinition, type ComponentEventDefinition, type ComponentManifest, ConfirmationComponent, ConfirmationPropsSchema, type ConversationDefinition, type ConversationSnapshot, type ConversationStateDefinition, type DeterministicAnswerAdapter, type DeterministicAnswerAdapterOptions, type DeterministicAnswerResolver, type DeterministicAnswerResolverOptions, type DeterministicRoute, type DeterministicRouteContext, ErrorNoticeComponent, ErrorNoticePropsSchema, FileAttachmentComponent, FileAttachmentPropsSchema, FormComponent, FormPropsSchema, LinkCardComponent, LinkCardPropsSchema, ProgressComponent, ProgressPropsSchema, type ResolveChoiceListFrameResult, type ResolveComponentFrameResult, type ResumeChatSessionOptions, STANDARD_COMPONENT_KEYS, type SemanticFallback, SemanticFallbackSchema, SessionConflictError, type SessionStorage, SourceListComponent, SourceListPropsSchema, StandardComponentCatalog, TableComponent, TablePropsSchema, ToolCallComponent, ToolCallPropsSchema, type TrustedActionContext, type TurnTrace, type TurnTraceKind, commandRoute, createActionConfirmation, createAskAdapter, createAskSessionMemory, createCapabilityPolicy, createChatSession, createComponentInteraction, createDeterministicAnswerAdapter, createDeterministicAnswerResolver, defaultChatTheme, defineChat, defineComponentManifest, formatSemanticFallback, getLifecycleTargets, normalizeDeterministicQuery, parseSemanticFallback, presentChatMessage, projectAskEvent, projectAskMessages, resolveChatSession, resolveChatTheme, resolveChoiceAction, resolveChoiceListFrame, resolveComponentFallback, resolveComponentFrame, resumeChatSession, selectChoice, validateStandardComponentInteraction, withActionPolicy };
621
+ export { type ActionConfirmation, type ActionConfirmationCoordinator, type ActionConfirmationOptions, type ActionConfirmationStatus, type ActionPolicy, type ActionPolicyReason, type ActionPolicyTrace, ApprovalRequestComponent, ApprovalRequestPropsSchema, type AskAdapter, type AskAdapterOptions, type AskMemoryOptions, type AskProjection, type AskToolProjector, ButtonGroupComponent, ButtonGroupPropsSchema, CHOICE_LIST_COMPONENT_KEY, type CapabilityPolicyOptions, type ChatDefinition, type ChatMessagePresentation, type ChatSession, type ChatSessionOptions, type ChatTheme, type ChatThemeInput, ChatThemeSchema, type ChoiceAction, ChoiceListComponent, type ChoiceListProps, ChoiceListPropsSchema, type ChoiceSubmissionReservation, type ChoiceSubmissionUnavailable, type ComponentAccessibilityDefinition, type ComponentCapability, type ComponentDefinition, type ComponentEventDefinition, type ComponentManifest, ConfirmationComponent, ConfirmationPropsSchema, type ConversationDefinition, type ConversationSnapshot, type ConversationStateDefinition, type DeterministicAnswerAdapter, type DeterministicAnswerAdapterOptions, type DeterministicAnswerResolver, type DeterministicAnswerResolverOptions, type DeterministicRoute, type DeterministicRouteContext, ErrorNoticeComponent, ErrorNoticePropsSchema, FileAttachmentComponent, FileAttachmentPropsSchema, FormComponent, FormPropsSchema, LinkCardComponent, LinkCardPropsSchema, ProgressComponent, ProgressPropsSchema, type ResolveChoiceListFrameResult, type ResolveComponentFrameResult, type ResumeChatSessionOptions, STANDARD_COMPONENT_KEYS, type SemanticFallback, SemanticFallbackSchema, SessionConflictError, type SessionStorage, SourceListComponent, SourceListPropsSchema, StandardComponentCatalog, TableComponent, TablePropsSchema, ToolCallComponent, ToolCallPropsSchema, type TrustedActionContext, type TurnTrace, type TurnTraceKind, commandRoute, createActionConfirmation, createAskAdapter, createAskSessionMemory, createCapabilityPolicy, createChatSession, createComponentInteraction, createDeterministicAnswerAdapter, createDeterministicAnswerResolver, defaultChatTheme, defineChat, defineComponentManifest, formatSemanticFallback, getLifecycleTargets, normalizeDeterministicQuery, parseSemanticFallback, presentChatMessage, projectAskEvent, projectAskMessages, resolveChatSession, resolveChatTheme, resolveChoiceAction, resolveChoiceListFrame, resolveComponentFallback, resolveComponentFrame, resumeChatSession, selectChoice, validateStandardComponentInteraction, withActionPolicy };
package/dist/index.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import * as _agentskit_chat_protocol from '@agentskit/chat-protocol';
2
2
  import { AskToolEvent, ComponentRenderFrame, AskEvent, VerifiedLocalKnowledgeArtifact, DeterministicSiteConfig, AnswerResponse, SessionConfirmation, SessionSnapshot, ComponentInteractionEvent, ComponentSelectionEvent } from '@agentskit/chat-protocol';
3
3
  export { AskEvent, AskEventSchema, AskToolEvent, decodeAskEvents } from '@agentskit/chat-protocol';
4
- import { AdapterFactory, ChatMemory, Message, AdapterRequest, StreamSource, ChatReturn, ToolAuthorizer, ChatConfig } from '@agentskit/core';
4
+ import { AdapterFactory, AdapterRequest, StreamSource, ChatMemory, Message, ChatReturn, ToolAuthorizer, ChatConfig } from '@agentskit/core';
5
5
  import { z } from 'zod';
6
6
  import { WebStorageLike } from '@agentskit/memory/web-storage';
7
7
 
@@ -342,6 +342,9 @@ interface AskMemoryOptions {
342
342
  readonly getStorage?: () => WebStorageLike | undefined;
343
343
  readonly projectTool?: AskToolProjector;
344
344
  }
345
+ interface AskAdapter extends AdapterFactory {
346
+ readonly createSourceForSession: (request: AdapterRequest, sessionId: string) => StreamSource;
347
+ }
345
348
 
346
349
  /** Projects a validated Ask wire event into canonical ordered assistant content. */
347
350
  declare function projectAskEvent(event: AskEvent, projectTool?: AskToolProjector): AskProjection | undefined;
@@ -350,7 +353,7 @@ declare function projectAskMessages(messages: readonly Message[]): Array<{
350
353
  readonly content: string;
351
354
  }>;
352
355
  /** Creates the shared Ask adapter without replacing the AgentsKit controller or message model. */
353
- declare function createAskAdapter(options?: AskAdapterOptions): AdapterFactory;
356
+ declare function createAskAdapter(options?: AskAdapterOptions): AskAdapter;
354
357
  /** Composes Ask legacy migration over the released, validated Web Storage ChatMemory. */
355
358
  declare function createAskSessionMemory({ key, legacyKeys, maxMessages, maxRecordBytes, getStorage, projectTool, }: AskMemoryOptions): ChatMemory;
356
359
 
@@ -615,4 +618,4 @@ type SemanticFallback = z.infer<typeof SemanticFallbackSchema>;
615
618
  declare const parseSemanticFallback: (input: unknown) => SemanticFallback;
616
619
  declare const formatSemanticFallback: (fallback: SemanticFallback) => string;
617
620
 
618
- export { type ActionConfirmation, type ActionConfirmationCoordinator, type ActionConfirmationOptions, type ActionConfirmationStatus, type ActionPolicy, type ActionPolicyReason, type ActionPolicyTrace, ApprovalRequestComponent, ApprovalRequestPropsSchema, type AskAdapterOptions, type AskMemoryOptions, type AskProjection, type AskToolProjector, ButtonGroupComponent, ButtonGroupPropsSchema, CHOICE_LIST_COMPONENT_KEY, type CapabilityPolicyOptions, type ChatDefinition, type ChatMessagePresentation, type ChatSession, type ChatSessionOptions, type ChatTheme, type ChatThemeInput, ChatThemeSchema, type ChoiceAction, ChoiceListComponent, type ChoiceListProps, ChoiceListPropsSchema, type ChoiceSubmissionReservation, type ChoiceSubmissionUnavailable, type ComponentAccessibilityDefinition, type ComponentCapability, type ComponentDefinition, type ComponentEventDefinition, type ComponentManifest, ConfirmationComponent, ConfirmationPropsSchema, type ConversationDefinition, type ConversationSnapshot, type ConversationStateDefinition, type DeterministicAnswerAdapter, type DeterministicAnswerAdapterOptions, type DeterministicAnswerResolver, type DeterministicAnswerResolverOptions, type DeterministicRoute, type DeterministicRouteContext, ErrorNoticeComponent, ErrorNoticePropsSchema, FileAttachmentComponent, FileAttachmentPropsSchema, FormComponent, FormPropsSchema, LinkCardComponent, LinkCardPropsSchema, ProgressComponent, ProgressPropsSchema, type ResolveChoiceListFrameResult, type ResolveComponentFrameResult, type ResumeChatSessionOptions, STANDARD_COMPONENT_KEYS, type SemanticFallback, SemanticFallbackSchema, SessionConflictError, type SessionStorage, SourceListComponent, SourceListPropsSchema, StandardComponentCatalog, TableComponent, TablePropsSchema, ToolCallComponent, ToolCallPropsSchema, type TrustedActionContext, type TurnTrace, type TurnTraceKind, commandRoute, createActionConfirmation, createAskAdapter, createAskSessionMemory, createCapabilityPolicy, createChatSession, createComponentInteraction, createDeterministicAnswerAdapter, createDeterministicAnswerResolver, defaultChatTheme, defineChat, defineComponentManifest, formatSemanticFallback, getLifecycleTargets, normalizeDeterministicQuery, parseSemanticFallback, presentChatMessage, projectAskEvent, projectAskMessages, resolveChatSession, resolveChatTheme, resolveChoiceAction, resolveChoiceListFrame, resolveComponentFallback, resolveComponentFrame, resumeChatSession, selectChoice, validateStandardComponentInteraction, withActionPolicy };
621
+ export { type ActionConfirmation, type ActionConfirmationCoordinator, type ActionConfirmationOptions, type ActionConfirmationStatus, type ActionPolicy, type ActionPolicyReason, type ActionPolicyTrace, ApprovalRequestComponent, ApprovalRequestPropsSchema, type AskAdapter, type AskAdapterOptions, type AskMemoryOptions, type AskProjection, type AskToolProjector, ButtonGroupComponent, ButtonGroupPropsSchema, CHOICE_LIST_COMPONENT_KEY, type CapabilityPolicyOptions, type ChatDefinition, type ChatMessagePresentation, type ChatSession, type ChatSessionOptions, type ChatTheme, type ChatThemeInput, ChatThemeSchema, type ChoiceAction, ChoiceListComponent, type ChoiceListProps, ChoiceListPropsSchema, type ChoiceSubmissionReservation, type ChoiceSubmissionUnavailable, type ComponentAccessibilityDefinition, type ComponentCapability, type ComponentDefinition, type ComponentEventDefinition, type ComponentManifest, ConfirmationComponent, ConfirmationPropsSchema, type ConversationDefinition, type ConversationSnapshot, type ConversationStateDefinition, type DeterministicAnswerAdapter, type DeterministicAnswerAdapterOptions, type DeterministicAnswerResolver, type DeterministicAnswerResolverOptions, type DeterministicRoute, type DeterministicRouteContext, ErrorNoticeComponent, ErrorNoticePropsSchema, FileAttachmentComponent, FileAttachmentPropsSchema, FormComponent, FormPropsSchema, LinkCardComponent, LinkCardPropsSchema, ProgressComponent, ProgressPropsSchema, type ResolveChoiceListFrameResult, type ResolveComponentFrameResult, type ResumeChatSessionOptions, STANDARD_COMPONENT_KEYS, type SemanticFallback, SemanticFallbackSchema, SessionConflictError, type SessionStorage, SourceListComponent, SourceListPropsSchema, StandardComponentCatalog, TableComponent, TablePropsSchema, ToolCallComponent, ToolCallPropsSchema, type TrustedActionContext, type TurnTrace, type TurnTraceKind, commandRoute, createActionConfirmation, createAskAdapter, createAskSessionMemory, createCapabilityPolicy, createChatSession, createComponentInteraction, createDeterministicAnswerAdapter, createDeterministicAnswerResolver, defaultChatTheme, defineChat, defineComponentManifest, formatSemanticFallback, getLifecycleTargets, normalizeDeterministicQuery, parseSemanticFallback, presentChatMessage, projectAskEvent, projectAskMessages, resolveChatSession, resolveChatTheme, resolveChoiceAction, resolveChoiceListFrame, resolveComponentFallback, resolveComponentFrame, resumeChatSession, selectChoice, validateStandardComponentInteraction, withActionPolicy };
package/dist/index.js CHANGED
@@ -155,6 +155,7 @@ var validateStandardComponentInteraction = (componentKey, props, event, value) =
155
155
  import { createWebStorageMemory } from "@agentskit/memory/web-storage";
156
156
  import {
157
157
  ASK_EVENT_MAX_BYTES,
158
+ AnswerResponseSchema,
158
159
  ASSISTANT_CONTENT_MAX_BYTES,
159
160
  ASSISTANT_CONTENT_MAX_RECORDS,
160
161
  ComponentRenderFrameSchema,
@@ -274,101 +275,111 @@ var encodeText = function* (encode, text) {
274
275
  }
275
276
  };
276
277
  function createAskAdapter(options = {}) {
277
- return {
278
- capabilities: { streaming: true, structuredOutput: true },
279
- createSource(request) {
280
- const controller = new AbortController();
281
- return {
282
- abort: () => controller.abort(),
283
- async *stream() {
284
- const encode = createBoundedAssistantEncoder();
278
+ const createSourceForSession = (request, sessionId) => {
279
+ const controller = new AbortController();
280
+ const escalation2 = AnswerResponseSchema.safeParse(request.context?.metadata?.["agentskit.chat.escalation"]);
281
+ const deterministic = escalation2.success && escalation2.data.outcome === "escalation" ? escalation2.data : void 0;
282
+ return {
283
+ abort: () => controller.abort(),
284
+ async *stream() {
285
+ const encode = createBoundedAssistantEncoder();
286
+ try {
287
+ const connection = new AbortController();
288
+ const timeout = setTimeout(() => connection.abort(), DEFAULT_CONNECTION_TIMEOUT_MS);
289
+ let response;
285
290
  try {
286
- const connection = new AbortController();
287
- const timeout = setTimeout(() => connection.abort(), DEFAULT_CONNECTION_TIMEOUT_MS);
288
- let response;
289
- try {
290
- response = await fetch(endpointWithParams(options), {
291
- method: "POST",
292
- signal: AbortSignal.any([controller.signal, connection.signal]),
293
- headers: { "content-type": "application/json" },
294
- body: JSON.stringify({ messages: projectAskMessages(request.messages) })
295
- });
296
- } finally {
297
- clearTimeout(timeout);
298
- }
299
- if (!response.ok || response.body === null) throw new Error(`Ask request failed (${response.status}).`);
300
- const reader = response.body.getReader();
301
- const decoder = new TextDecoder();
302
- let buffer = "";
303
- const contentType = response.headers.get("content-type")?.toLowerCase() ?? "";
304
- let mode = contentType.includes("text/plain") ? "text" : contentType.includes("ndjson") ? "ndjson" : "unknown";
305
- let discardingOversizedLine = false;
306
- while (true) {
307
- const result = await reader.read();
308
- let incoming = decoder.decode(result.value, { stream: !result.done });
309
- if (discardingOversizedLine) {
310
- const lineEnd = incoming.indexOf("\n");
311
- if (lineEnd < 0) {
312
- if (result.done) break;
313
- continue;
314
- }
315
- incoming = incoming.slice(lineEnd + 1);
316
- discardingOversizedLine = false;
317
- }
318
- buffer += incoming;
319
- if (mode === "unknown" && buffer.trimStart() !== "") {
320
- if (!buffer.trimStart().startsWith("{")) mode = "text";
321
- else {
322
- const lineEnd = buffer.indexOf("\n");
323
- if (lineEnd >= 0 || result.done) {
324
- const firstLine = lineEnd >= 0 ? buffer.slice(0, lineEnd + 1) : `${buffer}
325
- `;
326
- mode = decodeAskEvents(firstLine).events.length > 0 ? "ndjson" : "text";
327
- } else if (new TextEncoder().encode(buffer).byteLength > ASK_EVENT_MAX_BYTES) {
328
- buffer = "";
329
- discardingOversizedLine = true;
330
- }
331
- }
332
- }
333
- if (mode === "unknown" && !result.done) continue;
334
- if (mode === "text") {
335
- yield* encodeText(encode, buffer);
336
- buffer = "";
291
+ response = await fetch(endpointWithParams(options), {
292
+ method: "POST",
293
+ signal: AbortSignal.any([controller.signal, connection.signal]),
294
+ headers: { "content-type": "application/json" },
295
+ body: JSON.stringify({
296
+ protocol: "agentskit.chat.ask",
297
+ version: 1,
298
+ ...sessionId === "unscoped" ? {} : { sessionId },
299
+ messages: projectAskMessages(request.messages),
300
+ ...deterministic === void 0 ? {} : { deterministic }
301
+ })
302
+ });
303
+ } finally {
304
+ clearTimeout(timeout);
305
+ }
306
+ if (!response.ok || response.body === null) throw new Error(`Ask request failed (${response.status}).`);
307
+ const reader = response.body.getReader();
308
+ const decoder = new TextDecoder();
309
+ let buffer = "";
310
+ const contentType = response.headers.get("content-type")?.toLowerCase() ?? "";
311
+ let mode = contentType.includes("ndjson") ? "ndjson" : "unknown";
312
+ let discardingOversizedLine = false;
313
+ while (true) {
314
+ const result = await reader.read();
315
+ let incoming = decoder.decode(result.value, { stream: !result.done });
316
+ if (discardingOversizedLine) {
317
+ const lineEnd = incoming.indexOf("\n");
318
+ if (lineEnd < 0) {
337
319
  if (result.done) break;
338
320
  continue;
339
321
  }
340
- const decoded = decodeAskEvents(result.done ? `${buffer}
341
- ` : buffer);
342
- buffer = decoded.rest;
343
- discardingOversizedLine = decoded.discardedPartial;
344
- for (const event of decoded.events) {
345
- const projected = projectAskEvent(event, options.projectTool);
346
- if (projected?.kind === "error") {
347
- void reader.cancel().catch(() => void 0);
348
- yield { type: "error", content: projected.message };
349
- return;
350
- }
351
- if (projected?.kind === "done") {
352
- void reader.cancel().catch(() => void 0);
353
- yield { type: "done" };
354
- return;
355
- }
356
- if (projected?.kind === "text") yield* encodeText(encode, projected.text);
357
- if (projected?.kind === "component") {
358
- yield { type: "text", content: encode({ kind: "component", frame: projected.frame }) };
322
+ incoming = incoming.slice(lineEnd + 1);
323
+ discardingOversizedLine = false;
324
+ }
325
+ buffer += incoming;
326
+ if (mode === "unknown" && buffer.trimStart() !== "") {
327
+ if (!buffer.trimStart().startsWith("{")) mode = "text";
328
+ else {
329
+ const lineEnd = buffer.indexOf("\n");
330
+ if (lineEnd >= 0 || result.done) {
331
+ const firstLine = lineEnd >= 0 ? buffer.slice(0, lineEnd + 1) : `${buffer}
332
+ `;
333
+ mode = decodeAskEvents(firstLine).events.length > 0 ? "ndjson" : "text";
334
+ } else if (new TextEncoder().encode(buffer).byteLength > ASK_EVENT_MAX_BYTES) {
335
+ buffer = "";
336
+ discardingOversizedLine = true;
359
337
  }
360
338
  }
339
+ }
340
+ if (mode === "unknown" && !result.done) continue;
341
+ if (mode === "text") {
342
+ yield* encodeText(encode, buffer);
343
+ buffer = "";
361
344
  if (result.done) break;
345
+ continue;
362
346
  }
363
- yield { type: "done" };
364
- } catch (cause) {
365
- if (!controller.signal.aborted) {
366
- yield { type: "error", content: cause instanceof Error ? cause.message : "Ask request failed." };
347
+ const decoded = decodeAskEvents(result.done ? `${buffer}
348
+ ` : buffer);
349
+ buffer = decoded.rest;
350
+ discardingOversizedLine = decoded.discardedPartial;
351
+ for (const event of decoded.events) {
352
+ const projected = projectAskEvent(event, options.projectTool);
353
+ if (projected?.kind === "error") {
354
+ void reader.cancel().catch(() => void 0);
355
+ yield { type: "error", content: projected.message };
356
+ return;
357
+ }
358
+ if (projected?.kind === "done") {
359
+ void reader.cancel().catch(() => void 0);
360
+ yield { type: "done" };
361
+ return;
362
+ }
363
+ if (projected?.kind === "text") yield* encodeText(encode, projected.text);
364
+ if (projected?.kind === "component") {
365
+ yield { type: "text", content: encode({ kind: "component", frame: projected.frame }) };
366
+ }
367
367
  }
368
+ if (result.done) break;
369
+ }
370
+ yield { type: "done" };
371
+ } catch (cause) {
372
+ if (!controller.signal.aborted) {
373
+ yield { type: "error", content: cause instanceof Error ? cause.message : "Ask request failed." };
368
374
  }
369
375
  }
370
- };
371
- }
376
+ }
377
+ };
378
+ };
379
+ return {
380
+ capabilities: { streaming: true, structuredOutput: true },
381
+ createSource: (request) => createSourceForSession(request, "unscoped"),
382
+ createSourceForSession
372
383
  };
373
384
  }
374
385
  var legacyContent = (record, projectTool) => {
@@ -465,7 +476,7 @@ import {
465
476
  ANSWER_PROTOCOL,
466
477
  ANSWER_PROTOCOL_VERSION,
467
478
  AnswerCitationSchema,
468
- AnswerResponseSchema,
479
+ AnswerResponseSchema as AnswerResponseSchema2,
469
480
  COMPONENT_PROTOCOL,
470
481
  COMPONENT_PROTOCOL_VERSION,
471
482
  createAssistantContentEncoder as createAssistantContentEncoder2,
@@ -481,7 +492,7 @@ var baseResponse = (query) => ({
481
492
  query: query.slice(0, 512),
482
493
  normalizedQuery: normalizeDeterministicQuery(query.slice(0, 512)).slice(0, 512)
483
494
  });
484
- var escalation = (query, reason, message) => AnswerResponseSchema.parse({
495
+ var escalation = (query, reason, message) => AnswerResponseSchema2.parse({
485
496
  ...baseResponse(query),
486
497
  outcome: "escalation",
487
498
  message,
@@ -507,7 +518,7 @@ var createDeterministicAnswerResolver = (artifactInput, options) => {
507
518
  }
508
519
  const now = options.now ?? Date.now;
509
520
  const isStale = () => artifact.expiresAt !== void 0 && Date.parse(artifact.expiresAt) <= now();
510
- const answerForEntry = (entry, query) => AnswerResponseSchema.parse({
521
+ const answerForEntry = (entry, query) => AnswerResponseSchema2.parse({
511
522
  ...baseResponse(query),
512
523
  outcome: "answer",
513
524
  answer: entry.answer,
@@ -529,7 +540,7 @@ var createDeterministicAnswerResolver = (artifactInput, options) => {
529
540
  const entries = index.get(base.normalizedQuery) ?? [];
530
541
  if (entries.length === 0) return escalation(query, "miss", "No exact local answer was found. A backend answer is required.");
531
542
  if (entries.length > 1) {
532
- return AnswerResponseSchema.parse({
543
+ return AnswerResponseSchema2.parse({
533
544
  ...base,
534
545
  outcome: "choices",
535
546
  message: "More than one exact local answer matches. Choose one to continue.",
@@ -644,7 +655,7 @@ var backendAnswer = (query, content, backend) => {
644
655
  return citation.success ? [citation.data] : [];
645
656
  });
646
657
  }).slice(0, 8) : [];
647
- return AnswerResponseSchema.parse({
658
+ return AnswerResponseSchema2.parse({
648
659
  ...baseResponse(query),
649
660
  outcome: "answer",
650
661
  answer: { markdown, citations },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agentskit/chat",
3
- "version": "0.1.0",
3
+ "version": "0.2.0",
4
4
  "description": "Cross-framework application definitions for AgentsKit Chat.",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -33,7 +33,7 @@
33
33
  "@agentskit/memory": "^0.11.0",
34
34
  "@agentskit/statechart": "^0.2.0",
35
35
  "zod": "^4.3.6",
36
- "@agentskit/chat-protocol": "0.1.0"
36
+ "@agentskit/chat-protocol": "0.2.0"
37
37
  },
38
38
  "devDependencies": {
39
39
  "@agentskit/core": "^1.12.3",