spora 0.7.3 → 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-HGNMHGAF.js → chunk-5R4AJZHN.js} +4 -4
- package/dist/{chunk-HGNMHGAF.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-VZBHRUZS.js → chunk-SXNZVKLJ.js} +2 -2
- package/dist/chunk-SXNZVKLJ.js.map +1 -0
- package/dist/{chunk-7OOGNZBU.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-4KGOBIXE.js → client-AR5ZD6S4.js} +48 -16
- package/dist/client-AR5ZD6S4.js.map +1 -0
- package/dist/{colony-IVYR233C.js → colony-UGVYALOS.js} +7 -7
- package/dist/{config-FL4VJVKZ.js → config-MU2ODEO3.js} +3 -3
- package/dist/{crypto-NOXNL4GP.js → crypto-GDG5K3ZH.js} +3 -3
- package/dist/{goals-RBKLMILE.js → goals-QWX3A47Y.js} +3 -3
- package/dist/{heartbeat-CUL2FTFD.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-2REECUVH.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/chat.html +190 -3
- package/dist/{web-chat-O24HGJVE.js → web-chat-TB3ACPVF.js} +125 -32
- 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-6UWPXTPD.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-7OOGNZBU.js.map +0 -1
- package/dist/chunk-M6YOQVSI.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/chunk-VZBHRUZS.js.map +0 -1
- package/dist/chunk-ZBP2ROAZ.js +0 -377
- package/dist/chunk-ZBP2ROAZ.js.map +0 -1
- package/dist/client-4KGOBIXE.js.map +0 -1
- package/dist/heartbeat-CUL2FTFD.js.map +0 -1
- package/dist/init-2REECUVH.js.map +0 -1
- package/dist/prompt-builder-KJKFCGM7.js +0 -25
- package/dist/queue-D3MRKABU.js +0 -14
- package/dist/strategy-Z4JSFHSP.js +0 -12
- package/dist/web-chat-O24HGJVE.js.map +0 -1
- package/dist/x-client-ASXVQ6EV.js +0 -12
- /package/dist/{autonomy-6UWPXTPD.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/{colony-IVYR233C.js.map → colony-UGVYALOS.js.map} +0 -0
- /package/dist/{config-FL4VJVKZ.js.map → config-MU2ODEO3.js.map} +0 -0
- /package/dist/{crypto-NOXNL4GP.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-D3MRKABU.js.map → queue-QCGNDHH2.js.map} +0 -0
- /package/dist/{strategy-Z4JSFHSP.js.map → strategy-R2BMRVJ3.js.map} +0 -0
- /package/dist/{x-client-ASXVQ6EV.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
|
package/dist/web-chat/chat.html
CHANGED
|
@@ -38,7 +38,7 @@
|
|
|
38
38
|
margin-left: auto;
|
|
39
39
|
display: flex;
|
|
40
40
|
align-items: center;
|
|
41
|
-
gap: 0.
|
|
41
|
+
gap: 0.75rem;
|
|
42
42
|
}
|
|
43
43
|
|
|
44
44
|
.status-dot {
|
|
@@ -54,6 +54,82 @@
|
|
|
54
54
|
color: rgba(255, 255, 255, 0.4);
|
|
55
55
|
}
|
|
56
56
|
|
|
57
|
+
.heartbeat-menu {
|
|
58
|
+
position: relative;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
.heartbeat-trigger {
|
|
62
|
+
width: 30px;
|
|
63
|
+
height: 30px;
|
|
64
|
+
border-radius: 999px;
|
|
65
|
+
border: 1px solid rgba(255, 255, 255, 0.15);
|
|
66
|
+
background: #141414;
|
|
67
|
+
color: #ff647d;
|
|
68
|
+
cursor: pointer;
|
|
69
|
+
font-size: 0.95rem;
|
|
70
|
+
line-height: 1;
|
|
71
|
+
display: inline-flex;
|
|
72
|
+
align-items: center;
|
|
73
|
+
justify-content: center;
|
|
74
|
+
transition: transform 0.15s ease, border-color 0.2s ease;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
.heartbeat-trigger:hover {
|
|
78
|
+
transform: scale(1.06);
|
|
79
|
+
border-color: rgba(255, 100, 125, 0.45);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
.heartbeat-trigger:disabled {
|
|
83
|
+
opacity: 0.4;
|
|
84
|
+
cursor: not-allowed;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
.heartbeat-popover {
|
|
88
|
+
position: absolute;
|
|
89
|
+
right: 0;
|
|
90
|
+
top: calc(100% + 0.45rem);
|
|
91
|
+
min-width: 150px;
|
|
92
|
+
background: #111111;
|
|
93
|
+
border: 1px solid rgba(255, 255, 255, 0.14);
|
|
94
|
+
border-radius: 0.7rem;
|
|
95
|
+
padding: 0.5rem;
|
|
96
|
+
z-index: 10;
|
|
97
|
+
box-shadow: 0 8px 18px rgba(0, 0, 0, 0.45);
|
|
98
|
+
animation: fadeIn 0.18s ease-in;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
.heartbeat-popover-title {
|
|
102
|
+
font-size: 0.67rem;
|
|
103
|
+
color: rgba(255, 255, 255, 0.44);
|
|
104
|
+
margin-bottom: 0.35rem;
|
|
105
|
+
padding: 0 0.2rem;
|
|
106
|
+
text-transform: uppercase;
|
|
107
|
+
letter-spacing: 0.04em;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
.heartbeat-option {
|
|
111
|
+
width: 100%;
|
|
112
|
+
border: 1px solid transparent;
|
|
113
|
+
background: transparent;
|
|
114
|
+
color: rgba(255, 255, 255, 0.88);
|
|
115
|
+
padding: 0.42rem 0.5rem;
|
|
116
|
+
font-size: 0.75rem;
|
|
117
|
+
text-align: left;
|
|
118
|
+
border-radius: 0.5rem;
|
|
119
|
+
cursor: pointer;
|
|
120
|
+
transition: background 0.18s ease, border-color 0.18s ease;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
.heartbeat-option:hover {
|
|
124
|
+
background: rgba(255, 255, 255, 0.06);
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
.heartbeat-option.active {
|
|
128
|
+
border-color: rgba(56, 158, 119, 0.65);
|
|
129
|
+
background: rgba(56, 158, 119, 0.16);
|
|
130
|
+
color: #89dbba;
|
|
131
|
+
}
|
|
132
|
+
|
|
57
133
|
@keyframes pulse {
|
|
58
134
|
0%, 100% { opacity: 1; }
|
|
59
135
|
50% { opacity: 0.5; }
|
|
@@ -328,7 +404,18 @@
|
|
|
328
404
|
</svg>
|
|
329
405
|
<div class="header-right">
|
|
330
406
|
<span class="status-dot"></span>
|
|
331
|
-
<span class="status-text">Online</span>
|
|
407
|
+
<span class="status-text" id="statusText">Online</span>
|
|
408
|
+
<div class="heartbeat-menu" id="heartbeatMenu">
|
|
409
|
+
<button class="heartbeat-trigger" id="heartbeatTrigger" title="Heartbeat settings" aria-label="Heartbeat settings">♥</button>
|
|
410
|
+
<div class="heartbeat-popover" id="heartbeatPopover" hidden>
|
|
411
|
+
<div class="heartbeat-popover-title">Heartbeat</div>
|
|
412
|
+
<button class="heartbeat-option" data-interval="60000">1 min</button>
|
|
413
|
+
<button class="heartbeat-option" data-interval="300000">5 min</button>
|
|
414
|
+
<button class="heartbeat-option" data-interval="1800000">30 min</button>
|
|
415
|
+
<button class="heartbeat-option" data-interval="3600000">1 hour</button>
|
|
416
|
+
<button class="heartbeat-option" data-interval="21600000">6 hours</button>
|
|
417
|
+
</div>
|
|
418
|
+
</div>
|
|
332
419
|
</div>
|
|
333
420
|
</div>
|
|
334
421
|
|
|
@@ -350,12 +437,86 @@
|
|
|
350
437
|
const chatContainer = document.getElementById('chatContainer');
|
|
351
438
|
const messageInput = document.getElementById('messageInput');
|
|
352
439
|
const sendButton = document.getElementById('sendButton');
|
|
440
|
+
const heartbeatMenu = document.getElementById('heartbeatMenu');
|
|
441
|
+
const heartbeatTrigger = document.getElementById('heartbeatTrigger');
|
|
442
|
+
const heartbeatPopover = document.getElementById('heartbeatPopover');
|
|
443
|
+
const heartbeatOptions = Array.from(document.querySelectorAll('.heartbeat-option'));
|
|
444
|
+
const statusText = document.getElementById('statusText');
|
|
353
445
|
|
|
354
446
|
let isLoading = false;
|
|
355
447
|
let agentName = 'Your Spore';
|
|
356
448
|
let agentHandle = '';
|
|
357
449
|
let agentPfp = null;
|
|
358
450
|
let sleepTimerId = null;
|
|
451
|
+
let heartbeatMs = 300000;
|
|
452
|
+
|
|
453
|
+
const HEARTBEAT_LABELS = {
|
|
454
|
+
60000: '1 min',
|
|
455
|
+
300000: '5 min',
|
|
456
|
+
1800000: '30 min',
|
|
457
|
+
3600000: '1 hour',
|
|
458
|
+
21600000: '6 hours',
|
|
459
|
+
};
|
|
460
|
+
|
|
461
|
+
function heartbeatLabel(ms) {
|
|
462
|
+
return HEARTBEAT_LABELS[ms] || `${Math.round(ms / 60000)} min`;
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
function updateStatusText() {
|
|
466
|
+
statusText.textContent = `Online • ${heartbeatLabel(heartbeatMs)} heartbeat`;
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
function setHeartbeatPopoverOpen(isOpen) {
|
|
470
|
+
heartbeatPopover.hidden = !isOpen;
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
function updateHeartbeatOptions() {
|
|
474
|
+
for (const option of heartbeatOptions) {
|
|
475
|
+
const value = parseInt(option.dataset.interval || '0', 10);
|
|
476
|
+
option.classList.toggle('active', value === heartbeatMs);
|
|
477
|
+
}
|
|
478
|
+
}
|
|
479
|
+
|
|
480
|
+
async function loadHeartbeatConfig() {
|
|
481
|
+
try {
|
|
482
|
+
const response = await fetch('/api/heartbeat-config');
|
|
483
|
+
if (!response.ok) return;
|
|
484
|
+
const data = await response.json();
|
|
485
|
+
if (data.intervalMs) {
|
|
486
|
+
heartbeatMs = data.intervalMs;
|
|
487
|
+
updateStatusText();
|
|
488
|
+
updateHeartbeatOptions();
|
|
489
|
+
}
|
|
490
|
+
} catch {
|
|
491
|
+
// best effort
|
|
492
|
+
}
|
|
493
|
+
}
|
|
494
|
+
|
|
495
|
+
async function setHeartbeatConfig(intervalMs) {
|
|
496
|
+
const previous = heartbeatMs;
|
|
497
|
+
heartbeatTrigger.disabled = true;
|
|
498
|
+
setHeartbeatPopoverOpen(false);
|
|
499
|
+
try {
|
|
500
|
+
const response = await fetch('/api/heartbeat-config', {
|
|
501
|
+
method: 'POST',
|
|
502
|
+
headers: { 'Content-Type': 'application/json' },
|
|
503
|
+
body: JSON.stringify({ intervalMs }),
|
|
504
|
+
});
|
|
505
|
+
if (!response.ok) {
|
|
506
|
+
throw new Error('Failed to update heartbeat');
|
|
507
|
+
}
|
|
508
|
+
heartbeatMs = intervalMs;
|
|
509
|
+
updateStatusText();
|
|
510
|
+
updateHeartbeatOptions();
|
|
511
|
+
addNarration(`Heartbeat updated to ${heartbeatLabel(intervalMs)}`, 'action');
|
|
512
|
+
} catch {
|
|
513
|
+
heartbeatMs = previous;
|
|
514
|
+
updateHeartbeatOptions();
|
|
515
|
+
addNarration('Could not update heartbeat interval', 'error');
|
|
516
|
+
} finally {
|
|
517
|
+
heartbeatTrigger.disabled = false;
|
|
518
|
+
}
|
|
519
|
+
}
|
|
359
520
|
|
|
360
521
|
// ===== Init =====
|
|
361
522
|
async function init() {
|
|
@@ -372,6 +533,7 @@
|
|
|
372
533
|
console.error('Failed to load identity:', error);
|
|
373
534
|
}
|
|
374
535
|
|
|
536
|
+
await loadHeartbeatConfig();
|
|
375
537
|
addMessage('assistant', `Hey! I'm ${agentName}. I run on my own — posting, replying, exploring X during my heartbeat cycles. You can shape who I am by chatting with me here.`);
|
|
376
538
|
await loadMessages();
|
|
377
539
|
}
|
|
@@ -480,7 +642,6 @@
|
|
|
480
642
|
|
|
481
643
|
// ===== Narration =====
|
|
482
644
|
function addNarration(text, type) {
|
|
483
|
-
removeSleepCard();
|
|
484
645
|
const el = document.createElement('div');
|
|
485
646
|
el.className = 'narration';
|
|
486
647
|
const dot = document.createElement('div');
|
|
@@ -588,6 +749,30 @@
|
|
|
588
749
|
}
|
|
589
750
|
|
|
590
751
|
sendButton.addEventListener('click', sendMessage);
|
|
752
|
+
heartbeatTrigger.addEventListener('click', (e) => {
|
|
753
|
+
e.preventDefault();
|
|
754
|
+
e.stopPropagation();
|
|
755
|
+
setHeartbeatPopoverOpen(heartbeatPopover.hidden);
|
|
756
|
+
});
|
|
757
|
+
|
|
758
|
+
heartbeatPopover.addEventListener('click', (e) => {
|
|
759
|
+
const target = e.target.closest('.heartbeat-option');
|
|
760
|
+
if (!target) return;
|
|
761
|
+
const intervalMs = parseInt(target.dataset.interval || '0', 10);
|
|
762
|
+
if (!Number.isFinite(intervalMs)) return;
|
|
763
|
+
if (intervalMs === heartbeatMs) {
|
|
764
|
+
setHeartbeatPopoverOpen(false);
|
|
765
|
+
return;
|
|
766
|
+
}
|
|
767
|
+
setHeartbeatConfig(intervalMs);
|
|
768
|
+
});
|
|
769
|
+
|
|
770
|
+
document.addEventListener('click', (e) => {
|
|
771
|
+
if (!heartbeatMenu.contains(e.target)) {
|
|
772
|
+
setHeartbeatPopoverOpen(false);
|
|
773
|
+
}
|
|
774
|
+
});
|
|
775
|
+
|
|
591
776
|
messageInput.addEventListener('keydown', (e) => {
|
|
592
777
|
if (e.key === 'Enter' && !e.shiftKey) {
|
|
593
778
|
e.preventDefault();
|
|
@@ -642,6 +827,8 @@
|
|
|
642
827
|
setInterval(pollAgentEvents, 2000);
|
|
643
828
|
|
|
644
829
|
// Initialize
|
|
830
|
+
updateStatusText();
|
|
831
|
+
updateHeartbeatOptions();
|
|
645
832
|
init();
|
|
646
833
|
messageInput.focus();
|
|
647
834
|
</script>
|
|
@@ -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";
|
|
@@ -11,6 +11,7 @@ import { join, dirname } from "path";
|
|
|
11
11
|
import { fileURLToPath } from "url";
|
|
12
12
|
var __filename = fileURLToPath(import.meta.url);
|
|
13
13
|
var __dirname = dirname(__filename);
|
|
14
|
+
var ALLOWED_HEARTBEAT_INTERVALS = [6e4, 3e5, 18e5, 36e5, 216e5];
|
|
14
15
|
var WebChatServer = class {
|
|
15
16
|
server = null;
|
|
16
17
|
port;
|
|
@@ -19,6 +20,7 @@ var WebChatServer = class {
|
|
|
19
20
|
agentEvents = [];
|
|
20
21
|
onUserMessage;
|
|
21
22
|
identity;
|
|
23
|
+
heartbeatConfigHandlers;
|
|
22
24
|
constructor(port = 3737) {
|
|
23
25
|
this.port = port;
|
|
24
26
|
}
|
|
@@ -28,6 +30,9 @@ var WebChatServer = class {
|
|
|
28
30
|
setMessageHandler(handler) {
|
|
29
31
|
this.onUserMessage = handler;
|
|
30
32
|
}
|
|
33
|
+
setHeartbeatConfigHandlers(handlers) {
|
|
34
|
+
this.heartbeatConfigHandlers = handlers;
|
|
35
|
+
}
|
|
31
36
|
/** Push an activity update (from heartbeat) to the UI — kept for backwards compat */
|
|
32
37
|
pushActivity(type, message) {
|
|
33
38
|
this.activities.push({ type, message, timestamp: Date.now() });
|
|
@@ -109,6 +114,52 @@ var WebChatServer = class {
|
|
|
109
114
|
res.end(JSON.stringify({ events: newEvents }));
|
|
110
115
|
return;
|
|
111
116
|
}
|
|
117
|
+
if (url.pathname === "/api/heartbeat-config" && req.method === "GET") {
|
|
118
|
+
if (!this.heartbeatConfigHandlers) {
|
|
119
|
+
res.writeHead(503, { "Content-Type": "application/json" });
|
|
120
|
+
res.end(JSON.stringify({ error: "Heartbeat config unavailable" }));
|
|
121
|
+
return;
|
|
122
|
+
}
|
|
123
|
+
try {
|
|
124
|
+
const intervalMs = await this.heartbeatConfigHandlers.getIntervalMs();
|
|
125
|
+
res.writeHead(200, { "Content-Type": "application/json" });
|
|
126
|
+
res.end(JSON.stringify({ intervalMs, allowedIntervals: ALLOWED_HEARTBEAT_INTERVALS }));
|
|
127
|
+
} catch {
|
|
128
|
+
res.writeHead(500, { "Content-Type": "application/json" });
|
|
129
|
+
res.end(JSON.stringify({ error: "Failed to load heartbeat config" }));
|
|
130
|
+
}
|
|
131
|
+
return;
|
|
132
|
+
}
|
|
133
|
+
if (url.pathname === "/api/heartbeat-config" && req.method === "POST") {
|
|
134
|
+
if (!this.heartbeatConfigHandlers) {
|
|
135
|
+
res.writeHead(503, { "Content-Type": "application/json" });
|
|
136
|
+
res.end(JSON.stringify({ error: "Heartbeat config unavailable" }));
|
|
137
|
+
return;
|
|
138
|
+
}
|
|
139
|
+
const handlers = this.heartbeatConfigHandlers;
|
|
140
|
+
let body = "";
|
|
141
|
+
req.on("data", (chunk) => {
|
|
142
|
+
body += chunk.toString();
|
|
143
|
+
});
|
|
144
|
+
req.on("end", async () => {
|
|
145
|
+
try {
|
|
146
|
+
const parsed = JSON.parse(body);
|
|
147
|
+
const intervalMs = parsed.intervalMs;
|
|
148
|
+
if (typeof intervalMs !== "number" || !Number.isInteger(intervalMs) || !ALLOWED_HEARTBEAT_INTERVALS.includes(intervalMs)) {
|
|
149
|
+
res.writeHead(400, { "Content-Type": "application/json" });
|
|
150
|
+
res.end(JSON.stringify({ error: "Unsupported heartbeat interval" }));
|
|
151
|
+
return;
|
|
152
|
+
}
|
|
153
|
+
await handlers.setIntervalMs(intervalMs);
|
|
154
|
+
res.writeHead(200, { "Content-Type": "application/json" });
|
|
155
|
+
res.end(JSON.stringify({ success: true, intervalMs }));
|
|
156
|
+
} catch {
|
|
157
|
+
res.writeHead(400, { "Content-Type": "application/json" });
|
|
158
|
+
res.end(JSON.stringify({ error: "Invalid request" }));
|
|
159
|
+
}
|
|
160
|
+
});
|
|
161
|
+
return;
|
|
162
|
+
}
|
|
112
163
|
if (url.pathname === "/api/message" && req.method === "POST") {
|
|
113
164
|
let body = "";
|
|
114
165
|
req.on("data", (chunk) => {
|
|
@@ -171,11 +222,18 @@ var WebChatServer = class {
|
|
|
171
222
|
// src/web-chat/index.ts
|
|
172
223
|
import { execSync } from "child_process";
|
|
173
224
|
import chalk from "chalk";
|
|
225
|
+
var HEARTBEAT_INTERVAL_OPTIONS = [6e4, 3e5, 18e5, 36e5, 216e5];
|
|
226
|
+
function formatHeartbeatInterval(intervalMs) {
|
|
227
|
+
const minutes = intervalMs / 6e4;
|
|
228
|
+
if (minutes < 60) return `${minutes} minute${minutes === 1 ? "" : "s"}`;
|
|
229
|
+
const hours = minutes / 60;
|
|
230
|
+
return `${hours} hour${hours === 1 ? "" : "s"}`;
|
|
231
|
+
}
|
|
174
232
|
async function extractAndSaveLearnings(responseText) {
|
|
175
233
|
const learnPattern = /<<LEARN:\s*(.+?)>>/g;
|
|
176
234
|
const matches = [...responseText.matchAll(learnPattern)];
|
|
177
235
|
if (matches.length > 0) {
|
|
178
|
-
const { addLearning } = await import("./memory-
|
|
236
|
+
const { addLearning } = await import("./memory-DTSLVSQG.js");
|
|
179
237
|
for (const match of matches) {
|
|
180
238
|
const learning = match[1].trim();
|
|
181
239
|
addLearning(learning, "web-chat", ["chat", "creator-interaction"]);
|
|
@@ -191,7 +249,7 @@ async function extractAndApplyTraining(responseText) {
|
|
|
191
249
|
try {
|
|
192
250
|
const update = JSON.parse(match[1].trim());
|
|
193
251
|
if (update.identity) {
|
|
194
|
-
const { loadIdentity: loadIdentity2, mutateIdentity, saveIdentity } = await import("./identity-
|
|
252
|
+
const { loadIdentity: loadIdentity2, mutateIdentity, saveIdentity } = await import("./identity-ASHVWIN5.js");
|
|
195
253
|
let identity = loadIdentity2();
|
|
196
254
|
const identityFields = {
|
|
197
255
|
tone: "tone",
|
|
@@ -230,7 +288,7 @@ async function extractAndApplyTraining(responseText) {
|
|
|
230
288
|
saveIdentity(identity);
|
|
231
289
|
}
|
|
232
290
|
if (update.strategy) {
|
|
233
|
-
const { loadStrategy, saveStrategy } = await import("./strategy-
|
|
291
|
+
const { loadStrategy, saveStrategy } = await import("./strategy-R2BMRVJ3.js");
|
|
234
292
|
const strategy = loadStrategy();
|
|
235
293
|
if (update.strategy.currentFocus) strategy.currentFocus = update.strategy.currentFocus;
|
|
236
294
|
if (update.strategy.shortTermGoals) strategy.shortTermGoals = update.strategy.shortTermGoals;
|
|
@@ -245,7 +303,7 @@ async function extractAndApplyTraining(responseText) {
|
|
|
245
303
|
console.log(chalk.dim(` [Training] Updated strategy`));
|
|
246
304
|
}
|
|
247
305
|
if (update.learning) {
|
|
248
|
-
const { addLearning } = await import("./memory-
|
|
306
|
+
const { addLearning } = await import("./memory-DTSLVSQG.js");
|
|
249
307
|
addLearning(
|
|
250
308
|
update.learning.content,
|
|
251
309
|
"training-chat",
|
|
@@ -254,7 +312,7 @@ async function extractAndApplyTraining(responseText) {
|
|
|
254
312
|
console.log(chalk.dim(` [Training] Saved learning: ${update.learning.content}`));
|
|
255
313
|
}
|
|
256
314
|
if (update.reflection) {
|
|
257
|
-
const { loadIdentity: loadIdentity2, saveIdentity } = await import("./identity-
|
|
315
|
+
const { loadIdentity: loadIdentity2, saveIdentity } = await import("./identity-ASHVWIN5.js");
|
|
258
316
|
const identity = loadIdentity2();
|
|
259
317
|
identity.evolutionJournal.push({
|
|
260
318
|
date: (/* @__PURE__ */ new Date()).toISOString(),
|
|
@@ -264,7 +322,7 @@ async function extractAndApplyTraining(responseText) {
|
|
|
264
322
|
console.log(chalk.dim(` [Training] Added reflection to evolution journal`));
|
|
265
323
|
}
|
|
266
324
|
if (update.goalUpdates && Array.isArray(update.goalUpdates)) {
|
|
267
|
-
const { loadGoals, saveGoals } = await import("./goals-
|
|
325
|
+
const { loadGoals, saveGoals } = await import("./goals-QWX3A47Y.js");
|
|
268
326
|
const tracker = loadGoals();
|
|
269
327
|
for (const gu of update.goalUpdates) {
|
|
270
328
|
const existing = tracker.goals.find((g) => g.goal === gu.goal);
|
|
@@ -290,7 +348,7 @@ async function extractAndApplyTraining(responseText) {
|
|
|
290
348
|
return responseText.replace(/<<TRAINING:[\s\S]*?>>/g, "").trim();
|
|
291
349
|
}
|
|
292
350
|
async function logChatInteraction(userMessage, agentResponse) {
|
|
293
|
-
const { logInteraction } = await import("./memory-
|
|
351
|
+
const { logInteraction } = await import("./memory-DTSLVSQG.js");
|
|
294
352
|
logInteraction({
|
|
295
353
|
id: `chat-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`,
|
|
296
354
|
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
@@ -302,26 +360,46 @@ async function logChatInteraction(userMessage, agentResponse) {
|
|
|
302
360
|
});
|
|
303
361
|
}
|
|
304
362
|
async function runNarratedHeartbeat(server) {
|
|
305
|
-
const { loadConfig } = await import("./config-
|
|
306
|
-
const { flushQueue } = await import("./queue-
|
|
307
|
-
const { runAutonomyCycle } = await import("./autonomy-
|
|
308
|
-
const { buildReflectionPrompt } = await import("./prompt-builder-
|
|
309
|
-
const { generateResponse } = await import("./llm-
|
|
310
|
-
const { addLearning } = await import("./memory-
|
|
311
|
-
const { loadStrategy, saveStrategy } = await import("./strategy-
|
|
312
|
-
const config = loadConfig();
|
|
313
|
-
const intervalMs = config.runtime?.heartbeatIntervalMs ?? 3e5;
|
|
314
|
-
const maxActions = config.runtime?.actionsPerHeartbeat ?? 4;
|
|
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");
|
|
315
370
|
let heartbeatCount = 0;
|
|
316
|
-
|
|
371
|
+
let lastIntervalMs = loadConfig().runtime?.heartbeatIntervalMs ?? 3e5;
|
|
372
|
+
console.log(chalk.cyan(` [Agent] Autonomous heartbeat started (every ${Math.round(lastIntervalMs / 6e4)} min)`));
|
|
317
373
|
while (true) {
|
|
374
|
+
const runtimeConfig = loadConfig();
|
|
375
|
+
const intervalMs = runtimeConfig.runtime?.heartbeatIntervalMs ?? 3e5;
|
|
376
|
+
const maxActions = runtimeConfig.runtime?.actionsPerHeartbeat ?? 4;
|
|
377
|
+
if (intervalMs !== lastIntervalMs) {
|
|
378
|
+
server.pushAgentEvent("narration", `Heartbeat interval updated to ${formatHeartbeatInterval(intervalMs)}.`);
|
|
379
|
+
console.log(chalk.cyan(` [Agent] Heartbeat interval updated to ${Math.round(intervalMs / 6e4)} min`));
|
|
380
|
+
lastIntervalMs = intervalMs;
|
|
381
|
+
}
|
|
318
382
|
const jitter = Math.floor(Math.random() * intervalMs * 0.3);
|
|
319
383
|
const sleepMs = heartbeatCount === 0 ? 1e4 : intervalMs + jitter;
|
|
320
384
|
const wakeUpAt = Date.now() + sleepMs;
|
|
321
385
|
if (heartbeatCount > 0) {
|
|
322
386
|
server.pushAgentEvent("sleep", "sleeping", { wakeUpAt });
|
|
323
387
|
}
|
|
324
|
-
|
|
388
|
+
let sleptMs = 0;
|
|
389
|
+
let intervalChangedDuringSleep = false;
|
|
390
|
+
while (sleptMs < sleepMs) {
|
|
391
|
+
const chunkMs = Math.min(1e3, sleepMs - sleptMs);
|
|
392
|
+
await new Promise((r) => setTimeout(r, chunkMs));
|
|
393
|
+
sleptMs += chunkMs;
|
|
394
|
+
const liveIntervalMs = loadConfig().runtime?.heartbeatIntervalMs ?? 3e5;
|
|
395
|
+
if (liveIntervalMs !== intervalMs) {
|
|
396
|
+
intervalChangedDuringSleep = true;
|
|
397
|
+
break;
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
if (intervalChangedDuringSleep) {
|
|
401
|
+
continue;
|
|
402
|
+
}
|
|
325
403
|
heartbeatCount++;
|
|
326
404
|
console.log(chalk.cyan(` [Agent] Heartbeat #${heartbeatCount}`));
|
|
327
405
|
server.pushAgentEvent("wake", `Waking up... heartbeat #${heartbeatCount}`);
|
|
@@ -334,7 +412,7 @@ async function runNarratedHeartbeat(server) {
|
|
|
334
412
|
} catch {
|
|
335
413
|
}
|
|
336
414
|
server.pushAgentEvent("narration", "Observing timeline and planning actions...");
|
|
337
|
-
const cycle = await runAutonomyCycle(maxActions);
|
|
415
|
+
const cycle = await runAutonomyCycle(maxActions, heartbeatCount);
|
|
338
416
|
if (cycle.timeline.length > 0 || cycle.mentions.length > 0) {
|
|
339
417
|
server.pushAgentEvent("narration", `Found ${cycle.timeline.length} timeline posts and ${cycle.mentions.length} mentions`);
|
|
340
418
|
}
|
|
@@ -395,12 +473,7 @@ async function runNarratedHeartbeat(server) {
|
|
|
395
473
|
}
|
|
396
474
|
if (reflection.strategyUpdate && reflection.strategyUpdate !== "null") {
|
|
397
475
|
const strategy = loadStrategy();
|
|
398
|
-
strategy.
|
|
399
|
-
description: reflection.strategyUpdate,
|
|
400
|
-
status: "pending"
|
|
401
|
-
});
|
|
402
|
-
strategy.lastUpdated = (/* @__PURE__ */ new Date()).toISOString();
|
|
403
|
-
saveStrategy(strategy);
|
|
476
|
+
saveStrategy(applyStrategyUpdate(strategy, reflection.strategyUpdate));
|
|
404
477
|
server.pushAgentEvent("narration", `Strategy: ${reflection.strategyUpdate}`);
|
|
405
478
|
console.log(chalk.dim(` [Agent] Strategy update: ${reflection.strategyUpdate}`));
|
|
406
479
|
}
|
|
@@ -420,6 +493,7 @@ async function runNarratedHeartbeat(server) {
|
|
|
420
493
|
}
|
|
421
494
|
async function startWebChat() {
|
|
422
495
|
const identity = loadIdentity();
|
|
496
|
+
const { loadConfig: loadRuntimeConfig, saveConfig } = await import("./config-MU2ODEO3.js");
|
|
423
497
|
const server = new WebChatServer();
|
|
424
498
|
server.setIdentity({
|
|
425
499
|
name: identity.name,
|
|
@@ -427,17 +501,36 @@ async function startWebChat() {
|
|
|
427
501
|
bio: identity.bio,
|
|
428
502
|
profileImage: identity.profileImage
|
|
429
503
|
});
|
|
504
|
+
server.setHeartbeatConfigHandlers({
|
|
505
|
+
getIntervalMs: () => {
|
|
506
|
+
const config = loadRuntimeConfig();
|
|
507
|
+
return config.runtime?.heartbeatIntervalMs ?? 3e5;
|
|
508
|
+
},
|
|
509
|
+
setIntervalMs: (intervalMs) => {
|
|
510
|
+
if (!HEARTBEAT_INTERVAL_OPTIONS.includes(intervalMs)) {
|
|
511
|
+
throw new Error("Unsupported heartbeat interval.");
|
|
512
|
+
}
|
|
513
|
+
const config = loadRuntimeConfig();
|
|
514
|
+
config.runtime = {
|
|
515
|
+
heartbeatIntervalMs: intervalMs,
|
|
516
|
+
actionsPerHeartbeat: config.runtime?.actionsPerHeartbeat ?? 4,
|
|
517
|
+
enabled: true
|
|
518
|
+
};
|
|
519
|
+
saveConfig(config);
|
|
520
|
+
server.pushAgentEvent("narration", `Heartbeat interval set to ${formatHeartbeatInterval(intervalMs)}.`);
|
|
521
|
+
}
|
|
522
|
+
});
|
|
430
523
|
const chatHistory = [];
|
|
431
524
|
let systemPrompt = null;
|
|
432
525
|
let messageCount = 0;
|
|
433
526
|
server.setMessageHandler(async (message) => {
|
|
434
527
|
try {
|
|
435
528
|
if (!systemPrompt || messageCount % 10 === 0) {
|
|
436
|
-
const { buildTrainingChatPrompt } = await import("./prompt-builder-
|
|
529
|
+
const { buildTrainingChatPrompt } = await import("./prompt-builder-XJHXZCSQ.js");
|
|
437
530
|
systemPrompt = buildTrainingChatPrompt();
|
|
438
531
|
}
|
|
439
532
|
messageCount++;
|
|
440
|
-
const { hasLLMKey, chat: chatLLM } = await import("./llm-
|
|
533
|
+
const { hasLLMKey, chat: chatLLM } = await import("./llm-IJBRQ7O2.js");
|
|
441
534
|
if (!hasLLMKey()) {
|
|
442
535
|
return "I can't respond right now - no API key configured. Run `spora llm set --provider <provider>` to set one up.";
|
|
443
536
|
}
|
|
@@ -463,7 +556,7 @@ async function startWebChat() {
|
|
|
463
556
|
`));
|
|
464
557
|
openBrowser(url);
|
|
465
558
|
try {
|
|
466
|
-
const { hasLLMKey } = await import("./llm-
|
|
559
|
+
const { hasLLMKey } = await import("./llm-IJBRQ7O2.js");
|
|
467
560
|
if (hasLLMKey()) {
|
|
468
561
|
runNarratedHeartbeat(server).catch((err) => {
|
|
469
562
|
console.error(chalk.red(`Heartbeat failed to start: ${err}`));
|
|
@@ -516,4 +609,4 @@ export {
|
|
|
516
609
|
openBrowser,
|
|
517
610
|
startWebChat
|
|
518
611
|
};
|
|
519
|
-
//# sourceMappingURL=web-chat-
|
|
612
|
+
//# sourceMappingURL=web-chat-TB3ACPVF.js.map
|