Ada Extensions
Concepts

Lifecycle

When your extension starts, when update runs, and how the view reaches the island.

An extension registers itself by calling AdanotchKit.activity({...}) once, at the top level of its script. Adanotch then goes through these steps:

  1. The script loads; its top-level code runs.
  2. setup(ctx) runs once.
  3. The first update(ctx) runs and its view goes to the island.
  4. From then on, update runs again every refresh interval, after every action, after every settings change, and on every ctx.refresh().
AdanotchKit.activity<Settings>({
  async setup(ctx) {
    // Once: subscribe to events, start timers, prepare the first data.
  },
  async update(ctx) {
    // Return the view.
    return { compact: { trailing: AdanotchKit.ui.text("42") } };
  },
  async onAction(action, ctx, value) {
    // A button, toggle, slider, text field or list row was used.
  },
  async onSettingsChange(ctx) {
    // The user changed a value in Settings; ctx.settings already has the new values.
  },
});

Hooks

Prop

Type

When update runs

TriggerNote
The refresh intervalrefresh in manifest.json ("5s", "10m", "1h"); 5 s if left out. "manual" never runs it on its own.
After onActionNot if the action throws.
After onSettingsChangeWhen the user changes a value in Settings.
ctx.refresh()To refresh the view from events and timers.

Overlapping runs merge

Requests that arrive while an update runs don't queue up; update runs once more when the current one ends. Calling ctx.refresh() ten times during a slow fetch means one more run, not ten.

Changing part of the view: ctx.render

When you don't want to wait for update to return (say, from a timer every second), use ctx.render. Keys you pass replace, null removes, anything you leave out stays as it is:

// Change only the compact area; the card stays as it is.
ctx.render({ compact: { trailing: ui.text("Loading…", { tone: "secondary" }) } });

// Remove the card.
ctx.render({ expanded: null });

Several render calls in one turn go out as one message. Calling render inside update and returning nothing is fine too.

Where state lives

  • Module variables (const history: number[] = []) last as long as the extension's process. They reset when Adanotch restarts, when the extension is updated, or when the process is restarted after hitting a limit.
  • ctx.storage is written to disk and survives restarts. Storage and settings

Errors

  • If update throws, the last view stays; the error shows with its source line in Settings › Extensions and in the adanotch dev output.
  • An uncaught error in an event handler or a timer is logged and doesn't stop the extension.
  • An error in setup or while loading stops the extension at once.
  • Three update errors in a row, or going over a process limit three times in a row, turns the extension off. Details: Limits.

On this page