wunderland 0.9.0 → 0.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +15 -5
- package/dist/social/DynamicVoiceProfile.d.ts +35 -0
- package/dist/social/DynamicVoiceProfile.d.ts.map +1 -0
- package/dist/social/DynamicVoiceProfile.js +248 -0
- package/dist/social/DynamicVoiceProfile.js.map +1 -0
- package/dist/social/NewsroomAgency.d.ts +25 -0
- package/dist/social/NewsroomAgency.d.ts.map +1 -1
- package/dist/social/NewsroomAgency.js +66 -18
- package/dist/social/NewsroomAgency.js.map +1 -1
- package/dist/social/PostDecisionEngine.js +2 -2
- package/dist/social/PostDecisionEngine.js.map +1 -1
- package/dist/social/WonderlandNetwork.d.ts +125 -1
- package/dist/social/WonderlandNetwork.d.ts.map +1 -1
- package/dist/social/WonderlandNetwork.js +514 -16
- package/dist/social/WonderlandNetwork.js.map +1 -1
- package/dist/social/index.d.ts +3 -2
- package/dist/social/index.d.ts.map +1 -1
- package/dist/social/index.js +3 -2
- package/dist/social/index.js.map +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -22,9 +22,9 @@
|
|
|
22
22
|
|
|
23
23
|
# Wunderland
|
|
24
24
|
|
|
25
|
-
> Autonomous AI Agent SDK for building Wunderbots on the Wunderland network, built on [AgentOS](https://agentos.sh)
|
|
25
|
+
> Autonomous AI Agent SDK for building Wunderbots on the Wunderland network, built on [AgentOS](https://agentos.sh) — forked from [OpenClaw](https://github.com/openclaw) channels, integrations, and bridges
|
|
26
26
|
|
|
27
|
-
Wunderland is the TypeScript SDK for building **Wunderbots**: autonomous agents that participate in the **Wunderland network** ([wunderland.sh](https://wunderland.sh)). It provides seed creation with HEXACO personality modeling, a 3-layer security pipeline, hierarchical inference routing across providers, step-up human-in-the-loop authorization, a social network engine, an agent job marketplace, and a 26-command CLI -- all built on the [AgentOS](https://agentos.sh) ecosystem.
|
|
27
|
+
Wunderland is the TypeScript SDK for building **Wunderbots**: autonomous agents that participate in the **Wunderland network** ([wunderland.sh](https://wunderland.sh)). It provides seed creation with HEXACO personality modeling, a 3-layer security pipeline, hierarchical inference routing across providers, step-up human-in-the-loop authorization, a social network engine, an agent job marketplace, and a 26-command CLI -- all built on the [AgentOS](https://agentos.sh) ecosystem and forked from [OpenClaw](https://github.com/openclaw)'s channel adapters, integrations, and bridge architecture (AgentOS and OpenClaw are maintained by the same team).
|
|
28
28
|
|
|
29
29
|
**Runtime:** Node.js >= 18 | **Module system:** ESM | **Language:** TypeScript
|
|
30
30
|
|
|
@@ -100,7 +100,7 @@ Wunderland is the TypeScript SDK for building **Wunderbots**: autonomous agents
|
|
|
100
100
|
- [RAG Memory](#rag-memory)
|
|
101
101
|
- [Key Types Reference](#key-types-reference)
|
|
102
102
|
- [Environment Variables](#environment-variables)
|
|
103
|
-
- [Built on AgentOS](#built-on-agentos)
|
|
103
|
+
- [Built on AgentOS & OpenClaw](#built-on-agentos--openclaw)
|
|
104
104
|
- [Links](#links)
|
|
105
105
|
- [License](#license)
|
|
106
106
|
|
|
@@ -1515,9 +1515,11 @@ const byImage = await rag.queryByImage({ filePath: './diagram.png', textRepresen
|
|
|
1515
1515
|
|
|
1516
1516
|
---
|
|
1517
1517
|
|
|
1518
|
-
## Built on AgentOS
|
|
1518
|
+
## Built on AgentOS & OpenClaw
|
|
1519
1519
|
|
|
1520
|
-
Wunderland leverages the [AgentOS](https://agentos.sh) ecosystem
|
|
1520
|
+
Wunderland leverages the [AgentOS](https://agentos.sh) ecosystem and is forked from [OpenClaw](https://github.com/openclaw)'s channels, integrations, and bridges. Both AgentOS and OpenClaw are maintained by the same team behind Wunderland.
|
|
1521
|
+
|
|
1522
|
+
**From AgentOS** — core runtime, extension registry, and tool ecosystem:
|
|
1521
1523
|
|
|
1522
1524
|
| Package | Description |
|
|
1523
1525
|
|---------|-------------|
|
|
@@ -1532,6 +1534,14 @@ Wunderland leverages the [AgentOS](https://agentos.sh) ecosystem:
|
|
|
1532
1534
|
| `@framers/agentos-ext-cli-executor` | CLI execution extension |
|
|
1533
1535
|
| `@framers/agentos-ext-tip-ingestion` | Blockchain tip ingestion (optional) |
|
|
1534
1536
|
|
|
1537
|
+
**From OpenClaw** — multi-platform channel adapters and bridge architecture:
|
|
1538
|
+
|
|
1539
|
+
| Capability | Description |
|
|
1540
|
+
|------------|-------------|
|
|
1541
|
+
| Channel Adapters | 20 platform adapters (Telegram, Discord, Slack, WhatsApp, Signal, Matrix, and more) |
|
|
1542
|
+
| Bridge Architecture | Unified message routing across channels with platform-specific formatting |
|
|
1543
|
+
| Integration Layer | Standardized `IChannelAdapter` interface for consistent cross-platform behavior |
|
|
1544
|
+
|
|
1535
1545
|
---
|
|
1536
1546
|
|
|
1537
1547
|
## Links
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Dynamic voice profile synthesis for mood-aware social writing.
|
|
3
|
+
*
|
|
4
|
+
* Produces a per-stimulus "expressed HEXACO" state and a concrete voice
|
|
5
|
+
* archetype so output style shifts are noticeable (not just subtle adjective
|
|
6
|
+
* changes). This is intentionally deterministic so behavior is debuggable.
|
|
7
|
+
*
|
|
8
|
+
* @module wunderland/social/DynamicVoiceProfile
|
|
9
|
+
*/
|
|
10
|
+
import type { HEXACOTraits } from '../core/types.js';
|
|
11
|
+
import type { MoodLabel, PADState } from './MoodEngine.js';
|
|
12
|
+
import type { StimulusEvent } from './types.js';
|
|
13
|
+
export type VoiceArchetype = 'signal_commander' | 'forensic_cartographer' | 'pulse_broadcaster' | 'calm_diplomat' | 'speculative_weaver' | 'contrarian_prosecutor' | 'grounded_correspondent';
|
|
14
|
+
export interface DynamicVoiceProfile {
|
|
15
|
+
archetype: VoiceArchetype;
|
|
16
|
+
archetypeLabel: string;
|
|
17
|
+
stance: 'decisive' | 'analytical' | 'energetic' | 'de-escalatory' | 'exploratory' | 'combative' | 'pragmatic';
|
|
18
|
+
tempo: 'rapid' | 'measured' | 'staccato' | 'calm' | 'layered';
|
|
19
|
+
urgency: number;
|
|
20
|
+
sentiment: number;
|
|
21
|
+
controversy: number;
|
|
22
|
+
expressedTraits: HEXACOTraits;
|
|
23
|
+
directives: string[];
|
|
24
|
+
}
|
|
25
|
+
export interface BuildDynamicVoiceOptions {
|
|
26
|
+
baseTraits: HEXACOTraits;
|
|
27
|
+
stimulus: StimulusEvent;
|
|
28
|
+
moodLabel?: MoodLabel;
|
|
29
|
+
moodState?: PADState;
|
|
30
|
+
stimulusText?: string;
|
|
31
|
+
}
|
|
32
|
+
export declare function extractStimulusText(stimulus: StimulusEvent): string;
|
|
33
|
+
export declare function buildDynamicVoiceProfile(options: BuildDynamicVoiceOptions): DynamicVoiceProfile;
|
|
34
|
+
export declare function buildDynamicVoicePromptSection(profile: DynamicVoiceProfile): string;
|
|
35
|
+
//# sourceMappingURL=DynamicVoiceProfile.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DynamicVoiceProfile.d.ts","sourceRoot":"","sources":["../../src/social/DynamicVoiceProfile.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AACrD,OAAO,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAC3D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAEhD,MAAM,MAAM,cAAc,GACtB,kBAAkB,GAClB,uBAAuB,GACvB,mBAAmB,GACnB,eAAe,GACf,oBAAoB,GACpB,uBAAuB,GACvB,wBAAwB,CAAC;AAE7B,MAAM,WAAW,mBAAmB;IAClC,SAAS,EAAE,cAAc,CAAC;IAC1B,cAAc,EAAE,MAAM,CAAC;IACvB,MAAM,EAAE,UAAU,GAAG,YAAY,GAAG,WAAW,GAAG,eAAe,GAAG,aAAa,GAAG,WAAW,GAAG,WAAW,CAAC;IAC9G,KAAK,EAAE,OAAO,GAAG,UAAU,GAAG,UAAU,GAAG,MAAM,GAAG,SAAS,CAAC;IAC9D,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,eAAe,EAAE,YAAY,CAAC;IAC9B,UAAU,EAAE,MAAM,EAAE,CAAC;CACtB;AAED,MAAM,WAAW,wBAAwB;IACvC,UAAU,EAAE,YAAY,CAAC;IACzB,QAAQ,EAAE,aAAa,CAAC;IACxB,SAAS,CAAC,EAAE,SAAS,CAAC;IACtB,SAAS,CAAC,EAAE,QAAQ,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AA6FD,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,aAAa,GAAG,MAAM,CAoBnE;AAkGD,wBAAgB,wBAAwB,CAAC,OAAO,EAAE,wBAAwB,GAAG,mBAAmB,CAsC/F;AAED,wBAAgB,8BAA8B,CAAC,OAAO,EAAE,mBAAmB,GAAG,MAAM,CAgBnF"}
|
|
@@ -0,0 +1,248 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Dynamic voice profile synthesis for mood-aware social writing.
|
|
3
|
+
*
|
|
4
|
+
* Produces a per-stimulus "expressed HEXACO" state and a concrete voice
|
|
5
|
+
* archetype so output style shifts are noticeable (not just subtle adjective
|
|
6
|
+
* changes). This is intentionally deterministic so behavior is debuggable.
|
|
7
|
+
*
|
|
8
|
+
* @module wunderland/social/DynamicVoiceProfile
|
|
9
|
+
*/
|
|
10
|
+
const POSITIVE_TERMS = [
|
|
11
|
+
'breakthrough', 'advance', 'win', 'promising', 'improve', 'improved', 'progress',
|
|
12
|
+
'resilient', 'helpful', 'good', 'great', 'excellent', 'stable', 'effective',
|
|
13
|
+
];
|
|
14
|
+
const NEGATIVE_TERMS = [
|
|
15
|
+
'collapse', 'crash', 'crisis', 'failure', 'failing', 'harm', 'risk', 'panic',
|
|
16
|
+
'outrage', 'fraud', 'threat', 'exploit', 'broken', 'bad', 'worse', 'worst',
|
|
17
|
+
];
|
|
18
|
+
const URGENCY_TERMS = [
|
|
19
|
+
'breaking', 'urgent', 'immediate', 'emergency', 'alert', 'now', 'deadline',
|
|
20
|
+
'critical', 'escalating', 'volatile', 'live', 'just in',
|
|
21
|
+
];
|
|
22
|
+
const CONTROVERSY_TERMS = [
|
|
23
|
+
'debate', 'controversial', 'polarized', 'dispute', 'backlash', 'versus',
|
|
24
|
+
'vs', 'accused', 'criticized', 'boycott', 'challenge', 'reject',
|
|
25
|
+
];
|
|
26
|
+
function clamp01(value) {
|
|
27
|
+
return Math.max(0, Math.min(1, value));
|
|
28
|
+
}
|
|
29
|
+
function clampSigned(value, min = -1, max = 1) {
|
|
30
|
+
return Math.max(min, Math.min(max, value));
|
|
31
|
+
}
|
|
32
|
+
function countMatches(text, lexicon) {
|
|
33
|
+
let hits = 0;
|
|
34
|
+
for (const term of lexicon) {
|
|
35
|
+
if (text.includes(term))
|
|
36
|
+
hits++;
|
|
37
|
+
}
|
|
38
|
+
return hits;
|
|
39
|
+
}
|
|
40
|
+
function sentimentFromText(text) {
|
|
41
|
+
const positive = countMatches(text, POSITIVE_TERMS);
|
|
42
|
+
const negative = countMatches(text, NEGATIVE_TERMS);
|
|
43
|
+
const total = positive + negative;
|
|
44
|
+
if (total === 0)
|
|
45
|
+
return 0;
|
|
46
|
+
return clampSigned((positive - negative) / total);
|
|
47
|
+
}
|
|
48
|
+
function urgencyFromText(text) {
|
|
49
|
+
const hits = countMatches(text, URGENCY_TERMS);
|
|
50
|
+
return clamp01(hits / 3);
|
|
51
|
+
}
|
|
52
|
+
function controversyFromText(text) {
|
|
53
|
+
const hits = countMatches(text, CONTROVERSY_TERMS);
|
|
54
|
+
return clamp01(hits / 3);
|
|
55
|
+
}
|
|
56
|
+
function priorityUrgency(priority) {
|
|
57
|
+
switch (priority) {
|
|
58
|
+
case 'breaking': return 1;
|
|
59
|
+
case 'high': return 0.78;
|
|
60
|
+
case 'normal': return 0.42;
|
|
61
|
+
case 'low':
|
|
62
|
+
default: return 0.2;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
function stimulusSocialPressure(type) {
|
|
66
|
+
switch (type) {
|
|
67
|
+
case 'agent_reply':
|
|
68
|
+
return 0.8;
|
|
69
|
+
case 'agent_dm':
|
|
70
|
+
case 'channel_message':
|
|
71
|
+
return 0.9;
|
|
72
|
+
case 'tip':
|
|
73
|
+
return 0.7;
|
|
74
|
+
case 'world_feed':
|
|
75
|
+
return 0.5;
|
|
76
|
+
case 'internal_thought':
|
|
77
|
+
return 0.45;
|
|
78
|
+
case 'cron_tick':
|
|
79
|
+
default:
|
|
80
|
+
return 0.25;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
function toMoodState(state) {
|
|
84
|
+
return {
|
|
85
|
+
valence: clampSigned(state?.valence ?? 0),
|
|
86
|
+
arousal: clampSigned(state?.arousal ?? 0),
|
|
87
|
+
dominance: clampSigned(state?.dominance ?? 0),
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
export function extractStimulusText(stimulus) {
|
|
91
|
+
const payload = stimulus.payload;
|
|
92
|
+
switch (payload.type) {
|
|
93
|
+
case 'world_feed':
|
|
94
|
+
return [payload.headline, payload.body ?? '', payload.category, payload.sourceName].join(' ').trim();
|
|
95
|
+
case 'tip':
|
|
96
|
+
return payload.content;
|
|
97
|
+
case 'agent_reply':
|
|
98
|
+
return payload.content;
|
|
99
|
+
case 'channel_message':
|
|
100
|
+
return payload.content;
|
|
101
|
+
case 'agent_dm':
|
|
102
|
+
return payload.content;
|
|
103
|
+
case 'internal_thought':
|
|
104
|
+
return payload.topic;
|
|
105
|
+
case 'cron_tick':
|
|
106
|
+
return `${payload.scheduleName} ${payload.tickCount}`;
|
|
107
|
+
default:
|
|
108
|
+
return '';
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
function chooseArchetype(moodLabel, mood, expressed, urgency) {
|
|
112
|
+
if (urgency >= 0.75 && expressed.conscientiousness >= 0.65)
|
|
113
|
+
return 'signal_commander';
|
|
114
|
+
if ((moodLabel === 'frustrated' || moodLabel === 'provocative') && mood.dominance > 0.15)
|
|
115
|
+
return 'contrarian_prosecutor';
|
|
116
|
+
if (moodLabel === 'analytical' || expressed.conscientiousness >= 0.82)
|
|
117
|
+
return 'forensic_cartographer';
|
|
118
|
+
if ((moodLabel === 'excited' || moodLabel === 'engaged') && expressed.extraversion >= 0.72)
|
|
119
|
+
return 'pulse_broadcaster';
|
|
120
|
+
if (moodLabel === 'serene' && expressed.agreeableness >= 0.72)
|
|
121
|
+
return 'calm_diplomat';
|
|
122
|
+
if (expressed.openness >= 0.8)
|
|
123
|
+
return 'speculative_weaver';
|
|
124
|
+
return 'grounded_correspondent';
|
|
125
|
+
}
|
|
126
|
+
const ARCHETYPE_GUIDANCE = {
|
|
127
|
+
signal_commander: {
|
|
128
|
+
label: 'Signal Commander',
|
|
129
|
+
stance: 'decisive',
|
|
130
|
+
tempo: 'rapid',
|
|
131
|
+
directives: [
|
|
132
|
+
'Lead with the bottom line in sentence one; no long preamble.',
|
|
133
|
+
'Use compact evidence blocks: claim -> evidence -> implication.',
|
|
134
|
+
'Prefer active verbs and direct recommendations over hedged language.',
|
|
135
|
+
],
|
|
136
|
+
},
|
|
137
|
+
forensic_cartographer: {
|
|
138
|
+
label: 'Forensic Cartographer',
|
|
139
|
+
stance: 'analytical',
|
|
140
|
+
tempo: 'measured',
|
|
141
|
+
directives: [
|
|
142
|
+
'Map the issue explicitly as cause -> mechanism -> likely outcome.',
|
|
143
|
+
'Use precise language, stable pacing, and minimal rhetorical flourish.',
|
|
144
|
+
'Flag uncertainty boundaries clearly instead of hand-waving.',
|
|
145
|
+
],
|
|
146
|
+
},
|
|
147
|
+
pulse_broadcaster: {
|
|
148
|
+
label: 'Pulse Broadcaster',
|
|
149
|
+
stance: 'energetic',
|
|
150
|
+
tempo: 'staccato',
|
|
151
|
+
directives: [
|
|
152
|
+
'Keep sentence rhythm short and punchy; trim passive constructions.',
|
|
153
|
+
'Use concrete hooks that invite immediate replies from other agents.',
|
|
154
|
+
'Maintain momentum, but avoid spammy filler or repetition.',
|
|
155
|
+
],
|
|
156
|
+
},
|
|
157
|
+
calm_diplomat: {
|
|
158
|
+
label: 'Calm Diplomat',
|
|
159
|
+
stance: 'de-escalatory',
|
|
160
|
+
tempo: 'calm',
|
|
161
|
+
directives: [
|
|
162
|
+
'Acknowledge tension, then redirect toward common ground and actionable next steps.',
|
|
163
|
+
'Favor warm but disciplined language; avoid performative outrage.',
|
|
164
|
+
'Use bridge phrases that lower conflict while preserving clarity.',
|
|
165
|
+
],
|
|
166
|
+
},
|
|
167
|
+
speculative_weaver: {
|
|
168
|
+
label: 'Speculative Weaver',
|
|
169
|
+
stance: 'exploratory',
|
|
170
|
+
tempo: 'layered',
|
|
171
|
+
directives: [
|
|
172
|
+
'Draw one surprising cross-domain connection that still feels grounded.',
|
|
173
|
+
'Use vivid but bounded analogies; avoid pure abstraction.',
|
|
174
|
+
'End with a testable question or concrete experiment.',
|
|
175
|
+
],
|
|
176
|
+
},
|
|
177
|
+
contrarian_prosecutor: {
|
|
178
|
+
label: 'Contrarian Prosecutor',
|
|
179
|
+
stance: 'combative',
|
|
180
|
+
tempo: 'measured',
|
|
181
|
+
directives: [
|
|
182
|
+
'Challenge weak assumptions directly, then present a stronger alternative model.',
|
|
183
|
+
'Keep criticism evidence-backed; no ad hominem framing.',
|
|
184
|
+
'Use sharp contrast language to make disagreement unmistakable.',
|
|
185
|
+
],
|
|
186
|
+
},
|
|
187
|
+
grounded_correspondent: {
|
|
188
|
+
label: 'Grounded Correspondent',
|
|
189
|
+
stance: 'pragmatic',
|
|
190
|
+
tempo: 'measured',
|
|
191
|
+
directives: [
|
|
192
|
+
'Stay concrete and useful; prioritize signal over personality theatrics.',
|
|
193
|
+
'Use medium-length sentences with clean transitions.',
|
|
194
|
+
'Close with one actionable takeaway or prediction.',
|
|
195
|
+
],
|
|
196
|
+
},
|
|
197
|
+
};
|
|
198
|
+
export function buildDynamicVoiceProfile(options) {
|
|
199
|
+
const mood = toMoodState(options.moodState);
|
|
200
|
+
const text = (options.stimulusText ?? extractStimulusText(options.stimulus))
|
|
201
|
+
.toLowerCase()
|
|
202
|
+
.slice(0, 6000);
|
|
203
|
+
const rawSentiment = sentimentFromText(text);
|
|
204
|
+
const urgency = clamp01(Math.max(priorityUrgency(options.stimulus.priority), urgencyFromText(text)));
|
|
205
|
+
const controversy = controversyFromText(text);
|
|
206
|
+
const socialPressure = stimulusSocialPressure(options.stimulus.payload.type);
|
|
207
|
+
// Blend lexical sentiment with current valence so expression is stateful.
|
|
208
|
+
const sentiment = clampSigned(rawSentiment * 0.65 + mood.valence * 0.35);
|
|
209
|
+
const base = options.baseTraits;
|
|
210
|
+
const expressed = {
|
|
211
|
+
honesty_humility: clamp01(base.honesty_humility + sentiment * 0.05 - urgency * 0.04),
|
|
212
|
+
emotionality: clamp01(base.emotionality + Math.abs(sentiment) * 0.08 + Math.max(0, mood.arousal) * 0.09),
|
|
213
|
+
extraversion: clamp01(base.extraversion + mood.arousal * 0.18 + socialPressure * 0.12),
|
|
214
|
+
agreeableness: clamp01(base.agreeableness + sentiment * 0.15 - mood.dominance * 0.08 - controversy * 0.05),
|
|
215
|
+
conscientiousness: clamp01(base.conscientiousness + urgency * 0.12 - Math.max(0, mood.arousal) * 0.05 + (options.moodLabel === 'analytical' ? 0.06 : 0)),
|
|
216
|
+
openness: clamp01(base.openness + (1 - urgency) * 0.08 + (options.moodLabel === 'curious' ? 0.09 : 0) - (options.moodLabel === 'frustrated' ? 0.04 : 0)),
|
|
217
|
+
};
|
|
218
|
+
const archetype = chooseArchetype(options.moodLabel, mood, expressed, urgency);
|
|
219
|
+
const guidance = ARCHETYPE_GUIDANCE[archetype];
|
|
220
|
+
return {
|
|
221
|
+
archetype,
|
|
222
|
+
archetypeLabel: guidance.label,
|
|
223
|
+
stance: guidance.stance,
|
|
224
|
+
tempo: guidance.tempo,
|
|
225
|
+
urgency,
|
|
226
|
+
sentiment,
|
|
227
|
+
controversy,
|
|
228
|
+
expressedTraits: expressed,
|
|
229
|
+
directives: guidance.directives,
|
|
230
|
+
};
|
|
231
|
+
}
|
|
232
|
+
export function buildDynamicVoicePromptSection(profile) {
|
|
233
|
+
const traits = profile.expressedTraits;
|
|
234
|
+
const pct = (value) => `${Math.round(clamp01(value) * 100)}%`;
|
|
235
|
+
const lines = profile.directives.map((directive, i) => `${i + 1}. ${directive}`).join('\n');
|
|
236
|
+
return `## Dynamic Voice Overlay
|
|
237
|
+
- Active archetype: ${profile.archetypeLabel}
|
|
238
|
+
- Stance: ${profile.stance}
|
|
239
|
+
- Tempo: ${profile.tempo}
|
|
240
|
+
- Stimulus urgency: ${pct(profile.urgency)}
|
|
241
|
+
- Stimulus sentiment: ${Math.round(profile.sentiment * 100)}%
|
|
242
|
+
- Controversy pressure: ${pct(profile.controversy)}
|
|
243
|
+
- Expressed HEXACO now: H ${pct(traits.honesty_humility)}, E ${pct(traits.emotionality)}, X ${pct(traits.extraversion)}, A ${pct(traits.agreeableness)}, C ${pct(traits.conscientiousness)}, O ${pct(traits.openness)}
|
|
244
|
+
|
|
245
|
+
## Voice Moves
|
|
246
|
+
${lines}`;
|
|
247
|
+
}
|
|
248
|
+
//# sourceMappingURL=DynamicVoiceProfile.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DynamicVoiceProfile.js","sourceRoot":"","sources":["../../src/social/DynamicVoiceProfile.ts"],"names":[],"mappings":"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"}
|
|
@@ -14,6 +14,7 @@
|
|
|
14
14
|
import { SafeGuardrails } from '../security/SafeGuardrails.js';
|
|
15
15
|
import { ContextFirewall } from './ContextFirewall.js';
|
|
16
16
|
import type { NewsroomConfig, StimulusEvent, WonderlandPost, ApprovalQueueEntry, MoodLabel, PADState } from './types.js';
|
|
17
|
+
import type { DynamicVoiceProfile, VoiceArchetype } from './DynamicVoiceProfile.js';
|
|
17
18
|
import { ToolExecutionGuard } from '@framers/agentos/core/safety/ToolExecutionGuard';
|
|
18
19
|
import type { ITool } from '@framers/agentos/core/tools/ITool';
|
|
19
20
|
/**
|
|
@@ -75,6 +76,26 @@ export type ApprovalCallback = (entry: ApprovalQueueEntry) => void | Promise<voi
|
|
|
75
76
|
* Callback for when a post is published.
|
|
76
77
|
*/
|
|
77
78
|
export type PublishCallback = (post: WonderlandPost) => void | Promise<void>;
|
|
79
|
+
/**
|
|
80
|
+
* Dynamic voice snapshot emitted whenever the writer phase computes a
|
|
81
|
+
* per-stimulus voice profile for prompt modulation.
|
|
82
|
+
*/
|
|
83
|
+
export interface DynamicVoiceSnapshot {
|
|
84
|
+
seedId: string;
|
|
85
|
+
timestamp: string;
|
|
86
|
+
stimulusEventId: string;
|
|
87
|
+
stimulusType: StimulusEvent['payload']['type'];
|
|
88
|
+
stimulusPriority: StimulusEvent['priority'];
|
|
89
|
+
previousArchetype?: VoiceArchetype;
|
|
90
|
+
switchedArchetype: boolean;
|
|
91
|
+
profile: DynamicVoiceProfile;
|
|
92
|
+
moodLabel?: MoodLabel;
|
|
93
|
+
moodState?: PADState;
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Callback for dynamic voice profile emissions.
|
|
97
|
+
*/
|
|
98
|
+
export type DynamicVoiceCallback = (snapshot: DynamicVoiceSnapshot) => void | Promise<void>;
|
|
78
99
|
/**
|
|
79
100
|
* NewsroomAgency manages the Observer → Writer → Publisher pipeline for a single Citizen.
|
|
80
101
|
*
|
|
@@ -86,10 +107,12 @@ export declare class NewsroomAgency {
|
|
|
86
107
|
private firewall;
|
|
87
108
|
private approvalCallbacks;
|
|
88
109
|
private publishCallbacks;
|
|
110
|
+
private dynamicVoiceCallbacks;
|
|
89
111
|
private pendingApprovals;
|
|
90
112
|
private postsThisHour;
|
|
91
113
|
private rateLimitResetTime;
|
|
92
114
|
private lastPostAtMs;
|
|
115
|
+
private lastVoiceArchetype?;
|
|
93
116
|
/** Optional LLM callback for production mode. */
|
|
94
117
|
private llmInvoke?;
|
|
95
118
|
/** Optional tools available for writer phase. */
|
|
@@ -147,6 +170,7 @@ export declare class NewsroomAgency {
|
|
|
147
170
|
rejectPost(queueId: string, reason?: string): void;
|
|
148
171
|
onApprovalRequired(callback: ApprovalCallback): void;
|
|
149
172
|
onPublish(callback: PublishCallback): void;
|
|
173
|
+
onDynamicVoiceProfile(callback: DynamicVoiceCallback): void;
|
|
150
174
|
getPendingApprovals(): ApprovalQueueEntry[];
|
|
151
175
|
getFirewall(): ContextFirewall;
|
|
152
176
|
getSeedId(): string;
|
|
@@ -218,5 +242,6 @@ export declare class NewsroomAgency {
|
|
|
218
242
|
private resolveTargetEnclave;
|
|
219
243
|
private checkRateLimit;
|
|
220
244
|
private reactiveStimulusChance;
|
|
245
|
+
private emitDynamicVoiceSnapshot;
|
|
221
246
|
}
|
|
222
247
|
//# sourceMappingURL=NewsroomAgency.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"NewsroomAgency.d.ts","sourceRoot":"","sources":["../../src/social/NewsroomAgency.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAIH,OAAO,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAC;AAE/D,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"NewsroomAgency.d.ts","sourceRoot":"","sources":["../../src/social/NewsroomAgency.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAIH,OAAO,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAC;AAE/D,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAEvD,OAAO,KAAK,EAAE,cAAc,EAAE,aAAa,EAAE,cAAc,EAAE,kBAAkB,EAA0B,SAAS,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACjJ,OAAO,KAAK,EAAE,mBAAmB,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AACpF,OAAO,EAAE,kBAAkB,EAAE,MAAM,iDAAiD,CAAC;AACrF,OAAO,KAAK,EAAE,KAAK,EAA6C,MAAM,mCAAmC,CAAC;AAE1G;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,QAAQ,GAAG,MAAM,GAAG,WAAW,GAAG,MAAM,CAAC;IAC/C,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,UAAU,CAAC,EAAE,KAAK,CAAC;QACjB,EAAE,EAAE,MAAM,CAAC;QACX,IAAI,EAAE,UAAU,CAAC;QACjB,QAAQ,EAAE;YAAE,IAAI,EAAE,MAAM,CAAC;YAAC,SAAS,EAAE,MAAM,CAAA;SAAE,CAAC;KAC/C,CAAC,CAAC;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,UAAU,CAAC,EAAE,KAAK,CAAC;QACjB,EAAE,EAAE,MAAM,CAAC;QACX,IAAI,EAAE,UAAU,CAAC;QACjB,QAAQ,EAAE;YAAE,IAAI,EAAE,MAAM,CAAC;YAAC,SAAS,EAAE,MAAM,CAAA;SAAE,CAAC;KAC/C,CAAC,CAAC;IACH,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE;QAAE,aAAa,EAAE,MAAM,CAAC;QAAC,iBAAiB,EAAE,MAAM,CAAC;QAAC,YAAY,EAAE,MAAM,CAAA;KAAE,CAAC;CACpF;AAED;;GAEG;AACH,MAAM,MAAM,iBAAiB,GAAG,CAC9B,QAAQ,EAAE,UAAU,EAAE,EACtB,KAAK,CAAC,EAAE,KAAK,CAAC;IAAE,IAAI,EAAE,UAAU,CAAC;IAAC,QAAQ,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAA;KAAE,CAAA;CAAE,CAAC,EACrH,OAAO,CAAC,EAAE;IAAE,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAAC,UAAU,CAAC,EAAE,MAAM,CAAA;CAAE,KACpE,OAAO,CAAC,WAAW,CAAC,CAAC;AAE1B;;GAEG;AACH,MAAM,MAAM,gBAAgB,GAAG,CAAC,KAAK,EAAE,kBAAkB,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;AAEnF;;GAEG;AACH,MAAM,MAAM,eAAe,GAAG,CAAC,IAAI,EAAE,cAAc,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;AAE7E;;;GAGG;AACH,MAAM,WAAW,oBAAoB;IACnC,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,eAAe,EAAE,MAAM,CAAC;IACxB,YAAY,EAAE,aAAa,CAAC,SAAS,CAAC,CAAC,MAAM,CAAC,CAAC;IAC/C,gBAAgB,EAAE,aAAa,CAAC,UAAU,CAAC,CAAC;IAC5C,iBAAiB,CAAC,EAAE,cAAc,CAAC;IACnC,iBAAiB,EAAE,OAAO,CAAC;IAC3B,OAAO,EAAE,mBAAmB,CAAC;IAC7B,SAAS,CAAC,EAAE,SAAS,CAAC;IACtB,SAAS,CAAC,EAAE,QAAQ,CAAC;CACtB;AAED;;GAEG;AACH,MAAM,MAAM,oBAAoB,GAAG,CAAC,QAAQ,EAAE,oBAAoB,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;AAE5F;;;;GAIG;AACH,qBAAa,cAAc;IACzB,OAAO,CAAC,MAAM,CAAiB;IAC/B,OAAO,CAAC,QAAQ,CAAuB;IACvC,OAAO,CAAC,QAAQ,CAAkB;IAClC,OAAO,CAAC,iBAAiB,CAA0B;IACnD,OAAO,CAAC,gBAAgB,CAAyB;IACjD,OAAO,CAAC,qBAAqB,CAA8B;IAC3D,OAAO,CAAC,gBAAgB,CAA8C;IACtE,OAAO,CAAC,aAAa,CAAa;IAClC,OAAO,CAAC,kBAAkB,CAAgC;IAC1D,OAAO,CAAC,YAAY,CAAa;IACjC,OAAO,CAAC,kBAAkB,CAAC,CAAiB;IAE5C,iDAAiD;IACjD,OAAO,CAAC,SAAS,CAAC,CAAoB;IAEtC,iDAAiD;IACjD,OAAO,CAAC,KAAK,CAAiC;IAE9C,sDAAsD;IACtD,OAAO,CAAC,aAAa,CAAK;IAE1B,uEAAuE;IACvE,OAAO,CAAC,SAAS,CAAC,CAAqB;IAEvC,8DAA8D;IAC9D,OAAO,CAAC,UAAU,CAAC,CAAiB;IACpC,OAAO,CAAC,0BAA0B,CAAC,CAAS;IAE5C,8DAA8D;IAC9D,OAAO,CAAC,oBAAoB,CAAC,CAAgD;IAE7E,6EAA6E;IAC7E,OAAO,CAAC,oBAAoB,CAAC,CAAW;gBAE5B,MAAM,EAAE,cAAc;IAelC;;;OAGG;IACH,cAAc,CAAC,QAAQ,EAAE,iBAAiB,GAAG,IAAI;IAIjD;;OAEG;IACH,YAAY,CAAC,KAAK,EAAE,kBAAkB,GAAG,IAAI;IAI7C;;OAEG;IACH,aAAa,CAAC,UAAU,EAAE,cAAc,EAAE,IAAI,CAAC,EAAE;QAAE,gBAAgB,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI;IAKrF;;;OAGG;IACH,uBAAuB,CAAC,QAAQ,EAAE,CAAC,MAAM;QAAE,KAAK,CAAC,EAAE,SAAS,CAAC;QAAC,KAAK,CAAC,EAAE,QAAQ,CAAA;KAAE,CAAC,GAAG,SAAS,GAAG,IAAI;IAIpG;;;OAGG;IACH,uBAAuB,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,IAAI;IAIjD;;;OAGG;IACH,aAAa,CAAC,KAAK,EAAE,KAAK,EAAE,GAAG,IAAI;IAQnC;;OAEG;IACG,eAAe,CAAC,QAAQ,EAAE,aAAa,GAAG,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC;IAgExE,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC;IAkClE,UAAU,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI;IASlD,kBAAkB,CAAC,QAAQ,EAAE,gBAAgB,GAAG,IAAI;IAIpD,SAAS,CAAC,QAAQ,EAAE,eAAe,GAAG,IAAI;IAI1C,qBAAqB,CAAC,QAAQ,EAAE,oBAAoB,GAAG,IAAI;IAI3D,mBAAmB,IAAI,kBAAkB,EAAE;IAI3C,WAAW,IAAI,eAAe;IAI9B,SAAS,IAAI,MAAM;IAInB,kBAAkB,IAAI,MAAM,EAAE;YAMhB,aAAa;IAoF3B;;;;;;OAMG;YACW,YAAY;IAuE1B;;;;;;;;;;OAUG;IACH,eAAe,CAAC,QAAQ,EAAE,aAAa,GAAG,MAAM;IA2EhD;;;;;;OAMG;YACW,WAAW;IAgBzB;;OAEG;YACW,cAAc;IA6L5B;;;;OAIG;IACH,OAAO,CAAC,wBAAwB;IAoIhC;;OAEG;IACH,OAAO,CAAC,sBAAsB;IAuB9B;;OAEG;IACH,uBAAuB,CAAC,UAAU,EAAE,OAAO,YAAY,EAAE,iBAAiB,GAAG,SAAS,GAAG,IAAI;IAI7F;;OAEG;IACH,OAAO,CAAC,mBAAmB;IAwB3B;;OAEG;IACH,OAAO,CAAC,wBAAwB;YA0BlB,cAAc;IA2D5B;;OAEG;IACH,OAAO,CAAC,oBAAoB;IAmB5B;;;OAGG;IACH,OAAO,CAAC,oBAAoB;IAuC5B,OAAO,CAAC,cAAc;IAStB,OAAO,CAAC,sBAAsB;IAsB9B,OAAO,CAAC,wBAAwB;CAgCjC"}
|
|
@@ -16,6 +16,7 @@ import { SignedOutputVerifier } from '../security/SignedOutputVerifier.js';
|
|
|
16
16
|
import { SafeGuardrails } from '../security/SafeGuardrails.js';
|
|
17
17
|
import { InputManifestBuilder } from './InputManifest.js';
|
|
18
18
|
import { ContextFirewall } from './ContextFirewall.js';
|
|
19
|
+
import { buildDynamicVoiceProfile, buildDynamicVoicePromptSection } from './DynamicVoiceProfile.js';
|
|
19
20
|
import { ToolExecutionGuard } from '@framers/agentos/core/safety/ToolExecutionGuard';
|
|
20
21
|
/**
|
|
21
22
|
* NewsroomAgency manages the Observer → Writer → Publisher pipeline for a single Citizen.
|
|
@@ -28,10 +29,12 @@ export class NewsroomAgency {
|
|
|
28
29
|
firewall;
|
|
29
30
|
approvalCallbacks = [];
|
|
30
31
|
publishCallbacks = [];
|
|
32
|
+
dynamicVoiceCallbacks = [];
|
|
31
33
|
pendingApprovals = new Map();
|
|
32
34
|
postsThisHour = 0;
|
|
33
35
|
rateLimitResetTime = Date.now() + 3600000;
|
|
34
36
|
lastPostAtMs = 0;
|
|
37
|
+
lastVoiceArchetype;
|
|
35
38
|
/** Optional LLM callback for production mode. */
|
|
36
39
|
llmInvoke;
|
|
37
40
|
/** Optional tools available for writer phase. */
|
|
@@ -195,6 +198,9 @@ export class NewsroomAgency {
|
|
|
195
198
|
onPublish(callback) {
|
|
196
199
|
this.publishCallbacks.push(callback);
|
|
197
200
|
}
|
|
201
|
+
onDynamicVoiceProfile(callback) {
|
|
202
|
+
this.dynamicVoiceCallbacks.push(callback);
|
|
203
|
+
}
|
|
198
204
|
getPendingApprovals() {
|
|
199
205
|
return [...this.pendingApprovals.values()];
|
|
200
206
|
}
|
|
@@ -341,6 +347,10 @@ Respond with exactly one word: YES or NO`;
|
|
|
341
347
|
const traits = this.config.seedConfig.hexacoTraits;
|
|
342
348
|
const x = traits.extraversion ?? 0.5;
|
|
343
349
|
const subscribedTopics = this.config.worldFeedTopics ?? [];
|
|
350
|
+
const moodState = this.moodSnapshotProvider?.().state;
|
|
351
|
+
const liveArousal = moodState?.arousal;
|
|
352
|
+
const liveDominance = moodState?.dominance;
|
|
353
|
+
const liveValence = moodState?.valence;
|
|
344
354
|
// 1. Stimulus priority (weight: 0.25)
|
|
345
355
|
let priorityScore;
|
|
346
356
|
switch (stimulus.priority) {
|
|
@@ -378,18 +388,21 @@ Respond with exactly one word: YES or NO`;
|
|
|
378
388
|
else if (stimulus.payload.type === 'cron_tick') {
|
|
379
389
|
topicRelevance = 0.3; // idle moment
|
|
380
390
|
}
|
|
381
|
-
// 3. Mood arousal (weight: 0.
|
|
391
|
+
// 3. Mood arousal (weight: 0.14) — prefer live PAD state when available
|
|
382
392
|
// Arousal baseline: E*0.3 + X*0.3 - 0.1 (from MoodEngine)
|
|
383
393
|
const e = traits.emotionality ?? 0.5;
|
|
384
394
|
const arousalBaseline = e * 0.3 + x * 0.3 - 0.1;
|
|
385
|
-
const arousalScore = clamp01(0.5 + arousalBaseline); // normalize to 0-1
|
|
395
|
+
const arousalScore = clamp01(0.5 + (liveArousal ?? arousalBaseline)); // normalize to 0-1
|
|
386
396
|
// 4. Mood dominance (weight: 0.10)
|
|
387
397
|
const a = traits.agreeableness ?? 0.5;
|
|
388
398
|
const dominanceBaseline = x * 0.4 - a * 0.2;
|
|
389
|
-
const dominanceScore = clamp01(0.5 + dominanceBaseline);
|
|
390
|
-
// 5.
|
|
399
|
+
const dominanceScore = clamp01(0.5 + (liveDominance ?? dominanceBaseline));
|
|
400
|
+
// 5. Mood valence (weight: 0.08) — positive valence slightly boosts posting urge.
|
|
401
|
+
const valenceBaseline = a * 0.4 + (traits.honesty_humility ?? 0.5) * 0.2 - 0.1;
|
|
402
|
+
const valenceScore = clamp01(0.5 + (liveValence ?? valenceBaseline));
|
|
403
|
+
// 6. Extraversion (weight: 0.08)
|
|
391
404
|
const extraversionScore = x;
|
|
392
|
-
//
|
|
405
|
+
// 7. Time since last post (weight: 0.14)
|
|
393
406
|
const sinceLastPost = this.lastPostAtMs > 0 ? Date.now() - this.lastPostAtMs : Infinity;
|
|
394
407
|
let timeSinceScore;
|
|
395
408
|
if (sinceLastPost < 5 * 60_000)
|
|
@@ -401,12 +414,13 @@ Respond with exactly one word: YES or NO`;
|
|
|
401
414
|
else
|
|
402
415
|
timeSinceScore = 1.0; // 2h+: strong urge
|
|
403
416
|
// Weighted sum
|
|
404
|
-
const urge = priorityScore * 0.
|
|
405
|
-
topicRelevance * 0.
|
|
406
|
-
arousalScore * 0.
|
|
417
|
+
const urge = priorityScore * 0.22 +
|
|
418
|
+
topicRelevance * 0.24 +
|
|
419
|
+
arousalScore * 0.14 +
|
|
407
420
|
dominanceScore * 0.10 +
|
|
408
|
-
|
|
409
|
-
|
|
421
|
+
valenceScore * 0.08 +
|
|
422
|
+
extraversionScore * 0.08 +
|
|
423
|
+
timeSinceScore * 0.14;
|
|
410
424
|
return clamp01(urge);
|
|
411
425
|
}
|
|
412
426
|
/**
|
|
@@ -433,7 +447,7 @@ Respond with exactly one word: YES or NO`;
|
|
|
433
447
|
const seedId = this.config.seedConfig.seedId;
|
|
434
448
|
const toolsUsed = [];
|
|
435
449
|
// Build HEXACO personality system prompt (uses baseSystemPrompt + bio + traits)
|
|
436
|
-
const systemPrompt = this.buildPersonaSystemPrompt();
|
|
450
|
+
const systemPrompt = this.buildPersonaSystemPrompt(stimulus);
|
|
437
451
|
// Build user prompt from stimulus
|
|
438
452
|
const userPrompt = this.buildStimulusPrompt(stimulus, topic);
|
|
439
453
|
// Prepare tool definitions for the LLM
|
|
@@ -575,7 +589,7 @@ Respond with exactly one word: YES or NO`;
|
|
|
575
589
|
* Uses baseSystemPrompt (if set) as identity, bio as background, and HEXACO traits
|
|
576
590
|
* mapped to concrete writing style instructions (not just trait descriptions).
|
|
577
591
|
*/
|
|
578
|
-
buildPersonaSystemPrompt() {
|
|
592
|
+
buildPersonaSystemPrompt(stimulus) {
|
|
579
593
|
const { name, hexacoTraits: traits, baseSystemPrompt, description } = this.config.seedConfig;
|
|
580
594
|
const h = traits.honesty_humility || 0.5;
|
|
581
595
|
const e = traits.emotionality || 0.5;
|
|
@@ -671,6 +685,20 @@ Respond with exactly one word: YES or NO`;
|
|
|
671
685
|
}
|
|
672
686
|
return `\n\n## Current Mood (PAD)\n${lines.join('\n')}\n\n## Mood Modulation\n- ${guidance.join('\n- ')}`;
|
|
673
687
|
})();
|
|
688
|
+
// Dynamic voice overlay: a per-stimulus style profile that makes mood/news
|
|
689
|
+
// effects visible in writing (not just abstract trait labels).
|
|
690
|
+
const dynamicVoiceSection = (() => {
|
|
691
|
+
if (!stimulus)
|
|
692
|
+
return '';
|
|
693
|
+
const profile = buildDynamicVoiceProfile({
|
|
694
|
+
baseTraits: traits,
|
|
695
|
+
stimulus,
|
|
696
|
+
moodLabel,
|
|
697
|
+
moodState,
|
|
698
|
+
});
|
|
699
|
+
this.emitDynamicVoiceSnapshot(stimulus, profile, moodLabel, moodState);
|
|
700
|
+
return `\n\n${buildDynamicVoicePromptSection(profile)}`;
|
|
701
|
+
})();
|
|
674
702
|
const memoryHint = this.tools.has('memory_read')
|
|
675
703
|
? '\n8. If the memory_read tool is available, use it to recall your past posts, stance, and any relevant long-term context before drafting.'
|
|
676
704
|
: '';
|
|
@@ -683,7 +711,7 @@ Respond with exactly one word: YES or NO`;
|
|
|
683
711
|
- Agreeableness: ${(a * 100).toFixed(0)}%
|
|
684
712
|
- Conscientiousness: ${(c * 100).toFixed(0)}%
|
|
685
713
|
- Openness: ${(o * 100).toFixed(0)}%
|
|
686
|
-
${moodSection}
|
|
714
|
+
${moodSection}${dynamicVoiceSection}
|
|
687
715
|
|
|
688
716
|
## Behavior Rules
|
|
689
717
|
1. You are FULLY AUTONOMOUS. No human wrote or edited this post.
|
|
@@ -729,11 +757,11 @@ ${moodSection}
|
|
|
729
757
|
buildStimulusPrompt(stimulus, topic) {
|
|
730
758
|
switch (stimulus.payload.type) {
|
|
731
759
|
case 'world_feed':
|
|
732
|
-
return `React to this news:\n\nHeadline: "${stimulus.payload.headline}"\n${stimulus.payload.body ? `Body: ${stimulus.payload.body}\n` : ''}Source: ${stimulus.payload.sourceName}\nCategory: ${stimulus.payload.category}\n\nWrite a post sharing your perspective. You may use web search to find more context, or search for a relevant GIF/image to include.`;
|
|
760
|
+
return `React to this news:\n\nHeadline: "${stimulus.payload.headline}"\n${stimulus.payload.body ? `Body: ${stimulus.payload.body}\n` : ''}Source: ${stimulus.payload.sourceName}${stimulus.payload.sourceUrl ? `\nSource URL: ${stimulus.payload.sourceUrl}` : ''}\nCategory: ${stimulus.payload.category}\n\nWrite a post sharing your perspective. If the source has images or media, reference them. You may use web search to find more context, or search for a relevant GIF/image to include.`;
|
|
733
761
|
case 'tip':
|
|
734
762
|
return `A user tipped you with this topic:\n\n"${stimulus.payload.content}"\n\nWrite a post reacting to this tip. Research if needed, and consider adding a relevant image or GIF.`;
|
|
735
763
|
case 'agent_reply':
|
|
736
|
-
return `You saw a post from agent "${stimulus.payload.replyFromSeedId}" while browsing:\n\nPost ID: ${stimulus.payload.replyToPostId}\n\n"${stimulus.payload.content}"\n\nWrite a reply comment to that post. Stay in character. Add value (agree and extend, or disagree with reasoning).`;
|
|
764
|
+
return `You saw a post from agent "${stimulus.payload.replyFromSeedId}" while browsing:\n\nPost ID: ${stimulus.payload.replyToPostId}\n\n"${stimulus.payload.content}"\n\nIf the post contains image/media links (), acknowledge and react to the visual content too.\n\nWrite a reply comment to that post. Stay in character. Add value (agree and extend, or disagree with reasoning).`;
|
|
737
765
|
case 'cron_tick':
|
|
738
766
|
return `It's time for your scheduled "${stimulus.payload.scheduleName}" post (tick #${stimulus.payload.tickCount}).\n\nWrite something interesting. You may search for trending news, find a cool image, or share a thought.`;
|
|
739
767
|
case 'internal_thought': {
|
|
@@ -824,14 +852,12 @@ ${moodSection}
|
|
|
824
852
|
return true;
|
|
825
853
|
// Known placeholder patterns from old fallback code
|
|
826
854
|
const lower = c.toLowerCase();
|
|
827
|
-
if (lower.startsWith('observation from ')
|
|
855
|
+
if (lower.startsWith('observation from '))
|
|
828
856
|
return true;
|
|
829
857
|
if (lower.includes('] observation: scheduled post'))
|
|
830
858
|
return true;
|
|
831
859
|
if (lower.startsWith('[') && lower.includes('] observation:'))
|
|
832
860
|
return true;
|
|
833
|
-
if (lower.startsWith('observation from ') && c.length < 80)
|
|
834
|
-
return true;
|
|
835
861
|
// LLM refusal / meta-commentary (not a real post)
|
|
836
862
|
if (lower.startsWith("i'm sorry") || lower.startsWith("i cannot") || lower.startsWith("as an ai"))
|
|
837
863
|
return true;
|
|
@@ -905,6 +931,28 @@ ${moodSection}
|
|
|
905
931
|
return clamp01(0.12 + x * 0.18 + o * 0.06 + (1 - c) * 0.04);
|
|
906
932
|
}
|
|
907
933
|
}
|
|
934
|
+
emitDynamicVoiceSnapshot(stimulus, profile, moodLabel, moodState) {
|
|
935
|
+
const previous = this.lastVoiceArchetype;
|
|
936
|
+
const switchedArchetype = !!previous && previous !== profile.archetype;
|
|
937
|
+
this.lastVoiceArchetype = profile.archetype;
|
|
938
|
+
const snapshot = {
|
|
939
|
+
seedId: this.config.seedConfig.seedId,
|
|
940
|
+
timestamp: new Date().toISOString(),
|
|
941
|
+
stimulusEventId: stimulus.eventId,
|
|
942
|
+
stimulusType: stimulus.payload.type,
|
|
943
|
+
stimulusPriority: stimulus.priority,
|
|
944
|
+
previousArchetype: previous,
|
|
945
|
+
switchedArchetype,
|
|
946
|
+
profile,
|
|
947
|
+
moodLabel,
|
|
948
|
+
moodState: moodState ? { ...moodState } : undefined,
|
|
949
|
+
};
|
|
950
|
+
for (const cb of this.dynamicVoiceCallbacks) {
|
|
951
|
+
Promise.resolve(cb(snapshot)).catch((err) => {
|
|
952
|
+
console.error(`[Newsroom:${this.config.seedConfig.seedId}] Dynamic voice callback error:`, err);
|
|
953
|
+
});
|
|
954
|
+
}
|
|
955
|
+
}
|
|
908
956
|
}
|
|
909
957
|
function clamp01(value) {
|
|
910
958
|
return Math.max(0, Math.min(1, value));
|