@effect-uai/ui 0.17.0 → 0.19.0-dev-20261110065930
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -1
- package/dist/UiContract.d.mts +5 -6
- package/dist/UiContract.d.mts.map +1 -1
- package/dist/UiContract.mjs.map +1 -1
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -38,7 +38,8 @@ const ChatUi = UiContract.make({ tools: [GetWeather] })
|
|
|
38
38
|
// client: the state is typed by the contract
|
|
39
39
|
const chat = Atoms.thread({ contract: ChatUi, runtime, transport, busy: "block" })
|
|
40
40
|
for (const b of thread.active?.blocks ?? [])
|
|
41
|
-
if (b.type === "tool" && b.name === "get_weather"
|
|
41
|
+
if (b.type === "tool" && b.name === "get_weather" && b.outcome?._tag === "Success")
|
|
42
|
+
b.outcome.value.observedAt // Date
|
|
42
43
|
```
|
|
43
44
|
|
|
44
45
|
Client:
|
package/dist/UiContract.d.mts
CHANGED
|
@@ -28,14 +28,13 @@ type Spec = {
|
|
|
28
28
|
readonly metadata?: AnyCodec;
|
|
29
29
|
};
|
|
30
30
|
type InputOf<S> = S extends Schema.Top ? S["Type"] : S extends ToolInputSchema<infer A> ? A : Json;
|
|
31
|
-
type
|
|
32
|
-
readonly _tag: "LocalTool";
|
|
33
|
-
}
|
|
31
|
+
type CoreTool = {
|
|
32
|
+
readonly _tag: "LocalTool" | "DeclaredTool";
|
|
33
|
+
};
|
|
34
|
+
type OutputOf<T> = T extends CoreTool ? Tool.ToolOutput<T> : T extends {
|
|
34
35
|
readonly outputSchema: infer O extends Schema.Top;
|
|
35
36
|
} ? O["Type"] : Content.Value;
|
|
36
|
-
type FailureOf<T> = T extends {
|
|
37
|
-
readonly _tag: "LocalTool";
|
|
38
|
-
} ? Tool.ToolFailure<T> : T extends {
|
|
37
|
+
type FailureOf<T> = T extends CoreTool ? Tool.ToolFailure<T> : T extends {
|
|
39
38
|
readonly failureSchema: infer F extends Schema.Top;
|
|
40
39
|
} ? F["Type"] : never;
|
|
41
40
|
type ToolOf<T> = T extends ToolSpec ? {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"UiContract.d.mts","names":[],"sources":["../src/UiContract.ts"],"mappings":";;;;;;;;;;;;;KAuCK,WAAW,OAAO;KAElB,YAAY,OAAO,WAAW,OAAO;;KAG9B;WACD;WACA,aAAa,WAAW;WACxB,eAAe;WACf,gBAAgB;;KAGf;WACD,QAAQ,cAAc;WACtB,UAAU,SAAS,eAAe;WAClC,OAAO,SAAS,eAAe;WAC/B,OAAO,SAAS,eAAe;WAC/B,WAAW;;KAGjB,QAAQ,KAAK,UAAU,OAAO,MAAM,YAAY,UAAU,sBAAsB,KAAK,IAAI;KAGzF,SAAS,KAAK
|
|
1
|
+
{"version":3,"file":"UiContract.d.mts","names":[],"sources":["../src/UiContract.ts"],"mappings":";;;;;;;;;;;;;KAuCK,WAAW,OAAO;KAElB,YAAY,OAAO,WAAW,OAAO;;KAG9B;WACD;WACA,aAAa,WAAW;WACxB,eAAe;WACf,gBAAgB;;KAGf;WACD,QAAQ,cAAc;WACtB,UAAU,SAAS,eAAe;WAClC,OAAO,SAAS,eAAe;WAC/B,OAAO,SAAS,eAAe;WAC/B,WAAW;;KAGjB,QAAQ,KAAK,UAAU,OAAO,MAAM,YAAY,UAAU,sBAAsB,KAAK,IAAI;KAGzF;WAAsB;;KACtB,SAAS,KAAK,UAAU,WACzB,KAAK,WAAW,KAChB;WAAqB,oBAAoB,UAAU,OAAO;IACxD,YACA,QAAQ;KACT,UAAU,KAAK,UAAU,WAC1B,KAAK,YAAY,KACjB;WAAqB,qBAAqB,UAAU,OAAO;IACzD;KAED,OAAO,KAAK,UAAU;WAEZ,MAAM;WACN,OAAO,QAAQ;WACf,QAAQ,SAAS;WACjB,SAAS,UAAU,KAAK,WAAW;;KAG7C,UAAU,KAAK,UAAU,oBAAoB,KAAK;KAClD,QAAQ,iBACD,WAAW;WACV,MAAM;WACN,OAAO,EAAE,WAAW,OAAO,MAAM,EAAE;WAExC;;KAEI,WAAW,UAAU;WACtB,MAAM,OAAO,UAAU;WACvB,QAAQ,QAAQ;WAChB,MAAM,QAAQ;WACd,MAAM,QAAQ;WACd,UAAU,sBAAsB,OAAO,MAAM,wBAAwB;;KAG3E,OAAO,KAAK;WAAqB,YAAY;IAAM;KACnD,QAAQ,GAAG,KACd,QAAQ;WAAc,MAAM;;WAAwB,aAAa;IAAM;KACpE,UAAU,GAAG,GAAG,kCACnB,QAAQ;WAAc,MAAM;kBAAmB,UAAU,eAAc,EAAE;;KAG/D,KAAK;WAAwC;WAA0B,MAAM;;;;;;KAM7E,SAAS,KAAK,UAAU,iBAAiB,KAAK;UAEzC,WAAW,UAAU;;EAEpC,OAAO,UAAU,WAAW,OAAO,OAAO,SAAS,IAAI,OAAO;;WAErD,UAAU,OAAO,MAAM,SAAS,IAAI;;WAEpC,SAAS,OAAO,MAAM,QAAgB,IAAI;;WAE1C,QAAQ,OAAO,MAAM,OAAc,IAAI;;EAEhD,KAAK,UAAU,OAAO,YACpB,MAAM,GACN,OAAO,QAAQ,WAAW,IAC1B;aAAqB;MACpB,OAAO,OAAO,UAAU,OAAO;;EAElC,KAAK,UAAU,OAAO,YACpB,MAAM,GACN,OAAO,QAAQ,WAAW,KACzB,OAAO,OAAO,UAAU,OAAO;;EAElC,SAAS,OAAO,gBAAgB,OAAO,OAAO,MAAM,OAAO;;EAE3D,UAAU,OAAO,UAAU,YAAY,OAAO,OAAO,UAAU,OAAO;;EAEtE,WAAW,MAAM,MAAM,gBAAgB,eAAe,OAAO,OAAO,UAAU,OAAO;;EAErF,QAAQ,UAAU,OAAO,YACvB,MAAM,KAAK,IACX,OAAO,UAAU,WAAW,eAC3B,OAAO,OAAO,UAAU,OAAO;;EAElC,QAAQ,UAAU,OAAO,YACvB,MAAM,KAAK,IACX,OAAO,UAAU,WAAW,gBAC3B,OAAO,OAAO,UAAU,OAAO;;;;;;iBAyEpB,WAAW,UAAU,MAAM,MAAM,IAAI,WAAW,WAAW"}
|
package/dist/UiContract.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"UiContract.mjs","names":["Event.Outcome","Event.outcome","Event.ToolCallReady","Event.ToolApprovalRequested","Event.Data","Event.Live","Event.envelopeFields","RunView.schema","RunView.contentBlocks","RunView.toolBlock","RunView.objectBlock","RunView.unnamedObject","RunView.dataBlock","Thread.State","Thread.UserContent"],"sources":["../src/UiContract.ts"],"sourcesContent":["/**\n * A typed contract between server and client, built from Schemas only, so\n * both sides import the same value (the pattern of Effect's `HttpApi`). The\n * wire stays JSON; the client decodes each envelope once on arrival, and from\n * then on the state holds decoded values: a tool block narrowed by `name`\n * has its tool's input and output types, a `Date` is a `Date`.\n *\n * const ChatUi = UiContract.make({ tools: [GetWeather], live: { metrics: Metrics } })\n *\n * // server: typed payload events (tool outputs are encoded by the Toolkit)\n * yield* ChatUi.live(\"metrics\", { tokps: 42 })\n *\n * // client: the state is typed by the contract\n * const chat = Atoms.thread({ contract: ChatUi, transport, busy: \"block\" })\n *\n * The types list the contract's names only, so narrowing by name is exact. A\n * name the contract doesn't list (a newer server rolling out a tool) still\n * arrives, as JSON, but the types don't mention it: a `switch (b.name)` skips\n * it. A listed name whose payload doesn't decode fails the envelope: that is\n * a contract violation, not data to show.\n *\n * A tool is a core `Tool` or a shared spec (`as const`, schemas only). Its\n * result is `Success { value } | Failure { error }`: the error is the tool's\n * `failureSchema` (app closings like `ToolDecision.Denied` included) or core's\n * `ToolOutput.CoreError`.\n * Without `outputSchema`, values are a `Content.Value` (media as classes).\n */\nimport * as Content from \"@effect-uai/core/Content\"\nimport type * as Items from \"@effect-uai/core/Items\"\nimport type * as Tool from \"@effect-uai/core/Tool\"\nimport type { ToolInputSchema } from \"@effect-uai/core/Tool\"\nimport type * as ToolEvent from \"@effect-uai/core/ToolEvent\"\nimport * as ToolOutput from \"@effect-uai/core/ToolOutput\"\nimport { Effect, HashMap, Match, Option, Result, Schema } from \"effect\"\nimport * as Event from \"./RunEvent.js\"\nimport type { Envelope, Json, Payloads as AnyPayloads, RunEvent, ToolPayload } from \"./RunEvent.js\"\nimport * as RunView from \"./RunView.js\"\nimport * as Thread from \"./Thread.js\"\n\ntype AnyCodec = Schema.Codec<any, any, never, never>\n// Tool values reach history and the UI through the same schema, so it must encode to JSON.\ntype JsonCodec = Schema.Codec<any, Schema.Json, never, never>\n\n/** A tool as the contract sees it: a core `Tool` or a shared spec (`as const`). */\nexport type ToolSpec = {\n readonly name: string\n readonly inputSchema: AnyCodec | ToolInputSchema<any>\n readonly outputSchema?: JsonCodec\n readonly failureSchema?: JsonCodec\n}\n\nexport type Spec = {\n readonly tools?: ReadonlyArray<ToolSpec>\n readonly objects?: Readonly<Record<string, AnyCodec>>\n readonly data?: Readonly<Record<string, AnyCodec>>\n readonly live?: Readonly<Record<string, AnyCodec>>\n readonly metadata?: AnyCodec\n}\n\ntype InputOf<S> = S extends Schema.Top ? S[\"Type\"] : S extends ToolInputSchema<infer A> ? A : Json\n// A core `Tool` carries its types; a spec has them in its schemas. Without\n// `outputSchema` a tool returns a `Content.Value`, and that is what arrives.\ntype OutputOf<T> = T extends { readonly _tag: \"LocalTool\" }\n ? Tool.ToolOutput<T>\n : T extends { readonly outputSchema: infer O extends Schema.Top }\n ? O[\"Type\"]\n : Content.Value\ntype FailureOf<T> = T extends { readonly _tag: \"LocalTool\" }\n ? Tool.ToolFailure<T>\n : T extends { readonly failureSchema: infer F extends Schema.Top }\n ? F[\"Type\"]\n : never\ntype ToolOf<T> = T extends ToolSpec\n ? {\n readonly name: T[\"name\"]\n readonly input: InputOf<T[\"inputSchema\"]>\n readonly output: OutputOf<T>\n readonly failure: FailureOf<T> | ToolOutput.CoreError\n }\n : never\ntype ElementOf<T> = T extends ReadonlyArray<infer E> ? E : never\ntype NamedOf<M> = {\n readonly [K in keyof M & string]: {\n readonly name: K\n readonly value: M[K] extends Schema.Top ? M[K][\"Type\"] : never\n }\n}[keyof M & string]\n/** The payload types a spec describes: its listed names only. */\nexport type PayloadsOf<S extends Spec> = {\n readonly tool: ToolOf<ElementOf<S[\"tools\"]>>\n readonly object: NamedOf<S[\"objects\"]>\n readonly data: NamedOf<S[\"data\"]>\n readonly live: NamedOf<S[\"live\"]>\n readonly metadata: S[\"metadata\"] extends Schema.Top ? S[\"metadata\"][\"Type\"] : Json\n}\n\ntype NameOf<T> = T extends { readonly name: infer N } ? N : never\ntype ValueOf<T, N> =\n Extract<T, { readonly name: N }> extends { readonly value: infer V } ? V : never\ntype ToolField<T, N, K extends \"output\" | \"failure\"> =\n Extract<T, { readonly name: N }> extends infer X extends ToolPayload ? X[K] : never\n\n/** The call an app closes itself: its id and the tool's name. */\nexport type Call<N extends string = string> = { readonly call_id: string; readonly name: N }\n\n/**\n * A contract's payload types, for the generic folds:\n * `Thread.presetFor<UiContract.Payloads<typeof ChatUi>>()`.\n */\nexport type Payloads<C> = C extends UiContract<infer P> ? P : never\n\nexport interface UiContract<P extends AnyPayloads> {\n /** Decode a wire envelope (as `Client` reads it) into a typed one. */\n decode(envelope: Envelope): Effect.Effect<Envelope<P>, Schema.SchemaError>\n /** Typed envelope ⇄ wire envelope. */\n readonly Envelope: Schema.Codec<Envelope<P>, Envelope>\n /** A typed run view ⇄ the untyped one, for persisting or a framework's model. */\n readonly RunView: Schema.Codec<RunView.RunView<P>, RunView.RunView>\n /** A typed `Thread` ⇄ the untyped one. */\n readonly Thread: Schema.Codec<Thread.Thread<P>, Thread.Thread>\n /** Server: a `data` event with its value encoded for the wire. */\n data<N extends NameOf<P[\"data\"]>>(\n name: N,\n value: ValueOf<P[\"data\"], N>,\n options?: { readonly id?: string },\n ): Effect.Effect<RunEvent, Schema.SchemaError>\n /** Server: a `live` event with its value encoded for the wire. */\n live<N extends NameOf<P[\"live\"]>>(\n name: N,\n value: ValueOf<P[\"live\"], N>,\n ): Effect.Effect<RunEvent, Schema.SchemaError>\n /** Server: run metadata encoded for `run-completed`. */\n metadata(value: P[\"metadata\"]): Effect.Effect<Json, Schema.SchemaError>\n /** Server: a toolkit event (`Toolkit.run`) encoded with the tool's schemas. */\n toolEvent(event: ToolEvent.ToolEvent): Effect.Effect<RunEvent, Schema.SchemaError>\n /** Server: a history item (already encoded) as the `tool-result` of tool `name`. */\n toolOutput(item: Items.ToolCallOutput, name: string): Effect.Effect<RunEvent, Schema.SchemaError>\n /** Server: close a call with a value of its tool's output (e.g. supplied by the user). */\n success<N extends NameOf<P[\"tool\"]>>(\n call: Call<N>,\n value: ToolField<P[\"tool\"], N, \"output\">,\n ): Effect.Effect<RunEvent, Schema.SchemaError>\n /** Server: close a call with an error (e.g. the app's `Denied`). */\n failure<N extends NameOf<P[\"tool\"]>>(\n call: Call<N>,\n error: ToolField<P[\"tool\"], N, \"failure\">,\n ): Effect.Effect<RunEvent, Schema.SchemaError>\n}\n\n// ---------------------------------------------------------------------------\n// Runtime: one schema member per listed name, plus a fallback for the rest\n// ---------------------------------------------------------------------------\n\nconst json = <S extends Schema.Top>(schema: S) => Schema.toCodecJson(schema)\nconst listed = (name: string) => Schema.Literal(name)\nconst unlisted = (names: ReadonlyArray<string>) =>\n Schema.String.check(Schema.makeFilter((name: string) => !names.includes(name)))\n\n/** A payload codec: decodes from JSON without services. */\ntype PayloadCodec = Schema.Codec<unknown, unknown, never, never>\n\n// A core `Tool` built from an Effect Schema keeps it (`fromEffectSchema`), so it decodes too.\nconst isCodec = (schema: ToolSpec[\"inputSchema\"]): schema is AnyCodec => Schema.isSchema(schema)\n\n// Effect Schemas decode the model's JSON; other Standard Schemas validate it as is.\nconst inputCodec = (tool: ToolSpec): PayloadCodec => {\n const schema = tool.inputSchema\n if (isCodec(schema)) return json(schema)\n return Schema.declare((u: unknown): u is Json => {\n const result = schema[\"~standard\"].validate(u)\n return !(result instanceof Promise) && result.issues === undefined\n })\n}\n// \"Anything\": a tool typed `Content.Value`, or a name the contract doesn't list.\nconst isAnything = (tool: ToolSpec | undefined): boolean =>\n tool?.outputSchema === undefined || tool.outputSchema === Content.Value\n\n// The tool's own schemas, as `Toolkit.output` uses them: they encode to JSON, so\n// the UI and history agree by construction (no `toCodecJson` on top). \"Anything\"\n// travels as typed parts, so JSON can't be mistaken for media.\nconst outputCodec = (tool: ToolSpec | undefined): PayloadCodec =>\n isAnything(tool) ? ToolOutput.ValueParts : (tool?.outputSchema ?? ToolOutput.ValueParts)\n\nconst encodeParts = Schema.encodeEffect(Schema.Array(ToolOutput.PartJson))\n\nconst failureCodec = (tool: ToolSpec | undefined): PayloadCodec =>\n tool?.failureSchema === undefined\n ? ToolOutput.CoreError\n : Schema.Union([tool.failureSchema, ToolOutput.CoreError])\n\nconst entries = (record: Readonly<Record<string, AnyCodec>> | undefined) =>\n Object.entries(record ?? {})\n\n/** Encoded loosely; `make`'s signature carries the types. */\ntype Loose = {\n decode(envelope: Envelope): Effect.Effect<unknown, Schema.SchemaError>\n readonly Envelope: Schema.Top\n readonly RunView: Schema.Top\n readonly Thread: Schema.Top\n data(\n name: string,\n value: unknown,\n options?: { readonly id?: string },\n ): Effect.Effect<RunEvent, Schema.SchemaError>\n live(name: string, value: unknown): Effect.Effect<RunEvent, Schema.SchemaError>\n metadata(value: unknown): Effect.Effect<Json, Schema.SchemaError>\n toolEvent(event: ToolEvent.ToolEvent): Effect.Effect<RunEvent, Schema.SchemaError>\n toolOutput(item: Items.ToolCallOutput, name: string): Effect.Effect<RunEvent, Schema.SchemaError>\n success(call: Call, value: unknown): Effect.Effect<RunEvent, Schema.SchemaError>\n failure(call: Call, error: unknown): Effect.Effect<RunEvent, Schema.SchemaError>\n}\n\nconst toJson = Schema.decodeUnknownEffect(Schema.Json)\nconst toOutcome = Schema.decodeUnknownEffect(Event.Outcome)\n\n/**\n * Build a contract. Tool names must be literal types: pass core `Tool`s or\n * specs declared `as const`.\n */\nexport function make<const S extends Spec>(spec: S): UiContract<PayloadsOf<S>>\nexport function make(spec: Spec): Loose {\n const tools = spec.tools ?? []\n const objects = entries(spec.objects)\n const data = entries(spec.data)\n const live = entries(spec.live)\n const toolNames = tools.map((t) => t.name)\n const metadata = spec.metadata === undefined ? Schema.Json : json(spec.metadata)\n const resultCodec = (tool: ToolSpec | undefined) =>\n Event.outcome(outputCodec(tool), failureCodec(tool))\n // Built once per tool; an unlisted name falls back to the tool-less codecs.\n const codecsOf = (tool: ToolSpec | undefined) => ({\n output: outputCodec(tool),\n result: resultCodec(tool),\n anything: isAnything(tool),\n })\n const unlistedCodecs = codecsOf(undefined)\n const codecsByName = HashMap.fromIterable(tools.map((t) => [t.name, codecsOf(t)] as const))\n const codecs = (name: string) =>\n Option.getOrElse(HashMap.get(codecsByName, name), () => unlistedCodecs)\n\n const interrupt = Schema.Union([\n ...tools.map((t) =>\n Schema.Struct({ ...Event.Interrupt.fields, name: listed(t.name), input: inputCodec(t) }),\n ),\n Schema.Struct({ ...Event.Interrupt.fields, name: unlisted(toolNames) }),\n ])\n\n const toolInput = (event: typeof Event.ToolCallReady | typeof Event.ToolApprovalRequested) =>\n Schema.Union([\n ...tools.map((t) =>\n Schema.Struct({ ...event.fields, name: listed(t.name), input: inputCodec(t) }),\n ),\n Schema.Struct({ ...event.fields, name: unlisted(toolNames) }),\n ])\n\n const named = (\n event: typeof Event.Data | typeof Event.Live,\n members: ReadonlyArray<readonly [string, AnyCodec]>,\n ) =>\n Schema.Union([\n ...members.map(([name, schema]) =>\n Schema.Struct({ ...event.fields, name: listed(name), value: json(schema) }),\n ),\n Schema.Struct({ ...event.fields, name: unlisted(members.map(([name]) => name)) }),\n ])\n\n const event = Schema.Union([\n ...Event.plainEvents.map((e) => Schema.toType(e)),\n Schema.Struct({ ...Event.RunCompleted.fields, metadata: Schema.optional(metadata) }),\n Schema.Struct({ ...Event.RunInterrupted.fields, interrupts: Schema.Array(interrupt) }),\n Schema.Union([\n ...objects.map(([name, schema]) =>\n Schema.Struct({ ...Event.ObjectDone.fields, name: listed(name), value: json(schema) }),\n ),\n Schema.Struct({\n ...Event.ObjectDone.fields,\n name: Schema.optional(unlisted(objects.map(([name]) => name))),\n }),\n ]),\n toolInput(Event.ToolCallReady),\n toolInput(Event.ToolApprovalRequested),\n Schema.Union([\n ...tools.map((t) =>\n Schema.Struct({ ...Event.ToolPartial.fields, name: listed(t.name), value: outputCodec(t) }),\n ),\n Schema.Struct({ ...Event.ToolPartial.fields, name: unlisted(toolNames) }),\n ]),\n Schema.Union([\n ...tools.map((t) =>\n Schema.Struct({ ...Event.ToolResult.fields, name: listed(t.name), result: resultCodec(t) }),\n ),\n Schema.Struct({ ...Event.ToolResult.fields, name: unlisted(toolNames) }),\n ]),\n named(Event.Data, data),\n named(Event.Live, live),\n ])\n const envelope = Schema.Struct({ ...Event.envelopeFields, event })\n\n const view = RunView.schema({\n block: Schema.Union([\n ...RunView.contentBlocks,\n ...tools.map((t) =>\n RunView.toolBlock(listed(t.name), inputCodec(t), outputCodec(t), failureCodec(t)),\n ),\n RunView.toolBlock(unlisted(toolNames), Schema.Json, Schema.Json, Schema.Json),\n ...objects.map(([name, schema]) => RunView.objectBlock(listed(name), json(schema))),\n RunView.objectBlock(unlisted(objects.map(([name]) => name)), Schema.Json),\n RunView.unnamedObject,\n ...data.map(([name, schema]) => RunView.dataBlock(listed(name), json(schema))),\n RunView.dataBlock(unlisted(data.map(([name]) => name)), Schema.Json),\n ]),\n interrupt,\n // Unlisted live values are transient and untyped: the schema keeps listed ones only.\n live: Schema.Struct(\n Object.fromEntries(live.map(([name, schema]) => [name, Schema.optionalKey(json(schema))])),\n ),\n metadata,\n })\n\n const codecOf = (members: ReadonlyArray<readonly [string, AnyCodec]>, name: string) =>\n members.find(([n]) => n === name)?.[1]\n const encode = (schema: AnyCodec | undefined, value: unknown) =>\n Schema.encodeUnknownEffect(schema === undefined ? Schema.Json : json(schema))(value).pipe(\n Effect.flatMap(toJson),\n )\n const toolResult = (call: Call, outcome: Event.Outcome<unknown, unknown>) =>\n Schema.encodeUnknownEffect(codecs(call.name).result)(outcome).pipe(\n Effect.flatMap(toOutcome),\n Effect.map((result): RunEvent => ({\n type: \"tool-result\",\n callId: call.call_id,\n name: call.name,\n result,\n })),\n )\n\n return {\n decode: Schema.decodeUnknownEffect(envelope),\n Envelope: envelope,\n RunView: view,\n Thread: Thread.State(Thread.UserContent, view, view),\n data: (name, value, options) =>\n encode(codecOf(data, name), value).pipe(\n Effect.map((encoded): RunEvent =>\n options?.id === undefined\n ? { type: \"data\", name, value: encoded }\n : { type: \"data\", name, value: encoded, id: options.id },\n ),\n ),\n live: (name, value) =>\n encode(codecOf(live, name), value).pipe(\n Effect.map((encoded): RunEvent => ({ type: \"live\", name, value: encoded })),\n ),\n metadata: (value) => encode(spec.metadata, value),\n toolEvent: (event) =>\n Match.value(event).pipe(\n Match.tagsExhaustive({\n Partial: (e) =>\n Schema.encodeUnknownEffect(codecs(e.tool).output)(e.value).pipe(\n Effect.flatMap(toJson),\n Effect.map((value): RunEvent => ({\n type: \"tool-partial\",\n callId: e.call_id,\n name: e.tool,\n value,\n })),\n ),\n Output: (e) =>\n toolResult(\n { call_id: e.call_id, name: e.tool },\n Result.match(e.result, {\n onSuccess: (value): Event.Outcome<unknown, unknown> => ({ _tag: \"Success\", value }),\n onFailure: (error): Event.Outcome<unknown, unknown> => ({ _tag: \"Failure\", error }),\n }),\n ),\n }),\n ),\n // The item holds the encoded value: \"anything\" goes as its parts, the rest as the JSON they encode.\n toolOutput: (item, name) =>\n Match.value(item).pipe(\n Match.when({ isError: true }, (o) =>\n Effect.map(ToolOutput.encoded(o.output), (error) => ({ _tag: \"Failure\", error })),\n ),\n Match.orElse((o) =>\n Effect.map(\n codecs(name).anything ? encodeParts(o.output) : ToolOutput.encoded(o.output),\n (value) => ({ _tag: \"Success\", value }),\n ),\n ),\n Effect.flatMap(toOutcome),\n Effect.map((result): RunEvent => ({\n type: \"tool-result\",\n callId: item.call_id,\n name,\n result,\n })),\n ),\n success: (call, value) => toolResult(call, { _tag: \"Success\", value }),\n failure: (call, error) => toolResult(call, { _tag: \"Failure\", error }),\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"UiContract.mjs","names":["Event.Outcome","Event.outcome","Event.ToolCallReady","Event.ToolApprovalRequested","Event.Data","Event.Live","Event.envelopeFields","RunView.schema","RunView.contentBlocks","RunView.toolBlock","RunView.objectBlock","RunView.unnamedObject","RunView.dataBlock","Thread.State","Thread.UserContent"],"sources":["../src/UiContract.ts"],"sourcesContent":["/**\n * A typed contract between server and client, built from Schemas only, so\n * both sides import the same value (the pattern of Effect's `HttpApi`). The\n * wire stays JSON; the client decodes each envelope once on arrival, and from\n * then on the state holds decoded values: a tool block narrowed by `name`\n * has its tool's input and output types, a `Date` is a `Date`.\n *\n * const ChatUi = UiContract.make({ tools: [GetWeather], live: { metrics: Metrics } })\n *\n * // server: typed payload events (tool outputs are encoded by the Toolkit)\n * yield* ChatUi.live(\"metrics\", { tokps: 42 })\n *\n * // client: the state is typed by the contract\n * const chat = Atoms.thread({ contract: ChatUi, transport, busy: \"block\" })\n *\n * The types list the contract's names only, so narrowing by name is exact. A\n * name the contract doesn't list (a newer server rolling out a tool) still\n * arrives, as JSON, but the types don't mention it: a `switch (b.name)` skips\n * it. A listed name whose payload doesn't decode fails the envelope: that is\n * a contract violation, not data to show.\n *\n * A tool is a core `Tool` or a shared spec (`as const`, schemas only). Its\n * result is `Success { value } | Failure { error }`: the error is the tool's\n * `failureSchema` (app closings like `ToolDecision.Denied` included) or core's\n * `ToolOutput.CoreError`.\n * Without `outputSchema`, values are a `Content.Value` (media as classes).\n */\nimport * as Content from \"@effect-uai/core/Content\"\nimport type * as Items from \"@effect-uai/core/Items\"\nimport type * as Tool from \"@effect-uai/core/Tool\"\nimport type { ToolInputSchema } from \"@effect-uai/core/Tool\"\nimport type * as ToolEvent from \"@effect-uai/core/ToolEvent\"\nimport * as ToolOutput from \"@effect-uai/core/ToolOutput\"\nimport { Effect, HashMap, Match, Option, Result, Schema } from \"effect\"\nimport * as Event from \"./RunEvent.js\"\nimport type { Envelope, Json, Payloads as AnyPayloads, RunEvent, ToolPayload } from \"./RunEvent.js\"\nimport * as RunView from \"./RunView.js\"\nimport * as Thread from \"./Thread.js\"\n\ntype AnyCodec = Schema.Codec<any, any, never, never>\n// Tool values reach history and the UI through the same schema, so it must encode to JSON.\ntype JsonCodec = Schema.Codec<any, Schema.Json, never, never>\n\n/** A tool as the contract sees it: a core `Tool` or a shared spec (`as const`). */\nexport type ToolSpec = {\n readonly name: string\n readonly inputSchema: AnyCodec | ToolInputSchema<any>\n readonly outputSchema?: JsonCodec\n readonly failureSchema?: JsonCodec\n}\n\nexport type Spec = {\n readonly tools?: ReadonlyArray<ToolSpec>\n readonly objects?: Readonly<Record<string, AnyCodec>>\n readonly data?: Readonly<Record<string, AnyCodec>>\n readonly live?: Readonly<Record<string, AnyCodec>>\n readonly metadata?: AnyCodec\n}\n\ntype InputOf<S> = S extends Schema.Top ? S[\"Type\"] : S extends ToolInputSchema<infer A> ? A : Json\n// A core `Tool` carries its types; a spec has them in its schemas. Without\n// `outputSchema` a tool returns a `Content.Value`, and that is what arrives.\ntype CoreTool = { readonly _tag: \"LocalTool\" | \"DeclaredTool\" }\ntype OutputOf<T> = T extends CoreTool\n ? Tool.ToolOutput<T>\n : T extends { readonly outputSchema: infer O extends Schema.Top }\n ? O[\"Type\"]\n : Content.Value\ntype FailureOf<T> = T extends CoreTool\n ? Tool.ToolFailure<T>\n : T extends { readonly failureSchema: infer F extends Schema.Top }\n ? F[\"Type\"]\n : never\ntype ToolOf<T> = T extends ToolSpec\n ? {\n readonly name: T[\"name\"]\n readonly input: InputOf<T[\"inputSchema\"]>\n readonly output: OutputOf<T>\n readonly failure: FailureOf<T> | ToolOutput.CoreError\n }\n : never\ntype ElementOf<T> = T extends ReadonlyArray<infer E> ? E : never\ntype NamedOf<M> = {\n readonly [K in keyof M & string]: {\n readonly name: K\n readonly value: M[K] extends Schema.Top ? M[K][\"Type\"] : never\n }\n}[keyof M & string]\n/** The payload types a spec describes: its listed names only. */\nexport type PayloadsOf<S extends Spec> = {\n readonly tool: ToolOf<ElementOf<S[\"tools\"]>>\n readonly object: NamedOf<S[\"objects\"]>\n readonly data: NamedOf<S[\"data\"]>\n readonly live: NamedOf<S[\"live\"]>\n readonly metadata: S[\"metadata\"] extends Schema.Top ? S[\"metadata\"][\"Type\"] : Json\n}\n\ntype NameOf<T> = T extends { readonly name: infer N } ? N : never\ntype ValueOf<T, N> =\n Extract<T, { readonly name: N }> extends { readonly value: infer V } ? V : never\ntype ToolField<T, N, K extends \"output\" | \"failure\"> =\n Extract<T, { readonly name: N }> extends infer X extends ToolPayload ? X[K] : never\n\n/** The call an app closes itself: its id and the tool's name. */\nexport type Call<N extends string = string> = { readonly call_id: string; readonly name: N }\n\n/**\n * A contract's payload types, for the generic folds:\n * `Thread.presetFor<UiContract.Payloads<typeof ChatUi>>()`.\n */\nexport type Payloads<C> = C extends UiContract<infer P> ? P : never\n\nexport interface UiContract<P extends AnyPayloads> {\n /** Decode a wire envelope (as `Client` reads it) into a typed one. */\n decode(envelope: Envelope): Effect.Effect<Envelope<P>, Schema.SchemaError>\n /** Typed envelope ⇄ wire envelope. */\n readonly Envelope: Schema.Codec<Envelope<P>, Envelope>\n /** A typed run view ⇄ the untyped one, for persisting or a framework's model. */\n readonly RunView: Schema.Codec<RunView.RunView<P>, RunView.RunView>\n /** A typed `Thread` ⇄ the untyped one. */\n readonly Thread: Schema.Codec<Thread.Thread<P>, Thread.Thread>\n /** Server: a `data` event with its value encoded for the wire. */\n data<N extends NameOf<P[\"data\"]>>(\n name: N,\n value: ValueOf<P[\"data\"], N>,\n options?: { readonly id?: string },\n ): Effect.Effect<RunEvent, Schema.SchemaError>\n /** Server: a `live` event with its value encoded for the wire. */\n live<N extends NameOf<P[\"live\"]>>(\n name: N,\n value: ValueOf<P[\"live\"], N>,\n ): Effect.Effect<RunEvent, Schema.SchemaError>\n /** Server: run metadata encoded for `run-completed`. */\n metadata(value: P[\"metadata\"]): Effect.Effect<Json, Schema.SchemaError>\n /** Server: a toolkit event (`Toolkit.run`) encoded with the tool's schemas. */\n toolEvent(event: ToolEvent.ToolEvent): Effect.Effect<RunEvent, Schema.SchemaError>\n /** Server: a history item (already encoded) as the `tool-result` of tool `name`. */\n toolOutput(item: Items.ToolCallOutput, name: string): Effect.Effect<RunEvent, Schema.SchemaError>\n /** Server: close a call with a value of its tool's output (e.g. supplied by the user). */\n success<N extends NameOf<P[\"tool\"]>>(\n call: Call<N>,\n value: ToolField<P[\"tool\"], N, \"output\">,\n ): Effect.Effect<RunEvent, Schema.SchemaError>\n /** Server: close a call with an error (e.g. the app's `Denied`). */\n failure<N extends NameOf<P[\"tool\"]>>(\n call: Call<N>,\n error: ToolField<P[\"tool\"], N, \"failure\">,\n ): Effect.Effect<RunEvent, Schema.SchemaError>\n}\n\n// ---------------------------------------------------------------------------\n// Runtime: one schema member per listed name, plus a fallback for the rest\n// ---------------------------------------------------------------------------\n\nconst json = <S extends Schema.Top>(schema: S) => Schema.toCodecJson(schema)\nconst listed = (name: string) => Schema.Literal(name)\nconst unlisted = (names: ReadonlyArray<string>) =>\n Schema.String.check(Schema.makeFilter((name: string) => !names.includes(name)))\n\n/** A payload codec: decodes from JSON without services. */\ntype PayloadCodec = Schema.Codec<unknown, unknown, never, never>\n\n// A core `Tool` built from an Effect Schema keeps it (`fromEffectSchema`), so it decodes too.\nconst isCodec = (schema: ToolSpec[\"inputSchema\"]): schema is AnyCodec => Schema.isSchema(schema)\n\n// Effect Schemas decode the model's JSON; other Standard Schemas validate it as is.\nconst inputCodec = (tool: ToolSpec): PayloadCodec => {\n const schema = tool.inputSchema\n if (isCodec(schema)) return json(schema)\n return Schema.declare((u: unknown): u is Json => {\n const result = schema[\"~standard\"].validate(u)\n return !(result instanceof Promise) && result.issues === undefined\n })\n}\n// \"Anything\": a tool typed `Content.Value`, or a name the contract doesn't list.\nconst isAnything = (tool: ToolSpec | undefined): boolean =>\n tool?.outputSchema === undefined || tool.outputSchema === Content.Value\n\n// The tool's own schemas, as `Toolkit.output` uses them: they encode to JSON, so\n// the UI and history agree by construction (no `toCodecJson` on top). \"Anything\"\n// travels as typed parts, so JSON can't be mistaken for media.\nconst outputCodec = (tool: ToolSpec | undefined): PayloadCodec =>\n isAnything(tool) ? ToolOutput.ValueParts : (tool?.outputSchema ?? ToolOutput.ValueParts)\n\nconst encodeParts = Schema.encodeEffect(Schema.Array(ToolOutput.PartJson))\n\nconst failureCodec = (tool: ToolSpec | undefined): PayloadCodec =>\n tool?.failureSchema === undefined\n ? ToolOutput.CoreError\n : Schema.Union([tool.failureSchema, ToolOutput.CoreError])\n\nconst entries = (record: Readonly<Record<string, AnyCodec>> | undefined) =>\n Object.entries(record ?? {})\n\n/** Encoded loosely; `make`'s signature carries the types. */\ntype Loose = {\n decode(envelope: Envelope): Effect.Effect<unknown, Schema.SchemaError>\n readonly Envelope: Schema.Top\n readonly RunView: Schema.Top\n readonly Thread: Schema.Top\n data(\n name: string,\n value: unknown,\n options?: { readonly id?: string },\n ): Effect.Effect<RunEvent, Schema.SchemaError>\n live(name: string, value: unknown): Effect.Effect<RunEvent, Schema.SchemaError>\n metadata(value: unknown): Effect.Effect<Json, Schema.SchemaError>\n toolEvent(event: ToolEvent.ToolEvent): Effect.Effect<RunEvent, Schema.SchemaError>\n toolOutput(item: Items.ToolCallOutput, name: string): Effect.Effect<RunEvent, Schema.SchemaError>\n success(call: Call, value: unknown): Effect.Effect<RunEvent, Schema.SchemaError>\n failure(call: Call, error: unknown): Effect.Effect<RunEvent, Schema.SchemaError>\n}\n\nconst toJson = Schema.decodeUnknownEffect(Schema.Json)\nconst toOutcome = Schema.decodeUnknownEffect(Event.Outcome)\n\n/**\n * Build a contract. Tool names must be literal types: pass core `Tool`s or\n * specs declared `as const`.\n */\nexport function make<const S extends Spec>(spec: S): UiContract<PayloadsOf<S>>\nexport function make(spec: Spec): Loose {\n const tools = spec.tools ?? []\n const objects = entries(spec.objects)\n const data = entries(spec.data)\n const live = entries(spec.live)\n const toolNames = tools.map((t) => t.name)\n const metadata = spec.metadata === undefined ? Schema.Json : json(spec.metadata)\n const resultCodec = (tool: ToolSpec | undefined) =>\n Event.outcome(outputCodec(tool), failureCodec(tool))\n // Built once per tool; an unlisted name falls back to the tool-less codecs.\n const codecsOf = (tool: ToolSpec | undefined) => ({\n output: outputCodec(tool),\n result: resultCodec(tool),\n anything: isAnything(tool),\n })\n const unlistedCodecs = codecsOf(undefined)\n const codecsByName = HashMap.fromIterable(tools.map((t) => [t.name, codecsOf(t)] as const))\n const codecs = (name: string) =>\n Option.getOrElse(HashMap.get(codecsByName, name), () => unlistedCodecs)\n\n const interrupt = Schema.Union([\n ...tools.map((t) =>\n Schema.Struct({ ...Event.Interrupt.fields, name: listed(t.name), input: inputCodec(t) }),\n ),\n Schema.Struct({ ...Event.Interrupt.fields, name: unlisted(toolNames) }),\n ])\n\n const toolInput = (event: typeof Event.ToolCallReady | typeof Event.ToolApprovalRequested) =>\n Schema.Union([\n ...tools.map((t) =>\n Schema.Struct({ ...event.fields, name: listed(t.name), input: inputCodec(t) }),\n ),\n Schema.Struct({ ...event.fields, name: unlisted(toolNames) }),\n ])\n\n const named = (\n event: typeof Event.Data | typeof Event.Live,\n members: ReadonlyArray<readonly [string, AnyCodec]>,\n ) =>\n Schema.Union([\n ...members.map(([name, schema]) =>\n Schema.Struct({ ...event.fields, name: listed(name), value: json(schema) }),\n ),\n Schema.Struct({ ...event.fields, name: unlisted(members.map(([name]) => name)) }),\n ])\n\n const event = Schema.Union([\n ...Event.plainEvents.map((e) => Schema.toType(e)),\n Schema.Struct({ ...Event.RunCompleted.fields, metadata: Schema.optional(metadata) }),\n Schema.Struct({ ...Event.RunInterrupted.fields, interrupts: Schema.Array(interrupt) }),\n Schema.Union([\n ...objects.map(([name, schema]) =>\n Schema.Struct({ ...Event.ObjectDone.fields, name: listed(name), value: json(schema) }),\n ),\n Schema.Struct({\n ...Event.ObjectDone.fields,\n name: Schema.optional(unlisted(objects.map(([name]) => name))),\n }),\n ]),\n toolInput(Event.ToolCallReady),\n toolInput(Event.ToolApprovalRequested),\n Schema.Union([\n ...tools.map((t) =>\n Schema.Struct({ ...Event.ToolPartial.fields, name: listed(t.name), value: outputCodec(t) }),\n ),\n Schema.Struct({ ...Event.ToolPartial.fields, name: unlisted(toolNames) }),\n ]),\n Schema.Union([\n ...tools.map((t) =>\n Schema.Struct({ ...Event.ToolResult.fields, name: listed(t.name), result: resultCodec(t) }),\n ),\n Schema.Struct({ ...Event.ToolResult.fields, name: unlisted(toolNames) }),\n ]),\n named(Event.Data, data),\n named(Event.Live, live),\n ])\n const envelope = Schema.Struct({ ...Event.envelopeFields, event })\n\n const view = RunView.schema({\n block: Schema.Union([\n ...RunView.contentBlocks,\n ...tools.map((t) =>\n RunView.toolBlock(listed(t.name), inputCodec(t), outputCodec(t), failureCodec(t)),\n ),\n RunView.toolBlock(unlisted(toolNames), Schema.Json, Schema.Json, Schema.Json),\n ...objects.map(([name, schema]) => RunView.objectBlock(listed(name), json(schema))),\n RunView.objectBlock(unlisted(objects.map(([name]) => name)), Schema.Json),\n RunView.unnamedObject,\n ...data.map(([name, schema]) => RunView.dataBlock(listed(name), json(schema))),\n RunView.dataBlock(unlisted(data.map(([name]) => name)), Schema.Json),\n ]),\n interrupt,\n // Unlisted live values are transient and untyped: the schema keeps listed ones only.\n live: Schema.Struct(\n Object.fromEntries(live.map(([name, schema]) => [name, Schema.optionalKey(json(schema))])),\n ),\n metadata,\n })\n\n const codecOf = (members: ReadonlyArray<readonly [string, AnyCodec]>, name: string) =>\n members.find(([n]) => n === name)?.[1]\n const encode = (schema: AnyCodec | undefined, value: unknown) =>\n Schema.encodeUnknownEffect(schema === undefined ? Schema.Json : json(schema))(value).pipe(\n Effect.flatMap(toJson),\n )\n const toolResult = (call: Call, outcome: Event.Outcome<unknown, unknown>) =>\n Schema.encodeUnknownEffect(codecs(call.name).result)(outcome).pipe(\n Effect.flatMap(toOutcome),\n Effect.map((result): RunEvent => ({\n type: \"tool-result\",\n callId: call.call_id,\n name: call.name,\n result,\n })),\n )\n\n return {\n decode: Schema.decodeUnknownEffect(envelope),\n Envelope: envelope,\n RunView: view,\n Thread: Thread.State(Thread.UserContent, view, view),\n data: (name, value, options) =>\n encode(codecOf(data, name), value).pipe(\n Effect.map((encoded): RunEvent =>\n options?.id === undefined\n ? { type: \"data\", name, value: encoded }\n : { type: \"data\", name, value: encoded, id: options.id },\n ),\n ),\n live: (name, value) =>\n encode(codecOf(live, name), value).pipe(\n Effect.map((encoded): RunEvent => ({ type: \"live\", name, value: encoded })),\n ),\n metadata: (value) => encode(spec.metadata, value),\n toolEvent: (event) =>\n Match.value(event).pipe(\n Match.tagsExhaustive({\n Partial: (e) =>\n Schema.encodeUnknownEffect(codecs(e.tool).output)(e.value).pipe(\n Effect.flatMap(toJson),\n Effect.map((value): RunEvent => ({\n type: \"tool-partial\",\n callId: e.call_id,\n name: e.tool,\n value,\n })),\n ),\n Output: (e) =>\n toolResult(\n { call_id: e.call_id, name: e.tool },\n Result.match(e.result, {\n onSuccess: (value): Event.Outcome<unknown, unknown> => ({ _tag: \"Success\", value }),\n onFailure: (error): Event.Outcome<unknown, unknown> => ({ _tag: \"Failure\", error }),\n }),\n ),\n }),\n ),\n // The item holds the encoded value: \"anything\" goes as its parts, the rest as the JSON they encode.\n toolOutput: (item, name) =>\n Match.value(item).pipe(\n Match.when({ isError: true }, (o) =>\n Effect.map(ToolOutput.encoded(o.output), (error) => ({ _tag: \"Failure\", error })),\n ),\n Match.orElse((o) =>\n Effect.map(\n codecs(name).anything ? encodeParts(o.output) : ToolOutput.encoded(o.output),\n (value) => ({ _tag: \"Success\", value }),\n ),\n ),\n Effect.flatMap(toOutcome),\n Effect.map((result): RunEvent => ({\n type: \"tool-result\",\n callId: item.call_id,\n name,\n result,\n })),\n ),\n success: (call, value) => toolResult(call, { _tag: \"Success\", value }),\n failure: (call, error) => toolResult(call, { _tag: \"Failure\", error }),\n }\n}\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@effect-uai/ui",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.19.0-dev-20261110065930",
|
|
4
4
|
"description": "Agentic UI primitives for @effect-uai/core: a resumable run-event protocol, projection, client folds and Effect atoms.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"agents",
|
|
@@ -89,10 +89,10 @@
|
|
|
89
89
|
"@effect/vitest": "4.1.2",
|
|
90
90
|
"effect": "4.1.2",
|
|
91
91
|
"typescript": "^7.0.2",
|
|
92
|
-
"@effect-uai/core": "0.
|
|
92
|
+
"@effect-uai/core": "0.19.0-dev-20261110065930"
|
|
93
93
|
},
|
|
94
94
|
"peerDependencies": {
|
|
95
|
-
"@effect-uai/core": "
|
|
95
|
+
"@effect-uai/core": "0.19.0-dev-20261110065930",
|
|
96
96
|
"effect": ">=4.0.1 <5.0.0"
|
|
97
97
|
},
|
|
98
98
|
"scripts": {
|