mirror of
https://github.com/JackChen-me/open-multi-agent.git
synced 2026-10-19 01:29:57 -05:00
The examples index is the first page most visitors open after the root README, but it never said the scripts import the framework source and need a repository checkout, which examples run without an API key, or that four integrations existed at all. - Add a "Run an example" block (clone, install, key, npx tsx) and note the two exceptions: observability-v2 needs a build, apps have their own start scripts. Explain how to port a script into a real project. - Add a "No API key needed" table for the seven offline examples. - Let the basics scripts switch provider through OMA_PROVIDER and OMA_MODEL instead of hard-coding Claude, following the convention the cookbook already uses. - List external-agent-acp, external-agent-process, with-engram, and with-tencentdb-memory, and fail test:example-catalog when a catalog entry has no link in the index so it cannot drift again. - Reorder sections so the 20-row providers table no longer sits between basics and the patterns and cookbook tables; mark production/ as empty. - Align integrations/README.md with the apps grouping and define the mcp-<server>.ts versus with-<product>/ naming by example shape.
82 lines
2.5 KiB
TypeScript
82 lines
2.5 KiB
TypeScript
/**
|
|
* Structured Multimodal Input
|
|
*
|
|
* Send an image and caller-owned message history through runAgent() without
|
|
* bypassing OMA's hooks, tracing, budgets, progress, or evaluation path.
|
|
*
|
|
* Run:
|
|
* npx tsx packages/core/examples/basics/structured-input.ts ./photo.png
|
|
*
|
|
* Prerequisites:
|
|
* ANTHROPIC_API_KEY env var must be set (default provider). To use any
|
|
* other built-in provider, set OMA_PROVIDER and OMA_MODEL plus that
|
|
* provider's key, for example:
|
|
* OMA_PROVIDER=deepseek OMA_MODEL=deepseek-chat DEEPSEEK_API_KEY=...
|
|
* OMA_PROVIDER=openai OMA_MODEL=gpt-5.4 OPENAI_API_KEY=...
|
|
* The model must accept image input. See docs/providers.md for the full
|
|
* provider and env var list.
|
|
* The image must be PNG, JPEG, GIF, or WebP.
|
|
*/
|
|
|
|
import { readFile } from 'node:fs/promises'
|
|
import { extname } from 'node:path'
|
|
|
|
import { OpenMultiAgent, type LLMMessage, type SupportedProvider } from '../../src/index.js'
|
|
|
|
// Defaults to Claude. Any built-in provider works: set OMA_PROVIDER and
|
|
// OMA_MODEL plus that provider's API key (see docs/providers.md).
|
|
const provider = (process.env.OMA_PROVIDER ?? 'anthropic') as SupportedProvider
|
|
const model = process.env.OMA_MODEL ?? 'claude-sonnet-4-6'
|
|
|
|
const imagePath = process.argv[2]
|
|
if (!imagePath) {
|
|
throw new Error('Pass an image path: npx tsx packages/core/examples/basics/structured-input.ts ./photo.png')
|
|
}
|
|
|
|
const mediaTypes: Readonly<Record<string, string>> = {
|
|
'.gif': 'image/gif',
|
|
'.jpeg': 'image/jpeg',
|
|
'.jpg': 'image/jpeg',
|
|
'.png': 'image/png',
|
|
'.webp': 'image/webp',
|
|
}
|
|
const mediaType = mediaTypes[extname(imagePath).toLowerCase()]
|
|
if (!mediaType) {
|
|
throw new Error('Unsupported image extension. Use PNG, JPEG, GIF, or WebP.')
|
|
}
|
|
|
|
const imageData = (await readFile(imagePath)).toString('base64')
|
|
const messages: LLMMessage[] = [
|
|
{
|
|
role: 'user',
|
|
content: [{ type: 'text', text: 'When I share an image, describe only visible facts.' }],
|
|
},
|
|
{
|
|
role: 'assistant',
|
|
content: [{ type: 'text', text: 'Understood.' }],
|
|
},
|
|
{
|
|
role: 'user',
|
|
content: [
|
|
{ type: 'text', text: 'Describe this image in three concise bullet points.' },
|
|
{
|
|
type: 'image',
|
|
source: {
|
|
type: 'base64',
|
|
media_type: mediaType,
|
|
data: imageData,
|
|
},
|
|
},
|
|
],
|
|
},
|
|
]
|
|
|
|
const oma = new OpenMultiAgent({
|
|
defaultProvider: provider,
|
|
defaultModel: model,
|
|
})
|
|
const result = await oma.runAgent({ name: 'vision-assistant' }, messages)
|
|
|
|
if (!result.success) throw new Error(result.output)
|
|
console.log(result.output)
|