@canonmsg/agent-sdk 1.1.2 → 1.1.3
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.js +52 -39
- package/dist/index.d.ts +1 -1
- package/dist/types.d.ts +14 -14
- package/package.json +2 -2
package/dist/canon-agent.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { CanonClient, createRuntimeStatePublisher, FINAL_MESSAGE_HANDOFF_MS, initRTDBAuth, rtdbRead, rtdbWrite,
|
|
1
|
+
import { CanonClient, createRuntimeStatePublisher, FINAL_MESSAGE_HANDOFF_MS, initRTDBAuth, rtdbRead, rtdbWrite, normalizeTurnMetadata, reachOutToCanonContact, } from '@canonmsg/core';
|
|
2
2
|
import { randomUUID } from 'node:crypto';
|
|
3
3
|
import { AuthManager } from './auth.js';
|
|
4
4
|
import { Debouncer } from './debouncer.js';
|
|
@@ -152,7 +152,10 @@ export class CanonAgent {
|
|
|
152
152
|
// Include the opener/request payloads in the dedupe key so two concurrent
|
|
153
153
|
// calls with different `text`, `requestMessage`, or setup choices don't silently collapse
|
|
154
154
|
// and lose the second caller's intended side effect.
|
|
155
|
-
const
|
|
155
|
+
const contextualKey = options?.selfContext
|
|
156
|
+
? `${options.sourceConversationId ?? ''}\u0000${options.selfContext.type}\u0000${options.selfContext.context}`
|
|
157
|
+
: '';
|
|
158
|
+
const inFlightKey = `${targetUserId}\u0000${options?.text ?? ''}\u0000${options?.requestMessage ?? ''}\u0000${JSON.stringify(options?.sessionConfig ?? null)}\u0000${contextualKey}`;
|
|
156
159
|
const inFlight = this.reachOutInFlight.get(inFlightKey);
|
|
157
160
|
if (inFlight)
|
|
158
161
|
return inFlight;
|
|
@@ -163,6 +166,29 @@ export class CanonAgent {
|
|
|
163
166
|
return promise;
|
|
164
167
|
}
|
|
165
168
|
async executeReachOut(targetUserId, options) {
|
|
169
|
+
if (options?.selfContext) {
|
|
170
|
+
if (!options.sourceConversationId) {
|
|
171
|
+
throw new Error('sourceConversationId is required for contextual reachOut');
|
|
172
|
+
}
|
|
173
|
+
if (!options.text) {
|
|
174
|
+
throw new Error('text is required for contextual reachOut');
|
|
175
|
+
}
|
|
176
|
+
const result = await this.apiClient.sendContextualMessage({
|
|
177
|
+
sourceConversationId: options.sourceConversationId,
|
|
178
|
+
targetUserId,
|
|
179
|
+
text: options.text,
|
|
180
|
+
selfContext: options.selfContext,
|
|
181
|
+
requestMessage: options.requestMessage ?? null,
|
|
182
|
+
sessionConfig: options.sessionConfig ?? null,
|
|
183
|
+
});
|
|
184
|
+
return result.status === 'messaged'
|
|
185
|
+
? {
|
|
186
|
+
status: 'messaged',
|
|
187
|
+
conversationId: result.conversationId,
|
|
188
|
+
messageId: result.messageId,
|
|
189
|
+
}
|
|
190
|
+
: result;
|
|
191
|
+
}
|
|
166
192
|
return reachOutToCanonContact(this.apiClient, {
|
|
167
193
|
targetUserId,
|
|
168
194
|
text: options?.text ?? null,
|
|
@@ -634,6 +660,9 @@ export class CanonAgent {
|
|
|
634
660
|
catch { }
|
|
635
661
|
const result = await this.apiClient.sendMessage(conversationId, text, {
|
|
636
662
|
...(options ?? {}),
|
|
663
|
+
...(options?.selfContextId === undefined && activeSelfContextId
|
|
664
|
+
? { selfContextId: activeSelfContextId }
|
|
665
|
+
: {}),
|
|
637
666
|
metadata: {
|
|
638
667
|
...(options?.metadata ?? {}),
|
|
639
668
|
turnId,
|
|
@@ -672,11 +701,8 @@ export class CanonAgent {
|
|
|
672
701
|
m.isOwner = m.senderId === ownerId;
|
|
673
702
|
}
|
|
674
703
|
}
|
|
675
|
-
const
|
|
676
|
-
|
|
677
|
-
?? null;
|
|
678
|
-
const activeWorkSessions = mergeWorkSessionContexts(explicitWorkSession, page.workSessions ?? []);
|
|
679
|
-
const workSession = explicitWorkSession;
|
|
704
|
+
const selfContexts = page.selfContexts ?? [];
|
|
705
|
+
const activeSelfContextId = selfContexts[0]?.id;
|
|
680
706
|
// Build agent context (fallback to minimal if not yet received)
|
|
681
707
|
const agent = this.agentContext ?? {
|
|
682
708
|
agentId: this.agentId,
|
|
@@ -693,32 +719,21 @@ export class CanonAgent {
|
|
|
693
719
|
const react = (messageId, emoji) => this.apiClient.react(conversationId, messageId, emoji);
|
|
694
720
|
const addMember = (userId) => this.apiClient.addMember(conversationId, userId);
|
|
695
721
|
const removeMember = (userId) => this.apiClient.removeMember(conversationId, userId);
|
|
696
|
-
const
|
|
697
|
-
conversationId,
|
|
698
|
-
...
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
targetConversationId,
|
|
709
|
-
text,
|
|
710
|
-
...(options ?? {}),
|
|
711
|
-
messageOptions: {
|
|
712
|
-
...(options?.messageOptions ?? {}),
|
|
713
|
-
metadata: {
|
|
714
|
-
...(options?.messageOptions?.metadata ?? {}),
|
|
715
|
-
turnId,
|
|
716
|
-
turnSemantics: 'turn_complete',
|
|
717
|
-
turnComplete: true,
|
|
718
|
-
},
|
|
722
|
+
const sendContextualMessage = (target, text, options) => this.apiClient.sendContextualMessage({
|
|
723
|
+
sourceConversationId: conversationId,
|
|
724
|
+
...target,
|
|
725
|
+
text,
|
|
726
|
+
...options,
|
|
727
|
+
messageOptions: {
|
|
728
|
+
...(options.messageOptions ?? {}),
|
|
729
|
+
metadata: {
|
|
730
|
+
...(options.messageOptions?.metadata ?? {}),
|
|
731
|
+
turnId,
|
|
732
|
+
turnSemantics: 'turn_complete',
|
|
733
|
+
turnComplete: true,
|
|
719
734
|
},
|
|
720
|
-
}
|
|
721
|
-
};
|
|
735
|
+
},
|
|
736
|
+
});
|
|
722
737
|
const uploadFile = (filePath, options) => uploadMediaFile(this.apiClient, conversationId, filePath, options);
|
|
723
738
|
const replyWithFile = async (filePath, text = '', options) => {
|
|
724
739
|
try {
|
|
@@ -733,13 +748,15 @@ export class CanonAgent {
|
|
|
733
748
|
? { replyToPosition: options.replyToPosition }
|
|
734
749
|
: {}),
|
|
735
750
|
...(options?.mentions ? { mentions: options.mentions } : {}),
|
|
751
|
+
...(options?.selfContextId === undefined && activeSelfContextId
|
|
752
|
+
? { selfContextId: activeSelfContextId }
|
|
753
|
+
: {}),
|
|
736
754
|
metadata: {
|
|
737
755
|
...(options?.metadata ?? {}),
|
|
738
756
|
turnId,
|
|
739
757
|
turnSemantics: 'turn_complete',
|
|
740
758
|
turnComplete: true,
|
|
741
759
|
},
|
|
742
|
-
...(options?.workSessionId ? { workSessionId: options.workSessionId } : {}),
|
|
743
760
|
contentType: uploaded.attachment.kind,
|
|
744
761
|
attachments: [uploaded.attachment],
|
|
745
762
|
});
|
|
@@ -767,13 +784,9 @@ export class CanonAgent {
|
|
|
767
784
|
react,
|
|
768
785
|
addMember,
|
|
769
786
|
removeMember,
|
|
770
|
-
|
|
771
|
-
getWorkSession,
|
|
772
|
-
updateWorkSessionContext,
|
|
773
|
-
sendLinkedMessage,
|
|
787
|
+
sendContextualMessage,
|
|
774
788
|
agent,
|
|
775
|
-
|
|
776
|
-
activeWorkSessions,
|
|
789
|
+
selfContexts,
|
|
777
790
|
abortSignal: abortController.signal,
|
|
778
791
|
media: {
|
|
779
792
|
materialize: (message = hydratedMessages[hydratedMessages.length - 1], options) => {
|
package/dist/index.d.ts
CHANGED
|
@@ -6,5 +6,5 @@ export { SessionManager } from './session-manager.js';
|
|
|
6
6
|
export { getCodexImagePath, getMessageAttachments, inferUploadMimeType, isAnthropicImageAttachment, materializeAttachment, materializeMessageMedia, resolveAttachmentMimeType, toAnthropicImageBlock, uploadMediaFile, } from './media.js';
|
|
7
7
|
export type { AnthropicImageBlock, AnthropicImageMimeType, MaterializeMediaOptions, MaterializedCanonAttachment, ReplyWithFileOptions, UploadMediaFileOptions, } from './media.js';
|
|
8
8
|
export type { SessionConfig, Session } from './session-manager.js';
|
|
9
|
-
export type { AgentContext, CanonContactRequest, CanonMessage, CanonConversation,
|
|
9
|
+
export type { AgentContext, CanonContactRequest, CanonMessage, CanonConversation, CanonSelfContext, SendContextualMessageOptions, SendContextualMessageResult, SendContextualSelfContextInput, SendMessageOptions, CreateConversationOptions, } from '@canonmsg/core';
|
|
10
10
|
export type { CanonAgentOptions, ContactAddedHandler, ContactRemovedHandler, ContactRequestHandler, MessageHandler, MessageHandlerContext, ProgressMessageOptions, ProgressMessageResult, ReachOutOptions, ReachOutResult, SessionInfo, SessionOptions, DeliveryMode, } from './types.js';
|
package/dist/types.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
export type { AddMemberResult, AgentClientType, CanonRuntimeDescriptor, CanonMessage, CanonConversation, CanonContact, CanonContactRequest, CanonResolveAdmissionResult, ContactAddedPayload, ContactRemovedPayload, ContactSource, AgentContext, ResolvedAdmissionState, ResolvedAdmissionTargetSummary, ResolvedTargetAdmissionPayload,
|
|
2
|
-
import type { AddMemberResult, CanonMessage, CanonConversation, CanonRuntimeActionDispatch,
|
|
1
|
+
export type { AddMemberResult, AgentClientType, CanonRuntimeDescriptor, CanonMessage, CanonConversation, 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, CanonMessage, CanonConversation, CanonRuntimeActionDispatch, 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
|
/**
|
|
@@ -61,20 +61,16 @@ export interface MessageHandlerContext {
|
|
|
61
61
|
addMember: (userId: string) => Promise<AddMemberResult>;
|
|
62
62
|
/** Remove a member from this conversation (requires owner/admin role) */
|
|
63
63
|
removeMember: (userId: string) => Promise<void>;
|
|
64
|
-
/**
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
/** Send into another conversation under an existing or lazily created Canon work session. */
|
|
71
|
-
sendLinkedMessage: (targetConversationId: string, text: string, options?: Omit<import('@canonmsg/core').SendLinkedMessageOptions, 'sourceConversationId' | 'targetConversationId' | 'text'>) => Promise<import('@canonmsg/core').SendLinkedMessageResult>;
|
|
64
|
+
/** Send into another Canon conversation with private cross-session self-context. */
|
|
65
|
+
sendContextualMessage: (target: {
|
|
66
|
+
targetConversationId: string;
|
|
67
|
+
} | {
|
|
68
|
+
targetUserId: string;
|
|
69
|
+
}, text: string, options: Omit<import('@canonmsg/core').SendContextualMessageOptions, 'sourceConversationId' | 'targetConversationId' | 'targetUserId' | 'text'>) => Promise<import('@canonmsg/core').SendContextualMessageResult>;
|
|
72
70
|
/** Trusted agent identity & access context */
|
|
73
71
|
agent: import('@canonmsg/core').AgentContext;
|
|
74
|
-
/** Canon-provided
|
|
75
|
-
|
|
76
|
-
/** All active Canon work sessions currently linked to this conversation. */
|
|
77
|
-
activeWorkSessions?: import('@canonmsg/core').CanonWorkSessionContext[];
|
|
72
|
+
/** Canon-provided private context explaining this agent's cross-session actions. */
|
|
73
|
+
selfContexts?: import('@canonmsg/core').CanonSelfContext[];
|
|
78
74
|
/** Canon-managed local media access for the current conversation. */
|
|
79
75
|
media: {
|
|
80
76
|
materialize: (message?: CanonMessage, options?: Omit<MaterializeMediaOptions, 'agentId' | 'conversationId' | 'messageId'>) => Promise<MaterializedCanonAttachment[]>;
|
|
@@ -179,4 +175,8 @@ export interface ReachOutOptions {
|
|
|
179
175
|
requestMessage?: string;
|
|
180
176
|
/** Explicit session setup to use when the contact-card target is an agent. */
|
|
181
177
|
sessionConfig?: SessionConfig | null;
|
|
178
|
+
/** Source conversation for contextual cross-session reach-outs. */
|
|
179
|
+
sourceConversationId?: string;
|
|
180
|
+
/** Private context for the agent when this reach-out sends a cross-session message. */
|
|
181
|
+
selfContext?: SendContextualSelfContextInput;
|
|
182
182
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@canonmsg/agent-sdk",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.3",
|
|
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.15.
|
|
31
|
+
"@canonmsg/core": "^0.15.5"
|
|
32
32
|
},
|
|
33
33
|
"publishConfig": {
|
|
34
34
|
"access": "public"
|