@canonmsg/agent-sdk 13.0.3 → 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/README.md +11 -1
- package/dist/chunks/{chunk-ZPBOGOAD.js → chunk-5YKGDUJX.js} +271 -359
- package/dist/chunks/{chunk-XKUG2BQR.js → chunk-6FD6KFQN.js} +528 -167
- package/dist/cli.js +50 -6
- package/dist/index.d.ts +2 -1
- package/dist/index.js +6 -2
- package/dist/internal/core/client.d.ts +1 -215
- package/dist/internal/core/index.d.ts +0 -1
- package/dist/internal/endpoint/completions.d.ts +45 -0
- package/dist/internal/endpoint/engine.d.ts +15 -0
- package/dist/internal/endpoint/index.d.ts +1 -0
- package/dist/internal/endpoint/transient-publisher.d.ts +3 -2
- package/dist/media.js +1 -1
- package/dist/runner/errands.d.ts +2 -2
- package/dist/runner/runner.d.ts +34 -1
- package/dist/runner/wake.d.ts +16 -0
- package/package.json +1 -1
- package/dist/internal/core/completed-output-journal.d.ts +0 -34
package/dist/cli.js
CHANGED
|
@@ -17,13 +17,15 @@ import {
|
|
|
17
17
|
loadInstructions,
|
|
18
18
|
loadMlsDevConfiguration,
|
|
19
19
|
loadRelayConfiguration,
|
|
20
|
+
loadWakeConfiguration,
|
|
21
|
+
parseIdleTimeout,
|
|
20
22
|
queueErrand,
|
|
21
23
|
readRelayCredential,
|
|
22
24
|
relayRunnerHome,
|
|
23
25
|
runMlsDevSetup,
|
|
24
26
|
startRelayChannel,
|
|
25
27
|
writeRelayCredential
|
|
26
|
-
} from "./chunks/chunk-
|
|
28
|
+
} from "./chunks/chunk-6FD6KFQN.js";
|
|
27
29
|
import {
|
|
28
30
|
assertPrivateHome,
|
|
29
31
|
runnerLockName
|
|
@@ -38,7 +40,7 @@ import {
|
|
|
38
40
|
resolveCanonRuntimeConnection,
|
|
39
41
|
runCli,
|
|
40
42
|
verifyCanonRuntimeConnection
|
|
41
|
-
} from "./chunks/chunk-
|
|
43
|
+
} from "./chunks/chunk-5YKGDUJX.js";
|
|
42
44
|
import "./chunks/chunk-YJUPKU47.js";
|
|
43
45
|
import "./chunks/chunk-YHDDOADK.js";
|
|
44
46
|
import {
|
|
@@ -56,10 +58,10 @@ var RUNNER_VERSION = readCliPackageVersion(import.meta.url);
|
|
|
56
58
|
var RUNNER_CLIENT = isCanonClientVersion(RUNNER_VERSION) ? { kind: "runner", version: RUNNER_VERSION } : void 0;
|
|
57
59
|
function once(handler) {
|
|
58
60
|
let called = false;
|
|
59
|
-
return (
|
|
61
|
+
return (...args) => {
|
|
60
62
|
if (!called) {
|
|
61
63
|
called = true;
|
|
62
|
-
handler(
|
|
64
|
+
handler(...args);
|
|
63
65
|
}
|
|
64
66
|
};
|
|
65
67
|
}
|
|
@@ -97,6 +99,14 @@ command also takes --mls-dev-config <path>, an operator's own custody instead. W
|
|
|
97
99
|
of these, the agent refuses every room, and where Canon encrypts every new conversation
|
|
98
100
|
it does not start.
|
|
99
101
|
|
|
102
|
+
Waking and sleeping: code, claude, codex and acp also take [--wake-config <path> |
|
|
103
|
+
--wake-off] [--idle-timeout <duration>]. With --wake-config the agent registers, at
|
|
104
|
+
each start, a public HTTPS callback for up to 32 rooms; Canon POSTs it a signed,
|
|
105
|
+
content-free hint when a person types or a message arrives there, so the host can
|
|
106
|
+
start (or resume) the agent. With --idle-timeout the agent stops and exits 0 once it
|
|
107
|
+
has had nothing to do for that long: no turn, no input, no errand, nothing Canon has
|
|
108
|
+
yet to accept. Nothing is lost while it is stopped; it answers once it starts again.
|
|
109
|
+
|
|
100
110
|
Team rooms (an owner's agents working together): claude, codex and acp also take
|
|
101
111
|
[--instructions <file>] [--trust-agent <agentId>]...; every run command takes
|
|
102
112
|
[--agent-turn-cap <n>] [--mention-alias <name>]....
|
|
@@ -174,6 +184,17 @@ Flags:
|
|
|
174
184
|
$CANON_HOME/relay. The relay serves only encrypted rooms,
|
|
175
185
|
which are then not end-to-end encrypted to that agent. It sets
|
|
176
186
|
up the relay's device with that credential.
|
|
187
|
+
--wake-config <path> Register the agent's wake callback at start: a private JSON file
|
|
188
|
+
(0600, owned by you, not a link) {"version": 1, "callbackUrl":
|
|
189
|
+
"https://...", "secret": "whsec_<base64 of 32 random bytes>",
|
|
190
|
+
"conversationIds": [up to 32 room ids]}. Canon checks the URL
|
|
191
|
+
with a signed challenge first; the agent does not start if
|
|
192
|
+
that fails. Without the flag a registration is left as it is.
|
|
193
|
+
--wake-off Remove the agent's wake callback at start.
|
|
194
|
+
--idle-timeout <d> Stop and exit 0 after this long with nothing to do: whole
|
|
195
|
+
seconds, or 90s, 10m, 1h. Typing in a room does not reach the
|
|
196
|
+
agent: a host that also receives typing hints decides itself
|
|
197
|
+
whether to keep the agent awake for them.
|
|
177
198
|
--mls-dev-config <p> An operator's own MLS configuration, instead of the device the
|
|
178
199
|
runner keeps itself: an absolute path to a private JSON file
|
|
179
200
|
with the environment's issuer pins and the custody helper (no
|
|
@@ -263,6 +284,16 @@ async function main() {
|
|
|
263
284
|
if (values["guest-mode"] !== void 0 && values["unguarded-guests"]) throw new UsageError("--guest-mode and --unguarded-guests are alternatives.");
|
|
264
285
|
const team = teamOptions(values);
|
|
265
286
|
if (values.driver === "connector" && values["allow-session-for-destructive"]) throw new UsageError("--allow-session-for-destructive goes with a driver that asks.");
|
|
287
|
+
if (values.driver === "connector" && (values["wake-config"] !== void 0 || values["wake-off"] || values["idle-timeout"] !== void 0)) {
|
|
288
|
+
throw new UsageError("--wake-config, --wake-off and --idle-timeout go with an agent's own key, not --driver connector.");
|
|
289
|
+
}
|
|
290
|
+
if (values["wake-config"] !== void 0 && values["wake-off"]) throw new UsageError("--wake-config and --wake-off are alternatives.");
|
|
291
|
+
let idleTimeoutMs;
|
|
292
|
+
try {
|
|
293
|
+
idleTimeoutMs = values["idle-timeout"] !== void 0 ? parseIdleTimeout(values["idle-timeout"]) : void 0;
|
|
294
|
+
} catch (error) {
|
|
295
|
+
throw new UsageError(error.message);
|
|
296
|
+
}
|
|
266
297
|
if (values.driver === "connector") return runRelay(values, team);
|
|
267
298
|
const permissionMode = values["permission-mode"];
|
|
268
299
|
if (permissionMode !== void 0 && !PERMISSION_MODES.includes(permissionMode)) {
|
|
@@ -278,6 +309,7 @@ async function main() {
|
|
|
278
309
|
const trustedAgents = values["trust-agent"] ?? [];
|
|
279
310
|
if (trustedAgents.some((id) => !/^[\w.:-]{1,200}$/.test(id))) throw new UsageError("--trust-agent takes an agent id.");
|
|
280
311
|
const instructions = values.instructions !== void 0 ? await loadInstructions(resolve(values.instructions)) : void 0;
|
|
312
|
+
const wake = values["wake-off"] ? null : values["wake-config"] !== void 0 ? await loadWakeConfiguration(resolve(values["wake-config"])) : void 0;
|
|
281
313
|
const { environmentId, home, profile, apiKey } = await settings(values);
|
|
282
314
|
const mls = await mlsDevice(values, environmentId, home);
|
|
283
315
|
const baseUrl = process.env.CANON_BASE_URL || profile?.baseUrl;
|
|
@@ -335,6 +367,15 @@ async function main() {
|
|
|
335
367
|
...trustedAgents.length ? { trustedAgents } : {},
|
|
336
368
|
...values["allow-session-for-destructive"] ? { sessionApprovalForDestructive: true } : {},
|
|
337
369
|
...RUNNER_CLIENT ? { client: RUNNER_CLIENT } : {},
|
|
370
|
+
...wake !== void 0 ? { wake } : {},
|
|
371
|
+
// Idle: a clean stop and exit 0, so a supervisor that restarts only on failure leaves the agent stopped until it is woken.
|
|
372
|
+
...idleTimeoutMs !== void 0 ? { idleTimeoutMs, onIdle: once(() => {
|
|
373
|
+
console.error(`canon-agent: nothing to do for ${values["idle-timeout"]}; stopping.`);
|
|
374
|
+
runner.stop().then(() => process.exit(0), (error) => {
|
|
375
|
+
console.error(`canon-agent: ${error instanceof Error ? error.message : String(error)}`);
|
|
376
|
+
process.exit(1);
|
|
377
|
+
});
|
|
378
|
+
}) } : {},
|
|
338
379
|
onFatal: once((error) => {
|
|
339
380
|
console.error(`canon-agent: ${error.message}`);
|
|
340
381
|
void runner.stop().catch(() => void 0).finally(() => process.exit(1));
|
|
@@ -347,7 +388,7 @@ async function main() {
|
|
|
347
388
|
await runner.stop().catch(() => void 0);
|
|
348
389
|
throw error;
|
|
349
390
|
}
|
|
350
|
-
console.error(`canon-agent: running the ${values.driver} driver in ${environmentId}. Ctrl-C stops it.`);
|
|
391
|
+
console.error(`canon-agent: running the ${values.driver} driver in ${environmentId}. Ctrl-C stops it${idleTimeoutMs !== void 0 ? `, and it stops itself after ${values["idle-timeout"]} with nothing to do` : ""}.`);
|
|
351
392
|
}
|
|
352
393
|
__name(main, "main");
|
|
353
394
|
async function runRelay(values, team) {
|
|
@@ -478,7 +519,10 @@ function parse() {
|
|
|
478
519
|
why: { type: "string" },
|
|
479
520
|
origin: { type: "string" },
|
|
480
521
|
follow: { type: "boolean" },
|
|
481
|
-
cancel: { type: "string" }
|
|
522
|
+
cancel: { type: "string" },
|
|
523
|
+
"wake-config": { type: "string" },
|
|
524
|
+
"wake-off": { type: "boolean" },
|
|
525
|
+
"idle-timeout": { type: "string" }
|
|
482
526
|
}
|
|
483
527
|
});
|
|
484
528
|
}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
export { createRunner, runtimeDescriptor } from './runner/runner.js';
|
|
2
|
-
export type { Runner, RunnerOptions } from './runner/runner.js';
|
|
2
|
+
export type { Runner, RunnerActivity, RunnerOptions } from './runner/runner.js';
|
|
3
|
+
export { loadWakeConfiguration, parseWakeConfiguration } from './runner/wake.js';
|
|
3
4
|
export { ConnectorRelayError, DriverSessionError } from './runner/types.js';
|
|
4
5
|
export { loadMlsDevConfiguration, MLS_SETUP_ACTIONS, mlsDevRoomPackageId, runMlsDevSetup } from './runner/mls.js';
|
|
5
6
|
export type { MlsSetupAction, RunnerMlsOptions } from './runner/mls.js';
|
package/dist/index.js
CHANGED
|
@@ -18,13 +18,15 @@ import {
|
|
|
18
18
|
loadClaudeQuery,
|
|
19
19
|
loadMlsDevConfiguration,
|
|
20
20
|
loadRelayConfiguration,
|
|
21
|
+
loadWakeConfiguration,
|
|
21
22
|
managedMlsDevice,
|
|
22
23
|
mlsDevRoomPackageId,
|
|
24
|
+
parseWakeConfiguration,
|
|
23
25
|
queueErrand,
|
|
24
26
|
runMlsDevSetup,
|
|
25
27
|
runtimeDescriptor,
|
|
26
28
|
startRelayChannel
|
|
27
|
-
} from "./chunks/chunk-
|
|
29
|
+
} from "./chunks/chunk-6FD6KFQN.js";
|
|
28
30
|
import "./chunks/chunk-DTAWEQCM.js";
|
|
29
31
|
import {
|
|
30
32
|
CanonApiError,
|
|
@@ -50,7 +52,7 @@ import {
|
|
|
50
52
|
toAnthropicImageBlock,
|
|
51
53
|
toAnthropicImageBlocksWithinBudget,
|
|
52
54
|
uploadMediaFile
|
|
53
|
-
} from "./chunks/chunk-
|
|
55
|
+
} from "./chunks/chunk-5YKGDUJX.js";
|
|
54
56
|
import "./chunks/chunk-YJUPKU47.js";
|
|
55
57
|
import "./chunks/chunk-YHDDOADK.js";
|
|
56
58
|
import "./chunks/chunk-5WPAB5MB.js";
|
|
@@ -88,11 +90,13 @@ export {
|
|
|
88
90
|
loadClaudeQuery,
|
|
89
91
|
loadMlsDevConfiguration,
|
|
90
92
|
loadRelayConfiguration,
|
|
93
|
+
loadWakeConfiguration,
|
|
91
94
|
managedMlsDevice,
|
|
92
95
|
materializeAttachment,
|
|
93
96
|
materializeMessageMedia,
|
|
94
97
|
materializeReplyContextMedia,
|
|
95
98
|
mlsDevRoomPackageId,
|
|
99
|
+
parseWakeConfiguration,
|
|
96
100
|
queueErrand,
|
|
97
101
|
resolveAttachmentMimeType,
|
|
98
102
|
resumeRegistration,
|
|
@@ -1,11 +1,6 @@
|
|
|
1
1
|
import type { AgentWakeConfiguration } from '../backend-contracts/index.js';
|
|
2
|
-
import { type CanonMessage, type CanonConversation, type
|
|
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,8 +1,9 @@
|
|
|
1
1
|
import type { Endpoint } from './engine.js';
|
|
2
2
|
/** Transient writes are coalesced here; they never enter the durable outbox. */
|
|
3
3
|
export declare function createEndpointTransientPublisher(endpoint: Pick<Endpoint, 'publish'>, clock?: () => number): {
|
|
4
|
-
|
|
5
|
-
|
|
4
|
+
/** A keystroke in the composer wakes the room's agents: once per burst of typing (a 3 s pause ends one), and every 10 s
|
|
5
|
+
* of it. The hint carries no content; typing itself never leaves the device. */
|
|
6
|
+
prewarmAgents(conversationId: string): void;
|
|
6
7
|
setPresence(state: "online" | "offline" | "hidden"): void;
|
|
7
8
|
close(): void;
|
|
8
9
|
};
|
package/dist/media.js
CHANGED
|
@@ -18,7 +18,7 @@ import {
|
|
|
18
18
|
toAnthropicImageBlock,
|
|
19
19
|
toAnthropicImageBlocksWithinBudget,
|
|
20
20
|
uploadMediaFile
|
|
21
|
-
} from "./chunks/chunk-
|
|
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";
|
package/dist/runner/errands.d.ts
CHANGED
|
@@ -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
|
|
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.
|
package/dist/runner/runner.d.ts
CHANGED
|
@@ -68,16 +68,49 @@ export interface RunnerOptions {
|
|
|
68
68
|
sessionApprovalForDestructive?: boolean;
|
|
69
69
|
/** How long running turns may finish on shutdown before they are aborted (default 10 s). */
|
|
70
70
|
shutdownGraceMs?: number;
|
|
71
|
+
/**
|
|
72
|
+
* Idle (agent-wake.md): `onIdle` is called once the runner has been idle (`activity().idle`) for this long, in ms, and
|
|
73
|
+
* again only after new activity and another idle period. The runner does nothing else about it: the host decides, as the
|
|
74
|
+
* CLI's --idle-timeout stops and exits, or a hosting platform suspends the agent's machine until Canon's wake callback.
|
|
75
|
+
*/
|
|
76
|
+
idleTimeoutMs?: number;
|
|
77
|
+
/** Idle: called with the activity that showed it; it never names a room, message or content. */
|
|
78
|
+
onIdle?(activity: RunnerActivity): void;
|
|
71
79
|
/** Never receives prompt or reply text. */
|
|
72
80
|
log?: (line: string) => void;
|
|
73
81
|
}
|
|
82
|
+
/**
|
|
83
|
+
* What the runner has in hand, for a host that stops or suspends an idle agent (agent-wake.md). Counts only. Idle is all
|
|
84
|
+
* of them 0: once stopped or suspended, the agent loses nothing (input waits in Canon and in its inbox) but answers only
|
|
85
|
+
* when Canon's wake callback, or its host, starts it again.
|
|
86
|
+
*/
|
|
87
|
+
export interface RunnerActivity {
|
|
88
|
+
idle: boolean;
|
|
89
|
+
/** When the runner last had something to do (epoch ms), or when it started. */
|
|
90
|
+
lastActiveAt: number;
|
|
91
|
+
/** Turns running or starting, errand turns, restart recovery and New session resets included. */
|
|
92
|
+
turns: number;
|
|
93
|
+
/** Input waiting for a turn: in the inbox, being admitted, or queued behind a running turn (whose own input is in `turns`). */
|
|
94
|
+
inputs: number;
|
|
95
|
+
/** Errands waiting for their turn. */
|
|
96
|
+
errands: number;
|
|
97
|
+
/** In-flight proactive/relay calls plus operations Canon has not answered, including replies, cards and group changes. */
|
|
98
|
+
outbound: number;
|
|
99
|
+
}
|
|
74
100
|
export interface Runner {
|
|
75
101
|
/** Connects and starts taking input; resolves once listening is set up. */
|
|
76
102
|
start(): Promise<void>;
|
|
77
103
|
/** Stops intake, releases unsubmitted input, lets running turns finish within the shutdown grace. */
|
|
78
104
|
stop(): Promise<void>;
|
|
79
|
-
/**
|
|
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
|
+
*/
|
|
80
111
|
communicate(input: CommunicateInput): Promise<CommunicateResult>;
|
|
112
|
+
/** What the runner has in hand now, for a host's idle policy (agent-wake.md). Only between start and stop. */
|
|
113
|
+
activity(): Promise<RunnerActivity>;
|
|
81
114
|
/**
|
|
82
115
|
* Relay mode (§11.6): an encrypted room's history as this device verified it and Canon accepted it, newest first, cut
|
|
83
116
|
* to the channel's response budget. `deadline` (epoch ms, default the channel's answer budget) bounds the read.
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { AgentWakeConfiguration } from '../internal/backend-contracts/index.js';
|
|
2
|
+
/**
|
|
3
|
+
* A wake callback's signing secret: `whsec_` and the standard base64 (padded) of 32 to 64 random bytes. Canon takes at
|
|
4
|
+
* least 32 for a wake callback, and a receiver such as Agent Platform's `/wake/:bindingId` at most 64, padded.
|
|
5
|
+
*/
|
|
6
|
+
export declare function isWakeSecret(value: unknown): value is string;
|
|
7
|
+
/** The same checks Canon makes before it sends the callback its verification challenge; Canon checks again. */
|
|
8
|
+
export declare function parseWakeConfiguration(value: unknown): AgentWakeConfiguration;
|
|
9
|
+
/**
|
|
10
|
+
* `--wake-config <path>` (agent-wake.md): the agent's signed wake callback. A private JSON file (0600, owned by this user,
|
|
11
|
+
* one name, no links; on Windows only this user, SYSTEM and Administrators may reach it and its folder), since it holds
|
|
12
|
+
* the callback's signing secret: `{ "version": 1, "callbackUrl", "secret", "conversationIds" }`. Its text is never logged.
|
|
13
|
+
*/
|
|
14
|
+
export declare function loadWakeConfiguration(path: string): Promise<AgentWakeConfiguration>;
|
|
15
|
+
/** `--idle-timeout`: whole seconds, or a number with `s`, `m` or `h`; at least one second. Returns milliseconds. */
|
|
16
|
+
export declare function parseIdleTimeout(value: string): number;
|