spora 0.7.4 → 0.7.6
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-E3DWYRJM.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-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-Q3YXJ2C6.js → chunk-E5PEY36J.js} +408 -63
- package/dist/chunk-E5PEY36J.js.map +1 -0
- package/dist/chunk-FBHLDOMC.js +2436 -0
- package/dist/chunk-FBHLDOMC.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-GVBLNAFM.js} +18 -21
- package/dist/heartbeat-GVBLNAFM.js.map +1 -0
- package/dist/{identity-VDUW4I2K.js → identity-ASHVWIN5.js} +3 -3
- package/dist/{init-SEJPTOOB.js → init-C4OZPGUC.js} +108 -15
- package/dist/init-C4OZPGUC.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-NTN4FCBD.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-2N2RN6J7.js} +23 -28
- package/dist/web-chat-2N2RN6J7.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-E3DWYRJM.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-NTN4FCBD.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
|
@@ -1,97 +1,278 @@
|
|
|
1
1
|
import {
|
|
2
|
+
loadStrategy,
|
|
3
|
+
renderActiveIntentsForPrompt,
|
|
2
4
|
renderStrategyForPrompt
|
|
3
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-OTZNHIXT.js";
|
|
4
6
|
import {
|
|
5
7
|
renderGoalsForPrompt
|
|
6
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-CAWWG3MD.js";
|
|
7
9
|
import {
|
|
10
|
+
getPerformanceSummary,
|
|
8
11
|
rateLimiter
|
|
9
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-CP6JWCLY.js";
|
|
10
13
|
import {
|
|
11
14
|
loadIdentity,
|
|
12
15
|
renderIdentityDocument
|
|
13
|
-
} from "./chunk-
|
|
16
|
+
} from "./chunk-IULO3GRE.js";
|
|
14
17
|
import {
|
|
15
18
|
loadConfig
|
|
16
|
-
} from "./chunk-
|
|
19
|
+
} from "./chunk-QYFNAGNI.js";
|
|
17
20
|
import {
|
|
18
21
|
getRecentInteractions,
|
|
19
22
|
loadLearnings,
|
|
20
23
|
loadRelationships
|
|
21
|
-
} from "./chunk-
|
|
22
|
-
import {
|
|
23
|
-
paths
|
|
24
|
-
} from "./chunk-3RYCUGXE.js";
|
|
24
|
+
} from "./chunk-BBXHECZ5.js";
|
|
25
25
|
|
|
26
|
-
// src/
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
if (!existsSync(paths.performance)) {
|
|
30
|
-
return { trackedPosts: [], selfMetrics: [] };
|
|
31
|
-
}
|
|
32
|
-
try {
|
|
33
|
-
return JSON.parse(readFileSync(paths.performance, "utf-8"));
|
|
34
|
-
} catch {
|
|
35
|
-
return { trackedPosts: [], selfMetrics: [] };
|
|
36
|
-
}
|
|
26
|
+
// src/runtime/persona-constraints.ts
|
|
27
|
+
function normalizeHandle(handle) {
|
|
28
|
+
return handle.replace(/^@/, "").trim().toLowerCase();
|
|
37
29
|
}
|
|
38
|
-
function
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
const
|
|
43
|
-
|
|
30
|
+
function unique(values) {
|
|
31
|
+
return [...new Set(values)];
|
|
32
|
+
}
|
|
33
|
+
function extractHandles(text) {
|
|
34
|
+
const fromMentions = [...text.matchAll(/@([a-zA-Z0-9_]{1,15})/g)].map((m) => m[1]);
|
|
35
|
+
const fromUrls = [...text.matchAll(/x\.com\/([a-zA-Z0-9_]{1,15})/gi)].map((m) => m[1]);
|
|
36
|
+
return unique(
|
|
37
|
+
[...fromMentions, ...fromUrls].map(normalizeHandle).filter((handle) => handle.length > 0)
|
|
44
38
|
);
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
39
|
+
}
|
|
40
|
+
function includesOnlyQualifier(text) {
|
|
41
|
+
return /\b(only|just|exclusively|strictly)\b/i.test(text);
|
|
42
|
+
}
|
|
43
|
+
function includesReplyIntent(text) {
|
|
44
|
+
return /\b(reply|respond|response|replying)\b/i.test(text);
|
|
45
|
+
}
|
|
46
|
+
function includesInteractionIntent(text) {
|
|
47
|
+
return /\b(interact|engage|talk|chat|speak|communicate|message)\b/i.test(text);
|
|
48
|
+
}
|
|
49
|
+
function impliesNoOriginalPosts(text) {
|
|
50
|
+
const lower = text.toLowerCase();
|
|
51
|
+
if (/\bonly\s+repl(?:y|ies)\b/.test(lower)) return true;
|
|
52
|
+
if (/\brepl(?:y|ies)\s+only\b/.test(lower)) return true;
|
|
53
|
+
if (/\breply-?only\b/.test(lower)) return true;
|
|
54
|
+
if (/\b(no|never|don['’]?t|dont|avoid)\s+(?:do\s+)?(?:original\s+)?posts?\b/.test(lower)) return true;
|
|
55
|
+
if (/\bno\s+tweets?\b/.test(lower)) return true;
|
|
56
|
+
return false;
|
|
57
|
+
}
|
|
58
|
+
function getPersonaConstraints(identityArg) {
|
|
59
|
+
const identity = identityArg ?? loadIdentity();
|
|
60
|
+
const strictReplyHandles = /* @__PURE__ */ new Set();
|
|
61
|
+
const strictInteractionHandles = /* @__PURE__ */ new Set();
|
|
62
|
+
const lines = [
|
|
63
|
+
...identity.goals ?? [],
|
|
64
|
+
...identity.boundaries ?? [],
|
|
65
|
+
identity.bio ?? "",
|
|
66
|
+
identity.originStory ?? "",
|
|
67
|
+
identity.worldview ?? "",
|
|
68
|
+
identity.tone ?? ""
|
|
69
|
+
].filter((value) => typeof value === "string" && value.trim().length > 0);
|
|
70
|
+
let replyOnlyMode = false;
|
|
71
|
+
let noOriginalPosts = false;
|
|
72
|
+
for (const line of lines) {
|
|
73
|
+
const handles = extractHandles(line);
|
|
74
|
+
const hasOnly = includesOnlyQualifier(line);
|
|
75
|
+
const hasReply = includesReplyIntent(line);
|
|
76
|
+
const hasInteract = includesInteractionIntent(line);
|
|
77
|
+
if (impliesNoOriginalPosts(line)) {
|
|
78
|
+
replyOnlyMode = true;
|
|
79
|
+
noOriginalPosts = true;
|
|
63
80
|
}
|
|
64
|
-
if (
|
|
65
|
-
|
|
66
|
-
|
|
81
|
+
if (hasOnly && hasReply) {
|
|
82
|
+
replyOnlyMode = true;
|
|
83
|
+
noOriginalPosts = true;
|
|
84
|
+
for (const handle of handles) {
|
|
85
|
+
strictReplyHandles.add(handle);
|
|
86
|
+
strictInteractionHandles.add(handle);
|
|
87
|
+
}
|
|
88
|
+
continue;
|
|
67
89
|
}
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
const latest = data.selfMetrics[data.selfMetrics.length - 1];
|
|
73
|
-
lines.push(`- Followers: ${latest.followers} | Following: ${latest.following} | Total tweets: ${latest.totalTweets}`);
|
|
74
|
-
const dayAgoMetric = data.selfMetrics.find(
|
|
75
|
-
(m) => Math.abs(new Date(m.checkedAt).getTime() - (Date.now() - 24 * 60 * 60 * 1e3)) < 12 * 60 * 60 * 1e3
|
|
76
|
-
);
|
|
77
|
-
if (dayAgoMetric) {
|
|
78
|
-
const diff = latest.followers - dayAgoMetric.followers;
|
|
79
|
-
if (diff !== 0) {
|
|
80
|
-
lines.push(`- Follower trend: ${diff > 0 ? "+" : ""}${diff} in the last ~24h`);
|
|
90
|
+
if (hasOnly && hasInteract) {
|
|
91
|
+
noOriginalPosts = true;
|
|
92
|
+
for (const handle of handles) {
|
|
93
|
+
strictInteractionHandles.add(handle);
|
|
81
94
|
}
|
|
82
95
|
}
|
|
83
96
|
}
|
|
84
|
-
|
|
97
|
+
if (strictReplyHandles.size > 0) {
|
|
98
|
+
replyOnlyMode = true;
|
|
99
|
+
noOriginalPosts = true;
|
|
100
|
+
}
|
|
101
|
+
if (strictInteractionHandles.size > 0) {
|
|
102
|
+
noOriginalPosts = true;
|
|
103
|
+
}
|
|
104
|
+
return {
|
|
105
|
+
onlyReplyToHandles: [...strictReplyHandles],
|
|
106
|
+
onlyInteractWithHandles: [...strictInteractionHandles],
|
|
107
|
+
noOriginalPosts,
|
|
108
|
+
replyOnlyMode
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
function personaConstraintHandles(constraints) {
|
|
112
|
+
return unique([
|
|
113
|
+
...constraints.onlyReplyToHandles.map(normalizeHandle),
|
|
114
|
+
...constraints.onlyInteractWithHandles.map(normalizeHandle)
|
|
115
|
+
]).filter(Boolean);
|
|
116
|
+
}
|
|
117
|
+
function buildPersonaConstraintLines(constraints) {
|
|
118
|
+
const lines = [];
|
|
119
|
+
if (constraints.onlyReplyToHandles.length > 0) {
|
|
120
|
+
lines.push(`- Hard constraint: only reply to @${constraints.onlyReplyToHandles.join(", @")}`);
|
|
121
|
+
} else if (constraints.replyOnlyMode) {
|
|
122
|
+
lines.push("- Hard constraint: reply-only mode (no like/retweet/follow/post actions).");
|
|
123
|
+
}
|
|
124
|
+
const onlyInteract = constraints.onlyInteractWithHandles.filter(
|
|
125
|
+
(handle) => !constraints.onlyReplyToHandles.includes(handle)
|
|
126
|
+
);
|
|
127
|
+
if (onlyInteract.length > 0) {
|
|
128
|
+
lines.push(`- Hard constraint: only interact with @${onlyInteract.join(", @")}`);
|
|
129
|
+
}
|
|
130
|
+
if (constraints.noOriginalPosts) {
|
|
131
|
+
lines.push("- Hard constraint: do not create standalone original posts.");
|
|
132
|
+
}
|
|
133
|
+
return lines;
|
|
85
134
|
}
|
|
86
135
|
|
|
87
136
|
// src/runtime/prompt-builder.ts
|
|
137
|
+
var PROMPT_TOKEN_STOPWORDS = /* @__PURE__ */ new Set([
|
|
138
|
+
"about",
|
|
139
|
+
"after",
|
|
140
|
+
"again",
|
|
141
|
+
"against",
|
|
142
|
+
"among",
|
|
143
|
+
"because",
|
|
144
|
+
"being",
|
|
145
|
+
"between",
|
|
146
|
+
"could",
|
|
147
|
+
"every",
|
|
148
|
+
"first",
|
|
149
|
+
"from",
|
|
150
|
+
"going",
|
|
151
|
+
"have",
|
|
152
|
+
"having",
|
|
153
|
+
"into",
|
|
154
|
+
"just",
|
|
155
|
+
"like",
|
|
156
|
+
"more",
|
|
157
|
+
"most",
|
|
158
|
+
"only",
|
|
159
|
+
"other",
|
|
160
|
+
"over",
|
|
161
|
+
"really",
|
|
162
|
+
"same",
|
|
163
|
+
"some",
|
|
164
|
+
"than",
|
|
165
|
+
"that",
|
|
166
|
+
"their",
|
|
167
|
+
"there",
|
|
168
|
+
"these",
|
|
169
|
+
"they",
|
|
170
|
+
"this",
|
|
171
|
+
"those",
|
|
172
|
+
"through",
|
|
173
|
+
"very",
|
|
174
|
+
"what",
|
|
175
|
+
"when",
|
|
176
|
+
"where",
|
|
177
|
+
"which",
|
|
178
|
+
"while",
|
|
179
|
+
"with",
|
|
180
|
+
"would",
|
|
181
|
+
"your",
|
|
182
|
+
"youre",
|
|
183
|
+
"dont",
|
|
184
|
+
"cant",
|
|
185
|
+
"will",
|
|
186
|
+
"also",
|
|
187
|
+
"tweet",
|
|
188
|
+
"tweets",
|
|
189
|
+
"thread",
|
|
190
|
+
"threads",
|
|
191
|
+
"future",
|
|
192
|
+
"human",
|
|
193
|
+
"humans",
|
|
194
|
+
"technology",
|
|
195
|
+
"tech",
|
|
196
|
+
"agent",
|
|
197
|
+
"agents",
|
|
198
|
+
"build",
|
|
199
|
+
"building"
|
|
200
|
+
]);
|
|
201
|
+
function normalizeForPrompt(text) {
|
|
202
|
+
return text.toLowerCase().replace(/https?:\/\/\S+/g, " ").replace(/[@#]\w+/g, " ").replace(/[^a-z0-9\s]/g, " ").replace(/\s+/g, " ").trim();
|
|
203
|
+
}
|
|
204
|
+
function recentWrittenTextsForPrompt(limit = 12) {
|
|
205
|
+
return getRecentInteractions(60).filter((entry) => entry.type === "post" || entry.type === "reply").map((entry) => entry.content ?? "").filter((text) => text.trim().length > 0).slice(0, limit);
|
|
206
|
+
}
|
|
207
|
+
function findOverusedOpenings(texts) {
|
|
208
|
+
const counts = /* @__PURE__ */ new Map();
|
|
209
|
+
for (const text of texts) {
|
|
210
|
+
const opening = normalizeForPrompt(text).split(" ").filter(Boolean).slice(0, 4).join(" ");
|
|
211
|
+
if (!opening || opening.split(" ").length < 3) continue;
|
|
212
|
+
counts.set(opening, (counts.get(opening) ?? 0) + 1);
|
|
213
|
+
}
|
|
214
|
+
return [...counts.entries()].filter(([, count]) => count >= 2).sort((a, b) => b[1] - a[1]).slice(0, 4).map(([opening]) => opening);
|
|
215
|
+
}
|
|
216
|
+
function findOverusedTokens(texts) {
|
|
217
|
+
const counts = /* @__PURE__ */ new Map();
|
|
218
|
+
for (const text of texts) {
|
|
219
|
+
const tokens = new Set(
|
|
220
|
+
normalizeForPrompt(text).split(" ").filter((token) => token.length >= 5 && !PROMPT_TOKEN_STOPWORDS.has(token))
|
|
221
|
+
);
|
|
222
|
+
for (const token of tokens) {
|
|
223
|
+
counts.set(token, (counts.get(token) ?? 0) + 1);
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
return [...counts.entries()].filter(([, count]) => count >= 3).sort((a, b) => b[1] - a[1]).slice(0, 6).map(([token]) => token);
|
|
227
|
+
}
|
|
228
|
+
function buildVoiceLockLines(identity) {
|
|
229
|
+
const lines = [];
|
|
230
|
+
const { traits } = identity;
|
|
231
|
+
const assertive = traits.confidence >= 0.72 || traits.aggression >= 0.62 || identity.conflictStyle === "clap-back" || identity.conflictStyle === "debate";
|
|
232
|
+
lines.push(`- Tone anchor: ${identity.tone}`);
|
|
233
|
+
lines.push(`- Conflict style: ${identity.conflictStyle}`);
|
|
234
|
+
lines.push(`- Vocabulary: ${identity.vocabularyStyle}; tweet style: ${identity.tweetStyle}`);
|
|
235
|
+
if (assertive) {
|
|
236
|
+
lines.push("- Be stubborn and decisive. Take a side. Do not hedge or play both sides.");
|
|
237
|
+
}
|
|
238
|
+
if (traits.curiosity >= 0.72) {
|
|
239
|
+
lines.push("- Ask sharp questions when engaging. Curiosity should show up in replies.");
|
|
240
|
+
}
|
|
241
|
+
if (traits.verbosity <= 0.48) {
|
|
242
|
+
lines.push("- Keep replies punchy: 1-2 short sentences unless a longer reply is truly necessary.");
|
|
243
|
+
} else {
|
|
244
|
+
lines.push("- Keep replies compact and human; avoid essay-like paragraphs.");
|
|
245
|
+
}
|
|
246
|
+
if (identity.catchphrases.length > 0) {
|
|
247
|
+
lines.push(`- Your signature phrases: ${identity.catchphrases.slice(0, 3).join(" | ")} (use occasionally, not every post).`);
|
|
248
|
+
}
|
|
249
|
+
if (identity.framework !== "philosopher") {
|
|
250
|
+
lines.push("- Do NOT use philosopher framing: avoid lines like 'the real question', 'the deeper question', or abstract manifesto language.");
|
|
251
|
+
lines.push("- Ground every post/reply in concrete context: a person, a claim, an event, or a direct observation.");
|
|
252
|
+
}
|
|
253
|
+
lines.push("- If the reply could be posted by any generic AI account, rewrite it.");
|
|
254
|
+
return lines;
|
|
255
|
+
}
|
|
88
256
|
function buildSystemPrompt() {
|
|
89
257
|
const identity = loadIdentity();
|
|
258
|
+
const constraints = getPersonaConstraints(identity);
|
|
90
259
|
const config = loadConfig();
|
|
91
260
|
const identityDoc = renderIdentityDocument(identity);
|
|
92
261
|
const sections = [];
|
|
93
262
|
sections.push(`You are ${identity.name} (@${identity.handle}), an autonomous AI agent on X/Twitter.`);
|
|
94
263
|
sections.push("");
|
|
264
|
+
sections.push("## Voice Lock (Non-Negotiable)");
|
|
265
|
+
for (const line of buildVoiceLockLines(identity)) {
|
|
266
|
+
sections.push(line);
|
|
267
|
+
}
|
|
268
|
+
const constraintLines = buildPersonaConstraintLines(constraints);
|
|
269
|
+
if (constraintLines.length > 0) {
|
|
270
|
+
sections.push("- Operational constraints override all other behavior:");
|
|
271
|
+
for (const line of constraintLines) {
|
|
272
|
+
sections.push(` ${line}`);
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
sections.push("");
|
|
95
276
|
sections.push("## Your Identity");
|
|
96
277
|
sections.push(identityDoc);
|
|
97
278
|
sections.push("");
|
|
@@ -125,6 +306,15 @@ function buildSystemPrompt() {
|
|
|
125
306
|
}
|
|
126
307
|
sections.push("");
|
|
127
308
|
}
|
|
309
|
+
const intentsText = renderActiveIntentsForPrompt();
|
|
310
|
+
if (intentsText) {
|
|
311
|
+
sections.push("### Active Mission Intents");
|
|
312
|
+
for (const line of intentsText.split("\n")) {
|
|
313
|
+
if (!line || line.startsWith("**Active mission intents:**")) continue;
|
|
314
|
+
sections.push(line);
|
|
315
|
+
}
|
|
316
|
+
sections.push("");
|
|
317
|
+
}
|
|
128
318
|
const relationships = loadRelationships();
|
|
129
319
|
const topRelationships = Object.values(relationships.accounts).sort((a, b) => b.interactionCount - a.interactionCount).slice(0, 10);
|
|
130
320
|
if (topRelationships.length > 0) {
|
|
@@ -229,6 +419,8 @@ function buildHeartbeatUserMessage(research) {
|
|
|
229
419
|
parts.push("**DON'T:**");
|
|
230
420
|
parts.push(`- Write explanatory or educational posts ("Here's why X matters...")`);
|
|
231
421
|
parts.push('- Start tweets with "I think" or "This is interesting because"');
|
|
422
|
+
parts.push('- Use philosopher opener templates like "The real question is..." or "The deeper question is..."');
|
|
423
|
+
parts.push("- Use colon/semicolon/em-dash manifesto framing in normal tweets");
|
|
232
424
|
parts.push("- Write like a blog post or article \u2014 this is Twitter, keep it punchy");
|
|
233
425
|
parts.push("- Post generic observations nobody would engage with");
|
|
234
426
|
parts.push("- Ignore your timeline and just post into the void");
|
|
@@ -256,7 +448,20 @@ function buildHeartbeatUserMessage(research) {
|
|
|
256
448
|
return parts.join("\n");
|
|
257
449
|
}
|
|
258
450
|
function buildToolDecisionMessage(input) {
|
|
259
|
-
const
|
|
451
|
+
const identity = loadIdentity();
|
|
452
|
+
const strategy = loadStrategy();
|
|
453
|
+
const {
|
|
454
|
+
step,
|
|
455
|
+
maxActions,
|
|
456
|
+
timeline,
|
|
457
|
+
mentions,
|
|
458
|
+
topicSearchResults = [],
|
|
459
|
+
peopleActivity = [],
|
|
460
|
+
executedActions,
|
|
461
|
+
policyFeedback,
|
|
462
|
+
blockedTweetIds = [],
|
|
463
|
+
disallowedActions = []
|
|
464
|
+
} = input;
|
|
260
465
|
const parts = [];
|
|
261
466
|
parts.push(`Heartbeat step ${step + 1} of ${maxActions}.`);
|
|
262
467
|
parts.push("");
|
|
@@ -267,6 +472,18 @@ function buildToolDecisionMessage(input) {
|
|
|
267
472
|
parts.push("3. Avoid repetitive templates, slogans, and lecture-like formats.");
|
|
268
473
|
parts.push("4. Ask questions sometimes. Curiosity beats certainty.");
|
|
269
474
|
parts.push("5. Never reuse the same wording across replies; tailor each reply to the specific tweet.");
|
|
475
|
+
parts.push("6. Never interact with your own tweets. No self-replies, self-likes, or self-retweets.");
|
|
476
|
+
parts.push("");
|
|
477
|
+
const priorityTargets = strategy.peopleToEngage.filter((person) => person.priority === "high").map((person) => `@${person.handle.replace(/^@/, "")}`);
|
|
478
|
+
if (priorityTargets.length > 0) {
|
|
479
|
+
parts.push(`Priority targets: ${priorityTargets.slice(0, 5).join(", ")}`);
|
|
480
|
+
parts.push("If any priority target appears in current context, prefer engaging them.");
|
|
481
|
+
parts.push("");
|
|
482
|
+
}
|
|
483
|
+
parts.push("Voice lock:");
|
|
484
|
+
for (const line of buildVoiceLockLines(identity)) {
|
|
485
|
+
parts.push(line);
|
|
486
|
+
}
|
|
270
487
|
parts.push("");
|
|
271
488
|
if (policyFeedback.length > 0) {
|
|
272
489
|
parts.push("Policy feedback from previous attempts:");
|
|
@@ -282,6 +499,15 @@ function buildToolDecisionMessage(input) {
|
|
|
282
499
|
}
|
|
283
500
|
parts.push("");
|
|
284
501
|
}
|
|
502
|
+
if (blockedTweetIds.length > 0) {
|
|
503
|
+
parts.push("Tweet IDs you must NOT use this heartbeat:");
|
|
504
|
+
parts.push(`- ${blockedTweetIds.slice(0, 20).join(", ")}`);
|
|
505
|
+
parts.push("");
|
|
506
|
+
}
|
|
507
|
+
if (disallowedActions.length > 0) {
|
|
508
|
+
parts.push(`Temporarily disallowed actions this heartbeat: ${disallowedActions.join(", ")}`);
|
|
509
|
+
parts.push("");
|
|
510
|
+
}
|
|
285
511
|
if (mentions.length > 0) {
|
|
286
512
|
parts.push("Mentions:");
|
|
287
513
|
for (const t of mentions.slice(0, 10)) {
|
|
@@ -296,6 +522,26 @@ function buildToolDecisionMessage(input) {
|
|
|
296
522
|
}
|
|
297
523
|
parts.push("");
|
|
298
524
|
}
|
|
525
|
+
if (topicSearchResults.length > 0) {
|
|
526
|
+
parts.push("Topic Search (fresh conversations beyond your home timeline):");
|
|
527
|
+
for (const result of topicSearchResults.slice(0, 2)) {
|
|
528
|
+
parts.push(`- Query: "${result.query}"`);
|
|
529
|
+
for (const t of result.tweets.slice(0, 4)) {
|
|
530
|
+
parts.push(` - @${t.authorHandle}: "${t.text}" [tweet:${t.id}]`);
|
|
531
|
+
}
|
|
532
|
+
}
|
|
533
|
+
parts.push("");
|
|
534
|
+
}
|
|
535
|
+
if (peopleActivity.length > 0) {
|
|
536
|
+
parts.push("People Monitoring (accounts you track):");
|
|
537
|
+
for (const person of peopleActivity.slice(0, 3)) {
|
|
538
|
+
parts.push(`- @${person.handle} (${person.reason})`);
|
|
539
|
+
for (const t of person.tweets.slice(0, 2)) {
|
|
540
|
+
parts.push(` - "${t.text}" [tweet:${t.id}]`);
|
|
541
|
+
}
|
|
542
|
+
}
|
|
543
|
+
parts.push("");
|
|
544
|
+
}
|
|
299
545
|
parts.push("Available tools (choose one):");
|
|
300
546
|
parts.push("- post { content, reasoning }");
|
|
301
547
|
parts.push("- reply { tweetId, content, reasoning }");
|
|
@@ -312,6 +558,101 @@ function buildToolDecisionMessage(input) {
|
|
|
312
558
|
parts.push('{"action":"reply","tweetId":"123","content":"Great point. Curious: what changed your mind?","reasoning":"Directly engages a relevant mention."}');
|
|
313
559
|
return parts.join("\n");
|
|
314
560
|
}
|
|
561
|
+
function buildOpportunityPortfolioMessage(input) {
|
|
562
|
+
const identity = loadIdentity();
|
|
563
|
+
const constraints = getPersonaConstraints(identity);
|
|
564
|
+
const strategy = loadStrategy();
|
|
565
|
+
const recentWritten = recentWrittenTextsForPrompt(12);
|
|
566
|
+
const overusedOpenings = findOverusedOpenings(recentWritten);
|
|
567
|
+
const overusedTokens = findOverusedTokens(recentWritten);
|
|
568
|
+
const { opportunities, maxActions, policyFeedback, executedActions } = input;
|
|
569
|
+
const parts = [];
|
|
570
|
+
parts.push(`Select a portfolio of up to ${maxActions} actions from ranked opportunities.`);
|
|
571
|
+
parts.push("");
|
|
572
|
+
parts.push("Portfolio goals:");
|
|
573
|
+
parts.push("1. Be socially immersed and grounded in real tweets.");
|
|
574
|
+
parts.push("2. Diversify actions and targets, avoid repetitive reply chains.");
|
|
575
|
+
parts.push("3. Prefer quality over quantity; skip weak opportunities.");
|
|
576
|
+
parts.push("4. Advance current strategy targets and focus areas from memory.");
|
|
577
|
+
parts.push("5. Use only listed candidate IDs.");
|
|
578
|
+
parts.push("");
|
|
579
|
+
const priorityTargets = strategy.peopleToEngage.filter((person) => person.priority === "high").map((person) => `@${person.handle.replace(/^@/, "")}`);
|
|
580
|
+
if (priorityTargets.length > 0) {
|
|
581
|
+
parts.push(`Priority targets: ${priorityTargets.slice(0, 5).join(", ")}`);
|
|
582
|
+
parts.push("When opportunities include these targets, prioritize them.");
|
|
583
|
+
parts.push("");
|
|
584
|
+
}
|
|
585
|
+
parts.push("Voice lock:");
|
|
586
|
+
for (const line of buildVoiceLockLines(identity)) {
|
|
587
|
+
parts.push(line);
|
|
588
|
+
}
|
|
589
|
+
const constraintLines = buildPersonaConstraintLines(constraints);
|
|
590
|
+
if (constraintLines.length > 0) {
|
|
591
|
+
parts.push("Operational constraints (hard):");
|
|
592
|
+
for (const line of constraintLines) {
|
|
593
|
+
parts.push(line);
|
|
594
|
+
}
|
|
595
|
+
}
|
|
596
|
+
parts.push("");
|
|
597
|
+
parts.push("Human style rotation:");
|
|
598
|
+
parts.push("- For each `reply`/`post`, pick one lane: quick reaction, curious question, friendly pushback, playful line, plain observation.");
|
|
599
|
+
parts.push("- Do not reuse the same lane for multiple content actions in this portfolio.");
|
|
600
|
+
parts.push("- Keep phrasing short and spoken; contractions and fragments are allowed.");
|
|
601
|
+
if (overusedOpenings.length > 0) {
|
|
602
|
+
parts.push(`- Avoid these repeated opening patterns: ${overusedOpenings.join(" | ")}`);
|
|
603
|
+
}
|
|
604
|
+
if (overusedTokens.length > 0) {
|
|
605
|
+
parts.push(`- Avoid overused anchor words this round: ${overusedTokens.join(", ")}`);
|
|
606
|
+
}
|
|
607
|
+
parts.push("");
|
|
608
|
+
if (policyFeedback.length > 0) {
|
|
609
|
+
parts.push("Latest policy feedback:");
|
|
610
|
+
for (const feedback of policyFeedback.slice(-6)) {
|
|
611
|
+
parts.push(`- ${feedback}`);
|
|
612
|
+
}
|
|
613
|
+
parts.push("");
|
|
614
|
+
}
|
|
615
|
+
if (executedActions.length > 0) {
|
|
616
|
+
parts.push("Actions already executed:");
|
|
617
|
+
for (const action of executedActions) {
|
|
618
|
+
parts.push(`- ${JSON.stringify(action)}`);
|
|
619
|
+
}
|
|
620
|
+
parts.push("");
|
|
621
|
+
}
|
|
622
|
+
parts.push("Opportunities (higher score = better):");
|
|
623
|
+
for (const opportunity of opportunities) {
|
|
624
|
+
parts.push(
|
|
625
|
+
`- ${opportunity.id} | action=${opportunity.actionType} | score=${opportunity.score.toFixed(2)} | source=${opportunity.source}${opportunity.authorHandle ? ` | author=@${opportunity.authorHandle}` : ""}${opportunity.tweetId ? ` | tweet=${opportunity.tweetId}` : ""}`
|
|
626
|
+
);
|
|
627
|
+
parts.push(` summary: ${opportunity.summary}`);
|
|
628
|
+
parts.push(` context: ${opportunity.context}`);
|
|
629
|
+
if (opportunity.requiresContent) {
|
|
630
|
+
parts.push(" content_required: true");
|
|
631
|
+
}
|
|
632
|
+
}
|
|
633
|
+
parts.push("");
|
|
634
|
+
parts.push("Return JSON only in this shape:");
|
|
635
|
+
parts.push("```json");
|
|
636
|
+
parts.push("{");
|
|
637
|
+
parts.push(' "selections": [');
|
|
638
|
+
parts.push(' { "candidateId": "opp-3", "content": "optional for reply/post", "reasoning": "short reason" }');
|
|
639
|
+
parts.push(" ]");
|
|
640
|
+
parts.push("}");
|
|
641
|
+
parts.push("```");
|
|
642
|
+
parts.push("Rules:");
|
|
643
|
+
parts.push("- For `reply` and `post`, include `content`.");
|
|
644
|
+
parts.push("- Keep content concise, natural, and non-repetitive.");
|
|
645
|
+
parts.push("- Avoid explanatory/essay voice. No lecture framing.");
|
|
646
|
+
parts.push("- Do NOT use abstract philosopher framing unless the identity framework is explicitly philosopher.");
|
|
647
|
+
parts.push("- Prefer short, human syntax: plain sentence fragments are fine.");
|
|
648
|
+
parts.push("- Avoid colon/semicolon/em-dash for non-philosopher personas.");
|
|
649
|
+
parts.push("- Prefer short conversational language: plain words, occasional question, and direct reaction.");
|
|
650
|
+
parts.push("- Reply content target: usually 8-24 words, max 2 short sentences.");
|
|
651
|
+
parts.push("- Prefer at least one non-reply action when viable.");
|
|
652
|
+
parts.push("- Do not target the same author repeatedly in one portfolio.");
|
|
653
|
+
parts.push("- Avoid consensus phrasing like 'you're both right' if your persona is assertive.");
|
|
654
|
+
return parts.join("\n");
|
|
655
|
+
}
|
|
315
656
|
function buildChatPrompt() {
|
|
316
657
|
const identity = loadIdentity();
|
|
317
658
|
const identityDoc = renderIdentityDocument(identity);
|
|
@@ -520,11 +861,15 @@ function buildReflectionPrompt(actionResults) {
|
|
|
520
861
|
}
|
|
521
862
|
|
|
522
863
|
export {
|
|
864
|
+
getPersonaConstraints,
|
|
865
|
+
personaConstraintHandles,
|
|
866
|
+
buildPersonaConstraintLines,
|
|
523
867
|
buildSystemPrompt,
|
|
524
868
|
buildHeartbeatUserMessage,
|
|
525
869
|
buildToolDecisionMessage,
|
|
870
|
+
buildOpportunityPortfolioMessage,
|
|
526
871
|
buildChatPrompt,
|
|
527
872
|
buildTrainingChatPrompt,
|
|
528
873
|
buildReflectionPrompt
|
|
529
874
|
};
|
|
530
|
-
//# sourceMappingURL=chunk-
|
|
875
|
+
//# sourceMappingURL=chunk-E5PEY36J.js.map
|