Wave 2 prep: LedgerEvent.ref, demo bridge protocol, artifact stubs, sendText in ChatActionsContext

This commit is contained in:
Amos
2026-08-22 10:03:20 +03:00
parent 34dee919bb
commit 6a68fcfba1
6 changed files with 60 additions and 2 deletions
+10
View File
@@ -0,0 +1,10 @@
import type { ArtifactPartProps } from "@/src/core/contracts";
/**
* Demo artifact card (W6): sandboxed iframe rendering DemoResult.html with
* the auto-injected resize/error bridge (contracts.ts "Demo iframe bridge").
* While input-available: job activity card (poll /api/jobs).
*/
export function DemoCard(_props: ArtifactPartProps) {
return null;
}
+8 -1
View File
@@ -1,6 +1,9 @@
import type { ComponentType } from "react";
import type { ArtifactPartProps } from "@/src/core/contracts";
import { DemoCard } from "@/components/artifacts/demo-card";
import { JobCard } from "@/components/artifacts/job-card";
import { PlanDivider } from "@/components/artifacts/plan-divider";
import { VisualCard } from "@/components/artifacts/visual-card";
/**
* Artifact renderer registry — the extension point for tool-part UI.
@@ -16,5 +19,9 @@ import { JobCard } from "@/components/artifacts/job-card";
*/
export const artifactRenderers: Record<string, ComponentType<ArtifactPartProps>> = {
research: JobCard,
// W6: "demo" → sandboxed iframe card, "visual" → svg card
// Phase divider where the plan lands (W5 fills in the component):
plan_init: PlanDivider,
// Artifacts (W6 fills in the components):
demo: DemoCard,
visual: VisualCard,
};
+9
View File
@@ -0,0 +1,9 @@
import type { ArtifactPartProps } from "@/src/core/contracts";
/**
* Phase divider rendered where plan_init lands in the transcript (W5).
* Probe → teach transition marker per vision §2 "Two phases".
*/
export function PlanDivider(_props: ArtifactPartProps) {
return null;
}
+9
View File
@@ -0,0 +1,9 @@
import type { ArtifactPartProps } from "@/src/core/contracts";
/**
* Visual artifact card (W6): renders VisualResult.svg inline.
* While input-available: job activity card (poll /api/jobs).
*/
export function VisualCard(_props: ArtifactPartProps) {
return null;
}
+3 -1
View File
@@ -37,6 +37,8 @@ const COLUMN = "mx-auto w-full max-w-3xl px-4";
export const ChatActionsContext = createContext<{
chatId: string;
syncFromServer: () => Promise<void>;
/** Send a user message into the session (demo error-fix loop, W6). */
sendText: (text: string) => void;
} | null>(null);
/** useLayoutEffect that is silent during SSR (client components still render on the server in Next). */
@@ -143,7 +145,7 @@ export function Chat({
};
return (
<ChatActionsContext.Provider value={{ chatId, syncFromServer }}>
<ChatActionsContext.Provider value={{ chatId, syncFromServer, sendText: (t: string) => void sendMessage({ text: t }) }}>
<div className="flex h-dvh flex-col">
<header className="flex items-center gap-3 px-3 py-2">
<SidebarToggle />