@canonmsg/agent-sdk 1.5.3 → 1.5.5
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/canon-agent.d.ts +1 -0
- package/dist/canon-agent.js +167 -2
- package/dist/index.d.ts +2 -2
- package/dist/types.d.ts +29 -2
- package/package.json +2 -2
package/dist/canon-agent.d.ts
CHANGED
|
@@ -140,6 +140,7 @@ export declare class CanonAgent {
|
|
|
140
140
|
private publishAcceptedRuntimeSignal;
|
|
141
141
|
private abortActiveTurns;
|
|
142
142
|
private resolveBatchDeliveryIntent;
|
|
143
|
+
private markQueuedMessagesAccepted;
|
|
143
144
|
private notifyMessageInterrupt;
|
|
144
145
|
private createRuntimeStatePublisher;
|
|
145
146
|
private requireRuntimeStatePublisher;
|
package/dist/canon-agent.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
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';
|
|
1
|
+
import { ApprovalManager, CanonClient, buildCanonGroupContext, createRuntimeStatePublisher, diffCanonMemberIds, FINAL_MESSAGE_HANDOFF_MS, RUNTIME_NEW_SESSION_ACTION, RUNTIME_STOP_ACTION, RUNTIME_STOP_AND_DROP_ACTION, buildRuntimeInputOutcome, buildRuntimeInputRequest, 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';
|
|
@@ -7,6 +7,9 @@ import { SessionManager } from './session-manager.js';
|
|
|
7
7
|
const AGENT_RUNTIME_HEARTBEAT_MS = 30_000;
|
|
8
8
|
const RUNTIME_PRIMITIVE_DEDUPE_TTL_MS = 5 * 60 * 1000;
|
|
9
9
|
const RUNTIME_PRIMITIVE_DEDUPE_MAX = 1_000;
|
|
10
|
+
const DEFAULT_RUNTIME_INPUT_TIMEOUT_MS = 5 * 60_000;
|
|
11
|
+
const RUNTIME_INPUT_POLL_MS = 1_000;
|
|
12
|
+
const RUNTIME_INPUT_ID_PATTERN = /^[A-Za-z0-9_.:-]{1,160}$/;
|
|
10
13
|
const SDK_RUNTIME_CAPABILITIES = {
|
|
11
14
|
supportsInterrupt: false,
|
|
12
15
|
supportsInputInterrupt: false,
|
|
@@ -125,6 +128,24 @@ const STANDARD_PRIMITIVE_COMMANDS = {
|
|
|
125
128
|
function sleep(ms) {
|
|
126
129
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
127
130
|
}
|
|
131
|
+
function sleepWithAbort(ms, signal) {
|
|
132
|
+
if (signal.aborted)
|
|
133
|
+
return Promise.reject(createTurnAbortError());
|
|
134
|
+
return new Promise((resolve, reject) => {
|
|
135
|
+
const timer = setTimeout(resolve, ms);
|
|
136
|
+
signal.addEventListener('abort', () => {
|
|
137
|
+
clearTimeout(timer);
|
|
138
|
+
reject(createTurnAbortError());
|
|
139
|
+
}, { once: true });
|
|
140
|
+
});
|
|
141
|
+
}
|
|
142
|
+
function safeRuntimeInputId(value, kind) {
|
|
143
|
+
const raw = value?.trim() || `${kind}_${randomUUID()}`;
|
|
144
|
+
const normalized = raw.replace(/[.#$\[\]\/\s]+/g, '_').slice(0, 160);
|
|
145
|
+
return RUNTIME_INPUT_ID_PATTERN.test(normalized)
|
|
146
|
+
? normalized
|
|
147
|
+
: `${kind}_${randomUUID()}`;
|
|
148
|
+
}
|
|
128
149
|
function isRuntimePrimitiveId(value) {
|
|
129
150
|
return value === 'runtime.status'
|
|
130
151
|
|| value === 'runtime.reasoning.set'
|
|
@@ -227,6 +248,7 @@ export class CanonAgent {
|
|
|
227
248
|
debounceMs: 2000,
|
|
228
249
|
historyLimit: 50,
|
|
229
250
|
autoMarkRead: true,
|
|
251
|
+
runtimeControlSurface: 'agent',
|
|
230
252
|
...options,
|
|
231
253
|
};
|
|
232
254
|
this.apiClient = new CanonClient(this.options.apiKey, this.options.baseUrl);
|
|
@@ -983,6 +1005,14 @@ export class CanonAgent {
|
|
|
983
1005
|
? 'interrupt'
|
|
984
1006
|
: 'queue';
|
|
985
1007
|
}
|
|
1008
|
+
async markQueuedMessagesAccepted(conversationId, messages) {
|
|
1009
|
+
await Promise.all(messages.map((message) => {
|
|
1010
|
+
if (!message.id || normalizeTurnMetadata(message.metadata)?.inboundDisposition !== 'queued') {
|
|
1011
|
+
return Promise.resolve();
|
|
1012
|
+
}
|
|
1013
|
+
return this.apiClient.updateMessageDisposition(conversationId, message.id, 'accepted_now').catch(() => { });
|
|
1014
|
+
}));
|
|
1015
|
+
}
|
|
986
1016
|
async notifyMessageInterrupt(conversationId, abortSignal) {
|
|
987
1017
|
if (!abortSignal || !this.interruptHandler)
|
|
988
1018
|
return;
|
|
@@ -1001,7 +1031,7 @@ export class CanonAgent {
|
|
|
1001
1031
|
return createRuntimeStatePublisher({
|
|
1002
1032
|
agentId: this.agentId,
|
|
1003
1033
|
clientType: this.options.clientType ?? 'generic',
|
|
1004
|
-
hostMode:
|
|
1034
|
+
hostMode: this.options.runtimeControlSurface === 'host',
|
|
1005
1035
|
});
|
|
1006
1036
|
}
|
|
1007
1037
|
requireRuntimeStatePublisher() {
|
|
@@ -1037,6 +1067,7 @@ export class CanonAgent {
|
|
|
1037
1067
|
async executeHandler(conversationId, messages, session, provenanceByMessageId) {
|
|
1038
1068
|
if (!this.handler)
|
|
1039
1069
|
return;
|
|
1070
|
+
await this.markQueuedMessagesAccepted(conversationId, messages);
|
|
1040
1071
|
const turnId = randomUUID();
|
|
1041
1072
|
const turnOpenedAt = Date.now();
|
|
1042
1073
|
let turnState = 'thinking';
|
|
@@ -1337,6 +1368,139 @@ export class CanonAgent {
|
|
|
1337
1368
|
return { decision: 'deny' };
|
|
1338
1369
|
}
|
|
1339
1370
|
};
|
|
1371
|
+
const requestRuntimeInput = async (request) => {
|
|
1372
|
+
throwIfAborted();
|
|
1373
|
+
const inputId = safeRuntimeInputId(request.inputId, request.kind);
|
|
1374
|
+
const timeoutMs = Math.max(1_000, request.timeoutMs ?? DEFAULT_RUNTIME_INPUT_TIMEOUT_MS);
|
|
1375
|
+
const expiresAtMs = Date.now() + timeoutMs;
|
|
1376
|
+
const expiresAt = new Date(expiresAtMs).toISOString();
|
|
1377
|
+
let result = { status: 'timeout', inputId };
|
|
1378
|
+
let requestCreated = false;
|
|
1379
|
+
let requestResolved = false;
|
|
1380
|
+
const cancelPendingRequest = async () => {
|
|
1381
|
+
if (!requestCreated || requestResolved)
|
|
1382
|
+
return;
|
|
1383
|
+
try {
|
|
1384
|
+
await this.apiClient.consumeRuntimeInputResponse({
|
|
1385
|
+
conversationId,
|
|
1386
|
+
inputId,
|
|
1387
|
+
cancel: true,
|
|
1388
|
+
});
|
|
1389
|
+
requestResolved = true;
|
|
1390
|
+
}
|
|
1391
|
+
catch { }
|
|
1392
|
+
};
|
|
1393
|
+
shouldPersistTurnState = true;
|
|
1394
|
+
try {
|
|
1395
|
+
await this.apiClient.createRuntimeInputRequest({
|
|
1396
|
+
conversationId,
|
|
1397
|
+
inputId,
|
|
1398
|
+
kind: request.kind,
|
|
1399
|
+
expiresAt: expiresAtMs,
|
|
1400
|
+
});
|
|
1401
|
+
requestCreated = true;
|
|
1402
|
+
try {
|
|
1403
|
+
await this.apiClient.clearStreaming(conversationId);
|
|
1404
|
+
}
|
|
1405
|
+
catch { }
|
|
1406
|
+
await writeTurn('waiting_input');
|
|
1407
|
+
try {
|
|
1408
|
+
await this.apiClient.setTyping(conversationId, false);
|
|
1409
|
+
}
|
|
1410
|
+
catch { }
|
|
1411
|
+
const card = buildRuntimeInputRequest(inputId, {
|
|
1412
|
+
kind: request.kind,
|
|
1413
|
+
responseUserId: agent.ownerId,
|
|
1414
|
+
title: request.title,
|
|
1415
|
+
prompt: request.prompt,
|
|
1416
|
+
...(request.choices ? { choices: request.choices } : {}),
|
|
1417
|
+
...(request.secretName ? { secretName: request.secretName } : {}),
|
|
1418
|
+
...(request.native ? { native: request.native } : {}),
|
|
1419
|
+
expiresAt,
|
|
1420
|
+
...(request.sensitive !== undefined ? { sensitive: request.sensitive } : {}),
|
|
1421
|
+
});
|
|
1422
|
+
await this.apiClient.sendMessage(conversationId, card.text, {
|
|
1423
|
+
metadata: {
|
|
1424
|
+
...card.metadata,
|
|
1425
|
+
turnId: request.turnId ?? turnId,
|
|
1426
|
+
turnSemantics: 'control',
|
|
1427
|
+
replyBehavior: 'suppress_auto_reply',
|
|
1428
|
+
},
|
|
1429
|
+
});
|
|
1430
|
+
while (Date.now() < expiresAtMs) {
|
|
1431
|
+
throwIfAborted();
|
|
1432
|
+
try {
|
|
1433
|
+
const response = await this.apiClient.consumeRuntimeInputResponse({
|
|
1434
|
+
conversationId,
|
|
1435
|
+
inputId,
|
|
1436
|
+
});
|
|
1437
|
+
if (response.status === 'submitted') {
|
|
1438
|
+
requestResolved = true;
|
|
1439
|
+
result = {
|
|
1440
|
+
status: 'submitted',
|
|
1441
|
+
value: response.value,
|
|
1442
|
+
inputId,
|
|
1443
|
+
};
|
|
1444
|
+
break;
|
|
1445
|
+
}
|
|
1446
|
+
if (response.status === 'cancelled' || response.status === 'timeout') {
|
|
1447
|
+
requestResolved = true;
|
|
1448
|
+
result = { status: response.status, inputId };
|
|
1449
|
+
break;
|
|
1450
|
+
}
|
|
1451
|
+
}
|
|
1452
|
+
catch {
|
|
1453
|
+
// Transient consume failures should not leak sensitive input or
|
|
1454
|
+
// break the runtime; keep waiting until the explicit timeout.
|
|
1455
|
+
}
|
|
1456
|
+
await sleepWithAbort(Math.min(RUNTIME_INPUT_POLL_MS, Math.max(1, expiresAtMs - Date.now())), abortController.signal);
|
|
1457
|
+
}
|
|
1458
|
+
if (!requestResolved) {
|
|
1459
|
+
try {
|
|
1460
|
+
const response = await this.apiClient.consumeRuntimeInputResponse({
|
|
1461
|
+
conversationId,
|
|
1462
|
+
inputId,
|
|
1463
|
+
});
|
|
1464
|
+
if (response.status === 'submitted') {
|
|
1465
|
+
result = { status: 'submitted', value: response.value, inputId };
|
|
1466
|
+
}
|
|
1467
|
+
else if (response.status === 'cancelled' || response.status === 'timeout') {
|
|
1468
|
+
result = { status: response.status, inputId };
|
|
1469
|
+
}
|
|
1470
|
+
}
|
|
1471
|
+
catch { }
|
|
1472
|
+
requestResolved = true;
|
|
1473
|
+
}
|
|
1474
|
+
const outcome = buildRuntimeInputOutcome(inputId, result.status, {
|
|
1475
|
+
kind: request.kind,
|
|
1476
|
+
reason: result.status,
|
|
1477
|
+
});
|
|
1478
|
+
await this.apiClient.sendMessage(conversationId, outcome.text, {
|
|
1479
|
+
metadata: {
|
|
1480
|
+
...outcome.metadata,
|
|
1481
|
+
turnId: request.turnId ?? turnId,
|
|
1482
|
+
turnSemantics: 'control',
|
|
1483
|
+
replyBehavior: 'suppress_auto_reply',
|
|
1484
|
+
},
|
|
1485
|
+
});
|
|
1486
|
+
throwIfAborted();
|
|
1487
|
+
shouldPersistTurnState = false;
|
|
1488
|
+
try {
|
|
1489
|
+
await this.apiClient.setTyping(conversationId, true, 'thinking');
|
|
1490
|
+
}
|
|
1491
|
+
catch { }
|
|
1492
|
+
await setLiveState('thinking', 'Thinking...', 'thinking');
|
|
1493
|
+
return result;
|
|
1494
|
+
}
|
|
1495
|
+
catch (error) {
|
|
1496
|
+
await cancelPendingRequest();
|
|
1497
|
+
if (abortController.signal.aborted || isAbortLikeError(error)) {
|
|
1498
|
+
throw error;
|
|
1499
|
+
}
|
|
1500
|
+
shouldPersistTurnState = false;
|
|
1501
|
+
return result;
|
|
1502
|
+
}
|
|
1503
|
+
};
|
|
1340
1504
|
const uploadFile = (filePath, options) => uploadMediaFile(this.apiClient, conversationId, filePath, options);
|
|
1341
1505
|
const replyWithFile = async (filePath, text = '', options) => {
|
|
1342
1506
|
throwIfAborted();
|
|
@@ -1399,6 +1563,7 @@ export class CanonAgent {
|
|
|
1399
1563
|
selfContexts,
|
|
1400
1564
|
provenance,
|
|
1401
1565
|
requestApproval,
|
|
1566
|
+
requestRuntimeInput,
|
|
1402
1567
|
abortSignal: abortController.signal,
|
|
1403
1568
|
media: {
|
|
1404
1569
|
materialize: (message = hydratedMessages[hydratedMessages.length - 1], options) => {
|
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
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';
|
|
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, RuntimeInputChoice, RuntimeInputKind, RuntimeInputNativeMetadata, 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, RuntimeApprovalRequest, RuntimePrimitiveContext, RuntimePrimitiveHandler, RuntimePrimitiveHandlers, SessionInfo, SessionOptions, DeliveryMode, } from './types.js';
|
|
10
|
+
export type { CanonAgentOptions, ContactAddedHandler, ContactRemovedHandler, ContactRequestHandler, MessageHandler, MessageHandlerContext, ProgressMessageOptions, ProgressMessageResult, ReachOutOptions, ReachOutResult, RuntimeApprovalRequest, RuntimeInputRequest, RuntimeInputResult, RuntimeControlSurface, RuntimePrimitiveContext, RuntimePrimitiveHandler, RuntimePrimitiveHandlers, SessionInfo, SessionOptions, DeliveryMode, } from './types.js';
|
package/dist/types.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
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';
|
|
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, RuntimeInputChoice, RuntimeInputKind, RuntimeInputNativeMetadata, SessionRule, ApprovalResult, } from '@canonmsg/core';
|
|
2
|
+
import type { AddMemberResult, CanonGroupContext, CanonMessage, CanonConversation, CanonReplyContext, ContactCardPayload, CanonRuntimeActionDispatch, CanonRuntimePrimitiveId, CanonRuntimeProvenance, ApprovalNativeRequestMetadata, ApprovalRequestCategory, ApprovalRequestDetail, ApprovalResult, ApprovalRisk, RuntimeInputChoice, RuntimeInputKind, RuntimeInputNativeMetadata, 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
|
/**
|
|
@@ -56,6 +56,24 @@ export interface RuntimeApprovalRequest {
|
|
|
56
56
|
/** Whether an approval reply may set an in-memory session rule. */
|
|
57
57
|
allowSessionRule?: boolean;
|
|
58
58
|
}
|
|
59
|
+
export interface RuntimeInputRequest {
|
|
60
|
+
kind: RuntimeInputKind;
|
|
61
|
+
title: string;
|
|
62
|
+
prompt: string;
|
|
63
|
+
choices?: RuntimeInputChoice[];
|
|
64
|
+
secretName?: string;
|
|
65
|
+
sensitive?: boolean;
|
|
66
|
+
runtimeId?: string;
|
|
67
|
+
turnId?: string;
|
|
68
|
+
native?: RuntimeInputNativeMetadata;
|
|
69
|
+
inputId?: string;
|
|
70
|
+
timeoutMs?: number;
|
|
71
|
+
}
|
|
72
|
+
export interface RuntimeInputResult {
|
|
73
|
+
status: 'submitted' | 'cancelled' | 'timeout';
|
|
74
|
+
value?: string;
|
|
75
|
+
inputId: string;
|
|
76
|
+
}
|
|
59
77
|
export interface MessageHandlerContext {
|
|
60
78
|
messages: CanonMessage[];
|
|
61
79
|
history: CanonMessage[];
|
|
@@ -109,6 +127,12 @@ export interface MessageHandlerContext {
|
|
|
109
127
|
* and enforce the returned decision in their own approval hook.
|
|
110
128
|
*/
|
|
111
129
|
requestApproval: (request: RuntimeApprovalRequest) => Promise<ApprovalResult>;
|
|
130
|
+
/**
|
|
131
|
+
* Ask the agent owner for runtime input such as clarification, sudo, or a
|
|
132
|
+
* secret. Sensitive values are returned only to the calling runtime and are
|
|
133
|
+
* never persisted in Canon message metadata.
|
|
134
|
+
*/
|
|
135
|
+
requestRuntimeInput: (request: RuntimeInputRequest) => Promise<RuntimeInputResult>;
|
|
112
136
|
/** Canon-managed local media access for the current conversation. */
|
|
113
137
|
media: {
|
|
114
138
|
materialize: (message?: CanonMessage, options?: Omit<MaterializeMediaOptions, 'agentId' | 'conversationId' | 'messageId'>) => Promise<MaterializedCanonAttachment[]>;
|
|
@@ -155,6 +179,7 @@ export interface RuntimeControlHandlers {
|
|
|
155
179
|
onStopAndDrop?: RuntimeSignalHandler;
|
|
156
180
|
onNewSession?: RuntimeSignalHandler;
|
|
157
181
|
}
|
|
182
|
+
export type RuntimeControlSurface = 'agent' | 'host';
|
|
158
183
|
export interface RuntimePrimitiveContext {
|
|
159
184
|
conversationId: string;
|
|
160
185
|
primitive: CanonRuntimePrimitiveId;
|
|
@@ -186,6 +211,8 @@ export interface CanonAgentOptions {
|
|
|
186
211
|
runtimeDescriptor?: import('@canonmsg/core').CanonRuntimeDescriptor;
|
|
187
212
|
/** Optional Canon runtime signal handlers. Enables interrupt controls when provided. */
|
|
188
213
|
runtimeControls?: RuntimeControlHandlers;
|
|
214
|
+
/** Runtime publishing surface. Use `host` when this agent owns live runtime controls. */
|
|
215
|
+
runtimeControlSurface?: RuntimeControlSurface;
|
|
189
216
|
/** Optional typed runtime primitive handlers. Enables descriptor-backed command controls when provided. */
|
|
190
217
|
runtimePrimitives?: RuntimePrimitiveHandlers;
|
|
191
218
|
/**
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@canonmsg/agent-sdk",
|
|
3
|
-
"version": "1.5.
|
|
3
|
+
"version": "1.5.5",
|
|
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.21.0"
|
|
32
32
|
},
|
|
33
33
|
"publishConfig": {
|
|
34
34
|
"access": "public"
|