@sleep2agi/agent-network-dashboard 0.4.6-preview.234 → 0.4.6-preview.236
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/prerender-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/page_client-reference-manifest.js +1 -1
- package/.next/server/app/_not-found.html +2 -2
- package/.next/server/app/_not-found.rsc +2 -2
- package/.next/server/app/_not-found.segments/_full.segment.rsc +2 -2
- package/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
- package/.next/server/app/_not-found.segments/_index.segment.rsc +2 -2
- 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 +2 -2
- package/.next/server/app/admin/page_client-reference-manifest.js +1 -1
- package/.next/server/app/admin.html +2 -2
- package/.next/server/app/admin.rsc +2 -2
- package/.next/server/app/admin.segments/_full.segment.rsc +2 -2
- package/.next/server/app/admin.segments/_head.segment.rsc +1 -1
- package/.next/server/app/admin.segments/_index.segment.rsc +2 -2
- package/.next/server/app/admin.segments/_tree.segment.rsc +2 -2
- 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 +3 -3
- package/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
- package/.next/server/app/index.segments/_full.segment.rsc +3 -3
- package/.next/server/app/index.segments/_head.segment.rsc +1 -1
- package/.next/server/app/index.segments/_index.segment.rsc +2 -2
- package/.next/server/app/index.segments/_tree.segment.rsc +2 -2
- 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 +3 -3
- package/.next/server/app/login.segments/_full.segment.rsc +3 -3
- package/.next/server/app/login.segments/_head.segment.rsc +1 -1
- package/.next/server/app/login.segments/_index.segment.rsc +2 -2
- package/.next/server/app/login.segments/_tree.segment.rsc +2 -2
- 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/page_client-reference-manifest.js +1 -1
- package/.next/server/app/logs.html +2 -2
- package/.next/server/app/logs.rsc +2 -2
- package/.next/server/app/logs.segments/_full.segment.rsc +2 -2
- package/.next/server/app/logs.segments/_head.segment.rsc +1 -1
- package/.next/server/app/logs.segments/_index.segment.rsc +2 -2
- package/.next/server/app/logs.segments/_tree.segment.rsc +2 -2
- 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/page_client-reference-manifest.js +1 -1
- package/.next/server/app/messages.html +2 -2
- package/.next/server/app/messages.rsc +2 -2
- package/.next/server/app/messages.segments/_full.segment.rsc +2 -2
- package/.next/server/app/messages.segments/_head.segment.rsc +1 -1
- package/.next/server/app/messages.segments/_index.segment.rsc +2 -2
- package/.next/server/app/messages.segments/_tree.segment.rsc +2 -2
- 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/page_client-reference-manifest.js +1 -1
- package/.next/server/app/node.html +2 -2
- package/.next/server/app/node.rsc +2 -2
- package/.next/server/app/node.segments/_full.segment.rsc +2 -2
- package/.next/server/app/node.segments/_head.segment.rsc +1 -1
- package/.next/server/app/node.segments/_index.segment.rsc +2 -2
- package/.next/server/app/node.segments/_tree.segment.rsc +2 -2
- 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/page_client-reference-manifest.js +1 -1
- package/.next/server/app/nodes.html +2 -2
- package/.next/server/app/nodes.rsc +2 -2
- package/.next/server/app/nodes.segments/_full.segment.rsc +2 -2
- package/.next/server/app/nodes.segments/_head.segment.rsc +1 -1
- package/.next/server/app/nodes.segments/_index.segment.rsc +2 -2
- package/.next/server/app/nodes.segments/_tree.segment.rsc +2 -2
- 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/page_client-reference-manifest.js +1 -1
- package/.next/server/app/server-logs.html +2 -2
- package/.next/server/app/server-logs.rsc +2 -2
- package/.next/server/app/server-logs.segments/_full.segment.rsc +2 -2
- package/.next/server/app/server-logs.segments/_head.segment.rsc +1 -1
- package/.next/server/app/server-logs.segments/_index.segment.rsc +2 -2
- package/.next/server/app/server-logs.segments/_tree.segment.rsc +2 -2
- 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/page_client-reference-manifest.js +1 -1
- package/.next/server/app/settings/networks.html +2 -2
- package/.next/server/app/settings/networks.rsc +2 -2
- package/.next/server/app/settings/networks.segments/_full.segment.rsc +2 -2
- package/.next/server/app/settings/networks.segments/_head.segment.rsc +1 -1
- package/.next/server/app/settings/networks.segments/_index.segment.rsc +2 -2
- package/.next/server/app/settings/networks.segments/_tree.segment.rsc +2 -2
- 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/page_client-reference-manifest.js +1 -1
- package/.next/server/app/settings/tokens.html +2 -2
- package/.next/server/app/settings/tokens.rsc +2 -2
- package/.next/server/app/settings/tokens.segments/_full.segment.rsc +2 -2
- package/.next/server/app/settings/tokens.segments/_head.segment.rsc +1 -1
- package/.next/server/app/settings/tokens.segments/_index.segment.rsc +2 -2
- package/.next/server/app/settings/tokens.segments/_tree.segment.rsc +2 -2
- 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 +3 -3
- package/.next/server/app/settings.segments/_full.segment.rsc +3 -3
- package/.next/server/app/settings.segments/_head.segment.rsc +1 -1
- package/.next/server/app/settings.segments/_index.segment.rsc +2 -2
- package/.next/server/app/settings.segments/_tree.segment.rsc +2 -2
- 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/[id]/page_client-reference-manifest.js +1 -1
- package/.next/server/app/tasks/page_client-reference-manifest.js +1 -1
- package/.next/server/app/tasks.html +2 -2
- package/.next/server/app/tasks.rsc +2 -2
- package/.next/server/app/tasks.segments/_full.segment.rsc +2 -2
- package/.next/server/app/tasks.segments/_head.segment.rsc +1 -1
- package/.next/server/app/tasks.segments/_index.segment.rsc +2 -2
- package/.next/server/app/tasks.segments/_tree.segment.rsc +2 -2
- 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 +2 -2
- package/.next/server/pages/500.html +1 -1
- package/.next/server/server-reference-manifest.js +1 -1
- package/.next/server/server-reference-manifest.json +1 -1
- package/.next/static/chunks/{0klaaq0_k_dxm.js → 0dxbwid~u6awc.js} +1 -1
- package/.next/static/chunks/{0_emp5p873h~z.js → 0f_7j4d32pd_5.js} +1 -1
- package/.next/static/chunks/0r50330w~i9ea.css +2 -0
- package/.next/static/chunks/0yqmjy005995r.js +4 -0
- package/.next/trace +2 -2
- package/.next/trace-build +1 -1
- package/app/components/TopoGraph.tsx +95 -5
- package/package.json +1 -1
- package/scripts/topo-group-label-count-inherit-test.mjs +99 -0
- package/scripts/topo-ping-pulse-ease-test.mjs +96 -0
- package/.next/static/chunks/0j0jff7iipl3~.js +0 -4
- package/.next/static/chunks/0~k1yvhakbob6.css +0 -2
- /package/.next/static/{XbxeLaE3cwT2xRHuIRjrc → w5JTcbtsPlvOhgfAMLaO2}/_buildManifest.js +0 -0
- /package/.next/static/{XbxeLaE3cwT2xRHuIRjrc → w5JTcbtsPlvOhgfAMLaO2}/_clientMiddlewareManifest.js +0 -0
- /package/.next/static/{XbxeLaE3cwT2xRHuIRjrc → w5JTcbtsPlvOhgfAMLaO2}/_ssgManifest.js +0 -0
|
@@ -3055,7 +3055,37 @@ export function TopoGraph({ sessions, sseSessions, renameSignal }: TopoGraphProp
|
|
|
3055
3055
|
the node↔label guard still catches if the chip ever
|
|
3056
3056
|
pushes the label far enough right to clip a node.
|
|
3057
3057
|
Smaller + lighter weight reads as metadata, not name. */}
|
|
3058
|
-
|
|
3058
|
+
{/* Round 229 / Loop: member-count chip drops its explicit
|
|
3059
|
+
fill so it inherits from the parent <text>, which means
|
|
3060
|
+
R142's hover-fill transition (legendText → legend-
|
|
3061
|
+
Headline, 200ms ease-out) NOW carries the count chip
|
|
3062
|
+
with it. Pre-R229 the parent name brightened on
|
|
3063
|
+
hover while the count tspan stayed at legendText —
|
|
3064
|
+
"name lit, count dimmer than at rest" inverted the
|
|
3065
|
+
tonal hierarchy. Inheriting matches the name's
|
|
3066
|
+
transition; both rest and hover keep the SAME
|
|
3067
|
+
tonal relationship between name and count.
|
|
3068
|
+
7th surface in the hover-deepen-own-hue family
|
|
3069
|
+
(legend rows, chip-row counts, status pip, recent
|
|
3070
|
+
row text, pressure-bar segments, group-box fill +
|
|
3071
|
+
this round's group-label-count chip).
|
|
3072
|
+
|
|
3073
|
+
Also picks up tabular-nums (5th surface in the
|
|
3074
|
+
info-density tabular-nums sweep after R224 edge
|
|
3075
|
+
badge / R225 hub digit / R225 panel header /
|
|
3076
|
+
R225 recent row count). The member count rolls
|
|
3077
|
+
over often (4→5→…→9→10 as a group grows) and
|
|
3078
|
+
lives at a fixed dx=6 offset from the name, so a
|
|
3079
|
+
digit-width jitter at 9→10 used to shift the
|
|
3080
|
+
whole count visibly. Tabular locks it. */}
|
|
3081
|
+
<tspan
|
|
3082
|
+
dx="6"
|
|
3083
|
+
fontSize="11"
|
|
3084
|
+
fontWeight="400"
|
|
3085
|
+
data-group-label-count={box.key}
|
|
3086
|
+
data-group-label-count-value={box.count}
|
|
3087
|
+
style={{ fontVariantNumeric: 'tabular-nums' }}
|
|
3088
|
+
>· {box.count}</tspan>
|
|
3059
3089
|
{/* Round 58 / Loop: status mix pip strip. Compact text-
|
|
3060
3090
|
based chips (e.g. "2w 1i") so the strip stays inside
|
|
3061
3091
|
the same <text> bbox the overlap-test reads — keeps
|
|
@@ -3313,8 +3343,43 @@ export function TopoGraph({ sessions, sseSessions, renameSignal }: TopoGraphProp
|
|
|
3313
3343
|
style={{ pointerEvents: 'none' }}
|
|
3314
3344
|
data-arrival-ping={link.key}
|
|
3315
3345
|
>
|
|
3316
|
-
|
|
3317
|
-
|
|
3346
|
+
{/* Round 228 / Loop: pulse-pop ease curves on the
|
|
3347
|
+
arrival ping SMIL — extends R227's keySplines
|
|
3348
|
+
adoption from the click ripple (one-shot, two-
|
|
3349
|
+
value linear) to the canvas's repeating delivery-
|
|
3350
|
+
confirmation surfaces. Both <animate>s use
|
|
3351
|
+
calcMode=spline with keyTimes='0;0.5;1' (two
|
|
3352
|
+
segments).
|
|
3353
|
+
• r grows 0→14→22 (monotonic): unified ease-out
|
|
3354
|
+
across both segments — the ring decelerates
|
|
3355
|
+
as it expands, settling at its widest.
|
|
3356
|
+
• opacity bumps 0→0.55→0 (pulse): ease-out on
|
|
3357
|
+
the rise (fast appearance), ease-in on the
|
|
3358
|
+
fall (slow start of fade then accelerates) —
|
|
3359
|
+
the canonical "pulse-pop" kinetic shape.
|
|
3360
|
+
Together r decelerating and opacity pulse-popping
|
|
3361
|
+
give the arrival ping a real-event physicality
|
|
3362
|
+
instead of the prior linear-velocity tick. */}
|
|
3363
|
+
<animate
|
|
3364
|
+
attributeName="r"
|
|
3365
|
+
values="0;14;22"
|
|
3366
|
+
dur={`${duration}s`}
|
|
3367
|
+
begin={`-${(duration * 0.92).toFixed(2)}s`}
|
|
3368
|
+
repeatCount="indefinite"
|
|
3369
|
+
calcMode="spline"
|
|
3370
|
+
keyTimes="0;0.5;1"
|
|
3371
|
+
keySplines="0.25 0.1 0.25 1;0.25 0.1 0.25 1"
|
|
3372
|
+
/>
|
|
3373
|
+
<animate
|
|
3374
|
+
attributeName="opacity"
|
|
3375
|
+
values="0;0.55;0"
|
|
3376
|
+
dur={`${duration}s`}
|
|
3377
|
+
begin={`-${(duration * 0.92).toFixed(2)}s`}
|
|
3378
|
+
repeatCount="indefinite"
|
|
3379
|
+
calcMode="spline"
|
|
3380
|
+
keyTimes="0;0.5;1"
|
|
3381
|
+
keySplines="0.25 0.1 0.25 1;0.42 0 1 1"
|
|
3382
|
+
/>
|
|
3318
3383
|
</circle>
|
|
3319
3384
|
)}
|
|
3320
3385
|
{/* Round 76 / Loop: source dispatch pulse — mirror to the
|
|
@@ -3340,8 +3405,33 @@ export function TopoGraph({ sessions, sseSessions, renameSignal }: TopoGraphProp
|
|
|
3340
3405
|
style={{ pointerEvents: 'none' }}
|
|
3341
3406
|
data-dispatch-pulse={link.key}
|
|
3342
3407
|
>
|
|
3343
|
-
|
|
3344
|
-
|
|
3408
|
+
{/* Round 228 / Loop: same pulse-pop curves as the
|
|
3409
|
+
arrival ping above. r ease-out + opacity
|
|
3410
|
+
ease-out→ease-in. The dispatch pulse is smaller
|
|
3411
|
+
(0→12→18 vs arrival's 0→14→22), but the kinetic
|
|
3412
|
+
feel should be identical — both bookend a
|
|
3413
|
+
single message in flight, so they should
|
|
3414
|
+
physically ease the same way. */}
|
|
3415
|
+
<animate
|
|
3416
|
+
attributeName="r"
|
|
3417
|
+
values="0;12;18"
|
|
3418
|
+
dur={`${duration}s`}
|
|
3419
|
+
begin="0s"
|
|
3420
|
+
repeatCount="indefinite"
|
|
3421
|
+
calcMode="spline"
|
|
3422
|
+
keyTimes="0;0.5;1"
|
|
3423
|
+
keySplines="0.25 0.1 0.25 1;0.25 0.1 0.25 1"
|
|
3424
|
+
/>
|
|
3425
|
+
<animate
|
|
3426
|
+
attributeName="opacity"
|
|
3427
|
+
values="0;0.45;0"
|
|
3428
|
+
dur={`${duration}s`}
|
|
3429
|
+
begin="0s"
|
|
3430
|
+
repeatCount="indefinite"
|
|
3431
|
+
calcMode="spline"
|
|
3432
|
+
keyTimes="0;0.5;1"
|
|
3433
|
+
keySplines="0.25 0.1 0.25 1;0.42 0 1 1"
|
|
3434
|
+
/>
|
|
3345
3435
|
</circle>
|
|
3346
3436
|
)}
|
|
3347
3437
|
{/* Round 100 / Loop: midpoint count badge for high-
|
package/package.json
CHANGED
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
/* Round 229 verification: group-label member-count tspan drops
|
|
2
|
+
* its explicit fill (now inherits from parent <text>) and picks up
|
|
3
|
+
* fontVariantNumeric: 'tabular-nums'.
|
|
4
|
+
*
|
|
5
|
+
* Two scopes:
|
|
6
|
+
* 1) Hover-deepen-own-hue family — count chip color now follows
|
|
7
|
+
* parent name's R142 hover transition (legendText → legend-
|
|
8
|
+
* Headline). Tonal hierarchy (count < name brightness) is
|
|
9
|
+
* preserved across both rest AND hover instead of inverting
|
|
10
|
+
* on hover.
|
|
11
|
+
* 2) Info-density tabular-nums — 5th surface after R224 edge
|
|
12
|
+
* badge / R225 hub + panel header + recent row.
|
|
13
|
+
*
|
|
14
|
+
* Scenario: 6 prefix-shared aliases (alpha-1..alpha-3, beta-1..
|
|
15
|
+
* beta-3) → R106 cluster-by-prefix forms two groups, each with
|
|
16
|
+
* count=3. Grid layout has explicit group label rendering (#111).
|
|
17
|
+
*
|
|
18
|
+
* Verifications:
|
|
19
|
+
* - data-group-label-count attr present (probe selector)
|
|
20
|
+
* - tspan has NO explicit fill attribute (inheriting)
|
|
21
|
+
* - getComputedStyle().fontVariantNumeric contains 'tabular-nums'
|
|
22
|
+
* - tspan computed fill matches PARENT <text> computed fill
|
|
23
|
+
* (R142 rest-state hierarchy preserved)
|
|
24
|
+
* - count text matches '· 3'
|
|
25
|
+
* - data-group-label-count-value reflects {box.count}
|
|
26
|
+
*/
|
|
27
|
+
import { chromium } from 'playwright';
|
|
28
|
+
import { readFileSync } from 'node:fs';
|
|
29
|
+
|
|
30
|
+
const TOKEN = JSON.parse(readFileSync('/home/vansin/.anet/config.json', 'utf8')).token;
|
|
31
|
+
const browser = await chromium.launch({ headless: true });
|
|
32
|
+
const ctx = await browser.newContext({ viewport: { width: 1500, height: 1500 } });
|
|
33
|
+
await ctx.addCookies([{ name: 'anet_dashboard_session', value: `v3:${TOKEN}`, domain: '127.0.0.1', path: '/' }]);
|
|
34
|
+
await ctx.addInitScript(() => {
|
|
35
|
+
try {
|
|
36
|
+
localStorage.setItem('anet-theme', 'cyber');
|
|
37
|
+
sessionStorage.setItem('anet_v3_auth', '1');
|
|
38
|
+
// R226 grid layout — group labels render here. Storage key inferred
|
|
39
|
+
// from data-topo-layout-toggle persistence pattern.
|
|
40
|
+
localStorage.setItem('anet-topo-layout', 'grid');
|
|
41
|
+
} catch {}
|
|
42
|
+
});
|
|
43
|
+
const fresh = new Date(Date.now() - 60 * 1000).toISOString();
|
|
44
|
+
await ctx.route('**/api/hub/status*', async (route) => {
|
|
45
|
+
const r = await route.fetch();
|
|
46
|
+
const b = await r.json();
|
|
47
|
+
const nid = (b.sessions || [])[0]?.network_id || 'default';
|
|
48
|
+
const mk = (alias) => ({
|
|
49
|
+
alias, status: 'working', model: 'claude-opus-4', runtime: 'claude-code-cli',
|
|
50
|
+
network_id: nid, project_dir: null,
|
|
51
|
+
created_at: fresh, updated_at: fresh, last_seen_at: fresh,
|
|
52
|
+
});
|
|
53
|
+
await route.fulfill({ response: r, json: { ...b, sessions: [
|
|
54
|
+
mk('alpha-1'), mk('alpha-2'), mk('alpha-3'),
|
|
55
|
+
mk('beta-1'), mk('beta-2'), mk('beta-3'),
|
|
56
|
+
] } });
|
|
57
|
+
});
|
|
58
|
+
await ctx.route('**/api/hub/messages*', (r2) => r2.fulfill({ json: { messages: [] } }));
|
|
59
|
+
await ctx.route('**/api/hub/tasks*', (r2) => r2.fulfill({ json: { tasks: [] } }));
|
|
60
|
+
|
|
61
|
+
const page = await ctx.newPage();
|
|
62
|
+
await page.goto('http://127.0.0.1:3000/', { waitUntil: 'domcontentloaded' });
|
|
63
|
+
await page.waitForFunction(() => document.querySelectorAll('g[data-node]').length === 6, { timeout: 30000 });
|
|
64
|
+
await page.waitForSelector('[data-group-label-count]', { timeout: 10000, state: 'attached' });
|
|
65
|
+
await page.waitForTimeout(400);
|
|
66
|
+
|
|
67
|
+
const out = await page.evaluate(() => {
|
|
68
|
+
const counts = Array.from(document.querySelectorAll('[data-group-label-count]'));
|
|
69
|
+
return counts.map((tspan) => {
|
|
70
|
+
const parent = tspan.parentElement; // the <text data-group-label>
|
|
71
|
+
return {
|
|
72
|
+
key: tspan.getAttribute('data-group-label-count'),
|
|
73
|
+
countValue: tspan.getAttribute('data-group-label-count-value'),
|
|
74
|
+
hasFillAttr: tspan.hasAttribute('fill'),
|
|
75
|
+
text: tspan.textContent,
|
|
76
|
+
fontVarNumeric: getComputedStyle(tspan).fontVariantNumeric,
|
|
77
|
+
tspanFill: getComputedStyle(tspan).fill,
|
|
78
|
+
parentFill: parent ? getComputedStyle(parent).fill : null,
|
|
79
|
+
};
|
|
80
|
+
});
|
|
81
|
+
});
|
|
82
|
+
await browser.close();
|
|
83
|
+
|
|
84
|
+
const hasTab = (s) => /tabular-nums/.test(s || '');
|
|
85
|
+
const present = out.length > 0;
|
|
86
|
+
|
|
87
|
+
const results = {
|
|
88
|
+
groups_found: out.length === 2,
|
|
89
|
+
all_have_key: present && out.every(o => typeof o.key === 'string' && o.key.length > 0),
|
|
90
|
+
all_count_3: present && out.every(o => o.countValue === '3'),
|
|
91
|
+
all_text_dot_3: present && out.every(o => /·\s*3$/.test((o.text || '').trim())),
|
|
92
|
+
all_no_fill_attr: present && out.every(o => !o.hasFillAttr),
|
|
93
|
+
all_tabular_nums: present && out.every(o => hasTab(o.fontVarNumeric)),
|
|
94
|
+
fill_inherits_parent: present && out.every(o => o.tspanFill === o.parentFill),
|
|
95
|
+
};
|
|
96
|
+
const ok = Object.values(results).every(Boolean);
|
|
97
|
+
console.log(`${ok ? '✅' : '❌'} group-label count inherit + tabular:`, JSON.stringify(results),
|
|
98
|
+
'\n probed:', out);
|
|
99
|
+
process.exit(ok ? 0 : 1);
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
/* Round 228 verification: arrival-ping (R75) and dispatch-pulse
|
|
2
|
+
* (R76) SMIL <animate>s get pulse-pop ease curves via calcMode/
|
|
3
|
+
* keyTimes/keySplines.
|
|
4
|
+
*
|
|
5
|
+
* Coverage:
|
|
6
|
+
* - [data-arrival-ping] r → ease-out across both segments
|
|
7
|
+
* - [data-arrival-ping] opacity → ease-out rise, ease-in fall
|
|
8
|
+
* - [data-dispatch-pulse] r → ease-out across both segments
|
|
9
|
+
* - [data-dispatch-pulse] opacity → ease-out rise, ease-in fall
|
|
10
|
+
*
|
|
11
|
+
* Scenario: 4 working agents + 5 messages alpha→beta so:
|
|
12
|
+
* - link.count = 5 ≥ 3 (dispatch pulse fires)
|
|
13
|
+
* - fresh > 0.5 (both ping + pulse gate active)
|
|
14
|
+
* - reducedMotion off (cyber-themed cookie default)
|
|
15
|
+
*/
|
|
16
|
+
import { chromium } from 'playwright';
|
|
17
|
+
import { readFileSync } from 'node:fs';
|
|
18
|
+
|
|
19
|
+
const TOKEN = JSON.parse(readFileSync('/home/vansin/.anet/config.json', 'utf8')).token;
|
|
20
|
+
const browser = await chromium.launch({ headless: true });
|
|
21
|
+
const ctx = await browser.newContext({ viewport: { width: 1500, height: 1500 } });
|
|
22
|
+
await ctx.addCookies([{ name: 'anet_dashboard_session', value: `v3:${TOKEN}`, domain: '127.0.0.1', path: '/' }]);
|
|
23
|
+
await ctx.addInitScript(() => {
|
|
24
|
+
try { localStorage.setItem('anet-theme', 'cyber'); sessionStorage.setItem('anet_v3_auth', '1'); } catch {}
|
|
25
|
+
});
|
|
26
|
+
const fresh = new Date(Date.now() - 60 * 1000).toISOString();
|
|
27
|
+
await ctx.route('**/api/hub/status*', async (route) => {
|
|
28
|
+
const r = await route.fetch();
|
|
29
|
+
const b = await r.json();
|
|
30
|
+
const nid = (b.sessions || [])[0]?.network_id || 'default';
|
|
31
|
+
const mk = (alias) => ({
|
|
32
|
+
alias, status: 'working', model: 'claude-opus-4', runtime: 'claude-code-cli',
|
|
33
|
+
network_id: nid, project_dir: null,
|
|
34
|
+
created_at: fresh, updated_at: fresh, last_seen_at: fresh,
|
|
35
|
+
});
|
|
36
|
+
await route.fulfill({ response: r, json: { ...b, sessions: [
|
|
37
|
+
mk('alpha'), mk('beta'), mk('gamma'), mk('delta'),
|
|
38
|
+
] } });
|
|
39
|
+
});
|
|
40
|
+
const now = Date.now();
|
|
41
|
+
const msgs = [];
|
|
42
|
+
for (let i = 0; i < 5; i++) {
|
|
43
|
+
msgs.push({
|
|
44
|
+
id: `m${i}`, from_alias: 'alpha', to_alias: 'beta', content: 'hi',
|
|
45
|
+
network_id: 'default', created_at: new Date(now - (1000 + i * 50)).toISOString(),
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
await ctx.route('**/api/hub/messages*', (r2) => r2.fulfill({ json: { messages: msgs } }));
|
|
49
|
+
await ctx.route('**/api/hub/tasks*', (r2) => r2.fulfill({ json: { tasks: [] } }));
|
|
50
|
+
|
|
51
|
+
const page = await ctx.newPage();
|
|
52
|
+
await page.goto('http://127.0.0.1:3000/', { waitUntil: 'domcontentloaded' });
|
|
53
|
+
await page.waitForFunction(() => document.querySelectorAll('g[data-node]').length === 4, { timeout: 30000 });
|
|
54
|
+
await page.waitForSelector('[data-arrival-ping]', { timeout: 10000, state: 'attached' });
|
|
55
|
+
await page.waitForSelector('[data-dispatch-pulse]', { timeout: 10000, state: 'attached' });
|
|
56
|
+
await page.waitForTimeout(400);
|
|
57
|
+
|
|
58
|
+
const out = await page.evaluate(() => {
|
|
59
|
+
const probe = (parentSelector) => {
|
|
60
|
+
const el = document.querySelector(parentSelector);
|
|
61
|
+
if (!el) return null;
|
|
62
|
+
const animates = Array.from(el.querySelectorAll('animate'));
|
|
63
|
+
return animates.map((a) => ({
|
|
64
|
+
attr: a.getAttribute('attributeName'),
|
|
65
|
+
calcMode: a.getAttribute('calcMode'),
|
|
66
|
+
keyTimes: a.getAttribute('keyTimes'),
|
|
67
|
+
keySplines: a.getAttribute('keySplines'),
|
|
68
|
+
}));
|
|
69
|
+
};
|
|
70
|
+
return {
|
|
71
|
+
arrival: probe('[data-arrival-ping]'),
|
|
72
|
+
dispatch: probe('[data-dispatch-pulse]'),
|
|
73
|
+
};
|
|
74
|
+
});
|
|
75
|
+
await browser.close();
|
|
76
|
+
|
|
77
|
+
const easeOutBoth = '0.25 0.1 0.25 1;0.25 0.1 0.25 1';
|
|
78
|
+
const pulsePop = '0.25 0.1 0.25 1;0.42 0 1 1';
|
|
79
|
+
const keyTimes = '0;0.5;1';
|
|
80
|
+
|
|
81
|
+
const find = (arr, attr) => arr?.find(a => a.attr === attr);
|
|
82
|
+
const matches = (a, splines) => a && a.calcMode === 'spline' && a.keyTimes === keyTimes && a.keySplines === splines;
|
|
83
|
+
|
|
84
|
+
const results = {
|
|
85
|
+
arrival_present: Array.isArray(out.arrival) && out.arrival.length === 2,
|
|
86
|
+
arrival_r_easeout: matches(find(out.arrival, 'r'), easeOutBoth),
|
|
87
|
+
arrival_op_pulse: matches(find(out.arrival, 'opacity'), pulsePop),
|
|
88
|
+
dispatch_present: Array.isArray(out.dispatch) && out.dispatch.length === 2,
|
|
89
|
+
dispatch_r_easeout: matches(find(out.dispatch, 'r'), easeOutBoth),
|
|
90
|
+
dispatch_op_pulse: matches(find(out.dispatch, 'opacity'), pulsePop),
|
|
91
|
+
};
|
|
92
|
+
const ok = Object.values(results).every(Boolean);
|
|
93
|
+
console.log(`${ok ? '✅' : '❌'} ping+pulse ease:`, JSON.stringify(results),
|
|
94
|
+
'\n arrival:', out.arrival,
|
|
95
|
+
'\n dispatch:', out.dispatch);
|
|
96
|
+
process.exit(ok ? 0 : 1);
|