@canonmsg/agent-sdk 1.4.1 → 1.5.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 +1 -0
- package/dist/canon-agent.d.ts +5 -0
- package/dist/canon-agent.js +132 -7
- package/dist/debouncer.d.ts +4 -3
- package/dist/debouncer.js +15 -2
- package/dist/index.d.ts +3 -3
- package/dist/index.js +1 -1
- package/dist/realtime.js +1 -1
- package/dist/types.d.ts +32 -2
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -130,6 +130,7 @@ Current rules of thumb:
|
|
|
130
130
|
- `selectionPolicy: 'required_explicit'` means Canon should require the user to make a choice instead of silently inheriting a default
|
|
131
131
|
- `workspaceRoots` and `writableRoots` document allowed roots and let Canon group project choices. Canon still stores the selected concrete `workspaceId`; it does not send arbitrary root-relative paths to generic SDK agents.
|
|
132
132
|
- Publishing a descriptor does not automatically make your SDK agent enforce those controls. If you advertise model, workspace, execution mode, or runtime-native controls, your runtime must actually read and apply the stored config.
|
|
133
|
+
- Message handlers receive `ctx.provenance`, a Canon-computed sender/conversation context for the latest inbound message in the batch. Use it when your runtime wants owner-only tools, group mention policy, or self-context-aware behavior; Canon does not impose a sandbox on SDK agents.
|
|
133
134
|
|
|
134
135
|
## Delivery Modes
|
|
135
136
|
|
package/dist/canon-agent.d.ts
CHANGED
|
@@ -42,6 +42,9 @@ export declare class CanonAgent {
|
|
|
42
42
|
private readonly reachOutInFlight;
|
|
43
43
|
private agentId;
|
|
44
44
|
private agentContext;
|
|
45
|
+
private approvalManager;
|
|
46
|
+
private approvalManagerAgentId;
|
|
47
|
+
private approvalManagerOwnerId;
|
|
45
48
|
private cachedConversationIds;
|
|
46
49
|
private running;
|
|
47
50
|
private runtimeHeartbeatTimer;
|
|
@@ -53,6 +56,8 @@ export declare class CanonAgent {
|
|
|
53
56
|
private readonly conversationMemberIds;
|
|
54
57
|
private readonly pendingMembershipChanges;
|
|
55
58
|
constructor(options: CanonAgentOptions);
|
|
59
|
+
private ensureApprovalManager;
|
|
60
|
+
private filterApprovalReplyMessages;
|
|
56
61
|
on(event: 'message', handler: MessageHandler): void;
|
|
57
62
|
on(event: 'contactRequest', handler: ContactRequestHandler): void;
|
|
58
63
|
on(event: 'contactApproved', handler: ContactRequestHandler): void;
|
package/dist/canon-agent.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { CanonClient, buildCanonGroupContext, createRuntimeStatePublisher, diffCanonMemberIds, FINAL_MESSAGE_HANDOFF_MS, RUNTIME_NEW_SESSION_ACTION, RUNTIME_STOP_ACTION, RUNTIME_STOP_AND_DROP_ACTION, initRTDBAuth, rtdbRead, rtdbWrite, normalizeTurnMetadata, reachOutToCanonContact, resolveCanonReplyContext, resolveMessageActiveSelfContextId, selectActiveSelfContexts, } from '@canonmsg/core';
|
|
1
|
+
import { ApprovalManager, CanonClient, buildCanonGroupContext, createRuntimeStatePublisher, diffCanonMemberIds, FINAL_MESSAGE_HANDOFF_MS, RUNTIME_NEW_SESSION_ACTION, RUNTIME_STOP_ACTION, RUNTIME_STOP_AND_DROP_ACTION, initRTDBAuth, rtdbRead, rtdbWrite, normalizeTurnMetadata, reachOutToCanonContact, resolveCanonReplyContext, resolveMessageActiveSelfContextId, resolveRuntimeProvenance, selectActiveSelfContexts, } from '@canonmsg/core';
|
|
2
2
|
import { randomUUID } from 'node:crypto';
|
|
3
3
|
import { AuthManager } from './auth.js';
|
|
4
4
|
import { Debouncer } from './debouncer.js';
|
|
@@ -205,6 +205,9 @@ export class CanonAgent {
|
|
|
205
205
|
reachOutInFlight = new Map();
|
|
206
206
|
agentId = null;
|
|
207
207
|
agentContext = null;
|
|
208
|
+
approvalManager = null;
|
|
209
|
+
approvalManagerAgentId = null;
|
|
210
|
+
approvalManagerOwnerId = null;
|
|
208
211
|
cachedConversationIds = [];
|
|
209
212
|
running = false;
|
|
210
213
|
runtimeHeartbeatTimer = null;
|
|
@@ -257,6 +260,47 @@ export class CanonAgent {
|
|
|
257
260
|
}
|
|
258
261
|
}
|
|
259
262
|
}
|
|
263
|
+
ensureApprovalManager(agentContext = this.agentContext) {
|
|
264
|
+
const agentId = agentContext?.agentId || this.agentId;
|
|
265
|
+
const ownerId = agentContext?.ownerId;
|
|
266
|
+
if (!agentId || !ownerId)
|
|
267
|
+
return null;
|
|
268
|
+
if (this.approvalManager
|
|
269
|
+
&& this.approvalManagerAgentId === agentId
|
|
270
|
+
&& this.approvalManagerOwnerId === ownerId) {
|
|
271
|
+
return this.approvalManager;
|
|
272
|
+
}
|
|
273
|
+
if (this.approvalManager?.pendingCount) {
|
|
274
|
+
return this.approvalManager;
|
|
275
|
+
}
|
|
276
|
+
this.approvalManager?.dispose();
|
|
277
|
+
this.approvalManager = new ApprovalManager(this.apiClient, agentId, ownerId);
|
|
278
|
+
this.approvalManagerAgentId = agentId;
|
|
279
|
+
this.approvalManagerOwnerId = ownerId;
|
|
280
|
+
return this.approvalManager;
|
|
281
|
+
}
|
|
282
|
+
filterApprovalReplyMessages(conversationId, messages) {
|
|
283
|
+
const manager = this.ensureApprovalManager();
|
|
284
|
+
if (!manager) {
|
|
285
|
+
return messages.filter((message) => {
|
|
286
|
+
const metadata = message.metadata;
|
|
287
|
+
return !(metadata && typeof metadata === 'object' && !Array.isArray(metadata)
|
|
288
|
+
&& metadata.type === 'approval_reply');
|
|
289
|
+
});
|
|
290
|
+
}
|
|
291
|
+
return messages.filter((message) => {
|
|
292
|
+
const metadata = message.metadata;
|
|
293
|
+
const metadataRecord = metadata && typeof metadata === 'object' && !Array.isArray(metadata)
|
|
294
|
+
? metadata
|
|
295
|
+
: null;
|
|
296
|
+
const consumed = manager.handleMessage(conversationId, {
|
|
297
|
+
senderId: message.senderId,
|
|
298
|
+
...(typeof message.text === 'string' ? { text: message.text } : {}),
|
|
299
|
+
...(metadataRecord ? { metadata: metadataRecord } : {}),
|
|
300
|
+
});
|
|
301
|
+
return !consumed && metadataRecord?.type !== 'approval_reply';
|
|
302
|
+
});
|
|
303
|
+
}
|
|
260
304
|
on(event, handler) {
|
|
261
305
|
if (event === 'message') {
|
|
262
306
|
this.handler = handler;
|
|
@@ -411,9 +455,9 @@ export class CanonAgent {
|
|
|
411
455
|
this.agentId = agentId;
|
|
412
456
|
console.log(`[canon-sdk] Authenticated as ${agentId}`);
|
|
413
457
|
// 2. Wire debouncer to handler
|
|
414
|
-
this.debouncer.setCallback(async (conversationId, messages) => {
|
|
458
|
+
this.debouncer.setCallback(async (conversationId, messages, provenanceByMessageId) => {
|
|
415
459
|
this.rememberConversationId(conversationId);
|
|
416
|
-
await this.handleMessages(conversationId, messages);
|
|
460
|
+
await this.handleMessages(conversationId, messages, provenanceByMessageId);
|
|
417
461
|
});
|
|
418
462
|
// 3. Fetch conversations (used for delivery mode + session state)
|
|
419
463
|
let conversations = [];
|
|
@@ -437,6 +481,7 @@ export class CanonAgent {
|
|
|
437
481
|
// 3b. Fetch agent context (identity, owner, access level)
|
|
438
482
|
try {
|
|
439
483
|
this.agentContext = await this.apiClient.getAgentMe();
|
|
484
|
+
this.ensureApprovalManager(this.agentContext);
|
|
440
485
|
}
|
|
441
486
|
catch {
|
|
442
487
|
console.warn('[canon-sdk] Failed to fetch agent context — owner/access info unavailable');
|
|
@@ -462,6 +507,7 @@ export class CanonAgent {
|
|
|
462
507
|
const rtm = new RealtimeManager(this.options.apiKey, this.debouncer, agentId, this.options.streamUrl, this.apiClient);
|
|
463
508
|
rtm.setOnAgentContext((ctx) => {
|
|
464
509
|
this.agentContext = ctx;
|
|
510
|
+
this.ensureApprovalManager(ctx);
|
|
465
511
|
});
|
|
466
512
|
rtm.setContactRequestHandlers({
|
|
467
513
|
onContactRequest: (request) => {
|
|
@@ -950,7 +996,12 @@ export class CanonAgent {
|
|
|
950
996
|
}
|
|
951
997
|
return publisher;
|
|
952
998
|
}
|
|
953
|
-
async handleMessages(conversationId, messages) {
|
|
999
|
+
async handleMessages(conversationId, messages, provenanceByMessageId) {
|
|
1000
|
+
const actionableMessages = this.filterApprovalReplyMessages(conversationId, messages);
|
|
1001
|
+
if (actionableMessages.length === 0) {
|
|
1002
|
+
return;
|
|
1003
|
+
}
|
|
1004
|
+
messages = actionableMessages;
|
|
954
1005
|
if (!this.handler) {
|
|
955
1006
|
console.warn(`[canon-sdk] No message handler registered — messages for ${conversationId} dropped. Call agent.on('message', handler) before starting.`);
|
|
956
1007
|
return;
|
|
@@ -961,14 +1012,14 @@ export class CanonAgent {
|
|
|
961
1012
|
await this.notifyMessageInterrupt(conversationId, abortSignal);
|
|
962
1013
|
if (this.sessionManager) {
|
|
963
1014
|
await this.sessionManager.enqueue(conversationId, messages, async (session, newMessages) => {
|
|
964
|
-
await this.executeHandler(conversationId, newMessages, session);
|
|
1015
|
+
await this.executeHandler(conversationId, newMessages, session, provenanceByMessageId);
|
|
965
1016
|
}, { toFront: shouldInterrupt });
|
|
966
1017
|
}
|
|
967
1018
|
else {
|
|
968
|
-
await this.executeHandler(conversationId, messages);
|
|
1019
|
+
await this.executeHandler(conversationId, messages, undefined, provenanceByMessageId);
|
|
969
1020
|
}
|
|
970
1021
|
}
|
|
971
|
-
async executeHandler(conversationId, messages, session) {
|
|
1022
|
+
async executeHandler(conversationId, messages, session, provenanceByMessageId) {
|
|
972
1023
|
if (!this.handler)
|
|
973
1024
|
return;
|
|
974
1025
|
const turnId = randomUUID();
|
|
@@ -1147,6 +1198,32 @@ export class CanonAgent {
|
|
|
1147
1198
|
inboundPolicy: 'approval-required',
|
|
1148
1199
|
groupJoinPolicy: 'approval-required',
|
|
1149
1200
|
};
|
|
1201
|
+
const provenance = latestMessage
|
|
1202
|
+
? resolveRuntimeProvenance({
|
|
1203
|
+
provenance: provenanceByMessageId?.get(latestMessage.id) ?? null,
|
|
1204
|
+
conversationId,
|
|
1205
|
+
conversationType: conversation.type,
|
|
1206
|
+
memberCount: conversation.memberIds.length,
|
|
1207
|
+
senderId: latestMessage.senderId,
|
|
1208
|
+
senderName: latestMessage.senderName ?? latestMessage.senderId,
|
|
1209
|
+
senderType: latestMessage.senderType,
|
|
1210
|
+
isOwner: latestMessage.isOwner,
|
|
1211
|
+
agentId: agent.agentId,
|
|
1212
|
+
mentions: latestMessage.mentions,
|
|
1213
|
+
activeSelfContextId,
|
|
1214
|
+
selfContexts,
|
|
1215
|
+
})
|
|
1216
|
+
: resolveRuntimeProvenance({
|
|
1217
|
+
conversationId,
|
|
1218
|
+
conversationType: conversation.type,
|
|
1219
|
+
memberCount: conversation.memberIds.length,
|
|
1220
|
+
senderId: '',
|
|
1221
|
+
senderType: 'human',
|
|
1222
|
+
isOwner: false,
|
|
1223
|
+
agentId: agent.agentId,
|
|
1224
|
+
activeSelfContextId,
|
|
1225
|
+
selfContexts,
|
|
1226
|
+
});
|
|
1150
1227
|
if (replyContext?.found && replyContext.attachments?.length) {
|
|
1151
1228
|
try {
|
|
1152
1229
|
const materializedReply = await materializeReplyContextMedia(replyContext, {
|
|
@@ -1194,6 +1271,52 @@ export class CanonAgent {
|
|
|
1194
1271
|
...(options ?? {}),
|
|
1195
1272
|
sourceConversationId: conversationId,
|
|
1196
1273
|
});
|
|
1274
|
+
const requestApproval = async (request) => {
|
|
1275
|
+
throwIfAborted();
|
|
1276
|
+
const manager = this.ensureApprovalManager(agent);
|
|
1277
|
+
if (!manager) {
|
|
1278
|
+
return { decision: 'deny' };
|
|
1279
|
+
}
|
|
1280
|
+
shouldPersistTurnState = true;
|
|
1281
|
+
try {
|
|
1282
|
+
try {
|
|
1283
|
+
await this.apiClient.clearStreaming(conversationId);
|
|
1284
|
+
}
|
|
1285
|
+
catch { }
|
|
1286
|
+
await writeTurn('waiting_input');
|
|
1287
|
+
try {
|
|
1288
|
+
await this.apiClient.setTyping(conversationId, false);
|
|
1289
|
+
}
|
|
1290
|
+
catch { }
|
|
1291
|
+
const result = await manager.requestApproval(conversationId, request.toolName, request.toolInput ?? {}, {
|
|
1292
|
+
riskLevel: request.riskLevel,
|
|
1293
|
+
risk: request.risk,
|
|
1294
|
+
category: request.category,
|
|
1295
|
+
runtimeId: request.runtimeId,
|
|
1296
|
+
turnId: request.turnId ?? turnId,
|
|
1297
|
+
native: request.native,
|
|
1298
|
+
toolSummary: request.toolSummary,
|
|
1299
|
+
details: request.details,
|
|
1300
|
+
ignoreSessionRules: request.ignoreSessionRules,
|
|
1301
|
+
allowSessionRule: request.allowSessionRule,
|
|
1302
|
+
});
|
|
1303
|
+
throwIfAborted();
|
|
1304
|
+
shouldPersistTurnState = false;
|
|
1305
|
+
try {
|
|
1306
|
+
await this.apiClient.setTyping(conversationId, true, 'thinking');
|
|
1307
|
+
}
|
|
1308
|
+
catch { }
|
|
1309
|
+
await setLiveState('thinking', 'Thinking...', 'thinking');
|
|
1310
|
+
return result;
|
|
1311
|
+
}
|
|
1312
|
+
catch (error) {
|
|
1313
|
+
if (abortController.signal.aborted || isAbortLikeError(error)) {
|
|
1314
|
+
throw error;
|
|
1315
|
+
}
|
|
1316
|
+
shouldPersistTurnState = false;
|
|
1317
|
+
return { decision: 'deny' };
|
|
1318
|
+
}
|
|
1319
|
+
};
|
|
1197
1320
|
const uploadFile = (filePath, options) => uploadMediaFile(this.apiClient, conversationId, filePath, options);
|
|
1198
1321
|
const replyWithFile = async (filePath, text = '', options) => {
|
|
1199
1322
|
throwIfAborted();
|
|
@@ -1254,6 +1377,8 @@ export class CanonAgent {
|
|
|
1254
1377
|
agent,
|
|
1255
1378
|
activeSelfContextId,
|
|
1256
1379
|
selfContexts,
|
|
1380
|
+
provenance,
|
|
1381
|
+
requestApproval,
|
|
1257
1382
|
abortSignal: abortController.signal,
|
|
1258
1383
|
media: {
|
|
1259
1384
|
materialize: (message = hydratedMessages[hydratedMessages.length - 1], options) => {
|
package/dist/debouncer.d.ts
CHANGED
|
@@ -1,13 +1,14 @@
|
|
|
1
|
-
import type { CanonMessage } from '@canonmsg/core';
|
|
1
|
+
import type { CanonMessage, CanonRuntimeProvenance } from '@canonmsg/core';
|
|
2
2
|
export declare class Debouncer {
|
|
3
3
|
private debounceMs;
|
|
4
4
|
private pending;
|
|
5
|
+
private provenanceByMessageId;
|
|
5
6
|
private timers;
|
|
6
7
|
private orderedFlags;
|
|
7
8
|
private callback;
|
|
8
9
|
constructor(debounceMs: number);
|
|
9
|
-
setCallback(cb: (conversationId: string, messages: CanonMessage[]) => void): void;
|
|
10
|
-
add(conversationId: string, message: CanonMessage): void;
|
|
10
|
+
setCallback(cb: (conversationId: string, messages: CanonMessage[], provenanceByMessageId: ReadonlyMap<string, CanonRuntimeProvenance>) => void): void;
|
|
11
|
+
add(conversationId: string, message: CanonMessage, provenance?: CanonRuntimeProvenance | null): void;
|
|
11
12
|
private flush;
|
|
12
13
|
destroy(): void;
|
|
13
14
|
}
|
package/dist/debouncer.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
export class Debouncer {
|
|
2
2
|
debounceMs;
|
|
3
3
|
pending = new Map();
|
|
4
|
+
provenanceByMessageId = new Map();
|
|
4
5
|
timers = new Map();
|
|
5
6
|
// Track whether each conversation's pending messages are already in sorted
|
|
6
7
|
// order so we can skip the sort on flush when possible (#10)
|
|
@@ -12,8 +13,11 @@ export class Debouncer {
|
|
|
12
13
|
setCallback(cb) {
|
|
13
14
|
this.callback = cb;
|
|
14
15
|
}
|
|
15
|
-
add(conversationId, message) {
|
|
16
|
+
add(conversationId, message, provenance) {
|
|
16
17
|
const existing = this.pending.get(conversationId) || [];
|
|
18
|
+
if (provenance) {
|
|
19
|
+
this.provenanceByMessageId.set(message.id, provenance);
|
|
20
|
+
}
|
|
17
21
|
// Deduplicate by message ID
|
|
18
22
|
if (!existing.some((m) => m.id === message.id)) {
|
|
19
23
|
if (existing.length === 0) {
|
|
@@ -50,7 +54,15 @@ export class Debouncer {
|
|
|
50
54
|
if (!isOrdered) {
|
|
51
55
|
messages.sort((a, b) => new Date(a.createdAt).getTime() - new Date(b.createdAt).getTime());
|
|
52
56
|
}
|
|
53
|
-
|
|
57
|
+
const provenanceByMessageId = new Map();
|
|
58
|
+
for (const message of messages) {
|
|
59
|
+
const provenance = this.provenanceByMessageId.get(message.id);
|
|
60
|
+
if (provenance) {
|
|
61
|
+
provenanceByMessageId.set(message.id, provenance);
|
|
62
|
+
this.provenanceByMessageId.delete(message.id);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
this.callback(conversationId, messages, provenanceByMessageId);
|
|
54
66
|
}
|
|
55
67
|
}
|
|
56
68
|
destroy() {
|
|
@@ -59,6 +71,7 @@ export class Debouncer {
|
|
|
59
71
|
}
|
|
60
72
|
this.timers.clear();
|
|
61
73
|
this.pending.clear();
|
|
74
|
+
this.provenanceByMessageId.clear();
|
|
62
75
|
this.orderedFlags.clear();
|
|
63
76
|
}
|
|
64
77
|
}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
export { CanonAgent } from './canon-agent.js';
|
|
2
2
|
export type { AgentContactsAPI, AgentUsersAPI } from './canon-agent.js';
|
|
3
|
-
export { CanonApiError, HOST_ADMISSION_ACTION_CAPABILITIES, HOST_ADMISSION_ACTIONS_DISABLED, } from '@canonmsg/core';
|
|
4
|
-
export type { CanonContact, CanonRuntimeActivityItem, CanonRuntimeActivityKind, CanonRuntimeActivityStatus, CanonRuntimeFact, CanonRuntimeFactGroup, CanonResolveAdmissionResult, ContactAddedPayload, ContactCardPayload, ContactRemovedPayload, ContactSource, HostAdmissionActionCapabilities, ResolvedAdmissionState, ResolvedAdmissionTargetSummary, ResolvedTargetAdmissionPayload, } from '@canonmsg/core';
|
|
3
|
+
export { ApprovalManager, buildApprovalOutcome, buildApprovalReply, buildApprovalRequest, CanonApiError, DEFAULT_APPROVAL_CONFIG, generateApprovalId, HOST_ADMISSION_ACTION_CAPABILITIES, HOST_ADMISSION_ACTIONS_DISABLED, parseApprovalReplyMetadata, parseApprovalRequestMetadata, parseSessionRule, parseTextApprovalReply, redactSecrets, } from '@canonmsg/core';
|
|
4
|
+
export type { ApprovalConfig, ApprovalNativeRequestMetadata, ApprovalOutcomeMetadata, ApprovalReplyMetadata, ApprovalRequestCategory, ApprovalRequestDetail, ApprovalRequestMetadata, ApprovalResult, ApprovalRisk, CanonContact, CanonRuntimeActivityItem, CanonRuntimeActivityKind, CanonRuntimeActivityStatus, CanonRuntimeFact, CanonRuntimeFactGroup, CanonResolveAdmissionResult, ContactAddedPayload, ContactCardPayload, ContactRemovedPayload, ContactSource, HostAdmissionActionCapabilities, ResolvedAdmissionState, ResolvedAdmissionTargetSummary, ResolvedTargetAdmissionPayload, SessionRule, } from '@canonmsg/core';
|
|
5
5
|
export { SessionManager } from './session-manager.js';
|
|
6
6
|
export { DEFAULT_MEDIA_CACHE_DIR, getCodexImagePath, getMessageAttachments, inferUploadMimeType, isAnthropicImageAttachment, materializeAttachment, materializeMessageMedia, materializeReplyContextMedia, resolveAttachmentMimeType, sendMediaFileMessage, toAnthropicImageBlock, uploadMediaFile, } from './media.js';
|
|
7
7
|
export type { AnthropicImageBlock, AnthropicImageMimeType, MaterializeMediaOptions, MaterializedCanonAttachment, MaterializedCanonReplyContext, ReplyWithFileOptions, UploadMediaFileOptions, } from './media.js';
|
|
8
8
|
export type { SessionConfig, Session } from './session-manager.js';
|
|
9
9
|
export type { AgentContext, CanonGroupContext, CanonKnownRecentParticipant, CanonMembershipChange, CanonContactRequest, CanonMessage, CanonConversation, CanonReplyContext, CanonSelfContext, SendContextualMessageOptions, SendContextualMessageResult, SendContextualSelfContextInput, SendMessageOptions, CreateConversationOptions, } from '@canonmsg/core';
|
|
10
|
-
export type { CanonAgentOptions, ContactAddedHandler, ContactRemovedHandler, ContactRequestHandler, MessageHandler, MessageHandlerContext, ProgressMessageOptions, ProgressMessageResult, ReachOutOptions, ReachOutResult, RuntimePrimitiveContext, RuntimePrimitiveHandler, RuntimePrimitiveHandlers, SessionInfo, SessionOptions, DeliveryMode, } from './types.js';
|
|
10
|
+
export type { CanonAgentOptions, ContactAddedHandler, ContactRemovedHandler, ContactRequestHandler, MessageHandler, MessageHandlerContext, ProgressMessageOptions, ProgressMessageResult, ReachOutOptions, ReachOutResult, RuntimeApprovalRequest, RuntimePrimitiveContext, RuntimePrimitiveHandler, RuntimePrimitiveHandlers, SessionInfo, SessionOptions, DeliveryMode, } from './types.js';
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
export { CanonAgent } from './canon-agent.js';
|
|
2
|
-
export { CanonApiError, HOST_ADMISSION_ACTION_CAPABILITIES, HOST_ADMISSION_ACTIONS_DISABLED, } from '@canonmsg/core';
|
|
2
|
+
export { ApprovalManager, buildApprovalOutcome, buildApprovalReply, buildApprovalRequest, CanonApiError, DEFAULT_APPROVAL_CONFIG, generateApprovalId, HOST_ADMISSION_ACTION_CAPABILITIES, HOST_ADMISSION_ACTIONS_DISABLED, parseApprovalReplyMetadata, parseApprovalRequestMetadata, parseSessionRule, parseTextApprovalReply, redactSecrets, } from '@canonmsg/core';
|
|
3
3
|
export { SessionManager } from './session-manager.js';
|
|
4
4
|
export { DEFAULT_MEDIA_CACHE_DIR, getCodexImagePath, getMessageAttachments, inferUploadMimeType, isAnthropicImageAttachment, materializeAttachment, materializeMessageMedia, materializeReplyContextMedia, resolveAttachmentMimeType, sendMediaFileMessage, toAnthropicImageBlock, uploadMediaFile, } from './media.js';
|
package/dist/realtime.js
CHANGED
|
@@ -52,7 +52,7 @@ export class RealtimeManager {
|
|
|
52
52
|
...(m.contactCard ? { contactCard: m.contactCard } : {}),
|
|
53
53
|
...(m.metadata ? { metadata: m.metadata } : {}),
|
|
54
54
|
};
|
|
55
|
-
this.debouncer.add(payload.conversationId, message);
|
|
55
|
+
this.debouncer.add(payload.conversationId, message, payload.provenance ?? null);
|
|
56
56
|
},
|
|
57
57
|
onAgentContext: (ctx) => {
|
|
58
58
|
this.onAgentContext?.(ctx);
|
package/dist/types.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
export type { AddMemberResult, AgentClientType, CanonGroupContext, CanonRuntimeActivityItem, CanonRuntimeActivityKind, CanonRuntimeActivityStatus, CanonRuntimeDescriptor, CanonRuntimeFact, CanonRuntimeFactGroup, CanonRuntimePrimitiveId, CanonMessage, CanonConversation, CanonReplyContext, CanonContact, CanonContactRequest, CanonResolveAdmissionResult, ContactAddedPayload, ContactRemovedPayload, ContactSource, AgentContext, ResolvedAdmissionState, ResolvedAdmissionTargetSummary, ResolvedTargetAdmissionPayload, CanonSelfContext, SendContextualMessageOptions, SendContextualMessageResult, SendContextualSelfContextInput, SendMessageOptions, SessionConfig, CreateConversationOptions, TurnLifecycleState, } from '@canonmsg/core';
|
|
2
|
-
import type { AddMemberResult, CanonGroupContext, CanonMessage, CanonConversation, CanonReplyContext, ContactCardPayload, CanonRuntimeActionDispatch, CanonRuntimePrimitiveId, SendMessageOptions, SendContextualSelfContextInput, SessionConfig } from '@canonmsg/core';
|
|
1
|
+
export type { AddMemberResult, AgentClientType, CanonGroupContext, CanonRuntimeActivityItem, CanonRuntimeActivityKind, CanonRuntimeActivityStatus, CanonRuntimeDescriptor, CanonRuntimeFact, CanonRuntimeFactGroup, CanonRuntimePrimitiveId, CanonRuntimeProvenance, CanonMessage, CanonConversation, CanonReplyContext, CanonContact, CanonContactRequest, CanonResolveAdmissionResult, ContactAddedPayload, ContactRemovedPayload, ContactSource, AgentContext, ResolvedAdmissionState, ResolvedAdmissionTargetSummary, ResolvedTargetAdmissionPayload, CanonSelfContext, SendContextualMessageOptions, SendContextualMessageResult, SendContextualSelfContextInput, SendMessageOptions, SessionConfig, CreateConversationOptions, TurnLifecycleState, ApprovalNativeRequestMetadata, ApprovalRequestCategory, ApprovalRequestDetail, ApprovalRequestMetadata, ApprovalRisk, ApprovalReplyMetadata, ApprovalOutcomeMetadata, SessionRule, ApprovalResult, } from '@canonmsg/core';
|
|
2
|
+
import type { AddMemberResult, CanonGroupContext, CanonMessage, CanonConversation, CanonReplyContext, ContactCardPayload, CanonRuntimeActionDispatch, CanonRuntimePrimitiveId, CanonRuntimeProvenance, ApprovalNativeRequestMetadata, ApprovalRequestCategory, ApprovalRequestDetail, ApprovalResult, ApprovalRisk, SendMessageOptions, SendContextualSelfContextInput, SessionConfig } from '@canonmsg/core';
|
|
3
3
|
import type { MaterializeMediaOptions, MaterializedCanonAttachment, ReplyWithFileOptions, UploadMediaFileOptions } from './media.js';
|
|
4
4
|
export interface ProgressMessageOptions extends SendMessageOptions {
|
|
5
5
|
/**
|
|
@@ -34,6 +34,28 @@ export interface TurnController {
|
|
|
34
34
|
setTool: (text: string) => Promise<void>;
|
|
35
35
|
setWaitingInput: (text?: string) => Promise<void>;
|
|
36
36
|
}
|
|
37
|
+
export interface RuntimeApprovalRequest {
|
|
38
|
+
/** Native runtime/tool/action name that is asking for permission. */
|
|
39
|
+
toolName: string;
|
|
40
|
+
/** Structured native input. Raw values are summarized/redacted before storage. */
|
|
41
|
+
toolInput?: Record<string, unknown>;
|
|
42
|
+
/** Optional pre-redacted summary when a runtime already has user-facing copy. */
|
|
43
|
+
toolSummary?: string;
|
|
44
|
+
category?: ApprovalRequestCategory;
|
|
45
|
+
risk?: ApprovalRisk;
|
|
46
|
+
riskLevel?: 'normal' | 'destructive';
|
|
47
|
+
runtimeId?: string;
|
|
48
|
+
turnId?: string;
|
|
49
|
+
native?: ApprovalNativeRequestMetadata;
|
|
50
|
+
details?: ApprovalRequestDetail[];
|
|
51
|
+
/**
|
|
52
|
+
* Ignore in-memory session rules for this approval request. Useful when the
|
|
53
|
+
* action was triggered by someone other than the agent owner.
|
|
54
|
+
*/
|
|
55
|
+
ignoreSessionRules?: boolean;
|
|
56
|
+
/** Whether an approval reply may set an in-memory session rule. */
|
|
57
|
+
allowSessionRule?: boolean;
|
|
58
|
+
}
|
|
37
59
|
export interface MessageHandlerContext {
|
|
38
60
|
messages: CanonMessage[];
|
|
39
61
|
history: CanonMessage[];
|
|
@@ -79,6 +101,14 @@ export interface MessageHandlerContext {
|
|
|
79
101
|
activeSelfContextId: string | null;
|
|
80
102
|
/** Canon-provided private context explaining this agent's cross-session actions. */
|
|
81
103
|
selfContexts?: import('@canonmsg/core').CanonSelfContext[];
|
|
104
|
+
/** Trusted Canon provenance for the latest inbound message in this handler batch. */
|
|
105
|
+
provenance: CanonRuntimeProvenance;
|
|
106
|
+
/**
|
|
107
|
+
* Ask the conversation owner to approve a native runtime action. This only
|
|
108
|
+
* renders Canon's inline approval card; runtimes must explicitly wait for
|
|
109
|
+
* and enforce the returned decision in their own approval hook.
|
|
110
|
+
*/
|
|
111
|
+
requestApproval: (request: RuntimeApprovalRequest) => Promise<ApprovalResult>;
|
|
82
112
|
/** Canon-managed local media access for the current conversation. */
|
|
83
113
|
media: {
|
|
84
114
|
materialize: (message?: CanonMessage, options?: Omit<MaterializeMediaOptions, 'agentId' | 'conversationId' | 'messageId'>) => Promise<MaterializedCanonAttachment[]>;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@canonmsg/agent-sdk",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.5.0",
|
|
4
4
|
"description": "Canon Agent SDK — build AI agents that participate in Canon conversations",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
"node": ">=18.0.0"
|
|
29
29
|
},
|
|
30
30
|
"dependencies": {
|
|
31
|
-
"@canonmsg/core": "^0.
|
|
31
|
+
"@canonmsg/core": "^0.19.0"
|
|
32
32
|
},
|
|
33
33
|
"publishConfig": {
|
|
34
34
|
"access": "public"
|