spora 0.7.6 → 0.7.7
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 → autonomy-NNFTM5NW.js} +3 -3
- package/dist/{chunk-E5PEY36J.js → chunk-JIMONWKO.js} +342 -2
- package/dist/chunk-JIMONWKO.js.map +1 -0
- package/dist/{chunk-FBHLDOMC.js → chunk-TTM54LQR.js} +382 -49
- package/dist/chunk-TTM54LQR.js.map +1 -0
- package/dist/cli.js +5 -5
- package/dist/{heartbeat-GVBLNAFM.js → heartbeat-WJJSGUAQ.js} +3 -3
- package/dist/{init-C4OZPGUC.js → init-6HY4ZPFJ.js} +3 -3
- package/dist/{prompt-builder-NTN4FCBD.js → prompt-builder-ZFUZNQY2.js} +2 -2
- package/dist/{web-chat-2N2RN6J7.js → web-chat-AKUEBSWS.js} +4 -4
- package/package.json +1 -1
- package/dist/chunk-E5PEY36J.js.map +0 -1
- package/dist/chunk-FBHLDOMC.js.map +0 -1
- /package/dist/{autonomy-E3DWYRJM.js.map → autonomy-NNFTM5NW.js.map} +0 -0
- /package/dist/{heartbeat-GVBLNAFM.js.map → heartbeat-WJJSGUAQ.js.map} +0 -0
- /package/dist/{init-C4OZPGUC.js.map → init-6HY4ZPFJ.js.map} +0 -0
- /package/dist/{prompt-builder-NTN4FCBD.js.map → prompt-builder-ZFUZNQY2.js.map} +0 -0
- /package/dist/{web-chat-2N2RN6J7.js.map → web-chat-AKUEBSWS.js.map} +0 -0
|
@@ -8,9 +8,10 @@ import {
|
|
|
8
8
|
buildOpportunityPortfolioMessage,
|
|
9
9
|
buildPersonaConstraintLines,
|
|
10
10
|
buildSystemPrompt,
|
|
11
|
+
compilePersonaActionProfile,
|
|
11
12
|
getPersonaConstraints,
|
|
12
13
|
personaConstraintHandles
|
|
13
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-JIMONWKO.js";
|
|
14
15
|
import {
|
|
15
16
|
listIntents,
|
|
16
17
|
loadStrategy,
|
|
@@ -783,8 +784,9 @@ function evaluateActionPolicy(context) {
|
|
|
783
784
|
}
|
|
784
785
|
}
|
|
785
786
|
if (action.action === "reply" && action.tweetId) {
|
|
787
|
+
const inStrictTargetMode = strictReplyHandles.size > 0 || strictInteractHandles.size > 0;
|
|
786
788
|
const repliesThisHeartbeat = executedActions.filter((a) => a.action === "reply").length;
|
|
787
|
-
if (repliesThisHeartbeat >= 2) {
|
|
789
|
+
if (repliesThisHeartbeat >= 2 && !inStrictTargetMode) {
|
|
788
790
|
return {
|
|
789
791
|
allowed: false,
|
|
790
792
|
reason: "Reply cap reached for this heartbeat. Use another tool action."
|
|
@@ -795,7 +797,7 @@ function evaluateActionPolicy(context) {
|
|
|
795
797
|
const repliedAuthors = new Set(
|
|
796
798
|
executedActions.filter((a) => a.action === "reply" && a.tweetId).map((a) => normalizeHandle(tweetById.get(a.tweetId)?.authorHandle)).filter(Boolean)
|
|
797
799
|
);
|
|
798
|
-
if (repliedAuthors.has(currentAuthor)) {
|
|
800
|
+
if (repliedAuthors.has(currentAuthor) && !inStrictTargetMode) {
|
|
799
801
|
return {
|
|
800
802
|
allowed: false,
|
|
801
803
|
reason: `Already replied to @${currentAuthor} this heartbeat. Diversify interactions.`
|
|
@@ -1020,6 +1022,9 @@ function shuffle(items) {
|
|
|
1020
1022
|
}
|
|
1021
1023
|
return arr;
|
|
1022
1024
|
}
|
|
1025
|
+
function clampInt(value, min, max) {
|
|
1026
|
+
return Math.max(min, Math.min(max, Math.round(value)));
|
|
1027
|
+
}
|
|
1023
1028
|
function buildTopicQueryVariants(topic) {
|
|
1024
1029
|
const trimmed = topic.trim();
|
|
1025
1030
|
if (!trimmed) return [];
|
|
@@ -1244,12 +1249,17 @@ async function runTopicSearch(client, heartbeatCount, seedTweets) {
|
|
|
1244
1249
|
const constraints = getPersonaConstraints(identity);
|
|
1245
1250
|
const strictHandles = personaConstraintHandles(constraints).filter(Boolean);
|
|
1246
1251
|
const strategy = loadStrategy();
|
|
1252
|
+
const personaProfile = compilePersonaActionProfile({ identity, strategy, constraints });
|
|
1247
1253
|
const selfHandle = canonicalAgentHandle(identity.handle);
|
|
1254
|
+
const topicSearchBias = personaProfile.sourceBias.topic_search;
|
|
1255
|
+
const peopleWatchBias = personaProfile.sourceBias.people_watch;
|
|
1248
1256
|
const allTopics = [
|
|
1257
|
+
...personaProfile.priorityTopics,
|
|
1249
1258
|
...identity.topics ?? [],
|
|
1250
1259
|
...strategy.currentFocus
|
|
1251
1260
|
].flatMap(splitTopicSignal).filter(Boolean);
|
|
1252
|
-
const
|
|
1261
|
+
const discoveredBudget = clampInt(1 + Math.max(0, topicSearchBias), 1, 3);
|
|
1262
|
+
const discovered = discoverQueriesFromTweets(seedTweets, discoveredBudget);
|
|
1253
1263
|
const targetHandles = [.../* @__PURE__ */ new Set([
|
|
1254
1264
|
...strategy.peopleToEngage.filter((person) => person.priority === "high" || person.priority === "medium").map((person) => person.handle.replace(/^@/, "").toLowerCase()),
|
|
1255
1265
|
...(identity.heroes ?? []).map((handle) => handle.replace(/^@/, "").toLowerCase())
|
|
@@ -1257,11 +1267,16 @@ async function runTopicSearch(client, heartbeatCount, seedTweets) {
|
|
|
1257
1267
|
const strictQueries = buildTargetedPersonQueries(
|
|
1258
1268
|
strictHandles.filter((handle) => handle !== selfHandle),
|
|
1259
1269
|
heartbeatCount,
|
|
1260
|
-
|
|
1270
|
+
clampInt(2 + Math.max(0, topicSearchBias), 1, 4)
|
|
1271
|
+
);
|
|
1272
|
+
const personQueries = buildTargetedPersonQueries(
|
|
1273
|
+
targetHandles,
|
|
1274
|
+
heartbeatCount,
|
|
1275
|
+
clampInt(1 + Math.max(0, peopleWatchBias), 0, 3)
|
|
1261
1276
|
);
|
|
1262
|
-
const
|
|
1263
|
-
const topicQueries = allTopics.length > 0 ? pickTopicQueries(allTopics, Math.min(
|
|
1264
|
-
const discoveredQueries = discovered.length > 0 ? pickDirectQueries(discovered, Math.min(
|
|
1277
|
+
const topicBudget = clampInt(3 + topicSearchBias, 1, 5);
|
|
1278
|
+
const topicQueries = allTopics.length > 0 ? pickTopicQueries(allTopics, Math.min(topicBudget, Math.max(1, allTopics.length))) : [];
|
|
1279
|
+
const discoveredQueries = discovered.length > 0 ? pickDirectQueries(discovered, Math.min(discoveredBudget, discovered.length)) : [];
|
|
1265
1280
|
const topicsToSearch = strictQueries.length > 0 ? [...new Set(strictQueries)] : [.../* @__PURE__ */ new Set([...topicQueries, ...discoveredQueries, ...personQueries])];
|
|
1266
1281
|
if (topicsToSearch.length === 0) return [];
|
|
1267
1282
|
const results = [];
|
|
@@ -1287,6 +1302,7 @@ async function runPeopleMonitoring(client, heartbeatCount, seedTweets) {
|
|
|
1287
1302
|
const strategy = loadStrategy();
|
|
1288
1303
|
const identity = loadIdentity();
|
|
1289
1304
|
const constraints = getPersonaConstraints(identity);
|
|
1305
|
+
const personaProfile = compilePersonaActionProfile({ identity, strategy, constraints });
|
|
1290
1306
|
const strictHandles = personaConstraintHandles(constraints).map((handle) => canonicalAgentHandle(handle)).filter((handle) => handle.length > 0);
|
|
1291
1307
|
const selfHandle = identity.handle.replace(/^@/, "").toLowerCase();
|
|
1292
1308
|
const relationships = loadRelationships();
|
|
@@ -1335,9 +1351,10 @@ async function runPeopleMonitoring(client, heartbeatCount, seedTweets) {
|
|
|
1335
1351
|
for (const p of strategy.peopleToEngage.filter((p2) => p2.priority === "high")) {
|
|
1336
1352
|
addPerson(p.handle, p.reason, true);
|
|
1337
1353
|
}
|
|
1354
|
+
const sporaPinInterval = personaProfile.sourceBias.people_watch >= 0.6 ? 4 : 8;
|
|
1338
1355
|
for (const handle of networkHandles) {
|
|
1339
1356
|
if (handle === "sporaai") {
|
|
1340
|
-
const pinSpora = heartbeatCount %
|
|
1357
|
+
const pinSpora = heartbeatCount % sporaPinInterval === 0;
|
|
1341
1358
|
addPerson(handle, "core Spora profile", pinSpora);
|
|
1342
1359
|
} else {
|
|
1343
1360
|
addPerson(handle, "spora agent network");
|
|
@@ -1362,7 +1379,8 @@ async function runPeopleMonitoring(client, heartbeatCount, seedTweets) {
|
|
|
1362
1379
|
addPerson(handle, "active voice in current conversations");
|
|
1363
1380
|
}
|
|
1364
1381
|
if (people.length === 0) return [];
|
|
1365
|
-
const
|
|
1382
|
+
const monitoringBudget = clampInt(3 + personaProfile.sourceBias.people_watch, 2, 5);
|
|
1383
|
+
const budget = Math.min(monitoringBudget, people.length);
|
|
1366
1384
|
const selected = [];
|
|
1367
1385
|
const selectedHandles = /* @__PURE__ */ new Set();
|
|
1368
1386
|
const pinned = people.filter((person) => person.pinned);
|
|
@@ -1464,6 +1482,7 @@ function buildPersonaContext() {
|
|
|
1464
1482
|
const identity = loadIdentity();
|
|
1465
1483
|
const constraints = getPersonaConstraints(identity);
|
|
1466
1484
|
const strategy = loadStrategy();
|
|
1485
|
+
const actionProfile = compilePersonaActionProfile({ identity, strategy, constraints });
|
|
1467
1486
|
const focusKeywords = unique(
|
|
1468
1487
|
[
|
|
1469
1488
|
...identity.topics,
|
|
@@ -1486,7 +1505,22 @@ function buildPersonaContext() {
|
|
|
1486
1505
|
(identity.heroes ?? []).map((handle) => normalizeHandle3(handle)).filter(Boolean)
|
|
1487
1506
|
);
|
|
1488
1507
|
const networkHandles = new Set(listAgentNetworkHandles(60).map((handle) => normalizeHandle3(handle)).filter(Boolean));
|
|
1489
|
-
return { focusKeywords, avoidKeywords, priorityHandles, heroHandles, networkHandles };
|
|
1508
|
+
return { focusKeywords, avoidKeywords, priorityHandles, heroHandles, networkHandles, actionProfile };
|
|
1509
|
+
}
|
|
1510
|
+
function personaActionDelta(actionType, source, profile) {
|
|
1511
|
+
return profile.actionBias[actionType] * 0.9 + profile.sourceBias[source] * 0.55;
|
|
1512
|
+
}
|
|
1513
|
+
function isActionStronglySuppressed(actionType, profile) {
|
|
1514
|
+
return profile.actionBias[actionType] <= -1.35;
|
|
1515
|
+
}
|
|
1516
|
+
function matchesPersonaGeneratedProfile(actionType, source, profile) {
|
|
1517
|
+
const actionBias = profile.actionBias[actionType];
|
|
1518
|
+
const sourceBias = profile.sourceBias[source];
|
|
1519
|
+
const combined = personaActionDelta(actionType, source, profile);
|
|
1520
|
+
if (actionBias <= -0.55) return false;
|
|
1521
|
+
if (sourceBias <= -1.05) return false;
|
|
1522
|
+
if (combined <= -0.3) return false;
|
|
1523
|
+
return true;
|
|
1490
1524
|
}
|
|
1491
1525
|
function phraseMatchScore(text, keywords) {
|
|
1492
1526
|
if (keywords.length === 0) return 0;
|
|
@@ -1591,6 +1625,7 @@ function buildActionOpportunities(input) {
|
|
|
1591
1625
|
const onlyReplyHandles = new Set(constraints.onlyReplyToHandles.map((h) => normalizeHandle3(h)));
|
|
1592
1626
|
const onlyInteractHandles = new Set(constraints.onlyInteractWithHandles.map((h) => normalizeHandle3(h)));
|
|
1593
1627
|
const persona = buildPersonaContext();
|
|
1628
|
+
const actionProfile = persona.actionProfile;
|
|
1594
1629
|
const recent = getRecentInteractions(300);
|
|
1595
1630
|
const {
|
|
1596
1631
|
repliedTweetIds,
|
|
@@ -1638,27 +1673,33 @@ function buildActionOpportunities(input) {
|
|
|
1638
1673
|
persona
|
|
1639
1674
|
);
|
|
1640
1675
|
const shortTweet = clip(tweet.text, 170);
|
|
1641
|
-
|
|
1642
|
-
|
|
1643
|
-
|
|
1644
|
-
|
|
1645
|
-
|
|
1646
|
-
|
|
1647
|
-
|
|
1648
|
-
|
|
1649
|
-
|
|
1650
|
-
|
|
1651
|
-
|
|
1652
|
-
|
|
1653
|
-
|
|
1676
|
+
const replyScore = baseScore + 0.7 + personaActionDelta("reply", source, actionProfile);
|
|
1677
|
+
const likeScore = baseScore + 0.2 + personaActionDelta("like", source, actionProfile);
|
|
1678
|
+
const retweetScore = baseScore - 0.1 + personaActionDelta("retweet", source, actionProfile);
|
|
1679
|
+
const followScore = baseScore - 0.2 + personaActionDelta("follow", source, actionProfile);
|
|
1680
|
+
if (!isActionStronglySuppressed("reply", actionProfile) && matchesPersonaGeneratedProfile("reply", source, actionProfile)) {
|
|
1681
|
+
opportunities.push({
|
|
1682
|
+
id: nextId(),
|
|
1683
|
+
armKey: armKey("reply", source),
|
|
1684
|
+
actionType: "reply",
|
|
1685
|
+
source,
|
|
1686
|
+
score: replyScore,
|
|
1687
|
+
summary: `Reply to @${handle} from ${source}`,
|
|
1688
|
+
authorHandle: handle,
|
|
1689
|
+
tweetId: tweet.id,
|
|
1690
|
+
requiresContent: true,
|
|
1691
|
+
template: { action: "reply", tweetId: tweet.id, source, targetHandle: `@${handle}` },
|
|
1692
|
+
context: `@${handle}: "${shortTweet}"`
|
|
1693
|
+
});
|
|
1694
|
+
}
|
|
1654
1695
|
const stronglyRelevant = alignment >= 0.35 || source === "mention" || source === "people_watch" || persona.priorityHandles.has(handle);
|
|
1655
|
-
if (onlyReplyHandles.size === 0 && !constraints.replyOnlyMode && !likedTweetIds.has(tweet.id) &&
|
|
1696
|
+
if (onlyReplyHandles.size === 0 && !constraints.replyOnlyMode && !isActionStronglySuppressed("like", actionProfile) && matchesPersonaGeneratedProfile("like", source, actionProfile) && !likedTweetIds.has(tweet.id) && likeScore >= 1.8 && stronglyRelevant) {
|
|
1656
1697
|
opportunities.push({
|
|
1657
1698
|
id: nextId(),
|
|
1658
1699
|
armKey: armKey("like", source),
|
|
1659
1700
|
actionType: "like",
|
|
1660
1701
|
source,
|
|
1661
|
-
score:
|
|
1702
|
+
score: likeScore,
|
|
1662
1703
|
summary: `Like @${handle} from ${source}`,
|
|
1663
1704
|
authorHandle: handle,
|
|
1664
1705
|
tweetId: tweet.id,
|
|
@@ -1667,13 +1708,13 @@ function buildActionOpportunities(input) {
|
|
|
1667
1708
|
context: `@${handle}: "${shortTweet}"`
|
|
1668
1709
|
});
|
|
1669
1710
|
}
|
|
1670
|
-
if (onlyReplyHandles.size === 0 && !constraints.replyOnlyMode && !retweetedTweetIds.has(tweet.id) &&
|
|
1711
|
+
if (onlyReplyHandles.size === 0 && !constraints.replyOnlyMode && !isActionStronglySuppressed("retweet", actionProfile) && matchesPersonaGeneratedProfile("retweet", source, actionProfile) && !retweetedTweetIds.has(tweet.id) && retweetScore >= 2.6 && alignment >= 0.15) {
|
|
1671
1712
|
opportunities.push({
|
|
1672
1713
|
id: nextId(),
|
|
1673
1714
|
armKey: armKey("retweet", source),
|
|
1674
1715
|
actionType: "retweet",
|
|
1675
1716
|
source,
|
|
1676
|
-
score:
|
|
1717
|
+
score: retweetScore,
|
|
1677
1718
|
summary: `Retweet @${handle} from ${source}`,
|
|
1678
1719
|
authorHandle: handle,
|
|
1679
1720
|
tweetId: tweet.id,
|
|
@@ -1682,7 +1723,7 @@ function buildActionOpportunities(input) {
|
|
|
1682
1723
|
context: `@${handle}: "${shortTweet}"`
|
|
1683
1724
|
});
|
|
1684
1725
|
}
|
|
1685
|
-
const shouldConsiderFollow = onlyReplyHandles.size === 0 && !constraints.replyOnlyMode && !followedHandles.has(handle) && !followOpportunityByHandle.has(handle) && !isLikelySyntheticHandle2(handle) &&
|
|
1726
|
+
const shouldConsiderFollow = onlyReplyHandles.size === 0 && !constraints.replyOnlyMode && !isActionStronglySuppressed("follow", actionProfile) && matchesPersonaGeneratedProfile("follow", source, actionProfile) && !followedHandles.has(handle) && !followOpportunityByHandle.has(handle) && !isLikelySyntheticHandle2(handle) && followScore >= 3 && (persona.priorityHandles.has(handle) || persona.heroHandles.has(handle) || source === "mention" || alignment >= 0.8);
|
|
1686
1727
|
if (shouldConsiderFollow) {
|
|
1687
1728
|
followOpportunityByHandle.add(handle);
|
|
1688
1729
|
opportunities.push({
|
|
@@ -1690,7 +1731,7 @@ function buildActionOpportunities(input) {
|
|
|
1690
1731
|
armKey: armKey("follow", source),
|
|
1691
1732
|
actionType: "follow",
|
|
1692
1733
|
source,
|
|
1693
|
-
score:
|
|
1734
|
+
score: followScore,
|
|
1694
1735
|
summary: `Follow @${handle}`,
|
|
1695
1736
|
authorHandle: handle,
|
|
1696
1737
|
requiresContent: false,
|
|
@@ -1700,17 +1741,19 @@ function buildActionOpportunities(input) {
|
|
|
1700
1741
|
}
|
|
1701
1742
|
}
|
|
1702
1743
|
const queryList = research.topicSearchResults.map((r) => r.query).filter(Boolean);
|
|
1703
|
-
if (queryList.length > 0 && !constraints.noOriginalPosts && !constraints.replyOnlyMode && onlyInteractHandles.size === 0 && onlyReplyHandles.size === 0) {
|
|
1744
|
+
if (queryList.length > 0 && !constraints.noOriginalPosts && !constraints.replyOnlyMode && !isActionStronglySuppressed("post", actionProfile) && matchesPersonaGeneratedProfile("post", "synthesis", actionProfile) && onlyInteractHandles.size === 0 && onlyReplyHandles.size === 0) {
|
|
1745
|
+
const synthesisScore = 2.25 + personaActionDelta("post", "synthesis", actionProfile);
|
|
1746
|
+
const priorityTopicHint = actionProfile.priorityTopics.slice(0, 3).join(", ");
|
|
1704
1747
|
opportunities.push({
|
|
1705
1748
|
id: nextId(),
|
|
1706
1749
|
armKey: armKey("post", "synthesis"),
|
|
1707
1750
|
actionType: "post",
|
|
1708
1751
|
source: "synthesis",
|
|
1709
|
-
score:
|
|
1752
|
+
score: synthesisScore,
|
|
1710
1753
|
summary: "Post an original thought synthesized from active conversations",
|
|
1711
1754
|
requiresContent: true,
|
|
1712
1755
|
template: { action: "post", source: "synthesis" },
|
|
1713
|
-
context: `Weave a fresh take from active topics: ${queryList.slice(0, 4).join(", ")}`
|
|
1756
|
+
context: `Weave a fresh take from active topics: ${queryList.slice(0, 4).join(", ")}${priorityTopicHint ? `. Persona-priority topics: ${priorityTopicHint}` : ""}`
|
|
1714
1757
|
});
|
|
1715
1758
|
}
|
|
1716
1759
|
opportunities.sort((a, b) => b.score - a.score);
|
|
@@ -1783,6 +1826,202 @@ async function planActionPortfolio(input) {
|
|
|
1783
1826
|
return actions;
|
|
1784
1827
|
}
|
|
1785
1828
|
|
|
1829
|
+
// src/runtime/mission-director.ts
|
|
1830
|
+
function normalizeHandle4(handle) {
|
|
1831
|
+
return handle.replace(/^@/, "").trim().toLowerCase();
|
|
1832
|
+
}
|
|
1833
|
+
function unique2(values) {
|
|
1834
|
+
return [...new Set(values)];
|
|
1835
|
+
}
|
|
1836
|
+
function isAction(value) {
|
|
1837
|
+
return ["reply", "like", "retweet", "follow", "post"].includes(value);
|
|
1838
|
+
}
|
|
1839
|
+
function sanitizeActions(raw, fallback) {
|
|
1840
|
+
if (!Array.isArray(raw) || raw.length === 0) return fallback;
|
|
1841
|
+
const cleaned = raw.map((item) => String(item).trim().toLowerCase()).filter((item) => isAction(item));
|
|
1842
|
+
return cleaned.length > 0 ? unique2(cleaned) : fallback;
|
|
1843
|
+
}
|
|
1844
|
+
function parseJsonObject(text) {
|
|
1845
|
+
const fenced = text.match(/```(?:json)?\s*([\s\S]*?)```/i)?.[1];
|
|
1846
|
+
const candidates = [fenced, text].filter((v) => Boolean(v)).map((v) => v.trim());
|
|
1847
|
+
for (const candidate of candidates) {
|
|
1848
|
+
try {
|
|
1849
|
+
return JSON.parse(candidate);
|
|
1850
|
+
} catch {
|
|
1851
|
+
}
|
|
1852
|
+
const obj = candidate.match(/\{[\s\S]*\}/);
|
|
1853
|
+
if (!obj) continue;
|
|
1854
|
+
try {
|
|
1855
|
+
return JSON.parse(obj[0]);
|
|
1856
|
+
} catch {
|
|
1857
|
+
}
|
|
1858
|
+
}
|
|
1859
|
+
return null;
|
|
1860
|
+
}
|
|
1861
|
+
function buildPersonaAllowedActions(profile, noOriginalPosts) {
|
|
1862
|
+
const byBias = profile.prioritizedActions.filter((action) => profile.actionBias[action] > -1.1);
|
|
1863
|
+
const withFallback = byBias.length > 0 ? byBias : ["reply", "like", "retweet", "follow", "post"];
|
|
1864
|
+
const filtered = noOriginalPosts ? withFallback.filter((action) => action !== "post") : withFallback;
|
|
1865
|
+
return unique2(filtered).slice(0, 5);
|
|
1866
|
+
}
|
|
1867
|
+
function buildDeterministicMission(research, profile) {
|
|
1868
|
+
const identity = loadIdentity();
|
|
1869
|
+
const strategy = loadStrategy();
|
|
1870
|
+
const constraints = getPersonaConstraints(identity);
|
|
1871
|
+
const constraintTargets = personaConstraintHandles(constraints).map(normalizeHandle4).filter(Boolean);
|
|
1872
|
+
const focusTopics = unique2(
|
|
1873
|
+
[
|
|
1874
|
+
...profile.priorityTopics,
|
|
1875
|
+
...identity.topics ?? [],
|
|
1876
|
+
...strategy.currentFocus,
|
|
1877
|
+
...strategy.shortTermGoals
|
|
1878
|
+
].map((topic) => String(topic).trim()).filter(Boolean).slice(0, 10)
|
|
1879
|
+
);
|
|
1880
|
+
const strictReply = constraints.onlyReplyToHandles.length > 0 || constraints.replyOnlyMode;
|
|
1881
|
+
if (strictReply) {
|
|
1882
|
+
const strictTargets = constraints.onlyReplyToHandles.length > 0 ? constraints.onlyReplyToHandles.map(normalizeHandle4) : constraintTargets;
|
|
1883
|
+
return {
|
|
1884
|
+
mode: "strict_target_reply",
|
|
1885
|
+
objective: strictTargets.length > 0 ? `Reply only to @${strictTargets.join(", @")} while staying fully in character.` : "Reply-only mode. Stay in character and do not perform non-reply actions.",
|
|
1886
|
+
allowedActions: ["reply"],
|
|
1887
|
+
targetHandles: strictTargets,
|
|
1888
|
+
focusTopics,
|
|
1889
|
+
rationale: "Hard persona constraint detected in identity goals/boundaries/bio."
|
|
1890
|
+
};
|
|
1891
|
+
}
|
|
1892
|
+
if (constraintTargets.length > 0) {
|
|
1893
|
+
return {
|
|
1894
|
+
mode: "strict_target_interaction",
|
|
1895
|
+
objective: `Interact only with @${constraintTargets.join(", @")} in persona voice.`,
|
|
1896
|
+
allowedActions: constraints.noOriginalPosts ? ["reply", "like", "retweet", "follow"] : ["reply", "like", "retweet", "follow", "post"],
|
|
1897
|
+
targetHandles: constraintTargets,
|
|
1898
|
+
focusTopics,
|
|
1899
|
+
rationale: "Hard persona interaction target detected."
|
|
1900
|
+
};
|
|
1901
|
+
}
|
|
1902
|
+
const preferredActions = buildPersonaAllowedActions(profile, constraints.noOriginalPosts);
|
|
1903
|
+
const primaryActionHint = preferredActions.length > 0 ? preferredActions.slice(0, 2).join(" + ") : "context-aware interactions";
|
|
1904
|
+
return {
|
|
1905
|
+
mode: "persona_balanced",
|
|
1906
|
+
objective: `Advance ${identity.name}'s mission through ${primaryActionHint} while staying in strict persona voice.`,
|
|
1907
|
+
allowedActions: preferredActions,
|
|
1908
|
+
targetHandles: [],
|
|
1909
|
+
focusTopics,
|
|
1910
|
+
rationale: `No strict target lock; persona profile drives soft action/source priorities (${profile.rationale.slice(0, 2).join("; ")}).`
|
|
1911
|
+
};
|
|
1912
|
+
}
|
|
1913
|
+
function buildMissionPrompt(research, fallback, profile) {
|
|
1914
|
+
const identity = loadIdentity();
|
|
1915
|
+
const constraints = getPersonaConstraints(identity);
|
|
1916
|
+
const topTimeline = research.timeline.slice(0, 5);
|
|
1917
|
+
const topMentions = research.mentions.slice(0, 5);
|
|
1918
|
+
const topicQueries = research.topicSearchResults.map((r) => r.query).filter(Boolean).slice(0, 6);
|
|
1919
|
+
const people = research.peopleActivity.map((p) => p.handle).filter(Boolean).slice(0, 6);
|
|
1920
|
+
const lines = [];
|
|
1921
|
+
lines.push("Create one heartbeat mission JSON for this agent.");
|
|
1922
|
+
lines.push("Hard rule: Persona constraints override everything.");
|
|
1923
|
+
lines.push("");
|
|
1924
|
+
lines.push(`Agent: ${identity.name} (@${identity.handle})`);
|
|
1925
|
+
lines.push(`Bio: ${identity.bio}`);
|
|
1926
|
+
lines.push(`Tone: ${identity.tone}`);
|
|
1927
|
+
lines.push(`Goals: ${(identity.goals ?? []).join(" | ")}`);
|
|
1928
|
+
lines.push(`Boundaries: ${(identity.boundaries ?? []).join(" | ")}`);
|
|
1929
|
+
lines.push(`Framework: ${identity.framework}`);
|
|
1930
|
+
lines.push(`Existing strict constraints: ${JSON.stringify(constraints)}`);
|
|
1931
|
+
lines.push(`Persona action priors: ${JSON.stringify({
|
|
1932
|
+
prioritizedActions: profile.prioritizedActions.slice(0, 5),
|
|
1933
|
+
priorityTopics: profile.priorityTopics.slice(0, 8),
|
|
1934
|
+
actionBias: profile.actionBias,
|
|
1935
|
+
sourceBias: profile.sourceBias,
|
|
1936
|
+
rationale: profile.rationale.slice(0, 5)
|
|
1937
|
+
})}`);
|
|
1938
|
+
lines.push("");
|
|
1939
|
+
lines.push(`Fallback mission if unsure: ${JSON.stringify(fallback)}`);
|
|
1940
|
+
lines.push("");
|
|
1941
|
+
lines.push(`Observed timeline sample (${topTimeline.length}):`);
|
|
1942
|
+
for (const tweet of topTimeline) {
|
|
1943
|
+
lines.push(`- @${tweet.authorHandle}: ${tweet.text.slice(0, 180)}`);
|
|
1944
|
+
}
|
|
1945
|
+
lines.push(`Observed mentions sample (${topMentions.length}):`);
|
|
1946
|
+
for (const tweet of topMentions) {
|
|
1947
|
+
lines.push(`- @${tweet.authorHandle}: ${tweet.text.slice(0, 180)}`);
|
|
1948
|
+
}
|
|
1949
|
+
lines.push(`Topic queries: ${topicQueries.join(" | ") || "none"}`);
|
|
1950
|
+
lines.push(`People watched: ${people.map((h) => `@${h}`).join(", ") || "none"}`);
|
|
1951
|
+
lines.push("");
|
|
1952
|
+
lines.push("Return JSON only with this shape:");
|
|
1953
|
+
lines.push("{");
|
|
1954
|
+
lines.push(' "mode": "strict_target_reply|strict_target_interaction|persona_balanced",');
|
|
1955
|
+
lines.push(' "objective": "one-sentence mission",');
|
|
1956
|
+
lines.push(' "allowedActions": ["reply","like","retweet","follow","post"],');
|
|
1957
|
+
lines.push(' "targetHandles": ["grok"],');
|
|
1958
|
+
lines.push(' "focusTopics": ["topic a","topic b"],');
|
|
1959
|
+
lines.push(' "rationale": "short why"');
|
|
1960
|
+
lines.push("}");
|
|
1961
|
+
return lines.join("\n");
|
|
1962
|
+
}
|
|
1963
|
+
function mergeMission(fallback, parsed) {
|
|
1964
|
+
if (!parsed) return fallback;
|
|
1965
|
+
const mode = parsed.mode === "strict_target_reply" || parsed.mode === "strict_target_interaction" || parsed.mode === "persona_balanced" ? parsed.mode : fallback.mode;
|
|
1966
|
+
const objective = typeof parsed.objective === "string" && parsed.objective.trim().length > 0 ? parsed.objective.trim() : fallback.objective;
|
|
1967
|
+
const rationale = typeof parsed.rationale === "string" && parsed.rationale.trim().length > 0 ? parsed.rationale.trim() : fallback.rationale;
|
|
1968
|
+
const focusTopics = Array.isArray(parsed.focusTopics) ? unique2(
|
|
1969
|
+
parsed.focusTopics.map((topic) => String(topic).trim()).filter(Boolean).slice(0, 10)
|
|
1970
|
+
) : fallback.focusTopics;
|
|
1971
|
+
const targetHandles = Array.isArray(parsed.targetHandles) ? unique2(
|
|
1972
|
+
parsed.targetHandles.map((handle) => normalizeHandle4(String(handle))).filter(Boolean)
|
|
1973
|
+
) : fallback.targetHandles;
|
|
1974
|
+
let allowedActions = sanitizeActions(parsed.allowedActions, fallback.allowedActions);
|
|
1975
|
+
const mustReplyOnly = mode === "strict_target_reply";
|
|
1976
|
+
if (mustReplyOnly) {
|
|
1977
|
+
allowedActions = ["reply"];
|
|
1978
|
+
}
|
|
1979
|
+
const hasStrictTargets = fallback.targetHandles.length > 0;
|
|
1980
|
+
if (hasStrictTargets) {
|
|
1981
|
+
return {
|
|
1982
|
+
...fallback,
|
|
1983
|
+
mode: mustReplyOnly ? "strict_target_reply" : mode,
|
|
1984
|
+
objective,
|
|
1985
|
+
rationale,
|
|
1986
|
+
focusTopics,
|
|
1987
|
+
allowedActions,
|
|
1988
|
+
targetHandles: fallback.targetHandles
|
|
1989
|
+
};
|
|
1990
|
+
}
|
|
1991
|
+
return {
|
|
1992
|
+
mode,
|
|
1993
|
+
objective,
|
|
1994
|
+
rationale,
|
|
1995
|
+
focusTopics,
|
|
1996
|
+
allowedActions,
|
|
1997
|
+
targetHandles
|
|
1998
|
+
};
|
|
1999
|
+
}
|
|
2000
|
+
async function createHeartbeatMission(research) {
|
|
2001
|
+
const identity = loadIdentity();
|
|
2002
|
+
const strategy = loadStrategy();
|
|
2003
|
+
const constraints = getPersonaConstraints(identity);
|
|
2004
|
+
const profile = compilePersonaActionProfile({ identity, strategy, constraints });
|
|
2005
|
+
const fallback = buildDeterministicMission(research, profile);
|
|
2006
|
+
if (fallback.mode !== "persona_balanced") {
|
|
2007
|
+
return fallback;
|
|
2008
|
+
}
|
|
2009
|
+
const system = [
|
|
2010
|
+
"You are a mission director for an autonomous X agent.",
|
|
2011
|
+
"Your output must be strict JSON only.",
|
|
2012
|
+
"Prioritize persona fidelity over engagement.",
|
|
2013
|
+
"Never violate explicit persona constraints."
|
|
2014
|
+
].join(" ");
|
|
2015
|
+
try {
|
|
2016
|
+
const prompt = buildMissionPrompt(research, fallback, profile);
|
|
2017
|
+
const response = await generateResponse(system, prompt);
|
|
2018
|
+
const parsed = parseJsonObject(response.content);
|
|
2019
|
+
return mergeMission(fallback, parsed);
|
|
2020
|
+
} catch {
|
|
2021
|
+
return fallback;
|
|
2022
|
+
}
|
|
2023
|
+
}
|
|
2024
|
+
|
|
1786
2025
|
// src/runtime/bandit.ts
|
|
1787
2026
|
import { existsSync as existsSync2, readFileSync as readFileSync2, writeFileSync as writeFileSync2 } from "fs";
|
|
1788
2027
|
var DEFAULT_EXPLORATION_BUDGET = 0.25;
|
|
@@ -2027,7 +2266,7 @@ function selfUserIdFromCredentials() {
|
|
|
2027
2266
|
return null;
|
|
2028
2267
|
}
|
|
2029
2268
|
}
|
|
2030
|
-
function
|
|
2269
|
+
function normalizeHandle5(handle) {
|
|
2031
2270
|
return (handle ?? "").replace(/^@/, "").trim().toLowerCase();
|
|
2032
2271
|
}
|
|
2033
2272
|
function roughWordCount(text) {
|
|
@@ -2097,6 +2336,64 @@ function shouldAttemptStyleRewrite(action, reason) {
|
|
|
2097
2336
|
const lower = reason.toLowerCase();
|
|
2098
2337
|
return lower.includes("lecture-like") || lower.includes("abstract philosopher cadence") || lower.includes("manifesto") || lower.includes("too long/explanatory") || lower.includes("grounded in the target tweet context") || lower.includes("hedged consensus phrasing") || lower.includes("repetitive anchor phrase/term") || lower.includes("repetitive opening phrase") || lower.includes("low-novelty vocabulary loop") || lower.includes("abstract wording without concrete anchor");
|
|
2099
2338
|
}
|
|
2339
|
+
function personaAdjustedOpportunityScore(opportunity, profile) {
|
|
2340
|
+
const actionType = opportunity.actionType;
|
|
2341
|
+
const source = opportunity.source;
|
|
2342
|
+
const actionBias = profile.actionBias[actionType] ?? 0;
|
|
2343
|
+
const sourceBias = profile.sourceBias[source] ?? 0;
|
|
2344
|
+
return opportunity.score + actionBias * 0.9 + sourceBias * 0.55;
|
|
2345
|
+
}
|
|
2346
|
+
function buildPersonaGeneratedPool(opportunities, maxSize, profile) {
|
|
2347
|
+
if (opportunities.length <= 1) return opportunities.slice(0, maxSize);
|
|
2348
|
+
const maxPool = Math.max(1, Math.min(maxSize, opportunities.length));
|
|
2349
|
+
const byAction = /* @__PURE__ */ new Map();
|
|
2350
|
+
for (const action of ["reply", "like", "retweet", "follow", "post"]) {
|
|
2351
|
+
byAction.set(action, []);
|
|
2352
|
+
}
|
|
2353
|
+
for (const opportunity of opportunities) {
|
|
2354
|
+
const action = opportunity.actionType;
|
|
2355
|
+
byAction.get(action)?.push(opportunity);
|
|
2356
|
+
}
|
|
2357
|
+
for (const [action, rows] of byAction.entries()) {
|
|
2358
|
+
rows.sort((a, b) => personaAdjustedOpportunityScore(b, profile) - personaAdjustedOpportunityScore(a, profile));
|
|
2359
|
+
byAction.set(action, rows);
|
|
2360
|
+
}
|
|
2361
|
+
const actionOrder = profile.prioritizedActions.filter((action) => (byAction.get(action)?.length ?? 0) > 0);
|
|
2362
|
+
const weightedActions = actionOrder.map((action) => ({
|
|
2363
|
+
action,
|
|
2364
|
+
weight: Math.max(0.2, profile.actionBias[action] + 1.25)
|
|
2365
|
+
})).filter((row) => row.weight > 0);
|
|
2366
|
+
const selected = /* @__PURE__ */ new Map();
|
|
2367
|
+
if (weightedActions.length > 0) {
|
|
2368
|
+
const totalWeight = weightedActions.reduce((sum, row) => sum + row.weight, 0);
|
|
2369
|
+
const quotas = /* @__PURE__ */ new Map();
|
|
2370
|
+
for (const row of weightedActions) {
|
|
2371
|
+
quotas.set(row.action, Math.max(0, Math.floor(row.weight / totalWeight * maxPool)));
|
|
2372
|
+
}
|
|
2373
|
+
for (const topAction of actionOrder.slice(0, 2)) {
|
|
2374
|
+
const rows = byAction.get(topAction) ?? [];
|
|
2375
|
+
if (rows.length === 0) continue;
|
|
2376
|
+
quotas.set(topAction, Math.max(1, quotas.get(topAction) ?? 0));
|
|
2377
|
+
}
|
|
2378
|
+
for (const row of weightedActions) {
|
|
2379
|
+
const rows = byAction.get(row.action) ?? [];
|
|
2380
|
+
const limit = quotas.get(row.action) ?? 0;
|
|
2381
|
+
for (const candidate of rows.slice(0, limit)) {
|
|
2382
|
+
if (selected.size >= maxPool) break;
|
|
2383
|
+
selected.set(candidate.id, candidate);
|
|
2384
|
+
}
|
|
2385
|
+
if (selected.size >= maxPool) break;
|
|
2386
|
+
}
|
|
2387
|
+
}
|
|
2388
|
+
const globalSorted = [...opportunities].sort(
|
|
2389
|
+
(a, b) => personaAdjustedOpportunityScore(b, profile) - personaAdjustedOpportunityScore(a, profile)
|
|
2390
|
+
);
|
|
2391
|
+
for (const candidate of globalSorted) {
|
|
2392
|
+
if (selected.size >= maxPool) break;
|
|
2393
|
+
selected.set(candidate.id, candidate);
|
|
2394
|
+
}
|
|
2395
|
+
return [...selected.values()].slice(0, maxPool);
|
|
2396
|
+
}
|
|
2100
2397
|
function cleanRewriteOutput(text) {
|
|
2101
2398
|
const cleaned = text.replace(/```[\s\S]*?```/g, "").replace(/^["'`]+|["'`]+$/g, "").trim();
|
|
2102
2399
|
const firstLine = cleaned.split("\n").map((line) => line.trim()).filter(Boolean)[0] ?? cleaned;
|
|
@@ -2148,12 +2445,19 @@ async function rewriteDraftForHumanVoice(input) {
|
|
|
2148
2445
|
}
|
|
2149
2446
|
async function runAutonomyCycle(maxActions, heartbeatCount = 0) {
|
|
2150
2447
|
const client = await getXClient();
|
|
2448
|
+
const identity = loadIdentity();
|
|
2449
|
+
const strategy = loadStrategy();
|
|
2151
2450
|
const constraints = getPersonaConstraints();
|
|
2451
|
+
const personaProfile = compilePersonaActionProfile({ identity, strategy, constraints });
|
|
2152
2452
|
const strictReplyOnly = constraints.replyOnlyMode || constraints.onlyReplyToHandles.length > 0;
|
|
2453
|
+
const interactionActions = /* @__PURE__ */ new Set(["reply", "like", "retweet", "follow"]);
|
|
2153
2454
|
const constraintLines = buildPersonaConstraintLines(constraints);
|
|
2154
2455
|
if (constraintLines.length > 0) {
|
|
2155
2456
|
logger.info(`Persona constraints active: ${constraintLines.join(" | ")}`);
|
|
2156
2457
|
}
|
|
2458
|
+
logger.info(
|
|
2459
|
+
`Persona action profile: actions=${personaProfile.prioritizedActions.slice(0, 4).join(" > ")}, sources=${Object.entries(personaProfile.sourceBias).sort((a, b) => b[1] - a[1]).map(([source]) => source).slice(0, 3).join(" > ")}`
|
|
2460
|
+
);
|
|
2157
2461
|
try {
|
|
2158
2462
|
const delayed = await collectDelayedOutcomes(client);
|
|
2159
2463
|
if (delayed.processed > 0) {
|
|
@@ -2164,7 +2468,7 @@ async function runAutonomyCycle(maxActions, heartbeatCount = 0) {
|
|
|
2164
2468
|
} catch (error) {
|
|
2165
2469
|
logger.warn(`Delayed outcome collection failed: ${error.message}`);
|
|
2166
2470
|
}
|
|
2167
|
-
const selfHandle =
|
|
2471
|
+
const selfHandle = identity.handle.replace(/^@/, "").toLowerCase();
|
|
2168
2472
|
const selfUserId = selfUserIdFromCredentials();
|
|
2169
2473
|
const isSelfTweet = (tweet) => tweet.authorHandle.replace(/^@/, "").toLowerCase() === selfHandle || selfUserId !== null && tweet.authorId === selfUserId;
|
|
2170
2474
|
const research = await runResearchPhase(client, heartbeatCount);
|
|
@@ -2193,15 +2497,39 @@ async function runAutonomyCycle(maxActions, heartbeatCount = 0) {
|
|
|
2193
2497
|
...filteredTopicSearchResults.flatMap((result) => result.tweets),
|
|
2194
2498
|
...filteredPeopleActivity.flatMap((person) => person.tweets)
|
|
2195
2499
|
];
|
|
2500
|
+
const mission = await createHeartbeatMission({
|
|
2501
|
+
...research,
|
|
2502
|
+
timeline: filteredTimeline,
|
|
2503
|
+
mentions: filteredMentions,
|
|
2504
|
+
topicSearchResults: filteredTopicSearchResults,
|
|
2505
|
+
peopleActivity: filteredPeopleActivity
|
|
2506
|
+
});
|
|
2507
|
+
logger.info(
|
|
2508
|
+
`Mission: mode=${mission.mode}, objective="${mission.objective}", allowed=${mission.allowedActions.join(",")}, targets=${mission.targetHandles.length > 0 ? mission.targetHandles.map((h) => `@${h}`).join(",") : "none"}`
|
|
2509
|
+
);
|
|
2196
2510
|
logger.info(
|
|
2197
2511
|
`Autonomy context: timeline=${filteredTimeline.length}, mentions=${filteredMentions.length}, topicTweets=${filteredTopicSearchResults.reduce((sum, r) => sum + r.tweets.length, 0)}, peopleTweets=${filteredPeopleActivity.reduce((sum, p) => sum + p.tweets.length, 0)}`
|
|
2198
2512
|
);
|
|
2199
2513
|
const systemPrompt = buildSystemPrompt();
|
|
2200
2514
|
const actions = [];
|
|
2201
2515
|
const results = [];
|
|
2202
|
-
const policyFeedback = [
|
|
2516
|
+
const policyFeedback = [
|
|
2517
|
+
`Heartbeat mission: ${mission.objective}`,
|
|
2518
|
+
`Mission mode: ${mission.mode}`
|
|
2519
|
+
];
|
|
2203
2520
|
const blockedTweetIds = new Set(recentReplyTargetIds);
|
|
2204
|
-
const
|
|
2521
|
+
const allowedActionSet = new Set(mission.allowedActions);
|
|
2522
|
+
const disallowedActions = new Set(
|
|
2523
|
+
["reply", "like", "retweet", "follow", "post"].filter((action) => !allowedActionSet.has(action))
|
|
2524
|
+
);
|
|
2525
|
+
if (mission.targetHandles.length > 0) {
|
|
2526
|
+
policyFeedback.push(`Mission targets: ${mission.targetHandles.map((handle) => `@${handle}`).join(", ")}`);
|
|
2527
|
+
}
|
|
2528
|
+
if (mission.focusTopics.length > 0) {
|
|
2529
|
+
policyFeedback.push(`Mission focus: ${mission.focusTopics.slice(0, 5).join(", ")}`);
|
|
2530
|
+
}
|
|
2531
|
+
policyFeedback.push(`Mission rationale: ${mission.rationale}`);
|
|
2532
|
+
const missionTargetSet = new Set(mission.targetHandles.map((handle) => normalizeHandle5(handle)).filter(Boolean));
|
|
2205
2533
|
let replyRejectionCount = 0;
|
|
2206
2534
|
const opportunities = buildActionOpportunities({
|
|
2207
2535
|
research: {
|
|
@@ -2215,27 +2543,28 @@ async function runAutonomyCycle(maxActions, heartbeatCount = 0) {
|
|
|
2215
2543
|
selfUserId,
|
|
2216
2544
|
maxCandidates: 30
|
|
2217
2545
|
});
|
|
2218
|
-
const
|
|
2546
|
+
const personaSeedPool = buildPersonaGeneratedPool(opportunities, 30, personaProfile);
|
|
2547
|
+
const banditPool = selectBanditOpportunityPool(personaSeedPool, 24);
|
|
2548
|
+
const planningPool = buildPersonaGeneratedPool(banditPool, 24, personaProfile);
|
|
2219
2549
|
const byType = planningPool.reduce((acc, opportunity) => {
|
|
2220
2550
|
acc[opportunity.actionType] = (acc[opportunity.actionType] ?? 0) + 1;
|
|
2221
2551
|
return acc;
|
|
2222
2552
|
}, {});
|
|
2223
2553
|
logger.info(`Opportunities selected: total=${planningPool.length}, byType=${JSON.stringify(byType)}`);
|
|
2224
|
-
const strategy = loadStrategy();
|
|
2225
2554
|
const activeIntents = listIntents();
|
|
2226
2555
|
const intentTargetHandles = new Set(
|
|
2227
|
-
activeIntents.flatMap((intent) => intent.targetHandles.map((handle) =>
|
|
2556
|
+
activeIntents.flatMap((intent) => intent.targetHandles.map((handle) => normalizeHandle5(handle)))
|
|
2228
2557
|
);
|
|
2229
2558
|
const priorityHandles = /* @__PURE__ */ new Set(
|
|
2230
2559
|
[
|
|
2231
|
-
...strategy.peopleToEngage.filter((person) => person.priority === "high").map((person) =>
|
|
2560
|
+
...strategy.peopleToEngage.filter((person) => person.priority === "high").map((person) => normalizeHandle5(person.handle)).filter(Boolean),
|
|
2232
2561
|
...intentTargetHandles
|
|
2233
2562
|
]
|
|
2234
2563
|
);
|
|
2235
2564
|
const authorByTweetId = /* @__PURE__ */ new Map();
|
|
2236
2565
|
for (const opportunity of planningPool) {
|
|
2237
2566
|
if (opportunity.tweetId && opportunity.authorHandle) {
|
|
2238
|
-
authorByTweetId.set(opportunity.tweetId,
|
|
2567
|
+
authorByTweetId.set(opportunity.tweetId, normalizeHandle5(opportunity.authorHandle));
|
|
2239
2568
|
}
|
|
2240
2569
|
}
|
|
2241
2570
|
getRecentInteractions(20);
|
|
@@ -2243,6 +2572,10 @@ async function runAutonomyCycle(maxActions, heartbeatCount = 0) {
|
|
|
2243
2572
|
return planningPool.filter((opportunity) => {
|
|
2244
2573
|
if (disallowedActions.has(opportunity.actionType)) return false;
|
|
2245
2574
|
if (opportunity.tweetId && blockedTweetIds.has(opportunity.tweetId)) return false;
|
|
2575
|
+
if (missionTargetSet.size > 0 && interactionActions.has(opportunity.actionType)) {
|
|
2576
|
+
const author = normalizeHandle5(opportunity.authorHandle);
|
|
2577
|
+
if (!author || !missionTargetSet.has(author)) return false;
|
|
2578
|
+
}
|
|
2246
2579
|
return true;
|
|
2247
2580
|
});
|
|
2248
2581
|
};
|
|
@@ -2274,18 +2607,18 @@ async function runAutonomyCycle(maxActions, heartbeatCount = 0) {
|
|
|
2274
2607
|
const authorByTweetId2 = /* @__PURE__ */ new Map();
|
|
2275
2608
|
for (const opportunity of candidates) {
|
|
2276
2609
|
if (opportunity.tweetId && opportunity.authorHandle) {
|
|
2277
|
-
authorByTweetId2.set(opportunity.tweetId,
|
|
2610
|
+
authorByTweetId2.set(opportunity.tweetId, normalizeHandle5(opportunity.authorHandle));
|
|
2278
2611
|
}
|
|
2279
2612
|
}
|
|
2280
2613
|
const touchesPriorityTarget = plannedActions.some((action) => {
|
|
2281
|
-
if (action.handle && priorityHandles.has(
|
|
2282
|
-
if (action.targetHandle && priorityHandles.has(
|
|
2614
|
+
if (action.handle && priorityHandles.has(normalizeHandle5(action.handle))) return true;
|
|
2615
|
+
if (action.targetHandle && priorityHandles.has(normalizeHandle5(action.targetHandle))) return true;
|
|
2283
2616
|
if (action.tweetId && priorityHandles.has(authorByTweetId2.get(action.tweetId) ?? "")) return true;
|
|
2284
2617
|
return false;
|
|
2285
2618
|
});
|
|
2286
2619
|
if (!touchesPriorityTarget) {
|
|
2287
2620
|
const priorityCandidate = candidates.find(
|
|
2288
|
-
(opportunity) => Boolean(opportunity.authorHandle) && priorityHandles.has(
|
|
2621
|
+
(opportunity) => Boolean(opportunity.authorHandle) && priorityHandles.has(normalizeHandle5(opportunity.authorHandle)) && (!strictReplyOnly ? !opportunity.requiresContent : opportunity.actionType === "reply")
|
|
2289
2622
|
);
|
|
2290
2623
|
if (priorityCandidate) {
|
|
2291
2624
|
plannedActions = [
|
|
@@ -2377,12 +2710,12 @@ async function runAutonomyCycle(maxActions, heartbeatCount = 0) {
|
|
|
2377
2710
|
actions.push(candidateAction);
|
|
2378
2711
|
results.push(result);
|
|
2379
2712
|
if (activeIntents.length > 0) {
|
|
2380
|
-
const touchedHandle =
|
|
2713
|
+
const touchedHandle = normalizeHandle5(
|
|
2381
2714
|
candidateAction.targetHandle ?? candidateAction.handle ?? (candidateAction.tweetId ? authorByTweetId.get(candidateAction.tweetId) : void 0)
|
|
2382
2715
|
);
|
|
2383
2716
|
const loweredContent = (candidateAction.content ?? "").toLowerCase();
|
|
2384
2717
|
for (const intent of activeIntents) {
|
|
2385
|
-
const handleMatch = touchedHandle.length > 0 && intent.targetHandles.some((handle) =>
|
|
2718
|
+
const handleMatch = touchedHandle.length > 0 && intent.targetHandles.some((handle) => normalizeHandle5(handle) === touchedHandle);
|
|
2386
2719
|
const topicMatch = loweredContent.length > 0 && intent.focusTopics.some((topic) => loweredContent.includes(topic.toLowerCase()));
|
|
2387
2720
|
if (!handleMatch && !topicMatch) continue;
|
|
2388
2721
|
recordIntentExecution(intent.id, {
|
|
@@ -2433,4 +2766,4 @@ async function runAutonomyCycle(maxActions, heartbeatCount = 0) {
|
|
|
2433
2766
|
export {
|
|
2434
2767
|
runAutonomyCycle
|
|
2435
2768
|
};
|
|
2436
|
-
//# sourceMappingURL=chunk-
|
|
2769
|
+
//# sourceMappingURL=chunk-TTM54LQR.js.map
|