@canonmsg/agent-sdk 13.1.0 → 13.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.js CHANGED
@@ -25,7 +25,7 @@ import {
25
25
  runMlsDevSetup,
26
26
  startRelayChannel,
27
27
  writeRelayCredential
28
- } from "./chunks/chunk-IEKVS7AN.js";
28
+ } from "./chunks/chunk-6FD6KFQN.js";
29
29
  import {
30
30
  assertPrivateHome,
31
31
  runnerLockName
@@ -40,7 +40,7 @@ import {
40
40
  resolveCanonRuntimeConnection,
41
41
  runCli,
42
42
  verifyCanonRuntimeConnection
43
- } from "./chunks/chunk-ZPBOGOAD.js";
43
+ } from "./chunks/chunk-5YKGDUJX.js";
44
44
  import "./chunks/chunk-YJUPKU47.js";
45
45
  import "./chunks/chunk-YHDDOADK.js";
46
46
  import {
package/dist/index.js CHANGED
@@ -26,7 +26,7 @@ import {
26
26
  runMlsDevSetup,
27
27
  runtimeDescriptor,
28
28
  startRelayChannel
29
- } from "./chunks/chunk-IEKVS7AN.js";
29
+ } from "./chunks/chunk-6FD6KFQN.js";
30
30
  import "./chunks/chunk-DTAWEQCM.js";
31
31
  import {
32
32
  CanonApiError,
@@ -52,7 +52,7 @@ import {
52
52
  toAnthropicImageBlock,
53
53
  toAnthropicImageBlocksWithinBudget,
54
54
  uploadMediaFile
55
- } from "./chunks/chunk-ZPBOGOAD.js";
55
+ } from "./chunks/chunk-5YKGDUJX.js";
56
56
  import "./chunks/chunk-YJUPKU47.js";
57
57
  import "./chunks/chunk-YHDDOADK.js";
58
58
  import "./chunks/chunk-5WPAB5MB.js";
@@ -1,11 +1,6 @@
1
1
  import type { AgentWakeConfiguration } from '../backend-contracts/index.js';
2
- import { type CanonMessage, type CanonConversation, type CanonUnifiedDiff, type CanonMessagesPage, type AgentContext, type MediaAttachment, type SendMessageOptions, type RegistrationStatus, type AgentOriginDeclaration, type SetRuntimeTurnOptions, type SetStreamingOptions } from './types.js';
3
- import type { RuntimeInputKind } from './runtime-cards.js';
4
- import type { ApprovalNativeRequestMetadata, ApprovalRequestCategory, ApprovalRequestDetail, ApprovalRisk, SessionRule } from './approval-types.js';
5
- import type { RuntimeInputAnswers, RuntimeInputChoice, RuntimeInputNativeMetadata, RuntimeInputQuestion, RuntimeCardNativeMetadata, RuntimeCardV1 } from './runtime-cards.js';
6
- import type { InboundDisposition } from './turn-protocol.js';
2
+ import { type CanonMessage, type CanonConversation, type CanonMessagesPage, type AgentContext, type MediaAttachment, type SendMessageOptions, type RegistrationStatus, type AgentOriginDeclaration, type SetRuntimeTurnOptions } from './types.js';
7
3
  import { type CanonVerbWireRequest, type CanonVerbWireResponse, type CommunicateInput, type CommunicateResult, type DiscoverAgentsInput, type DiscoverAgentsResult } from '../backend-contracts/index.js';
8
- import { type EndpointOperation } from '../endpoint/index.js';
9
4
  import { type CanonClientEndpointOptions, type CanonEndpoint } from './endpoint-client.js';
10
5
  export interface ResumableMediaUploadResult {
11
6
  uploadId: string;
@@ -53,28 +48,6 @@ export declare class CanonClient {
53
48
  }): Promise<{
54
49
  messageId: string;
55
50
  }>;
56
- /** Inspect a trusted reply's durable delivery without rebuilding its body. */
57
- getMessageOperation(conversationId: string, messageId: string, delivery?: {
58
- operationId?: string;
59
- }): Promise<EndpointOperation | undefined>;
60
- /** Core's chunker records all ordered message intents before publishing any part. */
61
- prepareMessageGroup(conversationId: string, messageId: string, parts: Array<{
62
- text: string;
63
- options: SendMessageOptions;
64
- }>, delivery?: {
65
- operationId?: string;
66
- signal?: AbortSignal;
67
- replacesOperationId?: string;
68
- }): Promise<{
69
- id: string;
70
- sendPart(index: number, options?: {
71
- signal?: AbortSignal;
72
- timeoutMs?: number;
73
- }): Promise<{
74
- messageId: string;
75
- }>;
76
- }>;
77
- cancelMessageGroup(id: string): Promise<void>;
78
51
  /**
79
52
  * Execute a canonical verb over the wire contract (canon.verb-wire.v1).
80
53
  * Bindings build the request with projectVerbIntentToWire; the endpoint
@@ -99,13 +72,10 @@ export declare class CanonClient {
99
72
  private startWithheld;
100
73
  blockUser(userId: string): Promise<void>;
101
74
  deleteMessage(conversationId: string, messageId: string): Promise<void>;
102
- updateMessageDisposition(conversationId: string, messageId: string, inboundDisposition: InboundDisposition): Promise<void>;
103
75
  markAsRead(conversationId: string): Promise<void>;
104
76
  react(conversationId: string, messageId: string, emoji: string): Promise<void>;
105
- setStreaming(options: SetStreamingOptions): Promise<void>;
106
77
  clearStreaming(conversationId: string): Promise<void>;
107
78
  setRuntimeTurn(options: SetRuntimeTurnOptions): Promise<void>;
108
- setTyping(conversationId: string, typing: boolean, status?: 'thinking' | 'typing'): Promise<void>;
109
79
  peekRuntimeSignal(conversationId: string): Promise<Record<string, unknown>>;
110
80
  /** Acknowledge exactly the signal observed before the native handler ran. */
111
81
  acknowledgeRuntimeSignal(conversationId: string, signalId: string): Promise<Record<string, unknown>>;
@@ -124,190 +94,6 @@ export declare class CanonClient {
124
94
  mode: 'clear';
125
95
  }): Promise<void>;
126
96
  patchRuntimeStreaming(conversationId: string, patch: Record<string, unknown>): Promise<void>;
127
- createRuntimeInputRequest(options: {
128
- conversationId: string;
129
- inputId: string;
130
- kind: RuntimeInputKind;
131
- expiresAt: number;
132
- title?: string;
133
- prompt?: string;
134
- choices?: RuntimeInputChoice[];
135
- questions?: RuntimeInputQuestion[];
136
- secretName?: string;
137
- native?: RuntimeInputNativeMetadata;
138
- sensitive?: boolean;
139
- responseUserId?: string;
140
- turnId?: string;
141
- }): Promise<{
142
- success: true;
143
- inputId: string;
144
- expiresAt: number;
145
- messageId?: string;
146
- }>;
147
- consumeRuntimeInputResponse(options: {
148
- conversationId: string;
149
- inputId: string;
150
- cancel?: boolean;
151
- }): Promise<{
152
- status: 'pending';
153
- inputId: string;
154
- expiresAt?: number;
155
- } | {
156
- status: 'submitted';
157
- inputId: string;
158
- kind: RuntimeInputKind;
159
- value: string;
160
- answers?: RuntimeInputAnswers;
161
- } | {
162
- status: 'cancelled';
163
- inputId: string;
164
- kind: RuntimeInputKind;
165
- } | {
166
- status: 'timeout';
167
- inputId: string;
168
- kind: RuntimeInputKind;
169
- }>;
170
- createRuntimeApprovalRequest(options: {
171
- conversationId: string;
172
- approvalId?: string;
173
- toolName: string;
174
- toolSummary: string;
175
- expiresAt: number;
176
- responseUserId?: string;
177
- riskLevel?: 'normal' | 'destructive';
178
- risk?: ApprovalRisk;
179
- category?: ApprovalRequestCategory;
180
- runtimeId?: string;
181
- turnId?: string;
182
- native?: ApprovalNativeRequestMetadata;
183
- details?: ApprovalRequestDetail[];
184
- /** File-change preview rendered inline on the approval card. Truncate via truncateUnifiedDiff before sending. */
185
- diff?: CanonUnifiedDiff;
186
- allowSessionRule?: boolean;
187
- }): Promise<{
188
- success: true;
189
- approvalId: string;
190
- expiresAt: number;
191
- messageId?: string;
192
- responseUserId: string;
193
- allowSessionRule: boolean;
194
- }>;
195
- consumeRuntimeApprovalResponse(options: {
196
- conversationId: string;
197
- approvalId: string;
198
- cancel?: boolean;
199
- }): Promise<{
200
- status: 'pending';
201
- approvalId: string;
202
- expiresAt?: number;
203
- } | {
204
- status: 'allow';
205
- approvalId: string;
206
- sessionRule?: SessionRule;
207
- respondedBy?: string;
208
- } | {
209
- status: 'deny';
210
- approvalId: string;
211
- sessionRule?: SessionRule;
212
- respondedBy?: string;
213
- } | {
214
- status: 'timeout';
215
- approvalId: string;
216
- }>;
217
- createRuntimeCardRequest(options: {
218
- conversationId: string;
219
- card: RuntimeCardV1;
220
- cardId?: string;
221
- expiresAt?: number;
222
- responseUserId?: string;
223
- runtimeId?: string;
224
- turnId?: string;
225
- native?: RuntimeCardNativeMetadata;
226
- }): Promise<{
227
- success: true;
228
- cardId: string;
229
- messageId: string;
230
- /** True when the card has actions and a response is pending; false for display cards. */
231
- interactive: boolean;
232
- /** Effective human responder selected by Canon. */
233
- responseUserId?: string;
234
- /** Present only for interactive cards. */
235
- expiresAt?: number;
236
- }>;
237
- consumeRuntimeCardResponse(options: {
238
- conversationId: string;
239
- cardId: string;
240
- cancel?: boolean;
241
- }): Promise<{
242
- status: 'pending';
243
- cardId: string;
244
- expiresAt?: number;
245
- } | {
246
- status: 'submitted';
247
- cardId: string;
248
- actionId?: string;
249
- values?: Record<string, unknown>;
250
- respondedBy?: string;
251
- } | {
252
- status: 'cancelled';
253
- cardId: string;
254
- respondedBy?: string;
255
- } | {
256
- status: 'timeout';
257
- cardId: string;
258
- }>;
259
- /**
260
- * Create a server-owned plan-approval interaction.
261
- *
262
- * Seeds the pending node + attention + runtime-card state and authors the
263
- * `plan_approval` card message, mirroring the other `createRuntime*Request`
264
- * spine methods. Hosts resolve it through `consumeRuntimePlanResponse()` so
265
- * the canonical pending state, rather than a timeline receipt, is authoritative.
266
- */
267
- createRuntimePlanRequest(options: {
268
- conversationId: string;
269
- planId?: string;
270
- title?: string;
271
- summary?: string;
272
- body?: string;
273
- allowedPrompts?: ReadonlyArray<{
274
- tool: string;
275
- prompt: string;
276
- }>;
277
- responseUserId?: string;
278
- turnId?: string;
279
- expiresAt?: number;
280
- }): Promise<{
281
- success: true;
282
- planId: string;
283
- expiresAt: number;
284
- messageId?: string;
285
- interactive: boolean;
286
- }>;
287
- consumeRuntimePlanResponse(options: {
288
- conversationId: string;
289
- planId: string;
290
- cancel?: boolean;
291
- }): Promise<{
292
- status: 'pending';
293
- planId: string;
294
- expiresAt?: number;
295
- } | {
296
- status: 'approve' | 'revise' | 'reject';
297
- planId: string;
298
- feedback?: string;
299
- grantedPrompts?: Array<{
300
- tool: string;
301
- prompt: string;
302
- }>;
303
- receiptId?: string;
304
- } | {
305
- status: 'cancelled';
306
- planId: string;
307
- } | {
308
- status: 'timeout';
309
- planId: string;
310
- }>;
311
97
  updateRuntimeStatus(options: {
312
98
  runtime: string;
313
99
  hostMode?: boolean;
@@ -57,4 +57,3 @@ export { CANON_VERB_NAMES, CANON_VERB_NAMESPACE, CANON_VERBS_SCHEMA_ID, CANON_VE
57
57
  export { DEFAULT_DISCOVER_AGENTS_LIMIT, MAX_DISCOVER_AGENTS_LIMIT, MAX_DISCOVER_AGENTS_QUERY_LENGTH, type CanonAgentDirectoryEntry, type DiscoverAgentsInput, type DiscoverAgentsResult, } from '../backend-contracts/index.js';
58
58
  export { parseDirectConversationSelection, readCommunicationRule, type CommunicateInput, type CommunicateResult, type CommunicationRule, type DirectConversationSelection, type StartDirectInput, type StartDirectResult, } from '../backend-contracts/index.js';
59
59
  export { canonMediaDownloadUrl, sanitizeDownloadFileName, buildMediaContentDisposition, getStoredFileExtension } from '../backend-contracts/index.js';
60
- export * from './completed-output-journal.js';
@@ -0,0 +1,45 @@
1
+ import { type EndpointStore, type EndpointStoreTransaction } from './store.js';
2
+ /**
3
+ * A runtime's finished output, recorded before it is published: a turn's answer, or text a host sends with no turn. A
4
+ * host that dies between the answer and Canon's acceptance publishes exactly that output on restart and never runs the
5
+ * turn again. One record holds the answer, the inputs it answers and the audience it may reach, in the engine's own
6
+ * store, so recording it and settling its inputs once it is durable are each one transaction with the inbox.
7
+ */
8
+ export interface EndpointCompletion<T = unknown> {
9
+ version: 1;
10
+ id: string;
11
+ conversationId: string;
12
+ /** The inbox inputs it answers. They settle with it (`finishCompletion`); an uncertain input that no completion names is an orphan. */
13
+ inputIds: string[];
14
+ /** The audience its publication may reach (an encrypted room's group head, roster and admissions), or null. */
15
+ fence: unknown;
16
+ /** What the runtime answered, as its host records it. */
17
+ output: T;
18
+ createdAt: string;
19
+ }
20
+ /** Completions in the engine's store. Every write checks the current installation, as content writes do. */
21
+ export declare function createCompletions(input: {
22
+ store: EndpointStore;
23
+ ready(): Promise<unknown>;
24
+ assertOpen(): void;
25
+ assertCurrent(tx: EndpointStoreTransaction): Promise<void>;
26
+ /** Settles one inbox input inside the caller's transaction, as `setInboundState` does. */
27
+ settleInbound(tx: EndpointStoreTransaction, id: string, reason: string): Promise<void>;
28
+ }): {
29
+ save(record: EndpointCompletion): Promise<void>;
30
+ get<T>(id: string): Promise<EndpointCompletion<T> | undefined>;
31
+ /** Oldest first. */
32
+ list<T>(): Promise<Array<EndpointCompletion<T>>>;
33
+ /** One record for another, in one step: a Stop's cut keeps only what was already queued. */
34
+ replace(previousId: string, next: EndpointCompletion): Promise<void>;
35
+ /**
36
+ * The output is durable or withdrawn: its record goes, and in the same step `settle`'s inputs settle. An input already
37
+ * settled, or no longer in the inbox, is left as it is.
38
+ */
39
+ finish(id: string, settle?: {
40
+ inputIds: readonly string[];
41
+ reason: string;
42
+ }): Promise<void>;
43
+ /** The input ids every completion names, read inside the caller's transaction. */
44
+ answered(tx: EndpointStoreTransaction): Promise<Set<string>>;
45
+ };
@@ -10,6 +10,7 @@ import { type EndpointRecoveryMigration, type EndpointMigrationReceipt } from '.
10
10
  import { type EndpointBackgroundMediaAdapter, type EndpointMediaBytes, type EndpointMediaPipeline } from './media.js';
11
11
  import { type EndpointOrdering } from './queue.js';
12
12
  import { type EndpointInboundHandoff, type EndpointInboundStartResult } from './handoff.js';
13
+ import { type EndpointCompletion } from './completions.js';
13
14
  import { type ExternalInboundClaim } from './external-inbound.js';
14
15
  import type { EndpointExternalInboundClaimResult, EndpointExternalInboundOutcome } from '../backend-contracts/index.js';
15
16
  import { type MlsDevGroupClient } from './mls-dev-groups.js';
@@ -246,11 +247,25 @@ export interface Endpoint {
246
247
  }): Promise<boolean>;
247
248
  acceptInbound(options: EndpointInboundConsumerOptions): EndpointInboundConsumer;
248
249
  setInboundState(id: string, state: EndpointInboundState, reason?: string): Promise<void>;
250
+ /** `unanswered`: only inputs no completion names (`completions.ts`), read in the same transaction. */
249
251
  listInbound(options?: {
250
252
  states?: EndpointInboundState[];
251
253
  after?: string;
252
254
  limit?: number;
255
+ unanswered?: boolean;
253
256
  }): Promise<EndpointInboundRecord[]>;
257
+ /** A runtime's finished output, recorded before it is published (`completions.ts`). The same record again is a no-op. */
258
+ saveCompletion(record: EndpointCompletion): Promise<void>;
259
+ getCompletion<T = unknown>(id: string): Promise<EndpointCompletion<T> | undefined>;
260
+ /** Every recorded completion, oldest first. */
261
+ listCompletions<T = unknown>(): Promise<Array<EndpointCompletion<T>>>;
262
+ /** One completion for another, in one transaction. */
263
+ replaceCompletion(previousId: string, next: EndpointCompletion): Promise<void>;
264
+ /** The output is durable or withdrawn: the completion goes, and `settle`'s inputs settle, in one transaction. */
265
+ finishCompletion(id: string, settle?: {
266
+ inputIds: readonly string[];
267
+ reason: string;
268
+ }): Promise<void>;
254
269
  discardPending(): Promise<void>;
255
270
  logout(): Promise<void>;
256
271
  close(): Promise<void>;
@@ -1,4 +1,5 @@
1
1
  export * from './engine.js';
2
+ export type { EndpointCompletion } from './completions.js';
2
3
  export * from './store.js';
3
4
  export * from './transport.js';
4
5
  export * from './observe-query.js';
package/dist/media.js CHANGED
@@ -18,7 +18,7 @@ import {
18
18
  toAnthropicImageBlock,
19
19
  toAnthropicImageBlocksWithinBudget,
20
20
  uploadMediaFile
21
- } from "./chunks/chunk-ZPBOGOAD.js";
21
+ } from "./chunks/chunk-5YKGDUJX.js";
22
22
  import "./chunks/chunk-YJUPKU47.js";
23
23
  import "./chunks/chunk-YHDDOADK.js";
24
24
  import "./chunks/chunk-5WPAB5MB.js";
@@ -95,8 +95,8 @@ export declare function awaitErrand(directory: string, command: Pick<ErrandComma
95
95
  accepted: boolean;
96
96
  }>;
97
97
  export interface ErrandHandler {
98
- /** The command was taken already (its record or its journaled output exists): its file is only removed. */
99
- taken(id: string): boolean;
98
+ /** The command was taken already (its record or its saved output exists): its file is only removed. */
99
+ taken(id: string): boolean | Promise<boolean>;
100
100
  /**
101
101
  * The command, or why its file is refused. True once its effect (or refusal) is journaled, so the file may go; false
102
102
  * leaves it for the next scan. A throw is logged once per command and reason, and also leaves it.
@@ -102,7 +102,12 @@ export interface Runner {
102
102
  start(): Promise<void>;
103
103
  /** Stops intake, releases unsubmitted input, lets running turns finish within the shutdown grace. */
104
104
  stop(): Promise<void>;
105
- /** A proactive send outside any turn (cron): the `communicate` tool's handler, under the runner's identity. */
105
+ /**
106
+ * A proactive send outside any turn (cron), under the runner's identity, with the `communicate` tool's input. Text to a
107
+ * conversation is encrypted for the members it has now, journaled first and sent once, even across a restart; a new
108
+ * conversation is founded encrypted by this device. `messageId` makes a retry the same message or start. Other actions
109
+ * go to Canon as they are.
110
+ */
106
111
  communicate(input: CommunicateInput): Promise<CommunicateResult>;
107
112
  /** What the runner has in hand now, for a host's idle policy (agent-wake.md). Only between start and stop. */
108
113
  activity(): Promise<RunnerActivity>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@canonmsg/agent-sdk",
3
- "version": "13.1.0",
3
+ "version": "13.2.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",
@@ -1,34 +0,0 @@
1
- /**
2
- * A runtime's finished turn output, saved before it is published so a host that
3
- * dies between the native result and Canon delivery replays exactly that
4
- * output on restart instead of losing it, and never runs the turn again.
5
- */
6
- export interface CompletedOutputRecordBase {
7
- version: 1;
8
- turnId: string;
9
- conversationId: string;
10
- createdAt: string;
11
- /** Who could read the conversation when the output was produced. */
12
- audience: {
13
- memberIds: string[];
14
- membershipRevision?: number;
15
- } | null;
16
- }
17
- export interface CompletedOutputJournal<T extends CompletedOutputRecordBase> {
18
- /** Durably save a record; saving the identical record again is a no-op, a different one is refused. */
19
- save(record: T): void;
20
- /** Every saved record, oldest first, after recovering writes a crash interrupted. */
21
- list(): T[];
22
- remove(turnId: string): void;
23
- }
24
- /**
25
- * Atomic, fsynced, one file per turn under a folder keyed by `scope` (runtime,
26
- * environment, principal, ownership generation, installation), so a transferred
27
- * agent or another installation never sees these plaintext records.
28
- */
29
- export declare function createCompletedOutputJournal<T extends CompletedOutputRecordBase>(directory: string, scope: unknown, options: {
30
- /** Names the runtime in errors, e.g. `Codex`. */
31
- label: string;
32
- /** Runtime-specific shape check beyond the base fields; false is an invalid record. */
33
- validate?: (record: T) => boolean;
34
- }): CompletedOutputJournal<T>;