pomljs
Version:
Prompt Orchestration Markup Language
113 lines (110 loc) • 4.35 kB
JavaScript
import { component } from '../base.js';
import { Text, Image, ToolRequest, ToolResponse } from '../essentials.js';
import * as React from 'react';
import { parsePythonStyleSlice } from './utils.js';
/**
* Wrap the contents in a system message.
*
* @see {@link Text} for other props available.
*
* @example
* ```xml
* <system-msg>Answer concisely.</system-msg>
* ```
*/
component('SystemMessage', ['system-msg'])((props) => {
const { children, ...others } = props;
return (React.createElement(Text, { speaker: "system", ...others }, children));
});
/**
* Wrap the contents in a user message.
*
* @see {@link Text} for other props available.
*
* @example
* ```xml
* <user-msg>What is the capital of France?</user-msg>
* ```
*/
component('HumanMessage', ['human-msg'])((props) => {
const { children, ...others } = props;
return (React.createElement(Text, { speaker: "human", ...others }, children));
});
/**
* Wrap the contents in a AI message.
*
* @see {@link Text} for other props available.
*
* @example
* ```xml
* <ai-msg>Paris</ai-msg>
* ```
*/
component('AiMessage', ['ai-msg'])((props) => {
const { children, ...others } = props;
return (React.createElement(Text, { speaker: "ai", ...others }, children));
});
/**
* Display a message content.
*
* @param {object|string} content - The content of the message. It can be a string, or an array of strings and multimedia content.
*
* @example
* ```xml
* <msg-content content="What is the capital of France?" />
* ```
*/
const MessageContent = component('MessageContent', ['msg-content'])((props) => {
const { children, content, ...others } = props;
const displayStringOrMultimedia = (media, key) => {
if (typeof media === 'string') {
return (React.createElement(Text, { key: key, ...others }, media));
}
else if (media.type.startsWith('image/')) {
const image = media;
return (React.createElement(Image, { key: key, base64: image.base64, alt: image.alt, type: image.type, ...others }));
}
else if (media.type === 'application/vnd.poml.toolrequest') {
const toolRequest = media;
return (React.createElement(ToolRequest, { key: key, id: toolRequest.id, name: toolRequest.name, parameters: toolRequest.content, ...others }));
}
else if (media.type === 'application/vnd.poml.toolresponse') {
const toolResponse = media;
return (React.createElement(ToolResponse, { key: key, id: toolResponse.id, name: toolResponse.name, ...others },
React.createElement(MessageContent, { content: toolResponse.content, ...others })));
}
else {
throw new Error(`Unsupported media type: ${media.type}`);
}
};
if (typeof content === 'string') {
return displayStringOrMultimedia(content);
}
else if (Array.isArray(content)) {
return React.createElement(Text, null, content.map((item, index) => displayStringOrMultimedia(item, `content-${index}`)));
}
});
/**
* Display a conversation between system, human and AI.
*
* @param {object} messages - A list of message. Each message should have a `speaker` and a `content` field.
* @param {string} selectedMessages - The messages to be selected. If not provided, all messages will be selected.
* You can use a string like `2` to specify a single message, or slice like `2:4` to specify a range of messages (2 inclusive, 4 exclusive).
* Or use `-6:` to select the last 6 messages.
*
* @example
* ```xml
* <conversation messages="{{[{ speaker: 'human', content: 'What is the capital of France?' }, { speaker: 'ai', content: 'Paris' }]}}" />
* ```
*/
component('Conversation', ['conversation'])((props) => {
let { children, messages, selectedMessages, ...others } = props;
if (selectedMessages) {
const [start, end] = parsePythonStyleSlice(selectedMessages, messages.length);
messages = messages.slice(start, end);
}
return (React.createElement(Text, null, messages.map((message, index) => (React.createElement(Text, { key: `message-${index}`, speaker: message.speaker, ...others },
React.createElement(MessageContent, { content: message.content, ...others }))))));
});
export { MessageContent };
//# sourceMappingURL=message.js.map