@canonmsg/agent-sdk 12.0.0 → 12.1.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.
Files changed (99) hide show
  1. package/README.md +97 -7
  2. package/dist/chunks/{chunk-FPQFTTND.js → chunk-7N6OPPW4.js} +1616 -1085
  3. package/dist/chunks/chunk-N722GWCP.js +4897 -0
  4. package/dist/chunks/{chunk-OLJ7H4E2.js → chunk-QZ4PPRQW.js} +6462 -6920
  5. package/dist/chunks/{mls-crypto-NZDNSPAO.js → mls-crypto-LMNQZOS6.js} +3 -3
  6. package/dist/cli.js +403 -29
  7. package/dist/drivers/claude.d.ts +8 -2
  8. package/dist/drivers/codex.d.ts +11 -2
  9. package/dist/drivers/connector.d.ts +34 -0
  10. package/dist/index.d.ts +10 -2
  11. package/dist/index.js +26 -4
  12. package/dist/internal/backend-contracts/artifactActions.d.ts +0 -151
  13. package/dist/internal/backend-contracts/clientFloor.d.ts +41 -0
  14. package/dist/internal/backend-contracts/communication.d.ts +15 -0
  15. package/dist/internal/backend-contracts/connectorRelay.d.ts +179 -0
  16. package/dist/internal/backend-contracts/endpoint.d.ts +17 -0
  17. package/dist/internal/backend-contracts/endpointContentPolicy.d.ts +15 -4
  18. package/dist/internal/backend-contracts/index.d.ts +7 -1
  19. package/dist/internal/backend-contracts/media-url.d.ts +14 -0
  20. package/dist/internal/backend-contracts/message.d.ts +1 -1
  21. package/dist/internal/backend-contracts/mlsDevApplication.d.ts +90 -2
  22. package/dist/internal/backend-contracts/mlsDevCredential.d.ts +5 -2
  23. package/dist/internal/backend-contracts/mlsDevDeviceCustody.d.ts +2 -1
  24. package/dist/internal/backend-contracts/mlsDevEnrollment.d.ts +3 -2
  25. package/dist/internal/backend-contracts/mlsDevFeedReceipt.d.ts +43 -0
  26. package/dist/internal/backend-contracts/mlsDevGroup.d.ts +129 -5
  27. package/dist/internal/backend-contracts/mlsDevGroupFeed.d.ts +6 -2
  28. package/dist/internal/backend-contracts/mlsDevInteraction.d.ts +159 -0
  29. package/dist/internal/backend-contracts/mlsEnvironment.d.ts +35 -0
  30. package/dist/internal/backend-contracts/mlsPrincipalAlias.d.ts +23 -0
  31. package/dist/internal/backend-contracts/runtimeCardFields.d.ts +2 -2
  32. package/dist/internal/backend-contracts/upload-mime-types.d.ts +17 -0
  33. package/dist/internal/backend-contracts/verbContract.d.ts +15 -7
  34. package/dist/internal/backend-contracts/verbSchemas.d.ts +35 -25
  35. package/dist/internal/core/agent-profiles.d.ts +0 -4
  36. package/dist/internal/core/approval-format.d.ts +1 -5
  37. package/dist/internal/core/approval-types.d.ts +1 -2
  38. package/dist/internal/core/client.d.ts +2 -56
  39. package/dist/internal/core/constants.d.ts +0 -3
  40. package/dist/internal/core/endpoint-client.d.ts +14 -1
  41. package/dist/internal/core/execution-environment-mode.d.ts +0 -2
  42. package/dist/internal/core/gifs.d.ts +0 -6
  43. package/dist/internal/core/host-runtime.d.ts +2 -206
  44. package/dist/internal/core/index.d.ts +21 -60
  45. package/dist/internal/core/registration.d.ts +1 -17
  46. package/dist/internal/core/retry.d.ts +0 -9
  47. package/dist/internal/core/rtdb-rest.d.ts +0 -4
  48. package/dist/internal/core/runtime-cards.d.ts +0 -45
  49. package/dist/internal/core/runtime-descriptor.d.ts +1 -60
  50. package/dist/internal/core/runtime-presentation.d.ts +1 -27
  51. package/dist/internal/core/runtime-request-manager.d.ts +0 -1
  52. package/dist/internal/core/self-context.d.ts +0 -39
  53. package/dist/internal/core/silent-turn.d.ts +1 -38
  54. package/dist/internal/core/stream.d.ts +2 -1
  55. package/dist/internal/core/turn-protocol.d.ts +0 -5
  56. package/dist/internal/core/turn-verbosity.d.ts +0 -12
  57. package/dist/internal/core/types.d.ts +0 -111
  58. package/dist/internal/endpoint/engine.d.ts +31 -1
  59. package/dist/internal/endpoint/index.d.ts +1 -1
  60. package/dist/internal/endpoint/media.d.ts +5 -0
  61. package/dist/internal/endpoint/mls-crypto.d.ts +12 -5
  62. package/dist/internal/endpoint/mls-dev-client.d.ts +9 -1
  63. package/dist/internal/endpoint/mls-dev-device.d.ts +2 -0
  64. package/dist/internal/endpoint/mls-dev-groups.d.ts +65 -5
  65. package/dist/internal/endpoint/mls-dev-interactions.d.ts +99 -0
  66. package/dist/internal/endpoint/mls-dev-key-package-service.d.ts +13 -0
  67. package/dist/internal/endpoint/mls-dev-key-packages.d.ts +23 -3
  68. package/dist/internal/endpoint/mls-dev-text.d.ts +67 -0
  69. package/dist/internal/endpoint/mls-dev-transport.d.ts +2 -1
  70. package/dist/internal/endpoint/node-mls-custody-protocol.d.ts +5 -0
  71. package/dist/internal/endpoint/transport.d.ts +6 -1
  72. package/dist/media.js +2 -2
  73. package/dist/runner/errands.d.ts +118 -0
  74. package/dist/runner/mls.d.ts +97 -0
  75. package/dist/runner/relay.d.ts +87 -0
  76. package/dist/runner/runner.d.ts +61 -0
  77. package/dist/runner/types.d.ts +51 -4
  78. package/package.json +1 -1
  79. package/dist/chunks/chunk-6VK4UZHJ.js +0 -2806
  80. package/dist/internal/backend-contracts/workSessions.d.ts +0 -205
  81. package/dist/internal/core/agent-resolver.d.ts +0 -49
  82. package/dist/internal/core/agent-session.d.ts +0 -12
  83. package/dist/internal/core/artifacts.d.ts +0 -262
  84. package/dist/internal/core/attached-native-session.d.ts +0 -174
  85. package/dist/internal/core/attached-session-file-store.d.ts +0 -3
  86. package/dist/internal/core/control-poller.d.ts +0 -221
  87. package/dist/internal/core/exclusive-json-file-store.d.ts +0 -7
  88. package/dist/internal/core/execution-environment.d.ts +0 -55
  89. package/dist/internal/core/group-context.d.ts +0 -25
  90. package/dist/internal/core/inbound-frame.d.ts +0 -64
  91. package/dist/internal/core/local-runtime-catalog.d.ts +0 -131
  92. package/dist/internal/core/message-format.d.ts +0 -13
  93. package/dist/internal/core/native-session-interaction.d.ts +0 -44
  94. package/dist/internal/core/provenance.d.ts +0 -31
  95. package/dist/internal/core/registration-cli.d.ts +0 -40
  96. package/dist/internal/core/turn-output-controller.d.ts +0 -69
  97. package/dist/internal/core/typing-status-publisher.d.ts +0 -14
  98. package/dist/internal/core/work-session-provider.d.ts +0 -29
  99. package/dist/internal/core/workspace-discovery.d.ts +0 -17
@@ -10,7 +10,6 @@ export interface RuntimeRequestContext {
10
10
  agentId: string;
11
11
  ownerId: string;
12
12
  }
13
- export type RuntimeResolveReason = 'replied' | 'timeout' | 'aborted';
14
13
  /** Normalized outcome of a single consume poll. */
15
14
  export type RuntimeConsumeOutcome<Result> = {
16
15
  state: 'pending';
@@ -20,42 +20,3 @@ export interface CanonSelfContext {
20
20
  createdAt?: string | null;
21
21
  updatedAt?: string | null;
22
22
  }
23
- export interface SelfContextPromptRenderOptions {
24
- maxSelfContexts?: number;
25
- }
26
- export declare function normalizeSelfContexts(selfContexts?: CanonSelfContext[] | null, options?: SelfContextPromptRenderOptions): CanonSelfContext[];
27
- export declare function resolveMessageActiveSelfContextId(input: {
28
- messageId?: string | null;
29
- activeSelfContextId?: string | null;
30
- activeSelfContextIdByMessageId?: Record<string, string> | null;
31
- }): string | null;
32
- export declare function selectActiveSelfContexts(selfContexts?: CanonSelfContext[] | null, activeSelfContextId?: string | null): CanonSelfContext[];
33
- /**
34
- * Select private explanations for one inbound turn. A reply can activate only
35
- * the explanation attached to its exact target. Other recent explanations are
36
- * background, not a claim that the incoming message answers any one of them.
37
- */
38
- export declare function selectInboundSelfContexts(input: {
39
- selfContexts?: CanonSelfContext[] | null;
40
- replyTo?: string | null;
41
- /** Backend-validated association for this inbound message, when available. */
42
- linkedSelfContextId?: string | null;
43
- messages?: ReadonlyArray<{
44
- id?: string | null;
45
- text?: string | null;
46
- createdAt?: string | null;
47
- deleted?: boolean | null;
48
- }> | null;
49
- replyContext?: {
50
- messageId: string;
51
- text?: string | null;
52
- found: boolean;
53
- } | null;
54
- maxSelfContexts?: number;
55
- }): {
56
- activeSelfContextId: string | null;
57
- selfContexts: CanonSelfContext[];
58
- };
59
- export declare function buildSelfContextPromptLines(selfContexts?: CanonSelfContext[] | null, options?: SelfContextPromptRenderOptions & {
60
- activeSelfContextId?: string | null;
61
- }): string[];
@@ -2,8 +2,7 @@
2
2
  * Deliberate silence — the shared half of the `no_reply` verb.
3
3
  *
4
4
  * A turn that calls `no_reply` must end without posting anything: the trigger
5
- * gate is message-driven, so no message means no other agent is woken. Every
6
- * host wires its own teardown, but they all ask the same question here.
5
+ * gate is message-driven, so no message means no other agent is woken.
7
6
  */
8
7
  /**
9
8
  * The model-facing closure sentence, re-exported so a runtime that answers
@@ -48,39 +47,3 @@ export declare function reportNoReplyOutcome(client: NoReplyReportClient, params
48
47
  reason?: string;
49
48
  now?: number;
50
49
  }): void;
51
- /**
52
- * Owner ruling 2026-07-31 (docs/history/group-behavior-2026-08-01.md), as
53
- * implemented. `strict` (default): a no_reply call suppresses the final
54
- * unconditionally. `advisory`: non-empty final text overrides the sentinel.
55
- * ONE switch, so the ruling can be flipped without touching five hosts.
56
- */
57
- export type SilentTurnPrecedence = 'strict' | 'advisory';
58
- export declare const DEFAULT_SILENT_TURN_PRECEDENCE: SilentTurnPrecedence;
59
- export declare function resolveSilentTurnDelivery(input: {
60
- silenced: boolean;
61
- finalText: string | null | undefined;
62
- precedence?: SilentTurnPrecedence;
63
- }): 'deliver' | 'suppress';
64
- /**
65
- * Whether SILENCE is what withholds this turn's own output — the single
66
- * question every consumer of the ruling asks, so they cannot disagree.
67
- *
68
- * `resolveSilentTurnDelivery` answers "is there anything to deliver", which
69
- * also returns `suppress` for an ordinary turn that simply produced no text.
70
- * A caller deciding what ELSE a silenced turn withholds — its workspace
71
- * artifacts, its plan card — needs the narrower question, and deriving it by
72
- * hand (`silenced && ...`) is how a second, independent reading of
73
- * `DEFAULT_SILENT_TURN_PRECEDENCE` creeps in. Flipping that constant to
74
- * `advisory` must move a turn's text and its artifacts together: a turn that
75
- * talks about the chart it made and then ships no chart is worse than either
76
- * consistent behaviour.
77
- *
78
- * `finalText` is the MODEL's own text for the turn — never Canon's failure
79
- * notice, which is a host diagnostic rather than something the model said, and
80
- * which is delivered whether the turn went silent or not.
81
- */
82
- export declare function isSilentTurnSuppressed(input: {
83
- silenced: boolean;
84
- finalText: string | null | undefined;
85
- precedence?: SilentTurnPrecedence;
86
- }): boolean;
@@ -53,7 +53,8 @@ export type StreamHandler = {
53
53
  * raw consumers that only register `onError` keep the existing behavior.
54
54
  */
55
55
  onReplayExpired?: (payload: ReplayExpiredPayload) => void;
56
- onError?: (error: Error) => void;
56
+ /** `conversationId` names the room when endpoint recovery failed for one. */
57
+ onError?: (error: Error, conversationId?: string) => void;
57
58
  };
58
59
  /** Typed agent event projection; the endpoint owns authentication, SSE and reconnect. */
59
60
  export declare class CanonStream {
@@ -9,7 +9,6 @@ export interface RuntimeCapabilities {
9
9
  supportsRequiresAction: boolean;
10
10
  supportsNonFinalPermanentMessages: boolean;
11
11
  }
12
- export declare const FINAL_MESSAGE_HANDOFF_MS = 750;
13
12
  export interface TurnState {
14
13
  turnId?: string | null;
15
14
  state: TurnLifecycleState;
@@ -23,11 +22,7 @@ export interface TurnState {
23
22
  updatedAt?: number;
24
23
  completedAt?: number | null;
25
24
  }
26
- export declare const DEFAULT_RUNTIME_CAPABILITIES: RuntimeCapabilities;
27
25
  /** The one optional proactive communication capability a runtime may expose. */
28
26
  export interface HostAdmissionActionCapabilities {
29
27
  communicate: boolean;
30
28
  }
31
- export declare const HOST_ADMISSION_ACTION_CAPABILITIES: HostAdmissionActionCapabilities;
32
- export declare const HOST_ADMISSION_ACTIONS_DISABLED: HostAdmissionActionCapabilities;
33
- export declare function normalizeTurnState(value: unknown): TurnState | null;
@@ -22,10 +22,6 @@
22
22
  * Notes for the runtimes that consume this (the guards are per-integration):
23
23
  * - Suppress by CALL SITE, never by `turnSemantics === 'progress'` (D5): the
24
24
  * leading parts of a chunked final carry that semantic and are answer body.
25
- * - `TurnOutputController`'s `mode: 'status'` silences the `/streaming` writes
26
- * but does NOT suppress the trail — blocks still accumulate in memory and
27
- * `getFinalTrail()` still returns them. Gate the trail separately, with
28
- * `shouldPublishTurnTrail`, at every site that attaches it to a final.
29
25
  * - A quiet turn still clears `/streaming` at turn open (a surviving node from
30
26
  * an earlier turn would otherwise strand a stale bubble), still writes
31
27
  * `/turn-state`, and still writes `/typing`. Quiet removes the narration,
@@ -53,12 +49,6 @@ export declare const DEFAULT_TURN_VERBOSITY_BY_CONVERSATION_TYPE: {
53
49
  readonly group: "quiet";
54
50
  readonly unknown: "verbose";
55
51
  };
56
- /**
57
- * Does quiet also drop the margin turnTrail rows on the final?
58
- * Owner ruling 5's open sub-question, answered YES. Named so a veto is a
59
- * one-line flip here rather than a five-host revert.
60
- */
61
- export declare const QUIET_SUPPRESSES_TURN_TRAIL: boolean;
62
52
  /**
63
53
  * Folds every spelling a runtime might hand us onto the three keys the
64
54
  * defaults map has. Accepts a raw string because the value arrives from
@@ -93,5 +83,3 @@ export declare function resolveTurnVerbosity(input: {
93
83
  * `parse(flag) ?? parse(env)`, keeps working.
94
84
  */
95
85
  export declare function parseTurnVerbosityConfig(raw: string | null | undefined): TurnVerbosityConfig | null;
96
- /** Convenience for the trail attach sites; folds the ruling above in. */
97
- export declare function shouldPublishTurnTrail(verbosity: TurnVerbosity): boolean;
@@ -249,36 +249,6 @@ export interface CanonResolveAdmissionResult {
249
249
  admission: ResolvedTargetAdmissionPayload;
250
250
  }
251
251
  export type AgentClientType = SerializedAgentClientType;
252
- export interface ResolvedAdmission {
253
- discoverable: boolean;
254
- inboundPolicy: CommunicationRule;
255
- outboundPolicy?: CommunicationRule;
256
- groupJoinPolicy: CommunicationRule;
257
- }
258
- /** Declares what session controls an agent type supports. */
259
- export interface AgentCapabilities {
260
- supportsModelSwitch: boolean;
261
- supportsPermissionMode: boolean;
262
- /**
263
- * Whether permissionMode can be changed mid-session. When undefined,
264
- * defaults to `supportsPermissionMode` — keep the UI chip non-interactive
265
- * for agents whose approval mode is locked at session creation.
266
- */
267
- supportsRuntimePermissionMode?: boolean;
268
- supportsEffort: boolean;
269
- supportsSessionState: boolean;
270
- supportsInterrupt: boolean;
271
- supportsQueue?: boolean;
272
- supportsInterleave?: boolean;
273
- /**
274
- * Whether the agent can present a plan for approval before executing
275
- * (Mac-app "plan mode"). First-class so clients can advertise/query it
276
- * instead of inferring it from the descriptor's turnModes shape.
277
- */
278
- supportsPlanMode?: boolean;
279
- /** Whether the agent asks the user structured questions (AskUserQuestion-style). */
280
- supportsQuestions?: boolean;
281
- }
282
252
  export interface ModelOption {
283
253
  value: string;
284
254
  label: string;
@@ -553,8 +523,6 @@ export interface RuntimeInfoPayload {
553
523
  notes?: ReadonlyArray<string>;
554
524
  updatedAt?: number;
555
525
  }
556
- /** Capability map keyed by clientType. Add new agent types here. */
557
- export declare const AGENT_CAPABILITIES: Record<AgentClientType, AgentCapabilities>;
558
526
  /** Trusted agent identity & access context, provided by the server */
559
527
  export interface AgentContext {
560
528
  agentId: string;
@@ -578,11 +546,6 @@ export interface AgentContext {
578
546
  clientType?: AgentClientType;
579
547
  defaultBehavior?: ResolvedAgentBehaviorPolicy;
580
548
  }
581
- export interface UpdateAgentProfileOptions {
582
- name?: string;
583
- avatarUrl?: string | null;
584
- description?: string;
585
- }
586
549
  export interface CanonTurnDispatch {
587
550
  kind: 'run_turn' | 'observe_only';
588
551
  reason: string;
@@ -696,25 +659,6 @@ export interface CanonMembershipChange {
696
659
  removedMemberIds: string[];
697
660
  memberCount: number;
698
661
  }
699
- export interface CanonKnownRecentParticipant {
700
- id: string;
701
- name: string;
702
- userType: 'human' | 'ai_agent' | 'unknown';
703
- isOwner: boolean;
704
- isSelf: boolean;
705
- }
706
- export interface CanonGroupContext {
707
- memberCount: number;
708
- memberIds: string[];
709
- ownerId: string;
710
- ownerName: string;
711
- ownerPresent: boolean;
712
- knownRecentParticipants: CanonKnownRecentParticipant[];
713
- /** Complete current roster, including participants who have not spoken. */
714
- participants?: CanonKnownRecentParticipant[];
715
- membershipChange?: CanonMembershipChange;
716
- }
717
- export type CanonGroupContextMode = 'initial' | 'membership_change';
718
662
  export interface ConversationUpdatedPayload {
719
663
  conversationId: string;
720
664
  changes: Record<string, unknown>;
@@ -732,52 +676,6 @@ export interface VoiceSessionEventPayload {
732
676
  */
733
677
  targetsMe?: boolean;
734
678
  }
735
- export type CanonStreamEvent = {
736
- type: 'agent.context';
737
- payload: AgentContext;
738
- } | {
739
- type: 'message.created';
740
- payload: MessageCreatedPayload;
741
- } | {
742
- type: 'message.updated';
743
- payload: MessageUpdatedPayload;
744
- } | {
745
- type: 'contact.added';
746
- payload: ContactAddedPayload;
747
- } | {
748
- type: 'contact.removed';
749
- payload: ContactRemovedPayload;
750
- } | {
751
- type: 'typing';
752
- payload: TypingPayload;
753
- } | {
754
- type: 'presence';
755
- payload: PresencePayload;
756
- } | {
757
- type: 'runtime.updated';
758
- payload: RuntimeUpdatedPayload;
759
- } | {
760
- type: 'turn.updated';
761
- payload: TurnUpdatedPayload;
762
- } | {
763
- type: 'runtime.control';
764
- payload: RuntimeControlEventPayload;
765
- } | {
766
- type: 'message.deleted';
767
- payload: {
768
- conversationId: string;
769
- messageId: string;
770
- };
771
- } | {
772
- type: 'conversation.updated';
773
- payload: ConversationUpdatedPayload;
774
- } | {
775
- type: 'voice.session.started';
776
- payload: VoiceSessionEventPayload;
777
- } | {
778
- type: 'voice.session.ended';
779
- payload: VoiceSessionEventPayload;
780
- };
781
679
  export interface SendMessageOptions {
782
680
  messageId?: string;
783
681
  contentType?: 'text' | 'audio' | 'image' | 'video' | 'file' | 'contact_card';
@@ -854,7 +752,6 @@ export interface CreateVoiceSessionOptions {
854
752
  /** Requested call media; the server defaults absent/unknown to 'audio'. */
855
753
  media?: CanonVoiceSessionMedia;
856
754
  }
857
- export type CanonMemoStreamStatus = 'live' | 'finalizing' | 'finalized' | 'aborted';
858
755
  export interface CreateMemoStreamOptions {
859
756
  conversationId: string;
860
757
  /** v1 accepts 'wav' only (byte-append decodable and seekable everywhere). */
@@ -1057,14 +954,6 @@ export interface RegistrationInput {
1057
954
  requestedAgentId?: string;
1058
955
  localRegistrationId?: string;
1059
956
  }
1060
- export interface RegistrationResult {
1061
- status: 'approved' | 'rejected' | 'timeout';
1062
- apiKey?: string;
1063
- agentId?: string;
1064
- agentName?: string;
1065
- requestId?: string;
1066
- pollToken?: string;
1067
- }
1068
957
  export interface RegistrationStatus {
1069
958
  status: 'pending' | 'approving' | 'approved' | 'rejected';
1070
959
  agentName: string;
@@ -1,5 +1,5 @@
1
1
  import { type EndpointMessageGroupInput } from './delivery.js';
2
- import { type PreparedContent, type EndpointEvent, type EndpointOperationReceipt, type EndpointOperationRequest, type EndpointCapabilities, type EndpointPreconditions } from '../backend-contracts/index.js';
2
+ import { type PreparedContent, type EndpointEvent, type EndpointOperationReceipt, type EndpointOperationRequest, type EndpointCapabilities, type EndpointPreconditions, type StartDirectInput, type StartDirectResult } from '../backend-contracts/index.js';
3
3
  import { type EndpointStore } from './store.js';
4
4
  import { type EndpointCredentials, type EndpointTransport } from './transport.js';
5
5
  import { type EndpointInboundConsumer, type EndpointInboundConsumerOptions } from './inbound.js';
@@ -116,6 +116,12 @@ export interface EndpointOptions {
116
116
  hashBytes?: (value: Uint8Array) => Promise<string>;
117
117
  queryIntervalMs?: number;
118
118
  leaseMs?: number;
119
+ /** The admission duty's retry while a member still has no device in an encrypted room (mls-rooms-by-default.md §2.4):
120
+ * the first delay and the most it backs off to. Defaults 30 s and 2 min. */
121
+ mlsAdmissionRetryMs?: {
122
+ initial: number;
123
+ maximum: number;
124
+ };
119
125
  /** Must remain shorter than the server's guaranteed receipt retention. */
120
126
  retryHorizonMs?: number;
121
127
  /** Agent input must pass the same server admission policy as live delivery. */
@@ -154,6 +160,18 @@ export interface Endpoint {
154
160
  subscribe(listener: (operation: EndpointOperation) => void): () => void;
155
161
  query<T>(query: string, parameters?: Record<string, unknown>): Promise<T>;
156
162
  capabilities(): Promise<EndpointCapabilities | null>;
163
+ /** This account's MLS principal ID: its alias, checked against its opening, or its account ID while it has none
164
+ * (mls-dev-groups.md, erasure privacy). */
165
+ mlsPrincipalId(): Promise<string>;
166
+ /** The account an MLS principal in this room's group stands for, by the room's checked openings; undefined when nothing
167
+ * opens it as that type (an erased account's alias). */
168
+ mlsAccountOf(conversationId: string, principal: {
169
+ type: string;
170
+ id: string;
171
+ }): Promise<string | undefined>;
172
+ /** The alias an account of this type carries in this room's group, among `admitted` aliases when given; undefined when
173
+ * none or several do (its account ID while it has none, until step 14c). */
174
+ mlsAliasOf(conversationId: string, accountId: string, type: 'human' | 'ai_agent', admitted?: readonly string[]): Promise<string | undefined>;
157
175
  publish<T = unknown>(action: string, body: Record<string, unknown>): Promise<T>;
158
176
  observeQuery<T>(query: string, parameters: Record<string, unknown>, listener: (value: T) => void, onError?: (error: unknown) => void): () => void;
159
177
  refreshQueries(): void;
@@ -171,6 +189,18 @@ export interface Endpoint {
171
189
  * Return false to defer, or throw a nonretryable EndpointError to retire an
172
190
  * unsent operation. An attempted operation still needs its server receipt. */
173
191
  registerDeliveryGuard(id: string, allow: () => Promise<boolean>): () => void;
192
+ /** Keep a start's opening line that Canon did not store, and send it once the room and the request allow (§2a.13). */
193
+ deferOpener(input: {
194
+ conversationId: string;
195
+ messageId: string;
196
+ text: string;
197
+ requestId?: string | null;
198
+ }): Promise<void>;
199
+ /** Persist the opening line before starting a room; recover the start through its durable receipt. */
200
+ startWithheldOpener(input: Omit<StartDirectInput, 'opener'> & {
201
+ messageId: string;
202
+ text: string;
203
+ }): Promise<StartDirectResult>;
174
204
  applyConversationSnapshot<T extends EndpointConversation>(snapshot: T): Promise<T>;
175
205
  getConversation<T extends EndpointConversation = EndpointConversation>(id: string): Promise<T | null>;
176
206
  applyEvent(event: EndpointEvent): Promise<boolean>;
@@ -29,4 +29,4 @@ export { createMlsDevDeviceCoordinator, type MlsDevDeviceView, type MlsDevProtec
29
29
  export type { MlsDevDeviceClient, MlsDevDeviceClientOptions } from './mls-dev-client.js';
30
30
  export type { MlsDevDeviceTransport, MlsDevDeviceHttpOptions, MlsDevKeyPackageTransport } from './mls-dev-transport.js';
31
31
  export type { MlsDevKeyPackageClient, MlsDevKeyPackageView, MlsDevProtectedKeyPackagePreparer, MlsDevKeyPackagePublicationView, MlsDevKeyPackageClaimView, MlsDevKeyPackageClaimInput } from './mls-dev-key-packages.js';
32
- export type { MlsDevGroupClient, MlsDevVerifiedMessageBinding, MlsDevCurrentAudience, MlsDevGroupView, MlsDevGroupRecoveryFailure, MlsDevProtectedGroupPreparer } from './mls-dev-groups.js';
32
+ export type { MlsDevGroupClient, MlsDevVerifiedMessageBinding, MlsDevCurrentAudience, MlsDevAdmissionHold, MlsDevGroupView, MlsDevGroupRecoveryFailure, MlsDevProtectedGroupPreparer } from './mls-dev-groups.js';
@@ -52,6 +52,8 @@ export interface EndpointMediaFlow {
52
52
  uploadId?: string;
53
53
  generation?: number;
54
54
  attachment?: Record<string, unknown>;
55
+ /** How many times a resend asked Canon to process this encrypted room's failed video again. */
56
+ processingRetries?: number;
55
57
  }>;
56
58
  purpose?: 'prepare';
57
59
  publicationGeneration?: number;
@@ -144,8 +146,11 @@ export interface EndpointMediaPipeline<Source> {
144
146
  descriptor: EndpointMediaDescriptor;
145
147
  }>;
146
148
  }, options?: EndpointMediaSendOptions): Promise<string>;
149
+ /** With `conversationId`, false for an encrypted room (or one whose mode is unknown): its files are prepared on the
150
+ * device and sent without the background handoff, so a caller decides before building their descriptors. */
147
151
  canSendInBackground(options?: {
148
152
  maxProbeWaitMs?: number;
153
+ conversationId?: string;
149
154
  }): Promise<boolean>;
150
155
  resume(id: string, options?: EndpointMediaSendOptions): Promise<string>;
151
156
  resumePending(): Promise<void>;
@@ -1,4 +1,4 @@
1
- import { type MlsDevCredentialReceipt } from '../backend-contracts/index.js';
1
+ import { type MlsDevCredentialReceipt, type MlsEnvironmentId } from '../backend-contracts/index.js';
2
2
  import type { MlsDevDeviceHttpOptions } from './mls-dev-transport.js';
3
3
  export interface MlsDevIssuerKey {
4
4
  readonly keyVersion: string;
@@ -6,13 +6,20 @@ export interface MlsDevIssuerKey {
6
6
  }
7
7
  export interface MlsDevClientConfiguration {
8
8
  readonly version: 1;
9
- readonly environmentId: 'canon-dev-v1';
9
+ /** A declared MLS environment (`MLS_ENVIRONMENT_PROFILES`); every issuer key belongs to it. */
10
+ readonly environmentId: MlsEnvironmentId;
10
11
  readonly enabled: true;
11
- readonly principalIds: readonly string[];
12
+ /**
13
+ * A Dev build's synthetic accounts, the only ones it sets a device up for. A production build lists none: Canon's
14
+ * eligibility (`/endpoint/capabilities`) decides who uses MLS, so an account made after the build can.
15
+ */
16
+ readonly principalIds?: readonly string[];
12
17
  readonly issuerKeys: readonly MlsDevIssuerKey[];
18
+ /** The feed-receipt keys native checks Canon's signed acceptance times with (mls-signed-acceptance.md). */
19
+ readonly receiptKeys: readonly MlsDevIssuerKey[];
13
20
  }
14
- /** Reviewed Dev gateway routes, never values learned from a credential response. */
15
- export declare const MLS_DEV_DEVICE_HTTP_CONFIGURATION: Readonly<MlsDevDeviceHttpOptions>;
21
+ /** An environment's reviewed gateway routes on its own API origin, never values learned from a credential response. */
22
+ export declare function mlsDevDeviceHttpConfiguration(environmentId: MlsEnvironmentId): Readonly<MlsDevDeviceHttpOptions>;
16
23
  /** Public build configuration. Issuer pins must come from reviewed provisioning;
17
24
  * authenticated service responses are not a trust-root distribution channel. */
18
25
  export declare function parseMlsDevClientConfiguration(value: unknown): MlsDevClientConfiguration;
@@ -23,9 +23,14 @@ export interface MlsDevDeviceClient {
23
23
  /** Requires a committed same-key credential proof, but not an issuer receipt. */
24
24
  reconcile(): Promise<MlsDevDeviceView>;
25
25
  /** Resume deliberate provisioning and keep an enrolled device ready, renewing
26
- * within five minutes of expiry. Never creates an unrequested enrollment. */
26
+ * once less than half the credential's lifetime remains, so whatever this
27
+ * device sends stays valid for receivers at least that long. While the
28
+ * current credential is valid, a failed renewal returns it and is retried
29
+ * after a minute. Never creates an unrequested enrollment. */
27
30
  ensureReady(): Promise<MlsDevDeviceView>;
28
31
  }
32
+ /** Whether readiness would renew this registered device: it has no credential, or less than half its lifetime remains. */
33
+ export declare function isMlsDevCredentialRenewalDue(view: MlsDevDeviceView, now: number): boolean;
29
34
  /** Internal factory: the engine owns storage, lifetime, identity and generation. */
30
35
  export interface MlsDevDeviceClientContext {
31
36
  store: EndpointStore;
@@ -33,6 +38,9 @@ export interface MlsDevDeviceClientContext {
33
38
  identity: EndpointResolvedIdentity;
34
39
  installationGeneration: number;
35
40
  }>;
41
+ /** The account's MLS principal ID, its alias (mls-dev-groups.md, erasure privacy), as Canon gave and this device checked
42
+ * it; the account ID itself while it has none. Bindings, credentials and rosters carry it. */
43
+ mlsPrincipalId(): Promise<string>;
36
44
  signal: AbortSignal;
37
45
  assertOpen(): void;
38
46
  assertCurrent(tx: EndpointStoreTransaction): Promise<void>;
@@ -37,6 +37,8 @@ export interface MlsDevKeyPackagePrerequisite {
37
37
  export declare function createMlsDevDeviceCoordinator(input: {
38
38
  store: EndpointStore;
39
39
  binding: MlsDevDeviceBinding;
40
+ /** The endpoint identity's account, when the binding's principal is its alias. */
41
+ accountId?: string;
40
42
  installationGeneration: number;
41
43
  prepareProtected: MlsDevProtectedPreparer;
42
44
  /** Required independent issuer signature/trust validation, outside storage.
@@ -1,9 +1,10 @@
1
- import { type MlsDevEnrollmentPrincipal, type MlsDevDeviceContext, type MlsDevGroupContext, type MlsDevGroupCommand, type MlsDevGroupPreparation, type MlsDevGroupHead, type MlsDevGroupRosterEntry, type MlsDevGroupQuery, type MlsDevGroupQueryResult, MLS_DEV_TEXT_PROTOCOL, type MlsDevGroupFeedQuery, type MlsDevGroupFeedResult, type EndpointOperationReceipt } from '../backend-contracts/index.js';
1
+ import { type MlsDevEnrollmentPrincipal, type MlsDevDeviceContext, type MlsDevGroupContext, type MlsDevGroupCommand, type MlsDevGroupPreparation, type MlsDevGroupHead, type MlsDevGroupRosterEntry, type MlsDevGroupQuery, type MlsDevGroupQueryResult, type MlsDevGroupFeedQuery, type MlsDevGroupFeedResult, type MlsDevTextProtocol, type MlsDevInteractionAnswer, type MlsDevInteractionRequestBody, type MlsDevInteractionWithdrawReason, type EndpointOperationReceipt } from '../backend-contracts/index.js';
2
2
  import type { EndpointOperation } from './engine.js';
3
3
  import type { MlsDevDeviceClientContext, MlsDevDeviceClientOptions } from './mls-dev-client.js';
4
4
  import { type MlsDevKeyPackageClient } from './mls-dev-key-packages.js';
5
5
  import { type EndpointStoreTransaction } from './store.js';
6
6
  import { EndpointError } from './transport.js';
7
+ import { type MlsDevInteractionView } from './mls-dev-interactions.js';
7
8
  import type { EndpointSyncPage, EndpointSyncOptions } from './sync.js';
8
9
  export type MlsDevProtectedGroupPreparer = (identityContext: MlsDevDeviceContext, groupContext: MlsDevGroupContext, command: MlsDevGroupCommand, wrappedIdentity: string, wrappedGroup: string | null, wrappedKeyPackage: string | null) => Promise<MlsDevGroupPreparation>;
9
10
  export interface MlsDevGroupView {
@@ -27,7 +28,7 @@ export declare function isMlsDevGroupRoomRecoveryFailure(error: unknown): error
27
28
  /** Derived exclusively from an atomically committed, native-verified application. */
28
29
  export interface MlsDevVerifiedMessageBinding {
29
30
  readonly version: 1;
30
- readonly protocol: typeof MLS_DEV_TEXT_PROTOCOL;
31
+ readonly protocol: MlsDevTextProtocol;
31
32
  readonly conversationId: string;
32
33
  readonly messageId: string;
33
34
  readonly groupId: string;
@@ -38,11 +39,17 @@ export interface MlsDevVerifiedMessageBinding {
38
39
  readonly senderPrincipal: MlsDevEnrollmentPrincipal;
39
40
  readonly head: MlsDevGroupHead;
40
41
  readonly acceptedAtMs: number;
42
+ /** The account the sender's alias opens to in this room, or the erased sender (mls-dev-groups.md, erasure privacy). */
43
+ readonly senderId: string;
41
44
  }
42
45
  /** An online, fully caught-up audience snapshot for a model turn and its delivery guard. */
46
+ export interface MlsDevAdmissionHold {
47
+ readonly held: boolean;
48
+ readonly waitingPrincipalIds: readonly string[];
49
+ }
43
50
  export interface MlsDevCurrentAudience {
44
51
  readonly version: 1;
45
- readonly protocol: typeof MLS_DEV_TEXT_PROTOCOL;
52
+ readonly protocol: MlsDevTextProtocol;
46
53
  readonly conversationId: string;
47
54
  readonly groupId: string;
48
55
  readonly ownDeviceId: string;
@@ -52,13 +59,36 @@ export interface MlsDevCurrentAudience {
52
59
  readonly roster: readonly MlsDevGroupRosterEntry[];
53
60
  readonly feedOrdinal: number;
54
61
  }
62
+ /** One encrypted card operation in a v2 room (encrypted-interactions.md §2.3): exactly one of `request` (agents),
63
+ * `response` (the responder; a secret's plaintext goes in `secret`, which native seals and the endpoint never stores)
64
+ * or `withdraw` (the requesting device). */
65
+ export interface MlsDevInteractionInput {
66
+ readonly conversationId: string;
67
+ readonly messageId?: string;
68
+ readonly operationId?: string;
69
+ readonly guardId?: string;
70
+ readonly request?: Omit<MlsDevInteractionRequestBody, 'secretKey'>;
71
+ readonly response?: {
72
+ readonly requestId: string;
73
+ readonly agentId: string;
74
+ readonly answer: MlsDevInteractionAnswer;
75
+ } | {
76
+ readonly requestId: string;
77
+ readonly agentId: string;
78
+ readonly secret: string;
79
+ };
80
+ readonly withdraw?: {
81
+ readonly requestId: string;
82
+ readonly reason: MlsDevInteractionWithdrawReason;
83
+ };
84
+ }
55
85
  export interface MlsDevGroupClient {
56
86
  createRoom(input: {
57
87
  conversationId: string;
58
88
  name: string;
59
89
  memberIds: string[];
60
90
  operationId?: string;
61
- protocol?: typeof MLS_DEV_TEXT_PROTOCOL;
91
+ protocol?: MlsDevTextProtocol;
62
92
  }): Promise<EndpointOperation>;
63
93
  create(input: {
64
94
  conversationId: string;
@@ -81,13 +111,29 @@ export interface MlsDevGroupClient {
81
111
  messageId: string;
82
112
  }): Promise<MlsDevVerifiedMessageBinding | undefined>;
83
113
  readCurrentAudience(conversationId: string): Promise<MlsDevCurrentAudience>;
114
+ /** D2 (mls-rooms-by-default.md §2.7): in a room Canon made, the current members with no device in this device's group;
115
+ * while there are any, the room sends nothing. Local state only, as of the last refresh. */
116
+ readAdmissionHold(conversationId: string): Promise<MlsDevAdmissionHold>;
84
117
  assertCurrentAudience(expected: MlsDevCurrentAudience): Promise<void>;
85
118
  readRecoveryFailure(conversationId: string): Promise<MlsDevGroupRecoveryFailure | undefined>;
119
+ /** Encrypts, journals and queues one card operation from this device; never inbox input for anyone. */
120
+ sendInteraction(input: MlsDevInteractionInput): Promise<EndpointOperation>;
121
+ /** The local reduction of one request, with its derived state (the local deadline is authoritative). */
122
+ readInteraction(input: {
123
+ conversationId: string;
124
+ agentId: string;
125
+ requestId: string;
126
+ }): Promise<MlsDevInteractionView | undefined>;
127
+ /** The requester opens its answered secret once, in memory; the one-time key is deleted in the same commit. */
128
+ openSecretAnswer(input: {
129
+ conversationId: string;
130
+ requestId: string;
131
+ }): Promise<string>;
86
132
  }
87
133
  export interface MlsDevGroupBridge {
88
134
  hash(value: string): Promise<string>;
89
135
  hashBytes?(value: Uint8Array): Promise<string>;
90
- resolveProtocol?(conversationId: string): Promise<typeof MLS_DEV_TEXT_PROTOCOL | undefined>;
136
+ resolveProtocol?(conversationId: string): Promise<MlsDevTextProtocol | undefined>;
91
137
  queryFeed?(request: MlsDevGroupFeedQuery): Promise<MlsDevGroupFeedResult>;
92
138
  query(request: MlsDevGroupQuery): Promise<MlsDevGroupQueryResult>;
93
139
  queue(tx: EndpointStoreTransaction, operation: EndpointOperation): Promise<EndpointOperation>;
@@ -95,11 +141,25 @@ export interface MlsDevGroupBridge {
95
141
  afterReceipt(operation: EndpointOperation): Promise<void>;
96
142
  submitted(operation: EndpointOperation): void;
97
143
  lookup(operationId: string, installationId: string): Promise<EndpointOperationReceipt | null>;
144
+ /** Renews this device's credential when due, before an operation captures it. Best effort: the operation's own
145
+ * credential checks still decide. */
146
+ ensureDevice?(): Promise<unknown>;
147
+ /** A Welcome used up one of this device's KeyPackages; called after its commit. */
148
+ keyPackageConsumed?(): void;
149
+ /** A control of this device's settled, accepted or lost to another device's: what waited on it can go on now. A hint
150
+ * announcing the room's change may have come while it was pending, and none may follow (D2 holds the room's sends). */
151
+ controlSettled?(conversationId: string): void;
152
+ /** Reads and applies the room's conversation snapshot from Canon, for openings of members admitted since. */
153
+ readRoom?(conversationId: string): Promise<unknown>;
98
154
  }
99
155
  /** Internal attachment: the engine supplies its existing queue, receipt reducer,
100
156
  * event/recovery intake, store and lifetime. Native work never runs inside tx. */
101
157
  export declare function createMlsDevGroups(options: MlsDevDeviceClientOptions, context: MlsDevDeviceClientContext, keyPackages: MlsDevKeyPackageClient | undefined, bridge: MlsDevGroupBridge): {
102
158
  client: MlsDevGroupClient;
159
+ commitHeldRemoval(conversationId: string): Promise<EndpointOperation | undefined>;
160
+ /** Forwards an encrypted text by re-encryption: this device's own decrypted copy, sent as new text to another
161
+ * encrypted room (mls-payload-v3.md §4). Items and cards are not forwarded yet. */
162
+ forwardText(value: unknown, operationId: string, guardId?: string): Promise<EndpointOperation>;
103
163
  sendText(value: unknown, operationId: string, guardId?: string): Promise<EndpointOperation>;
104
164
  queryTextHistory(conversationId: string, name: string, parameters: Record<string, unknown>): Promise<{
105
165
  messages: Record<string, unknown>[];