spora 0.7.7 → 0.7.9
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-NNFTM5NW.js → autonomy-ZMFZRXDZ.js} +7 -7
- package/dist/{chunk-BBXHECZ5.js → chunk-6WBIVXOY.js} +1 -1
- package/dist/chunk-6WBIVXOY.js.map +1 -0
- package/dist/{chunk-JIMONWKO.js → chunk-73CWOI44.js} +4 -4
- package/dist/chunk-73CWOI44.js.map +1 -0
- package/dist/{chunk-ZLSDFYBR.js → chunk-AIGSCHZK.js} +2 -2
- package/dist/{chunk-CP6JWCLY.js → chunk-ER6TILYZ.js} +1 -25
- package/dist/{chunk-CP6JWCLY.js.map → chunk-ER6TILYZ.js.map} +1 -1
- package/dist/chunk-OLYPPXKP.js +69 -0
- package/dist/chunk-OLYPPXKP.js.map +1 -0
- package/dist/{chunk-5R4AJZHN.js → chunk-TKGB5LIN.js} +2 -2
- package/dist/chunk-TTDQZI5W.js +1699 -0
- package/dist/chunk-TTDQZI5W.js.map +1 -0
- package/dist/cli.js +28 -28
- package/dist/{client-AR5ZD6S4.js → client-3APKWQ6O.js} +3 -3
- package/dist/{colony-UGVYALOS.js → colony-7GZ2ODF2.js} +2 -2
- package/dist/{heartbeat-WJJSGUAQ.js → heartbeat-CUM7FIHS.js} +23 -7
- package/dist/heartbeat-CUM7FIHS.js.map +1 -0
- package/dist/heartbeat-narrative-B3RD3OPJ.js +11 -0
- package/dist/{init-6HY4ZPFJ.js → init-4SBU4H6F.js} +3 -3
- package/dist/mcp-server.js +20 -20
- package/dist/{memory-DTSLVSQG.js → memory-G4DNIGLT.js} +2 -2
- package/dist/{prompt-builder-ZFUZNQY2.js → prompt-builder-S6PJVEC5.js} +4 -4
- package/dist/{queue-QCGNDHH2.js → queue-YPBUUP22.js} +2 -2
- package/dist/web-chat/chat.html +64 -72
- package/dist/web-chat/logo2.png +0 -0
- package/dist/{web-chat-AKUEBSWS.js → web-chat-YRQQB435.js} +70 -31
- package/dist/web-chat-YRQQB435.js.map +1 -0
- package/dist/{x-client-S2LUVEKV.js → x-client-2HFEHHVE.js} +2 -2
- package/dist/x-client-2HFEHHVE.js.map +1 -0
- package/package.json +1 -1
- package/dist/chunk-BBXHECZ5.js.map +0 -1
- package/dist/chunk-JIMONWKO.js.map +0 -1
- package/dist/chunk-TTM54LQR.js +0 -2769
- package/dist/chunk-TTM54LQR.js.map +0 -1
- package/dist/heartbeat-WJJSGUAQ.js.map +0 -1
- package/dist/web-chat-AKUEBSWS.js.map +0 -1
- /package/dist/{autonomy-NNFTM5NW.js.map → autonomy-ZMFZRXDZ.js.map} +0 -0
- /package/dist/{chunk-ZLSDFYBR.js.map → chunk-AIGSCHZK.js.map} +0 -0
- /package/dist/{chunk-5R4AJZHN.js.map → chunk-TKGB5LIN.js.map} +0 -0
- /package/dist/{client-AR5ZD6S4.js.map → client-3APKWQ6O.js.map} +0 -0
- /package/dist/{colony-UGVYALOS.js.map → colony-7GZ2ODF2.js.map} +0 -0
- /package/dist/{memory-DTSLVSQG.js.map → heartbeat-narrative-B3RD3OPJ.js.map} +0 -0
- /package/dist/{init-6HY4ZPFJ.js.map → init-4SBU4H6F.js.map} +0 -0
- /package/dist/{prompt-builder-ZFUZNQY2.js.map → memory-G4DNIGLT.js.map} +0 -0
- /package/dist/{queue-QCGNDHH2.js.map → prompt-builder-S6PJVEC5.js.map} +0 -0
- /package/dist/{x-client-S2LUVEKV.js.map → queue-YPBUUP22.js.map} +0 -0
|
@@ -1,20 +1,24 @@
|
|
|
1
1
|
import {
|
|
2
2
|
runAutonomyCycle
|
|
3
|
-
} from "./chunk-
|
|
4
|
-
import "./chunk-
|
|
3
|
+
} from "./chunk-TTDQZI5W.js";
|
|
4
|
+
import "./chunk-TKGB5LIN.js";
|
|
5
5
|
import {
|
|
6
6
|
flushQueue
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-AIGSCHZK.js";
|
|
8
8
|
import {
|
|
9
9
|
buildReflectionPrompt
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-73CWOI44.js";
|
|
11
11
|
import {
|
|
12
12
|
applyStrategyUpdate,
|
|
13
13
|
loadStrategy,
|
|
14
14
|
saveStrategy
|
|
15
15
|
} from "./chunk-OTZNHIXT.js";
|
|
16
16
|
import "./chunk-CAWWG3MD.js";
|
|
17
|
-
import "./chunk-
|
|
17
|
+
import "./chunk-ER6TILYZ.js";
|
|
18
|
+
import {
|
|
19
|
+
buildHeartbeatNarrative,
|
|
20
|
+
saveHeartbeatNarrative
|
|
21
|
+
} from "./chunk-OLYPPXKP.js";
|
|
18
22
|
import {
|
|
19
23
|
loadIdentity
|
|
20
24
|
} from "./chunk-IULO3GRE.js";
|
|
@@ -30,7 +34,7 @@ import {
|
|
|
30
34
|
} from "./chunk-QYFNAGNI.js";
|
|
31
35
|
import {
|
|
32
36
|
addLearning
|
|
33
|
-
} from "./chunk-
|
|
37
|
+
} from "./chunk-6WBIVXOY.js";
|
|
34
38
|
import {
|
|
35
39
|
ensureDirectories,
|
|
36
40
|
paths
|
|
@@ -188,6 +192,18 @@ async function runHeartbeat(maxActions, heartbeatCount) {
|
|
|
188
192
|
logger.warn(`Queue flush failed: ${error.message}`);
|
|
189
193
|
}
|
|
190
194
|
const cycle = await runAutonomyCycle(maxActions, heartbeatCount);
|
|
195
|
+
const narrative = buildHeartbeatNarrative({
|
|
196
|
+
heartbeatCount,
|
|
197
|
+
timelineCount: cycle.timeline.length,
|
|
198
|
+
mentionsCount: cycle.mentions.length,
|
|
199
|
+
actions: cycle.actions,
|
|
200
|
+
results: cycle.results
|
|
201
|
+
});
|
|
202
|
+
saveHeartbeatNarrative(
|
|
203
|
+
narrative.summary,
|
|
204
|
+
cycle.results.length === 0 ? true : cycle.results.every((r) => r.success)
|
|
205
|
+
);
|
|
206
|
+
logger.info(`Narrative: ${narrative.summary}`);
|
|
191
207
|
logger.info(`Observed ${cycle.timeline.length} timeline posts and ${cycle.mentions.length} mentions.`);
|
|
192
208
|
if (cycle.actions.length === 0) {
|
|
193
209
|
logger.info("Planner returned no approved actions.");
|
|
@@ -250,4 +266,4 @@ export {
|
|
|
250
266
|
requestStop,
|
|
251
267
|
startHeartbeatLoop
|
|
252
268
|
};
|
|
253
|
-
//# sourceMappingURL=heartbeat-
|
|
269
|
+
//# sourceMappingURL=heartbeat-CUM7FIHS.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/runtime/heartbeat.ts","../src/runtime/telemetry.ts"],"sourcesContent":["import { existsSync, unlinkSync, writeFileSync, readFileSync } from \"node:fs\";\nimport { logger } from \"../utils/logger.js\";\nimport { loadConfig } from \"../utils/config.js\";\nimport { paths } from \"../utils/paths.js\";\nimport { flushQueue } from \"../scheduler/queue.js\";\nimport { runAutonomyCycle } from \"./autonomy.js\";\nimport { writeHeartbeatMetrics } from \"./telemetry.js\";\nimport { buildReflectionPrompt } from \"./prompt-builder.js\";\nimport { generateResponse } from \"./llm.js\";\nimport { addLearning } from \"../memory/index.js\";\nimport { applyStrategyUpdate, loadStrategy, saveStrategy } from \"../memory/strategy.js\";\nimport { loadIdentity } from \"../identity/index.js\";\nimport { buildHeartbeatNarrative, saveHeartbeatNarrative } from \"./heartbeat-narrative.js\";\n\nlet running = false;\n\nexport function isRunning(): boolean {\n return running;\n}\n\nexport function requestStop(): void {\n writeFileSync(paths.stopSignal, \"stop\");\n logger.info(\"Stop signal sent.\");\n}\n\nfunction shouldStop(): boolean {\n if (existsSync(paths.stopSignal)) {\n unlinkSync(paths.stopSignal);\n return true;\n }\n return false;\n}\n\nfunction writePid(): void {\n writeFileSync(paths.runtimePid, String(process.pid));\n}\n\nfunction clearPid(): void {\n if (existsSync(paths.runtimePid)) {\n unlinkSync(paths.runtimePid);\n }\n}\n\nexport function getRunningPid(): number | null {\n if (!existsSync(paths.runtimePid)) return null;\n const pid = parseInt(readFileSync(paths.runtimePid, \"utf-8\").trim(), 10);\n if (isNaN(pid)) return null;\n\n // Check if process is actually running\n try {\n process.kill(pid, 0);\n return pid;\n } catch {\n // Process not running, clean up stale PID\n clearPid();\n return null;\n }\n}\n\nexport async function startHeartbeatLoop(): Promise<void> {\n // Check if already running\n const existingPid = getRunningPid();\n if (existingPid) {\n throw new Error(`Spora is already running (PID ${existingPid}). Run \\`spora stop\\` first.`);\n }\n\n running = true;\n writePid();\n\n const config = loadConfig();\n const intervalMs = config.runtime?.heartbeatIntervalMs ?? 300_000;\n const maxActions = config.runtime?.actionsPerHeartbeat ?? 3;\n\n logger.info(`Spora agent starting. Heartbeat interval: ${intervalMs / 1000}s, max actions: ${maxActions}`);\n console.log(`\\nSpora agent is running (PID ${process.pid})`);\n console.log(`Heartbeat every ${Math.round(intervalMs / 60_000)} minutes`);\n console.log(`Press Ctrl+C or run \\`spora stop\\` to stop.\\n`);\n\n // Handle graceful shutdown\n const shutdown = () => {\n logger.info(\"Shutting down...\");\n running = false;\n clearPid();\n process.exit(0);\n };\n process.on(\"SIGINT\", shutdown);\n process.on(\"SIGTERM\", shutdown);\n\n // Clean any stale stop signal\n if (existsSync(paths.stopSignal)) {\n unlinkSync(paths.stopSignal);\n }\n\n let heartbeatCount = 0;\n\n while (running) {\n heartbeatCount++;\n logger.info(`=== Heartbeat #${heartbeatCount} ===`);\n\n try {\n await runHeartbeat(maxActions, heartbeatCount);\n } catch (error) {\n logger.error(\"Heartbeat error\", error);\n console.error(`Heartbeat #${heartbeatCount} failed: ${(error as Error).message}`);\n }\n\n // Check for stop signal\n if (shouldStop()) {\n logger.info(\"Stop signal received.\");\n break;\n }\n\n // Sleep with jitter\n const jitter = Math.floor(Math.random() * intervalMs * 0.3);\n const sleepMs = intervalMs + jitter;\n logger.info(`Sleeping ${Math.round(sleepMs / 1000)}s until next heartbeat...`);\n\n // Sleep in chunks so we can check for stop signals\n const chunkMs = 10_000;\n let slept = 0;\n while (slept < sleepMs && running) {\n await new Promise((r) => setTimeout(r, Math.min(chunkMs, sleepMs - slept)));\n slept += chunkMs;\n if (shouldStop()) {\n running = false;\n break;\n }\n }\n }\n\n clearPid();\n logger.info(\"Spora agent stopped.\");\n console.log(\"\\nSpora agent stopped.\");\n}\n\nasync function runHeartbeat(maxActions: number, heartbeatCount: number): Promise<void> {\n // 1. Flush any queued posts\n logger.info(\"Checking queue...\");\n try {\n const flushed = await flushQueue();\n if (flushed.posted > 0) {\n logger.info(`Flushed ${flushed.posted} queued posts.`);\n }\n } catch (error) {\n logger.warn(`Queue flush failed: ${(error as Error).message}`);\n }\n\n // 2. Run planner/executor cycle.\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 logger.info(`Narrative: ${narrative.summary}`);\n logger.info(`Observed ${cycle.timeline.length} timeline posts and ${cycle.mentions.length} mentions.`);\n\n if (cycle.actions.length === 0) {\n logger.info(\"Planner returned no approved actions.\");\n return;\n }\n\n logger.info(`Executed ${cycle.results.length} action(s).`);\n\n // 3. Log results\n for (const result of cycle.results) {\n if (result.success) {\n logger.info(` [OK] ${result.action}${result.detail ? `: ${result.detail}` : \"\"}`);\n } else {\n logger.warn(` [FAIL] ${result.action}: ${result.error}`);\n }\n }\n\n for (const note of cycle.policyFeedback) {\n logger.info(` [POLICY] ${note}`);\n }\n\n const metrics = writeHeartbeatMetrics({\n timelineCount: cycle.timeline.length,\n mentionsCount: cycle.mentions.length,\n actions: cycle.actions,\n results: cycle.results,\n policyFeedbackCount: cycle.policyFeedback.length,\n });\n logger.info(\n `Metrics: interactionRatio=${metrics.interactionRatio.toFixed(2)}, repeatedFormatRate=${metrics.repeatedFormatRate.toFixed(2)}`\n );\n\n logger.info(`Heartbeat complete. ${cycle.results.filter((r) => r.success).length}/${cycle.results.length} actions succeeded.`);\n\n // Reflection phase — every 3rd heartbeat\n if (heartbeatCount % 3 === 0) {\n try {\n logger.info(\"Running reflection phase...\");\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 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 logger.info(`Reflection learning: ${reflection.learning}`);\n }\n if (reflection.strategyUpdate && reflection.strategyUpdate !== \"null\") {\n const strategy = loadStrategy();\n saveStrategy(applyStrategyUpdate(strategy, reflection.strategyUpdate));\n logger.info(`Strategy update: ${reflection.strategyUpdate}`);\n }\n } catch {\n // Couldn't parse reflection JSON\n }\n }\n } catch (err) {\n logger.warn(`Reflection failed: ${(err as Error).message}`);\n }\n }\n}\n","import { appendFileSync } from \"node:fs\";\nimport { paths, ensureDirectories } from \"../utils/paths.js\";\nimport type { AgentAction, ActionResult } from \"./decision-engine.js\";\n\nexport interface HeartbeatMetrics {\n timestamp: string;\n timelineCount: number;\n mentionsCount: number;\n actionCount: number;\n successCount: number;\n postCount: number;\n interactionCount: number;\n interactionRatio: number;\n repeatedFormatRate: number;\n policyRejectionCount: number;\n}\n\nfunction normalize(text: string): string {\n return text.toLowerCase().replace(/[^a-z0-9\\s]/g, \" \").replace(/\\s+/g, \" \").trim();\n}\n\nfunction prefix(text: string, n = 6): string {\n return normalize(text).split(\" \").filter(Boolean).slice(0, n).join(\" \");\n}\n\nfunction repeatedFormatRate(actions: AgentAction[]): number {\n const posts = actions\n .filter((action) => action.action === \"post\" && action.content)\n .map((action) => action.content ?? \"\");\n\n if (posts.length <= 1) return 0;\n\n const seen = new Map<string, number>();\n for (const content of posts) {\n const key = prefix(content);\n seen.set(key, (seen.get(key) ?? 0) + 1);\n }\n\n let repeated = 0;\n for (const count of seen.values()) {\n if (count > 1) repeated += count;\n }\n\n return repeated / posts.length;\n}\n\nexport function writeHeartbeatMetrics(input: {\n timelineCount: number;\n mentionsCount: number;\n actions: AgentAction[];\n results: ActionResult[];\n policyFeedbackCount: number;\n}): HeartbeatMetrics {\n const interactionCount = input.actions.filter((a) => [\"reply\", \"like\", \"retweet\", \"follow\"].includes(a.action)).length;\n const postCount = input.actions.filter((a) => a.action === \"post\").length;\n const successCount = input.results.filter((r) => r.success).length;\n\n const metrics: HeartbeatMetrics = {\n timestamp: new Date().toISOString(),\n timelineCount: input.timelineCount,\n mentionsCount: input.mentionsCount,\n actionCount: input.actions.length,\n successCount,\n postCount,\n interactionCount,\n interactionRatio: input.actions.length > 0 ? interactionCount / input.actions.length : 0,\n repeatedFormatRate: repeatedFormatRate(input.actions),\n policyRejectionCount: input.policyFeedbackCount,\n };\n\n ensureDirectories();\n appendFileSync(paths.runtimeMetrics, JSON.stringify(metrics) + \"\\n\");\n return metrics;\n}\n"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import {
|
|
2
|
+
buildHeartbeatNarrative,
|
|
3
|
+
saveHeartbeatNarrative
|
|
4
|
+
} from "./chunk-OLYPPXKP.js";
|
|
5
|
+
import "./chunk-6WBIVXOY.js";
|
|
6
|
+
import "./chunk-ZWKTKWS6.js";
|
|
7
|
+
export {
|
|
8
|
+
buildHeartbeatNarrative,
|
|
9
|
+
saveHeartbeatNarrative
|
|
10
|
+
};
|
|
11
|
+
//# sourceMappingURL=heartbeat-narrative-B3RD3OPJ.js.map
|
|
@@ -276,7 +276,7 @@ async function loginFlow() {
|
|
|
276
276
|
console.log(chalk.green("\u2713 Logged in!\n"));
|
|
277
277
|
console.log(chalk.gray("Opening chat interface...\n"));
|
|
278
278
|
try {
|
|
279
|
-
const { startWebChat } = await import("./web-chat-
|
|
279
|
+
const { startWebChat } = await import("./web-chat-YRQQB435.js");
|
|
280
280
|
await startWebChat();
|
|
281
281
|
} catch (error) {
|
|
282
282
|
console.log(chalk.yellow(`Could not start chat interface: ${error.message}
|
|
@@ -368,7 +368,7 @@ async function showDoneAndOpenChat() {
|
|
|
368
368
|
console.log(chalk.bold.cyan("\u2501\u2501\u2501 Your Spore is Ready! \u2501\u2501\u2501\n"));
|
|
369
369
|
console.log(chalk.gray("Opening chat interface...\n"));
|
|
370
370
|
try {
|
|
371
|
-
const { startWebChat } = await import("./web-chat-
|
|
371
|
+
const { startWebChat } = await import("./web-chat-YRQQB435.js");
|
|
372
372
|
await startWebChat();
|
|
373
373
|
} catch (error) {
|
|
374
374
|
console.log(chalk.yellow(`Could not start chat interface: ${error.message}
|
|
@@ -506,4 +506,4 @@ async function runInit(token) {
|
|
|
506
506
|
export {
|
|
507
507
|
runInit
|
|
508
508
|
};
|
|
509
|
-
//# sourceMappingURL=init-
|
|
509
|
+
//# sourceMappingURL=init-4SBU4H6F.js.map
|
package/dist/mcp-server.js
CHANGED
|
@@ -21,7 +21,7 @@ import {
|
|
|
21
21
|
loadLearnings,
|
|
22
22
|
loadRelationships,
|
|
23
23
|
updateRelationship
|
|
24
|
-
} from "./chunk-
|
|
24
|
+
} from "./chunk-6WBIVXOY.js";
|
|
25
25
|
import "./chunk-ZWKTKWS6.js";
|
|
26
26
|
|
|
27
27
|
// src/mcp-server.ts
|
|
@@ -388,7 +388,7 @@ Identity saved. Your Spore is alive. Use spora_get_identity to read the full doc
|
|
|
388
388
|
},
|
|
389
389
|
async ({ content }) => {
|
|
390
390
|
try {
|
|
391
|
-
const { getXClient } = await import("./x-client-
|
|
391
|
+
const { getXClient } = await import("./x-client-2HFEHHVE.js");
|
|
392
392
|
const client = await getXClient();
|
|
393
393
|
const result = await client.postTweet(content);
|
|
394
394
|
return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
|
|
@@ -406,7 +406,7 @@ Identity saved. Your Spore is alive. Use spora_get_identity to read the full doc
|
|
|
406
406
|
},
|
|
407
407
|
async ({ tweetId, content }) => {
|
|
408
408
|
try {
|
|
409
|
-
const { getXClient } = await import("./x-client-
|
|
409
|
+
const { getXClient } = await import("./x-client-2HFEHHVE.js");
|
|
410
410
|
const client = await getXClient();
|
|
411
411
|
const result = await client.replyToTweet(tweetId, content);
|
|
412
412
|
return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
|
|
@@ -421,7 +421,7 @@ Identity saved. Your Spore is alive. Use spora_get_identity to read the full doc
|
|
|
421
421
|
{ tweetId: z.string().describe("The ID of the tweet to like") },
|
|
422
422
|
async ({ tweetId }) => {
|
|
423
423
|
try {
|
|
424
|
-
const { getXClient } = await import("./x-client-
|
|
424
|
+
const { getXClient } = await import("./x-client-2HFEHHVE.js");
|
|
425
425
|
const client = await getXClient();
|
|
426
426
|
const result = await client.likeTweet(tweetId);
|
|
427
427
|
return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
|
|
@@ -436,7 +436,7 @@ Identity saved. Your Spore is alive. Use spora_get_identity to read the full doc
|
|
|
436
436
|
{ tweetId: z.string().describe("The ID of the tweet to retweet") },
|
|
437
437
|
async ({ tweetId }) => {
|
|
438
438
|
try {
|
|
439
|
-
const { getXClient } = await import("./x-client-
|
|
439
|
+
const { getXClient } = await import("./x-client-2HFEHHVE.js");
|
|
440
440
|
const client = await getXClient();
|
|
441
441
|
const result = await client.retweet(tweetId);
|
|
442
442
|
return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
|
|
@@ -451,7 +451,7 @@ Identity saved. Your Spore is alive. Use spora_get_identity to read the full doc
|
|
|
451
451
|
{ userId: z.string().describe("The user ID or handle to follow") },
|
|
452
452
|
async ({ userId }) => {
|
|
453
453
|
try {
|
|
454
|
-
const { getXClient } = await import("./x-client-
|
|
454
|
+
const { getXClient } = await import("./x-client-2HFEHHVE.js");
|
|
455
455
|
const client = await getXClient();
|
|
456
456
|
const result = await client.followUser(userId);
|
|
457
457
|
return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
|
|
@@ -466,7 +466,7 @@ Identity saved. Your Spore is alive. Use spora_get_identity to read the full doc
|
|
|
466
466
|
{ userId: z.string().describe("The user ID or handle to unfollow") },
|
|
467
467
|
async ({ userId }) => {
|
|
468
468
|
try {
|
|
469
|
-
const { getXClient } = await import("./x-client-
|
|
469
|
+
const { getXClient } = await import("./x-client-2HFEHHVE.js");
|
|
470
470
|
const client = await getXClient();
|
|
471
471
|
const result = await client.unfollowUser(userId);
|
|
472
472
|
return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
|
|
@@ -481,7 +481,7 @@ Identity saved. Your Spore is alive. Use spora_get_identity to read the full doc
|
|
|
481
481
|
{ count: z.number().optional().describe("Number of tweets to fetch (default 20)") },
|
|
482
482
|
async ({ count }) => {
|
|
483
483
|
try {
|
|
484
|
-
const { getXClient } = await import("./x-client-
|
|
484
|
+
const { getXClient } = await import("./x-client-2HFEHHVE.js");
|
|
485
485
|
const client = await getXClient();
|
|
486
486
|
const result = await client.getTimeline({ count: count ?? 20 });
|
|
487
487
|
return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
|
|
@@ -496,7 +496,7 @@ Identity saved. Your Spore is alive. Use spora_get_identity to read the full doc
|
|
|
496
496
|
{ count: z.number().optional().describe("Number of mentions to fetch (default 20)") },
|
|
497
497
|
async ({ count }) => {
|
|
498
498
|
try {
|
|
499
|
-
const { getXClient } = await import("./x-client-
|
|
499
|
+
const { getXClient } = await import("./x-client-2HFEHHVE.js");
|
|
500
500
|
const client = await getXClient();
|
|
501
501
|
const result = await client.getMentions({ count: count ?? 20 });
|
|
502
502
|
return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
|
|
@@ -514,7 +514,7 @@ Identity saved. Your Spore is alive. Use spora_get_identity to read the full doc
|
|
|
514
514
|
},
|
|
515
515
|
async ({ query, count }) => {
|
|
516
516
|
try {
|
|
517
|
-
const { getXClient } = await import("./x-client-
|
|
517
|
+
const { getXClient } = await import("./x-client-2HFEHHVE.js");
|
|
518
518
|
const client = await getXClient();
|
|
519
519
|
const result = await client.searchTweets(query, { count: count ?? 20 });
|
|
520
520
|
return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
|
|
@@ -529,7 +529,7 @@ Identity saved. Your Spore is alive. Use spora_get_identity to read the full doc
|
|
|
529
529
|
{ handle: z.string().describe("X handle (without @)") },
|
|
530
530
|
async ({ handle }) => {
|
|
531
531
|
try {
|
|
532
|
-
const { getXClient } = await import("./x-client-
|
|
532
|
+
const { getXClient } = await import("./x-client-2HFEHHVE.js");
|
|
533
533
|
const client = await getXClient();
|
|
534
534
|
const result = await client.getProfile(handle);
|
|
535
535
|
return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
|
|
@@ -547,7 +547,7 @@ Identity saved. Your Spore is alive. Use spora_get_identity to read the full doc
|
|
|
547
547
|
},
|
|
548
548
|
async ({ content, scheduledFor }) => {
|
|
549
549
|
try {
|
|
550
|
-
const { addToQueue } = await import("./queue-
|
|
550
|
+
const { addToQueue } = await import("./queue-YPBUUP22.js");
|
|
551
551
|
const entry = addToQueue(content, scheduledFor);
|
|
552
552
|
return {
|
|
553
553
|
content: [
|
|
@@ -565,7 +565,7 @@ Identity saved. Your Spore is alive. Use spora_get_identity to read the full doc
|
|
|
565
565
|
{},
|
|
566
566
|
async () => {
|
|
567
567
|
try {
|
|
568
|
-
const { flushQueue } = await import("./queue-
|
|
568
|
+
const { flushQueue } = await import("./queue-YPBUUP22.js");
|
|
569
569
|
const results = await flushQueue();
|
|
570
570
|
return {
|
|
571
571
|
content: [
|
|
@@ -586,7 +586,7 @@ Identity saved. Your Spore is alive. Use spora_get_identity to read the full doc
|
|
|
586
586
|
{ message: z.string().optional().describe("Optional message to post to the Colony community") },
|
|
587
587
|
async ({ message }) => {
|
|
588
588
|
try {
|
|
589
|
-
const { colonyCheckin } = await import("./colony-
|
|
589
|
+
const { colonyCheckin } = await import("./colony-7GZ2ODF2.js");
|
|
590
590
|
const result = await colonyCheckin(message);
|
|
591
591
|
return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
|
|
592
592
|
} catch (error) {
|
|
@@ -600,7 +600,7 @@ Identity saved. Your Spore is alive. Use spora_get_identity to read the full doc
|
|
|
600
600
|
{},
|
|
601
601
|
async () => {
|
|
602
602
|
try {
|
|
603
|
-
const { getColonyMemory } = await import("./colony-
|
|
603
|
+
const { getColonyMemory } = await import("./colony-7GZ2ODF2.js");
|
|
604
604
|
const memory = getColonyMemory();
|
|
605
605
|
return { content: [{ type: "text", text: JSON.stringify(memory, null, 2) }] };
|
|
606
606
|
} catch (error) {
|
|
@@ -614,7 +614,7 @@ Identity saved. Your Spore is alive. Use spora_get_identity to read the full doc
|
|
|
614
614
|
{},
|
|
615
615
|
async () => {
|
|
616
616
|
try {
|
|
617
|
-
const { getActivePlans } = await import("./colony-
|
|
617
|
+
const { getActivePlans } = await import("./colony-7GZ2ODF2.js");
|
|
618
618
|
const plans = getActivePlans();
|
|
619
619
|
return {
|
|
620
620
|
content: [
|
|
@@ -637,7 +637,7 @@ Identity saved. Your Spore is alive. Use spora_get_identity to read the full doc
|
|
|
637
637
|
},
|
|
638
638
|
async ({ description }) => {
|
|
639
639
|
try {
|
|
640
|
-
const { proposePlan } = await import("./colony-
|
|
640
|
+
const { proposePlan } = await import("./colony-7GZ2ODF2.js");
|
|
641
641
|
const result = await proposePlan(description);
|
|
642
642
|
if (result.success) {
|
|
643
643
|
return {
|
|
@@ -660,7 +660,7 @@ Identity saved. Your Spore is alive. Use spora_get_identity to read the full doc
|
|
|
660
660
|
},
|
|
661
661
|
async ({ planId }) => {
|
|
662
662
|
try {
|
|
663
|
-
const { joinPlan } = await import("./colony-
|
|
663
|
+
const { joinPlan } = await import("./colony-7GZ2ODF2.js");
|
|
664
664
|
const result = await joinPlan(planId);
|
|
665
665
|
if (result.success) {
|
|
666
666
|
return { content: [{ type: "text", text: "Joined the plan! Go execute it." }] };
|
|
@@ -679,7 +679,7 @@ Identity saved. Your Spore is alive. Use spora_get_identity to read the full doc
|
|
|
679
679
|
},
|
|
680
680
|
async ({ status }) => {
|
|
681
681
|
try {
|
|
682
|
-
const { postStatus } = await import("./colony-
|
|
682
|
+
const { postStatus } = await import("./colony-7GZ2ODF2.js");
|
|
683
683
|
const result = await postStatus(status);
|
|
684
684
|
if (result.success) {
|
|
685
685
|
return { content: [{ type: "text", text: "Status posted to the Colony." }] };
|
|
@@ -696,7 +696,7 @@ Identity saved. Your Spore is alive. Use spora_get_identity to read the full doc
|
|
|
696
696
|
{},
|
|
697
697
|
async () => {
|
|
698
698
|
try {
|
|
699
|
-
const { getTodaysActivity } = await import("./colony-
|
|
699
|
+
const { getTodaysActivity } = await import("./colony-7GZ2ODF2.js");
|
|
700
700
|
const activity = getTodaysActivity();
|
|
701
701
|
return {
|
|
702
702
|
content: [
|
|
@@ -8,7 +8,7 @@ import {
|
|
|
8
8
|
saveLearnings,
|
|
9
9
|
saveRelationships,
|
|
10
10
|
updateRelationship
|
|
11
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-6WBIVXOY.js";
|
|
12
12
|
import "./chunk-ZWKTKWS6.js";
|
|
13
13
|
export {
|
|
14
14
|
addLearning,
|
|
@@ -21,4 +21,4 @@ export {
|
|
|
21
21
|
saveRelationships,
|
|
22
22
|
updateRelationship
|
|
23
23
|
};
|
|
24
|
-
//# sourceMappingURL=memory-
|
|
24
|
+
//# sourceMappingURL=memory-G4DNIGLT.js.map
|
|
@@ -6,14 +6,14 @@ import {
|
|
|
6
6
|
buildSystemPrompt,
|
|
7
7
|
buildToolDecisionMessage,
|
|
8
8
|
buildTrainingChatPrompt
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-73CWOI44.js";
|
|
10
10
|
import "./chunk-OTZNHIXT.js";
|
|
11
11
|
import "./chunk-CAWWG3MD.js";
|
|
12
|
-
import "./chunk-
|
|
12
|
+
import "./chunk-ER6TILYZ.js";
|
|
13
13
|
import "./chunk-IULO3GRE.js";
|
|
14
14
|
import "./chunk-RSNEVBEI.js";
|
|
15
15
|
import "./chunk-QYFNAGNI.js";
|
|
16
|
-
import "./chunk-
|
|
16
|
+
import "./chunk-6WBIVXOY.js";
|
|
17
17
|
import "./chunk-ZWKTKWS6.js";
|
|
18
18
|
export {
|
|
19
19
|
buildChatPrompt,
|
|
@@ -24,4 +24,4 @@ export {
|
|
|
24
24
|
buildToolDecisionMessage,
|
|
25
25
|
buildTrainingChatPrompt
|
|
26
26
|
};
|
|
27
|
-
//# sourceMappingURL=prompt-builder-
|
|
27
|
+
//# sourceMappingURL=prompt-builder-S6PJVEC5.js.map
|
|
@@ -2,7 +2,7 @@ import {
|
|
|
2
2
|
addToQueue,
|
|
3
3
|
flushQueue,
|
|
4
4
|
showQueue
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-AIGSCHZK.js";
|
|
6
6
|
import "./chunk-RSNEVBEI.js";
|
|
7
7
|
import "./chunk-QYFNAGNI.js";
|
|
8
8
|
import "./chunk-ZWKTKWS6.js";
|
|
@@ -11,4 +11,4 @@ export {
|
|
|
11
11
|
flushQueue,
|
|
12
12
|
showQueue
|
|
13
13
|
};
|
|
14
|
-
//# sourceMappingURL=queue-
|
|
14
|
+
//# sourceMappingURL=queue-YPBUUP22.js.map
|
package/dist/web-chat/chat.html
CHANGED
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
}
|
|
31
31
|
|
|
32
32
|
.logo-img {
|
|
33
|
-
height:
|
|
33
|
+
height: 24px;
|
|
34
34
|
width: auto;
|
|
35
35
|
}
|
|
36
36
|
|
|
@@ -41,42 +41,26 @@
|
|
|
41
41
|
gap: 0.75rem;
|
|
42
42
|
}
|
|
43
43
|
|
|
44
|
-
.status-dot {
|
|
45
|
-
width: 7px;
|
|
46
|
-
height: 7px;
|
|
47
|
-
border-radius: 50%;
|
|
48
|
-
background: #389e77;
|
|
49
|
-
animation: pulse 2s infinite;
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
.status-text {
|
|
53
|
-
font-size: 0.75rem;
|
|
54
|
-
color: rgba(255, 255, 255, 0.4);
|
|
55
|
-
}
|
|
56
|
-
|
|
57
44
|
.heartbeat-menu {
|
|
58
45
|
position: relative;
|
|
59
46
|
}
|
|
60
47
|
|
|
61
48
|
.heartbeat-trigger {
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
border: 1px solid rgba(255, 255, 255, 0.15);
|
|
66
|
-
background: #141414;
|
|
67
|
-
color: #ff647d;
|
|
49
|
+
border: none;
|
|
50
|
+
background: transparent;
|
|
51
|
+
color: #fff;
|
|
68
52
|
cursor: pointer;
|
|
69
|
-
font-size:
|
|
53
|
+
font-size: 1.05rem;
|
|
70
54
|
line-height: 1;
|
|
71
55
|
display: inline-flex;
|
|
72
56
|
align-items: center;
|
|
73
57
|
justify-content: center;
|
|
74
|
-
|
|
58
|
+
padding: 0;
|
|
59
|
+
transition: opacity 0.2s ease;
|
|
75
60
|
}
|
|
76
61
|
|
|
77
62
|
.heartbeat-trigger:hover {
|
|
78
|
-
|
|
79
|
-
border-color: rgba(255, 100, 125, 0.45);
|
|
63
|
+
opacity: 0.72;
|
|
80
64
|
}
|
|
81
65
|
|
|
82
66
|
.heartbeat-trigger:disabled {
|
|
@@ -130,11 +114,6 @@
|
|
|
130
114
|
color: #89dbba;
|
|
131
115
|
}
|
|
132
116
|
|
|
133
|
-
@keyframes pulse {
|
|
134
|
-
0%, 100% { opacity: 1; }
|
|
135
|
-
50% { opacity: 0.5; }
|
|
136
|
-
}
|
|
137
|
-
|
|
138
117
|
.chat-container {
|
|
139
118
|
flex: 1;
|
|
140
119
|
overflow-y: auto;
|
|
@@ -280,27 +259,27 @@
|
|
|
280
259
|
|
|
281
260
|
.tweet-card-status.success { color: #389e77; }
|
|
282
261
|
|
|
283
|
-
|
|
284
|
-
.narration {
|
|
262
|
+
.live-status {
|
|
285
263
|
display: flex;
|
|
286
264
|
align-items: center;
|
|
287
|
-
gap: 0.
|
|
265
|
+
gap: 0.45rem;
|
|
288
266
|
padding: 0.4rem 0;
|
|
289
|
-
font-size: 0.
|
|
290
|
-
color: rgba(255, 255, 255, 0.
|
|
291
|
-
animation: fadeIn 0.
|
|
267
|
+
font-size: 0.74rem;
|
|
268
|
+
color: rgba(255, 255, 255, 0.42);
|
|
269
|
+
animation: fadeIn 0.2s ease-in;
|
|
292
270
|
}
|
|
293
271
|
|
|
294
|
-
.
|
|
272
|
+
.live-status::before {
|
|
273
|
+
content: '';
|
|
295
274
|
width: 5px;
|
|
296
275
|
height: 5px;
|
|
297
276
|
border-radius: 50%;
|
|
298
|
-
background: rgba(255, 255, 255, 0.
|
|
277
|
+
background: rgba(255, 255, 255, 0.28);
|
|
299
278
|
flex-shrink: 0;
|
|
300
279
|
}
|
|
301
280
|
|
|
302
|
-
.
|
|
303
|
-
.
|
|
281
|
+
.live-status.action::before { background: #389e77; }
|
|
282
|
+
.live-status.error::before { background: #e74c4c; }
|
|
304
283
|
|
|
305
284
|
/* ===== Sleep State ===== */
|
|
306
285
|
.sleep-card {
|
|
@@ -399,12 +378,8 @@
|
|
|
399
378
|
</head>
|
|
400
379
|
<body>
|
|
401
380
|
<div class="header">
|
|
402
|
-
<
|
|
403
|
-
<text x="0" y="22" font-family="-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif" font-size="22" font-weight="800" letter-spacing="-0.5" fill="#fff">spora</text>
|
|
404
|
-
</svg>
|
|
381
|
+
<img class="logo-img" src="/logo2.png" alt="Spora" />
|
|
405
382
|
<div class="header-right">
|
|
406
|
-
<span class="status-dot"></span>
|
|
407
|
-
<span class="status-text" id="statusText">Online</span>
|
|
408
383
|
<div class="heartbeat-menu" id="heartbeatMenu">
|
|
409
384
|
<button class="heartbeat-trigger" id="heartbeatTrigger" title="Heartbeat settings" aria-label="Heartbeat settings">♥</button>
|
|
410
385
|
<div class="heartbeat-popover" id="heartbeatPopover" hidden>
|
|
@@ -441,7 +416,6 @@
|
|
|
441
416
|
const heartbeatTrigger = document.getElementById('heartbeatTrigger');
|
|
442
417
|
const heartbeatPopover = document.getElementById('heartbeatPopover');
|
|
443
418
|
const heartbeatOptions = Array.from(document.querySelectorAll('.heartbeat-option'));
|
|
444
|
-
const statusText = document.getElementById('statusText');
|
|
445
419
|
|
|
446
420
|
let isLoading = false;
|
|
447
421
|
let agentName = 'Your Spore';
|
|
@@ -462,10 +436,6 @@
|
|
|
462
436
|
return HEARTBEAT_LABELS[ms] || `${Math.round(ms / 60000)} min`;
|
|
463
437
|
}
|
|
464
438
|
|
|
465
|
-
function updateStatusText() {
|
|
466
|
-
statusText.textContent = `Online • ${heartbeatLabel(heartbeatMs)} heartbeat`;
|
|
467
|
-
}
|
|
468
|
-
|
|
469
439
|
function setHeartbeatPopoverOpen(isOpen) {
|
|
470
440
|
heartbeatPopover.hidden = !isOpen;
|
|
471
441
|
}
|
|
@@ -484,7 +454,6 @@
|
|
|
484
454
|
const data = await response.json();
|
|
485
455
|
if (data.intervalMs) {
|
|
486
456
|
heartbeatMs = data.intervalMs;
|
|
487
|
-
updateStatusText();
|
|
488
457
|
updateHeartbeatOptions();
|
|
489
458
|
}
|
|
490
459
|
} catch {
|
|
@@ -506,13 +475,12 @@
|
|
|
506
475
|
throw new Error('Failed to update heartbeat');
|
|
507
476
|
}
|
|
508
477
|
heartbeatMs = intervalMs;
|
|
509
|
-
updateStatusText();
|
|
510
478
|
updateHeartbeatOptions();
|
|
511
|
-
|
|
479
|
+
setLiveStatus(`heartbeat set to ${heartbeatLabel(intervalMs)}`, 'action');
|
|
512
480
|
} catch {
|
|
513
481
|
heartbeatMs = previous;
|
|
514
482
|
updateHeartbeatOptions();
|
|
515
|
-
|
|
483
|
+
setLiveStatus('could not update heartbeat', 'error');
|
|
516
484
|
} finally {
|
|
517
485
|
heartbeatTrigger.disabled = false;
|
|
518
486
|
}
|
|
@@ -570,6 +538,7 @@
|
|
|
570
538
|
}
|
|
571
539
|
|
|
572
540
|
function addMessage(role, content, animate = true) {
|
|
541
|
+
clearLiveStatus();
|
|
573
542
|
removeSleepCard();
|
|
574
543
|
const messageDiv = document.createElement('div');
|
|
575
544
|
messageDiv.className = `message ${role}`;
|
|
@@ -589,8 +558,12 @@
|
|
|
589
558
|
}
|
|
590
559
|
|
|
591
560
|
// ===== Tweet Card =====
|
|
592
|
-
function addTweetCard(text,
|
|
561
|
+
function addTweetCard(text, meta = {}) {
|
|
562
|
+
clearLiveStatus();
|
|
593
563
|
removeSleepCard();
|
|
564
|
+
const kind = typeof meta.kind === 'string' ? meta.kind : 'Post';
|
|
565
|
+
const status = typeof meta.status === 'string' ? meta.status : '';
|
|
566
|
+
const replyTo = typeof meta.replyTo === 'string' ? meta.replyTo : '';
|
|
594
567
|
const card = document.createElement('div');
|
|
595
568
|
card.className = 'tweet-card';
|
|
596
569
|
|
|
@@ -611,7 +584,7 @@
|
|
|
611
584
|
|
|
612
585
|
const badge = document.createElement('span');
|
|
613
586
|
badge.className = 'tweet-card-badge';
|
|
614
|
-
badge.textContent =
|
|
587
|
+
badge.textContent = kind;
|
|
615
588
|
|
|
616
589
|
header.appendChild(avatar);
|
|
617
590
|
header.appendChild(author);
|
|
@@ -627,12 +600,19 @@
|
|
|
627
600
|
|
|
628
601
|
card.appendChild(header);
|
|
629
602
|
card.appendChild(body);
|
|
603
|
+
if (replyTo) {
|
|
604
|
+
const replyToEl = document.createElement('div');
|
|
605
|
+
replyToEl.className = 'tweet-card-time';
|
|
606
|
+
replyToEl.textContent = `replying to ${replyTo}`;
|
|
607
|
+
card.appendChild(replyToEl);
|
|
608
|
+
}
|
|
630
609
|
card.appendChild(time);
|
|
631
610
|
|
|
632
611
|
if (status) {
|
|
633
612
|
const statusEl = document.createElement('div');
|
|
634
|
-
|
|
635
|
-
statusEl.
|
|
613
|
+
const successLike = /posted|sent|queued|success/i.test(status);
|
|
614
|
+
statusEl.className = `tweet-card-status ${successLike ? 'success' : ''}`;
|
|
615
|
+
statusEl.textContent = status;
|
|
636
616
|
card.appendChild(statusEl);
|
|
637
617
|
}
|
|
638
618
|
|
|
@@ -641,15 +621,24 @@
|
|
|
641
621
|
}
|
|
642
622
|
|
|
643
623
|
// ===== Narration =====
|
|
644
|
-
function
|
|
645
|
-
const
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
624
|
+
function clearLiveStatus() {
|
|
625
|
+
const existing = document.getElementById('liveStatus');
|
|
626
|
+
if (existing) existing.remove();
|
|
627
|
+
}
|
|
628
|
+
|
|
629
|
+
function setLiveStatus(text, type) {
|
|
630
|
+
if (!text) {
|
|
631
|
+
clearLiveStatus();
|
|
632
|
+
return;
|
|
633
|
+
}
|
|
634
|
+
removeSleepCard();
|
|
635
|
+
let el = document.getElementById('liveStatus');
|
|
636
|
+
if (!el) {
|
|
637
|
+
el = document.createElement('div');
|
|
638
|
+
el.id = 'liveStatus';
|
|
639
|
+
}
|
|
640
|
+
el.className = `live-status ${type || ''}`;
|
|
641
|
+
el.textContent = text;
|
|
653
642
|
chatContainer.appendChild(el);
|
|
654
643
|
chatContainer.scrollTop = chatContainer.scrollHeight;
|
|
655
644
|
}
|
|
@@ -803,23 +792,27 @@
|
|
|
803
792
|
function renderAgentEvent(event) {
|
|
804
793
|
switch (event.type) {
|
|
805
794
|
case 'narration':
|
|
806
|
-
|
|
795
|
+
setLiveStatus(event.content);
|
|
796
|
+
break;
|
|
797
|
+
case 'summary':
|
|
798
|
+
addMessage('assistant', event.content);
|
|
807
799
|
break;
|
|
808
800
|
case 'tweet':
|
|
809
|
-
addTweetCard(event.content, event.meta
|
|
801
|
+
addTweetCard(event.content, event.meta || {});
|
|
810
802
|
break;
|
|
811
803
|
case 'action':
|
|
812
|
-
|
|
804
|
+
setLiveStatus(event.content, 'action');
|
|
813
805
|
break;
|
|
814
806
|
case 'error':
|
|
815
|
-
|
|
807
|
+
setLiveStatus(event.content, 'error');
|
|
816
808
|
break;
|
|
817
809
|
case 'sleep':
|
|
810
|
+
clearLiveStatus();
|
|
818
811
|
showSleepState(event.meta?.wakeUpAt || (Date.now() + 300000));
|
|
819
812
|
break;
|
|
820
813
|
case 'wake':
|
|
821
814
|
removeSleepCard();
|
|
822
|
-
|
|
815
|
+
setLiveStatus(event.content);
|
|
823
816
|
break;
|
|
824
817
|
}
|
|
825
818
|
}
|
|
@@ -827,7 +820,6 @@
|
|
|
827
820
|
setInterval(pollAgentEvents, 2000);
|
|
828
821
|
|
|
829
822
|
// Initialize
|
|
830
|
-
updateStatusText();
|
|
831
823
|
updateHeartbeatOptions();
|
|
832
824
|
init();
|
|
833
825
|
messageInput.focus();
|
|
Binary file
|