@tecla/tools-sdk
v1.0.4
Published
SDK for building and hosting Tecla tools via postMessage
Downloads
4,743
Readme
@tecla/tools-sdk
SDK for building and hosting Tecla tools via postMessage. Provides React hooks for the two sides of the iframe boundary: the tool (inside the iframe) and the parent (the shell that embeds it).
Installation
npm install @tecla/tools-sdkRequires React 18 or 19 as a peer dependency.
Concepts
Tools communicate with their parent shell through postMessage. Each message follows the format {toolCode}#{eventName} with an optional payload. The tool's toolCode is the canonical identifier; id is accepted only as a legacy fallback.
Every tool has a config — validated via Zod — that the parent sends on init. The base config includes locale and theme; tools extend it with their own fields.
Built-in events:
| Direction | Event | Description |
|-----------|-------|-------------|
| Tool → Parent | ready | Sent automatically on mount. Carries widthRatio. |
| Tool → Parent | progress | Reports completion percentage. |
| Parent → Tool | init | Delivers the tool config. |
| Parent → Tool | reset | Tells the tool to return to its initial state. |
Usage
Tool side (useToolCommunication)
Used inside the iframe app. Handles the postMessage contract, sends ready on mount, and exposes typed sendMessage / onMessage helpers.
import { useToolCommunication, BaseToolConfigSchema } from '@tecla/tools-sdk'
import type { ToolConfig } from '@tecla/tools-sdk'
import { z } from 'zod'
const MyConfigSchema = BaseToolConfigSchema.extend({
prompt: z.string(),
})
type MyConfig = z.infer<typeof MyConfigSchema>
const toolDef: ToolConfig = {
toolCode: 'my-tool',
name: 'My Tool',
description: 'Does something useful.',
version: '1.0.0',
widthRatio: 0.4,
}
export function MyTool() {
const { config, sendMessage, onMessage } = useToolCommunication<MyConfig>(toolDef)
// Listen for a custom inbound event
onMessage('reset', () => {
// handle reset
})
const handleComplete = () => {
sendMessage('progress', { percentage: 100, completed: true })
}
if (!config) return <p>Waiting for init…</p>
return (
<div>
<p>{config.prompt}</p>
<button onClick={handleComplete}>Done</button>
</div>
)
}Parent side (useParentCommunication)
Used in the shell that renders the <iframe>. Tracks the full message history and sends typed messages to the tool.
import { useRef } from 'react'
import { useParentCommunication } from '@tecla/tools-sdk'
export function Shell() {
const iframeRef = useRef<HTMLIFrameElement>(null)
const { sendMessage, messages, clearMessages } = useParentCommunication(
iframeRef,
'my-tool',
{
// Automatically sent to the tool whenever it fires `ready`
autoInit: { locale: 'en', theme: 'dark', prompt: 'Hello!' },
},
)
return (
<iframe ref={iframeRef} src="https://my-tool.example.com" />
)
}Defining a tool config
// tool.config.ts
import { BaseToolConfigSchema } from '@tecla/tools-sdk'
import type { ToolConfig } from '@tecla/tools-sdk'
import { z } from 'zod'
export const ConfigSchema = BaseToolConfigSchema.extend({
apiKey: z.string(),
})
export const toolDef: ToolConfig = {
toolCode: 'my-tool',
name: 'My Tool',
description: 'Does something useful.',
version: '1.0.0',
widthRatio: 0.4,
additionalInboundEvents: [
{ name: 'update', description: 'Receive new data', schema: z.object({ value: z.string() }) },
],
additionalOutboundEvents: [
{ name: 'result', description: 'Send result back', schema: z.object({ output: z.string() }) },
],
}API
useToolCommunication(toolDef)
| Return | Type | Description |
|--------|------|-------------|
| config | TConfig \| null | Config received from the parent via init. Null until initialized. |
| sendMessage(event, payload) | function | Send a typed event to the parent. |
| onMessage(event, handler) | function | Register a handler for an inbound event. Returns a cleanup function. |
useParentCommunication(iframeRef, toolSlug, options?)
| Return | Type | Description |
|--------|------|-------------|
| sendMessage(event, payload) | function | Send a typed event to the tool. |
| messages | ToolEvent[] | Full message log (inbound + outbound). |
| clearMessages() | function | Clear the message log. |
Options:
| Option | Type | Description |
|--------|------|-------------|
| autoInit | Record<string, unknown> | Config sent automatically on every ready received from the tool. |
BaseToolConfigSchema
Zod schema with locale: string (default 'en') and theme: 'light' | 'dark' (default 'light'). Extend it for your tool's config.
License
MIT
