@tloncorp/openclaw 0.6.0 → 0.6.1
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 +559 -17
- package/dist/index.js.map +1 -1
- package/dist/src/channel.js +12 -0
- package/dist/src/channel.js.map +1 -1
- package/dist/src/diagnostic-subscriptions.js +49 -0
- package/dist/src/diagnostic-subscriptions.js.map +1 -0
- package/dist/src/monitor/index.js +275 -41
- package/dist/src/monitor/index.js.map +1 -1
- package/dist/src/monitor/session-routing.js +261 -0
- package/dist/src/monitor/session-routing.js.map +1 -0
- package/dist/src/session-route.js +44 -0
- package/dist/src/session-route.js.map +1 -0
- package/dist/src/telemetry.js +749 -22
- package/dist/src/telemetry.js.map +1 -1
- package/dist/src/version.generated.js +2 -2
- package/dist/src/version.js +134 -0
- package/dist/src/version.js.map +1 -0
- package/package.json +3 -29
|
@@ -0,0 +1,261 @@
|
|
|
1
|
+
import { resolvePinnedMainDmOwnerFromAllowlist } from 'openclaw/plugin-sdk/conversation-runtime';
|
|
2
|
+
import { resolveInboundLastRouteSessionKey, } from 'openclaw/plugin-sdk/routing';
|
|
3
|
+
import { canonicalizeNest, normalizeShip } from '../targets.js';
|
|
4
|
+
/**
|
|
5
|
+
* Build the parameters for persisting a Tlon inbound turn's durable session
|
|
6
|
+
* route. Pure: no I/O, no SDK store access. The caller passes the result to
|
|
7
|
+
* `recordInboundSession` (see `recordTlonInboundRoute`).
|
|
8
|
+
*
|
|
9
|
+
* Routing rules:
|
|
10
|
+
* - DM: persist `tlon:<senderShip>`. When the last-route session is the agent
|
|
11
|
+
* main session and a single owner is pinned, attach `mainDmOwnerPin` so a
|
|
12
|
+
* non-owner DM cannot silently overwrite the owner/main route.
|
|
13
|
+
* - Group/channel: persist `tlon:<groupChannel>` only when the last-route
|
|
14
|
+
* session is NOT the main session (avoid clobbering a broad shared session).
|
|
15
|
+
* Skip — but still record origin metadata — when `groupChannel` is missing.
|
|
16
|
+
*/
|
|
17
|
+
export function buildTlonInboundRouteRecord(input) {
|
|
18
|
+
const { cfg, route, ctxSessionKey, isGroup, groupChannel, senderShip, parentId, deliverParentId, effectiveOwnerShip, effectiveDmAllowlist, } = input;
|
|
19
|
+
const recordSessionKey = ctxSessionKey ?? route.sessionKey;
|
|
20
|
+
const lastRouteSessionKey = resolveInboundLastRouteSessionKey({
|
|
21
|
+
route,
|
|
22
|
+
sessionKey: recordSessionKey,
|
|
23
|
+
});
|
|
24
|
+
const rawThread = deliverParentId ?? parentId;
|
|
25
|
+
const threadId = rawThread != null && rawThread !== '' ? String(rawThread) : undefined;
|
|
26
|
+
const base = { recordSessionKey, lastRouteSessionKey };
|
|
27
|
+
if (isGroup) {
|
|
28
|
+
const nest = groupChannel?.trim();
|
|
29
|
+
if (!nest) {
|
|
30
|
+
return { ...base, target: null, skippedReason: 'group-missing-channel' };
|
|
31
|
+
}
|
|
32
|
+
// Validate/canonicalize the nest before storing. Firehose nests are already
|
|
33
|
+
// canonical, but config/settings-watched values can be malformed; a bad
|
|
34
|
+
// nest would otherwise persist an unusable `lastTo`.
|
|
35
|
+
const canonicalNest = canonicalizeNest(nest);
|
|
36
|
+
if (!canonicalNest) {
|
|
37
|
+
return { ...base, target: null, skippedReason: 'group-invalid-channel' };
|
|
38
|
+
}
|
|
39
|
+
const target = `tlon:${canonicalNest}`;
|
|
40
|
+
// Don't overwrite a broad shared main session with a per-group route.
|
|
41
|
+
if (lastRouteSessionKey === route.mainSessionKey) {
|
|
42
|
+
return {
|
|
43
|
+
...base,
|
|
44
|
+
target,
|
|
45
|
+
skippedReason: 'group-route-targets-main-session',
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
return {
|
|
49
|
+
...base,
|
|
50
|
+
target,
|
|
51
|
+
updateLastRoute: {
|
|
52
|
+
sessionKey: lastRouteSessionKey,
|
|
53
|
+
channel: 'tlon',
|
|
54
|
+
to: target,
|
|
55
|
+
...(route.accountId ? { accountId: route.accountId } : {}),
|
|
56
|
+
...(threadId !== undefined ? { threadId } : {}),
|
|
57
|
+
},
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
// DM
|
|
61
|
+
const target = `tlon:${senderShip}`;
|
|
62
|
+
const mainDmOwnerPin = resolveMainDmOwnerPin({
|
|
63
|
+
cfg,
|
|
64
|
+
route,
|
|
65
|
+
lastRouteSessionKey,
|
|
66
|
+
senderShip,
|
|
67
|
+
effectiveOwnerShip,
|
|
68
|
+
effectiveDmAllowlist,
|
|
69
|
+
});
|
|
70
|
+
return {
|
|
71
|
+
...base,
|
|
72
|
+
target,
|
|
73
|
+
updateLastRoute: {
|
|
74
|
+
sessionKey: lastRouteSessionKey,
|
|
75
|
+
channel: 'tlon',
|
|
76
|
+
to: target,
|
|
77
|
+
...(route.accountId ? { accountId: route.accountId } : {}),
|
|
78
|
+
...(threadId !== undefined ? { threadId } : {}),
|
|
79
|
+
...(mainDmOwnerPin ? { mainDmOwnerPin } : {}),
|
|
80
|
+
},
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
function resolveMainDmOwnerPin(params) {
|
|
84
|
+
const { cfg, route, lastRouteSessionKey, senderShip, effectiveOwnerShip, effectiveDmAllowlist, } = params;
|
|
85
|
+
// Only the main session can be clobbered by another DM sender; isolated
|
|
86
|
+
// per-peer sessions need no pin.
|
|
87
|
+
if (lastRouteSessionKey !== route.mainSessionKey) {
|
|
88
|
+
return undefined;
|
|
89
|
+
}
|
|
90
|
+
const sender = senderShip.trim();
|
|
91
|
+
if (!sender) {
|
|
92
|
+
return undefined;
|
|
93
|
+
}
|
|
94
|
+
// Tlon's configured owner (`ownerShip`) is separate from `dmAllowlist`, and
|
|
95
|
+
// owner DMs are valid even when the owner isn't allowlisted. Prefer pinning
|
|
96
|
+
// the configured owner; otherwise fall back to the SDK's allowlist semantics
|
|
97
|
+
// (which only pin when there is exactly one allowed sender).
|
|
98
|
+
const pinnedOwner = resolvePinnedMainDmOwnerFromAllowlist({
|
|
99
|
+
dmScope: cfg.session?.dmScope,
|
|
100
|
+
allowFrom: effectiveOwnerShip ? [effectiveOwnerShip] : effectiveDmAllowlist,
|
|
101
|
+
normalizeEntry: normalizeShip,
|
|
102
|
+
});
|
|
103
|
+
if (!pinnedOwner) {
|
|
104
|
+
return undefined;
|
|
105
|
+
}
|
|
106
|
+
return {
|
|
107
|
+
ownerRecipient: pinnedOwner,
|
|
108
|
+
senderRecipient: normalizeShip(sender),
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Persist a Tlon inbound turn's session route. Always records origin metadata
|
|
113
|
+
* (even when `record.updateLastRoute` is omitted) and fails open: a persistence
|
|
114
|
+
* failure is logged but never blocks the live reply.
|
|
115
|
+
*/
|
|
116
|
+
export async function recordTlonInboundRoute(deps) {
|
|
117
|
+
const { session, storePath, ctxPayload, record, messageId, accountId } = deps;
|
|
118
|
+
if (record.skippedReason === 'group-missing-channel' ||
|
|
119
|
+
record.skippedReason === 'group-invalid-channel') {
|
|
120
|
+
// Anomalous (a group turn with no/malformed channel nest); surface outside
|
|
121
|
+
// debug too.
|
|
122
|
+
deps.logError?.(`[tlon] route persistence skipped (${record.skippedReason}): ` +
|
|
123
|
+
`messageId=${messageId ?? '?'} lastRouteSessionKey=${record.lastRouteSessionKey}`);
|
|
124
|
+
}
|
|
125
|
+
else if (record.skippedReason) {
|
|
126
|
+
// Normal policy outcome (e.g. a group route that targets the shared main
|
|
127
|
+
// session); debug-only to avoid high-volume logs for an expected case.
|
|
128
|
+
deps.logDebug?.(`[tlon] route persistence skipped (${record.skippedReason}): ` +
|
|
129
|
+
`messageId=${messageId ?? '?'} lastRouteSessionKey=${record.lastRouteSessionKey} ` +
|
|
130
|
+
`target=${record.target ?? '(none)'}`);
|
|
131
|
+
}
|
|
132
|
+
// When a main-session DM is pinned to an owner, the SDK skips the durable
|
|
133
|
+
// route update for a non-owner sender. Wire an onSkip so that decision is
|
|
134
|
+
// observable instead of silently looking like a successful write.
|
|
135
|
+
const pin = record.updateLastRoute?.mainDmOwnerPin;
|
|
136
|
+
const updateLastRoute = record.updateLastRoute
|
|
137
|
+
? {
|
|
138
|
+
...record.updateLastRoute,
|
|
139
|
+
...(pin
|
|
140
|
+
? {
|
|
141
|
+
mainDmOwnerPin: {
|
|
142
|
+
...pin,
|
|
143
|
+
onSkip: ({ ownerRecipient, senderRecipient }) => deps.logDebug?.(`[tlon] durable route update skipped by owner pin: ` +
|
|
144
|
+
`messageId=${messageId ?? '?'} owner=${ownerRecipient} ` +
|
|
145
|
+
`sender=${senderRecipient} lastRouteSessionKey=${record.lastRouteSessionKey}`),
|
|
146
|
+
},
|
|
147
|
+
}
|
|
148
|
+
: {}),
|
|
149
|
+
}
|
|
150
|
+
: undefined;
|
|
151
|
+
try {
|
|
152
|
+
await session.recordInboundSession({
|
|
153
|
+
storePath,
|
|
154
|
+
sessionKey: record.recordSessionKey,
|
|
155
|
+
ctx: ctxPayload,
|
|
156
|
+
updateLastRoute,
|
|
157
|
+
onRecordError: (err) => {
|
|
158
|
+
deps.logError?.(`[tlon] failed updating session meta: ${String(err)}`);
|
|
159
|
+
},
|
|
160
|
+
});
|
|
161
|
+
}
|
|
162
|
+
catch (err) {
|
|
163
|
+
deps.logError?.(`[tlon] failed recording inbound session route: ${String(err)} ` +
|
|
164
|
+
`(messageId=${messageId ?? '?'} storePath=${storePath} ` +
|
|
165
|
+
`recordSessionKey=${record.recordSessionKey} ` +
|
|
166
|
+
`lastRouteSessionKey=${record.lastRouteSessionKey} ` +
|
|
167
|
+
`target=${record.target ?? '(none)'} accountId=${accountId ?? '(none)'} ` +
|
|
168
|
+
`hadUpdateLastRoute=${Boolean(record.updateLastRoute)})`);
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
/**
|
|
172
|
+
* Whether the SDK will skip the durable route update because a main-session DM
|
|
173
|
+
* is pinned to an owner different from the sender. A built `updateLastRoute`
|
|
174
|
+
* does not guarantee a write, so diagnostics should report this rather than
|
|
175
|
+
* imply the route was persisted.
|
|
176
|
+
*/
|
|
177
|
+
export function routeUpdateWillSkipByPin(update) {
|
|
178
|
+
const pin = update?.mainDmOwnerPin;
|
|
179
|
+
if (!pin) {
|
|
180
|
+
return false;
|
|
181
|
+
}
|
|
182
|
+
return pin.ownerRecipient !== pin.senderRecipient;
|
|
183
|
+
}
|
|
184
|
+
/**
|
|
185
|
+
* Run the durable route-record step before reply dispatch. The bug this fixes
|
|
186
|
+
* lives at exactly this boundary: route-dependent sends that happen during
|
|
187
|
+
* dispatch must observe the persisted route, so recording must complete first.
|
|
188
|
+
* Keeping this ordering in one place gives the monitor a testable guard.
|
|
189
|
+
*/
|
|
190
|
+
export async function recordRouteThenDispatch(steps) {
|
|
191
|
+
await steps.record();
|
|
192
|
+
return steps.dispatch();
|
|
193
|
+
}
|
|
194
|
+
/**
|
|
195
|
+
* The monitor's "build ctx → record route → dispatch" boundary, as a single
|
|
196
|
+
* testable unit (this is where the original webchat-leak bug lived). Builds the
|
|
197
|
+
* Tlon route record, persists it, and only then runs `dispatch`. The monitor
|
|
198
|
+
* delegates its entire record+dispatch to this so the ordering is covered by a
|
|
199
|
+
* unit test rather than only by the monitor's structure.
|
|
200
|
+
*/
|
|
201
|
+
export async function recordTlonRouteAndDispatch(params) {
|
|
202
|
+
const record = buildTlonInboundRouteRecord({
|
|
203
|
+
cfg: params.cfg,
|
|
204
|
+
route: params.route,
|
|
205
|
+
ctxSessionKey: params.ctxSessionKey,
|
|
206
|
+
isGroup: params.isGroup,
|
|
207
|
+
groupChannel: params.groupChannel,
|
|
208
|
+
senderShip: params.senderShip,
|
|
209
|
+
parentId: params.parentId,
|
|
210
|
+
deliverParentId: params.deliverParentId,
|
|
211
|
+
effectiveOwnerShip: params.effectiveOwnerShip,
|
|
212
|
+
effectiveDmAllowlist: params.effectiveDmAllowlist,
|
|
213
|
+
});
|
|
214
|
+
params.onRecord?.(record);
|
|
215
|
+
return recordRouteThenDispatch({
|
|
216
|
+
// Fail open across the *entire* persistence step — including
|
|
217
|
+
// resolveStorePath, which can throw on bad session-store config — so a
|
|
218
|
+
// persistence failure never suppresses the live Tlon reply.
|
|
219
|
+
record: async () => {
|
|
220
|
+
let storePath;
|
|
221
|
+
try {
|
|
222
|
+
storePath = params.session.resolveStorePath(params.sessionStore, {
|
|
223
|
+
agentId: params.route.agentId,
|
|
224
|
+
});
|
|
225
|
+
}
|
|
226
|
+
catch (err) {
|
|
227
|
+
params.logError?.(`[tlon] failed resolving session store path: ${String(err)} ` +
|
|
228
|
+
`(messageId=${params.messageId ?? '?'})`);
|
|
229
|
+
return;
|
|
230
|
+
}
|
|
231
|
+
await recordTlonInboundRoute({
|
|
232
|
+
session: params.session,
|
|
233
|
+
storePath,
|
|
234
|
+
ctxPayload: params.ctxPayload,
|
|
235
|
+
record,
|
|
236
|
+
messageId: params.messageId,
|
|
237
|
+
accountId: params.route.accountId,
|
|
238
|
+
logError: params.logError,
|
|
239
|
+
logDebug: params.logDebug,
|
|
240
|
+
});
|
|
241
|
+
},
|
|
242
|
+
dispatch: params.dispatch,
|
|
243
|
+
});
|
|
244
|
+
}
|
|
245
|
+
/**
|
|
246
|
+
* Build a Tlon `deliveryContext` for an enqueued system event (reactions,
|
|
247
|
+
* group-join notices). System-event turns resolve delivery from the event's
|
|
248
|
+
* `deliveryContext` or the session store; attaching this ensures a later
|
|
249
|
+
* system/heartbeat turn driven by the event routes to Tlon instead of falling
|
|
250
|
+
* back to webchat, even on a session that hasn't persisted an inbound route yet.
|
|
251
|
+
* `to` is the provider-qualified target (`tlon:~ship` for DMs, `tlon:<nest>` for
|
|
252
|
+
* channels), matching `OriginatingTo` and the durable route.
|
|
253
|
+
*/
|
|
254
|
+
export function tlonDeliveryContext(to, accountId) {
|
|
255
|
+
return { channel: 'tlon', to, ...(accountId ? { accountId } : {}) };
|
|
256
|
+
}
|
|
257
|
+
/** Route-debug gate: enabled via `TLON_OPENCLAW_ROUTE_DEBUG=1`. */
|
|
258
|
+
export function isRouteDebugEnabled() {
|
|
259
|
+
return process.env.TLON_OPENCLAW_ROUTE_DEBUG === '1';
|
|
260
|
+
}
|
|
261
|
+
//# sourceMappingURL=session-routing.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session-routing.js","sourceRoot":"","sources":["../../../src/monitor/session-routing.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { buildChannelOutboundSessionRoute, } from 'openclaw/plugin-sdk/core';
|
|
2
|
+
import { parseTlonTarget } from './targets.js';
|
|
3
|
+
/**
|
|
4
|
+
* Channel-native outbound session-route builder for Tlon.
|
|
5
|
+
*
|
|
6
|
+
* Lets explicit outbound sends to a Tlon target (e.g. the shared `message` tool
|
|
7
|
+
* with `to: tlon:~ship`) derive a stable Tlon session route, so they resolve
|
|
8
|
+
* to Tlon even when the current turn's surface is something else. Returns
|
|
9
|
+
* `null` for non-Tlon / unparseable targets so core can fall through.
|
|
10
|
+
*/
|
|
11
|
+
export function resolveTlonOutboundSessionRoute(params) {
|
|
12
|
+
const parsed = parseTlonTarget(params.target);
|
|
13
|
+
if (!parsed) {
|
|
14
|
+
return null;
|
|
15
|
+
}
|
|
16
|
+
const threadId = params.threadId != null && params.threadId !== ''
|
|
17
|
+
? params.threadId
|
|
18
|
+
: undefined;
|
|
19
|
+
if (parsed.kind === 'dm') {
|
|
20
|
+
return buildChannelOutboundSessionRoute({
|
|
21
|
+
cfg: params.cfg,
|
|
22
|
+
agentId: params.agentId,
|
|
23
|
+
channel: 'tlon',
|
|
24
|
+
accountId: params.accountId,
|
|
25
|
+
peer: { kind: 'direct', id: parsed.ship },
|
|
26
|
+
chatType: 'direct',
|
|
27
|
+
from: `tlon:${parsed.ship}`,
|
|
28
|
+
to: `tlon:${parsed.ship}`,
|
|
29
|
+
...(threadId !== undefined ? { threadId } : {}),
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
return buildChannelOutboundSessionRoute({
|
|
33
|
+
cfg: params.cfg,
|
|
34
|
+
agentId: params.agentId,
|
|
35
|
+
channel: 'tlon',
|
|
36
|
+
accountId: params.accountId,
|
|
37
|
+
peer: { kind: 'group', id: parsed.nest },
|
|
38
|
+
chatType: 'group',
|
|
39
|
+
from: `tlon:group:${parsed.nest}`,
|
|
40
|
+
to: `tlon:${parsed.nest}`,
|
|
41
|
+
...(threadId !== undefined ? { threadId } : {}),
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
//# sourceMappingURL=session-route.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session-route.js","sourceRoot":"","sources":["../../src/session-route.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,gCAAgC,GACjC,MAAM,0BAA0B,CAAC;AAElC,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAE/C;;;;;;;GAOG;AACH,MAAM,UAAU,+BAA+B,CAC7C,MAAyC;IAEzC,MAAM,MAAM,GAAG,eAAe,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;IAC9C,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,OAAO,IAAI,CAAC;IACd,CAAC;IAED,MAAM,QAAQ,GACZ,MAAM,CAAC,QAAQ,IAAI,IAAI,IAAI,MAAM,CAAC,QAAQ,KAAK,EAAE;QAC/C,CAAC,CAAC,MAAM,CAAC,QAAQ;QACjB,CAAC,CAAC,SAAS,CAAC;IAEhB,IAAI,MAAM,CAAC,IAAI,KAAK,IAAI,EAAE,CAAC;QACzB,OAAO,gCAAgC,CAAC;YACtC,GAAG,EAAE,MAAM,CAAC,GAAG;YACf,OAAO,EAAE,MAAM,CAAC,OAAO;YACvB,OAAO,EAAE,MAAM;YACf,SAAS,EAAE,MAAM,CAAC,SAAS;YAC3B,IAAI,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,CAAC,IAAI,EAAE;YACzC,QAAQ,EAAE,QAAQ;YAClB,IAAI,EAAE,QAAQ,MAAM,CAAC,IAAI,EAAE;YAC3B,EAAE,EAAE,QAAQ,MAAM,CAAC,IAAI,EAAE;YACzB,GAAG,CAAC,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SAChD,CAAC,CAAC;IACL,CAAC;IAED,OAAO,gCAAgC,CAAC;QACtC,GAAG,EAAE,MAAM,CAAC,GAAG;QACf,OAAO,EAAE,MAAM,CAAC,OAAO;QACvB,OAAO,EAAE,MAAM;QACf,SAAS,EAAE,MAAM,CAAC,SAAS;QAC3B,IAAI,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,EAAE,EAAE,MAAM,CAAC,IAAI,EAAE;QACxC,QAAQ,EAAE,OAAO;QACjB,IAAI,EAAE,cAAc,MAAM,CAAC,IAAI,EAAE;QACjC,EAAE,EAAE,QAAQ,MAAM,CAAC,IAAI,EAAE;QACzB,GAAG,CAAC,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KAChD,CAAC,CAAC;AACL,CAAC"}
|