feat(runtime): establish miniapp kernel and sdk design

This commit is contained in:
2026-08-05 00:46:16 +08:00
parent d8aa087bc8
commit 9fb8cd1598
86 changed files with 4615 additions and 1364 deletions
@@ -0,0 +1,251 @@
import { describe, expect, it } from "vitest";
import { decodeConversationItem, parseEnvelopeJSON } from "@/runtime/protocol/lineup-v1";
import { InteractionKernel } from "@/runtime/coordination/interaction-kernel";
function envelope(overrides: Record<string, unknown> = {}): string {
return JSON.stringify({
v: 1,
id: "evt_kernel_001",
type: "lineup.v1.text",
conversation_id: "conversation_kernel_test",
sender: { kind: "agent", id: "agent_test" },
payload: { markdown: "# Hello\n\n**trusted**" },
...overrides,
});
}
describe("InteractionKernel", () => {
it("accepts a valid typed envelope and projects its trusted markdown item", () => {
const kernel = new InteractionKernel();
const result = kernel.ingest({ raw: envelope(), source: "sync", transport_id: "41" });
expect(result.disposition).toBe("accepted");
expect(result.items).toEqual([expect.objectContaining({
kind: "markdown",
id: "evt_kernel_001",
markdown: "# Hello\n\n**trusted**",
})]);
expect(result.snapshot.seen_envelope_ids).toBe(1);
});
it("rejects invalid protocol JSON while preserving legacy plain text as safe markdown", () => {
const kernel = new InteractionKernel();
const invalidProtocol = parseEnvelopeJSON("{");
const legacyText = kernel.ingest({ raw: "{", source: "sync" });
const unknown = kernel.ingest({
raw: envelope({ id: "evt_kernel_unknown", type: "lineup.v1.unknown" }),
source: "live",
});
expect(invalidProtocol).toMatchObject({ ok: false, fallback: { code: "invalid_json" } });
expect(legacyText.items).toEqual([expect.objectContaining({ kind: "markdown", markdown: "{" })]);
expect(unknown.items).toEqual([expect.objectContaining({ kind: "fallback", reason: "unsupported_type", id: "evt_kernel_unknown" })]);
});
it("deduplicates one envelope id across sync and live transport sources", () => {
const kernel = new InteractionKernel();
const first = kernel.ingest({ raw: envelope(), source: "sync" });
const duplicate = kernel.ingest({ raw: envelope(), source: "live" });
expect(first.disposition).toBe("accepted");
expect(duplicate).toMatchObject({ disposition: "duplicate", items: [] });
expect(duplicate.snapshot.seen_envelope_ids).toBe(1);
});
it("projects the latest agent status by actor and retains a bounded dedupe set", () => {
const kernel = new InteractionKernel(2);
const thinking = kernel.ingest({
raw: envelope({ id: "evt_status_thinking", type: "lineup.v1.agent.status", payload: { status: "thinking", detail: "planning" } }),
source: "sync",
received_at: "2026-08-03T00:00:00.000Z",
});
kernel.ingest({ raw: envelope({ id: "evt_other", payload: { markdown: "one" } }), source: "sync" });
kernel.ingest({ raw: envelope({ id: "evt_newer", payload: { markdown: "two" } }), source: "sync" });
expect(thinking.snapshot.agent_presence).toEqual([expect.objectContaining({
status: "thinking",
detail: "planning",
envelope_id: "evt_status_thinking",
updated_at: "2026-08-03T00:00:00.000Z",
})]);
// The first id has expired from the bounded set and is accepted again.
expect(kernel.ingest({ raw: envelope({ id: "evt_status_thinking" }), source: "live" }).disposition).toBe("accepted");
});
it("projects tool calls by call_id and applies a result only after submission", () => {
const kernel = new InteractionKernel();
const call = kernel.ingest({
raw: envelope({
id: "evt_tool_call",
type: "lineup.v1.tool.call",
payload: { call_id: "call_kernel_001", tool: "choice", title: "Choose", prompt: "One", data: { action_group: { mode: "single-choice", actions: [{ id: "alpha", label: "Alpha" }] } } },
}),
source: "sync",
received_at: "2026-08-03T08:00:00.000Z",
});
const duplicateCallID = kernel.ingest({
raw: envelope({
id: "evt_tool_call_duplicate_id",
type: "lineup.v1.tool.call",
payload: { call_id: "call_kernel_001", tool: "choice", title: "Ignored", prompt: "Ignored", data: { action_group: { mode: "button", actions: [{ id: "beta", label: "Beta" }] } } },
}),
source: "live",
});
const earlyResult = kernel.ingest({
raw: envelope({ id: "evt_tool_result_early", type: "lineup.v1.tool.result", payload: { call_id: "call_kernel_001", status: "completed", result: {} } }),
source: "live",
});
expect(call.snapshot.tool_calls).toEqual([expect.objectContaining({ call_id: "call_kernel_001", status: "pending" })]);
expect(duplicateCallID.snapshot.tool_calls).toEqual([
expect.objectContaining({ request: expect.objectContaining({ title: "Choose" }) }),
]);
expect(earlyResult.snapshot.tool_calls).toEqual([expect.objectContaining({ status: "pending" })]);
expect(kernel.submitToolCall("call_kernel_001", "2026-08-03T08:01:00.000Z")).toMatchObject({ disposition: "accepted" });
const completed = kernel.ingest({
raw: envelope({ id: "evt_tool_result_completed", type: "lineup.v1.tool.result", payload: { call_id: "call_kernel_001", status: "completed", result: { selected: "alpha" } } }),
source: "live",
});
expect(completed.snapshot.tool_calls).toEqual([
expect.objectContaining({ call_id: "call_kernel_001", status: "completed", result: { selected: "alpha" } }),
]);
});
it("keeps malformed tool payloads on the safe fallback path", () => {
const kernel = new InteractionKernel();
const invalidCall = kernel.ingest({
raw: envelope({ id: "evt_invalid_tool_call", type: "lineup.v1.tool.call", payload: { call_id: "call_bad", tool: "shell", data: {} } }),
source: "sync",
});
const invalidResult = kernel.ingest({
raw: envelope({ id: "evt_invalid_tool_result", type: "lineup.v1.tool.result", payload: { call_id: "call_bad", status: "submitted", result: {} } }),
source: "sync",
});
expect(invalidCall.items).toEqual([expect.objectContaining({ kind: "fallback", reason: "invalid_payload" })]);
expect(invalidResult.items).toEqual([expect.objectContaining({ kind: "fallback", reason: "invalid_payload" })]);
});
it("accepts only a bounded, uniquely identified ActionGroup for choice calls", () => {
const kernel = new InteractionKernel();
const accepted = kernel.ingest({
raw: envelope({
id: "evt_choice_group",
type: "lineup.v1.tool.call",
payload: {
call_id: "call_choice_group",
tool: "choice",
title: "Pick deployment targets",
prompt: "You may select multiple targets.",
data: { action_group: { mode: "multi-choice", actions: [{ id: "staging", label: "Staging" }, { id: "production", label: "Production", description: "Requires approval" }] } },
},
}),
source: "sync",
});
const duplicateActionID = kernel.ingest({
raw: envelope({
id: "evt_choice_invalid_group",
type: "lineup.v1.tool.call",
payload: { call_id: "call_bad_group", tool: "choice", title: "Bad", prompt: "Bad", data: { action_group: { mode: "multi-choice", actions: [{ id: "same", label: "One" }, { id: "same", label: "Two" }] } } },
}),
source: "sync",
});
expect(accepted.items).toEqual([expect.objectContaining({
kind: "tool-call",
call: expect.objectContaining({ action_group: { mode: "multi-choice", actions: [{ id: "staging", label: "Staging" }, { id: "production", label: "Production", description: "Requires approval" }] } }),
})]);
expect(duplicateActionID.items).toEqual([expect.objectContaining({ kind: "fallback", reason: "invalid_payload" })]);
});
it("accepts trusted confirm and input schemas while rejecting unsafe form fields", () => {
const kernel = new InteractionKernel();
const confirm = kernel.ingest({
raw: envelope({ id: "evt_confirm", type: "lineup.v1.tool.call", payload: { call_id: "call_confirm", tool: "confirm", title: "Continue?", prompt: "This can be cancelled.", data: { confirm: { approve_label: "Continue", cancel_label: "Stop" } } } }),
source: "sync",
});
const form = kernel.ingest({
raw: envelope({ id: "evt_input", type: "lineup.v1.tool.call", payload: { call_id: "call_input", tool: "input", title: "Release", prompt: "Version and notes", data: { form: { fields: [{ id: "version", label: "Version", type: "text", required: true, pattern: "^v\\d+\\.\\d+\\.\\d+$" }, { id: "notes", label: "Notes", type: "textarea", max_length: 200 }], submit_label: "Create", cancel_label: "Cancel" } } } }),
source: "sync",
});
const invalid = kernel.ingest({
raw: envelope({ id: "evt_input_invalid", type: "lineup.v1.tool.call", payload: { call_id: "call_input_invalid", tool: "input", title: "Bad", prompt: "Bad", data: { form: { fields: [{ id: "bad", label: "Bad", type: "file" }] } } } }),
source: "sync",
});
expect(confirm.items).toEqual([expect.objectContaining({ kind: "tool-call", call: expect.objectContaining({ confirm: { approve_label: "Continue", cancel_label: "Stop" } }) })]);
expect(form.items).toEqual([expect.objectContaining({ kind: "tool-call", call: expect.objectContaining({ form: expect.objectContaining({ fields: expect.arrayContaining([expect.objectContaining({ id: "version", required: true })]) }) }) })]);
expect(invalid.items).toEqual([expect.objectContaining({ kind: "fallback", reason: "invalid_payload" })]);
});
it("aggregates structured task progress by operation_id and exposes a local cancellation request", () => {
const kernel = new InteractionKernel();
const first = kernel.ingest({
raw: envelope({ id: "evt_task_first", type: "lineup.v1.agent.progress", payload: { operation_id: "task_kernel_001", title: "Build report", percent: 15, status: "running", cancellable: true } }),
source: "sync",
});
const update = kernel.ingest({
raw: envelope({ id: "evt_task_update", type: "lineup.v1.agent.progress", payload: { operation_id: "task_kernel_001", title: "Build report", percent: 65, status: "running", cancellable: true } }),
source: "live",
});
expect(first.snapshot.tasks).toEqual([expect.objectContaining({ operation_id: "task_kernel_001", percent: 15 })]);
expect(update.snapshot.tasks).toEqual([expect.objectContaining({ operation_id: "task_kernel_001", percent: 65 })]);
expect(kernel.requestTaskCancel("task_kernel_001", "2026-08-03T09:05:00.000Z")).toMatchObject({ disposition: "accepted" });
expect(kernel.snapshot().tasks).toEqual([expect.objectContaining({ cancel_requested_at: "2026-08-03T09:05:00.000Z" })]);
});
it("admits only app identity and state for a Surface open, never an Agent-provided bundle", () => {
const safe = decodeConversationItem(envelope({
id: "evt_surface_safe",
type: "lineup.v1.ui.open",
payload: { instance_id: "task:001", app: { app_id: "lineup.task-dashboard", version: "0.1.0" }, state: { title: "Build" } },
}));
const injectedBundle = decodeConversationItem(envelope({
id: "evt_surface_bundle",
type: "lineup.v1.ui.open",
payload: { instance_id: "task:002", app: { app_id: "lineup.task-dashboard", version: "0.1.0" }, bundle_url: "https://example.invalid/app.js" },
}));
const extraAppField = decodeConversationItem(envelope({
id: "evt_surface_extra_app",
type: "lineup.v1.ui.open",
payload: { instance_id: "task:003", app: { app_id: "lineup.task-dashboard", version: "0.1.0", source: "injected" } },
}));
expect(safe).toEqual(expect.objectContaining({ kind: "surface", id: "evt_surface_safe" }));
expect(injectedBundle).toEqual(expect.objectContaining({ kind: "fallback", reason: "invalid_payload" }));
expect(extraAppField).toEqual(expect.objectContaining({ kind: "fallback", reason: "invalid_payload" }));
});
it("requires a bounded reason, expiry and exact payload shape for app calls", () => {
const valid = decodeConversationItem(envelope({
id: "evt_capability_valid", type: "lineup.v1.app.call",
payload: { call_id: "cap_001", capability: "app.open_url", reason: "打开文档", expires_at: "2026-08-04T00:00:00.000Z", arguments: { url: "https://example.com" } },
}));
const missingExpiry = decodeConversationItem(envelope({
id: "evt_capability_invalid", type: "lineup.v1.app.call",
payload: { call_id: "cap_002", capability: "app.open_url", reason: "打开文档", arguments: { url: "https://example.com" } },
}));
expect(valid).toEqual(expect.objectContaining({ kind: "app-call" }));
expect(missingExpiry).toEqual(expect.objectContaining({ kind: "fallback", reason: "invalid_payload" }));
});
it("admits artifact offers as data but rejects undeclared control fields", () => {
const safe = decodeConversationItem(envelope({
id: "evt_artifact_safe", type: "lineup.v1.artifact.offer",
payload: { artifact_id: "report_001", name: "report.pdf", mime_type: "application/pdf", size_bytes: 42, integrity: "verified", created_at: "2026-08-03T00:00:00.000Z" },
}));
const injected = decodeConversationItem(envelope({
id: "evt_artifact_injected", type: "lineup.v1.artifact.offer",
payload: { artifact_id: "report_002", name: "report.pdf", mime_type: "application/pdf", size_bytes: 42, integrity: "verified", created_at: "2026-08-03T00:00:00.000Z", url: "https://bad.example" },
}));
expect(safe).toEqual(expect.objectContaining({ kind: "artifact-offer" }));
const content = decodeConversationItem(envelope({
id: "evt_artifact_content", type: "lineup.v1.artifact.offer",
payload: { artifact_id: "report_003", name: "report.txt", mime_type: "text/plain", size_bytes: 5, integrity: "verified", created_at: "2026-08-03T00:00:00.000Z", local_ref: "artifact-cache-003", content_base64: "aGVsbG8=" },
}));
expect(content).toEqual(expect.objectContaining({ kind: "artifact-offer" }));
expect(injected).toEqual(expect.objectContaining({ kind: "fallback", reason: "invalid_payload" }));
});
});