ltcai 4.3.1 → 4.4.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.
- package/README.md +191 -278
- package/docs/CHANGELOG.md +128 -0
- package/docs/V4_3_2_DEADCODE_AUDIT_REPORT.md +174 -0
- package/docs/V4_3_2_DOCUMENTATION_CLEANUP_REPORT.md +81 -0
- package/docs/V4_3_2_GITHUB_VERCEL_CHECK_REPORT.md +75 -0
- package/docs/V4_3_2_GRAPH_UX_REPORT.md +48 -0
- package/docs/V4_3_2_INDEPENDENT_AUDIT_PACKAGE.md +209 -0
- package/docs/V4_3_2_PRODUCT_POLISH_REPORT.md +57 -0
- package/docs/V4_3_2_SELF_AUDIT_REPORT.md +63 -0
- package/docs/V4_3_2_VALIDATION_REPORT.md +97 -0
- package/docs/V4_3_3_VALIDATION_REPORT.md +46 -0
- package/docs/V4_4_0_EXTRACTION_REPORT.md +239 -0
- package/docs/V4_DIGITAL_BRAIN_RECOVERY.md +18 -19
- package/frontend/openapi.json +1 -1
- package/frontend/src/components/primitives.tsx +92 -10
- package/frontend/src/pages/Act.tsx +11 -9
- package/frontend/src/pages/Ask.tsx +2 -2
- package/frontend/src/pages/Brain.tsx +607 -65
- package/frontend/src/pages/Capture.tsx +11 -7
- package/frontend/src/pages/Library.tsx +3 -3
- package/frontend/src/pages/System.tsx +186 -23
- package/lattice_brain/__init__.py +38 -23
- package/lattice_brain/_kg_common.py +11 -1
- package/lattice_brain/context.py +212 -2
- package/lattice_brain/conversations.py +234 -1
- package/lattice_brain/discovery.py +11 -1
- package/lattice_brain/documents.py +11 -1
- package/lattice_brain/graph/__init__.py +28 -0
- package/lattice_brain/graph/_kg_common.py +1123 -0
- package/lattice_brain/graph/curator.py +473 -0
- package/lattice_brain/graph/discovery.py +1455 -0
- package/lattice_brain/graph/documents.py +218 -0
- package/lattice_brain/graph/identity.py +175 -0
- package/lattice_brain/graph/ingest.py +644 -0
- package/lattice_brain/graph/network.py +205 -0
- package/lattice_brain/graph/projection.py +571 -0
- package/lattice_brain/graph/provenance.py +401 -0
- package/lattice_brain/graph/retrieval.py +1341 -0
- package/lattice_brain/graph/schema.py +640 -0
- package/lattice_brain/graph/store.py +237 -0
- package/lattice_brain/graph/write_master.py +225 -0
- package/lattice_brain/identity.py +11 -13
- package/lattice_brain/ingest.py +11 -1
- package/lattice_brain/ingestion.py +318 -0
- package/lattice_brain/memory.py +100 -1
- package/lattice_brain/network.py +11 -1
- package/lattice_brain/portability.py +431 -0
- package/lattice_brain/projection.py +11 -1
- package/lattice_brain/provenance.py +11 -1
- package/lattice_brain/retrieval.py +11 -1
- package/lattice_brain/runtime/__init__.py +32 -0
- package/lattice_brain/runtime/agent_runtime.py +569 -0
- package/lattice_brain/runtime/hooks.py +754 -0
- package/lattice_brain/runtime/multi_agent.py +795 -0
- package/lattice_brain/schema.py +11 -1
- package/lattice_brain/store.py +10 -2
- package/lattice_brain/workflow.py +461 -0
- package/lattice_brain/write_master.py +11 -1
- package/latticeai/__init__.py +1 -1
- package/latticeai/api/agents.py +2 -2
- package/latticeai/api/browser.py +1 -1
- package/latticeai/api/chat.py +1 -1
- package/latticeai/api/computer_use.py +1 -1
- package/latticeai/api/hooks.py +2 -2
- package/latticeai/api/mcp.py +1 -1
- package/latticeai/api/tools.py +1 -1
- package/latticeai/api/workflow_designer.py +2 -2
- package/latticeai/app_factory.py +4 -4
- package/latticeai/brain/__init__.py +24 -6
- package/latticeai/brain/_kg_common.py +11 -1117
- package/latticeai/brain/context.py +12 -208
- package/latticeai/brain/conversations.py +12 -231
- package/latticeai/brain/discovery.py +13 -1451
- package/latticeai/brain/documents.py +13 -214
- package/latticeai/brain/identity.py +11 -169
- package/latticeai/brain/ingest.py +13 -640
- package/latticeai/brain/memory.py +12 -97
- package/latticeai/brain/network.py +12 -200
- package/latticeai/brain/projection.py +13 -567
- package/latticeai/brain/provenance.py +13 -397
- package/latticeai/brain/retrieval.py +13 -1337
- package/latticeai/brain/schema.py +12 -635
- package/latticeai/brain/store.py +13 -233
- package/latticeai/brain/write_master.py +13 -221
- package/latticeai/core/agent.py +1 -1
- package/latticeai/core/agent_registry.py +2 -2
- package/latticeai/core/builtin_hooks.py +2 -2
- package/latticeai/core/graph_curator.py +6 -468
- package/latticeai/core/hooks.py +6 -749
- package/latticeai/core/marketplace.py +1 -1
- package/latticeai/core/multi_agent.py +6 -790
- package/latticeai/core/workflow_engine.py +6 -456
- package/latticeai/core/workspace_os.py +1 -1
- package/latticeai/services/agent_runtime.py +6 -564
- package/latticeai/services/ingestion.py +6 -313
- package/latticeai/services/kg_portability.py +6 -426
- package/latticeai/services/platform_runtime.py +3 -3
- package/latticeai/services/run_executor.py +1 -1
- package/latticeai/services/upload_service.py +1 -1
- package/p_reinforce.py +1 -1
- package/package.json +3 -6
- package/scripts/build_vercel_static.mjs +77 -0
- package/scripts/bump_version.py +1 -1
- package/scripts/check_markdown_links.mjs +75 -0
- package/scripts/wheel_smoke.py +7 -0
- package/src-tauri/Cargo.lock +1 -1
- package/src-tauri/Cargo.toml +1 -1
- package/src-tauri/src/main.rs +12 -2
- package/src-tauri/tauri.conf.json +1 -1
- package/static/app/asset-manifest.json +5 -5
- package/static/app/assets/index-CHHal8Zl.css +2 -0
- package/static/app/assets/index-pdzil9ac.js +333 -0
- package/static/app/assets/index-pdzil9ac.js.map +1 -0
- package/static/app/index.html +2 -2
- package/latticeai/api/deps.py +0 -15
- package/scripts/capture/README.md +0 -28
- package/scripts/capture/capture_enterprise.js +0 -8
- package/scripts/capture/capture_graph.js +0 -8
- package/scripts/capture/capture_onboarding.js +0 -8
- package/scripts/capture/capture_page.js +0 -43
- package/scripts/capture/capture_release_media.js +0 -125
- package/scripts/capture/capture_skills.js +0 -8
- package/scripts/capture/capture_v340.js +0 -88
- package/scripts/capture/capture_workspace.js +0 -8
- package/scripts/generate_diagrams.py +0 -512
- package/scripts/release-0.3.1.sh +0 -105
- package/scripts/take_screenshots.js +0 -69
- package/static/app/assets/index-BhPuj8rT.js +0 -333
- package/static/app/assets/index-BhPuj8rT.js.map +0 -1
- package/static/app/assets/index-yZswHE3d.css +0 -2
- package/static/css/tokens.3ba22e37.css +0 -260
package/static/app/index.html
CHANGED
|
@@ -15,8 +15,8 @@
|
|
|
15
15
|
} catch (e) {}
|
|
16
16
|
})();
|
|
17
17
|
</script>
|
|
18
|
-
<script type="module" crossorigin src="/static/app/assets/index-
|
|
19
|
-
<link rel="stylesheet" crossorigin href="/static/app/assets/index-
|
|
18
|
+
<script type="module" crossorigin src="/static/app/assets/index-pdzil9ac.js"></script>
|
|
19
|
+
<link rel="stylesheet" crossorigin href="/static/app/assets/index-CHHal8Zl.css">
|
|
20
20
|
</head>
|
|
21
21
|
<body>
|
|
22
22
|
<div id="root"></div>
|
package/latticeai/api/deps.py
DELETED
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
"""Shared API dependency type aliases.
|
|
2
|
-
|
|
3
|
-
Routers receive concrete callables from ``server_app`` at assembly time. Keeping
|
|
4
|
-
the aliases here avoids app imports inside router modules and gives future
|
|
5
|
-
router splits a single dependency vocabulary.
|
|
6
|
-
"""
|
|
7
|
-
|
|
8
|
-
from __future__ import annotations
|
|
9
|
-
|
|
10
|
-
from typing import Any, Callable, Dict
|
|
11
|
-
|
|
12
|
-
RequireUser = Callable[[Any], str]
|
|
13
|
-
RequireAdmin = Callable[[Any], tuple[str, Dict]]
|
|
14
|
-
AuditAppender = Callable[..., None]
|
|
15
|
-
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
# Screenshot Capture
|
|
2
|
-
|
|
3
|
-
Reproducible Playwright capture scripts for release screenshots.
|
|
4
|
-
|
|
5
|
-
Prerequisites:
|
|
6
|
-
|
|
7
|
-
```bash
|
|
8
|
-
npm ci
|
|
9
|
-
npx playwright install chromium
|
|
10
|
-
LTCAI
|
|
11
|
-
```
|
|
12
|
-
|
|
13
|
-
Optional environment:
|
|
14
|
-
|
|
15
|
-
- `LTCAI_CAPTURE_BASE_URL` defaults to `http://localhost:4825`
|
|
16
|
-
- `SESSION_TOKEN` or `LTCAI_SESSION_TOKEN` injects an authenticated session cookie
|
|
17
|
-
- `LTCAI_CAPTURE_OUT` defaults to `docs/images`
|
|
18
|
-
- `LTCAI_CAPTURE_HEADED=1` runs with a visible browser
|
|
19
|
-
|
|
20
|
-
Commands:
|
|
21
|
-
|
|
22
|
-
```bash
|
|
23
|
-
npm run capture:workspace
|
|
24
|
-
npm run capture:graph
|
|
25
|
-
npm run capture:skills
|
|
26
|
-
npm run capture:enterprise
|
|
27
|
-
npm run capture:onboarding
|
|
28
|
-
```
|
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
const fs = require("fs");
|
|
2
|
-
const path = require("path");
|
|
3
|
-
|
|
4
|
-
async function loadPlaywright() {
|
|
5
|
-
try {
|
|
6
|
-
return require("@playwright/test");
|
|
7
|
-
} catch (_) {
|
|
8
|
-
return require("playwright");
|
|
9
|
-
}
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
async function capturePage(options) {
|
|
13
|
-
const { chromium } = await loadPlaywright();
|
|
14
|
-
const baseURL = process.env.LTCAI_CAPTURE_BASE_URL || "http://localhost:4825";
|
|
15
|
-
const outDir = path.resolve(process.env.LTCAI_CAPTURE_OUT || path.join(__dirname, "..", "..", "docs", "images"));
|
|
16
|
-
const sessionToken = process.env.SESSION_TOKEN || process.env.LTCAI_SESSION_TOKEN || "";
|
|
17
|
-
fs.mkdirSync(outDir, { recursive: true });
|
|
18
|
-
|
|
19
|
-
const browser = await chromium.launch({ headless: process.env.LTCAI_CAPTURE_HEADED !== "1" });
|
|
20
|
-
const context = await browser.newContext({
|
|
21
|
-
viewport: { width: Number(process.env.LTCAI_CAPTURE_WIDTH || 1440), height: Number(process.env.LTCAI_CAPTURE_HEIGHT || 920) },
|
|
22
|
-
deviceScaleFactor: Number(process.env.LTCAI_CAPTURE_SCALE || 2),
|
|
23
|
-
});
|
|
24
|
-
if (sessionToken) {
|
|
25
|
-
const host = new URL(baseURL).hostname;
|
|
26
|
-
await context.addCookies([{ name: "session_token", value: sessionToken, domain: host, path: "/", httpOnly: true, secure: false }]);
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
const page = await context.newPage();
|
|
30
|
-
const target = new URL(options.path, baseURL).toString();
|
|
31
|
-
await page.goto(target, { waitUntil: "networkidle", timeout: Number(process.env.LTCAI_CAPTURE_TIMEOUT || 30_000) });
|
|
32
|
-
if (options.hash) await page.evaluate((hash) => { location.hash = hash; }, options.hash);
|
|
33
|
-
if (options.waitFor) await page.waitForSelector(options.waitFor, { timeout: 15_000 });
|
|
34
|
-
await page.waitForTimeout(Number(process.env.LTCAI_CAPTURE_SETTLE_MS || options.settleMs || 900));
|
|
35
|
-
|
|
36
|
-
const outPath = path.join(outDir, options.filename);
|
|
37
|
-
await page.screenshot({ path: outPath, fullPage: Boolean(options.fullPage) });
|
|
38
|
-
await browser.close();
|
|
39
|
-
console.log(outPath);
|
|
40
|
-
return outPath;
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
module.exports = { capturePage };
|
|
@@ -1,125 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
const fs = require("fs");
|
|
3
|
-
const path = require("path");
|
|
4
|
-
const { spawnSync } = require("child_process");
|
|
5
|
-
|
|
6
|
-
async function loadPlaywright() {
|
|
7
|
-
try {
|
|
8
|
-
return require("@playwright/test");
|
|
9
|
-
} catch (_) {
|
|
10
|
-
return require("playwright");
|
|
11
|
-
}
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
const ROOT = path.resolve(__dirname, "..", "..");
|
|
15
|
-
const OUT = path.join(ROOT, "docs", "images");
|
|
16
|
-
const FRAMES = path.join(OUT, "tmp_frames", "release_221");
|
|
17
|
-
const BASE = process.env.LTCAI_CAPTURE_BASE_URL || "http://127.0.0.1:4825";
|
|
18
|
-
|
|
19
|
-
function ensureDirs() {
|
|
20
|
-
fs.mkdirSync(OUT, { recursive: true });
|
|
21
|
-
fs.rmSync(FRAMES, { recursive: true, force: true });
|
|
22
|
-
fs.mkdirSync(FRAMES, { recursive: true });
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
async function preparePage(page, theme = "light") {
|
|
26
|
-
await page.addInitScript((mode) => {
|
|
27
|
-
localStorage.setItem("lt-theme", mode);
|
|
28
|
-
localStorage.setItem("ltcai_workspace_type", "personal");
|
|
29
|
-
localStorage.setItem("ltcai_mode", "advanced");
|
|
30
|
-
localStorage.setItem("ltcai_user_email", "demo@lattice.local");
|
|
31
|
-
localStorage.setItem("ltcai_is_admin", "true");
|
|
32
|
-
sessionStorage.setItem("ltcai_force_setup_after_login", "false");
|
|
33
|
-
}, theme);
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
async function gotoReady(page, pathname, selector, theme = "light") {
|
|
37
|
-
await preparePage(page, theme);
|
|
38
|
-
await page.goto(new URL(pathname, BASE).toString(), { waitUntil: "domcontentloaded", timeout: 30000 });
|
|
39
|
-
if (selector) await page.waitForSelector(selector, { timeout: 20000 });
|
|
40
|
-
await page.evaluate((mode) => {
|
|
41
|
-
document.documentElement.setAttribute("data-lt-theme", mode);
|
|
42
|
-
document.body.dataset.capture = "release-221";
|
|
43
|
-
}, theme);
|
|
44
|
-
await page.waitForTimeout(1800);
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
async function screenshot(page, filename, options = {}) {
|
|
48
|
-
const out = path.join(OUT, filename);
|
|
49
|
-
await page.screenshot({ path: out, fullPage: Boolean(options.fullPage) });
|
|
50
|
-
console.log(out);
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
async function captureAll() {
|
|
54
|
-
ensureDirs();
|
|
55
|
-
const { chromium } = await loadPlaywright();
|
|
56
|
-
const browser = await chromium.launch({ headless: true });
|
|
57
|
-
|
|
58
|
-
const desktop = await browser.newContext({
|
|
59
|
-
viewport: { width: 1440, height: 920 },
|
|
60
|
-
deviceScaleFactor: 1,
|
|
61
|
-
});
|
|
62
|
-
const mobile = await browser.newContext({
|
|
63
|
-
viewport: { width: 390, height: 844 },
|
|
64
|
-
deviceScaleFactor: 2,
|
|
65
|
-
isMobile: true,
|
|
66
|
-
});
|
|
67
|
-
|
|
68
|
-
let page = await desktop.newPage();
|
|
69
|
-
await gotoReady(page, "/workspace", "#workspace-health-grid", "light");
|
|
70
|
-
await screenshot(page, "workspace-light.png");
|
|
71
|
-
await screenshot(page, "lattice-ai-hero.png");
|
|
72
|
-
|
|
73
|
-
await page.evaluate(() => document.documentElement.setAttribute("data-lt-theme", "dark"));
|
|
74
|
-
await page.waitForTimeout(800);
|
|
75
|
-
await screenshot(page, "workspace-dark.png");
|
|
76
|
-
|
|
77
|
-
await gotoReady(page, "/graph", "#graph", "dark");
|
|
78
|
-
await screenshot(page, "knowledge-graph.png");
|
|
79
|
-
|
|
80
|
-
await gotoReady(page, "/workflows", "#wfNodes", "light");
|
|
81
|
-
await screenshot(page, "pipeline.png");
|
|
82
|
-
|
|
83
|
-
await gotoReady(page, "/admin", "#admin-root, .admin-shell, body", "light");
|
|
84
|
-
await page.waitForTimeout(2200);
|
|
85
|
-
await screenshot(page, "admin-dashboard.png");
|
|
86
|
-
|
|
87
|
-
const mobilePage = await mobile.newPage();
|
|
88
|
-
await gotoReady(mobilePage, "/chat", ".reference-shell, body", "light");
|
|
89
|
-
await screenshot(mobilePage, "mobile-responsive.png", { fullPage: false });
|
|
90
|
-
|
|
91
|
-
const framePlan = [
|
|
92
|
-
["/workspace", "#workspace-health-grid", "light"],
|
|
93
|
-
["/workspace", "#workspace-health-grid", "dark"],
|
|
94
|
-
["/graph", "#graph", "dark"],
|
|
95
|
-
["/workflows", "#wfNodes", "light"],
|
|
96
|
-
["/chat", ".reference-shell, body", "light"],
|
|
97
|
-
];
|
|
98
|
-
let frame = 0;
|
|
99
|
-
for (const [pathname, selector, theme] of framePlan) {
|
|
100
|
-
await gotoReady(page, pathname, selector, theme);
|
|
101
|
-
for (let repeat = 0; repeat < 3; repeat += 1) {
|
|
102
|
-
await page.screenshot({ path: path.join(FRAMES, `frame_${String(frame).padStart(3, "0")}.png`) });
|
|
103
|
-
frame += 1;
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
await browser.close();
|
|
108
|
-
|
|
109
|
-
const gifPath = path.join(OUT, "lattice-ai-demo.gif");
|
|
110
|
-
const ffmpeg = spawnSync("ffmpeg", [
|
|
111
|
-
"-y",
|
|
112
|
-
"-framerate", "1.5",
|
|
113
|
-
"-i", path.join(FRAMES, "frame_%03d.png"),
|
|
114
|
-
"-vf", "scale=1280:-1:flags=lanczos,fps=6",
|
|
115
|
-
"-loop", "0",
|
|
116
|
-
gifPath,
|
|
117
|
-
], { stdio: "inherit" });
|
|
118
|
-
if (ffmpeg.status !== 0) process.exit(ffmpeg.status || 1);
|
|
119
|
-
console.log(gifPath);
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
captureAll().catch((error) => {
|
|
123
|
-
console.error(error);
|
|
124
|
-
process.exit(1);
|
|
125
|
-
});
|
|
@@ -1,88 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
/*
|
|
3
|
-
* Capture v3.4.0 /app view screenshots into docs/assets/v3.4.0/.
|
|
4
|
-
*
|
|
5
|
-
* Drives the real SPA (built hashed assets) against the visual mock server, so
|
|
6
|
-
* every screenshot is the genuine v3.4.0 frontend rendering real view code with
|
|
7
|
-
* representative-but-honest mock data. Live-model output (VLM inference, agent
|
|
8
|
-
* LLM text) is NOT simulated; those remain runtime-pending per the release notes.
|
|
9
|
-
* Run `npm run build:assets` first so the manifest points at the new code.
|
|
10
|
-
*
|
|
11
|
-
* node scripts/capture/capture_v340.js
|
|
12
|
-
* Env: LTCAI_CAPTURE_BASE_URL (default http://127.0.0.1:4927 — the mock server)
|
|
13
|
-
*/
|
|
14
|
-
const fs = require("fs");
|
|
15
|
-
const path = require("path");
|
|
16
|
-
|
|
17
|
-
async function loadPlaywright() {
|
|
18
|
-
try { return require("@playwright/test"); } catch (_) { return require("playwright"); }
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
const ROOT = path.resolve(__dirname, "..", "..");
|
|
22
|
-
const OUT = path.join(ROOT, "docs", "assets", "v3.4.0");
|
|
23
|
-
const BASE = process.env.LTCAI_CAPTURE_BASE_URL || "http://127.0.0.1:4927";
|
|
24
|
-
|
|
25
|
-
// { route, file, [action] }. action: "agent-run" clicks Run and waits for logs;
|
|
26
|
-
// "scroll-bottom" scrolls the view to reveal lower panels before the shot.
|
|
27
|
-
const SHOTS = [
|
|
28
|
-
{ route: "home", file: "home.png" },
|
|
29
|
-
{ route: "chat", file: "chat.png" },
|
|
30
|
-
{ route: "chat", file: "vision-input.png" },
|
|
31
|
-
{ route: "files", file: "files.png" },
|
|
32
|
-
{ route: "files", file: "connect-folder.png", action: "scroll-bottom" },
|
|
33
|
-
{ route: "knowledge-graph", file: "knowledge-graph.png" },
|
|
34
|
-
{ route: "memory", file: "memory.png" },
|
|
35
|
-
{ route: "agents", file: "agents.png" },
|
|
36
|
-
{ route: "agents", file: "agent-run.png", action: "agent-run" },
|
|
37
|
-
{ route: "workflows", file: "workflows.png" },
|
|
38
|
-
{ route: "settings", file: "settings.png" },
|
|
39
|
-
{ route: "my-computer", file: "local-agent.png" },
|
|
40
|
-
{ route: "hooks", file: "hooks-dispatch.png", action: "scroll-bottom" },
|
|
41
|
-
];
|
|
42
|
-
|
|
43
|
-
async function main() {
|
|
44
|
-
fs.mkdirSync(OUT, { recursive: true });
|
|
45
|
-
const { chromium } = await loadPlaywright();
|
|
46
|
-
const browser = await chromium.launch({ headless: true });
|
|
47
|
-
const context = await browser.newContext({ viewport: { width: 1480, height: 940 }, deviceScaleFactor: 2 });
|
|
48
|
-
await context.addInitScript(() => {
|
|
49
|
-
localStorage.setItem("lt-theme", "light");
|
|
50
|
-
localStorage.setItem("ltcai_mode", "admin");
|
|
51
|
-
localStorage.setItem("ltcai_user_email", "demo@lattice.local");
|
|
52
|
-
localStorage.setItem("ltcai_is_admin", "true");
|
|
53
|
-
});
|
|
54
|
-
const page = await context.newPage();
|
|
55
|
-
|
|
56
|
-
for (const shot of SHOTS) {
|
|
57
|
-
// Fresh full-page load per shot — avoids transient cross-view overlap that a
|
|
58
|
-
// same-page hash change can leave behind, so headers render crisp.
|
|
59
|
-
await page.goto(new URL("/app#/" + shot.route, BASE).toString(), { waitUntil: "domcontentloaded", timeout: 30000 });
|
|
60
|
-
await page.evaluate((mode) => document.documentElement.setAttribute("data-lt-theme", mode), "light");
|
|
61
|
-
await page.waitForSelector("#app .lt3-vhead, #app .lt3-chat", { timeout: 15000 }).catch(() => {});
|
|
62
|
-
await page.waitForTimeout(1800); // let the view hydrate fully (crisp, not mid-load)
|
|
63
|
-
|
|
64
|
-
if (shot.action === "agent-run") {
|
|
65
|
-
// Fill the goal and trigger a real run; wait for the logs/timeline to render.
|
|
66
|
-
const ta = page.locator("#app textarea").first();
|
|
67
|
-
await ta.fill("Summarize this week's release work and propose next steps.").catch(() => {});
|
|
68
|
-
const runBtn = page.getByRole("button", { name: /run agents/i }).first();
|
|
69
|
-
await runBtn.click({ timeout: 4000 }).catch(() => {});
|
|
70
|
-
await page.waitForTimeout(1500);
|
|
71
|
-
await page.evaluate(() => { const a = document.querySelector(".lt3-view"); if (a) a.scrollTop = 0; });
|
|
72
|
-
} else if (shot.action === "scroll-bottom") {
|
|
73
|
-
await page.evaluate(() => {
|
|
74
|
-
const sc = document.querySelector(".lt3-view") || document.scrollingElement;
|
|
75
|
-
if (sc) sc.scrollTop = sc.scrollHeight;
|
|
76
|
-
});
|
|
77
|
-
await page.waitForTimeout(700);
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
const out = path.join(OUT, shot.file);
|
|
81
|
-
await page.screenshot({ path: out, fullPage: false });
|
|
82
|
-
console.log(out);
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
await browser.close();
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
main().catch((e) => { console.error(e); process.exit(1); });
|