lyu-extension-workflow 0.0.0-stage → 0.1.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.
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Workflow Extension for lyu-code
3
+ *
4
+ * /workflow — 打开本地前端页面,可视化编排多 agent 工作流
5
+ *
6
+ * 架构:
7
+ * - 命令启动本地 HTTP 服务(默认 18789)+ WebSocket
8
+ * - serve frontend/dist/ 下的静态文件(用户自行提供)
9
+ * - WebSocket 通道让前端和 Pi 通信
10
+ * - 前端发指令(addNode, connect, run, stop, ...)
11
+ * - 扩展执行操作,回传状态和结果
12
+ *
13
+ * 用法:
14
+ * /workflow — 打开编辑器
15
+ * /workflow stop — 关闭服务
16
+ */
17
+ import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
18
+ export default function (pi: ExtensionAPI): void;
19
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,KAAK,EACV,YAAY,EAGb,MAAM,iCAAiC,CAAC;AAkbzC,MAAM,CAAC,OAAO,WAAW,EAAE,EAAE,YAAY,QAoDxC"}
package/dist/index.js ADDED
@@ -0,0 +1,482 @@
1
+ /**
2
+ * Workflow Extension for lyu-code
3
+ *
4
+ * /workflow — 打开本地前端页面,可视化编排多 agent 工作流
5
+ *
6
+ * 架构:
7
+ * - 命令启动本地 HTTP 服务(默认 18789)+ WebSocket
8
+ * - serve frontend/dist/ 下的静态文件(用户自行提供)
9
+ * - WebSocket 通道让前端和 Pi 通信
10
+ * - 前端发指令(addNode, connect, run, stop, ...)
11
+ * - 扩展执行操作,回传状态和结果
12
+ *
13
+ * 用法:
14
+ * /workflow — 打开编辑器
15
+ * /workflow stop — 关闭服务
16
+ */
17
+ import * as http from "node:http";
18
+ import * as fs from "node:fs";
19
+ import * as path from "node:path";
20
+ import { URL } from "node:url";
21
+ const DEFAULT_PORT = 18789;
22
+ // ─── 简易 WebSocket (RFC 6455, 最小实现) ──────────────────────────
23
+ function wsAcceptKey(key) {
24
+ const crypto = require("node:crypto");
25
+ return crypto.createHash("sha1").update(key + "258EAFA5-E914-47DA-95CA-5AB5DC828B12").digest("base64");
26
+ }
27
+ // ─── 全局状态 ──────────────────────────────────────────────────────
28
+ let server = null;
29
+ let port = DEFAULT_PORT;
30
+ let piRef = null;
31
+ const workflows = new Map();
32
+ const runStates = new Map();
33
+ const wsClients = [];
34
+ // ─── 广播 ──────────────────────────────────────────────────────────
35
+ function broadcast(type, data) {
36
+ const msg = JSON.stringify({ type, data });
37
+ for (const c of wsClients) {
38
+ try {
39
+ c.send(msg);
40
+ }
41
+ catch { /* ignore */ }
42
+ }
43
+ }
44
+ // ─── 前端静态文件 ──────────────────────────────────────────────────
45
+ const MIME = {
46
+ ".html": "text/html", ".js": "application/javascript", ".mjs": "application/javascript",
47
+ ".css": "text/css", ".json": "application/json", ".png": "image/png",
48
+ ".jpg": "image/jpeg", ".svg": "image/svg+xml", ".ico": "image/x-icon",
49
+ ".woff": "font/woff", ".woff2": "font/woff2",
50
+ };
51
+ function getFrontendDir() {
52
+ const thisDir = path.dirname(new URL(import.meta.url).pathname.replace(/^\/([A-Z]:)/, "$1"));
53
+ return path.join(thisDir, "..", "frontend", "dist");
54
+ }
55
+ function serveStatic(req, res) {
56
+ const frontendDir = getFrontendDir();
57
+ let urlPath = new URL(req.url ?? "/", "http://localhost").pathname;
58
+ // API 路由
59
+ if (urlPath.startsWith("/api/")) {
60
+ handleApi(req, res, urlPath);
61
+ return;
62
+ }
63
+ // 静态文件
64
+ if (urlPath === "/")
65
+ urlPath = "/index.html";
66
+ const filePath = path.join(frontendDir, urlPath);
67
+ try {
68
+ if (!filePath.startsWith(frontendDir)) {
69
+ res.writeHead(403);
70
+ res.end();
71
+ return;
72
+ }
73
+ const stat = fs.statSync(filePath);
74
+ if (!stat.isFile())
75
+ throw new Error("not file");
76
+ const ext = path.extname(filePath);
77
+ res.writeHead(200, { "Content-Type": (MIME[ext] || "application/octet-stream") + "; charset=utf-8" });
78
+ res.end(fs.readFileSync(filePath));
79
+ }
80
+ catch {
81
+ // SPA fallback
82
+ try {
83
+ const fallback = path.join(frontendDir, "index.html");
84
+ res.writeHead(200, { "Content-Type": "text/html; charset=utf-8" });
85
+ res.end(fs.readFileSync(fallback));
86
+ }
87
+ catch {
88
+ res.writeHead(404);
89
+ res.end("Not found — put frontend files in frontend/dist/");
90
+ }
91
+ }
92
+ }
93
+ function handleApi(_req, res, urlPath) {
94
+ const ok = (d) => { res.writeHead(200, { "Content-Type": "application/json" }); res.end(JSON.stringify(d)); };
95
+ if (urlPath === "/api/workflows") {
96
+ ok([...workflows.values()].map(w => ({ id: w.id, name: w.name, nodeCount: w.nodes.length, globalMaxLoops: w.globalMaxLoops })));
97
+ }
98
+ else if (urlPath === "/api/status") {
99
+ ok({ ok: true, workflows: workflows.size, clients: wsClients.length });
100
+ }
101
+ else {
102
+ ok({ error: "not found" });
103
+ }
104
+ }
105
+ // ─── WebSocket 消息处理 ────────────────────────────────────────────
106
+ function handleWsMessage(raw) {
107
+ let msg;
108
+ try {
109
+ msg = JSON.parse(raw);
110
+ }
111
+ catch {
112
+ return;
113
+ }
114
+ switch (msg.type) {
115
+ case "workflow:create": {
116
+ const wf = {
117
+ id: msg.data?.id ?? `wf-${Date.now()}`,
118
+ name: msg.data?.name ?? "Untitled Workflow",
119
+ nodes: msg.data?.nodes ?? [],
120
+ edges: msg.data?.edges ?? [],
121
+ globalMaxLoops: msg.data?.globalMaxLoops ?? 10,
122
+ createdAt: Date.now(),
123
+ updatedAt: Date.now(),
124
+ };
125
+ workflows.set(wf.id, wf);
126
+ runStates.set(wf.id, { status: "idle", iteration: 0, results: {} });
127
+ broadcast("workflow:created", wf);
128
+ break;
129
+ }
130
+ case "workflow:update": {
131
+ const wf = workflows.get(msg.data?.id);
132
+ if (wf) {
133
+ Object.assign(wf, msg.data, { updatedAt: Date.now() });
134
+ broadcast("workflow:updated", wf);
135
+ }
136
+ break;
137
+ }
138
+ case "workflow:delete": {
139
+ workflows.delete(msg.data?.id);
140
+ runStates.delete(msg.data?.id);
141
+ broadcast("workflow:deleted", { id: msg.data?.id });
142
+ break;
143
+ }
144
+ case "node:add": {
145
+ const wf = workflows.get(msg.data?.workflowId);
146
+ if (wf) {
147
+ wf.nodes.push(msg.data.node);
148
+ wf.updatedAt = Date.now();
149
+ broadcast("workflow:updated", wf);
150
+ }
151
+ break;
152
+ }
153
+ case "node:update": {
154
+ const wf = workflows.get(msg.data?.workflowId);
155
+ if (wf) {
156
+ const i = wf.nodes.findIndex(n => n.id === msg.data.node.id);
157
+ if (i >= 0) {
158
+ wf.nodes[i] = { ...wf.nodes[i], ...msg.data.node };
159
+ wf.updatedAt = Date.now();
160
+ broadcast("workflow:updated", wf);
161
+ }
162
+ }
163
+ break;
164
+ }
165
+ case "node:remove": {
166
+ const wf = workflows.get(msg.data?.workflowId);
167
+ if (wf) {
168
+ wf.nodes = wf.nodes.filter(n => n.id !== msg.data.nodeId);
169
+ wf.edges = wf.edges.filter(e => e.source !== msg.data.nodeId && e.target !== msg.data.nodeId);
170
+ wf.updatedAt = Date.now();
171
+ broadcast("workflow:updated", wf);
172
+ }
173
+ break;
174
+ }
175
+ case "edge:add": {
176
+ const wf = workflows.get(msg.data?.workflowId);
177
+ if (wf) {
178
+ wf.edges.push(msg.data.edge);
179
+ wf.updatedAt = Date.now();
180
+ broadcast("workflow:updated", wf);
181
+ }
182
+ break;
183
+ }
184
+ case "edge:remove": {
185
+ const wf = workflows.get(msg.data?.workflowId);
186
+ if (wf) {
187
+ wf.edges = wf.edges.filter(e => e.id !== msg.data.edgeId);
188
+ wf.updatedAt = Date.now();
189
+ broadcast("workflow:updated", wf);
190
+ }
191
+ break;
192
+ }
193
+ case "workflow:run": {
194
+ const wfId = msg.data?.workflowId;
195
+ const wf = workflows.get(wfId);
196
+ const state = runStates.get(wfId);
197
+ if (!wf || !state || state.status === "running")
198
+ break;
199
+ state.status = "running";
200
+ state.iteration = 0;
201
+ state.results = {};
202
+ for (const n of wf.nodes)
203
+ state.results[n.id] = { status: "pending" };
204
+ broadcast("run:state", { workflowId: wfId, state });
205
+ runWorkflow(wf, state).catch(err => {
206
+ state.status = "error";
207
+ broadcast("run:state", { workflowId: wfId, state, error: String(err) });
208
+ });
209
+ break;
210
+ }
211
+ case "workflow:stop": {
212
+ const state = runStates.get(msg.data?.workflowId);
213
+ if (state) {
214
+ state.status = "idle";
215
+ broadcast("run:state", { workflowId: msg.data?.workflowId, state });
216
+ }
217
+ break;
218
+ }
219
+ case "agent:send": {
220
+ if (piRef) {
221
+ piRef.sendUserMessage(msg.data?.message ?? "", { deliverAs: "followUp" });
222
+ }
223
+ break;
224
+ }
225
+ }
226
+ }
227
+ // ─── Workflow 执行引擎 ─────────────────────────────────────────────
228
+ async function runWorkflow(wf, state) {
229
+ const sorted = topoSort(wf.nodes, wf.edges);
230
+ for (let iter = 0; iter < wf.globalMaxLoops; iter++) {
231
+ state.iteration = iter + 1;
232
+ broadcast("run:state", { workflowId: wf.id, state });
233
+ for (const node of sorted) {
234
+ const ns = state.results[node.id];
235
+ if (!ns)
236
+ continue;
237
+ ns.status = "running";
238
+ state.currentStep = node.id;
239
+ broadcast("run:state", { workflowId: wf.id, state });
240
+ // 收集上游输出
241
+ const upstream = wf.edges
242
+ .filter(e => e.target === node.id)
243
+ .map(e => state.results[e.source]?.output ?? "")
244
+ .filter(Boolean)
245
+ .join("\n\n");
246
+ // 通过 Pi 驱动 agent
247
+ if (piRef) {
248
+ const prompt = upstream
249
+ ? `[上游输入]\n${upstream}\n\n[请处理以上输入并输出结果]`
250
+ : node.config.systemPrompt ?? "请开始工作";
251
+ piRef.sendUserMessage(prompt, { deliverAs: "followUp" });
252
+ }
253
+ // 等待一小段时间让 Pi 处理(实际结果由 agent_end 事件回填)
254
+ await new Promise(r => setTimeout(r, 500));
255
+ ns.status = "done";
256
+ ns.iterations = (ns.iterations ?? 0) + 1;
257
+ broadcast("run:state", { workflowId: wf.id, state });
258
+ }
259
+ // 无回边则不循环
260
+ const hasBack = wf.edges.some(e => {
261
+ const si = sorted.findIndex(n => n.id === e.source);
262
+ const ti = sorted.findIndex(n => n.id === e.target);
263
+ return ti <= si;
264
+ });
265
+ if (!hasBack)
266
+ break;
267
+ }
268
+ state.status = "done";
269
+ state.currentStep = undefined;
270
+ broadcast("run:state", { workflowId: wf.id, state });
271
+ }
272
+ function topoSort(nodes, edges) {
273
+ const nodeMap = new Map(nodes.map(n => [n.id, n]));
274
+ const deg = new Map(nodes.map(n => [n.id, 0]));
275
+ const adj = new Map(nodes.map(n => [n.id, []]));
276
+ for (const e of edges) {
277
+ adj.get(e.source)?.push(e.target);
278
+ deg.set(e.target, (deg.get(e.target) ?? 0) + 1);
279
+ }
280
+ const q = [];
281
+ for (const [id, d] of deg)
282
+ if (d === 0)
283
+ q.push(id);
284
+ const result = [];
285
+ while (q.length) {
286
+ const id = q.shift();
287
+ const n = nodeMap.get(id);
288
+ if (n)
289
+ result.push(n);
290
+ for (const next of adj.get(id) ?? []) {
291
+ const d = (deg.get(next) ?? 1) - 1;
292
+ deg.set(next, d);
293
+ if (d === 0)
294
+ q.push(next);
295
+ }
296
+ }
297
+ for (const n of nodes)
298
+ if (!result.find(r => r.id === n.id))
299
+ result.push(n);
300
+ return result;
301
+ }
302
+ // ─── 启停 ──────────────────────────────────────────────────────────
303
+ function startServer() {
304
+ return new Promise((resolve, reject) => {
305
+ server = http.createServer(serveStatic);
306
+ // WebSocket upgrade (简易实现)
307
+ server.on("upgrade", (req, socket, head) => {
308
+ if (!(req.url ?? "/").startsWith("/ws")) {
309
+ socket.destroy();
310
+ return;
311
+ }
312
+ const key = req.headers["sec-websocket-key"];
313
+ if (!key) {
314
+ socket.destroy();
315
+ return;
316
+ }
317
+ socket.write("HTTP/1.1 101 Switching Protocols\r\n" +
318
+ "Upgrade: websocket\r\n" +
319
+ "Connection: Upgrade\r\n" +
320
+ `Sec-WebSocket-Accept: ${wsAcceptKey(key)}\r\n\r\n`);
321
+ const client = {
322
+ socket,
323
+ send(data) {
324
+ // 简易:发 text frame (opcode 0x1), 无掩码, 不分片
325
+ const buf = Buffer.from(data, "utf-8");
326
+ const len = buf.length;
327
+ const frames = [];
328
+ if (len < 126) {
329
+ frames.push(Buffer.from([0x81, len]));
330
+ }
331
+ else if (len < 65536) {
332
+ const h = Buffer.alloc(4);
333
+ h[0] = 0x81;
334
+ h[1] = 126;
335
+ h.writeUInt16BE(len, 2);
336
+ frames.push(h);
337
+ }
338
+ else {
339
+ const h = Buffer.alloc(10);
340
+ h[0] = 0x81;
341
+ h[1] = 127;
342
+ h.writeBigUInt64BE(BigInt(len), 2);
343
+ frames.push(h);
344
+ }
345
+ frames.push(buf);
346
+ socket.write(Buffer.concat(frames));
347
+ },
348
+ };
349
+ wsClients.push(client);
350
+ // 接收帧(简易:只处理小 text 帧)
351
+ let buf = Buffer.alloc(0);
352
+ socket.on("data", (chunk) => {
353
+ buf = Buffer.concat([buf, chunk]);
354
+ // 解析 text frame
355
+ if (buf.length < 2)
356
+ return;
357
+ const opcode = buf[0] & 0x0f;
358
+ const masked = !!(buf[1] & 0x80);
359
+ let payloadLen = buf[1] & 0x7f;
360
+ let offset = 2;
361
+ if (payloadLen === 126) {
362
+ if (buf.length < 4)
363
+ return;
364
+ payloadLen = buf.readUInt16BE(2);
365
+ offset = 4;
366
+ }
367
+ else if (payloadLen === 127) {
368
+ if (buf.length < 10)
369
+ return;
370
+ payloadLen = Number(buf.readBigUInt64BE(2));
371
+ offset = 10;
372
+ }
373
+ if (masked)
374
+ offset += 4;
375
+ if (buf.length < offset + payloadLen)
376
+ return;
377
+ let payload = buf.subarray(offset, offset + payloadLen);
378
+ if (masked) {
379
+ const mask = buf.subarray(offset - 4, offset);
380
+ payload = Buffer.from(payload.map((b, i) => b ^ mask[i % 4]));
381
+ }
382
+ buf = buf.subarray(offset + payloadLen);
383
+ if (opcode === 0x1) { // text
384
+ handleWsMessage(payload.toString("utf-8"));
385
+ }
386
+ else if (opcode === 0x8) { // close
387
+ const idx = wsClients.indexOf(client);
388
+ if (idx >= 0)
389
+ wsClients.splice(idx, 1);
390
+ }
391
+ });
392
+ socket.on("close", () => {
393
+ const idx = wsClients.indexOf(client);
394
+ if (idx >= 0)
395
+ wsClients.splice(idx, 1);
396
+ });
397
+ // 发送初始状态
398
+ client.send(JSON.stringify({
399
+ type: "connected",
400
+ data: { workflows: [...workflows.values()], port },
401
+ }));
402
+ });
403
+ server.on("error", (err) => {
404
+ if (err.code === "EADDRINUSE") {
405
+ port++;
406
+ server.listen(port, "127.0.0.1");
407
+ }
408
+ else
409
+ reject(err);
410
+ });
411
+ server.on("listening", () => resolve(port));
412
+ server.listen(port, "127.0.0.1");
413
+ });
414
+ }
415
+ function stopServer() {
416
+ for (const c of wsClients)
417
+ try {
418
+ c.socket.destroy();
419
+ }
420
+ catch { /* ok */ }
421
+ wsClients.length = 0;
422
+ server?.close();
423
+ server = null;
424
+ }
425
+ // ─── 扩展入口 ──────────────────────────────────────────────────────
426
+ export default function (pi) {
427
+ piRef = pi;
428
+ pi.registerCommand("workflow", {
429
+ description: "Open workflow editor — visually compose multi-agent pipelines",
430
+ handler: async (args, _ctx) => {
431
+ if (args.trim() === "stop") {
432
+ stopServer();
433
+ pi.sendMessage({ customType: "workflow", content: "Workflow server stopped", display: true });
434
+ return;
435
+ }
436
+ if (!server) {
437
+ const actualPort = await startServer();
438
+ const url = `http://127.0.0.1:${actualPort}`;
439
+ // 打开浏览器
440
+ const cmd = process.platform === "darwin" ? "open" : process.platform === "win32" ? "start" : "xdg-open";
441
+ try {
442
+ require("node:child_process").execSync(`${cmd} "${url}"`, { stdio: "ignore" });
443
+ }
444
+ catch { /* ok */ }
445
+ pi.sendMessage({
446
+ customType: "workflow",
447
+ content: `Workflow editor: ${url}`,
448
+ display: true,
449
+ details: { url, port: actualPort },
450
+ });
451
+ }
452
+ else {
453
+ const url = `http://127.0.0.1:${port}`;
454
+ const cmd = process.platform === "darwin" ? "open" : process.platform === "win32" ? "start" : "xdg-open";
455
+ try {
456
+ require("node:child_process").execSync(`${cmd} "${url}"`, { stdio: "ignore" });
457
+ }
458
+ catch { /* ok */ }
459
+ }
460
+ },
461
+ });
462
+ // agent_end 事件回填节点结果
463
+ pi.on("agent_end", (event) => {
464
+ for (const [wfId, state] of runStates) {
465
+ if (state.status !== "running" || !state.currentStep)
466
+ continue;
467
+ const lastMsg = event.messages[event.messages.length - 1];
468
+ if (lastMsg?.role === "assistant") {
469
+ const content = lastMsg.content;
470
+ const text = Array.isArray(content)
471
+ ? content.filter((b) => b.type === "text").map((b) => b.text).join("\n")
472
+ : typeof content === "string" ? content : "";
473
+ const ns = state.results[state.currentStep];
474
+ if (ns)
475
+ ns.output = text;
476
+ broadcast("run:nodeResult", { workflowId: wfId, nodeId: state.currentStep, output: text });
477
+ }
478
+ }
479
+ });
480
+ console.error("[workflow] Extension loaded — /workflow to open editor");
481
+ }
482
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,196 @@
1
+ <!DOCTYPE html>
2
+ <html lang="zh-CN">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>Lyu-Code Workflow Editor</title>
7
+ <style>
8
+ * { margin: 0; padding: 0; box-sizing: border-box; }
9
+ body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif; background: #0a0a0a; color: #e0e0e0; }
10
+ #app { display: flex; flex-direction: column; height: 100vh; }
11
+
12
+ .header { padding: 12px 20px; background: #141414; border-bottom: 1px solid #262626; display: flex; align-items: center; gap: 12px; }
13
+ .header h1 { font-size: 16px; font-weight: 600; }
14
+ .header .status { margin-left: auto; font-size: 12px; color: #888; }
15
+ .header .status.connected { color: #4ade80; }
16
+
17
+ .toolbar { padding: 8px 20px; background: #1a1a1a; border-bottom: 1px solid #262626; display: flex; gap: 8px; }
18
+ .toolbar button { padding: 6px 14px; border: 1px solid #333; border-radius: 6px; background: #222; color: #ccc; cursor: pointer; font-size: 13px; }
19
+ .toolbar button:hover { background: #2a2a2a; border-color: #444; }
20
+ .toolbar button.primary { background: #2563eb; border-color: #2563eb; color: #fff; }
21
+ .toolbar button.primary:hover { background: #1d4ed8; }
22
+ .toolbar button.danger { background: #dc2626; border-color: #dc2626; color: #fff; }
23
+
24
+ .canvas-area { flex: 1; display: flex; align-items: center; justify-content: center; position: relative; }
25
+ .placeholder { text-align: center; color: #555; }
26
+ .placeholder h2 { font-size: 20px; margin-bottom: 8px; color: #888; }
27
+ .placeholder p { font-size: 14px; }
28
+
29
+ .panel { position: absolute; right: 16px; top: 16px; bottom: 16px; width: 300px; background: #141414; border: 1px solid #262626; border-radius: 8px; overflow: hidden; display: none; }
30
+ .panel.open { display: flex; flex-direction: column; }
31
+ .panel-header { padding: 12px 16px; border-bottom: 1px solid #262626; font-size: 14px; font-weight: 600; }
32
+ .panel-body { flex: 1; overflow-y: auto; padding: 12px 16px; }
33
+ .panel-body label { display: block; font-size: 12px; color: #888; margin-bottom: 4px; margin-top: 12px; }
34
+ .panel-body input, .panel-body textarea, .panel-body select {
35
+ width: 100%; padding: 6px 8px; background: #222; border: 1px solid #333; border-radius: 4px; color: #e0e0e0; font-size: 13px;
36
+ }
37
+ .panel-body textarea { min-height: 80px; resize: vertical; }
38
+ </style>
39
+ </head>
40
+ <body>
41
+ <div id="app">
42
+ <div class="header">
43
+ <h1>⚡ Lyu-Code Workflow</h1>
44
+ <span class="status" id="status">Connecting…</span>
45
+ </div>
46
+
47
+ <div class="toolbar">
48
+ <button class="primary" onclick="createWorkflow()">+ New Workflow</button>
49
+ <button onclick="addAgentNode()">Add Agent</button>
50
+ <button class="primary" onclick="runWorkflow()">▶ Run</button>
51
+ <button onclick="stopWorkflow()">■ Stop</button>
52
+ <button class="danger" onclick="clearWorkflow()">✕ Clear</button>
53
+ <span style="margin-left:auto;font-size:12px;color:#666;">
54
+ Max Loops: <input type="number" id="maxLoops" value="10" min="1" max="100" style="width:60px;padding:2px 4px;background:#222;border:1px solid #333;border-radius:3px;color:#e0e0e0;font-size:12px;">
55
+ </span>
56
+ </div>
57
+
58
+ <div class="canvas-area">
59
+ <div class="placeholder">
60
+ <h2>🎨 Workflow Canvas</h2>
61
+ <p>Replace this placeholder with your React Flow frontend.<br>
62
+ Put built files in <code>frontend/dist/</code></p>
63
+ <p style="margin-top:16px;font-size:12px;color:#444;">
64
+ WebSocket: <code id="wsUrl">ws://127.0.0.1:18789/ws</code><br>
65
+ API: <code id="apiUrl">http://127.0.0.1:18789/api</code>
66
+ </p>
67
+ </div>
68
+ </div>
69
+
70
+ <div class="panel" id="nodePanel">
71
+ <div class="panel-header">Node Config</div>
72
+ <div class="panel-body">
73
+ <label>Label</label>
74
+ <input type="text" id="nodeLabel" placeholder="Agent name">
75
+
76
+ <label>System Prompt</label>
77
+ <textarea id="nodePrompt" placeholder="You are a helpful coding agent..."></textarea>
78
+
79
+ <label>Model</label>
80
+ <select id="nodeModel">
81
+ <option value="">default</option>
82
+ <option value="gpt-6-sol">GPT-6 Sol</option>
83
+ <option value="gpt-5.6-luna">GPT-5.6 Luna</option>
84
+ <option value="deepseek-v4-pro">DeepSeek V4 Pro</option>
85
+ </select>
86
+
87
+ <label>Max Loops (this node)</label>
88
+ <input type="number" id="nodeMaxLoops" value="1" min="1" max="100">
89
+ </div>
90
+ </div>
91
+ </div>
92
+
93
+ <script>
94
+ // ─── WebSocket 连接 ─────────────────────────────────
95
+ let ws = null;
96
+ let currentWorkflow = null;
97
+ let msgId = 0;
98
+
99
+ function connectWS() {
100
+ const proto = location.protocol === 'https:' ? 'wss:' : 'ws:';
101
+ ws = new WebSocket(`${proto}//${location.host}/ws`);
102
+
103
+ ws.onopen = () => {
104
+ document.getElementById('status').textContent = 'Connected';
105
+ document.getElementById('status').classList.add('connected');
106
+ };
107
+
108
+ ws.onclose = () => {
109
+ document.getElementById('status').textContent = 'Disconnected';
110
+ document.getElementById('status').classList.remove('connected');
111
+ setTimeout(connectWS, 2000);
112
+ };
113
+
114
+ ws.onmessage = (e) => {
115
+ const msg = JSON.parse(e.data);
116
+ handleMessage(msg);
117
+ };
118
+ }
119
+
120
+ function send(type, data = {}) {
121
+ if (!ws || ws.readyState !== WebSocket.OPEN) return;
122
+ ws.send(JSON.stringify({ type, data, id: String(++msgId) }));
123
+ }
124
+
125
+ function handleMessage(msg) {
126
+ switch (msg.type) {
127
+ case 'connected':
128
+ console.log('Connected to workflow server', msg.data);
129
+ break;
130
+ case 'workflow:created':
131
+ currentWorkflow = msg.data;
132
+ console.log('Workflow created:', msg.data.id);
133
+ break;
134
+ case 'workflow:updated':
135
+ currentWorkflow = msg.data;
136
+ break;
137
+ case 'run:state':
138
+ console.log('Run state:', msg.data);
139
+ break;
140
+ case 'run:nodeResult':
141
+ console.log('Node result:', msg.data);
142
+ break;
143
+ }
144
+ }
145
+
146
+ // ─── UI 操作 ─────────────────────────────────────────
147
+ function createWorkflow() {
148
+ send('workflow:create', {
149
+ name: 'New Workflow',
150
+ globalMaxLoops: parseInt(document.getElementById('maxLoops').value) || 10,
151
+ });
152
+ }
153
+
154
+ function addAgentNode() {
155
+ if (!currentWorkflow) { createWorkflow(); setTimeout(addAgentNode, 100); return; }
156
+ const id = 'agent-' + Date.now();
157
+ send('node:add', {
158
+ workflowId: currentWorkflow.id,
159
+ node: {
160
+ id,
161
+ type: 'agent',
162
+ label: 'Agent ' + (currentWorkflow.nodes.length + 1),
163
+ config: { systemPrompt: '', maxLoops: 1 },
164
+ position: { x: 100 + currentWorkflow.nodes.length * 200, y: 200 },
165
+ },
166
+ });
167
+ }
168
+
169
+ function runWorkflow() {
170
+ if (!currentWorkflow) return;
171
+ // 先更新 globalMaxLoops
172
+ send('workflow:update', {
173
+ id: currentWorkflow.id,
174
+ globalMaxLoops: parseInt(document.getElementById('maxLoops').value) || 10,
175
+ });
176
+ setTimeout(() => {
177
+ send('workflow:run', { workflowId: currentWorkflow.id });
178
+ }, 50);
179
+ }
180
+
181
+ function stopWorkflow() {
182
+ if (!currentWorkflow) return;
183
+ send('workflow:stop', { workflowId: currentWorkflow.id });
184
+ }
185
+
186
+ function clearWorkflow() {
187
+ if (!currentWorkflow) return;
188
+ send('workflow:delete', { id: currentWorkflow.id });
189
+ currentWorkflow = null;
190
+ }
191
+
192
+ // ─── 启动 ───────────────────────────────────────────
193
+ connectWS();
194
+ </script>
195
+ </body>
196
+ </html>
package/package.json CHANGED
@@ -1,6 +1,33 @@
1
1
  {
2
2
  "name": "lyu-extension-workflow",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
6
- }
3
+ "version": "0.1.0",
4
+ "description": "Workflow extension for lyu-code — visually compose multi-agent pipelines",
5
+ "type": "module",
6
+ "main": "dist/index.js",
7
+ "scripts": {
8
+ "build": "tsc -p tsconfig.json"
9
+ },
10
+ "files": [
11
+ "dist",
12
+ "frontend/dist"
13
+ ],
14
+ "pi": {
15
+ "extensions": [
16
+ "dist/index.js"
17
+ ]
18
+ },
19
+ "dependencies": {
20
+ "@earendil-works/pi-coding-agent": "^0.87.1",
21
+ "@earendil-works/pi-ai": "^0.87.1"
22
+ },
23
+ "devDependencies": {
24
+ "typescript": "^5.8.0",
25
+ "@types/node": "^22.0.0"
26
+ },
27
+ "license": "MIT",
28
+ "repository": {
29
+ "type": "git",
30
+ "url": "https://github.com/WeeeeeKdY/lyu-code.git",
31
+ "directory": "packages/extensions/workflow"
32
+ }
33
+ }
package/README.md DELETED
@@ -1,3 +0,0 @@
1
- # Temporary Holding Version
2
-
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.