@letta-ai/letta-code 0.23.3 → 0.23.5
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/letta.js +997 -249
- package/package.json +1 -1
package/letta.js
CHANGED
|
@@ -3269,7 +3269,7 @@ var package_default;
|
|
|
3269
3269
|
var init_package = __esm(() => {
|
|
3270
3270
|
package_default = {
|
|
3271
3271
|
name: "@letta-ai/letta-code",
|
|
3272
|
-
version: "0.23.
|
|
3272
|
+
version: "0.23.5",
|
|
3273
3273
|
description: "Letta Code is a CLI tool for interacting with stateful Letta agents from the terminal.",
|
|
3274
3274
|
type: "module",
|
|
3275
3275
|
bin: {
|
|
@@ -8394,7 +8394,7 @@ var init_models2 = __esm(() => {
|
|
|
8394
8394
|
id: "opus",
|
|
8395
8395
|
handle: "anthropic/claude-opus-4-6",
|
|
8396
8396
|
label: "Opus 4.6",
|
|
8397
|
-
description: "Anthropic's best model (high reasoning)",
|
|
8397
|
+
description: "Anthropic's (legacy) best model (high reasoning)",
|
|
8398
8398
|
isFeatured: true,
|
|
8399
8399
|
updateArgs: {
|
|
8400
8400
|
context_window: 200000,
|
|
@@ -8458,6 +8458,88 @@ var init_models2 = __esm(() => {
|
|
|
8458
8458
|
parallel_tool_calls: true
|
|
8459
8459
|
}
|
|
8460
8460
|
},
|
|
8461
|
+
{
|
|
8462
|
+
id: "opus-4.7",
|
|
8463
|
+
handle: "anthropic/claude-opus-4-7",
|
|
8464
|
+
label: "Opus 4.7",
|
|
8465
|
+
description: "Anthropic's best model (med reasoning)",
|
|
8466
|
+
isFeatured: true,
|
|
8467
|
+
updateArgs: {
|
|
8468
|
+
context_window: 200000,
|
|
8469
|
+
max_output_tokens: 128000,
|
|
8470
|
+
reasoning_effort: "medium",
|
|
8471
|
+
enable_reasoner: true,
|
|
8472
|
+
max_reasoning_tokens: 12000,
|
|
8473
|
+
parallel_tool_calls: true
|
|
8474
|
+
}
|
|
8475
|
+
},
|
|
8476
|
+
{
|
|
8477
|
+
id: "opus-4.7-low",
|
|
8478
|
+
handle: "anthropic/claude-opus-4-7",
|
|
8479
|
+
label: "Opus 4.7",
|
|
8480
|
+
description: "Opus 4.7 (low reasoning)",
|
|
8481
|
+
updateArgs: {
|
|
8482
|
+
context_window: 200000,
|
|
8483
|
+
max_output_tokens: 128000,
|
|
8484
|
+
reasoning_effort: "low",
|
|
8485
|
+
enable_reasoner: true,
|
|
8486
|
+
max_reasoning_tokens: 4000,
|
|
8487
|
+
parallel_tool_calls: true
|
|
8488
|
+
}
|
|
8489
|
+
},
|
|
8490
|
+
{
|
|
8491
|
+
id: "opus-4.7-medium",
|
|
8492
|
+
handle: "anthropic/claude-opus-4-7",
|
|
8493
|
+
label: "Opus 4.7",
|
|
8494
|
+
description: "Opus 4.7 (med reasoning)",
|
|
8495
|
+
updateArgs: {
|
|
8496
|
+
context_window: 200000,
|
|
8497
|
+
max_output_tokens: 128000,
|
|
8498
|
+
reasoning_effort: "medium",
|
|
8499
|
+
enable_reasoner: true,
|
|
8500
|
+
max_reasoning_tokens: 12000,
|
|
8501
|
+
parallel_tool_calls: true
|
|
8502
|
+
}
|
|
8503
|
+
},
|
|
8504
|
+
{
|
|
8505
|
+
id: "opus-4.7-high",
|
|
8506
|
+
handle: "anthropic/claude-opus-4-7",
|
|
8507
|
+
label: "Opus 4.7",
|
|
8508
|
+
description: "Opus 4.7 (high reasoning)",
|
|
8509
|
+
updateArgs: {
|
|
8510
|
+
context_window: 200000,
|
|
8511
|
+
max_output_tokens: 128000,
|
|
8512
|
+
reasoning_effort: "high",
|
|
8513
|
+
enable_reasoner: true,
|
|
8514
|
+
parallel_tool_calls: true
|
|
8515
|
+
}
|
|
8516
|
+
},
|
|
8517
|
+
{
|
|
8518
|
+
id: "opus-4.7-xhigh",
|
|
8519
|
+
handle: "anthropic/claude-opus-4-7",
|
|
8520
|
+
label: "Opus 4.7",
|
|
8521
|
+
description: "Opus 4.7 (extra-high reasoning)",
|
|
8522
|
+
updateArgs: {
|
|
8523
|
+
context_window: 200000,
|
|
8524
|
+
max_output_tokens: 128000,
|
|
8525
|
+
reasoning_effort: "xhigh",
|
|
8526
|
+
enable_reasoner: true,
|
|
8527
|
+
parallel_tool_calls: true
|
|
8528
|
+
}
|
|
8529
|
+
},
|
|
8530
|
+
{
|
|
8531
|
+
id: "opus-4.7-max",
|
|
8532
|
+
handle: "anthropic/claude-opus-4-7",
|
|
8533
|
+
label: "Opus 4.7",
|
|
8534
|
+
description: "Opus 4.7 (max reasoning)",
|
|
8535
|
+
updateArgs: {
|
|
8536
|
+
context_window: 200000,
|
|
8537
|
+
max_output_tokens: 128000,
|
|
8538
|
+
reasoning_effort: "max",
|
|
8539
|
+
enable_reasoner: true,
|
|
8540
|
+
parallel_tool_calls: true
|
|
8541
|
+
}
|
|
8542
|
+
},
|
|
8461
8543
|
{
|
|
8462
8544
|
id: "opus-1m",
|
|
8463
8545
|
handle: "anthropic/claude-opus-4-6",
|
|
@@ -41245,6 +41327,18 @@ function normalizeSlackAttachmentLike(value) {
|
|
|
41245
41327
|
files
|
|
41246
41328
|
};
|
|
41247
41329
|
}
|
|
41330
|
+
function resolveSlackThreadMessageText(message) {
|
|
41331
|
+
const text = typeof message.text === "string" ? message.text.trim() : "";
|
|
41332
|
+
if (text) {
|
|
41333
|
+
return text;
|
|
41334
|
+
}
|
|
41335
|
+
const files = Array.isArray(message.files) ? message.files.map((entry) => normalizeSlackFileLike(entry)).filter((entry) => Boolean(entry)) : [];
|
|
41336
|
+
if (files.length === 0) {
|
|
41337
|
+
return "";
|
|
41338
|
+
}
|
|
41339
|
+
const fileNames = files.map((file) => file.name ?? "file").join(", ");
|
|
41340
|
+
return `[attached: ${fileNames}]`;
|
|
41341
|
+
}
|
|
41248
41342
|
function isAllowedSlackHostname(hostname3) {
|
|
41249
41343
|
const normalized = hostname3.trim().toLowerCase();
|
|
41250
41344
|
return ALLOWED_SLACK_HOST_SUFFIXES.some((suffix) => normalized === suffix || normalized.endsWith(`.${suffix}`));
|
|
@@ -41413,6 +41507,78 @@ async function resolveSlackInboundAttachments(params) {
|
|
|
41413
41507
|
}).catch(() => null)));
|
|
41414
41508
|
return resolved.filter((attachment) => Boolean(attachment));
|
|
41415
41509
|
}
|
|
41510
|
+
async function resolveSlackThreadStarter(params) {
|
|
41511
|
+
try {
|
|
41512
|
+
const response = await params.client.conversations.replies({
|
|
41513
|
+
channel: params.channelId,
|
|
41514
|
+
ts: params.threadTs,
|
|
41515
|
+
limit: 1,
|
|
41516
|
+
inclusive: true
|
|
41517
|
+
});
|
|
41518
|
+
const message = response.messages?.[0];
|
|
41519
|
+
if (!message) {
|
|
41520
|
+
return null;
|
|
41521
|
+
}
|
|
41522
|
+
const text = resolveSlackThreadMessageText(message);
|
|
41523
|
+
if (!text) {
|
|
41524
|
+
return null;
|
|
41525
|
+
}
|
|
41526
|
+
return {
|
|
41527
|
+
text,
|
|
41528
|
+
userId: isNonEmptyString(message.user) ? message.user : undefined,
|
|
41529
|
+
botId: isNonEmptyString(message.bot_id) ? message.bot_id : undefined,
|
|
41530
|
+
ts: isNonEmptyString(message.ts) ? message.ts : undefined
|
|
41531
|
+
};
|
|
41532
|
+
} catch {
|
|
41533
|
+
return null;
|
|
41534
|
+
}
|
|
41535
|
+
}
|
|
41536
|
+
async function resolveSlackThreadHistory(params) {
|
|
41537
|
+
const maxMessages = params.limit ?? 20;
|
|
41538
|
+
if (!Number.isFinite(maxMessages) || maxMessages <= 0) {
|
|
41539
|
+
return [];
|
|
41540
|
+
}
|
|
41541
|
+
const fetchLimit = 200;
|
|
41542
|
+
const retained = [];
|
|
41543
|
+
let cursor;
|
|
41544
|
+
try {
|
|
41545
|
+
do {
|
|
41546
|
+
const response = await params.client.conversations.replies({
|
|
41547
|
+
channel: params.channelId,
|
|
41548
|
+
ts: params.threadTs,
|
|
41549
|
+
limit: fetchLimit,
|
|
41550
|
+
inclusive: true,
|
|
41551
|
+
...cursor ? { cursor } : {}
|
|
41552
|
+
});
|
|
41553
|
+
for (const message of response.messages ?? []) {
|
|
41554
|
+
const text = resolveSlackThreadMessageText(message);
|
|
41555
|
+
if (!text) {
|
|
41556
|
+
continue;
|
|
41557
|
+
}
|
|
41558
|
+
if (params.currentMessageTs && message.ts === params.currentMessageTs) {
|
|
41559
|
+
continue;
|
|
41560
|
+
}
|
|
41561
|
+
if (message.ts === params.threadTs) {
|
|
41562
|
+
continue;
|
|
41563
|
+
}
|
|
41564
|
+
retained.push(message);
|
|
41565
|
+
if (retained.length > maxMessages) {
|
|
41566
|
+
retained.shift();
|
|
41567
|
+
}
|
|
41568
|
+
}
|
|
41569
|
+
const nextCursor = response.response_metadata?.next_cursor;
|
|
41570
|
+
cursor = typeof nextCursor === "string" && nextCursor.trim().length > 0 ? nextCursor.trim() : undefined;
|
|
41571
|
+
} while (cursor);
|
|
41572
|
+
return retained.map((message) => ({
|
|
41573
|
+
text: resolveSlackThreadMessageText(message),
|
|
41574
|
+
userId: isNonEmptyString(message.user) ? message.user : undefined,
|
|
41575
|
+
botId: isNonEmptyString(message.bot_id) ? message.bot_id : undefined,
|
|
41576
|
+
ts: isNonEmptyString(message.ts) ? message.ts : undefined
|
|
41577
|
+
}));
|
|
41578
|
+
} catch {
|
|
41579
|
+
return [];
|
|
41580
|
+
}
|
|
41581
|
+
}
|
|
41416
41582
|
var MAX_SLACK_ATTACHMENTS = 8, MAX_SLACK_ATTACHMENT_BYTES, ALLOWED_SLACK_HOST_SUFFIXES;
|
|
41417
41583
|
var init_media2 = __esm(() => {
|
|
41418
41584
|
init_config();
|
|
@@ -41428,6 +41594,9 @@ var init_media2 = __esm(() => {
|
|
|
41428
41594
|
async function loadSlackBoltModule() {
|
|
41429
41595
|
return loadChannelRuntimeModule("slack", "@slack/bolt");
|
|
41430
41596
|
}
|
|
41597
|
+
async function loadSlackWebApiModule() {
|
|
41598
|
+
return loadChannelRuntimeModule("slack", "@slack/web-api");
|
|
41599
|
+
}
|
|
41431
41600
|
async function ensureSlackRuntimeInstalled() {
|
|
41432
41601
|
return ensureChannelRuntimeInstalled("slack");
|
|
41433
41602
|
}
|
|
@@ -41457,6 +41626,22 @@ function resolveSlackAppConstructor(mod) {
|
|
|
41457
41626
|
}
|
|
41458
41627
|
return App2;
|
|
41459
41628
|
}
|
|
41629
|
+
function resolveSlackWebClientModule(value) {
|
|
41630
|
+
if (!value || typeof value !== "object") {
|
|
41631
|
+
return null;
|
|
41632
|
+
}
|
|
41633
|
+
const webClient = Reflect.get(value, "WebClient");
|
|
41634
|
+
return isConstructorFunction(webClient) ? webClient : null;
|
|
41635
|
+
}
|
|
41636
|
+
function resolveSlackWebClientConstructor(mod) {
|
|
41637
|
+
const defaultExport = mod && typeof mod === "object" ? Reflect.get(mod, "default") : undefined;
|
|
41638
|
+
const nestedDefault = defaultExport && typeof defaultExport === "object" ? Reflect.get(defaultExport, "default") : undefined;
|
|
41639
|
+
const WebClient = resolveSlackWebClientModule(mod) ?? resolveSlackWebClientModule(defaultExport) ?? resolveSlackWebClientModule(nestedDefault) ?? (isConstructorFunction(defaultExport) ? defaultExport : null);
|
|
41640
|
+
if (!WebClient) {
|
|
41641
|
+
throw new Error('Installed Slack runtime did not export constructor "WebClient".');
|
|
41642
|
+
}
|
|
41643
|
+
return WebClient;
|
|
41644
|
+
}
|
|
41460
41645
|
function isNonEmptyString2(value) {
|
|
41461
41646
|
return typeof value === "string" && value.length > 0;
|
|
41462
41647
|
}
|
|
@@ -41499,7 +41684,7 @@ function resolveUploadMimeType(filePath) {
|
|
|
41499
41684
|
return;
|
|
41500
41685
|
}
|
|
41501
41686
|
}
|
|
41502
|
-
async function uploadSlackFile(
|
|
41687
|
+
async function uploadSlackFile(slackClient, msg) {
|
|
41503
41688
|
if (!msg.mediaPath) {
|
|
41504
41689
|
throw new Error("mediaPath is required for Slack file uploads.");
|
|
41505
41690
|
}
|
|
@@ -41507,7 +41692,7 @@ async function uploadSlackFile(slackApp, msg) {
|
|
|
41507
41692
|
const uploadFileName = msg.fileName ?? basename4(msg.mediaPath);
|
|
41508
41693
|
const uploadTitle = msg.title ?? uploadFileName;
|
|
41509
41694
|
const uploadMimeType = resolveUploadMimeType(uploadFileName);
|
|
41510
|
-
const uploadUrlResp = await
|
|
41695
|
+
const uploadUrlResp = await slackClient.files.getUploadURLExternal({
|
|
41511
41696
|
filename: uploadFileName,
|
|
41512
41697
|
length: buffer.length
|
|
41513
41698
|
});
|
|
@@ -41522,7 +41707,7 @@ async function uploadSlackFile(slackApp, msg) {
|
|
|
41522
41707
|
if (!uploadResp.ok) {
|
|
41523
41708
|
throw new Error(`Failed to upload Slack file: HTTP ${uploadResp.status}`);
|
|
41524
41709
|
}
|
|
41525
|
-
const completeResp = await
|
|
41710
|
+
const completeResp = await slackClient.files.completeUploadExternal({
|
|
41526
41711
|
files: [{ id: uploadUrlResp.file_id, title: uploadTitle }],
|
|
41527
41712
|
channel_id: msg.chatId,
|
|
41528
41713
|
...msg.text.trim() ? { initial_comment: msg.text } : {},
|
|
@@ -41538,6 +41723,27 @@ function resolveSlackUserDisplayName(userInfo) {
|
|
|
41538
41723
|
const profile = asRecord2(user?.profile);
|
|
41539
41724
|
return firstNonEmptyString(profile?.display_name, profile?.real_name, user?.name);
|
|
41540
41725
|
}
|
|
41726
|
+
function truncateSlackThreadLabel(text, maxLength = 80) {
|
|
41727
|
+
const normalized = text.replace(/\s+/g, " ").trim();
|
|
41728
|
+
if (!normalized) {
|
|
41729
|
+
return null;
|
|
41730
|
+
}
|
|
41731
|
+
if (normalized.length <= maxLength) {
|
|
41732
|
+
return normalized;
|
|
41733
|
+
}
|
|
41734
|
+
return `${normalized.slice(0, maxLength - 1).trimEnd()}…`;
|
|
41735
|
+
}
|
|
41736
|
+
function buildSlackThreadLabel(msg, starterText) {
|
|
41737
|
+
if (msg.chatType !== "channel") {
|
|
41738
|
+
return;
|
|
41739
|
+
}
|
|
41740
|
+
const roomLabel = isNonEmptyString2(msg.chatLabel) && msg.chatLabel !== msg.chatId ? ` in ${msg.chatLabel}` : "";
|
|
41741
|
+
const preview = truncateSlackThreadLabel(starterText ?? msg.text);
|
|
41742
|
+
if (preview) {
|
|
41743
|
+
return `Slack thread${roomLabel}: ${preview}`;
|
|
41744
|
+
}
|
|
41745
|
+
return roomLabel ? `Slack thread${roomLabel}` : `Slack thread ${msg.chatId}`;
|
|
41746
|
+
}
|
|
41541
41747
|
async function resolveSlackAccountDisplayName(botToken, appToken) {
|
|
41542
41748
|
const bolt = await loadSlackBoltModule();
|
|
41543
41749
|
const App2 = resolveSlackAppConstructor(bolt);
|
|
@@ -41563,11 +41769,14 @@ async function resolveSlackAccountDisplayName(botToken, appToken) {
|
|
|
41563
41769
|
}
|
|
41564
41770
|
function createSlackAdapter(config) {
|
|
41565
41771
|
let app = null;
|
|
41772
|
+
let writeClient = null;
|
|
41566
41773
|
let running = false;
|
|
41567
41774
|
let botUserId = null;
|
|
41568
41775
|
const knownThreadIdsByMessageId = new Map;
|
|
41569
41776
|
const knownUserDisplayNames = new Map;
|
|
41570
41777
|
const seenIngressMessageKeys = new Map;
|
|
41778
|
+
const lifecycleStateByMessageKey = new Map;
|
|
41779
|
+
const lifecycleOperationByMessageKey = new Map;
|
|
41571
41780
|
function buildIngressMessageKey(channelId, messageId) {
|
|
41572
41781
|
if (!isNonEmptyString2(channelId) || !isNonEmptyString2(messageId)) {
|
|
41573
41782
|
return null;
|
|
@@ -41592,6 +41801,96 @@ function createSlackAdapter(config) {
|
|
|
41592
41801
|
}
|
|
41593
41802
|
}
|
|
41594
41803
|
}
|
|
41804
|
+
function getLifecycleMessageKey(source) {
|
|
41805
|
+
if (source.channel !== "slack" || !isNonEmptyString2(source.chatId) || !isNonEmptyString2(source.messageId)) {
|
|
41806
|
+
return null;
|
|
41807
|
+
}
|
|
41808
|
+
return `${source.chatId}:${source.messageId}`;
|
|
41809
|
+
}
|
|
41810
|
+
function pruneLifecycleState(now = Date.now()) {
|
|
41811
|
+
for (const [key, entry] of lifecycleStateByMessageKey) {
|
|
41812
|
+
if (entry.updatedAt + SLACK_LIFECYCLE_STATE_TTL_MS <= now) {
|
|
41813
|
+
lifecycleStateByMessageKey.delete(key);
|
|
41814
|
+
}
|
|
41815
|
+
}
|
|
41816
|
+
if (lifecycleStateByMessageKey.size <= SLACK_LIFECYCLE_STATE_MAX) {
|
|
41817
|
+
return;
|
|
41818
|
+
}
|
|
41819
|
+
const oldestEntries = Array.from(lifecycleStateByMessageKey.entries()).sort((a, b) => a[1].updatedAt - b[1].updatedAt);
|
|
41820
|
+
const overflowCount = lifecycleStateByMessageKey.size - SLACK_LIFECYCLE_STATE_MAX;
|
|
41821
|
+
for (let index = 0;index < overflowCount; index += 1) {
|
|
41822
|
+
const entry = oldestEntries[index];
|
|
41823
|
+
if (entry) {
|
|
41824
|
+
lifecycleStateByMessageKey.delete(entry[0]);
|
|
41825
|
+
}
|
|
41826
|
+
}
|
|
41827
|
+
}
|
|
41828
|
+
async function sendLifecycleReaction(source, emoji, removeReaction = false) {
|
|
41829
|
+
if (!isNonEmptyString2(source.messageId)) {
|
|
41830
|
+
return;
|
|
41831
|
+
}
|
|
41832
|
+
await ensureApp();
|
|
41833
|
+
const slackClient = await ensureWriteClient();
|
|
41834
|
+
if (removeReaction) {
|
|
41835
|
+
await slackClient.reactions.remove({
|
|
41836
|
+
channel: source.chatId,
|
|
41837
|
+
timestamp: source.messageId,
|
|
41838
|
+
name: emoji
|
|
41839
|
+
});
|
|
41840
|
+
return;
|
|
41841
|
+
}
|
|
41842
|
+
await slackClient.reactions.add({
|
|
41843
|
+
channel: source.chatId,
|
|
41844
|
+
timestamp: source.messageId,
|
|
41845
|
+
name: emoji
|
|
41846
|
+
});
|
|
41847
|
+
}
|
|
41848
|
+
function scheduleLifecycleTransition(source, nextState) {
|
|
41849
|
+
const key = getLifecycleMessageKey(source);
|
|
41850
|
+
if (!key) {
|
|
41851
|
+
return null;
|
|
41852
|
+
}
|
|
41853
|
+
const previous = lifecycleOperationByMessageKey.get(key) ?? Promise.resolve();
|
|
41854
|
+
const operation = previous.catch(() => {}).then(async () => {
|
|
41855
|
+
pruneLifecycleState();
|
|
41856
|
+
const currentState = lifecycleStateByMessageKey.get(key)?.state;
|
|
41857
|
+
if (currentState === nextState) {
|
|
41858
|
+
lifecycleStateByMessageKey.set(key, {
|
|
41859
|
+
state: nextState,
|
|
41860
|
+
updatedAt: Date.now()
|
|
41861
|
+
});
|
|
41862
|
+
return;
|
|
41863
|
+
}
|
|
41864
|
+
if (nextState === "queued") {
|
|
41865
|
+
if (!currentState) {
|
|
41866
|
+
await sendLifecycleReaction(source, "eyes");
|
|
41867
|
+
lifecycleStateByMessageKey.set(key, {
|
|
41868
|
+
state: nextState,
|
|
41869
|
+
updatedAt: Date.now()
|
|
41870
|
+
});
|
|
41871
|
+
}
|
|
41872
|
+
return;
|
|
41873
|
+
}
|
|
41874
|
+
if (currentState === "queued") {
|
|
41875
|
+
try {
|
|
41876
|
+
await sendLifecycleReaction(source, "eyes", true);
|
|
41877
|
+
} catch {}
|
|
41878
|
+
}
|
|
41879
|
+
await sendLifecycleReaction(source, nextState === "completed" ? "white_check_mark" : "x");
|
|
41880
|
+
lifecycleStateByMessageKey.set(key, {
|
|
41881
|
+
state: nextState,
|
|
41882
|
+
updatedAt: Date.now()
|
|
41883
|
+
});
|
|
41884
|
+
}).catch((error) => {
|
|
41885
|
+
console.warn(`[Slack] Failed to update lifecycle reaction for ${key}:`, error instanceof Error ? error.message : error);
|
|
41886
|
+
}).finally(() => {
|
|
41887
|
+
if (lifecycleOperationByMessageKey.get(key) === operation) {
|
|
41888
|
+
lifecycleOperationByMessageKey.delete(key);
|
|
41889
|
+
}
|
|
41890
|
+
});
|
|
41891
|
+
lifecycleOperationByMessageKey.set(key, operation);
|
|
41892
|
+
return operation;
|
|
41893
|
+
}
|
|
41595
41894
|
function markIngressMessageSeen(channelId, messageId) {
|
|
41596
41895
|
const key = buildIngressMessageKey(channelId, messageId);
|
|
41597
41896
|
if (!key) {
|
|
@@ -41815,6 +42114,19 @@ function createSlackAdapter(config) {
|
|
|
41815
42114
|
app = instance;
|
|
41816
42115
|
return instance;
|
|
41817
42116
|
}
|
|
42117
|
+
async function ensureWriteClient() {
|
|
42118
|
+
if (writeClient) {
|
|
42119
|
+
return writeClient;
|
|
42120
|
+
}
|
|
42121
|
+
const webApi = await loadSlackWebApiModule();
|
|
42122
|
+
const WebClient = resolveSlackWebClientConstructor(webApi);
|
|
42123
|
+
writeClient = new WebClient(config.botToken, {
|
|
42124
|
+
retryConfig: {
|
|
42125
|
+
retries: 0
|
|
42126
|
+
}
|
|
42127
|
+
});
|
|
42128
|
+
return writeClient;
|
|
42129
|
+
}
|
|
41818
42130
|
const adapter = {
|
|
41819
42131
|
id: `slack:${config.accountId}`,
|
|
41820
42132
|
channelId: "slack",
|
|
@@ -41838,15 +42150,33 @@ function createSlackAdapter(config) {
|
|
|
41838
42150
|
await app.stop();
|
|
41839
42151
|
running = false;
|
|
41840
42152
|
app = null;
|
|
42153
|
+
writeClient = null;
|
|
41841
42154
|
botUserId = null;
|
|
41842
42155
|
seenIngressMessageKeys.clear();
|
|
42156
|
+
lifecycleStateByMessageKey.clear();
|
|
42157
|
+
lifecycleOperationByMessageKey.clear();
|
|
41843
42158
|
console.log("[Slack] App stopped");
|
|
41844
42159
|
},
|
|
41845
42160
|
isRunning() {
|
|
41846
42161
|
return running;
|
|
41847
42162
|
},
|
|
42163
|
+
async handleTurnLifecycleEvent(event) {
|
|
42164
|
+
if (!running) {
|
|
42165
|
+
return;
|
|
42166
|
+
}
|
|
42167
|
+
if (event.type === "queued") {
|
|
42168
|
+
await scheduleLifecycleTransition(event.source, "queued");
|
|
42169
|
+
return;
|
|
42170
|
+
}
|
|
42171
|
+
if (event.type === "processing") {
|
|
42172
|
+
return;
|
|
42173
|
+
}
|
|
42174
|
+
const nextState = event.outcome === "completed" ? "completed" : event.outcome === "cancelled" ? "cancelled" : "error";
|
|
42175
|
+
await Promise.all(event.sources.map((source) => scheduleLifecycleTransition(source, nextState)));
|
|
42176
|
+
},
|
|
41848
42177
|
async sendMessage(msg) {
|
|
41849
|
-
|
|
42178
|
+
await ensureApp();
|
|
42179
|
+
const slackClient = await ensureWriteClient();
|
|
41850
42180
|
if (msg.reaction) {
|
|
41851
42181
|
const targetMessageId = msg.targetMessageId ?? msg.replyToMessageId;
|
|
41852
42182
|
if (!targetMessageId) {
|
|
@@ -41857,13 +42187,13 @@ function createSlackAdapter(config) {
|
|
|
41857
42187
|
throw new Error("Slack reaction emoji cannot be empty.");
|
|
41858
42188
|
}
|
|
41859
42189
|
if (msg.removeReaction) {
|
|
41860
|
-
await
|
|
42190
|
+
await slackClient.reactions.remove({
|
|
41861
42191
|
channel: msg.chatId,
|
|
41862
42192
|
timestamp: targetMessageId,
|
|
41863
42193
|
name: emoji
|
|
41864
42194
|
});
|
|
41865
42195
|
} else {
|
|
41866
|
-
await
|
|
42196
|
+
await slackClient.reactions.add({
|
|
41867
42197
|
channel: msg.chatId,
|
|
41868
42198
|
timestamp: targetMessageId,
|
|
41869
42199
|
name: emoji
|
|
@@ -41872,9 +42202,9 @@ function createSlackAdapter(config) {
|
|
|
41872
42202
|
return { messageId: targetMessageId };
|
|
41873
42203
|
}
|
|
41874
42204
|
if (msg.mediaPath) {
|
|
41875
|
-
return uploadSlackFile(
|
|
42205
|
+
return uploadSlackFile(slackClient, msg);
|
|
41876
42206
|
}
|
|
41877
|
-
const response = await
|
|
42207
|
+
const response = await slackClient.chat.postMessage({
|
|
41878
42208
|
channel: msg.chatId,
|
|
41879
42209
|
text: msg.text,
|
|
41880
42210
|
...msg.threadId ?? msg.replyToMessageId ? { thread_ts: msg.threadId ?? msg.replyToMessageId } : {}
|
|
@@ -41883,22 +42213,88 @@ function createSlackAdapter(config) {
|
|
|
41883
42213
|
return { messageId: response.ts ?? "" };
|
|
41884
42214
|
},
|
|
41885
42215
|
async sendDirectReply(chatId, text, options) {
|
|
41886
|
-
|
|
41887
|
-
const
|
|
42216
|
+
await ensureApp();
|
|
42217
|
+
const slackClient = await ensureWriteClient();
|
|
42218
|
+
const response = await slackClient.chat.postMessage({
|
|
41888
42219
|
channel: chatId,
|
|
41889
42220
|
text,
|
|
41890
42221
|
...options?.replyToMessageId ? { thread_ts: options.replyToMessageId } : {}
|
|
41891
42222
|
});
|
|
41892
42223
|
rememberMessageThread(response.ts, options?.replyToMessageId ?? response.ts ?? null);
|
|
41893
42224
|
},
|
|
42225
|
+
async prepareInboundMessage(msg, options) {
|
|
42226
|
+
if (!options?.isFirstRouteTurn || msg.channel !== "slack" || msg.chatType !== "channel" || !isNonEmptyString2(msg.threadId) || !isNonEmptyString2(msg.messageId) || msg.threadId === msg.messageId) {
|
|
42227
|
+
return msg;
|
|
42228
|
+
}
|
|
42229
|
+
const slackApp = await ensureApp();
|
|
42230
|
+
const starter = await resolveSlackThreadStarter({
|
|
42231
|
+
channelId: msg.chatId,
|
|
42232
|
+
threadTs: msg.threadId,
|
|
42233
|
+
client: slackApp.client
|
|
42234
|
+
});
|
|
42235
|
+
const history = await resolveSlackThreadHistory({
|
|
42236
|
+
channelId: msg.chatId,
|
|
42237
|
+
threadTs: msg.threadId,
|
|
42238
|
+
client: slackApp.client,
|
|
42239
|
+
currentMessageTs: msg.messageId,
|
|
42240
|
+
limit: INITIAL_SLACK_THREAD_HISTORY_LIMIT
|
|
42241
|
+
});
|
|
42242
|
+
if (!starter && history.length === 0) {
|
|
42243
|
+
return msg;
|
|
42244
|
+
}
|
|
42245
|
+
const uniqueUserIds = new Set;
|
|
42246
|
+
if (isNonEmptyString2(starter?.userId)) {
|
|
42247
|
+
uniqueUserIds.add(starter.userId);
|
|
42248
|
+
}
|
|
42249
|
+
for (const entry of history) {
|
|
42250
|
+
if (isNonEmptyString2(entry.userId)) {
|
|
42251
|
+
uniqueUserIds.add(entry.userId);
|
|
42252
|
+
}
|
|
42253
|
+
}
|
|
42254
|
+
await Promise.all(Array.from(uniqueUserIds).map(async (userId) => {
|
|
42255
|
+
await resolveUserName(slackApp, userId);
|
|
42256
|
+
}));
|
|
42257
|
+
const resolveThreadSenderName = (userId, botId) => {
|
|
42258
|
+
if (isNonEmptyString2(userId)) {
|
|
42259
|
+
return knownUserDisplayNames.get(userId) ?? userId;
|
|
42260
|
+
}
|
|
42261
|
+
if (isNonEmptyString2(botId)) {
|
|
42262
|
+
return `Bot (${botId})`;
|
|
42263
|
+
}
|
|
42264
|
+
return;
|
|
42265
|
+
};
|
|
42266
|
+
return {
|
|
42267
|
+
...msg,
|
|
42268
|
+
threadContext: {
|
|
42269
|
+
label: buildSlackThreadLabel(msg, starter?.text),
|
|
42270
|
+
...starter ? {
|
|
42271
|
+
starter: {
|
|
42272
|
+
messageId: starter.ts,
|
|
42273
|
+
senderId: starter.userId ?? starter.botId,
|
|
42274
|
+
senderName: resolveThreadSenderName(starter.userId, starter.botId),
|
|
42275
|
+
text: starter.text
|
|
42276
|
+
}
|
|
42277
|
+
} : {},
|
|
42278
|
+
...history.length > 0 ? {
|
|
42279
|
+
history: history.map((entry) => ({
|
|
42280
|
+
messageId: entry.ts,
|
|
42281
|
+
senderId: entry.userId ?? entry.botId,
|
|
42282
|
+
senderName: resolveThreadSenderName(entry.userId, entry.botId),
|
|
42283
|
+
text: entry.text
|
|
42284
|
+
}))
|
|
42285
|
+
} : {}
|
|
42286
|
+
}
|
|
42287
|
+
};
|
|
42288
|
+
},
|
|
41894
42289
|
onMessage: undefined
|
|
41895
42290
|
};
|
|
41896
42291
|
return adapter;
|
|
41897
42292
|
}
|
|
41898
|
-
var SLACK_INGRESS_DEDUPE_TTL_MS = 60000, SLACK_INGRESS_DEDUPE_MAX = 2000;
|
|
42293
|
+
var INITIAL_SLACK_THREAD_HISTORY_LIMIT = 20, SLACK_INGRESS_DEDUPE_TTL_MS = 60000, SLACK_INGRESS_DEDUPE_MAX = 2000, SLACK_LIFECYCLE_STATE_TTL_MS, SLACK_LIFECYCLE_STATE_MAX = 2000;
|
|
41899
42294
|
var init_adapter2 = __esm(() => {
|
|
41900
42295
|
init_media2();
|
|
41901
42296
|
init_runtime2();
|
|
42297
|
+
SLACK_LIFECYCLE_STATE_TTL_MS = 6 * 60 * 60 * 1000;
|
|
41902
42298
|
});
|
|
41903
42299
|
|
|
41904
42300
|
// src/channels/slack/messageActions.ts
|
|
@@ -42081,8 +42477,8 @@ var init_plugin2 = __esm(() => {
|
|
|
42081
42477
|
metadata: {
|
|
42082
42478
|
id: "slack",
|
|
42083
42479
|
displayName: "Slack",
|
|
42084
|
-
runtimePackages: ["@slack/bolt@4.7.0"],
|
|
42085
|
-
runtimeModules: ["@slack/bolt"]
|
|
42480
|
+
runtimePackages: ["@slack/bolt@4.7.0", "@slack/web-api@7.15.0"],
|
|
42481
|
+
runtimeModules: ["@slack/bolt", "@slack/web-api"]
|
|
42086
42482
|
},
|
|
42087
42483
|
createAdapter(account) {
|
|
42088
42484
|
return createSlackAdapter(account);
|
|
@@ -42138,8 +42534,8 @@ var init_pluginRegistry = __esm(() => {
|
|
|
42138
42534
|
metadata: {
|
|
42139
42535
|
id: "slack",
|
|
42140
42536
|
displayName: "Slack",
|
|
42141
|
-
runtimePackages: ["@slack/bolt@4.7.0"],
|
|
42142
|
-
runtimeModules: ["@slack/bolt"]
|
|
42537
|
+
runtimePackages: ["@slack/bolt@4.7.0", "@slack/web-api@7.15.0"],
|
|
42538
|
+
runtimeModules: ["@slack/bolt", "@slack/web-api"]
|
|
42143
42539
|
},
|
|
42144
42540
|
load: async () => {
|
|
42145
42541
|
const { slackChannelPlugin: slackChannelPlugin2 } = await Promise.resolve().then(() => (init_plugin2(), exports_plugin2));
|
|
@@ -42724,6 +43120,47 @@ function buildReactionXml(msg) {
|
|
|
42724
43120
|
}
|
|
42725
43121
|
return `<reaction ${attrs.join(" ")} />`;
|
|
42726
43122
|
}
|
|
43123
|
+
function buildThreadContextEntryXml(tagName, entry) {
|
|
43124
|
+
const attrs = [];
|
|
43125
|
+
if (entry.senderId) {
|
|
43126
|
+
attrs.push(`sender_id="${escapeXmlAttribute(entry.senderId)}"`);
|
|
43127
|
+
}
|
|
43128
|
+
if (entry.senderName) {
|
|
43129
|
+
attrs.push(`sender_name="${escapeXmlAttribute(entry.senderName)}"`);
|
|
43130
|
+
}
|
|
43131
|
+
if (entry.messageId) {
|
|
43132
|
+
attrs.push(`message_id="${escapeXmlAttribute(entry.messageId)}"`);
|
|
43133
|
+
}
|
|
43134
|
+
const attrString = attrs.length > 0 ? ` ${attrs.join(" ")}` : "";
|
|
43135
|
+
return `<${tagName}${attrString}>
|
|
43136
|
+
${escapeXmlText(entry.text)}
|
|
43137
|
+
</${tagName}>`;
|
|
43138
|
+
}
|
|
43139
|
+
function buildThreadContextXml(msg) {
|
|
43140
|
+
const threadContext = msg.threadContext;
|
|
43141
|
+
if (!threadContext) {
|
|
43142
|
+
return null;
|
|
43143
|
+
}
|
|
43144
|
+
const parts = [];
|
|
43145
|
+
if (threadContext.starter) {
|
|
43146
|
+
parts.push(buildThreadContextEntryXml("thread-starter", threadContext.starter));
|
|
43147
|
+
}
|
|
43148
|
+
const historyEntries = threadContext.history ?? [];
|
|
43149
|
+
if (historyEntries.length > 0) {
|
|
43150
|
+
parts.push([
|
|
43151
|
+
"<thread-history>",
|
|
43152
|
+
...historyEntries.map((entry) => buildThreadContextEntryXml("thread-message", entry)),
|
|
43153
|
+
"</thread-history>"
|
|
43154
|
+
].join(`
|
|
43155
|
+
`));
|
|
43156
|
+
}
|
|
43157
|
+
if (parts.length === 0) {
|
|
43158
|
+
return null;
|
|
43159
|
+
}
|
|
43160
|
+
const attrs = threadContext.label ? ` label="${escapeXmlAttribute(threadContext.label)}"` : "";
|
|
43161
|
+
return [`<thread-context${attrs}>`, ...parts, "</thread-context>"].join(`
|
|
43162
|
+
`);
|
|
43163
|
+
}
|
|
42727
43164
|
function buildChannelNotificationXml(msg) {
|
|
42728
43165
|
const attrs = [
|
|
42729
43166
|
`source="${escapeXmlAttribute(msg.channel)}"`,
|
|
@@ -42742,8 +43179,9 @@ function buildChannelNotificationXml(msg) {
|
|
|
42742
43179
|
const attrString = attrs.join(" ");
|
|
42743
43180
|
const escapedText = msg.text ? escapeXmlText(msg.text) : "";
|
|
42744
43181
|
const reactionXml = buildReactionXml(msg);
|
|
43182
|
+
const threadContextXml = buildThreadContextXml(msg);
|
|
42745
43183
|
const attachmentXml = (msg.attachments ?? []).map(buildAttachmentXml);
|
|
42746
|
-
const body = [reactionXml, ...attachmentXml, escapedText].filter(Boolean).join(`
|
|
43184
|
+
const body = [threadContextXml, reactionXml, ...attachmentXml, escapedText].filter(Boolean).join(`
|
|
42747
43185
|
`);
|
|
42748
43186
|
return `<channel-notification ${attrString}>
|
|
42749
43187
|
${body}
|
|
@@ -42828,6 +43266,18 @@ function buildSlackConversationSummary(msg) {
|
|
|
42828
43266
|
}
|
|
42829
43267
|
return `[Slack] Thread${channelLabel || ` ${msg.chatId}`}`;
|
|
42830
43268
|
}
|
|
43269
|
+
function buildChannelTurnSource(route, msg) {
|
|
43270
|
+
return {
|
|
43271
|
+
channel: msg.channel,
|
|
43272
|
+
accountId: msg.accountId,
|
|
43273
|
+
chatId: msg.chatId,
|
|
43274
|
+
chatType: msg.chatType,
|
|
43275
|
+
messageId: msg.messageId,
|
|
43276
|
+
threadId: msg.threadId,
|
|
43277
|
+
agentId: route.agentId,
|
|
43278
|
+
conversationId: route.conversationId
|
|
43279
|
+
};
|
|
43280
|
+
}
|
|
42831
43281
|
function getChannelRegistry() {
|
|
42832
43282
|
return instance;
|
|
42833
43283
|
}
|
|
@@ -42867,6 +43317,51 @@ class ChannelRegistry {
|
|
|
42867
43317
|
getActiveChannelIds() {
|
|
42868
43318
|
return Array.from(this.adapters.values()).filter((adapter) => adapter.isRunning()).map((adapter) => adapter.channelId ?? adapter.id);
|
|
42869
43319
|
}
|
|
43320
|
+
async dispatchTurnLifecycleEvent(event) {
|
|
43321
|
+
const groups = new Map;
|
|
43322
|
+
const sources = event.type === "queued" ? [event.source] : event.sources;
|
|
43323
|
+
for (const source of sources) {
|
|
43324
|
+
const adapter = this.getAdapter(source.channel, source.accountId ?? LEGACY_CHANNEL_ACCOUNT_ID);
|
|
43325
|
+
if (!adapter?.handleTurnLifecycleEvent) {
|
|
43326
|
+
continue;
|
|
43327
|
+
}
|
|
43328
|
+
const groupKey = this.getAdapterKey(source.channel, source.accountId ?? LEGACY_CHANNEL_ACCOUNT_ID);
|
|
43329
|
+
const existing = groups.get(groupKey);
|
|
43330
|
+
if (existing) {
|
|
43331
|
+
existing.sources.push(source);
|
|
43332
|
+
continue;
|
|
43333
|
+
}
|
|
43334
|
+
groups.set(groupKey, {
|
|
43335
|
+
adapter,
|
|
43336
|
+
sources: [source]
|
|
43337
|
+
});
|
|
43338
|
+
}
|
|
43339
|
+
for (const { adapter, sources: groupedSources } of groups.values()) {
|
|
43340
|
+
const handleTurnLifecycleEvent = adapter.handleTurnLifecycleEvent;
|
|
43341
|
+
if (!handleTurnLifecycleEvent) {
|
|
43342
|
+
continue;
|
|
43343
|
+
}
|
|
43344
|
+
try {
|
|
43345
|
+
if (event.type === "queued") {
|
|
43346
|
+
const [firstSource] = groupedSources;
|
|
43347
|
+
if (!firstSource) {
|
|
43348
|
+
continue;
|
|
43349
|
+
}
|
|
43350
|
+
await handleTurnLifecycleEvent({
|
|
43351
|
+
type: "queued",
|
|
43352
|
+
source: firstSource
|
|
43353
|
+
});
|
|
43354
|
+
continue;
|
|
43355
|
+
}
|
|
43356
|
+
await handleTurnLifecycleEvent({
|
|
43357
|
+
...event,
|
|
43358
|
+
sources: groupedSources
|
|
43359
|
+
});
|
|
43360
|
+
} catch (error) {
|
|
43361
|
+
console.error(`[Channels] Failed to handle ${event.type} lifecycle event for ${adapter.channelId ?? adapter.id}/${adapter.accountId ?? LEGACY_CHANNEL_ACCOUNT_ID}:`, error instanceof Error ? error.message : error);
|
|
43362
|
+
}
|
|
43363
|
+
}
|
|
43364
|
+
}
|
|
42870
43365
|
setMessageHandler(handler) {
|
|
42871
43366
|
this.messageHandler = handler;
|
|
42872
43367
|
}
|
|
@@ -42985,11 +43480,20 @@ class ChannelRegistry {
|
|
|
42985
43480
|
if (!config)
|
|
42986
43481
|
return;
|
|
42987
43482
|
if (msg.channel === "slack" && config.channel === "slack") {
|
|
42988
|
-
const
|
|
42989
|
-
if (!
|
|
43483
|
+
const slackResult = await this.ensureSlackRoute(adapter, msg, config);
|
|
43484
|
+
if (!slackResult) {
|
|
42990
43485
|
return;
|
|
42991
43486
|
}
|
|
42992
|
-
|
|
43487
|
+
const preparedMessage = adapter.prepareInboundMessage ? await adapter.prepareInboundMessage(msg, {
|
|
43488
|
+
isFirstRouteTurn: slackResult.isFirstRouteTurn
|
|
43489
|
+
}) : msg;
|
|
43490
|
+
this.deliverOrBuffer({
|
|
43491
|
+
route: slackResult.route,
|
|
43492
|
+
content: formatChannelNotification(preparedMessage),
|
|
43493
|
+
turnSources: [
|
|
43494
|
+
buildChannelTurnSource(slackResult.route, preparedMessage)
|
|
43495
|
+
]
|
|
43496
|
+
});
|
|
42993
43497
|
return;
|
|
42994
43498
|
}
|
|
42995
43499
|
if (config.dmPolicy === "allowlist") {
|
|
@@ -43021,7 +43525,11 @@ class ChannelRegistry {
|
|
|
43021
43525
|
return;
|
|
43022
43526
|
}
|
|
43023
43527
|
const content = formatChannelNotification(msg);
|
|
43024
|
-
this.deliverOrBuffer(
|
|
43528
|
+
this.deliverOrBuffer({
|
|
43529
|
+
route,
|
|
43530
|
+
content,
|
|
43531
|
+
turnSources: [buildChannelTurnSource(route, msg)]
|
|
43532
|
+
});
|
|
43025
43533
|
}
|
|
43026
43534
|
async createConversationForAgent(agentId, summary) {
|
|
43027
43535
|
const client = await getClient();
|
|
@@ -43071,7 +43579,10 @@ class ChannelRegistry {
|
|
|
43071
43579
|
route = getRoute(msg.channel, msg.chatId, accountId, routeThreadId);
|
|
43072
43580
|
}
|
|
43073
43581
|
if (route) {
|
|
43074
|
-
return
|
|
43582
|
+
return {
|
|
43583
|
+
route,
|
|
43584
|
+
isFirstRouteTurn: false
|
|
43585
|
+
};
|
|
43075
43586
|
}
|
|
43076
43587
|
if (msg.chatType === "channel" && !msg.isMention) {
|
|
43077
43588
|
return null;
|
|
@@ -43092,14 +43603,17 @@ class ChannelRegistry {
|
|
|
43092
43603
|
type: "targets_updated",
|
|
43093
43604
|
channelId: msg.channel
|
|
43094
43605
|
});
|
|
43095
|
-
return
|
|
43606
|
+
return {
|
|
43607
|
+
route: await this.createSlackRoute(config, msg),
|
|
43608
|
+
isFirstRouteTurn: true
|
|
43609
|
+
};
|
|
43096
43610
|
}
|
|
43097
|
-
deliverOrBuffer(
|
|
43611
|
+
deliverOrBuffer(delivery) {
|
|
43098
43612
|
if (this.isReady()) {
|
|
43099
|
-
this.messageHandler?.(
|
|
43613
|
+
this.messageHandler?.(delivery);
|
|
43100
43614
|
return;
|
|
43101
43615
|
}
|
|
43102
|
-
this.buffer.push(
|
|
43616
|
+
this.buffer.push(delivery);
|
|
43103
43617
|
}
|
|
43104
43618
|
flushBuffer() {
|
|
43105
43619
|
if (!this.messageHandler)
|
|
@@ -43107,7 +43621,7 @@ class ChannelRegistry {
|
|
|
43107
43621
|
while (this.buffer.length > 0) {
|
|
43108
43622
|
const item = this.buffer.shift();
|
|
43109
43623
|
if (item) {
|
|
43110
|
-
this.messageHandler(item
|
|
43624
|
+
this.messageHandler(item);
|
|
43111
43625
|
}
|
|
43112
43626
|
}
|
|
43113
43627
|
}
|
|
@@ -43512,15 +44026,20 @@ No external channel adapters are currently running.`;
|
|
|
43512
44026
|
|
|
43513
44027
|
Currently active channels: ${channelList}. Available actions across the active channels: ${actionList}. The JSON schema reflects the currently active channel plugins.`;
|
|
43514
44028
|
}
|
|
43515
|
-
async function resolveMessageChannelToolDiscovery() {
|
|
43516
|
-
const
|
|
44029
|
+
async function resolveMessageChannelToolDiscovery(scope) {
|
|
44030
|
+
const scopedChannels = scope?.channels ?? [];
|
|
44031
|
+
const discoveryTargets = scopedChannels.length > 0 ? scopedChannels : getActiveChannelIds().map((channelId) => ({
|
|
44032
|
+
channelId,
|
|
44033
|
+
accountId: null
|
|
44034
|
+
}));
|
|
44035
|
+
const activeChannels = Array.from(new Set(discoveryTargets.map(({ channelId }) => channelId)));
|
|
43517
44036
|
const actions = new Set(["send"]);
|
|
43518
44037
|
const schemaContributions = [];
|
|
43519
|
-
for (const channelId of
|
|
44038
|
+
for (const { channelId, accountId } of discoveryTargets) {
|
|
43520
44039
|
try {
|
|
43521
44040
|
const plugin = await loadChannelPlugin(channelId);
|
|
43522
44041
|
const discovery = plugin.messageActions?.describeMessageTool({
|
|
43523
|
-
accountId: null
|
|
44042
|
+
accountId: accountId ?? null
|
|
43524
44043
|
});
|
|
43525
44044
|
for (const action of collectDiscoveryActions(discovery)) {
|
|
43526
44045
|
actions.add(action);
|
|
@@ -43536,16 +44055,18 @@ async function resolveMessageChannelToolDiscovery() {
|
|
|
43536
44055
|
schemaContributions
|
|
43537
44056
|
};
|
|
43538
44057
|
}
|
|
43539
|
-
async function buildDynamicMessageChannelToolDefinition(baseDescription, baseSchema) {
|
|
43540
|
-
const discovery = await resolveMessageChannelToolDiscovery();
|
|
44058
|
+
async function buildDynamicMessageChannelToolDefinition(baseDescription, baseSchema, scope) {
|
|
44059
|
+
const discovery = await resolveMessageChannelToolDiscovery(scope);
|
|
43541
44060
|
const resolved = {
|
|
43542
44061
|
description: buildDynamicMessageChannelDescriptionFromDiscovery(baseDescription, discovery),
|
|
43543
44062
|
schema: buildDynamicMessageChannelSchemaFromDiscovery(baseSchema, discovery)
|
|
43544
44063
|
};
|
|
43545
|
-
|
|
43546
|
-
|
|
43547
|
-
|
|
43548
|
-
|
|
44064
|
+
if (!scope || scope.channels.length === 0) {
|
|
44065
|
+
cachedDynamicMessageChannelTool = {
|
|
44066
|
+
description: resolved.description,
|
|
44067
|
+
schema: structuredClone(resolved.schema)
|
|
44068
|
+
};
|
|
44069
|
+
}
|
|
43549
44070
|
return resolved;
|
|
43550
44071
|
}
|
|
43551
44072
|
function getCachedDynamicMessageChannelToolDefinition() {
|
|
@@ -45239,7 +45760,7 @@ function getPreferredAgentModelHandle(agent) {
|
|
|
45239
45760
|
}
|
|
45240
45761
|
return buildModelHandleFromLlmConfig(agent.llm_config);
|
|
45241
45762
|
}
|
|
45242
|
-
function getToolNamesForToolset(toolsetName) {
|
|
45763
|
+
function getToolNamesForToolset(toolsetName, channelToolScope) {
|
|
45243
45764
|
let tools;
|
|
45244
45765
|
switch (toolsetName) {
|
|
45245
45766
|
case "codex":
|
|
@@ -45260,7 +45781,8 @@ function getToolNamesForToolset(toolsetName) {
|
|
|
45260
45781
|
tools = [...ANTHROPIC_DEFAULT_TOOLS];
|
|
45261
45782
|
break;
|
|
45262
45783
|
}
|
|
45263
|
-
|
|
45784
|
+
const hasScopedChannelTool = channelToolScope !== undefined ? (channelToolScope?.channels.length ?? 0) > 0 : (getChannelRegistry()?.getActiveChannelIds().length ?? 0) > 0;
|
|
45785
|
+
if (hasScopedChannelTool && !tools.includes("MessageChannel")) {
|
|
45264
45786
|
tools.push("MessageChannel");
|
|
45265
45787
|
}
|
|
45266
45788
|
return tools;
|
|
@@ -45271,14 +45793,16 @@ async function prepareToolExecutionContextForResolvedTarget(params) {
|
|
|
45271
45793
|
toolsetPreference,
|
|
45272
45794
|
exclude,
|
|
45273
45795
|
workingDirectory,
|
|
45274
|
-
permissionModeState
|
|
45796
|
+
permissionModeState,
|
|
45797
|
+
channelToolScope
|
|
45275
45798
|
} = params;
|
|
45276
45799
|
const effectiveModel = modelIdentifier && modelIdentifier.length > 0 ? resolveModel2(modelIdentifier) ?? modelIdentifier : null;
|
|
45277
45800
|
if (toolsetPreference === "auto") {
|
|
45278
45801
|
const preparedToolContext2 = await prepareToolExecutionContextForModel(effectiveModel ?? undefined, {
|
|
45279
45802
|
exclude,
|
|
45280
45803
|
workingDirectory,
|
|
45281
|
-
permissionModeState
|
|
45804
|
+
permissionModeState,
|
|
45805
|
+
channelToolScope
|
|
45282
45806
|
});
|
|
45283
45807
|
return {
|
|
45284
45808
|
preparedToolContext: preparedToolContext2,
|
|
@@ -45287,9 +45811,10 @@ async function prepareToolExecutionContextForResolvedTarget(params) {
|
|
|
45287
45811
|
effectiveModel
|
|
45288
45812
|
};
|
|
45289
45813
|
}
|
|
45290
|
-
const preparedToolContext = await prepareToolExecutionContextForSpecificTools(getToolNamesForToolset(toolsetPreference).filter((toolName) => exclude ? !exclude.includes(toolName) : true), {
|
|
45814
|
+
const preparedToolContext = await prepareToolExecutionContextForSpecificTools(getToolNamesForToolset(toolsetPreference, channelToolScope).filter((toolName) => exclude ? !exclude.includes(toolName) : true), {
|
|
45291
45815
|
workingDirectory,
|
|
45292
|
-
permissionModeState
|
|
45816
|
+
permissionModeState,
|
|
45817
|
+
channelToolScope
|
|
45293
45818
|
});
|
|
45294
45819
|
return {
|
|
45295
45820
|
preparedToolContext,
|
|
@@ -45298,6 +45823,36 @@ async function prepareToolExecutionContextForResolvedTarget(params) {
|
|
|
45298
45823
|
effectiveModel
|
|
45299
45824
|
};
|
|
45300
45825
|
}
|
|
45826
|
+
function resolveConversationChannelToolScope(agentId, conversationId) {
|
|
45827
|
+
const registry = getChannelRegistry();
|
|
45828
|
+
if (!registry) {
|
|
45829
|
+
return { channels: [] };
|
|
45830
|
+
}
|
|
45831
|
+
const channels = [];
|
|
45832
|
+
const seen = new Set;
|
|
45833
|
+
for (const channelId of SUPPORTED_CHANNEL_IDS) {
|
|
45834
|
+
loadRoutes(channelId);
|
|
45835
|
+
for (const route of getRoutesForChannel(channelId)) {
|
|
45836
|
+
if (route.agentId !== agentId || route.conversationId !== conversationId || !route.enabled) {
|
|
45837
|
+
continue;
|
|
45838
|
+
}
|
|
45839
|
+
const adapter = registry.getAdapter(channelId, route.accountId);
|
|
45840
|
+
if (!adapter?.isRunning()) {
|
|
45841
|
+
continue;
|
|
45842
|
+
}
|
|
45843
|
+
const key = `${channelId}:${route.accountId ?? ""}`;
|
|
45844
|
+
if (seen.has(key)) {
|
|
45845
|
+
continue;
|
|
45846
|
+
}
|
|
45847
|
+
seen.add(key);
|
|
45848
|
+
channels.push({
|
|
45849
|
+
channelId,
|
|
45850
|
+
accountId: route.accountId ?? null
|
|
45851
|
+
});
|
|
45852
|
+
}
|
|
45853
|
+
}
|
|
45854
|
+
return { channels };
|
|
45855
|
+
}
|
|
45301
45856
|
async function prepareToolExecutionContextForScope(params) {
|
|
45302
45857
|
const {
|
|
45303
45858
|
agentId,
|
|
@@ -45332,7 +45887,8 @@ async function prepareToolExecutionContextForScope(params) {
|
|
|
45332
45887
|
toolsetPreference,
|
|
45333
45888
|
exclude,
|
|
45334
45889
|
workingDirectory,
|
|
45335
|
-
permissionModeState
|
|
45890
|
+
permissionModeState,
|
|
45891
|
+
channelToolScope: resolveConversationChannelToolScope(agentId, conversationId ?? "default")
|
|
45336
45892
|
});
|
|
45337
45893
|
}
|
|
45338
45894
|
async function ensureCorrectMemoryTool(agentId, modelIdentifier, useMemoryPatch) {
|
|
@@ -45489,6 +46045,8 @@ var init_toolset = __esm(async () => {
|
|
|
45489
46045
|
init_client2();
|
|
45490
46046
|
init_model2();
|
|
45491
46047
|
init_registry();
|
|
46048
|
+
init_routing();
|
|
46049
|
+
init_types();
|
|
45492
46050
|
init_settings_manager();
|
|
45493
46051
|
init_filter();
|
|
45494
46052
|
await init_manager3();
|
|
@@ -45573,10 +46131,12 @@ var exports_memoryFilesystem = {};
|
|
|
45573
46131
|
__export(exports_memoryFilesystem, {
|
|
45574
46132
|
renderMemoryFilesystemTree: () => renderMemoryFilesystemTree,
|
|
45575
46133
|
labelFromRelativePath: () => labelFromRelativePath,
|
|
46134
|
+
isMemfsEnabledOnServer: () => isMemfsEnabledOnServer,
|
|
45576
46135
|
isLettaCloud: () => isLettaCloud,
|
|
45577
46136
|
getMemorySystemDir: () => getMemorySystemDir,
|
|
45578
46137
|
getMemoryFilesystemRoot: () => getMemoryFilesystemRoot,
|
|
45579
46138
|
ensureMemoryFilesystemDirs: () => ensureMemoryFilesystemDirs,
|
|
46139
|
+
ensureLocalMemfsCheckout: () => ensureLocalMemfsCheckout,
|
|
45580
46140
|
enableMemfsIfCloud: () => enableMemfsIfCloud,
|
|
45581
46141
|
applyMemfsFlags: () => applyMemfsFlags,
|
|
45582
46142
|
MEMORY_TREE_MAX_LINES: () => MEMORY_TREE_MAX_LINES,
|
|
@@ -45606,6 +46166,23 @@ function ensureMemoryFilesystemDirs(agentId, homeDir = homedir10()) {
|
|
|
45606
46166
|
mkdirSync13(systemDir, { recursive: true });
|
|
45607
46167
|
}
|
|
45608
46168
|
}
|
|
46169
|
+
async function isMemfsEnabledOnServer(agentId) {
|
|
46170
|
+
const { getClient: getClient3 } = await Promise.resolve().then(() => (init_client2(), exports_client));
|
|
46171
|
+
const client = await getClient3();
|
|
46172
|
+
const agent = await client.agents.retrieve(agentId);
|
|
46173
|
+
const { GIT_MEMORY_ENABLED_TAG: GIT_MEMORY_ENABLED_TAG2 } = await Promise.resolve().then(() => (init_memoryGit(), exports_memoryGit));
|
|
46174
|
+
const enabled = agent.tags?.includes(GIT_MEMORY_ENABLED_TAG2) ?? false;
|
|
46175
|
+
const { settingsManager: settingsManager2 } = await Promise.resolve().then(() => (init_settings_manager(), exports_settings_manager));
|
|
46176
|
+
settingsManager2.setMemfsEnabled(agentId, enabled);
|
|
46177
|
+
return enabled;
|
|
46178
|
+
}
|
|
46179
|
+
async function ensureLocalMemfsCheckout(agentId) {
|
|
46180
|
+
const { isGitRepo: isGitRepo2, cloneMemoryRepo: cloneMemoryRepo2 } = await Promise.resolve().then(() => (init_memoryGit(), exports_memoryGit));
|
|
46181
|
+
if (isGitRepo2(agentId)) {
|
|
46182
|
+
return;
|
|
46183
|
+
}
|
|
46184
|
+
await cloneMemoryRepo2(agentId);
|
|
46185
|
+
}
|
|
45609
46186
|
function labelFromRelativePath(relativePath) {
|
|
45610
46187
|
const normalized = relativePath.replace(/\\/g, "/");
|
|
45611
46188
|
return normalized.replace(/\.md$/, "");
|
|
@@ -49851,6 +50428,19 @@ function resolveLettaInvocation(env3 = process.env, argv = process.argv, execPat
|
|
|
49851
50428
|
}
|
|
49852
50429
|
const scriptPath = argv[1] || "";
|
|
49853
50430
|
if (scriptPath && isDevLettaEntryScript(scriptPath)) {
|
|
50431
|
+
const runtimeName = path4.basename(execPath).toLowerCase();
|
|
50432
|
+
if (runtimeName.includes("bun")) {
|
|
50433
|
+
return {
|
|
50434
|
+
command: execPath,
|
|
50435
|
+
args: [
|
|
50436
|
+
"--loader:.md=text",
|
|
50437
|
+
"--loader:.mdx=text",
|
|
50438
|
+
"--loader:.txt=text",
|
|
50439
|
+
"run",
|
|
50440
|
+
scriptPath
|
|
50441
|
+
]
|
|
50442
|
+
};
|
|
50443
|
+
}
|
|
49854
50444
|
return { command: execPath, args: [scriptPath] };
|
|
49855
50445
|
}
|
|
49856
50446
|
return null;
|
|
@@ -73556,20 +74146,21 @@ var init_analyzer = __esm(() => {
|
|
|
73556
74146
|
// src/tools/manager.ts
|
|
73557
74147
|
import * as nodeFs from "node:fs/promises";
|
|
73558
74148
|
import * as nodePath from "node:path";
|
|
73559
|
-
function maybeAppendChannelTools(toolNames) {
|
|
73560
|
-
|
|
74149
|
+
function maybeAppendChannelTools(toolNames, channelToolScope) {
|
|
74150
|
+
const hasActiveChannelTools = channelToolScope !== undefined ? (channelToolScope?.channels.length ?? 0) > 0 : getActiveChannelIds().length > 0;
|
|
74151
|
+
if (hasActiveChannelTools && !toolNames.includes("MessageChannel")) {
|
|
73561
74152
|
return [...toolNames, "MessageChannel"];
|
|
73562
74153
|
}
|
|
73563
74154
|
return toolNames;
|
|
73564
74155
|
}
|
|
73565
|
-
async function maybeResolveDynamicChannelTool(name, description, schema) {
|
|
74156
|
+
async function maybeResolveDynamicChannelTool(name, description, schema, channelToolScope) {
|
|
73566
74157
|
if (name !== "MessageChannel") {
|
|
73567
74158
|
return {
|
|
73568
74159
|
description,
|
|
73569
74160
|
input_schema: schema
|
|
73570
74161
|
};
|
|
73571
74162
|
}
|
|
73572
|
-
const resolved = await buildDynamicMessageChannelToolDefinition(description, schema);
|
|
74163
|
+
const resolved = await buildDynamicMessageChannelToolDefinition(description, schema, channelToolScope);
|
|
73573
74164
|
return {
|
|
73574
74165
|
description: resolved.description,
|
|
73575
74166
|
input_schema: resolved.schema
|
|
@@ -73577,6 +74168,10 @@ async function maybeResolveDynamicChannelTool(name, description, schema) {
|
|
|
73577
74168
|
}
|
|
73578
74169
|
function withDynamicMessageChannelCache(registry) {
|
|
73579
74170
|
const nextRegistry = new Map(registry);
|
|
74171
|
+
const existing = nextRegistry.get("MessageChannel");
|
|
74172
|
+
if (existing && existing.schema.description !== TOOL_DEFINITIONS.MessageChannel.description) {
|
|
74173
|
+
return nextRegistry;
|
|
74174
|
+
}
|
|
73580
74175
|
if (getActiveChannelIds().length === 0) {
|
|
73581
74176
|
nextRegistry.delete("MessageChannel");
|
|
73582
74177
|
return nextRegistry;
|
|
@@ -73585,7 +74180,6 @@ function withDynamicMessageChannelCache(registry) {
|
|
|
73585
74180
|
if (!cachedMessageChannel) {
|
|
73586
74181
|
return nextRegistry;
|
|
73587
74182
|
}
|
|
73588
|
-
const existing = nextRegistry.get("MessageChannel");
|
|
73589
74183
|
nextRegistry.set("MessageChannel", {
|
|
73590
74184
|
schema: {
|
|
73591
74185
|
name: "MessageChannel",
|
|
@@ -73788,7 +74382,7 @@ async function prepareCurrentToolExecutionContext(options) {
|
|
|
73788
74382
|
}, options);
|
|
73789
74383
|
}
|
|
73790
74384
|
async function prepareToolExecutionContextForSpecificTools(toolNames, options) {
|
|
73791
|
-
const toolRegistrySnapshot = await buildSpecificToolRegistry(toolNames);
|
|
74385
|
+
const toolRegistrySnapshot = await buildSpecificToolRegistry(toolNames, options?.channelToolScope);
|
|
73792
74386
|
return capturePreparedToolExecutionContext({
|
|
73793
74387
|
toolRegistry: toolRegistrySnapshot,
|
|
73794
74388
|
externalTools: new Map(getExternalToolsRegistry()),
|
|
@@ -73861,7 +74455,7 @@ function maybeApplyLspReadOverride(registry) {
|
|
|
73861
74455
|
fn: lspDefinition.impl
|
|
73862
74456
|
});
|
|
73863
74457
|
}
|
|
73864
|
-
async function buildSpecificToolRegistry(toolNames) {
|
|
74458
|
+
async function buildSpecificToolRegistry(toolNames, channelToolScope) {
|
|
73865
74459
|
const { toolFilter: toolFilter2 } = await Promise.resolve().then(() => (init_filter(), exports_filter));
|
|
73866
74460
|
const newRegistry = new Map;
|
|
73867
74461
|
for (const name of toolNames) {
|
|
@@ -73877,7 +74471,7 @@ async function buildSpecificToolRegistry(toolNames) {
|
|
|
73877
74471
|
if (!definition.impl) {
|
|
73878
74472
|
throw new Error(`Tool implementation not found for ${internalName}`);
|
|
73879
74473
|
}
|
|
73880
|
-
const resolvedTool = await maybeResolveDynamicChannelTool(internalName, definition.description, definition.schema);
|
|
74474
|
+
const resolvedTool = await maybeResolveDynamicChannelTool(internalName, definition.description, definition.schema, channelToolScope);
|
|
73881
74475
|
const toolSchema = {
|
|
73882
74476
|
name: internalName,
|
|
73883
74477
|
description: resolvedTool.description,
|
|
@@ -73907,7 +74501,7 @@ async function resolveBaseToolNamesForModel(modelIdentifier, options) {
|
|
|
73907
74501
|
const excludeSet = new Set(options.exclude);
|
|
73908
74502
|
baseToolNames = baseToolNames.filter((name) => !excludeSet.has(name));
|
|
73909
74503
|
}
|
|
73910
|
-
baseToolNames = maybeAppendChannelTools(baseToolNames);
|
|
74504
|
+
baseToolNames = maybeAppendChannelTools(baseToolNames, options?.channelToolScope);
|
|
73911
74505
|
return baseToolNames;
|
|
73912
74506
|
}
|
|
73913
74507
|
async function buildRegistryForModel(modelIdentifier, options) {
|
|
@@ -73936,7 +74530,7 @@ async function buildRegistryForModel(modelIdentifier, options) {
|
|
|
73936
74530
|
if (name === "Task" && discoveredSubagents.length > 0) {
|
|
73937
74531
|
description = injectSubagentsIntoTaskDescription(description, discoveredSubagents);
|
|
73938
74532
|
}
|
|
73939
|
-
const resolvedTool = await maybeResolveDynamicChannelTool(name, description, definition.schema);
|
|
74533
|
+
const resolvedTool = await maybeResolveDynamicChannelTool(name, description, definition.schema, options?.channelToolScope);
|
|
73940
74534
|
const toolSchema = {
|
|
73941
74535
|
name,
|
|
73942
74536
|
description: resolvedTool.description,
|
|
@@ -85334,7 +85928,7 @@ __export(exports_diff, {
|
|
|
85334
85928
|
ADV_DIFF_IGNORE_WHITESPACE: () => ADV_DIFF_IGNORE_WHITESPACE,
|
|
85335
85929
|
ADV_DIFF_CONTEXT_LINES: () => ADV_DIFF_CONTEXT_LINES
|
|
85336
85930
|
});
|
|
85337
|
-
import { basename as
|
|
85931
|
+
import { basename as basename8 } from "node:path";
|
|
85338
85932
|
function readFileOrNull(p) {
|
|
85339
85933
|
try {
|
|
85340
85934
|
return __require("node:fs").readFileSync(p, "utf-8");
|
|
@@ -85358,7 +85952,7 @@ function applyAllOccurrences(content, oldStr, newStr) {
|
|
|
85358
85952
|
return { ok: true, out: content.split(oldStr).join(newStr) };
|
|
85359
85953
|
}
|
|
85360
85954
|
function computeAdvancedDiff(input, opts) {
|
|
85361
|
-
const fileName =
|
|
85955
|
+
const fileName = basename8(input.filePath || "");
|
|
85362
85956
|
const fileContent = opts?.oldStrOverride !== undefined ? opts.oldStrOverride : readFileOrNull(input.filePath);
|
|
85363
85957
|
if (fileContent === null && input.kind !== "write") {
|
|
85364
85958
|
return { mode: "fallback", reason: "File not readable" };
|
|
@@ -85424,7 +86018,7 @@ function computeAdvancedDiff(input, opts) {
|
|
|
85424
86018
|
return { mode: "advanced", fileName, oldStr, newStr, hunks };
|
|
85425
86019
|
}
|
|
85426
86020
|
function parsePatchToAdvancedDiff(patchLines, filePath) {
|
|
85427
|
-
const fileName =
|
|
86021
|
+
const fileName = basename8(filePath);
|
|
85428
86022
|
const hunks = [];
|
|
85429
86023
|
let currentHunk = null;
|
|
85430
86024
|
let oldLine = 1;
|
|
@@ -85705,8 +86299,8 @@ function isFormatterSegment(tokens) {
|
|
|
85705
86299
|
}
|
|
85706
86300
|
}
|
|
85707
86301
|
function isShellExecutor2(token) {
|
|
85708
|
-
const
|
|
85709
|
-
return ["bash", "sh", "zsh", "dash", "ksh"].includes(
|
|
86302
|
+
const basename9 = token.split("/").pop() ?? token;
|
|
86303
|
+
return ["bash", "sh", "zsh", "dash", "ksh"].includes(basename9.toLowerCase());
|
|
85710
86304
|
}
|
|
85711
86305
|
function normalizeRawCommand(command) {
|
|
85712
86306
|
if (Array.isArray(command)) {
|
|
@@ -86415,7 +87009,7 @@ var init_formatArgsDisplay = __esm(async () => {
|
|
|
86415
87009
|
});
|
|
86416
87010
|
|
|
86417
87011
|
// src/helpers/diffPreview.ts
|
|
86418
|
-
import path21, { basename as
|
|
87012
|
+
import path21, { basename as basename9 } from "node:path";
|
|
86419
87013
|
function parseHunkLinePrefix(raw) {
|
|
86420
87014
|
if (raw.length === 0) {
|
|
86421
87015
|
return { type: "context", content: "" };
|
|
@@ -86521,7 +87115,7 @@ async function computeDiffPreviews(toolName, toolArgs, workingDirectory = proces
|
|
|
86521
87115
|
filePath: resolvedFilePath,
|
|
86522
87116
|
content: toolArgs.content || ""
|
|
86523
87117
|
});
|
|
86524
|
-
previews.push(toDiffPreview(result,
|
|
87118
|
+
previews.push(toDiffPreview(result, basename9(filePath)));
|
|
86525
87119
|
}
|
|
86526
87120
|
} else if (isFileEditTool2(toolName)) {
|
|
86527
87121
|
const filePath = toolArgs.file_path;
|
|
@@ -86533,7 +87127,7 @@ async function computeDiffPreviews(toolName, toolArgs, workingDirectory = proces
|
|
|
86533
87127
|
filePath: resolvedFilePath,
|
|
86534
87128
|
edits: toolArgs.edits
|
|
86535
87129
|
});
|
|
86536
|
-
previews.push(toDiffPreview(result,
|
|
87130
|
+
previews.push(toDiffPreview(result, basename9(filePath)));
|
|
86537
87131
|
} else {
|
|
86538
87132
|
const result = computeAdvancedDiff2({
|
|
86539
87133
|
kind: "edit",
|
|
@@ -86542,7 +87136,7 @@ async function computeDiffPreviews(toolName, toolArgs, workingDirectory = proces
|
|
|
86542
87136
|
newString: toolArgs.new_string || "",
|
|
86543
87137
|
replaceAll: toolArgs.replace_all
|
|
86544
87138
|
});
|
|
86545
|
-
previews.push(toDiffPreview(result,
|
|
87139
|
+
previews.push(toDiffPreview(result, basename9(filePath)));
|
|
86546
87140
|
}
|
|
86547
87141
|
}
|
|
86548
87142
|
} else if (isPatchTool2(toolName) && toolArgs.input) {
|
|
@@ -86551,7 +87145,7 @@ async function computeDiffPreviews(toolName, toolArgs, workingDirectory = proces
|
|
|
86551
87145
|
if (op.kind === "add" || op.kind === "update") {
|
|
86552
87146
|
const result = parsePatchToAdvancedDiff2(op.patchLines, op.path);
|
|
86553
87147
|
if (result) {
|
|
86554
|
-
previews.push(toDiffPreview(result,
|
|
87148
|
+
previews.push(toDiffPreview(result, basename9(op.path)));
|
|
86555
87149
|
}
|
|
86556
87150
|
}
|
|
86557
87151
|
}
|
|
@@ -86561,7 +87155,7 @@ async function computeDiffPreviews(toolName, toolArgs, workingDirectory = proces
|
|
|
86561
87155
|
if (op.kind === "add" || op.kind === "update") {
|
|
86562
87156
|
const result = parsePatchToAdvancedDiff2(op.patchLines, op.path);
|
|
86563
87157
|
if (result) {
|
|
86564
|
-
previews.push(toDiffPreview(result,
|
|
87158
|
+
previews.push(toDiffPreview(result, basename9(op.path)));
|
|
86565
87159
|
}
|
|
86566
87160
|
}
|
|
86567
87161
|
}
|
|
@@ -89655,6 +90249,65 @@ function mergeDequeuedBatchContent(items) {
|
|
|
89655
90249
|
normalizeUserContent: (content) => content
|
|
89656
90250
|
});
|
|
89657
90251
|
}
|
|
90252
|
+
function getChannelTurnSourceKey(source) {
|
|
90253
|
+
return [
|
|
90254
|
+
source.channel,
|
|
90255
|
+
source.accountId ?? "",
|
|
90256
|
+
source.chatId,
|
|
90257
|
+
source.messageId ?? "",
|
|
90258
|
+
source.threadId ?? "",
|
|
90259
|
+
source.agentId,
|
|
90260
|
+
source.conversationId
|
|
90261
|
+
].join(":");
|
|
90262
|
+
}
|
|
90263
|
+
function collectBatchChannelTurnSources(runtime, batch) {
|
|
90264
|
+
const seen = new Set;
|
|
90265
|
+
const sources = [];
|
|
90266
|
+
for (const item of batch.items) {
|
|
90267
|
+
const template = runtime.queuedMessagesByItemId.get(item.id);
|
|
90268
|
+
for (const source of template?.channelTurnSources ?? []) {
|
|
90269
|
+
const key = getChannelTurnSourceKey(source);
|
|
90270
|
+
if (seen.has(key)) {
|
|
90271
|
+
continue;
|
|
90272
|
+
}
|
|
90273
|
+
seen.add(key);
|
|
90274
|
+
sources.push(source);
|
|
90275
|
+
}
|
|
90276
|
+
}
|
|
90277
|
+
return sources.length > 0 ? sources : undefined;
|
|
90278
|
+
}
|
|
90279
|
+
async function dispatchChannelTurnLifecycleEvent(event) {
|
|
90280
|
+
if (event.sources.length === 0) {
|
|
90281
|
+
return;
|
|
90282
|
+
}
|
|
90283
|
+
const registry = getChannelRegistry();
|
|
90284
|
+
if (!registry) {
|
|
90285
|
+
return;
|
|
90286
|
+
}
|
|
90287
|
+
if (event.type === "processing") {
|
|
90288
|
+
await registry.dispatchTurnLifecycleEvent(event);
|
|
90289
|
+
return;
|
|
90290
|
+
}
|
|
90291
|
+
await registry.dispatchTurnLifecycleEvent({
|
|
90292
|
+
type: "finished",
|
|
90293
|
+
batchId: event.batchId,
|
|
90294
|
+
sources: event.sources,
|
|
90295
|
+
outcome: event.outcome,
|
|
90296
|
+
...event.error ? { error: event.error } : {}
|
|
90297
|
+
});
|
|
90298
|
+
}
|
|
90299
|
+
function mapTurnLifecycleOutcome(lastStopReason, didThrow) {
|
|
90300
|
+
if (didThrow) {
|
|
90301
|
+
return "error";
|
|
90302
|
+
}
|
|
90303
|
+
if (lastStopReason === "cancelled") {
|
|
90304
|
+
return "cancelled";
|
|
90305
|
+
}
|
|
90306
|
+
if (lastStopReason && lastStopReason !== "end_turn") {
|
|
90307
|
+
return "error";
|
|
90308
|
+
}
|
|
90309
|
+
return "completed";
|
|
90310
|
+
}
|
|
89658
90311
|
function isBase64ImageContentPart(part) {
|
|
89659
90312
|
if (!part || typeof part !== "object") {
|
|
89660
90313
|
return false;
|
|
@@ -89714,6 +90367,7 @@ function getPrimaryQueueMessageItem(items) {
|
|
|
89714
90367
|
return null;
|
|
89715
90368
|
}
|
|
89716
90369
|
function buildQueuedTurnMessage(runtime, batch) {
|
|
90370
|
+
const channelTurnSources = collectBatchChannelTurnSources(runtime, batch);
|
|
89717
90371
|
const primaryItem = getPrimaryQueueMessageItem(batch.items);
|
|
89718
90372
|
if (!primaryItem) {
|
|
89719
90373
|
for (const item of batch.items) {
|
|
@@ -89728,6 +90382,7 @@ function buildQueuedTurnMessage(runtime, batch) {
|
|
|
89728
90382
|
type: "message",
|
|
89729
90383
|
agentId: scopeItem?.agentId ?? runtime.agentId ?? undefined,
|
|
89730
90384
|
conversationId: scopeItem?.conversationId ?? runtime.conversationId,
|
|
90385
|
+
...channelTurnSources ? { channelTurnSources } : {},
|
|
89731
90386
|
messages: [
|
|
89732
90387
|
{
|
|
89733
90388
|
role: "user",
|
|
@@ -89760,6 +90415,7 @@ function buildQueuedTurnMessage(runtime, batch) {
|
|
|
89760
90415
|
messages[firstMessageIndex] = mergedFirstMessage;
|
|
89761
90416
|
return {
|
|
89762
90417
|
...template,
|
|
90418
|
+
...channelTurnSources ? { channelTurnSources } : {},
|
|
89763
90419
|
messages
|
|
89764
90420
|
};
|
|
89765
90421
|
}
|
|
@@ -89840,13 +90496,39 @@ async function drainQueuedMessages(runtime, socket, opts, processQueuedTurn) {
|
|
|
89840
90496
|
return;
|
|
89841
90497
|
}
|
|
89842
90498
|
const { dequeuedBatch, queuedTurn } = consumedQueuedTurn;
|
|
90499
|
+
const channelTurnSources = queuedTurn.channelTurnSources ?? [];
|
|
89843
90500
|
emitDequeuedUserMessage(socket, runtime, queuedTurn, dequeuedBatch);
|
|
89844
90501
|
const preTurnStatus = getListenerStatus(runtime.listener) === "processing" ? "processing" : "receiving";
|
|
89845
90502
|
if (opts.connectionId && runtime.listener.lastEmittedStatus !== preTurnStatus) {
|
|
89846
90503
|
runtime.listener.lastEmittedStatus = preTurnStatus;
|
|
89847
90504
|
opts.onStatusChange?.(preTurnStatus, opts.connectionId);
|
|
89848
90505
|
}
|
|
89849
|
-
|
|
90506
|
+
if (channelTurnSources.length > 0) {
|
|
90507
|
+
await dispatchChannelTurnLifecycleEvent({
|
|
90508
|
+
type: "processing",
|
|
90509
|
+
batchId: dequeuedBatch.batchId,
|
|
90510
|
+
sources: channelTurnSources
|
|
90511
|
+
});
|
|
90512
|
+
}
|
|
90513
|
+
let turnError;
|
|
90514
|
+
let didThrow = false;
|
|
90515
|
+
try {
|
|
90516
|
+
await processQueuedTurn(queuedTurn, dequeuedBatch);
|
|
90517
|
+
} catch (error) {
|
|
90518
|
+
didThrow = true;
|
|
90519
|
+
turnError = error instanceof Error ? error.message : String(error);
|
|
90520
|
+
throw error;
|
|
90521
|
+
} finally {
|
|
90522
|
+
if (channelTurnSources.length > 0) {
|
|
90523
|
+
await dispatchChannelTurnLifecycleEvent({
|
|
90524
|
+
type: "finished",
|
|
90525
|
+
batchId: dequeuedBatch.batchId,
|
|
90526
|
+
sources: channelTurnSources,
|
|
90527
|
+
outcome: mapTurnLifecycleOutcome(runtime.lastStopReason, didThrow),
|
|
90528
|
+
...turnError ? { error: turnError } : {}
|
|
90529
|
+
});
|
|
90530
|
+
}
|
|
90531
|
+
}
|
|
89850
90532
|
emitListenerStatus(runtime.listener, opts.onStatusChange, opts.connectionId);
|
|
89851
90533
|
evictConversationRuntimeIfIdle(runtime);
|
|
89852
90534
|
}
|
|
@@ -89879,6 +90561,7 @@ function scheduleQueuePump(runtime, socket, opts, processQueuedTurn) {
|
|
|
89879
90561
|
});
|
|
89880
90562
|
}
|
|
89881
90563
|
var init_queue = __esm(async () => {
|
|
90564
|
+
init_registry();
|
|
89882
90565
|
init_queueRuntime();
|
|
89883
90566
|
init_errorReporting();
|
|
89884
90567
|
init_runtime3();
|
|
@@ -90985,7 +91668,7 @@ function scanMemoryFilesystem(memoryRoot) {
|
|
|
90985
91668
|
} catch {
|
|
90986
91669
|
return;
|
|
90987
91670
|
}
|
|
90988
|
-
const relativePath = relative12(memoryRoot, fullPath);
|
|
91671
|
+
const relativePath = relative12(memoryRoot, fullPath).replace(/\\/g, "/");
|
|
90989
91672
|
const isLast = index === sorted.length - 1;
|
|
90990
91673
|
nodes.push({
|
|
90991
91674
|
name: isDir ? `${name}/` : name,
|
|
@@ -91232,9 +91915,10 @@ async function applyModelUpdateForRuntime(params) {
|
|
|
91232
91915
|
let toolsetError = null;
|
|
91233
91916
|
try {
|
|
91234
91917
|
await ensureCorrectMemoryTool(agentId, model.handle);
|
|
91235
|
-
const preparedToolContext = await
|
|
91236
|
-
|
|
91237
|
-
|
|
91918
|
+
const preparedToolContext = await prepareToolExecutionContextForScope({
|
|
91919
|
+
agentId,
|
|
91920
|
+
conversationId,
|
|
91921
|
+
overrideModel: model.handle
|
|
91238
91922
|
});
|
|
91239
91923
|
nextToolset = preparedToolContext.toolset;
|
|
91240
91924
|
nextLoadedTools = preparedToolContext.preparedToolContext.loadedToolNames;
|
|
@@ -91357,6 +92041,165 @@ function emitChannelTargetsUpdated(socket, channelId) {
|
|
|
91357
92041
|
channel_id: channelId
|
|
91358
92042
|
}, "listener_channels_send_failed", "listener_channels_command");
|
|
91359
92043
|
}
|
|
92044
|
+
async function handleListMemoryCommand(parsed, socket, overrides = {}) {
|
|
92045
|
+
try {
|
|
92046
|
+
const {
|
|
92047
|
+
ensureLocalMemfsCheckout: actualEnsureLocalMemfsCheckout,
|
|
92048
|
+
getMemoryFilesystemRoot: actualGetMemoryFilesystemRoot,
|
|
92049
|
+
isMemfsEnabledOnServer: actualIsMemfsEnabledOnServer
|
|
92050
|
+
} = await Promise.resolve().then(() => (init_memoryFilesystem(), exports_memoryFilesystem));
|
|
92051
|
+
const ensureLocalMemfsCheckout2 = overrides.ensureLocalMemfsCheckout ?? actualEnsureLocalMemfsCheckout;
|
|
92052
|
+
const getMemoryFilesystemRoot2 = overrides.getMemoryFilesystemRoot ?? actualGetMemoryFilesystemRoot;
|
|
92053
|
+
const isMemfsEnabledOnServer2 = overrides.isMemfsEnabledOnServer ?? actualIsMemfsEnabledOnServer;
|
|
92054
|
+
const { scanMemoryFilesystem: scanMemoryFilesystem2, getFileNodes: getFileNodes2, readFileContent: readFileContent2 } = await Promise.resolve().then(() => (init_memoryScanner(), exports_memoryScanner));
|
|
92055
|
+
const { parseFrontmatter: parseFrontmatter2 } = await Promise.resolve().then(() => exports_frontmatter);
|
|
92056
|
+
const { existsSync: existsSync26 } = await import("node:fs");
|
|
92057
|
+
const { join: join31, posix: posix2 } = await import("node:path");
|
|
92058
|
+
const memoryRoot = getMemoryFilesystemRoot2(parsed.agent_id);
|
|
92059
|
+
let memfsInitialized = existsSync26(join31(memoryRoot, ".git"));
|
|
92060
|
+
const memfsEnabled = memfsInitialized ? true : await isMemfsEnabledOnServer2(parsed.agent_id);
|
|
92061
|
+
if (!memfsEnabled) {
|
|
92062
|
+
safeSocketSend(socket, {
|
|
92063
|
+
type: "list_memory_response",
|
|
92064
|
+
request_id: parsed.request_id,
|
|
92065
|
+
entries: [],
|
|
92066
|
+
done: true,
|
|
92067
|
+
total: 0,
|
|
92068
|
+
success: true,
|
|
92069
|
+
memfs_enabled: false,
|
|
92070
|
+
memfs_initialized: false
|
|
92071
|
+
}, "listener_list_memory_send_failed", "listener_list_memory");
|
|
92072
|
+
return true;
|
|
92073
|
+
}
|
|
92074
|
+
if (!memfsInitialized) {
|
|
92075
|
+
await ensureLocalMemfsCheckout2(parsed.agent_id);
|
|
92076
|
+
memfsInitialized = existsSync26(join31(memoryRoot, ".git"));
|
|
92077
|
+
}
|
|
92078
|
+
if (!memfsInitialized) {
|
|
92079
|
+
throw new Error("MemFS is enabled, but the local memory checkout could not be initialized.");
|
|
92080
|
+
}
|
|
92081
|
+
const treeNodes = scanMemoryFilesystem2(memoryRoot);
|
|
92082
|
+
const fileNodes = getFileNodes2(treeNodes).filter((n) => n.name.endsWith(".md"));
|
|
92083
|
+
const includeReferences = parsed.include_references === true;
|
|
92084
|
+
const allPaths = new Set(fileNodes.map((node) => node.relativePath));
|
|
92085
|
+
const normalizeMemoryReference = (rawReference, sourcePath) => {
|
|
92086
|
+
let target = rawReference.trim();
|
|
92087
|
+
if (!target) {
|
|
92088
|
+
return null;
|
|
92089
|
+
}
|
|
92090
|
+
if (target.startsWith("http://") || target.startsWith("https://") || target.startsWith("mailto:")) {
|
|
92091
|
+
return null;
|
|
92092
|
+
}
|
|
92093
|
+
target = target.replace(/^<|>$/g, "");
|
|
92094
|
+
target = target.split("#")[0] ?? "";
|
|
92095
|
+
target = target.split("?")[0] ?? "";
|
|
92096
|
+
target = target.trim().replace(/\\/g, "/");
|
|
92097
|
+
if (!target || target.startsWith("#")) {
|
|
92098
|
+
return null;
|
|
92099
|
+
}
|
|
92100
|
+
if (target.includes("|")) {
|
|
92101
|
+
target = target.split("|")[0] ?? "";
|
|
92102
|
+
}
|
|
92103
|
+
if (!target) {
|
|
92104
|
+
return null;
|
|
92105
|
+
}
|
|
92106
|
+
const sourceDir = posix2.dirname(sourcePath.replace(/\\/g, "/"));
|
|
92107
|
+
const candidate = target.startsWith("./") || target.startsWith("../") ? posix2.normalize(posix2.join(sourceDir, target)) : posix2.normalize(target.startsWith("/") ? target.slice(1) : target);
|
|
92108
|
+
if (!candidate || candidate.startsWith("../") || candidate === "." || candidate === "..") {
|
|
92109
|
+
return null;
|
|
92110
|
+
}
|
|
92111
|
+
const withExtension = candidate.endsWith(".md") ? candidate : `${candidate}.md`;
|
|
92112
|
+
const candidates = new Set([withExtension]);
|
|
92113
|
+
const isExplicitRelative = target.startsWith("./") || target.startsWith("../");
|
|
92114
|
+
if (!isExplicitRelative && !target.startsWith("/") && sourceDir && sourceDir !== ".") {
|
|
92115
|
+
candidates.add(posix2.normalize(posix2.join(sourceDir, withExtension)));
|
|
92116
|
+
}
|
|
92117
|
+
if (!withExtension.startsWith("system/")) {
|
|
92118
|
+
candidates.add(posix2.normalize(`system/${withExtension}`));
|
|
92119
|
+
}
|
|
92120
|
+
for (const resolved of candidates) {
|
|
92121
|
+
if (allPaths.has(resolved)) {
|
|
92122
|
+
return resolved;
|
|
92123
|
+
}
|
|
92124
|
+
}
|
|
92125
|
+
return null;
|
|
92126
|
+
};
|
|
92127
|
+
const extractMemoryReferences = (body, sourcePath) => {
|
|
92128
|
+
if (!body.includes("[[")) {
|
|
92129
|
+
return [];
|
|
92130
|
+
}
|
|
92131
|
+
const refs = new Set;
|
|
92132
|
+
for (const wikiMatch of body.matchAll(WIKI_LINK_REGEX)) {
|
|
92133
|
+
const rawTarget = wikiMatch[1];
|
|
92134
|
+
if (!rawTarget)
|
|
92135
|
+
continue;
|
|
92136
|
+
const normalized = normalizeMemoryReference(rawTarget, sourcePath);
|
|
92137
|
+
if (normalized && normalized !== sourcePath) {
|
|
92138
|
+
refs.add(normalized);
|
|
92139
|
+
}
|
|
92140
|
+
}
|
|
92141
|
+
return [...refs];
|
|
92142
|
+
};
|
|
92143
|
+
const CHUNK_SIZE = 5;
|
|
92144
|
+
const total = fileNodes.length;
|
|
92145
|
+
for (let i = 0;i < total; i += CHUNK_SIZE) {
|
|
92146
|
+
const chunk = fileNodes.slice(i, i + CHUNK_SIZE);
|
|
92147
|
+
const entries = chunk.map((node) => {
|
|
92148
|
+
const raw = readFileContent2(node.fullPath);
|
|
92149
|
+
const { frontmatter, body } = parseFrontmatter2(raw);
|
|
92150
|
+
const desc = frontmatter.description;
|
|
92151
|
+
return {
|
|
92152
|
+
relative_path: node.relativePath,
|
|
92153
|
+
is_system: node.relativePath.startsWith("system/") || node.relativePath.startsWith("system\\"),
|
|
92154
|
+
description: typeof desc === "string" ? desc : null,
|
|
92155
|
+
content: body,
|
|
92156
|
+
size: body.length,
|
|
92157
|
+
...includeReferences ? {
|
|
92158
|
+
references: extractMemoryReferences(body, node.relativePath)
|
|
92159
|
+
} : {}
|
|
92160
|
+
};
|
|
92161
|
+
});
|
|
92162
|
+
const done = i + CHUNK_SIZE >= total;
|
|
92163
|
+
const sent = safeSocketSend(socket, {
|
|
92164
|
+
type: "list_memory_response",
|
|
92165
|
+
request_id: parsed.request_id,
|
|
92166
|
+
entries,
|
|
92167
|
+
done,
|
|
92168
|
+
total,
|
|
92169
|
+
success: true,
|
|
92170
|
+
memfs_enabled: true,
|
|
92171
|
+
memfs_initialized: true
|
|
92172
|
+
}, "listener_list_memory_send_failed", "listener_list_memory");
|
|
92173
|
+
if (!sent) {
|
|
92174
|
+
return true;
|
|
92175
|
+
}
|
|
92176
|
+
}
|
|
92177
|
+
if (total === 0) {
|
|
92178
|
+
safeSocketSend(socket, {
|
|
92179
|
+
type: "list_memory_response",
|
|
92180
|
+
request_id: parsed.request_id,
|
|
92181
|
+
entries: [],
|
|
92182
|
+
done: true,
|
|
92183
|
+
total: 0,
|
|
92184
|
+
success: true,
|
|
92185
|
+
memfs_enabled: true,
|
|
92186
|
+
memfs_initialized: true
|
|
92187
|
+
}, "listener_list_memory_send_failed", "listener_list_memory");
|
|
92188
|
+
}
|
|
92189
|
+
} catch (err) {
|
|
92190
|
+
trackListenerError("listener_list_memory_failed", err, "listener_memory_browser");
|
|
92191
|
+
safeSocketSend(socket, {
|
|
92192
|
+
type: "list_memory_response",
|
|
92193
|
+
request_id: parsed.request_id,
|
|
92194
|
+
entries: [],
|
|
92195
|
+
done: true,
|
|
92196
|
+
total: 0,
|
|
92197
|
+
success: false,
|
|
92198
|
+
error: err instanceof Error ? err.message : "Failed to list memory"
|
|
92199
|
+
}, "listener_list_memory_send_failed", "listener_list_memory");
|
|
92200
|
+
}
|
|
92201
|
+
return true;
|
|
92202
|
+
}
|
|
91360
92203
|
async function handleCronCommand(parsed, socket) {
|
|
91361
92204
|
if (parsed.type === "cron_list") {
|
|
91362
92205
|
try {
|
|
@@ -92210,7 +93053,7 @@ async function handleSkillCommand(parsed, socket) {
|
|
|
92210
93053
|
symlinkSync,
|
|
92211
93054
|
unlinkSync: unlinkSync8
|
|
92212
93055
|
} = await import("node:fs");
|
|
92213
|
-
const { basename:
|
|
93056
|
+
const { basename: basename10, join: join31 } = await import("node:path");
|
|
92214
93057
|
const lettaHome = process.env.LETTA_HOME || join31(process.env.HOME || process.env.USERPROFILE || "~", ".letta");
|
|
92215
93058
|
const globalSkillsDir = join31(lettaHome, "skills");
|
|
92216
93059
|
if (parsed.type === "skill_enable") {
|
|
@@ -92234,7 +93077,7 @@ async function handleSkillCommand(parsed, socket) {
|
|
|
92234
93077
|
}, "listener_skill_send_failed", "listener_skill_command");
|
|
92235
93078
|
return true;
|
|
92236
93079
|
}
|
|
92237
|
-
const linkName =
|
|
93080
|
+
const linkName = basename10(parsed.skill_path);
|
|
92238
93081
|
const linkPath = join31(globalSkillsDir, linkName);
|
|
92239
93082
|
mkdirSync19(globalSkillsDir, { recursive: true });
|
|
92240
93083
|
if (existsSync26(linkPath)) {
|
|
@@ -92446,12 +93289,21 @@ function wireChannelIngress(listener, socket, opts, processQueuedTurn) {
|
|
|
92446
93289
|
const registry = getChannelRegistry();
|
|
92447
93290
|
if (!registry)
|
|
92448
93291
|
return;
|
|
92449
|
-
registry.setMessageHandler((
|
|
92450
|
-
const rawRuntime = getOrCreateConversationRuntime(listener, route.agentId, route.conversationId);
|
|
93292
|
+
registry.setMessageHandler((delivery) => {
|
|
93293
|
+
const rawRuntime = getOrCreateConversationRuntime(listener, delivery.route.agentId, delivery.route.conversationId);
|
|
92451
93294
|
if (!rawRuntime)
|
|
92452
93295
|
return;
|
|
92453
93296
|
const conversationRuntime = ensureConversationQueueRuntime(listener, rawRuntime);
|
|
92454
|
-
enqueueChannelTurn(conversationRuntime, route,
|
|
93297
|
+
const enqueuedItem = enqueueChannelTurn(conversationRuntime, delivery.route, delivery.content, delivery.turnSources);
|
|
93298
|
+
if (!enqueuedItem) {
|
|
93299
|
+
return;
|
|
93300
|
+
}
|
|
93301
|
+
for (const turnSource of delivery.turnSources ?? []) {
|
|
93302
|
+
registry.dispatchTurnLifecycleEvent({
|
|
93303
|
+
type: "queued",
|
|
93304
|
+
source: turnSource
|
|
93305
|
+
});
|
|
93306
|
+
}
|
|
92455
93307
|
scheduleQueuePump(conversationRuntime, socket, opts, processQueuedTurn);
|
|
92456
93308
|
});
|
|
92457
93309
|
registry.setEventHandler((event) => {
|
|
@@ -92485,7 +93337,7 @@ function stampInboundUserMessageOtids(incoming) {
|
|
|
92485
93337
|
messages
|
|
92486
93338
|
};
|
|
92487
93339
|
}
|
|
92488
|
-
function enqueueChannelTurn(runtime, route, messageContent) {
|
|
93340
|
+
function enqueueChannelTurn(runtime, route, messageContent, turnSources) {
|
|
92489
93341
|
const clientMessageId = `cm-channel-${crypto.randomUUID()}`;
|
|
92490
93342
|
const enqueuedItem = runtime.queueRuntime.enqueue({
|
|
92491
93343
|
kind: "message",
|
|
@@ -92502,6 +93354,7 @@ function enqueueChannelTurn(runtime, route, messageContent) {
|
|
|
92502
93354
|
type: "message",
|
|
92503
93355
|
agentId: route.agentId,
|
|
92504
93356
|
conversationId: route.conversationId,
|
|
93357
|
+
...turnSources?.length ? { channelTurnSources: turnSources } : {},
|
|
92505
93358
|
messages: [
|
|
92506
93359
|
{
|
|
92507
93360
|
role: "user",
|
|
@@ -93460,144 +94313,7 @@ async function connectWithRetry(runtime, opts, attempt = 0, startTime = Date.now
|
|
|
93460
94313
|
}
|
|
93461
94314
|
if (isListMemoryCommand(parsed)) {
|
|
93462
94315
|
runDetachedListenerTask("list_memory", async () => {
|
|
93463
|
-
|
|
93464
|
-
const { getMemoryFilesystemRoot: getMemoryFilesystemRoot2 } = await Promise.resolve().then(() => (init_memoryFilesystem(), exports_memoryFilesystem));
|
|
93465
|
-
const { scanMemoryFilesystem: scanMemoryFilesystem2, getFileNodes: getFileNodes2, readFileContent: readFileContent2 } = await Promise.resolve().then(() => (init_memoryScanner(), exports_memoryScanner));
|
|
93466
|
-
const { parseFrontmatter: parseFrontmatter2 } = await Promise.resolve().then(() => exports_frontmatter);
|
|
93467
|
-
const { existsSync: existsSync26 } = await import("node:fs");
|
|
93468
|
-
const { join: join31, posix: posix2 } = await import("node:path");
|
|
93469
|
-
const memoryRoot = getMemoryFilesystemRoot2(parsed.agent_id);
|
|
93470
|
-
const memfsInitialized = existsSync26(join31(memoryRoot, ".git"));
|
|
93471
|
-
if (!memfsInitialized) {
|
|
93472
|
-
safeSocketSend(socket, {
|
|
93473
|
-
type: "list_memory_response",
|
|
93474
|
-
request_id: parsed.request_id,
|
|
93475
|
-
entries: [],
|
|
93476
|
-
done: true,
|
|
93477
|
-
total: 0,
|
|
93478
|
-
success: true,
|
|
93479
|
-
memfs_initialized: false
|
|
93480
|
-
}, "listener_list_memory_send_failed", "listener_list_memory");
|
|
93481
|
-
return;
|
|
93482
|
-
}
|
|
93483
|
-
const treeNodes = scanMemoryFilesystem2(memoryRoot);
|
|
93484
|
-
const fileNodes = getFileNodes2(treeNodes).filter((n) => n.name.endsWith(".md"));
|
|
93485
|
-
const includeReferences = parsed.include_references === true;
|
|
93486
|
-
const allPaths = new Set(fileNodes.map((node) => node.relativePath));
|
|
93487
|
-
const normalizeMemoryReference = (rawReference, sourcePath) => {
|
|
93488
|
-
let target = rawReference.trim();
|
|
93489
|
-
if (!target) {
|
|
93490
|
-
return null;
|
|
93491
|
-
}
|
|
93492
|
-
if (target.startsWith("http://") || target.startsWith("https://") || target.startsWith("mailto:")) {
|
|
93493
|
-
return null;
|
|
93494
|
-
}
|
|
93495
|
-
target = target.replace(/^<|>$/g, "");
|
|
93496
|
-
target = target.split("#")[0] ?? "";
|
|
93497
|
-
target = target.split("?")[0] ?? "";
|
|
93498
|
-
target = target.trim().replace(/\\/g, "/");
|
|
93499
|
-
if (!target || target.startsWith("#")) {
|
|
93500
|
-
return null;
|
|
93501
|
-
}
|
|
93502
|
-
if (target.includes("|")) {
|
|
93503
|
-
target = target.split("|")[0] ?? "";
|
|
93504
|
-
}
|
|
93505
|
-
if (!target) {
|
|
93506
|
-
return null;
|
|
93507
|
-
}
|
|
93508
|
-
const sourceDir = posix2.dirname(sourcePath.replace(/\\/g, "/"));
|
|
93509
|
-
const candidate = target.startsWith("./") || target.startsWith("../") ? posix2.normalize(posix2.join(sourceDir, target)) : posix2.normalize(target.startsWith("/") ? target.slice(1) : target);
|
|
93510
|
-
if (!candidate || candidate.startsWith("../") || candidate === "." || candidate === "..") {
|
|
93511
|
-
return null;
|
|
93512
|
-
}
|
|
93513
|
-
const withExtension = candidate.endsWith(".md") ? candidate : `${candidate}.md`;
|
|
93514
|
-
const candidates = new Set([withExtension]);
|
|
93515
|
-
const isExplicitRelative = target.startsWith("./") || target.startsWith("../");
|
|
93516
|
-
if (!isExplicitRelative && !target.startsWith("/") && sourceDir && sourceDir !== ".") {
|
|
93517
|
-
candidates.add(posix2.normalize(posix2.join(sourceDir, withExtension)));
|
|
93518
|
-
}
|
|
93519
|
-
if (!withExtension.startsWith("system/")) {
|
|
93520
|
-
candidates.add(posix2.normalize(`system/${withExtension}`));
|
|
93521
|
-
}
|
|
93522
|
-
for (const resolved of candidates) {
|
|
93523
|
-
if (allPaths.has(resolved)) {
|
|
93524
|
-
return resolved;
|
|
93525
|
-
}
|
|
93526
|
-
}
|
|
93527
|
-
return null;
|
|
93528
|
-
};
|
|
93529
|
-
const extractMemoryReferences = (body, sourcePath) => {
|
|
93530
|
-
if (!body.includes("[[")) {
|
|
93531
|
-
return [];
|
|
93532
|
-
}
|
|
93533
|
-
const refs = new Set;
|
|
93534
|
-
for (const wikiMatch of body.matchAll(WIKI_LINK_REGEX)) {
|
|
93535
|
-
const rawTarget = wikiMatch[1];
|
|
93536
|
-
if (!rawTarget)
|
|
93537
|
-
continue;
|
|
93538
|
-
const normalized = normalizeMemoryReference(rawTarget, sourcePath);
|
|
93539
|
-
if (normalized && normalized !== sourcePath) {
|
|
93540
|
-
refs.add(normalized);
|
|
93541
|
-
}
|
|
93542
|
-
}
|
|
93543
|
-
return [...refs];
|
|
93544
|
-
};
|
|
93545
|
-
const CHUNK_SIZE = 5;
|
|
93546
|
-
const total = fileNodes.length;
|
|
93547
|
-
for (let i = 0;i < total; i += CHUNK_SIZE) {
|
|
93548
|
-
const chunk = fileNodes.slice(i, i + CHUNK_SIZE);
|
|
93549
|
-
const entries = chunk.map((node) => {
|
|
93550
|
-
const raw2 = readFileContent2(node.fullPath);
|
|
93551
|
-
const { frontmatter, body } = parseFrontmatter2(raw2);
|
|
93552
|
-
const desc = frontmatter.description;
|
|
93553
|
-
return {
|
|
93554
|
-
relative_path: node.relativePath,
|
|
93555
|
-
is_system: node.relativePath.startsWith("system/") || node.relativePath.startsWith("system\\"),
|
|
93556
|
-
description: typeof desc === "string" ? desc : null,
|
|
93557
|
-
content: body,
|
|
93558
|
-
size: body.length,
|
|
93559
|
-
...includeReferences ? {
|
|
93560
|
-
references: extractMemoryReferences(body, node.relativePath)
|
|
93561
|
-
} : {}
|
|
93562
|
-
};
|
|
93563
|
-
});
|
|
93564
|
-
const done = i + CHUNK_SIZE >= total;
|
|
93565
|
-
const sent = safeSocketSend(socket, {
|
|
93566
|
-
type: "list_memory_response",
|
|
93567
|
-
request_id: parsed.request_id,
|
|
93568
|
-
entries,
|
|
93569
|
-
done,
|
|
93570
|
-
total,
|
|
93571
|
-
success: true,
|
|
93572
|
-
memfs_initialized: true
|
|
93573
|
-
}, "listener_list_memory_send_failed", "listener_list_memory");
|
|
93574
|
-
if (!sent) {
|
|
93575
|
-
return;
|
|
93576
|
-
}
|
|
93577
|
-
}
|
|
93578
|
-
if (total === 0) {
|
|
93579
|
-
safeSocketSend(socket, {
|
|
93580
|
-
type: "list_memory_response",
|
|
93581
|
-
request_id: parsed.request_id,
|
|
93582
|
-
entries: [],
|
|
93583
|
-
done: true,
|
|
93584
|
-
total: 0,
|
|
93585
|
-
success: true,
|
|
93586
|
-
memfs_initialized: true
|
|
93587
|
-
}, "listener_list_memory_send_failed", "listener_list_memory");
|
|
93588
|
-
}
|
|
93589
|
-
} catch (err) {
|
|
93590
|
-
trackListenerError("listener_list_memory_failed", err, "listener_memory_browser");
|
|
93591
|
-
safeSocketSend(socket, {
|
|
93592
|
-
type: "list_memory_response",
|
|
93593
|
-
request_id: parsed.request_id,
|
|
93594
|
-
entries: [],
|
|
93595
|
-
done: true,
|
|
93596
|
-
total: 0,
|
|
93597
|
-
success: false,
|
|
93598
|
-
error: err instanceof Error ? err.message : "Failed to list memory"
|
|
93599
|
-
}, "listener_list_memory_send_failed", "listener_list_memory");
|
|
93600
|
-
}
|
|
94316
|
+
await handleListMemoryCommand(parsed, socket);
|
|
93601
94317
|
});
|
|
93602
94318
|
return;
|
|
93603
94319
|
}
|
|
@@ -94275,6 +94991,7 @@ var init_client4 = __esm(async () => {
|
|
|
94275
94991
|
handleAbortMessageInput,
|
|
94276
94992
|
handleChangeDeviceStateInput,
|
|
94277
94993
|
handleCronCommand,
|
|
94994
|
+
handleListMemoryCommand,
|
|
94278
94995
|
isDetachedChannelsCommand,
|
|
94279
94996
|
handleChannelsProtocolCommand,
|
|
94280
94997
|
handleSkillCommand,
|
|
@@ -115359,16 +116076,16 @@ function clipStyledSpans(spans, maxColumns) {
|
|
|
115359
116076
|
return { spans: clipped, clipped: false };
|
|
115360
116077
|
}
|
|
115361
116078
|
function languageFromPath(filePath) {
|
|
115362
|
-
const
|
|
115363
|
-
const lower =
|
|
116079
|
+
const basename10 = filePath.split("/").pop() ?? filePath;
|
|
116080
|
+
const lower = basename10.toLowerCase();
|
|
115364
116081
|
if (lower === "makefile")
|
|
115365
116082
|
return "makefile";
|
|
115366
116083
|
if (lower === "dockerfile")
|
|
115367
116084
|
return "dockerfile";
|
|
115368
|
-
const dotIdx =
|
|
116085
|
+
const dotIdx = basename10.lastIndexOf(".");
|
|
115369
116086
|
if (dotIdx < 0)
|
|
115370
116087
|
return;
|
|
115371
|
-
const ext3 =
|
|
116088
|
+
const ext3 = basename10.slice(dotIdx + 1).toLowerCase();
|
|
115372
116089
|
return EXT_TO_LANG[ext3];
|
|
115373
116090
|
}
|
|
115374
116091
|
function colorForClassName(className, palette) {
|
|
@@ -121780,7 +122497,7 @@ var init_pasteRegistry = __esm(() => {
|
|
|
121780
122497
|
import { execFileSync as execFileSync3 } from "node:child_process";
|
|
121781
122498
|
import { existsSync as existsSync34, readFileSync as readFileSync20, statSync as statSync10, unlinkSync as unlinkSync10 } from "node:fs";
|
|
121782
122499
|
import { tmpdir as tmpdir4 } from "node:os";
|
|
121783
|
-
import { basename as
|
|
122500
|
+
import { basename as basename10, extname as extname8, isAbsolute as isAbsolute20, join as join42, resolve as resolve29 } from "node:path";
|
|
121784
122501
|
function countLines2(text) {
|
|
121785
122502
|
return (text.match(/\r\n|\r|\n/g) || []).length + 1;
|
|
121786
122503
|
}
|
|
@@ -121837,7 +122554,7 @@ function translatePasteForImages(paste) {
|
|
|
121837
122554
|
const id = allocateImage({
|
|
121838
122555
|
data: b64,
|
|
121839
122556
|
mediaType: mt,
|
|
121840
|
-
filename:
|
|
122557
|
+
filename: basename10(filePath)
|
|
121841
122558
|
});
|
|
121842
122559
|
s = `[Image #${id}]`;
|
|
121843
122560
|
}
|
|
@@ -123444,7 +124161,7 @@ __export(exports_custom, {
|
|
|
123444
124161
|
});
|
|
123445
124162
|
import { existsSync as existsSync36 } from "node:fs";
|
|
123446
124163
|
import { readdir as readdir10, readFile as readFile14 } from "node:fs/promises";
|
|
123447
|
-
import { basename as
|
|
124164
|
+
import { basename as basename11, dirname as dirname17, join as join44 } from "node:path";
|
|
123448
124165
|
async function getCustomCommands() {
|
|
123449
124166
|
if (cachedCommands !== null) {
|
|
123450
124167
|
return cachedCommands;
|
|
@@ -123504,7 +124221,7 @@ async function findCommandFiles(currentPath, rootPath, commands2, source2) {
|
|
|
123504
124221
|
async function parseCommandFile(filePath, rootPath, source2) {
|
|
123505
124222
|
const content = await readFile14(filePath, "utf-8");
|
|
123506
124223
|
const { frontmatter, body } = parseFrontmatter(content);
|
|
123507
|
-
const id =
|
|
124224
|
+
const id = basename11(filePath, ".md");
|
|
123508
124225
|
const relativePath = dirname17(filePath).slice(rootPath.length);
|
|
123509
124226
|
const namespace = relativePath.replace(/^[/\\]/, "") || undefined;
|
|
123510
124227
|
let description = getStringField(frontmatter, "description");
|
|
@@ -143505,6 +144222,10 @@ function App2({
|
|
|
143505
144222
|
import_react104.useEffect(() => {
|
|
143506
144223
|
conversationIdRef.current = conversationId;
|
|
143507
144224
|
}, [conversationId]);
|
|
144225
|
+
const setConversationIdAndRef = import_react104.useCallback((nextConversationId) => {
|
|
144226
|
+
conversationIdRef.current = nextConversationId;
|
|
144227
|
+
setConversationId3(nextConversationId);
|
|
144228
|
+
}, []);
|
|
143508
144229
|
const pendingTranscriptStartLineIndexRef = import_react104.useRef(null);
|
|
143509
144230
|
const lastRunIdRef = import_react104.useRef(null);
|
|
143510
144231
|
const resumeKey = useSuspend();
|
|
@@ -143528,10 +144249,9 @@ function App2({
|
|
|
143528
144249
|
import_react104.useEffect(() => {
|
|
143529
144250
|
if (initialConversationId !== prevInitialConversationIdRef.current) {
|
|
143530
144251
|
prevInitialConversationIdRef.current = initialConversationId;
|
|
143531
|
-
|
|
143532
|
-
setConversationId3(initialConversationId);
|
|
144252
|
+
setConversationIdAndRef(initialConversationId);
|
|
143533
144253
|
}
|
|
143534
|
-
}, [initialConversationId]);
|
|
144254
|
+
}, [initialConversationId, setConversationIdAndRef]);
|
|
143535
144255
|
import_react104.useEffect(() => {
|
|
143536
144256
|
if (agentId) {
|
|
143537
144257
|
setCurrentAgentId(agentId);
|
|
@@ -147022,7 +147742,7 @@ ${feedback}
|
|
|
147022
147742
|
const client = await getClient();
|
|
147023
147743
|
const resumeData = await getResumeData2(client, agentState, conversationId2);
|
|
147024
147744
|
await maybeCarryOverActiveConversationModel(conversationId2);
|
|
147025
|
-
|
|
147745
|
+
setConversationIdAndRef(conversationId2);
|
|
147026
147746
|
pendingConversationSwitchRef.current = {
|
|
147027
147747
|
origin: "fork",
|
|
147028
147748
|
conversationId: conversationId2,
|
|
@@ -147087,6 +147807,7 @@ ${feedback}
|
|
|
147087
147807
|
runEndHooks,
|
|
147088
147808
|
maybeCarryOverActiveConversationModel,
|
|
147089
147809
|
resetBootstrapReminderState,
|
|
147810
|
+
setConversationIdAndRef,
|
|
147090
147811
|
setCommandRunning,
|
|
147091
147812
|
setStreaming,
|
|
147092
147813
|
recoverRestoredPendingApprovals,
|
|
@@ -147139,7 +147860,7 @@ ${feedback}
|
|
|
147139
147860
|
setLlmConfig(agent.llm_config);
|
|
147140
147861
|
const agentModelHandle = getPreferredAgentModelHandle2(agent);
|
|
147141
147862
|
setCurrentModelHandle(agentModelHandle);
|
|
147142
|
-
|
|
147863
|
+
setConversationIdAndRef(targetConversationId);
|
|
147143
147864
|
resetBootstrapReminderState();
|
|
147144
147865
|
{
|
|
147145
147866
|
const { getModelDisplayName: getModelDisplayName3 } = await Promise.resolve().then(() => (init_model2(), exports_model2));
|
|
@@ -147192,7 +147913,8 @@ ${feedback}
|
|
|
147192
147913
|
resetDeferredToolCallCommits,
|
|
147193
147914
|
resetTrajectoryBases,
|
|
147194
147915
|
resetBootstrapReminderState,
|
|
147195
|
-
resetPendingReasoningCycle
|
|
147916
|
+
resetPendingReasoningCycle,
|
|
147917
|
+
setConversationIdAndRef
|
|
147196
147918
|
]);
|
|
147197
147919
|
const handleCreateNewAgent = import_react104.useCallback(async (name) => {
|
|
147198
147920
|
setActiveOverlay(null);
|
|
@@ -147260,7 +147982,7 @@ ${feedback}
|
|
|
147260
147982
|
setLlmConfig(agent.llm_config);
|
|
147261
147983
|
const agentModelHandle = getPreferredAgentModelHandle2(agent);
|
|
147262
147984
|
setCurrentModelHandle(agentModelHandle);
|
|
147263
|
-
|
|
147985
|
+
setConversationIdAndRef(targetConversationId);
|
|
147264
147986
|
pendingConversationSwitchRef.current = {
|
|
147265
147987
|
origin: "agent-switch",
|
|
147266
147988
|
conversationId: targetConversationId,
|
|
@@ -147294,7 +148016,8 @@ ${feedback}
|
|
|
147294
148016
|
setCommandRunning,
|
|
147295
148017
|
resetDeferredToolCallCommits,
|
|
147296
148018
|
resetTrajectoryBases,
|
|
147297
|
-
resetBootstrapReminderState
|
|
148019
|
+
resetBootstrapReminderState,
|
|
148020
|
+
setConversationIdAndRef
|
|
147298
148021
|
]);
|
|
147299
148022
|
const handleBashSubmit = import_react104.useCallback(async (command) => {
|
|
147300
148023
|
if (bashRunning)
|
|
@@ -148235,7 +148958,7 @@ Type your task to begin the loop.`, true);
|
|
|
148235
148958
|
hasSetConversationSummaryRef.current = true;
|
|
148236
148959
|
}
|
|
148237
148960
|
await maybeCarryOverActiveConversationModel(conversation.id);
|
|
148238
|
-
|
|
148961
|
+
setConversationIdAndRef(conversation.id);
|
|
148239
148962
|
pendingConversationSwitchRef.current = {
|
|
148240
148963
|
origin: "new",
|
|
148241
148964
|
conversationId: conversation.id,
|
|
@@ -148280,7 +149003,7 @@ Type your task to begin the loop.`, true);
|
|
|
148280
149003
|
hasSetConversationSummaryRef.current = true;
|
|
148281
149004
|
}
|
|
148282
149005
|
await maybeCarryOverActiveConversationModel(forked.id);
|
|
148283
|
-
|
|
149006
|
+
setConversationIdAndRef(forked.id);
|
|
148284
149007
|
pendingConversationSwitchRef.current = {
|
|
148285
149008
|
origin: "fork",
|
|
148286
149009
|
conversationId: forked.id,
|
|
@@ -148334,7 +149057,7 @@ Type your task to begin the loop.`, true);
|
|
|
148334
149057
|
isolated_block_labels: [...ISOLATED_BLOCK_LABELS]
|
|
148335
149058
|
});
|
|
148336
149059
|
await maybeCarryOverActiveConversationModel(conversation.id);
|
|
148337
|
-
|
|
149060
|
+
setConversationIdAndRef(conversation.id);
|
|
148338
149061
|
pendingConversationSwitchRef.current = {
|
|
148339
149062
|
origin: "clear",
|
|
148340
149063
|
conversationId: conversation.id,
|
|
@@ -148585,7 +149308,7 @@ Type your task to begin the loop.`, true);
|
|
|
148585
149308
|
if (agentState) {
|
|
148586
149309
|
const client = await getClient();
|
|
148587
149310
|
const resumeData = await getResumeData2(client, agentState, targetConvId);
|
|
148588
|
-
|
|
149311
|
+
setConversationIdAndRef(targetConvId);
|
|
148589
149312
|
pendingConversationSwitchRef.current = {
|
|
148590
149313
|
origin: "resume-direct",
|
|
148591
149314
|
conversationId: targetConvId,
|
|
@@ -149520,7 +150243,7 @@ ${SYSTEM_REMINDER_CLOSE}
|
|
|
149520
150243
|
name: agentName,
|
|
149521
150244
|
description: agentDescription,
|
|
149522
150245
|
lastRunAt: agentLastRunAt,
|
|
149523
|
-
conversationId
|
|
150246
|
+
conversationId: conversationIdRef.current
|
|
149524
150247
|
},
|
|
149525
150248
|
state: sharedReminderStateRef.current,
|
|
149526
150249
|
sessionContextReminderEnabled,
|
|
@@ -149973,6 +150696,7 @@ ${SYSTEM_REMINDER_CLOSE}
|
|
|
149973
150696
|
agentName,
|
|
149974
150697
|
agentDescription,
|
|
149975
150698
|
agentLastRunAt,
|
|
150699
|
+
conversationId,
|
|
149976
150700
|
commandRunner,
|
|
149977
150701
|
handleExit,
|
|
149978
150702
|
isExecutingTool,
|
|
@@ -149991,7 +150715,8 @@ ${SYSTEM_REMINDER_CLOSE}
|
|
|
149991
150715
|
resetTrajectoryBases,
|
|
149992
150716
|
sessionContextReminderEnabled,
|
|
149993
150717
|
appendTaskNotificationEvents,
|
|
149994
|
-
maybeCarryOverActiveConversationModel
|
|
150718
|
+
maybeCarryOverActiveConversationModel,
|
|
150719
|
+
setConversationIdAndRef
|
|
149995
150720
|
]);
|
|
149996
150721
|
const onSubmitRef = import_react104.useRef(onSubmit);
|
|
149997
150722
|
import_react104.useEffect(() => {
|
|
@@ -150991,7 +151716,7 @@ ${guidance}`);
|
|
|
150991
151716
|
const client = await getClient();
|
|
150992
151717
|
if (agentState) {
|
|
150993
151718
|
const resumeData = await getResumeData2(client, agentState, action.conversationId);
|
|
150994
|
-
|
|
151719
|
+
setConversationIdAndRef(action.conversationId);
|
|
150995
151720
|
pendingConversationSwitchRef.current = {
|
|
150996
151721
|
origin: "resume-selector",
|
|
150997
151722
|
conversationId: action.conversationId,
|
|
@@ -151044,7 +151769,8 @@ ${guidance}`);
|
|
|
151044
151769
|
commandRunner.getHandle,
|
|
151045
151770
|
commandRunner.start,
|
|
151046
151771
|
recoverRestoredPendingApprovals,
|
|
151047
|
-
resetBootstrapReminderState
|
|
151772
|
+
resetBootstrapReminderState,
|
|
151773
|
+
setConversationIdAndRef
|
|
151048
151774
|
]);
|
|
151049
151775
|
const handleFeedbackSubmit = import_react104.useCallback(async (message) => {
|
|
151050
151776
|
const overlayCommand = consumeOverlayCommand("feedback");
|
|
@@ -152302,7 +153028,7 @@ If using apply_patch, use this exact relative patch path: ${applyPatchRelativePa
|
|
|
152302
153028
|
if (agentState) {
|
|
152303
153029
|
const client = await getClient();
|
|
152304
153030
|
const resumeData = await getResumeData2(client, agentState, convId);
|
|
152305
|
-
|
|
153031
|
+
setConversationIdAndRef(convId);
|
|
152306
153032
|
pendingConversationSwitchRef.current = {
|
|
152307
153033
|
origin: "resume-selector",
|
|
152308
153034
|
conversationId: convId,
|
|
@@ -152414,7 +153140,7 @@ If using apply_patch, use this exact relative patch path: ${applyPatchRelativePa
|
|
|
152414
153140
|
isolated_block_labels: [...ISOLATED_BLOCK_LABELS]
|
|
152415
153141
|
});
|
|
152416
153142
|
await maybeCarryOverActiveConversationModel(conversation.id);
|
|
152417
|
-
|
|
153143
|
+
setConversationIdAndRef(conversation.id);
|
|
152418
153144
|
settingsManager.persistSession(agentId, conversation.id);
|
|
152419
153145
|
const currentAgentName = agentState?.name || "Unnamed Agent";
|
|
152420
153146
|
const shortConvId = conversation.id.slice(0, 20);
|
|
@@ -152498,7 +153224,7 @@ If using apply_patch, use this exact relative patch path: ${applyPatchRelativePa
|
|
|
152498
153224
|
if (agentState) {
|
|
152499
153225
|
const client = await getClient();
|
|
152500
153226
|
const resumeData = await getResumeData2(client, agentState, actualTargetConv);
|
|
152501
|
-
|
|
153227
|
+
setConversationIdAndRef(actualTargetConv);
|
|
152502
153228
|
pendingConversationSwitchRef.current = {
|
|
152503
153229
|
origin: "search",
|
|
152504
153230
|
conversationId: actualTargetConv,
|
|
@@ -153870,10 +154596,12 @@ var exports_memoryFilesystem2 = {};
|
|
|
153870
154596
|
__export(exports_memoryFilesystem2, {
|
|
153871
154597
|
renderMemoryFilesystemTree: () => renderMemoryFilesystemTree2,
|
|
153872
154598
|
labelFromRelativePath: () => labelFromRelativePath2,
|
|
154599
|
+
isMemfsEnabledOnServer: () => isMemfsEnabledOnServer2,
|
|
153873
154600
|
isLettaCloud: () => isLettaCloud2,
|
|
153874
154601
|
getMemorySystemDir: () => getMemorySystemDir2,
|
|
153875
154602
|
getMemoryFilesystemRoot: () => getMemoryFilesystemRoot2,
|
|
153876
154603
|
ensureMemoryFilesystemDirs: () => ensureMemoryFilesystemDirs2,
|
|
154604
|
+
ensureLocalMemfsCheckout: () => ensureLocalMemfsCheckout2,
|
|
153877
154605
|
enableMemfsIfCloud: () => enableMemfsIfCloud2,
|
|
153878
154606
|
applyMemfsFlags: () => applyMemfsFlags2,
|
|
153879
154607
|
MEMORY_TREE_MAX_LINES: () => MEMORY_TREE_MAX_LINES2,
|
|
@@ -153903,6 +154631,23 @@ function ensureMemoryFilesystemDirs2(agentId, homeDir = homedir41()) {
|
|
|
153903
154631
|
mkdirSync30(systemDir, { recursive: true });
|
|
153904
154632
|
}
|
|
153905
154633
|
}
|
|
154634
|
+
async function isMemfsEnabledOnServer2(agentId) {
|
|
154635
|
+
const { getClient: getClient3 } = await Promise.resolve().then(() => (init_client2(), exports_client));
|
|
154636
|
+
const client = await getClient3();
|
|
154637
|
+
const agent = await client.agents.retrieve(agentId);
|
|
154638
|
+
const { GIT_MEMORY_ENABLED_TAG: GIT_MEMORY_ENABLED_TAG2 } = await Promise.resolve().then(() => (init_memoryGit(), exports_memoryGit));
|
|
154639
|
+
const enabled = agent.tags?.includes(GIT_MEMORY_ENABLED_TAG2) ?? false;
|
|
154640
|
+
const { settingsManager: settingsManager3 } = await Promise.resolve().then(() => (init_settings_manager(), exports_settings_manager));
|
|
154641
|
+
settingsManager3.setMemfsEnabled(agentId, enabled);
|
|
154642
|
+
return enabled;
|
|
154643
|
+
}
|
|
154644
|
+
async function ensureLocalMemfsCheckout2(agentId) {
|
|
154645
|
+
const { isGitRepo: isGitRepo2, cloneMemoryRepo: cloneMemoryRepo2 } = await Promise.resolve().then(() => (init_memoryGit(), exports_memoryGit));
|
|
154646
|
+
if (isGitRepo2(agentId)) {
|
|
154647
|
+
return;
|
|
154648
|
+
}
|
|
154649
|
+
await cloneMemoryRepo2(agentId);
|
|
154650
|
+
}
|
|
153906
154651
|
function labelFromRelativePath2(relativePath) {
|
|
153907
154652
|
const normalized = relativePath.replace(/\\/g, "/");
|
|
153908
154653
|
return normalized.replace(/\.md$/, "");
|
|
@@ -161433,20 +162178,21 @@ await __promiseAll([
|
|
|
161433
162178
|
init_toolDefinitions()
|
|
161434
162179
|
]);
|
|
161435
162180
|
var TOOL_NAMES2 = Object.keys(TOOL_DEFINITIONS);
|
|
161436
|
-
function maybeAppendChannelTools2(toolNames) {
|
|
161437
|
-
|
|
162181
|
+
function maybeAppendChannelTools2(toolNames, channelToolScope) {
|
|
162182
|
+
const hasActiveChannelTools = channelToolScope !== undefined ? (channelToolScope?.channels.length ?? 0) > 0 : getActiveChannelIds().length > 0;
|
|
162183
|
+
if (hasActiveChannelTools && !toolNames.includes("MessageChannel")) {
|
|
161438
162184
|
return [...toolNames, "MessageChannel"];
|
|
161439
162185
|
}
|
|
161440
162186
|
return toolNames;
|
|
161441
162187
|
}
|
|
161442
|
-
async function maybeResolveDynamicChannelTool2(name, description, schema) {
|
|
162188
|
+
async function maybeResolveDynamicChannelTool2(name, description, schema, channelToolScope) {
|
|
161443
162189
|
if (name !== "MessageChannel") {
|
|
161444
162190
|
return {
|
|
161445
162191
|
description,
|
|
161446
162192
|
input_schema: schema
|
|
161447
162193
|
};
|
|
161448
162194
|
}
|
|
161449
|
-
const resolved = await buildDynamicMessageChannelToolDefinition(description, schema);
|
|
162195
|
+
const resolved = await buildDynamicMessageChannelToolDefinition(description, schema, channelToolScope);
|
|
161450
162196
|
return {
|
|
161451
162197
|
description: resolved.description,
|
|
161452
162198
|
input_schema: resolved.schema
|
|
@@ -161591,7 +162337,7 @@ async function resolveBaseToolNamesForModel2(modelIdentifier, options) {
|
|
|
161591
162337
|
const excludeSet = new Set(options.exclude);
|
|
161592
162338
|
baseToolNames = baseToolNames.filter((name) => !excludeSet.has(name));
|
|
161593
162339
|
}
|
|
161594
|
-
baseToolNames = maybeAppendChannelTools2(baseToolNames);
|
|
162340
|
+
baseToolNames = maybeAppendChannelTools2(baseToolNames, options?.channelToolScope);
|
|
161595
162341
|
return baseToolNames;
|
|
161596
162342
|
}
|
|
161597
162343
|
async function buildRegistryForModel2(modelIdentifier, options) {
|
|
@@ -161620,7 +162366,7 @@ async function buildRegistryForModel2(modelIdentifier, options) {
|
|
|
161620
162366
|
if (name === "Task" && discoveredSubagents.length > 0) {
|
|
161621
162367
|
description = injectSubagentsIntoTaskDescription2(description, discoveredSubagents);
|
|
161622
162368
|
}
|
|
161623
|
-
const resolvedTool = await maybeResolveDynamicChannelTool2(name, description, definition.schema);
|
|
162369
|
+
const resolvedTool = await maybeResolveDynamicChannelTool2(name, description, definition.schema, options?.channelToolScope);
|
|
161624
162370
|
const toolSchema = {
|
|
161625
162371
|
name,
|
|
161626
162372
|
description: resolvedTool.description,
|
|
@@ -161694,6 +162440,8 @@ ${after}`;
|
|
|
161694
162440
|
init_client2();
|
|
161695
162441
|
init_model2();
|
|
161696
162442
|
init_registry();
|
|
162443
|
+
init_routing();
|
|
162444
|
+
init_types();
|
|
161697
162445
|
init_settings_manager();
|
|
161698
162446
|
init_filter();
|
|
161699
162447
|
await init_manager3();
|
|
@@ -163129,4 +163877,4 @@ Error during initialization: ${message}`);
|
|
|
163129
163877
|
}
|
|
163130
163878
|
main();
|
|
163131
163879
|
|
|
163132
|
-
//# debugId=
|
|
163880
|
+
//# debugId=E826850D234138B664756E2164756E21
|