@canonmsg/agent-sdk 11.2.1 → 12.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.
Files changed (188) hide show
  1. package/README.md +171 -536
  2. package/dist/chunks/chunk-6VK4UZHJ.js +2806 -0
  3. package/dist/chunks/chunk-FPQFTTND.js +4899 -0
  4. package/dist/chunks/chunk-OLJ7H4E2.js +14705 -0
  5. package/dist/chunks/mls-crypto-NZDNSPAO.js +10 -0
  6. package/dist/cli.js +198 -0
  7. package/dist/drivers/claude.d.ts +36 -0
  8. package/dist/drivers/code.d.ts +18 -0
  9. package/dist/drivers/codex.d.ts +37 -0
  10. package/dist/index.d.ts +12 -25
  11. package/dist/index.js +69 -13
  12. package/dist/internal/backend-contracts/agentBehaviorPolicy.d.ts +122 -0
  13. package/dist/internal/backend-contracts/agentDirectory.d.ts +32 -0
  14. package/dist/internal/backend-contracts/agentOrigin.d.ts +23 -0
  15. package/dist/internal/backend-contracts/agentSearch.d.ts +17 -0
  16. package/dist/internal/backend-contracts/api-origins.generated.d.ts +4 -0
  17. package/dist/internal/backend-contracts/apiErrors.d.ts +1 -0
  18. package/dist/internal/backend-contracts/artifactActions.d.ts +159 -0
  19. package/dist/internal/backend-contracts/artifacts.d.ts +386 -0
  20. package/dist/internal/backend-contracts/communication.d.ts +131 -0
  21. package/dist/internal/backend-contracts/conversationMembership.d.ts +28 -0
  22. package/dist/internal/backend-contracts/deliveryObservation.d.ts +23 -0
  23. package/dist/internal/backend-contracts/diffRedaction.d.ts +6 -0
  24. package/dist/internal/backend-contracts/endpoint-unread.d.ts +4 -0
  25. package/dist/internal/backend-contracts/endpoint.d.ts +103 -0
  26. package/dist/internal/backend-contracts/endpointContentPolicy.d.ts +37 -0
  27. package/dist/internal/backend-contracts/environment.d.ts +20 -0
  28. package/dist/internal/backend-contracts/externalInbound.d.ts +24 -0
  29. package/dist/internal/backend-contracts/firestoreValues.d.ts +9 -0
  30. package/dist/internal/backend-contracts/index.d.ts +48 -0
  31. package/dist/internal/backend-contracts/media-url.d.ts +6 -0
  32. package/dist/internal/backend-contracts/media.d.ts +51 -0
  33. package/dist/internal/backend-contracts/mediaDelivery.d.ts +46 -0
  34. package/dist/internal/backend-contracts/mediaTransferProtocol.d.ts +17 -0
  35. package/dist/internal/backend-contracts/membershipChange.d.ts +21 -0
  36. package/dist/internal/backend-contracts/message.d.ts +86 -0
  37. package/dist/internal/backend-contracts/messageText.d.ts +6 -0
  38. package/dist/internal/backend-contracts/mlsDevApplication.d.ts +73 -0
  39. package/dist/internal/backend-contracts/mlsDevCredential.d.ts +75 -0
  40. package/dist/internal/backend-contracts/mlsDevCredentialReconciliation.d.ts +45 -0
  41. package/dist/internal/backend-contracts/mlsDevDeviceCustody.d.ts +51 -0
  42. package/dist/internal/backend-contracts/mlsDevEnrollment.d.ts +74 -0
  43. package/dist/internal/backend-contracts/mlsDevGroup.d.ts +197 -0
  44. package/dist/internal/backend-contracts/mlsDevGroupFeed.d.ts +47 -0
  45. package/dist/internal/backend-contracts/mlsDevKeyPackage.d.ts +42 -0
  46. package/dist/internal/backend-contracts/mlsDevKeyPackages.d.ts +55 -0
  47. package/dist/internal/backend-contracts/moderation.d.ts +7 -0
  48. package/dist/internal/backend-contracts/plaintextProcessors.d.ts +63 -0
  49. package/dist/internal/backend-contracts/preparedContent.d.ts +54 -0
  50. package/dist/internal/backend-contracts/replyAuthority.d.ts +14 -0
  51. package/dist/internal/backend-contracts/runtimeCardFields.d.ts +66 -0
  52. package/dist/internal/backend-contracts/runtimeCardStorage.d.ts +3 -0
  53. package/dist/internal/backend-contracts/runtimeDescriptor.d.ts +88 -0
  54. package/dist/internal/backend-contracts/selfContext.d.ts +9 -0
  55. package/dist/internal/backend-contracts/turnProtocol.d.ts +43 -0
  56. package/dist/internal/backend-contracts/verbContract.d.ts +848 -0
  57. package/dist/internal/backend-contracts/verbSchemas.d.ts +1707 -0
  58. package/dist/internal/backend-contracts/verbWire.d.ts +493 -0
  59. package/dist/internal/backend-contracts/webAuth.d.ts +8 -0
  60. package/dist/internal/backend-contracts/workSessions.d.ts +205 -0
  61. package/dist/internal/core/agent-profiles.d.ts +69 -0
  62. package/dist/internal/core/agent-resolver.d.ts +49 -0
  63. package/dist/internal/core/agent-session.d.ts +12 -0
  64. package/dist/internal/core/approval-format.d.ts +26 -0
  65. package/dist/internal/core/approval-manager.d.ts +43 -0
  66. package/dist/internal/core/approval-types.d.ts +74 -0
  67. package/dist/internal/core/artifacts.d.ts +262 -0
  68. package/dist/internal/core/attached-native-session.d.ts +174 -0
  69. package/dist/internal/core/attached-session-file-store.d.ts +3 -0
  70. package/dist/internal/core/base-url.d.ts +1 -0
  71. package/dist/internal/core/cli-metadata.d.ts +13 -0
  72. package/dist/internal/core/client.d.ts +486 -0
  73. package/dist/internal/core/completed-output-journal.d.ts +39 -0
  74. package/dist/internal/core/constants.d.ts +4 -0
  75. package/dist/internal/core/control-poller.d.ts +221 -0
  76. package/dist/internal/core/endpoint-client.d.ts +43 -0
  77. package/dist/internal/core/exclusive-json-file-store.d.ts +7 -0
  78. package/dist/internal/core/execution-environment-mode.d.ts +8 -0
  79. package/dist/internal/core/execution-environment.d.ts +55 -0
  80. package/dist/internal/core/gifs.d.ts +35 -0
  81. package/dist/internal/core/group-context.d.ts +25 -0
  82. package/dist/internal/core/host-runtime.d.ts +257 -0
  83. package/dist/internal/core/inbound-frame.d.ts +64 -0
  84. package/dist/internal/core/index.d.ts +107 -0
  85. package/dist/internal/core/local-runtime-catalog.d.ts +131 -0
  86. package/dist/internal/core/message-format.d.ts +13 -0
  87. package/dist/internal/core/native-session-interaction.d.ts +44 -0
  88. package/dist/internal/core/node-media.d.ts +6 -0
  89. package/dist/internal/core/policy.d.ts +2 -0
  90. package/dist/internal/core/provenance.d.ts +31 -0
  91. package/dist/internal/core/registration-cli.d.ts +40 -0
  92. package/dist/internal/core/registration-profile.d.ts +10 -0
  93. package/dist/internal/core/registration-session.d.ts +55 -0
  94. package/dist/internal/core/registration.d.ts +21 -0
  95. package/dist/internal/core/retry.d.ts +122 -0
  96. package/dist/internal/core/rtdb-rest.d.ts +145 -0
  97. package/dist/internal/core/runtime-cards.d.ts +331 -0
  98. package/dist/internal/core/runtime-descriptor.d.ts +75 -0
  99. package/dist/internal/core/runtime-endpoints.d.ts +26 -0
  100. package/dist/internal/core/runtime-heartbeat.d.ts +29 -0
  101. package/dist/internal/core/runtime-presentation.d.ts +35 -0
  102. package/dist/internal/core/runtime-request-manager.d.ts +284 -0
  103. package/dist/internal/core/runtime-state-publisher.d.ts +42 -0
  104. package/dist/internal/core/self-context.d.ts +61 -0
  105. package/dist/internal/core/silent-turn.d.ts +86 -0
  106. package/dist/internal/core/stream.d.ts +77 -0
  107. package/dist/internal/core/turn-output-controller.d.ts +69 -0
  108. package/dist/internal/core/turn-protocol.d.ts +33 -0
  109. package/dist/internal/core/turn-verbosity.d.ts +97 -0
  110. package/dist/internal/core/types.d.ts +1075 -0
  111. package/dist/internal/core/typing-status-publisher.d.ts +14 -0
  112. package/dist/internal/core/unified-diff.d.ts +35 -0
  113. package/dist/internal/core/work-session-provider.d.ts +29 -0
  114. package/dist/internal/core/workspace-discovery.d.ts +17 -0
  115. package/dist/internal/endpoint/artifact-images.d.ts +60 -0
  116. package/dist/internal/endpoint/artifact-reducer.d.ts +35 -0
  117. package/dist/internal/endpoint/artifact-views.d.ts +113 -0
  118. package/dist/internal/endpoint/artifacts.d.ts +75 -0
  119. package/dist/internal/endpoint/delivery.d.ts +47 -0
  120. package/dist/internal/endpoint/engine.d.ts +219 -0
  121. package/dist/internal/endpoint/ephemeral.d.ts +8 -0
  122. package/dist/internal/endpoint/events.d.ts +32 -0
  123. package/dist/internal/endpoint/external-inbound.d.ts +36 -0
  124. package/dist/internal/endpoint/handoff.d.ts +50 -0
  125. package/dist/internal/endpoint/history.d.ts +22 -0
  126. package/dist/internal/endpoint/image-generation-errors.d.ts +2 -0
  127. package/dist/internal/endpoint/inbound.d.ts +29 -0
  128. package/dist/internal/endpoint/index.d.ts +32 -0
  129. package/dist/internal/endpoint/media.d.ts +172 -0
  130. package/dist/internal/endpoint/migration.d.ts +50 -0
  131. package/dist/internal/endpoint/mls-crypto.d.ts +25 -0
  132. package/dist/internal/endpoint/mls-dev-client.d.ts +44 -0
  133. package/dist/internal/endpoint/mls-dev-device.d.ts +67 -0
  134. package/dist/internal/endpoint/mls-dev-groups.d.ts +114 -0
  135. package/dist/internal/endpoint/mls-dev-key-package-service.d.ts +33 -0
  136. package/dist/internal/endpoint/mls-dev-key-packages.d.ts +42 -0
  137. package/dist/internal/endpoint/mls-dev-transport.d.ts +37 -0
  138. package/dist/internal/endpoint/node-mls-custody-protocol.d.ts +24 -0
  139. package/dist/internal/endpoint/node-mls-custody.d.ts +15 -0
  140. package/dist/internal/endpoint/node.d.ts +7 -0
  141. package/dist/internal/endpoint/observe-query.d.ts +17 -0
  142. package/dist/internal/endpoint/portable-node-mls-custody.d.ts +23 -0
  143. package/dist/internal/endpoint/queue.d.ts +22 -0
  144. package/dist/internal/endpoint/recovery.d.ts +27 -0
  145. package/dist/internal/endpoint/retention.d.ts +7 -0
  146. package/dist/internal/endpoint/store.d.ts +22 -0
  147. package/dist/internal/endpoint/sync.d.ts +33 -0
  148. package/dist/internal/endpoint/transient-publisher.d.ts +8 -0
  149. package/dist/internal/endpoint/transport.d.ts +58 -0
  150. package/dist/media.d.ts +1 -1
  151. package/dist/media.js +42 -541
  152. package/dist/runner/runner.d.ts +37 -0
  153. package/dist/runner/types.d.ts +168 -0
  154. package/package.json +18 -5
  155. package/dist/attached-session.d.ts +0 -58
  156. package/dist/attached-session.js +0 -638
  157. package/dist/bounded-file-read.d.ts +0 -14
  158. package/dist/bounded-file-read.js +0 -34
  159. package/dist/canon-agent.d.ts +0 -236
  160. package/dist/canon-agent.js +0 -2531
  161. package/dist/debouncer.d.ts +0 -18
  162. package/dist/debouncer.js +0 -133
  163. package/dist/inbound-handoff.d.ts +0 -6
  164. package/dist/inbound-handoff.js +0 -17
  165. package/dist/managed-session-host.d.ts +0 -27
  166. package/dist/managed-session-host.js +0 -195
  167. package/dist/managed-session-setup.d.ts +0 -99
  168. package/dist/managed-session-setup.js +0 -234
  169. package/dist/realtime.d.ts +0 -62
  170. package/dist/realtime.js +0 -193
  171. package/dist/runtime-card.d.ts +0 -48
  172. package/dist/runtime-card.js +0 -64
  173. package/dist/session-manager.d.ts +0 -77
  174. package/dist/session-manager.js +0 -285
  175. package/dist/turn-streaming-request.d.ts +0 -17
  176. package/dist/turn-streaming-request.js +0 -22
  177. package/dist/turn-verbosity-option.d.ts +0 -33
  178. package/dist/turn-verbosity-option.js +0 -23
  179. package/dist/types.d.ts +0 -387
  180. package/dist/types.js +0 -1
  181. package/dist/work-session-coordination.d.ts +0 -21
  182. package/dist/work-session-coordination.js +0 -53
  183. package/dist/work-session-host.d.ts +0 -31
  184. package/dist/work-session-host.js +0 -617
  185. package/dist/work-session-interactions.d.ts +0 -12
  186. package/dist/work-session-interactions.js +0 -173
  187. package/dist/work-session-state.d.ts +0 -36
  188. package/dist/work-session-state.js +0 -62
@@ -0,0 +1,221 @@
1
+ /**
2
+ * Shared RTDB `/control/{conversationId}/{agentId}` channel poller.
3
+ *
4
+ * Four hosts historically implemented this loop independently (agent-sdk,
5
+ * claude-code-plugin, codex-plugin, openclaw-plugin) with duplicated
6
+ * constants and drifting semantics. This class covers the union of their
7
+ * behaviors via configuration so each host can migrate onto one engine:
8
+ *
9
+ * - Keys: `signal` (all) and `primitive` (sdk/openclaw), always read in that
10
+ * order.
11
+ * - Cadence: live endpoint hints with a one-minute reconciliation fallback;
12
+ * disconnected/legacy handles use fixed interval (agent-sdk) or active/idle delays + jitter
13
+ * (claude/codex/openclaw), with the activity probe sampled either at cycle
14
+ * start (claude/codex) or after the poll completes (openclaw).
15
+ * - Dedupe: endpoint revision identity (legacy handles use timestamp), primed
16
+ * either eagerly via {@link ControlChannelPoller.baseline} (sdk/claude/codex)
17
+ * or lazily against the poller start time (openclaw).
18
+ * - Consume: shared endpoint handles acknowledge the observed revision; whether a node is consumed
19
+ * after a handler error is configurable per key, and primitive dedupe
20
+ * entries may be released only on successful consume (agent-sdk).
21
+ *
22
+ * Normalizations shared by every profile (pinned by the characterization
23
+ * tests as the new contract):
24
+ * - Single-flight polling via setTimeout chaining — no overlapping cycles,
25
+ * even where the legacy host used a flat setInterval.
26
+ * - stop()/start() during an in-flight poll can never double-schedule.
27
+ * - A null agent id skips the cycle but keeps the cadence alive.
28
+ * - No added backoff on errors: the next cycle runs at the normal cadence.
29
+ *
30
+ * The poller uses the scoped runtime handle backed by its CanonClient endpoint.
31
+ * Passing the observed value into consume prevents a newer control request
32
+ * from being deleted after an older native handler completes.
33
+ */
34
+ export type ControlSignalType = 'interrupt' | 'stop_and_drop' | 'new_session';
35
+ export type ControlChannelKey = 'signal' | 'primitive';
36
+ /** Minimal scoped RTDB surface; `RTDBClientHandle` satisfies it. */
37
+ export interface ControlChannelRTDB {
38
+ read(path: string): Promise<unknown>;
39
+ write(path: string, data: unknown): Promise<void>;
40
+ /** Shared endpoint handles bind consumption to the exact observed revision. */
41
+ consume?(path: string, observed: unknown): Promise<void>;
42
+ observedRevision?(path: string, observed: unknown): string | undefined;
43
+ /** Shared endpoint hints; legacy handles retain their configured polling cadence. */
44
+ observeControls?(changed: (conversationId?: string) => void, connected: (value: boolean) => void): () => void;
45
+ }
46
+ export interface ControlSignalEvent {
47
+ conversationId: string;
48
+ type: ControlSignalType;
49
+ updatedAt: number;
50
+ raw: Record<string, unknown>;
51
+ }
52
+ export interface ControlPrimitiveEvent {
53
+ conversationId: string;
54
+ requestId: string;
55
+ updatedAt: number;
56
+ value: Record<string, unknown>;
57
+ }
58
+ /**
59
+ * Handlers may return `{ consume: false }` to leave the RTDB node in place
60
+ * while still marking it seen — it will not be re-dispatched for this
61
+ * revision. Returning `{ defer: true }` means "not mine yet": the node
62
+ * is left in place AND stays unseen, so it is re-dispatched on the next cycle
63
+ * — this is how a runtime that registers a handler after polling has started
64
+ * still receives signals observed during the gap. Returning nothing consumes
65
+ * the node after a successful handle. A throw never defers: the node is
66
+ * marked seen (and consumed per `consumeOnError`) so a crashing handler
67
+ * cannot spin on the same request.
68
+ */
69
+ export type ControlHandlerResult = {
70
+ consume?: boolean;
71
+ defer?: boolean;
72
+ } | void;
73
+ export interface ControlSignalHandlerConfig {
74
+ handle(event: ControlSignalEvent): Promise<ControlHandlerResult> | ControlHandlerResult;
75
+ /**
76
+ * Consume the signal node even when the handler throws.
77
+ * agent-sdk/openclaw: true. claude/codex hosts: false (default).
78
+ */
79
+ consumeOnError?: boolean;
80
+ }
81
+ export interface ControlPrimitiveHandlerConfig {
82
+ handle(event: ControlPrimitiveEvent): Promise<ControlHandlerResult> | ControlHandlerResult;
83
+ /** Both primitive hosts consume requests even when the handler throws (default true). */
84
+ consumeOnError?: boolean;
85
+ /**
86
+ * `sequential` handles object entries oldest-first by `updatedAt` (agent-sdk);
87
+ * `parallel` handles all entries concurrently and unsorted (openclaw).
88
+ * Default: `sequential`.
89
+ */
90
+ ordering?: 'sequential' | 'parallel';
91
+ /** Dedupe entry TTL; omitted means entries are remembered forever (openclaw). */
92
+ dedupeTtlMs?: number;
93
+ /** Oldest dedupe entries are evicted beyond this cap (agent-sdk: 1000). */
94
+ dedupeMaxEntries?: number;
95
+ /**
96
+ * Release the dedupe entry once the request node is successfully consumed,
97
+ * so a lingering node (failed consume) stays suppressed until TTL expiry
98
+ * while cleared requests free their slot immediately (agent-sdk). Default false.
99
+ */
100
+ releaseDedupeOnConsume?: boolean;
101
+ /**
102
+ * Consume entries whose value is not a plain object instead of leaving them
103
+ * untouched. openclaw: true (normalize-fail → consume); agent-sdk: false.
104
+ */
105
+ consumeInvalidEntries?: boolean;
106
+ /**
107
+ * Skip (but still consume) requests stamped before the poller started
108
+ * (openclaw replay guard). Default false.
109
+ */
110
+ skipStaleBeforeStart?: boolean;
111
+ }
112
+ export type ControlPollerCadence = {
113
+ /** Flat interval between cycle completions (agent-sdk: 2000ms). */
114
+ kind: 'fixed';
115
+ intervalMs: number;
116
+ } | {
117
+ /** Active/idle delays + jitter (claude/codex/openclaw: 2000/10000 + [0,1000)). */
118
+ kind: 'adaptive';
119
+ activeMs: number;
120
+ idleMs: number;
121
+ jitterMs: number;
122
+ hasActiveWork: () => boolean;
123
+ /**
124
+ * When the activity probe is sampled for the post-cycle delay:
125
+ * claude/codex sample before the poll runs (`cycle-start`, default);
126
+ * openclaw samples after the poll completes (`cycle-end`).
127
+ */
128
+ activitySample?: 'cycle-start' | 'cycle-end';
129
+ };
130
+ export interface ControlPollerError {
131
+ scope: 'read' | 'consume' | 'handler' | 'poll';
132
+ key?: ControlChannelKey;
133
+ conversationId?: string;
134
+ requestId?: string;
135
+ error: unknown;
136
+ }
137
+ export interface ControlChannelPollerOptions {
138
+ /** Scoped RTDB handle — the poller never touches the module-global default client. */
139
+ rtdb: ControlChannelRTDB;
140
+ /** Static agent id, or a getter for hosts whose id can become unavailable. */
141
+ agentId: string | (() => string | null);
142
+ /** Live conversation scope, snapshotted at the start of every cycle. */
143
+ conversationIds: () => Iterable<string>;
144
+ cadence: ControlPollerCadence;
145
+ /**
146
+ * Run the first cycle immediately on start (claude/codex/openclaw).
147
+ * `false` waits one cadence delay first (agent-sdk setInterval semantics).
148
+ * Default true.
149
+ */
150
+ pollOnStart?: boolean;
151
+ /**
152
+ * `sequential` polls conversations one at a time (claude/codex);
153
+ * `parallel` polls them concurrently (agent-sdk/openclaw). Default `sequential`.
154
+ */
155
+ conversationConcurrency?: 'sequential' | 'parallel';
156
+ /**
157
+ * Lazily prime signal dedupe against the poller start time on first
158
+ * sighting instead of requiring an eager {@link ControlChannelPoller.baseline}
159
+ * pass (openclaw). Default false.
160
+ */
161
+ lazyBaselineFromStart?: boolean;
162
+ handlers: {
163
+ signal?: ControlSignalHandlerConfig;
164
+ primitive?: ControlPrimitiveHandlerConfig;
165
+ };
166
+ onError?: (error: ControlPollerError) => void;
167
+ /** Injectable jitter source (default Math.random). */
168
+ random?: () => number;
169
+ /** Injectable clock (default Date.now). */
170
+ now?: () => number;
171
+ }
172
+ export declare class ControlChannelPoller {
173
+ private readonly options;
174
+ private timer;
175
+ private running;
176
+ private startedAt;
177
+ private connected;
178
+ private unsubscribe?;
179
+ private cycleActive;
180
+ private readonly cycleRetryRooms;
181
+ private readonly retryAt;
182
+ private fullRefresh;
183
+ private nextFullRefreshAt;
184
+ private readonly changedRooms;
185
+ private readonly lastSeenSignal;
186
+ private readonly lastSeenSignalRevision;
187
+ private readonly primitiveDedupe;
188
+ constructor(options: ControlChannelPollerOptions);
189
+ start(): void;
190
+ stop(): void;
191
+ isRunning(): boolean;
192
+ /**
193
+ * Eagerly prime signal dedupe from the current RTDB node without
194
+ * handling them (agent-sdk at connect; claude/codex at session creation).
195
+ */
196
+ baseline(conversationIds: Iterable<string>): Promise<void>;
197
+ /** Run one full poll cycle across the current conversation scope. */
198
+ pollOnce(): Promise<void>;
199
+ private pollRooms;
200
+ private wake;
201
+ private schedule;
202
+ private runCycle;
203
+ private sampleActivity;
204
+ private nextDelayMs;
205
+ private pollConversation;
206
+ private pollSignalKey;
207
+ private pollPrimitiveKey;
208
+ private processPrimitiveEntry;
209
+ private dispatch;
210
+ private readKey;
211
+ private consumeKey;
212
+ private baselineKey;
213
+ private maybeLazyBaseline;
214
+ private prunePrimitiveDedupe;
215
+ private releasePrimitiveDedupe;
216
+ private controlBasePath;
217
+ private resolveAgentId;
218
+ private reportError;
219
+ private random;
220
+ private now;
221
+ }
@@ -0,0 +1,43 @@
1
+ import { createEndpoint, type EndpointMediaBytes, type EndpointMediaPipeline, type MlsDevProtectedPreparer, type MlsDevProtectedKeyPackagePreparer, type MlsDevProtectedGroupPreparer } from '../endpoint/index.js';
2
+ import type { MlsDevClientConfiguration } from '../endpoint/mls-crypto.js';
3
+ export type CanonEndpoint = ReturnType<typeof createEndpoint>;
4
+ /** Operator-owned custody. Keep the same object for every shared endpoint lease. */
5
+ export interface CanonMlsDevCustody {
6
+ prepareProtected: MlsDevProtectedPreparer;
7
+ prepareProtectedKeyPackage: MlsDevProtectedKeyPackagePreparer;
8
+ prepareProtectedGroup: MlsDevProtectedGroupPreparer;
9
+ }
10
+ export interface CanonMlsDevOptions {
11
+ configuration: MlsDevClientConfiguration;
12
+ custody: CanonMlsDevCustody;
13
+ }
14
+ export interface CanonClientEndpointOptions {
15
+ /** Explicit synthetic Dev opt-in; enrollment remains an operator action. */
16
+ mlsDev?: CanonMlsDevOptions;
17
+ /** Inject an operator-controlled store/engine for replicated or ephemeral hosts. */
18
+ endpoint?: CanonEndpoint;
19
+ environmentId?: string;
20
+ principalId?: string;
21
+ streamUrl?: string;
22
+ /** Persistent volume for the engine journal; never use a container temporary directory. */
23
+ stateDirectory?: string;
24
+ mediaDirectory?: string;
25
+ /** Operator inspection/import does not automatically publish queued operations. */
26
+ autoDrain?: boolean;
27
+ /** Replicated cloud hosts supply operator-owned durable byte storage. */
28
+ mediaBytes?: EndpointMediaBytes<string>;
29
+ /** Test seam for the client's out-of-protocol HTTP (identity, profile); production leaves it unset. */
30
+ fetch?: typeof fetch;
31
+ }
32
+ export declare function acquireFileMediaPipeline(endpoint: CanonEndpoint, options: CanonClientEndpointOptions, fetchImpl?: typeof fetch): Promise<EndpointMediaPipeline<string>>;
33
+ /** One protocol owner per account, environment and durable profile in this process. */
34
+ export declare function acquireAgentEndpoint(input: {
35
+ apiKey: string;
36
+ baseUrl: string;
37
+ principalId: string;
38
+ ownershipVersion: number;
39
+ options: CanonClientEndpointOptions;
40
+ }): Promise<{
41
+ endpoint: CanonEndpoint;
42
+ release(): Promise<void>;
43
+ }>;
@@ -0,0 +1,7 @@
1
+ export interface ExclusiveJsonFileStore<T> {
2
+ load(): Promise<T | null>;
3
+ save(value: T): Promise<void>;
4
+ close(): Promise<void>;
5
+ }
6
+ /** Private atomic snapshots guarded by one recoverable process lock. */
7
+ export declare function createExclusiveJsonFileStore<T>(path: string, name?: string): ExclusiveJsonFileStore<T>;
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Browser-safe helpers for Canon execution modes. Separated from
3
+ * `execution-environment.ts` (which pulls in Node-only modules) so both
4
+ * Node hosts and browser/Expo clients can import these primitives.
5
+ */
6
+ export type ExecutionEnvironmentMode = 'worktree' | 'locked';
7
+ export declare const EXECUTION_ENVIRONMENT_MODES: readonly ExecutionEnvironmentMode[];
8
+ export declare function isExecutionEnvironmentMode(value: unknown): value is ExecutionEnvironmentMode;
@@ -0,0 +1,55 @@
1
+ import type { WorkspaceOption, WorkspaceOptionSource } from './types.js';
2
+ import { EXECUTION_ENVIRONMENT_MODES, isExecutionEnvironmentMode, type ExecutionEnvironmentMode } from './execution-environment-mode.js';
3
+ export { EXECUTION_ENVIRONMENT_MODES, isExecutionEnvironmentMode };
4
+ export type { ExecutionEnvironmentMode };
5
+ export interface PreparedExecutionEnvironment {
6
+ cwd: string;
7
+ baseCwd: string;
8
+ mode: ExecutionEnvironmentMode;
9
+ repoRoot?: string;
10
+ branch?: string;
11
+ worktreePath?: string;
12
+ lockPath?: string;
13
+ reason?: string;
14
+ }
15
+ export declare class ExecutionEnvironmentError extends Error {
16
+ readonly userMessage: string;
17
+ constructor(message: string, userMessage?: string);
18
+ }
19
+ interface WorkspaceResolverOption {
20
+ id: string;
21
+ cwd: string;
22
+ }
23
+ export interface ConfiguredWorkspaceOption extends WorkspaceResolverOption {
24
+ label: string;
25
+ description?: string;
26
+ workspaceRootId?: string;
27
+ workspaceRelativePath?: string;
28
+ source?: WorkspaceOptionSource;
29
+ }
30
+ export declare function normalizeOptionalString(value: unknown): string | undefined;
31
+ export declare function isEnabledFlag(value: unknown): boolean;
32
+ export declare function buildConversationEnvironmentKey(conversationId: string, workspaceCwd: string): string;
33
+ export declare function buildWorkspaceOptionId(workspaceCwd: string): string;
34
+ export declare function buildConfiguredWorkspaceOptions(primaryCwd: string, configured: string[]): ConfiguredWorkspaceOption[];
35
+ export declare function buildPublicWorkspaceOptions(workspaceOptions: Array<Pick<ConfiguredWorkspaceOption, 'id' | 'label'> & Partial<Pick<ConfiguredWorkspaceOption, 'description' | 'workspaceRootId' | 'workspaceRelativePath' | 'source'>>>): WorkspaceOption[];
36
+ export declare function resolveConfiguredWorkspaceCwd(input: {
37
+ workspaceOptions: WorkspaceResolverOption[];
38
+ workspaceId?: string;
39
+ defaultCwd: string;
40
+ }): string;
41
+ export declare function buildConversationWorktreeSpec(input: {
42
+ agentId: string;
43
+ conversationId: string;
44
+ workspaceCwd: string;
45
+ }): {
46
+ branch: string;
47
+ worktreePath: string;
48
+ };
49
+ export declare function prepareConversationEnvironment(input: {
50
+ agentId: string;
51
+ conversationId: string;
52
+ workspaceCwd: string;
53
+ allowWorktrees?: boolean;
54
+ }): PreparedExecutionEnvironment;
55
+ export declare function releaseConversationEnvironment(environment: Pick<PreparedExecutionEnvironment, 'lockPath'>): void;
@@ -0,0 +1,35 @@
1
+ import type { MediaAttachment } from './types.js';
2
+ export type GifProvider = 'klipy';
3
+ export interface CanonGifResult {
4
+ id: string;
5
+ title: string;
6
+ description: string | null;
7
+ url: string;
8
+ previewUrl: string;
9
+ width: number | null;
10
+ height: number | null;
11
+ sizeBytes: number | null;
12
+ itemUrl: string;
13
+ provider: GifProvider;
14
+ attributionLabel: string;
15
+ }
16
+ export interface CanonGifSearchResponse {
17
+ results: CanonGifResult[];
18
+ nextCursor: string | null;
19
+ }
20
+ export interface CanonGifSearchOptions {
21
+ query?: string;
22
+ limit?: number;
23
+ cursor?: string | null;
24
+ locale?: string | null;
25
+ }
26
+ export interface CanonGifMetadata {
27
+ provider: GifProvider;
28
+ id: string;
29
+ itemUrl: string;
30
+ title: string;
31
+ previewUrl: string;
32
+ attributionLabel: string;
33
+ }
34
+ export declare function buildGifAttachment(gif: CanonGifResult): MediaAttachment;
35
+ export declare function buildGifMetadata(gif: CanonGifResult): CanonGifMetadata;
@@ -0,0 +1,25 @@
1
+ import type { CanonConversation, CanonGroupContext, CanonGroupContextMode, CanonKnownRecentParticipant, CanonMembershipChange, CanonMessage } from './types.js';
2
+ type MessageLike = {
3
+ senderId?: string | null;
4
+ senderName?: string | null;
5
+ senderType?: CanonMessage['senderType'];
6
+ isOwner?: boolean;
7
+ createdAt?: string | null;
8
+ };
9
+ export declare function diffCanonMemberIds(previousMemberIds: unknown[], nextMemberIds: unknown[]): CanonMembershipChange | null;
10
+ export declare function buildCanonKnownRecentParticipants(input: {
11
+ messages: MessageLike[];
12
+ agentId: string;
13
+ ownerId?: string | null;
14
+ maxParticipants?: number;
15
+ }): CanonKnownRecentParticipant[];
16
+ export declare function buildCanonGroupContext(input: {
17
+ conversation: CanonConversation | null | undefined;
18
+ messages: MessageLike[];
19
+ agentId: string;
20
+ ownerId?: string | null;
21
+ ownerName?: string | null;
22
+ membershipChange?: CanonMembershipChange | null;
23
+ }): CanonGroupContext | undefined;
24
+ export declare function buildCompactGroupContextLines(groupContext: CanonGroupContext, mode: CanonGroupContextMode): string[];
25
+ export {};
@@ -0,0 +1,257 @@
1
+ import { type AgentClientType, type AgentRuntime, type CanonConversation, type CanonGroupContext, type CanonGroupContextMode, type CanonMembershipChange, type CanonMessage, type CanonMessagesPage, type CanonRuntimeProvenance, type MessageCreatedPayload } from './types.js';
2
+ import { type ArtifactContext } from '../backend-contracts/index.js';
3
+ import { type CanonClient } from './client.js';
4
+ import { type ResolvedAgentBehaviorPolicy } from './policy.js';
5
+ import type { RTDBClientHandle } from './rtdb-rest.js';
6
+ import type { CanonInboundPromptOptions } from './inbound-frame.js';
7
+ export interface HostInboundParticipantContext {
8
+ conversationType: CanonConversation['type'] | 'unknown';
9
+ memberCount: number | null;
10
+ senderType: 'human' | 'ai_agent';
11
+ senderName: string;
12
+ isOwner: boolean;
13
+ mentionedAgent: boolean;
14
+ groupContext?: CanonGroupContext;
15
+ groupContextMode?: CanonGroupContextMode;
16
+ recentSenderTypes: Array<'human' | 'ai_agent'>;
17
+ recentHumanCount: number;
18
+ recentAgentCount: number;
19
+ consecutiveAgentTurns: number;
20
+ currentAgentStreakStartedByHuman: boolean;
21
+ }
22
+ export interface AutoReplyDecision {
23
+ allow: boolean;
24
+ reason: string;
25
+ }
26
+ /**
27
+ * Decide whether a coding host should auto-reply to an inbound message.
28
+ * Thin adapter over {@link evaluateParticipationPolicy}; lives here (not in
29
+ * @canonmsg/coding-agent-host) because it needs core's participation-policy
30
+ * engine and the context type above, and coding-agent-host is deliberately
31
+ * dependency-free.
32
+ */
33
+ export declare function decideAutoReply(context: HostInboundParticipantContext, behavior?: ResolvedAgentBehaviorPolicy | null): AutoReplyDecision;
34
+ type HostInboundMessage = {
35
+ id?: string | null;
36
+ senderId?: string | null;
37
+ senderName?: string | null;
38
+ text?: string | null;
39
+ contentType?: CanonMessage['contentType'] | null;
40
+ attachments?: CanonMessage['attachments'];
41
+ senderType?: CanonMessage['senderType'];
42
+ mentions?: string[] | null;
43
+ contactCard?: CanonMessage['contactCard'];
44
+ replyTo?: string | null;
45
+ replyToPosition?: number | null;
46
+ deleted?: boolean | null;
47
+ metadata?: Record<string, unknown>;
48
+ };
49
+ export interface CanonReplyContext {
50
+ /** Earlier message’s references remain quoted context, never the active selection. */
51
+ artifactContext?: ArtifactContext;
52
+ messageId: string;
53
+ senderId?: string | null;
54
+ senderName?: string | null;
55
+ senderType?: CanonMessage['senderType'] | null;
56
+ text?: string | null;
57
+ contentType?: CanonMessage['contentType'] | null;
58
+ attachments?: CanonMessage['attachments'];
59
+ contactCard?: CanonMessage['contactCard'];
60
+ body: string;
61
+ replyToPosition?: number | null;
62
+ found: boolean;
63
+ }
64
+ export declare const CANON_TURN_CONTEXT_SCHEMA_V2: "canon.turn.v2";
65
+ export interface CanonTurnContextAttachmentV2 {
66
+ index: number;
67
+ kind: NonNullable<HostInboundMessage['attachments']>[number]['kind'];
68
+ placeholder: string;
69
+ fileName: string | null;
70
+ mimeType: string | null;
71
+ sizeBytes: number | null;
72
+ width: number | null;
73
+ height: number | null;
74
+ durationMs: number | null;
75
+ }
76
+ export interface CanonTurnContextContactCardV2 {
77
+ userId: string;
78
+ canonContactId: string | null;
79
+ displayName: string;
80
+ userType: NonNullable<HostInboundMessage['contactCard']>['userType'];
81
+ ownerName: string | null;
82
+ about: string | null;
83
+ }
84
+ export interface CanonTurnContextReplyContextV2 {
85
+ artifactContext?: ArtifactContext;
86
+ messageId: string;
87
+ found: boolean;
88
+ senderId: string | null;
89
+ senderName: string | null;
90
+ senderType: CanonMessage['senderType'] | null;
91
+ contentType: CanonMessage['contentType'] | null;
92
+ text: string | null;
93
+ body: string;
94
+ replyToPosition: number | null;
95
+ attachments: CanonTurnContextAttachmentV2[];
96
+ contactCard: CanonTurnContextContactCardV2 | null;
97
+ }
98
+ export interface CanonTurnContextProvenanceV2 {
99
+ sender: {
100
+ id: string | null;
101
+ name: string | null;
102
+ type: HostInboundParticipantContext['senderType'];
103
+ isOwner: boolean;
104
+ };
105
+ mentionedAgent: boolean;
106
+ activeSelfContext: CanonRuntimeProvenance['activeSelfContext'];
107
+ }
108
+ export interface CanonTurnContextBehaviorV2 {
109
+ participationStyle: ResolvedAgentBehaviorPolicy['participation']['style'];
110
+ requireMentionForGroupReplies?: boolean;
111
+ allowAgentToAgent?: boolean;
112
+ allowLongRunningCollaboration?: boolean;
113
+ maxConsecutiveAgentTurns?: number;
114
+ instructions?: string[];
115
+ source?: ResolvedAgentBehaviorPolicy['source'];
116
+ }
117
+ export interface CanonTurnContextParticipationV2 {
118
+ recentRoleSummary?: HostInboundParticipantContext['recentSenderTypes'];
119
+ recentHumanCount?: number;
120
+ recentAgentCount?: number;
121
+ consecutiveAgentTurns?: number;
122
+ currentAgentStreakStartedByHuman?: boolean;
123
+ }
124
+ export interface CanonTurnContextV2 {
125
+ schema: typeof CANON_TURN_CONTEXT_SCHEMA_V2;
126
+ conversation: {
127
+ id: string;
128
+ type: HostInboundParticipantContext['conversationType'];
129
+ memberCount: number | null;
130
+ };
131
+ provenance: CanonTurnContextProvenanceV2;
132
+ behavior?: CanonTurnContextBehaviorV2;
133
+ participation?: CanonTurnContextParticipationV2;
134
+ group?: {
135
+ context: CanonGroupContext;
136
+ mode?: CanonGroupContextMode;
137
+ };
138
+ selfContext?: {
139
+ activeSelfContextId: string | null;
140
+ contexts: NonNullable<MessageCreatedPayload['selfContexts']>;
141
+ };
142
+ replyContext?: CanonTurnContextReplyContextV2;
143
+ session?: {
144
+ lines: string[];
145
+ };
146
+ message: {
147
+ id: string | null;
148
+ contentType: CanonMessage['contentType'] | null;
149
+ renderedContent: string;
150
+ /** Frozen by the sender; independent of the quoted reply target. */
151
+ artifactContext?: ArtifactContext;
152
+ /** One-line state of referenced work as of message arrival, keyed by artifact ID. */
153
+ artifactSummaries?: Record<string, string>;
154
+ attachments?: CanonTurnContextAttachmentV2[];
155
+ contactCard?: CanonTurnContextContactCardV2;
156
+ mentions?: string[];
157
+ replyTo?: string;
158
+ replyToPosition?: number;
159
+ deleted?: true;
160
+ };
161
+ }
162
+ export declare function buildCanonTurnContextV2(input: {
163
+ content: string;
164
+ conversationId: string;
165
+ participantContext: HostInboundParticipantContext;
166
+ behavior?: ResolvedAgentBehaviorPolicy | null;
167
+ selfContexts?: MessageCreatedPayload['selfContexts'];
168
+ activeSelfContextId?: string | null;
169
+ provenance: CanonRuntimeProvenance;
170
+ replyContext?: CanonReplyContext | null;
171
+ sessionContextLines?: string[];
172
+ message?: HostInboundMessage | null;
173
+ /** From `summarizeArtifactReferences`; lines for work the message does not reference are dropped. */
174
+ artifactSummaries?: Record<string, string>;
175
+ }): CanonTurnContextV2;
176
+ export declare function renderCanonTurnBriefPrompt(context: CanonTurnContextV2, options?: CanonInboundPromptOptions): string;
177
+ export declare function buildCanonReplyContextLines(replyContext: CanonReplyContext | null): string[];
178
+ /**
179
+ * Render the **text portion** of an inbound Canon message. Images are
180
+ * referenced by short placeholders — their actual bytes are delivered to the
181
+ * host as native vision/media inputs (Codex `-i <file>`, Anthropic image
182
+ * blocks). URLs are intentionally *not* inlined, since the harness never
183
+ * needs to refetch and earlier `[Image: <url>]` inlining caused vision
184
+ * models to see a string about an image instead of the image itself.
185
+ *
186
+ * `materialized` may be passed so non-image attachments can reference a
187
+ * local path the agent can Read. Without it we fall back to an unadorned
188
+ * placeholder; the vision path still works because image args carry the
189
+ * file path directly.
190
+ */
191
+ export declare function renderCanonHostInboundContent(message: HostInboundMessage, materialized?: ReadonlyArray<{
192
+ kind: 'image' | 'audio' | 'video' | 'file';
193
+ path: string;
194
+ fileName?: string;
195
+ durationMs?: number;
196
+ index: number;
197
+ }>): string;
198
+ export declare function resolveCanonReplyContext(input: {
199
+ message: HostInboundMessage;
200
+ messages?: ReadonlyArray<HostInboundMessage> | null;
201
+ }): CanonReplyContext | null;
202
+ /**
203
+ * Hydrate only an explicit reply target missing from the ordinary history page.
204
+ * The result stays quoted context: never append it to history or inbound work,
205
+ * and never follow the target's own replyTo. The endpoint enforces membership
206
+ * and content projection; unavailable references must not block the new input.
207
+ */
208
+ export declare function hydrateCanonReplyContext(input: {
209
+ client: Pick<CanonClient, 'getMessage'>;
210
+ conversationId: string;
211
+ message: HostInboundMessage;
212
+ messages?: ReadonlyArray<HostInboundMessage> | null;
213
+ }): Promise<CanonReplyContext | null>;
214
+ export declare function buildHydratedInboundContext(input: {
215
+ agentId: string;
216
+ conversationId: string;
217
+ conversation: CanonConversation | null;
218
+ /** Coding hosts must verify membership before acquiring or resuming a session. */
219
+ requireAgentMembership?: boolean;
220
+ page?: CanonMessagesPage | null;
221
+ activeSelfContextId?: string | null;
222
+ selfContexts?: MessageCreatedPayload['selfContexts'];
223
+ provenance?: MessageCreatedPayload['provenance'];
224
+ message: HostInboundMessage;
225
+ senderName: string;
226
+ isOwner: boolean;
227
+ ownerId?: string | null;
228
+ ownerName?: string | null;
229
+ membershipChange?: CanonMembershipChange | null;
230
+ groupContextMode?: CanonGroupContextMode;
231
+ }): {
232
+ participantContext: HostInboundParticipantContext;
233
+ behavior?: ResolvedAgentBehaviorPolicy | null;
234
+ activeSelfContextId: string | null;
235
+ selfContexts: NonNullable<MessageCreatedPayload['selfContexts']>;
236
+ provenance: CanonRuntimeProvenance;
237
+ replyContext: CanonReplyContext | null;
238
+ hydratedFromPage: boolean;
239
+ };
240
+ export declare function publishHostAgentRuntime(agentId: string, clientType: AgentClientType, runtime: AgentRuntime, rtdb: RTDBClientHandle): Promise<void>;
241
+ export declare function publishHostSessionSnapshots(input: {
242
+ conversationIds: string[];
243
+ agentId: string;
244
+ rtdb: RTDBClientHandle;
245
+ clientType: AgentClientType;
246
+ }): Promise<void>;
247
+ export declare function createConversationMetadataLoader(input: {
248
+ client: CanonClient;
249
+ conversationCache: Map<string, CanonConversation>;
250
+ cacheTtlMs?: number;
251
+ }): {
252
+ refreshConversationCache(force?: boolean): Promise<void>;
253
+ getConversationMeta(conversationId: string, options?: {
254
+ refreshIfMemberMissing?: string;
255
+ }): Promise<CanonConversation | null>;
256
+ };
257
+ export {};