opencode-pixel-office 1.0.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,971 @@
1
+ import http from "node:http";
2
+ import path from "node:path";
3
+ import fs from "node:fs";
4
+ import os from "node:os";
5
+ import { fileURLToPath } from "node:url";
6
+ import express from "express";
7
+ import { WebSocketServer } from "ws";
8
+
9
+ const __filename = fileURLToPath(import.meta.url);
10
+ const __dirname = path.dirname(__filename);
11
+
12
+ const PORT = Number.parseInt(process.env.PORT || "5100", 10);
13
+ const CLIENT_DIST_DIR = path.join(__dirname, "..", "client", "dist");
14
+ const CLIENT_DIR = fs.existsSync(CLIENT_DIST_DIR)
15
+ ? CLIENT_DIST_DIR
16
+ : path.join(__dirname, "..", "client");
17
+
18
+ const app = express();
19
+ app.use(express.json({ limit: "256kb" }));
20
+ app.use(express.static(CLIENT_DIR));
21
+
22
+ const server = http.createServer(app);
23
+ const wss = new WebSocketServer({ server, path: "/ws" });
24
+
25
+ type BossMessage = {
26
+ text: string;
27
+ status?: string;
28
+ updatedAt: number;
29
+ };
30
+
31
+ type TodoSummary = {
32
+ total: number;
33
+ completed: number;
34
+ updatedAt: number;
35
+ };
36
+
37
+ type TodoItem = {
38
+ id: string;
39
+ content: string;
40
+ status: string;
41
+ priority: string;
42
+ };
43
+
44
+ type SessionInfo = {
45
+ id: string;
46
+ title?: string;
47
+ slug?: string;
48
+ status?: string;
49
+ version?: string;
50
+ directory?: string;
51
+ projectId?: string;
52
+ updatedAt: number;
53
+ };
54
+
55
+ type OfficeState = {
56
+ agents: Map<string, any>;
57
+ interactions: Map<string, { with: string; updatedAt: number }>;
58
+ aliases: Map<string, string>;
59
+ nextDeskIndex: number;
60
+ nextAliasIndex: number;
61
+ activeSessionId: string | null;
62
+ lastActiveAt: number;
63
+ loggedEventTypes: Set<string>;
64
+ appVersion: string | null;
65
+ lastTodoSummary: TodoSummary | null;
66
+ todos: TodoItem[];
67
+ sessions: Map<string, SessionInfo>;
68
+ bossMessage: BossMessage | null;
69
+ messageRoles: Map<string, string>;
70
+ networkIp: string | null;
71
+ };
72
+
73
+ type EventPayload = {
74
+ type?: string;
75
+ properties?: Record<string, any>;
76
+ };
77
+
78
+ const officeState: OfficeState = {
79
+ agents: new Map(),
80
+ interactions: new Map(),
81
+ aliases: new Map(),
82
+ nextDeskIndex: 0,
83
+ nextAliasIndex: 1,
84
+ activeSessionId: null,
85
+ lastActiveAt: 0,
86
+ loggedEventTypes: new Set(),
87
+ appVersion: null,
88
+ lastTodoSummary: null,
89
+ todos: [],
90
+ sessions: new Map(),
91
+ bossMessage: null,
92
+ messageRoles: new Map(),
93
+ networkIp: null,
94
+ };
95
+
96
+ const MAX_DESKS = 15;
97
+ const DESK_COLUMNS = 5;
98
+ const IDLE_TTL_MS = 6000;
99
+
100
+ const KNOWN_EVENTS = new Set([
101
+ "command.executed",
102
+ "file.edited",
103
+ "file.watcher.updated",
104
+ "installation.updated",
105
+ "lsp.client.diagnostics",
106
+ "lsp.updated",
107
+ "message.part.removed",
108
+ "message.part.updated",
109
+ "message.removed",
110
+ "message.updated",
111
+ "permission.asked",
112
+ "permission.replied",
113
+ "server.connected",
114
+ "session.created",
115
+ "session.compacted",
116
+ "session.deleted",
117
+ "session.diff",
118
+ "session.error",
119
+ "session.idle",
120
+ "session.status",
121
+ "session.updated",
122
+ "todo.updated",
123
+ "tool.execute.after",
124
+ "tool.execute.before",
125
+ "tui.prompt.append",
126
+ "tui.command.execute",
127
+ "tui.toast.show",
128
+ ]);
129
+
130
+ const safeString = (value: unknown, fallback: string) => {
131
+ if (typeof value === "string" && value.trim().length > 0) {
132
+ return value.trim();
133
+ }
134
+ return fallback;
135
+ };
136
+
137
+ const getEventType = (event: EventPayload) => safeString(event?.type, "").toLowerCase();
138
+
139
+ const logEventSummary = (event: EventPayload) => {
140
+ const type = getEventType(event);
141
+ const props = event?.properties || {};
142
+
143
+ switch (type) {
144
+ case "command.executed": {
145
+ const command = safeString(props.command ?? "", "");
146
+ console.log(`[PixelOffice] command.executed: ${command || "(no command)"}`);
147
+ return;
148
+ }
149
+ case "file.edited":
150
+ case "file.watcher.updated": {
151
+ const file = safeString(props.file ?? "", "");
152
+ console.log(`[PixelOffice] ${type}: ${file || "(no file)"}`);
153
+ return;
154
+ }
155
+ case "installation.updated": {
156
+ const version = safeString(props.version ?? "", "");
157
+ console.log(`[PixelOffice] installation.updated: ${version || "(no version)"}`);
158
+ return;
159
+ }
160
+ case "lsp.client.diagnostics": {
161
+ const diagnostics = Array.isArray(props.diagnostics) ? props.diagnostics : [];
162
+ console.log(`[PixelOffice] lsp.client.diagnostics: ${diagnostics.length} issues`);
163
+ return;
164
+ }
165
+ case "lsp.updated": {
166
+ const status = safeString(props.status ?? "", "");
167
+ console.log(`[PixelOffice] lsp.updated: ${status || "(no status)"}`);
168
+ return;
169
+ }
170
+ case "message.part.removed": {
171
+ const partId = safeString(props.part?.id ?? "", "");
172
+ console.log(`[PixelOffice] message.part.removed: ${partId || "(no part id)"}`);
173
+ return;
174
+ }
175
+ case "message.part.updated": {
176
+ const text = safeString(props.part?.text ?? "", "");
177
+ console.log(`[PixelOffice] message.part.updated: ${text || "(no text)"}`);
178
+ return;
179
+ }
180
+ case "message.removed": {
181
+ const messageId = safeString(props.message?.id ?? "", "");
182
+ console.log(`[PixelOffice] message.removed: ${messageId || "(no message id)"}`);
183
+ return;
184
+ }
185
+ case "message.updated": {
186
+ const text = normalizeMessageContent(props.message?.content);
187
+ console.log(`[PixelOffice] message.updated: ${text || "(no content)"}`);
188
+ return;
189
+ }
190
+ case "permission.asked":
191
+ case "permission.replied": {
192
+ const permission = safeString(props.permission?.action ?? "", "");
193
+ console.log(`[PixelOffice] ${type}: ${permission || "(no permission)"}`);
194
+ return;
195
+ }
196
+ case "server.connected": {
197
+ const host = safeString(props.server?.host ?? "", "");
198
+ console.log(`[PixelOffice] server.connected: ${host || "(no host)"}`);
199
+ return;
200
+ }
201
+ case "session.created":
202
+ case "session.compacted":
203
+ case "session.deleted":
204
+ case "session.diff":
205
+ case "session.error":
206
+ case "session.idle":
207
+ case "session.status":
208
+ case "session.updated": {
209
+ if (type === "session.diff") {
210
+ const diff = Array.isArray(props.diff) ? props.diff : [];
211
+ if (diff.length === 0) {
212
+ return;
213
+ }
214
+ }
215
+ const sessionId = safeString(props.info?.id ?? props.sessionID ?? "", "");
216
+ const status = safeString(props.status?.type ?? "", "");
217
+ const suffix = status ? ` (${status})` : "";
218
+ console.log(`[PixelOffice] ${type}: ${sessionId || "(no session)"}${suffix}`);
219
+ return;
220
+ }
221
+ case "todo.updated": {
222
+ const todos = Array.isArray(props.todos) ? props.todos : [];
223
+ const completed = todos.filter((todo) => todo.status === "completed").length;
224
+ console.log(`[PixelOffice] todo.updated: ${completed}/${todos.length}`);
225
+ return;
226
+ }
227
+ case "tool.execute.after":
228
+ case "tool.execute.before": {
229
+ const toolName = safeString(props.tool?.name ?? "", "");
230
+ console.log(`[PixelOffice] ${type}: ${toolName || "(no tool)"}`);
231
+ return;
232
+ }
233
+ case "tui.prompt.append": {
234
+ const prompt = safeString(props.prompt ?? "", "");
235
+ console.log(`[PixelOffice] tui.prompt.append: ${prompt || "(no prompt)"}`);
236
+ return;
237
+ }
238
+ case "tui.command.execute": {
239
+ const command = safeString(props.command ?? "", "");
240
+ console.log(`[PixelOffice] tui.command.execute: ${command || "(no command)"}`);
241
+ return;
242
+ }
243
+ case "tui.toast.show": {
244
+ const message = safeString(props.message ?? "", "");
245
+ console.log(`[PixelOffice] tui.toast.show: ${message || "(no message)"}`);
246
+ return;
247
+ }
248
+ default:
249
+ console.log(`[PixelOffice] ${type}`);
250
+ }
251
+ };
252
+
253
+ const normalizeMessageContent = (content: unknown) => {
254
+ if (typeof content === "string") {
255
+ return content.trim();
256
+ }
257
+ if (Array.isArray(content)) {
258
+ return content
259
+ .map((item) => {
260
+ if (typeof item === "string") {
261
+ return item.trim();
262
+ }
263
+ if (item && typeof item.text === "string") {
264
+ return item.text.trim();
265
+ }
266
+ return "";
267
+ })
268
+ .filter(Boolean)
269
+ .join(" ")
270
+ .trim();
271
+ }
272
+ return "";
273
+ };
274
+
275
+ const extractUserMessage = (event: EventPayload) => {
276
+ const props = event?.properties || {};
277
+ const message = props.message || {};
278
+ const part = props.part || {};
279
+ const info = props.info || {};
280
+ const eventType = getEventType(event);
281
+ if (eventType !== "message.updated" && eventType !== "message.part.updated") {
282
+ return null;
283
+ }
284
+ const role = safeString(info.role ?? message.role ?? "", "").toLowerCase();
285
+ const roleIsUser = role === "user";
286
+ const roleIsAssistant = role === "assistant" || role === "system";
287
+ const messageId = safeString(
288
+ eventType === "message.part.updated" ? part.messageID ?? "" : info.id ?? "",
289
+ ""
290
+ );
291
+ if (messageId && role) {
292
+ officeState.messageRoles.set(messageId, role);
293
+ }
294
+ const storedRole = messageId ? officeState.messageRoles.get(messageId) : "";
295
+ const isUser = roleIsUser || storedRole === "user";
296
+ if (!isUser || roleIsAssistant) {
297
+ return null;
298
+ }
299
+ const text =
300
+ eventType === "message.part.updated"
301
+ ? safeString(part.text ?? "", "")
302
+ : normalizeMessageContent(message.content) || safeString(message.text ?? "", "");
303
+ if (!text) {
304
+ return null;
305
+ }
306
+ const status = safeString(message.status ?? "", "");
307
+ return { text, status };
308
+ };
309
+
310
+ const extractAgentId = (event: EventPayload) => {
311
+ const props = event?.properties || {};
312
+ const info = props.info || {};
313
+ const agentName = safeString(info.agent ?? "", "");
314
+ const sessionId = safeString(info.sessionID ?? "", "");
315
+ if (agentName && sessionId) {
316
+ return `${sessionId}:${agentName}`;
317
+ }
318
+ if (agentName) {
319
+ return agentName;
320
+ }
321
+ return sessionId;
322
+ };
323
+
324
+ const extractSessionId = (event: EventPayload) => {
325
+ const props = event?.properties || {};
326
+ const info = props.info || {};
327
+ const part = props.part || {};
328
+ const eventType = getEventType(event);
329
+ if (eventType === "session.updated" || eventType === "session.created" || eventType === "session.compacted") {
330
+ return safeString(info.id ?? "", "");
331
+ }
332
+ if (
333
+ eventType === "session.status" ||
334
+ eventType === "session.diff" ||
335
+ eventType === "session.idle" ||
336
+ eventType === "session.deleted" ||
337
+ eventType === "session.error"
338
+ ) {
339
+ return safeString(props.sessionID ?? "", "");
340
+ }
341
+ if (eventType === "message.part.updated") {
342
+ return safeString(part.sessionID ?? "", "");
343
+ }
344
+ if (eventType === "file.edited" || eventType === "file.watcher.updated") {
345
+ return safeString(props.sessionID ?? "", "");
346
+ }
347
+ return safeString(info.sessionID ?? "", "");
348
+ };
349
+
350
+ const isSessionOnlyOrPartEvent = (event: EventPayload) => {
351
+ const type = getEventType(event);
352
+ return (
353
+ type === "session.updated" ||
354
+ type === "session.status" ||
355
+ type === "session.diff" ||
356
+ type === "session.idle" ||
357
+ type === "session.deleted" ||
358
+ type === "session.error" ||
359
+ type === "session.created" ||
360
+ type === "session.compacted" ||
361
+ type === "tui.toast.show" ||
362
+ type === "message.part.updated"
363
+ );
364
+ };
365
+
366
+ const resolveAgentIdsForEvent = (event: EventPayload) => {
367
+ const props = event?.properties || {};
368
+ const info = props.info || {};
369
+ const sessionId = extractSessionId(event);
370
+ const agentName = safeString(info.agent ?? "", "");
371
+ if (!sessionId) {
372
+ const direct = extractAgentId(event);
373
+ return direct ? [direct] : [];
374
+ }
375
+
376
+ const matches = Array.from(officeState.agents.keys()).filter((key) =>
377
+ key.startsWith(`${sessionId}:`)
378
+ );
379
+ if (matches.length > 0) {
380
+ return matches;
381
+ }
382
+
383
+ if (isSessionOnlyOrPartEvent(event)) {
384
+ return [];
385
+ }
386
+
387
+ if (agentName) {
388
+ return [`${sessionId}:${agentName}`];
389
+ }
390
+
391
+ const direct = extractAgentId(event);
392
+ return direct ? [direct] : [];
393
+ };
394
+
395
+ const isSessionOnlyEvent = (event: EventPayload) => {
396
+ const type = getEventType(event);
397
+ return (
398
+ type === "session.updated" ||
399
+ type === "session.status" ||
400
+ type === "session.diff" ||
401
+ type === "session.idle" ||
402
+ type === "session.deleted" ||
403
+ type === "session.error"
404
+ );
405
+ };
406
+
407
+ const extractAgentName = (event: EventPayload, agentId: string) => {
408
+ const props = event?.properties || {};
409
+ const info = props.info || {};
410
+ const session = props.session || {};
411
+ const preferred = safeString(info.agent ?? session.name ?? agentId, agentId);
412
+ if (preferred === agentId) {
413
+ return agentId;
414
+ }
415
+ if (preferred.startsWith("ses_")) {
416
+ return agentId;
417
+ }
418
+ if (preferred.includes("session")) {
419
+ return agentId;
420
+ }
421
+ return preferred;
422
+ };
423
+
424
+ const extractAgentModel = (event: EventPayload) => {
425
+ const props = event?.properties || {};
426
+ const info = props.info || {};
427
+ return safeString(info.model?.modelID ?? "unknown", "unknown");
428
+ };
429
+
430
+ const extractActiveSessionId = (event: EventPayload) => {
431
+ const props = event?.properties || {};
432
+ const info = props.info || {};
433
+ const eventType = getEventType(event);
434
+ if (
435
+ eventType === "session.status" ||
436
+ eventType === "session.diff" ||
437
+ eventType === "session.idle" ||
438
+ eventType === "session.deleted" ||
439
+ eventType === "session.error"
440
+ ) {
441
+ return safeString(props.sessionID ?? "", "");
442
+ }
443
+ if (eventType === "session.updated" || eventType === "session.created" || eventType === "session.compacted") {
444
+ return safeString(info.id ?? "", "");
445
+ }
446
+ return safeString(info.sessionID ?? "", "");
447
+ };
448
+
449
+ const applySessionLifecycle = (event: EventPayload) => {
450
+ const type = getEventType(event);
451
+ if (type === "session.deleted") {
452
+ const props = event?.properties || {};
453
+ const sessionId = safeString(props.sessionID ?? "", "");
454
+ if (sessionId) {
455
+ officeState.sessions.delete(sessionId);
456
+ for (const key of officeState.agents.keys()) {
457
+ if (key.startsWith(`${sessionId}:`) || key === sessionId) {
458
+ officeState.agents.delete(key);
459
+ officeState.aliases.delete(key);
460
+ officeState.interactions.delete(key);
461
+ }
462
+ }
463
+ if (officeState.activeSessionId === sessionId) {
464
+ officeState.activeSessionId = null;
465
+ }
466
+ }
467
+ }
468
+
469
+ if (type === "session.idle") {
470
+ const agentIds = resolveAgentIdsForEvent(event);
471
+ agentIds.forEach((agentId) => {
472
+ if (officeState.agents.has(agentId)) {
473
+ const existing = officeState.agents.get(agentId);
474
+ officeState.agents.set(agentId, {
475
+ ...existing,
476
+ status: "idle",
477
+ updatedAt: Date.now(),
478
+ });
479
+ }
480
+ });
481
+ }
482
+ };
483
+
484
+ const getAlias = (agentId: string, preferredName: string) => {
485
+ if (preferredName && preferredName !== agentId) {
486
+ officeState.aliases.set(agentId, preferredName);
487
+ }
488
+ if (!officeState.aliases.has(agentId)) {
489
+ officeState.aliases.set(agentId, `Agent ${officeState.nextAliasIndex}`);
490
+ officeState.nextAliasIndex += 1;
491
+ }
492
+ return officeState.aliases.get(agentId);
493
+ };
494
+
495
+ const mapStatusFromEvent = (event: EventPayload) => {
496
+ const type = getEventType(event);
497
+ const status = safeString(event?.properties?.status ?? "", "").toLowerCase();
498
+
499
+ if (status) {
500
+ return status;
501
+ }
502
+ if (type === "session.error") {
503
+ return "error";
504
+ }
505
+ if (type === "tool.execute.before") {
506
+ return "working";
507
+ }
508
+ if (type === "tool.execute.after") {
509
+ return "thinking";
510
+ }
511
+ if (type.startsWith("message.")) {
512
+ return "thinking";
513
+ }
514
+ if (type === "session.idle") {
515
+ return "idle";
516
+ }
517
+ if (type === "session.created") {
518
+ return "idle";
519
+ }
520
+ if (type === "session.status") {
521
+ return "working";
522
+ }
523
+ if (type === "session.compacted") {
524
+ return "planning";
525
+ }
526
+ return "working";
527
+ };
528
+
529
+ const extractParentId = (event: EventPayload) => {
530
+ const props = event?.properties || {};
531
+ return safeString(props.parentSessionId ?? "", "");
532
+ };
533
+
534
+ const extractSessionInfo = (event: EventPayload) => {
535
+ const props = event?.properties || {};
536
+ const info = props.info || {};
537
+ const eventType = getEventType(event);
538
+ if (
539
+ eventType !== "session.updated" &&
540
+ eventType !== "session.created" &&
541
+ eventType !== "session.compacted"
542
+ ) {
543
+ return null;
544
+ }
545
+ const sessionId = safeString(info.id ?? "", "");
546
+ if (!sessionId) {
547
+ return null;
548
+ }
549
+ return {
550
+ id: sessionId,
551
+ title: safeString(info.title ?? "", ""),
552
+ slug: safeString(info.slug ?? "", ""),
553
+ status: "",
554
+ version: safeString(info.version ?? "", ""),
555
+ directory: safeString(info.directory ?? "", ""),
556
+ projectId: safeString(info.projectID ?? "", ""),
557
+ updatedAt: Date.now(),
558
+ };
559
+ };
560
+
561
+ const upsertSession = (event: EventPayload) => {
562
+ const info = extractSessionInfo(event);
563
+ if (!info) {
564
+ return;
565
+ }
566
+ const existing = officeState.sessions.get(info.id);
567
+ const nextInfo = existing
568
+ ? {
569
+ ...existing,
570
+ ...info,
571
+ updatedAt: Date.now(),
572
+ }
573
+ : info;
574
+ officeState.sessions.set(info.id, nextInfo);
575
+ };
576
+
577
+ const updateSessionStatus = (event: EventPayload) => {
578
+ const eventType = getEventType(event);
579
+ if (eventType !== "session.status") {
580
+ return;
581
+ }
582
+ const props = event?.properties || {};
583
+ const sessionId = safeString(props.sessionID ?? "", "");
584
+ if (!sessionId) {
585
+ return;
586
+ }
587
+ const status = safeString(props.status?.type ?? "", "");
588
+ const existing = officeState.sessions.get(sessionId);
589
+ const nextInfo = existing
590
+ ? {
591
+ ...existing,
592
+ status,
593
+ updatedAt: Date.now(),
594
+ }
595
+ : {
596
+ id: sessionId,
597
+ status,
598
+ updatedAt: Date.now(),
599
+ };
600
+ officeState.sessions.set(sessionId, nextInfo);
601
+ };
602
+
603
+ const assignDesk = () => {
604
+ const deskIndex = officeState.nextDeskIndex % MAX_DESKS;
605
+ officeState.nextDeskIndex += 1;
606
+ return {
607
+ deskIndex,
608
+ row: Math.floor(deskIndex / DESK_COLUMNS),
609
+ column: deskIndex % DESK_COLUMNS,
610
+ };
611
+ };
612
+
613
+ const extractSessionTitle = (event: EventPayload) => {
614
+ const info = event?.properties?.info || {};
615
+ return safeString(info.title ?? "", "");
616
+ };
617
+
618
+ const isBackgroundSession = (title: string) =>
619
+ Boolean(title) &&
620
+ (title.toLowerCase().includes("subagent") ||
621
+ title.toLowerCase().includes("looker") ||
622
+ title.toLowerCase().includes("multimodal"));
623
+
624
+ const pruneAgents = () => {
625
+ const now = Date.now();
626
+ for (const [key, agent] of officeState.agents.entries()) {
627
+ const lastActivity = agent.lastActivityAt || agent.lastMessageAt || 0;
628
+ if (!agent.isBackground && agent.status !== "idle" && lastActivity) {
629
+ if (now - lastActivity > IDLE_TTL_MS) {
630
+ officeState.agents.set(key, {
631
+ ...agent,
632
+ status: "idle",
633
+ updatedAt: now,
634
+ });
635
+ }
636
+ }
637
+ if (
638
+ agent.isBackground &&
639
+ agent.status !== "idle" &&
640
+ agent.status !== "error" &&
641
+ agent.lastActivityAt &&
642
+ now - agent.lastActivityAt > 4000
643
+ ) {
644
+ officeState.agents.set(key, {
645
+ ...agent,
646
+ status: "idle",
647
+ updatedAt: now,
648
+ });
649
+ }
650
+ if (
651
+ agent.isBackground &&
652
+ agent.status === "idle" &&
653
+ now - agent.updatedAt > 3000
654
+ ) {
655
+ officeState.agents.delete(key);
656
+ officeState.aliases.delete(key);
657
+ officeState.interactions.delete(key);
658
+ }
659
+ }
660
+ };
661
+
662
+ const setInteraction = (fromId: string, toId: string) => {
663
+ if (!fromId || !toId || fromId === toId) {
664
+ return;
665
+ }
666
+ officeState.interactions.set(fromId, {
667
+ with: toId,
668
+ updatedAt: Date.now(),
669
+ });
670
+ };
671
+
672
+ const pruneInteractions = () => {
673
+ const now = Date.now();
674
+ for (const [key, value] of officeState.interactions.entries()) {
675
+ if (now - value.updatedAt > 15_000) {
676
+ officeState.interactions.delete(key);
677
+ }
678
+ }
679
+ };
680
+
681
+ const upsertAgentFromEvent = (event: EventPayload) => {
682
+ const agentIds = resolveAgentIdsForEvent(event);
683
+ const targetIds = isSessionOnlyOrPartEvent(event)
684
+ ? agentIds
685
+ : agentIds.length > 0
686
+ ? agentIds
687
+ : [extractAgentId(event)];
688
+ const cleanedIds = targetIds.filter(
689
+ (id): id is string => typeof id === "string" && id.length > 0
690
+ );
691
+ if (cleanedIds.length === 0) {
692
+ return null;
693
+ }
694
+ if (isSessionOnlyOrPartEvent(event)) {
695
+ const hasAgentMatch = cleanedIds.some((id) => officeState.agents.has(id));
696
+ if (!hasAgentMatch) {
697
+ return null;
698
+ }
699
+ }
700
+ const props = event?.properties || {};
701
+ const part = props.part || {};
702
+ const partText = safeString(part.text, "");
703
+ const partContent = safeString(part.content, "");
704
+ const partDelta = safeString(part.delta, "");
705
+ const messageSnippet = partText || partContent || partDelta;
706
+ const status = mapStatusFromEvent(event);
707
+ const model = extractAgentModel(event);
708
+ const provider = safeString(event?.properties?.info?.model?.providerID, "");
709
+ const modelId = safeString(event?.properties?.info?.model?.modelID, "");
710
+ const rawSessionId = extractSessionId(event);
711
+ const sessionTitle = extractSessionTitle(event);
712
+ const updatedAt = Date.now();
713
+ const eventType = getEventType(event);
714
+ const isPartUpdate = eventType === "message.part.updated";
715
+ const messageId = isPartUpdate
716
+ ? safeString(part.messageID ?? "", "")
717
+ : safeString(props.info?.id ?? "", "");
718
+ const messageRole = messageId ? officeState.messageRoles.get(messageId) : "";
719
+ const isUserMessage = messageRole === "user";
720
+ let primaryId = cleanedIds[0];
721
+
722
+ cleanedIds.forEach((agentId) => {
723
+ const existing = officeState.agents.get(agentId);
724
+ const name = isSessionOnlyOrPartEvent(event)
725
+ ? existing?.name || agentId
726
+ : extractAgentName(event, agentId);
727
+ const alias = getAlias(agentId, name);
728
+ const resolvedModel = modelId || model;
729
+ const nextModel =
730
+ resolvedModel !== "unknown"
731
+ ? resolvedModel
732
+ : existing?.model || "unknown";
733
+ const nextProvider = provider || existing?.provider || "";
734
+ const nextSessionId = rawSessionId || existing?.sessionId || "";
735
+ const nextSessionTitle = sessionTitle || existing?.sessionTitle || "";
736
+ const nextIsBackground = isBackgroundSession(nextSessionTitle);
737
+
738
+ const nextMessageSnippet = isUserMessage
739
+ ? existing?.lastMessageSnippet || ""
740
+ : isPartUpdate && !partText && !partContent && partDelta
741
+ ? `${existing?.lastMessageSnippet || ""}${partDelta}`
742
+ : messageSnippet || existing?.lastMessageSnippet || "";
743
+ const trimmedSnippet =
744
+ nextMessageSnippet.length > 400
745
+ ? nextMessageSnippet.slice(-400)
746
+ : nextMessageSnippet;
747
+ const hasMessageUpdate = !isUserMessage && Boolean(messageSnippet);
748
+ const now = Date.now();
749
+ const isFileEditEvent = eventType === "file.edited" || eventType === "file.watcher.updated";
750
+ const isActivityEvent =
751
+ eventType === "tool.execute.before" ||
752
+ isFileEditEvent ||
753
+ isPartUpdate ||
754
+ (eventType === "message.updated" && hasMessageUpdate);
755
+ const nextMessageAt = hasMessageUpdate
756
+ ? now
757
+ : existing?.lastMessageAt || 0;
758
+ const nextStreamingAt = isPartUpdate && hasMessageUpdate
759
+ ? now
760
+ : existing?.lastStreamingAt || 0;
761
+ const nextActivityAt = isActivityEvent
762
+ ? now
763
+ : existing?.lastActivityAt || 0;
764
+ const nextStatus =
765
+ existing?.status === "idle" && !isActivityEvent && status !== "error"
766
+ ? "idle"
767
+ : status;
768
+
769
+ if (existing) {
770
+ officeState.agents.set(agentId, {
771
+ ...existing,
772
+ name,
773
+ alias,
774
+ model: nextModel,
775
+ provider: nextProvider,
776
+ sessionId: nextSessionId,
777
+ sessionTitle: nextSessionTitle,
778
+ isBackground: nextIsBackground,
779
+ status: nextStatus,
780
+ lastEventType: event?.type || existing.lastEventType,
781
+ lastMessageSnippet: trimmedSnippet,
782
+ lastMessageAt: nextMessageAt,
783
+ lastStreamingAt: nextStreamingAt,
784
+ lastActivityAt: nextActivityAt,
785
+ lastStatusType: props.status?.type || existing.lastStatusType || "",
786
+ lastEventAt: now,
787
+ lastDiffAt: eventType === "session.diff" ? Date.now() : existing.lastDiffAt,
788
+ lastFileEdited: props.file || existing.lastFileEdited || "",
789
+ lastFileEditAt: isFileEditEvent ? Date.now() : existing.lastFileEditAt,
790
+ updatedAt,
791
+ });
792
+ } else {
793
+ officeState.agents.set(agentId, {
794
+ id: agentId,
795
+ name,
796
+ alias,
797
+ model: nextModel,
798
+ provider: nextProvider,
799
+ sessionId: nextSessionId,
800
+ sessionTitle: nextSessionTitle,
801
+ isBackground: nextIsBackground,
802
+ status,
803
+ lastEventType: event?.type || "unknown",
804
+ lastMessageSnippet: trimmedSnippet,
805
+ lastMessageAt: hasMessageUpdate ? Date.now() : 0,
806
+ lastStreamingAt: isPartUpdate && hasMessageUpdate ? Date.now() : 0,
807
+ lastActivityAt: isActivityEvent ? Date.now() : 0,
808
+ lastStatusType: props.status?.type || "",
809
+ lastEventAt: now,
810
+ lastDiffAt: eventType === "session.diff" ? Date.now() : 0,
811
+ lastFileEdited: props.file || "",
812
+ lastFileEditAt: isFileEditEvent ? Date.now() : 0,
813
+ updatedAt,
814
+ desk: assignDesk(),
815
+ });
816
+ }
817
+ });
818
+
819
+ return primaryId;
820
+ };
821
+
822
+ const updateBossMessage = (event: EventPayload) => {
823
+ const userMessage = extractUserMessage(event);
824
+ if (!userMessage) {
825
+ return;
826
+ }
827
+ officeState.bossMessage = {
828
+ ...userMessage,
829
+ updatedAt: Date.now(),
830
+ };
831
+ };
832
+
833
+ const getStateSnapshot = () => {
834
+ pruneInteractions();
835
+ pruneAgents();
836
+ return {
837
+ agents: Array.from(officeState.agents.values()),
838
+ sessions: Array.from(officeState.sessions.values()).sort(
839
+ (a, b) => b.updatedAt - a.updatedAt
840
+ ),
841
+ todos: officeState.todos,
842
+ activeSessionId: officeState.activeSessionId,
843
+ appVersion: officeState.appVersion,
844
+ lastTodoSummary: officeState.lastTodoSummary,
845
+ interactions: Array.from(officeState.interactions.entries()).map(
846
+ ([from, info]) => ({
847
+ from,
848
+ to: info.with,
849
+ updatedAt: info.updatedAt,
850
+ })
851
+ ),
852
+ bossMessage: officeState.bossMessage,
853
+ networkIp: officeState.networkIp,
854
+ updatedAt: Date.now(),
855
+ };
856
+ };
857
+
858
+ const broadcast = (payload: unknown) => {
859
+ const data = JSON.stringify(payload);
860
+ for (const client of wss.clients) {
861
+ if (client.readyState === 1) {
862
+ client.send(data);
863
+ }
864
+ }
865
+ };
866
+
867
+ app.post("/events", (req: any, res: any) => {
868
+ const event = req.body as EventPayload;
869
+ const eventType = getEventType(event) || "unknown";
870
+ // console.log(`[PixelOffice] Event received: ${eventType}`);
871
+ if (!officeState.loggedEventTypes.has(eventType)) {
872
+ officeState.loggedEventTypes.add(eventType);
873
+ }
874
+ if (!KNOWN_EVENTS.has(eventType)) {
875
+ res.status(202).json({ ok: true });
876
+ return;
877
+ }
878
+ logEventSummary(event);
879
+
880
+ if (eventType === "installation.updated") {
881
+ const nextVersion = safeString(event?.properties?.version ?? "", "");
882
+ officeState.appVersion = nextVersion || null;
883
+ }
884
+
885
+ if (eventType === "session.diff") {
886
+ const diff = Array.isArray(event?.properties?.diff)
887
+ ? event.properties.diff
888
+ : [];
889
+ if (diff.length === 0) {
890
+ res.status(202).json({ ok: true });
891
+ return;
892
+ }
893
+ }
894
+
895
+ if (eventType === "todo.updated") {
896
+ const todos = Array.isArray(event?.properties?.todos)
897
+ ? event.properties.todos
898
+ : [];
899
+ const completed = todos.filter((todo) => todo.status === "completed").length;
900
+ const updatedAt = Date.now();
901
+ if (todos.length > 0 && completed === todos.length) {
902
+ officeState.lastTodoSummary = {
903
+ total: 0,
904
+ completed: 0,
905
+ updatedAt,
906
+ };
907
+ officeState.todos = [];
908
+ } else {
909
+ officeState.lastTodoSummary = {
910
+ total: todos.length,
911
+ completed,
912
+ updatedAt,
913
+ };
914
+ officeState.todos = todos.map((todo) => ({
915
+ id: safeString(todo.id, ""),
916
+ content: safeString(todo.content, ""),
917
+ status: safeString(todo.status, ""),
918
+ priority: safeString(todo.priority, ""),
919
+ }));
920
+ }
921
+ }
922
+ const activeSessionId = extractActiveSessionId(event);
923
+ if (activeSessionId) {
924
+ officeState.activeSessionId = activeSessionId;
925
+ officeState.lastActiveAt = Date.now();
926
+ }
927
+
928
+ upsertSession(event);
929
+ updateSessionStatus(event);
930
+
931
+ applySessionLifecycle(event);
932
+ const agentId = upsertAgentFromEvent(event);
933
+ updateBossMessage(event);
934
+ const parentId = extractParentId(event);
935
+ if (agentId && parentId) {
936
+ setInteraction(parentId, agentId);
937
+ }
938
+
939
+ broadcast({ type: "event", event });
940
+ broadcast({ type: "state", state: getStateSnapshot() });
941
+ res.status(202).json({ ok: true });
942
+ });
943
+
944
+ app.get("/health", (_req: any, res: any) => {
945
+ res.json({ ok: true });
946
+ });
947
+
948
+ wss.on("connection", (socket: any) => {
949
+ socket.send(JSON.stringify({ type: "state", state: getStateSnapshot() }));
950
+ });
951
+
952
+ const getLocalIp = () => {
953
+ const nets = os.networkInterfaces();
954
+ for (const name of Object.keys(nets)) {
955
+ for (const net of nets[name] || []) {
956
+ // Skip over non-IPv4 and internal (i.e. 127.0.0.1) addresses
957
+ if (net.family === "IPv4" && !net.internal) {
958
+ return net.address;
959
+ }
960
+ }
961
+ }
962
+ return "localhost";
963
+ };
964
+
965
+ server.listen(PORT, "0.0.0.0", () => {
966
+ const ip = getLocalIp();
967
+ officeState.networkIp = ip;
968
+ console.log(`Pixel Office Server Running:`);
969
+ console.log(` Local: http://localhost:${PORT}`);
970
+ console.log(` Network: http://${ip}:${PORT}`);
971
+ });