feat(runtime): establish miniapp kernel and sdk design
This commit is contained in:
@@ -0,0 +1,62 @@
|
||||
/**
|
||||
* 面向 Agent 的客户端能力清单生成器。
|
||||
*
|
||||
* 根据当前公开的 Surface 和 Capability 计算带 revision 的 Inventory;只有可见能力变化时
|
||||
* 才更新,避免重试或内部状态抖动错误扩大 Agent 的可调用范围。
|
||||
*/
|
||||
import type { CapabilityDefinition } from "@/runtime/capabilities/capability-registry";
|
||||
import type { SurfaceRegistrySnapshot } from "@/runtime/surfaces/surface-registry";
|
||||
import type { CoreAppRecord } from "@/runtime/app-management/app-registry";
|
||||
|
||||
export type ClientInventory = Readonly<{
|
||||
revision: string;
|
||||
standard_components: readonly Readonly<{ id: "choice" | "confirm" | "input"; version: "1" }>[];
|
||||
applications: readonly Readonly<{
|
||||
id: string;
|
||||
version: string;
|
||||
surfaces: readonly Readonly<{ id: string; events: readonly string[] }>[];
|
||||
tools?: readonly Readonly<{ name: string; handling: string }>[];
|
||||
}>[];
|
||||
capabilities: readonly CapabilityDefinition[];
|
||||
}>;
|
||||
|
||||
/**
|
||||
* Builds the only inventory the Agent may receive. It is an observation of
|
||||
* host-local enablement and policy, not an install operation nor a grant of
|
||||
* authority. The model deliberately has no access to bundle IDs, code, local
|
||||
* paths, enabled timestamps, user content, cookies, or device identifiers.
|
||||
*/
|
||||
export class ClientInventoryPublisher {
|
||||
private revision = 0;
|
||||
private previousFingerprint = "";
|
||||
private current: ClientInventory | undefined;
|
||||
|
||||
public sync(surfaces: SurfaceRegistrySnapshot, capabilities: readonly CapabilityDefinition[], apps: readonly CoreAppRecord[] = []): { changed: boolean; inventory: ClientInventory } {
|
||||
const surfaceApplications = surfaces.enabled
|
||||
.map(enabled => ({ id: enabled.app_id, version: enabled.version, surfaces: [{ id: "task-dashboard" as const, events: ["cancel"] as ["cancel"] }] }))
|
||||
const manifestApplications = apps.filter(app => app.enabled).map(app => ({
|
||||
id: app.app_scope, version: app.manifest.version, surfaces: [],
|
||||
tools: app.manifest.tools.map(tool => ({ name: tool.name, handling: tool.handling })),
|
||||
}));
|
||||
const applications = [...surfaceApplications, ...manifestApplications]
|
||||
.sort((left, right) => `${left.id}@${left.version}`.localeCompare(`${right.id}@${right.version}`));
|
||||
const allowedCapabilities = [...capabilities]
|
||||
.sort((left, right) => left.name.localeCompare(right.name))
|
||||
.map(definition => ({ ...definition, input_schema: { ...definition.input_schema, required: [...definition.input_schema.required], properties: { ...definition.input_schema.properties } } }));
|
||||
const fingerprint = JSON.stringify({ applications, capabilities: allowedCapabilities });
|
||||
if (this.current && fingerprint === this.previousFingerprint) return { changed: false, inventory: this.current };
|
||||
this.revision += 1;
|
||||
this.previousFingerprint = fingerprint;
|
||||
this.current = {
|
||||
revision: `catalog-${this.revision}`,
|
||||
standard_components: [
|
||||
{ id: "choice", version: "1" },
|
||||
{ id: "confirm", version: "1" },
|
||||
{ id: "input", version: "1" },
|
||||
],
|
||||
applications,
|
||||
capabilities: allowedCapabilities,
|
||||
};
|
||||
return { changed: true, inventory: this.current };
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user