SDK Reference
The mini-program SDK is a ~2 KB JavaScript library that gets injected into every mini-program iframe. It provides the window.ais namespace with methods to interact with the AI Supreme Council platform through a secure postMessage bridge.
How the SDK Works
The SDK is injected as a <script> tag before your app's HTML in the iframe's srcdoc. You do not need to include it yourself -- it is always available as window.ais when your code runs.
Every method call (except platform.* properties) sends a message to the host page and returns a Promise. The host validates permissions, executes the request, and sends the result back.
Your app code SDK Host platform
| | |
|-- ais.chat.send("hi")-->| |
| |-- postMessage({ |
| | method: "chat.send", |
| | args: {text: "hi"} |
| | }) ---------------------->|
| | |-- check permissions
| | |-- execute AIS.Chat.send()
| |<-- postMessage({result}) --|
|<-- Promise resolves ---| |
All SDK methods are available synchronously as function references, but they return Promises that resolve asynchronously. Always use await or .then() to get results.
TypeScript Support
TypeScript type definitions are available in sdk/ais.d.ts. Add a reference to your project:
/// <reference path="./ais.d.ts" />
ais.ready(async () => {
const history = await ais.chat.getHistory(10);
// history is typed as ais.ChatMessage[]
});
Or copy the AisManifest and AisPermission types for manifest validation in your build tooling.
Lifecycle
ais.ready(callback)
Register a callback that fires when the platform bridge is connected and ready. This is the entry point for your app -- wrap all initialization logic inside this callback.
| Parameter | Type | Description |
|---|---|---|
callback | () => void | Function to call when the bridge is ready |
ais.ready(async function() {
// Platform is connected, SDK calls will work now
const user = await ais.auth.getUser();
document.getElementById('greeting').textContent = 'Hello, ' + user.name;
});
Do not call other ais.* methods before ais.ready() fires. The postMessage bridge may not be established yet, and calls will hang indefinitely.
ais.onShow(callback)
Register a callback that fires each time the mini-program becomes visible (e.g., user switches back to the app tab).
| Parameter | Type | Description |
|---|---|---|
callback | () => void | Function to call on show |
ais.onShow(function() {
// Refresh data when user returns to the app
refreshDashboard();
});
ais.onHide(callback)
Register a callback that fires when the mini-program is hidden (e.g., user switches to chat or another app).
| Parameter | Type | Description |
|---|---|---|
callback | () => void | Function to call on hide |
ais.onHide(function() {
// Pause expensive operations
stopPolling();
});
ais.close()
Close the mini-program and return to the chat view. The iframe is destroyed after this call.
Returns: Promise<boolean>
document.getElementById('done-btn').addEventListener('click', function() {
ais.close();
});
Storage
Per-app isolated key-value storage backed by IndexedDB. Keys are automatically namespaced with mp:{app-name}: so apps cannot access each other's data.
Permission: Always allowed -- no permission required.
ais.storage.get(key)
Retrieve a value by key. Returns undefined if the key does not exist.
| Parameter | Type | Description |
|---|---|---|
key | string | The storage key |
Returns: Promise<unknown> -- the stored value, or undefined
const count = await ais.storage.get('visit-count');
console.log('Visits:', count); // number, string, object, array, or undefined
ais.storage.set(key, value)
Store a key-value pair. The value can be any JSON-serializable type (string, number, boolean, object, array, null).
| Parameter | Type | Description |
|---|---|---|
key | string | The storage key |
value | unknown | The value to store (must be JSON-serializable) |
Returns: Promise<boolean> -- true on success
await ais.storage.set('visit-count', 42);
await ais.storage.set('preferences', { theme: 'dark', fontSize: 16 });
ais.storage.remove(key)
Delete a key from storage.
| Parameter | Type | Description |
|---|---|---|
key | string | The key to remove |
Returns: Promise<boolean> -- true on success
await ais.storage.remove('temporary-data');
ais.storage.keys()
List all keys stored by this mini-program (without the internal mp:{name}: prefix).
Returns: Promise<string[]>
const keys = await ais.storage.keys();
console.log('Stored keys:', keys); // ['visit-count', 'preferences']
Chat
Read chat history, send messages, and subscribe to new messages in the active conversation.
Permissions required: chat:read for reading, chat:write for sending.
ais.chat.getHistory(limit?)
Get recent messages from the active chat session.
| Parameter | Type | Default | Description |
|---|---|---|---|
limit | number | 50 | Maximum number of messages to return |
Returns: Promise<ChatMessage[]>
interface ChatMessage {
role: 'user' | 'assistant' | 'system';
content: string;
timestamp?: number;
}
const messages = await ais.chat.getHistory(20);
messages.forEach(function(msg) {
console.log(msg.role + ': ' + msg.content);
});
ais.chat.send(text)
Send a message as the user. This triggers the active AI model to generate a response.
| Parameter | Type | Description |
|---|---|---|
text | string | The message text to send |
Returns: Promise<boolean> -- true on success
await ais.chat.send('Summarize the last 5 messages');
Calling ais.chat.send() triggers an actual API call to the user's configured AI provider. This consumes tokens and may incur costs. Use responsibly and always inform the user before sending messages programmatically.
ais.chat.onMessage(callback)
Subscribe to new chat messages. The callback fires for every new message (both user and assistant).
| Parameter | Type | Description |
|---|---|---|
callback | (msg: ChatMessage) => void | Handler for incoming messages |
ais.chat.onMessage(function(msg) {
if (msg.role === 'assistant') {
// AI model responded
updateResponseDisplay(msg.content);
}
});
Config
Read the active bot's configuration (provider, model, system prompt, etc.).
Permission required: config:read
ais.config.get()
Get the full bot configuration object.
Returns: Promise<BotConfig>
interface BotConfig {
n?: string; // Bot name
p?: string; // Provider ID (e.g., 'anthropic', 'openai', 'gemini')
m?: string; // Model ID (e.g., 'claude-sonnet-4-20250514')
s?: string; // System prompt
t?: number; // Temperature (0.0 - 2.0)
x?: number; // Max output tokens
[key: string]: unknown;
}
const config = await ais.config.get();
console.log('Using model:', config.m);
console.log('System prompt:', config.s);
ais.config.getProvider()
Get the active provider ID.
Returns: Promise<string> -- e.g., 'anthropic', 'openai', 'gemini', 'xai', 'openrouter', 'ollama'
const provider = await ais.config.getProvider();
if (provider === 'ollama') {
showLocalModelBanner();
}
ais.config.getModel()
Get the active model ID.
Returns: Promise<string> -- e.g., 'claude-sonnet-4-20250514', 'gpt-4o', 'gemini-2.5-flash'
const model = await ais.config.getModel();
document.getElementById('model-name').textContent = model;
UI
Show notifications, confirmation dialogs, and update the apps panel title.
ais.ui.toast(message, duration?)
Display a temporary toast notification in the platform UI.
| Parameter | Type | Default | Description |
|---|---|---|---|
message | string | -- | Notification text (max 200 characters) |
duration | number | 3000 | Duration in milliseconds |
Returns: Promise<boolean>
Permission: ui:toast (recommended but not strictly enforced -- toast is low-impact)
await ais.ui.toast('File saved successfully!');
await ais.ui.toast('Processing...', 5000); // 5 second toast
ais.ui.confirm(title, message)
Show a confirmation dialog and wait for the user's response.
| Parameter | Type | Description |
|---|---|---|
title | string | Dialog title (max 100 characters) |
message | string | Dialog body text (max 500 characters) |
Returns: Promise<boolean> -- true if user clicked OK, false if cancelled
Permission required: ui:modal
const confirmed = await ais.ui.confirm(
'Delete all data?',
'This will permanently remove all saved items. This action cannot be undone.'
);
if (confirmed) {
await clearAllData();
}
ais.ui.setTitle(title)
Set the text displayed in the apps panel title bar.
| Parameter | Type | Description |
|---|---|---|
title | string | Title text (max 100 characters) |
Returns: Promise<boolean>
ais.ui.setTitle('Word Counter - 1,234 words');
Auth
Read information about the currently signed-in user.
Permission required: auth:read
ais.auth.getUser()
Get the current user's profile information.
Returns: Promise<UserInfo | null> -- null if not signed in
interface UserInfo {
name: string; // Display name
email: string; // Email address
picture: string; // Profile photo URL
}
const user = await ais.auth.getUser();
if (user) {
document.getElementById('avatar').src = user.picture;
document.getElementById('name').textContent = user.name;
} else {
document.getElementById('name').textContent = 'Guest';
}
ais.auth.getTier()
Get the user's subscription tier.
Returns: Promise<string> -- e.g., 'free', 'pro', 'team'
const tier = await ais.auth.getTier();
if (tier === 'free') {
showUpgradePrompt();
}
Secrets
Read and write API keys for device-to-device transfer scenarios. This is a privileged API used by apps like Device Sync.
Permission required: secrets:sync
The secrets:sync permission grants access to the user's stored API keys. Only request this permission if your app genuinely needs to transfer or back up credentials. Users will see a clear warning in the permission dialog.
ais.secrets.list()
List provider names that have stored API keys.
Returns: Promise<string[]> -- e.g., ['anthropic', 'openai', 'gemini']
ais.secrets.get(provider)
Get an API key value by provider name.
| Parameter | Type | Description |
|---|---|---|
provider | string | Provider name (e.g., 'anthropic', 'openai') |
Returns: Promise<string | null>
ais.secrets.set(provider, value)
Store an API key for a provider.
| Parameter | Type | Description |
|---|---|---|
provider | string | Provider name |
value | string | API key value (max 1024 characters) |
Returns: Promise<boolean>
Sync
Sync profiles, settings, and WebRTC signaling for device-to-device transfer.
Permission required: secrets:sync
ais.sync.getProfiles()
Get all user profiles from the host platform.
Returns: Promise<Profile[]>
ais.sync.setProfiles(profiles)
Import profiles into the host platform.
| Parameter | Type | Description |
|---|---|---|
profiles | Profile[] | Array of profile objects to import |
Returns: Promise<number> -- count of profiles imported
ais.sync.getSettings()
Get app settings (theme, locale, etc.) from the host.
Returns: Promise<Record<string, string>>
ais.sync.setSettings(settings)
Write app settings to the host.
| Parameter | Type | Description |
|---|---|---|
settings | Record<string, string> | Key-value settings to write |
Returns: Promise<boolean>
ais.sync.signal(code, type, sdp)
Post an SDP offer/answer to the API relay for WebRTC signaling.
| Parameter | Type | Description |
|---|---|---|
code | string | Pairing code |
type | 'offer' | 'answer' | SDP type |
sdp | RTCSessionDescriptionInit | SDP data |
Returns: Promise<boolean>
ais.sync.pollSignal(code, type)
Poll for an SDP offer/answer from the API relay.
| Parameter | Type | Description |
|---|---|---|
code | string | Pairing code |
type | 'offer' | 'answer' | SDP type to poll for |
Returns: Promise<RTCSessionDescriptionInit | null>
Hooks
Register and fire custom hook events to extend platform behavior or communicate between apps.
Permissions required: hooks:action for firing events, hooks:filter for registering filter handlers.
ais.hooks.on(hookName, handler)
Listen for a named hook event.
| Parameter | Type | Description |
|---|---|---|
hookName | string | Hook name (e.g., 'chat:before-send') |
handler | (data: unknown) => void | Event handler |
Returns: Promise<boolean>
ais.hooks.on('chat:before-send', function(data) {
console.log('Message about to be sent:', data);
});
ais.hooks.fire(hookName, data?)
Fire a named hook event. All registered handlers for this hook will be called.
| Parameter | Type | Description |
|---|---|---|
hookName | string | Hook name to fire |
data | unknown | Optional data payload |
Returns: Promise<unknown>
await ais.hooks.fire('my-app:data-updated', { count: 42 });
Pages
Publish web pages to bcz.co with a custom slug. Used by the App Builder mini-program.
Permission required: pages:publish
ais.pages.getInfo()
Get info about the user's published page.
Returns: Promise<PageInfo>
interface PageInfo {
slug: string | null;
url: string | null;
title: string | null;
updatedAt: number | null;
hasPage: boolean;
}
ais.pages.claim(slug)
Claim a slug (username) for bcz.co/@slug.
| Parameter | Type | Description |
|---|---|---|
slug | string | Desired slug |
Returns: Promise<{ slug: string; url: string }>
ais.pages.publish(specBase64, opts?)
Publish or update a page. The spec is a base64-encoded PDL document.
| Parameter | Type | Description |
|---|---|---|
specBase64 | string | Base64-encoded page spec |
opts | { title?: string; description?: string } | Optional metadata |
Returns: Promise<PublishResult>
ais.pages.unpublish()
Unpublish and release the slug.
Returns: Promise<boolean>
Platform Info
Read-only properties with platform metadata. These are synchronous -- no Promise, no permission required.
ais.platform.version
The platform version string (semver).
Type: string -- currently '1.0.0'
ais.platform.abi
The ABI version number. Used to verify compatibility between the SDK and the host platform.
Type: number -- currently 1
if (ais.platform.abi !== 1) {
ais.ui.toast('This app requires ABI version 1');
ais.close();
}
Error Handling
All SDK calls that require permissions will reject with a PermissionDenied error if the app does not have the required permission:
try {
const history = await ais.chat.getHistory();
} catch (err) {
if (err.message.includes('PermissionDenied')) {
console.log('App does not have chat:read permission');
}
}
Unknown methods return an error with the message Unknown method: {method}.
If the host platform encounters an unexpected error, the Promise rejects with the error message string.
Always wrap SDK calls in try/catch blocks, especially for permission-gated APIs. This makes your app resilient even if the user's platform version differs from what you tested against.
Complete Example
A minimal app that uses multiple SDK features:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<style>
body { font-family: system-ui; padding: 16px; color: #e0e0e0; background: #1a1a2e; }
button { min-height: 48px; padding: 8px 16px; font-size: 16px;
border: 1px solid #444; border-radius: 6px;
background: #2a2a4e; color: #e0e0e0; cursor: pointer; }
button:hover { background: #3a3a5e; }
pre { background: #111; padding: 12px; border-radius: 6px; overflow: auto; }
</style>
</head>
<body>
<h2>Chat Inspector</h2>
<button id="load">Load History</button>
<button id="close">Close</button>
<pre id="output">Click "Load History" to begin...</pre>
<script>
ais.ready(async function() {
// Show which model is active
var model = await ais.config.getModel();
ais.ui.setTitle('Chat Inspector - ' + model);
document.getElementById('load').addEventListener('click', async function() {
var messages = await ais.chat.getHistory(25);
var output = messages.map(function(m) {
return '[' + m.role + '] ' + m.content.slice(0, 100);
}).join('\n');
document.getElementById('output').textContent = output || '(no messages)';
ais.ui.toast('Loaded ' + messages.length + ' messages');
});
document.getElementById('close').addEventListener('click', function() {
ais.close();
});
// Subscribe to new messages in real time
ais.chat.onMessage(function(msg) {
var el = document.getElementById('output');
el.textContent += '\n[' + msg.role + '] ' + msg.content.slice(0, 100);
});
});
</script>
</body>
</html>
Manifest for this example:
{
"name": "chat-inspector",
"version": "1.0.0",
"abi": 1,
"type": "mini-program",
"description": "View and monitor chat history",
"entry": "index.html",
"base_url": "https://your-cdn.com/chat-inspector/",
"permissions": ["chat:read", "config:read", "ui:toast"]
}