@canonmsg/core 1.0.0 → 1.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/dist/browser.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  export { AGENT_CAPABILITIES, CLAUDE_PERMISSION_MODE_OPTIONS, } from './types.js';
2
2
  export { resolveCanonBaseUrl } from './base-url.js';
3
3
  export { DEFAULT_BASE_URL, DEFAULT_STREAM_URL, DEFAULT_RTDB_URL, FIREBASE_WEB_API_KEY } from './constants.js';
4
- export type { AddMemberResult, AgentCapabilities, AgentClientType, AgentSessionSnapshot, AgentRuntime, CanonControlAvailability, CanonControlDescriptor, CanonControlLiveBehavior, CanonControlSelectionPolicy, CanonControlValue, CanonContact, CanonContactRequest, CanonContactRequestStatus, CanonResolveAdmissionResult, ContactAddedPayload, ContactApprovedPayload, ContactRemovedPayload, ContactRequestPayload, ContactSource, ResolvedAdmissionState, ResolvedAdmissionTargetSummary, ResolvedTargetAdmissionPayload, CanonStreamEvent, CreateContactRequestResult, MediaAttachment, MediaAttachmentKind, ModelOption, PermissionModeOption, CanonRuntimeDescriptor, CanonRuntimeActionAvailability, CanonRuntimeActionCategory, CanonRuntimeActionDescriptor, CanonRuntimeActionDispatch, CanonRuntimeActionPlacement, CanonRuntimeCommandArgumentChoice, CanonRuntimeCommandArgumentDescriptor, CanonRuntimeCommandArgumentKind, CanonRuntimeCommandDescriptor, CanonRuntimeDetailTier, CanonRuntimeExecutionMetadata, CanonRuntimePresentationField, CanonRuntimePresentationHint, CanonRuntimePresentationPolicy, CanonRuntimePresentationPreset, CanonRuntimeVisibility, CanonRuntimeProvenance, CanonRuntimeActivityItem, CanonRuntimeActivityKind, CanonRuntimeActivityStatus, CanonRuntimeFact, CanonRuntimeFactGroup, CanonRuntimeInventory, CanonRuntimeInventoryEntry, CanonRuntimePrimitiveId, CanonRuntimeStreamingMode, CanonRuntimeStatusItem, CanonRuntimeSurfaceMode, CanonWorkspaceRootMetadata, RuntimeUpdatedPayload, RuntimeInfoPayload, RuntimeControlError, RuntimeControlState, RuntimeControlValueSource, ResolvedAdmission, SessionConfig, TurnOutputBlock, TurnOutputBlockKind, TurnOutputBlockStatus, TurnUpdatedPayload, WorkspaceOption, WorkspaceOptionSource, } from './types.js';
4
+ export type { AddMemberResult, AgentCapabilities, AgentClientType, AgentSessionSnapshot, AgentRuntime, CanonControlAvailability, CanonControlDescriptor, CanonControlLiveBehavior, CanonControlSelectionPolicy, CanonControlValue, CanonRuntimeCardCapabilities, CanonRuntimeRichCardCapability, CanonContact, CanonContactRequest, CanonContactRequestStatus, CanonResolveAdmissionResult, ContactAddedPayload, ContactApprovedPayload, ContactRemovedPayload, ContactRequestPayload, ContactSource, ResolvedAdmissionState, ResolvedAdmissionTargetSummary, ResolvedTargetAdmissionPayload, CanonStreamEvent, CreateContactRequestResult, MediaAttachment, MediaAttachmentKind, ModelOption, PermissionModeOption, CanonRuntimeDescriptor, CanonRuntimeActionAvailability, CanonRuntimeActionCategory, CanonRuntimeActionDescriptor, CanonRuntimeActionDispatch, CanonRuntimeActionPlacement, CanonRuntimeCommandArgumentChoice, CanonRuntimeCommandArgumentDescriptor, CanonRuntimeCommandArgumentKind, CanonRuntimeCommandDescriptor, CanonRuntimeDetailTier, CanonRuntimeExecutionMetadata, CanonRuntimePresentationField, CanonRuntimePresentationHint, CanonRuntimePresentationPolicy, CanonRuntimePresentationPreset, CanonRuntimeVisibility, CanonRuntimeProvenance, CanonRuntimeActivityItem, CanonRuntimeActivityKind, CanonRuntimeActivityStatus, CanonRuntimeFact, CanonRuntimeFactGroup, CanonRuntimeInventory, CanonRuntimeInventoryEntry, CanonRuntimePrimitiveId, CanonRuntimeStreamingMode, CanonRuntimeStatusItem, CanonRuntimeSurfaceMode, CanonWorkspaceRootMetadata, RuntimeUpdatedPayload, RuntimeInfoPayload, RuntimeControlError, RuntimeControlState, RuntimeControlValueSource, ResolvedAdmission, SessionConfig, TurnOutputBlock, TurnOutputBlockKind, TurnOutputBlockStatus, TurnUpdatedPayload, WorkspaceOption, WorkspaceOptionSource, } from './types.js';
5
5
  export { DEFAULT_FIRST_PARTY_RUNTIME_PRESENTATION, RUNTIME_PRESENTATION_FIELDS, buildRuntimePresentationPolicy, getRuntimePresentationHint, isRuntimePresentationField, isRuntimePresentationFieldHidden, redactAgentSessionSnapshotForConversation, redactExecutionMetadataForConversation, redactRuntimeDescriptorForConversation, redactRuntimeInfoForConversation, } from './runtime-presentation.js';
6
6
  export { buildRuntimeProvenance, resolveRuntimeProvenance, } from './provenance.js';
7
7
  export { EXECUTION_ENVIRONMENT_MODES, isExecutionEnvironmentMode, } from './execution-environment-mode.js';
@@ -17,7 +17,7 @@ export type { DeliveryIntent, InboundDisposition, RuntimeCapabilities, TriggerDe
17
17
  export { buildApprovalReply, buildApprovalRequest, buildApprovalOutcome, generateApprovalId, redactSecrets, } from './approval-format.js';
18
18
  export type { ApprovalRequestCategory, ApprovalRequestDetail, ApprovalRequestMetadata, ApprovalNativeRequestMetadata, ApprovalRisk, ApprovalReplyMetadata, ApprovalOutcomeMetadata, SessionRule, ApprovalResult, ApprovalConfig, } from './approval-types.js';
19
19
  export { DEFAULT_APPROVAL_CONFIG, parseApprovalRequestMetadata, parseApprovalReplyMetadata, parseSessionRule, } from './approval-types.js';
20
- export { buildRuntimeInputOutcome, buildRuntimeInputReply, buildRuntimeInputRequest, buildPlanApprovalReply, buildPlanApprovalRequest, buildQuestionReply, buildQuestionRequest, parseRuntimeInputOutcomeMetadata, parseRuntimeInputReplyMetadata, parseRuntimeInputRequestMetadata, } from './runtime-cards.js';
21
- export type { ClaudeQuestionMetadata, ClaudeQuestionReplyMetadata, PlanApprovalMetadata, PlanApprovalReplyMetadata, RuntimeInputAnswers, RuntimeInputChoice, RuntimeInputKind, RuntimeInputNativeMetadata, RuntimeInputOutcomeMetadata, RuntimeInputQuestion, RuntimeInputReplyMetadata, RuntimeInputReplyStatus, RuntimeInputRequestMetadata, RuntimeInputResolutionStatus, RuntimeQuestionDefinition, RuntimeQuestionOption, } from './runtime-cards.js';
20
+ export { RUNTIME_CARD_SCHEMA_V1, buildRuntimeCardOutcome, buildRuntimeCardPreview, buildRuntimeCardReply, buildRuntimeCardRequest, buildRuntimeInputOutcome, buildRuntimeInputReply, buildRuntimeInputRequest, buildPlanApprovalReply, buildPlanApprovalRequest, buildQuestionReply, buildQuestionRequest, parseRuntimeCardOutcomeMetadata, parseRuntimeCardReplyMetadata, parseRuntimeCardRequestMetadata, parseRuntimeCardV1, parseRuntimeInputOutcomeMetadata, parseRuntimeInputReplyMetadata, parseRuntimeInputRequestMetadata, } from './runtime-cards.js';
21
+ export type { ClaudeQuestionMetadata, ClaudeQuestionReplyMetadata, PlanApprovalMetadata, PlanApprovalReplyMetadata, RuntimeCardAction, RuntimeCardActionsBlock, RuntimeCardBlock, RuntimeCardBlockKind, RuntimeCardCalloutBlock, RuntimeCardChartBlock, RuntimeCardChartPoint, RuntimeCardChartSeries, RuntimeCardListBlock, RuntimeCardListItem, RuntimeCardMetric, RuntimeCardMetricGridBlock, RuntimeCardNativeMetadata, RuntimeCardOutcomeMetadata, RuntimeCardPreview, RuntimeCardReplyMetadata, RuntimeCardReplyStatus, RuntimeCardRequestMetadata, RuntimeCardResolutionStatus, RuntimeCardSchemaV1, RuntimeCardSummaryBlock, RuntimeCardTableBlock, RuntimeCardTone, RuntimeCardV1, RuntimeInputAnswers, RuntimeInputChoice, RuntimeInputKind, RuntimeInputNativeMetadata, RuntimeInputOutcomeMetadata, RuntimeInputQuestion, RuntimeInputReplyMetadata, RuntimeInputReplyStatus, RuntimeInputRequestMetadata, RuntimeInputResolutionStatus, RuntimeQuestionDefinition, RuntimeQuestionOption, } from './runtime-cards.js';
22
22
  export { DEFAULT_TURN_TRAIL_MAX_BLOCKS, DEFAULT_TURN_TRAIL_METADATA_BUDGET_BYTES, buildBoundedTurnTrail, } from './turn-output-controller.js';
23
23
  export type { BuildBoundedTurnTrailOptions, TurnOutputBlockInput, } from './turn-output-controller.js';
package/dist/browser.js CHANGED
@@ -11,5 +11,5 @@ export { buildParticipationHistorySnapshot, buildParticipationHistorySnapshots,
11
11
  export { DEFAULT_RUNTIME_CAPABILITIES, ACTIVE_TURN_STALE_THRESHOLD_MS, FINAL_MESSAGE_HANDOFF_MS, WAITING_INPUT_STALE_THRESHOLD_MS, getTurnStateStaleThresholdMs, isTurnOpen, isTurnStateStale, normalizeTurnMetadata, normalizeTurnState, resolveTurnMessageSemantics, shouldPromoteConversationMessage, shouldTriggerAgentTurn, } from './turn-protocol.js';
12
12
  export { buildApprovalReply, buildApprovalRequest, buildApprovalOutcome, generateApprovalId, redactSecrets, } from './approval-format.js';
13
13
  export { DEFAULT_APPROVAL_CONFIG, parseApprovalRequestMetadata, parseApprovalReplyMetadata, parseSessionRule, } from './approval-types.js';
14
- export { buildRuntimeInputOutcome, buildRuntimeInputReply, buildRuntimeInputRequest, buildPlanApprovalReply, buildPlanApprovalRequest, buildQuestionReply, buildQuestionRequest, parseRuntimeInputOutcomeMetadata, parseRuntimeInputReplyMetadata, parseRuntimeInputRequestMetadata, } from './runtime-cards.js';
14
+ export { RUNTIME_CARD_SCHEMA_V1, buildRuntimeCardOutcome, buildRuntimeCardPreview, buildRuntimeCardReply, buildRuntimeCardRequest, buildRuntimeInputOutcome, buildRuntimeInputReply, buildRuntimeInputRequest, buildPlanApprovalReply, buildPlanApprovalRequest, buildQuestionReply, buildQuestionRequest, parseRuntimeCardOutcomeMetadata, parseRuntimeCardReplyMetadata, parseRuntimeCardRequestMetadata, parseRuntimeCardV1, parseRuntimeInputOutcomeMetadata, parseRuntimeInputReplyMetadata, parseRuntimeInputRequestMetadata, } from './runtime-cards.js';
15
15
  export { DEFAULT_TURN_TRAIL_MAX_BLOCKS, DEFAULT_TURN_TRAIL_METADATA_BUDGET_BYTES, buildBoundedTurnTrail, } from './turn-output-controller.js';
package/dist/client.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import { type CanonMessage, type CanonConversation, type CanonContact, type CanonContactRequest, type CanonMessagesPage, type CanonResolveAdmissionResult, type AgentContext, type AddMemberResult, type CreateContactRequestResult, type MediaAttachment, type SendMessageOptions, type CreateConversationOptions, type RegistrationStatus, type SetRuntimeTurnOptions, type SetStreamingOptions } from './types.js';
2
2
  import type { RuntimeInputKind } from './runtime-cards.js';
3
3
  import type { ApprovalNativeRequestMetadata, ApprovalRequestCategory, ApprovalRequestDetail, ApprovalRisk, SessionRule } from './approval-types.js';
4
- import type { RuntimeInputAnswers, RuntimeInputChoice, RuntimeInputNativeMetadata, RuntimeInputQuestion } from './runtime-cards.js';
4
+ import type { RuntimeInputAnswers, RuntimeInputChoice, RuntimeInputNativeMetadata, RuntimeInputQuestion, RuntimeCardNativeMetadata, RuntimeCardV1 } from './runtime-cards.js';
5
5
  import type { SendContextualMessageOptions, SendContextualMessageResult } from './self-context.js';
6
6
  import type { InboundDisposition } from './turn-protocol.js';
7
7
  /**
@@ -141,6 +141,44 @@ export declare class CanonClient {
141
141
  status: 'timeout';
142
142
  approvalId: string;
143
143
  }>;
144
+ createRuntimeCardRequest(options: {
145
+ conversationId: string;
146
+ card: RuntimeCardV1;
147
+ cardId?: string;
148
+ expiresAt?: number;
149
+ responseUserId?: string;
150
+ runtimeId?: string;
151
+ turnId?: string;
152
+ native?: RuntimeCardNativeMetadata;
153
+ }): Promise<{
154
+ success: true;
155
+ cardId: string;
156
+ messageId: string;
157
+ /** True when the card has actions and a response is pending; false for display cards. */
158
+ interactive: boolean;
159
+ /** Present only for interactive cards. */
160
+ expiresAt?: number;
161
+ }>;
162
+ consumeRuntimeCardResponse(options: {
163
+ conversationId: string;
164
+ cardId: string;
165
+ cancel?: boolean;
166
+ }): Promise<{
167
+ status: 'pending';
168
+ cardId: string;
169
+ expiresAt?: number;
170
+ } | {
171
+ status: 'submitted';
172
+ cardId: string;
173
+ actionId?: string;
174
+ values?: Record<string, unknown>;
175
+ } | {
176
+ status: 'cancelled';
177
+ cardId: string;
178
+ } | {
179
+ status: 'timeout';
180
+ cardId: string;
181
+ }>;
144
182
  updateRuntimeStatus(options: {
145
183
  runtime: string;
146
184
  hostMode?: boolean;
package/dist/client.js CHANGED
@@ -368,6 +368,26 @@ export class CanonClient {
368
368
  throw new CanonApiError(res.status, await res.text());
369
369
  return res.json();
370
370
  }
371
+ async createRuntimeCardRequest(options) {
372
+ const res = await fetch(`${this.baseUrl}/runtime-card/request`, {
373
+ method: 'POST',
374
+ headers: this.authHeaders(),
375
+ body: JSON.stringify(options),
376
+ });
377
+ if (!res.ok)
378
+ throw new CanonApiError(res.status, await res.text());
379
+ return res.json();
380
+ }
381
+ async consumeRuntimeCardResponse(options) {
382
+ const res = await fetch(`${this.baseUrl}/runtime-card/consume`, {
383
+ method: 'POST',
384
+ headers: this.authHeaders(),
385
+ body: JSON.stringify(options),
386
+ });
387
+ if (!res.ok)
388
+ throw new CanonApiError(res.status, await res.text());
389
+ return res.json();
390
+ }
371
391
  async updateRuntimeStatus(options) {
372
392
  const res = await fetch(`${this.baseUrl}/runtime/status`, {
373
393
  method: 'POST',
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  export { AGENT_CAPABILITIES, CLAUDE_PERMISSION_MODE_OPTIONS, } from './types.js';
2
- export type { AddMemberResult, AgentCapabilities, AgentClientType, CanonControlAvailability, CanonControlDescriptor, CanonControlLiveBehavior, CanonControlSelectionPolicy, CanonControlValue, CanonContact, CanonContactRequest, CanonContactRequestStatus, CanonGroupContext, CanonGroupContextMode, CanonKnownRecentParticipant, CanonMembershipChange, CanonResolveAdmissionResult, ConversationUpdatedPayload, ContactAddedPayload, ContactApprovedPayload, ContactCardPayload, ContactRemovedPayload, ContactRequestPayload, ContactSource, ResolvedAdmissionState, ResolvedAdmissionTargetSummary, ResolvedTargetAdmissionPayload, CanonMessage, CanonRuntimeProvenance, CanonConversation, CanonMessagesPage, CreateContactRequestResult, AgentContext, CanonStreamEvent, AgentSessionSnapshot, ResolvedAdmission, MediaAttachment, MediaAttachmentKind, MessageCreatedPayload, TypingPayload, PresencePayload, RuntimeUpdatedPayload, TurnUpdatedPayload, SendMessageOptions, CreateConversationOptions, RegistrationInput, RegistrationResult, RegistrationStatus, SetRuntimeTurnOptions, StreamingStatus, SetStreamingOptions, SessionControl, SessionState, SessionConfig, AgentRuntime, CanonRuntimeDescriptor, CanonRuntimeActionAvailability, CanonRuntimeActionCategory, CanonRuntimeActionDescriptor, CanonRuntimeActionDispatch, CanonRuntimeActionPlacement, CanonRuntimeCommandArgumentChoice, CanonRuntimeCommandArgumentDescriptor, CanonRuntimeCommandArgumentKind, CanonRuntimeCommandDescriptor, CanonRuntimeDetailTier, CanonRuntimeExecutionMetadata, CanonRuntimePresentationField, CanonRuntimePresentationHint, CanonRuntimePresentationPolicy, CanonRuntimePresentationPreset, CanonRuntimeVisibility, CanonRuntimeActivityItem, CanonRuntimeActivityKind, CanonRuntimeActivityStatus, CanonRuntimeFact, CanonRuntimeFactGroup, CanonRuntimeInventory, CanonRuntimeInventoryEntry, CanonRuntimePrimitiveId, CanonRuntimeStreamingMode, CanonRuntimeStatusItem, CanonRuntimeSurfaceMode, CanonWorkspaceRootMetadata, ModelOption, PermissionModeOption, RuntimeInfoPayload, RuntimeControlError, RuntimeControlState, RuntimeControlValueSource, TurnOutputBlock, TurnOutputBlockKind, TurnOutputBlockStatus, WorkspaceOption, WorkspaceOptionSource, } from './types.js';
2
+ export type { AddMemberResult, AgentCapabilities, AgentClientType, CanonControlAvailability, CanonControlDescriptor, CanonControlLiveBehavior, CanonControlSelectionPolicy, CanonControlValue, CanonRuntimeCardCapabilities, CanonRuntimeRichCardCapability, CanonContact, CanonContactRequest, CanonContactRequestStatus, CanonGroupContext, CanonGroupContextMode, CanonKnownRecentParticipant, CanonMembershipChange, CanonResolveAdmissionResult, ConversationUpdatedPayload, ContactAddedPayload, ContactApprovedPayload, ContactCardPayload, ContactRemovedPayload, ContactRequestPayload, ContactSource, ResolvedAdmissionState, ResolvedAdmissionTargetSummary, ResolvedTargetAdmissionPayload, CanonMessage, CanonRuntimeProvenance, CanonConversation, CanonMessagesPage, CreateContactRequestResult, AgentContext, CanonStreamEvent, AgentSessionSnapshot, ResolvedAdmission, MediaAttachment, MediaAttachmentKind, MessageCreatedPayload, TypingPayload, PresencePayload, RuntimeUpdatedPayload, TurnUpdatedPayload, SendMessageOptions, CreateConversationOptions, RegistrationInput, RegistrationResult, RegistrationStatus, SetRuntimeTurnOptions, StreamingStatus, SetStreamingOptions, SessionControl, SessionState, SessionConfig, AgentRuntime, CanonRuntimeDescriptor, CanonRuntimeActionAvailability, CanonRuntimeActionCategory, CanonRuntimeActionDescriptor, CanonRuntimeActionDispatch, CanonRuntimeActionPlacement, CanonRuntimeCommandArgumentChoice, CanonRuntimeCommandArgumentDescriptor, CanonRuntimeCommandArgumentKind, CanonRuntimeCommandDescriptor, CanonRuntimeDetailTier, CanonRuntimeExecutionMetadata, CanonRuntimePresentationField, CanonRuntimePresentationHint, CanonRuntimePresentationPolicy, CanonRuntimePresentationPreset, CanonRuntimeVisibility, CanonRuntimeActivityItem, CanonRuntimeActivityKind, CanonRuntimeActivityStatus, CanonRuntimeFact, CanonRuntimeFactGroup, CanonRuntimeInventory, CanonRuntimeInventoryEntry, CanonRuntimePrimitiveId, CanonRuntimeStreamingMode, CanonRuntimeStatusItem, CanonRuntimeSurfaceMode, CanonWorkspaceRootMetadata, ModelOption, PermissionModeOption, RuntimeInfoPayload, RuntimeControlError, RuntimeControlState, RuntimeControlValueSource, TurnOutputBlock, TurnOutputBlockKind, TurnOutputBlockStatus, WorkspaceOption, WorkspaceOptionSource, } from './types.js';
3
3
  export { DEFAULT_FIRST_PARTY_RUNTIME_PRESENTATION, RUNTIME_PRESENTATION_FIELDS, buildRuntimePresentationPolicy, getRuntimePresentationHint, isRuntimePresentationField, isRuntimePresentationFieldHidden, redactAgentRuntimeForConversation, redactAgentSessionSnapshotForConversation, redactExecutionMetadataForConversation, redactRuntimeActivityItemForConversation, redactRuntimeDescriptorForConversation, redactRuntimeInfoForConversation, redactSessionStateForConversation, } from './runtime-presentation.js';
4
4
  export { buildRuntimeProvenance, resolveRuntimeProvenance, } from './provenance.js';
5
5
  export type { CanonSelfContext, CanonSelfContextType, SelfContextPromptRenderOptions, SendContextualMessageOptions, SendContextualMessageResult, SendContextualSelfContextInput, } from './self-context.js';
@@ -20,8 +20,8 @@ export { ApprovalManager } from './approval-manager.js';
20
20
  export { generateApprovalId, buildApprovalRequest, buildApprovalReply, buildApprovalOutcome, redactSecrets, } from './approval-format.js';
21
21
  export { DEFAULT_APPROVAL_CONFIG, parseApprovalRequestMetadata, parseApprovalReplyMetadata, parseSessionRule, } from './approval-types.js';
22
22
  export type { ApprovalRequestCategory, ApprovalRequestDetail, ApprovalRequestMetadata, ApprovalNativeRequestMetadata, ApprovalRisk, ApprovalReplyMetadata, ApprovalOutcomeMetadata, SessionRule, ApprovalResult, ApprovalConfig, } from './approval-types.js';
23
- export { buildRuntimeInputOutcome, buildRuntimeInputReply, buildRuntimeInputRequest, buildPlanApprovalReply, buildPlanApprovalRequest, buildQuestionReply, buildQuestionRequest, parseRuntimeInputOutcomeMetadata, parseRuntimeInputReplyMetadata, parseRuntimeInputRequestMetadata, } from './runtime-cards.js';
24
- export type { ClaudeQuestionMetadata, ClaudeQuestionReplyMetadata, PlanApprovalMetadata, PlanApprovalReplyMetadata, RuntimeInputAnswers, RuntimeInputChoice, RuntimeInputKind, RuntimeInputNativeMetadata, RuntimeInputOutcomeMetadata, RuntimeInputQuestion, RuntimeInputReplyMetadata, RuntimeInputReplyStatus, RuntimeInputRequestMetadata, RuntimeInputResolutionStatus, RuntimeQuestionDefinition, RuntimeQuestionOption, } from './runtime-cards.js';
23
+ export { RUNTIME_CARD_SCHEMA_V1, buildRuntimeCardOutcome, buildRuntimeCardPreview, buildRuntimeCardReply, buildRuntimeCardRequest, buildRuntimeInputOutcome, buildRuntimeInputReply, buildRuntimeInputRequest, buildPlanApprovalReply, buildPlanApprovalRequest, buildQuestionReply, buildQuestionRequest, parseRuntimeCardOutcomeMetadata, parseRuntimeCardReplyMetadata, parseRuntimeCardRequestMetadata, parseRuntimeCardV1, parseRuntimeInputOutcomeMetadata, parseRuntimeInputReplyMetadata, parseRuntimeInputRequestMetadata, } from './runtime-cards.js';
24
+ export type { ClaudeQuestionMetadata, ClaudeQuestionReplyMetadata, PlanApprovalMetadata, PlanApprovalReplyMetadata, RuntimeCardAction, RuntimeCardActionsBlock, RuntimeCardBlock, RuntimeCardBlockKind, RuntimeCardCalloutBlock, RuntimeCardChartBlock, RuntimeCardChartPoint, RuntimeCardChartSeries, RuntimeCardListBlock, RuntimeCardListItem, RuntimeCardMetric, RuntimeCardMetricGridBlock, RuntimeCardNativeMetadata, RuntimeCardOutcomeMetadata, RuntimeCardPreview, RuntimeCardReplyMetadata, RuntimeCardReplyStatus, RuntimeCardRequestMetadata, RuntimeCardResolutionStatus, RuntimeCardSchemaV1, RuntimeCardSummaryBlock, RuntimeCardTableBlock, RuntimeCardTone, RuntimeCardV1, RuntimeInputAnswers, RuntimeInputChoice, RuntimeInputKind, RuntimeInputNativeMetadata, RuntimeInputOutcomeMetadata, RuntimeInputQuestion, RuntimeInputReplyMetadata, RuntimeInputReplyStatus, RuntimeInputRequestMetadata, RuntimeInputResolutionStatus, RuntimeQuestionDefinition, RuntimeQuestionOption, } from './runtime-cards.js';
25
25
  export { createStreamingHelper } from './streaming.js';
26
26
  export type { RTDBHandle, RTDBRef, ServerTimestamp, StreamingHelperOptions, StreamingNode } from './streaming.js';
27
27
  export { DEFAULT_TURN_TRAIL_MAX_BLOCKS, DEFAULT_TURN_TRAIL_METADATA_BUDGET_BYTES, buildBoundedTurnTrail, createTurnOutputController, } from './turn-output-controller.js';
package/dist/index.js CHANGED
@@ -19,7 +19,7 @@ export { ackRegistrationApproval, registerAndWaitForApproval, submitRegistration
19
19
  export { ApprovalManager } from './approval-manager.js';
20
20
  export { generateApprovalId, buildApprovalRequest, buildApprovalReply, buildApprovalOutcome, redactSecrets, } from './approval-format.js';
21
21
  export { DEFAULT_APPROVAL_CONFIG, parseApprovalRequestMetadata, parseApprovalReplyMetadata, parseSessionRule, } from './approval-types.js';
22
- export { buildRuntimeInputOutcome, buildRuntimeInputReply, buildRuntimeInputRequest, buildPlanApprovalReply, buildPlanApprovalRequest, buildQuestionReply, buildQuestionRequest, parseRuntimeInputOutcomeMetadata, parseRuntimeInputReplyMetadata, parseRuntimeInputRequestMetadata, } from './runtime-cards.js';
22
+ export { RUNTIME_CARD_SCHEMA_V1, buildRuntimeCardOutcome, buildRuntimeCardPreview, buildRuntimeCardReply, buildRuntimeCardRequest, buildRuntimeInputOutcome, buildRuntimeInputReply, buildRuntimeInputRequest, buildPlanApprovalReply, buildPlanApprovalRequest, buildQuestionReply, buildQuestionRequest, parseRuntimeCardOutcomeMetadata, parseRuntimeCardReplyMetadata, parseRuntimeCardRequestMetadata, parseRuntimeCardV1, parseRuntimeInputOutcomeMetadata, parseRuntimeInputReplyMetadata, parseRuntimeInputRequestMetadata, } from './runtime-cards.js';
23
23
  // Streaming (RTDB helpers)
24
24
  export { createStreamingHelper } from './streaming.js';
25
25
  export { DEFAULT_TURN_TRAIL_MAX_BLOCKS, DEFAULT_TURN_TRAIL_METADATA_BUDGET_BYTES, buildBoundedTurnTrail, createTurnOutputController, } from './turn-output-controller.js';
@@ -98,6 +98,138 @@ export interface RuntimeInputOutcomeMetadata {
98
98
  status: RuntimeInputResolutionStatus;
99
99
  reason?: 'submitted' | 'cancelled' | 'timeout' | 'expired' | 'interrupted';
100
100
  }
101
+ export declare const RUNTIME_CARD_SCHEMA_V1: "canon.card.v1";
102
+ export declare const RUNTIME_CARD_PUBLIC_REQUEST_TEXT: "Action requested";
103
+ export type RuntimeCardSchemaV1 = typeof RUNTIME_CARD_SCHEMA_V1;
104
+ export type RuntimeCardBlockKind = 'summary' | 'metricGrid' | 'chart' | 'table' | 'list' | 'callout' | 'actions';
105
+ export type RuntimeCardTone = 'neutral' | 'primary' | 'positive' | 'warning' | 'negative' | 'danger' | 'critical' | 'welcome';
106
+ export type RuntimeCardReplyStatus = 'submitted' | 'cancelled';
107
+ export type RuntimeCardResolutionStatus = RuntimeCardReplyStatus | 'timeout';
108
+ export interface RuntimeCardSummaryBlock {
109
+ kind: 'summary';
110
+ title?: string;
111
+ text: string;
112
+ }
113
+ export interface RuntimeCardMetric {
114
+ label: string;
115
+ value: string;
116
+ delta?: string;
117
+ tone?: RuntimeCardTone;
118
+ }
119
+ export interface RuntimeCardMetricGridBlock {
120
+ kind: 'metricGrid';
121
+ title?: string;
122
+ metrics: RuntimeCardMetric[];
123
+ }
124
+ export interface RuntimeCardChartPoint {
125
+ x: string;
126
+ y: number;
127
+ }
128
+ export interface RuntimeCardChartSeries {
129
+ name?: string;
130
+ points: RuntimeCardChartPoint[];
131
+ }
132
+ export interface RuntimeCardChartBlock {
133
+ kind: 'chart';
134
+ chart: 'line' | 'bar';
135
+ title?: string;
136
+ yLabel?: string;
137
+ series: RuntimeCardChartSeries[];
138
+ }
139
+ export interface RuntimeCardTableBlock {
140
+ kind: 'table';
141
+ title?: string;
142
+ columns: string[];
143
+ rows: string[][];
144
+ }
145
+ export interface RuntimeCardListItem {
146
+ label: string;
147
+ detail?: string;
148
+ status?: 'pending' | 'done' | 'blocked' | 'warning';
149
+ }
150
+ export interface RuntimeCardListBlock {
151
+ kind: 'list';
152
+ title?: string;
153
+ items: RuntimeCardListItem[];
154
+ }
155
+ export interface RuntimeCardCalloutBlock {
156
+ kind: 'callout';
157
+ title?: string;
158
+ text: string;
159
+ tone?: RuntimeCardTone;
160
+ }
161
+ export interface RuntimeCardAction {
162
+ id: string;
163
+ label: string;
164
+ tone?: RuntimeCardTone;
165
+ }
166
+ export interface RuntimeCardActionsBlock {
167
+ kind: 'actions';
168
+ title?: string;
169
+ actions: RuntimeCardAction[];
170
+ }
171
+ export type RuntimeCardBlock = RuntimeCardSummaryBlock | RuntimeCardMetricGridBlock | RuntimeCardChartBlock | RuntimeCardTableBlock | RuntimeCardListBlock | RuntimeCardCalloutBlock | RuntimeCardActionsBlock;
172
+ export interface RuntimeCardV1 {
173
+ schema: RuntimeCardSchemaV1;
174
+ cardId?: string;
175
+ template?: string;
176
+ tone?: RuntimeCardTone;
177
+ title: string;
178
+ fallbackText: string;
179
+ blocks: RuntimeCardBlock[];
180
+ }
181
+ export interface RuntimeCardPreview {
182
+ title?: string;
183
+ tone?: RuntimeCardTone;
184
+ template?: string;
185
+ blockKinds: RuntimeCardBlockKind[];
186
+ }
187
+ export interface RuntimeCardNativeMetadata {
188
+ runtime?: string;
189
+ method?: string;
190
+ requestId?: string;
191
+ sessionKey?: string;
192
+ turnId?: string;
193
+ handles?: Record<string, string>;
194
+ }
195
+ export interface RuntimeCardRequestMetadata {
196
+ type: 'runtime_card_request';
197
+ cardId: string;
198
+ cardKind: string;
199
+ schemaVersion: RuntimeCardSchemaV1;
200
+ fallbackText: string;
201
+ responseUserId?: string;
202
+ expiresAt: string;
203
+ runtimeId?: string;
204
+ turnId?: string;
205
+ native?: RuntimeCardNativeMetadata;
206
+ /** True when the card carries an actions block (the agent waits for a
207
+ * response); false/absent for display/report cards shown to all members. */
208
+ interactive?: boolean;
209
+ cardPreview: RuntimeCardPreview;
210
+ turnSemantics: 'control';
211
+ replyBehavior: 'suppress_auto_reply';
212
+ }
213
+ export interface RuntimeCardReplyMetadata {
214
+ type: 'runtime_card_reply';
215
+ cardId: string;
216
+ status: RuntimeCardReplyStatus;
217
+ actionId?: string;
218
+ answerSummary?: string;
219
+ sensitive?: boolean;
220
+ turnSemantics: 'control';
221
+ replyBehavior: 'suppress_auto_reply';
222
+ }
223
+ export interface RuntimeCardOutcomeMetadata {
224
+ type: 'runtime_card_outcome';
225
+ cardId: string;
226
+ status: RuntimeCardResolutionStatus;
227
+ reason?: 'submitted' | 'cancelled' | 'timeout' | 'expired' | 'interrupted';
228
+ turnSemantics: 'control';
229
+ replyBehavior: 'suppress_auto_reply';
230
+ }
231
+ export declare function parseRuntimeCardV1(value: unknown): RuntimeCardV1 | null;
232
+ export declare function buildRuntimeCardPreview(card: RuntimeCardV1): RuntimeCardPreview;
101
233
  export declare function buildQuestionRequest(questionId: string, questions: RuntimeQuestionDefinition[], options?: {
102
234
  responseUserId?: string;
103
235
  }): {
@@ -136,6 +268,34 @@ export declare function buildRuntimeInputOutcome(inputId: string, status: Runtim
136
268
  text: string;
137
269
  metadata: RuntimeInputOutcomeMetadata;
138
270
  };
271
+ export declare function buildRuntimeCardRequest(card: RuntimeCardV1, input: {
272
+ cardId?: string;
273
+ responseUserId?: string;
274
+ expiresAt: string | number | Date;
275
+ runtimeId?: string;
276
+ turnId?: string;
277
+ native?: RuntimeCardNativeMetadata;
278
+ }): {
279
+ text: string;
280
+ metadata: RuntimeCardRequestMetadata;
281
+ };
282
+ export declare function buildRuntimeCardReply(cardId: string, status: RuntimeCardReplyStatus, details?: {
283
+ actionId?: string;
284
+ answerSummary?: string;
285
+ sensitive?: boolean;
286
+ }): {
287
+ text: string;
288
+ metadata: RuntimeCardReplyMetadata;
289
+ };
290
+ export declare function buildRuntimeCardOutcome(cardId: string, status: RuntimeCardResolutionStatus, details?: {
291
+ reason?: RuntimeCardOutcomeMetadata['reason'];
292
+ }): {
293
+ text: string;
294
+ metadata: RuntimeCardOutcomeMetadata;
295
+ };
139
296
  export declare function parseRuntimeInputRequestMetadata(value: unknown): RuntimeInputRequestMetadata | null;
297
+ export declare function parseRuntimeCardRequestMetadata(value: unknown): RuntimeCardRequestMetadata | null;
298
+ export declare function parseRuntimeCardReplyMetadata(value: unknown): RuntimeCardReplyMetadata | null;
299
+ export declare function parseRuntimeCardOutcomeMetadata(value: unknown): RuntimeCardOutcomeMetadata | null;
140
300
  export declare function parseRuntimeInputReplyMetadata(value: unknown): RuntimeInputReplyMetadata | null;
141
301
  export declare function parseRuntimeInputOutcomeMetadata(value: unknown): RuntimeInputOutcomeMetadata | null;
@@ -1,3 +1,5 @@
1
+ export const RUNTIME_CARD_SCHEMA_V1 = 'canon.card.v1';
2
+ export const RUNTIME_CARD_PUBLIC_REQUEST_TEXT = 'Action requested';
1
3
  function isRecord(value) {
2
4
  return Boolean(value && typeof value === 'object' && !Array.isArray(value));
3
5
  }
@@ -85,6 +87,223 @@ function normalizeRuntimeInputNative(value) {
85
87
  }
86
88
  return Object.keys(native).length > 0 ? native : undefined;
87
89
  }
90
+ function normalizeRuntimeCardTone(value) {
91
+ return value === 'neutral'
92
+ || value === 'primary'
93
+ || value === 'positive'
94
+ || value === 'warning'
95
+ || value === 'negative'
96
+ || value === 'danger'
97
+ || value === 'critical'
98
+ || value === 'welcome'
99
+ ? value
100
+ : undefined;
101
+ }
102
+ function normalizeRuntimeCardBlockKind(value) {
103
+ return value === 'summary'
104
+ || value === 'metricGrid'
105
+ || value === 'chart'
106
+ || value === 'table'
107
+ || value === 'list'
108
+ || value === 'callout'
109
+ || value === 'actions'
110
+ ? value
111
+ : null;
112
+ }
113
+ function normalizeRuntimeCardActionId(value) {
114
+ const normalized = normalizeString(value, 80);
115
+ return normalized && /^[A-Za-z0-9_.:-]{1,80}$/.test(normalized) ? normalized : null;
116
+ }
117
+ function cardText(value) {
118
+ if (typeof value !== 'string')
119
+ return null;
120
+ const trimmed = value.trim();
121
+ return trimmed ? trimmed : null;
122
+ }
123
+ // Lenient structural parse: shape and required-field checks only — no numeric
124
+ // caps, no length caps, and unknown extra keys are tolerated for
125
+ // forward-compatibility. Strict business caps (<=6 series, <=24 rows, single
126
+ // actions block, deduped action ids, etc.) live in @canonmsg/rich-cards
127
+ // `validateCard()` and run agent-side before send; the backend additionally
128
+ // bounds total card size and block count at the transport envelope.
129
+ function normalizeRuntimeCardStringArray(value) {
130
+ if (!Array.isArray(value) || value.length === 0)
131
+ return null;
132
+ const out = value.flatMap((entry) => {
133
+ const normalized = cardText(entry);
134
+ return normalized ? [normalized] : [];
135
+ });
136
+ return out.length === value.length ? out : null;
137
+ }
138
+ function normalizeRuntimeCardMetrics(value) {
139
+ if (!Array.isArray(value) || value.length === 0)
140
+ return null;
141
+ const metrics = value.flatMap((entry) => {
142
+ if (!isRecord(entry))
143
+ return [];
144
+ const label = cardText(entry.label);
145
+ const metricValue = cardText(entry.value);
146
+ if (!label || !metricValue)
147
+ return [];
148
+ const delta = cardText(entry.delta) ?? undefined;
149
+ const tone = normalizeRuntimeCardTone(entry.tone);
150
+ return [{
151
+ label,
152
+ value: metricValue,
153
+ ...(delta ? { delta } : {}),
154
+ ...(tone ? { tone } : {}),
155
+ }];
156
+ });
157
+ return metrics.length === value.length ? metrics : null;
158
+ }
159
+ function normalizeRuntimeCardSeries(value) {
160
+ if (!Array.isArray(value) || value.length === 0)
161
+ return null;
162
+ const series = value.flatMap((entry) => {
163
+ if (!isRecord(entry) || !Array.isArray(entry.points) || entry.points.length === 0)
164
+ return [];
165
+ const points = entry.points.flatMap((point) => {
166
+ if (!isRecord(point))
167
+ return [];
168
+ const x = cardText(point.x);
169
+ const y = typeof point.y === 'number' && Number.isFinite(point.y) ? point.y : null;
170
+ return x && y !== null ? [{ x, y }] : [];
171
+ });
172
+ if (points.length !== entry.points.length)
173
+ return [];
174
+ const name = cardText(entry.name) ?? undefined;
175
+ return [{ ...(name ? { name } : {}), points }];
176
+ });
177
+ return series.length === value.length ? series : null;
178
+ }
179
+ function normalizeRuntimeCardRows(value) {
180
+ if (!Array.isArray(value) || value.length === 0)
181
+ return null;
182
+ const rows = value.flatMap((entry) => {
183
+ const cells = normalizeRuntimeCardStringArray(entry);
184
+ return cells ? [cells] : [];
185
+ });
186
+ return rows.length === value.length ? rows : null;
187
+ }
188
+ function normalizeRuntimeCardListItems(value) {
189
+ if (!Array.isArray(value) || value.length === 0)
190
+ return null;
191
+ const items = value.flatMap((entry) => {
192
+ if (!isRecord(entry))
193
+ return [];
194
+ const label = cardText(entry.label);
195
+ if (!label)
196
+ return [];
197
+ const detail = cardText(entry.detail) ?? undefined;
198
+ const status = entry.status === 'pending'
199
+ || entry.status === 'done'
200
+ || entry.status === 'blocked'
201
+ || entry.status === 'warning'
202
+ ? entry.status
203
+ : undefined;
204
+ return [{ label, ...(detail ? { detail } : {}), ...(status ? { status } : {}) }];
205
+ });
206
+ return items.length === value.length ? items : null;
207
+ }
208
+ function normalizeRuntimeCardActions(value) {
209
+ if (!Array.isArray(value) || value.length === 0)
210
+ return null;
211
+ const actions = value.flatMap((entry) => {
212
+ if (!isRecord(entry))
213
+ return [];
214
+ const id = normalizeRuntimeCardActionId(entry.id);
215
+ const label = cardText(entry.label);
216
+ if (!id || !label)
217
+ return [];
218
+ const tone = normalizeRuntimeCardTone(entry.tone);
219
+ return [{ id, label, ...(tone ? { tone } : {}) }];
220
+ });
221
+ return actions.length === value.length ? actions : null;
222
+ }
223
+ function normalizeRuntimeCardBlocks(value) {
224
+ if (!Array.isArray(value) || value.length === 0)
225
+ return null;
226
+ const blocks = value.flatMap((entry) => {
227
+ if (!isRecord(entry))
228
+ return [];
229
+ const kind = normalizeRuntimeCardBlockKind(entry.kind);
230
+ if (!kind)
231
+ return [];
232
+ const title = cardText(entry.title) ?? undefined;
233
+ if (kind === 'summary') {
234
+ const text = cardText(entry.text);
235
+ return text ? [{ kind, ...(title ? { title } : {}), text }] : [];
236
+ }
237
+ if (kind === 'metricGrid') {
238
+ const metrics = normalizeRuntimeCardMetrics(entry.metrics);
239
+ return metrics ? [{ kind, ...(title ? { title } : {}), metrics }] : [];
240
+ }
241
+ if (kind === 'chart') {
242
+ const chart = entry.chart === 'line' || entry.chart === 'bar' ? entry.chart : null;
243
+ const series = normalizeRuntimeCardSeries(entry.series);
244
+ const yLabel = cardText(entry.yLabel) ?? undefined;
245
+ return chart && series ? [{ kind, chart, ...(title ? { title } : {}), ...(yLabel ? { yLabel } : {}), series }] : [];
246
+ }
247
+ if (kind === 'table') {
248
+ const columns = normalizeRuntimeCardStringArray(entry.columns);
249
+ const rows = normalizeRuntimeCardRows(entry.rows);
250
+ return columns && rows ? [{ kind, ...(title ? { title } : {}), columns, rows }] : [];
251
+ }
252
+ if (kind === 'list') {
253
+ const items = normalizeRuntimeCardListItems(entry.items);
254
+ return items ? [{ kind, ...(title ? { title } : {}), items }] : [];
255
+ }
256
+ if (kind === 'callout') {
257
+ const text = cardText(entry.text);
258
+ const tone = normalizeRuntimeCardTone(entry.tone);
259
+ return text ? [{ kind, ...(title ? { title } : {}), text, ...(tone ? { tone } : {}) }] : [];
260
+ }
261
+ const actions = normalizeRuntimeCardActions(entry.actions);
262
+ return actions ? [{ kind, ...(title ? { title } : {}), actions }] : [];
263
+ });
264
+ return blocks.length === value.length && blocks.length > 0 ? blocks : null;
265
+ }
266
+ function normalizeRuntimeCardNative(value) {
267
+ const native = normalizeRuntimeInputNative(value);
268
+ return native;
269
+ }
270
+ function assertNoSensitiveRuntimeCardPayload(value) {
271
+ return !('value' in value)
272
+ && !('values' in value)
273
+ && !('answer' in value)
274
+ && !('answers' in value)
275
+ && !('password' in value)
276
+ && !('secret' in value)
277
+ && !('rawValue' in value);
278
+ }
279
+ export function parseRuntimeCardV1(value) {
280
+ if (!isRecord(value) || value.schema !== RUNTIME_CARD_SCHEMA_V1)
281
+ return null;
282
+ const title = cardText(value.title);
283
+ const fallbackText = cardText(value.fallbackText);
284
+ const blocks = normalizeRuntimeCardBlocks(value.blocks);
285
+ if (!title || !fallbackText || !blocks)
286
+ return null;
287
+ const cardId = normalizeRuntimeCardActionId(value.cardId) ?? undefined;
288
+ const template = cardText(value.template) ?? undefined;
289
+ const tone = normalizeRuntimeCardTone(value.tone);
290
+ return {
291
+ schema: RUNTIME_CARD_SCHEMA_V1,
292
+ ...(cardId ? { cardId } : {}),
293
+ ...(template ? { template } : {}),
294
+ ...(tone ? { tone } : {}),
295
+ title,
296
+ fallbackText,
297
+ blocks,
298
+ };
299
+ }
300
+ export function buildRuntimeCardPreview(card) {
301
+ const hasActions = card.blocks.some((block) => block.kind === 'actions');
302
+ return {
303
+ title: hasActions ? 'Action requested' : 'Runtime card',
304
+ blockKinds: card.blocks.map((block) => block.kind).slice(0, 12),
305
+ };
306
+ }
88
307
  function assertNoSensitiveRuntimeInputPayload(value) {
89
308
  return !('value' in value)
90
309
  && !('answer' in value)
@@ -194,6 +413,65 @@ export function buildRuntimeInputOutcome(inputId, status, details) {
194
413
  },
195
414
  };
196
415
  }
416
+ export function buildRuntimeCardRequest(card, input) {
417
+ const parsed = parseRuntimeCardV1(card);
418
+ if (!parsed) {
419
+ throw new Error('Invalid runtime card document');
420
+ }
421
+ const cardId = normalizeRuntimeCardActionId(input.cardId ?? parsed.cardId) ?? `card_${Date.now().toString(36)}`;
422
+ const expiresAt = input.expiresAt instanceof Date
423
+ ? input.expiresAt.toISOString()
424
+ : typeof input.expiresAt === 'number'
425
+ ? new Date(input.expiresAt).toISOString()
426
+ : new Date(Date.parse(input.expiresAt)).toISOString();
427
+ return {
428
+ text: RUNTIME_CARD_PUBLIC_REQUEST_TEXT,
429
+ metadata: {
430
+ type: 'runtime_card_request',
431
+ cardId,
432
+ cardKind: 'runtime_card',
433
+ schemaVersion: RUNTIME_CARD_SCHEMA_V1,
434
+ fallbackText: RUNTIME_CARD_PUBLIC_REQUEST_TEXT,
435
+ ...(input.responseUserId ? { responseUserId: input.responseUserId.slice(0, 128) } : {}),
436
+ expiresAt,
437
+ ...(input.runtimeId ? { runtimeId: input.runtimeId.slice(0, 128) } : {}),
438
+ ...(input.turnId ? { turnId: input.turnId.slice(0, 128) } : {}),
439
+ cardPreview: buildRuntimeCardPreview(parsed),
440
+ turnSemantics: 'control',
441
+ replyBehavior: 'suppress_auto_reply',
442
+ },
443
+ };
444
+ }
445
+ export function buildRuntimeCardReply(cardId, status, details) {
446
+ return {
447
+ text: status === 'submitted' ? 'Submitted' : 'Cancelled',
448
+ metadata: {
449
+ type: 'runtime_card_reply',
450
+ cardId,
451
+ status,
452
+ ...(details?.sensitive ? { sensitive: true } : {}),
453
+ turnSemantics: 'control',
454
+ replyBehavior: 'suppress_auto_reply',
455
+ },
456
+ };
457
+ }
458
+ export function buildRuntimeCardOutcome(cardId, status, details) {
459
+ return {
460
+ text: status === 'timeout'
461
+ ? 'Card request expired'
462
+ : status === 'cancelled'
463
+ ? 'Card request cancelled'
464
+ : 'Card request resolved',
465
+ metadata: {
466
+ type: 'runtime_card_outcome',
467
+ cardId,
468
+ status,
469
+ ...(details?.reason ? { reason: details.reason } : {}),
470
+ turnSemantics: 'control',
471
+ replyBehavior: 'suppress_auto_reply',
472
+ },
473
+ };
474
+ }
197
475
  export function parseRuntimeInputRequestMetadata(value) {
198
476
  if (!isRecord(value) || value.type !== 'runtime_input_request')
199
477
  return null;
@@ -229,6 +507,105 @@ export function parseRuntimeInputRequestMetadata(value) {
229
507
  ...(value.sensitive === true ? { sensitive: true } : {}),
230
508
  };
231
509
  }
510
+ function normalizeRuntimeCardPreview(value) {
511
+ if (!isRecord(value))
512
+ return null;
513
+ const blockKinds = Array.isArray(value.blockKinds)
514
+ ? value.blockKinds.slice(0, 12).flatMap((entry) => {
515
+ const kind = normalizeRuntimeCardBlockKind(entry);
516
+ return kind ? [kind] : [];
517
+ })
518
+ : [];
519
+ return {
520
+ ...(normalizeString(value.title, 120) ? { title: normalizeString(value.title, 120) } : {}),
521
+ ...(normalizeRuntimeCardTone(value.tone) ? { tone: normalizeRuntimeCardTone(value.tone) } : {}),
522
+ ...(normalizeString(value.template, 120) ? { template: normalizeString(value.template, 120) } : {}),
523
+ blockKinds,
524
+ };
525
+ }
526
+ export function parseRuntimeCardRequestMetadata(value) {
527
+ if (!isRecord(value) || value.type !== 'runtime_card_request')
528
+ return null;
529
+ if (!assertNoSensitiveRuntimeCardPayload(value))
530
+ return null;
531
+ const cardId = normalizeRuntimeCardActionId(value.cardId);
532
+ const cardKind = normalizeString(value.cardKind, 120);
533
+ const fallbackText = normalizeString(value.fallbackText, 500);
534
+ const responseUserId = normalizeString(value.responseUserId, 128) ?? undefined;
535
+ const expiresAtRaw = normalizeString(value.expiresAt, 128);
536
+ const expiresMs = expiresAtRaw ? Date.parse(expiresAtRaw) : NaN;
537
+ const cardPreview = normalizeRuntimeCardPreview(value.cardPreview);
538
+ if (!cardId || !cardKind || value.schemaVersion !== RUNTIME_CARD_SCHEMA_V1 || !fallbackText || !Number.isFinite(expiresMs) || !cardPreview) {
539
+ return null;
540
+ }
541
+ const runtimeId = normalizeString(value.runtimeId, 128) ?? undefined;
542
+ const turnId = normalizeString(value.turnId, 128) ?? undefined;
543
+ const native = normalizeRuntimeCardNative(value.native);
544
+ return {
545
+ type: 'runtime_card_request',
546
+ cardId,
547
+ cardKind,
548
+ schemaVersion: RUNTIME_CARD_SCHEMA_V1,
549
+ fallbackText,
550
+ ...(responseUserId ? { responseUserId } : {}),
551
+ expiresAt: new Date(expiresMs).toISOString(),
552
+ ...(runtimeId ? { runtimeId } : {}),
553
+ ...(turnId ? { turnId } : {}),
554
+ ...(native ? { native } : {}),
555
+ cardPreview,
556
+ turnSemantics: 'control',
557
+ replyBehavior: 'suppress_auto_reply',
558
+ };
559
+ }
560
+ export function parseRuntimeCardReplyMetadata(value) {
561
+ if (!isRecord(value) || value.type !== 'runtime_card_reply')
562
+ return null;
563
+ if (!assertNoSensitiveRuntimeCardPayload(value))
564
+ return null;
565
+ const cardId = normalizeRuntimeCardActionId(value.cardId);
566
+ const status = value.status === 'submitted' || value.status === 'cancelled' ? value.status : null;
567
+ if (!cardId || !status)
568
+ return null;
569
+ const actionId = normalizeRuntimeCardActionId(value.actionId) ?? undefined;
570
+ const answerSummary = value.sensitive === true ? undefined : normalizeString(value.answerSummary, 500) ?? undefined;
571
+ return {
572
+ type: 'runtime_card_reply',
573
+ cardId,
574
+ status,
575
+ ...(actionId ? { actionId } : {}),
576
+ ...(answerSummary ? { answerSummary } : {}),
577
+ ...(value.sensitive === true ? { sensitive: true } : {}),
578
+ turnSemantics: 'control',
579
+ replyBehavior: 'suppress_auto_reply',
580
+ };
581
+ }
582
+ export function parseRuntimeCardOutcomeMetadata(value) {
583
+ if (!isRecord(value) || value.type !== 'runtime_card_outcome')
584
+ return null;
585
+ if (!assertNoSensitiveRuntimeCardPayload(value))
586
+ return null;
587
+ const cardId = normalizeRuntimeCardActionId(value.cardId);
588
+ const status = value.status === 'submitted' || value.status === 'cancelled' || value.status === 'timeout'
589
+ ? value.status
590
+ : null;
591
+ if (!cardId || !status)
592
+ return null;
593
+ const reason = value.reason === 'submitted'
594
+ || value.reason === 'cancelled'
595
+ || value.reason === 'timeout'
596
+ || value.reason === 'expired'
597
+ || value.reason === 'interrupted'
598
+ ? value.reason
599
+ : undefined;
600
+ return {
601
+ type: 'runtime_card_outcome',
602
+ cardId,
603
+ status,
604
+ ...(reason ? { reason } : {}),
605
+ turnSemantics: 'control',
606
+ replyBehavior: 'suppress_auto_reply',
607
+ };
608
+ }
232
609
  export function parseRuntimeInputReplyMetadata(value) {
233
610
  if (!isRecord(value) || value.type !== 'runtime_input_reply')
234
611
  return null;
@@ -11,6 +11,12 @@ export declare const CLAUDE_EFFORT_OPTIONS: readonly [{
11
11
  }, {
12
12
  readonly value: "high";
13
13
  readonly label: "High";
14
+ }, {
15
+ readonly value: "xhigh";
16
+ readonly label: "Extra high";
17
+ }, {
18
+ readonly value: "max";
19
+ readonly label: "Max";
14
20
  }];
15
21
  export declare const EXECUTION_MODE_CONTROL_OPTIONS: ReadonlyArray<{
16
22
  value: ExecutionEnvironmentMode;
@@ -52,4 +58,5 @@ export declare function buildFirstPartyCodingRuntimeDescriptor(input: {
52
58
  streamingTextMode: CanonRuntimeStreamingMode;
53
59
  admissionActions?: HostAdmissionActionCapabilities;
54
60
  presentation?: CanonRuntimePresentationPolicy;
61
+ runtimeCards?: CanonRuntimeDescriptor['runtimeCards'];
55
62
  }): CanonRuntimeDescriptor;
@@ -4,6 +4,8 @@ export const CLAUDE_EFFORT_OPTIONS = [
4
4
  { value: 'low', label: 'Low' },
5
5
  { value: 'medium', label: 'Medium' },
6
6
  { value: 'high', label: 'High' },
7
+ { value: 'xhigh', label: 'Extra high' },
8
+ { value: 'max', label: 'Max' },
7
9
  ];
8
10
  export const EXECUTION_MODE_CONTROL_OPTIONS = [
9
11
  {
@@ -157,5 +159,6 @@ export function buildFirstPartyCodingRuntimeDescriptor(input) {
157
159
  streamingTextMode: input.streamingTextMode,
158
160
  presentation: input.presentation ?? DEFAULT_FIRST_PARTY_RUNTIME_PRESENTATION,
159
161
  admissionActions: input.admissionActions,
162
+ ...(input.runtimeCards ? { runtimeCards: input.runtimeCards } : {}),
160
163
  };
161
164
  }
@@ -54,7 +54,9 @@ function isHiddenRuntimeCardMetadata(metadata) {
54
54
  || metadata.type === 'question_reply'
55
55
  || metadata.type === 'plan_approval_reply'
56
56
  || metadata.type === 'runtime_input_reply'
57
- || metadata.type === 'runtime_input_outcome';
57
+ || metadata.type === 'runtime_input_outcome'
58
+ || metadata.type === 'runtime_card_reply'
59
+ || metadata.type === 'runtime_card_outcome';
58
60
  }
59
61
  export function normalizeTurnMetadata(metadata) {
60
62
  if (!isRecord(metadata))
package/dist/types.d.ts CHANGED
@@ -2,6 +2,7 @@ import type { ExecutionEnvironmentMode } from './execution-environment-mode.js';
2
2
  import type { ResolvedAgentBehaviorPolicy } from './policy.js';
3
3
  import type { DeliveryIntent, RuntimeCapabilities, TurnLifecycleState } from './turn-protocol.js';
4
4
  import type { CanonSelfContext } from './self-context.js';
5
+ import type { RuntimeCardV1 } from './runtime-cards.js';
5
6
  export type { ExecutionEnvironmentMode };
6
7
  export type MediaAttachmentKind = 'image' | 'audio' | 'file';
7
8
  export interface MediaAttachment {
@@ -54,6 +55,8 @@ export interface CanonMessage {
54
55
  forwardedFrom?: ForwardedFrom;
55
56
  metadata?: Record<string, unknown>;
56
57
  contactCard?: ContactCardPayload;
58
+ /** Durable canon.card.v1 runtime card content (persists in chat history). */
59
+ runtimeCard?: RuntimeCardV1;
57
60
  status: 'sent' | 'read';
58
61
  deleted: boolean;
59
62
  createdAt: string;
@@ -340,10 +343,23 @@ export interface CanonControlDescriptor {
340
343
  tier?: CanonRuntimeDetailTier;
341
344
  sensitive?: boolean;
342
345
  }
346
+ export interface CanonRuntimeRichCardCapability {
347
+ schema: 'canon.card.v1';
348
+ lifecycle?: 'blocking_requires_action';
349
+ responder?: 'agent_owner';
350
+ result?: 'action_or_values';
351
+ maxTimeoutMs?: number;
352
+ blockKinds: ReadonlyArray<'summary' | 'metricGrid' | 'chart' | 'table' | 'list' | 'callout' | 'actions'>;
353
+ native?: boolean;
354
+ }
355
+ export interface CanonRuntimeCardCapabilities {
356
+ rich?: CanonRuntimeRichCardCapability;
357
+ }
343
358
  export interface CanonRuntimeDescriptor {
344
359
  coreControls: ReadonlyArray<CanonControlDescriptor>;
345
360
  runtimeControls?: ReadonlyArray<CanonControlDescriptor>;
346
361
  commands?: ReadonlyArray<CanonRuntimeCommandDescriptor>;
362
+ runtimeCards?: CanonRuntimeCardCapabilities;
347
363
  /**
348
364
  * Optional setup-time local roots advertised by a runtime. These are
349
365
  * metadata only for now; existing session config still selects concrete
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@canonmsg/core",
3
- "version": "1.0.0",
3
+ "version": "1.2.0",
4
4
  "description": "Canon core — shared types, REST client, SSE stream, and registration for Canon messaging",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",