Every scope accessor has three metadata properties: source and query describe where a scope comes from, and name is the scope's own name. They are reserved — scope methods cannot use these names.
aui.thread.source; // "root" | "parentScope" | null
aui.thread.query; // {} | { index: 0 } | null
aui.thread.name; // "thread"
Root scopes#
When you fill a scope directly via a provider's AuiConfig({ ... }), it gets source: "root" and an empty query:
const config = AuiConfig({ thread: ThreadResource() });
<AuiProvider config={config}>
aui.thread.source; // "root"
aui.thread.query; // {}
This is the default — the scope was provided directly, not derived from another scope.
Derived scopes#
When a scope is created via Derived, its source points to the parent scope it was derived from, and query carries the lookup parameters:
const aui = useAui();
const config = AuiConfig({
message: Derived({
source: "thread",
query: { index: 0 },
get: (aui) => aui.thread.message({ index: 0 }),
}),
});
<AuiProvider extends={aui} config={config}>
aui.message.source; // "thread"
aui.message.query; // { index: 0 }
You can declare the expected meta shape in ScopeRegistry:
declare module "@assistant-ui/store" {
interface ScopeRegistry {
message: {
methods: {
getState: () => { role: string; content: string };
};
meta: { source: "thread"; query: { index: number } };
};
}
}
This makes the source and query types precise — TypeScript will enforce that any Derived providing the message scope uses the correct source and query shape.
Unavailable scopes#
When a scope hasn't been provided by any AuiProvider above the current component, its accessor has source: null and query: null. name still answers; calling the accessor or reading any other property throws:
aui.message.source; // null — no message scope in context
aui.message.query; // null
aui.message.name; // "message"
aui.message.getState(); // throws
The accessor itself is always truthy, so if (aui.message) does not tell you anything. Check availability through the optional view, which resolves an unavailable scope to undefined:
if (aui.optional.message) {
// scope is available
}
Summary#
source | Meaning |
|---|---|
"root" | Scope was filled directly via AuiConfig({ ... }) |
"parentScope" | Scope was derived from another scope via Derived |
null | Scope is not available in the current context |