@letta-ai/letta-code 0.28.7 → 0.28.8
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/agent-presets.js +80 -1
- package/dist/agent-presets.js.map +2 -2
- package/letta.js +467 -239
- package/package.json +1 -1
- package/scripts/source-file-size-baseline.json +2 -2
- package/skills/converting-mcps-to-skills/SKILL.md +44 -3
- package/skills/converting-mcps-to-skills/scripts/mcp-http.ts +696 -145
package/letta.js
CHANGED
|
@@ -4853,7 +4853,7 @@ var package_default;
|
|
|
4853
4853
|
var init_package = __esm(() => {
|
|
4854
4854
|
package_default = {
|
|
4855
4855
|
name: "@letta-ai/letta-code",
|
|
4856
|
-
version: "0.28.
|
|
4856
|
+
version: "0.28.8",
|
|
4857
4857
|
description: "Letta Code is a CLI tool for interacting with stateful Letta agents from the terminal.",
|
|
4858
4858
|
type: "module",
|
|
4859
4859
|
packageManager: "bun@1.3.0",
|
|
@@ -159689,6 +159689,85 @@ var init_models7 = __esm(() => {
|
|
|
159689
159689
|
parallel_tool_calls: true
|
|
159690
159690
|
}
|
|
159691
159691
|
},
|
|
159692
|
+
{
|
|
159693
|
+
id: "gpt-5.6-luna-plus-pro-none",
|
|
159694
|
+
handle: "chatgpt-plus-pro/gpt-5.6-luna",
|
|
159695
|
+
label: "GPT-5.6 Luna (ChatGPT)",
|
|
159696
|
+
description: "GPT-5.6 Luna (no reasoning) via ChatGPT Plus/Pro",
|
|
159697
|
+
updateArgs: {
|
|
159698
|
+
reasoning_effort: "none",
|
|
159699
|
+
verbosity: "low",
|
|
159700
|
+
context_window: 272000,
|
|
159701
|
+
max_output_tokens: 128000,
|
|
159702
|
+
parallel_tool_calls: true
|
|
159703
|
+
}
|
|
159704
|
+
},
|
|
159705
|
+
{
|
|
159706
|
+
id: "gpt-5.6-luna-plus-pro-low",
|
|
159707
|
+
handle: "chatgpt-plus-pro/gpt-5.6-luna",
|
|
159708
|
+
label: "GPT-5.6 Luna (ChatGPT)",
|
|
159709
|
+
description: "GPT-5.6 Luna (low reasoning) via ChatGPT Plus/Pro",
|
|
159710
|
+
updateArgs: {
|
|
159711
|
+
reasoning_effort: "low",
|
|
159712
|
+
verbosity: "low",
|
|
159713
|
+
context_window: 272000,
|
|
159714
|
+
max_output_tokens: 128000,
|
|
159715
|
+
parallel_tool_calls: true
|
|
159716
|
+
}
|
|
159717
|
+
},
|
|
159718
|
+
{
|
|
159719
|
+
id: "gpt-5.6-luna-plus-pro-medium",
|
|
159720
|
+
handle: "chatgpt-plus-pro/gpt-5.6-luna",
|
|
159721
|
+
label: "GPT-5.6 Luna (ChatGPT)",
|
|
159722
|
+
description: "GPT-5.6 Luna (med reasoning) via ChatGPT Plus/Pro",
|
|
159723
|
+
updateArgs: {
|
|
159724
|
+
reasoning_effort: "medium",
|
|
159725
|
+
verbosity: "low",
|
|
159726
|
+
context_window: 272000,
|
|
159727
|
+
max_output_tokens: 128000,
|
|
159728
|
+
parallel_tool_calls: true
|
|
159729
|
+
}
|
|
159730
|
+
},
|
|
159731
|
+
{
|
|
159732
|
+
id: "gpt-5.6-luna-plus-pro-high",
|
|
159733
|
+
handle: "chatgpt-plus-pro/gpt-5.6-luna",
|
|
159734
|
+
label: "GPT-5.6 Luna (ChatGPT)",
|
|
159735
|
+
description: "GPT-5.6 Luna (high reasoning) via ChatGPT Plus/Pro",
|
|
159736
|
+
updateArgs: {
|
|
159737
|
+
reasoning_effort: "high",
|
|
159738
|
+
verbosity: "low",
|
|
159739
|
+
context_window: 272000,
|
|
159740
|
+
max_output_tokens: 128000,
|
|
159741
|
+
parallel_tool_calls: true
|
|
159742
|
+
},
|
|
159743
|
+
isFeatured: true
|
|
159744
|
+
},
|
|
159745
|
+
{
|
|
159746
|
+
id: "gpt-5.6-luna-plus-pro-xhigh",
|
|
159747
|
+
handle: "chatgpt-plus-pro/gpt-5.6-luna",
|
|
159748
|
+
label: "GPT-5.6 Luna (ChatGPT)",
|
|
159749
|
+
description: "GPT-5.6 Luna (extra-high reasoning) via ChatGPT Plus/Pro",
|
|
159750
|
+
updateArgs: {
|
|
159751
|
+
reasoning_effort: "xhigh",
|
|
159752
|
+
verbosity: "low",
|
|
159753
|
+
context_window: 272000,
|
|
159754
|
+
max_output_tokens: 128000,
|
|
159755
|
+
parallel_tool_calls: true
|
|
159756
|
+
}
|
|
159757
|
+
},
|
|
159758
|
+
{
|
|
159759
|
+
id: "gpt-5.6-luna-plus-pro-max",
|
|
159760
|
+
handle: "chatgpt-plus-pro/gpt-5.6-luna",
|
|
159761
|
+
label: "GPT-5.6 Luna (ChatGPT)",
|
|
159762
|
+
description: "GPT-5.6 Luna (max reasoning) via ChatGPT Plus/Pro",
|
|
159763
|
+
updateArgs: {
|
|
159764
|
+
reasoning_effort: "max",
|
|
159765
|
+
verbosity: "low",
|
|
159766
|
+
context_window: 272000,
|
|
159767
|
+
max_output_tokens: 128000,
|
|
159768
|
+
parallel_tool_calls: true
|
|
159769
|
+
}
|
|
159770
|
+
},
|
|
159692
159771
|
{
|
|
159693
159772
|
id: "fable",
|
|
159694
159773
|
handle: "anthropic/claude-fable-5",
|
|
@@ -162195,6 +162274,44 @@ var init_mode = __esm(() => {
|
|
|
162195
162274
|
permissionMode = new PermissionModeManager;
|
|
162196
162275
|
});
|
|
162197
162276
|
|
|
162277
|
+
// src/channels/slack/bot-policy.ts
|
|
162278
|
+
function isValidSlackAllowBotsConfigValue(value) {
|
|
162279
|
+
return value === undefined || value === false || value === "mentions";
|
|
162280
|
+
}
|
|
162281
|
+
function normalizeSlackAllowBotsMode(value) {
|
|
162282
|
+
if (value === "mentions")
|
|
162283
|
+
return "mentions";
|
|
162284
|
+
return false;
|
|
162285
|
+
}
|
|
162286
|
+
function resolveSlackAllowBotsMode(value) {
|
|
162287
|
+
if (value === "mentions")
|
|
162288
|
+
return "mentions";
|
|
162289
|
+
return "off";
|
|
162290
|
+
}
|
|
162291
|
+
function isNonEmptyString(value) {
|
|
162292
|
+
return typeof value === "string" && value.length > 0;
|
|
162293
|
+
}
|
|
162294
|
+
function isSlackBotAuthoredInboundMessage(message) {
|
|
162295
|
+
return isNonEmptyString(message.bot_id) || message.subtype === "bot_message";
|
|
162296
|
+
}
|
|
162297
|
+
function isOwnSlackBotInboundMessage(params) {
|
|
162298
|
+
return isNonEmptyString(params.botUserId) && params.message.user === params.botUserId || isNonEmptyString(params.botId) && params.message.bot_id === params.botId;
|
|
162299
|
+
}
|
|
162300
|
+
function shouldAcceptSlackInboundBotMessage(params) {
|
|
162301
|
+
if (isOwnSlackBotInboundMessage({
|
|
162302
|
+
message: params.message,
|
|
162303
|
+
botUserId: params.botUserId,
|
|
162304
|
+
botId: params.botId
|
|
162305
|
+
})) {
|
|
162306
|
+
return false;
|
|
162307
|
+
}
|
|
162308
|
+
if (!isSlackBotAuthoredInboundMessage(params.message)) {
|
|
162309
|
+
return true;
|
|
162310
|
+
}
|
|
162311
|
+
const mode = resolveSlackAllowBotsMode(params.allowBots);
|
|
162312
|
+
return mode === "mentions" && params.wasMentioned;
|
|
162313
|
+
}
|
|
162314
|
+
|
|
162198
162315
|
// src/channels/config.ts
|
|
162199
162316
|
import { existsSync as existsSync5, readFileSync as readFileSync4 } from "node:fs";
|
|
162200
162317
|
import { homedir as homedir5 } from "node:os";
|
|
@@ -162337,7 +162454,8 @@ var init_config2 = __esm(() => {
|
|
|
162337
162454
|
dmPolicy: parsed.dm_policy ?? "pairing",
|
|
162338
162455
|
allowedUsers: parsed.allowed_users ?? [],
|
|
162339
162456
|
transcribeVoice: parsed.transcribe_voice === true,
|
|
162340
|
-
listenMode: parsed.listen_mode === true
|
|
162457
|
+
listenMode: parsed.listen_mode === true,
|
|
162458
|
+
allowBots: normalizeSlackAllowBotsMode(parsed.allow_bots)
|
|
162341
162459
|
};
|
|
162342
162460
|
}
|
|
162343
162461
|
};
|
|
@@ -162591,7 +162709,7 @@ var init_plugin = __esm(() => {
|
|
|
162591
162709
|
});
|
|
162592
162710
|
|
|
162593
162711
|
// src/channels/schema-config.ts
|
|
162594
|
-
function
|
|
162712
|
+
function isNonEmptyString2(value) {
|
|
162595
162713
|
return typeof value === "string" && value.length > 0;
|
|
162596
162714
|
}
|
|
162597
162715
|
function parseSelectOptions(value) {
|
|
@@ -162604,7 +162722,7 @@ function parseSelectOptions(value) {
|
|
|
162604
162722
|
if (!isRecord(entry)) {
|
|
162605
162723
|
return null;
|
|
162606
162724
|
}
|
|
162607
|
-
if (!
|
|
162725
|
+
if (!isNonEmptyString2(entry.value) || !isNonEmptyString2(entry.label)) {
|
|
162608
162726
|
return null;
|
|
162609
162727
|
}
|
|
162610
162728
|
if (seen.has(entry.value)) {
|
|
@@ -162623,10 +162741,10 @@ function parseField(value) {
|
|
|
162623
162741
|
if (typeof type3 !== "string" || !FIELD_TYPES.has(type3)) {
|
|
162624
162742
|
return null;
|
|
162625
162743
|
}
|
|
162626
|
-
if (!
|
|
162744
|
+
if (!isNonEmptyString2(value.key) || !FIELD_KEY_PATTERN.test(value.key)) {
|
|
162627
162745
|
return null;
|
|
162628
162746
|
}
|
|
162629
|
-
if (!
|
|
162747
|
+
if (!isNonEmptyString2(value.label)) {
|
|
162630
162748
|
return null;
|
|
162631
162749
|
}
|
|
162632
162750
|
if (value.description !== undefined && typeof value.description !== "string") {
|
|
@@ -166094,6 +166212,7 @@ function normalizeLoadedAccount(account) {
|
|
|
166094
166212
|
delete next.progress_ui;
|
|
166095
166213
|
delete next.progressUi;
|
|
166096
166214
|
next.listenMode = next.listenMode === true;
|
|
166215
|
+
next.allowBots = normalizeSlackAllowBotsMode(next.allowBots);
|
|
166097
166216
|
}
|
|
166098
166217
|
if (isDiscordChannelAccount(next)) {
|
|
166099
166218
|
const migrated = migratePermissionMode(next.defaultPermissionMode ?? "standard");
|
|
@@ -166220,6 +166339,7 @@ function makeDefaultLegacyAccount(channelId) {
|
|
|
166220
166339
|
defaultPermissionMode: DEFAULT_SLACK_PERMISSION_MODE,
|
|
166221
166340
|
transcribeVoice: config3.transcribeVoice === true,
|
|
166222
166341
|
listenMode: config3.listenMode === true,
|
|
166342
|
+
allowBots: config3.allowBots ?? false,
|
|
166223
166343
|
createdAt: now,
|
|
166224
166344
|
updatedAt: now
|
|
166225
166345
|
};
|
|
@@ -166407,6 +166527,7 @@ var init_accounts = __esm(() => {
|
|
|
166407
166527
|
account_uuid: "accountUuid",
|
|
166408
166528
|
allowed_channels: "allowedChannels",
|
|
166409
166529
|
allowed_groups: "allowedGroups",
|
|
166530
|
+
allow_bots: "allowBots",
|
|
166410
166531
|
auto_thread_on_mention: "autoThreadOnMention",
|
|
166411
166532
|
base_url: "baseUrl",
|
|
166412
166533
|
acknowledge_message_reaction: "acknowledgeMessageReaction",
|
|
@@ -166708,11 +166829,11 @@ function resolveSlackAppConstructor(mod) {
|
|
|
166708
166829
|
}
|
|
166709
166830
|
return App;
|
|
166710
166831
|
}
|
|
166711
|
-
function
|
|
166832
|
+
function isNonEmptyString3(value) {
|
|
166712
166833
|
return typeof value === "string" && value.length > 0;
|
|
166713
166834
|
}
|
|
166714
166835
|
function firstNonEmptyString(...values2) {
|
|
166715
|
-
return values2.find(
|
|
166836
|
+
return values2.find(isNonEmptyString3);
|
|
166716
166837
|
}
|
|
166717
166838
|
function asRecord2(value) {
|
|
166718
166839
|
return value && typeof value === "object" ? value : null;
|
|
@@ -166725,10 +166846,10 @@ function normalizeSlackText(text) {
|
|
|
166725
166846
|
return text.replace(/^(?:\s*<@[A-Z0-9]+>\s*)+/, "").trim();
|
|
166726
166847
|
}
|
|
166727
166848
|
function isProcessableSlackInboundMessage(rawMessage) {
|
|
166728
|
-
if (
|
|
166849
|
+
if (!isNonEmptyString3(rawMessage.user) && !isNonEmptyString3(rawMessage.bot_id) || !isNonEmptyString3(rawMessage.ts) || rawMessage.hidden === true) {
|
|
166729
166850
|
return false;
|
|
166730
166851
|
}
|
|
166731
|
-
const subtype =
|
|
166852
|
+
const subtype = isNonEmptyString3(rawMessage.subtype) ? rawMessage.subtype : null;
|
|
166732
166853
|
if (!subtype) {
|
|
166733
166854
|
return true;
|
|
166734
166855
|
}
|
|
@@ -166812,16 +166933,15 @@ function resolveSlackUserDisplayName(userInfo) {
|
|
|
166812
166933
|
return firstNonEmptyString(profile?.display_name, profile?.real_name, user?.name);
|
|
166813
166934
|
}
|
|
166814
166935
|
function hasSlackMention(text, userId) {
|
|
166815
|
-
return
|
|
166936
|
+
return isNonEmptyString3(text) && isNonEmptyString3(userId) && (text.includes(`<@${userId}>`) || text.includes(`<@${userId}|`));
|
|
166816
166937
|
}
|
|
166817
166938
|
function isSlackFlatChannelThreadOpener(source2) {
|
|
166818
|
-
return source2.chatType === "channel" &&
|
|
166939
|
+
return source2.chatType === "channel" && isNonEmptyString3(source2.messageId) && (!isNonEmptyString3(source2.threadId) || source2.threadId === source2.messageId);
|
|
166819
166940
|
}
|
|
166820
166941
|
var IGNORED_SLACK_MESSAGE_SUBTYPES, WRAPPER_SLACK_MESSAGE_SUBTYPES;
|
|
166821
166942
|
var init_utils5 = __esm(() => {
|
|
166822
166943
|
IGNORED_SLACK_MESSAGE_SUBTYPES = new Set([
|
|
166823
166944
|
"assistant_app_thread",
|
|
166824
|
-
"bot_message",
|
|
166825
166945
|
"channel_archive",
|
|
166826
166946
|
"channel_convert_to_private",
|
|
166827
166947
|
"channel_convert_to_public",
|
|
@@ -166863,7 +166983,7 @@ async function resolveSlackAccountDisplayName(botToken, appToken) {
|
|
|
166863
166983
|
socketMode: true
|
|
166864
166984
|
});
|
|
166865
166985
|
const auth = await app.client.auth.test({ token: botToken });
|
|
166866
|
-
if (
|
|
166986
|
+
if (isNonEmptyString3(auth.user_id)) {
|
|
166867
166987
|
try {
|
|
166868
166988
|
const userInfo = await app.client.users.info({
|
|
166869
166989
|
token: botToken,
|
|
@@ -166875,7 +166995,7 @@ async function resolveSlackAccountDisplayName(botToken, appToken) {
|
|
|
166875
166995
|
}
|
|
166876
166996
|
} catch {}
|
|
166877
166997
|
}
|
|
166878
|
-
return
|
|
166998
|
+
return isNonEmptyString3(auth.user) ? auth.user : undefined;
|
|
166879
166999
|
}
|
|
166880
167000
|
var init_account_display2 = __esm(() => {
|
|
166881
167001
|
init_runtime2();
|
|
@@ -168247,10 +168367,10 @@ function formatSlackToolNameForDisplay(toolName) {
|
|
|
168247
168367
|
return isTaskTool(toolName) ? "Subagent" : getDisplayToolName(toolName);
|
|
168248
168368
|
}
|
|
168249
168369
|
function resolveSlackConcreteActivity(event2) {
|
|
168250
|
-
if (event2.kind === "command" &&
|
|
168370
|
+
if (event2.kind === "command" && isNonEmptyString3(event2.command)) {
|
|
168251
168371
|
return sanitizeSlackStatusText(formatSlackToolNameForDisplay(event2.command), SLACK_STATUS_TEXT_MAX);
|
|
168252
168372
|
}
|
|
168253
|
-
if (event2.kind !== "tool" || !
|
|
168373
|
+
if (event2.kind !== "tool" || !isNonEmptyString3(event2.toolName) || event2.toolName.toLowerCase() === "messagechannel") {
|
|
168254
168374
|
return null;
|
|
168255
168375
|
}
|
|
168256
168376
|
for (const description of [
|
|
@@ -168259,7 +168379,7 @@ function resolveSlackConcreteActivity(event2) {
|
|
|
168259
168379
|
isShellTool(event2.toolName) ? event2.message : undefined,
|
|
168260
168380
|
formatSlackToolNameForDisplay(event2.toolName)
|
|
168261
168381
|
]) {
|
|
168262
|
-
if (!
|
|
168382
|
+
if (!isNonEmptyString3(description)) {
|
|
168263
168383
|
continue;
|
|
168264
168384
|
}
|
|
168265
168385
|
const sanitized = sanitizeSlackStatusText(description, SLACK_STATUS_TEXT_MAX);
|
|
@@ -168311,12 +168431,12 @@ Run \`${toolName}\`?`
|
|
|
168311
168431
|
];
|
|
168312
168432
|
}
|
|
168313
168433
|
function parseSlackApprovalActionPayload(value) {
|
|
168314
|
-
if (!
|
|
168434
|
+
if (!isNonEmptyString3(value)) {
|
|
168315
168435
|
return null;
|
|
168316
168436
|
}
|
|
168317
168437
|
try {
|
|
168318
168438
|
const parsed = JSON.parse(value);
|
|
168319
|
-
if (!
|
|
168439
|
+
if (!isNonEmptyString3(parsed.requestId) || parsed.decision !== "allow" && parsed.decision !== "deny") {
|
|
168320
168440
|
return null;
|
|
168321
168441
|
}
|
|
168322
168442
|
return { requestId: parsed.requestId, decision: parsed.decision };
|
|
@@ -168513,16 +168633,16 @@ async function mapSlackThreadMessage(message, attachmentOptions, sourceThreadId)
|
|
|
168513
168633
|
const attachments = await resolveSlackMessageAttachments(message, attachmentOptions, sourceThreadId);
|
|
168514
168634
|
return {
|
|
168515
168635
|
text: resolveSlackThreadMessageText(message),
|
|
168516
|
-
userId:
|
|
168517
|
-
botId:
|
|
168518
|
-
ts:
|
|
168636
|
+
userId: isNonEmptyString4(message.user) ? message.user : undefined,
|
|
168637
|
+
botId: isNonEmptyString4(message.bot_id) ? message.bot_id : undefined,
|
|
168638
|
+
ts: isNonEmptyString4(message.ts) ? message.ts : undefined,
|
|
168519
168639
|
...attachments.length > 0 ? { attachments } : {}
|
|
168520
168640
|
};
|
|
168521
168641
|
}
|
|
168522
168642
|
function asRecord4(value) {
|
|
168523
168643
|
return value && typeof value === "object" ? value : null;
|
|
168524
168644
|
}
|
|
168525
|
-
function
|
|
168645
|
+
function isNonEmptyString4(value) {
|
|
168526
168646
|
return typeof value === "string" && value.trim().length > 0;
|
|
168527
168647
|
}
|
|
168528
168648
|
function normalizeSlackFileLike(value) {
|
|
@@ -168531,12 +168651,12 @@ function normalizeSlackFileLike(value) {
|
|
|
168531
168651
|
return null;
|
|
168532
168652
|
}
|
|
168533
168653
|
return {
|
|
168534
|
-
id:
|
|
168535
|
-
name:
|
|
168536
|
-
mimetype:
|
|
168654
|
+
id: isNonEmptyString4(record5.id) ? record5.id : undefined,
|
|
168655
|
+
name: isNonEmptyString4(record5.name) ? record5.name : undefined,
|
|
168656
|
+
mimetype: isNonEmptyString4(record5.mimetype) ? record5.mimetype : undefined,
|
|
168537
168657
|
size: typeof record5.size === "number" ? record5.size : undefined,
|
|
168538
|
-
url_private:
|
|
168539
|
-
url_private_download:
|
|
168658
|
+
url_private: isNonEmptyString4(record5.url_private) ? record5.url_private : undefined,
|
|
168659
|
+
url_private_download: isNonEmptyString4(record5.url_private_download) ? record5.url_private_download : undefined
|
|
168540
168660
|
};
|
|
168541
168661
|
}
|
|
168542
168662
|
function normalizeSlackAttachmentLike(value) {
|
|
@@ -168546,12 +168666,12 @@ function normalizeSlackAttachmentLike(value) {
|
|
|
168546
168666
|
}
|
|
168547
168667
|
const files = Array.isArray(record5.files) ? record5.files.map((entry) => normalizeSlackFileLike(entry)).filter((entry) => Boolean(entry)) : undefined;
|
|
168548
168668
|
return {
|
|
168549
|
-
text:
|
|
168550
|
-
fallback:
|
|
168551
|
-
pretext:
|
|
168552
|
-
author_name:
|
|
168553
|
-
title:
|
|
168554
|
-
image_url:
|
|
168669
|
+
text: isNonEmptyString4(record5.text) ? record5.text : undefined,
|
|
168670
|
+
fallback: isNonEmptyString4(record5.fallback) ? record5.fallback : undefined,
|
|
168671
|
+
pretext: isNonEmptyString4(record5.pretext) ? record5.pretext : undefined,
|
|
168672
|
+
author_name: isNonEmptyString4(record5.author_name) ? record5.author_name : undefined,
|
|
168673
|
+
title: isNonEmptyString4(record5.title) ? record5.title : undefined,
|
|
168674
|
+
image_url: isNonEmptyString4(record5.image_url) ? record5.image_url : undefined,
|
|
168555
168675
|
files
|
|
168556
168676
|
};
|
|
168557
168677
|
}
|
|
@@ -168584,7 +168704,7 @@ function resolveSlackThreadMessageText(message) {
|
|
|
168584
168704
|
if (text) {
|
|
168585
168705
|
return text;
|
|
168586
168706
|
}
|
|
168587
|
-
const attachmentTexts = Array.isArray(message.attachments) ? message.attachments.map((entry) => normalizeSlackAttachmentLike(entry)).filter((entry) => Boolean(entry)).map((attachment) => resolveSlackAttachmentText(attachment)).filter(
|
|
168707
|
+
const attachmentTexts = Array.isArray(message.attachments) ? message.attachments.map((entry) => normalizeSlackAttachmentLike(entry)).filter((entry) => Boolean(entry)).map((attachment) => resolveSlackAttachmentText(attachment)).filter(isNonEmptyString4) : [];
|
|
168588
168708
|
if (attachmentTexts.length > 0) {
|
|
168589
168709
|
return attachmentTexts.join(`
|
|
168590
168710
|
|
|
@@ -168885,7 +169005,7 @@ async function resolveSlackFilesAsAttachments(params) {
|
|
|
168885
169005
|
return resolved;
|
|
168886
169006
|
}
|
|
168887
169007
|
function resolveSlackThreadAttachmentOptions(params) {
|
|
168888
|
-
if (!
|
|
169008
|
+
if (!isNonEmptyString4(params.accountId) || !isNonEmptyString4(params.token)) {
|
|
168889
169009
|
return;
|
|
168890
169010
|
}
|
|
168891
169011
|
return {
|
|
@@ -168912,7 +169032,7 @@ async function resolveSlackMessageAttachments(message, attachmentOptions, source
|
|
|
168912
169032
|
token: attachmentOptions.token,
|
|
168913
169033
|
files: collectSlackFiles(message),
|
|
168914
169034
|
sourceMessageId: message.ts,
|
|
168915
|
-
sourceThreadId: sourceThreadId ?? (
|
|
169035
|
+
sourceThreadId: sourceThreadId ?? (isNonEmptyString4(message.thread_ts) ? message.thread_ts : null),
|
|
168916
169036
|
transcribeVoice: attachmentOptions.transcribeVoice
|
|
168917
169037
|
});
|
|
168918
169038
|
}
|
|
@@ -168922,8 +169042,8 @@ async function resolveSlackInboundAttachments(params) {
|
|
|
168922
169042
|
accountId: params.accountId,
|
|
168923
169043
|
token: params.token,
|
|
168924
169044
|
files: collectSlackFiles(params.rawEvent),
|
|
168925
|
-
sourceMessageId:
|
|
168926
|
-
sourceThreadId:
|
|
169045
|
+
sourceMessageId: isNonEmptyString4(rawEvent?.ts) ? rawEvent.ts : undefined,
|
|
169046
|
+
sourceThreadId: isNonEmptyString4(rawEvent?.thread_ts) ? rawEvent.thread_ts : null,
|
|
168927
169047
|
transcribeVoice: params.transcribeVoice
|
|
168928
169048
|
});
|
|
168929
169049
|
}
|
|
@@ -168996,7 +169116,7 @@ async function resolveSlackThreadHistory(params) {
|
|
|
168996
169116
|
...cursor ? { cursor } : {}
|
|
168997
169117
|
});
|
|
168998
169118
|
for (const message of response.messages ?? []) {
|
|
168999
|
-
if (params.include === "bot" && !
|
|
169119
|
+
if (params.include === "bot" && !isNonEmptyString4(message.bot_id)) {
|
|
169000
169120
|
continue;
|
|
169001
169121
|
}
|
|
169002
169122
|
if (!hasSlackThreadMessageContent(message, attachmentOptions)) {
|
|
@@ -169060,11 +169180,11 @@ var init_media2 = __esm(() => {
|
|
|
169060
169180
|
});
|
|
169061
169181
|
|
|
169062
169182
|
// src/channels/slack/attachment-download.ts
|
|
169063
|
-
function
|
|
169183
|
+
function isNonEmptyString5(value) {
|
|
169064
169184
|
return typeof value === "string" && value.trim().length > 0;
|
|
169065
169185
|
}
|
|
169066
169186
|
async function resolveCanonicalSlackMessage(params) {
|
|
169067
|
-
if (
|
|
169187
|
+
if (isNonEmptyString5(params.threadTs)) {
|
|
169068
169188
|
let cursor;
|
|
169069
169189
|
do {
|
|
169070
169190
|
const response2 = await params.client.conversations.replies({
|
|
@@ -169079,7 +169199,7 @@ async function resolveCanonicalSlackMessage(params) {
|
|
|
169079
169199
|
return message;
|
|
169080
169200
|
}
|
|
169081
169201
|
const nextCursor = response2.response_metadata?.next_cursor;
|
|
169082
|
-
cursor =
|
|
169202
|
+
cursor = isNonEmptyString5(nextCursor) ? nextCursor.trim() : undefined;
|
|
169083
169203
|
} while (cursor);
|
|
169084
169204
|
return null;
|
|
169085
169205
|
}
|
|
@@ -169230,7 +169350,7 @@ function createSlackInboundDebounceController(params) {
|
|
|
169230
169350
|
const deduped = [];
|
|
169231
169351
|
for (const entry of entries) {
|
|
169232
169352
|
const messageId = entry.inbound.messageId;
|
|
169233
|
-
const messageKey =
|
|
169353
|
+
const messageKey = isNonEmptyString3(messageId) ? `${entry.inbound.chatId}:${messageId}` : null;
|
|
169234
169354
|
if (!messageKey) {
|
|
169235
169355
|
deduped.push(entry);
|
|
169236
169356
|
continue;
|
|
@@ -169265,7 +169385,7 @@ function createSlackInboundDebounceController(params) {
|
|
|
169265
169385
|
if (pending?.size === 0)
|
|
169266
169386
|
pendingTopLevelKeys.delete(conversationKey);
|
|
169267
169387
|
}
|
|
169268
|
-
if (
|
|
169388
|
+
if (isNonEmptyString3(last.inbound.messageId)) {
|
|
169269
169389
|
const seenKey = `${last.inbound.chatId}:${last.inbound.messageId}`;
|
|
169270
169390
|
pruneAppMentionMaps(Date.now());
|
|
169271
169391
|
if (last.opts.source === "app_mention") {
|
|
@@ -169361,7 +169481,7 @@ function createSlackIngressController(params) {
|
|
|
169361
169481
|
}
|
|
169362
169482
|
}
|
|
169363
169483
|
function markIngressMessageSeen(channelId, messageId) {
|
|
169364
|
-
if (!
|
|
169484
|
+
if (!isNonEmptyString3(channelId) || !isNonEmptyString3(messageId)) {
|
|
169365
169485
|
return false;
|
|
169366
169486
|
}
|
|
169367
169487
|
const key = `${channelId}:${messageId}`;
|
|
@@ -169372,12 +169492,12 @@ function createSlackIngressController(params) {
|
|
|
169372
169492
|
return false;
|
|
169373
169493
|
}
|
|
169374
169494
|
function rememberMessageThread(messageId, threadId) {
|
|
169375
|
-
if (
|
|
169495
|
+
if (isNonEmptyString3(messageId)) {
|
|
169376
169496
|
knownThreadIdsByMessageId.set(messageId, threadId);
|
|
169377
169497
|
}
|
|
169378
169498
|
}
|
|
169379
169499
|
async function resolveUserName(app, userId) {
|
|
169380
|
-
if (!
|
|
169500
|
+
if (!isNonEmptyString3(userId))
|
|
169381
169501
|
return;
|
|
169382
169502
|
const cached2 = knownUserDisplayNames.get(userId);
|
|
169383
169503
|
if (cached2)
|
|
@@ -169392,6 +169512,21 @@ function createSlackIngressController(params) {
|
|
|
169392
169512
|
knownUserDisplayNames.set(userId, userId);
|
|
169393
169513
|
return userId;
|
|
169394
169514
|
}
|
|
169515
|
+
async function resolveInboundSenderName(app, userId, botId) {
|
|
169516
|
+
if (isNonEmptyString3(userId)) {
|
|
169517
|
+
return resolveUserName(app, userId);
|
|
169518
|
+
}
|
|
169519
|
+
return isNonEmptyString3(botId) ? `Bot (${botId})` : undefined;
|
|
169520
|
+
}
|
|
169521
|
+
function shouldAcceptInboundMessageByBotPolicy(input) {
|
|
169522
|
+
return shouldAcceptSlackInboundBotMessage({
|
|
169523
|
+
message: input.message,
|
|
169524
|
+
allowBots: config3.allowBots,
|
|
169525
|
+
botUserId: params.getBotUserId(),
|
|
169526
|
+
botId: params.getBotId(),
|
|
169527
|
+
wasMentioned: input.wasMentioned
|
|
169528
|
+
});
|
|
169529
|
+
}
|
|
169395
169530
|
async function dispatchInbound(inbound, raw, source2, wasMentioned, errorLabel) {
|
|
169396
169531
|
try {
|
|
169397
169532
|
await params.debounce.dispatch({
|
|
@@ -169409,11 +169544,20 @@ function createSlackIngressController(params) {
|
|
|
169409
169544
|
return;
|
|
169410
169545
|
const rawMessage = asRecord2(message);
|
|
169411
169546
|
const channelId = rawMessage?.channel;
|
|
169412
|
-
if (!rawMessage || !
|
|
169547
|
+
if (!rawMessage || !isNonEmptyString3(channelId) || !isProcessableSlackInboundMessage(rawMessage)) {
|
|
169413
169548
|
return;
|
|
169414
169549
|
}
|
|
169415
|
-
const text =
|
|
169550
|
+
const text = isNonEmptyString3(rawMessage.text) ? rawMessage.text : "";
|
|
169416
169551
|
const wasMentioned = hasSlackMention(text, params.getBotUserId());
|
|
169552
|
+
if (!shouldAcceptInboundMessageByBotPolicy({
|
|
169553
|
+
message: rawMessage,
|
|
169554
|
+
wasMentioned
|
|
169555
|
+
})) {
|
|
169556
|
+
return;
|
|
169557
|
+
}
|
|
169558
|
+
const senderId = firstNonEmptyString(rawMessage.user, rawMessage.bot_id);
|
|
169559
|
+
if (!senderId)
|
|
169560
|
+
return;
|
|
169417
169561
|
const attachments = await resolveSlackInboundAttachments({
|
|
169418
169562
|
accountId: config3.accountId,
|
|
169419
169563
|
token: config3.botToken,
|
|
@@ -169423,9 +169567,10 @@ function createSlackIngressController(params) {
|
|
|
169423
169567
|
const chatType = resolveSlackChatType(channelId);
|
|
169424
169568
|
const threadId = chatType === "direct" ? firstNonEmptyString(rawMessage.thread_ts) ?? null : firstNonEmptyString(rawMessage.thread_ts, rawMessage.ts) ?? null;
|
|
169425
169569
|
rememberMessageThread(rawMessage.ts, threadId);
|
|
169426
|
-
const senderName = await
|
|
169427
|
-
const isAgentThread = chatType === "channel" &&
|
|
169428
|
-
const
|
|
169570
|
+
const senderName = await resolveInboundSenderName(app, rawMessage.user, rawMessage.bot_id);
|
|
169571
|
+
const isAgentThread = chatType === "channel" && isNonEmptyString3(threadId) && params.agentThreadTracker.has(channelId, threadId);
|
|
169572
|
+
const isBotAuthored = isSlackBotAuthoredInboundMessage(rawMessage);
|
|
169573
|
+
const effectiveMention = isBotAuthored ? wasMentioned : wasMentioned || isAgentThread;
|
|
169429
169574
|
if (chatType === "direct") {
|
|
169430
169575
|
const seenKey2 = `${channelId}:${rawMessage.ts}`;
|
|
169431
169576
|
if (markIngressMessageSeen(channelId, rawMessage.ts))
|
|
@@ -169435,7 +169580,7 @@ function createSlackIngressController(params) {
|
|
|
169435
169580
|
channel: "slack",
|
|
169436
169581
|
accountId: config3.accountId,
|
|
169437
169582
|
chatId: channelId,
|
|
169438
|
-
senderId
|
|
169583
|
+
senderId,
|
|
169439
169584
|
senderTeamId: resolveSlackSenderTeamId(rawMessage),
|
|
169440
169585
|
senderName,
|
|
169441
169586
|
text: wasMentioned ? normalizeSlackText(text) : text,
|
|
@@ -169449,7 +169594,7 @@ function createSlackIngressController(params) {
|
|
|
169449
169594
|
}, rawMessage, "message", wasMentioned, "DM message");
|
|
169450
169595
|
return;
|
|
169451
169596
|
}
|
|
169452
|
-
if (!
|
|
169597
|
+
if (!isNonEmptyString3(rawMessage.thread_ts))
|
|
169453
169598
|
return;
|
|
169454
169599
|
const seenKey = `${channelId}:${rawMessage.ts}`;
|
|
169455
169600
|
if (markIngressMessageSeen(channelId, rawMessage.ts))
|
|
@@ -169459,7 +169604,7 @@ function createSlackIngressController(params) {
|
|
|
169459
169604
|
channel: "slack",
|
|
169460
169605
|
accountId: config3.accountId,
|
|
169461
169606
|
chatId: channelId,
|
|
169462
|
-
senderId
|
|
169607
|
+
senderId,
|
|
169463
169608
|
senderTeamId: resolveSlackSenderTeamId(rawMessage),
|
|
169464
169609
|
senderName,
|
|
169465
169610
|
chatLabel: channelId,
|
|
@@ -169474,26 +169619,37 @@ function createSlackIngressController(params) {
|
|
|
169474
169619
|
}, rawMessage, "message", effectiveMention, "threaded channel message");
|
|
169475
169620
|
});
|
|
169476
169621
|
app.event("app_mention", async ({ event: event2 }) => {
|
|
169477
|
-
|
|
169622
|
+
const rawEvent = asRecord2(event2);
|
|
169623
|
+
const channelId = rawEvent?.channel;
|
|
169624
|
+
const ts = rawEvent?.ts;
|
|
169625
|
+
const senderId = firstNonEmptyString(rawEvent?.user, rawEvent?.bot_id);
|
|
169626
|
+
if (!params.getAdapter().onMessage || !rawEvent || !isNonEmptyString3(channelId) || !isNonEmptyString3(ts) || !senderId) {
|
|
169627
|
+
return;
|
|
169628
|
+
}
|
|
169629
|
+
if (!shouldAcceptInboundMessageByBotPolicy({
|
|
169630
|
+
message: rawEvent,
|
|
169631
|
+
wasMentioned: true
|
|
169632
|
+
})) {
|
|
169478
169633
|
return;
|
|
169479
169634
|
}
|
|
169480
|
-
const
|
|
169481
|
-
|
|
169635
|
+
const threadId = firstNonEmptyString(rawEvent.thread_ts, ts) ?? ts;
|
|
169636
|
+
const seenKey = `${channelId}:${ts}`;
|
|
169637
|
+
if (markIngressMessageSeen(channelId, ts) && !params.debounce.consumeAppMentionRetry(seenKey)) {
|
|
169482
169638
|
return;
|
|
169483
169639
|
}
|
|
169484
|
-
rememberMessageThread(
|
|
169640
|
+
rememberMessageThread(ts, threadId);
|
|
169485
169641
|
await dispatchInbound({
|
|
169486
169642
|
channel: "slack",
|
|
169487
169643
|
accountId: config3.accountId,
|
|
169488
|
-
chatId:
|
|
169489
|
-
senderId
|
|
169490
|
-
senderTeamId: resolveSlackSenderTeamId(
|
|
169491
|
-
senderName: await
|
|
169492
|
-
chatLabel:
|
|
169493
|
-
text: normalizeSlackText(
|
|
169494
|
-
timestamp: slackTimestampToMillis(
|
|
169495
|
-
messageId:
|
|
169496
|
-
threadId
|
|
169644
|
+
chatId: channelId,
|
|
169645
|
+
senderId,
|
|
169646
|
+
senderTeamId: resolveSlackSenderTeamId(rawEvent),
|
|
169647
|
+
senderName: await resolveInboundSenderName(app, firstNonEmptyString(rawEvent.user), firstNonEmptyString(rawEvent.bot_id)),
|
|
169648
|
+
chatLabel: channelId,
|
|
169649
|
+
text: normalizeSlackText(isNonEmptyString3(rawEvent.text) ? rawEvent.text : ""),
|
|
169650
|
+
timestamp: slackTimestampToMillis(ts),
|
|
169651
|
+
messageId: ts,
|
|
169652
|
+
threadId,
|
|
169497
169653
|
chatType: "channel",
|
|
169498
169654
|
isMention: true,
|
|
169499
169655
|
attachments: await resolveSlackInboundAttachments({
|
|
@@ -169503,7 +169659,7 @@ function createSlackIngressController(params) {
|
|
|
169503
169659
|
transcribeVoice: config3.transcribeVoice === true
|
|
169504
169660
|
}),
|
|
169505
169661
|
raw: event2
|
|
169506
|
-
},
|
|
169662
|
+
}, rawEvent, "app_mention", true, "channel mention");
|
|
169507
169663
|
});
|
|
169508
169664
|
const handleCommand = async ({
|
|
169509
169665
|
command,
|
|
@@ -169511,10 +169667,10 @@ function createSlackIngressController(params) {
|
|
|
169511
169667
|
}) => {
|
|
169512
169668
|
await ack();
|
|
169513
169669
|
const adapter = params.getAdapter();
|
|
169514
|
-
if (!adapter.onMessage || !
|
|
169670
|
+
if (!adapter.onMessage || !isNonEmptyString3(command.command) || !isNonEmptyString3(command.channel_id) || !isNonEmptyString3(command.user_id)) {
|
|
169515
169671
|
return;
|
|
169516
169672
|
}
|
|
169517
|
-
const args =
|
|
169673
|
+
const args = isNonEmptyString3(command.text) ? command.text.trim() : "";
|
|
169518
169674
|
try {
|
|
169519
169675
|
await adapter.onMessage({
|
|
169520
169676
|
channel: "slack",
|
|
@@ -169578,7 +169734,7 @@ function createSlackIngressController(params) {
|
|
|
169578
169734
|
const item = asRecord2(event2.item);
|
|
169579
169735
|
const chatId = item?.channel;
|
|
169580
169736
|
const targetMessageId = item?.ts;
|
|
169581
|
-
if (!adapter.onMessage || item?.type !== "message" || !
|
|
169737
|
+
if (!adapter.onMessage || item?.type !== "message" || !isNonEmptyString3(chatId) || !isNonEmptyString3(targetMessageId) || !isNonEmptyString3(event2.user) || !isNonEmptyString3(event2.reaction) || event2.user === params.getBotUserId()) {
|
|
169582
169738
|
return;
|
|
169583
169739
|
}
|
|
169584
169740
|
const chatType = resolveSlackChatType(chatId);
|
|
@@ -169602,7 +169758,7 @@ function createSlackIngressController(params) {
|
|
|
169602
169758
|
action: action3,
|
|
169603
169759
|
emoji: event2.reaction,
|
|
169604
169760
|
targetMessageId,
|
|
169605
|
-
targetSenderId:
|
|
169761
|
+
targetSenderId: isNonEmptyString3(event2.item_user) ? event2.item_user : undefined
|
|
169606
169762
|
},
|
|
169607
169763
|
raw: event2
|
|
169608
169764
|
});
|
|
@@ -169647,22 +169803,22 @@ function createSlackStatusController(params) {
|
|
|
169647
169803
|
const keepaliveByConversation = new Map;
|
|
169648
169804
|
const clearedStaleReplyKeys = new Set;
|
|
169649
169805
|
function getConversationKey(source2) {
|
|
169650
|
-
return source2.channel === "slack" &&
|
|
169806
|
+
return source2.channel === "slack" && isNonEmptyString3(source2.agentId) && isNonEmptyString3(source2.conversationId) ? `${source2.agentId}:${source2.conversationId}` : null;
|
|
169651
169807
|
}
|
|
169652
169808
|
function getLifecycleReplyKey(source2) {
|
|
169653
|
-
if (source2.channel !== "slack" || !
|
|
169809
|
+
if (source2.channel !== "slack" || !isNonEmptyString3(source2.chatId)) {
|
|
169654
169810
|
return null;
|
|
169655
169811
|
}
|
|
169656
169812
|
const replyToMessageId = resolveSlackProgressThreadTs(source2);
|
|
169657
|
-
return
|
|
169813
|
+
return isNonEmptyString3(replyToMessageId) ? `${source2.chatId}:${replyToMessageId}` : null;
|
|
169658
169814
|
}
|
|
169659
169815
|
function getLifecycleErrorReplyKey(source2) {
|
|
169660
|
-
if (source2.channel !== "slack" || !
|
|
169816
|
+
if (source2.channel !== "slack" || !isNonEmptyString3(source2.chatId)) {
|
|
169661
169817
|
return null;
|
|
169662
169818
|
}
|
|
169663
169819
|
if (source2.chatType === "direct" || resolveSlackChatType(source2.chatId) === "direct") {
|
|
169664
169820
|
const replyToMessageId = resolveSlackSourceThreadTs(source2);
|
|
169665
|
-
return
|
|
169821
|
+
return isNonEmptyString3(replyToMessageId) ? `${source2.chatId}:${replyToMessageId}` : `${source2.chatId}:direct`;
|
|
169666
169822
|
}
|
|
169667
169823
|
return getLifecycleReplyKey(source2);
|
|
169668
169824
|
}
|
|
@@ -169821,7 +169977,7 @@ ${loadingText}`;
|
|
|
169821
169977
|
markAutoClearedByKey(key);
|
|
169822
169978
|
},
|
|
169823
169979
|
markAutoClearedForMessage(msg) {
|
|
169824
|
-
if (
|
|
169980
|
+
if (isNonEmptyString3(msg.agentId) && isNonEmptyString3(msg.conversationId)) {
|
|
169825
169981
|
markAutoClearedByKey(`${msg.agentId}:${msg.conversationId}`);
|
|
169826
169982
|
return;
|
|
169827
169983
|
}
|
|
@@ -169871,7 +170027,7 @@ function truncateThreadLabel(text, maxLength3 = 80) {
|
|
|
169871
170027
|
return normalized.length <= maxLength3 ? normalized : `${normalized.slice(0, maxLength3 - 1).trimEnd()}…`;
|
|
169872
170028
|
}
|
|
169873
170029
|
function buildThreadLabel(msg, starterText) {
|
|
169874
|
-
const roomLabel = msg.chatType === "channel" &&
|
|
170030
|
+
const roomLabel = msg.chatType === "channel" && isNonEmptyString3(msg.chatLabel) && msg.chatLabel !== msg.chatId ? ` in ${msg.chatLabel}` : "";
|
|
169875
170031
|
const preview = truncateThreadLabel(starterText ?? msg.text);
|
|
169876
170032
|
const threadLabel = msg.chatType === "direct" ? "Slack DM thread" : "Slack thread";
|
|
169877
170033
|
if (preview)
|
|
@@ -169881,12 +170037,12 @@ function buildThreadLabel(msg, starterText) {
|
|
|
169881
170037
|
function buildChannelContextLabel(msg) {
|
|
169882
170038
|
if (msg.chatType !== "channel")
|
|
169883
170039
|
return;
|
|
169884
|
-
const roomLabel =
|
|
170040
|
+
const roomLabel = isNonEmptyString3(msg.chatLabel) && msg.chatLabel !== msg.chatId ? ` in ${msg.chatLabel}` : "";
|
|
169885
170041
|
return roomLabel ? `Slack channel context${roomLabel} before thread start` : "Slack channel context before thread start";
|
|
169886
170042
|
}
|
|
169887
170043
|
async function prepareSlackInboundMessage(params) {
|
|
169888
170044
|
const { msg, config: config3 } = params;
|
|
169889
|
-
if (msg.channel !== "slack" || !
|
|
170045
|
+
if (msg.channel !== "slack" || !isNonEmptyString3(msg.threadId) || !isNonEmptyString3(msg.messageId)) {
|
|
169890
170046
|
return msg;
|
|
169891
170047
|
}
|
|
169892
170048
|
const isFirstRouteTurn = params.options?.isFirstRouteTurn === true;
|
|
@@ -169935,18 +170091,18 @@ async function prepareSlackInboundMessage(params) {
|
|
|
169935
170091
|
return msg;
|
|
169936
170092
|
}
|
|
169937
170093
|
const userIds = new Set;
|
|
169938
|
-
if (
|
|
170094
|
+
if (isNonEmptyString3(starter?.userId))
|
|
169939
170095
|
userIds.add(starter.userId);
|
|
169940
170096
|
for (const entry of history) {
|
|
169941
|
-
if (
|
|
170097
|
+
if (isNonEmptyString3(entry.userId))
|
|
169942
170098
|
userIds.add(entry.userId);
|
|
169943
170099
|
}
|
|
169944
170100
|
await Promise.all(Array.from(userIds).map((userId) => params.resolveUserName(app, userId)));
|
|
169945
170101
|
const resolveSenderName = (userId, botId) => {
|
|
169946
|
-
if (
|
|
170102
|
+
if (isNonEmptyString3(userId)) {
|
|
169947
170103
|
return params.getKnownUserDisplayName(userId) ?? userId;
|
|
169948
170104
|
}
|
|
169949
|
-
return
|
|
170105
|
+
return isNonEmptyString3(botId) ? `Bot (${botId})` : undefined;
|
|
169950
170106
|
};
|
|
169951
170107
|
return {
|
|
169952
170108
|
...msg,
|
|
@@ -170016,6 +170172,7 @@ function createSlackAdapter(config3) {
|
|
|
170016
170172
|
let writeClientPromise = null;
|
|
170017
170173
|
let running = false;
|
|
170018
170174
|
let botUserId = null;
|
|
170175
|
+
let botId = null;
|
|
170019
170176
|
let adapter;
|
|
170020
170177
|
const agentThreadTracker = createAgentThreadTracker();
|
|
170021
170178
|
const debounce = createSlackInboundDebounceController({
|
|
@@ -170026,6 +170183,7 @@ function createSlackAdapter(config3) {
|
|
|
170026
170183
|
config: config3,
|
|
170027
170184
|
getAdapter: () => adapter,
|
|
170028
170185
|
getBotUserId: () => botUserId,
|
|
170186
|
+
getBotId: () => botId,
|
|
170029
170187
|
agentThreadTracker,
|
|
170030
170188
|
debounce
|
|
170031
170189
|
});
|
|
@@ -170102,7 +170260,7 @@ function createSlackAdapter(config3) {
|
|
|
170102
170260
|
if (!running)
|
|
170103
170261
|
return;
|
|
170104
170262
|
if (event2.type === "queued") {
|
|
170105
|
-
if (isSlackFlatChannelThreadOpener(event2.source) &&
|
|
170263
|
+
if (isSlackFlatChannelThreadOpener(event2.source) && isNonEmptyString3(event2.source.messageId) && !agentThreadTracker.has(event2.source.chatId, event2.source.messageId)) {
|
|
170106
170264
|
await status.activate(event2.source, SLACK_ASSISTANT_STARTUP_STATUS, SLACK_ASSISTANT_STARTUP_STATUS);
|
|
170107
170265
|
}
|
|
170108
170266
|
return;
|
|
@@ -170164,7 +170322,7 @@ function createSlackAdapter(config3) {
|
|
|
170164
170322
|
if (msg.mediaPath) {
|
|
170165
170323
|
const result = await uploadSlackFile(client, msg);
|
|
170166
170324
|
const threadId = msg.threadId ?? msg.replyToMessageId ?? null;
|
|
170167
|
-
if (resolveSlackChatType(msg.chatId) === "channel" &&
|
|
170325
|
+
if (resolveSlackChatType(msg.chatId) === "channel" && isNonEmptyString3(threadId)) {
|
|
170168
170326
|
agentThreadTracker.remember(msg.chatId, threadId);
|
|
170169
170327
|
}
|
|
170170
170328
|
status.markAutoClearedForMessage(msg);
|
|
@@ -170175,7 +170333,7 @@ function createSlackAdapter(config3) {
|
|
|
170175
170333
|
threadId: msg.threadId,
|
|
170176
170334
|
replyToMessageId: msg.replyToMessageId
|
|
170177
170335
|
});
|
|
170178
|
-
const footnote =
|
|
170336
|
+
const footnote = isNonEmptyString3(msg.agentId) && isNonEmptyString3(msg.conversationId) ? buildSlackChatFootnote({
|
|
170179
170337
|
agentId: msg.agentId,
|
|
170180
170338
|
conversationId: msg.conversationId
|
|
170181
170339
|
}) : "";
|
|
@@ -170188,7 +170346,7 @@ function createSlackAdapter(config3) {
|
|
|
170188
170346
|
});
|
|
170189
170347
|
const outboundThreadId = threadTs ?? (resolveSlackChatType(msg.chatId) === "channel" ? response.ts ?? null : null);
|
|
170190
170348
|
ingress.rememberMessageThread(response.ts, outboundThreadId);
|
|
170191
|
-
if (resolveSlackChatType(msg.chatId) === "channel" &&
|
|
170349
|
+
if (resolveSlackChatType(msg.chatId) === "channel" && isNonEmptyString3(outboundThreadId)) {
|
|
170192
170350
|
agentThreadTracker.remember(msg.chatId, outboundThreadId);
|
|
170193
170351
|
}
|
|
170194
170352
|
status.markAutoClearedForMessage(msg);
|
|
@@ -170211,7 +170369,7 @@ function createSlackAdapter(config3) {
|
|
|
170211
170369
|
});
|
|
170212
170370
|
const outboundThreadId = threadTs ?? (resolveSlackChatType(chatId) === "channel" ? response.ts ?? null : null);
|
|
170213
170371
|
ingress.rememberMessageThread(response.ts, outboundThreadId);
|
|
170214
|
-
if (resolveSlackChatType(chatId) === "channel" &&
|
|
170372
|
+
if (resolveSlackChatType(chatId) === "channel" && isNonEmptyString3(outboundThreadId)) {
|
|
170215
170373
|
agentThreadTracker.remember(chatId, outboundThreadId);
|
|
170216
170374
|
}
|
|
170217
170375
|
status.markAutoClearedForMessage({
|
|
@@ -170237,7 +170395,7 @@ function createSlackAdapter(config3) {
|
|
|
170237
170395
|
if (event2.kind === "generic_tool_approval" && response.ts) {
|
|
170238
170396
|
approvals.rememberPrompt(event2, response.ts);
|
|
170239
170397
|
}
|
|
170240
|
-
if (resolveSlackChatType(event2.source.chatId) === "channel" &&
|
|
170398
|
+
if (resolveSlackChatType(event2.source.chatId) === "channel" && isNonEmptyString3(outboundThreadId)) {
|
|
170241
170399
|
agentThreadTracker.remember(event2.source.chatId, outboundThreadId);
|
|
170242
170400
|
}
|
|
170243
170401
|
status.markAutoCleared(event2.source);
|
|
@@ -170252,7 +170410,9 @@ function createSlackAdapter(config3) {
|
|
|
170252
170410
|
return;
|
|
170253
170411
|
const slackApp = await ensureApp();
|
|
170254
170412
|
const auth = await slackApp.client.auth.test();
|
|
170255
|
-
|
|
170413
|
+
const authRecord = auth;
|
|
170414
|
+
botUserId = isNonEmptyString3(authRecord.user_id) ? authRecord.user_id : null;
|
|
170415
|
+
botId = isNonEmptyString3(authRecord.bot_id) ? authRecord.bot_id : null;
|
|
170256
170416
|
await slackApp.start();
|
|
170257
170417
|
running = true;
|
|
170258
170418
|
console.log(`[Slack] App started for workspace ${auth.team ?? "unknown"} (dm_policy: ${config3.dmPolicy})`);
|
|
@@ -170267,6 +170427,7 @@ function createSlackAdapter(config3) {
|
|
|
170267
170427
|
writeClient = null;
|
|
170268
170428
|
writeClientPromise = null;
|
|
170269
170429
|
botUserId = null;
|
|
170430
|
+
botId = null;
|
|
170270
170431
|
status.clear();
|
|
170271
170432
|
approvals.clear();
|
|
170272
170433
|
debounce.clear();
|
|
@@ -171167,7 +171328,7 @@ function formatDiscordDeliveryError(error54) {
|
|
|
171167
171328
|
}
|
|
171168
171329
|
|
|
171169
171330
|
// src/channels/discord/utils.ts
|
|
171170
|
-
function
|
|
171331
|
+
function isNonEmptyString6(value) {
|
|
171171
171332
|
return typeof value === "string" && value.length > 0;
|
|
171172
171333
|
}
|
|
171173
171334
|
function isDiscordTextChannel(channel) {
|
|
@@ -171234,7 +171395,7 @@ function shouldAutoThreadOnDiscordMention(account, channelId) {
|
|
|
171234
171395
|
return account.autoThreadOnMention ?? false;
|
|
171235
171396
|
}
|
|
171236
171397
|
function buildDiscordIngressMessageKey(accountId, messageId) {
|
|
171237
|
-
if (!
|
|
171398
|
+
if (!isNonEmptyString6(accountId) || !isNonEmptyString6(messageId)) {
|
|
171238
171399
|
return null;
|
|
171239
171400
|
}
|
|
171240
171401
|
return `${accountId}:${messageId}`;
|
|
@@ -171318,13 +171479,13 @@ function createDiscordAdapter(config3) {
|
|
|
171318
171479
|
return false;
|
|
171319
171480
|
}
|
|
171320
171481
|
function getLifecycleMessageKey(source2) {
|
|
171321
|
-
if (source2.channel !== "discord" || !
|
|
171482
|
+
if (source2.channel !== "discord" || !isNonEmptyString6(source2.chatId) || !isNonEmptyString6(source2.messageId)) {
|
|
171322
171483
|
return null;
|
|
171323
171484
|
}
|
|
171324
171485
|
return `${source2.chatId}:${source2.messageId}`;
|
|
171325
171486
|
}
|
|
171326
171487
|
function getLifecycleReplyKey(source2) {
|
|
171327
|
-
if (source2.channel !== "discord" || !
|
|
171488
|
+
if (source2.channel !== "discord" || !isNonEmptyString6(source2.chatId)) {
|
|
171328
171489
|
return null;
|
|
171329
171490
|
}
|
|
171330
171491
|
return [
|
|
@@ -171337,7 +171498,7 @@ function createDiscordAdapter(config3) {
|
|
|
171337
171498
|
if (source2.channel !== "discord")
|
|
171338
171499
|
return null;
|
|
171339
171500
|
const channelId = source2.threadId ?? source2.chatId;
|
|
171340
|
-
return
|
|
171501
|
+
return isNonEmptyString6(channelId) ? channelId : null;
|
|
171341
171502
|
}
|
|
171342
171503
|
function getTypingSourceKey(source2) {
|
|
171343
171504
|
const channelId = getTypingChannelId(source2);
|
|
@@ -171389,7 +171550,7 @@ function createDiscordAdapter(config3) {
|
|
|
171389
171550
|
return true;
|
|
171390
171551
|
}
|
|
171391
171552
|
async function sendLifecycleReaction(source2, emoji3, remove = false) {
|
|
171392
|
-
if (!client || !
|
|
171553
|
+
if (!client || !isNonEmptyString6(source2.messageId))
|
|
171393
171554
|
return;
|
|
171394
171555
|
try {
|
|
171395
171556
|
const channel = await client.channels.fetch(source2.chatId);
|
|
@@ -171928,7 +172089,7 @@ function createDiscordAdapter(config3) {
|
|
|
171928
172089
|
clearTypingForChannel(chatId);
|
|
171929
172090
|
},
|
|
171930
172091
|
async prepareInboundMessage(msg, options3) {
|
|
171931
|
-
if (!options3?.isFirstRouteTurn || msg.channel !== "discord" || msg.chatType !== "channel" || !
|
|
172092
|
+
if (!options3?.isFirstRouteTurn || msg.channel !== "discord" || msg.chatType !== "channel" || !isNonEmptyString6(msg.threadId) || !client) {
|
|
171932
172093
|
return msg;
|
|
171933
172094
|
}
|
|
171934
172095
|
const starter = await resolveDiscordThreadStarter({
|
|
@@ -182846,11 +183007,11 @@ When users ask you to perform tasks, check if any of the available skills match.
|
|
|
182846
183007
|
When users reference a "slash command" or "/<something>" (e.g., "/commit", "/review-pr"), they are referring to a skill. Use this tool to invoke it.
|
|
182847
183008
|
|
|
182848
183009
|
How to invoke:
|
|
182849
|
-
- Use this tool with the skill name
|
|
183010
|
+
- Use this tool with only the skill name
|
|
182850
183011
|
- Examples:
|
|
182851
183012
|
- \`skill: "pdf"\` - invoke the pdf skill
|
|
182852
|
-
- \`skill: "commit"
|
|
182853
|
-
- \`skill: "review-pr"
|
|
183013
|
+
- \`skill: "commit"\` - invoke the commit skill
|
|
183014
|
+
- \`skill: "review-pr"\` - invoke the review-pr skill
|
|
182854
183015
|
- \`skill: "ms-office-suite:pdf"\` - invoke using fully qualified name
|
|
182855
183016
|
|
|
182856
183017
|
Important:
|
|
@@ -196395,7 +196556,6 @@ When to use: ${whenToUse}` : description;
|
|
|
196395
196556
|
description: modelDescription,
|
|
196396
196557
|
whenToUse,
|
|
196397
196558
|
argumentHint: getFrontmatterString(frontmatter, "argument-hint"),
|
|
196398
|
-
arguments: getFrontmatterStringList(frontmatter, "arguments"),
|
|
196399
196559
|
disableModelInvocation: getFrontmatterBoolean(frontmatter, "disable-model-invocation") ?? false,
|
|
196400
196560
|
userInvocable: getFrontmatterBoolean(frontmatter, "user-invocable") ?? true,
|
|
196401
196561
|
category: getFrontmatterString(frontmatter, "category"),
|
|
@@ -382984,6 +383144,7 @@ var init_skill_content_registry = __esm(() => {
|
|
|
382984
383144
|
// src/tools/impl/skill.ts
|
|
382985
383145
|
var exports_skill = {};
|
|
382986
383146
|
__export(exports_skill, {
|
|
383147
|
+
wrapSkillPrompt: () => wrapSkillPrompt,
|
|
382987
383148
|
wrapSkillContent: () => wrapSkillContent,
|
|
382988
383149
|
skill: () => skill,
|
|
382989
383150
|
renderSkillContent: () => renderSkillContent,
|
|
@@ -383081,50 +383242,6 @@ function getResolvedAgentId(args) {
|
|
|
383081
383242
|
return;
|
|
383082
383243
|
}
|
|
383083
383244
|
}
|
|
383084
|
-
function splitSkillArguments(args) {
|
|
383085
|
-
const parts = [];
|
|
383086
|
-
const pattern4 = /"([^"\\]*(?:\\.[^"\\]*)*)"|'([^'\\]*(?:\\.[^'\\]*)*)'|\S+/g;
|
|
383087
|
-
for (const match3 of args.matchAll(pattern4)) {
|
|
383088
|
-
const raw = match3[1] ?? match3[2] ?? match3[0];
|
|
383089
|
-
parts.push(raw.replace(/\\(["'\\])/g, "$1"));
|
|
383090
|
-
}
|
|
383091
|
-
return parts;
|
|
383092
|
-
}
|
|
383093
|
-
function substituteSkillArguments(content, args, argumentNames) {
|
|
383094
|
-
const rawArgs = args?.trim() ?? "";
|
|
383095
|
-
if (!rawArgs) {
|
|
383096
|
-
return content;
|
|
383097
|
-
}
|
|
383098
|
-
const argParts = splitSkillArguments(rawArgs);
|
|
383099
|
-
let result = content;
|
|
383100
|
-
let substituted = false;
|
|
383101
|
-
result = result.replace(/\$ARGUMENTS\[(\d+)\]/g, (_match, index) => {
|
|
383102
|
-
substituted = true;
|
|
383103
|
-
return argParts[Number(index)] ?? "";
|
|
383104
|
-
});
|
|
383105
|
-
result = result.replace(/\$ARGUMENTS/g, () => {
|
|
383106
|
-
substituted = true;
|
|
383107
|
-
return rawArgs;
|
|
383108
|
-
});
|
|
383109
|
-
result = result.replace(/\$(\d+)\b/g, (_match, index) => {
|
|
383110
|
-
substituted = true;
|
|
383111
|
-
return argParts[Number(index)] ?? "";
|
|
383112
|
-
});
|
|
383113
|
-
for (const [index, name] of (argumentNames ?? []).entries()) {
|
|
383114
|
-
const escapedName = name.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
383115
|
-
const namePattern = new RegExp(`\\$${escapedName}\\b`, "g");
|
|
383116
|
-
result = result.replace(namePattern, () => {
|
|
383117
|
-
substituted = true;
|
|
383118
|
-
return argParts[index] ?? "";
|
|
383119
|
-
});
|
|
383120
|
-
}
|
|
383121
|
-
if (!substituted) {
|
|
383122
|
-
result = `${result.trimEnd()}
|
|
383123
|
-
|
|
383124
|
-
ARGUMENTS: ${rawArgs}`;
|
|
383125
|
-
}
|
|
383126
|
-
return result;
|
|
383127
|
-
}
|
|
383128
383245
|
function renderSkillContent(skillName, skillContent, skillPath, options3 = {}) {
|
|
383129
383246
|
const { frontmatter } = parseFrontmatter(skillContent);
|
|
383130
383247
|
if (!options3.allowDisabledModelInvocation && getFrontmatterBoolean(frontmatter, "disable-model-invocation") === true) {
|
|
@@ -383132,13 +383249,11 @@ function renderSkillContent(skillName, skillContent, skillPath, options3 = {}) {
|
|
|
383132
383249
|
}
|
|
383133
383250
|
const skillDir = dirname16(skillPath);
|
|
383134
383251
|
const hasExtras = hasAdditionalFiles(skillPath);
|
|
383135
|
-
const argumentNames = getFrontmatterStringList(frontmatter, "arguments");
|
|
383136
383252
|
const withSkillDir = skillContent.replace(/<SKILL_DIR>/g, skillDir).replace(/\$\{CLAUDE_SKILL_DIR\}/g, skillDir);
|
|
383137
|
-
const withArguments = substituteSkillArguments(withSkillDir, options3.args, argumentNames);
|
|
383138
383253
|
const dirHeader = hasExtras ? `# Skill Directory: ${skillDir}
|
|
383139
383254
|
|
|
383140
383255
|
` : "";
|
|
383141
|
-
return `${dirHeader}${
|
|
383256
|
+
return `${dirHeader}${withSkillDir}`;
|
|
383142
383257
|
}
|
|
383143
383258
|
async function loadRenderedSkillContent(skillName, options3 = {}) {
|
|
383144
383259
|
const skillsDir = options3.skillsDir ?? await getResolvedSkillsDir();
|
|
@@ -383158,6 +383273,12 @@ ${content}
|
|
|
383158
383273
|
${content}
|
|
383159
383274
|
</skill>`;
|
|
383160
383275
|
}
|
|
383276
|
+
function wrapSkillPrompt(skillName, content, userRequest) {
|
|
383277
|
+
const wrappedSkill = wrapSkillContent(skillName, content);
|
|
383278
|
+
return userRequest ? `${wrappedSkill}
|
|
383279
|
+
|
|
383280
|
+
${userRequest}` : wrappedSkill;
|
|
383281
|
+
}
|
|
383161
383282
|
async function skill(args) {
|
|
383162
383283
|
validateRequiredParams(args, ["skill"], "Skill");
|
|
383163
383284
|
const { skill: skillName, toolCallId } = args;
|
|
@@ -383169,8 +383290,7 @@ async function skill(args) {
|
|
|
383169
383290
|
const skillsDir = await getResolvedSkillsDir();
|
|
383170
383291
|
const fullContent = await loadRenderedSkillContent(skillName, {
|
|
383171
383292
|
agentId,
|
|
383172
|
-
skillsDir
|
|
383173
|
-
args: args.args
|
|
383293
|
+
skillsDir
|
|
383174
383294
|
});
|
|
383175
383295
|
if (toolCallId) {
|
|
383176
383296
|
queueSkillContent(toolCallId, wrapSkillContent(skillName, fullContent));
|
|
@@ -386826,10 +386946,6 @@ var init_Skill2 = __esm(() => {
|
|
|
386826
386946
|
skill: {
|
|
386827
386947
|
type: "string",
|
|
386828
386948
|
description: 'The skill name. E.g., "commit", "review-pr", or "pdf"'
|
|
386829
|
-
},
|
|
386830
|
-
args: {
|
|
386831
|
-
type: "string",
|
|
386832
|
-
description: "Optional arguments for the skill"
|
|
386833
386949
|
}
|
|
386834
386950
|
},
|
|
386835
386951
|
required: ["skill"],
|
|
@@ -400213,10 +400329,6 @@ async function resolveAvailableLocalModelForTurn(input) {
|
|
|
400213
400329
|
}
|
|
400214
400330
|
};
|
|
400215
400331
|
}
|
|
400216
|
-
function shouldIncludeLocalModel(provider, model) {
|
|
400217
|
-
const modelId = isPiProvider(provider) ? stripProviderHandlePrefix(model, provider) ?? model : model;
|
|
400218
|
-
return !(localProviderTypeForModelConfig(provider) === "chatgpt_oauth" && UNSUPPORTED_LOCAL_CHATGPT_OAUTH_MODELS.has(modelId));
|
|
400219
|
-
}
|
|
400220
400332
|
async function listLocalModels(storageDir, options3 = {}) {
|
|
400221
400333
|
const records = listLocalProviderRecords(storageDir);
|
|
400222
400334
|
const providerNames = localProviderNamesFromRecords(records);
|
|
@@ -400225,8 +400337,6 @@ async function listLocalModels(storageDir, options3 = {}) {
|
|
|
400225
400337
|
const registeredProviders2 = listRegisteredPiProviders();
|
|
400226
400338
|
const registeredProvidersWithModels = new Set(registeredProviders2.filter((provider) => provider.config.models !== undefined).map((provider) => provider.providerName));
|
|
400227
400339
|
const addModel = (provider, model, options4 = {}) => {
|
|
400228
|
-
if (!shouldIncludeLocalModel(provider, model))
|
|
400229
|
-
return;
|
|
400230
400340
|
const handle = options4.handle ?? (typeof provider === "string" && !isPiProviderForLocalModelHandle(provider) ? `${provider}/${model}` : localModelHandle(provider, model));
|
|
400231
400341
|
if (models3.some((entry) => entry.handle === handle))
|
|
400232
400342
|
return;
|
|
@@ -400313,7 +400423,7 @@ async function listLocalModels(storageDir, options3 = {}) {
|
|
|
400313
400423
|
}
|
|
400314
400424
|
return models3;
|
|
400315
400425
|
}
|
|
400316
|
-
var LOCAL_MODEL_DISCOVERY_TIMEOUT_MS = 2000, LOCAL_MODEL_AUTODETECT_DISCOVERY_TIMEOUT_MS = 500
|
|
400426
|
+
var LOCAL_MODEL_DISCOVERY_TIMEOUT_MS = 2000, LOCAL_MODEL_AUTODETECT_DISCOVERY_TIMEOUT_MS = 500;
|
|
400317
400427
|
var init_local_model_config = __esm(() => {
|
|
400318
400428
|
init_compat2();
|
|
400319
400429
|
init_pi_model_factory();
|
|
@@ -400321,7 +400431,6 @@ var init_local_model_config = __esm(() => {
|
|
|
400321
400431
|
init_pi_provider_registry();
|
|
400322
400432
|
init_registered_pi_provider_runtime();
|
|
400323
400433
|
init_local_provider_auth_store();
|
|
400324
|
-
UNSUPPORTED_LOCAL_CHATGPT_OAUTH_MODELS = new Set(["gpt-5.6-luna"]);
|
|
400325
400434
|
});
|
|
400326
400435
|
|
|
400327
400436
|
// src/backend/local/local-context-estimate.ts
|
|
@@ -445716,6 +445825,117 @@ var init_cron_file = __esm(() => {
|
|
|
445716
445825
|
GC_AGE_MS = 24 * 60 * 60 * 1000;
|
|
445717
445826
|
});
|
|
445718
445827
|
|
|
445828
|
+
// src/cron/prompt.ts
|
|
445829
|
+
function pad(value, width) {
|
|
445830
|
+
return String(value).padStart(width, "0");
|
|
445831
|
+
}
|
|
445832
|
+
function formatOffset(minutes) {
|
|
445833
|
+
const sign = minutes >= 0 ? "+" : "-";
|
|
445834
|
+
const abs = Math.abs(minutes);
|
|
445835
|
+
return `${sign}${pad(Math.floor(abs / 60), 2)}:${pad(abs % 60, 2)}`;
|
|
445836
|
+
}
|
|
445837
|
+
function getLocalDateTimeParts(date6) {
|
|
445838
|
+
return {
|
|
445839
|
+
year: date6.getFullYear(),
|
|
445840
|
+
month: date6.getMonth() + 1,
|
|
445841
|
+
day: date6.getDate(),
|
|
445842
|
+
hour: date6.getHours(),
|
|
445843
|
+
minute: date6.getMinutes(),
|
|
445844
|
+
second: date6.getSeconds()
|
|
445845
|
+
};
|
|
445846
|
+
}
|
|
445847
|
+
function isValidTimezone(timezone) {
|
|
445848
|
+
try {
|
|
445849
|
+
new Intl.DateTimeFormat("en-US", { timeZone: timezone });
|
|
445850
|
+
return true;
|
|
445851
|
+
} catch {
|
|
445852
|
+
return false;
|
|
445853
|
+
}
|
|
445854
|
+
}
|
|
445855
|
+
function getSystemTimezone() {
|
|
445856
|
+
const timezone = Intl.DateTimeFormat().resolvedOptions().timeZone;
|
|
445857
|
+
if (!timezone || !isValidTimezone(timezone)) {
|
|
445858
|
+
return null;
|
|
445859
|
+
}
|
|
445860
|
+
return timezone;
|
|
445861
|
+
}
|
|
445862
|
+
function getEffectiveTimezone(timezone) {
|
|
445863
|
+
const trimmed = timezone.trim();
|
|
445864
|
+
if (trimmed && isValidTimezone(trimmed)) {
|
|
445865
|
+
return trimmed;
|
|
445866
|
+
}
|
|
445867
|
+
return getSystemTimezone();
|
|
445868
|
+
}
|
|
445869
|
+
function formatTimezoneDisplay(timezone) {
|
|
445870
|
+
const trimmed = timezone.trim();
|
|
445871
|
+
if (!trimmed) {
|
|
445872
|
+
return "local time";
|
|
445873
|
+
}
|
|
445874
|
+
if (isValidTimezone(trimmed)) {
|
|
445875
|
+
return trimmed;
|
|
445876
|
+
}
|
|
445877
|
+
return `${trimmed} (invalid; using local time)`;
|
|
445878
|
+
}
|
|
445879
|
+
function getZonedDateTimeParts(date6, timezone) {
|
|
445880
|
+
const formatter = new Intl.DateTimeFormat("en-US", {
|
|
445881
|
+
timeZone: timezone,
|
|
445882
|
+
calendar: "iso8601",
|
|
445883
|
+
numberingSystem: "latn",
|
|
445884
|
+
hourCycle: "h23",
|
|
445885
|
+
year: "numeric",
|
|
445886
|
+
month: "2-digit",
|
|
445887
|
+
day: "2-digit",
|
|
445888
|
+
hour: "2-digit",
|
|
445889
|
+
minute: "2-digit",
|
|
445890
|
+
second: "2-digit"
|
|
445891
|
+
});
|
|
445892
|
+
const parts = new Map(formatter.formatToParts(date6).map((part) => [part.type, part.value]));
|
|
445893
|
+
return {
|
|
445894
|
+
year: Number.parseInt(parts.get("year") ?? "0", 10),
|
|
445895
|
+
month: Number.parseInt(parts.get("month") ?? "1", 10),
|
|
445896
|
+
day: Number.parseInt(parts.get("day") ?? "1", 10),
|
|
445897
|
+
hour: Number.parseInt(parts.get("hour") ?? "0", 10),
|
|
445898
|
+
minute: Number.parseInt(parts.get("minute") ?? "0", 10),
|
|
445899
|
+
second: Number.parseInt(parts.get("second") ?? "0", 10)
|
|
445900
|
+
};
|
|
445901
|
+
}
|
|
445902
|
+
function formatTimezoneQualifiedIso(date6, timezone) {
|
|
445903
|
+
const effectiveTimezone = getEffectiveTimezone(timezone);
|
|
445904
|
+
const parts = effectiveTimezone ? getZonedDateTimeParts(date6, effectiveTimezone) : getLocalDateTimeParts(date6);
|
|
445905
|
+
const millis = date6.getMilliseconds();
|
|
445906
|
+
const zonedAsUtcMs = Date.UTC(parts.year, parts.month - 1, parts.day, parts.hour, parts.minute, parts.second, millis);
|
|
445907
|
+
const offsetMinutes = Math.round((zonedAsUtcMs - date6.getTime()) / 60000);
|
|
445908
|
+
return `${pad(parts.year, 4)}-${pad(parts.month, 2)}-${pad(parts.day, 2)}T${pad(parts.hour, 2)}:${pad(parts.minute, 2)}:${pad(parts.second, 2)}.${pad(millis, 3)}${formatOffset(offsetMinutes)}[${effectiveTimezone ?? "local"}]`;
|
|
445909
|
+
}
|
|
445910
|
+
function getIntendedCronOccurrence(task2, matchedAt) {
|
|
445911
|
+
if (!task2.recurring && task2.scheduled_for) {
|
|
445912
|
+
const scheduledFor = new Date(task2.scheduled_for);
|
|
445913
|
+
if (Number.isFinite(scheduledFor.getTime())) {
|
|
445914
|
+
return scheduledFor;
|
|
445915
|
+
}
|
|
445916
|
+
}
|
|
445917
|
+
const occurrence = new Date(matchedAt);
|
|
445918
|
+
occurrence.setSeconds(0, 0);
|
|
445919
|
+
return occurrence;
|
|
445920
|
+
}
|
|
445921
|
+
function formatCronPrompt(task2, timing) {
|
|
445922
|
+
const timezone = typeof task2.timezone === "string" ? task2.timezone : "";
|
|
445923
|
+
const lines = [
|
|
445924
|
+
`Scheduled task "${task2.name}" is firing.`,
|
|
445925
|
+
`Description: ${task2.description}`,
|
|
445926
|
+
`Timezone: ${formatTimezoneDisplay(timezone)}`,
|
|
445927
|
+
`Scheduled for: ${formatTimezoneQualifiedIso(timing.intendedOccurrence, timezone)}`,
|
|
445928
|
+
`Current time: ${formatTimezoneQualifiedIso(timing.schedulerNow, timezone)}`,
|
|
445929
|
+
task2.recurring ? `This is fire #${task2.fire_count + 1} (cron: ${task2.cron}).` : "This is a one-off scheduled task.",
|
|
445930
|
+
"",
|
|
445931
|
+
"You are running autonomously: no user is watching this turn and questions will not be answered. Deliver results through your available channels or record them in memory, and work until the task is done or genuinely blocked.",
|
|
445932
|
+
"",
|
|
445933
|
+
`Prompt: ${task2.prompt}`
|
|
445934
|
+
];
|
|
445935
|
+
return lines.join(`
|
|
445936
|
+
`);
|
|
445937
|
+
}
|
|
445938
|
+
|
|
445719
445939
|
// src/cron/run-log.ts
|
|
445720
445940
|
import {
|
|
445721
445941
|
appendFileSync as appendFileSync5,
|
|
@@ -445900,18 +446120,8 @@ var init_run_log = __esm(() => {
|
|
|
445900
446120
|
function minuteKey(date6) {
|
|
445901
446121
|
return `${date6.getFullYear()}-${String(date6.getMonth() + 1).padStart(2, "0")}-${String(date6.getDate()).padStart(2, "0")}T${String(date6.getHours()).padStart(2, "0")}:${String(date6.getMinutes()).padStart(2, "0")}`;
|
|
445902
446122
|
}
|
|
445903
|
-
function wrapCronPrompt(task2) {
|
|
445904
|
-
|
|
445905
|
-
`Scheduled task "${task2.name}" is firing.`,
|
|
445906
|
-
`Description: ${task2.description}`,
|
|
445907
|
-
task2.recurring ? `This is fire #${task2.fire_count + 1} (cron: ${task2.cron}).` : `This is a one-off scheduled task.`,
|
|
445908
|
-
"",
|
|
445909
|
-
"You are running autonomously: no user is watching this turn and questions will not be answered. Deliver results through your available channels or record them in memory, and work until the task is done or genuinely blocked.",
|
|
445910
|
-
"",
|
|
445911
|
-
`Prompt: ${task2.prompt}`
|
|
445912
|
-
];
|
|
445913
|
-
return lines.join(`
|
|
445914
|
-
`);
|
|
446123
|
+
function wrapCronPrompt(task2, timing) {
|
|
446124
|
+
return formatCronPrompt(task2, timing);
|
|
445915
446125
|
}
|
|
445916
446126
|
function getCronConversationSummary(task2) {
|
|
445917
446127
|
return `[Schedule] ${task2.name}`;
|
|
@@ -445974,13 +446184,13 @@ function shouldFireTask(task2, now) {
|
|
|
445974
446184
|
}
|
|
445975
446185
|
return cronMatchesTime(task2.cron, now, task2.timezone);
|
|
445976
446186
|
}
|
|
445977
|
-
async function fireCronTask(task2,
|
|
446187
|
+
async function fireCronTask(task2, timing, socket, opts, processQueuedTurn) {
|
|
445978
446188
|
const listener = getActiveRuntime();
|
|
445979
446189
|
if (!listener) {
|
|
445980
446190
|
setLastRunOutcome(task2.id, {
|
|
445981
446191
|
outcome: "failed",
|
|
445982
446192
|
reason: "runtime_unavailable",
|
|
445983
|
-
runAt:
|
|
446193
|
+
runAt: timing.schedulerNow,
|
|
445984
446194
|
error: "No active runtime"
|
|
445985
446195
|
});
|
|
445986
446196
|
safeAppendCronRunLogForTask(task2, {
|
|
@@ -445988,7 +446198,7 @@ async function fireCronTask(task2, now, socket, opts, processQueuedTurn) {
|
|
|
445988
446198
|
outcome: "failed",
|
|
445989
446199
|
reason: "runtime_unavailable",
|
|
445990
446200
|
error: "No active runtime",
|
|
445991
|
-
runAtMs:
|
|
446201
|
+
runAtMs: timing.schedulerNow.getTime(),
|
|
445992
446202
|
scheduledFor: task2.scheduled_for
|
|
445993
446203
|
});
|
|
445994
446204
|
return false;
|
|
@@ -446000,7 +446210,7 @@ async function fireCronTask(task2, now, socket, opts, processQueuedTurn) {
|
|
|
446000
446210
|
safeAppendCronRunLogForTask(task2, {
|
|
446001
446211
|
status: "error",
|
|
446002
446212
|
error: err instanceof Error ? err.message : "failed to resolve conversation",
|
|
446003
|
-
runAtMs:
|
|
446213
|
+
runAtMs: timing.schedulerNow.getTime(),
|
|
446004
446214
|
scheduledFor: task2.scheduled_for
|
|
446005
446215
|
});
|
|
446006
446216
|
return false;
|
|
@@ -446010,7 +446220,7 @@ async function fireCronTask(task2, now, socket, opts, processQueuedTurn) {
|
|
|
446010
446220
|
setLastRunOutcome(task2.id, {
|
|
446011
446221
|
outcome: "failed",
|
|
446012
446222
|
reason: "runtime_unavailable",
|
|
446013
|
-
runAt:
|
|
446223
|
+
runAt: timing.schedulerNow,
|
|
446014
446224
|
error: "Conversation runtime unavailable"
|
|
446015
446225
|
});
|
|
446016
446226
|
safeAppendCronRunLogForTask(task2, {
|
|
@@ -446018,13 +446228,13 @@ async function fireCronTask(task2, now, socket, opts, processQueuedTurn) {
|
|
|
446018
446228
|
outcome: "failed",
|
|
446019
446229
|
reason: "runtime_unavailable",
|
|
446020
446230
|
error: "Conversation runtime unavailable",
|
|
446021
|
-
runAtMs:
|
|
446231
|
+
runAtMs: timing.schedulerNow.getTime(),
|
|
446022
446232
|
scheduledFor: task2.scheduled_for
|
|
446023
446233
|
});
|
|
446024
446234
|
return false;
|
|
446025
446235
|
}
|
|
446026
446236
|
const conversationRuntime = ensureConversationQueueRuntime(listener, rawRuntime);
|
|
446027
|
-
const text2 = wrapCronPrompt(task2);
|
|
446237
|
+
const text2 = wrapCronPrompt(task2, timing);
|
|
446028
446238
|
const queuedItem = conversationRuntime.queueRuntime.enqueue({
|
|
446029
446239
|
kind: "cron_prompt",
|
|
446030
446240
|
source: "cron",
|
|
@@ -446037,7 +446247,7 @@ async function fireCronTask(task2, now, socket, opts, processQueuedTurn) {
|
|
|
446037
446247
|
setLastRunOutcome(task2.id, {
|
|
446038
446248
|
outcome: "failed",
|
|
446039
446249
|
reason: "queue_full",
|
|
446040
|
-
runAt:
|
|
446250
|
+
runAt: timing.schedulerNow,
|
|
446041
446251
|
error: "queue buffer limit"
|
|
446042
446252
|
});
|
|
446043
446253
|
safeAppendCronRunLogForTask(task2, {
|
|
@@ -446045,13 +446255,13 @@ async function fireCronTask(task2, now, socket, opts, processQueuedTurn) {
|
|
|
446045
446255
|
outcome: "failed",
|
|
446046
446256
|
reason: "queue_full",
|
|
446047
446257
|
error: "queue buffer limit",
|
|
446048
|
-
runAtMs:
|
|
446258
|
+
runAtMs: timing.schedulerNow.getTime(),
|
|
446049
446259
|
scheduledFor: task2.scheduled_for
|
|
446050
446260
|
});
|
|
446051
446261
|
return false;
|
|
446052
446262
|
}
|
|
446053
446263
|
scheduleQueuePump(conversationRuntime, socket, opts, processQueuedTurn);
|
|
446054
|
-
const nowIso =
|
|
446264
|
+
const nowIso = timing.schedulerNow.toISOString();
|
|
446055
446265
|
if (task2.recurring) {
|
|
446056
446266
|
updateTask2(task2.id, (t2) => {
|
|
446057
446267
|
t2.last_fired_at = nowIso;
|
|
@@ -446077,7 +446287,7 @@ async function fireCronTask(task2, now, socket, opts, processQueuedTurn) {
|
|
|
446077
446287
|
status: "ok",
|
|
446078
446288
|
outcome: "queued",
|
|
446079
446289
|
reason: task2.recurring ? "scheduled_time_matched" : "one_off_due",
|
|
446080
|
-
runAtMs:
|
|
446290
|
+
runAtMs: timing.schedulerNow.getTime(),
|
|
446081
446291
|
queueItemId: queuedItem.id,
|
|
446082
446292
|
scheduledFor: task2.scheduled_for,
|
|
446083
446293
|
firedAt: nowIso,
|
|
@@ -446140,8 +446350,11 @@ async function runCronTaskNow(taskId) {
|
|
|
446140
446350
|
error: "Cron scheduler is not running"
|
|
446141
446351
|
};
|
|
446142
446352
|
}
|
|
446143
|
-
const
|
|
446144
|
-
const fired = await fireCronTask(task2,
|
|
446353
|
+
const schedulerNow = new Date;
|
|
446354
|
+
const fired = await fireCronTask(task2, {
|
|
446355
|
+
intendedOccurrence: getIntendedCronOccurrence(task2, schedulerNow),
|
|
446356
|
+
schedulerNow
|
|
446357
|
+
}, ctx.socket, ctx.opts, ctx.processQueuedTurn);
|
|
446145
446358
|
if (!fired) {
|
|
446146
446359
|
return {
|
|
446147
446360
|
success: false,
|
|
@@ -446161,8 +446374,8 @@ function tick2(state, socket, opts, processQueuedTurn) {
|
|
|
446161
446374
|
stopScheduler();
|
|
446162
446375
|
return;
|
|
446163
446376
|
}
|
|
446164
|
-
const
|
|
446165
|
-
const currentMinuteKey = minuteKey(
|
|
446377
|
+
const matchedAt = new Date;
|
|
446378
|
+
const currentMinuteKey = minuteKey(matchedAt);
|
|
446166
446379
|
if (currentMinuteKey !== state.lastMinuteKey) {
|
|
446167
446380
|
state.firedThisMinute.clear();
|
|
446168
446381
|
state.lastMinuteKey = currentMinuteKey;
|
|
@@ -446171,12 +446384,13 @@ function tick2(state, socket, opts, processQueuedTurn) {
|
|
|
446171
446384
|
for (const task2 of state.cachedTasks) {
|
|
446172
446385
|
if (task2.status !== "active")
|
|
446173
446386
|
continue;
|
|
446174
|
-
if (handleMissedOneShot(task2,
|
|
446387
|
+
if (handleMissedOneShot(task2, matchedAt))
|
|
446175
446388
|
continue;
|
|
446176
446389
|
if (state.firedThisMinute.has(task2.id))
|
|
446177
446390
|
continue;
|
|
446178
|
-
if (shouldFireTask(task2,
|
|
446391
|
+
if (shouldFireTask(task2, matchedAt)) {
|
|
446179
446392
|
state.firedThisMinute.add(task2.id);
|
|
446393
|
+
const intendedOccurrence = getIntendedCronOccurrence(task2, matchedAt);
|
|
446180
446394
|
const jitterMs = task2.recurring ? task2.jitter_offset_ms : 0;
|
|
446181
446395
|
const taskId = task2.id;
|
|
446182
446396
|
const doFire = () => {
|
|
@@ -446185,12 +446399,13 @@ function tick2(state, socket, opts, processQueuedTurn) {
|
|
|
446185
446399
|
const freshTask = getTask2(taskId);
|
|
446186
446400
|
if (!freshTask || freshTask.status !== "active")
|
|
446187
446401
|
return;
|
|
446188
|
-
|
|
446402
|
+
const schedulerNow = new Date;
|
|
446403
|
+
fireCronTask(freshTask, { intendedOccurrence, schedulerNow }, socket, opts, processQueuedTurn).catch((err) => {
|
|
446189
446404
|
console.error(`[Cron] Error firing task ${taskId}:`, err);
|
|
446190
446405
|
setLastRunOutcome(freshTask.id, {
|
|
446191
446406
|
outcome: "failed",
|
|
446192
446407
|
reason: "scheduler_error",
|
|
446193
|
-
runAt:
|
|
446408
|
+
runAt: schedulerNow,
|
|
446194
446409
|
error: err instanceof Error ? err.message : String(err)
|
|
446195
446410
|
});
|
|
446196
446411
|
safeAppendCronRunLogForTask(freshTask, {
|
|
@@ -446198,7 +446413,7 @@ function tick2(state, socket, opts, processQueuedTurn) {
|
|
|
446198
446413
|
outcome: "failed",
|
|
446199
446414
|
reason: "scheduler_error",
|
|
446200
446415
|
error: err instanceof Error ? err.message : String(err),
|
|
446201
|
-
runAtMs:
|
|
446416
|
+
runAtMs: schedulerNow.getTime(),
|
|
446202
446417
|
scheduledFor: freshTask.scheduled_for
|
|
446203
446418
|
});
|
|
446204
446419
|
});
|
|
@@ -447306,6 +447521,11 @@ function validateRequestedContextWindow(params) {
|
|
|
447306
447521
|
throw new Error(`Context window cannot exceed the model.json default of ${formatContextWindowTokens(defaultContextWindow)} tokens. Use --override to apply a larger value.`);
|
|
447307
447522
|
}
|
|
447308
447523
|
}
|
|
447524
|
+
function formatMissingContextWindowDefaultError(params) {
|
|
447525
|
+
const modelDescription = params.modelHandle ? `model ${params.modelHandle}` : "the current model";
|
|
447526
|
+
const suggestedValue = typeof params.currentContextWindow === "number" && Number.isSafeInteger(params.currentContextWindow) && params.currentContextWindow > 0 ? String(params.currentContextWindow) : "<tokens>";
|
|
447527
|
+
return `No catalog default for ${modelDescription}, so reset is unavailable. Pass an explicit value: /context-limit ${suggestedValue}.`;
|
|
447528
|
+
}
|
|
447309
447529
|
async function applySetMaxContext(params) {
|
|
447310
447530
|
const parsed = parseSetMaxContextArgs(params.args);
|
|
447311
447531
|
const backend4 = getBackend();
|
|
@@ -447328,7 +447548,10 @@ async function applySetMaxContext(params) {
|
|
|
447328
447548
|
const reset = parsed.value === null;
|
|
447329
447549
|
const contextWindow = reset ? modelDefault.contextWindow : parsed.value;
|
|
447330
447550
|
if (contextWindow === undefined || contextWindow === null) {
|
|
447331
|
-
throw new Error(
|
|
447551
|
+
throw new Error(formatMissingContextWindowDefaultError({
|
|
447552
|
+
modelHandle: effectiveModelHandle,
|
|
447553
|
+
currentContextWindow: effectiveContextWindow ?? effectiveLlmConfig?.context_window ?? null
|
|
447554
|
+
}));
|
|
447332
447555
|
}
|
|
447333
447556
|
if (!reset) {
|
|
447334
447557
|
validateRequestedContextWindow({
|
|
@@ -448057,7 +448280,8 @@ var init_account_config4 = __esm(() => {
|
|
|
448057
448280
|
"default_permission_mode",
|
|
448058
448281
|
"transcribe_voice",
|
|
448059
448282
|
"show_completed_reaction",
|
|
448060
|
-
"listen_mode"
|
|
448283
|
+
"listen_mode",
|
|
448284
|
+
"allow_bots"
|
|
448061
448285
|
]);
|
|
448062
448286
|
slackAccountConfigAdapter = {
|
|
448063
448287
|
isValidConfig(config3) {
|
|
@@ -448066,7 +448290,7 @@ var init_account_config4 = __esm(() => {
|
|
|
448066
448290
|
return false;
|
|
448067
448291
|
}
|
|
448068
448292
|
}
|
|
448069
|
-
return (config3.bot_token === undefined || isString3(config3.bot_token)) && (config3.app_token === undefined || isString3(config3.app_token)) && (config3.mode === undefined || config3.mode === "socket") && (config3.agent_id === undefined || isNullableString4(config3.agent_id)) && (config3.default_permission_mode === undefined || isDefaultPermissionMode2(config3.default_permission_mode)) && (config3.transcribe_voice === undefined || isBoolean3(config3.transcribe_voice)) && (config3.show_completed_reaction === undefined || isBoolean3(config3.show_completed_reaction)) && (config3.listen_mode === undefined || isBoolean3(config3.listen_mode));
|
|
448293
|
+
return (config3.bot_token === undefined || isString3(config3.bot_token)) && (config3.app_token === undefined || isString3(config3.app_token)) && (config3.mode === undefined || config3.mode === "socket") && (config3.agent_id === undefined || isNullableString4(config3.agent_id)) && (config3.default_permission_mode === undefined || isDefaultPermissionMode2(config3.default_permission_mode)) && (config3.transcribe_voice === undefined || isBoolean3(config3.transcribe_voice)) && (config3.show_completed_reaction === undefined || isBoolean3(config3.show_completed_reaction)) && (config3.listen_mode === undefined || isBoolean3(config3.listen_mode)) && isValidSlackAllowBotsConfigValue(config3.allow_bots);
|
|
448070
448294
|
},
|
|
448071
448295
|
toAccountPatch(config3) {
|
|
448072
448296
|
return {
|
|
@@ -448076,7 +448300,8 @@ var init_account_config4 = __esm(() => {
|
|
|
448076
448300
|
agentId: isNullableString4(config3.agent_id) ? config3.agent_id : undefined,
|
|
448077
448301
|
defaultPermissionMode: isDefaultPermissionMode2(config3.default_permission_mode) ? migratePermissionMode(config3.default_permission_mode) : undefined,
|
|
448078
448302
|
transcribeVoice: isBoolean3(config3.transcribe_voice) ? config3.transcribe_voice : undefined,
|
|
448079
|
-
listenMode: isBoolean3(config3.listen_mode) ? config3.listen_mode : undefined
|
|
448303
|
+
listenMode: isBoolean3(config3.listen_mode) ? config3.listen_mode : undefined,
|
|
448304
|
+
allowBots: config3.allow_bots !== undefined && isValidSlackAllowBotsConfigValue(config3.allow_bots) ? normalizeSlackAllowBotsMode(config3.allow_bots) : undefined
|
|
448080
448305
|
};
|
|
448081
448306
|
},
|
|
448082
448307
|
toAccountConfig(account) {
|
|
@@ -448087,7 +448312,8 @@ var init_account_config4 = __esm(() => {
|
|
|
448087
448312
|
agent_id: account.agentId,
|
|
448088
448313
|
default_permission_mode: account.defaultPermissionMode ?? DEFAULT_SLACK_PERMISSION_MODE,
|
|
448089
448314
|
transcribe_voice: account.transcribeVoice === true,
|
|
448090
|
-
listen_mode: account.listenMode === true
|
|
448315
|
+
listen_mode: account.listenMode === true,
|
|
448316
|
+
allow_bots: account.allowBots ?? false
|
|
448091
448317
|
};
|
|
448092
448318
|
},
|
|
448093
448319
|
toConfigSnapshotConfig(account) {
|
|
@@ -448098,7 +448324,8 @@ var init_account_config4 = __esm(() => {
|
|
|
448098
448324
|
agent_id: account.agentId,
|
|
448099
448325
|
default_permission_mode: account.defaultPermissionMode ?? DEFAULT_SLACK_PERMISSION_MODE,
|
|
448100
448326
|
transcribe_voice: account.transcribeVoice === true,
|
|
448101
|
-
listen_mode: account.listenMode === true
|
|
448327
|
+
listen_mode: account.listenMode === true,
|
|
448328
|
+
allow_bots: account.allowBots ?? false
|
|
448102
448329
|
};
|
|
448103
448330
|
},
|
|
448104
448331
|
shouldRefreshDisplayName(patch2) {
|
|
@@ -458863,6 +459090,7 @@ function createAccountFromPatch(channelId, accountId, patch2) {
|
|
|
458863
459090
|
defaultPermissionMode: normalizedPatch.defaultPermissionMode ?? DEFAULT_SLACK_PERMISSION_MODE,
|
|
458864
459091
|
transcribeVoice: normalizedPatch.transcribeVoice === true,
|
|
458865
459092
|
listenMode: normalizedPatch.listenMode === true,
|
|
459093
|
+
allowBots: normalizedPatch.allowBots ?? false,
|
|
458866
459094
|
dmPolicy: normalizedPatch.dmPolicy ?? "open",
|
|
458867
459095
|
allowedUsers: normalizedPatch.allowedUsers ?? [],
|
|
458868
459096
|
createdAt: now,
|
|
@@ -458969,6 +459197,7 @@ function mergeAccountPatch(existing, patch2) {
|
|
|
458969
459197
|
defaultPermissionMode: normalizedPatch.defaultPermissionMode ?? existing.defaultPermissionMode ?? DEFAULT_SLACK_PERMISSION_MODE,
|
|
458970
459198
|
transcribeVoice: normalizedPatch.transcribeVoice ?? existing.transcribeVoice ?? false,
|
|
458971
459199
|
listenMode: normalizedPatch.listenMode ?? existing.listenMode ?? false,
|
|
459200
|
+
allowBots: normalizedPatch.allowBots ?? existing.allowBots ?? false,
|
|
458972
459201
|
dmPolicy: normalizedPatch.dmPolicy ?? existing.dmPolicy,
|
|
458973
459202
|
allowedUsers: normalizedPatch.allowedUsers ?? existing.allowedUsers,
|
|
458974
459203
|
updatedAt: nextUpdatedAt
|
|
@@ -459150,6 +459379,7 @@ function toAccountSnapshot(account) {
|
|
|
459150
459379
|
defaultPermissionMode: account.defaultPermissionMode ?? DEFAULT_SLACK_PERMISSION_MODE,
|
|
459151
459380
|
transcribeVoice: account.transcribeVoice === true,
|
|
459152
459381
|
listenMode: account.listenMode === true,
|
|
459382
|
+
allowBots: account.allowBots ?? false,
|
|
459153
459383
|
createdAt: account.createdAt,
|
|
459154
459384
|
updatedAt: account.updatedAt
|
|
459155
459385
|
};
|
|
@@ -459297,7 +459527,8 @@ function getChannelConfigSnapshot(channelId, accountId) {
|
|
|
459297
459527
|
agentId: account.agentId,
|
|
459298
459528
|
defaultPermissionMode: account.defaultPermissionMode ?? DEFAULT_SLACK_PERMISSION_MODE,
|
|
459299
459529
|
transcribeVoice: account.transcribeVoice === true,
|
|
459300
|
-
listenMode: account.listenMode === true
|
|
459530
|
+
listenMode: account.listenMode === true,
|
|
459531
|
+
allowBots: account.allowBots ?? false
|
|
459301
459532
|
};
|
|
459302
459533
|
}
|
|
459303
459534
|
async function getChannelConfigSnapshotWithSecrets(channelId, accountId) {
|
|
@@ -459820,6 +460051,7 @@ async function setChannelConfigLive(channelId, patch2, accountId) {
|
|
|
459820
460051
|
threadPolicyByChannel: normalizedPatch.threadPolicyByChannel,
|
|
459821
460052
|
acknowledgeMessageReaction: normalizedPatch.acknowledgeMessageReaction,
|
|
459822
460053
|
listenMode: normalizedPatch.listenMode,
|
|
460054
|
+
allowBots: normalizedPatch.allowBots,
|
|
459823
460055
|
removeStaleRoutes: normalizedPatch.removeStaleRoutes,
|
|
459824
460056
|
inboundDebounceMs: normalizedPatch.inboundDebounceMs,
|
|
459825
460057
|
selfChatMode: normalizedPatch.selfChatMode,
|
|
@@ -459854,6 +460086,7 @@ async function setChannelConfigLive(channelId, patch2, accountId) {
|
|
|
459854
460086
|
threadPolicyByChannel: normalizedPatch.threadPolicyByChannel,
|
|
459855
460087
|
acknowledgeMessageReaction: normalizedPatch.acknowledgeMessageReaction,
|
|
459856
460088
|
listenMode: normalizedPatch.listenMode,
|
|
460089
|
+
allowBots: normalizedPatch.allowBots,
|
|
459857
460090
|
removeStaleRoutes: normalizedPatch.removeStaleRoutes,
|
|
459858
460091
|
inboundDebounceMs: normalizedPatch.inboundDebounceMs,
|
|
459859
460092
|
selfChatMode: normalizedPatch.selfChatMode,
|
|
@@ -473482,7 +473715,6 @@ When to use: ${whenToUse}` : description;
|
|
|
473482
473715
|
description: modelDescription,
|
|
473483
473716
|
whenToUse,
|
|
473484
473717
|
argumentHint: getFrontmatterString2(frontmatter, "argument-hint"),
|
|
473485
|
-
arguments: getFrontmatterStringList2(frontmatter, "arguments"),
|
|
473486
473718
|
disableModelInvocation: getFrontmatterBoolean2(frontmatter, "disable-model-invocation") ?? false,
|
|
473487
473719
|
userInvocable: getFrontmatterBoolean2(frontmatter, "user-invocable") ?? true,
|
|
473488
473720
|
category: getFrontmatterString2(frontmatter, "category"),
|
|
@@ -489812,10 +490044,10 @@ function columns(parts, width) {
|
|
|
489812
490044
|
let extra = spare - base3 * gaps;
|
|
489813
490045
|
let result = first;
|
|
489814
490046
|
for (let i4 = 1;i4 < items3.length; i4 += 1) {
|
|
489815
|
-
const
|
|
490047
|
+
const pad3 = base3 + (extra > 0 ? 1 : 0);
|
|
489816
490048
|
if (extra > 0)
|
|
489817
490049
|
extra -= 1;
|
|
489818
|
-
result += " ".repeat(
|
|
490050
|
+
result += " ".repeat(pad3) + items3[i4];
|
|
489819
490051
|
}
|
|
489820
490052
|
return truncateToWidth(result, width);
|
|
489821
490053
|
}
|
|
@@ -507243,8 +507475,8 @@ function splitSystemReminderBlocks(text2) {
|
|
|
507243
507475
|
return blocks;
|
|
507244
507476
|
}
|
|
507245
507477
|
function padToColumns(text2, columns2) {
|
|
507246
|
-
const
|
|
507247
|
-
return `${text2}${" ".repeat(
|
|
507478
|
+
const pad3 = Math.max(0, columns2 - inkStringWidth(text2));
|
|
507479
|
+
return `${text2}${" ".repeat(pad3)}`;
|
|
507248
507480
|
}
|
|
507249
507481
|
function renderBlock(text2, contentWidth, columns2, highlighted, promptPrefix, continuationPrefix) {
|
|
507250
507482
|
const inputLines = text2.split(`
|
|
@@ -534222,7 +534454,6 @@ ${SYSTEM_REMINDER_CLOSE}`),
|
|
|
534222
534454
|
const { loadRenderedSkillContent: loadRenderedSkillContent2, wrapSkillContent: wrapSkillContent2 } = await Promise.resolve().then(() => (init_skill(), exports_skill));
|
|
534223
534455
|
const skillContent = await loadRenderedSkillContent2("generating-mod-envs", {
|
|
534224
534456
|
agentId,
|
|
534225
|
-
args,
|
|
534226
534457
|
allowDisabledModelInvocation: true
|
|
534227
534458
|
});
|
|
534228
534459
|
const request = args ? `The user ran \`/mods generate-env ${args}\`. Use the loaded skill to help them generate, review, validate, or improve a mod learning env JSON.` : "The user ran `/mods generate-env` without arguments. Use the loaded skill's bare behavior for mod learning env generation.";
|
|
@@ -534492,7 +534723,6 @@ ${SYSTEM_REMINDER_CLOSE}`),
|
|
|
534492
534723
|
const { loadRenderedSkillContent: loadRenderedSkillContent2, wrapSkillContent: wrapSkillContent2 } = await Promise.resolve().then(() => (init_skill(), exports_skill));
|
|
534493
534724
|
const skillContent = await loadRenderedSkillContent2("customizing-statusline", {
|
|
534494
534725
|
agentId,
|
|
534495
|
-
args,
|
|
534496
534726
|
allowDisabledModelInvocation: true
|
|
534497
534727
|
});
|
|
534498
534728
|
const request = args ? `The user ran \`/statusline ${args}\`. Use the loaded skill to help them create, edit, or migrate their Letta Code statusline mod.` : "The user ran `/statusline` without arguments. Use the loaded skill's bare `/statusline` behavior.";
|
|
@@ -535968,13 +536198,12 @@ Resumed reflection arena choice prompt for run ${run2.runId}.`, true);
|
|
|
535968
536198
|
cmd.fail(`Pending approval(s). Resolve approvals before running /${matchedSkill.id}.`);
|
|
535969
536199
|
return { submitted: false };
|
|
535970
536200
|
}
|
|
535971
|
-
const
|
|
536201
|
+
const userRequest = trimmed.slice(`/${matchedSkill.id}`.length).trim();
|
|
535972
536202
|
setCommandRunning(true);
|
|
535973
536203
|
try {
|
|
535974
|
-
const { loadRenderedSkillContent: loadRenderedSkillContent2,
|
|
536204
|
+
const { loadRenderedSkillContent: loadRenderedSkillContent2, wrapSkillPrompt: wrapSkillPrompt2 } = await Promise.resolve().then(() => (init_skill(), exports_skill));
|
|
535975
536205
|
const skillContent = await loadRenderedSkillContent2(matchedSkill.id, {
|
|
535976
536206
|
agentId,
|
|
535977
|
-
args,
|
|
535978
536207
|
allowDisabledModelInvocation: true
|
|
535979
536208
|
});
|
|
535980
536209
|
cmd.finish("Running skill...", true);
|
|
@@ -535982,7 +536211,7 @@ Resumed reflection arena choice prompt for run ${run2.runId}.`, true);
|
|
|
535982
536211
|
{
|
|
535983
536212
|
type: "message",
|
|
535984
536213
|
role: "user",
|
|
535985
|
-
content: buildTextParts(
|
|
536214
|
+
content: buildTextParts(wrapSkillPrompt2(matchedSkill.id, skillContent, userRequest)),
|
|
535986
536215
|
otid: randomUUID37()
|
|
535987
536216
|
}
|
|
535988
536217
|
]);
|
|
@@ -537021,26 +537250,25 @@ function App2({
|
|
|
537021
537250
|
continue;
|
|
537022
537251
|
if (shouldFireTask(task2, now)) {
|
|
537023
537252
|
firedThisMinute.add(task2.id);
|
|
537253
|
+
const intendedOccurrence = getIntendedCronOccurrence(task2, now);
|
|
537024
537254
|
const jitterMs = task2.recurring ? task2.jitter_offset_ms : 0;
|
|
537025
537255
|
const taskId = task2.id;
|
|
537026
537256
|
const doFire = () => {
|
|
537027
537257
|
const freshTask = getTask2(taskId);
|
|
537028
537258
|
if (!freshTask || freshTask.status !== "active")
|
|
537029
537259
|
return;
|
|
537030
|
-
const
|
|
537031
|
-
|
|
537032
|
-
|
|
537033
|
-
|
|
537034
|
-
|
|
537035
|
-
].join(`
|
|
537036
|
-
`);
|
|
537260
|
+
const schedulerNow = new Date;
|
|
537261
|
+
const text2 = wrapCronPrompt(freshTask, {
|
|
537262
|
+
intendedOccurrence,
|
|
537263
|
+
schedulerNow
|
|
537264
|
+
});
|
|
537037
537265
|
addToMessageQueue({
|
|
537038
537266
|
kind: "user",
|
|
537039
537267
|
text: text2,
|
|
537040
537268
|
agentId: freshTask.agent_id,
|
|
537041
537269
|
conversationId: freshTask.conversation_id
|
|
537042
537270
|
});
|
|
537043
|
-
const nowIso =
|
|
537271
|
+
const nowIso = schedulerNow.toISOString();
|
|
537044
537272
|
if (freshTask.recurring) {
|
|
537045
537273
|
updateTask2(freshTask.id, (t2) => {
|
|
537046
537274
|
t2.last_fired_at = nowIso;
|
|
@@ -537056,7 +537284,7 @@ function App2({
|
|
|
537056
537284
|
}
|
|
537057
537285
|
safeAppendCronRunLogForTask(freshTask, {
|
|
537058
537286
|
status: "ok",
|
|
537059
|
-
runAtMs:
|
|
537287
|
+
runAtMs: schedulerNow.getTime(),
|
|
537060
537288
|
scheduledFor: freshTask.scheduled_for,
|
|
537061
537289
|
firedAt: nowIso
|
|
537062
537290
|
});
|
|
@@ -549661,15 +549889,15 @@ function convertLegacyMessage(message, nextId2) {
|
|
|
549661
549889
|
return result;
|
|
549662
549890
|
}
|
|
549663
549891
|
function timestampSuffix(date6 = new Date) {
|
|
549664
|
-
const
|
|
549892
|
+
const pad3 = (value) => String(value).padStart(2, "0");
|
|
549665
549893
|
return [
|
|
549666
549894
|
date6.getFullYear(),
|
|
549667
|
-
|
|
549668
|
-
|
|
549895
|
+
pad3(date6.getMonth() + 1),
|
|
549896
|
+
pad3(date6.getDate()),
|
|
549669
549897
|
"-",
|
|
549670
|
-
|
|
549671
|
-
|
|
549672
|
-
|
|
549898
|
+
pad3(date6.getHours()),
|
|
549899
|
+
pad3(date6.getMinutes()),
|
|
549900
|
+
pad3(date6.getSeconds())
|
|
549673
549901
|
].join("");
|
|
549674
549902
|
}
|
|
549675
549903
|
function manifest(input) {
|
|
@@ -550022,13 +550250,13 @@ function getAgentRoot(agentId) {
|
|
|
550022
550250
|
return dirname28(getMemoryRoot(agentId));
|
|
550023
550251
|
}
|
|
550024
550252
|
function formatBackupTimestamp(date6 = new Date) {
|
|
550025
|
-
const
|
|
550253
|
+
const pad3 = (value) => String(value).padStart(2, "0");
|
|
550026
550254
|
const yyyy = date6.getFullYear();
|
|
550027
|
-
const mm =
|
|
550028
|
-
const dd2 =
|
|
550029
|
-
const hh =
|
|
550030
|
-
const min =
|
|
550031
|
-
const ss =
|
|
550255
|
+
const mm = pad3(date6.getMonth() + 1);
|
|
550256
|
+
const dd2 = pad3(date6.getDate());
|
|
550257
|
+
const hh = pad3(date6.getHours());
|
|
550258
|
+
const min = pad3(date6.getMinutes());
|
|
550259
|
+
const ss = pad3(date6.getSeconds());
|
|
550032
550260
|
return `${yyyy}${mm}${dd2}-${hh}${min}${ss}`;
|
|
550033
550261
|
}
|
|
550034
550262
|
async function listBackups(agentId) {
|
|
@@ -556331,4 +556559,4 @@ Error during initialization: ${message}`);
|
|
|
556331
556559
|
}
|
|
556332
556560
|
main2();
|
|
556333
556561
|
|
|
556334
|
-
//# debugId=
|
|
556562
|
+
//# debugId=5F03A493E92C4D6964756E2164756E21
|