@agent-factory-platform/agent-react 0.2.0

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.
@@ -0,0 +1 @@
1
+ .af-agent-chat,.af-agent-studio{color:var(--color-ink);font-family:var(--font-product, system-ui, sans-serif)}.af-agent-chat{display:grid;grid-template-columns:minmax(12rem,15rem) minmax(0,1fr);min-height:36rem;overflow:hidden;border:1px solid var(--color-border);border-radius:var(--radius-panel);background:var(--color-surface-card)}.af-agent-chat>.af-agent-conversation:only-child{grid-column:1 / -1}.af-agent-threads{display:flex;min-width:0;flex-direction:column;border-right:1px solid var(--color-divider);background:var(--color-surface-fog)}.af-agent-threads__header,.af-agent-conversation__header{display:flex;min-height:3.5rem;align-items:center;justify-content:space-between;gap:.75rem;padding:.625rem .75rem;border-bottom:1px solid var(--color-divider)}.af-agent-threads__list{min-height:0;overflow-y:auto;padding:.375rem}.af-agent-thread-row{display:flex;align-items:center;border-radius:var(--radius-control)}.af-agent-thread-row:hover,.af-agent-thread-row[data-active]{background:var(--color-surface-hover)}.af-agent-thread-row__select{display:flex;min-height:2.75rem;min-width:0;flex:1;align-items:center;justify-content:space-between;gap:.5rem;padding:0 .625rem;border:0;background:transparent;color:inherit;text-align:left;cursor:pointer}.af-agent-thread-row__select span{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.af-agent-icon-button{display:grid;width:2.75rem;height:2.75rem;place-items:center;border:0;background:transparent;color:var(--color-graphite);cursor:pointer}.af-agent-thread-row:not(:hover):not(:focus-within) .af-agent-icon-button{opacity:0}.af-agent-conversation{display:grid;min-width:0;min-height:36rem;grid-template-rows:auto minmax(0,1fr) auto;background:var(--color-surface-canvas)}.af-agent-conversation__header{flex-wrap:wrap;background:var(--color-surface-card)}.af-agent-title{display:flex;min-width:0;align-items:center;gap:.625rem}.af-agent-title>div{display:grid;min-width:0}.af-agent-title strong{font-size:.875rem}.af-agent-title span{overflow:hidden;color:var(--color-graphite);font-size:.75rem;text-overflow:ellipsis;white-space:nowrap}.af-agent-resources{display:flex;min-width:0;flex:1;flex-wrap:wrap;align-items:center;justify-content:flex-end;gap:.375rem}.af-agent-resources button{min-height:2rem}.af-agent-option-meta{max-width:10rem;overflow:hidden;color:var(--color-graphite);font-size:.6875rem;text-overflow:ellipsis;white-space:nowrap}.af-agent-messages{min-height:0;overflow-y:auto;padding:1.25rem clamp(.75rem,3vw,2.5rem)}.af-agent-message{display:grid;max-width:52rem;grid-template-columns:1.875rem minmax(0,1fr);gap:.625rem;margin:0 auto 1.25rem}.af-agent-message__body>strong{display:block;margin-bottom:.25rem;font-size:.75rem}.af-agent-message__content{font-size:.875rem;line-height:1.65;white-space:pre-wrap}.af-agent-message[data-role=user] .af-agent-message__content{display:inline-block;padding:.625rem .75rem;border-radius:var(--radius-selection);background:var(--color-surface-warm)}.af-agent-thinking{color:var(--color-graphite)}.af-agent-thinking:after{content:"";display:inline-block;width:1.1rem;height:.25rem;margin-left:.25rem;background:radial-gradient(circle,var(--color-graphite) 1.5px,transparent 2px) 0 50% / .35rem .25rem repeat-x;animation:af-agent-pulse 1s ease-in-out infinite}.af-agent-surface{margin-top:.75rem}.af-agent-trace{max-width:52rem;margin:0 auto 1rem;border:1px solid var(--color-border);border-radius:var(--radius-control);background:var(--color-surface-card);font-size:.75rem}.af-agent-trace summary{display:flex;min-height:2.75rem;align-items:center;gap:.5rem;padding:0 .75rem;cursor:pointer}.af-agent-trace ol{margin:0;padding:0 .75rem .625rem 2rem;color:var(--color-graphite)}.af-agent-trace li{padding:.25rem 0}.af-agent-trace li span{display:flex;align-items:center;gap:.375rem}.af-agent-trace li span:last-child{margin-left:1.125rem;font-size:.6875rem}.af-agent-composer{display:grid;width:calc(100% - 1.5rem);max-width:52rem;grid-template-columns:minmax(0,1fr) 2.75rem;align-items:end;gap:.5rem;margin:0 auto .75rem;padding:.625rem;border:1px solid var(--color-border);border-radius:var(--radius-overlay);background:var(--color-surface-card);box-shadow:var(--shadow-pop)}.af-agent-composer textarea{min-height:2.75rem;max-height:10rem;resize:none}.af-agent-action{display:grid;grid-template-columns:minmax(0,1fr) auto;align-items:start;gap:.75rem}.af-agent-action [class*=CardLabel],.af-agent-action p{margin-top:.375rem;color:var(--color-graphite);font-size:.75rem}.af-agent-action__buttons{display:flex;grid-column:1 / -1;gap:.5rem}.af-agent-persona{display:grid;gap:1rem}.af-agent-persona__intro{display:flex;align-items:center;gap:.75rem}.af-agent-persona label{display:grid;gap:.375rem;color:var(--color-graphite);font-size:.75rem}.af-agent-studio{display:grid;grid-template-columns:minmax(18rem,24rem) minmax(0,1fr);overflow:hidden;border:1px solid var(--color-border);border-radius:var(--radius-panel);background:var(--color-surface-card)}.af-agent-studio>section{min-width:0;padding:1rem}.af-agent-studio>section+section{border-left:1px solid var(--color-divider);background:var(--color-surface-canvas)}@keyframes af-agent-pulse{50%{opacity:.35}}@media(prefers-reduced-motion:reduce){.af-agent-thinking:after{animation:none}}@media(max-width:720px){.af-agent-chat{grid-template-columns:minmax(0,1fr);min-height:42rem}.af-agent-threads{max-height:8rem;border-right:0;border-bottom:1px solid var(--color-divider)}.af-agent-threads__list{display:flex;gap:.25rem}.af-agent-thread-row{min-width:10rem}.af-agent-thread-row:not(:hover):not(:focus-within) .af-agent-icon-button{opacity:1}.af-agent-conversation{min-height:34rem}.af-agent-conversation__header{align-items:flex-start}.af-agent-resources{flex-basis:100%;justify-content:flex-start;overflow-x:auto;flex-wrap:nowrap;padding-bottom:.125rem}.af-agent-studio{grid-template-columns:1fr}.af-agent-studio>section+section{border-top:1px solid var(--color-divider);border-left:0}}
@@ -0,0 +1,2 @@
1
+ import type { AgentDataSlots, AgentSessionModel } from "@agent-factory-platform/client";
2
+ export declare function useAgentSession<Slots extends AgentDataSlots = AgentDataSlots>(model: AgentSessionModel<Slots>): import("@agent-factory-platform/client").AgentSessionState<Slots>;
@@ -0,0 +1,5 @@
1
+ import "./styles.css";
2
+ export { useAgentSession } from "./hooks";
3
+ export { AgentSlotRegistry, dataFallback, type AgentDataDecoder, type AgentSlot, type AgentSlotProps, type AgentSlotValues, type DecodedAgentDataProjection } from "./registry";
4
+ export { AgentActionCard, AgentChat, AgentComposer, AgentConversation, AgentExecutionTrace, AgentProfileEditor, AgentResourceBar, AgentSessionList, AgentStudio, DEFAULT_AGENT_UI_LABELS, type AgentUiLabels } from "./ui";
5
+ export { AgentSessionModel, type AgentProjectionItem, type AgentSessionProjection, type AgentSessionState, type AgentSessionTransport } from "@agent-factory-platform/client";
package/dist/index.js ADDED
@@ -0,0 +1,297 @@
1
+ var ne = Object.defineProperty;
2
+ var W = (e) => {
3
+ throw TypeError(e);
4
+ };
5
+ var te = (e, a, s) => a in e ? ne(e, a, { enumerable: !0, configurable: !0, writable: !0, value: s }) : e[a] = s;
6
+ var U = (e, a, s) => te(e, typeof a != "symbol" ? a + "" : a, s), $ = (e, a, s) => a.has(e) || W("Cannot " + s);
7
+ var u = (e, a, s) => ($(e, a, "read from private field"), s ? s.call(e) : a.get(e)), S = (e, a, s) => a.has(e) ? W("Cannot add the same private member more than once") : a instanceof WeakSet ? a.add(e) : a.set(e, s), J = (e, a, s, o) => ($(e, a, "write to private field"), o ? o.call(e, s) : a.set(e, s), s), C = (e, a, s) => ($(e, a, "access private method"), s);
8
+ import { useSyncExternalStore as X, useState as q, useMemo as se } from "react";
9
+ import { jsx as t, jsxs as i, Fragment as K } from "react/jsx-runtime";
10
+ import { Card as re, CardLabel as Z, CardTitle as y, Tag as k, Button as w, AvatarBadge as Y, Textarea as F, StateView as L, Input as P } from "@agent-factory-platform/ui-kit";
11
+ import { Wrench as oe, CircleStop as ie, Send as le, Bot as ee, Sparkles as ce, Check as de, MessageSquarePlus as ue, ChevronRight as he, Trash2 as pe } from "lucide-react";
12
+ import { AgentSessionModel as je } from "@agent-factory-platform/client";
13
+ function fe(e) {
14
+ return X(e.subscribe, e.getSnapshot, e.getSnapshot);
15
+ }
16
+ var f, g, A, R, v, z;
17
+ class qe {
18
+ constructor() {
19
+ S(this, v);
20
+ S(this, f, /* @__PURE__ */ new Map());
21
+ S(this, g, /* @__PURE__ */ new Map());
22
+ S(this, A, /* @__PURE__ */ new Set());
23
+ S(this, R, 0);
24
+ U(this, "getSnapshot", () => u(this, R));
25
+ U(this, "subscribe", (a) => (u(this, A).add(a), () => u(this, A).delete(a)));
26
+ }
27
+ register(a, s) {
28
+ const o = s;
29
+ return u(this, f).set(a, o), C(this, v, z).call(this), () => {
30
+ if (u(this, f).get(a) !== o) return !1;
31
+ const n = u(this, f).delete(a);
32
+ return n && C(this, v, z).call(this), n;
33
+ };
34
+ }
35
+ registerData(a, s, o) {
36
+ const n = { decode: s, renderer: o };
37
+ return u(this, g).set(a, n), C(this, v, z).call(this), () => {
38
+ if (u(this, g).get(a) !== n) return !1;
39
+ const c = u(this, g).delete(a);
40
+ return c && C(this, v, z).call(this), c;
41
+ };
42
+ }
43
+ render(a, s) {
44
+ if (a === "data") {
45
+ const n = s, c = u(this, g).get(n.name);
46
+ if (!c) return B(n.name, "unknown");
47
+ try {
48
+ const r = { ...n, value: c.decode(n.value) }, l = c.renderer;
49
+ return /* @__PURE__ */ t(l, { value: r });
50
+ } catch {
51
+ return B(n.name, "malformed");
52
+ }
53
+ }
54
+ const o = u(this, f).get(a);
55
+ return o ? /* @__PURE__ */ t(o, { value: s }) : null;
56
+ }
57
+ }
58
+ f = new WeakMap(), g = new WeakMap(), A = new WeakMap(), R = new WeakMap(), v = new WeakSet(), z = function() {
59
+ J(this, R, u(this, R) + 1), u(this, A).forEach((a) => a());
60
+ };
61
+ function B(e, a) {
62
+ return /* @__PURE__ */ i("span", { "data-agent-data-fallback": a, children: [
63
+ a === "malformed" ? "Invalid" : "Unsupported",
64
+ " data slot: ",
65
+ e || "(unnamed)"
66
+ ] });
67
+ }
68
+ const G = {
69
+ assistant: "Assistant",
70
+ newSession: "New conversation",
71
+ sessions: "Conversations",
72
+ emptyTitle: "How can I help?",
73
+ emptyDescription: "Ask a question in this profile-pinned session.",
74
+ composer: "Message the assistant",
75
+ send: "Send",
76
+ stop: "Stop",
77
+ retry: "Retry",
78
+ execution: "Execution",
79
+ explicitSkill: "Invoke skill"
80
+ }, D = (e) => ({ ...G, ...e }), ge = () => () => {
81
+ }, O = () => 0;
82
+ function I(e) {
83
+ X((e == null ? void 0 : e.subscribe) ?? ge, (e == null ? void 0 : e.getSnapshot) ?? O, (e == null ? void 0 : e.getSnapshot) ?? O);
84
+ }
85
+ function ve({ sessions: e, activeSessionId: a, onSelect: s, onNew: o, onDelete: n, labels: c }) {
86
+ const r = D(c);
87
+ return /* @__PURE__ */ i("aside", { className: "af-agent-threads", "aria-label": r.sessions, children: [
88
+ /* @__PURE__ */ i("div", { className: "af-agent-threads__header", children: [
89
+ /* @__PURE__ */ t("strong", { children: r.sessions }),
90
+ /* @__PURE__ */ t(w, { size: "icon", variant: "ghost", onClick: o, "aria-label": r.newSession, children: /* @__PURE__ */ t(ue, { size: 17, "aria-hidden": !0 }) })
91
+ ] }),
92
+ /* @__PURE__ */ t("div", { className: "af-agent-threads__list", children: e.map((l) => /* @__PURE__ */ i("div", { className: "af-agent-thread-row", "data-active": l.id === a || void 0, children: [
93
+ /* @__PURE__ */ i("button", { type: "button", className: "af-agent-thread-row__select", onClick: () => s(l.id), children: [
94
+ /* @__PURE__ */ t("span", { children: l.profileRevisionId }),
95
+ /* @__PURE__ */ t(he, { size: 14, "aria-hidden": !0 })
96
+ ] }),
97
+ n && /* @__PURE__ */ t("button", { type: "button", className: "af-agent-icon-button", onClick: () => n(l.id), "aria-label": `Delete ${l.id}`, children: /* @__PURE__ */ t(pe, { size: 14, "aria-hidden": !0 }) })
98
+ ] }, l.id)) })
99
+ ] });
100
+ }
101
+ function be({ profileRevisionId: e, explicitSkillSlug: a, onExplicitSkillChange: s, labels: o, registry: n }) {
102
+ I(n);
103
+ const c = n == null ? void 0 : n.render("resource-bar", { profileRevisionId: e, explicitSkillSlug: a, setExplicitSkillSlug: s });
104
+ if (c) return c;
105
+ const r = D(o);
106
+ return /* @__PURE__ */ i("div", { className: "af-agent-resources", "aria-label": "Agent resources", children: [
107
+ /* @__PURE__ */ t(k, { tone: "cool", children: e }),
108
+ /* @__PURE__ */ t(P, { "aria-label": r.explicitSkill, placeholder: r.explicitSkill, value: a, onChange: (l) => s(l.target.value) })
109
+ ] });
110
+ }
111
+ function me({ items: e, label: a = G.execution, registry: s }) {
112
+ I(s);
113
+ const o = e.filter((n) => n.kind === "step_started" || n.kind === "step_finished" || n.kind === "retry_scheduled");
114
+ return o.length ? /* @__PURE__ */ i("details", { className: "af-agent-trace", children: [
115
+ /* @__PURE__ */ i("summary", { children: [
116
+ /* @__PURE__ */ t(ce, { size: 14, "aria-hidden": !0 }),
117
+ a,
118
+ /* @__PURE__ */ t(k, { size: "micro", tone: "cool", children: o.length })
119
+ ] }),
120
+ /* @__PURE__ */ t("ol", { children: o.map((n) => /* @__PURE__ */ t("li", { children: (s == null ? void 0 : s.render("trace-item", n)) ?? /* @__PURE__ */ i(K, { children: [
121
+ /* @__PURE__ */ i("span", { children: [
122
+ /* @__PURE__ */ t(de, { size: 13, "aria-hidden": !0 }),
123
+ n.kind
124
+ ] }),
125
+ /* @__PURE__ */ t("span", { children: n.status })
126
+ ] }) }, n.anchorSeq.toString())) })
127
+ ] }) : null;
128
+ }
129
+ function Se({ interaction: e, onResolve: a }) {
130
+ const [s, o] = q(!1), [n, c] = q(""), r = async (l) => {
131
+ o(!0), c("");
132
+ try {
133
+ await a(l);
134
+ } catch (d) {
135
+ c(d instanceof Error ? d.message : String(d));
136
+ } finally {
137
+ o(!1);
138
+ }
139
+ };
140
+ return /* @__PURE__ */ i(re, { as: "article", tone: "warm", className: "af-agent-action", children: [
141
+ /* @__PURE__ */ i("div", { children: [
142
+ /* @__PURE__ */ i(Z, { children: [
143
+ /* @__PURE__ */ t(oe, { size: 14, "aria-hidden": !0 }),
144
+ " Approval required"
145
+ ] }),
146
+ /* @__PURE__ */ t(y, { children: e.kind })
147
+ ] }),
148
+ /* @__PURE__ */ t(k, { tone: e.status === "pending" ? "warning" : "neutral", children: e.status }),
149
+ e.status === "pending" && /* @__PURE__ */ i("div", { className: "af-agent-action__buttons", children: [
150
+ /* @__PURE__ */ t(w, { size: "compact", disabled: s, onClick: () => void r("confirmed"), children: s ? "Resolving…" : "Confirm" }),
151
+ /* @__PURE__ */ t(w, { size: "compact", variant: "secondary", disabled: s, onClick: () => void r("rejected"), children: "Reject" })
152
+ ] }),
153
+ n && /* @__PURE__ */ t("p", { role: "alert", children: n })
154
+ ] });
155
+ }
156
+ function ke({ value: e, onChange: a, onSubmit: s, running: o, onStop: n, labels: c }) {
157
+ const r = D(c);
158
+ return /* @__PURE__ */ i("form", { className: "af-agent-composer", onSubmit: (d) => {
159
+ d.preventDefault(), e.trim() && !o && s();
160
+ }, children: [
161
+ /* @__PURE__ */ t(F, { rows: 2, variant: "bare", value: e, onChange: (d) => a(d.target.value), "aria-label": r.composer, placeholder: r.composer, onKeyDown: (d) => {
162
+ d.key === "Enter" && !d.shiftKey && (d.preventDefault(), e.trim() && !o && s());
163
+ } }),
164
+ o ? /* @__PURE__ */ t(w, { type: "button", size: "icon", variant: "secondary", onClick: n, "aria-label": r.stop, children: /* @__PURE__ */ t(ie, { size: 17, "aria-hidden": !0 }) }) : /* @__PURE__ */ t(w, { type: "submit", size: "icon", disabled: !e.trim(), "aria-label": r.send, children: /* @__PURE__ */ t(le, { size: 17, "aria-hidden": !0 }) })
165
+ ] });
166
+ }
167
+ function Ae({ items: e, registry: a, onResolveInteraction: s }) {
168
+ I(a);
169
+ const o = e.filter((n) => n.slot !== "trace-item" && (n.slot !== "message-content" || n.text.length > 0));
170
+ return /* @__PURE__ */ t(K, { children: o.map((n) => n.slot === "message-content" ? /* @__PURE__ */ i("article", { className: "af-agent-message", "data-role": n.role, "data-anchor-seq": n.anchorSeq.toString(), "data-last-updated-seq": n.lastUpdatedSeq.toString(), children: [
171
+ /* @__PURE__ */ t(Y, { initials: n.role === "user" ? "You" : "AF", size: 30 }),
172
+ /* @__PURE__ */ i("div", { className: "af-agent-message__body", children: [
173
+ /* @__PURE__ */ t("strong", { children: n.role === "user" ? "You" : "Agent" }),
174
+ /* @__PURE__ */ t("div", { className: "af-agent-message__content", children: (a == null ? void 0 : a.render("message-content", n)) ?? n.text })
175
+ ] })
176
+ ] }, `message-${n.anchorSeq}`) : /* @__PURE__ */ t("div", { className: "af-agent-surface", "data-slot": n.slot, "data-anchor-seq": n.anchorSeq.toString(), "data-last-updated-seq": n.lastUpdatedSeq.toString(), children: n.slot === "tool-card" ? (a == null ? void 0 : a.render("tool-card", n)) ?? /* @__PURE__ */ i(k, { tone: n.error ? "warning" : "cool", children: [
177
+ n.phase,
178
+ " · ",
179
+ n.name || n.callId
180
+ ] }) : n.slot === "action" ? (a == null ? void 0 : a.render("action", n)) ?? (s ? /* @__PURE__ */ t(Se, { interaction: { id: n.interactionId, kind: Q(n), status: n.phase === "requested" ? "pending" : "resolved" }, onResolve: (c) => s(n.interactionId, c) }) : /* @__PURE__ */ i(k, { tone: "warning", children: [
181
+ Q(n),
182
+ " · ",
183
+ n.phase
184
+ ] })) : n.slot === "citation" ? (a == null ? void 0 : a.render("citation", n)) ?? /* @__PURE__ */ t(k, { children: n.resourceId }) : a ? a.render("data", n) : B(n.name, "unknown") }, n.slot === "tool-card" ? `tool-${n.callId}` : n.slot === "action" ? `action-${n.interactionId}` : `${n.slot}-${n.anchorSeq}-${n.blockIndex}`)) });
185
+ }
186
+ function Q(e) {
187
+ const a = e.payload && typeof e.payload == "object" && !Array.isArray(e.payload) ? e.payload.action : void 0;
188
+ return a && typeof a == "object" && !Array.isArray(a) && typeof a.kind == "string" ? a.kind : e.kind;
189
+ }
190
+ function we({ model: e, explicitSkillSlug: a = "", registry: s, header: o, labels: n, onError: c }) {
191
+ var H, V;
192
+ I(s);
193
+ const r = D(n), l = fe(e), [d, p] = q(""), [T, N] = q(""), _ = l.status === "submitting" || l.status === "queued" || l.status === "running" || l.status === "waiting_for_input", b = l.projection.items.filter((h) => h.slot === "trace-item"), E = l.projection.items.filter((h) => h.slot !== "trace-item" && (h.slot !== "message-content" || h.text.length > 0)), M = (h) => c == null ? void 0 : c(h instanceof Error ? h : new Error(String(h))), j = async (h) => {
194
+ var x;
195
+ const m = h.trim();
196
+ if (m) {
197
+ p(""), N(m);
198
+ try {
199
+ await e.submitText(m, a);
200
+ } catch (ae) {
201
+ p(((x = e.getSnapshot().retryDraft) == null ? void 0 : x.text) ?? m), M(ae);
202
+ }
203
+ }
204
+ };
205
+ return /* @__PURE__ */ i("section", { className: "af-agent-conversation", "aria-label": r.assistant, children: [
206
+ o && /* @__PURE__ */ t("header", { className: "af-agent-conversation__header", children: o }),
207
+ /* @__PURE__ */ i("div", { className: "af-agent-messages", "aria-live": "polite", children: [
208
+ !E.length && l.status === "idle" && /* @__PURE__ */ t(L, { size: "md", title: r.emptyTitle, description: r.emptyDescription, icon: /* @__PURE__ */ t(ee, { size: 24, "aria-hidden": !0 }) }),
209
+ /* @__PURE__ */ t(Ae, { items: E, registry: s, onResolveInteraction: async (h, m) => {
210
+ try {
211
+ await e.resolveInteraction(h, m);
212
+ } catch (x) {
213
+ throw M(x), x;
214
+ }
215
+ } }),
216
+ l.status !== "waiting_for_input" && _ && /* @__PURE__ */ t("span", { className: "af-agent-thinking", children: "Thinking…" }),
217
+ l.status === "disconnected" && /* @__PURE__ */ t(L, { variant: "error", size: "sm", title: ((H = l.error) == null ? void 0 : H.message) ?? "Disconnected", action: { label: r.retry, onClick: () => void e.retry().catch(M) } }),
218
+ l.status === "failed" && /* @__PURE__ */ t(L, { variant: "error", size: "sm", title: ((V = l.error) == null ? void 0 : V.message) ?? "Run failed", action: { label: r.retry, onClick: () => void j(T) } }),
219
+ l.status === "max_steps_reached" && /* @__PURE__ */ t(L, { variant: "error", size: "sm", title: "Maximum steps reached", action: { label: r.retry, onClick: () => void j(T) } }),
220
+ /* @__PURE__ */ t(me, { items: b, registry: s, label: r.execution })
221
+ ] }),
222
+ (s == null ? void 0 : s.render("composer", { draft: d, running: _, submit: () => void j(d), stop: () => void e.cancel(), setDraft: p })) ?? /* @__PURE__ */ t(ke, { value: d, onChange: p, onSubmit: () => void j(d), running: _, onStop: () => void e.cancel(), labels: r })
223
+ ] });
224
+ }
225
+ function Re({ model: e, title: a = G.assistant, subtitle: s, profileRevisionId: o, sessions: n, activeSessionId: c, onSelectSession: r, onNewSession: l, onDeleteSession: d, registry: p, labels: T }) {
226
+ const [N, _] = q(""), b = D(T), E = se(() => /* @__PURE__ */ i(K, { children: [
227
+ /* @__PURE__ */ i("div", { className: "af-agent-title", children: [
228
+ /* @__PURE__ */ t(Y, { initials: "AF", size: 36 }),
229
+ /* @__PURE__ */ i("div", { children: [
230
+ /* @__PURE__ */ t("strong", { children: a }),
231
+ s && /* @__PURE__ */ t("span", { children: s })
232
+ ] })
233
+ ] }),
234
+ /* @__PURE__ */ t(be, { profileRevisionId: o, explicitSkillSlug: N, onExplicitSkillChange: _, registry: p, labels: b })
235
+ ] }), [a, s, o, N, p, b]);
236
+ return /* @__PURE__ */ i("div", { className: "af-agent-chat", "data-testid": "agent-chat", children: [
237
+ n && r && l && /* @__PURE__ */ t(ve, { sessions: n, activeSessionId: c, onSelect: r, onNew: l, onDelete: d, labels: b }),
238
+ /* @__PURE__ */ t(we, { model: e, explicitSkillSlug: N, registry: p, header: E, labels: b })
239
+ ] });
240
+ }
241
+ function De({ revision: e, onChange: a, onSave: s, saving: o = !1, registry: n }) {
242
+ I(n);
243
+ const c = n == null ? void 0 : n.render("profile-editor", { revision: e, onChange: a });
244
+ return c || /* @__PURE__ */ i("form", { className: "af-agent-persona", onSubmit: (r) => {
245
+ r.preventDefault(), s();
246
+ }, children: [
247
+ /* @__PURE__ */ i("div", { className: "af-agent-persona__intro", children: [
248
+ /* @__PURE__ */ t(Y, { initials: e.name || "AF", src: e.avatar || void 0, size: 48 }),
249
+ /* @__PURE__ */ i("div", { children: [
250
+ /* @__PURE__ */ i(Z, { children: [
251
+ /* @__PURE__ */ t(ee, { size: 14, "aria-hidden": !0 }),
252
+ " Agent Profile"
253
+ ] }),
254
+ /* @__PURE__ */ t(y, { children: e.name || "Untitled Agent" })
255
+ ] })
256
+ ] }),
257
+ /* @__PURE__ */ i("label", { children: [
258
+ /* @__PURE__ */ t("span", { children: "Name" }),
259
+ /* @__PURE__ */ t(P, { required: !0, value: e.name, onChange: (r) => a({ ...e, name: r.target.value }) })
260
+ ] }),
261
+ /* @__PURE__ */ i("label", { children: [
262
+ /* @__PURE__ */ t("span", { children: "Avatar URL" }),
263
+ /* @__PURE__ */ t(P, { type: "url", value: e.avatar, onChange: (r) => a({ ...e, avatar: r.target.value }) })
264
+ ] }),
265
+ /* @__PURE__ */ i("label", { children: [
266
+ /* @__PURE__ */ t("span", { children: "Persona" }),
267
+ /* @__PURE__ */ t(F, { required: !0, rows: 5, value: e.persona, onChange: (r) => a({ ...e, persona: r.target.value }) })
268
+ ] }),
269
+ /* @__PURE__ */ i("label", { children: [
270
+ /* @__PURE__ */ t("span", { children: "Purpose" }),
271
+ /* @__PURE__ */ t(F, { required: !0, rows: 3, value: e.purpose, onChange: (r) => a({ ...e, purpose: r.target.value }) })
272
+ ] }),
273
+ /* @__PURE__ */ t(w, { type: "submit", disabled: o, children: o ? "Saving…" : "Save revision" })
274
+ ] });
275
+ }
276
+ function Ie({ editor: e, preview: a }) {
277
+ return /* @__PURE__ */ i("div", { className: "af-agent-studio", children: [
278
+ /* @__PURE__ */ t("section", { "aria-label": "Agent configuration", children: e }),
279
+ /* @__PURE__ */ t("section", { "aria-label": "Agent preview", children: a })
280
+ ] });
281
+ }
282
+ export {
283
+ Se as AgentActionCard,
284
+ Re as AgentChat,
285
+ ke as AgentComposer,
286
+ we as AgentConversation,
287
+ me as AgentExecutionTrace,
288
+ De as AgentProfileEditor,
289
+ be as AgentResourceBar,
290
+ ve as AgentSessionList,
291
+ je as AgentSessionModel,
292
+ qe as AgentSlotRegistry,
293
+ Ie as AgentStudio,
294
+ G as DEFAULT_AGENT_UI_LABELS,
295
+ B as dataFallback,
296
+ fe as useAgentSession
297
+ };
@@ -0,0 +1,57 @@
1
+ import type { AgentDataProjection, AgentDataSlots, AgentProjectionItem, agentV1 } from "@agent-factory-platform/client";
2
+ import type { ComponentType, ReactNode } from "react";
3
+ export type AgentDataDecoder<Value> = (value: unknown) => Value;
4
+ export type DecodedAgentDataProjection<DataSlots extends AgentDataSlots, Name extends keyof DataSlots & string> = Omit<Extract<AgentDataProjection<DataSlots>, {
5
+ name: Name;
6
+ }>, "value"> & {
7
+ value: DataSlots[Name];
8
+ };
9
+ export interface AgentSlotValues<DataSlots extends AgentDataSlots = AgentDataSlots> {
10
+ "message-content": Extract<AgentProjectionItem, {
11
+ slot: "message-content";
12
+ }>;
13
+ "tool-card": Extract<AgentProjectionItem, {
14
+ slot: "tool-card";
15
+ }>;
16
+ action: Extract<AgentProjectionItem, {
17
+ slot: "action";
18
+ }>;
19
+ citation: Extract<AgentProjectionItem, {
20
+ slot: "citation";
21
+ }>;
22
+ data: AgentDataProjection<DataSlots>;
23
+ "trace-item": Extract<AgentProjectionItem, {
24
+ slot: "trace-item";
25
+ }>;
26
+ composer: {
27
+ draft: string;
28
+ running: boolean;
29
+ submit: () => void;
30
+ stop: () => void;
31
+ setDraft: (value: string) => void;
32
+ };
33
+ "resource-bar": {
34
+ profileRevisionId: string;
35
+ explicitSkillSlug: string;
36
+ setExplicitSkillSlug: (value: string) => void;
37
+ };
38
+ "profile-editor": {
39
+ revision: agentV1.AgentProfileRevision;
40
+ onChange: (revision: agentV1.AgentProfileRevision) => void;
41
+ };
42
+ }
43
+ export type AgentSlot = keyof AgentSlotValues;
44
+ export type AgentSlotProps<K extends AgentSlot = AgentSlot, DataSlots extends AgentDataSlots = AgentDataSlots> = {
45
+ value: AgentSlotValues<DataSlots>[K];
46
+ };
47
+ export declare class AgentSlotRegistry<DataSlots extends AgentDataSlots = AgentDataSlots> {
48
+ #private;
49
+ getSnapshot: () => number;
50
+ subscribe: (listener: () => void) => () => boolean;
51
+ register<K extends Exclude<AgentSlot, "data">>(slot: K, renderer: ComponentType<AgentSlotProps<K, DataSlots>>): () => boolean;
52
+ registerData<Name extends keyof DataSlots & string>(name: Name, decode: AgentDataDecoder<DataSlots[Name]>, renderer: ComponentType<{
53
+ value: DecodedAgentDataProjection<DataSlots, Name>;
54
+ }>): () => boolean;
55
+ render<K extends AgentSlot>(slot: K, value: AgentSlotValues<DataSlots>[K]): ReactNode;
56
+ }
57
+ export declare function dataFallback(name: string, reason: "unknown" | "malformed"): ReactNode;
package/dist/ui.d.ts ADDED
@@ -0,0 +1,88 @@
1
+ import type { AgentDataSlots, AgentProjectionItem, AgentSessionModel, agentV1 } from "@agent-factory-platform/client";
2
+ import { type ReactNode } from "react";
3
+ import { type AgentSlotRegistry } from "./registry";
4
+ export interface AgentUiLabels {
5
+ assistant: string;
6
+ newSession: string;
7
+ sessions: string;
8
+ emptyTitle: string;
9
+ emptyDescription: string;
10
+ composer: string;
11
+ send: string;
12
+ stop: string;
13
+ retry: string;
14
+ execution: string;
15
+ explicitSkill: string;
16
+ }
17
+ export declare const DEFAULT_AGENT_UI_LABELS: AgentUiLabels;
18
+ export declare function AgentSessionList({ sessions, activeSessionId, onSelect, onNew, onDelete, labels: overrides }: {
19
+ sessions: readonly agentV1.Session[];
20
+ activeSessionId?: string;
21
+ onSelect: (id: string) => void;
22
+ onNew: () => void;
23
+ onDelete?: (id: string) => void;
24
+ labels?: Partial<AgentUiLabels>;
25
+ }): import("react").JSX.Element;
26
+ export declare function AgentResourceBar<Slots extends AgentDataSlots = AgentDataSlots>({ profileRevisionId, explicitSkillSlug, onExplicitSkillChange, labels: overrides, registry }: {
27
+ profileRevisionId: string;
28
+ explicitSkillSlug: string;
29
+ onExplicitSkillChange: (value: string) => void;
30
+ labels?: Partial<AgentUiLabels>;
31
+ registry?: AgentSlotRegistry<Slots>;
32
+ }): string | number | bigint | true | Iterable<ReactNode> | Promise<string | number | bigint | boolean | import("react").ReactPortal | import("react").ReactElement<unknown, string | import("react").JSXElementConstructor<any>> | Iterable<ReactNode> | null | undefined> | import("react").JSX.Element;
33
+ export declare function AgentExecutionTrace<Slots extends AgentDataSlots = AgentDataSlots>({ items, label, registry }: {
34
+ items: readonly Extract<AgentProjectionItem, {
35
+ slot: "trace-item";
36
+ }>[];
37
+ label?: string;
38
+ registry?: AgentSlotRegistry<Slots>;
39
+ }): import("react").JSX.Element | null;
40
+ export declare function AgentActionCard({ interaction, onResolve }: {
41
+ interaction: Pick<agentV1.Interaction, "id" | "kind" | "status">;
42
+ onResolve: (resolution: "confirmed" | "rejected") => void | Promise<void>;
43
+ }): import("react").JSX.Element;
44
+ export declare function AgentComposer({ value, onChange, onSubmit, running, onStop, labels: overrides }: {
45
+ value: string;
46
+ onChange: (value: string) => void;
47
+ onSubmit: () => void;
48
+ running: boolean;
49
+ onStop: () => void;
50
+ labels?: Partial<AgentUiLabels>;
51
+ }): import("react").JSX.Element;
52
+ export declare function AgentProjectionNodes<Slots extends AgentDataSlots = AgentDataSlots>({ items, registry, onResolveInteraction }: {
53
+ items: readonly AgentProjectionItem<Slots>[];
54
+ registry?: AgentSlotRegistry<Slots>;
55
+ onResolveInteraction?: (interactionId: string, resolution: "confirmed" | "rejected") => void | Promise<void>;
56
+ }): import("react").JSX.Element;
57
+ export declare function AgentConversation<Slots extends AgentDataSlots = AgentDataSlots>({ model, explicitSkillSlug, registry, header, labels: overrides, onError }: {
58
+ model: AgentSessionModel<Slots>;
59
+ explicitSkillSlug?: string;
60
+ registry?: AgentSlotRegistry<Slots>;
61
+ header?: ReactNode;
62
+ labels?: Partial<AgentUiLabels>;
63
+ onError?: (error: Error) => void;
64
+ }): import("react").JSX.Element;
65
+ export declare function AgentChat<Slots extends AgentDataSlots = AgentDataSlots>({ model, title, subtitle, profileRevisionId, sessions, activeSessionId, onSelectSession, onNewSession, onDeleteSession, registry, labels: overrides }: {
66
+ model: AgentSessionModel<Slots>;
67
+ title?: string;
68
+ subtitle?: string;
69
+ profileRevisionId: string;
70
+ sessions?: readonly agentV1.Session[];
71
+ activeSessionId?: string;
72
+ onSelectSession?: (id: string) => void;
73
+ onNewSession?: () => void;
74
+ onDeleteSession?: (id: string) => void;
75
+ registry?: AgentSlotRegistry<Slots>;
76
+ labels?: Partial<AgentUiLabels>;
77
+ }): import("react").JSX.Element;
78
+ export declare function AgentProfileEditor<Slots extends AgentDataSlots = AgentDataSlots>({ revision, onChange, onSave, saving, registry }: {
79
+ revision: agentV1.AgentProfileRevision;
80
+ onChange: (revision: agentV1.AgentProfileRevision) => void;
81
+ onSave: () => void;
82
+ saving?: boolean;
83
+ registry?: AgentSlotRegistry<Slots>;
84
+ }): string | number | bigint | true | Iterable<ReactNode> | Promise<string | number | bigint | boolean | import("react").ReactPortal | import("react").ReactElement<unknown, string | import("react").JSXElementConstructor<any>> | Iterable<ReactNode> | null | undefined> | import("react").JSX.Element;
85
+ export declare function AgentStudio({ editor, preview }: {
86
+ editor: ReactNode;
87
+ preview: ReactNode;
88
+ }): import("react").JSX.Element;
package/package.json ADDED
@@ -0,0 +1,50 @@
1
+ {
2
+ "name": "@agent-factory-platform/agent-react",
3
+ "version": "0.2.0",
4
+ "description": "Agent runtime bindings and themeable React conversation surfaces.",
5
+ "license": "MIT OR Apache-2.0",
6
+ "repository": {
7
+ "type": "git",
8
+ "url": "git+https://github.com/JingYeoh/agent-factory.git"
9
+ },
10
+ "publishConfig": {
11
+ "access": "public",
12
+ "provenance": true
13
+ },
14
+ "type": "module",
15
+ "files": [
16
+ "dist"
17
+ ],
18
+ "sideEffects": [
19
+ "./dist/agent-react.css"
20
+ ],
21
+ "exports": {
22
+ ".": {
23
+ "types": "./dist/index.d.ts",
24
+ "import": "./dist/index.js"
25
+ },
26
+ "./styles.css": "./dist/agent-react.css"
27
+ },
28
+ "peerDependencies": {
29
+ "react": "^19.0.0"
30
+ },
31
+ "dependencies": {
32
+ "@agent-factory-platform/client": "0.2.0",
33
+ "@agent-factory-platform/ui-kit": "0.2.0",
34
+ "@bufbuild/protobuf": "^2.2.3",
35
+ "lucide-react": "^1.23.0"
36
+ },
37
+ "devDependencies": {
38
+ "@types/react": "^19.0.0",
39
+ "@vitejs/plugin-react": "^4.3.4",
40
+ "react": "^19.0.0",
41
+ "typescript": "^5.7.2",
42
+ "vite": "^6.0.7",
43
+ "vitest": "^4.1.9"
44
+ },
45
+ "scripts": {
46
+ "lint": "tsc -p tsconfig.json --noEmit",
47
+ "test": "vitest run",
48
+ "build": "node ../../scripts/clean-package-dist.mjs . && vite build && tsc -p tsconfig.build.json"
49
+ }
50
+ }