@tloncorp/openclaw 0.4.1 → 0.4.3
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/index.js +16 -0
- package/dist/index.js.map +1 -1
- package/dist/src/config-schema.js +19 -0
- package/dist/src/config-schema.js.map +1 -1
- package/dist/src/monitor/command-bridge.js.map +1 -1
- package/dist/src/monitor/history.js +79 -2
- package/dist/src/monitor/history.js.map +1 -1
- package/dist/src/monitor/index.js +194 -26
- package/dist/src/monitor/index.js.map +1 -1
- package/dist/src/monitor/utils.js +53 -3
- package/dist/src/monitor/utils.js.map +1 -1
- package/dist/src/owner-listen-command.js +74 -0
- package/dist/src/owner-listen-command.js.map +1 -0
- package/dist/src/settings.js +12 -0
- package/dist/src/settings.js.map +1 -1
- package/dist/src/targets.js +17 -0
- package/dist/src/targets.js.map +1 -1
- package/dist/src/types.js +11 -0
- package/dist/src/types.js.map +1 -1
- package/dist/src/version.generated.js +1 -1
- package/dist/src/version.generated.js.map +1 -1
- package/openclaw.plugin.json +275 -2
- package/package.json +13 -32
- package/dist/src/heartbeat-telemetry.js +0 -155
- package/dist/src/heartbeat-telemetry.js.map +0 -1
- package/dist/src/nudge-candidate.js +0 -109
- package/dist/src/nudge-candidate.js.map +0 -1
- package/dist/src/onboarding.js +0 -178
- package/dist/src/onboarding.js.map +0 -1
|
@@ -3,11 +3,12 @@ import { configureGatewayStatus, gatewayStart } from "@tloncorp/api";
|
|
|
3
3
|
import { format } from "node:util";
|
|
4
4
|
import { getEffectiveOwnerShip, setEffectiveOwnerShip } from "../effective-owner.js";
|
|
5
5
|
import { getGatewayStatusManager, computeLeaseUntil, ACTIVE_WINDOW_SECS, OFFLINE_REPLY_COOLDOWN_SECS, } from "../gateway-status.js";
|
|
6
|
+
import { handleOwnerListenCommand } from "../owner-listen-command.js";
|
|
6
7
|
import { registerPersistCallback, syncPendingNudgeFromStore, getPendingNudge, clearPendingNudge, setPendingNudge, isNudgeEligible, } from "../pending-nudge.js";
|
|
7
8
|
import { getTlonRuntime } from "../runtime.js";
|
|
8
9
|
import { setSessionRole } from "../session-roles.js";
|
|
9
10
|
import { createSettingsManager } from "../settings.js";
|
|
10
|
-
import { normalizeShip, parseChannelNest } from "../targets.js";
|
|
11
|
+
import { canonicalizeNest, normalizeShip, parseChannelNest } from "../targets.js";
|
|
11
12
|
import { createTlonTelemetry } from "../telemetry.js";
|
|
12
13
|
import { resolveTlonAccount } from "../types.js";
|
|
13
14
|
import { configureTlonApiWithPoke } from "../urbit/api-client.js";
|
|
@@ -20,7 +21,7 @@ import { createPendingApproval, formatApprovalRequest, formatApprovalConfirmatio
|
|
|
20
21
|
import { setBridge, removeBridge } from "./command-bridge.js";
|
|
21
22
|
import { createComputingPresenceTracker } from "./computing-presence.js";
|
|
22
23
|
import { fetchAllChannels, fetchInitData } from "./discovery.js";
|
|
23
|
-
import { cacheMessage, lookupCachedMessage, getChannelHistory, fetchChannelHistory,
|
|
24
|
+
import { cacheMessage, buildThreadContextMessage, lookupCachedMessage, getChannelHistory, fetchChannelHistory, fetchThreadContextHistory, } from "./history.js";
|
|
24
25
|
import { downloadMessageImages, parseBlobData, formatBlobAnnotations, downloadBlobAttachments, } from "./media.js";
|
|
25
26
|
import { createNudgeRunner, shouldStartNudgeRunner } from "./nudge-runner.js";
|
|
26
27
|
import { clearShadowsForAccount, getLastNudgeStageShadow, getLastOwnerActivity, ownerActivityFromSettings, setLastNudgeStageShadow, setLastOwnerActivity, } from "./nudge-state.js";
|
|
@@ -28,7 +29,7 @@ import { createOwnerReplyPersistenceQueue } from "./owner-reply-persistence.js";
|
|
|
28
29
|
import { createPendingNudgePersistenceQueue } from "./pending-nudge-persistence.js";
|
|
29
30
|
import { createProcessedMessageTracker } from "./processed-messages.js";
|
|
30
31
|
import { resolveSettingsMirrorSync } from "./settings-sync.js";
|
|
31
|
-
import { extractMessageText, extractCites, formatModelName, isBotMentioned, stripBotMention, isDmAllowed, isSummarizationRequest, sanitizeMessageText, } from "./utils.js";
|
|
32
|
+
import { extractMessageText, extractCites, formatModelName, isBotMentioned, isOwnerListenSlashCommand, stripBotMention, isDmAllowed, isSummarizationRequest, sanitizeMessageText, shouldEngageInGroup, } from "./utils.js";
|
|
32
33
|
/** Refresh stale settings subscription state periodically as a fallback for silently-dead SSE subscriptions. */
|
|
33
34
|
const SETTINGS_REFRESH_INTERVAL_MS = 5 * 60 * 1000;
|
|
34
35
|
/**
|
|
@@ -161,6 +162,19 @@ export async function monitorTlonProvider(opts = {}) {
|
|
|
161
162
|
? normalizeShip(account.ownerShip)
|
|
162
163
|
: null;
|
|
163
164
|
setEffectiveOwnerShip(account.accountId, effectiveOwnerShip);
|
|
165
|
+
let effectiveOwnerListenEnabled = account.ownerListenEnabled ?? true;
|
|
166
|
+
// Canonicalize on every read so an entry stored from a slightly-off user
|
|
167
|
+
// input (e.g. missing "~" or wrong case) still matches incoming nest events.
|
|
168
|
+
const canonicalizeNestList = (list) => {
|
|
169
|
+
const out = new Set();
|
|
170
|
+
for (const raw of list) {
|
|
171
|
+
const canonical = canonicalizeNest(raw);
|
|
172
|
+
if (canonical)
|
|
173
|
+
out.add(canonical);
|
|
174
|
+
}
|
|
175
|
+
return [...out];
|
|
176
|
+
};
|
|
177
|
+
let effectiveOwnerListenDisabled = new Set(canonicalizeNestList(account.ownerListenDisabledChannels ?? []));
|
|
164
178
|
let pendingApprovals = [];
|
|
165
179
|
let currentSettings = {};
|
|
166
180
|
// Tracks whether pendingNudge has been successfully rehydrated from the settings
|
|
@@ -392,6 +406,14 @@ export async function monitorTlonProvider(opts = {}) {
|
|
|
392
406
|
setEffectiveOwnerShip(account.accountId, effectiveOwnerShip);
|
|
393
407
|
runtime.log?.(`[tlon] Using ownerShip from settings store: ${effectiveOwnerShip}`);
|
|
394
408
|
}
|
|
409
|
+
if (currentSettings.ownerListenEnabled !== undefined) {
|
|
410
|
+
effectiveOwnerListenEnabled = currentSettings.ownerListenEnabled;
|
|
411
|
+
runtime.log?.(`[tlon] Using ownerListenEnabled from settings store: ${effectiveOwnerListenEnabled}`);
|
|
412
|
+
}
|
|
413
|
+
if (currentSettings.ownerListenDisabledChannels !== undefined) {
|
|
414
|
+
effectiveOwnerListenDisabled = new Set(canonicalizeNestList(currentSettings.ownerListenDisabledChannels));
|
|
415
|
+
runtime.log?.(`[tlon] Loaded ${effectiveOwnerListenDisabled.size} owner-listen-disabled channel(s) from settings`);
|
|
416
|
+
}
|
|
395
417
|
// Rehydrate pending nudge from settings store only if the scry returned real data.
|
|
396
418
|
// On fallback (scry failure), leave pendingNudgeRehydrated false so the refresh
|
|
397
419
|
// recovery path can still pick up a persisted pendingNudge later.
|
|
@@ -478,7 +500,9 @@ export async function monitorTlonProvider(opts = {}) {
|
|
|
478
500
|
gsManager.waitForGatewayStart().then(() => "started"),
|
|
479
501
|
...(signal
|
|
480
502
|
? [
|
|
481
|
-
new Promise((r) => signal.addEventListener("abort", () => r("aborted"), {
|
|
503
|
+
new Promise((r) => signal.addEventListener("abort", () => r("aborted"), {
|
|
504
|
+
once: true,
|
|
505
|
+
})),
|
|
482
506
|
]
|
|
483
507
|
: []),
|
|
484
508
|
]);
|
|
@@ -661,7 +685,10 @@ export async function monitorTlonProvider(opts = {}) {
|
|
|
661
685
|
async function addToChannelAllowlist(ship, channelNest) {
|
|
662
686
|
const normalizedShip = normalizeShip(ship);
|
|
663
687
|
const channelRules = currentSettings.channelRules ?? {};
|
|
664
|
-
const rule = channelRules[channelNest] ?? {
|
|
688
|
+
const rule = channelRules[channelNest] ?? {
|
|
689
|
+
mode: "restricted",
|
|
690
|
+
allowedShips: [],
|
|
691
|
+
};
|
|
665
692
|
const allowedShips = [...(rule.allowedShips ?? [])]; // Clone to avoid mutation
|
|
666
693
|
if (!allowedShips.includes(normalizedShip)) {
|
|
667
694
|
allowedShips.push(normalizedShip);
|
|
@@ -990,6 +1017,88 @@ export async function monitorTlonProvider(opts = {}) {
|
|
|
990
1017
|
const success = await unblockShip(ship);
|
|
991
1018
|
return success ? `Unblocked ${ship}.` : `Failed to unblock ${ship}.`;
|
|
992
1019
|
},
|
|
1020
|
+
// ── Owner-listen controls ────────────────────────────────────────────
|
|
1021
|
+
isOwnedChannel(nest) {
|
|
1022
|
+
// Canonicalize first so case variants in user input (e.g.
|
|
1023
|
+
// `chat/~ZOD/general`) match the lowercase owner/bot ship strings.
|
|
1024
|
+
const canonical = canonicalizeNest(nest);
|
|
1025
|
+
if (!canonical) {
|
|
1026
|
+
return false;
|
|
1027
|
+
}
|
|
1028
|
+
const parsed = parseChannelNest(canonical);
|
|
1029
|
+
if (!parsed) {
|
|
1030
|
+
return false;
|
|
1031
|
+
}
|
|
1032
|
+
return parsed.hostShip === effectiveOwnerShip || parsed.hostShip === botShipName;
|
|
1033
|
+
},
|
|
1034
|
+
getOwnerListenGlobal() {
|
|
1035
|
+
return effectiveOwnerListenEnabled;
|
|
1036
|
+
},
|
|
1037
|
+
async setOwnerListenGlobal(enabled) {
|
|
1038
|
+
effectiveOwnerListenEnabled = enabled;
|
|
1039
|
+
try {
|
|
1040
|
+
await api.poke({
|
|
1041
|
+
app: "settings",
|
|
1042
|
+
mark: "settings-event",
|
|
1043
|
+
json: {
|
|
1044
|
+
"put-entry": {
|
|
1045
|
+
desk: "moltbot",
|
|
1046
|
+
"bucket-key": "tlon",
|
|
1047
|
+
"entry-key": "ownerListenEnabled",
|
|
1048
|
+
value: enabled,
|
|
1049
|
+
},
|
|
1050
|
+
},
|
|
1051
|
+
});
|
|
1052
|
+
runtime.log?.(`[tlon] ownerListenEnabled → ${enabled}`);
|
|
1053
|
+
}
|
|
1054
|
+
catch (err) {
|
|
1055
|
+
runtime.error?.(`[tlon] Failed to persist ownerListenEnabled: ${String(err)}`);
|
|
1056
|
+
}
|
|
1057
|
+
return enabled;
|
|
1058
|
+
},
|
|
1059
|
+
isOwnerListenDisabled(nest) {
|
|
1060
|
+
const canonical = canonicalizeNest(nest);
|
|
1061
|
+
if (!canonical) {
|
|
1062
|
+
return false;
|
|
1063
|
+
}
|
|
1064
|
+
return effectiveOwnerListenDisabled.has(canonical);
|
|
1065
|
+
},
|
|
1066
|
+
async setOwnerListenDisabled(nest, disabled) {
|
|
1067
|
+
const canonical = canonicalizeNest(nest);
|
|
1068
|
+
if (!canonical) {
|
|
1069
|
+
runtime.error?.(`[tlon] setOwnerListenDisabled: cannot parse nest ${nest}`);
|
|
1070
|
+
return !disabled;
|
|
1071
|
+
}
|
|
1072
|
+
if (disabled) {
|
|
1073
|
+
effectiveOwnerListenDisabled.add(canonical);
|
|
1074
|
+
}
|
|
1075
|
+
else {
|
|
1076
|
+
effectiveOwnerListenDisabled.delete(canonical);
|
|
1077
|
+
}
|
|
1078
|
+
const list = [...effectiveOwnerListenDisabled];
|
|
1079
|
+
try {
|
|
1080
|
+
await api.poke({
|
|
1081
|
+
app: "settings",
|
|
1082
|
+
mark: "settings-event",
|
|
1083
|
+
json: {
|
|
1084
|
+
"put-entry": {
|
|
1085
|
+
desk: "moltbot",
|
|
1086
|
+
"bucket-key": "tlon",
|
|
1087
|
+
"entry-key": "ownerListenDisabledChannels",
|
|
1088
|
+
value: list,
|
|
1089
|
+
},
|
|
1090
|
+
},
|
|
1091
|
+
});
|
|
1092
|
+
runtime.log?.(`[tlon] ownerListenDisabledChannels → [${list.join(", ")}]`);
|
|
1093
|
+
}
|
|
1094
|
+
catch (err) {
|
|
1095
|
+
runtime.error?.(`[tlon] Failed to persist ownerListenDisabledChannels: ${String(err)}`);
|
|
1096
|
+
}
|
|
1097
|
+
return !disabled;
|
|
1098
|
+
},
|
|
1099
|
+
listOwnerListenDisabled() {
|
|
1100
|
+
return [...effectiveOwnerListenDisabled];
|
|
1101
|
+
},
|
|
993
1102
|
};
|
|
994
1103
|
setBridge(accountKey, commandBridge);
|
|
995
1104
|
// Check if a ship is the owner (always allowed to DM)
|
|
@@ -1139,17 +1248,16 @@ export async function monitorTlonProvider(opts = {}) {
|
|
|
1139
1248
|
// Fetch thread context when entering a thread for the first time
|
|
1140
1249
|
if (isThreadReply && parentId && groupChannel) {
|
|
1141
1250
|
try {
|
|
1142
|
-
const
|
|
1143
|
-
if (
|
|
1144
|
-
const
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
runtime?.log?.(`[tlon] Added thread context (${threadHistory.length} replies) to message`);
|
|
1251
|
+
const threadContextHistory = await fetchThreadContextHistory(api, groupChannel, parentId, 20, runtime);
|
|
1252
|
+
if (threadContextHistory.length > 0) {
|
|
1253
|
+
const threadContextMessage = buildThreadContextMessage(threadContextHistory, messageText, {
|
|
1254
|
+
formatAuthor: formatShipWithNickname,
|
|
1255
|
+
sanitizeContent: sanitizeMessageText,
|
|
1256
|
+
});
|
|
1257
|
+
if (threadContextMessage) {
|
|
1258
|
+
messageText = threadContextMessage.messageText;
|
|
1259
|
+
runtime?.log?.(`[tlon] Added thread context (${threadContextMessage.contextMessages.length} messages, parent included) to message`);
|
|
1260
|
+
}
|
|
1153
1261
|
}
|
|
1154
1262
|
}
|
|
1155
1263
|
catch (error) {
|
|
@@ -1352,7 +1460,10 @@ export async function monitorTlonProvider(opts = {}) {
|
|
|
1352
1460
|
OriginatingChannel: "tlon",
|
|
1353
1461
|
OriginatingTo: `tlon:${isGroup ? groupChannel : senderShip}`,
|
|
1354
1462
|
// Include thread context for automatic reply routing
|
|
1355
|
-
...(parentId && {
|
|
1463
|
+
...(parentId && {
|
|
1464
|
+
MessageThreadId: String(parentId),
|
|
1465
|
+
ReplyToId: String(parentId),
|
|
1466
|
+
}),
|
|
1356
1467
|
});
|
|
1357
1468
|
const dispatchStartTime = Date.now();
|
|
1358
1469
|
const replyTelemetry = telemetry?.startReply({
|
|
@@ -1541,7 +1652,8 @@ export async function monitorTlonProvider(opts = {}) {
|
|
|
1541
1652
|
}
|
|
1542
1653
|
// Auto-watch channels from firehose: if we receive events for a channel,
|
|
1543
1654
|
// the bot is a member of the group — add it to watchedChannels automatically.
|
|
1544
|
-
if (!watchedChannels.has(nest) &&
|
|
1655
|
+
if (!watchedChannels.has(nest) &&
|
|
1656
|
+
(nest.startsWith("chat/") || nest.startsWith("heap/") || nest.startsWith("diary/"))) {
|
|
1545
1657
|
watchedChannels.add(nest);
|
|
1546
1658
|
runtime.log?.(`[tlon] Auto-watching channel from firehose: ${nest}`);
|
|
1547
1659
|
}
|
|
@@ -1671,17 +1783,59 @@ export async function monitorTlonProvider(opts = {}) {
|
|
|
1671
1783
|
? response?.post?.["r-post"]?.reply?.["r-reply"]?.set?.seal
|
|
1672
1784
|
: response?.post?.["r-post"]?.set?.seal;
|
|
1673
1785
|
const parentId = seal?.["parent-id"] || seal?.parent || null;
|
|
1786
|
+
const parsedDispatchNest = parseChannelNest(nest);
|
|
1787
|
+
// Control-plane escape hatch: owner-listen may be disabled, but the owner
|
|
1788
|
+
// still needs a no-mention way to turn it back on from the same owned
|
|
1789
|
+
// channel. Handle the exact slash command before the normal engagement
|
|
1790
|
+
// gate, without waking the agent/model for ordinary chatter.
|
|
1791
|
+
if (isOwnerListenSlashCommand(rawText) &&
|
|
1792
|
+
isOwner(senderShip) &&
|
|
1793
|
+
parsedDispatchNest &&
|
|
1794
|
+
(parsedDispatchNest.hostShip === effectiveOwnerShip ||
|
|
1795
|
+
parsedDispatchNest.hostShip === botShipName)) {
|
|
1796
|
+
const args = rawText
|
|
1797
|
+
.trim()
|
|
1798
|
+
.replace(/^\/owner-listen(?:\s+|$)/i, "")
|
|
1799
|
+
.trim();
|
|
1800
|
+
const replyText = await handleOwnerListenCommand(commandBridge, args, `tlon:group:${nest}`);
|
|
1801
|
+
await sendChannelPost({
|
|
1802
|
+
botProfile: getBotProfile(),
|
|
1803
|
+
fromShip: botShipName,
|
|
1804
|
+
nest,
|
|
1805
|
+
story: markdownToStory(replyText),
|
|
1806
|
+
replyToId: parentId ?? undefined,
|
|
1807
|
+
});
|
|
1808
|
+
return;
|
|
1809
|
+
}
|
|
1674
1810
|
// Check if we should respond:
|
|
1675
1811
|
// 1. Direct mention always triggers response
|
|
1676
1812
|
// 2. Thread replies where we've participated - respond if relevant (let agent decide)
|
|
1813
|
+
// 3. Owner blob-only message (image/file with no text from owner)
|
|
1814
|
+
// 4. Owner-listen: owner posts in an owner/bot-hosted channel and the
|
|
1815
|
+
// channel is not in the per-channel disabled list
|
|
1677
1816
|
const mentioned = isBotMentioned(messageText, botShipName, botNickname ?? undefined);
|
|
1678
|
-
const inParticipatedThread = isThreadReply && parentId && participatedThreads.has(String(parentId));
|
|
1817
|
+
const inParticipatedThread = Boolean(isThreadReply && parentId && participatedThreads.has(String(parentId)));
|
|
1679
1818
|
const isOwnerBlob = hasBlob && isOwner(senderShip);
|
|
1680
|
-
|
|
1819
|
+
const engageDecision = shouldEngageInGroup({
|
|
1820
|
+
mentioned,
|
|
1821
|
+
inParticipatedThread,
|
|
1822
|
+
isOwnerBlob,
|
|
1823
|
+
senderShip,
|
|
1824
|
+
ownerShip: effectiveOwnerShip,
|
|
1825
|
+
botShipName,
|
|
1826
|
+
channelNest: nest,
|
|
1827
|
+
groupHost: parsedDispatchNest?.hostShip ?? null,
|
|
1828
|
+
ownerListenEnabled: effectiveOwnerListenEnabled,
|
|
1829
|
+
ownerListenDisabledChannels: effectiveOwnerListenDisabled,
|
|
1830
|
+
});
|
|
1831
|
+
if (!engageDecision.engage) {
|
|
1681
1832
|
return;
|
|
1682
1833
|
}
|
|
1683
1834
|
// Log why we're responding
|
|
1684
|
-
if (
|
|
1835
|
+
if (engageDecision.reason === "owner-owned") {
|
|
1836
|
+
runtime.log?.(`[tlon] Owner ${senderShip} heard without mention in owned channel ${nest}`);
|
|
1837
|
+
}
|
|
1838
|
+
else if (isOwnerBlob && !mentioned && !inParticipatedThread) {
|
|
1685
1839
|
runtime.log?.(`[tlon] Responding to owner blob-only message in ${nest}`);
|
|
1686
1840
|
}
|
|
1687
1841
|
else if (inParticipatedThread && !mentioned) {
|
|
@@ -2180,6 +2334,14 @@ export async function monitorTlonProvider(opts = {}) {
|
|
|
2180
2334
|
effectiveAutoDiscoverChannels = newSettings.autoDiscoverChannels;
|
|
2181
2335
|
runtime.log?.(`[tlon] Settings: autoDiscoverChannels = ${effectiveAutoDiscoverChannels}`);
|
|
2182
2336
|
}
|
|
2337
|
+
if (newSettings.ownerListenEnabled !== undefined) {
|
|
2338
|
+
effectiveOwnerListenEnabled = newSettings.ownerListenEnabled;
|
|
2339
|
+
runtime.log?.(`[tlon] Settings: ownerListenEnabled = ${effectiveOwnerListenEnabled}`);
|
|
2340
|
+
}
|
|
2341
|
+
if (newSettings.ownerListenDisabledChannels !== undefined) {
|
|
2342
|
+
effectiveOwnerListenDisabled = new Set(canonicalizeNestList(newSettings.ownerListenDisabledChannels));
|
|
2343
|
+
runtime.log?.(`[tlon] Settings: ownerListenDisabledChannels updated (${effectiveOwnerListenDisabled.size} channel(s) disabled)`);
|
|
2344
|
+
}
|
|
2183
2345
|
// ownerShip is applied on both live subscription and refresh.
|
|
2184
2346
|
// pendingNudge is only rehydrated from the store during startup load. Once the
|
|
2185
2347
|
// monitor is running, the in-memory pending state is authoritative so refreshes
|
|
@@ -2229,7 +2391,7 @@ export async function monitorTlonProvider(opts = {}) {
|
|
|
2229
2391
|
// runner's stage guard today.
|
|
2230
2392
|
const stageChanged = prevSettings.lastNudgeStage !== newSettings.lastNudgeStage;
|
|
2231
2393
|
if (shadowReconcileTrusted && stageChanged) {
|
|
2232
|
-
const nextStage =
|
|
2394
|
+
const nextStage = newSettings.lastNudgeStage ?? 0;
|
|
2233
2395
|
setLastNudgeStageShadow(account.accountId, nextStage);
|
|
2234
2396
|
runtime.log?.(`[tlon] nudge: reconciled lastNudgeStageShadow from ${source} (stage=${nextStage})`);
|
|
2235
2397
|
}
|
|
@@ -2292,8 +2454,10 @@ export async function monitorTlonProvider(opts = {}) {
|
|
|
2292
2454
|
if (event.channels && typeof event.channels === "object") {
|
|
2293
2455
|
const channels = event.channels;
|
|
2294
2456
|
for (const [channelNest, _channelData] of Object.entries(channels)) {
|
|
2295
|
-
// Only monitor chat and
|
|
2296
|
-
if (!channelNest.startsWith("chat/") &&
|
|
2457
|
+
// Only monitor chat, heap, and diary channels
|
|
2458
|
+
if (!channelNest.startsWith("chat/") &&
|
|
2459
|
+
!channelNest.startsWith("heap/") &&
|
|
2460
|
+
!channelNest.startsWith("diary/")) {
|
|
2297
2461
|
continue;
|
|
2298
2462
|
}
|
|
2299
2463
|
// If this is a new channel we're not watching yet, add it
|
|
@@ -2334,7 +2498,9 @@ export async function monitorTlonProvider(opts = {}) {
|
|
|
2334
2498
|
const join = event.join;
|
|
2335
2499
|
if (join.channels) {
|
|
2336
2500
|
for (const channelNest of join.channels) {
|
|
2337
|
-
if (!channelNest.startsWith("chat/") &&
|
|
2501
|
+
if (!channelNest.startsWith("chat/") &&
|
|
2502
|
+
!channelNest.startsWith("heap/") &&
|
|
2503
|
+
!channelNest.startsWith("diary/")) {
|
|
2338
2504
|
continue;
|
|
2339
2505
|
}
|
|
2340
2506
|
if (!watchedChannels.has(channelNest)) {
|
|
@@ -2560,7 +2726,9 @@ export async function monitorTlonProvider(opts = {}) {
|
|
|
2560
2726
|
}
|
|
2561
2727
|
try {
|
|
2562
2728
|
const refreshResult = await settingsManager.load();
|
|
2563
|
-
applySettingsSnapshot(refreshResult.settings, "refresh", {
|
|
2729
|
+
applySettingsSnapshot(refreshResult.settings, "refresh", {
|
|
2730
|
+
fresh: refreshResult.fresh,
|
|
2731
|
+
});
|
|
2564
2732
|
}
|
|
2565
2733
|
catch (err) {
|
|
2566
2734
|
runtime.error?.(`[tlon] Settings refresh failed: ${String(err)}`);
|