mirror of
https://github.com/badlogic/pi-mono.git
synced 2026-11-05 23:37:25 +00:00
p2 rewritten by the Chord v2 authoring rules (decision "App authoring rules confirmed by the p2 audit"), in four parts merged together: - core: session lifecycle (relocate, clone, fork, archive) and search rebuild are persisted jobs on a new server store; Sessions v6 with client-chosen ids and visible operations; Retry answers with the worker's real outcome; workers push branch, subagent and status state to the server; roots take the method's ctx. - services: models, envs, ports, login, mcp, logs, sharing and voice follow external state (self.follow, followNative) instead of copy loops; methods answer after their state commits; presence from host.references. - chat: chat mode, artifacts and prompt resources follow Durable and native state; shell commands are Chord jobs (shellId is the requestId); status pushed before send and stop answer; race-free draft claim. - ui: optimistic updates on web (useOptimistic) and terminal (TuiScope.optimistic, extended in Chord with a reducer and a pending flag), pending states for long work, visible rollback, load waterfalls removed; merged with the one composer and immediate first send (ccff9876e) and the folder + button (5a31a6d5f). docs/optimistic-ui.md describes the pattern.
54 lines
1.8 KiB
TypeScript
54 lines
1.8 KiB
TypeScript
// Browser-only component fixture, bundled by `Browser.loadFixture`: a switch whose value is "server state" changed only
|
|
// by its call, shown through `useOptimisticCall`. The test settles each call from outside: `pass()` commits the new value
|
|
// before the call resolves (as Chord applies the answering host's state before its answer), `refuse(message)` rejects.
|
|
import { createElement, useState } from "react";
|
|
import { createRoot } from "react-dom/client";
|
|
import { errorText, useOptimisticCall } from "../../src/runtime/web.tsx";
|
|
|
|
type Settle = { pass: () => void; refuse: (message: string) => void };
|
|
const calls: Settle[] = [];
|
|
|
|
function Switch() {
|
|
const [server, setServer] = useState(false);
|
|
const [error, setError] = useState<string>();
|
|
const [shown, run, pending] = useOptimisticCall(
|
|
server,
|
|
(_, next: boolean) => next,
|
|
(reason) => setError(errorText(reason)),
|
|
);
|
|
const toggle = () => {
|
|
const next = !shown;
|
|
setError(undefined);
|
|
run(
|
|
next,
|
|
() =>
|
|
new Promise<void>((resolve, reject) =>
|
|
calls.push({
|
|
pass: () => {
|
|
setServer(next);
|
|
resolve();
|
|
},
|
|
refuse: (message) => reject(new Error(message)),
|
|
}),
|
|
),
|
|
);
|
|
};
|
|
return createElement(
|
|
"div",
|
|
null,
|
|
createElement("button", { id: "switch", type: "button", onClick: toggle }, shown ? "on" : "off"),
|
|
createElement("span", { id: "pending" }, pending ? "pending" : "idle"),
|
|
createElement("span", { id: "error" }, error ?? ""),
|
|
);
|
|
}
|
|
|
|
const element = document.createElement("div");
|
|
document.body.replaceChildren(element);
|
|
createRoot(element).render(createElement(Switch));
|
|
Object.assign(window, {
|
|
settleCall: (outcome: { pass: true } | { refuse: string }) => {
|
|
const call = calls.shift();
|
|
if (call && "pass" in outcome) call.pass();
|
|
else call?.refuse("refuse" in outcome ? outcome.refuse : "");
|
|
},
|
|
});
|