fix(chat): read messages via /api/ea2/edges/defines instead of /graph
process-definitions/{key}/graph filters to published process definitions
and returns empty for chat-thread flows, so the second persona saw no
message bodies. The raw defines edge endpoint returns the link correctly.
This commit is contained in:
@@ -0,0 +1,91 @@
|
|||||||
|
// Full chat dog-food: HR persona opens a thread with CEO, sends a message,
|
||||||
|
// then we re-load as CEO and verify the message is visible.
|
||||||
|
import { chromium } from "playwright";
|
||||||
|
|
||||||
|
const URL = "https://canvas.flow-master.ai/";
|
||||||
|
const args = ["--host-resolver-rules=MAP canvas.flow-master.ai 65.21.71.186", "--ignore-certificate-errors"];
|
||||||
|
|
||||||
|
async function asPersona(b, persona, work) {
|
||||||
|
const ctx = await b.newContext({ viewport: { width: 1440, height: 900 } });
|
||||||
|
const p = await ctx.newPage();
|
||||||
|
const writes = [];
|
||||||
|
p.on("request", (req) => {
|
||||||
|
const u = req.url();
|
||||||
|
if ((req.method() === "POST" || req.method() === "PUT") && /\/api\/(ea2|v1)\//.test(u)) {
|
||||||
|
writes.push({ method: req.method(), path: u.replace("https://canvas.flow-master.ai", "") });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
p.on("response", async (res) => {
|
||||||
|
if (/\/api\/(ea2|v1)\//.test(res.url()) && res.status() >= 400) {
|
||||||
|
const t = await res.text().catch(() => "");
|
||||||
|
console.log(`[${persona.label} resp ${res.status()}] ${res.url().replace("https://canvas.flow-master.ai","")} → ${t.slice(0,180)}`);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
await p.goto(URL, { waitUntil: "networkidle" });
|
||||||
|
await p.waitForTimeout(800);
|
||||||
|
await p.locator(".persona-chip", { hasText: persona.chipText }).click();
|
||||||
|
await p.locator(".dev-login-btn").click();
|
||||||
|
await p.waitForTimeout(2500);
|
||||||
|
console.log(`[${persona.label}] logged in`);
|
||||||
|
const enter = p.locator("button", { hasText: /Enter Mission Control/i }).first();
|
||||||
|
if (await enter.count()) {
|
||||||
|
await enter.click();
|
||||||
|
await p.waitForTimeout(1200);
|
||||||
|
}
|
||||||
|
await work(p, writes);
|
||||||
|
await ctx.close();
|
||||||
|
return writes;
|
||||||
|
}
|
||||||
|
|
||||||
|
const b = await chromium.launch({ headless: true, args });
|
||||||
|
|
||||||
|
// HR opens a chat with CEO and sends a message
|
||||||
|
const hrWrites = await asPersona(b, { label: "HR", chipText: /Aisha/ }, async (p, writes) => {
|
||||||
|
// Go to chat
|
||||||
|
const chatTab = p.locator(".tab", { hasText: /Chat/i }).first();
|
||||||
|
await chatTab.click();
|
||||||
|
await p.waitForTimeout(1500);
|
||||||
|
console.log("[HR] visible after Chat click:");
|
||||||
|
for (const b of await p.locator("button, .chat-thread-name").all()) {
|
||||||
|
const t = (await b.textContent())?.trim();
|
||||||
|
if (t) console.log(" -", t.slice(0, 70));
|
||||||
|
}
|
||||||
|
// Pick CEO from select
|
||||||
|
const sel = p.locator(".chat-new-row select").first();
|
||||||
|
if (await sel.count()) {
|
||||||
|
await sel.selectOption("ceo-head@flow-master.ai");
|
||||||
|
await p.locator(".chat-new-row button").click();
|
||||||
|
await p.waitForTimeout(2000);
|
||||||
|
}
|
||||||
|
// Send a message
|
||||||
|
const ta = p.locator(".chat-composer textarea").first();
|
||||||
|
if (await ta.count()) {
|
||||||
|
await ta.fill("Hey Mariana, store manager is requesting a new laptop. What's the approval cap this quarter?");
|
||||||
|
await p.locator(".chat-composer button", { hasText: /Send/i }).click();
|
||||||
|
await p.waitForTimeout(2500);
|
||||||
|
}
|
||||||
|
console.log(`[HR] writes so far: ${writes.length}`);
|
||||||
|
});
|
||||||
|
|
||||||
|
// CEO logs in and verifies the thread + message is visible
|
||||||
|
await asPersona(b, { label: "CEO", chipText: /Mariana/ }, async (p) => {
|
||||||
|
const chatTab = p.locator(".tab", { hasText: /Chat/i }).first();
|
||||||
|
await chatTab.click();
|
||||||
|
await p.waitForTimeout(2000);
|
||||||
|
const threadRows = await p.locator(".chat-thread-name").allTextContents();
|
||||||
|
console.log("[CEO] visible threads:", threadRows);
|
||||||
|
// Click the first thread that mentions Aisha
|
||||||
|
const aishaThread = p.locator(".chat-thread-row", { hasText: /Aisha/ }).first();
|
||||||
|
if (await aishaThread.count()) {
|
||||||
|
await aishaThread.click();
|
||||||
|
await p.waitForTimeout(1500);
|
||||||
|
const bodies = await p.locator(".chat-bubble-body").allTextContents();
|
||||||
|
console.log("[CEO] visible message bodies:", bodies);
|
||||||
|
} else {
|
||||||
|
console.log("[CEO] no Aisha thread found");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log(`\n=== HR side EA2 writes: ${hrWrites.length} ===`);
|
||||||
|
hrWrites.forEach((w) => console.log(` ${w.method} ${w.path}`));
|
||||||
|
await b.close();
|
||||||
+4
-4
@@ -88,13 +88,13 @@ export const chatApi = {
|
|||||||
return body._key;
|
return body._key;
|
||||||
},
|
},
|
||||||
|
|
||||||
/** Read every message under a thread via the graph endpoint. */
|
/** Read every message under a thread via the edges endpoint. */
|
||||||
async listMessages(threadKey: string, signal?: AbortSignal): Promise<ChatMessage[]> {
|
async listMessages(threadKey: string, signal?: AbortSignal): Promise<ChatMessage[]> {
|
||||||
const res = await jsonFetch(`/api/ea2/process-definitions/${threadKey}/graph`, { signal });
|
const res = await jsonFetch(`/api/ea2/edges/defines?from=flow/${threadKey}&limit=200`, { signal });
|
||||||
const edges = (res?.edges || []) as any[];
|
const edges = (res?.items || []) as any[];
|
||||||
const childKeys = edges
|
const childKeys = edges
|
||||||
.filter((e) => e?.role === "next")
|
.filter((e) => e?.role === "next")
|
||||||
.map((e) => (e.to_id || e._to || "").split("/").pop())
|
.map((e) => (e._to || "").split("/").pop())
|
||||||
.filter(Boolean) as string[];
|
.filter(Boolean) as string[];
|
||||||
|
|
||||||
const messages = await Promise.all(
|
const messages = await Promise.all(
|
||||||
|
|||||||
Reference in New Issue
Block a user