@ouro.bot/cli 0.1.0-alpha.720 → 0.1.0-alpha.722
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/LICENSE +21 -0
- package/changelog.json +12 -0
- package/dist/arc/flight-recorder.js +112 -6
- package/dist/heart/daemon/doctor.js +163 -12
- package/dist/heart/daemon/freshness.js +302 -0
- package/dist/heart/habits/habit-session.js +7 -4
- package/dist/heart/mailbox/mailbox-http-hooks.js +2 -0
- package/dist/heart/mailbox/mailbox-http-routes.js +23 -0
- package/dist/heart/mailbox/mailbox-read.js +3 -1
- package/dist/heart/mailbox/readers/runtime-readers.js +9 -0
- package/dist/rsvp/native-habit-runner.js +173 -5
- package/dist/senses/bluebubbles/context-packet.js +22 -1
- package/dist/senses/bluebubbles/index.js +54 -28
- package/dist/senses/context-packet-ledger.js +126 -0
- package/dist/senses/pipeline.js +37 -1
- package/package.json +1 -1
|
@@ -45,6 +45,23 @@ function messageToContextInput(event, chatGuidHash) {
|
|
|
45
45
|
},
|
|
46
46
|
};
|
|
47
47
|
}
|
|
48
|
+
function normalizeKnownMessageText(value) {
|
|
49
|
+
return value.replace(/\s+/g, " ").trim().toLowerCase();
|
|
50
|
+
}
|
|
51
|
+
function hasKnownMessageText(candidate, knownTexts) {
|
|
52
|
+
if (knownTexts.size === 0)
|
|
53
|
+
return false;
|
|
54
|
+
const body = normalizeKnownMessageText(candidate.textForAgent || candidate.text);
|
|
55
|
+
if (!body)
|
|
56
|
+
return true;
|
|
57
|
+
if (knownTexts.has(body))
|
|
58
|
+
return true;
|
|
59
|
+
for (const known of knownTexts) {
|
|
60
|
+
if (body.length >= 12 && known.includes(body))
|
|
61
|
+
return true;
|
|
62
|
+
}
|
|
63
|
+
return false;
|
|
64
|
+
}
|
|
48
65
|
async function buildBlueBubblesContextPacket(input) {
|
|
49
66
|
if (!Number.isFinite(input.event.timestamp))
|
|
50
67
|
return null;
|
|
@@ -53,6 +70,9 @@ async function buildBlueBubblesContextPacket(input) {
|
|
|
53
70
|
const event = input.event;
|
|
54
71
|
const chatGuidHash = blueBubblesContextChatKeyHash(event);
|
|
55
72
|
const anchorTimestamp = new Date(event.timestamp).toISOString();
|
|
73
|
+
const knownTexts = new Set((input.knownMessageTexts ?? [])
|
|
74
|
+
.map(normalizeKnownMessageText)
|
|
75
|
+
.filter((value) => value.length > 0));
|
|
56
76
|
const candidates = await input.client.listRecentMessages({
|
|
57
77
|
beforeTimestamp: event.timestamp,
|
|
58
78
|
limit: exports.BLUEBUBBLES_CONTEXT_PACKET_LIMIT,
|
|
@@ -65,7 +85,8 @@ async function buildBlueBubblesContextPacket(input) {
|
|
|
65
85
|
.filter((candidate) => isSameBlueBubblesChat(candidate, event))
|
|
66
86
|
.filter((candidate) => candidate.messageGuid !== event.messageGuid)
|
|
67
87
|
.filter((candidate) => candidate.timestamp <= event.timestamp)
|
|
68
|
-
.filter((candidate) => event.timestamp - candidate.timestamp <= exports.BLUEBUBBLES_CONTEXT_PACKET_MAX_AGE_MS)
|
|
88
|
+
.filter((candidate) => event.timestamp - candidate.timestamp <= exports.BLUEBUBBLES_CONTEXT_PACKET_MAX_AGE_MS)
|
|
89
|
+
.filter((candidate) => !hasKnownMessageText(candidate, knownTexts));
|
|
69
90
|
if (history.length === 0)
|
|
70
91
|
return null;
|
|
71
92
|
const packet = (0, context_packets_1.buildSenseContextPacket)({
|
|
@@ -623,12 +623,18 @@ function insertEphemeralContextMessages(messages, contextMessages) {
|
|
|
623
623
|
...messages.slice(insertionIndex),
|
|
624
624
|
];
|
|
625
625
|
}
|
|
626
|
+
function knownProviderMessageTexts(messages) {
|
|
627
|
+
return messages
|
|
628
|
+
.map((message) => extractMessageText(message.content))
|
|
629
|
+
.map((text) => text.trim())
|
|
630
|
+
.filter((text) => text.length > 0);
|
|
631
|
+
}
|
|
626
632
|
async function buildBlueBubblesContextMessages(input) {
|
|
627
633
|
if (input.event.kind !== "message")
|
|
628
|
-
return [];
|
|
634
|
+
return { messages: [], contextPacketIds: [] };
|
|
629
635
|
const event = input.event;
|
|
630
636
|
if (!Number.isFinite(event.timestamp))
|
|
631
|
-
return [];
|
|
637
|
+
return { messages: [], contextPacketIds: [] };
|
|
632
638
|
const chatGuidHash = (0, context_packet_1.blueBubblesContextChatKeyHash)(event);
|
|
633
639
|
const anchorTimestamp = new Date(event.timestamp).toISOString();
|
|
634
640
|
try {
|
|
@@ -636,9 +642,10 @@ async function buildBlueBubblesContextMessages(input) {
|
|
|
636
642
|
agentName: input.agentName,
|
|
637
643
|
client: input.client,
|
|
638
644
|
event,
|
|
645
|
+
knownMessageTexts: knownProviderMessageTexts(input.knownMessages ?? []),
|
|
639
646
|
});
|
|
640
647
|
if (!result)
|
|
641
|
-
return [];
|
|
648
|
+
return { messages: [], contextPacketIds: [] };
|
|
642
649
|
const { packet, rendered, historyCount } = result;
|
|
643
650
|
(0, context_packet_ledger_1.writeSenseContextPacket)(input.agentRoot, packet);
|
|
644
651
|
(0, runtime_1.emitNervesEvent)({
|
|
@@ -651,7 +658,10 @@ async function buildBlueBubblesContextMessages(input) {
|
|
|
651
658
|
contextMessages: historyCount,
|
|
652
659
|
},
|
|
653
660
|
});
|
|
654
|
-
return
|
|
661
|
+
return {
|
|
662
|
+
messages: [{ role: "system", content: rendered.text }],
|
|
663
|
+
contextPacketIds: [packet.packetId],
|
|
664
|
+
};
|
|
655
665
|
}
|
|
656
666
|
catch (error) {
|
|
657
667
|
(0, runtime_1.emitNervesEvent)({
|
|
@@ -671,9 +681,12 @@ async function buildBlueBubblesContextMessages(input) {
|
|
|
671
681
|
maxAgeMs: 24 * 60 * 60 * 1000,
|
|
672
682
|
});
|
|
673
683
|
if (!fallback)
|
|
674
|
-
return [];
|
|
684
|
+
return { messages: [], contextPacketIds: [] };
|
|
675
685
|
const rendered = (0, context_packets_1.renderSenseContextPacketForPrompt)(fallback);
|
|
676
|
-
return
|
|
686
|
+
return {
|
|
687
|
+
messages: [{ role: "system", content: rendered.text }],
|
|
688
|
+
contextPacketIds: [fallback.packetId],
|
|
689
|
+
};
|
|
677
690
|
}
|
|
678
691
|
}
|
|
679
692
|
function createReplyTargetController(event) {
|
|
@@ -1468,6 +1481,10 @@ async function handleBlueBubblesNormalizedEvent(event, resolvedDeps, source, opt
|
|
|
1468
1481
|
if (typeof timeoutTimer.unref === "function") {
|
|
1469
1482
|
timeoutTimer.unref();
|
|
1470
1483
|
}
|
|
1484
|
+
let preparedBlueBubblesContext = {
|
|
1485
|
+
messages: [],
|
|
1486
|
+
contextPacketIds: [],
|
|
1487
|
+
};
|
|
1471
1488
|
const turnPromise = (0, pipeline_1.handleInboundTurn)({
|
|
1472
1489
|
channel: "bluebubbles",
|
|
1473
1490
|
sessionKey: event.chat.sessionKey,
|
|
@@ -1494,35 +1511,44 @@ async function handleBlueBubblesNormalizedEvent(event, resolvedDeps, source, opt
|
|
|
1494
1511
|
enforceTrustGate: trust_gate_1.enforceTrustGate,
|
|
1495
1512
|
drainPending: pending_1.drainPending,
|
|
1496
1513
|
drainDeferredReturns: (deferredFriendId) => (0, pending_1.drainDeferredReturns)(resolvedDeps.getAgentName(), deferredFriendId),
|
|
1497
|
-
|
|
1498
|
-
|
|
1514
|
+
prepareRunAgentOptions: async ({ messages, runAgentOptions }) => {
|
|
1515
|
+
preparedBlueBubblesContext = await buildBlueBubblesContextMessages({
|
|
1499
1516
|
agentName,
|
|
1500
1517
|
agentRoot: (0, identity_1.getAgentRoot)(),
|
|
1501
1518
|
client,
|
|
1502
1519
|
event,
|
|
1520
|
+
knownMessages: messages,
|
|
1503
1521
|
});
|
|
1504
|
-
|
|
1505
|
-
|
|
1506
|
-
|
|
1507
|
-
|
|
1508
|
-
|
|
1509
|
-
...
|
|
1510
|
-
|
|
1511
|
-
|
|
1512
|
-
|
|
1513
|
-
|
|
1514
|
-
|
|
1515
|
-
|
|
1516
|
-
|
|
1517
|
-
|
|
1518
|
-
|
|
1519
|
-
|
|
1520
|
-
|
|
1521
|
-
|
|
1522
|
+
if (preparedBlueBubblesContext.contextPacketIds.length === 0)
|
|
1523
|
+
return undefined;
|
|
1524
|
+
return {
|
|
1525
|
+
contextPacketIds: [
|
|
1526
|
+
...(runAgentOptions.contextPacketIds ?? []),
|
|
1527
|
+
...preparedBlueBubblesContext.contextPacketIds,
|
|
1528
|
+
],
|
|
1529
|
+
};
|
|
1530
|
+
},
|
|
1531
|
+
runAgent: async (msgs, cb, channel, sig, opts) => resolvedDeps.runAgent(insertEphemeralContextMessages(msgs, preparedBlueBubblesContext.messages), cb, channel, sig, {
|
|
1532
|
+
...opts,
|
|
1533
|
+
toolContext: {
|
|
1534
|
+
/* v8 ignore next -- default no-op signin; pipeline provides the real one @preserve */
|
|
1535
|
+
signin: async () => undefined,
|
|
1536
|
+
...opts?.toolContext,
|
|
1537
|
+
summarize,
|
|
1538
|
+
bluebubblesReplyTarget: {
|
|
1539
|
+
setSelection: (selection) => replyTarget.setSelection(selection),
|
|
1540
|
+
},
|
|
1541
|
+
codingFeedback: {
|
|
1542
|
+
send: async (message) => {
|
|
1543
|
+
await client.sendText({
|
|
1544
|
+
chat: event.chat,
|
|
1545
|
+
text: message,
|
|
1546
|
+
replyToMessageGuid: replyTarget.getReplyToMessageGuid(),
|
|
1547
|
+
});
|
|
1522
1548
|
},
|
|
1523
1549
|
},
|
|
1524
|
-
}
|
|
1525
|
-
},
|
|
1550
|
+
},
|
|
1551
|
+
}),
|
|
1526
1552
|
postTurn: (turnMessages, sessionPathArg, usage, hooks, state) => {
|
|
1527
1553
|
const prepared = resolvedDeps.postTurnTrim(turnMessages, usage, hooks);
|
|
1528
1554
|
resolvedDeps.deferPostTurnPersist(sessionPathArg, prepared, usage, state);
|
|
@@ -35,6 +35,8 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
35
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
36
|
exports.writeSenseContextPacket = writeSenseContextPacket;
|
|
37
37
|
exports.readSenseContextLedger = readSenseContextLedger;
|
|
38
|
+
exports.listSenseContextPacketSummaries = listSenseContextPacketSummaries;
|
|
39
|
+
exports.readSenseContextPacketView = readSenseContextPacketView;
|
|
38
40
|
exports.readLatestVisibleSenseContextPacket = readLatestVisibleSenseContextPacket;
|
|
39
41
|
exports.compactSenseContextPacketReceipts = compactSenseContextPacketReceipts;
|
|
40
42
|
const fs = __importStar(require("node:fs"));
|
|
@@ -44,6 +46,9 @@ const context_packets_1 = require("./context-packets");
|
|
|
44
46
|
function contextPacketRoot(agentRoot, sense) {
|
|
45
47
|
return path.join(agentRoot, "state", "senses", "context-packets", sense);
|
|
46
48
|
}
|
|
49
|
+
function contextPacketBaseRoot(agentRoot) {
|
|
50
|
+
return path.join(agentRoot, "state", "senses", "context-packets");
|
|
51
|
+
}
|
|
47
52
|
function packetPath(agentRoot, packet) {
|
|
48
53
|
const month = packet.anchorTimestamp.slice(0, 7) || "unknown";
|
|
49
54
|
return path.join(contextPacketRoot(agentRoot, packet.sense), month, `${packet.packetId}.json`);
|
|
@@ -181,6 +186,127 @@ function readSenseContextLedger(agentRoot, sense) {
|
|
|
181
186
|
});
|
|
182
187
|
return rows;
|
|
183
188
|
}
|
|
189
|
+
function safeContextPacketLimit(limit) {
|
|
190
|
+
return Number.isInteger(limit) && typeof limit === "number" && limit >= 1 && limit <= 100 ? limit : 20;
|
|
191
|
+
}
|
|
192
|
+
function discoverContextPacketSenses(agentRoot) {
|
|
193
|
+
const root = contextPacketBaseRoot(agentRoot);
|
|
194
|
+
if (!fs.existsSync(root))
|
|
195
|
+
return [];
|
|
196
|
+
return fs.readdirSync(root)
|
|
197
|
+
.filter((entry) => {
|
|
198
|
+
try {
|
|
199
|
+
return fs.statSync(path.join(root, entry)).isDirectory();
|
|
200
|
+
}
|
|
201
|
+
catch {
|
|
202
|
+
return false;
|
|
203
|
+
}
|
|
204
|
+
})
|
|
205
|
+
.sort();
|
|
206
|
+
}
|
|
207
|
+
function summarizeLedgerRow(row) {
|
|
208
|
+
return {
|
|
209
|
+
packetId: row.packetId,
|
|
210
|
+
sense: row.sense,
|
|
211
|
+
agent: row.agent,
|
|
212
|
+
chatKeyHash: row.chatKeyHash,
|
|
213
|
+
anchorMessageGuid: row.anchorMessageGuid,
|
|
214
|
+
anchorTimestamp: row.anchorTimestamp,
|
|
215
|
+
createdAt: row.createdAt,
|
|
216
|
+
messageCount: row.messageCount,
|
|
217
|
+
sourceRefs: row.sourceRefs,
|
|
218
|
+
bodyHashes: row.bodyHashes,
|
|
219
|
+
rawBodyStored: row.rawBodyStored,
|
|
220
|
+
privacyClass: row.privacyClass,
|
|
221
|
+
omittedMessages: row.omittedMessages,
|
|
222
|
+
truncatedMessages: row.truncatedMessages,
|
|
223
|
+
};
|
|
224
|
+
}
|
|
225
|
+
function readAllContextPacketRows(agentRoot, sense) {
|
|
226
|
+
const senses = sense ? [sense] : discoverContextPacketSenses(agentRoot);
|
|
227
|
+
return senses.flatMap((entry) => readSenseContextLedger(agentRoot, entry));
|
|
228
|
+
}
|
|
229
|
+
function timestampSortValue(value) {
|
|
230
|
+
const parsed = Date.parse(value);
|
|
231
|
+
return Number.isFinite(parsed) ? parsed : 0;
|
|
232
|
+
}
|
|
233
|
+
function listSenseContextPacketSummaries(agentRoot, options = {}) {
|
|
234
|
+
const limit = safeContextPacketLimit(options.limit);
|
|
235
|
+
const rows = readAllContextPacketRows(agentRoot, options.sense)
|
|
236
|
+
.sort((left, right) => timestampSortValue(right.createdAt || right.anchorTimestamp) - timestampSortValue(left.createdAt || left.anchorTimestamp));
|
|
237
|
+
return {
|
|
238
|
+
totalCount: rows.length,
|
|
239
|
+
limit,
|
|
240
|
+
items: rows.slice(0, limit).map(summarizeLedgerRow),
|
|
241
|
+
};
|
|
242
|
+
}
|
|
243
|
+
function isSafeContextPacketId(packetId) {
|
|
244
|
+
return /^scp_[A-Za-z0-9_-]+$/.test(packetId);
|
|
245
|
+
}
|
|
246
|
+
function pathInsideContextPacketRoot(agentRoot, sense, filePath) {
|
|
247
|
+
const root = path.resolve(contextPacketRoot(agentRoot, sense));
|
|
248
|
+
const resolved = path.resolve(filePath);
|
|
249
|
+
return resolved === root || resolved.startsWith(`${root}${path.sep}`);
|
|
250
|
+
}
|
|
251
|
+
function redactPreview(value) {
|
|
252
|
+
return value
|
|
253
|
+
.replace(/\bpassword=[^\s]+/gi, "password=[redacted]")
|
|
254
|
+
.replace(/\b(token|api[_-]?key|secret)=[^\s]+/gi, "$1=[redacted]");
|
|
255
|
+
}
|
|
256
|
+
function viewMessage(message) {
|
|
257
|
+
const { chatGuid: _chatGuid, ...sourceRef } = message.sourceRef;
|
|
258
|
+
return {
|
|
259
|
+
timestamp: message.timestamp,
|
|
260
|
+
authorLabel: message.authorLabel,
|
|
261
|
+
bodyHash: message.bodyHash,
|
|
262
|
+
bodyPreview: redactPreview(message.bodyPreview),
|
|
263
|
+
sourceRef,
|
|
264
|
+
renderedSourceRef: message.renderedSourceRef,
|
|
265
|
+
};
|
|
266
|
+
}
|
|
267
|
+
function emitContextPacketReadWarning(packetId, reason) {
|
|
268
|
+
(0, runtime_1.emitNervesEvent)({
|
|
269
|
+
level: "warn",
|
|
270
|
+
component: "senses",
|
|
271
|
+
event: "senses.context_packet_read_error",
|
|
272
|
+
message: "failed to read sense context packet view",
|
|
273
|
+
meta: { packetId, reason },
|
|
274
|
+
});
|
|
275
|
+
}
|
|
276
|
+
function readSenseContextPacketView(agentRoot, packetId) {
|
|
277
|
+
if (!isSafeContextPacketId(packetId))
|
|
278
|
+
return null;
|
|
279
|
+
const row = readAllContextPacketRows(agentRoot).find((entry) => entry.packetId === packetId);
|
|
280
|
+
if (!row)
|
|
281
|
+
return null;
|
|
282
|
+
if (!pathInsideContextPacketRoot(agentRoot, row.sense, row.packetPath)) {
|
|
283
|
+
emitContextPacketReadWarning(packetId, "packet path escaped context-packet root");
|
|
284
|
+
return null;
|
|
285
|
+
}
|
|
286
|
+
if (!fs.existsSync(row.packetPath))
|
|
287
|
+
return null;
|
|
288
|
+
try {
|
|
289
|
+
const packet = JSON.parse(fs.readFileSync(row.packetPath, "utf-8"));
|
|
290
|
+
if (packet.packetId !== packetId || !Array.isArray(packet.messages))
|
|
291
|
+
return null;
|
|
292
|
+
return {
|
|
293
|
+
row: summarizeLedgerRow(row),
|
|
294
|
+
packet: {
|
|
295
|
+
packetId,
|
|
296
|
+
sense: typeof packet.sense === "string" ? packet.sense : row.sense,
|
|
297
|
+
agent: typeof packet.agent === "string" ? packet.agent : row.agent,
|
|
298
|
+
privacyClass: packet.privacyClass === "private-runtime" ? packet.privacyClass : "private-runtime",
|
|
299
|
+
messages: packet.messages.map((message) => viewMessage(message)),
|
|
300
|
+
omittedMessages: typeof packet.omittedMessages === "number" ? packet.omittedMessages : row.omittedMessages,
|
|
301
|
+
truncatedMessages: typeof packet.truncatedMessages === "number" ? packet.truncatedMessages : row.truncatedMessages,
|
|
302
|
+
},
|
|
303
|
+
};
|
|
304
|
+
}
|
|
305
|
+
catch (error) {
|
|
306
|
+
emitContextPacketReadWarning(packetId, error instanceof Error ? error.message : String(error));
|
|
307
|
+
return null;
|
|
308
|
+
}
|
|
309
|
+
}
|
|
184
310
|
function timestampMs(value) {
|
|
185
311
|
return Date.parse(value);
|
|
186
312
|
}
|
package/dist/senses/pipeline.js
CHANGED
|
@@ -369,6 +369,36 @@ let _lastSessionKey = null;
|
|
|
369
369
|
function runAgentOptionContextPacketIds(options) {
|
|
370
370
|
return Array.isArray(options.contextPacketIds) ? options.contextPacketIds : [];
|
|
371
371
|
}
|
|
372
|
+
function mergeRunAgentContextPacketIds(left, right) {
|
|
373
|
+
const merged = [
|
|
374
|
+
...(Array.isArray(left) ? left : []),
|
|
375
|
+
...(Array.isArray(right) ? right : []),
|
|
376
|
+
].filter((value) => typeof value === "string" && value.trim().length > 0);
|
|
377
|
+
return merged.length > 0 ? [...new Set(merged)] : undefined;
|
|
378
|
+
}
|
|
379
|
+
function mergePreparedRunAgentOptions(base, prepared) {
|
|
380
|
+
if (!prepared)
|
|
381
|
+
return base;
|
|
382
|
+
const contextPacketIds = mergeRunAgentContextPacketIds(base.contextPacketIds, prepared.contextPacketIds);
|
|
383
|
+
const { contextPacketIds: _baseContextPacketIds, ...baseOptions } = base;
|
|
384
|
+
const { contextPacketIds: _preparedContextPacketIds, ...preparedOptions } = prepared;
|
|
385
|
+
const merged = {
|
|
386
|
+
...baseOptions,
|
|
387
|
+
...preparedOptions,
|
|
388
|
+
...(contextPacketIds ? { contextPacketIds } : {}),
|
|
389
|
+
};
|
|
390
|
+
if (prepared.toolContext) {
|
|
391
|
+
const toolContext = {
|
|
392
|
+
...base.toolContext,
|
|
393
|
+
...prepared.toolContext,
|
|
394
|
+
};
|
|
395
|
+
merged.toolContext = {
|
|
396
|
+
...toolContext,
|
|
397
|
+
signin: toolContext.signin ?? (async () => undefined),
|
|
398
|
+
};
|
|
399
|
+
}
|
|
400
|
+
return merged;
|
|
401
|
+
}
|
|
372
402
|
function buildInboundRunLedgerInput(input) {
|
|
373
403
|
const target = {
|
|
374
404
|
channel: input.channel,
|
|
@@ -822,7 +852,7 @@ async function handleInboundTurn(input) {
|
|
|
822
852
|
const existingToolContext = input.runAgentOptions?.toolContext;
|
|
823
853
|
const currentUserMessage = existingToolContext?.currentUserMessage
|
|
824
854
|
?? latestUserAuthoredText(input.messages, input.continuityIngressTexts);
|
|
825
|
-
|
|
855
|
+
let runAgentOptions = {
|
|
826
856
|
...input.runAgentOptions,
|
|
827
857
|
...(orientationFrame ? { orientationFrame } : {}),
|
|
828
858
|
...(liveLatencyMode ? { skipKeptNotes: true } : {}),
|
|
@@ -856,6 +886,12 @@ async function handleInboundTurn(input) {
|
|
|
856
886
|
...(orientationFrame ? { orientationFrame } : {}),
|
|
857
887
|
},
|
|
858
888
|
};
|
|
889
|
+
runAgentOptions = mergePreparedRunAgentOptions(runAgentOptions, await input.prepareRunAgentOptions?.({
|
|
890
|
+
messages: sessionMessages,
|
|
891
|
+
currentUserMessages,
|
|
892
|
+
resolvedContext,
|
|
893
|
+
runAgentOptions,
|
|
894
|
+
}));
|
|
859
895
|
const runLedger = prepareInboundRunLedger({
|
|
860
896
|
channel: input.channel,
|
|
861
897
|
senseType: input.capabilities.senseType,
|