Saltar al contenido principal

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 ---| |
info

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.

ParameterTypeDescription
callback() => voidFunction 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;
});
precaución

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).

ParameterTypeDescription
callback() => voidFunction 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).

ParameterTypeDescription
callback() => voidFunction 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.

ParameterTypeDescription
keystringThe 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).

ParameterTypeDescription
keystringThe storage key
valueunknownThe 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.

ParameterTypeDescription
keystringThe 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.

ParameterTypeDefaultDescription
limitnumber50Maximum 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.

ParameterTypeDescription
textstringThe message text to send

Returns: Promise<boolean> -- true on success

await ais.chat.send('Summarize the last 5 messages');
aviso

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).

ParameterTypeDescription
callback(msg: ChatMessage) => voidHandler 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.

ParameterTypeDefaultDescription
messagestring--Notification text (max 200 characters)
durationnumber3000Duration 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.

ParameterTypeDescription
titlestringDialog title (max 100 characters)
messagestringDialog 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.

ParameterTypeDescription
titlestringTitle 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

precaución

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.

ParameterTypeDescription
providerstringProvider name (e.g., 'anthropic', 'openai')

Returns: Promise<string | null>

ais.secrets.set(provider, value)

Store an API key for a provider.

ParameterTypeDescription
providerstringProvider name
valuestringAPI 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.

ParameterTypeDescription
profilesProfile[]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.

ParameterTypeDescription
settingsRecord<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.

ParameterTypeDescription
codestringPairing code
type'offer' | 'answer'SDP type
sdpRTCSessionDescriptionInitSDP data

Returns: Promise<boolean>

ais.sync.pollSignal(code, type)

Poll for an SDP offer/answer from the API relay.

ParameterTypeDescription
codestringPairing 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.

ParameterTypeDescription
hookNamestringHook name (e.g., 'chat:before-send')
handler(data: unknown) => voidEvent 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.

ParameterTypeDescription
hookNamestringHook name to fire
dataunknownOptional 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.

ParameterTypeDescription
slugstringDesired 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.

ParameterTypeDescription
specBase64stringBase64-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.

tip

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"]
}