spora 0.7.9 → 0.7.10
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-ZMFZRXDZ.js → autonomy-YBWBP6QJ.js} +2 -2
- package/dist/{chunk-TTDQZI5W.js → chunk-245JDXK4.js} +194 -18
- package/dist/chunk-245JDXK4.js.map +1 -0
- package/dist/chunk-NX7FJ4GH.js +91 -0
- package/dist/chunk-NX7FJ4GH.js.map +1 -0
- package/dist/cli.js +5 -5
- package/dist/{heartbeat-CUM7FIHS.js → heartbeat-BIGGV4LO.js} +3 -3
- package/dist/{heartbeat-narrative-B3RD3OPJ.js → heartbeat-narrative-UMLQ3WU7.js} +2 -2
- package/dist/{init-4SBU4H6F.js → init-S5ZKOU64.js} +3 -3
- package/dist/web-chat/chat.html +16 -8
- package/dist/{web-chat-YRQQB435.js → web-chat-PQ6FR6BJ.js} +13 -14
- package/dist/web-chat-PQ6FR6BJ.js.map +1 -0
- package/package.json +1 -1
- package/dist/chunk-OLYPPXKP.js +0 -69
- package/dist/chunk-OLYPPXKP.js.map +0 -1
- package/dist/chunk-TTDQZI5W.js.map +0 -1
- package/dist/web-chat-YRQQB435.js.map +0 -1
- /package/dist/{autonomy-ZMFZRXDZ.js.map → autonomy-YBWBP6QJ.js.map} +0 -0
- /package/dist/{heartbeat-CUM7FIHS.js.map → heartbeat-BIGGV4LO.js.map} +0 -0
- /package/dist/{heartbeat-narrative-B3RD3OPJ.js.map → heartbeat-narrative-UMLQ3WU7.js.map} +0 -0
- /package/dist/{init-4SBU4H6F.js.map → init-S5ZKOU64.js.map} +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
runAutonomyCycle
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-245JDXK4.js";
|
|
4
4
|
import "./chunk-TKGB5LIN.js";
|
|
5
5
|
import "./chunk-AIGSCHZK.js";
|
|
6
6
|
import "./chunk-73CWOI44.js";
|
|
@@ -17,4 +17,4 @@ import "./chunk-ZWKTKWS6.js";
|
|
|
17
17
|
export {
|
|
18
18
|
runAutonomyCycle
|
|
19
19
|
};
|
|
20
|
-
//# sourceMappingURL=autonomy-
|
|
20
|
+
//# sourceMappingURL=autonomy-YBWBP6QJ.js.map
|
|
@@ -967,6 +967,37 @@ function canonicalPlannerHandle(handle) {
|
|
|
967
967
|
function canonicalizePlannerQuery(rawQuery) {
|
|
968
968
|
return rawQuery.replace(/from:([a-zA-Z0-9_]{1,15})/gi, (_match, handle) => `from:${canonicalPlannerHandle(handle)}`);
|
|
969
969
|
}
|
|
970
|
+
var REPLY_TARGET_COOLDOWN_MS = 6 * 60 * 60 * 1e3;
|
|
971
|
+
function normalizeDraftText(text) {
|
|
972
|
+
return text.toLowerCase().replace(/https?:\/\/\S+/g, "").replace(/[@#][a-z0-9_]+/g, "").replace(/[^a-z0-9\s]/g, " ").replace(/\s+/g, " ").trim();
|
|
973
|
+
}
|
|
974
|
+
function tokenJaccard(a, b) {
|
|
975
|
+
const aTokens = new Set(normalizeDraftText(a).split(" ").filter(Boolean));
|
|
976
|
+
const bTokens = new Set(normalizeDraftText(b).split(" ").filter(Boolean));
|
|
977
|
+
if (aTokens.size === 0 || bTokens.size === 0) return 0;
|
|
978
|
+
let overlap = 0;
|
|
979
|
+
for (const token of aTokens) {
|
|
980
|
+
if (bTokens.has(token)) overlap += 1;
|
|
981
|
+
}
|
|
982
|
+
const union = aTokens.size + bTokens.size - overlap;
|
|
983
|
+
return union > 0 ? overlap / union : 0;
|
|
984
|
+
}
|
|
985
|
+
function nearDuplicateDraft(content, previous) {
|
|
986
|
+
const normalized = normalizeDraftText(content);
|
|
987
|
+
if (!normalized) return false;
|
|
988
|
+
return previous.some((sample) => {
|
|
989
|
+
const candidate = normalizeDraftText(sample);
|
|
990
|
+
if (!candidate) return false;
|
|
991
|
+
if (candidate === normalized) return true;
|
|
992
|
+
const sameOpening = normalized.split(" ").slice(0, 7).join(" ") === candidate.split(" ").slice(0, 7).join(" ");
|
|
993
|
+
if (sameOpening) return true;
|
|
994
|
+
return tokenJaccard(normalized, candidate) >= 0.86;
|
|
995
|
+
});
|
|
996
|
+
}
|
|
997
|
+
function shouldHardBlockPolicyReason(reason) {
|
|
998
|
+
const lower = reason.toLowerCase();
|
|
999
|
+
return lower.includes("already executed for tweet") || lower.includes("rejected self-interaction") || lower.includes("self-follow") || lower.includes("requires replying only") || lower.includes("reply target must be one of") || lower.includes("interaction target must be one of") || lower.includes("forbids standalone original posts") || lower.includes("reply-only mode");
|
|
1000
|
+
}
|
|
970
1001
|
function roughWordCount(text) {
|
|
971
1002
|
return text.trim().split(/\s+/).filter(Boolean).length;
|
|
972
1003
|
}
|
|
@@ -1270,6 +1301,21 @@ function buildToolLoopPrompt(input) {
|
|
|
1270
1301
|
lines.push(
|
|
1271
1302
|
`Current context counts: timeline=${input.state.timeline.length}, mentions=${input.state.mentions.length}, topicTweets=${input.state.topicSearchResults.reduce((sum, item) => sum + item.tweets.length, 0)}, peopleTweets=${input.state.peopleActivity.reduce((sum, item) => sum + item.tweets.length, 0)}`
|
|
1272
1303
|
);
|
|
1304
|
+
if (input.usedReplyTargets.length > 0) {
|
|
1305
|
+
lines.push(`Reply targets already used this heartbeat: ${input.usedReplyTargets.slice(-8).join(", ")}`);
|
|
1306
|
+
}
|
|
1307
|
+
if (input.recentReplyTargets.length > 0) {
|
|
1308
|
+
lines.push(`Recently replied targets (cooldown): ${input.recentReplyTargets.slice(0, 8).join(", ")}`);
|
|
1309
|
+
}
|
|
1310
|
+
if (input.blockedReplyTargets.length > 0) {
|
|
1311
|
+
lines.push(`Temporarily blocked reply targets this heartbeat: ${input.blockedReplyTargets.slice(0, 8).join(", ")}`);
|
|
1312
|
+
}
|
|
1313
|
+
if (input.recentWrittenSamples.length > 0) {
|
|
1314
|
+
lines.push("Recent writing to avoid repeating:");
|
|
1315
|
+
for (const sample of input.recentWrittenSamples.slice(0, 4)) {
|
|
1316
|
+
lines.push(`- ${sample.slice(0, 100)}`);
|
|
1317
|
+
}
|
|
1318
|
+
}
|
|
1273
1319
|
lines.push("");
|
|
1274
1320
|
if (input.toolHistory.length > 0) {
|
|
1275
1321
|
lines.push("Recent tool steps:");
|
|
@@ -1316,6 +1362,7 @@ function buildToolLoopPrompt(input) {
|
|
|
1316
1362
|
lines.push("- if timeline/mentions already have viable tweets, prefer acting over more research");
|
|
1317
1363
|
lines.push("- use search/profile checks only when you have a clear reason");
|
|
1318
1364
|
lines.push("- avoid repeating the same query/target unless context changed");
|
|
1365
|
+
lines.push("- one reply per target tweet per heartbeat, always choose a new tweet next");
|
|
1319
1366
|
lines.push("");
|
|
1320
1367
|
lines.push("Writing constraints:");
|
|
1321
1368
|
lines.push("- sound human and specific, no manifesto language");
|
|
@@ -1374,6 +1421,10 @@ async function runAutonomyCycle(maxActions, heartbeatCount = 0) {
|
|
|
1374
1421
|
const client = await getXClient();
|
|
1375
1422
|
const identity = loadIdentity();
|
|
1376
1423
|
const constraints = getPersonaConstraints();
|
|
1424
|
+
const strictReplyHandles = new Set(constraints.onlyReplyToHandles.map((handle) => normalizeHandle2(handle)));
|
|
1425
|
+
const strictInteractHandles = new Set(
|
|
1426
|
+
[...constraints.onlyReplyToHandles, ...constraints.onlyInteractWithHandles].map((handle) => normalizeHandle2(handle))
|
|
1427
|
+
);
|
|
1377
1428
|
const constraintLines = buildPersonaConstraintLines(constraints);
|
|
1378
1429
|
if (constraintLines.length > 0) {
|
|
1379
1430
|
logger.info(`Persona constraints active: ${constraintLines.join(" | ")}`);
|
|
@@ -1432,9 +1483,50 @@ async function runAutonomyCycle(maxActions, heartbeatCount = 0) {
|
|
|
1432
1483
|
const activeIntents = listIntents();
|
|
1433
1484
|
let staleSteps = 0;
|
|
1434
1485
|
let attemptedActions = 0;
|
|
1435
|
-
const
|
|
1486
|
+
const maxConfiguredActions = Math.max(1, maxActions);
|
|
1487
|
+
let actionBudget = maxConfiguredActions;
|
|
1488
|
+
if (constraints.replyOnlyMode || strictReplyHandles.size > 0) {
|
|
1489
|
+
actionBudget = 1;
|
|
1490
|
+
} else {
|
|
1491
|
+
const upper = Math.min(maxConfiguredActions, 3);
|
|
1492
|
+
actionBudget = Math.max(1, Math.floor(Math.random() * upper) + 1);
|
|
1493
|
+
}
|
|
1494
|
+
const maxToolSteps = Math.max(8, actionBudget * 5);
|
|
1495
|
+
const recentInteractions = getRecentInteractions(220);
|
|
1496
|
+
const now = Date.now();
|
|
1497
|
+
const recentReplyTargets = new Set(
|
|
1498
|
+
recentInteractions.filter((entry) => entry.type === "reply" && typeof entry.inReplyTo === "string").filter((entry) => {
|
|
1499
|
+
const ts = Date.parse(entry.timestamp);
|
|
1500
|
+
return Number.isNaN(ts) || now - ts <= REPLY_TARGET_COOLDOWN_MS;
|
|
1501
|
+
}).map((entry) => entry.inReplyTo)
|
|
1502
|
+
);
|
|
1503
|
+
const recentWrittenSamples = recentInteractions.filter((entry) => (entry.type === "post" || entry.type === "reply") && typeof entry.content === "string").map((entry) => entry.content.trim()).filter(Boolean).slice(0, 16);
|
|
1504
|
+
const usedReplyTargets = /* @__PURE__ */ new Set();
|
|
1505
|
+
const blockedReplyTargets = /* @__PURE__ */ new Set();
|
|
1506
|
+
const writtenThisHeartbeat = [];
|
|
1436
1507
|
getRecentInteractions(20);
|
|
1437
|
-
|
|
1508
|
+
const markNoProgress = (note) => {
|
|
1509
|
+
if (note) policyFeedback.push(note);
|
|
1510
|
+
staleSteps += 1;
|
|
1511
|
+
if (staleSteps >= 5) {
|
|
1512
|
+
logger.info("Tool loop stopped after repeated blocked/no-progress steps.");
|
|
1513
|
+
return true;
|
|
1514
|
+
}
|
|
1515
|
+
return false;
|
|
1516
|
+
};
|
|
1517
|
+
const hasEligibleStrictReplyTarget = () => {
|
|
1518
|
+
const observed = collectObserved(state);
|
|
1519
|
+
return observed.tweets.some((tweet) => {
|
|
1520
|
+
const handle = normalizeHandle2(tweet.authorHandle);
|
|
1521
|
+
return strictReplyHandles.has(handle) && !usedReplyTargets.has(tweet.id) && !recentReplyTargets.has(tweet.id) && !blockedReplyTargets.has(tweet.id);
|
|
1522
|
+
});
|
|
1523
|
+
};
|
|
1524
|
+
for (let step = 0; step < maxToolSteps && actions.length < actionBudget; step += 1) {
|
|
1525
|
+
if (strictReplyHandles.size > 0 && !hasEligibleStrictReplyTarget()) {
|
|
1526
|
+
policyFeedback.push("No eligible fresh target tweets remain for strict reply mode this heartbeat.");
|
|
1527
|
+
logger.info("Planner loop ended: no eligible strict-reply targets left.");
|
|
1528
|
+
break;
|
|
1529
|
+
}
|
|
1438
1530
|
const candidates = buildPlannerCandidates(state);
|
|
1439
1531
|
const recentMemory = getRecentInteractions(24).slice(0, 12).map((entry) => {
|
|
1440
1532
|
const text = (entry.content ?? "").replace(/\s+/g, " ").trim().slice(0, 120);
|
|
@@ -1457,6 +1549,10 @@ async function runAutonomyCycle(maxActions, heartbeatCount = 0) {
|
|
|
1457
1549
|
policyFeedback,
|
|
1458
1550
|
toolHistory,
|
|
1459
1551
|
recentMemory,
|
|
1552
|
+
usedReplyTargets: [...usedReplyTargets],
|
|
1553
|
+
recentReplyTargets: [...recentReplyTargets],
|
|
1554
|
+
blockedReplyTargets: [...blockedReplyTargets],
|
|
1555
|
+
recentWrittenSamples: [...writtenThisHeartbeat, ...recentWrittenSamples].slice(0, 8),
|
|
1460
1556
|
heartbeatCount
|
|
1461
1557
|
});
|
|
1462
1558
|
let decision = fallbackPlannerDecision(step, candidates.length);
|
|
@@ -1488,7 +1584,7 @@ async function runAutonomyCycle(maxActions, heartbeatCount = 0) {
|
|
|
1488
1584
|
} catch (error) {
|
|
1489
1585
|
policyFeedback.push(`observe_timeline failed: ${error.message}`);
|
|
1490
1586
|
}
|
|
1491
|
-
if (!stepProgress
|
|
1587
|
+
if (!stepProgress && markNoProgress("observe_timeline found no new tweets.")) break;
|
|
1492
1588
|
continue;
|
|
1493
1589
|
}
|
|
1494
1590
|
if (decision.tool === "observe_mentions") {
|
|
@@ -1506,13 +1602,13 @@ async function runAutonomyCycle(maxActions, heartbeatCount = 0) {
|
|
|
1506
1602
|
} catch (error) {
|
|
1507
1603
|
policyFeedback.push(`observe_mentions failed: ${error.message}`);
|
|
1508
1604
|
}
|
|
1509
|
-
if (!stepProgress
|
|
1605
|
+
if (!stepProgress && markNoProgress("observe_mentions found no new tweets.")) break;
|
|
1510
1606
|
continue;
|
|
1511
1607
|
}
|
|
1512
1608
|
if (decision.tool === "search_tweets") {
|
|
1513
1609
|
const rawQuery = argString(decision.args, "query");
|
|
1514
1610
|
if (!rawQuery) {
|
|
1515
|
-
|
|
1611
|
+
if (markNoProgress("search_tweets rejected: missing query.")) break;
|
|
1516
1612
|
continue;
|
|
1517
1613
|
}
|
|
1518
1614
|
const query = canonicalizePlannerQuery(rawQuery);
|
|
@@ -1534,14 +1630,14 @@ async function runAutonomyCycle(maxActions, heartbeatCount = 0) {
|
|
|
1534
1630
|
} catch (error) {
|
|
1535
1631
|
policyFeedback.push(`search_tweets failed for "${query}": ${error.message}`);
|
|
1536
1632
|
}
|
|
1537
|
-
if (!stepProgress
|
|
1633
|
+
if (!stepProgress && markNoProgress(`search_tweets "${query}" found no new tweets.`)) break;
|
|
1538
1634
|
continue;
|
|
1539
1635
|
}
|
|
1540
1636
|
if (decision.tool === "check_profile") {
|
|
1541
1637
|
const handleInput = argString(decision.args, "handle");
|
|
1542
1638
|
const handle = handleInput ? canonicalPlannerHandle(handleInput) : "";
|
|
1543
1639
|
if (!handle) {
|
|
1544
|
-
|
|
1640
|
+
if (markNoProgress("check_profile rejected: missing handle.")) break;
|
|
1545
1641
|
continue;
|
|
1546
1642
|
}
|
|
1547
1643
|
const count = argCount(decision.args, 6, 3, 12);
|
|
@@ -1565,14 +1661,13 @@ async function runAutonomyCycle(maxActions, heartbeatCount = 0) {
|
|
|
1565
1661
|
} catch (error) {
|
|
1566
1662
|
policyFeedback.push(`check_profile failed for @${handle}: ${error.message}`);
|
|
1567
1663
|
}
|
|
1568
|
-
if (!stepProgress
|
|
1664
|
+
if (!stepProgress && markNoProgress(`check_profile @${handle} found no new tweets.`)) break;
|
|
1569
1665
|
continue;
|
|
1570
1666
|
}
|
|
1571
1667
|
const observed = collectObserved(state);
|
|
1572
1668
|
let candidateAction = decisionToAgentAction(decision);
|
|
1573
1669
|
if (!candidateAction) {
|
|
1574
|
-
|
|
1575
|
-
staleSteps += 1;
|
|
1670
|
+
if (markNoProgress(`Tool decision ${decision.tool} rejected: invalid arguments.`)) break;
|
|
1576
1671
|
continue;
|
|
1577
1672
|
}
|
|
1578
1673
|
if (candidateAction.tweetId && observed.byId.has(candidateAction.tweetId)) {
|
|
@@ -1581,6 +1676,9 @@ async function runAutonomyCycle(maxActions, heartbeatCount = 0) {
|
|
|
1581
1676
|
candidateAction.targetHandle = `@${author}`;
|
|
1582
1677
|
}
|
|
1583
1678
|
}
|
|
1679
|
+
const actionTargetHandle = normalizeHandle2(
|
|
1680
|
+
candidateAction.targetHandle ?? candidateAction.handle ?? (candidateAction.tweetId ? observed.byId.get(candidateAction.tweetId)?.authorHandle : void 0)
|
|
1681
|
+
);
|
|
1584
1682
|
if (candidateAction.action === "skip") {
|
|
1585
1683
|
const reason = candidateAction.reason ?? candidateAction.reasoning ?? "planner skip";
|
|
1586
1684
|
policyFeedback.push(`Planner chose skip: ${reason}`);
|
|
@@ -1589,10 +1687,76 @@ async function runAutonomyCycle(maxActions, heartbeatCount = 0) {
|
|
|
1589
1687
|
tool: decision.tool,
|
|
1590
1688
|
summary: reason
|
|
1591
1689
|
});
|
|
1592
|
-
|
|
1593
|
-
|
|
1690
|
+
if (markNoProgress()) break;
|
|
1691
|
+
continue;
|
|
1692
|
+
}
|
|
1693
|
+
if (constraints.noOriginalPosts && (candidateAction.action === "post" || candidateAction.action === "schedule")) {
|
|
1694
|
+
const reason = "Original posts are disabled by persona constraints.";
|
|
1695
|
+
policyFeedback.push(reason);
|
|
1696
|
+
logger.info(`Policy blocked action ${candidateAction.action}: ${reason}`);
|
|
1697
|
+
if (markNoProgress()) break;
|
|
1594
1698
|
continue;
|
|
1595
1699
|
}
|
|
1700
|
+
if (strictReplyHandles.size > 0) {
|
|
1701
|
+
if (candidateAction.action !== "reply") {
|
|
1702
|
+
const reason = `Only reply actions are allowed for this persona target: @${[...strictReplyHandles].join(", @")}.`;
|
|
1703
|
+
policyFeedback.push(reason);
|
|
1704
|
+
logger.info(`Policy blocked action ${candidateAction.action}: ${reason}`);
|
|
1705
|
+
if (markNoProgress()) break;
|
|
1706
|
+
continue;
|
|
1707
|
+
}
|
|
1708
|
+
if (!actionTargetHandle || !strictReplyHandles.has(actionTargetHandle)) {
|
|
1709
|
+
const reason = `Reply target must be one of @${[...strictReplyHandles].join(", @")}.`;
|
|
1710
|
+
policyFeedback.push(reason);
|
|
1711
|
+
logger.info(`Policy blocked action ${candidateAction.action}: ${reason}`);
|
|
1712
|
+
if (markNoProgress()) break;
|
|
1713
|
+
continue;
|
|
1714
|
+
}
|
|
1715
|
+
}
|
|
1716
|
+
if (strictInteractHandles.size > 0 && ["reply", "like", "retweet", "follow"].includes(candidateAction.action)) {
|
|
1717
|
+
if (!actionTargetHandle || !strictInteractHandles.has(actionTargetHandle)) {
|
|
1718
|
+
const reason = `Interaction target must be one of @${[...strictInteractHandles].join(", @")}.`;
|
|
1719
|
+
policyFeedback.push(reason);
|
|
1720
|
+
logger.info(`Policy blocked action ${candidateAction.action}: ${reason}`);
|
|
1721
|
+
if (markNoProgress()) break;
|
|
1722
|
+
continue;
|
|
1723
|
+
}
|
|
1724
|
+
}
|
|
1725
|
+
if (candidateAction.action === "reply" && candidateAction.tweetId) {
|
|
1726
|
+
if (blockedReplyTargets.has(candidateAction.tweetId)) {
|
|
1727
|
+
const reason = `Reply target ${candidateAction.tweetId} is temporarily blocked this heartbeat. Pick a different tweet.`;
|
|
1728
|
+
policyFeedback.push(reason);
|
|
1729
|
+
logger.info(`Planner loop guard: ${reason}`);
|
|
1730
|
+
if (markNoProgress()) break;
|
|
1731
|
+
continue;
|
|
1732
|
+
}
|
|
1733
|
+
if (usedReplyTargets.has(candidateAction.tweetId)) {
|
|
1734
|
+
const reason = `Reply target ${candidateAction.tweetId} already used this heartbeat. Pick a different tweet.`;
|
|
1735
|
+
policyFeedback.push(reason);
|
|
1736
|
+
logger.info(`Planner loop guard: ${reason}`);
|
|
1737
|
+
blockedReplyTargets.add(candidateAction.tweetId);
|
|
1738
|
+
if (markNoProgress()) break;
|
|
1739
|
+
continue;
|
|
1740
|
+
}
|
|
1741
|
+
if (recentReplyTargets.has(candidateAction.tweetId)) {
|
|
1742
|
+
const reason = `Reply target ${candidateAction.tweetId} is in cooldown from recent history. Pick a fresher target.`;
|
|
1743
|
+
policyFeedback.push(reason);
|
|
1744
|
+
logger.info(`Planner loop guard: ${reason}`);
|
|
1745
|
+
blockedReplyTargets.add(candidateAction.tweetId);
|
|
1746
|
+
if (markNoProgress()) break;
|
|
1747
|
+
continue;
|
|
1748
|
+
}
|
|
1749
|
+
}
|
|
1750
|
+
if ((candidateAction.action === "reply" || candidateAction.action === "post") && candidateAction.content) {
|
|
1751
|
+
const seenDrafts = [...writtenThisHeartbeat, ...recentWrittenSamples].slice(0, 18);
|
|
1752
|
+
if (nearDuplicateDraft(candidateAction.content, seenDrafts)) {
|
|
1753
|
+
const reason = "Draft is too similar to recent writing. Try a new angle before posting.";
|
|
1754
|
+
policyFeedback.push(reason);
|
|
1755
|
+
logger.info(`Planner loop guard: ${reason}`);
|
|
1756
|
+
if (markNoProgress()) break;
|
|
1757
|
+
continue;
|
|
1758
|
+
}
|
|
1759
|
+
}
|
|
1596
1760
|
attemptedActions += 1;
|
|
1597
1761
|
let policy = evaluateActionPolicy({
|
|
1598
1762
|
action: candidateAction,
|
|
@@ -1634,9 +1798,24 @@ async function runAutonomyCycle(maxActions, heartbeatCount = 0) {
|
|
|
1634
1798
|
}
|
|
1635
1799
|
if (!policy.allowed) {
|
|
1636
1800
|
const reason = policy.reason ?? "Policy rejected action";
|
|
1801
|
+
if (shouldHardBlockPolicyReason(reason)) {
|
|
1802
|
+
policyFeedback.push(`Policy blocked action: ${reason}`);
|
|
1803
|
+
logger.info(`Policy blocked ${candidateAction.action}: ${reason}`);
|
|
1804
|
+
if (markNoProgress()) break;
|
|
1805
|
+
continue;
|
|
1806
|
+
}
|
|
1637
1807
|
policyFeedback.push(`Policy advisory (not blocking): ${reason}`);
|
|
1638
1808
|
logger.info(`Policy advisory for ${candidateAction.action}: ${reason}`);
|
|
1639
1809
|
}
|
|
1810
|
+
if (candidateAction.action === "reply" && candidateAction.tweetId) {
|
|
1811
|
+
usedReplyTargets.add(candidateAction.tweetId);
|
|
1812
|
+
}
|
|
1813
|
+
if ((candidateAction.action === "reply" || candidateAction.action === "post") && candidateAction.content) {
|
|
1814
|
+
writtenThisHeartbeat.unshift(candidateAction.content.trim());
|
|
1815
|
+
if (writtenThisHeartbeat.length > 16) {
|
|
1816
|
+
writtenThisHeartbeat.length = 16;
|
|
1817
|
+
}
|
|
1818
|
+
}
|
|
1640
1819
|
const result = await executeAction(candidateAction);
|
|
1641
1820
|
actions.push(candidateAction);
|
|
1642
1821
|
results.push(result);
|
|
@@ -1667,6 +1846,7 @@ async function runAutonomyCycle(maxActions, heartbeatCount = 0) {
|
|
|
1667
1846
|
if (candidateAction.action === "reply" && /duplicate content/i.test(err)) {
|
|
1668
1847
|
const reason = "Reply failed with duplicate-content error. Planner should choose a different wording/target.";
|
|
1669
1848
|
policyFeedback.push(reason);
|
|
1849
|
+
if (candidateAction.tweetId) blockedReplyTargets.add(candidateAction.tweetId);
|
|
1670
1850
|
logger.info(`Policy adjustment: ${reason}`);
|
|
1671
1851
|
}
|
|
1672
1852
|
if (candidateAction.action === "post" && /duplicate content/i.test(err)) {
|
|
@@ -1675,11 +1855,7 @@ async function runAutonomyCycle(maxActions, heartbeatCount = 0) {
|
|
|
1675
1855
|
logger.info(`Policy adjustment: ${reason}`);
|
|
1676
1856
|
}
|
|
1677
1857
|
}
|
|
1678
|
-
if (!stepProgress) {
|
|
1679
|
-
staleSteps += 1;
|
|
1680
|
-
}
|
|
1681
|
-
if (staleSteps >= 5) {
|
|
1682
|
-
logger.info("Tool loop stopped after repeated no-progress steps.");
|
|
1858
|
+
if (!stepProgress && markNoProgress()) {
|
|
1683
1859
|
break;
|
|
1684
1860
|
}
|
|
1685
1861
|
}
|
|
@@ -1696,4 +1872,4 @@ async function runAutonomyCycle(maxActions, heartbeatCount = 0) {
|
|
|
1696
1872
|
export {
|
|
1697
1873
|
runAutonomyCycle
|
|
1698
1874
|
};
|
|
1699
|
-
//# sourceMappingURL=chunk-
|
|
1875
|
+
//# sourceMappingURL=chunk-245JDXK4.js.map
|