@canonmsg/agent-sdk 1.1.3 → 1.1.4

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.
@@ -2,7 +2,7 @@ import { CanonClient, createRuntimeStatePublisher, FINAL_MESSAGE_HANDOFF_MS, ini
2
2
  import { randomUUID } from 'node:crypto';
3
3
  import { AuthManager } from './auth.js';
4
4
  import { Debouncer } from './debouncer.js';
5
- import { materializeMessageMedia, uploadMediaFile, } from './media.js';
5
+ import { materializeMessageMedia, sendMediaFileMessage, uploadMediaFile, } from './media.js';
6
6
  import { SessionManager } from './session-manager.js';
7
7
  const AGENT_RUNTIME_HEARTBEAT_MS = 30_000;
8
8
  const SDK_RUNTIME_CAPABILITIES = {
@@ -741,8 +741,7 @@ export class CanonAgent {
741
741
  }
742
742
  catch { }
743
743
  try {
744
- const uploaded = await uploadFile(filePath, options);
745
- const result = await this.apiClient.sendMessage(conversationId, text, {
744
+ const result = await sendMediaFileMessage(this.apiClient, conversationId, filePath, text, {
746
745
  ...(options?.replyTo ? { replyTo: options.replyTo } : {}),
747
746
  ...(options?.replyToPosition != null
748
747
  ? { replyToPosition: options.replyToPosition }
@@ -757,8 +756,9 @@ export class CanonAgent {
757
756
  turnSemantics: 'turn_complete',
758
757
  turnComplete: true,
759
758
  },
760
- contentType: uploaded.attachment.kind,
761
- attachments: [uploaded.attachment],
759
+ ...(options?.fileName ? { fileName: options.fileName } : {}),
760
+ ...(options?.mimeType ? { mimeType: options.mimeType } : {}),
761
+ ...(options?.durationMs != null ? { durationMs: options.durationMs } : {}),
762
762
  });
763
763
  await sleep(FINAL_MESSAGE_HANDOFF_MS);
764
764
  return result;
package/dist/index.d.ts CHANGED
@@ -3,7 +3,7 @@ export type { AgentContactsAPI, AgentUsersAPI } from './canon-agent.js';
3
3
  export { CanonApiError, HOST_ADMISSION_ACTION_CAPABILITIES, HOST_ADMISSION_ACTIONS_DISABLED, } from '@canonmsg/core';
4
4
  export type { CanonContact, CanonResolveAdmissionResult, ContactAddedPayload, ContactCardPayload, ContactRemovedPayload, ContactSource, HostAdmissionActionCapabilities, ResolvedAdmissionState, ResolvedAdmissionTargetSummary, ResolvedTargetAdmissionPayload, } from '@canonmsg/core';
5
5
  export { SessionManager } from './session-manager.js';
6
- export { getCodexImagePath, getMessageAttachments, inferUploadMimeType, isAnthropicImageAttachment, materializeAttachment, materializeMessageMedia, resolveAttachmentMimeType, toAnthropicImageBlock, uploadMediaFile, } from './media.js';
6
+ export { DEFAULT_MEDIA_CACHE_DIR, getCodexImagePath, getMessageAttachments, inferUploadMimeType, isAnthropicImageAttachment, materializeAttachment, materializeMessageMedia, resolveAttachmentMimeType, sendMediaFileMessage, 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
9
  export type { AgentContext, CanonContactRequest, CanonMessage, CanonConversation, CanonSelfContext, SendContextualMessageOptions, SendContextualMessageResult, SendContextualSelfContextInput, SendMessageOptions, CreateConversationOptions, } from '@canonmsg/core';
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
1
  export { CanonAgent } from './canon-agent.js';
2
2
  export { CanonApiError, HOST_ADMISSION_ACTION_CAPABILITIES, HOST_ADMISSION_ACTIONS_DISABLED, } from '@canonmsg/core';
3
3
  export { SessionManager } from './session-manager.js';
4
- export { getCodexImagePath, getMessageAttachments, inferUploadMimeType, isAnthropicImageAttachment, materializeAttachment, materializeMessageMedia, resolveAttachmentMimeType, toAnthropicImageBlock, uploadMediaFile, } from './media.js';
4
+ export { DEFAULT_MEDIA_CACHE_DIR, getCodexImagePath, getMessageAttachments, inferUploadMimeType, isAnthropicImageAttachment, materializeAttachment, materializeMessageMedia, resolveAttachmentMimeType, sendMediaFileMessage, toAnthropicImageBlock, uploadMediaFile, } from './media.js';
package/dist/media.d.ts CHANGED
@@ -10,6 +10,7 @@ export interface MaterializeMediaOptions {
10
10
  export interface UploadMediaFileOptions {
11
11
  fileName?: string;
12
12
  mimeType?: string;
13
+ durationMs?: number;
13
14
  }
14
15
  export interface ReplyWithFileOptions extends Omit<SendMessageOptions, 'attachments' | 'contentType'>, UploadMediaFileOptions {
15
16
  }
@@ -39,6 +40,7 @@ export interface AnthropicImageBlock {
39
40
  data: string;
40
41
  };
41
42
  }
43
+ export declare const DEFAULT_MEDIA_CACHE_DIR: string;
42
44
  export declare function getMessageAttachments(message: Pick<CanonMessage, 'attachments'>): MediaAttachment[];
43
45
  export declare function materializeAttachment(attachment: MediaAttachment, options: MaterializeMediaOptions & {
44
46
  index?: number;
@@ -49,6 +51,9 @@ export declare function uploadMediaFile(client: CanonClient, conversationId: str
49
51
  url: string;
50
52
  attachment: MediaAttachment;
51
53
  }>;
54
+ export declare function sendMediaFileMessage(client: CanonClient, conversationId: string, filePath: string, text?: string, options?: ReplyWithFileOptions): Promise<{
55
+ messageId: string;
56
+ }>;
52
57
  /**
53
58
  * Resolve the effective MIME type of a materialized attachment, falling back
54
59
  * to filename/URL extensions when the server didn't tell us explicitly.
package/dist/media.js CHANGED
@@ -7,7 +7,7 @@ const ANTHROPIC_IMAGE_MIME_TYPES = new Set([
7
7
  'image/gif',
8
8
  'image/webp',
9
9
  ]);
10
- const DEFAULT_MEDIA_CACHE_DIR = join(CANON_DIR, 'media-cache');
10
+ export const DEFAULT_MEDIA_CACHE_DIR = join(CANON_DIR, 'media-cache');
11
11
  const EXTENSION_BY_MIME = {
12
12
  'application/json': 'json',
13
13
  'application/pdf': 'pdf',
@@ -117,7 +117,7 @@ export async function materializeAttachment(attachment, options) {
117
117
  }
118
118
  responseMimeType = response.headers.get('content-type');
119
119
  const body = Buffer.from(await response.arrayBuffer());
120
- await writeFile(path, body);
120
+ await writeFile(path, body, { mode: 0o644 });
121
121
  }
122
122
  return {
123
123
  ...attachment,
@@ -150,7 +150,33 @@ export async function uploadMediaFile(client, conversationId, filePath, options)
150
150
  const buffer = await readFile(filePath);
151
151
  const mimeType = inferUploadMimeType(filePath, options?.mimeType);
152
152
  const fileName = options?.fileName ?? basename(filePath);
153
- return client.uploadMedia(conversationId, buffer.toString('base64'), mimeType, fileName);
153
+ const uploaded = await client.uploadMedia(conversationId, buffer.toString('base64'), mimeType, fileName);
154
+ if (uploaded.attachment.kind === 'audio'
155
+ && typeof options?.durationMs === 'number'
156
+ && Number.isFinite(options.durationMs)
157
+ && options.durationMs > 0) {
158
+ return {
159
+ ...uploaded,
160
+ attachment: {
161
+ ...uploaded.attachment,
162
+ durationMs: Math.round(options.durationMs),
163
+ },
164
+ };
165
+ }
166
+ return uploaded;
167
+ }
168
+ export async function sendMediaFileMessage(client, conversationId, filePath, text = '', options) {
169
+ const { fileName, mimeType, durationMs, ...sendOptions } = options ?? {};
170
+ const uploaded = await uploadMediaFile(client, conversationId, filePath, {
171
+ ...(fileName ? { fileName } : {}),
172
+ ...(mimeType ? { mimeType } : {}),
173
+ ...(durationMs != null ? { durationMs } : {}),
174
+ });
175
+ return client.sendMessage(conversationId, text, {
176
+ ...sendOptions,
177
+ contentType: uploaded.attachment.kind,
178
+ attachments: [uploaded.attachment],
179
+ });
154
180
  }
155
181
  /**
156
182
  * Resolve the effective MIME type of a materialized attachment, falling back
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@canonmsg/agent-sdk",
3
- "version": "1.1.3",
3
+ "version": "1.1.4",
4
4
  "description": "Canon Agent SDK — build AI agents that participate in Canon conversations",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",