@letta-ai/letta-code 0.30.16 → 0.30.18
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/channels-slack.js +232 -34
- package/dist/channels-slack.js.map +7 -5
- package/dist/mcp-client.js +2 -2
- package/dist/mcp-client.js.map +1 -1
- package/dist/types/agent/message.d.ts +0 -2
- package/dist/types/agent/message.d.ts.map +1 -1
- package/dist/types/channels/slack/ingress-policy.d.ts +2 -1
- package/dist/types/channels/slack/ingress-policy.d.ts.map +1 -1
- package/dist/types/channels/slack/model-picker-blocks.d.ts +10 -0
- package/dist/types/channels/slack/model-picker-blocks.d.ts.map +1 -0
- package/dist/types/channels/slack/utils.d.ts +0 -1
- package/dist/types/channels/slack/utils.d.ts.map +1 -1
- package/dist/types/channels-slack.d.ts +1 -0
- package/dist/types/channels-slack.d.ts.map +1 -1
- package/dist/types/types/runtime-scope.d.ts +0 -2
- package/dist/types/types/runtime-scope.d.ts.map +1 -1
- package/dist/types/websocket/listener/protocol-outbound.d.ts +2 -1
- package/dist/types/websocket/listener/protocol-outbound.d.ts.map +1 -1
- package/dist/types/websocket/listener/runtime.d.ts.map +1 -1
- package/dist/types/websocket/listener/scope.d.ts +0 -1
- package/dist/types/websocket/listener/scope.d.ts.map +1 -1
- package/dist/types/websocket/listener/turn-lifecycle.d.ts +0 -3
- package/dist/types/websocket/listener/turn-lifecycle.d.ts.map +1 -1
- package/dist/types/websocket/listener/types.d.ts +0 -4
- package/dist/types/websocket/listener/types.d.ts.map +1 -1
- package/letta.js +44 -94
- package/package.json +1 -1
- package/scripts/source-file-size-baseline.json +1 -1
package/dist/channels-slack.js
CHANGED
|
@@ -154,6 +154,9 @@ function resolveSlackMessageIngressPolicy(params) {
|
|
|
154
154
|
}
|
|
155
155
|
const rawText = isNonEmptyString2(message.text) ? message.text : "";
|
|
156
156
|
const wasMentioned = hasSlackMention(rawText, params.botUserId);
|
|
157
|
+
if (chatType === "channel" && wasMentioned && params.appMentionEventWillHandleMentions === true) {
|
|
158
|
+
return { shouldRoute: false, reason: "handled_by_app_mention" };
|
|
159
|
+
}
|
|
157
160
|
const isAgentThread = params.isAgentThread === true;
|
|
158
161
|
const effectiveMention = isBotAuthoredMessage(message) ? wasMentioned : wasMentioned || isAgentThread;
|
|
159
162
|
return {
|
|
@@ -339,6 +342,231 @@ function createSlackMessageActionAdapter(options = {}) {
|
|
|
339
342
|
}
|
|
340
343
|
};
|
|
341
344
|
}
|
|
345
|
+
// src/channels/command-runtime-executor.ts
|
|
346
|
+
function getModelEntryRank(entry) {
|
|
347
|
+
if (entry.isDefault)
|
|
348
|
+
return 0;
|
|
349
|
+
if (entry.isFeatured)
|
|
350
|
+
return 1;
|
|
351
|
+
const effort = entry.updateArgs?.reasoning_effort;
|
|
352
|
+
if (effort === "medium")
|
|
353
|
+
return 2;
|
|
354
|
+
if (effort === "high")
|
|
355
|
+
return 3;
|
|
356
|
+
return 4;
|
|
357
|
+
}
|
|
358
|
+
function preferModelEntry(current, candidate) {
|
|
359
|
+
return getModelEntryRank(candidate) < getModelEntryRank(current) ? candidate : current;
|
|
360
|
+
}
|
|
361
|
+
function buildModelEntriesByHandle(entries) {
|
|
362
|
+
const byHandle = new Map;
|
|
363
|
+
for (const entry of entries) {
|
|
364
|
+
const current = byHandle.get(entry.handle);
|
|
365
|
+
byHandle.set(entry.handle, current ? preferModelEntry(current, entry) : entry);
|
|
366
|
+
}
|
|
367
|
+
return byHandle;
|
|
368
|
+
}
|
|
369
|
+
function makeUnknownModelEntry(handle) {
|
|
370
|
+
return {
|
|
371
|
+
id: handle,
|
|
372
|
+
handle,
|
|
373
|
+
label: handle,
|
|
374
|
+
description: ""
|
|
375
|
+
};
|
|
376
|
+
}
|
|
377
|
+
function resolveModelHandles(params) {
|
|
378
|
+
const { handles, byHandle, availableHandles } = params;
|
|
379
|
+
const seen = new Set;
|
|
380
|
+
const resolved = [];
|
|
381
|
+
for (const handle of handles) {
|
|
382
|
+
if (!handle || seen.has(handle))
|
|
383
|
+
continue;
|
|
384
|
+
seen.add(handle);
|
|
385
|
+
if (availableHandles && !availableHandles.has(handle))
|
|
386
|
+
continue;
|
|
387
|
+
resolved.push(byHandle.get(handle) ?? makeUnknownModelEntry(handle));
|
|
388
|
+
}
|
|
389
|
+
return resolved;
|
|
390
|
+
}
|
|
391
|
+
function getFallbackModelEntries(byHandle) {
|
|
392
|
+
const preferred = Array.from(byHandle.values()).filter((entry) => entry.isDefault || entry.isFeatured);
|
|
393
|
+
return preferred.length > 0 ? preferred : Array.from(byHandle.values());
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
// src/channels/slack/utils.ts
|
|
397
|
+
function isNonEmptyString3(value) {
|
|
398
|
+
return typeof value === "string" && value.length > 0;
|
|
399
|
+
}
|
|
400
|
+
function firstNonEmptyString2(...values) {
|
|
401
|
+
return values.find(isNonEmptyString3);
|
|
402
|
+
}
|
|
403
|
+
function asRecord(value) {
|
|
404
|
+
return value && typeof value === "object" ? value : null;
|
|
405
|
+
}
|
|
406
|
+
var IGNORED_SLACK_MESSAGE_SUBTYPES2 = new Set([
|
|
407
|
+
"assistant_app_thread",
|
|
408
|
+
"channel_archive",
|
|
409
|
+
"channel_convert_to_private",
|
|
410
|
+
"channel_convert_to_public",
|
|
411
|
+
"channel_join",
|
|
412
|
+
"channel_leave",
|
|
413
|
+
"channel_name",
|
|
414
|
+
"channel_posting_permissions",
|
|
415
|
+
"channel_purpose",
|
|
416
|
+
"channel_topic",
|
|
417
|
+
"channel_unarchive",
|
|
418
|
+
"document_mention",
|
|
419
|
+
"ekm_access_denied",
|
|
420
|
+
"file_comment",
|
|
421
|
+
"group_archive",
|
|
422
|
+
"group_join",
|
|
423
|
+
"group_leave",
|
|
424
|
+
"group_name",
|
|
425
|
+
"group_purpose",
|
|
426
|
+
"group_topic",
|
|
427
|
+
"group_unarchive",
|
|
428
|
+
"pinned_item",
|
|
429
|
+
"reminder_add",
|
|
430
|
+
"unpinned_item"
|
|
431
|
+
]);
|
|
432
|
+
var WRAPPER_SLACK_MESSAGE_SUBTYPES2 = new Set([
|
|
433
|
+
"message_changed",
|
|
434
|
+
"message_deleted",
|
|
435
|
+
"message_replied"
|
|
436
|
+
]);
|
|
437
|
+
function getSlackActionRecord(action, body) {
|
|
438
|
+
const directAction = asRecord(action);
|
|
439
|
+
if (directAction) {
|
|
440
|
+
return directAction;
|
|
441
|
+
}
|
|
442
|
+
const actions = asRecord(body)?.actions;
|
|
443
|
+
return Array.isArray(actions) ? asRecord(actions[0]) : null;
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
// src/channels/slack/model-picker-blocks.ts
|
|
447
|
+
var SLACK_MODEL_PICKER_OPTION_LIMIT = 100;
|
|
448
|
+
var SLACK_MODEL_OPTION_TEXT_LIMIT = 75;
|
|
449
|
+
var SLACK_MODEL_OPTION_VALUE_LIMIT = 75;
|
|
450
|
+
var SLACK_MODEL_SELECT_ACTION_ID = "letta_channel_model_select";
|
|
451
|
+
function resolveSlackSelectedModel(action, body) {
|
|
452
|
+
const actionRecord = getSlackActionRecord(action, body);
|
|
453
|
+
const selectedOption = asRecord(actionRecord?.selected_option);
|
|
454
|
+
return firstNonEmptyString2(selectedOption?.value, actionRecord?.value) ?? null;
|
|
455
|
+
}
|
|
456
|
+
function escapeSlackMrkdwn(text) {
|
|
457
|
+
return text.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
|
|
458
|
+
}
|
|
459
|
+
function truncateSlackPlainText(text, limit) {
|
|
460
|
+
if (text.length <= limit) {
|
|
461
|
+
return text;
|
|
462
|
+
}
|
|
463
|
+
return `${text.slice(0, Math.max(0, limit - 3)).trimEnd()}...`;
|
|
464
|
+
}
|
|
465
|
+
function getSlackModelOptionValue(entry) {
|
|
466
|
+
const candidates = [entry.id, entry.handle].filter((value) => typeof value === "string" && value.length > 0);
|
|
467
|
+
return candidates.find((value) => value.length <= SLACK_MODEL_OPTION_VALUE_LIMIT) ?? null;
|
|
468
|
+
}
|
|
469
|
+
function buildSlackModelOption(entry) {
|
|
470
|
+
const value = getSlackModelOptionValue(entry);
|
|
471
|
+
if (!value) {
|
|
472
|
+
return null;
|
|
473
|
+
}
|
|
474
|
+
const labelText = entry.handle === entry.label ? entry.label : `${entry.label} - ${entry.handle}`;
|
|
475
|
+
const option = {
|
|
476
|
+
text: {
|
|
477
|
+
type: "plain_text",
|
|
478
|
+
text: truncateSlackPlainText(labelText, SLACK_MODEL_OPTION_TEXT_LIMIT),
|
|
479
|
+
emoji: true
|
|
480
|
+
},
|
|
481
|
+
value
|
|
482
|
+
};
|
|
483
|
+
if (entry.description) {
|
|
484
|
+
option.description = {
|
|
485
|
+
type: "plain_text",
|
|
486
|
+
text: truncateSlackPlainText(entry.description, SLACK_MODEL_OPTION_TEXT_LIMIT),
|
|
487
|
+
emoji: true
|
|
488
|
+
};
|
|
489
|
+
}
|
|
490
|
+
return option;
|
|
491
|
+
}
|
|
492
|
+
function buildSlackModelPickerBlocks(params) {
|
|
493
|
+
const entries = params.entries;
|
|
494
|
+
const byHandle = buildModelEntriesByHandle(entries);
|
|
495
|
+
const availableHandleList = Array.isArray(params.availableHandles) ? params.availableHandles : null;
|
|
496
|
+
const availableSet = availableHandleList ? new Set(availableHandleList) : null;
|
|
497
|
+
const recentEntries = resolveModelHandles({
|
|
498
|
+
handles: params.recentHandles ?? [],
|
|
499
|
+
byHandle,
|
|
500
|
+
availableHandles: availableSet
|
|
501
|
+
});
|
|
502
|
+
const availableEntries = availableHandleList ? resolveModelHandles({ handles: availableHandleList, byHandle }) : getFallbackModelEntries(byHandle);
|
|
503
|
+
const optionEntries = [...recentEntries, ...availableEntries];
|
|
504
|
+
const options = [];
|
|
505
|
+
const seenValues = new Set;
|
|
506
|
+
for (const entry of optionEntries) {
|
|
507
|
+
const option = buildSlackModelOption(entry);
|
|
508
|
+
if (!option || seenValues.has(option.value)) {
|
|
509
|
+
continue;
|
|
510
|
+
}
|
|
511
|
+
seenValues.add(option.value);
|
|
512
|
+
options.push(option);
|
|
513
|
+
if (options.length >= SLACK_MODEL_PICKER_OPTION_LIMIT) {
|
|
514
|
+
break;
|
|
515
|
+
}
|
|
516
|
+
}
|
|
517
|
+
if (options.length === 0) {
|
|
518
|
+
return;
|
|
519
|
+
}
|
|
520
|
+
const currentScope = params.current.scope === "agent" ? "agent" : "conversation";
|
|
521
|
+
const currentHandleText = params.current.modelHandle ? `
|
|
522
|
+
Handle: ${escapeSlackMrkdwn(params.current.modelHandle)}` : "";
|
|
523
|
+
const currentHandle = params.current.modelHandle;
|
|
524
|
+
const initialOption = options.find((option) => {
|
|
525
|
+
const entry = optionEntries.find((candidate) => candidate.id === option.value || candidate.handle === option.value);
|
|
526
|
+
return currentHandle ? entry?.handle === currentHandle || option.value === currentHandle : false;
|
|
527
|
+
});
|
|
528
|
+
return [
|
|
529
|
+
{
|
|
530
|
+
type: "section",
|
|
531
|
+
text: {
|
|
532
|
+
type: "mrkdwn",
|
|
533
|
+
text: `*Current ${currentScope} model:* ${escapeSlackMrkdwn(params.current.modelLabel)}${currentHandleText}`
|
|
534
|
+
}
|
|
535
|
+
},
|
|
536
|
+
{
|
|
537
|
+
type: "section",
|
|
538
|
+
text: {
|
|
539
|
+
type: "mrkdwn",
|
|
540
|
+
text: "Choose a model for this routed conversation:"
|
|
541
|
+
}
|
|
542
|
+
},
|
|
543
|
+
{
|
|
544
|
+
type: "actions",
|
|
545
|
+
elements: [
|
|
546
|
+
{
|
|
547
|
+
type: "static_select",
|
|
548
|
+
action_id: SLACK_MODEL_SELECT_ACTION_ID,
|
|
549
|
+
placeholder: {
|
|
550
|
+
type: "plain_text",
|
|
551
|
+
text: "Select a model",
|
|
552
|
+
emoji: true
|
|
553
|
+
},
|
|
554
|
+
options,
|
|
555
|
+
...initialOption ? { initial_option: initialOption } : {}
|
|
556
|
+
}
|
|
557
|
+
]
|
|
558
|
+
},
|
|
559
|
+
{
|
|
560
|
+
type: "context",
|
|
561
|
+
elements: [
|
|
562
|
+
{
|
|
563
|
+
type: "mrkdwn",
|
|
564
|
+
text: "Need another handle? Mention the app with `@agent /model <handle-or-id>`."
|
|
565
|
+
}
|
|
566
|
+
]
|
|
567
|
+
}
|
|
568
|
+
];
|
|
569
|
+
}
|
|
342
570
|
// src/agent/agent-id.ts
|
|
343
571
|
function isLocalAgentId(agentId) {
|
|
344
572
|
return agentId.startsWith("agent-local-");
|
|
@@ -599,39 +827,6 @@ function resolveSlackConcreteActivity(event) {
|
|
|
599
827
|
}
|
|
600
828
|
return null;
|
|
601
829
|
}
|
|
602
|
-
// src/channels/slack/utils.ts
|
|
603
|
-
var IGNORED_SLACK_MESSAGE_SUBTYPES2 = new Set([
|
|
604
|
-
"assistant_app_thread",
|
|
605
|
-
"channel_archive",
|
|
606
|
-
"channel_convert_to_private",
|
|
607
|
-
"channel_convert_to_public",
|
|
608
|
-
"channel_join",
|
|
609
|
-
"channel_leave",
|
|
610
|
-
"channel_name",
|
|
611
|
-
"channel_posting_permissions",
|
|
612
|
-
"channel_purpose",
|
|
613
|
-
"channel_topic",
|
|
614
|
-
"channel_unarchive",
|
|
615
|
-
"document_mention",
|
|
616
|
-
"ekm_access_denied",
|
|
617
|
-
"file_comment",
|
|
618
|
-
"group_archive",
|
|
619
|
-
"group_join",
|
|
620
|
-
"group_leave",
|
|
621
|
-
"group_name",
|
|
622
|
-
"group_purpose",
|
|
623
|
-
"group_topic",
|
|
624
|
-
"group_unarchive",
|
|
625
|
-
"pinned_item",
|
|
626
|
-
"reminder_add",
|
|
627
|
-
"unpinned_item"
|
|
628
|
-
]);
|
|
629
|
-
var WRAPPER_SLACK_MESSAGE_SUBTYPES2 = new Set([
|
|
630
|
-
"message_changed",
|
|
631
|
-
"message_deleted",
|
|
632
|
-
"message_replied"
|
|
633
|
-
]);
|
|
634
|
-
|
|
635
830
|
// src/channels/slack/presentation.ts
|
|
636
831
|
var SLACK_MARKDOWN_BLOCK_TEXT_MAX = 12000;
|
|
637
832
|
var SLACK_LIFECYCLE_ERROR_TEXT_MAX = 3000;
|
|
@@ -980,6 +1175,7 @@ export {
|
|
|
980
1175
|
shouldSkipSlackMessageByLastSeen,
|
|
981
1176
|
shouldPostSlackTerminalError,
|
|
982
1177
|
shouldAcceptSlackInboundBotMessage,
|
|
1178
|
+
resolveSlackSelectedModel,
|
|
983
1179
|
resolveSlackReactionIngressPolicy,
|
|
984
1180
|
resolveSlackOutboundThreadTs,
|
|
985
1181
|
resolveSlackMessageIngressPolicy,
|
|
@@ -995,8 +1191,10 @@ export {
|
|
|
995
1191
|
createSlackStatusController,
|
|
996
1192
|
createSlackMessageActionAdapter,
|
|
997
1193
|
createSlackChannelSender,
|
|
1194
|
+
buildSlackModelPickerBlocks,
|
|
1195
|
+
SLACK_MODEL_SELECT_ACTION_ID,
|
|
998
1196
|
SLACK_ASSISTANT_WORKING_STATUS,
|
|
999
1197
|
SLACK_ASSISTANT_STARTUP_STATUS
|
|
1000
1198
|
};
|
|
1001
1199
|
|
|
1002
|
-
//# debugId=
|
|
1200
|
+
//# debugId=58FD8893F1E7078D64756E2164756E21
|