spora 0.7.4 → 0.7.5
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-DFPA3OK6.js +20 -0
- package/dist/{chunk-SUZUJGGW.js → chunk-342ZX72W.js} +4 -4
- package/dist/{chunk-PN5A6MCV.js → chunk-5R4AJZHN.js} +4 -4
- package/dist/{chunk-PN5A6MCV.js.map → chunk-5R4AJZHN.js.map} +1 -1
- package/dist/{chunk-Q3YXJ2C6.js → chunk-A2XTKC7B.js} +281 -65
- package/dist/chunk-A2XTKC7B.js.map +1 -0
- package/dist/{chunk-JBYZ7K56.js → chunk-BBXHECZ5.js} +2 -2
- package/dist/{chunk-WN35MRMF.js → chunk-CAWWG3MD.js} +2 -2
- package/dist/chunk-CP6JWCLY.js +171 -0
- package/dist/chunk-CP6JWCLY.js.map +1 -0
- package/dist/{chunk-T7L2L7ZL.js → chunk-D47OFTEK.js} +2 -2
- package/dist/chunk-HXI2EH5C.js +2338 -0
- package/dist/chunk-HXI2EH5C.js.map +1 -0
- package/dist/{chunk-M6YOQVSI.js → chunk-IULO3GRE.js} +4 -4
- package/dist/chunk-IULO3GRE.js.map +1 -0
- package/dist/chunk-OTZNHIXT.js +431 -0
- package/dist/chunk-OTZNHIXT.js.map +1 -0
- package/dist/{chunk-NO3NQN67.js → chunk-QYFNAGNI.js} +2 -2
- package/dist/{chunk-YMGJQRKG.js → chunk-RSNEVBEI.js} +2 -2
- package/dist/{chunk-QWEYVDLU.js → chunk-SXNZVKLJ.js} +2 -2
- package/dist/{chunk-MDOFAAZB.js → chunk-ZLSDFYBR.js} +17 -5
- package/dist/chunk-ZLSDFYBR.js.map +1 -0
- package/dist/{chunk-3RYCUGXE.js → chunk-ZWKTKWS6.js} +4 -1
- package/dist/chunk-ZWKTKWS6.js.map +1 -0
- package/dist/cli.js +49 -49
- package/dist/{client-Z5UQWPPI.js → client-AR5ZD6S4.js} +48 -16
- package/dist/client-AR5ZD6S4.js.map +1 -0
- package/dist/{colony-NNX45EAV.js → colony-UGVYALOS.js} +7 -7
- package/dist/{config-FL4VJVKZ.js → config-MU2ODEO3.js} +3 -3
- package/dist/{crypto-B65ZH7KN.js → crypto-GDG5K3ZH.js} +3 -3
- package/dist/{goals-RBKLMILE.js → goals-QWX3A47Y.js} +3 -3
- package/dist/{heartbeat-ZCCOIZGU.js → heartbeat-RAOEIKWC.js} +18 -21
- package/dist/heartbeat-RAOEIKWC.js.map +1 -0
- package/dist/{identity-VDUW4I2K.js → identity-ASHVWIN5.js} +3 -3
- package/dist/{init-SEJPTOOB.js → init-ETUTFHT6.js} +59 -13
- package/dist/init-ETUTFHT6.js.map +1 -0
- package/dist/{llm-OGOYCWBH.js → llm-IJBRQ7O2.js} +5 -5
- package/dist/mcp-server.js +24 -24
- package/dist/{memory-PNW7SX7A.js → memory-AWKIW2KW.js} +3 -3
- package/dist/{memory-OIAH33G2.js → memory-DTSLVSQG.js} +3 -3
- package/dist/{paths-BYR6MEPR.js → paths-4V5OCB5F.js} +2 -2
- package/dist/prompt-builder-XJHXZCSQ.js +27 -0
- package/dist/queue-QCGNDHH2.js +14 -0
- package/dist/strategy-R2BMRVJ3.js +19 -0
- package/dist/{web-chat-ZZ65DUID.js → web-chat-TB3ACPVF.js} +23 -28
- package/dist/web-chat-TB3ACPVF.js.map +1 -0
- package/dist/x-client-S2LUVEKV.js +12 -0
- package/package.json +1 -1
- package/dist/autonomy-XUKCAZM3.js +0 -19
- package/dist/chunk-3RYCUGXE.js.map +0 -1
- package/dist/chunk-4LNMA56H.js +0 -57
- package/dist/chunk-4LNMA56H.js.map +0 -1
- package/dist/chunk-EU4FMOKG.js +0 -377
- package/dist/chunk-EU4FMOKG.js.map +0 -1
- package/dist/chunk-M6YOQVSI.js.map +0 -1
- package/dist/chunk-MDOFAAZB.js.map +0 -1
- package/dist/chunk-P6KZIJYL.js +0 -79
- package/dist/chunk-P6KZIJYL.js.map +0 -1
- package/dist/chunk-Q3YXJ2C6.js.map +0 -1
- package/dist/client-Z5UQWPPI.js.map +0 -1
- package/dist/heartbeat-ZCCOIZGU.js.map +0 -1
- package/dist/init-SEJPTOOB.js.map +0 -1
- package/dist/prompt-builder-KJKFCGM7.js +0 -25
- package/dist/queue-2ZBKDFX3.js +0 -14
- package/dist/strategy-Z4JSFHSP.js +0 -12
- package/dist/web-chat-ZZ65DUID.js.map +0 -1
- package/dist/x-client-YG7UCCNI.js +0 -12
- /package/dist/{autonomy-XUKCAZM3.js.map → autonomy-DFPA3OK6.js.map} +0 -0
- /package/dist/{chunk-SUZUJGGW.js.map → chunk-342ZX72W.js.map} +0 -0
- /package/dist/{chunk-JBYZ7K56.js.map → chunk-BBXHECZ5.js.map} +0 -0
- /package/dist/{chunk-WN35MRMF.js.map → chunk-CAWWG3MD.js.map} +0 -0
- /package/dist/{chunk-T7L2L7ZL.js.map → chunk-D47OFTEK.js.map} +0 -0
- /package/dist/{chunk-NO3NQN67.js.map → chunk-QYFNAGNI.js.map} +0 -0
- /package/dist/{chunk-YMGJQRKG.js.map → chunk-RSNEVBEI.js.map} +0 -0
- /package/dist/{chunk-QWEYVDLU.js.map → chunk-SXNZVKLJ.js.map} +0 -0
- /package/dist/{colony-NNX45EAV.js.map → colony-UGVYALOS.js.map} +0 -0
- /package/dist/{config-FL4VJVKZ.js.map → config-MU2ODEO3.js.map} +0 -0
- /package/dist/{crypto-B65ZH7KN.js.map → crypto-GDG5K3ZH.js.map} +0 -0
- /package/dist/{goals-RBKLMILE.js.map → goals-QWX3A47Y.js.map} +0 -0
- /package/dist/{identity-VDUW4I2K.js.map → identity-ASHVWIN5.js.map} +0 -0
- /package/dist/{llm-OGOYCWBH.js.map → llm-IJBRQ7O2.js.map} +0 -0
- /package/dist/{memory-OIAH33G2.js.map → memory-AWKIW2KW.js.map} +0 -0
- /package/dist/{memory-PNW7SX7A.js.map → memory-DTSLVSQG.js.map} +0 -0
- /package/dist/{paths-BYR6MEPR.js.map → paths-4V5OCB5F.js.map} +0 -0
- /package/dist/{prompt-builder-KJKFCGM7.js.map → prompt-builder-XJHXZCSQ.js.map} +0 -0
- /package/dist/{queue-2ZBKDFX3.js.map → queue-QCGNDHH2.js.map} +0 -0
- /package/dist/{strategy-Z4JSFHSP.js.map → strategy-R2BMRVJ3.js.map} +0 -0
- /package/dist/{x-client-YG7UCCNI.js.map → x-client-S2LUVEKV.js.map} +0 -0
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import {
|
|
2
|
+
buildChatPrompt,
|
|
3
|
+
buildHeartbeatUserMessage,
|
|
4
|
+
buildOpportunityPortfolioMessage,
|
|
5
|
+
buildReflectionPrompt,
|
|
6
|
+
buildSystemPrompt,
|
|
7
|
+
buildToolDecisionMessage,
|
|
8
|
+
buildTrainingChatPrompt
|
|
9
|
+
} from "./chunk-A2XTKC7B.js";
|
|
10
|
+
import "./chunk-OTZNHIXT.js";
|
|
11
|
+
import "./chunk-CAWWG3MD.js";
|
|
12
|
+
import "./chunk-CP6JWCLY.js";
|
|
13
|
+
import "./chunk-IULO3GRE.js";
|
|
14
|
+
import "./chunk-RSNEVBEI.js";
|
|
15
|
+
import "./chunk-QYFNAGNI.js";
|
|
16
|
+
import "./chunk-BBXHECZ5.js";
|
|
17
|
+
import "./chunk-ZWKTKWS6.js";
|
|
18
|
+
export {
|
|
19
|
+
buildChatPrompt,
|
|
20
|
+
buildHeartbeatUserMessage,
|
|
21
|
+
buildOpportunityPortfolioMessage,
|
|
22
|
+
buildReflectionPrompt,
|
|
23
|
+
buildSystemPrompt,
|
|
24
|
+
buildToolDecisionMessage,
|
|
25
|
+
buildTrainingChatPrompt
|
|
26
|
+
};
|
|
27
|
+
//# sourceMappingURL=prompt-builder-XJHXZCSQ.js.map
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import {
|
|
2
|
+
addToQueue,
|
|
3
|
+
flushQueue,
|
|
4
|
+
showQueue
|
|
5
|
+
} from "./chunk-ZLSDFYBR.js";
|
|
6
|
+
import "./chunk-RSNEVBEI.js";
|
|
7
|
+
import "./chunk-QYFNAGNI.js";
|
|
8
|
+
import "./chunk-ZWKTKWS6.js";
|
|
9
|
+
export {
|
|
10
|
+
addToQueue,
|
|
11
|
+
flushQueue,
|
|
12
|
+
showQueue
|
|
13
|
+
};
|
|
14
|
+
//# sourceMappingURL=queue-QCGNDHH2.js.map
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import {
|
|
2
|
+
applyStrategyUpdate,
|
|
3
|
+
deriveStrategyIntent,
|
|
4
|
+
extractHandlesFromText,
|
|
5
|
+
loadStrategy,
|
|
6
|
+
renderStrategyForPrompt,
|
|
7
|
+
saveStrategy
|
|
8
|
+
} from "./chunk-OTZNHIXT.js";
|
|
9
|
+
import "./chunk-IULO3GRE.js";
|
|
10
|
+
import "./chunk-ZWKTKWS6.js";
|
|
11
|
+
export {
|
|
12
|
+
applyStrategyUpdate,
|
|
13
|
+
deriveStrategyIntent,
|
|
14
|
+
extractHandlesFromText,
|
|
15
|
+
loadStrategy,
|
|
16
|
+
renderStrategyForPrompt,
|
|
17
|
+
saveStrategy
|
|
18
|
+
};
|
|
19
|
+
//# sourceMappingURL=strategy-R2BMRVJ3.js.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
loadIdentity
|
|
3
|
-
} from "./chunk-
|
|
4
|
-
import "./chunk-
|
|
3
|
+
} from "./chunk-IULO3GRE.js";
|
|
4
|
+
import "./chunk-ZWKTKWS6.js";
|
|
5
5
|
|
|
6
6
|
// src/web-chat/server.ts
|
|
7
7
|
import http from "http";
|
|
@@ -233,7 +233,7 @@ async function extractAndSaveLearnings(responseText) {
|
|
|
233
233
|
const learnPattern = /<<LEARN:\s*(.+?)>>/g;
|
|
234
234
|
const matches = [...responseText.matchAll(learnPattern)];
|
|
235
235
|
if (matches.length > 0) {
|
|
236
|
-
const { addLearning } = await import("./memory-
|
|
236
|
+
const { addLearning } = await import("./memory-DTSLVSQG.js");
|
|
237
237
|
for (const match of matches) {
|
|
238
238
|
const learning = match[1].trim();
|
|
239
239
|
addLearning(learning, "web-chat", ["chat", "creator-interaction"]);
|
|
@@ -249,7 +249,7 @@ async function extractAndApplyTraining(responseText) {
|
|
|
249
249
|
try {
|
|
250
250
|
const update = JSON.parse(match[1].trim());
|
|
251
251
|
if (update.identity) {
|
|
252
|
-
const { loadIdentity: loadIdentity2, mutateIdentity, saveIdentity } = await import("./identity-
|
|
252
|
+
const { loadIdentity: loadIdentity2, mutateIdentity, saveIdentity } = await import("./identity-ASHVWIN5.js");
|
|
253
253
|
let identity = loadIdentity2();
|
|
254
254
|
const identityFields = {
|
|
255
255
|
tone: "tone",
|
|
@@ -288,7 +288,7 @@ async function extractAndApplyTraining(responseText) {
|
|
|
288
288
|
saveIdentity(identity);
|
|
289
289
|
}
|
|
290
290
|
if (update.strategy) {
|
|
291
|
-
const { loadStrategy, saveStrategy } = await import("./strategy-
|
|
291
|
+
const { loadStrategy, saveStrategy } = await import("./strategy-R2BMRVJ3.js");
|
|
292
292
|
const strategy = loadStrategy();
|
|
293
293
|
if (update.strategy.currentFocus) strategy.currentFocus = update.strategy.currentFocus;
|
|
294
294
|
if (update.strategy.shortTermGoals) strategy.shortTermGoals = update.strategy.shortTermGoals;
|
|
@@ -303,7 +303,7 @@ async function extractAndApplyTraining(responseText) {
|
|
|
303
303
|
console.log(chalk.dim(` [Training] Updated strategy`));
|
|
304
304
|
}
|
|
305
305
|
if (update.learning) {
|
|
306
|
-
const { addLearning } = await import("./memory-
|
|
306
|
+
const { addLearning } = await import("./memory-DTSLVSQG.js");
|
|
307
307
|
addLearning(
|
|
308
308
|
update.learning.content,
|
|
309
309
|
"training-chat",
|
|
@@ -312,7 +312,7 @@ async function extractAndApplyTraining(responseText) {
|
|
|
312
312
|
console.log(chalk.dim(` [Training] Saved learning: ${update.learning.content}`));
|
|
313
313
|
}
|
|
314
314
|
if (update.reflection) {
|
|
315
|
-
const { loadIdentity: loadIdentity2, saveIdentity } = await import("./identity-
|
|
315
|
+
const { loadIdentity: loadIdentity2, saveIdentity } = await import("./identity-ASHVWIN5.js");
|
|
316
316
|
const identity = loadIdentity2();
|
|
317
317
|
identity.evolutionJournal.push({
|
|
318
318
|
date: (/* @__PURE__ */ new Date()).toISOString(),
|
|
@@ -322,7 +322,7 @@ async function extractAndApplyTraining(responseText) {
|
|
|
322
322
|
console.log(chalk.dim(` [Training] Added reflection to evolution journal`));
|
|
323
323
|
}
|
|
324
324
|
if (update.goalUpdates && Array.isArray(update.goalUpdates)) {
|
|
325
|
-
const { loadGoals, saveGoals } = await import("./goals-
|
|
325
|
+
const { loadGoals, saveGoals } = await import("./goals-QWX3A47Y.js");
|
|
326
326
|
const tracker = loadGoals();
|
|
327
327
|
for (const gu of update.goalUpdates) {
|
|
328
328
|
const existing = tracker.goals.find((g) => g.goal === gu.goal);
|
|
@@ -348,7 +348,7 @@ async function extractAndApplyTraining(responseText) {
|
|
|
348
348
|
return responseText.replace(/<<TRAINING:[\s\S]*?>>/g, "").trim();
|
|
349
349
|
}
|
|
350
350
|
async function logChatInteraction(userMessage, agentResponse) {
|
|
351
|
-
const { logInteraction } = await import("./memory-
|
|
351
|
+
const { logInteraction } = await import("./memory-DTSLVSQG.js");
|
|
352
352
|
logInteraction({
|
|
353
353
|
id: `chat-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`,
|
|
354
354
|
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
@@ -360,13 +360,13 @@ async function logChatInteraction(userMessage, agentResponse) {
|
|
|
360
360
|
});
|
|
361
361
|
}
|
|
362
362
|
async function runNarratedHeartbeat(server) {
|
|
363
|
-
const { loadConfig } = await import("./config-
|
|
364
|
-
const { flushQueue } = await import("./queue-
|
|
365
|
-
const { runAutonomyCycle } = await import("./autonomy-
|
|
366
|
-
const { buildReflectionPrompt } = await import("./prompt-builder-
|
|
367
|
-
const { generateResponse } = await import("./llm-
|
|
368
|
-
const { addLearning } = await import("./memory-
|
|
369
|
-
const { loadStrategy, saveStrategy } = await import("./strategy-
|
|
363
|
+
const { loadConfig } = await import("./config-MU2ODEO3.js");
|
|
364
|
+
const { flushQueue } = await import("./queue-QCGNDHH2.js");
|
|
365
|
+
const { runAutonomyCycle } = await import("./autonomy-DFPA3OK6.js");
|
|
366
|
+
const { buildReflectionPrompt } = await import("./prompt-builder-XJHXZCSQ.js");
|
|
367
|
+
const { generateResponse } = await import("./llm-IJBRQ7O2.js");
|
|
368
|
+
const { addLearning } = await import("./memory-DTSLVSQG.js");
|
|
369
|
+
const { loadStrategy, saveStrategy, applyStrategyUpdate } = await import("./strategy-R2BMRVJ3.js");
|
|
370
370
|
let heartbeatCount = 0;
|
|
371
371
|
let lastIntervalMs = loadConfig().runtime?.heartbeatIntervalMs ?? 3e5;
|
|
372
372
|
console.log(chalk.cyan(` [Agent] Autonomous heartbeat started (every ${Math.round(lastIntervalMs / 6e4)} min)`));
|
|
@@ -412,7 +412,7 @@ async function runNarratedHeartbeat(server) {
|
|
|
412
412
|
} catch {
|
|
413
413
|
}
|
|
414
414
|
server.pushAgentEvent("narration", "Observing timeline and planning actions...");
|
|
415
|
-
const cycle = await runAutonomyCycle(maxActions);
|
|
415
|
+
const cycle = await runAutonomyCycle(maxActions, heartbeatCount);
|
|
416
416
|
if (cycle.timeline.length > 0 || cycle.mentions.length > 0) {
|
|
417
417
|
server.pushAgentEvent("narration", `Found ${cycle.timeline.length} timeline posts and ${cycle.mentions.length} mentions`);
|
|
418
418
|
}
|
|
@@ -473,12 +473,7 @@ async function runNarratedHeartbeat(server) {
|
|
|
473
473
|
}
|
|
474
474
|
if (reflection.strategyUpdate && reflection.strategyUpdate !== "null") {
|
|
475
475
|
const strategy = loadStrategy();
|
|
476
|
-
strategy.
|
|
477
|
-
description: reflection.strategyUpdate,
|
|
478
|
-
status: "pending"
|
|
479
|
-
});
|
|
480
|
-
strategy.lastUpdated = (/* @__PURE__ */ new Date()).toISOString();
|
|
481
|
-
saveStrategy(strategy);
|
|
476
|
+
saveStrategy(applyStrategyUpdate(strategy, reflection.strategyUpdate));
|
|
482
477
|
server.pushAgentEvent("narration", `Strategy: ${reflection.strategyUpdate}`);
|
|
483
478
|
console.log(chalk.dim(` [Agent] Strategy update: ${reflection.strategyUpdate}`));
|
|
484
479
|
}
|
|
@@ -498,7 +493,7 @@ async function runNarratedHeartbeat(server) {
|
|
|
498
493
|
}
|
|
499
494
|
async function startWebChat() {
|
|
500
495
|
const identity = loadIdentity();
|
|
501
|
-
const { loadConfig: loadRuntimeConfig, saveConfig } = await import("./config-
|
|
496
|
+
const { loadConfig: loadRuntimeConfig, saveConfig } = await import("./config-MU2ODEO3.js");
|
|
502
497
|
const server = new WebChatServer();
|
|
503
498
|
server.setIdentity({
|
|
504
499
|
name: identity.name,
|
|
@@ -531,11 +526,11 @@ async function startWebChat() {
|
|
|
531
526
|
server.setMessageHandler(async (message) => {
|
|
532
527
|
try {
|
|
533
528
|
if (!systemPrompt || messageCount % 10 === 0) {
|
|
534
|
-
const { buildTrainingChatPrompt } = await import("./prompt-builder-
|
|
529
|
+
const { buildTrainingChatPrompt } = await import("./prompt-builder-XJHXZCSQ.js");
|
|
535
530
|
systemPrompt = buildTrainingChatPrompt();
|
|
536
531
|
}
|
|
537
532
|
messageCount++;
|
|
538
|
-
const { hasLLMKey, chat: chatLLM } = await import("./llm-
|
|
533
|
+
const { hasLLMKey, chat: chatLLM } = await import("./llm-IJBRQ7O2.js");
|
|
539
534
|
if (!hasLLMKey()) {
|
|
540
535
|
return "I can't respond right now - no API key configured. Run `spora llm set --provider <provider>` to set one up.";
|
|
541
536
|
}
|
|
@@ -561,7 +556,7 @@ async function startWebChat() {
|
|
|
561
556
|
`));
|
|
562
557
|
openBrowser(url);
|
|
563
558
|
try {
|
|
564
|
-
const { hasLLMKey } = await import("./llm-
|
|
559
|
+
const { hasLLMKey } = await import("./llm-IJBRQ7O2.js");
|
|
565
560
|
if (hasLLMKey()) {
|
|
566
561
|
runNarratedHeartbeat(server).catch((err) => {
|
|
567
562
|
console.error(chalk.red(`Heartbeat failed to start: ${err}`));
|
|
@@ -614,4 +609,4 @@ export {
|
|
|
614
609
|
openBrowser,
|
|
615
610
|
startWebChat
|
|
616
611
|
};
|
|
617
|
-
//# sourceMappingURL=web-chat-
|
|
612
|
+
//# sourceMappingURL=web-chat-TB3ACPVF.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 } 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\";\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 this.agentEvents.push({ type, content, timestamp: Date.now(), meta });\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 // 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 { 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 interval updated 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\", `Waking up... 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\", \"Observing timeline and planning actions...\");\n const cycle = await runAutonomyCycle(maxActions, heartbeatCount);\n\n if (cycle.timeline.length > 0 || cycle.mentions.length > 0) {\n server.pushAgentEvent(\"narration\", `Found ${cycle.timeline.length} timeline posts and ${cycle.mentions.length} mentions`);\n }\n\n if (cycle.actions.length === 0) {\n server.pushAgentEvent(\"narration\", \"Nothing interesting right now, going back to sleep\");\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, { status: \"success\" });\n } else if (action.action === \"reply\" && action.content) {\n server.pushAgentEvent(\"action\", `Replied to tweet: \"${action.content.slice(0, 80)}\"`);\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, { status: \"Scheduled\" });\n } else {\n server.pushAgentEvent(\"action\", `${action.action}${result.detail ? `: ${result.detail}` : \"\"}`);\n }\n console.log(chalk.green(` [Agent] ✓ ${result.action}`));\n } else {\n if (action.action === \"post\" && action.content) {\n server.pushAgentEvent(\"tweet\", action.content, { status: `Failed: ${result.error}` });\n } else {\n server.pushAgentEvent(\"error\", `${result.action} failed: ${result.error}`);\n }\n console.log(chalk.red(` [Agent] ✗ ${result.action}: ${result.error}`));\n }\n }\n\n for (const feedback of cycle.policyFeedback) {\n server.pushAgentEvent(\"narration\", `Policy adjusted plan: ${feedback}`);\n }\n\n // Reflection phase — every 3rd heartbeat, review performance\n if (heartbeatCount % 3 === 0) {\n try {\n server.pushAgentEvent(\"narration\", \"Reflecting on recent performance...\");\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: ${reflection.learning}`);\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: ${reflection.strategyUpdate}`);\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 server.pushAgentEvent(\"error\", `Something went wrong: ${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"]}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import {
|
|
2
|
+
getXClient,
|
|
3
|
+
resetXClient
|
|
4
|
+
} from "./chunk-5R4AJZHN.js";
|
|
5
|
+
import "./chunk-RSNEVBEI.js";
|
|
6
|
+
import "./chunk-QYFNAGNI.js";
|
|
7
|
+
import "./chunk-ZWKTKWS6.js";
|
|
8
|
+
export {
|
|
9
|
+
getXClient,
|
|
10
|
+
resetXClient
|
|
11
|
+
};
|
|
12
|
+
//# sourceMappingURL=x-client-S2LUVEKV.js.map
|
package/package.json
CHANGED
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
runAutonomyCycle
|
|
3
|
-
} from "./chunk-EU4FMOKG.js";
|
|
4
|
-
import "./chunk-PN5A6MCV.js";
|
|
5
|
-
import "./chunk-MDOFAAZB.js";
|
|
6
|
-
import "./chunk-Q3YXJ2C6.js";
|
|
7
|
-
import "./chunk-P6KZIJYL.js";
|
|
8
|
-
import "./chunk-WN35MRMF.js";
|
|
9
|
-
import "./chunk-4LNMA56H.js";
|
|
10
|
-
import "./chunk-M6YOQVSI.js";
|
|
11
|
-
import "./chunk-SUZUJGGW.js";
|
|
12
|
-
import "./chunk-YMGJQRKG.js";
|
|
13
|
-
import "./chunk-NO3NQN67.js";
|
|
14
|
-
import "./chunk-JBYZ7K56.js";
|
|
15
|
-
import "./chunk-3RYCUGXE.js";
|
|
16
|
-
export {
|
|
17
|
-
runAutonomyCycle
|
|
18
|
-
};
|
|
19
|
-
//# sourceMappingURL=autonomy-XUKCAZM3.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/utils/paths.ts"],"sourcesContent":["import { homedir } from \"node:os\";\nimport { join } from \"node:path\";\nimport { mkdirSync, existsSync } from \"node:fs\";\n\nconst SPORA_DIR = join(homedir(), \".spora\");\n\nexport const paths = {\n root: SPORA_DIR,\n config: join(SPORA_DIR, \"config.json\"),\n credentials: join(SPORA_DIR, \"credentials.json\"),\n spore: join(SPORA_DIR, \"spore.json\"),\n identity: join(SPORA_DIR, \"identity.json\"),\n colonyToken: join(SPORA_DIR, \"colony-token.json\"),\n browser: join(SPORA_DIR, \"browser\"),\n browserAuth: join(SPORA_DIR, \"browser\", \"auth-state.json\"),\n memory: join(SPORA_DIR, \"memory\"),\n interactions: join(SPORA_DIR, \"memory\", \"interactions\"),\n learnings: join(SPORA_DIR, \"memory\", \"learnings.json\"),\n relationships: join(SPORA_DIR, \"memory\", \"relationships.json\"),\n strategy: join(SPORA_DIR, \"memory\", \"strategy.json\"),\n goals: join(SPORA_DIR, \"memory\", \"goals.json\"),\n performance: join(SPORA_DIR, \"memory\", \"performance.json\"),\n compacted: join(SPORA_DIR, \"memory\", \"compacted\"),\n queue: join(SPORA_DIR, \"queue\"),\n pendingPosts: join(SPORA_DIR, \"queue\", \"pending-posts.json\"),\n logs: join(SPORA_DIR, \"logs\"),\n logFile: join(SPORA_DIR, \"logs\", \"spora.log\"),\n runtimeMetrics: join(SPORA_DIR, \"logs\", \"runtime-metrics.jsonl\"),\n dataDir: SPORA_DIR,\n llmKey: join(SPORA_DIR, \"llm-key\"),\n llmKeys: join(SPORA_DIR, \"llm-keys.json\"),\n runtimePid: join(SPORA_DIR, \"runtime.pid\"),\n stopSignal: join(SPORA_DIR, \"stop\"),\n connectionToken: join(SPORA_DIR, \"connection-token\"),\n} as const;\n\nexport function ensureDirectories(): void {\n const dirs = [\n paths.root,\n paths.memory,\n paths.interactions,\n paths.compacted,\n paths.queue,\n paths.logs,\n ];\n\n for (const dir of dirs) {\n if (!existsSync(dir)) {\n mkdirSync(dir, { recursive: true });\n }\n }\n}\n\nexport function sporaExists(): boolean {\n return existsSync(paths.config) && existsSync(paths.identity);\n}\n\nexport function hasXCredentials(): boolean {\n return existsSync(paths.credentials);\n}\n"],"mappings":";AAAA,SAAS,eAAe;AACxB,SAAS,YAAY;AACrB,SAAS,WAAW,kBAAkB;AAEtC,IAAM,YAAY,KAAK,QAAQ,GAAG,QAAQ;AAEnC,IAAM,QAAQ;AAAA,EACnB,MAAM;AAAA,EACN,QAAQ,KAAK,WAAW,aAAa;AAAA,EACrC,aAAa,KAAK,WAAW,kBAAkB;AAAA,EAC/C,OAAO,KAAK,WAAW,YAAY;AAAA,EACnC,UAAU,KAAK,WAAW,eAAe;AAAA,EACzC,aAAa,KAAK,WAAW,mBAAmB;AAAA,EAChD,SAAS,KAAK,WAAW,SAAS;AAAA,EAClC,aAAa,KAAK,WAAW,WAAW,iBAAiB;AAAA,EACzD,QAAQ,KAAK,WAAW,QAAQ;AAAA,EAChC,cAAc,KAAK,WAAW,UAAU,cAAc;AAAA,EACtD,WAAW,KAAK,WAAW,UAAU,gBAAgB;AAAA,EACrD,eAAe,KAAK,WAAW,UAAU,oBAAoB;AAAA,EAC7D,UAAU,KAAK,WAAW,UAAU,eAAe;AAAA,EACnD,OAAO,KAAK,WAAW,UAAU,YAAY;AAAA,EAC7C,aAAa,KAAK,WAAW,UAAU,kBAAkB;AAAA,EACzD,WAAW,KAAK,WAAW,UAAU,WAAW;AAAA,EAChD,OAAO,KAAK,WAAW,OAAO;AAAA,EAC9B,cAAc,KAAK,WAAW,SAAS,oBAAoB;AAAA,EAC3D,MAAM,KAAK,WAAW,MAAM;AAAA,EAC5B,SAAS,KAAK,WAAW,QAAQ,WAAW;AAAA,EAC5C,gBAAgB,KAAK,WAAW,QAAQ,uBAAuB;AAAA,EAC/D,SAAS;AAAA,EACT,QAAQ,KAAK,WAAW,SAAS;AAAA,EACjC,SAAS,KAAK,WAAW,eAAe;AAAA,EACxC,YAAY,KAAK,WAAW,aAAa;AAAA,EACzC,YAAY,KAAK,WAAW,MAAM;AAAA,EAClC,iBAAiB,KAAK,WAAW,kBAAkB;AACrD;AAEO,SAAS,oBAA0B;AACxC,QAAM,OAAO;AAAA,IACX,MAAM;AAAA,IACN,MAAM;AAAA,IACN,MAAM;AAAA,IACN,MAAM;AAAA,IACN,MAAM;AAAA,IACN,MAAM;AAAA,EACR;AAEA,aAAW,OAAO,MAAM;AACtB,QAAI,CAAC,WAAW,GAAG,GAAG;AACpB,gBAAU,KAAK,EAAE,WAAW,KAAK,CAAC;AAAA,IACpC;AAAA,EACF;AACF;AAEO,SAAS,cAAuB;AACrC,SAAO,WAAW,MAAM,MAAM,KAAK,WAAW,MAAM,QAAQ;AAC9D;AAEO,SAAS,kBAA2B;AACzC,SAAO,WAAW,MAAM,WAAW;AACrC;","names":[]}
|
package/dist/chunk-4LNMA56H.js
DELETED
|
@@ -1,57 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
logger
|
|
3
|
-
} from "./chunk-YMGJQRKG.js";
|
|
4
|
-
import {
|
|
5
|
-
loadConfig,
|
|
6
|
-
saveConfig
|
|
7
|
-
} from "./chunk-NO3NQN67.js";
|
|
8
|
-
|
|
9
|
-
// src/x-client/rate-limiter.ts
|
|
10
|
-
var RateLimiter = class {
|
|
11
|
-
checkResetDate() {
|
|
12
|
-
const config = loadConfig();
|
|
13
|
-
const now = /* @__PURE__ */ new Date();
|
|
14
|
-
const resetDate = new Date(config.credits.resetDate);
|
|
15
|
-
if (now >= resetDate) {
|
|
16
|
-
config.credits.postsUsedThisMonth = 0;
|
|
17
|
-
const nextReset = new Date(now.getFullYear(), now.getMonth() + 1, 1);
|
|
18
|
-
config.credits.resetDate = nextReset.toISOString();
|
|
19
|
-
saveConfig(config);
|
|
20
|
-
logger.info("Monthly credits reset");
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
canPost() {
|
|
24
|
-
this.checkResetDate();
|
|
25
|
-
const config = loadConfig();
|
|
26
|
-
return config.credits.postsUsedThisMonth < config.credits.monthlyPostLimit;
|
|
27
|
-
}
|
|
28
|
-
remaining() {
|
|
29
|
-
this.checkResetDate();
|
|
30
|
-
const config = loadConfig();
|
|
31
|
-
return config.credits.monthlyPostLimit - config.credits.postsUsedThisMonth;
|
|
32
|
-
}
|
|
33
|
-
consume(count = 1) {
|
|
34
|
-
this.checkResetDate();
|
|
35
|
-
const config = loadConfig();
|
|
36
|
-
config.credits.postsUsedThisMonth += count;
|
|
37
|
-
saveConfig(config);
|
|
38
|
-
const remaining = config.credits.monthlyPostLimit - config.credits.postsUsedThisMonth;
|
|
39
|
-
if (remaining <= Math.floor(config.credits.monthlyPostLimit * 0.2)) {
|
|
40
|
-
logger.warn(`Low credits: ${remaining} posts remaining this month`);
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
requireBasicTier(action) {
|
|
44
|
-
const config = loadConfig();
|
|
45
|
-
if (config.xMethod === "api" && config.xApiTier !== "basic") {
|
|
46
|
-
throw new Error(
|
|
47
|
-
`${action} requires X API Basic tier ($200/mo). Current tier: ${config.xApiTier ?? "free"}. Upgrade your API tier or adjust runtime behavior.`
|
|
48
|
-
);
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
};
|
|
52
|
-
var rateLimiter = new RateLimiter();
|
|
53
|
-
|
|
54
|
-
export {
|
|
55
|
-
rateLimiter
|
|
56
|
-
};
|
|
57
|
-
//# sourceMappingURL=chunk-4LNMA56H.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/x-client/rate-limiter.ts"],"sourcesContent":["import { loadConfig, saveConfig } from \"../utils/config.js\";\nimport { logger } from \"../utils/logger.js\";\n\nexport class RateLimiter {\n private checkResetDate(): void {\n const config = loadConfig();\n const now = new Date();\n const resetDate = new Date(config.credits.resetDate);\n\n if (now >= resetDate) {\n config.credits.postsUsedThisMonth = 0;\n const nextReset = new Date(now.getFullYear(), now.getMonth() + 1, 1);\n config.credits.resetDate = nextReset.toISOString();\n saveConfig(config);\n logger.info(\"Monthly credits reset\");\n }\n }\n\n canPost(): boolean {\n this.checkResetDate();\n const config = loadConfig();\n return config.credits.postsUsedThisMonth < config.credits.monthlyPostLimit;\n }\n\n remaining(): number {\n this.checkResetDate();\n const config = loadConfig();\n return config.credits.monthlyPostLimit - config.credits.postsUsedThisMonth;\n }\n\n consume(count: number = 1): void {\n this.checkResetDate();\n const config = loadConfig();\n config.credits.postsUsedThisMonth += count;\n saveConfig(config);\n\n const remaining = config.credits.monthlyPostLimit - config.credits.postsUsedThisMonth;\n if (remaining <= Math.floor(config.credits.monthlyPostLimit * 0.2)) {\n logger.warn(`Low credits: ${remaining} posts remaining this month`);\n }\n }\n\n requireBasicTier(action: string): void {\n const config = loadConfig();\n if (config.xMethod === \"api\" && config.xApiTier !== \"basic\") {\n throw new Error(\n `${action} requires X API Basic tier ($200/mo). ` +\n `Current tier: ${config.xApiTier ?? \"free\"}. ` +\n `Upgrade your API tier or adjust runtime behavior.`\n );\n }\n }\n}\n\nexport const rateLimiter = new RateLimiter();\n"],"mappings":";;;;;;;;;AAGO,IAAM,cAAN,MAAkB;AAAA,EACf,iBAAuB;AAC7B,UAAM,SAAS,WAAW;AAC1B,UAAM,MAAM,oBAAI,KAAK;AACrB,UAAM,YAAY,IAAI,KAAK,OAAO,QAAQ,SAAS;AAEnD,QAAI,OAAO,WAAW;AACpB,aAAO,QAAQ,qBAAqB;AACpC,YAAM,YAAY,IAAI,KAAK,IAAI,YAAY,GAAG,IAAI,SAAS,IAAI,GAAG,CAAC;AACnE,aAAO,QAAQ,YAAY,UAAU,YAAY;AACjD,iBAAW,MAAM;AACjB,aAAO,KAAK,uBAAuB;AAAA,IACrC;AAAA,EACF;AAAA,EAEA,UAAmB;AACjB,SAAK,eAAe;AACpB,UAAM,SAAS,WAAW;AAC1B,WAAO,OAAO,QAAQ,qBAAqB,OAAO,QAAQ;AAAA,EAC5D;AAAA,EAEA,YAAoB;AAClB,SAAK,eAAe;AACpB,UAAM,SAAS,WAAW;AAC1B,WAAO,OAAO,QAAQ,mBAAmB,OAAO,QAAQ;AAAA,EAC1D;AAAA,EAEA,QAAQ,QAAgB,GAAS;AAC/B,SAAK,eAAe;AACpB,UAAM,SAAS,WAAW;AAC1B,WAAO,QAAQ,sBAAsB;AACrC,eAAW,MAAM;AAEjB,UAAM,YAAY,OAAO,QAAQ,mBAAmB,OAAO,QAAQ;AACnE,QAAI,aAAa,KAAK,MAAM,OAAO,QAAQ,mBAAmB,GAAG,GAAG;AAClE,aAAO,KAAK,gBAAgB,SAAS,6BAA6B;AAAA,IACpE;AAAA,EACF;AAAA,EAEA,iBAAiB,QAAsB;AACrC,UAAM,SAAS,WAAW;AAC1B,QAAI,OAAO,YAAY,SAAS,OAAO,aAAa,SAAS;AAC3D,YAAM,IAAI;AAAA,QACR,GAAG,MAAM,uDACU,OAAO,YAAY,MAAM;AAAA,MAE9C;AAAA,IACF;AAAA,EACF;AACF;AAEO,IAAM,cAAc,IAAI,YAAY;","names":[]}
|