@sleep2agi/agent-network-dashboard 0.5.1-preview.40 → 0.5.1-preview.42
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/.next/BUILD_ID +1 -1
- package/.next/build-manifest.json +3 -3
- package/.next/diagnostics/route-bundle-stats.json +4 -4
- package/.next/fallback-build-manifest.json +3 -3
- package/.next/server/app/_global-error.html +1 -1
- package/.next/server/app/_global-error.rsc +1 -1
- package/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
- package/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
- package/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
- package/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/.next/server/app/_not-found.html +1 -1
- package/.next/server/app/_not-found.rsc +1 -1
- package/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
- package/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
- package/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
- package/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
- package/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
- package/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
- package/.next/server/app/admin.html +1 -1
- package/.next/server/app/admin.rsc +1 -1
- package/.next/server/app/admin.segments/_full.segment.rsc +1 -1
- package/.next/server/app/admin.segments/_head.segment.rsc +1 -1
- package/.next/server/app/admin.segments/_index.segment.rsc +1 -1
- package/.next/server/app/admin.segments/_tree.segment.rsc +1 -1
- package/.next/server/app/admin.segments/admin/__PAGE__.segment.rsc +1 -1
- package/.next/server/app/admin.segments/admin.segment.rsc +1 -1
- package/.next/server/app/index.html +2 -2
- package/.next/server/app/index.rsc +2 -2
- package/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
- package/.next/server/app/index.segments/_full.segment.rsc +2 -2
- package/.next/server/app/index.segments/_head.segment.rsc +1 -1
- package/.next/server/app/index.segments/_index.segment.rsc +1 -1
- package/.next/server/app/index.segments/_tree.segment.rsc +1 -1
- package/.next/server/app/login/page_client-reference-manifest.js +1 -1
- package/.next/server/app/login.html +2 -2
- package/.next/server/app/login.rsc +2 -2
- package/.next/server/app/login.segments/_full.segment.rsc +2 -2
- package/.next/server/app/login.segments/_head.segment.rsc +1 -1
- package/.next/server/app/login.segments/_index.segment.rsc +1 -1
- package/.next/server/app/login.segments/_tree.segment.rsc +1 -1
- package/.next/server/app/login.segments/login/__PAGE__.segment.rsc +2 -2
- package/.next/server/app/login.segments/login.segment.rsc +1 -1
- package/.next/server/app/logs.html +1 -1
- package/.next/server/app/logs.rsc +1 -1
- package/.next/server/app/logs.segments/_full.segment.rsc +1 -1
- package/.next/server/app/logs.segments/_head.segment.rsc +1 -1
- package/.next/server/app/logs.segments/_index.segment.rsc +1 -1
- package/.next/server/app/logs.segments/_tree.segment.rsc +1 -1
- package/.next/server/app/logs.segments/logs/__PAGE__.segment.rsc +1 -1
- package/.next/server/app/logs.segments/logs.segment.rsc +1 -1
- package/.next/server/app/messages.html +1 -1
- package/.next/server/app/messages.rsc +1 -1
- package/.next/server/app/messages.segments/_full.segment.rsc +1 -1
- package/.next/server/app/messages.segments/_head.segment.rsc +1 -1
- package/.next/server/app/messages.segments/_index.segment.rsc +1 -1
- package/.next/server/app/messages.segments/_tree.segment.rsc +1 -1
- package/.next/server/app/messages.segments/messages/__PAGE__.segment.rsc +1 -1
- package/.next/server/app/messages.segments/messages.segment.rsc +1 -1
- package/.next/server/app/node.html +1 -1
- package/.next/server/app/node.rsc +1 -1
- package/.next/server/app/node.segments/_full.segment.rsc +1 -1
- package/.next/server/app/node.segments/_head.segment.rsc +1 -1
- package/.next/server/app/node.segments/_index.segment.rsc +1 -1
- package/.next/server/app/node.segments/_tree.segment.rsc +1 -1
- package/.next/server/app/node.segments/node/__PAGE__.segment.rsc +1 -1
- package/.next/server/app/node.segments/node.segment.rsc +1 -1
- package/.next/server/app/nodes.html +1 -1
- package/.next/server/app/nodes.rsc +1 -1
- package/.next/server/app/nodes.segments/_full.segment.rsc +1 -1
- package/.next/server/app/nodes.segments/_head.segment.rsc +1 -1
- package/.next/server/app/nodes.segments/_index.segment.rsc +1 -1
- package/.next/server/app/nodes.segments/_tree.segment.rsc +1 -1
- package/.next/server/app/nodes.segments/nodes/__PAGE__.segment.rsc +1 -1
- package/.next/server/app/nodes.segments/nodes.segment.rsc +1 -1
- package/.next/server/app/page_client-reference-manifest.js +1 -1
- package/.next/server/app/server-logs.html +1 -1
- package/.next/server/app/server-logs.rsc +1 -1
- package/.next/server/app/server-logs.segments/_full.segment.rsc +1 -1
- package/.next/server/app/server-logs.segments/_head.segment.rsc +1 -1
- package/.next/server/app/server-logs.segments/_index.segment.rsc +1 -1
- package/.next/server/app/server-logs.segments/_tree.segment.rsc +1 -1
- package/.next/server/app/server-logs.segments/server-logs/__PAGE__.segment.rsc +1 -1
- package/.next/server/app/server-logs.segments/server-logs.segment.rsc +1 -1
- package/.next/server/app/settings/networks.html +1 -1
- package/.next/server/app/settings/networks.rsc +1 -1
- package/.next/server/app/settings/networks.segments/_full.segment.rsc +1 -1
- package/.next/server/app/settings/networks.segments/_head.segment.rsc +1 -1
- package/.next/server/app/settings/networks.segments/_index.segment.rsc +1 -1
- package/.next/server/app/settings/networks.segments/_tree.segment.rsc +1 -1
- package/.next/server/app/settings/networks.segments/settings/networks/__PAGE__.segment.rsc +1 -1
- package/.next/server/app/settings/networks.segments/settings/networks.segment.rsc +1 -1
- package/.next/server/app/settings/networks.segments/settings.segment.rsc +1 -1
- package/.next/server/app/settings/page_client-reference-manifest.js +1 -1
- package/.next/server/app/settings/tokens.html +1 -1
- package/.next/server/app/settings/tokens.rsc +1 -1
- package/.next/server/app/settings/tokens.segments/_full.segment.rsc +1 -1
- package/.next/server/app/settings/tokens.segments/_head.segment.rsc +1 -1
- package/.next/server/app/settings/tokens.segments/_index.segment.rsc +1 -1
- package/.next/server/app/settings/tokens.segments/_tree.segment.rsc +1 -1
- package/.next/server/app/settings/tokens.segments/settings/tokens/__PAGE__.segment.rsc +1 -1
- package/.next/server/app/settings/tokens.segments/settings/tokens.segment.rsc +1 -1
- package/.next/server/app/settings/tokens.segments/settings.segment.rsc +1 -1
- package/.next/server/app/settings.html +2 -2
- package/.next/server/app/settings.rsc +2 -2
- package/.next/server/app/settings.segments/_full.segment.rsc +2 -2
- package/.next/server/app/settings.segments/_head.segment.rsc +1 -1
- package/.next/server/app/settings.segments/_index.segment.rsc +1 -1
- package/.next/server/app/settings.segments/_tree.segment.rsc +1 -1
- package/.next/server/app/settings.segments/settings/__PAGE__.segment.rsc +2 -2
- package/.next/server/app/settings.segments/settings.segment.rsc +1 -1
- package/.next/server/app/tasks.html +1 -1
- package/.next/server/app/tasks.rsc +1 -1
- package/.next/server/app/tasks.segments/_full.segment.rsc +1 -1
- package/.next/server/app/tasks.segments/_head.segment.rsc +1 -1
- package/.next/server/app/tasks.segments/_index.segment.rsc +1 -1
- package/.next/server/app/tasks.segments/_tree.segment.rsc +1 -1
- package/.next/server/app/tasks.segments/tasks/__PAGE__.segment.rsc +1 -1
- package/.next/server/app/tasks.segments/tasks.segment.rsc +1 -1
- package/.next/server/chunks/ssr/agent-network-dashboard_09kk21a._.js +2 -2
- package/.next/server/chunks/ssr/agent-network-dashboard_09kk21a._.js.map +1 -1
- package/.next/server/chunks/ssr/agent-network-dashboard_app_01jhlxz._.js +1 -1
- package/.next/server/chunks/ssr/agent-network-dashboard_app_01jhlxz._.js.map +1 -1
- package/.next/server/chunks/ssr/agent-network-dashboard_app_09d29my._.js +1 -1
- package/.next/server/chunks/ssr/agent-network-dashboard_app_09d29my._.js.map +1 -1
- package/.next/server/middleware-build-manifest.js +3 -3
- package/.next/server/pages/404.html +1 -1
- package/.next/server/pages/500.html +1 -1
- package/.next/static/chunks/{06_k1dgr3isa2.js → 0_2.t7lf33cgr.js} +1 -1
- package/.next/static/chunks/{05.asnoxq2t39.js → 0zklaue5r5j3i.js} +1 -1
- package/.next/static/chunks/0~ace06dgycy0.js +4 -0
- package/.next/trace +2 -2
- package/.next/trace-build +1 -1
- package/app/components/TopoGraph.tsx +46 -0
- package/package.json +1 -1
- package/scripts/topo-edge-visible-linecap-test.mjs +89 -0
- package/scripts/topo-group-box-stroke-test.mjs +105 -0
- package/.next/static/chunks/0fxhdt5-198se.js +0 -4
- /package/.next/static/{PtUnxSzwOvGhpWPUawz9k → IcF-8xU_qK-YW8IVus8yf}/_buildManifest.js +0 -0
- /package/.next/static/{PtUnxSzwOvGhpWPUawz9k → IcF-8xU_qK-YW8IVus8yf}/_clientMiddlewareManifest.js +0 -0
- /package/.next/static/{PtUnxSzwOvGhpWPUawz9k → IcF-8xU_qK-YW8IVus8yf}/_ssgManifest.js +0 -0
|
@@ -3973,7 +3973,34 @@ export function TopoGraph({ sessions, sseSessions, renameSignal }: TopoGraphProp
|
|
|
3973
3973
|
stroke={(isPinned || isHovered) ? pal.legendAccent : pal.ringStroke}
|
|
3974
3974
|
strokeWidth={isPinned ? 3 : isHovered ? 2 : 1.5}
|
|
3975
3975
|
strokeDasharray={(isPinned || isHovered) ? 'none' : '6 6'}
|
|
3976
|
+
/* Round 380 / Loop: cluster box stroke gets round
|
|
3977
|
+
linecap + round linejoin. Sibling SVG stroke-
|
|
3978
|
+
softening polish to R378 flow-rail linecap + R379
|
|
3979
|
+
minimap viewport linejoin — extends the family to
|
|
3980
|
+
the group cluster boundary box (grid layout only):
|
|
3981
|
+
R288 chrome icons strokeLinecap='round'
|
|
3982
|
+
R378 flow-rail dashes strokeLinecap='round'
|
|
3983
|
+
R380 group box dashes strokeLinecap='round' (this round)
|
|
3984
|
+
R379 viewport rect strokeLinejoin='round'
|
|
3985
|
+
R380 group box corners strokeLinejoin='round' (this round)
|
|
3986
|
+
Linecap rounds the R85 '6 6' marching-ants dash
|
|
3987
|
+
pills at rest — each 6 px dash gains a ~0.75 px
|
|
3988
|
+
round cap (sw=1.5 idle), reading as soft pills
|
|
3989
|
+
instead of sharp 6 × 1.5 px rectangles. Linejoin
|
|
3990
|
+
rounds the 4 sharp 90° corners (any state — solid
|
|
3991
|
+
or dashed); at sw=1.5 the join arc is ~0.75 px,
|
|
3992
|
+
matching R379 viewport vocabulary. Geometry-safe:
|
|
3993
|
+
stroke-* properties only affect paint, not bbox.
|
|
3994
|
+
The R51 sentinel 1.5/3 strokeWidth values stay
|
|
3995
|
+
intact (the overlap probe is gated to g[data-
|
|
3996
|
+
node], so this cluster-internal rect is invisible
|
|
3997
|
+
to it anyway). data-group-box-linecap + -linejoin
|
|
3998
|
+
attrs expose the values for tests. */
|
|
3999
|
+
strokeLinecap="round"
|
|
4000
|
+
strokeLinejoin="round"
|
|
3976
4001
|
data-group-box-pinned={isPinned ? 'true' : 'false'}
|
|
4002
|
+
data-group-box-linecap="round"
|
|
4003
|
+
data-group-box-linejoin="round"
|
|
3977
4004
|
// R85: ambient "marching ants" drift on the perimeter
|
|
3978
4005
|
// when this group has at least one working member, and
|
|
3979
4006
|
// neither pin nor hover is active (those treatments
|
|
@@ -4488,15 +4515,34 @@ export function TopoGraph({ sessions, sseSessions, renameSignal }: TopoGraphProp
|
|
|
4488
4515
|
online chips to splice in additional properties
|
|
4489
4516
|
beside Tailwind's). data-edge-flow-rail attr
|
|
4490
4517
|
surfaces the path for test introspection. */}
|
|
4518
|
+
{/* Round 381 / Loop: edge visible flow path picks up
|
|
4519
|
+
strokeLinecap='round'. Sibling polish to R378
|
|
4520
|
+
flow-rail dashed linecap — both flow-element paths
|
|
4521
|
+
(visible primary + dashed secondary rail) now share
|
|
4522
|
+
'round' linecap vocabulary. The visible path runs
|
|
4523
|
+
source-node → dest-node as one continuous line, so
|
|
4524
|
+
the dest-end is covered by the markerEnd arrow and
|
|
4525
|
+
the source-end usually sits inside the source-node
|
|
4526
|
+
circle. At certain alignments (post-zoom, post-
|
|
4527
|
+
layout-switch transitions), the source-end may peek
|
|
4528
|
+
out by a fraction of a px past the node edge —
|
|
4529
|
+
round caps render that overshoot as a smooth half-
|
|
4530
|
+
disc instead of a sharp rectangle. Pure paint
|
|
4531
|
+
refinement, geometry-safe (bbox of the stroke
|
|
4532
|
+
unchanged at the join with the arrow marker).
|
|
4533
|
+
data-edge-visible-linecap attr exposes the value
|
|
4534
|
+
for tests. */}
|
|
4491
4535
|
<path
|
|
4492
4536
|
d={path}
|
|
4493
4537
|
fill="none"
|
|
4494
4538
|
stroke={pal.flowEdge}
|
|
4495
4539
|
strokeWidth={renderWidth}
|
|
4540
|
+
strokeLinecap="round"
|
|
4496
4541
|
opacity={Math.min(1, (isLight ? 0.22 : 0.28) * fresh * edgeOpacityMul)}
|
|
4497
4542
|
filter={isLight ? undefined : 'url(#topo-glow)'}
|
|
4498
4543
|
markerEnd={`url(#${arrowId})`}
|
|
4499
4544
|
data-edge-visible={link.key}
|
|
4545
|
+
data-edge-visible-linecap="round"
|
|
4500
4546
|
style={{
|
|
4501
4547
|
pointerEvents: 'none',
|
|
4502
4548
|
transition: 'opacity 300ms ease-out, stroke-width 300ms ease-out, stroke 300ms ease-out',
|
package/package.json
CHANGED
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
/* Round 381 verification: edge visible flow path strokeLinecap='round'.
|
|
2
|
+
* Sibling SVG stroke-softening polish to R378 flow-rail linecap — both
|
|
3
|
+
* flow-element paths now share 'round' linecap. R380 group box closed
|
|
4
|
+
* dash-cap + corner softening; R381 closes the flow-path family at the
|
|
5
|
+
* visible primary path.
|
|
6
|
+
*
|
|
7
|
+
* Stroke-softening family snapshot post-R381:
|
|
8
|
+
* R288 chrome icons strokeLinecap='round'
|
|
9
|
+
* R378 flow-rail dashes strokeLinecap='round'
|
|
10
|
+
* R380 group box dashes strokeLinecap='round'
|
|
11
|
+
* R381 flow visible path strokeLinecap='round' (this round)
|
|
12
|
+
* R379 viewport rect strokeLinejoin='round'
|
|
13
|
+
* R380 group box corners strokeLinejoin='round'
|
|
14
|
+
*
|
|
15
|
+
* Contract:
|
|
16
|
+
* - [data-edge-visible] element stroke-linecap attr === 'round'.
|
|
17
|
+
* - data-edge-visible-linecap === 'round'.
|
|
18
|
+
* - Pre-R381 invariants:
|
|
19
|
+
* * fill='none', stroke=pal.flowEdge
|
|
20
|
+
* * markerEnd referencing arrow id
|
|
21
|
+
* * opacity-based freshness preserved (any value in 0..1)
|
|
22
|
+
* * transition list contains opacity + stroke-width + stroke
|
|
23
|
+
*/
|
|
24
|
+
import { chromium } from 'playwright';
|
|
25
|
+
import { readFileSync } from 'node:fs';
|
|
26
|
+
|
|
27
|
+
const TOKEN = JSON.parse(readFileSync('/home/vansin/.anet/config.json', 'utf8')).token;
|
|
28
|
+
const browser = await chromium.launch({ headless: true });
|
|
29
|
+
const ctx = await browser.newContext({ viewport: { width: 1500, height: 1500 } });
|
|
30
|
+
await ctx.addCookies([{ name: 'anet_dashboard_session', value: `v3:${TOKEN}`, domain: '127.0.0.1', path: '/' }]);
|
|
31
|
+
await ctx.addInitScript(() => {
|
|
32
|
+
try { localStorage.setItem('anet-theme', 'cyber'); sessionStorage.setItem('anet_v3_auth', '1'); } catch {}
|
|
33
|
+
});
|
|
34
|
+
const fresh = new Date(Date.now() - 60 * 1000).toISOString();
|
|
35
|
+
await ctx.route('**/api/hub/status*', async (route) => {
|
|
36
|
+
const r = await route.fetch();
|
|
37
|
+
const b = await r.json();
|
|
38
|
+
const nid = (b.sessions || [])[0]?.network_id || 'default';
|
|
39
|
+
const mk = (alias) => ({
|
|
40
|
+
alias, status: 'working', model: 'claude-opus-4', runtime: 'claude-code-cli',
|
|
41
|
+
network_id: nid, project_dir: null,
|
|
42
|
+
created_at: fresh, updated_at: fresh, last_seen_at: fresh,
|
|
43
|
+
});
|
|
44
|
+
await route.fulfill({ response: r, json: { ...b, sessions: [ mk('a'), mk('b') ] } });
|
|
45
|
+
});
|
|
46
|
+
const now = Date.now();
|
|
47
|
+
await ctx.route('**/api/hub/messages*', (r) => r.fulfill({ json: { messages: [
|
|
48
|
+
{ id: 'm1', from_alias: 'a', to_alias: 'b', content: 'ping',
|
|
49
|
+
network_id: 'default', created_at: new Date(now - 5000).toISOString() },
|
|
50
|
+
] } }));
|
|
51
|
+
await ctx.route('**/api/hub/tasks*', (r) => r.fulfill({ json: { tasks: [] } }));
|
|
52
|
+
|
|
53
|
+
const page = await ctx.newPage();
|
|
54
|
+
await page.goto('http://127.0.0.1:3000/', { waitUntil: 'domcontentloaded' });
|
|
55
|
+
await page.waitForSelector('[data-edge-visible]', { timeout: 15000 });
|
|
56
|
+
await page.waitForTimeout(300);
|
|
57
|
+
|
|
58
|
+
const probe = await page.evaluate(() => {
|
|
59
|
+
const p = document.querySelector('[data-edge-visible]');
|
|
60
|
+
const cs = p ? getComputedStyle(p) : null;
|
|
61
|
+
return {
|
|
62
|
+
linecapAttr: p?.getAttribute('stroke-linecap') ?? null,
|
|
63
|
+
linecapData: p?.getAttribute('data-edge-visible-linecap') ?? null,
|
|
64
|
+
fillAttr: p?.getAttribute('fill') ?? null,
|
|
65
|
+
markerEndAttr: p?.getAttribute('marker-end') ?? null,
|
|
66
|
+
transition: cs?.transition ?? null,
|
|
67
|
+
linkKey: p?.getAttribute('data-edge-visible') ?? null,
|
|
68
|
+
};
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
await browser.close();
|
|
72
|
+
|
|
73
|
+
const hasTrans = (s, prop) =>
|
|
74
|
+
new RegExp(`${prop}\\s+\\d*\\.?\\d*s|${prop}\\s+\\d+ms`, 'i').test(s || '');
|
|
75
|
+
|
|
76
|
+
const results = {
|
|
77
|
+
linecap_round: probe.linecapAttr === 'round',
|
|
78
|
+
data_linecap_round: probe.linecapData === 'round',
|
|
79
|
+
fill_none: probe.fillAttr === 'none',
|
|
80
|
+
marker_end_arrow: /^url\(#topo-arrow-/.test(probe.markerEndAttr || ''),
|
|
81
|
+
trans_has_opacity: hasTrans(probe.transition, 'opacity'),
|
|
82
|
+
trans_has_stroke_w: hasTrans(probe.transition, 'stroke-width'),
|
|
83
|
+
trans_has_stroke: hasTrans(probe.transition, 'stroke'),
|
|
84
|
+
link_key_present: (probe.linkKey || '').length > 0,
|
|
85
|
+
};
|
|
86
|
+
const ok = Object.values(results).every(Boolean);
|
|
87
|
+
console.log(`${ok ? '✅' : '❌'} edge visible path strokeLinecap='round':`, JSON.stringify(results),
|
|
88
|
+
'\n probe:', probe);
|
|
89
|
+
process.exit(ok ? 0 : 1);
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
/* Round 380 verification: cluster box stroke gets round linecap +
|
|
2
|
+
* round linejoin. Sibling SVG stroke-softening polish to R378 flow-
|
|
3
|
+
* rail linecap + R379 minimap viewport linejoin — extends the family
|
|
4
|
+
* to the group cluster boundary box (grid layout only).
|
|
5
|
+
*
|
|
6
|
+
* Family snapshot post-R380:
|
|
7
|
+
* R288 chrome icons strokeLinecap='round'
|
|
8
|
+
* R378 flow-rail dashes strokeLinecap='round'
|
|
9
|
+
* R380 group box dashes strokeLinecap='round' (this round)
|
|
10
|
+
* R379 viewport rect strokeLinejoin='round'
|
|
11
|
+
* R380 group box corners strokeLinejoin='round' (this round)
|
|
12
|
+
*
|
|
13
|
+
* Contract (cyber, grid layout):
|
|
14
|
+
* - [data-group-box-pinned] elements have stroke-linecap='round'
|
|
15
|
+
* + stroke-linejoin='round'.
|
|
16
|
+
* - data-group-box-linecap + data-group-box-linejoin === 'round'.
|
|
17
|
+
* - Pre-R380 invariants:
|
|
18
|
+
* * strokeWidth=1.5 at rest (R68 ladder)
|
|
19
|
+
* * strokeDasharray='6 6' at rest (R85 marching ants)
|
|
20
|
+
* * data-group-box-pinned 'false' at rest
|
|
21
|
+
* * data-group-box-lifted 'false' at rest
|
|
22
|
+
*/
|
|
23
|
+
import { chromium } from 'playwright';
|
|
24
|
+
import { readFileSync } from 'node:fs';
|
|
25
|
+
|
|
26
|
+
const TOKEN = JSON.parse(readFileSync('/home/vansin/.anet/config.json', 'utf8')).token;
|
|
27
|
+
const browser = await chromium.launch({ headless: true });
|
|
28
|
+
const ctx = await browser.newContext({ viewport: { width: 1500, height: 1500 } });
|
|
29
|
+
await ctx.addCookies([{ name: 'anet_dashboard_session', value: `v3:${TOKEN}`, domain: '127.0.0.1', path: '/' }]);
|
|
30
|
+
await ctx.addInitScript(() => {
|
|
31
|
+
try {
|
|
32
|
+
localStorage.setItem('anet-theme', 'cyber');
|
|
33
|
+
sessionStorage.setItem('anet_v3_auth', '1');
|
|
34
|
+
localStorage.setItem('anet-layout', JSON.stringify('grid'));
|
|
35
|
+
} catch {}
|
|
36
|
+
});
|
|
37
|
+
const fresh = new Date(Date.now() - 60 * 1000).toISOString();
|
|
38
|
+
await ctx.route('**/api/hub/status*', async (route) => {
|
|
39
|
+
const r = await route.fetch();
|
|
40
|
+
const b = await r.json();
|
|
41
|
+
const nid = (b.sessions || [])[0]?.network_id || 'default';
|
|
42
|
+
const mk = (alias) => ({
|
|
43
|
+
alias, status: 'working', model: 'claude-opus-4', runtime: 'claude-code-cli',
|
|
44
|
+
network_id: nid, project_dir: null,
|
|
45
|
+
created_at: fresh, updated_at: fresh, last_seen_at: fresh,
|
|
46
|
+
});
|
|
47
|
+
// Cluster groups via prefix alias → group boxes render.
|
|
48
|
+
await route.fulfill({ response: r, json: { ...b, sessions: [
|
|
49
|
+
mk('alpha-1'), mk('alpha-2'), mk('alpha-3'),
|
|
50
|
+
mk('beta-1'), mk('beta-2'),
|
|
51
|
+
] } });
|
|
52
|
+
});
|
|
53
|
+
await ctx.route('**/api/hub/messages*', (r) => r.fulfill({ json: { messages: [] } }));
|
|
54
|
+
await ctx.route('**/api/hub/tasks*', (r) => r.fulfill({ json: { tasks: [] } }));
|
|
55
|
+
|
|
56
|
+
const page = await ctx.newPage();
|
|
57
|
+
await page.goto('http://127.0.0.1:3000/', { waitUntil: 'domcontentloaded' });
|
|
58
|
+
await page.waitForSelector('[data-topo-chrome-layout="grid"]', { timeout: 15000 });
|
|
59
|
+
const layoutActive = await page.getAttribute('[data-topo-chrome-layout="grid"]', 'data-topo-chrome-layout-active');
|
|
60
|
+
if (layoutActive !== 'true') await page.click('[data-topo-chrome-layout="grid"]');
|
|
61
|
+
await page.waitForSelector('[data-group-box-pinned]', { timeout: 10000 });
|
|
62
|
+
await page.waitForTimeout(400);
|
|
63
|
+
|
|
64
|
+
const probe = await page.evaluate(() => {
|
|
65
|
+
const boxes = Array.from(document.querySelectorAll('[data-group-box-pinned]'));
|
|
66
|
+
return boxes.map(el => ({
|
|
67
|
+
linecapAttr: el.getAttribute('stroke-linecap'),
|
|
68
|
+
linejoinAttr: el.getAttribute('stroke-linejoin'),
|
|
69
|
+
linecapData: el.getAttribute('data-group-box-linecap'),
|
|
70
|
+
linejoinData: el.getAttribute('data-group-box-linejoin'),
|
|
71
|
+
strokeWidth: el.getAttribute('stroke-width'),
|
|
72
|
+
strokeDasharray: el.getAttribute('stroke-dasharray'),
|
|
73
|
+
pinnedAttr: el.getAttribute('data-group-box-pinned'),
|
|
74
|
+
liftedAttr: el.getAttribute('data-group-box-lifted'),
|
|
75
|
+
}));
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
await browser.close();
|
|
79
|
+
|
|
80
|
+
const allOk = probe.length >= 1 && probe.every(b =>
|
|
81
|
+
b.linecapAttr === 'round'
|
|
82
|
+
&& b.linejoinAttr === 'round'
|
|
83
|
+
&& b.linecapData === 'round'
|
|
84
|
+
&& b.linejoinData === 'round'
|
|
85
|
+
&& b.strokeWidth === '1.5' // R68 rest
|
|
86
|
+
&& b.strokeDasharray === '6 6' // R85 rest
|
|
87
|
+
&& b.pinnedAttr === 'false'
|
|
88
|
+
&& b.liftedAttr === 'false'
|
|
89
|
+
);
|
|
90
|
+
|
|
91
|
+
const results = {
|
|
92
|
+
boxes_rendered: probe.length >= 1,
|
|
93
|
+
all_linecap_round: probe.every(b => b.linecapAttr === 'round'),
|
|
94
|
+
all_linejoin_round: probe.every(b => b.linejoinAttr === 'round'),
|
|
95
|
+
all_data_linecap: probe.every(b => b.linecapData === 'round'),
|
|
96
|
+
all_data_linejoin: probe.every(b => b.linejoinData === 'round'),
|
|
97
|
+
all_strokew_1_5_rest: probe.every(b => b.strokeWidth === '1.5'),
|
|
98
|
+
all_dash_6_6_rest: probe.every(b => b.strokeDasharray === '6 6'),
|
|
99
|
+
all_pinned_false: probe.every(b => b.pinnedAttr === 'false'),
|
|
100
|
+
all_lifted_false: probe.every(b => b.liftedAttr === 'false'),
|
|
101
|
+
};
|
|
102
|
+
const ok = allOk && Object.values(results).every(Boolean);
|
|
103
|
+
console.log(`${ok ? '✅' : '❌'} group box strokeLinecap + Linejoin = round:`, JSON.stringify(results),
|
|
104
|
+
'\n boxes:', probe.map(b => ({ linecap: b.linecapAttr, linejoin: b.linejoinAttr, sw: b.strokeWidth, dash: b.strokeDasharray })));
|
|
105
|
+
process.exit(ok ? 0 : 1);
|