@canonmsg/agent-sdk 0.7.1 → 0.8.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/dist/index.d.ts +2 -2
- package/dist/index.js +1 -1
- package/dist/media.d.ts +42 -0
- package/dist/media.js +66 -0
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
export { CanonAgent } from './canon-agent.js';
|
|
2
2
|
export { CanonApiError } from '@canonmsg/core';
|
|
3
3
|
export { SessionManager } from './session-manager.js';
|
|
4
|
-
export { getMessageAttachments, inferUploadMimeType, materializeAttachment, materializeMessageMedia, uploadMediaFile, } from './media.js';
|
|
5
|
-
export type { MaterializeMediaOptions, MaterializedCanonAttachment, ReplyWithFileOptions, UploadMediaFileOptions, } from './media.js';
|
|
4
|
+
export { getCodexImagePath, getMessageAttachments, inferUploadMimeType, isAnthropicImageAttachment, materializeAttachment, materializeMessageMedia, resolveAttachmentMimeType, toAnthropicImageBlock, uploadMediaFile, } from './media.js';
|
|
5
|
+
export type { AnthropicImageBlock, AnthropicImageMimeType, MaterializeMediaOptions, MaterializedCanonAttachment, ReplyWithFileOptions, UploadMediaFileOptions, } from './media.js';
|
|
6
6
|
export type { SessionConfig, Session } from './session-manager.js';
|
|
7
7
|
export type { AgentContext, CanonMessage, CanonConversation, CanonResolvedWorkSession, CanonWorkSession, CanonWorkSessionContext, CanonWorkSessionConversationRole, CanonWorkSessionDisclosureMode, CanonWorkSessionParticipant, CanonWorkSessionStatus, CreateWorkSessionOptions, SendLinkedMessageOptions, SendLinkedMessageResult, SendMessageOptions, CreateConversationOptions, UpdateWorkSessionConversationOptions, } from '@canonmsg/core';
|
|
8
8
|
export type { SDKMessage, SDKConversation, CanonAgentOptions, MessageHandler, MessageHandlerContext, ProgressMessageOptions, ProgressMessageResult, SessionInfo, SessionOptions, DeliveryMode, } from './types.js';
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
export { CanonAgent } from './canon-agent.js';
|
|
2
2
|
export { CanonApiError } from '@canonmsg/core';
|
|
3
3
|
export { SessionManager } from './session-manager.js';
|
|
4
|
-
export { getMessageAttachments, inferUploadMimeType, materializeAttachment, materializeMessageMedia, uploadMediaFile, } from './media.js';
|
|
4
|
+
export { getCodexImagePath, getMessageAttachments, inferUploadMimeType, isAnthropicImageAttachment, materializeAttachment, materializeMessageMedia, resolveAttachmentMimeType, toAnthropicImageBlock, uploadMediaFile, } from './media.js';
|
package/dist/media.d.ts
CHANGED
|
@@ -20,6 +20,25 @@ export interface MaterializedCanonAttachment extends MediaAttachment {
|
|
|
20
20
|
conversationId: string;
|
|
21
21
|
messageId: string;
|
|
22
22
|
}
|
|
23
|
+
/**
|
|
24
|
+
* Anthropic `image` content blocks only accept these MIME types for
|
|
25
|
+
* base64 sources. Anything outside this set must either be re-encoded or
|
|
26
|
+
* degraded to a text reference.
|
|
27
|
+
*/
|
|
28
|
+
export type AnthropicImageMimeType = 'image/jpeg' | 'image/png' | 'image/gif' | 'image/webp';
|
|
29
|
+
/**
|
|
30
|
+
* Structural shape of an Anthropic `ImageBlockParam` (base64 source). We
|
|
31
|
+
* do not import from `@anthropic-ai/sdk` here because the agent-sdk must
|
|
32
|
+
* stay dependency-free; the Claude Code plugin re-casts to the SDK type.
|
|
33
|
+
*/
|
|
34
|
+
export interface AnthropicImageBlock {
|
|
35
|
+
type: 'image';
|
|
36
|
+
source: {
|
|
37
|
+
type: 'base64';
|
|
38
|
+
media_type: AnthropicImageMimeType;
|
|
39
|
+
data: string;
|
|
40
|
+
};
|
|
41
|
+
}
|
|
23
42
|
export declare function getMessageAttachments(message: Pick<CanonMessage, 'attachments' | 'imageUrl' | 'audioUrl' | 'audioDurationMs'>): MediaAttachment[];
|
|
24
43
|
export declare function materializeAttachment(attachment: MediaAttachment, options: MaterializeMediaOptions & {
|
|
25
44
|
index?: number;
|
|
@@ -30,3 +49,26 @@ export declare function uploadMediaFile(client: CanonClient, conversationId: str
|
|
|
30
49
|
url: string;
|
|
31
50
|
attachment: MediaAttachment;
|
|
32
51
|
}>;
|
|
52
|
+
/**
|
|
53
|
+
* Resolve the effective MIME type of a materialized attachment, falling back
|
|
54
|
+
* to filename/URL extensions when the server didn't tell us explicitly.
|
|
55
|
+
*/
|
|
56
|
+
export declare function resolveAttachmentMimeType(attachment: MaterializedCanonAttachment): string | null;
|
|
57
|
+
/**
|
|
58
|
+
* True when a materialized attachment can be sent to Anthropic as a base64
|
|
59
|
+
* `image` block (jpeg, png, gif, webp). Other images (heic, tiff, svg, …)
|
|
60
|
+
* must be re-encoded before they can be delivered as a vision block.
|
|
61
|
+
*/
|
|
62
|
+
export declare function isAnthropicImageAttachment(attachment: MaterializedCanonAttachment): boolean;
|
|
63
|
+
/**
|
|
64
|
+
* Read the materialized bytes and build an Anthropic `image` content block.
|
|
65
|
+
* Callers should first check `isAnthropicImageAttachment`; this function
|
|
66
|
+
* throws if the MIME type is not supported.
|
|
67
|
+
*/
|
|
68
|
+
export declare function toAnthropicImageBlock(attachment: MaterializedCanonAttachment): Promise<AnthropicImageBlock>;
|
|
69
|
+
/**
|
|
70
|
+
* Return the local path to pass to Codex via its `-i/--image` flag when the
|
|
71
|
+
* attachment is an image Codex can consume. Codex accepts the same MIME types
|
|
72
|
+
* as Anthropic in practice (jpeg/png/gif/webp), so we reuse the allowlist.
|
|
73
|
+
*/
|
|
74
|
+
export declare function getCodexImagePath(attachment: MaterializedCanonAttachment): string | null;
|
package/dist/media.js
CHANGED
|
@@ -1,6 +1,12 @@
|
|
|
1
1
|
import { mkdir, readFile, stat, writeFile } from 'node:fs/promises';
|
|
2
2
|
import { basename, dirname, extname, join } from 'node:path';
|
|
3
3
|
import { CANON_DIR, } from '@canonmsg/core';
|
|
4
|
+
const ANTHROPIC_IMAGE_MIME_TYPES = new Set([
|
|
5
|
+
'image/jpeg',
|
|
6
|
+
'image/png',
|
|
7
|
+
'image/gif',
|
|
8
|
+
'image/webp',
|
|
9
|
+
]);
|
|
4
10
|
const DEFAULT_MEDIA_CACHE_DIR = join(CANON_DIR, 'media-cache');
|
|
5
11
|
const EXTENSION_BY_MIME = {
|
|
6
12
|
'application/json': 'json',
|
|
@@ -164,3 +170,63 @@ export async function uploadMediaFile(client, conversationId, filePath, options)
|
|
|
164
170
|
const fileName = options?.fileName ?? basename(filePath);
|
|
165
171
|
return client.uploadMedia(conversationId, buffer.toString('base64'), mimeType, fileName);
|
|
166
172
|
}
|
|
173
|
+
/**
|
|
174
|
+
* Resolve the effective MIME type of a materialized attachment, falling back
|
|
175
|
+
* to filename/URL extensions when the server didn't tell us explicitly.
|
|
176
|
+
*/
|
|
177
|
+
export function resolveAttachmentMimeType(attachment) {
|
|
178
|
+
if (attachment.mimeType)
|
|
179
|
+
return attachment.mimeType.toLowerCase();
|
|
180
|
+
const pathExt = extname(attachment.path).toLowerCase();
|
|
181
|
+
const fromPath = MIME_BY_EXTENSION[pathExt];
|
|
182
|
+
if (fromPath)
|
|
183
|
+
return fromPath;
|
|
184
|
+
const fileExt = extname(attachment.fileName ?? '').toLowerCase();
|
|
185
|
+
const fromFileName = MIME_BY_EXTENSION[fileExt];
|
|
186
|
+
if (fromFileName)
|
|
187
|
+
return fromFileName;
|
|
188
|
+
const urlExt = extname(attachment.sourceUrl.split('?')[0] ?? '').toLowerCase();
|
|
189
|
+
const fromUrl = MIME_BY_EXTENSION[urlExt];
|
|
190
|
+
if (fromUrl)
|
|
191
|
+
return fromUrl;
|
|
192
|
+
return null;
|
|
193
|
+
}
|
|
194
|
+
/**
|
|
195
|
+
* True when a materialized attachment can be sent to Anthropic as a base64
|
|
196
|
+
* `image` block (jpeg, png, gif, webp). Other images (heic, tiff, svg, …)
|
|
197
|
+
* must be re-encoded before they can be delivered as a vision block.
|
|
198
|
+
*/
|
|
199
|
+
export function isAnthropicImageAttachment(attachment) {
|
|
200
|
+
if (attachment.kind !== 'image')
|
|
201
|
+
return false;
|
|
202
|
+
const mime = resolveAttachmentMimeType(attachment);
|
|
203
|
+
return mime != null && ANTHROPIC_IMAGE_MIME_TYPES.has(mime);
|
|
204
|
+
}
|
|
205
|
+
/**
|
|
206
|
+
* Read the materialized bytes and build an Anthropic `image` content block.
|
|
207
|
+
* Callers should first check `isAnthropicImageAttachment`; this function
|
|
208
|
+
* throws if the MIME type is not supported.
|
|
209
|
+
*/
|
|
210
|
+
export async function toAnthropicImageBlock(attachment) {
|
|
211
|
+
if (!isAnthropicImageAttachment(attachment)) {
|
|
212
|
+
throw new Error(`Canon attachment ${attachment.index} is not a supported Anthropic image (kind=${attachment.kind}, mime=${attachment.mimeType ?? 'unknown'})`);
|
|
213
|
+
}
|
|
214
|
+
const mediaType = resolveAttachmentMimeType(attachment);
|
|
215
|
+
const buffer = await readFile(attachment.path);
|
|
216
|
+
return {
|
|
217
|
+
type: 'image',
|
|
218
|
+
source: {
|
|
219
|
+
type: 'base64',
|
|
220
|
+
media_type: mediaType,
|
|
221
|
+
data: buffer.toString('base64'),
|
|
222
|
+
},
|
|
223
|
+
};
|
|
224
|
+
}
|
|
225
|
+
/**
|
|
226
|
+
* Return the local path to pass to Codex via its `-i/--image` flag when the
|
|
227
|
+
* attachment is an image Codex can consume. Codex accepts the same MIME types
|
|
228
|
+
* as Anthropic in practice (jpeg/png/gif/webp), so we reuse the allowlist.
|
|
229
|
+
*/
|
|
230
|
+
export function getCodexImagePath(attachment) {
|
|
231
|
+
return isAnthropicImageAttachment(attachment) ? attachment.path : null;
|
|
232
|
+
}
|