@canonmsg/agent-sdk 8.8.0 → 9.0.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
@@ -190,8 +190,7 @@ The `message` event handler receives a context object with:
190
190
  | `leave` | `() => Promise<void>` | Leave the current group conversation |
191
191
  | `react` | `(messageId, emoji) => Promise<void>` | Toggle an emoji reaction |
192
192
  | `addMember` / `removeMember` | functions | Manage group members when the agent has permission |
193
- | `sendContextualMessage` | function | Send into another conversation with private self-context from this conversation |
194
- | `reachOut` | function | Act on a Canon contact card using live admission resolution |
193
+ | `communicate` | function | Message an existing conversation, start a direct conversation, create a group, or forward an exact message |
195
194
  | `agent` | `AgentContext` | Trusted Canon agent identity and access context |
196
195
  | `activeSelfContextId` | `string \| null` | Active private self-context id for this turn |
197
196
  | `selfContexts` | `CanonSelfContext[] \| undefined` | Private context explaining this agent's cross-session actions |
@@ -508,7 +507,7 @@ A conversation whose type Canon could not determine falls back to verbose, never
508
507
 
509
508
  **Quiet suppresses**: every `/streaming` publication — the `'Thinking...'` seed and its keepalive, `turn.setThinking/setStreaming/setTool`, `turn.appendDelta`/`appendBlock`/segment updates, `turn.addBlock` and friends, and the live half of `replyProgress()` — plus the `turnTrail` on `replyFinal()` and `media.replyWithFile()`. Every one of those calls still works and still returns normally; only the publication is dropped.
510
509
 
511
- **Quiet does not suppress**: the typing/thinking indicator (which stays up for the turn's whole working phase; while the turn is parked on an approval the clients suppress an agent's dots and the header line carries the state), turn state, `replyFinal()` including every part of a chunked reply, the partial-final notice, `media.replyWithFile()` itself, `turn.setWaitingInput()`'s note, `sendContextualMessage()`, `publishRuntimeActivity()`, approval/input/card requests, and their outcome receipts.
510
+ **Quiet does not suppress**: the typing/thinking indicator (which stays up for the turn's whole working phase; while the turn is parked on an approval the clients suppress an agent's dots and the header line carries the state), turn state, `replyFinal()` including every part of a chunked reply, the partial-final notice, `media.replyWithFile()` itself, `turn.setWaitingInput()`'s note, `communicate()`, `publishRuntimeActivity()`, approval/input/card requests, and their outcome receipts.
512
511
 
513
512
  **`replyProgress(text, { durable: true })` still posts.** Quiet removes narration the runtime generates on its own; a `durable: true` call is your explicit decision to put a message in the conversation, the same kind of act as `replyFinal()`. Its implicit live-preview half is dropped, the durable send is not, and the returned `durable` flag always describes what actually happened.
514
513
 
@@ -533,4 +532,4 @@ Canon caps a single message at 4 KB of UTF-8 text, and rejects anything longer o
533
532
  Every other send path passes your text through as-is, so text over the cap still fails there. Notably:
534
533
 
535
534
  - `media.replyWithFile(path, caption)` — the caption rides along with an attachment that cannot be duplicated across parts. Keep captions short and send long prose as a separate `replyFinal()`.
536
- - `sendContextualMessage()` and `reachOut({ text })` a different endpoint with no chunked sender behind it.
535
+ - `communicate()` a distinct compact cross-conversation operation; keep each message under the cap.
@@ -1,5 +1,5 @@
1
- import { type AddMemberResult, type CanonContact, type CanonConversation, type CanonConversationsPage, type CanonConversationsPageOptions, type CreateConversationResult, type CanonRuntimeActivityItem, type CanonRuntimeCommandDescriptor, type CanonRuntimeFact, type CanonRuntimePrimitiveId, type ContactCardPayload, type ClearRuntimeActivityOptions, type CreateContactRequestResult, type CanonVoiceSession, type CanonVoiceSessionToken, type CreateVoiceSessionOptions, type VoiceSessionEventPayload } from '@canonmsg/core';
2
- import type { CanonAgentConnectionOptions, CanonAgentOptions, ContactAddedHandler, ContactRemovedHandler, CreateConversationOptions, MessageHandler, MessageUpdatedHandler, ParticipationSuppressedHandler, ReachOutOptions, ReachOutResult, ContactRequestHandler, RuntimeSignalHandler, RuntimePrimitiveHandler } from './types.js';
1
+ import { type AddMemberResult, type CanonContact, type CommunicateInput, type CommunicateResult, type CanonConversation, type CanonConversationsPage, type CanonConversationsPageOptions, type CreateGroupOptions, type CreateGroupResult, type CanonRuntimeActivityItem, type CanonRuntimeCommandDescriptor, type CanonRuntimeFact, type CanonRuntimePrimitiveId, type ClearRuntimeActivityOptions, type CanonVoiceSession, type CanonVoiceSessionToken, type CreateVoiceSessionOptions, type VoiceSessionEventPayload } from '@canonmsg/core';
2
+ import type { CanonAgentConnectionOptions, CanonAgentOptions, ContactAddedHandler, ContactRemovedHandler, MessageHandler, MessageUpdatedHandler, ParticipationSuppressedHandler, ContactRequestHandler, RuntimeSignalHandler, RuntimePrimitiveHandler } from './types.js';
3
3
  /**
4
4
  * Contact-graph operations exposed under `agent.contacts`. Wraps the REST
5
5
  * endpoints in CanonClient — the same surface a human user would hit through
@@ -9,7 +9,6 @@ export interface AgentContactsAPI {
9
9
  list(): Promise<CanonContact[]>;
10
10
  get(contactId: string): Promise<CanonContact | null>;
11
11
  remove(contactId: string): Promise<void>;
12
- request(targetUserId: string, message?: string | null): Promise<CreateContactRequestResult>;
13
12
  }
14
13
  /**
15
14
  * User-level moderation actions exposed under `agent.users`.
@@ -62,7 +61,6 @@ export declare class CanonAgent {
62
61
  readonly users: AgentUsersAPI;
63
62
  /** Conversation discovery for choosing existing sessions intentionally. */
64
63
  readonly conversations: AgentConversationsAPI;
65
- private readonly reachOutInFlight;
66
64
  private agentId;
67
65
  private agentContext;
68
66
  private approvalManager;
@@ -127,16 +125,13 @@ export declare class CanonAgent {
127
125
  publishRuntimeActivity(conversationId: string, item: CanonRuntimeActivityItem): Promise<void>;
128
126
  clearRuntimeActivity(conversationId: string, options?: ClearRuntimeActivityOptions): Promise<void>;
129
127
  /**
130
- * Resolve admission live for a target user (typically read off a shared
131
- * contact card) and route into either an immediate message or a contact
132
- * request. Never reads `card.accessLevel` that snapshot is stale by the
133
- * time an LLM acts on it. Instead defers to `resolveAdmission` so the
134
- * answer reflects the target's *current* inbound policy.
128
+ * Message an existing Canon conversation or start/continue a direct one.
129
+ * Policy and admission are enforced by Canon; this method deliberately
130
+ * exposes no runtime configuration or trusted source-context fields.
135
131
  */
136
- reachOut(card: ContactCardPayload, options?: ReachOutOptions): Promise<ReachOutResult>;
137
- private executeReachOut;
132
+ communicate(input: CommunicateInput): Promise<CommunicateResult>;
138
133
  start(): Promise<void>;
139
- createConversation(options: CreateConversationOptions): Promise<CreateConversationResult>;
134
+ createGroup(options: CreateGroupOptions): Promise<CreateGroupResult>;
140
135
  /** Start (or rejoin) a call in a conversation and get the room token. */
141
136
  startCall(options: CreateVoiceSessionOptions): Promise<CanonVoiceSessionToken>;
142
137
  /** Join an active call session and get the room token. */
@@ -1,4 +1,4 @@
1
- import { ApprovalManager, RuntimeRequestManager, runtimeInputDescriptor, runtimeCardDescriptor, CanonClient, ControlChannelPoller, buildCanonTurnContextV2, buildCanonGroupContext, buildParticipationHistorySnapshot, createTurnOutputController, createRuntimeStatePublisher, createTypingStatusPublisher, diffCanonMemberIds, FINAL_MESSAGE_HANDOFF_MS, RUNTIME_NEW_SESSION_ACTION, RUNTIME_STOP_ACTION, RUNTIME_STOP_AND_DROP_ACTION, buildRuntimeCardOutcome, buildRuntimeInputOutcome, initRTDBAuth, isChunkedSendMessageError, normalizeRuntimeCommandDescriptors, normalizeTurnMetadata, normalizeTurnVerbosityConversationType, reachOutToCanonContact, reportNoReplyOutcome, resolveCanonReplyContext, resolveMessageActiveSelfContextId, resolveRuntimeProvenance, resolveTurnVerbosity, selectActiveSelfContexts, renderCanonHostInboundContent, resolveCanonRuntimeConnection, sendMessageWithRetryChunked, shouldPublishTurnTrail, splitTextByUtf8Bytes, verifyCanonRuntimeConnection, } from '@canonmsg/core';
1
+ import { ApprovalManager, RuntimeRequestManager, runtimeInputDescriptor, runtimeCardDescriptor, CanonClient, ControlChannelPoller, buildCanonTurnContextV2, buildCanonGroupContext, buildParticipationHistorySnapshot, createTurnOutputController, createRuntimeStatePublisher, createTypingStatusPublisher, diffCanonMemberIds, FINAL_MESSAGE_HANDOFF_MS, RUNTIME_NEW_SESSION_ACTION, RUNTIME_STOP_ACTION, RUNTIME_STOP_AND_DROP_ACTION, buildRuntimeCardOutcome, buildRuntimeInputOutcome, initRTDBAuth, isChunkedSendMessageError, normalizeRuntimeCommandDescriptors, normalizeTurnMetadata, normalizeTurnVerbosityConversationType, reportNoReplyOutcome, resolveCanonReplyContext, resolveMessageActiveSelfContextId, resolveRuntimeProvenance, resolveTurnVerbosity, selectActiveSelfContexts, renderCanonHostInboundContent, resolveCanonRuntimeConnection, sendMessageWithRetryChunked, shouldPublishTurnTrail, splitTextByUtf8Bytes, verifyCanonRuntimeConnection, } from '@canonmsg/core';
2
2
  import { createHash, randomUUID } from 'node:crypto';
3
3
  import { AuthManager } from './auth.js';
4
4
  import { Debouncer } from './debouncer.js';
@@ -275,7 +275,6 @@ export class CanonAgent {
275
275
  users;
276
276
  /** Conversation discovery for choosing existing sessions intentionally. */
277
277
  conversations;
278
- reachOutInFlight = new Map();
279
278
  agentId = null;
280
279
  agentContext = null;
281
280
  approvalManager = null;
@@ -335,7 +334,6 @@ export class CanonAgent {
335
334
  list: () => apiClient.listContacts(),
336
335
  get: (contactId) => apiClient.getContact(contactId),
337
336
  remove: (contactId) => apiClient.deleteContact(contactId),
338
- request: (targetUserId, message) => apiClient.createContactRequest(targetUserId, message ?? null),
339
337
  };
340
338
  this.users = {
341
339
  block: (userId) => apiClient.blockUser(userId),
@@ -546,75 +544,12 @@ export class CanonAgent {
546
544
  await this.requireRuntimeStatePublisher().clearRuntimeActivity(conversationId, options);
547
545
  }
548
546
  /**
549
- * Resolve admission live for a target user (typically read off a shared
550
- * contact card) and route into either an immediate message or a contact
551
- * request. Never reads `card.accessLevel` that snapshot is stale by the
552
- * time an LLM acts on it. Instead defers to `resolveAdmission` so the
553
- * answer reflects the target's *current* inbound policy.
547
+ * Message an existing Canon conversation or start/continue a direct one.
548
+ * Policy and admission are enforced by Canon; this method deliberately
549
+ * exposes no runtime configuration or trusted source-context fields.
554
550
  */
555
- async reachOut(card, options) {
556
- const target = {
557
- targetUserId: card.userId,
558
- ...(card.userType === 'ai_agent' && card.canonContactId
559
- ? { canonContactId: card.canonContactId }
560
- : {}),
561
- };
562
- const targetKey = target.canonContactId ?? target.targetUserId;
563
- // Include the opener/request payloads in the dedupe key so two concurrent
564
- // calls with different `text`, `requestMessage`, or setup choices don't silently collapse
565
- // and lose the second caller's intended side effect.
566
- const contextualKey = options?.selfContext
567
- ? `${options.sourceConversationId ?? ''}\u0000${options.selfContext.type}\u0000${options.selfContext.context}`
568
- : '';
569
- const inFlightKey = `${targetKey}\u0000${options?.text ?? ''}\u0000${options?.requestMessage ?? ''}\u0000${JSON.stringify(options?.sessionConfig ?? null)}\u0000${JSON.stringify(options?.sessionSelection ?? null)}\u0000${contextualKey}`;
570
- const inFlight = this.reachOutInFlight.get(inFlightKey);
571
- if (inFlight)
572
- return inFlight;
573
- const promise = this.executeReachOut(target, options).finally(() => {
574
- this.reachOutInFlight.delete(inFlightKey);
575
- });
576
- this.reachOutInFlight.set(inFlightKey, promise);
577
- return promise;
578
- }
579
- async executeReachOut(target, options) {
580
- const { targetUserId } = target;
581
- if (options?.selfContext) {
582
- if (!options.sourceConversationId) {
583
- throw new Error('sourceConversationId is required for contextual reachOut');
584
- }
585
- if (!options.text) {
586
- throw new Error('text is required for contextual reachOut');
587
- }
588
- const result = await this.apiClient.sendContextualMessage({
589
- sourceConversationId: options.sourceConversationId,
590
- targetUserId,
591
- text: options.text,
592
- selfContext: options.selfContext,
593
- requestMessage: options.requestMessage ?? null,
594
- sessionConfig: options.sessionConfig ?? null,
595
- sessionSelection: options.sessionSelection,
596
- });
597
- return result.status === 'messaged'
598
- ? {
599
- status: 'messaged',
600
- conversationId: result.conversationId,
601
- messageId: result.messageId,
602
- selfContextId: result.selfContextId,
603
- created: result.created,
604
- reused: result.reused,
605
- sessionSelection: result.sessionSelection,
606
- }
607
- : result;
608
- }
609
- return reachOutToCanonContact(this.apiClient, {
610
- ...(target.canonContactId
611
- ? { canonContactId: target.canonContactId }
612
- : { targetUserId }),
613
- text: options?.text ?? null,
614
- requestMessage: options?.requestMessage ?? null,
615
- sessionConfig: options?.sessionConfig ?? null,
616
- sessionSelection: options?.sessionSelection,
617
- });
551
+ async communicate(input) {
552
+ return this.apiClient.communicate(input);
618
553
  }
619
554
  async start() {
620
555
  if (this.running)
@@ -748,8 +683,8 @@ export class CanonAgent {
748
683
  this.realtimeManager = rtm;
749
684
  await rtm.start();
750
685
  }
751
- async createConversation(options) {
752
- return this.apiClient.createConversation(options);
686
+ async createGroup(options) {
687
+ return this.apiClient.createGroup(options);
753
688
  }
754
689
  // ── Calls ────────────────────────────────────────────────────────────
755
690
  // These return the LiveKit room token payload; the agent brings its own
@@ -1613,6 +1548,7 @@ export class CanonAgent {
1613
1548
  ownerName: '',
1614
1549
  discoverable: false,
1615
1550
  inboundPolicy: 'approval-required',
1551
+ outboundPolicy: 'approval-required',
1616
1552
  groupJoinPolicy: 'approval-required',
1617
1553
  };
1618
1554
  const provenance = latestMessage
@@ -1702,24 +1638,7 @@ export class CanonAgent {
1702
1638
  const react = (messageId, emoji) => this.apiClient.react(conversationId, messageId, emoji);
1703
1639
  const addMember = (userId) => this.apiClient.addMember(conversationId, userId);
1704
1640
  const removeMember = (userId) => this.apiClient.removeMember(conversationId, userId);
1705
- const sendContextualMessage = (target, text, options) => this.apiClient.sendContextualMessage({
1706
- sourceConversationId: conversationId,
1707
- ...target,
1708
- text,
1709
- ...options,
1710
- messageOptions: {
1711
- ...(options.messageOptions ?? {}),
1712
- metadata: {
1713
- ...(options.messageOptions?.metadata ?? {}),
1714
- turnId,
1715
- turnSemantics: 'turn_complete',
1716
- },
1717
- },
1718
- });
1719
- const reachOut = (card, options) => this.reachOut(card, {
1720
- ...(options ?? {}),
1721
- sourceConversationId: conversationId,
1722
- });
1641
+ const communicate = (input) => this.communicate(input);
1723
1642
  const requestApproval = async (request) => {
1724
1643
  throwIfAborted();
1725
1644
  const manager = this.ensureApprovalManager(agent);
@@ -2091,8 +2010,7 @@ export class CanonAgent {
2091
2010
  react,
2092
2011
  addMember,
2093
2012
  removeMember,
2094
- sendContextualMessage,
2095
- reachOut,
2013
+ communicate,
2096
2014
  agent,
2097
2015
  activeSelfContextId,
2098
2016
  selfContexts,
package/dist/index.d.ts CHANGED
@@ -7,5 +7,5 @@ export { DEFAULT_ANTHROPIC_REQUEST_HEADROOM_BYTES, DEFAULT_MEDIA_CACHE_DIR, DEFA
7
7
  export type { AnthropicImageBlock, AnthropicImageBudgetOptions, AnthropicImageMimeType, MaterializeMediaOptions, MaterializedCanonAttachment, MaterializedCanonReplyContext, ReplyWithFileOptions, UploadMediaFileOptions, } from './media.js';
8
8
  export type { SessionConfig, Session } from './session-manager.js';
9
9
  export type { CanonAgentTurnVerbosityOption } from './turn-verbosity-option.js';
10
- export type { AgentContext, CanonGroupContext, CanonKnownRecentParticipant, CanonMembershipChange, CanonContactRequest, GroupInviteRequirements, CanonMessage, CanonConversation, CanonConversationsPage, CanonConversationsPageOptions, CanonReplyContext, CanonSelfContext, CanonTurnContextV2, CanonRuntimeDescriptor, MessageUpdatedPayload, SendContextualMessageOptions, SendContextualMessageResult, SendContextualSelfContextInput, SendMessageOptions, CreateConversationOptions, CreateConversationResult, DirectSessionSelection, TurnVerbosity, TurnVerbosityConfig, } from '@canonmsg/core';
11
- export type { CanonAgentConnectionOptions, CanonAgentOptions, ContactAddedHandler, ContactRemovedHandler, ContactRequestHandler, FinalMessageResult, MessageHandler, MessageHandlerContext, MessageUpdatedHandler, ParticipationSuppressedHandler, ProgressMessageOptions, ProgressMessageResult, ReachOutOptions, ReachOutResult, RuntimeApprovalRequest, RuntimeInputRequest, RuntimeInputResult, RuntimeControlSurface, RuntimePrimitiveContext, RuntimePrimitiveHandler, RuntimePrimitiveHandlers, SessionInfo, SessionOptions, DeliveryMode, } from './types.js';
10
+ export type { AgentContext, CanonGroupContext, CanonKnownRecentParticipant, CanonMembershipChange, CanonContactRequest, GroupInviteRequirements, CanonMessage, CanonConversation, CommunicateInput, CommunicateResult, DirectConversationSelection, CanonConversationsPage, CanonConversationsPageOptions, CanonReplyContext, CanonSelfContext, CanonTurnContextV2, CanonRuntimeDescriptor, MessageUpdatedPayload, SendMessageOptions, CreateGroupOptions, CreateGroupResult, TurnVerbosity, TurnVerbosityConfig, } from '@canonmsg/core';
11
+ export type { CanonAgentConnectionOptions, CanonAgentOptions, ContactAddedHandler, ContactRemovedHandler, ContactRequestHandler, FinalMessageResult, MessageHandler, MessageHandlerContext, MessageUpdatedHandler, ParticipationSuppressedHandler, ProgressMessageOptions, ProgressMessageResult, RuntimeApprovalRequest, RuntimeInputRequest, RuntimeInputResult, RuntimeControlSurface, RuntimePrimitiveContext, RuntimePrimitiveHandler, RuntimePrimitiveHandlers, SessionInfo, SessionOptions, DeliveryMode, } from './types.js';
package/dist/types.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- export type { AddMemberResult, GroupInviteRequirements, AgentClientType, CanonGroupContext, CanonRuntimeActivityItem, CanonRuntimeActivityKind, CanonRuntimeActivityStatus, CanonRuntimeDescriptor, CanonRuntimeFact, CanonRuntimeFactGroup, CanonRuntimePrimitiveId, CanonRuntimeProvenance, CanonTurnContextV2, CanonMessage, CanonConversation, CanonReplyContext, CanonContact, CanonContactRequest, CanonResolveAdmissionResult, ContactAddedPayload, ContactRemovedPayload, ContactSource, AgentContext, ResolveAdmissionTargetInput, ResolvedAdmissionState, ResolvedAdmissionTargetSummary, ResolvedTargetAdmissionPayload, CanonSelfContext, CreateConversationResult, DirectSessionSelection, SendContextualMessageOptions, SendContextualMessageResult, SendContextualSelfContextInput, SendMessageOptions, SessionConfig, VerbSessionConfig, CreateConversationOptions, TurnLifecycleState, TurnOutputBlock, TurnOutputBlockInput, ApprovalNativeRequestMetadata, ApprovalRequestCategory, ApprovalRequestDetail, ApprovalRequestMetadata, ApprovalRisk, ApprovalReplyMetadata, ApprovalOutcomeMetadata, RuntimeInputChoice, RuntimeInputAnswers, RuntimeInputKind, RuntimeInputNativeMetadata, RuntimeInputQuestion, RuntimeCardNativeMetadata, RuntimeCardV1, ResumableMediaUploadResult, MediaAttachment, VideoProcessingStatus, VideoProcessingErrorCode, SessionRule, ApprovalResult, } from '@canonmsg/core';
2
- import type { AddMemberResult, CanonGroupContext, CanonMessage, CanonConversation, CanonReplyContext, ContactCardPayload, CanonRuntimeActionDispatch, CanonRuntimePrimitiveId, CanonRuntimeProvenance, CanonTurnContextV2, ApprovalNativeRequestMetadata, ApprovalRequestCategory, ApprovalRequestDetail, ApprovalResult, ApprovalRisk, RuntimeInputChoice, RuntimeInputAnswers, RuntimeInputKind, RuntimeInputNativeMetadata, RuntimeInputQuestion, RuntimeCardNativeMetadata, RuntimeCardV1, ResumableMediaUploadResult, SendMessageOptions, SendContextualSelfContextInput, VerbSessionConfig, DirectSessionSelection, TurnOutputBlock, TurnOutputBlockInput } from '@canonmsg/core';
1
+ export type { AddMemberResult, GroupInviteRequirements, AgentClientType, CanonGroupContext, CanonRuntimeActivityItem, CanonRuntimeActivityKind, CanonRuntimeActivityStatus, CanonRuntimeDescriptor, CanonRuntimeFact, CanonRuntimeFactGroup, CanonRuntimePrimitiveId, CanonRuntimeProvenance, CanonTurnContextV2, CanonMessage, CanonConversation, CommunicateInput, CommunicateResult, CanonReplyContext, CanonContact, CanonContactRequest, CanonResolveAdmissionResult, ContactAddedPayload, ContactRemovedPayload, ContactSource, AgentContext, ResolveAdmissionTargetInput, ResolvedAdmissionState, ResolvedAdmissionTargetSummary, ResolvedTargetAdmissionPayload, CanonSelfContext, CreateGroupOptions, CreateGroupResult, SendMessageOptions, SessionConfig, TurnLifecycleState, TurnOutputBlock, TurnOutputBlockInput, ApprovalNativeRequestMetadata, ApprovalRequestCategory, ApprovalRequestDetail, ApprovalRequestMetadata, ApprovalRisk, ApprovalReplyMetadata, ApprovalOutcomeMetadata, RuntimeInputChoice, RuntimeInputAnswers, RuntimeInputKind, RuntimeInputNativeMetadata, RuntimeInputQuestion, RuntimeCardNativeMetadata, RuntimeCardV1, ResumableMediaUploadResult, MediaAttachment, VideoProcessingStatus, VideoProcessingErrorCode, SessionRule, ApprovalResult, } from '@canonmsg/core';
2
+ import type { AddMemberResult, CanonGroupContext, CanonMessage, CanonConversation, CommunicateInput, CommunicateResult, CanonReplyContext, CanonRuntimeActionDispatch, CanonRuntimePrimitiveId, CanonRuntimeProvenance, CanonTurnContextV2, ApprovalNativeRequestMetadata, ApprovalRequestCategory, ApprovalRequestDetail, ApprovalResult, ApprovalRisk, RuntimeInputChoice, RuntimeInputAnswers, RuntimeInputKind, RuntimeInputNativeMetadata, RuntimeInputQuestion, RuntimeCardNativeMetadata, RuntimeCardV1, ResumableMediaUploadResult, SendMessageOptions, TurnOutputBlock, TurnOutputBlockInput } from '@canonmsg/core';
3
3
  import type { MaterializeMediaOptions, MaterializedCanonAttachment, ReplyWithFileOptions, UploadMediaFileOptions } from './media.js';
4
4
  export interface ProgressMessageOptions extends SendMessageOptions {
5
5
  /**
@@ -176,14 +176,8 @@ export interface MessageHandlerContext {
176
176
  addMember: (userId: string) => Promise<AddMemberResult>;
177
177
  /** Remove a member from this conversation (requires owner/admin role) */
178
178
  removeMember: (userId: string) => Promise<void>;
179
- /** Send into another Canon conversation with private cross-session self-context. */
180
- sendContextualMessage: (target: {
181
- targetConversationId: string;
182
- } | {
183
- targetUserId: string;
184
- }, text: string, options: Omit<import('@canonmsg/core').SendContextualMessageOptions, 'sourceConversationId' | 'targetConversationId' | 'targetUserId' | 'text'>) => Promise<import('@canonmsg/core').SendContextualMessageResult>;
185
- /** Reach a contact card from this conversation; contextual reach-outs use this conversation as source. */
186
- reachOut: (card: ContactCardPayload, options?: Omit<ReachOutOptions, 'sourceConversationId'>) => Promise<ReachOutResult>;
179
+ /** Message an existing Canon conversation or start/continue a direct one. */
180
+ communicate: (input: CommunicateInput) => Promise<CommunicateResult>;
187
181
  /** Trusted agent identity & access context */
188
182
  agent: import('@canonmsg/core').AgentContext;
189
183
  /** Active private self-context to continue for this turn, if Canon supplied one. */
@@ -345,56 +339,3 @@ export type ContactRemovedHandler = (payload: import('@canonmsg/core').ContactRe
345
339
  * benched agent can tell deliberate participation policy from a dead stream.
346
340
  */
347
341
  export type ParticipationSuppressedHandler = (payload: import('@canonmsg/core').ParticipationSuppressedPayload) => void | Promise<void>;
348
- /**
349
- * Result of `agent.reachOut(card)` — describes which side-effect ran so the
350
- * caller can decide what to tell the LLM. `messaged` means the agent opened
351
- * (or sent into) a direct conversation; `requested` means the target's
352
- * inbound policy required a contact request, which has been created;
353
- * `pending` means a prior outbound request is still awaiting approval; and
354
- * `blocked` / `unavailable` describe terminal states with `reason` set.
355
- */
356
- export type ReachOutResult = {
357
- status: 'messaged';
358
- conversationId: string;
359
- messageId?: string;
360
- selfContextId?: string;
361
- created?: boolean;
362
- reused?: boolean;
363
- sessionSelection?: DirectSessionSelection['mode'];
364
- } | {
365
- status: 'requested';
366
- requestId: string | null;
367
- deferredIntentId?: string | null;
368
- } | {
369
- status: 'pending';
370
- requestId: string | null;
371
- deferredIntentId?: string | null;
372
- } | {
373
- status: 'setup_required';
374
- reason: string;
375
- } | {
376
- status: 'no_session';
377
- reason: string;
378
- } | {
379
- status: 'blocked' | 'unavailable';
380
- reason: string;
381
- };
382
- export interface ReachOutOptions {
383
- /**
384
- * Optional first message; sent now when allowed or parked for exact delivery
385
- * after approval when it is visible text <= 4 KiB. Attachments and hidden
386
- * session setup cannot be parked; a setup-requiring coding target returns
387
- * `setup_required` before a contact request is created.
388
- */
389
- text?: string;
390
- /** Optional contact-request note. Defaults to `text` when admission is `request-required`. */
391
- requestMessage?: string;
392
- /** Explicit session setup to use when the contact-card target is an agent. */
393
- sessionConfig?: VerbSessionConfig | null;
394
- /** Whether to continue an existing direct agent session or start a fresh one. */
395
- sessionSelection?: DirectSessionSelection;
396
- /** Source conversation for contextual cross-session reach-outs. */
397
- sourceConversationId?: string;
398
- /** Private context for the agent when this reach-out sends a cross-session message. */
399
- selfContext?: SendContextualSelfContextInput;
400
- }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@canonmsg/agent-sdk",
3
- "version": "8.8.0",
3
+ "version": "9.0.0",
4
4
  "description": "Canon Agent SDK — build AI agents that participate in Canon conversations",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -28,7 +28,7 @@
28
28
  "node": ">=18.0.0"
29
29
  },
30
30
  "dependencies": {
31
- "@canonmsg/core": "^10.6.0"
31
+ "@canonmsg/core": "^11.0.0"
32
32
  },
33
33
  "publishConfig": {
34
34
  "access": "public"