@agentprojectcontext/apx 1.72.0 → 1.73.1
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/package.json +1 -1
- package/src/interfaces/web/dist/assets/index-CUeIhw7z.css +1 -0
- package/src/interfaces/web/dist/assets/index-CqlRznhf.js +819 -0
- package/src/interfaces/web/dist/assets/index-CqlRznhf.js.map +1 -0
- package/src/interfaces/web/dist/index.html +2 -2
- package/src/interfaces/web/src/i18n/en.ts +3 -0
- package/src/interfaces/web/src/i18n/es.ts +3 -0
- package/src/interfaces/web/src/screens/project/AgentBrainGraph.tsx +76 -7
- package/src/interfaces/web/dist/assets/index-DVxJfrii.js +0 -819
- package/src/interfaces/web/dist/assets/index-DVxJfrii.js.map +0 -1
- package/src/interfaces/web/dist/assets/index-vSNUqL56.css +0 -1
|
@@ -18,8 +18,8 @@
|
|
|
18
18
|
<link rel="apple-touch-icon" href="/favicon/dark/apple-touch-icon.png" media="(prefers-color-scheme: dark)" />
|
|
19
19
|
<link rel="manifest" href="/favicon/white/site.webmanifest" media="(prefers-color-scheme: light)" />
|
|
20
20
|
<link rel="manifest" href="/favicon/dark/site.webmanifest" media="(prefers-color-scheme: dark)" />
|
|
21
|
-
<script type="module" crossorigin src="/assets/index-
|
|
22
|
-
<link rel="stylesheet" crossorigin href="/assets/index-
|
|
21
|
+
<script type="module" crossorigin src="/assets/index-CqlRznhf.js"></script>
|
|
22
|
+
<link rel="stylesheet" crossorigin href="/assets/index-CUeIhw7z.css">
|
|
23
23
|
</head>
|
|
24
24
|
<body class="bg-background text-foreground antialiased">
|
|
25
25
|
<div id="root"></div>
|
|
@@ -1495,6 +1495,9 @@ export const en = {
|
|
|
1495
1495
|
brain_pan_hint: "scroll to zoom · drag background to pan",
|
|
1496
1496
|
brain_expand: "Expand brains",
|
|
1497
1497
|
brain_collapse: "Collapse",
|
|
1498
|
+
brain_open: "Open",
|
|
1499
|
+
brain_part_of: "Part of",
|
|
1500
|
+
brain_branches: "Branches",
|
|
1498
1501
|
config_def_desc: "definition (frontmatter + system prompt).",
|
|
1499
1502
|
memory_durable_desc: "durable facts the agent remembers.",
|
|
1500
1503
|
running: "running",
|
|
@@ -1493,6 +1493,9 @@ export const es = {
|
|
|
1493
1493
|
brain_pan_hint: "scroll para zoom · arrastrá el fondo para mover",
|
|
1494
1494
|
brain_expand: "Expandir cerebros",
|
|
1495
1495
|
brain_collapse: "Colapsar",
|
|
1496
|
+
brain_open: "Abrir",
|
|
1497
|
+
brain_part_of: "Parte de",
|
|
1498
|
+
brain_branches: "Ramas",
|
|
1496
1499
|
config_def_desc: "definición (frontmatter + system prompt).",
|
|
1497
1500
|
memory_durable_desc: "hechos durables que el agente recuerda.",
|
|
1498
1501
|
running: "running",
|
|
@@ -53,6 +53,12 @@ function kindLabel(k: BrainKind): string {
|
|
|
53
53
|
const RADIUS: Record<BrainRole, number> = { core: 24, hub: 12, leaf: 6 };
|
|
54
54
|
const roleOf = (n: BrainNode): BrainRole => n.role ?? "leaf";
|
|
55
55
|
const clamp = (v: number, lo: number, hi: number) => Math.max(lo, Math.min(hi, v));
|
|
56
|
+
const uniqById = <T extends { id: string }>(arr: T[]): T[] => {
|
|
57
|
+
const m = new Map<string, T>();
|
|
58
|
+
for (const n of arr) m.set(n.id, n);
|
|
59
|
+
return [...m.values()];
|
|
60
|
+
};
|
|
61
|
+
const clip = (s: string, n = 26) => (s.length > n ? `${s.slice(0, n)}…` : s);
|
|
56
62
|
|
|
57
63
|
export function BrainGraph({
|
|
58
64
|
nodes, edges, height = 520, onNodeClick, toolbar,
|
|
@@ -72,6 +78,9 @@ export function BrainGraph({
|
|
|
72
78
|
const linksRef = useRef<SimLink[]>([]);
|
|
73
79
|
const dragRef = useRef<SimNode | null>(null);
|
|
74
80
|
const panRef = useRef<{ x: number; y: number } | null>(null);
|
|
81
|
+
// Press bookkeeping so a drag is never mistaken for a click (which navigates).
|
|
82
|
+
const downRef = useRef<{ x: number; y: number } | null>(null);
|
|
83
|
+
const movedRef = useRef(false);
|
|
75
84
|
const viewRef = useRef({ tx: 0, ty: 0, k: 1 });
|
|
76
85
|
const fitRef = useRef<() => void>(() => {});
|
|
77
86
|
const [, setVersion] = useState(0);
|
|
@@ -188,6 +197,8 @@ export function BrainGraph({
|
|
|
188
197
|
if (roleOf(n) === "core") return;
|
|
189
198
|
e.stopPropagation();
|
|
190
199
|
dragRef.current = n;
|
|
200
|
+
downRef.current = { x: e.clientX, y: e.clientY };
|
|
201
|
+
movedRef.current = false;
|
|
191
202
|
(e.target as Element).setPointerCapture?.(e.pointerId);
|
|
192
203
|
simRef.current?.alphaTarget(0.3).restart();
|
|
193
204
|
};
|
|
@@ -197,6 +208,8 @@ export function BrainGraph({
|
|
|
197
208
|
};
|
|
198
209
|
const onMove = (e: React.PointerEvent) => {
|
|
199
210
|
if (dragRef.current) {
|
|
211
|
+
const d = downRef.current;
|
|
212
|
+
if (d && !movedRef.current && Math.hypot(e.clientX - d.x, e.clientY - d.y) > 4) movedRef.current = true;
|
|
200
213
|
const w = worldFromClient(e.clientX, e.clientY);
|
|
201
214
|
dragRef.current.fx = w.x; dragRef.current.fy = w.y;
|
|
202
215
|
return;
|
|
@@ -216,6 +229,8 @@ export function BrainGraph({
|
|
|
216
229
|
panRef.current = null;
|
|
217
230
|
simRef.current?.alphaTarget(0);
|
|
218
231
|
};
|
|
232
|
+
// Native click fires reliably on pointerup; skip it when the press was a drag.
|
|
233
|
+
const onNodeClickGuarded = (n: SimNode) => () => { if (!movedRef.current) pick(n); };
|
|
219
234
|
|
|
220
235
|
const simNodes = nodesRef.current;
|
|
221
236
|
const links = linksRef.current;
|
|
@@ -223,6 +238,13 @@ export function BrainGraph({
|
|
|
223
238
|
const legendKinds = [...new Set(nodes.map((n) => n.kind))].filter((k) => k !== "agent" && k !== "hub");
|
|
224
239
|
const pick = (n: SimNode) => { setSelected(n); onNodeClick?.(n); };
|
|
225
240
|
|
|
241
|
+
// For the detail panel: what the selected node hangs off (parents) and the
|
|
242
|
+
// branches that hang off it (children), derived from the live edges.
|
|
243
|
+
const selParents = selected ? uniqById(links.filter((l) => l.target.id === selected.id).map((l) => l.source)) : [];
|
|
244
|
+
const selChildren = selected ? uniqById(links.filter((l) => l.source.id === selected.id).map((l) => l.target)) : [];
|
|
245
|
+
// The detail line is only meaningful when it adds something beyond the title.
|
|
246
|
+
const selDetail = selected?.detail && selected.detail.trim() !== selected.label.trim() ? selected.detail : null;
|
|
247
|
+
|
|
226
248
|
const CtrlBtn = ({ onClick, title, children }: { onClick: () => void; title: string; children: React.ReactNode }) => (
|
|
227
249
|
<button type="button" title={title} onClick={onClick}
|
|
228
250
|
className="grid size-7 place-items-center rounded-md border border-border bg-card/80 text-muted-fg backdrop-blur hover:text-foreground">
|
|
@@ -329,7 +351,7 @@ export function BrainGraph({
|
|
|
329
351
|
const showLabel = isHub || isSel || !hideLeafLabels;
|
|
330
352
|
return (
|
|
331
353
|
<g key={n.id} transform={`translate(${n.x},${n.y})`} className="cursor-grab active:cursor-grabbing"
|
|
332
|
-
onPointerDown={onNodeDown(n)} onClick={(
|
|
354
|
+
onPointerDown={onNodeDown(n)} onClick={onNodeClickGuarded(n)}>
|
|
333
355
|
<circle r={r} fill={color} filter="url(#brain-glow)" opacity={0.3}>
|
|
334
356
|
<animate attributeName="r" values={`${r};${r + 6};${r}`} dur={`${beat}s`} begin={begin} repeatCount="indefinite" />
|
|
335
357
|
<animate attributeName="opacity" values="0.32;0.08;0.32" dur={`${beat}s`} begin={begin} repeatCount="indefinite" />
|
|
@@ -364,16 +386,63 @@ export function BrainGraph({
|
|
|
364
386
|
</div>
|
|
365
387
|
|
|
366
388
|
{selected && (
|
|
367
|
-
<div className="rounded-lg border border-border bg-card p-3 text-xs">
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
<span className="
|
|
389
|
+
<div className="space-y-2.5 rounded-lg border border-border bg-card p-3 text-xs">
|
|
390
|
+
{/* The clicked node: title, type, relation */}
|
|
391
|
+
<div className="flex flex-wrap items-center gap-2">
|
|
392
|
+
<span className="size-2.5 rounded-full" style={{ background: KIND_COLOR[selected.kind] }} />
|
|
393
|
+
{selected.emoji && <span className="text-sm leading-none">{selected.emoji}</span>}
|
|
394
|
+
<span className="text-[13px] font-semibold">{selected.label}</span>
|
|
395
|
+
<span className="rounded bg-muted px-1.5 py-0.5 text-[10px] uppercase tracking-wide text-muted-fg">
|
|
396
|
+
{kindLabel(selected.kind)}
|
|
397
|
+
</span>
|
|
372
398
|
{selected.relation && <span className="text-muted-fg">· {selected.relation}</span>}
|
|
399
|
+
<div className="ml-auto flex items-center gap-2">
|
|
400
|
+
{selected.slug && onNodeClick && (
|
|
401
|
+
<button type="button" onClick={() => onNodeClick(selected)} className="text-primary hover:underline">
|
|
402
|
+
{t("agents_ui.brain_open")}
|
|
403
|
+
</button>
|
|
404
|
+
)}
|
|
405
|
+
<button type="button" onClick={() => setSelected(null)} className="text-muted-fg hover:text-foreground">✕</button>
|
|
406
|
+
</div>
|
|
373
407
|
</div>
|
|
374
|
-
|
|
408
|
+
|
|
409
|
+
{/* Internal info — only when it adds something beyond the title */}
|
|
410
|
+
{selDetail && <p className="whitespace-pre-wrap text-muted-fg">{selDetail}</p>}
|
|
411
|
+
|
|
412
|
+
{/* Where it hangs from */}
|
|
413
|
+
{selParents.length > 0 && (
|
|
414
|
+
<div className="flex flex-wrap items-center gap-1.5">
|
|
415
|
+
<span className="text-[10px] uppercase tracking-wide text-muted-fg/70">{t("agents_ui.brain_part_of")}</span>
|
|
416
|
+
{selParents.map((p) => <NeighborChip key={p.id} node={p} onClick={() => setSelected(p)} />)}
|
|
417
|
+
</div>
|
|
418
|
+
)}
|
|
419
|
+
|
|
420
|
+
{/* Branches that follow it */}
|
|
421
|
+
{selChildren.length > 0 && (
|
|
422
|
+
<div className="flex flex-wrap items-center gap-1.5">
|
|
423
|
+
<span className="text-[10px] uppercase tracking-wide text-muted-fg/70">
|
|
424
|
+
{t("agents_ui.brain_branches")} · {selChildren.length}
|
|
425
|
+
</span>
|
|
426
|
+
{selChildren.map((c) => <NeighborChip key={c.id} node={c} onClick={() => setSelected(c)} />)}
|
|
427
|
+
</div>
|
|
428
|
+
)}
|
|
375
429
|
</div>
|
|
376
430
|
)}
|
|
377
431
|
</div>
|
|
378
432
|
);
|
|
379
433
|
}
|
|
434
|
+
|
|
435
|
+
// A clickable chip for a connected node in the detail panel.
|
|
436
|
+
function NeighborChip({ node, onClick }: { node: BrainNode; onClick: () => void }) {
|
|
437
|
+
return (
|
|
438
|
+
<button
|
|
439
|
+
type="button"
|
|
440
|
+
onClick={onClick}
|
|
441
|
+
className="inline-flex max-w-[220px] items-center gap-1 rounded-md border border-border bg-muted/40 px-1.5 py-0.5 text-[11px] hover:border-muted-fg/50 hover:bg-muted"
|
|
442
|
+
>
|
|
443
|
+
<span className="size-1.5 shrink-0 rounded-full" style={{ background: KIND_COLOR[node.kind] }} />
|
|
444
|
+
{node.emoji && <span className="leading-none">{node.emoji}</span>}
|
|
445
|
+
<span className="truncate">{clip(node.label, 28)}</span>
|
|
446
|
+
</button>
|
|
447
|
+
);
|
|
448
|
+
}
|