@letta-ai/letta-code 0.30.15 → 0.30.17

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.
Files changed (34) hide show
  1. package/dist/channels-slack.js +232 -34
  2. package/dist/channels-slack.js.map +7 -5
  3. package/dist/mcp-client.js +2 -2
  4. package/dist/mcp-client.js.map +1 -1
  5. package/dist/types/agent/message.d.ts +2 -0
  6. package/dist/types/agent/message.d.ts.map +1 -1
  7. package/dist/types/channels/slack/ingress-policy.d.ts +2 -1
  8. package/dist/types/channels/slack/ingress-policy.d.ts.map +1 -1
  9. package/dist/types/channels/slack/model-picker-blocks.d.ts +10 -0
  10. package/dist/types/channels/slack/model-picker-blocks.d.ts.map +1 -0
  11. package/dist/types/channels/slack/utils.d.ts +0 -1
  12. package/dist/types/channels/slack/utils.d.ts.map +1 -1
  13. package/dist/types/channels-slack.d.ts +1 -0
  14. package/dist/types/channels-slack.d.ts.map +1 -1
  15. package/dist/types/mods/mod-engine.d.ts.map +1 -1
  16. package/dist/types/mods/turn-start-input.d.ts +5 -0
  17. package/dist/types/mods/turn-start-input.d.ts.map +1 -0
  18. package/dist/types/tools/impl/monitor.d.ts.map +1 -1
  19. package/dist/types/tools/impl/worktree-git.d.ts.map +1 -1
  20. package/dist/types/types/runtime-scope.d.ts +2 -0
  21. package/dist/types/types/runtime-scope.d.ts.map +1 -1
  22. package/dist/types/websocket/listener/protocol-outbound.d.ts +1 -2
  23. package/dist/types/websocket/listener/protocol-outbound.d.ts.map +1 -1
  24. package/dist/types/websocket/listener/runtime.d.ts.map +1 -1
  25. package/dist/types/websocket/listener/scope.d.ts +1 -0
  26. package/dist/types/websocket/listener/scope.d.ts.map +1 -1
  27. package/dist/types/websocket/listener/turn-lifecycle.d.ts +3 -0
  28. package/dist/types/websocket/listener/turn-lifecycle.d.ts.map +1 -1
  29. package/dist/types/websocket/listener/types.d.ts +4 -0
  30. package/dist/types/websocket/listener/types.d.ts.map +1 -1
  31. package/letta.js +307 -213
  32. package/package.json +1 -1
  33. package/scripts/isolated-unit-tests.json +22 -0
  34. package/scripts/source-file-size-baseline.json +2 -2
@@ -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, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
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=6D8D899D103859E164756E2164756E21
1200
+ //# debugId=58FD8893F1E7078D64756E2164756E21