spora 0.7.9 → 0.7.10
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/dist/{autonomy-ZMFZRXDZ.js → autonomy-YBWBP6QJ.js} +2 -2
- package/dist/{chunk-TTDQZI5W.js → chunk-245JDXK4.js} +194 -18
- package/dist/chunk-245JDXK4.js.map +1 -0
- package/dist/chunk-NX7FJ4GH.js +91 -0
- package/dist/chunk-NX7FJ4GH.js.map +1 -0
- package/dist/cli.js +5 -5
- package/dist/{heartbeat-CUM7FIHS.js → heartbeat-BIGGV4LO.js} +3 -3
- package/dist/{heartbeat-narrative-B3RD3OPJ.js → heartbeat-narrative-UMLQ3WU7.js} +2 -2
- package/dist/{init-4SBU4H6F.js → init-S5ZKOU64.js} +3 -3
- package/dist/web-chat/chat.html +16 -8
- package/dist/{web-chat-YRQQB435.js → web-chat-PQ6FR6BJ.js} +13 -14
- package/dist/web-chat-PQ6FR6BJ.js.map +1 -0
- package/package.json +1 -1
- package/dist/chunk-OLYPPXKP.js +0 -69
- package/dist/chunk-OLYPPXKP.js.map +0 -1
- package/dist/chunk-TTDQZI5W.js.map +0 -1
- package/dist/web-chat-YRQQB435.js.map +0 -1
- /package/dist/{autonomy-ZMFZRXDZ.js.map → autonomy-YBWBP6QJ.js.map} +0 -0
- /package/dist/{heartbeat-CUM7FIHS.js.map → heartbeat-BIGGV4LO.js.map} +0 -0
- /package/dist/{heartbeat-narrative-B3RD3OPJ.js.map → heartbeat-narrative-UMLQ3WU7.js.map} +0 -0
- /package/dist/{init-4SBU4H6F.js.map → init-S5ZKOU64.js.map} +0 -0
package/dist/web-chat/chat.html
CHANGED
|
@@ -423,6 +423,7 @@
|
|
|
423
423
|
let agentPfp = null;
|
|
424
424
|
let sleepTimerId = null;
|
|
425
425
|
let heartbeatMs = 300000;
|
|
426
|
+
const HIDE_CLIENT_TEXT_RE = /(fail(?:ed|ure)?|error|unavailable|could not|cannot|can't)/i;
|
|
426
427
|
|
|
427
428
|
const HEARTBEAT_LABELS = {
|
|
428
429
|
60000: '1 min',
|
|
@@ -480,7 +481,7 @@
|
|
|
480
481
|
} catch {
|
|
481
482
|
heartbeatMs = previous;
|
|
482
483
|
updateHeartbeatOptions();
|
|
483
|
-
setLiveStatus('
|
|
484
|
+
setLiveStatus('heartbeat unchanged', 'action');
|
|
484
485
|
} finally {
|
|
485
486
|
heartbeatTrigger.disabled = false;
|
|
486
487
|
}
|
|
@@ -609,11 +610,13 @@
|
|
|
609
610
|
card.appendChild(time);
|
|
610
611
|
|
|
611
612
|
if (status) {
|
|
612
|
-
const statusEl = document.createElement('div');
|
|
613
613
|
const successLike = /posted|sent|queued|success/i.test(status);
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
614
|
+
if (successLike) {
|
|
615
|
+
const statusEl = document.createElement('div');
|
|
616
|
+
statusEl.className = 'tweet-card-status success';
|
|
617
|
+
statusEl.textContent = status;
|
|
618
|
+
card.appendChild(statusEl);
|
|
619
|
+
}
|
|
617
620
|
}
|
|
618
621
|
|
|
619
622
|
chatContainer.appendChild(card);
|
|
@@ -631,6 +634,7 @@
|
|
|
631
634
|
clearLiveStatus();
|
|
632
635
|
return;
|
|
633
636
|
}
|
|
637
|
+
if (HIDE_CLIENT_TEXT_RE.test(text)) return;
|
|
634
638
|
removeSleepCard();
|
|
635
639
|
let el = document.getElementById('liveStatus');
|
|
636
640
|
if (!el) {
|
|
@@ -724,11 +728,11 @@
|
|
|
724
728
|
if (data.response) {
|
|
725
729
|
addMessage('assistant', data.response);
|
|
726
730
|
} else {
|
|
727
|
-
addMessage('assistant', '
|
|
731
|
+
addMessage('assistant', 'Try that once more.');
|
|
728
732
|
}
|
|
729
733
|
} catch (error) {
|
|
730
734
|
hideLoading();
|
|
731
|
-
addMessage('assistant', '
|
|
735
|
+
addMessage('assistant', 'Connection dropped. Try once more.');
|
|
732
736
|
} finally {
|
|
733
737
|
isLoading = false;
|
|
734
738
|
sendButton.disabled = false;
|
|
@@ -790,6 +794,10 @@
|
|
|
790
794
|
}
|
|
791
795
|
|
|
792
796
|
function renderAgentEvent(event) {
|
|
797
|
+
if ((event.type === 'narration' || event.type === 'action' || event.type === 'summary' || event.type === 'wake') &&
|
|
798
|
+
HIDE_CLIENT_TEXT_RE.test(event.content || '')) {
|
|
799
|
+
return;
|
|
800
|
+
}
|
|
793
801
|
switch (event.type) {
|
|
794
802
|
case 'narration':
|
|
795
803
|
setLiveStatus(event.content);
|
|
@@ -804,7 +812,7 @@
|
|
|
804
812
|
setLiveStatus(event.content, 'action');
|
|
805
813
|
break;
|
|
806
814
|
case 'error':
|
|
807
|
-
|
|
815
|
+
// Hidden by design in client chat view.
|
|
808
816
|
break;
|
|
809
817
|
case 'sleep':
|
|
810
818
|
clearLiveStatus();
|
|
@@ -42,7 +42,16 @@ var WebChatServer = class {
|
|
|
42
42
|
}
|
|
43
43
|
/** Push an event into the chat stream (narration, tweet card, sleep state, etc.) */
|
|
44
44
|
pushAgentEvent(type, content, meta) {
|
|
45
|
-
|
|
45
|
+
if (type === "error") return;
|
|
46
|
+
const hiddenPattern = /(fail(?:ed|ure)?|error|unavailable|could not|cannot|can't)/i;
|
|
47
|
+
if (["narration", "action", "summary", "wake"].includes(type) && hiddenPattern.test(content)) return;
|
|
48
|
+
const safeContent = (content ?? "").trim();
|
|
49
|
+
if (!safeContent) return;
|
|
50
|
+
const safeMeta = meta ? { ...meta } : void 0;
|
|
51
|
+
if (safeMeta && typeof safeMeta.status === "string" && hiddenPattern.test(safeMeta.status)) {
|
|
52
|
+
delete safeMeta.status;
|
|
53
|
+
}
|
|
54
|
+
this.agentEvents.push({ type, content: safeContent, timestamp: Date.now(), meta: safeMeta });
|
|
46
55
|
if (this.agentEvents.length > 200) {
|
|
47
56
|
this.agentEvents = this.agentEvents.slice(-200);
|
|
48
57
|
}
|
|
@@ -382,8 +391,8 @@ async function logChatInteraction(userMessage, agentResponse) {
|
|
|
382
391
|
async function runNarratedHeartbeat(server) {
|
|
383
392
|
const { loadConfig } = await import("./config-MU2ODEO3.js");
|
|
384
393
|
const { flushQueue } = await import("./queue-YPBUUP22.js");
|
|
385
|
-
const { runAutonomyCycle } = await import("./autonomy-
|
|
386
|
-
const { buildHeartbeatNarrative, saveHeartbeatNarrative } = await import("./heartbeat-narrative-
|
|
394
|
+
const { runAutonomyCycle } = await import("./autonomy-YBWBP6QJ.js");
|
|
395
|
+
const { buildHeartbeatNarrative, saveHeartbeatNarrative } = await import("./heartbeat-narrative-UMLQ3WU7.js");
|
|
387
396
|
const { buildReflectionPrompt } = await import("./prompt-builder-S6PJVEC5.js");
|
|
388
397
|
const { generateResponse } = await import("./llm-IJBRQ7O2.js");
|
|
389
398
|
const { addLearning } = await import("./memory-G4DNIGLT.js");
|
|
@@ -481,15 +490,6 @@ async function runNarratedHeartbeat(server) {
|
|
|
481
490
|
}
|
|
482
491
|
console.log(chalk.green(` [Agent] \u2713 ${result.action}`));
|
|
483
492
|
} else {
|
|
484
|
-
if ((action.action === "post" || action.action === "reply") && action.content) {
|
|
485
|
-
server.pushAgentEvent("tweet", action.content, {
|
|
486
|
-
kind: action.action === "reply" ? "Reply" : "Post",
|
|
487
|
-
status: `Failed: ${result.error}`,
|
|
488
|
-
replyTo: action.action === "reply" ? action.tweetId : void 0
|
|
489
|
-
});
|
|
490
|
-
} else {
|
|
491
|
-
server.pushAgentEvent("error", `${result.action} failed`);
|
|
492
|
-
}
|
|
493
493
|
console.log(chalk.red(` [Agent] \u2717 ${result.action}: ${result.error}`));
|
|
494
494
|
}
|
|
495
495
|
}
|
|
@@ -526,7 +526,6 @@ async function runNarratedHeartbeat(server) {
|
|
|
526
526
|
} catch (error) {
|
|
527
527
|
const msg = error.message;
|
|
528
528
|
console.error(chalk.red(` [Agent] Heartbeat #${heartbeatCount} error: ${msg}`));
|
|
529
|
-
server.pushAgentEvent("error", `Something went wrong: ${msg}`);
|
|
530
529
|
}
|
|
531
530
|
}
|
|
532
531
|
}
|
|
@@ -648,4 +647,4 @@ export {
|
|
|
648
647
|
openBrowser,
|
|
649
648
|
startWebChat
|
|
650
649
|
};
|
|
651
|
-
//# sourceMappingURL=web-chat-
|
|
650
|
+
//# sourceMappingURL=web-chat-PQ6FR6BJ.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/web-chat/server.ts","../src/web-chat/index.ts"],"sourcesContent":["/**\n * Local web chat server\n * Serves a simple chat interface for interacting with your Spore\n */\n\nimport http from \"node:http\";\nimport { URL } from \"node:url\";\nimport { readFileSync, existsSync } from \"node:fs\";\nimport { join, dirname } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\n\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = dirname(__filename);\n\ninterface ChatMessage {\n role: \"user\" | \"assistant\";\n content: string;\n timestamp: number;\n}\n\ninterface AgentActivity {\n type: \"heartbeat\" | \"action\" | \"status\";\n message: string;\n timestamp: number;\n}\n\n/** Messages pushed from the heartbeat into the chat UI */\nexport interface AgentChatEvent {\n type: \"narration\" | \"tweet\" | \"action\" | \"sleep\" | \"wake\" | \"error\" | \"summary\";\n content: string;\n timestamp: number;\n meta?: Record<string, unknown>;\n}\n\ninterface AgentIdentity {\n name: string;\n handle: string;\n bio?: string;\n profileImage?: string;\n}\n\ninterface HeartbeatConfigHandlers {\n getIntervalMs: () => number | Promise<number>;\n setIntervalMs: (intervalMs: number) => void | Promise<void>;\n}\n\nconst ALLOWED_HEARTBEAT_INTERVALS = [60_000, 300_000, 1_800_000, 3_600_000, 21_600_000] as const;\n\nexport class WebChatServer {\n private server: http.Server | null = null;\n private port: number;\n private messages: ChatMessage[] = [];\n private activities: AgentActivity[] = [];\n private agentEvents: AgentChatEvent[] = [];\n private onUserMessage?: (message: string) => Promise<string>;\n private identity?: AgentIdentity;\n private heartbeatConfigHandlers?: HeartbeatConfigHandlers;\n\n constructor(port = 3737) {\n this.port = port;\n }\n\n setIdentity(identity: AgentIdentity) {\n this.identity = identity;\n }\n\n setMessageHandler(handler: (message: string) => Promise<string>) {\n this.onUserMessage = handler;\n }\n\n setHeartbeatConfigHandlers(handlers: HeartbeatConfigHandlers) {\n this.heartbeatConfigHandlers = handlers;\n }\n\n /** Push an activity update (from heartbeat) to the UI — kept for backwards compat */\n pushActivity(type: AgentActivity[\"type\"], message: string) {\n this.activities.push({ type, message, timestamp: Date.now() });\n if (this.activities.length > 100) {\n this.activities = this.activities.slice(-100);\n }\n }\n\n /** Push an event into the chat stream (narration, tweet card, sleep state, etc.) */\n pushAgentEvent(type: AgentChatEvent[\"type\"], content: string, meta?: Record<string, unknown>) {\n // UI policy: never expose failure/error/unavailable messaging to end users in local chat.\n if (type === \"error\") return;\n const hiddenPattern = /(fail(?:ed|ure)?|error|unavailable|could not|cannot|can't)/i;\n if ([\"narration\", \"action\", \"summary\", \"wake\"].includes(type) && hiddenPattern.test(content)) return;\n\n const safeContent = (content ?? \"\").trim();\n if (!safeContent) return;\n\n const safeMeta: Record<string, unknown> | undefined = meta ? { ...meta } : undefined;\n if (safeMeta && typeof safeMeta.status === \"string\" && hiddenPattern.test(safeMeta.status)) {\n delete safeMeta.status;\n }\n\n this.agentEvents.push({ type, content: safeContent, timestamp: Date.now(), meta: safeMeta });\n if (this.agentEvents.length > 200) {\n this.agentEvents = this.agentEvents.slice(-200);\n }\n }\n\n async start(): Promise<string> {\n return new Promise((resolve, reject) => {\n this.server = http.createServer(async (req, res) => {\n const url = new URL(req.url || \"/\", `http://${req.headers.host}`);\n\n // CORS headers\n res.setHeader(\"Access-Control-Allow-Origin\", \"*\");\n res.setHeader(\"Access-Control-Allow-Methods\", \"GET, POST, OPTIONS\");\n res.setHeader(\"Access-Control-Allow-Headers\", \"Content-Type\");\n\n if (req.method === \"OPTIONS\") {\n res.writeHead(200);\n res.end();\n return;\n }\n\n // Serve HTML\n if (url.pathname === \"/\" || url.pathname === \"/index.html\") {\n try {\n const possiblePaths = [\n join(__dirname, \"web-chat\", \"chat.html\"),\n join(__dirname, \"chat.html\"),\n join(__dirname, \"..\", \"web-chat\", \"chat.html\"),\n join(__dirname, \"..\", \"src\", \"web-chat\", \"chat.html\"),\n ];\n\n let html: string | null = null;\n for (const p of possiblePaths) {\n try {\n html = readFileSync(p, \"utf-8\");\n break;\n } catch {\n continue;\n }\n }\n\n if (html) {\n res.writeHead(200, { \"Content-Type\": \"text/html\" });\n res.end(html);\n } else {\n console.error(\"Could not find chat.html in any of:\", possiblePaths);\n res.writeHead(500);\n res.end(\"Error: Could not find chat.html\");\n }\n } catch (error) {\n res.writeHead(500);\n res.end(\"Error loading chat interface\");\n }\n return;\n }\n\n // API: Get agent identity\n if (url.pathname === \"/api/identity\" && req.method === \"GET\") {\n res.writeHead(200, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify({ identity: this.identity || null }));\n return;\n }\n\n // Static: logo asset for chat header\n if (url.pathname === \"/logo2.png\" && req.method === \"GET\") {\n const logoPaths = [\n join(__dirname, \"web-chat\", \"logo2.png\"),\n join(__dirname, \"..\", \"web-chat\", \"logo2.png\"),\n join(process.cwd(), \"dist\", \"web-chat\", \"logo2.png\"),\n join(process.cwd(), \"logo2.png\"),\n ];\n const logoPath = logoPaths.find((p) => existsSync(p));\n if (!logoPath) {\n res.writeHead(404);\n res.end(\"Not found\");\n return;\n }\n res.writeHead(200, {\n \"Content-Type\": \"image/png\",\n \"Cache-Control\": \"public, max-age=300\",\n });\n res.end(readFileSync(logoPath));\n return;\n }\n\n // API: Get messages\n if (url.pathname === \"/api/messages\" && req.method === \"GET\") {\n res.writeHead(200, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify({ messages: this.messages }));\n return;\n }\n\n // API: Get agent activity feed (legacy, kept for compat)\n if (url.pathname === \"/api/activity\" && req.method === \"GET\") {\n const since = parseInt(url.searchParams.get(\"since\") || \"0\", 10);\n const newActivities = this.activities.filter((a) => a.timestamp > since);\n res.writeHead(200, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify({ activities: newActivities }));\n return;\n }\n\n // API: Get agent events (narration, tweets, sleep) — polled by chat UI\n if (url.pathname === \"/api/agent-events\" && req.method === \"GET\") {\n const since = parseInt(url.searchParams.get(\"since\") || \"0\", 10);\n const newEvents = this.agentEvents.filter((e) => e.timestamp > since);\n res.writeHead(200, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify({ events: newEvents }));\n return;\n }\n\n // API: Read heartbeat interval config\n if (url.pathname === \"/api/heartbeat-config\" && req.method === \"GET\") {\n if (!this.heartbeatConfigHandlers) {\n res.writeHead(503, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify({ error: \"Heartbeat config unavailable\" }));\n return;\n }\n\n try {\n const intervalMs = await this.heartbeatConfigHandlers.getIntervalMs();\n res.writeHead(200, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify({ intervalMs, allowedIntervals: ALLOWED_HEARTBEAT_INTERVALS }));\n } catch {\n res.writeHead(500, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify({ error: \"Failed to load heartbeat config\" }));\n }\n return;\n }\n\n // API: Update heartbeat interval config\n if (url.pathname === \"/api/heartbeat-config\" && req.method === \"POST\") {\n if (!this.heartbeatConfigHandlers) {\n res.writeHead(503, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify({ error: \"Heartbeat config unavailable\" }));\n return;\n }\n const handlers = this.heartbeatConfigHandlers;\n\n let body = \"\";\n req.on(\"data\", (chunk) => {\n body += chunk.toString();\n });\n\n req.on(\"end\", async () => {\n try {\n const parsed = JSON.parse(body) as { intervalMs?: number };\n const intervalMs = parsed.intervalMs;\n\n if (\n typeof intervalMs !== \"number\" ||\n !Number.isInteger(intervalMs) ||\n !ALLOWED_HEARTBEAT_INTERVALS.includes(intervalMs as (typeof ALLOWED_HEARTBEAT_INTERVALS)[number])\n ) {\n res.writeHead(400, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify({ error: \"Unsupported heartbeat interval\" }));\n return;\n }\n\n await handlers.setIntervalMs(intervalMs);\n res.writeHead(200, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify({ success: true, intervalMs }));\n } catch {\n res.writeHead(400, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify({ error: \"Invalid request\" }));\n }\n });\n return;\n }\n\n // API: Send message\n if (url.pathname === \"/api/message\" && req.method === \"POST\") {\n let body = \"\";\n req.on(\"data\", (chunk) => {\n body += chunk.toString();\n });\n\n req.on(\"end\", async () => {\n try {\n const { message } = JSON.parse(body);\n\n // Add user message\n this.messages.push({\n role: \"user\",\n content: message,\n timestamp: Date.now(),\n });\n\n // Get response\n if (this.onUserMessage) {\n const response = await this.onUserMessage(message);\n this.messages.push({\n role: \"assistant\",\n content: response,\n timestamp: Date.now(),\n });\n res.writeHead(200, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify({ success: true, response }));\n } else {\n res.writeHead(500, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify({ error: \"No message handler configured\" }));\n }\n } catch (error) {\n res.writeHead(400, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify({ error: \"Invalid request\" }));\n }\n });\n return;\n }\n\n // 404\n res.writeHead(404);\n res.end(\"Not found\");\n });\n\n this.server.listen(this.port, () => {\n const url = `http://localhost:${this.port}`;\n resolve(url);\n });\n\n this.server.on(\"error\", (error: NodeJS.ErrnoException) => {\n if (error.code === \"EADDRINUSE\") {\n this.port++;\n this.server?.close();\n this.start().then(resolve).catch(reject);\n } else {\n reject(error);\n }\n });\n });\n }\n\n stop() {\n if (this.server) {\n this.server.close();\n this.server = null;\n }\n }\n}\n","/**\n * Web chat integration with autonomous heartbeat\n */\n\nimport { WebChatServer } from \"./server.js\";\nimport { loadIdentity } from \"../identity/index.js\";\nimport { execSync } from \"node:child_process\";\nimport chalk from \"chalk\";\n\nconst HEARTBEAT_INTERVAL_OPTIONS = [60_000, 300_000, 1_800_000, 3_600_000, 21_600_000] as const;\n\nfunction formatHeartbeatInterval(intervalMs: number): string {\n const minutes = intervalMs / 60_000;\n if (minutes < 60) return `${minutes} minute${minutes === 1 ? \"\" : \"s\"}`;\n const hours = minutes / 60;\n return `${hours} hour${hours === 1 ? \"\" : \"s\"}`;\n}\n\n/**\n * Extract <<LEARN: ...>> tags from response, save them, and return cleaned text\n */\nasync function extractAndSaveLearnings(responseText: string): Promise<string> {\n const learnPattern = /<<LEARN:\\s*(.+?)>>/g;\n const matches = [...responseText.matchAll(learnPattern)];\n\n if (matches.length > 0) {\n const { addLearning } = await import(\"../memory/index.js\");\n for (const match of matches) {\n const learning = match[1].trim();\n addLearning(learning, \"web-chat\", [\"chat\", \"creator-interaction\"]);\n console.log(chalk.dim(` [Memory] Saved learning: ${learning}`));\n }\n }\n\n // Strip the learn tags from the response the user sees\n return responseText.replace(/<<LEARN:\\s*.+?>>/g, \"\").trim();\n}\n\n/**\n * Extract <<TRAINING:{json}>> tags from response, apply updates to identity/strategy/goals, and return cleaned text\n */\nasync function extractAndApplyTraining(responseText: string): Promise<string> {\n const trainingPattern = /<<TRAINING:([\\s\\S]*?)>>/g;\n const matches = [...responseText.matchAll(trainingPattern)];\n\n for (const match of matches) {\n try {\n const update = JSON.parse(match[1].trim());\n\n // Apply identity changes\n if (update.identity) {\n const { loadIdentity, mutateIdentity, saveIdentity } = await import(\"../identity/index.js\");\n let identity = loadIdentity();\n\n const identityFields: Record<string, string> = {\n tone: \"tone\",\n worldview: \"worldview\",\n conflictStyle: \"conflictStyle\",\n vocabularyStyle: \"vocabularyStyle\",\n tweetStyle: \"tweetStyle\",\n };\n\n // Simple string/enum fields\n for (const [key, field] of Object.entries(identityFields)) {\n if (update.identity[key] !== undefined) {\n identity = mutateIdentity(identity, field, update.identity[key], \"training-chat\");\n console.log(chalk.dim(` [Training] Updated ${field}`));\n }\n }\n\n // Array fields (replace entire array)\n const arrayFields = [\"coreValues\", \"topics\", \"avoidTopics\", \"goals\", \"boundaries\", \"catchphrases\", \"heroes\"];\n for (const field of arrayFields) {\n if (update.identity[field] !== undefined && Array.isArray(update.identity[field])) {\n identity = mutateIdentity(identity, field, update.identity[field], \"training-chat\");\n console.log(chalk.dim(` [Training] Updated ${field}`));\n }\n }\n\n // Traits (merge, don't replace)\n if (update.identity.traits && typeof update.identity.traits === \"object\") {\n for (const [trait, value] of Object.entries(update.identity.traits)) {\n if (typeof value === \"number\" && value >= 0 && value <= 1) {\n identity = mutateIdentity(identity, `traits.${trait}`, value, \"training-chat\");\n console.log(chalk.dim(` [Training] Updated traits.${trait} = ${value}`));\n }\n }\n }\n\n // Engagement strategy (merge)\n if (update.identity.engagementStrategy && typeof update.identity.engagementStrategy === \"object\") {\n for (const [key, value] of Object.entries(update.identity.engagementStrategy)) {\n identity = mutateIdentity(identity, `engagementStrategy.${key}`, value, \"training-chat\");\n console.log(chalk.dim(` [Training] Updated engagementStrategy.${key}`));\n }\n }\n\n saveIdentity(identity);\n }\n\n // Apply strategy changes\n if (update.strategy) {\n const { loadStrategy, saveStrategy } = await import(\"../memory/strategy.js\");\n const strategy = loadStrategy();\n\n if (update.strategy.currentFocus) strategy.currentFocus = update.strategy.currentFocus;\n if (update.strategy.shortTermGoals) strategy.shortTermGoals = update.strategy.shortTermGoals;\n if (update.strategy.experiments) {\n strategy.experiments.push(...update.strategy.experiments);\n }\n if (update.strategy.peopleToEngage) {\n strategy.peopleToEngage.push(...update.strategy.peopleToEngage);\n }\n\n strategy.lastUpdated = new Date().toISOString();\n saveStrategy(strategy);\n console.log(chalk.dim(` [Training] Updated strategy`));\n }\n\n // Apply standalone learning\n if (update.learning) {\n const { addLearning } = await import(\"../memory/index.js\");\n addLearning(\n update.learning.content,\n \"training-chat\",\n update.learning.tags || [\"training\"],\n );\n console.log(chalk.dim(` [Training] Saved learning: ${update.learning.content}`));\n }\n\n // Apply reflection to evolution journal\n if (update.reflection) {\n const { loadIdentity, saveIdentity } = await import(\"../identity/index.js\");\n const identity = loadIdentity();\n identity.evolutionJournal.push({\n date: new Date().toISOString(),\n reflection: update.reflection,\n });\n saveIdentity(identity);\n console.log(chalk.dim(` [Training] Added reflection to evolution journal`));\n }\n\n // Apply goal updates\n if (update.goalUpdates && Array.isArray(update.goalUpdates)) {\n const { loadGoals, saveGoals } = await import(\"../memory/goals.js\");\n const tracker = loadGoals();\n\n for (const gu of update.goalUpdates) {\n const existing = tracker.goals.find((g: { goal: string }) => g.goal === gu.goal);\n if (existing) {\n existing.progress = gu.progress;\n existing.lastUpdated = new Date().toISOString();\n } else {\n tracker.goals.push({\n goal: gu.goal,\n progress: gu.progress,\n lastUpdated: new Date().toISOString(),\n });\n }\n }\n\n tracker.lastReviewed = new Date().toISOString();\n saveGoals(tracker);\n console.log(chalk.dim(` [Training] Updated ${update.goalUpdates.length} goal(s)`));\n }\n\n } catch (err) {\n console.error(chalk.dim(` [Training] Failed to parse training update: ${(err as Error).message}`));\n }\n }\n\n // Strip the training tags from the response the user sees\n return responseText.replace(/<<TRAINING:[\\s\\S]*?>>/g, \"\").trim();\n}\n\n/**\n * Log a chat exchange as an interaction in memory\n */\nasync function logChatInteraction(userMessage: string, agentResponse: string): Promise<void> {\n const { logInteraction } = await import(\"../memory/index.js\");\n logInteraction({\n id: `chat-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`,\n timestamp: new Date().toISOString(),\n type: \"reply\",\n content: agentResponse.slice(0, 200),\n targetHandle: \"creator\",\n creditsUsed: 0,\n success: true,\n });\n}\n\n/**\n * Run the autonomous heartbeat in the background, narrating to the chat UI\n */\nasync function runNarratedHeartbeat(server: WebChatServer): Promise<void> {\n const { loadConfig } = await import(\"../utils/config.js\");\n const { flushQueue } = await import(\"../scheduler/queue.js\");\n const { runAutonomyCycle } = await import(\"../runtime/autonomy.js\");\n const { buildHeartbeatNarrative, saveHeartbeatNarrative } = await import(\"../runtime/heartbeat-narrative.js\");\n const { buildReflectionPrompt } = await import(\"../runtime/prompt-builder.js\");\n const { generateResponse } = await import(\"../runtime/llm.js\");\n const { addLearning } = await import(\"../memory/index.js\");\n const { loadStrategy, saveStrategy, applyStrategyUpdate } = await import(\"../memory/strategy.js\");\n\n let heartbeatCount = 0;\n let lastIntervalMs = loadConfig().runtime?.heartbeatIntervalMs ?? 300_000;\n\n console.log(chalk.cyan(` [Agent] Autonomous heartbeat started (every ${Math.round(lastIntervalMs / 60_000)} min)`));\n\n while (true) {\n const runtimeConfig = loadConfig();\n const intervalMs = runtimeConfig.runtime?.heartbeatIntervalMs ?? 300_000;\n const maxActions = runtimeConfig.runtime?.actionsPerHeartbeat ?? 4;\n\n if (intervalMs !== lastIntervalMs) {\n server.pushAgentEvent(\"narration\", `heartbeat set to ${formatHeartbeatInterval(intervalMs)}`);\n console.log(chalk.cyan(` [Agent] Heartbeat interval updated to ${Math.round(intervalMs / 60_000)} min`));\n lastIntervalMs = intervalMs;\n }\n\n // Sleep first, then heartbeat\n const jitter = Math.floor(Math.random() * intervalMs * 0.3);\n const sleepMs = heartbeatCount === 0 ? 10_000 : intervalMs + jitter;\n const wakeUpAt = Date.now() + sleepMs;\n\n // Show sleep state in chat (skip for first quick boot)\n if (heartbeatCount > 0) {\n server.pushAgentEvent(\"sleep\", \"sleeping\", { wakeUpAt });\n }\n\n // Sleep in short chunks so heartbeat interval changes apply immediately.\n let sleptMs = 0;\n let intervalChangedDuringSleep = false;\n while (sleptMs < sleepMs) {\n const chunkMs = Math.min(1000, sleepMs - sleptMs);\n await new Promise((r) => setTimeout(r, chunkMs));\n sleptMs += chunkMs;\n\n const liveIntervalMs = loadConfig().runtime?.heartbeatIntervalMs ?? 300_000;\n if (liveIntervalMs !== intervalMs) {\n intervalChangedDuringSleep = true;\n break;\n }\n }\n\n if (intervalChangedDuringSleep) {\n continue;\n }\n\n heartbeatCount++;\n console.log(chalk.cyan(` [Agent] Heartbeat #${heartbeatCount}`));\n server.pushAgentEvent(\"wake\", `heartbeat #${heartbeatCount}`);\n\n try {\n // 1. Flush queue\n try {\n const flushed = await flushQueue();\n if (flushed.posted > 0) {\n server.pushAgentEvent(\"action\", `Flushed ${flushed.posted} queued post(s)`);\n }\n } catch {\n // Queue flush is best-effort\n }\n\n // 2. Run tool-driven autonomy cycle\n server.pushAgentEvent(\"narration\", \"scanning timeline...\");\n const cycle = await runAutonomyCycle(maxActions, heartbeatCount);\n const narrative = buildHeartbeatNarrative({\n heartbeatCount,\n timelineCount: cycle.timeline.length,\n mentionsCount: cycle.mentions.length,\n actions: cycle.actions,\n results: cycle.results,\n });\n saveHeartbeatNarrative(\n narrative.summary,\n cycle.results.length === 0 ? true : cycle.results.every((r) => r.success),\n );\n server.pushAgentEvent(\"summary\", narrative.summary);\n\n if (cycle.timeline.length > 0 || cycle.mentions.length > 0) {\n server.pushAgentEvent(\"narration\", `found ${cycle.timeline.length} timeline, ${cycle.mentions.length} mentions`);\n }\n\n if (cycle.actions.length === 0) {\n server.pushAgentEvent(\"narration\", \"no actions, sleeping\");\n console.log(chalk.dim(` [Agent] No actions this heartbeat`));\n continue;\n }\n\n // 3. Report results — push tweet cards for posts, narration for everything else\n for (let i = 0; i < cycle.results.length; i++) {\n const result = cycle.results[i];\n const action = cycle.actions[i];\n if (!action) continue;\n\n if (result.success) {\n if (action.action === \"post\" && action.content) {\n server.pushAgentEvent(\"tweet\", action.content, { kind: \"Post\", status: \"Posted to X\", tweetId: result.detail });\n } else if (action.action === \"reply\" && action.content) {\n server.pushAgentEvent(\"tweet\", action.content, {\n kind: \"Reply\",\n status: \"Reply sent\",\n tweetId: result.detail,\n replyTo: action.tweetId,\n });\n } else if (action.action === \"like\") {\n server.pushAgentEvent(\"action\", \"liked a tweet\");\n } else if (action.action === \"retweet\") {\n server.pushAgentEvent(\"action\", \"retweeted\");\n } else if (action.action === \"follow\") {\n server.pushAgentEvent(\"action\", `followed @${action.handle}`);\n } else if (action.action === \"schedule\" && action.content) {\n server.pushAgentEvent(\"tweet\", action.content, { kind: \"Scheduled\", status: \"Queued\" });\n } else {\n server.pushAgentEvent(\"action\", `${action.action}${result.detail ? ` ${String(result.detail).slice(0, 40)}` : \"\"}`);\n }\n console.log(chalk.green(` [Agent] ✓ ${result.action}`));\n } else {\n // Keep failure details out of local client chat UI; logs still capture failures.\n console.log(chalk.red(` [Agent] ✗ ${result.action}: ${result.error}`));\n }\n }\n\n // Reflection phase — every 3rd heartbeat, review performance\n if (heartbeatCount % 3 === 0) {\n try {\n server.pushAgentEvent(\"narration\", \"reflecting...\");\n const reflectionPrompt = buildReflectionPrompt(cycle.results);\n const reflectionResponse = await generateResponse(\n `You are ${loadIdentity().name}. Reflect honestly on your performance.`,\n reflectionPrompt,\n );\n\n // Parse reflection JSON\n const jsonMatch = reflectionResponse.content.match(/\\{[\\s\\S]*\\}/);\n if (jsonMatch) {\n try {\n const reflection = JSON.parse(jsonMatch[0]);\n if (reflection.learning && reflection.learning !== \"null\") {\n addLearning(reflection.learning, \"reflection\", [\"heartbeat\", \"performance\"]);\n server.pushAgentEvent(\"narration\", \"learned something new\");\n console.log(chalk.dim(` [Agent] Reflection learning: ${reflection.learning}`));\n }\n if (reflection.strategyUpdate && reflection.strategyUpdate !== \"null\") {\n const strategy = loadStrategy();\n saveStrategy(applyStrategyUpdate(strategy, reflection.strategyUpdate));\n server.pushAgentEvent(\"narration\", \"strategy updated\");\n console.log(chalk.dim(` [Agent] Strategy update: ${reflection.strategyUpdate}`));\n }\n } catch {\n // Couldn't parse reflection JSON, that's fine\n }\n }\n } catch (err) {\n console.log(chalk.dim(` [Agent] Reflection failed: ${(err as Error).message}`));\n }\n }\n\n } catch (error) {\n const msg = (error as Error).message;\n console.error(chalk.red(` [Agent] Heartbeat #${heartbeatCount} error: ${msg}`));\n }\n }\n}\n\nexport async function startWebChat() {\n const identity = loadIdentity();\n const { loadConfig: loadRuntimeConfig, saveConfig } = await import(\"../utils/config.js\");\n\n const server = new WebChatServer();\n\n // Pass identity to server so the chat UI can display it\n server.setIdentity({\n name: identity.name,\n handle: identity.handle,\n bio: identity.bio,\n profileImage: identity.profileImage,\n });\n\n server.setHeartbeatConfigHandlers({\n getIntervalMs: () => {\n const config = loadRuntimeConfig();\n return config.runtime?.heartbeatIntervalMs ?? 300_000;\n },\n setIntervalMs: (intervalMs) => {\n if (!HEARTBEAT_INTERVAL_OPTIONS.includes(intervalMs as (typeof HEARTBEAT_INTERVAL_OPTIONS)[number])) {\n throw new Error(\"Unsupported heartbeat interval.\");\n }\n\n const config = loadRuntimeConfig();\n config.runtime = {\n heartbeatIntervalMs: intervalMs,\n actionsPerHeartbeat: config.runtime?.actionsPerHeartbeat ?? 4,\n enabled: true,\n };\n saveConfig(config);\n server.pushAgentEvent(\"narration\", `Heartbeat interval set to ${formatHeartbeatInterval(intervalMs)}.`);\n },\n });\n\n // Set up message handler - connected to actual LLM with memory\n const chatHistory: Array<{ role: \"user\" | \"assistant\"; content: string }> = [];\n let systemPrompt: string | null = null;\n let messageCount = 0;\n\n server.setMessageHandler(async (message: string) => {\n try {\n // Build training prompt on first message, rebuild every 10 messages to refresh memory\n if (!systemPrompt || messageCount % 10 === 0) {\n const { buildTrainingChatPrompt } = await import(\"../runtime/prompt-builder.js\");\n systemPrompt = buildTrainingChatPrompt();\n }\n messageCount++;\n\n // Check for LLM key\n const { hasLLMKey, chat: chatLLM } = await import(\"../runtime/llm.js\");\n if (!hasLLMKey()) {\n return \"I can't respond right now - no API key configured. Run `spora llm set --provider <provider>` to set one up.\";\n }\n\n // Add user message to history\n chatHistory.push({ role: \"user\", content: message });\n\n // Call LLM with full conversation history\n const response = await chatLLM(systemPrompt, chatHistory);\n\n // Extract training updates and learnings from response\n const afterTraining = await extractAndApplyTraining(response.content);\n const cleanResponse = await extractAndSaveLearnings(afterTraining);\n\n // Add cleaned assistant response to history\n chatHistory.push({ role: \"assistant\", content: cleanResponse });\n\n // Log interaction to memory (async, don't block response)\n logChatInteraction(message, cleanResponse).catch((err) =>\n console.error(chalk.dim(\" [Memory] Failed to log interaction:\"), err)\n );\n\n return cleanResponse;\n } catch (error) {\n console.error(\"Chat error:\", error);\n return `Sorry, I ran into an issue: ${(error as Error).message}`;\n }\n });\n\n const url = await server.start();\n\n console.log(chalk.green(`\\n✓ Chat interface started at ${chalk.bold(url)}\\n`));\n console.log(chalk.dim(`Press Ctrl+C to stop the server\\n`));\n\n // Open browser\n openBrowser(url);\n\n // Start autonomous heartbeat in background\n try {\n const { hasLLMKey } = await import(\"../runtime/llm.js\");\n if (hasLLMKey()) {\n runNarratedHeartbeat(server).catch((err) => {\n console.error(chalk.red(`Heartbeat failed to start: ${err}`));\n });\n } else {\n console.log(chalk.yellow(\" [Agent] No LLM key — autonomous heartbeat disabled. Run `spora llm set --provider <provider>` to enable.\"));\n server.pushActivity(\"status\", \"No LLM API key configured. Autonomous mode disabled.\");\n }\n } catch (err) {\n console.error(chalk.red(`Heartbeat failed to start: ${err}`));\n }\n\n // Keep process alive\n process.on(\"SIGINT\", () => {\n console.log(chalk.yellow(\"\\n\\nStopping chat server...\"));\n server.stop();\n process.exit(0);\n });\n\n // Return the server instance for external control\n return server;\n}\n\n/**\n * Open URL in a separate browser window (app-like)\n */\nfunction openBrowser(url: string) {\n const platform = process.platform;\n\n try {\n if (platform === \"darwin\") {\n // Open as a standalone Chrome app window (smaller, separate from existing tabs)\n try {\n execSync(`open -na \"Google Chrome\" --args --app=\"${url}\" --window-size=500,700`, { stdio: \"ignore\" });\n } catch {\n // Fallback: try Chromium-based browsers, then default\n try {\n execSync(`open -na \"Brave Browser\" --args --app=\"${url}\" --window-size=500,700`, { stdio: \"ignore\" });\n } catch {\n execSync(`open \"${url}\"`, { stdio: \"ignore\" });\n }\n }\n } else if (platform === \"win32\") {\n try {\n execSync(`start chrome --app=\"${url}\" --window-size=500,700`, { stdio: \"ignore\" });\n } catch {\n execSync(`start \"\" \"${url}\"`, { stdio: \"ignore\" });\n }\n } else {\n // Linux\n try {\n execSync(`google-chrome --app=\"${url}\" --window-size=500,700`, { stdio: \"ignore\" });\n } catch {\n execSync(`xdg-open \"${url}\"`, { stdio: \"ignore\" });\n }\n }\n } catch (error) {\n // Browser couldn't be opened, that's okay\n console.log(chalk.dim(`(Couldn't open browser automatically - please visit ${url} manually)`));\n }\n}\n\nexport { openBrowser };\n"],"mappings":"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","names":["loadIdentity"]}
|
package/package.json
CHANGED
package/dist/chunk-OLYPPXKP.js
DELETED
|
@@ -1,69 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
logInteraction
|
|
3
|
-
} from "./chunk-6WBIVXOY.js";
|
|
4
|
-
|
|
5
|
-
// src/runtime/heartbeat-narrative.ts
|
|
6
|
-
function clip(text, max = 70) {
|
|
7
|
-
if (!text) return "";
|
|
8
|
-
const clean = text.replace(/\s+/g, " ").trim();
|
|
9
|
-
if (clean.length <= max) return clean;
|
|
10
|
-
return `${clean.slice(0, max - 3)}...`;
|
|
11
|
-
}
|
|
12
|
-
function actionLine(action, result) {
|
|
13
|
-
const outcome = result.success ? "ok" : "fail";
|
|
14
|
-
if (action.action === "post") {
|
|
15
|
-
return `${outcome} post "${clip(action.content)}"`;
|
|
16
|
-
}
|
|
17
|
-
if (action.action === "reply") {
|
|
18
|
-
return `${outcome} reply "${clip(action.content)}"${action.tweetId ? ` -> ${action.tweetId}` : ""}`;
|
|
19
|
-
}
|
|
20
|
-
if (action.action === "follow") {
|
|
21
|
-
return `${outcome} follow @${action.handle ?? "unknown"}`;
|
|
22
|
-
}
|
|
23
|
-
if (action.action === "like" || action.action === "retweet") {
|
|
24
|
-
return `${outcome} ${action.action}${action.tweetId ? ` ${action.tweetId}` : ""}`;
|
|
25
|
-
}
|
|
26
|
-
if (action.action === "skip") {
|
|
27
|
-
return `skip ${clip(action.reason ?? action.reasoning, 40)}`;
|
|
28
|
-
}
|
|
29
|
-
return `${outcome} ${action.action}`;
|
|
30
|
-
}
|
|
31
|
-
function buildHeartbeatNarrative(input) {
|
|
32
|
-
const { heartbeatCount, timelineCount, mentionsCount, actions, results } = input;
|
|
33
|
-
const successCount = results.filter((r) => r.success).length;
|
|
34
|
-
const details = [];
|
|
35
|
-
for (let i = 0; i < actions.length; i += 1) {
|
|
36
|
-
const action = actions[i];
|
|
37
|
-
const result = results[i];
|
|
38
|
-
if (!action || !result) continue;
|
|
39
|
-
details.push(actionLine(action, result));
|
|
40
|
-
}
|
|
41
|
-
if (actions.length === 0) {
|
|
42
|
-
return {
|
|
43
|
-
summary: `Heartbeat #${heartbeatCount}: scanned ${timelineCount} timeline + ${mentionsCount} mentions, took no actions.`,
|
|
44
|
-
details
|
|
45
|
-
};
|
|
46
|
-
}
|
|
47
|
-
const preview = details.slice(0, 3).join(" | ");
|
|
48
|
-
return {
|
|
49
|
-
summary: `Heartbeat #${heartbeatCount}: scanned ${timelineCount}/${mentionsCount}, executed ${actions.length} actions (${successCount} ok). ${preview}`,
|
|
50
|
-
details
|
|
51
|
-
};
|
|
52
|
-
}
|
|
53
|
-
function saveHeartbeatNarrative(narrative, success) {
|
|
54
|
-
logInteraction({
|
|
55
|
-
id: `heartbeat-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`,
|
|
56
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
57
|
-
type: "heartbeat",
|
|
58
|
-
content: narrative.slice(0, 500),
|
|
59
|
-
targetHandle: "self",
|
|
60
|
-
creditsUsed: 0,
|
|
61
|
-
success
|
|
62
|
-
});
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
export {
|
|
66
|
-
buildHeartbeatNarrative,
|
|
67
|
-
saveHeartbeatNarrative
|
|
68
|
-
};
|
|
69
|
-
//# sourceMappingURL=chunk-OLYPPXKP.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/runtime/heartbeat-narrative.ts"],"sourcesContent":["import { logInteraction } from \"../memory/index.js\";\nimport type { AgentAction, ActionResult } from \"./decision-engine.js\";\n\ninterface BuildHeartbeatNarrativeInput {\n heartbeatCount: number;\n timelineCount: number;\n mentionsCount: number;\n actions: AgentAction[];\n results: ActionResult[];\n}\n\nexport interface HeartbeatNarrative {\n summary: string;\n details: string[];\n}\n\nfunction clip(text: string | undefined, max: number = 70): string {\n if (!text) return \"\";\n const clean = text.replace(/\\s+/g, \" \").trim();\n if (clean.length <= max) return clean;\n return `${clean.slice(0, max - 3)}...`;\n}\n\nfunction actionLine(action: AgentAction, result: ActionResult): string {\n const outcome = result.success ? \"ok\" : \"fail\";\n if (action.action === \"post\") {\n return `${outcome} post \"${clip(action.content)}\"`;\n }\n if (action.action === \"reply\") {\n return `${outcome} reply \"${clip(action.content)}\"${action.tweetId ? ` -> ${action.tweetId}` : \"\"}`;\n }\n if (action.action === \"follow\") {\n return `${outcome} follow @${action.handle ?? \"unknown\"}`;\n }\n if (action.action === \"like\" || action.action === \"retweet\") {\n return `${outcome} ${action.action}${action.tweetId ? ` ${action.tweetId}` : \"\"}`;\n }\n if (action.action === \"skip\") {\n return `skip ${clip(action.reason ?? action.reasoning, 40)}`;\n }\n return `${outcome} ${action.action}`;\n}\n\nexport function buildHeartbeatNarrative(input: BuildHeartbeatNarrativeInput): HeartbeatNarrative {\n const { heartbeatCount, timelineCount, mentionsCount, actions, results } = input;\n const successCount = results.filter((r) => r.success).length;\n\n const details: string[] = [];\n for (let i = 0; i < actions.length; i += 1) {\n const action = actions[i];\n const result = results[i];\n if (!action || !result) continue;\n details.push(actionLine(action, result));\n }\n\n if (actions.length === 0) {\n return {\n summary: `Heartbeat #${heartbeatCount}: scanned ${timelineCount} timeline + ${mentionsCount} mentions, took no actions.`,\n details,\n };\n }\n\n const preview = details.slice(0, 3).join(\" | \");\n return {\n summary: `Heartbeat #${heartbeatCount}: scanned ${timelineCount}/${mentionsCount}, executed ${actions.length} actions (${successCount} ok). ${preview}`,\n details,\n };\n}\n\nexport function saveHeartbeatNarrative(narrative: string, success: boolean): void {\n logInteraction({\n id: `heartbeat-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`,\n timestamp: new Date().toISOString(),\n type: \"heartbeat\",\n content: narrative.slice(0, 500),\n targetHandle: \"self\",\n creditsUsed: 0,\n success,\n });\n}\n\n"],"mappings":";;;;;AAgBA,SAAS,KAAK,MAA0B,MAAc,IAAY;AAChE,MAAI,CAAC,KAAM,QAAO;AAClB,QAAM,QAAQ,KAAK,QAAQ,QAAQ,GAAG,EAAE,KAAK;AAC7C,MAAI,MAAM,UAAU,IAAK,QAAO;AAChC,SAAO,GAAG,MAAM,MAAM,GAAG,MAAM,CAAC,CAAC;AACnC;AAEA,SAAS,WAAW,QAAqB,QAA8B;AACrE,QAAM,UAAU,OAAO,UAAU,OAAO;AACxC,MAAI,OAAO,WAAW,QAAQ;AAC5B,WAAO,GAAG,OAAO,UAAU,KAAK,OAAO,OAAO,CAAC;AAAA,EACjD;AACA,MAAI,OAAO,WAAW,SAAS;AAC7B,WAAO,GAAG,OAAO,WAAW,KAAK,OAAO,OAAO,CAAC,IAAI,OAAO,UAAU,OAAO,OAAO,OAAO,KAAK,EAAE;AAAA,EACnG;AACA,MAAI,OAAO,WAAW,UAAU;AAC9B,WAAO,GAAG,OAAO,YAAY,OAAO,UAAU,SAAS;AAAA,EACzD;AACA,MAAI,OAAO,WAAW,UAAU,OAAO,WAAW,WAAW;AAC3D,WAAO,GAAG,OAAO,IAAI,OAAO,MAAM,GAAG,OAAO,UAAU,IAAI,OAAO,OAAO,KAAK,EAAE;AAAA,EACjF;AACA,MAAI,OAAO,WAAW,QAAQ;AAC5B,WAAO,QAAQ,KAAK,OAAO,UAAU,OAAO,WAAW,EAAE,CAAC;AAAA,EAC5D;AACA,SAAO,GAAG,OAAO,IAAI,OAAO,MAAM;AACpC;AAEO,SAAS,wBAAwB,OAAyD;AAC/F,QAAM,EAAE,gBAAgB,eAAe,eAAe,SAAS,QAAQ,IAAI;AAC3E,QAAM,eAAe,QAAQ,OAAO,CAAC,MAAM,EAAE,OAAO,EAAE;AAEtD,QAAM,UAAoB,CAAC;AAC3B,WAAS,IAAI,GAAG,IAAI,QAAQ,QAAQ,KAAK,GAAG;AAC1C,UAAM,SAAS,QAAQ,CAAC;AACxB,UAAM,SAAS,QAAQ,CAAC;AACxB,QAAI,CAAC,UAAU,CAAC,OAAQ;AACxB,YAAQ,KAAK,WAAW,QAAQ,MAAM,CAAC;AAAA,EACzC;AAEA,MAAI,QAAQ,WAAW,GAAG;AACxB,WAAO;AAAA,MACL,SAAS,cAAc,cAAc,aAAa,aAAa,eAAe,aAAa;AAAA,MAC3F;AAAA,IACF;AAAA,EACF;AAEA,QAAM,UAAU,QAAQ,MAAM,GAAG,CAAC,EAAE,KAAK,KAAK;AAC9C,SAAO;AAAA,IACL,SAAS,cAAc,cAAc,aAAa,aAAa,IAAI,aAAa,cAAc,QAAQ,MAAM,aAAa,YAAY,SAAS,OAAO;AAAA,IACrJ;AAAA,EACF;AACF;AAEO,SAAS,uBAAuB,WAAmB,SAAwB;AAChF,iBAAe;AAAA,IACb,IAAI,aAAa,KAAK,IAAI,CAAC,IAAI,KAAK,OAAO,EAAE,SAAS,EAAE,EAAE,MAAM,GAAG,CAAC,CAAC;AAAA,IACrE,YAAW,oBAAI,KAAK,GAAE,YAAY;AAAA,IAClC,MAAM;AAAA,IACN,SAAS,UAAU,MAAM,GAAG,GAAG;AAAA,IAC/B,cAAc;AAAA,IACd,aAAa;AAAA,IACb;AAAA,EACF,CAAC;AACH;","names":[]}
|