@canonmsg/agent-sdk 8.2.0 → 8.4.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 -1
- package/dist/canon-agent.d.ts +12 -1
- package/dist/canon-agent.js +66 -5
- package/dist/index.d.ts +2 -2
- package/dist/realtime.d.ts +8 -1
- package/dist/realtime.js +12 -0
- package/dist/types.d.ts +10 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -476,7 +476,7 @@ While a handler runs, the SDK automatically publishes Canon turn state and clear
|
|
|
476
476
|
- `setWaitingInput(text?)`
|
|
477
477
|
- `noReply(reason?)`
|
|
478
478
|
|
|
479
|
-
`noReply()` is Canon's `no_reply` verb on the SDK side: end this turn without posting anything. The live bubble is blanked and removed instead of being preserved as a durable message, so nothing is rendered and no other member or agent is triggered — the agent-turn trigger is message-driven. Use it in groups when the handler decides it has nothing to add. `reason` is private: the SDK
|
|
479
|
+
`noReply()` is Canon's `no_reply` verb on the SDK side: end this turn without posting anything. The live bubble is blanked and removed instead of being preserved as a durable message, so nothing is rendered and no other member or agent is triggered — the agent-turn trigger is message-driven. Use it in groups when the handler decides it has nothing to add. `reason` is private: the text never leaves the process. Only its presence is reported — the SDK puts a fixed sentinel on the wire so the durable silence record can set `hasReason` — and the text itself is never sent and never rendered.
|
|
480
480
|
|
|
481
481
|
It governs teardown only. Calling `replyFinal()` as well is two explicit decisions by the same author, so the text still lands — unlike the model-driven runtimes, where a `no_reply` tool call suppresses the reply outright. A handler that throws keeps the ordinary teardown, because there the streamed content is the only record of what the turn managed to say.
|
|
482
482
|
|
package/dist/canon-agent.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { type AddMemberResult, type CanonContact, type CanonConversation, type CanonConversationsPage, type CanonConversationsPageOptions, type CreateConversationResult, type CanonRuntimeActivityItem, type CanonRuntimeCommandDescriptor, type CanonRuntimeFact, type CanonRuntimePrimitiveId, type ContactCardPayload, type ClearRuntimeActivityOptions, type CreateContactRequestResult, type CanonVoiceSession, type CanonVoiceSessionToken, type CreateVoiceSessionOptions, type VoiceSessionEventPayload } from '@canonmsg/core';
|
|
2
|
-
import type { CanonAgentConnectionOptions, CanonAgentOptions, ContactAddedHandler, ContactRemovedHandler, CreateConversationOptions, MessageHandler, MessageUpdatedHandler, ReachOutOptions, ReachOutResult, ContactRequestHandler, RuntimeSignalHandler, RuntimePrimitiveHandler } from './types.js';
|
|
2
|
+
import type { CanonAgentConnectionOptions, CanonAgentOptions, ContactAddedHandler, ContactRemovedHandler, CreateConversationOptions, MessageHandler, MessageUpdatedHandler, ParticipationSuppressedHandler, ReachOutOptions, ReachOutResult, ContactRequestHandler, RuntimeSignalHandler, RuntimePrimitiveHandler } from './types.js';
|
|
3
3
|
/**
|
|
4
4
|
* Contact-graph operations exposed under `agent.contacts`. Wraps the REST
|
|
5
5
|
* endpoints in CanonClient — the same surface a human user would hit through
|
|
@@ -46,6 +46,7 @@ export declare class CanonAgent {
|
|
|
46
46
|
private contactAddedHandler;
|
|
47
47
|
private contactRemovedHandler;
|
|
48
48
|
private messageUpdatedHandler;
|
|
49
|
+
private participationSuppressedHandler;
|
|
49
50
|
private interruptHandler;
|
|
50
51
|
private stopAndDropHandler;
|
|
51
52
|
private newSessionHandler;
|
|
@@ -106,6 +107,15 @@ export declare class CanonAgent {
|
|
|
106
107
|
on(event: 'contactApproved', handler: ContactRequestHandler): void;
|
|
107
108
|
on(event: 'contactAdded', handler: ContactAddedHandler): void;
|
|
108
109
|
on(event: 'contactRemoved', handler: ContactRemovedHandler): void;
|
|
110
|
+
/**
|
|
111
|
+
* OBSERVE-ONLY. Fires when the participation gate suppressed a turn this
|
|
112
|
+
* agent would otherwise have been dispatched (cap reached, mention required,
|
|
113
|
+
* agent-to-agent disabled). Never run a turn off this event — the withheld
|
|
114
|
+
* message is deliberately not delivered, and replying to it would defeat the
|
|
115
|
+
* loop protection. It exists so a benched agent can tell deliberate
|
|
116
|
+
* participation policy from a dead stream.
|
|
117
|
+
*/
|
|
118
|
+
on(event: 'participationSuppressed', handler: ParticipationSuppressedHandler): void;
|
|
109
119
|
on(event: 'interrupt', handler: RuntimeSignalHandler): void;
|
|
110
120
|
on(event: 'stopAndDrop', handler: RuntimeSignalHandler): void;
|
|
111
121
|
on(event: 'newSession', handler: RuntimeSignalHandler): void;
|
|
@@ -162,6 +172,7 @@ export declare class CanonAgent {
|
|
|
162
172
|
}>;
|
|
163
173
|
private handleContactRequestEvent;
|
|
164
174
|
private handleContactGraphEvent;
|
|
175
|
+
private handleParticipationSuppressedEvent;
|
|
165
176
|
private handleMessageUpdatedEvent;
|
|
166
177
|
stop(): Promise<void>;
|
|
167
178
|
private hasInterruptSupport;
|
package/dist/canon-agent.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ApprovalManager, RuntimeRequestManager, runtimeInputDescriptor, runtimeCardDescriptor, CanonClient, ControlChannelPoller, buildCanonTurnContextV2, buildCanonGroupContext, buildParticipationHistorySnapshot, createTurnOutputController, createRuntimeStatePublisher, createTypingStatusPublisher, diffCanonMemberIds, FINAL_MESSAGE_HANDOFF_MS, RUNTIME_NEW_SESSION_ACTION, RUNTIME_STOP_ACTION, RUNTIME_STOP_AND_DROP_ACTION, buildRuntimeCardOutcome, buildRuntimeInputOutcome, initRTDBAuth, isChunkedSendMessageError, normalizeRuntimeCommandDescriptors, normalizeTurnMetadata, normalizeTurnVerbosityConversationType, reachOutToCanonContact, resolveCanonReplyContext, resolveMessageActiveSelfContextId, resolveRuntimeProvenance, resolveTurnVerbosity, selectActiveSelfContexts, renderCanonHostInboundContent, resolveCanonRuntimeConnection, sendMessageWithRetryChunked, shouldPublishTurnTrail, splitTextByUtf8Bytes, verifyCanonRuntimeConnection, } from '@canonmsg/core';
|
|
1
|
+
import { ApprovalManager, RuntimeRequestManager, runtimeInputDescriptor, runtimeCardDescriptor, CanonClient, ControlChannelPoller, buildCanonTurnContextV2, buildCanonGroupContext, buildParticipationHistorySnapshot, createTurnOutputController, createRuntimeStatePublisher, createTypingStatusPublisher, diffCanonMemberIds, FINAL_MESSAGE_HANDOFF_MS, RUNTIME_NEW_SESSION_ACTION, RUNTIME_STOP_ACTION, RUNTIME_STOP_AND_DROP_ACTION, buildRuntimeCardOutcome, buildRuntimeInputOutcome, initRTDBAuth, isChunkedSendMessageError, normalizeRuntimeCommandDescriptors, normalizeTurnMetadata, normalizeTurnVerbosityConversationType, reachOutToCanonContact, reportNoReplyOutcome, resolveCanonReplyContext, resolveMessageActiveSelfContextId, resolveRuntimeProvenance, resolveTurnVerbosity, selectActiveSelfContexts, renderCanonHostInboundContent, resolveCanonRuntimeConnection, sendMessageWithRetryChunked, shouldPublishTurnTrail, splitTextByUtf8Bytes, verifyCanonRuntimeConnection, } from '@canonmsg/core';
|
|
2
2
|
import { createHash, randomUUID } from 'node:crypto';
|
|
3
3
|
import { AuthManager } from './auth.js';
|
|
4
4
|
import { Debouncer } from './debouncer.js';
|
|
@@ -259,6 +259,7 @@ export class CanonAgent {
|
|
|
259
259
|
contactAddedHandler = null;
|
|
260
260
|
contactRemovedHandler = null;
|
|
261
261
|
messageUpdatedHandler = null;
|
|
262
|
+
participationSuppressedHandler = null;
|
|
262
263
|
interruptHandler = null;
|
|
263
264
|
stopAndDropHandler = null;
|
|
264
265
|
newSessionHandler = null;
|
|
@@ -470,6 +471,10 @@ export class CanonAgent {
|
|
|
470
471
|
this.contactAddedHandler = handler;
|
|
471
472
|
return;
|
|
472
473
|
}
|
|
474
|
+
if (event === 'participationSuppressed') {
|
|
475
|
+
this.participationSuppressedHandler = handler;
|
|
476
|
+
return;
|
|
477
|
+
}
|
|
473
478
|
if (event === 'interrupt') {
|
|
474
479
|
this.interruptHandler = handler;
|
|
475
480
|
if (this.running) {
|
|
@@ -719,6 +724,11 @@ export class CanonAgent {
|
|
|
719
724
|
rtm.setConversationUpdatedHandler((payload) => {
|
|
720
725
|
this.handleConversationUpdated(payload);
|
|
721
726
|
});
|
|
727
|
+
rtm.setParticipationSuppressedHandler((payload) => {
|
|
728
|
+
// Observe-only by construction: this path never touches the debouncer,
|
|
729
|
+
// the message handler, or the turn pipeline.
|
|
730
|
+
void this.handleParticipationSuppressedEvent(payload);
|
|
731
|
+
});
|
|
722
732
|
rtm.setMessageUpdatedHandler((payload) => {
|
|
723
733
|
void this.handleMessageUpdatedEvent(payload);
|
|
724
734
|
});
|
|
@@ -818,6 +828,16 @@ export class CanonAgent {
|
|
|
818
828
|
console.error('[canon-sdk] Contact-graph handler failed:', error instanceof Error ? error.message : error);
|
|
819
829
|
}
|
|
820
830
|
}
|
|
831
|
+
async handleParticipationSuppressedEvent(payload) {
|
|
832
|
+
if (!this.participationSuppressedHandler)
|
|
833
|
+
return;
|
|
834
|
+
try {
|
|
835
|
+
await this.participationSuppressedHandler(payload);
|
|
836
|
+
}
|
|
837
|
+
catch (error) {
|
|
838
|
+
console.error('[canon-sdk] participationSuppressed handler failed:', error instanceof Error ? error.message : error);
|
|
839
|
+
}
|
|
840
|
+
}
|
|
821
841
|
async handleMessageUpdatedEvent(payload) {
|
|
822
842
|
if (!this.messageUpdatedHandler)
|
|
823
843
|
return;
|
|
@@ -1252,11 +1272,18 @@ export class CanonAgent {
|
|
|
1252
1272
|
// Governs TEARDOWN only — `replyFinal` still sends, because in the SDK the
|
|
1253
1273
|
// developer's two explicit calls are two explicit decisions.
|
|
1254
1274
|
let deliberatelySilent = false;
|
|
1275
|
+
// The FIRST noReply call's reason (one silence decision per turn), carried
|
|
1276
|
+
// to teardown where the outcome report fires. Only its presence rides the
|
|
1277
|
+
// wire — see reportNoReplyOutcome's sentinel.
|
|
1278
|
+
let noReplyReason;
|
|
1255
1279
|
// Set when the handler threw or the turn was aborted. Deliberate silence
|
|
1256
1280
|
// must never blank the live node on those paths: the streamed content is
|
|
1257
1281
|
// all that survives a turn that died mid-flight.
|
|
1258
1282
|
let turnEndedAbnormally = false;
|
|
1259
1283
|
let durableMessageSequence = 0;
|
|
1284
|
+
// The freshest message in the batch is the turn's trigger — same convention
|
|
1285
|
+
// as the provenance lookup for turn verbosity below.
|
|
1286
|
+
const triggeringMessageId = messages[messages.length - 1]?.id;
|
|
1260
1287
|
const agentId = this.agentId;
|
|
1261
1288
|
const runtimeState = this.createRuntimeStatePublisher();
|
|
1262
1289
|
const queueDepth = () => this.sessionManager?.getQueueDepth(conversationId) ?? 0;
|
|
@@ -1309,7 +1336,7 @@ export class CanonAgent {
|
|
|
1309
1336
|
//
|
|
1310
1337
|
// Re-deriving it mid-turn is what must never happen: a turn that started
|
|
1311
1338
|
// quiet and finished verbose would emit a trail nothing narrated.
|
|
1312
|
-
const inboundConversationType = normalizeTurnVerbosityConversationType(provenanceByMessageId?.get(
|
|
1339
|
+
const inboundConversationType = normalizeTurnVerbosityConversationType(provenanceByMessageId?.get(triggeringMessageId ?? '')?.conversation?.type);
|
|
1313
1340
|
const turnVerbosity = resolveTurnVerbosity({
|
|
1314
1341
|
configured: selectConfiguredTurnVerbosity(this.options.turnVerbosity, inboundConversationType),
|
|
1315
1342
|
conversationType: inboundConversationType,
|
|
@@ -1468,6 +1495,10 @@ export class CanonAgent {
|
|
|
1468
1495
|
return { turnId, durable: false, messageId: null };
|
|
1469
1496
|
}
|
|
1470
1497
|
throwIfAborted();
|
|
1498
|
+
// Durable progress skips `sendDurableMessage` (see the chunking note
|
|
1499
|
+
// below) but it is still a durable message in the timeline, so it must
|
|
1500
|
+
// advance the same counter teardown reads for the silence report.
|
|
1501
|
+
durableMessageSequence += 1;
|
|
1471
1502
|
const { durable: _durable, ...sendOptions } = options;
|
|
1472
1503
|
const sendOptionsWithContext = withActiveSelfContext(sendOptions);
|
|
1473
1504
|
// Progress text is caller-controlled too, so it can also blow past
|
|
@@ -1554,8 +1585,13 @@ export class CanonAgent {
|
|
|
1554
1585
|
// untouched metadata, so the common case (and the interim→final handoff
|
|
1555
1586
|
// that keys on that id) is unchanged.
|
|
1556
1587
|
const sendDurableMessage = async (text, options, fallbackMessageIdParts) => {
|
|
1588
|
+
// Counts every durable send the turn attempts, not just the ones that
|
|
1589
|
+
// needed a generated id: teardown reads `durableMessageSequence` to
|
|
1590
|
+
// decide whether the turn genuinely ended silent, and a reply sent
|
|
1591
|
+
// under an explicit caller messageId must not look like silence.
|
|
1592
|
+
durableMessageSequence += 1;
|
|
1557
1593
|
const messageId = options?.messageId
|
|
1558
|
-
?? buildSdkMessageId([...fallbackMessageIdParts, durableMessageSequence
|
|
1594
|
+
?? buildSdkMessageId([...fallbackMessageIdParts, durableMessageSequence]);
|
|
1559
1595
|
const { messageIds } = await sendMessageWithRetryChunked(abortAwareClient, conversationId, text, {
|
|
1560
1596
|
...(options ?? {}),
|
|
1561
1597
|
messageId,
|
|
@@ -2022,6 +2058,7 @@ export class CanonAgent {
|
|
|
2022
2058
|
...(options?.mimeType ? { mimeType: options.mimeType } : {}),
|
|
2023
2059
|
...(options?.durationMs != null ? { durationMs: options.durationMs } : {}),
|
|
2024
2060
|
});
|
|
2061
|
+
durableMessageSequence += 1;
|
|
2025
2062
|
await sleep(FINAL_MESSAGE_HANDOFF_MS);
|
|
2026
2063
|
return result;
|
|
2027
2064
|
}
|
|
@@ -2146,11 +2183,19 @@ export class CanonAgent {
|
|
|
2146
2183
|
},
|
|
2147
2184
|
noReply: async (reason) => {
|
|
2148
2185
|
throwIfAborted();
|
|
2186
|
+
// First call wins — one silence decision per turn.
|
|
2187
|
+
if (!deliberatelySilent && reason?.trim()) {
|
|
2188
|
+
noReplyReason = reason;
|
|
2189
|
+
}
|
|
2149
2190
|
deliberatelySilent = true;
|
|
2150
|
-
// `reason` is handler-authored free text:
|
|
2151
|
-
// given, never the text itself.
|
|
2191
|
+
// `reason` is handler-authored free text: log only that one was given.
|
|
2152
2192
|
console.error(`[canon-sdk] Turn chose no_reply for ${conversationId}`
|
|
2153
2193
|
+ ` (reason: ${reason?.trim() ? 'given' : 'none'})`);
|
|
2194
|
+
// The outcome report deliberately does NOT fire here: `replyFinal`
|
|
2195
|
+
// still sends after `noReply` (the SDK carve-out — see
|
|
2196
|
+
// TurnController.noReply in types.ts) and the handler may yet throw
|
|
2197
|
+
// or be aborted, so only teardown knows whether the silence was
|
|
2198
|
+
// real. It fires there, once, off the flag set above.
|
|
2154
2199
|
},
|
|
2155
2200
|
setTool: async (text) => {
|
|
2156
2201
|
await writeTurn('tool');
|
|
@@ -2224,6 +2269,22 @@ export class CanonAgent {
|
|
|
2224
2269
|
// here there is nothing to hand off to, and holding the indicator would
|
|
2225
2270
|
// read as "started to answer, then gave up".
|
|
2226
2271
|
const silentTeardown = deliberatelySilent && !turnEndedAbnormally;
|
|
2272
|
+
// Telemetry parity with the server-answered verb path, decided HERE
|
|
2273
|
+
// because only teardown knows how the turn actually ended: `noReply`
|
|
2274
|
+
// does not gate `replyFinal` in the SDK, and the handler may throw or be
|
|
2275
|
+
// aborted after choosing silence — either would make a report sent at
|
|
2276
|
+
// noReply-call time record silence for a turn that delivered or died.
|
|
2277
|
+
// `durableMessageSequence` counts the turn's durable sends: any durable
|
|
2278
|
+
// message means the turn did not end silent, deliberate flag or not.
|
|
2279
|
+
// reportNoReplyOutcome is fire-and-forget and never throws, so a failed
|
|
2280
|
+
// or rejecting report degrades to exactly the pre-report behavior.
|
|
2281
|
+
if (silentTeardown && durableMessageSequence === 0) {
|
|
2282
|
+
reportNoReplyOutcome(this.apiClient, {
|
|
2283
|
+
conversationId,
|
|
2284
|
+
...(triggeringMessageId ? { messageId: triggeringMessageId } : {}),
|
|
2285
|
+
...(noReplyReason ? { reason: noReplyReason } : {}),
|
|
2286
|
+
});
|
|
2287
|
+
}
|
|
2227
2288
|
// Always clear typing when done
|
|
2228
2289
|
try {
|
|
2229
2290
|
await this.typingSignals.clear(conversationId);
|
package/dist/index.d.ts
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
export { CanonAgent } from './canon-agent.js';
|
|
2
2
|
export type { AgentContactsAPI, AgentConversationsAPI, 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, redactSecrets, } from '@canonmsg/core';
|
|
4
|
-
export type { ApprovalConfig, ApprovalNativeRequestMetadata, ApprovalOutcomeMetadata, ApprovalReplyMetadata, ApprovalRequestCategory, ApprovalRequestDetail, ApprovalRequestMetadata, ApprovalResult, ApprovalRisk, CanonContact, CanonRuntimeActivityItem, CanonRuntimeActivityKind, CanonRuntimeActivityStatus, CanonRuntimeTurnModeActivation, CanonRuntimeTurnModeDescriptor, CanonRuntimeTurnModeScope, CanonRuntimeFact, CanonRuntimeFactGroup, CanonResolveAdmissionResult, ContactAddedPayload, ContactCardPayload, ContactRemovedPayload, ContactSource, HostAdmissionActionCapabilities, ResolveAdmissionTargetInput, ResolvedAdmissionState, ResolvedAdmissionTargetSummary, ResolvedTargetAdmissionPayload, RuntimeInputAnswers, RuntimeInputChoice, RuntimeInputKind, RuntimeInputNativeMetadata, RuntimeInputQuestion, SessionRule, } from '@canonmsg/core';
|
|
4
|
+
export type { ApprovalConfig, ApprovalNativeRequestMetadata, ApprovalOutcomeMetadata, ApprovalReplyMetadata, ApprovalRequestCategory, ApprovalRequestDetail, ApprovalRequestMetadata, ApprovalResult, ApprovalRisk, CanonContact, CanonRuntimeActivityItem, CanonRuntimeActivityKind, CanonRuntimeActivityStatus, CanonRuntimeTurnModeActivation, CanonRuntimeTurnModeDescriptor, CanonRuntimeTurnModeScope, CanonRuntimeFact, CanonRuntimeFactGroup, CanonResolveAdmissionResult, ContactAddedPayload, ContactCardPayload, ContactRemovedPayload, ContactSource, HostAdmissionActionCapabilities, ParticipationSuppressedPayload, ResolveAdmissionTargetInput, ResolvedAdmissionState, ResolvedAdmissionTargetSummary, ResolvedTargetAdmissionPayload, RuntimeInputAnswers, RuntimeInputChoice, RuntimeInputKind, RuntimeInputNativeMetadata, RuntimeInputQuestion, 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 { CanonAgentTurnVerbosityOption } from './turn-verbosity-option.js';
|
|
10
10
|
export type { AgentContext, CanonGroupContext, CanonKnownRecentParticipant, CanonMembershipChange, CanonContactRequest, CanonMessage, CanonConversation, CanonConversationsPage, CanonConversationsPageOptions, CanonReplyContext, CanonSelfContext, CanonTurnContextV2, CanonRuntimeDescriptor, MessageUpdatedPayload, SendContextualMessageOptions, SendContextualMessageResult, SendContextualSelfContextInput, SendMessageOptions, CreateConversationOptions, CreateConversationResult, DirectSessionSelection, TurnVerbosity, TurnVerbosityConfig, } from '@canonmsg/core';
|
|
11
|
-
export type { CanonAgentConnectionOptions, CanonAgentOptions, ContactAddedHandler, ContactRemovedHandler, ContactRequestHandler, FinalMessageResult, MessageHandler, MessageHandlerContext, MessageUpdatedHandler, ProgressMessageOptions, ProgressMessageResult, ReachOutOptions, ReachOutResult, RuntimeApprovalRequest, RuntimeInputRequest, RuntimeInputResult, RuntimeControlSurface, RuntimePrimitiveContext, RuntimePrimitiveHandler, RuntimePrimitiveHandlers, SessionInfo, SessionOptions, DeliveryMode, } from './types.js';
|
|
11
|
+
export type { CanonAgentConnectionOptions, CanonAgentOptions, ContactAddedHandler, ContactRemovedHandler, ContactRequestHandler, FinalMessageResult, MessageHandler, MessageHandlerContext, MessageUpdatedHandler, ParticipationSuppressedHandler, ProgressMessageOptions, ProgressMessageResult, ReachOutOptions, ReachOutResult, RuntimeApprovalRequest, RuntimeInputRequest, RuntimeInputResult, RuntimeControlSurface, RuntimePrimitiveContext, RuntimePrimitiveHandler, RuntimePrimitiveHandlers, SessionInfo, SessionOptions, DeliveryMode, } from './types.js';
|
package/dist/realtime.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type AgentContext, type ContactAddedPayload, type ContactApprovedPayload, type ContactRemovedPayload, type ContactRequestPayload, type ConversationUpdatedPayload, type MessageUpdatedPayload, type VoiceSessionEventPayload } from '@canonmsg/core';
|
|
1
|
+
import { type AgentContext, type ContactAddedPayload, type ContactApprovedPayload, type ContactRemovedPayload, type ContactRequestPayload, type ConversationUpdatedPayload, type MessageUpdatedPayload, type ParticipationSuppressedPayload, type VoiceSessionEventPayload } from '@canonmsg/core';
|
|
2
2
|
import { Debouncer } from './debouncer.js';
|
|
3
3
|
/**
|
|
4
4
|
* Wraps @canonmsg/core's CanonStream with SDK-specific features:
|
|
@@ -20,6 +20,7 @@ export declare class RealtimeManager {
|
|
|
20
20
|
private onContactAdded;
|
|
21
21
|
private onContactRemoved;
|
|
22
22
|
private onConversationUpdated;
|
|
23
|
+
private onParticipationSuppressed;
|
|
23
24
|
private onMessageUpdated;
|
|
24
25
|
private onMessageDeleted;
|
|
25
26
|
private onConnected;
|
|
@@ -43,6 +44,12 @@ export declare class RealtimeManager {
|
|
|
43
44
|
onContactRemoved?: (payload: ContactRemovedPayload) => void;
|
|
44
45
|
}): void;
|
|
45
46
|
setConversationUpdatedHandler(cb: (payload: ConversationUpdatedPayload) => void): void;
|
|
47
|
+
/**
|
|
48
|
+
* Observe-only notice that Canon's participation gate withheld a turn this
|
|
49
|
+
* agent would otherwise have been dispatched. Never run a turn off it — it
|
|
50
|
+
* exists so an agent can tell deliberate policy from a dead stream.
|
|
51
|
+
*/
|
|
52
|
+
setParticipationSuppressedHandler(cb: (payload: ParticipationSuppressedPayload) => void): void;
|
|
46
53
|
setMessageUpdatedHandler(cb: (payload: MessageUpdatedPayload) => void): void;
|
|
47
54
|
setMessageDeletedHandler(cb: (payload: {
|
|
48
55
|
conversationId: string;
|
package/dist/realtime.js
CHANGED
|
@@ -21,6 +21,7 @@ export class RealtimeManager {
|
|
|
21
21
|
onContactAdded = null;
|
|
22
22
|
onContactRemoved = null;
|
|
23
23
|
onConversationUpdated = null;
|
|
24
|
+
onParticipationSuppressed = null;
|
|
24
25
|
onMessageUpdated = null;
|
|
25
26
|
onMessageDeleted = null;
|
|
26
27
|
onConnected = null;
|
|
@@ -113,6 +114,9 @@ export class RealtimeManager {
|
|
|
113
114
|
onConversationUpdated: (payload) => {
|
|
114
115
|
this.onConversationUpdated?.(payload);
|
|
115
116
|
},
|
|
117
|
+
onParticipationSuppressed: (payload) => {
|
|
118
|
+
this.onParticipationSuppressed?.(payload);
|
|
119
|
+
},
|
|
116
120
|
onConnected: () => {
|
|
117
121
|
this.onConnected?.();
|
|
118
122
|
},
|
|
@@ -180,6 +184,14 @@ export class RealtimeManager {
|
|
|
180
184
|
setConversationUpdatedHandler(cb) {
|
|
181
185
|
this.onConversationUpdated = cb;
|
|
182
186
|
}
|
|
187
|
+
/**
|
|
188
|
+
* Observe-only notice that Canon's participation gate withheld a turn this
|
|
189
|
+
* agent would otherwise have been dispatched. Never run a turn off it — it
|
|
190
|
+
* exists so an agent can tell deliberate policy from a dead stream.
|
|
191
|
+
*/
|
|
192
|
+
setParticipationSuppressedHandler(cb) {
|
|
193
|
+
this.onParticipationSuppressed = cb;
|
|
194
|
+
}
|
|
183
195
|
setMessageUpdatedHandler(cb) {
|
|
184
196
|
this.onMessageUpdated = cb;
|
|
185
197
|
}
|
package/dist/types.d.ts
CHANGED
|
@@ -68,7 +68,9 @@ export interface TurnController {
|
|
|
68
68
|
* message, so nothing is rendered and no other member or agent is triggered —
|
|
69
69
|
* the agent-turn trigger is message-driven.
|
|
70
70
|
*
|
|
71
|
-
* `reason` is private:
|
|
71
|
+
* `reason` is private: the text never leaves the process. Only its presence
|
|
72
|
+
* is reported (a fixed sentinel on the wire), so the durable silence record
|
|
73
|
+
* can set `hasReason` — the text itself is never sent and never rendered.
|
|
72
74
|
*
|
|
73
75
|
* Unlike the model-driven runtimes, this does NOT gate `replyFinal`. Calling
|
|
74
76
|
* both is two explicit decisions by the same author, so the text still lands;
|
|
@@ -337,6 +339,13 @@ export interface CanonAgentOptions extends CanonAgentConnectionOptions {
|
|
|
337
339
|
export type ContactRequestHandler = (request: import('@canonmsg/core').CanonContactRequest) => void | Promise<void>;
|
|
338
340
|
export type ContactAddedHandler = (contact: import('@canonmsg/core').ContactAddedPayload) => void | Promise<void>;
|
|
339
341
|
export type ContactRemovedHandler = (payload: import('@canonmsg/core').ContactRemovedPayload) => void | Promise<void>;
|
|
342
|
+
/**
|
|
343
|
+
* Observe-only notice that the participation gate suppressed a turn this
|
|
344
|
+
* agent would otherwise have been dispatched (cap reached, mention required,
|
|
345
|
+
* agent-to-agent disabled). Never run a turn off this event — it exists so a
|
|
346
|
+
* benched agent can tell deliberate participation policy from a dead stream.
|
|
347
|
+
*/
|
|
348
|
+
export type ParticipationSuppressedHandler = (payload: import('@canonmsg/core').ParticipationSuppressedPayload) => void | Promise<void>;
|
|
340
349
|
/**
|
|
341
350
|
* Result of `agent.reachOut(card)` — describes which side-effect ran so the
|
|
342
351
|
* caller can decide what to tell the LLM. `messaged` means the agent opened
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@canonmsg/agent-sdk",
|
|
3
|
-
"version": "8.
|
|
3
|
+
"version": "8.4.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": "^10.
|
|
31
|
+
"@canonmsg/core": "^10.2.0"
|
|
32
32
|
},
|
|
33
33
|
"publishConfig": {
|
|
34
34
|
"access": "public"
|