@letta-ai/letta-code 0.22.0 → 0.22.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/letta.js +1118 -315
- package/package.json +1 -1
package/letta.js
CHANGED
|
@@ -3269,7 +3269,7 @@ var package_default;
|
|
|
3269
3269
|
var init_package = __esm(() => {
|
|
3270
3270
|
package_default = {
|
|
3271
3271
|
name: "@letta-ai/letta-code",
|
|
3272
|
-
version: "0.22.
|
|
3272
|
+
version: "0.22.2",
|
|
3273
3273
|
description: "Letta Code is a CLI tool for interacting with stateful Letta agents from the terminal.",
|
|
3274
3274
|
type: "module",
|
|
3275
3275
|
bin: {
|
|
@@ -5153,19 +5153,86 @@ __export(exports_oauth, {
|
|
|
5153
5153
|
OAUTH_CONFIG: () => OAUTH_CONFIG,
|
|
5154
5154
|
LETTA_CLOUD_API_URL: () => LETTA_CLOUD_API_URL
|
|
5155
5155
|
});
|
|
5156
|
+
function getOAuthAuthHost() {
|
|
5157
|
+
try {
|
|
5158
|
+
return new URL(OAUTH_CONFIG.authBaseUrl).host;
|
|
5159
|
+
} catch {
|
|
5160
|
+
return OAUTH_CONFIG.authBaseUrl;
|
|
5161
|
+
}
|
|
5162
|
+
}
|
|
5163
|
+
function getErrorLikeMessage(value) {
|
|
5164
|
+
if (value instanceof Error) {
|
|
5165
|
+
return value.message.trim() || null;
|
|
5166
|
+
}
|
|
5167
|
+
if (!value || typeof value !== "object") {
|
|
5168
|
+
return null;
|
|
5169
|
+
}
|
|
5170
|
+
const message = value.message;
|
|
5171
|
+
return typeof message === "string" && message.trim().length > 0 ? message.trim() : null;
|
|
5172
|
+
}
|
|
5173
|
+
function getErrorLikeCode(value) {
|
|
5174
|
+
if (!value || typeof value !== "object") {
|
|
5175
|
+
return null;
|
|
5176
|
+
}
|
|
5177
|
+
const code = value.code;
|
|
5178
|
+
return typeof code === "string" && code.trim().length > 0 ? code.trim() : null;
|
|
5179
|
+
}
|
|
5180
|
+
function isGenericFetchFailureMessage(message) {
|
|
5181
|
+
const normalized = message.trim().toLowerCase();
|
|
5182
|
+
return normalized === "fetch failed" || normalized === "network request failed";
|
|
5183
|
+
}
|
|
5184
|
+
function isOAuthTransportError(error) {
|
|
5185
|
+
if (!(error instanceof Error)) {
|
|
5186
|
+
return false;
|
|
5187
|
+
}
|
|
5188
|
+
if (isGenericFetchFailureMessage(error.message)) {
|
|
5189
|
+
return true;
|
|
5190
|
+
}
|
|
5191
|
+
return error.name === "TypeError" && error.cause !== undefined;
|
|
5192
|
+
}
|
|
5193
|
+
function extractOAuthTransportDetail(error) {
|
|
5194
|
+
const directMessage = isGenericFetchFailureMessage(error.message) ? null : error.message.trim() || null;
|
|
5195
|
+
const causeMessage = getErrorLikeMessage(error.cause);
|
|
5196
|
+
const causeCode = getErrorLikeCode(error.cause);
|
|
5197
|
+
let detail = causeMessage ?? directMessage;
|
|
5198
|
+
if (!detail && causeCode) {
|
|
5199
|
+
detail = causeCode;
|
|
5200
|
+
}
|
|
5201
|
+
if (detail && causeCode && !detail.includes(causeCode)) {
|
|
5202
|
+
detail = `${detail} (${causeCode})`;
|
|
5203
|
+
}
|
|
5204
|
+
return detail;
|
|
5205
|
+
}
|
|
5206
|
+
function toOAuthActionError(action, error, options) {
|
|
5207
|
+
if (isOAuthTransportError(error)) {
|
|
5208
|
+
const host = getOAuthAuthHost();
|
|
5209
|
+
const detail = extractOAuthTransportDetail(error);
|
|
5210
|
+
const reachabilityHint = options?.browserHint ? "Browser authorization may have succeeded, but the CLI could not reach Letta auth servers from this machine." : "The CLI could not reach Letta auth servers from this machine.";
|
|
5211
|
+
return new Error(`Failed to ${action} from ${host}${detail ? `: ${detail}` : ""}. ${reachabilityHint} Check your network, DNS, proxy, VPN, or TLS settings.`);
|
|
5212
|
+
}
|
|
5213
|
+
if (error instanceof Error) {
|
|
5214
|
+
return error;
|
|
5215
|
+
}
|
|
5216
|
+
return new Error(`Failed to ${action}: ${String(error)}`);
|
|
5217
|
+
}
|
|
5156
5218
|
async function requestDeviceCode() {
|
|
5157
|
-
const
|
|
5158
|
-
|
|
5159
|
-
|
|
5160
|
-
|
|
5161
|
-
|
|
5162
|
-
|
|
5163
|
-
|
|
5164
|
-
|
|
5165
|
-
|
|
5166
|
-
|
|
5219
|
+
const authHost = getOAuthAuthHost();
|
|
5220
|
+
try {
|
|
5221
|
+
const response = await fetch(`${OAUTH_CONFIG.authBaseUrl}/api/oauth/device/code`, {
|
|
5222
|
+
method: "POST",
|
|
5223
|
+
headers: { "Content-Type": "application/json" },
|
|
5224
|
+
body: JSON.stringify({
|
|
5225
|
+
client_id: OAUTH_CONFIG.clientId
|
|
5226
|
+
})
|
|
5227
|
+
});
|
|
5228
|
+
if (!response.ok) {
|
|
5229
|
+
const error = await response.json();
|
|
5230
|
+
throw new Error(`Failed to request device code from ${authHost}: ${error.error_description || error.error}`);
|
|
5231
|
+
}
|
|
5232
|
+
return await response.json();
|
|
5233
|
+
} catch (error) {
|
|
5234
|
+
throw toOAuthActionError("request device code", error);
|
|
5167
5235
|
}
|
|
5168
|
-
return await response.json();
|
|
5169
5236
|
}
|
|
5170
5237
|
async function pollForToken(deviceCode, interval = 5, expiresIn = 900, deviceId, deviceName) {
|
|
5171
5238
|
const startTime = Date.now();
|
|
@@ -5211,7 +5278,9 @@ async function pollForToken(deviceCode, interval = 5, expiresIn = 900, deviceId,
|
|
|
5211
5278
|
context: "auth_oauth_token_poll"
|
|
5212
5279
|
});
|
|
5213
5280
|
if (error instanceof Error) {
|
|
5214
|
-
throw error
|
|
5281
|
+
throw toOAuthActionError("poll for OAuth token", error, {
|
|
5282
|
+
browserHint: true
|
|
5283
|
+
});
|
|
5215
5284
|
}
|
|
5216
5285
|
throw new Error(`Failed to poll for token: ${String(error)}`);
|
|
5217
5286
|
}
|
|
@@ -5219,23 +5288,28 @@ async function pollForToken(deviceCode, interval = 5, expiresIn = 900, deviceId,
|
|
|
5219
5288
|
throw new Error("Timeout waiting for authorization (15 minutes)");
|
|
5220
5289
|
}
|
|
5221
5290
|
async function refreshAccessToken(refreshToken, deviceId, deviceName) {
|
|
5222
|
-
const
|
|
5223
|
-
|
|
5224
|
-
|
|
5225
|
-
|
|
5226
|
-
|
|
5227
|
-
|
|
5228
|
-
|
|
5229
|
-
|
|
5230
|
-
|
|
5231
|
-
|
|
5232
|
-
|
|
5233
|
-
|
|
5234
|
-
|
|
5235
|
-
|
|
5236
|
-
|
|
5291
|
+
const authHost = getOAuthAuthHost();
|
|
5292
|
+
try {
|
|
5293
|
+
const response = await fetch(`${OAUTH_CONFIG.authBaseUrl}/api/oauth/token`, {
|
|
5294
|
+
method: "POST",
|
|
5295
|
+
headers: { "Content-Type": "application/json" },
|
|
5296
|
+
body: JSON.stringify({
|
|
5297
|
+
grant_type: "refresh_token",
|
|
5298
|
+
client_id: OAUTH_CONFIG.clientId,
|
|
5299
|
+
refresh_token: refreshToken,
|
|
5300
|
+
refresh_token_mode: "new",
|
|
5301
|
+
device_id: deviceId,
|
|
5302
|
+
...deviceName && { device_name: deviceName }
|
|
5303
|
+
})
|
|
5304
|
+
});
|
|
5305
|
+
if (!response.ok) {
|
|
5306
|
+
const error = await response.json();
|
|
5307
|
+
throw new Error(`Failed to refresh access token from ${authHost}: ${error.error_description || error.error}`);
|
|
5308
|
+
}
|
|
5309
|
+
return await response.json();
|
|
5310
|
+
} catch (error) {
|
|
5311
|
+
throw toOAuthActionError("refresh access token", error);
|
|
5237
5312
|
}
|
|
5238
|
-
return await response.json();
|
|
5239
5313
|
}
|
|
5240
5314
|
async function revokeToken(refreshToken) {
|
|
5241
5315
|
try {
|
|
@@ -10364,19 +10438,86 @@ __export(exports_oauth2, {
|
|
|
10364
10438
|
OAUTH_CONFIG: () => OAUTH_CONFIG2,
|
|
10365
10439
|
LETTA_CLOUD_API_URL: () => LETTA_CLOUD_API_URL2
|
|
10366
10440
|
});
|
|
10441
|
+
function getOAuthAuthHost2() {
|
|
10442
|
+
try {
|
|
10443
|
+
return new URL(OAUTH_CONFIG2.authBaseUrl).host;
|
|
10444
|
+
} catch {
|
|
10445
|
+
return OAUTH_CONFIG2.authBaseUrl;
|
|
10446
|
+
}
|
|
10447
|
+
}
|
|
10448
|
+
function getErrorLikeMessage2(value) {
|
|
10449
|
+
if (value instanceof Error) {
|
|
10450
|
+
return value.message.trim() || null;
|
|
10451
|
+
}
|
|
10452
|
+
if (!value || typeof value !== "object") {
|
|
10453
|
+
return null;
|
|
10454
|
+
}
|
|
10455
|
+
const message = value.message;
|
|
10456
|
+
return typeof message === "string" && message.trim().length > 0 ? message.trim() : null;
|
|
10457
|
+
}
|
|
10458
|
+
function getErrorLikeCode2(value) {
|
|
10459
|
+
if (!value || typeof value !== "object") {
|
|
10460
|
+
return null;
|
|
10461
|
+
}
|
|
10462
|
+
const code = value.code;
|
|
10463
|
+
return typeof code === "string" && code.trim().length > 0 ? code.trim() : null;
|
|
10464
|
+
}
|
|
10465
|
+
function isGenericFetchFailureMessage2(message) {
|
|
10466
|
+
const normalized = message.trim().toLowerCase();
|
|
10467
|
+
return normalized === "fetch failed" || normalized === "network request failed";
|
|
10468
|
+
}
|
|
10469
|
+
function isOAuthTransportError2(error) {
|
|
10470
|
+
if (!(error instanceof Error)) {
|
|
10471
|
+
return false;
|
|
10472
|
+
}
|
|
10473
|
+
if (isGenericFetchFailureMessage2(error.message)) {
|
|
10474
|
+
return true;
|
|
10475
|
+
}
|
|
10476
|
+
return error.name === "TypeError" && error.cause !== undefined;
|
|
10477
|
+
}
|
|
10478
|
+
function extractOAuthTransportDetail2(error) {
|
|
10479
|
+
const directMessage = isGenericFetchFailureMessage2(error.message) ? null : error.message.trim() || null;
|
|
10480
|
+
const causeMessage = getErrorLikeMessage2(error.cause);
|
|
10481
|
+
const causeCode = getErrorLikeCode2(error.cause);
|
|
10482
|
+
let detail = causeMessage ?? directMessage;
|
|
10483
|
+
if (!detail && causeCode) {
|
|
10484
|
+
detail = causeCode;
|
|
10485
|
+
}
|
|
10486
|
+
if (detail && causeCode && !detail.includes(causeCode)) {
|
|
10487
|
+
detail = `${detail} (${causeCode})`;
|
|
10488
|
+
}
|
|
10489
|
+
return detail;
|
|
10490
|
+
}
|
|
10491
|
+
function toOAuthActionError2(action, error, options) {
|
|
10492
|
+
if (isOAuthTransportError2(error)) {
|
|
10493
|
+
const host = getOAuthAuthHost2();
|
|
10494
|
+
const detail = extractOAuthTransportDetail2(error);
|
|
10495
|
+
const reachabilityHint = options?.browserHint ? "Browser authorization may have succeeded, but the CLI could not reach Letta auth servers from this machine." : "The CLI could not reach Letta auth servers from this machine.";
|
|
10496
|
+
return new Error(`Failed to ${action} from ${host}${detail ? `: ${detail}` : ""}. ${reachabilityHint} Check your network, DNS, proxy, VPN, or TLS settings.`);
|
|
10497
|
+
}
|
|
10498
|
+
if (error instanceof Error) {
|
|
10499
|
+
return error;
|
|
10500
|
+
}
|
|
10501
|
+
return new Error(`Failed to ${action}: ${String(error)}`);
|
|
10502
|
+
}
|
|
10367
10503
|
async function requestDeviceCode2() {
|
|
10368
|
-
const
|
|
10369
|
-
|
|
10370
|
-
|
|
10371
|
-
|
|
10372
|
-
|
|
10373
|
-
|
|
10374
|
-
|
|
10375
|
-
|
|
10376
|
-
|
|
10377
|
-
|
|
10504
|
+
const authHost = getOAuthAuthHost2();
|
|
10505
|
+
try {
|
|
10506
|
+
const response = await fetch(`${OAUTH_CONFIG2.authBaseUrl}/api/oauth/device/code`, {
|
|
10507
|
+
method: "POST",
|
|
10508
|
+
headers: { "Content-Type": "application/json" },
|
|
10509
|
+
body: JSON.stringify({
|
|
10510
|
+
client_id: OAUTH_CONFIG2.clientId
|
|
10511
|
+
})
|
|
10512
|
+
});
|
|
10513
|
+
if (!response.ok) {
|
|
10514
|
+
const error = await response.json();
|
|
10515
|
+
throw new Error(`Failed to request device code from ${authHost}: ${error.error_description || error.error}`);
|
|
10516
|
+
}
|
|
10517
|
+
return await response.json();
|
|
10518
|
+
} catch (error) {
|
|
10519
|
+
throw toOAuthActionError2("request device code", error);
|
|
10378
10520
|
}
|
|
10379
|
-
return await response.json();
|
|
10380
10521
|
}
|
|
10381
10522
|
async function pollForToken2(deviceCode, interval = 5, expiresIn = 900, deviceId, deviceName) {
|
|
10382
10523
|
const startTime = Date.now();
|
|
@@ -10422,7 +10563,9 @@ async function pollForToken2(deviceCode, interval = 5, expiresIn = 900, deviceId
|
|
|
10422
10563
|
context: "auth_oauth_token_poll"
|
|
10423
10564
|
});
|
|
10424
10565
|
if (error instanceof Error) {
|
|
10425
|
-
throw error
|
|
10566
|
+
throw toOAuthActionError2("poll for OAuth token", error, {
|
|
10567
|
+
browserHint: true
|
|
10568
|
+
});
|
|
10426
10569
|
}
|
|
10427
10570
|
throw new Error(`Failed to poll for token: ${String(error)}`);
|
|
10428
10571
|
}
|
|
@@ -10430,23 +10573,28 @@ async function pollForToken2(deviceCode, interval = 5, expiresIn = 900, deviceId
|
|
|
10430
10573
|
throw new Error("Timeout waiting for authorization (15 minutes)");
|
|
10431
10574
|
}
|
|
10432
10575
|
async function refreshAccessToken2(refreshToken, deviceId, deviceName) {
|
|
10433
|
-
const
|
|
10434
|
-
|
|
10435
|
-
|
|
10436
|
-
|
|
10437
|
-
|
|
10438
|
-
|
|
10439
|
-
|
|
10440
|
-
|
|
10441
|
-
|
|
10442
|
-
|
|
10443
|
-
|
|
10444
|
-
|
|
10445
|
-
|
|
10446
|
-
|
|
10447
|
-
|
|
10576
|
+
const authHost = getOAuthAuthHost2();
|
|
10577
|
+
try {
|
|
10578
|
+
const response = await fetch(`${OAUTH_CONFIG2.authBaseUrl}/api/oauth/token`, {
|
|
10579
|
+
method: "POST",
|
|
10580
|
+
headers: { "Content-Type": "application/json" },
|
|
10581
|
+
body: JSON.stringify({
|
|
10582
|
+
grant_type: "refresh_token",
|
|
10583
|
+
client_id: OAUTH_CONFIG2.clientId,
|
|
10584
|
+
refresh_token: refreshToken,
|
|
10585
|
+
refresh_token_mode: "new",
|
|
10586
|
+
device_id: deviceId,
|
|
10587
|
+
...deviceName && { device_name: deviceName }
|
|
10588
|
+
})
|
|
10589
|
+
});
|
|
10590
|
+
if (!response.ok) {
|
|
10591
|
+
const error = await response.json();
|
|
10592
|
+
throw new Error(`Failed to refresh access token from ${authHost}: ${error.error_description || error.error}`);
|
|
10593
|
+
}
|
|
10594
|
+
return await response.json();
|
|
10595
|
+
} catch (error) {
|
|
10596
|
+
throw toOAuthActionError2("refresh access token", error);
|
|
10448
10597
|
}
|
|
10449
|
-
return await response.json();
|
|
10450
10598
|
}
|
|
10451
10599
|
async function revokeToken2(refreshToken) {
|
|
10452
10600
|
try {
|
|
@@ -38922,6 +39070,10 @@ for file in $(git diff --cached --name-only --diff-filter=ACM | grep -E '^(memor
|
|
|
38922
39070
|
# Validate each line
|
|
38923
39071
|
while IFS= read -r line; do
|
|
38924
39072
|
[ -z "$line" ] && continue
|
|
39073
|
+
# Skip YAML multiline continuation lines (indented lines that continue a previous value)
|
|
39074
|
+
case "$line" in
|
|
39075
|
+
" "*|$' '*) continue ;;
|
|
39076
|
+
esac
|
|
38925
39077
|
|
|
38926
39078
|
key=$(echo "$line" | cut -d: -f1 | tr -d ' ')
|
|
38927
39079
|
value=$(echo "$line" | cut -d: -f2- | sed 's/^ *//;s/ *$//')
|
|
@@ -39842,11 +39994,227 @@ var init_routing = __esm(() => {
|
|
|
39842
39994
|
routesByKey = new Map;
|
|
39843
39995
|
});
|
|
39844
39996
|
|
|
39997
|
+
// src/cli/helpers/gitContext.ts
|
|
39998
|
+
import { execFileSync } from "node:child_process";
|
|
39999
|
+
function runGit3(args, cwd2) {
|
|
40000
|
+
try {
|
|
40001
|
+
return execFileSync("git", args, {
|
|
40002
|
+
cwd: cwd2,
|
|
40003
|
+
encoding: "utf-8",
|
|
40004
|
+
stdio: ["ignore", "pipe", "ignore"]
|
|
40005
|
+
}).trim();
|
|
40006
|
+
} catch {
|
|
40007
|
+
return null;
|
|
40008
|
+
}
|
|
40009
|
+
}
|
|
40010
|
+
function truncateLines(value, maxLines) {
|
|
40011
|
+
const lines = value.split(`
|
|
40012
|
+
`);
|
|
40013
|
+
if (lines.length <= maxLines) {
|
|
40014
|
+
return value;
|
|
40015
|
+
}
|
|
40016
|
+
return lines.slice(0, maxLines).join(`
|
|
40017
|
+
`) + `
|
|
40018
|
+
... and ${lines.length - maxLines} more changes`;
|
|
40019
|
+
}
|
|
40020
|
+
function formatGitUser(name, email) {
|
|
40021
|
+
if (!name && !email) {
|
|
40022
|
+
return null;
|
|
40023
|
+
}
|
|
40024
|
+
if (name && email) {
|
|
40025
|
+
return `${name} <${email}>`;
|
|
40026
|
+
}
|
|
40027
|
+
return name || email;
|
|
40028
|
+
}
|
|
40029
|
+
function gatherGitContextSnapshot(options = {}) {
|
|
40030
|
+
const cwd2 = options.cwd ?? process.cwd();
|
|
40031
|
+
const recentCommitLimit = options.recentCommitLimit ?? 3;
|
|
40032
|
+
if (!runGit3(["rev-parse", "--git-dir"], cwd2)) {
|
|
40033
|
+
return {
|
|
40034
|
+
isGitRepo: false,
|
|
40035
|
+
branch: null,
|
|
40036
|
+
status: null,
|
|
40037
|
+
recentCommits: null,
|
|
40038
|
+
gitUser: null
|
|
40039
|
+
};
|
|
40040
|
+
}
|
|
40041
|
+
const branch = runGit3(["branch", "--show-current"], cwd2);
|
|
40042
|
+
const fullStatus = runGit3(["status", "--short"], cwd2);
|
|
40043
|
+
const status = typeof fullStatus === "string" && options.statusLineLimit ? truncateLines(fullStatus, options.statusLineLimit) : fullStatus;
|
|
40044
|
+
const recentCommits = options.recentCommitFormat ? runGit3([
|
|
40045
|
+
"log",
|
|
40046
|
+
`--format=${options.recentCommitFormat}`,
|
|
40047
|
+
"-n",
|
|
40048
|
+
String(recentCommitLimit)
|
|
40049
|
+
], cwd2) : runGit3(["log", "--oneline", "-n", String(recentCommitLimit)], cwd2);
|
|
40050
|
+
const userConfig = runGit3(["config", "--get-regexp", "^user\\.(name|email)$"], cwd2);
|
|
40051
|
+
let userName = null;
|
|
40052
|
+
let userEmail = null;
|
|
40053
|
+
if (userConfig) {
|
|
40054
|
+
for (const line of userConfig.split(`
|
|
40055
|
+
`)) {
|
|
40056
|
+
if (line.startsWith("user.name "))
|
|
40057
|
+
userName = line.slice("user.name ".length);
|
|
40058
|
+
else if (line.startsWith("user.email "))
|
|
40059
|
+
userEmail = line.slice("user.email ".length);
|
|
40060
|
+
}
|
|
40061
|
+
}
|
|
40062
|
+
const gitUser = formatGitUser(userName, userEmail);
|
|
40063
|
+
return {
|
|
40064
|
+
isGitRepo: true,
|
|
40065
|
+
branch,
|
|
40066
|
+
status,
|
|
40067
|
+
recentCommits,
|
|
40068
|
+
gitUser
|
|
40069
|
+
};
|
|
40070
|
+
}
|
|
40071
|
+
function getGitContext(cwd2) {
|
|
40072
|
+
if (!runGit3(["rev-parse", "--git-dir"], cwd2)) {
|
|
40073
|
+
return null;
|
|
40074
|
+
}
|
|
40075
|
+
const branch = runGit3(["branch", "--show-current"], cwd2);
|
|
40076
|
+
const branchList = runGit3([
|
|
40077
|
+
"branch",
|
|
40078
|
+
"--sort=-committerdate",
|
|
40079
|
+
"--format=%(refname:short)",
|
|
40080
|
+
"--no-color"
|
|
40081
|
+
], cwd2);
|
|
40082
|
+
const recentBranches = branchList ? branchList.split(`
|
|
40083
|
+
`).map((b) => b.trim()).filter((b) => b.length > 0 && b !== branch).slice(0, 10) : [];
|
|
40084
|
+
return { branch, recent_branches: recentBranches };
|
|
40085
|
+
}
|
|
40086
|
+
var init_gitContext = () => {};
|
|
40087
|
+
|
|
40088
|
+
// src/cli/helpers/sessionContext.ts
|
|
40089
|
+
import { platform as platform3 } from "node:os";
|
|
40090
|
+
function getLocalTime() {
|
|
40091
|
+
const now = new Date;
|
|
40092
|
+
return now.toLocaleString(undefined, {
|
|
40093
|
+
weekday: "long",
|
|
40094
|
+
year: "numeric",
|
|
40095
|
+
month: "long",
|
|
40096
|
+
day: "numeric",
|
|
40097
|
+
hour: "2-digit",
|
|
40098
|
+
minute: "2-digit",
|
|
40099
|
+
timeZoneName: "short"
|
|
40100
|
+
});
|
|
40101
|
+
}
|
|
40102
|
+
function getDeviceType() {
|
|
40103
|
+
const p = platform3();
|
|
40104
|
+
switch (p) {
|
|
40105
|
+
case "darwin":
|
|
40106
|
+
return "macOS";
|
|
40107
|
+
case "win32":
|
|
40108
|
+
return "Windows";
|
|
40109
|
+
case "linux":
|
|
40110
|
+
return "Linux";
|
|
40111
|
+
default:
|
|
40112
|
+
return p;
|
|
40113
|
+
}
|
|
40114
|
+
}
|
|
40115
|
+
function getGitInfo(cwd2) {
|
|
40116
|
+
const git = gatherGitContextSnapshot({
|
|
40117
|
+
cwd: cwd2,
|
|
40118
|
+
recentCommitLimit: 3,
|
|
40119
|
+
recentCommitFormat: "%h %s (%an)",
|
|
40120
|
+
statusLineLimit: 20
|
|
40121
|
+
});
|
|
40122
|
+
if (!git.isGitRepo) {
|
|
40123
|
+
return { isGitRepo: false };
|
|
40124
|
+
}
|
|
40125
|
+
return {
|
|
40126
|
+
isGitRepo: true,
|
|
40127
|
+
branch: git.branch ?? "(unknown)",
|
|
40128
|
+
recentCommits: git.recentCommits ?? "(failed to get commits)",
|
|
40129
|
+
status: git.status || "(clean working tree)",
|
|
40130
|
+
gitUser: git.gitUser ?? "(not configured)"
|
|
40131
|
+
};
|
|
40132
|
+
}
|
|
40133
|
+
function getIntroText(source, reason) {
|
|
40134
|
+
if (reason === "cwd_changed") {
|
|
40135
|
+
return "The working directory for this conversation has changed. Updated environment context follows.";
|
|
40136
|
+
}
|
|
40137
|
+
switch (source) {
|
|
40138
|
+
case "listen":
|
|
40139
|
+
return "This conversation is now connected to a Letta Code execution environment.";
|
|
40140
|
+
case "headless":
|
|
40141
|
+
return "The user has just initiated a new connection via the Letta Code headless client.";
|
|
40142
|
+
default:
|
|
40143
|
+
return "The user has just initiated a new connection via the [Letta Code CLI client](https://docs.letta.com/letta-code/index.md).";
|
|
40144
|
+
}
|
|
40145
|
+
}
|
|
40146
|
+
function buildSessionContext(options) {
|
|
40147
|
+
try {
|
|
40148
|
+
const cwd2 = options?.cwd ?? process.cwd();
|
|
40149
|
+
const source = options?.source ?? "interactive-cli";
|
|
40150
|
+
const reason = options?.reason ?? "initial_attach";
|
|
40151
|
+
let version = "unknown";
|
|
40152
|
+
try {
|
|
40153
|
+
version = getVersion();
|
|
40154
|
+
} catch {}
|
|
40155
|
+
let deviceType = "unknown";
|
|
40156
|
+
try {
|
|
40157
|
+
deviceType = getDeviceType();
|
|
40158
|
+
} catch {}
|
|
40159
|
+
let localTime = "unknown";
|
|
40160
|
+
try {
|
|
40161
|
+
localTime = getLocalTime();
|
|
40162
|
+
} catch {}
|
|
40163
|
+
const gitInfo = getGitInfo(cwd2);
|
|
40164
|
+
let context2 = `${SYSTEM_REMINDER_OPEN}
|
|
40165
|
+
This is an automated message providing context about the user's environment.
|
|
40166
|
+
${getIntroText(source, reason)}
|
|
40167
|
+
|
|
40168
|
+
## Device Information
|
|
40169
|
+
- **Local time**: ${localTime}
|
|
40170
|
+
- **Device type**: ${deviceType}
|
|
40171
|
+
- **Letta Code version**: ${version}
|
|
40172
|
+
- **Current working directory**: ${cwd2}
|
|
40173
|
+
`;
|
|
40174
|
+
if (gitInfo.isGitRepo) {
|
|
40175
|
+
context2 += `- **Git repository**: Yes (branch: ${gitInfo.branch})
|
|
40176
|
+
- **Git user**: ${gitInfo.gitUser}
|
|
40177
|
+
|
|
40178
|
+
### Recent Commits
|
|
40179
|
+
\`\`\`
|
|
40180
|
+
${gitInfo.recentCommits}
|
|
40181
|
+
\`\`\`
|
|
40182
|
+
|
|
40183
|
+
### Git Status
|
|
40184
|
+
\`\`\`
|
|
40185
|
+
${gitInfo.status}
|
|
40186
|
+
\`\`\`
|
|
40187
|
+
`;
|
|
40188
|
+
} else {
|
|
40189
|
+
context2 += `- **Git repository**: No
|
|
40190
|
+
`;
|
|
40191
|
+
}
|
|
40192
|
+
if (platform3() === "win32") {
|
|
40193
|
+
context2 += `
|
|
40194
|
+
## Windows Shell Notes
|
|
40195
|
+
- The Bash tool uses PowerShell or cmd.exe on Windows
|
|
40196
|
+
- HEREDOC syntax (e.g., \`$(cat <<'EOF'...EOF)\`) does NOT work on Windows
|
|
40197
|
+
- For multiline strings (git commits, PR bodies), use simple quoted strings instead
|
|
40198
|
+
`;
|
|
40199
|
+
}
|
|
40200
|
+
context2 += SYSTEM_REMINDER_CLOSE;
|
|
40201
|
+
return context2;
|
|
40202
|
+
} catch {
|
|
40203
|
+
return "";
|
|
40204
|
+
}
|
|
40205
|
+
}
|
|
40206
|
+
var init_sessionContext = __esm(() => {
|
|
40207
|
+
init_constants();
|
|
40208
|
+
init_version();
|
|
40209
|
+
init_gitContext();
|
|
40210
|
+
});
|
|
40211
|
+
|
|
39845
40212
|
// src/channels/xml.ts
|
|
39846
40213
|
function escapeXml(text) {
|
|
39847
40214
|
return text.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
|
|
39848
40215
|
}
|
|
39849
40216
|
function formatChannelNotification(msg) {
|
|
40217
|
+
const localTime = escapeXml(getLocalTime());
|
|
39850
40218
|
const attrs = [
|
|
39851
40219
|
`source="${escapeXml(msg.channel)}"`,
|
|
39852
40220
|
`chat_id="${escapeXml(msg.chatId)}"`,
|
|
@@ -39860,10 +40228,27 @@ function formatChannelNotification(msg) {
|
|
|
39860
40228
|
}
|
|
39861
40229
|
const attrString = attrs.join(" ");
|
|
39862
40230
|
const escapedText = escapeXml(msg.text);
|
|
39863
|
-
|
|
40231
|
+
const escapedChannel = escapeXml(msg.channel);
|
|
40232
|
+
const escapedChatId = escapeXml(msg.chatId);
|
|
40233
|
+
const reminder = [
|
|
40234
|
+
SYSTEM_REMINDER_OPEN,
|
|
40235
|
+
`This message originated from an external ${escapedChannel} channel.`,
|
|
40236
|
+
`If you want the ensure the user on ${escapedChannel} will see your reply, you must call the MessageChannel tool to send a message back on the same channel.`,
|
|
40237
|
+
`Use channel="${escapedChannel}" and chat_id="${escapedChatId}" when calling MessageChannel.`,
|
|
40238
|
+
"Only pass reply_to_message_id if you intentionally want the platform's quote/reply UI.",
|
|
40239
|
+
`Current local time on this device: ${localTime}`,
|
|
40240
|
+
SYSTEM_REMINDER_CLOSE
|
|
40241
|
+
].join(`
|
|
40242
|
+
`);
|
|
40243
|
+
return `${reminder}
|
|
40244
|
+
<channel-notification ${attrString}>
|
|
39864
40245
|
${escapedText}
|
|
39865
40246
|
</channel-notification>`;
|
|
39866
40247
|
}
|
|
40248
|
+
var init_xml = __esm(() => {
|
|
40249
|
+
init_sessionContext();
|
|
40250
|
+
init_constants();
|
|
40251
|
+
});
|
|
39867
40252
|
|
|
39868
40253
|
// node_modules/grammy/out/filter.js
|
|
39869
40254
|
var require_filter = __commonJS((exports) => {
|
|
@@ -48585,13 +48970,22 @@ function createTelegramAdapter(config) {
|
|
|
48585
48970
|
await bot.init();
|
|
48586
48971
|
const info = bot.botInfo;
|
|
48587
48972
|
console.log(`[Telegram] Bot started as @${info.username} (dm_policy: ${config.dmPolicy})`);
|
|
48588
|
-
|
|
48589
|
-
|
|
48590
|
-
|
|
48591
|
-
|
|
48592
|
-
|
|
48593
|
-
|
|
48594
|
-
|
|
48973
|
+
await new Promise((resolve2, reject) => {
|
|
48974
|
+
let started = false;
|
|
48975
|
+
bot.start({
|
|
48976
|
+
onStart: () => {
|
|
48977
|
+
running = true;
|
|
48978
|
+
started = true;
|
|
48979
|
+
resolve2();
|
|
48980
|
+
}
|
|
48981
|
+
}).catch((error) => {
|
|
48982
|
+
running = false;
|
|
48983
|
+
if (!started) {
|
|
48984
|
+
reject(error);
|
|
48985
|
+
return;
|
|
48986
|
+
}
|
|
48987
|
+
console.error("[Telegram] Long-polling stopped unexpectedly:", error);
|
|
48988
|
+
});
|
|
48595
48989
|
});
|
|
48596
48990
|
},
|
|
48597
48991
|
async stop() {
|
|
@@ -48635,12 +49029,16 @@ __export(exports_registry, {
|
|
|
48635
49029
|
initializeChannels: () => initializeChannels,
|
|
48636
49030
|
getChannelRegistry: () => getChannelRegistry,
|
|
48637
49031
|
getActiveChannelIds: () => getActiveChannelIds,
|
|
49032
|
+
ensureChannelRegistry: () => ensureChannelRegistry,
|
|
48638
49033
|
completePairing: () => completePairing,
|
|
48639
49034
|
ChannelRegistry: () => ChannelRegistry
|
|
48640
49035
|
});
|
|
48641
49036
|
function getChannelRegistry() {
|
|
48642
49037
|
return instance;
|
|
48643
49038
|
}
|
|
49039
|
+
function ensureChannelRegistry() {
|
|
49040
|
+
return instance ?? new ChannelRegistry;
|
|
49041
|
+
}
|
|
48644
49042
|
function getActiveChannelIds() {
|
|
48645
49043
|
if (!instance)
|
|
48646
49044
|
return [];
|
|
@@ -48651,6 +49049,7 @@ class ChannelRegistry {
|
|
|
48651
49049
|
adapters = new Map;
|
|
48652
49050
|
ready = false;
|
|
48653
49051
|
messageHandler = null;
|
|
49052
|
+
eventHandler = null;
|
|
48654
49053
|
buffer = [];
|
|
48655
49054
|
constructor() {
|
|
48656
49055
|
if (instance) {
|
|
@@ -48673,6 +49072,9 @@ class ChannelRegistry {
|
|
|
48673
49072
|
setMessageHandler(handler) {
|
|
48674
49073
|
this.messageHandler = handler;
|
|
48675
49074
|
}
|
|
49075
|
+
setEventHandler(handler) {
|
|
49076
|
+
this.eventHandler = handler;
|
|
49077
|
+
}
|
|
48676
49078
|
setReady() {
|
|
48677
49079
|
this.ready = true;
|
|
48678
49080
|
this.flushBuffer();
|
|
@@ -48683,6 +49085,39 @@ class ChannelRegistry {
|
|
|
48683
49085
|
getRoute(channel, chatId) {
|
|
48684
49086
|
return getRoute(channel, chatId);
|
|
48685
49087
|
}
|
|
49088
|
+
async startChannel(channelId) {
|
|
49089
|
+
const config = readChannelConfig(channelId);
|
|
49090
|
+
if (!config) {
|
|
49091
|
+
return false;
|
|
49092
|
+
}
|
|
49093
|
+
loadRoutes(channelId);
|
|
49094
|
+
loadPairingStore(channelId);
|
|
49095
|
+
const existing = this.adapters.get(channelId);
|
|
49096
|
+
if (existing?.isRunning()) {
|
|
49097
|
+
await existing.stop();
|
|
49098
|
+
}
|
|
49099
|
+
this.adapters.delete(channelId);
|
|
49100
|
+
if (channelId === "telegram") {
|
|
49101
|
+
const { createTelegramAdapter: createTelegramAdapter2 } = await Promise.resolve().then(() => (init_adapter(), exports_adapter));
|
|
49102
|
+
const adapter = createTelegramAdapter2(config);
|
|
49103
|
+
this.registerAdapter(adapter);
|
|
49104
|
+
await adapter.start();
|
|
49105
|
+
return true;
|
|
49106
|
+
}
|
|
49107
|
+
console.error(`Unknown channel "${channelId}". Supported: telegram`);
|
|
49108
|
+
return false;
|
|
49109
|
+
}
|
|
49110
|
+
async stopChannel(channelId) {
|
|
49111
|
+
const adapter = this.adapters.get(channelId);
|
|
49112
|
+
if (!adapter) {
|
|
49113
|
+
return false;
|
|
49114
|
+
}
|
|
49115
|
+
if (adapter.isRunning()) {
|
|
49116
|
+
await adapter.stop();
|
|
49117
|
+
}
|
|
49118
|
+
this.adapters.delete(channelId);
|
|
49119
|
+
return true;
|
|
49120
|
+
}
|
|
48686
49121
|
async startAll() {
|
|
48687
49122
|
for (const adapter of Array.from(this.adapters.values())) {
|
|
48688
49123
|
if (!adapter.isRunning()) {
|
|
@@ -48693,6 +49128,7 @@ class ChannelRegistry {
|
|
|
48693
49128
|
pause() {
|
|
48694
49129
|
this.ready = false;
|
|
48695
49130
|
this.messageHandler = null;
|
|
49131
|
+
this.eventHandler = null;
|
|
48696
49132
|
}
|
|
48697
49133
|
async stopAll() {
|
|
48698
49134
|
for (const adapter of Array.from(this.adapters.values())) {
|
|
@@ -48702,6 +49138,7 @@ class ChannelRegistry {
|
|
|
48702
49138
|
}
|
|
48703
49139
|
this.ready = false;
|
|
48704
49140
|
this.messageHandler = null;
|
|
49141
|
+
this.eventHandler = null;
|
|
48705
49142
|
instance = null;
|
|
48706
49143
|
}
|
|
48707
49144
|
async handleInboundMessage(msg) {
|
|
@@ -48722,11 +49159,15 @@ class ChannelRegistry {
|
|
|
48722
49159
|
}
|
|
48723
49160
|
if (!isUserApproved(msg.channel, msg.senderId)) {
|
|
48724
49161
|
const code = createPairingCode(msg.channel, msg.senderId, msg.chatId, msg.senderName);
|
|
49162
|
+
this.eventHandler?.({
|
|
49163
|
+
type: "pairings_updated",
|
|
49164
|
+
channelId: msg.channel
|
|
49165
|
+
});
|
|
48725
49166
|
await adapter.sendDirectReply(msg.chatId, `To connect this chat to a Letta Code agent, run:
|
|
48726
49167
|
|
|
48727
|
-
|
|
49168
|
+
/channels telegram pair ${code}
|
|
48728
49169
|
|
|
48729
|
-
|
|
49170
|
+
This code expires in 15 minutes.`);
|
|
48730
49171
|
return;
|
|
48731
49172
|
}
|
|
48732
49173
|
}
|
|
@@ -48736,7 +49177,7 @@ class ChannelRegistry {
|
|
|
48736
49177
|
route = getRoute(msg.channel, msg.chatId);
|
|
48737
49178
|
}
|
|
48738
49179
|
if (!route) {
|
|
48739
|
-
await adapter.sendDirectReply(msg.chatId, `This chat isn't bound to an agent.
|
|
49180
|
+
await adapter.sendDirectReply(msg.chatId, `This chat isn't bound to an agent. Run \`/channels telegram enable --chat-id ${msg.chatId}\` on your Letta Code agent to connect.`);
|
|
48740
49181
|
return;
|
|
48741
49182
|
}
|
|
48742
49183
|
const xmlContent = formatChannelNotification(msg);
|
|
@@ -48758,7 +49199,7 @@ class ChannelRegistry {
|
|
|
48758
49199
|
}
|
|
48759
49200
|
}
|
|
48760
49201
|
async function initializeChannels(channelNames) {
|
|
48761
|
-
const registry =
|
|
49202
|
+
const registry = ensureChannelRegistry();
|
|
48762
49203
|
for (const channelId of channelNames) {
|
|
48763
49204
|
const config = readChannelConfig(channelId);
|
|
48764
49205
|
if (!config) {
|
|
@@ -48769,17 +49210,8 @@ async function initializeChannels(channelNames) {
|
|
|
48769
49210
|
console.log(`Channel "${channelId}" is disabled in config, skipping.`);
|
|
48770
49211
|
continue;
|
|
48771
49212
|
}
|
|
48772
|
-
|
|
48773
|
-
loadPairingStore(channelId);
|
|
48774
|
-
if (channelId === "telegram") {
|
|
48775
|
-
const { createTelegramAdapter: createTelegramAdapter2 } = await Promise.resolve().then(() => (init_adapter(), exports_adapter));
|
|
48776
|
-
const adapter = createTelegramAdapter2(config);
|
|
48777
|
-
registry.registerAdapter(adapter);
|
|
48778
|
-
} else {
|
|
48779
|
-
console.error(`Unknown channel: "${channelId}". Supported: telegram`);
|
|
48780
|
-
}
|
|
49213
|
+
await registry.startChannel(channelId);
|
|
48781
49214
|
}
|
|
48782
|
-
await registry.startAll();
|
|
48783
49215
|
return registry;
|
|
48784
49216
|
}
|
|
48785
49217
|
function completePairing(channelId, code, agentId, conversationId) {
|
|
@@ -48816,6 +49248,7 @@ var init_registry = __esm(() => {
|
|
|
48816
49248
|
init_config();
|
|
48817
49249
|
init_pairing();
|
|
48818
49250
|
init_routing();
|
|
49251
|
+
init_xml();
|
|
48819
49252
|
});
|
|
48820
49253
|
|
|
48821
49254
|
// src/channels/telegram/setup.ts
|
|
@@ -49603,7 +50036,7 @@ var init_default_browser_id = __esm(() => {
|
|
|
49603
50036
|
// node_modules/run-applescript/index.js
|
|
49604
50037
|
import process17 from "node:process";
|
|
49605
50038
|
import { promisify as promisify4 } from "node:util";
|
|
49606
|
-
import { execFile as execFile4, execFileSync } from "node:child_process";
|
|
50039
|
+
import { execFile as execFile4, execFileSync as execFileSync2 } from "node:child_process";
|
|
49607
50040
|
async function runAppleScript(script, { humanReadableOutput = true, signal } = {}) {
|
|
49608
50041
|
if (process17.platform !== "darwin") {
|
|
49609
50042
|
throw new Error("macOS only");
|
|
@@ -49743,16 +50176,16 @@ function detectArchBinary(binary) {
|
|
|
49743
50176
|
}
|
|
49744
50177
|
return archBinary;
|
|
49745
50178
|
}
|
|
49746
|
-
function detectPlatformBinary({ [
|
|
50179
|
+
function detectPlatformBinary({ [platform4]: platformBinary }, { wsl }) {
|
|
49747
50180
|
if (wsl && is_wsl_default) {
|
|
49748
50181
|
return detectArchBinary(wsl);
|
|
49749
50182
|
}
|
|
49750
50183
|
if (!platformBinary) {
|
|
49751
|
-
throw new Error(`${
|
|
50184
|
+
throw new Error(`${platform4} is not supported`);
|
|
49752
50185
|
}
|
|
49753
50186
|
return detectArchBinary(platformBinary);
|
|
49754
50187
|
}
|
|
49755
|
-
var execFile7, __dirname2, localXdgOpenPath,
|
|
50188
|
+
var execFile7, __dirname2, localXdgOpenPath, platform4, arch, pTryEach = async (array, mapper) => {
|
|
49756
50189
|
let latestError;
|
|
49757
50190
|
for (const item of array) {
|
|
49758
50191
|
try {
|
|
@@ -49824,7 +50257,7 @@ var execFile7, __dirname2, localXdgOpenPath, platform3, arch, pTryEach = async (
|
|
|
49824
50257
|
let command;
|
|
49825
50258
|
const cliArguments = [];
|
|
49826
50259
|
const childProcessOptions = {};
|
|
49827
|
-
if (
|
|
50260
|
+
if (platform4 === "darwin") {
|
|
49828
50261
|
command = "open";
|
|
49829
50262
|
if (options.wait) {
|
|
49830
50263
|
cliArguments.push("--wait-apps");
|
|
@@ -49838,7 +50271,7 @@ var execFile7, __dirname2, localXdgOpenPath, platform3, arch, pTryEach = async (
|
|
|
49838
50271
|
if (app) {
|
|
49839
50272
|
cliArguments.push("-a", app);
|
|
49840
50273
|
}
|
|
49841
|
-
} else if (
|
|
50274
|
+
} else if (platform4 === "win32" || is_wsl_default && !isInsideContainer() && !app) {
|
|
49842
50275
|
command = await powerShellPath();
|
|
49843
50276
|
cliArguments.push("-NoProfile", "-NonInteractive", "-ExecutionPolicy", "Bypass", "-EncodedCommand");
|
|
49844
50277
|
if (!is_wsl_default) {
|
|
@@ -49871,7 +50304,7 @@ var execFile7, __dirname2, localXdgOpenPath, platform3, arch, pTryEach = async (
|
|
|
49871
50304
|
await fs6.access(localXdgOpenPath, fsConstants2.X_OK);
|
|
49872
50305
|
exeLocalXdgOpen = true;
|
|
49873
50306
|
} catch {}
|
|
49874
|
-
const useSystemXdgOpen = process19.versions.electron ?? (
|
|
50307
|
+
const useSystemXdgOpen = process19.versions.electron ?? (platform4 === "android" || isBundled || !exeLocalXdgOpen);
|
|
49875
50308
|
command = useSystemXdgOpen ? "xdg-open" : localXdgOpenPath;
|
|
49876
50309
|
}
|
|
49877
50310
|
if (appArguments.length > 0) {
|
|
@@ -49882,7 +50315,7 @@ var execFile7, __dirname2, localXdgOpenPath, platform3, arch, pTryEach = async (
|
|
|
49882
50315
|
childProcessOptions.detached = true;
|
|
49883
50316
|
}
|
|
49884
50317
|
}
|
|
49885
|
-
if (
|
|
50318
|
+
if (platform4 === "darwin" && appArguments.length > 0) {
|
|
49886
50319
|
cliArguments.push("--args", ...appArguments);
|
|
49887
50320
|
}
|
|
49888
50321
|
if (options.target) {
|
|
@@ -49934,7 +50367,7 @@ var init_open = __esm(() => {
|
|
|
49934
50367
|
execFile7 = promisify7(childProcess.execFile);
|
|
49935
50368
|
__dirname2 = path2.dirname(fileURLToPath(import.meta.url));
|
|
49936
50369
|
localXdgOpenPath = path2.join(__dirname2, "xdg-open");
|
|
49937
|
-
({ platform:
|
|
50370
|
+
({ platform: platform4, arch } = process19);
|
|
49938
50371
|
apps = {};
|
|
49939
50372
|
defineLazyProperty(apps, "chrome", () => detectPlatformBinary({
|
|
49940
50373
|
darwin: "google chrome",
|
|
@@ -53051,97 +53484,6 @@ var init_fileIndex = __esm(() => {
|
|
|
53051
53484
|
indexRoot2 = process.cwd();
|
|
53052
53485
|
});
|
|
53053
53486
|
|
|
53054
|
-
// src/cli/helpers/gitContext.ts
|
|
53055
|
-
import { execFileSync as execFileSync2 } from "node:child_process";
|
|
53056
|
-
function runGit3(args, cwd2) {
|
|
53057
|
-
try {
|
|
53058
|
-
return execFileSync2("git", args, {
|
|
53059
|
-
cwd: cwd2,
|
|
53060
|
-
encoding: "utf-8",
|
|
53061
|
-
stdio: ["ignore", "pipe", "ignore"]
|
|
53062
|
-
}).trim();
|
|
53063
|
-
} catch {
|
|
53064
|
-
return null;
|
|
53065
|
-
}
|
|
53066
|
-
}
|
|
53067
|
-
function truncateLines(value, maxLines) {
|
|
53068
|
-
const lines = value.split(`
|
|
53069
|
-
`);
|
|
53070
|
-
if (lines.length <= maxLines) {
|
|
53071
|
-
return value;
|
|
53072
|
-
}
|
|
53073
|
-
return lines.slice(0, maxLines).join(`
|
|
53074
|
-
`) + `
|
|
53075
|
-
... and ${lines.length - maxLines} more changes`;
|
|
53076
|
-
}
|
|
53077
|
-
function formatGitUser(name, email) {
|
|
53078
|
-
if (!name && !email) {
|
|
53079
|
-
return null;
|
|
53080
|
-
}
|
|
53081
|
-
if (name && email) {
|
|
53082
|
-
return `${name} <${email}>`;
|
|
53083
|
-
}
|
|
53084
|
-
return name || email;
|
|
53085
|
-
}
|
|
53086
|
-
function gatherGitContextSnapshot(options = {}) {
|
|
53087
|
-
const cwd2 = options.cwd ?? process.cwd();
|
|
53088
|
-
const recentCommitLimit = options.recentCommitLimit ?? 3;
|
|
53089
|
-
if (!runGit3(["rev-parse", "--git-dir"], cwd2)) {
|
|
53090
|
-
return {
|
|
53091
|
-
isGitRepo: false,
|
|
53092
|
-
branch: null,
|
|
53093
|
-
status: null,
|
|
53094
|
-
recentCommits: null,
|
|
53095
|
-
gitUser: null
|
|
53096
|
-
};
|
|
53097
|
-
}
|
|
53098
|
-
const branch = runGit3(["branch", "--show-current"], cwd2);
|
|
53099
|
-
const fullStatus = runGit3(["status", "--short"], cwd2);
|
|
53100
|
-
const status = typeof fullStatus === "string" && options.statusLineLimit ? truncateLines(fullStatus, options.statusLineLimit) : fullStatus;
|
|
53101
|
-
const recentCommits = options.recentCommitFormat ? runGit3([
|
|
53102
|
-
"log",
|
|
53103
|
-
`--format=${options.recentCommitFormat}`,
|
|
53104
|
-
"-n",
|
|
53105
|
-
String(recentCommitLimit)
|
|
53106
|
-
], cwd2) : runGit3(["log", "--oneline", "-n", String(recentCommitLimit)], cwd2);
|
|
53107
|
-
const userConfig = runGit3(["config", "--get-regexp", "^user\\.(name|email)$"], cwd2);
|
|
53108
|
-
let userName = null;
|
|
53109
|
-
let userEmail = null;
|
|
53110
|
-
if (userConfig) {
|
|
53111
|
-
for (const line of userConfig.split(`
|
|
53112
|
-
`)) {
|
|
53113
|
-
if (line.startsWith("user.name "))
|
|
53114
|
-
userName = line.slice("user.name ".length);
|
|
53115
|
-
else if (line.startsWith("user.email "))
|
|
53116
|
-
userEmail = line.slice("user.email ".length);
|
|
53117
|
-
}
|
|
53118
|
-
}
|
|
53119
|
-
const gitUser = formatGitUser(userName, userEmail);
|
|
53120
|
-
return {
|
|
53121
|
-
isGitRepo: true,
|
|
53122
|
-
branch,
|
|
53123
|
-
status,
|
|
53124
|
-
recentCommits,
|
|
53125
|
-
gitUser
|
|
53126
|
-
};
|
|
53127
|
-
}
|
|
53128
|
-
function getGitContext(cwd2) {
|
|
53129
|
-
if (!runGit3(["rev-parse", "--git-dir"], cwd2)) {
|
|
53130
|
-
return null;
|
|
53131
|
-
}
|
|
53132
|
-
const branch = runGit3(["branch", "--show-current"], cwd2);
|
|
53133
|
-
const branchList = runGit3([
|
|
53134
|
-
"branch",
|
|
53135
|
-
"--sort=-committerdate",
|
|
53136
|
-
"--format=%(refname:short)",
|
|
53137
|
-
"--no-color"
|
|
53138
|
-
], cwd2);
|
|
53139
|
-
const recentBranches = branchList ? branchList.split(`
|
|
53140
|
-
`).map((b) => b.trim()).filter((b) => b.length > 0 && b !== branch).slice(0, 10) : [];
|
|
53141
|
-
return { branch, recent_branches: recentBranches };
|
|
53142
|
-
}
|
|
53143
|
-
var init_gitContext = () => {};
|
|
53144
|
-
|
|
53145
53487
|
// src/cli/helpers/memoryReminder.ts
|
|
53146
53488
|
function isValidStepCount(value) {
|
|
53147
53489
|
return typeof value === "number" && Number.isFinite(value) && Number.isInteger(value) && value > 0;
|
|
@@ -64319,7 +64661,7 @@ var MemoryApplyPatch_default = "Apply a codex-style patch to memory files in `$M
|
|
|
64319
64661
|
var init_MemoryApplyPatch = () => {};
|
|
64320
64662
|
|
|
64321
64663
|
// src/tools/descriptions/MessageChannel.md
|
|
64322
|
-
var MessageChannel_default = "# MessageChannel\n\nSend a message to an external channel (Telegram, Slack, etc.) in response to a channel notification.\n\nWhen you receive a `<channel-notification>`, use this tool to reply. Extract the `source` and `chat_id` from the notification attributes and pass them as `channel` and `chat_id`.\n\nParameters:\n- `channel`: The platform to send to (matches the `source` attribute)\n- `chat_id`: The chat ID to send to (matches the `chat_id` attribute)\n- `text`: The message text to send\n- `reply_to_message_id`: (Optional) Reply to a specific message by its `message_id
|
|
64664
|
+
var MessageChannel_default = "# MessageChannel\n\nSend a message to an external channel (Telegram, Slack, etc.) in response to a channel notification.\n\nWhen you receive a `<channel-notification>`, use this tool to reply directly to the user on the same external channel (a normal assistant response is not delivered back to Telegram/Slack/etc). Extract the `source` and `chat_id` from the notification attributes and pass them as `channel` and `chat_id`.\n\nParameters:\n- `channel`: The platform to send to (matches the `source` attribute)\n- `chat_id`: The chat ID to send to (matches the `chat_id` attribute)\n- `text`: The message text to send\n- `reply_to_message_id`: (Optional) Reply to a specific message by its `message_id`. Omit this unless you intentionally want the platform's quote/reply UI.\n";
|
|
64323
64665
|
var init_MessageChannel = () => {};
|
|
64324
64666
|
|
|
64325
64667
|
// src/tools/descriptions/MultiEdit.md
|
|
@@ -74462,7 +74804,7 @@ class Pattern {
|
|
|
74462
74804
|
#isUNC;
|
|
74463
74805
|
#isAbsolute;
|
|
74464
74806
|
#followGlobstar = true;
|
|
74465
|
-
constructor(patternList, globList, index,
|
|
74807
|
+
constructor(patternList, globList, index, platform5) {
|
|
74466
74808
|
if (!isPatternList(patternList)) {
|
|
74467
74809
|
throw new TypeError("empty pattern list");
|
|
74468
74810
|
}
|
|
@@ -74479,7 +74821,7 @@ class Pattern {
|
|
|
74479
74821
|
this.#patternList = patternList;
|
|
74480
74822
|
this.#globList = globList;
|
|
74481
74823
|
this.#index = index;
|
|
74482
|
-
this.#platform =
|
|
74824
|
+
this.#platform = platform5;
|
|
74483
74825
|
if (this.#index === 0) {
|
|
74484
74826
|
if (this.isUNC()) {
|
|
74485
74827
|
const [p0, p1, p2, p3, ...prest] = this.#patternList;
|
|
@@ -74576,12 +74918,12 @@ class Ignore {
|
|
|
74576
74918
|
absoluteChildren;
|
|
74577
74919
|
platform;
|
|
74578
74920
|
mmopts;
|
|
74579
|
-
constructor(ignored, { nobrace, nocase, noext, noglobstar, platform:
|
|
74921
|
+
constructor(ignored, { nobrace, nocase, noext, noglobstar, platform: platform5 = defaultPlatform2 }) {
|
|
74580
74922
|
this.relative = [];
|
|
74581
74923
|
this.absolute = [];
|
|
74582
74924
|
this.relativeChildren = [];
|
|
74583
74925
|
this.absoluteChildren = [];
|
|
74584
|
-
this.platform =
|
|
74926
|
+
this.platform = platform5;
|
|
74585
74927
|
this.mmopts = {
|
|
74586
74928
|
dot: true,
|
|
74587
74929
|
nobrace,
|
|
@@ -74589,7 +74931,7 @@ class Ignore {
|
|
|
74589
74931
|
noext,
|
|
74590
74932
|
noglobstar,
|
|
74591
74933
|
optimizationLevel: 2,
|
|
74592
|
-
platform:
|
|
74934
|
+
platform: platform5,
|
|
74593
74935
|
nocomment: true,
|
|
74594
74936
|
nonegate: true
|
|
74595
74937
|
};
|
|
@@ -76674,7 +77016,7 @@ function resolveSubagentLauncher(cliArgs, options = {}) {
|
|
|
76674
77016
|
const env4 = options.env ?? process.env;
|
|
76675
77017
|
const argv = options.argv ?? process.argv;
|
|
76676
77018
|
const execPath = options.execPath ?? process.execPath;
|
|
76677
|
-
const
|
|
77019
|
+
const platform5 = options.platform ?? process.platform;
|
|
76678
77020
|
const invocation = resolveLettaInvocation(env4, argv, execPath);
|
|
76679
77021
|
if (invocation) {
|
|
76680
77022
|
return {
|
|
@@ -76689,7 +77031,7 @@ function resolveSubagentLauncher(cliArgs, options = {}) {
|
|
|
76689
77031
|
args: [currentScript, ...cliArgs]
|
|
76690
77032
|
};
|
|
76691
77033
|
}
|
|
76692
|
-
if (currentScript.endsWith(".js") &&
|
|
77034
|
+
if (currentScript.endsWith(".js") && platform5 === "win32") {
|
|
76693
77035
|
return {
|
|
76694
77036
|
command: execPath,
|
|
76695
77037
|
args: [currentScript, ...cliArgs]
|
|
@@ -87255,130 +87597,6 @@ var init_agentInfo = __esm(async () => {
|
|
|
87255
87597
|
await init_settings_manager();
|
|
87256
87598
|
});
|
|
87257
87599
|
|
|
87258
|
-
// src/cli/helpers/sessionContext.ts
|
|
87259
|
-
import { platform as platform4 } from "node:os";
|
|
87260
|
-
function getLocalTime() {
|
|
87261
|
-
const now = new Date;
|
|
87262
|
-
return now.toLocaleString(undefined, {
|
|
87263
|
-
weekday: "long",
|
|
87264
|
-
year: "numeric",
|
|
87265
|
-
month: "long",
|
|
87266
|
-
day: "numeric",
|
|
87267
|
-
hour: "2-digit",
|
|
87268
|
-
minute: "2-digit",
|
|
87269
|
-
timeZoneName: "short"
|
|
87270
|
-
});
|
|
87271
|
-
}
|
|
87272
|
-
function getDeviceType() {
|
|
87273
|
-
const p = platform4();
|
|
87274
|
-
switch (p) {
|
|
87275
|
-
case "darwin":
|
|
87276
|
-
return "macOS";
|
|
87277
|
-
case "win32":
|
|
87278
|
-
return "Windows";
|
|
87279
|
-
case "linux":
|
|
87280
|
-
return "Linux";
|
|
87281
|
-
default:
|
|
87282
|
-
return p;
|
|
87283
|
-
}
|
|
87284
|
-
}
|
|
87285
|
-
function getGitInfo(cwd2) {
|
|
87286
|
-
const git = gatherGitContextSnapshot({
|
|
87287
|
-
cwd: cwd2,
|
|
87288
|
-
recentCommitLimit: 3,
|
|
87289
|
-
recentCommitFormat: "%h %s (%an)",
|
|
87290
|
-
statusLineLimit: 20
|
|
87291
|
-
});
|
|
87292
|
-
if (!git.isGitRepo) {
|
|
87293
|
-
return { isGitRepo: false };
|
|
87294
|
-
}
|
|
87295
|
-
return {
|
|
87296
|
-
isGitRepo: true,
|
|
87297
|
-
branch: git.branch ?? "(unknown)",
|
|
87298
|
-
recentCommits: git.recentCommits ?? "(failed to get commits)",
|
|
87299
|
-
status: git.status || "(clean working tree)",
|
|
87300
|
-
gitUser: git.gitUser ?? "(not configured)"
|
|
87301
|
-
};
|
|
87302
|
-
}
|
|
87303
|
-
function getIntroText(source, reason) {
|
|
87304
|
-
if (reason === "cwd_changed") {
|
|
87305
|
-
return "The working directory for this conversation has changed. Updated environment context follows.";
|
|
87306
|
-
}
|
|
87307
|
-
switch (source) {
|
|
87308
|
-
case "listen":
|
|
87309
|
-
return "This conversation is now connected to a Letta Code execution environment.";
|
|
87310
|
-
case "headless":
|
|
87311
|
-
return "The user has just initiated a new connection via the Letta Code headless client.";
|
|
87312
|
-
default:
|
|
87313
|
-
return "The user has just initiated a new connection via the [Letta Code CLI client](https://docs.letta.com/letta-code/index.md).";
|
|
87314
|
-
}
|
|
87315
|
-
}
|
|
87316
|
-
function buildSessionContext(options) {
|
|
87317
|
-
try {
|
|
87318
|
-
const cwd2 = options?.cwd ?? process.cwd();
|
|
87319
|
-
const source = options?.source ?? "interactive-cli";
|
|
87320
|
-
const reason = options?.reason ?? "initial_attach";
|
|
87321
|
-
let version = "unknown";
|
|
87322
|
-
try {
|
|
87323
|
-
version = getVersion();
|
|
87324
|
-
} catch {}
|
|
87325
|
-
let deviceType = "unknown";
|
|
87326
|
-
try {
|
|
87327
|
-
deviceType = getDeviceType();
|
|
87328
|
-
} catch {}
|
|
87329
|
-
let localTime = "unknown";
|
|
87330
|
-
try {
|
|
87331
|
-
localTime = getLocalTime();
|
|
87332
|
-
} catch {}
|
|
87333
|
-
const gitInfo = getGitInfo(cwd2);
|
|
87334
|
-
let context3 = `${SYSTEM_REMINDER_OPEN}
|
|
87335
|
-
This is an automated message providing context about the user's environment.
|
|
87336
|
-
${getIntroText(source, reason)}
|
|
87337
|
-
|
|
87338
|
-
## Device Information
|
|
87339
|
-
- **Local time**: ${localTime}
|
|
87340
|
-
- **Device type**: ${deviceType}
|
|
87341
|
-
- **Letta Code version**: ${version}
|
|
87342
|
-
- **Current working directory**: ${cwd2}
|
|
87343
|
-
`;
|
|
87344
|
-
if (gitInfo.isGitRepo) {
|
|
87345
|
-
context3 += `- **Git repository**: Yes (branch: ${gitInfo.branch})
|
|
87346
|
-
- **Git user**: ${gitInfo.gitUser}
|
|
87347
|
-
|
|
87348
|
-
### Recent Commits
|
|
87349
|
-
\`\`\`
|
|
87350
|
-
${gitInfo.recentCommits}
|
|
87351
|
-
\`\`\`
|
|
87352
|
-
|
|
87353
|
-
### Git Status
|
|
87354
|
-
\`\`\`
|
|
87355
|
-
${gitInfo.status}
|
|
87356
|
-
\`\`\`
|
|
87357
|
-
`;
|
|
87358
|
-
} else {
|
|
87359
|
-
context3 += `- **Git repository**: No
|
|
87360
|
-
`;
|
|
87361
|
-
}
|
|
87362
|
-
if (platform4() === "win32") {
|
|
87363
|
-
context3 += `
|
|
87364
|
-
## Windows Shell Notes
|
|
87365
|
-
- The Bash tool uses PowerShell or cmd.exe on Windows
|
|
87366
|
-
- HEREDOC syntax (e.g., \`$(cat <<'EOF'...EOF)\`) does NOT work on Windows
|
|
87367
|
-
- For multiline strings (git commits, PR bodies), use simple quoted strings instead
|
|
87368
|
-
`;
|
|
87369
|
-
}
|
|
87370
|
-
context3 += SYSTEM_REMINDER_CLOSE;
|
|
87371
|
-
return context3;
|
|
87372
|
-
} catch {
|
|
87373
|
-
return "";
|
|
87374
|
-
}
|
|
87375
|
-
}
|
|
87376
|
-
var init_sessionContext = __esm(() => {
|
|
87377
|
-
init_constants();
|
|
87378
|
-
init_version();
|
|
87379
|
-
init_gitContext();
|
|
87380
|
-
});
|
|
87381
|
-
|
|
87382
87600
|
// src/reminders/catalog.ts
|
|
87383
87601
|
var SHARED_REMINDER_CATALOG, SHARED_REMINDER_IDS, SHARED_REMINDER_BY_ID;
|
|
87384
87602
|
var init_catalog = __esm(() => {
|
|
@@ -94145,6 +94363,67 @@ function isSetReflectionSettingsCommand(value) {
|
|
|
94145
94363
|
const settings = c.settings;
|
|
94146
94364
|
return (settings.trigger === "off" || settings.trigger === "step-count" || settings.trigger === "compaction-event") && typeof settings.step_count === "number" && Number.isInteger(settings.step_count) && settings.step_count > 0 && (c.scope === undefined || c.scope === "local_project" || c.scope === "global" || c.scope === "both");
|
|
94147
94365
|
}
|
|
94366
|
+
function isChannelId(value) {
|
|
94367
|
+
return value === "telegram";
|
|
94368
|
+
}
|
|
94369
|
+
function isChannelsListCommand(value) {
|
|
94370
|
+
if (!value || typeof value !== "object")
|
|
94371
|
+
return false;
|
|
94372
|
+
const c = value;
|
|
94373
|
+
return c.type === "channels_list" && typeof c.request_id === "string";
|
|
94374
|
+
}
|
|
94375
|
+
function isChannelGetConfigCommand(value) {
|
|
94376
|
+
if (!value || typeof value !== "object")
|
|
94377
|
+
return false;
|
|
94378
|
+
const c = value;
|
|
94379
|
+
return c.type === "channel_get_config" && typeof c.request_id === "string" && isChannelId(c.channel_id);
|
|
94380
|
+
}
|
|
94381
|
+
function isChannelSetConfigCommand(value) {
|
|
94382
|
+
if (!value || typeof value !== "object")
|
|
94383
|
+
return false;
|
|
94384
|
+
const c = value;
|
|
94385
|
+
if (c.type !== "channel_set_config" || typeof c.request_id !== "string" || !isChannelId(c.channel_id) || !c.config || typeof c.config !== "object") {
|
|
94386
|
+
return false;
|
|
94387
|
+
}
|
|
94388
|
+
const config = c.config;
|
|
94389
|
+
return (config.token === undefined || typeof config.token === "string") && (config.dm_policy === undefined || config.dm_policy === "pairing" || config.dm_policy === "allowlist" || config.dm_policy === "open") && (config.allowed_users === undefined || Array.isArray(config.allowed_users) && config.allowed_users.every((entry) => typeof entry === "string"));
|
|
94390
|
+
}
|
|
94391
|
+
function isChannelStartCommand(value) {
|
|
94392
|
+
if (!value || typeof value !== "object")
|
|
94393
|
+
return false;
|
|
94394
|
+
const c = value;
|
|
94395
|
+
return c.type === "channel_start" && typeof c.request_id === "string" && isChannelId(c.channel_id);
|
|
94396
|
+
}
|
|
94397
|
+
function isChannelStopCommand(value) {
|
|
94398
|
+
if (!value || typeof value !== "object")
|
|
94399
|
+
return false;
|
|
94400
|
+
const c = value;
|
|
94401
|
+
return c.type === "channel_stop" && typeof c.request_id === "string" && isChannelId(c.channel_id);
|
|
94402
|
+
}
|
|
94403
|
+
function isChannelPairingsListCommand(value) {
|
|
94404
|
+
if (!value || typeof value !== "object")
|
|
94405
|
+
return false;
|
|
94406
|
+
const c = value;
|
|
94407
|
+
return c.type === "channel_pairings_list" && typeof c.request_id === "string" && isChannelId(c.channel_id);
|
|
94408
|
+
}
|
|
94409
|
+
function isChannelPairingBindCommand(value) {
|
|
94410
|
+
if (!value || typeof value !== "object")
|
|
94411
|
+
return false;
|
|
94412
|
+
const c = value;
|
|
94413
|
+
return c.type === "channel_pairing_bind" && typeof c.request_id === "string" && isChannelId(c.channel_id) && isRuntimeScope(c.runtime) && typeof c.code === "string" && c.code.length > 0;
|
|
94414
|
+
}
|
|
94415
|
+
function isChannelRoutesListCommand(value) {
|
|
94416
|
+
if (!value || typeof value !== "object")
|
|
94417
|
+
return false;
|
|
94418
|
+
const c = value;
|
|
94419
|
+
return c.type === "channel_routes_list" && typeof c.request_id === "string" && (c.channel_id === undefined || isChannelId(c.channel_id)) && (c.agent_id === undefined || typeof c.agent_id === "string") && (c.conversation_id === undefined || typeof c.conversation_id === "string");
|
|
94420
|
+
}
|
|
94421
|
+
function isChannelRouteRemoveCommand(value) {
|
|
94422
|
+
if (!value || typeof value !== "object")
|
|
94423
|
+
return false;
|
|
94424
|
+
const c = value;
|
|
94425
|
+
return c.type === "channel_route_remove" && typeof c.request_id === "string" && isChannelId(c.channel_id) && typeof c.chat_id === "string" && c.chat_id.length > 0;
|
|
94426
|
+
}
|
|
94148
94427
|
function isSearchBranchesCommand(value) {
|
|
94149
94428
|
if (!value || typeof value !== "object")
|
|
94150
94429
|
return false;
|
|
@@ -94168,7 +94447,7 @@ function parseServerMessage(data) {
|
|
|
94168
94447
|
try {
|
|
94169
94448
|
const raw = typeof data === "string" ? data : data.toString();
|
|
94170
94449
|
const parsed = JSON.parse(raw);
|
|
94171
|
-
if (isInputCommand(parsed) || isChangeDeviceStateCommand(parsed) || isAbortMessageCommand(parsed) || isSyncCommand(parsed) || isTerminalSpawnCommand(parsed) || isTerminalInputCommand(parsed) || isTerminalResizeCommand(parsed) || isTerminalKillCommand(parsed) || isSearchFilesCommand(parsed) || isListInDirectoryCommand(parsed) || isReadFileCommand(parsed) || isWriteFileCommand(parsed) || isWatchFileCommand(parsed) || isUnwatchFileCommand(parsed) || isEditFileCommand(parsed) || isListMemoryCommand(parsed) || isMemoryHistoryCommand(parsed) || isMemoryFileAtRefCommand(parsed) || isEnableMemfsCommand(parsed) || isListModelsCommand(parsed) || isUpdateModelCommand(parsed) || isCronListCommand(parsed) || isCronAddCommand(parsed) || isCronGetCommand(parsed) || isCronDeleteCommand(parsed) || isCronDeleteAllCommand(parsed) || isSkillEnableCommand(parsed) || isSkillDisableCommand(parsed) || isCreateAgentCommand(parsed) || isGetReflectionSettingsCommand(parsed) || isSetReflectionSettingsCommand(parsed) || isExecuteCommandCommand(parsed) || isSearchBranchesCommand(parsed) || isCheckoutBranchCommand(parsed)) {
|
|
94450
|
+
if (isInputCommand(parsed) || isChangeDeviceStateCommand(parsed) || isAbortMessageCommand(parsed) || isSyncCommand(parsed) || isTerminalSpawnCommand(parsed) || isTerminalInputCommand(parsed) || isTerminalResizeCommand(parsed) || isTerminalKillCommand(parsed) || isSearchFilesCommand(parsed) || isListInDirectoryCommand(parsed) || isReadFileCommand(parsed) || isWriteFileCommand(parsed) || isWatchFileCommand(parsed) || isUnwatchFileCommand(parsed) || isEditFileCommand(parsed) || isListMemoryCommand(parsed) || isMemoryHistoryCommand(parsed) || isMemoryFileAtRefCommand(parsed) || isEnableMemfsCommand(parsed) || isListModelsCommand(parsed) || isUpdateModelCommand(parsed) || isCronListCommand(parsed) || isCronAddCommand(parsed) || isCronGetCommand(parsed) || isCronDeleteCommand(parsed) || isCronDeleteAllCommand(parsed) || isSkillEnableCommand(parsed) || isSkillDisableCommand(parsed) || isCreateAgentCommand(parsed) || isGetReflectionSettingsCommand(parsed) || isSetReflectionSettingsCommand(parsed) || isChannelsListCommand(parsed) || isChannelGetConfigCommand(parsed) || isChannelSetConfigCommand(parsed) || isChannelStartCommand(parsed) || isChannelStopCommand(parsed) || isChannelPairingsListCommand(parsed) || isChannelPairingBindCommand(parsed) || isChannelRoutesListCommand(parsed) || isChannelRouteRemoveCommand(parsed) || isExecuteCommandCommand(parsed) || isSearchBranchesCommand(parsed) || isCheckoutBranchCommand(parsed)) {
|
|
94172
94451
|
return parsed;
|
|
94173
94452
|
}
|
|
94174
94453
|
const invalidInput = getInvalidInputReason(parsed);
|
|
@@ -94189,6 +94468,201 @@ var init_protocol_inbound = __esm(async () => {
|
|
|
94189
94468
|
await init_approval();
|
|
94190
94469
|
});
|
|
94191
94470
|
|
|
94471
|
+
// src/channels/service.ts
|
|
94472
|
+
var exports_service = {};
|
|
94473
|
+
__export(exports_service, {
|
|
94474
|
+
stopChannelLive: () => stopChannelLive,
|
|
94475
|
+
startChannelLive: () => startChannelLive,
|
|
94476
|
+
setChannelConfigLive: () => setChannelConfigLive,
|
|
94477
|
+
removeChannelRouteLive: () => removeChannelRouteLive,
|
|
94478
|
+
listPendingPairingSnapshots: () => listPendingPairingSnapshots,
|
|
94479
|
+
listChannelSummaries: () => listChannelSummaries,
|
|
94480
|
+
listChannelRouteSnapshots: () => listChannelRouteSnapshots,
|
|
94481
|
+
getChannelConfigSnapshot: () => getChannelConfigSnapshot,
|
|
94482
|
+
bindChannelPairing: () => bindChannelPairing,
|
|
94483
|
+
CHANNEL_DISPLAY_NAMES: () => CHANNEL_DISPLAY_NAMES
|
|
94484
|
+
});
|
|
94485
|
+
function assertSupportedChannelId(channelId) {
|
|
94486
|
+
if (channelId !== "telegram") {
|
|
94487
|
+
throw new Error(`Unsupported channel: ${channelId}`);
|
|
94488
|
+
}
|
|
94489
|
+
}
|
|
94490
|
+
function toConfigSnapshot(channelId, config) {
|
|
94491
|
+
return {
|
|
94492
|
+
channelId,
|
|
94493
|
+
enabled: config.enabled,
|
|
94494
|
+
dmPolicy: config.dmPolicy,
|
|
94495
|
+
allowedUsers: [...config.allowedUsers],
|
|
94496
|
+
hasToken: config.token.trim().length > 0
|
|
94497
|
+
};
|
|
94498
|
+
}
|
|
94499
|
+
function toPendingPairingSnapshot(pending) {
|
|
94500
|
+
return {
|
|
94501
|
+
code: pending.code,
|
|
94502
|
+
senderId: pending.telegramUserId,
|
|
94503
|
+
senderName: pending.telegramUsername,
|
|
94504
|
+
chatId: pending.chatId,
|
|
94505
|
+
createdAt: pending.createdAt,
|
|
94506
|
+
expiresAt: pending.expiresAt
|
|
94507
|
+
};
|
|
94508
|
+
}
|
|
94509
|
+
function toRouteSnapshot(channelId, route) {
|
|
94510
|
+
return {
|
|
94511
|
+
channelId,
|
|
94512
|
+
chatId: route.chatId,
|
|
94513
|
+
agentId: route.agentId,
|
|
94514
|
+
conversationId: route.conversationId,
|
|
94515
|
+
enabled: route.enabled,
|
|
94516
|
+
createdAt: route.createdAt
|
|
94517
|
+
};
|
|
94518
|
+
}
|
|
94519
|
+
function listChannelSummaries() {
|
|
94520
|
+
const registry = getChannelRegistry();
|
|
94521
|
+
const channelId = "telegram";
|
|
94522
|
+
const config = readChannelConfig(channelId);
|
|
94523
|
+
if (!config) {
|
|
94524
|
+
return [
|
|
94525
|
+
{
|
|
94526
|
+
channelId,
|
|
94527
|
+
displayName: CHANNEL_DISPLAY_NAMES[channelId],
|
|
94528
|
+
configured: false,
|
|
94529
|
+
enabled: false,
|
|
94530
|
+
running: false,
|
|
94531
|
+
dmPolicy: null,
|
|
94532
|
+
pendingPairingsCount: 0,
|
|
94533
|
+
approvedUsersCount: 0,
|
|
94534
|
+
routesCount: 0
|
|
94535
|
+
}
|
|
94536
|
+
];
|
|
94537
|
+
}
|
|
94538
|
+
loadRoutes(channelId);
|
|
94539
|
+
loadPairingStore(channelId);
|
|
94540
|
+
return [
|
|
94541
|
+
{
|
|
94542
|
+
channelId,
|
|
94543
|
+
displayName: CHANNEL_DISPLAY_NAMES[channelId],
|
|
94544
|
+
configured: true,
|
|
94545
|
+
enabled: config.enabled,
|
|
94546
|
+
running: registry?.getAdapter(channelId)?.isRunning() ?? false,
|
|
94547
|
+
dmPolicy: config.dmPolicy,
|
|
94548
|
+
pendingPairingsCount: getPendingPairings(channelId).length,
|
|
94549
|
+
approvedUsersCount: getApprovedUsers(channelId).length,
|
|
94550
|
+
routesCount: getRoutesForChannel(channelId).length
|
|
94551
|
+
}
|
|
94552
|
+
];
|
|
94553
|
+
}
|
|
94554
|
+
function getChannelConfigSnapshot(channelId) {
|
|
94555
|
+
assertSupportedChannelId(channelId);
|
|
94556
|
+
const config = readChannelConfig(channelId);
|
|
94557
|
+
if (!config) {
|
|
94558
|
+
return null;
|
|
94559
|
+
}
|
|
94560
|
+
return toConfigSnapshot(channelId, config);
|
|
94561
|
+
}
|
|
94562
|
+
async function setChannelConfigLive(channelId, patch) {
|
|
94563
|
+
assertSupportedChannelId(channelId);
|
|
94564
|
+
const existing = readChannelConfig(channelId);
|
|
94565
|
+
const merged = {
|
|
94566
|
+
channel: "telegram",
|
|
94567
|
+
enabled: existing?.enabled ?? false,
|
|
94568
|
+
token: patch.token ?? existing?.token ?? "",
|
|
94569
|
+
dmPolicy: patch.dmPolicy ?? existing?.dmPolicy ?? "pairing",
|
|
94570
|
+
allowedUsers: patch.allowedUsers ?? existing?.allowedUsers ?? []
|
|
94571
|
+
};
|
|
94572
|
+
writeChannelConfig(channelId, merged);
|
|
94573
|
+
if (merged.enabled) {
|
|
94574
|
+
const registry = ensureChannelRegistry();
|
|
94575
|
+
await registry.startChannel(channelId);
|
|
94576
|
+
}
|
|
94577
|
+
return toConfigSnapshot(channelId, merged);
|
|
94578
|
+
}
|
|
94579
|
+
async function startChannelLive(channelId) {
|
|
94580
|
+
assertSupportedChannelId(channelId);
|
|
94581
|
+
const existing = readChannelConfig(channelId);
|
|
94582
|
+
if (!existing) {
|
|
94583
|
+
throw new Error(`Channel "${channelId}" is not configured. Configure it first.`);
|
|
94584
|
+
}
|
|
94585
|
+
if (!existing.token.trim()) {
|
|
94586
|
+
throw new Error(`Channel "${channelId}" is missing a token. Configure it first.`);
|
|
94587
|
+
}
|
|
94588
|
+
if (!existing.enabled) {
|
|
94589
|
+
writeChannelConfig(channelId, {
|
|
94590
|
+
...existing,
|
|
94591
|
+
enabled: true
|
|
94592
|
+
});
|
|
94593
|
+
}
|
|
94594
|
+
if (!getChannelRegistry()) {
|
|
94595
|
+
await initializeChannels([channelId]);
|
|
94596
|
+
} else {
|
|
94597
|
+
await ensureChannelRegistry().startChannel(channelId);
|
|
94598
|
+
}
|
|
94599
|
+
const summary = listChannelSummaries().find((entry) => entry.channelId === channelId);
|
|
94600
|
+
if (!summary) {
|
|
94601
|
+
throw new Error(`Channel "${channelId}" summary not found after start`);
|
|
94602
|
+
}
|
|
94603
|
+
return summary;
|
|
94604
|
+
}
|
|
94605
|
+
async function stopChannelLive(channelId) {
|
|
94606
|
+
assertSupportedChannelId(channelId);
|
|
94607
|
+
const existing = readChannelConfig(channelId);
|
|
94608
|
+
if (!existing) {
|
|
94609
|
+
throw new Error(`Channel "${channelId}" is not configured. Configure it first.`);
|
|
94610
|
+
}
|
|
94611
|
+
writeChannelConfig(channelId, {
|
|
94612
|
+
...existing,
|
|
94613
|
+
enabled: false
|
|
94614
|
+
});
|
|
94615
|
+
await getChannelRegistry()?.stopChannel(channelId);
|
|
94616
|
+
const summary = listChannelSummaries().find((entry) => entry.channelId === channelId);
|
|
94617
|
+
if (!summary) {
|
|
94618
|
+
throw new Error(`Channel "${channelId}" summary not found after stop`);
|
|
94619
|
+
}
|
|
94620
|
+
return summary;
|
|
94621
|
+
}
|
|
94622
|
+
function listPendingPairingSnapshots(channelId) {
|
|
94623
|
+
assertSupportedChannelId(channelId);
|
|
94624
|
+
loadPairingStore(channelId);
|
|
94625
|
+
return getPendingPairings(channelId).map(toPendingPairingSnapshot);
|
|
94626
|
+
}
|
|
94627
|
+
function bindChannelPairing(channelId, code, agentId, conversationId) {
|
|
94628
|
+
assertSupportedChannelId(channelId);
|
|
94629
|
+
loadRoutes(channelId);
|
|
94630
|
+
loadPairingStore(channelId);
|
|
94631
|
+
const result = completePairing(channelId, code, agentId, conversationId);
|
|
94632
|
+
if (!result.success || !result.chatId) {
|
|
94633
|
+
throw new Error(result.error ?? "Failed to bind pairing");
|
|
94634
|
+
}
|
|
94635
|
+
const route = getRoute(channelId, result.chatId);
|
|
94636
|
+
if (!route) {
|
|
94637
|
+
throw new Error("Pairing succeeded but route was not found");
|
|
94638
|
+
}
|
|
94639
|
+
return {
|
|
94640
|
+
chatId: result.chatId,
|
|
94641
|
+
route: toRouteSnapshot(channelId, route)
|
|
94642
|
+
};
|
|
94643
|
+
}
|
|
94644
|
+
function listChannelRouteSnapshots(params) {
|
|
94645
|
+
const channelId = params?.channelId ?? "telegram";
|
|
94646
|
+
assertSupportedChannelId(channelId);
|
|
94647
|
+
loadRoutes(channelId);
|
|
94648
|
+
return getRoutesForChannel(channelId).filter((route) => params?.agentId ? route.agentId === params.agentId : true).filter((route) => params?.conversationId ? route.conversationId === params.conversationId : true).map((route) => toRouteSnapshot(channelId, route));
|
|
94649
|
+
}
|
|
94650
|
+
function removeChannelRouteLive(channelId, chatId) {
|
|
94651
|
+
assertSupportedChannelId(channelId);
|
|
94652
|
+
loadRoutes(channelId);
|
|
94653
|
+
return removeRoute(channelId, chatId);
|
|
94654
|
+
}
|
|
94655
|
+
var CHANNEL_DISPLAY_NAMES;
|
|
94656
|
+
var init_service = __esm(() => {
|
|
94657
|
+
init_config();
|
|
94658
|
+
init_pairing();
|
|
94659
|
+
init_registry();
|
|
94660
|
+
init_routing();
|
|
94661
|
+
CHANNEL_DISPLAY_NAMES = {
|
|
94662
|
+
telegram: "Telegram"
|
|
94663
|
+
};
|
|
94664
|
+
});
|
|
94665
|
+
|
|
94192
94666
|
// src/agent/memoryScanner.ts
|
|
94193
94667
|
var exports_memoryScanner = {};
|
|
94194
94668
|
__export(exports_memoryScanner, {
|
|
@@ -94562,6 +95036,29 @@ function emitCronsUpdated(socket, scope) {
|
|
|
94562
95036
|
...scope?.conversation_id !== undefined ? { conversation_id: scope.conversation_id } : {}
|
|
94563
95037
|
}, "listener_cron_send_failed", "listener_cron_command");
|
|
94564
95038
|
}
|
|
95039
|
+
function emitChannelsUpdated(socket, channelId) {
|
|
95040
|
+
safeSocketSend(socket, {
|
|
95041
|
+
type: "channels_updated",
|
|
95042
|
+
timestamp: Date.now(),
|
|
95043
|
+
...channelId ? { channel_id: channelId } : {}
|
|
95044
|
+
}, "listener_channels_send_failed", "listener_channels_command");
|
|
95045
|
+
}
|
|
95046
|
+
function emitChannelPairingsUpdated(socket, channelId) {
|
|
95047
|
+
safeSocketSend(socket, {
|
|
95048
|
+
type: "channel_pairings_updated",
|
|
95049
|
+
timestamp: Date.now(),
|
|
95050
|
+
channel_id: channelId
|
|
95051
|
+
}, "listener_channels_send_failed", "listener_channels_command");
|
|
95052
|
+
}
|
|
95053
|
+
function emitChannelRoutesUpdated(socket, params) {
|
|
95054
|
+
safeSocketSend(socket, {
|
|
95055
|
+
type: "channel_routes_updated",
|
|
95056
|
+
timestamp: Date.now(),
|
|
95057
|
+
channel_id: params.channelId,
|
|
95058
|
+
...params.agentId ? { agent_id: params.agentId } : {},
|
|
95059
|
+
...params.conversationId !== undefined ? { conversation_id: params.conversationId } : {}
|
|
95060
|
+
}, "listener_channels_send_failed", "listener_channels_command");
|
|
95061
|
+
}
|
|
94565
95062
|
async function handleCronCommand(parsed, socket) {
|
|
94566
95063
|
if (parsed.type === "cron_list") {
|
|
94567
95064
|
try {
|
|
@@ -94699,6 +95196,299 @@ async function handleCronCommand(parsed, socket) {
|
|
|
94699
95196
|
}
|
|
94700
95197
|
return true;
|
|
94701
95198
|
}
|
|
95199
|
+
async function handleChannelsProtocolCommand(parsed, socket, runtime, opts, processQueuedTurn) {
|
|
95200
|
+
const {
|
|
95201
|
+
bindChannelPairing: bindChannelPairing2,
|
|
95202
|
+
getChannelConfigSnapshot: getChannelConfigSnapshot2,
|
|
95203
|
+
listChannelRouteSnapshots: listChannelRouteSnapshots2,
|
|
95204
|
+
listChannelSummaries: listChannelSummaries2,
|
|
95205
|
+
listPendingPairingSnapshots: listPendingPairingSnapshots2,
|
|
95206
|
+
removeChannelRouteLive: removeChannelRouteLive2,
|
|
95207
|
+
setChannelConfigLive: setChannelConfigLive2,
|
|
95208
|
+
startChannelLive: startChannelLive2,
|
|
95209
|
+
stopChannelLive: stopChannelLive2
|
|
95210
|
+
} = await Promise.resolve().then(() => (init_service(), exports_service));
|
|
95211
|
+
if (parsed.type === "channels_list") {
|
|
95212
|
+
try {
|
|
95213
|
+
safeSocketSend(socket, {
|
|
95214
|
+
type: "channels_list_response",
|
|
95215
|
+
request_id: parsed.request_id,
|
|
95216
|
+
success: true,
|
|
95217
|
+
channels: listChannelSummaries2().map((summary) => ({
|
|
95218
|
+
channel_id: summary.channelId,
|
|
95219
|
+
display_name: summary.displayName,
|
|
95220
|
+
configured: summary.configured,
|
|
95221
|
+
enabled: summary.enabled,
|
|
95222
|
+
running: summary.running,
|
|
95223
|
+
dm_policy: summary.dmPolicy,
|
|
95224
|
+
pending_pairings_count: summary.pendingPairingsCount,
|
|
95225
|
+
approved_users_count: summary.approvedUsersCount,
|
|
95226
|
+
routes_count: summary.routesCount
|
|
95227
|
+
}))
|
|
95228
|
+
}, "listener_channels_send_failed", "listener_channels_command");
|
|
95229
|
+
} catch (err) {
|
|
95230
|
+
safeSocketSend(socket, {
|
|
95231
|
+
type: "channels_list_response",
|
|
95232
|
+
request_id: parsed.request_id,
|
|
95233
|
+
success: false,
|
|
95234
|
+
channels: [],
|
|
95235
|
+
error: err instanceof Error ? err.message : "Failed to list channels"
|
|
95236
|
+
}, "listener_channels_send_failed", "listener_channels_command");
|
|
95237
|
+
}
|
|
95238
|
+
return true;
|
|
95239
|
+
}
|
|
95240
|
+
if (parsed.type === "channel_get_config") {
|
|
95241
|
+
try {
|
|
95242
|
+
safeSocketSend(socket, {
|
|
95243
|
+
type: "channel_get_config_response",
|
|
95244
|
+
request_id: parsed.request_id,
|
|
95245
|
+
success: true,
|
|
95246
|
+
config: (() => {
|
|
95247
|
+
const snapshot = getChannelConfigSnapshot2(parsed.channel_id);
|
|
95248
|
+
return snapshot ? {
|
|
95249
|
+
channel_id: snapshot.channelId,
|
|
95250
|
+
enabled: snapshot.enabled,
|
|
95251
|
+
dm_policy: snapshot.dmPolicy,
|
|
95252
|
+
allowed_users: snapshot.allowedUsers,
|
|
95253
|
+
has_token: snapshot.hasToken
|
|
95254
|
+
} : null;
|
|
95255
|
+
})()
|
|
95256
|
+
}, "listener_channels_send_failed", "listener_channels_command");
|
|
95257
|
+
} catch (err) {
|
|
95258
|
+
safeSocketSend(socket, {
|
|
95259
|
+
type: "channel_get_config_response",
|
|
95260
|
+
request_id: parsed.request_id,
|
|
95261
|
+
success: false,
|
|
95262
|
+
config: null,
|
|
95263
|
+
error: err instanceof Error ? err.message : "Failed to read channel config"
|
|
95264
|
+
}, "listener_channels_send_failed", "listener_channels_command");
|
|
95265
|
+
}
|
|
95266
|
+
return true;
|
|
95267
|
+
}
|
|
95268
|
+
if (parsed.type === "channel_set_config") {
|
|
95269
|
+
try {
|
|
95270
|
+
const snapshot = await setChannelConfigLive2(parsed.channel_id, {
|
|
95271
|
+
token: parsed.config.token,
|
|
95272
|
+
dmPolicy: parsed.config.dm_policy,
|
|
95273
|
+
allowedUsers: parsed.config.allowed_users
|
|
95274
|
+
});
|
|
95275
|
+
if (snapshot.enabled) {
|
|
95276
|
+
wireChannelIngress(runtime, socket, opts, processQueuedTurn);
|
|
95277
|
+
}
|
|
95278
|
+
safeSocketSend(socket, {
|
|
95279
|
+
type: "channel_set_config_response",
|
|
95280
|
+
request_id: parsed.request_id,
|
|
95281
|
+
success: true,
|
|
95282
|
+
config: {
|
|
95283
|
+
channel_id: snapshot.channelId,
|
|
95284
|
+
enabled: snapshot.enabled,
|
|
95285
|
+
dm_policy: snapshot.dmPolicy,
|
|
95286
|
+
allowed_users: snapshot.allowedUsers,
|
|
95287
|
+
has_token: snapshot.hasToken
|
|
95288
|
+
}
|
|
95289
|
+
}, "listener_channels_send_failed", "listener_channels_command");
|
|
95290
|
+
emitChannelsUpdated(socket, parsed.channel_id);
|
|
95291
|
+
} catch (err) {
|
|
95292
|
+
safeSocketSend(socket, {
|
|
95293
|
+
type: "channel_set_config_response",
|
|
95294
|
+
request_id: parsed.request_id,
|
|
95295
|
+
success: false,
|
|
95296
|
+
config: null,
|
|
95297
|
+
error: err instanceof Error ? err.message : "Failed to update channel config"
|
|
95298
|
+
}, "listener_channels_send_failed", "listener_channels_command");
|
|
95299
|
+
}
|
|
95300
|
+
return true;
|
|
95301
|
+
}
|
|
95302
|
+
if (parsed.type === "channel_start") {
|
|
95303
|
+
try {
|
|
95304
|
+
const summary = await startChannelLive2(parsed.channel_id);
|
|
95305
|
+
wireChannelIngress(runtime, socket, opts, processQueuedTurn);
|
|
95306
|
+
safeSocketSend(socket, {
|
|
95307
|
+
type: "channel_start_response",
|
|
95308
|
+
request_id: parsed.request_id,
|
|
95309
|
+
success: true,
|
|
95310
|
+
channel: {
|
|
95311
|
+
channel_id: summary.channelId,
|
|
95312
|
+
display_name: summary.displayName,
|
|
95313
|
+
configured: summary.configured,
|
|
95314
|
+
enabled: summary.enabled,
|
|
95315
|
+
running: summary.running,
|
|
95316
|
+
dm_policy: summary.dmPolicy,
|
|
95317
|
+
pending_pairings_count: summary.pendingPairingsCount,
|
|
95318
|
+
approved_users_count: summary.approvedUsersCount,
|
|
95319
|
+
routes_count: summary.routesCount
|
|
95320
|
+
}
|
|
95321
|
+
}, "listener_channels_send_failed", "listener_channels_command");
|
|
95322
|
+
emitChannelsUpdated(socket, parsed.channel_id);
|
|
95323
|
+
} catch (err) {
|
|
95324
|
+
safeSocketSend(socket, {
|
|
95325
|
+
type: "channel_start_response",
|
|
95326
|
+
request_id: parsed.request_id,
|
|
95327
|
+
success: false,
|
|
95328
|
+
channel: null,
|
|
95329
|
+
error: err instanceof Error ? err.message : "Failed to start channel"
|
|
95330
|
+
}, "listener_channels_send_failed", "listener_channels_command");
|
|
95331
|
+
}
|
|
95332
|
+
return true;
|
|
95333
|
+
}
|
|
95334
|
+
if (parsed.type === "channel_stop") {
|
|
95335
|
+
try {
|
|
95336
|
+
const summary = await stopChannelLive2(parsed.channel_id);
|
|
95337
|
+
safeSocketSend(socket, {
|
|
95338
|
+
type: "channel_stop_response",
|
|
95339
|
+
request_id: parsed.request_id,
|
|
95340
|
+
success: true,
|
|
95341
|
+
channel: {
|
|
95342
|
+
channel_id: summary.channelId,
|
|
95343
|
+
display_name: summary.displayName,
|
|
95344
|
+
configured: summary.configured,
|
|
95345
|
+
enabled: summary.enabled,
|
|
95346
|
+
running: summary.running,
|
|
95347
|
+
dm_policy: summary.dmPolicy,
|
|
95348
|
+
pending_pairings_count: summary.pendingPairingsCount,
|
|
95349
|
+
approved_users_count: summary.approvedUsersCount,
|
|
95350
|
+
routes_count: summary.routesCount
|
|
95351
|
+
}
|
|
95352
|
+
}, "listener_channels_send_failed", "listener_channels_command");
|
|
95353
|
+
emitChannelsUpdated(socket, parsed.channel_id);
|
|
95354
|
+
} catch (err) {
|
|
95355
|
+
safeSocketSend(socket, {
|
|
95356
|
+
type: "channel_stop_response",
|
|
95357
|
+
request_id: parsed.request_id,
|
|
95358
|
+
success: false,
|
|
95359
|
+
channel: null,
|
|
95360
|
+
error: err instanceof Error ? err.message : "Failed to stop channel"
|
|
95361
|
+
}, "listener_channels_send_failed", "listener_channels_command");
|
|
95362
|
+
}
|
|
95363
|
+
return true;
|
|
95364
|
+
}
|
|
95365
|
+
if (parsed.type === "channel_pairings_list") {
|
|
95366
|
+
try {
|
|
95367
|
+
safeSocketSend(socket, {
|
|
95368
|
+
type: "channel_pairings_list_response",
|
|
95369
|
+
request_id: parsed.request_id,
|
|
95370
|
+
success: true,
|
|
95371
|
+
channel_id: parsed.channel_id,
|
|
95372
|
+
pending: listPendingPairingSnapshots2(parsed.channel_id).map((pending) => ({
|
|
95373
|
+
code: pending.code,
|
|
95374
|
+
sender_id: pending.senderId,
|
|
95375
|
+
sender_name: pending.senderName,
|
|
95376
|
+
chat_id: pending.chatId,
|
|
95377
|
+
created_at: pending.createdAt,
|
|
95378
|
+
expires_at: pending.expiresAt
|
|
95379
|
+
}))
|
|
95380
|
+
}, "listener_channels_send_failed", "listener_channels_command");
|
|
95381
|
+
} catch (err) {
|
|
95382
|
+
safeSocketSend(socket, {
|
|
95383
|
+
type: "channel_pairings_list_response",
|
|
95384
|
+
request_id: parsed.request_id,
|
|
95385
|
+
success: false,
|
|
95386
|
+
channel_id: parsed.channel_id,
|
|
95387
|
+
pending: [],
|
|
95388
|
+
error: err instanceof Error ? err.message : "Failed to list pending pairings"
|
|
95389
|
+
}, "listener_channels_send_failed", "listener_channels_command");
|
|
95390
|
+
}
|
|
95391
|
+
return true;
|
|
95392
|
+
}
|
|
95393
|
+
if (parsed.type === "channel_pairing_bind") {
|
|
95394
|
+
try {
|
|
95395
|
+
const result = bindChannelPairing2(parsed.channel_id, parsed.code, parsed.runtime.agent_id, parsed.runtime.conversation_id);
|
|
95396
|
+
safeSocketSend(socket, {
|
|
95397
|
+
type: "channel_pairing_bind_response",
|
|
95398
|
+
request_id: parsed.request_id,
|
|
95399
|
+
success: true,
|
|
95400
|
+
channel_id: parsed.channel_id,
|
|
95401
|
+
chat_id: result.chatId,
|
|
95402
|
+
route: {
|
|
95403
|
+
channel_id: result.route.channelId,
|
|
95404
|
+
chat_id: result.route.chatId,
|
|
95405
|
+
agent_id: result.route.agentId,
|
|
95406
|
+
conversation_id: result.route.conversationId,
|
|
95407
|
+
enabled: result.route.enabled,
|
|
95408
|
+
created_at: result.route.createdAt
|
|
95409
|
+
}
|
|
95410
|
+
}, "listener_channels_send_failed", "listener_channels_command");
|
|
95411
|
+
emitChannelPairingsUpdated(socket, parsed.channel_id);
|
|
95412
|
+
emitChannelRoutesUpdated(socket, {
|
|
95413
|
+
channelId: parsed.channel_id,
|
|
95414
|
+
agentId: parsed.runtime.agent_id,
|
|
95415
|
+
conversationId: parsed.runtime.conversation_id
|
|
95416
|
+
});
|
|
95417
|
+
emitChannelsUpdated(socket, parsed.channel_id);
|
|
95418
|
+
} catch (err) {
|
|
95419
|
+
safeSocketSend(socket, {
|
|
95420
|
+
type: "channel_pairing_bind_response",
|
|
95421
|
+
request_id: parsed.request_id,
|
|
95422
|
+
success: false,
|
|
95423
|
+
channel_id: parsed.channel_id,
|
|
95424
|
+
route: null,
|
|
95425
|
+
error: err instanceof Error ? err.message : "Failed to bind pairing"
|
|
95426
|
+
}, "listener_channels_send_failed", "listener_channels_command");
|
|
95427
|
+
}
|
|
95428
|
+
return true;
|
|
95429
|
+
}
|
|
95430
|
+
if (parsed.type === "channel_routes_list") {
|
|
95431
|
+
try {
|
|
95432
|
+
const channelId = parsed.channel_id ?? "telegram";
|
|
95433
|
+
safeSocketSend(socket, {
|
|
95434
|
+
type: "channel_routes_list_response",
|
|
95435
|
+
request_id: parsed.request_id,
|
|
95436
|
+
success: true,
|
|
95437
|
+
channel_id: channelId,
|
|
95438
|
+
routes: listChannelRouteSnapshots2({
|
|
95439
|
+
channelId,
|
|
95440
|
+
agentId: parsed.agent_id,
|
|
95441
|
+
conversationId: parsed.conversation_id
|
|
95442
|
+
}).map((route) => ({
|
|
95443
|
+
channel_id: route.channelId,
|
|
95444
|
+
chat_id: route.chatId,
|
|
95445
|
+
agent_id: route.agentId,
|
|
95446
|
+
conversation_id: route.conversationId,
|
|
95447
|
+
enabled: route.enabled,
|
|
95448
|
+
created_at: route.createdAt
|
|
95449
|
+
}))
|
|
95450
|
+
}, "listener_channels_send_failed", "listener_channels_command");
|
|
95451
|
+
} catch (err) {
|
|
95452
|
+
safeSocketSend(socket, {
|
|
95453
|
+
type: "channel_routes_list_response",
|
|
95454
|
+
request_id: parsed.request_id,
|
|
95455
|
+
success: false,
|
|
95456
|
+
channel_id: parsed.channel_id,
|
|
95457
|
+
routes: [],
|
|
95458
|
+
error: err instanceof Error ? err.message : "Failed to list routes"
|
|
95459
|
+
}, "listener_channels_send_failed", "listener_channels_command");
|
|
95460
|
+
}
|
|
95461
|
+
return true;
|
|
95462
|
+
}
|
|
95463
|
+
try {
|
|
95464
|
+
const found = removeChannelRouteLive2(parsed.channel_id, parsed.chat_id);
|
|
95465
|
+
safeSocketSend(socket, {
|
|
95466
|
+
type: "channel_route_remove_response",
|
|
95467
|
+
request_id: parsed.request_id,
|
|
95468
|
+
success: true,
|
|
95469
|
+
channel_id: parsed.channel_id,
|
|
95470
|
+
chat_id: parsed.chat_id,
|
|
95471
|
+
found
|
|
95472
|
+
}, "listener_channels_send_failed", "listener_channels_command");
|
|
95473
|
+
if (found) {
|
|
95474
|
+
emitChannelRoutesUpdated(socket, {
|
|
95475
|
+
channelId: parsed.channel_id
|
|
95476
|
+
});
|
|
95477
|
+
emitChannelsUpdated(socket, parsed.channel_id);
|
|
95478
|
+
}
|
|
95479
|
+
} catch (err) {
|
|
95480
|
+
safeSocketSend(socket, {
|
|
95481
|
+
type: "channel_route_remove_response",
|
|
95482
|
+
request_id: parsed.request_id,
|
|
95483
|
+
success: false,
|
|
95484
|
+
channel_id: parsed.channel_id,
|
|
95485
|
+
chat_id: parsed.chat_id,
|
|
95486
|
+
found: false,
|
|
95487
|
+
error: err instanceof Error ? err.message : "Failed to remove route"
|
|
95488
|
+
}, "listener_channels_send_failed", "listener_channels_command");
|
|
95489
|
+
}
|
|
95490
|
+
return true;
|
|
95491
|
+
}
|
|
94702
95492
|
function emitSkillsUpdated(socket) {
|
|
94703
95493
|
safeSocketSend(socket, {
|
|
94704
95494
|
type: "skills_updated",
|
|
@@ -94958,6 +95748,12 @@ function wireChannelIngress(listener, socket, opts, processQueuedTurn) {
|
|
|
94958
95748
|
enqueueChannelTurn(conversationRuntime, route, xmlContent);
|
|
94959
95749
|
scheduleQueuePump(conversationRuntime, socket, opts, processQueuedTurn);
|
|
94960
95750
|
});
|
|
95751
|
+
registry.setEventHandler((event) => {
|
|
95752
|
+
if (event.type === "pairings_updated") {
|
|
95753
|
+
emitChannelPairingsUpdated(socket, event.channelId);
|
|
95754
|
+
emitChannelsUpdated(socket, event.channelId);
|
|
95755
|
+
}
|
|
95756
|
+
});
|
|
94961
95757
|
registry.setReady();
|
|
94962
95758
|
}
|
|
94963
95759
|
function enqueueChannelTurn(runtime, route, xmlContent) {
|
|
@@ -96196,6 +96992,12 @@ async function connectWithRetry(runtime, opts, attempt = 0, startTime = Date.now
|
|
|
96196
96992
|
});
|
|
96197
96993
|
return;
|
|
96198
96994
|
}
|
|
96995
|
+
if (isChannelsListCommand(parsed) || isChannelGetConfigCommand(parsed) || isChannelSetConfigCommand(parsed) || isChannelStartCommand(parsed) || isChannelStopCommand(parsed) || isChannelPairingsListCommand(parsed) || isChannelPairingBindCommand(parsed) || isChannelRoutesListCommand(parsed) || isChannelRouteRemoveCommand(parsed)) {
|
|
96996
|
+
runDetachedListenerTask("channels_command", async () => {
|
|
96997
|
+
await handleChannelsProtocolCommand(parsed, socket, runtime, opts, processQueuedTurn);
|
|
96998
|
+
});
|
|
96999
|
+
return;
|
|
97000
|
+
}
|
|
96199
97001
|
if (isSkillEnableCommand(parsed) || isSkillDisableCommand(parsed)) {
|
|
96200
97002
|
runDetachedListenerTask("skill_command", async () => {
|
|
96201
97003
|
await handleSkillCommand(parsed, socket);
|
|
@@ -96696,6 +97498,7 @@ var init_client4 = __esm(async () => {
|
|
|
96696
97498
|
handleAbortMessageInput,
|
|
96697
97499
|
handleChangeDeviceStateInput,
|
|
96698
97500
|
handleCronCommand,
|
|
97501
|
+
handleChannelsProtocolCommand,
|
|
96699
97502
|
handleSkillCommand,
|
|
96700
97503
|
handleCreateAgentCommand,
|
|
96701
97504
|
handleReflectionSettingsCommand,
|
|
@@ -115871,7 +116674,7 @@ function xml(hljs) {
|
|
|
115871
116674
|
]
|
|
115872
116675
|
};
|
|
115873
116676
|
}
|
|
115874
|
-
var
|
|
116677
|
+
var init_xml2 = () => {};
|
|
115875
116678
|
|
|
115876
116679
|
// node_modules/highlight.js/es/languages/yaml.js
|
|
115877
116680
|
function yaml(hljs) {
|
|
@@ -116091,7 +116894,7 @@ var init_common = __esm(() => {
|
|
|
116091
116894
|
init_typescript2();
|
|
116092
116895
|
init_vbnet();
|
|
116093
116896
|
init_wasm();
|
|
116094
|
-
|
|
116897
|
+
init_xml2();
|
|
116095
116898
|
init_yaml();
|
|
116096
116899
|
grammars = {
|
|
116097
116900
|
arduino,
|
|
@@ -165182,4 +165985,4 @@ Error during initialization: ${message}`);
|
|
|
165182
165985
|
}
|
|
165183
165986
|
main();
|
|
165184
165987
|
|
|
165185
|
-
//# debugId=
|
|
165988
|
+
//# debugId=177C3FD8089A6F3E64756E2164756E21
|