@antglobal/copilot-cards-core
v1.0.10
Published
Core logic engine for copilot bot card SDK — no UI, pure logic (Expression Engine, Action Runner, Schema Parser, Lifecycle Manager)
Readme
@antglobal/copilot-cards-core
Core logic for schema-driven cards in AI conversations. This package has no UI or DOM dependency and can run in browsers, Node.js, WebViews, and mini-program runtimes.
It provides schema parsing, expression resolution, action execution, lifecycle management, streaming commands, legacy-schema conversion, and the shared built-in icon registry used by the Web and mini-program renderers.
Installation
npm install @antglobal/copilot-cards-coreQuick start
import {
parseSchema,
resolveExpression,
validateSchema,
type CardSchema,
} from "@antglobal/copilot-cards-core";
const schema: CardSchema = {
version: "1.0",
rootID: "root",
elements: {
root: {
id: "root",
type: "Text",
props: {
content: { type: "static", value: "Hello, Copilot Cards!" },
},
},
},
variables: {
user: { name: "Alice" },
},
};
const errors = validateSchema(schema);
if (errors.length > 0) {
throw new Error(errors.join("\n"));
}
const tree = parseSchema(schema);
const greeting = resolveExpression("Hello, ${user.name}!", schema.variables);
console.log(tree, greeting);Structured and source-located validation
Core exposes two structured validators for different input stages:
| Input | API | Import path | Result |
| --- | --- | --- | --- |
| An already parsed Schema object | validateSchemaDetailed | @antglobal/copilot-cards-core | SchemaValidationIssue[] |
| Raw JSON source text | validateSchemaText | @antglobal/copilot-cards-core/validation-text | SchemaTextValidationResult |
validation-text is an optional package subpath, not a function name. There is
no validateText export. Keeping this API in a separate entry point prevents
render-only Core consumers from bundling jsonc-parser.
validateSchema(schema) remains the compatible string[] API. Use
validateSchemaDetailed(schema) when an integration needs stable error codes,
RFC 6901 JSON Pointer paths, and localization parameters:
import {
validateSchemaDetailed,
type SchemaValidationIssue,
} from "@antglobal/copilot-cards-core";
const issues: SchemaValidationIssue[] = validateSchemaDetailed(schema);
// [{ code, path, anchorPath?, message, params? }]JSON editors can opt into strict parsing and source ranges through a separate entry point, keeping parser code out of render-only Core bundles:
import {
validateSchemaText,
type SchemaTextValidationResult,
} from "@antglobal/copilot-cards-core/validation-text";
const result: SchemaTextValidationResult = validateSchemaText(jsonText);
if (!result.valid) {
for (const issue of result.errors) {
console.log(issue.code, issue.path, issue.range);
}
} else {
// The successful result already contains the parsed Schema.
render(result.schema);
}Lines and columns are 1-based; offsets are 0-based JavaScript UTF-16 offsets.
The text API rejects comments, trailing commas, duplicate properties, inputs
over 1,000,000 characters, and nesting deeper than 128 levels. It returns at
most 50 diagnostics and sets truncated: true when more exist.
Core validates only shared SDK protocol such as roots, slots, references and Repeat bindings. It deliberately does not validate component registration, custom component props, host actions/events, injected variables, or expression result types, so custom component JSON is not rejected for business-owned data.
Capabilities
| Module | Purpose |
| --- | --- |
| Schema parser | Validates, normalizes, and converts flat schemas into render trees |
| Expression engine | Resolves ${path} templates, ternaries, logical expressions, and comparisons |
| Action runner | Executes declarative action chains in order |
| Action registry | Registers custom action handlers, optionally scoped by bot ID |
| Action provider | Resolves named action chains supplied by the host |
| Lifecycle manager | Coordinates onMount, onExposed, and onDestroy hooks |
| Streaming engine | Parses and applies incremental card commands and A2UI envelopes |
| Legacy compatibility | Detects and converts legacy card schemas |
| Icon registry | Exposes shared built-in icon names and SVG definitions |
Expressions
import {
interpolate,
resolveDeep,
resolveExpression,
} from "@antglobal/copilot-cards-core";
const context = {
user: { name: "Alice", role: "admin" },
count: 3,
};
resolveExpression("${user.name}", context); // "Alice"
resolveExpression("${count > 2}", context); // true
resolveExpression(
"${user.role === 'admin' ? 'Administrator' : 'User'}",
context,
); // "Administrator"
interpolate("Hello, ${user.name}!", context); // "Hello, Alice!"
resolveDeep({ title: "${user.name}", visible: "${count > 0}" }, context);Actions
Built-in action types are host-independent. The host supplies capabilities such as fetch, navigation, toast notifications, clipboard access, and event emission through an ActionRunnerContext.
| Action | Behavior |
| --- | --- |
| emit | Emits an event to the host |
| request | Runs an HTTP request with response mapping, polling, timeout, and deduplication support |
| setVariable | Updates a card variable |
| toast | Requests a toast notification |
| url | Requests navigation |
| copy | Requests clipboard access |
Register a custom action handler:
import {
registerActionHandler,
runActionSteps,
} from "@antglobal/copilot-cards-core";
registerActionHandler("support-bot", "trackEvent", async (step) => {
console.log("track", step.params);
});
await runActionSteps(
[{ type: "trackEvent", params: { event: "card_opened" } }],
{ botId: "support-bot", variables: {} },
);Streaming
The package exports StreamingParser, StreamingEngine, extractPartialSchema, and A2UI conversion helpers for incrementally generated cards.
import {
StreamingEngine,
StreamingParser,
} from "@antglobal/copilot-cards-core";
const parser = new StreamingParser();
const engine = new StreamingEngine({
onSurfaceCreated: (surfaceId) => console.log("created", surfaceId),
onComponentsUpdated: (surfaceId, changes) =>
console.log("components", surfaceId, changes),
onDataModelUpdated: (surfaceId, path, value) =>
console.log("data", surfaceId, path, value),
onContentAppended: (surfaceId, elementId, content) =>
console.log("content", surfaceId, elementId, content),
onSurfaceDeleted: (surfaceId) => console.log("deleted", surfaceId),
});
engine.applyBatch(parser.parse(chunk));Related packages
@antglobal/copilot-cards-web— Web Component renderer for browser and WebView applications.@antglobal/copilot-cards-mini-program— native renderer for Alipay and WeChat mini-programs.
License
MIT
