@letta-ai/letta-code 0.27.12 → 0.27.14
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/app-server-client.js +20 -5
- package/dist/app-server-client.js.map +3 -3
- package/dist/types/app-server-client.d.ts +6 -1
- package/dist/types/app-server-client.d.ts.map +1 -1
- package/dist/types/types/protocol_v2.d.ts +2 -39
- package/dist/types/types/protocol_v2.d.ts.map +1 -1
- package/letta.js +767 -1677
- package/package.json +1 -1
package/letta.js
CHANGED
|
@@ -3550,7 +3550,7 @@ __export(exports_settings_manager, {
|
|
|
3550
3550
|
settingsManager: () => settingsManager
|
|
3551
3551
|
});
|
|
3552
3552
|
import { randomUUID } from "node:crypto";
|
|
3553
|
-
import {
|
|
3553
|
+
import { readFileSync as readFileSync2 } from "node:fs";
|
|
3554
3554
|
import { homedir as homedir3 } from "node:os";
|
|
3555
3555
|
import { join as join3, resolve } from "node:path";
|
|
3556
3556
|
function isSubagentProcess() {
|
|
@@ -3624,11 +3624,6 @@ class SettingsManager {
|
|
|
3624
3624
|
clearSecureTokensCache() {
|
|
3625
3625
|
this.secureTokensCache = {};
|
|
3626
3626
|
}
|
|
3627
|
-
ensureInitialized() {
|
|
3628
|
-
if (!this.initialized || !this.settings) {
|
|
3629
|
-
throw new Error("Settings not initialized. Call settingsManager.initialize() first.");
|
|
3630
|
-
}
|
|
3631
|
-
}
|
|
3632
3627
|
readJsonObjectSync(path2) {
|
|
3633
3628
|
if (!exists(path2))
|
|
3634
3629
|
return {};
|
|
@@ -3638,57 +3633,6 @@ class SettingsManager {
|
|
|
3638
3633
|
return {};
|
|
3639
3634
|
}
|
|
3640
3635
|
}
|
|
3641
|
-
normalizeSettingsRecord(raw) {
|
|
3642
|
-
const normalized = { ...raw };
|
|
3643
|
-
for (const key of OBSOLETE_SETTINGS_KEYS) {
|
|
3644
|
-
delete normalized[key];
|
|
3645
|
-
}
|
|
3646
|
-
return normalized;
|
|
3647
|
-
}
|
|
3648
|
-
settingsFromRaw(raw) {
|
|
3649
|
-
return {
|
|
3650
|
-
...DEFAULT_SETTINGS,
|
|
3651
|
-
...this.normalizeSettingsRecord(raw)
|
|
3652
|
-
};
|
|
3653
|
-
}
|
|
3654
|
-
readSettingsSnapshot() {
|
|
3655
|
-
this.ensureInitialized();
|
|
3656
|
-
const raw = this.readJsonObjectSync(this.getSettingsPath());
|
|
3657
|
-
const mergedRaw = this.normalizeSettingsRecord(raw);
|
|
3658
|
-
if (this.settings) {
|
|
3659
|
-
const currentRecord = this.settings;
|
|
3660
|
-
for (const key of this.dirtyKeys) {
|
|
3661
|
-
if (key in currentRecord) {
|
|
3662
|
-
mergedRaw[key] = currentRecord[key];
|
|
3663
|
-
} else {
|
|
3664
|
-
delete mergedRaw[key];
|
|
3665
|
-
}
|
|
3666
|
-
}
|
|
3667
|
-
}
|
|
3668
|
-
const settings = this.settingsFromRaw(mergedRaw);
|
|
3669
|
-
this.settings = settings;
|
|
3670
|
-
for (const key of Object.keys(mergedRaw)) {
|
|
3671
|
-
this.managedKeys.add(key);
|
|
3672
|
-
}
|
|
3673
|
-
return settings;
|
|
3674
|
-
}
|
|
3675
|
-
writeSettingsRecordSync(raw) {
|
|
3676
|
-
const settingsPath = this.getSettingsPath();
|
|
3677
|
-
const home = process.env.HOME || homedir3();
|
|
3678
|
-
const dirPath = join3(home, ".letta");
|
|
3679
|
-
if (!exists(dirPath)) {
|
|
3680
|
-
mkdirSync3(dirPath, { recursive: true });
|
|
3681
|
-
}
|
|
3682
|
-
const normalized = this.normalizeSettingsRecord(raw);
|
|
3683
|
-
writeFileSync(settingsPath, JSON.stringify(normalized, null, 2), {
|
|
3684
|
-
encoding: "utf-8",
|
|
3685
|
-
flush: true
|
|
3686
|
-
});
|
|
3687
|
-
this.settings = this.settingsFromRaw(normalized);
|
|
3688
|
-
for (const key of Object.keys(normalized)) {
|
|
3689
|
-
this.managedKeys.add(key);
|
|
3690
|
-
}
|
|
3691
|
-
}
|
|
3692
3636
|
get isReady() {
|
|
3693
3637
|
return this.initialized;
|
|
3694
3638
|
}
|
|
@@ -3737,7 +3681,6 @@ class SettingsManager {
|
|
|
3737
3681
|
if (!isSubagentProcess()) {
|
|
3738
3682
|
await this.migrateTokensToSecrets();
|
|
3739
3683
|
}
|
|
3740
|
-
this.migrateToAgentsArray();
|
|
3741
3684
|
} catch (error) {
|
|
3742
3685
|
trackBoundaryError({
|
|
3743
3686
|
errorType: "settings_load_failed",
|
|
@@ -3754,7 +3697,6 @@ class SettingsManager {
|
|
|
3754
3697
|
if (!isSubagentProcess()) {
|
|
3755
3698
|
await this.migrateTokensToSecrets();
|
|
3756
3699
|
}
|
|
3757
|
-
this.migrateToAgentsArray();
|
|
3758
3700
|
}
|
|
3759
3701
|
}
|
|
3760
3702
|
async checkSecretsSupport() {
|
|
@@ -3809,46 +3751,6 @@ class SettingsManager {
|
|
|
3809
3751
|
console.warn("Failed to migrate tokens to secrets:", error);
|
|
3810
3752
|
}
|
|
3811
3753
|
}
|
|
3812
|
-
migrateToAgentsArray() {
|
|
3813
|
-
if (!this.settings)
|
|
3814
|
-
return;
|
|
3815
|
-
if (this.settings.agents)
|
|
3816
|
-
return;
|
|
3817
|
-
const agents = [];
|
|
3818
|
-
const seen = new Set;
|
|
3819
|
-
if (this.settings.pinnedAgentsByServer) {
|
|
3820
|
-
for (const [serverKey, agentIds] of Object.entries(this.settings.pinnedAgentsByServer)) {
|
|
3821
|
-
for (const agentId of agentIds) {
|
|
3822
|
-
const baseUrl = serverKey === "api.letta.com" ? undefined : serverKey;
|
|
3823
|
-
const key = `${agentId}@${baseUrl ?? "cloud"}`;
|
|
3824
|
-
if (!seen.has(key)) {
|
|
3825
|
-
agents.push({
|
|
3826
|
-
agentId,
|
|
3827
|
-
baseUrl,
|
|
3828
|
-
pinned: true
|
|
3829
|
-
});
|
|
3830
|
-
seen.add(key);
|
|
3831
|
-
}
|
|
3832
|
-
}
|
|
3833
|
-
}
|
|
3834
|
-
}
|
|
3835
|
-
if (this.settings.pinnedAgents) {
|
|
3836
|
-
for (const agentId of this.settings.pinnedAgents) {
|
|
3837
|
-
const key = `${agentId}@cloud`;
|
|
3838
|
-
if (!seen.has(key)) {
|
|
3839
|
-
agents.push({ agentId, pinned: true });
|
|
3840
|
-
seen.add(key);
|
|
3841
|
-
}
|
|
3842
|
-
}
|
|
3843
|
-
}
|
|
3844
|
-
if (agents.length > 0) {
|
|
3845
|
-
this.settings = { ...this.settings, agents };
|
|
3846
|
-
this.markDirty("agents");
|
|
3847
|
-
this.persistSettings().catch((error) => {
|
|
3848
|
-
console.warn("Failed to persist agents array migration:", error);
|
|
3849
|
-
});
|
|
3850
|
-
}
|
|
3851
|
-
}
|
|
3852
3754
|
getSettings() {
|
|
3853
3755
|
if (!this.initialized || !this.settings) {
|
|
3854
3756
|
throw new Error("Settings not initialized. Call settingsManager.initialize() first.");
|
|
@@ -4489,182 +4391,20 @@ class SettingsManager {
|
|
|
4489
4391
|
}, workingDirectory);
|
|
4490
4392
|
return hadGoal;
|
|
4491
4393
|
}
|
|
4492
|
-
|
|
4394
|
+
getPinnedAgents() {
|
|
4493
4395
|
const settings = this.getSettings();
|
|
4494
4396
|
const serverKey = getCurrentServerKey(settings);
|
|
4495
|
-
|
|
4496
|
-
|
|
4497
|
-
}
|
|
4498
|
-
if (settings.profiles && !settings.pinnedAgents) {
|
|
4499
|
-
const agentIds = Object.values(settings.profiles);
|
|
4500
|
-
this.updateSettings({ pinnedAgents: agentIds, profiles: undefined });
|
|
4501
|
-
return agentIds;
|
|
4502
|
-
}
|
|
4503
|
-
return settings.pinnedAgents || [];
|
|
4504
|
-
}
|
|
4505
|
-
getLocalPinnedAgents(workingDirectory = process.cwd()) {
|
|
4506
|
-
const globalSettings = this.getSettings();
|
|
4507
|
-
const serverKey = getCurrentServerKey(globalSettings);
|
|
4508
|
-
const localSettings = this.getLocalProjectSettings(workingDirectory);
|
|
4509
|
-
if (localSettings.pinnedAgentsByServer?.[serverKey]) {
|
|
4510
|
-
return localSettings.pinnedAgentsByServer[serverKey];
|
|
4511
|
-
}
|
|
4512
|
-
if (localSettings.profiles && !localSettings.pinnedAgents) {
|
|
4513
|
-
const agentIds = Object.values(localSettings.profiles);
|
|
4514
|
-
this.updateLocalProjectSettings({ pinnedAgents: agentIds, profiles: undefined }, workingDirectory);
|
|
4515
|
-
return agentIds;
|
|
4516
|
-
}
|
|
4517
|
-
return localSettings.pinnedAgents || [];
|
|
4518
|
-
}
|
|
4519
|
-
getMergedPinnedAgents(workingDirectory = process.cwd()) {
|
|
4520
|
-
const globalAgents = this.getGlobalPinnedAgents();
|
|
4521
|
-
const localAgents = this.getLocalPinnedAgents(workingDirectory);
|
|
4522
|
-
const result = [];
|
|
4523
|
-
const seenAgentIds = new Set;
|
|
4524
|
-
for (const agentId of localAgents) {
|
|
4525
|
-
result.push({ agentId, isLocal: true });
|
|
4526
|
-
seenAgentIds.add(agentId);
|
|
4527
|
-
}
|
|
4528
|
-
for (const agentId of globalAgents) {
|
|
4529
|
-
if (!seenAgentIds.has(agentId)) {
|
|
4530
|
-
result.push({ agentId, isLocal: false });
|
|
4531
|
-
seenAgentIds.add(agentId);
|
|
4532
|
-
}
|
|
4533
|
-
}
|
|
4534
|
-
return result;
|
|
4535
|
-
}
|
|
4536
|
-
getGlobalPinnedConversations(agentId) {
|
|
4537
|
-
const settings = this.readSettingsSnapshot();
|
|
4538
|
-
const serverKey = getCurrentServerKey(settings);
|
|
4539
|
-
return settings.pinnedConversationsByServer?.[serverKey]?.[agentId] ?? [];
|
|
4540
|
-
}
|
|
4541
|
-
readLocalProjectSettingsSnapshot(workingDirectory) {
|
|
4542
|
-
const raw = this.normalizeSettingsRecord(this.readJsonObjectSync(this.getLocalProjectSettingsPath(workingDirectory)));
|
|
4543
|
-
const settings = {
|
|
4544
|
-
...DEFAULT_LOCAL_PROJECT_SETTINGS,
|
|
4545
|
-
...raw
|
|
4546
|
-
};
|
|
4547
|
-
this.localProjectSettings.set(workingDirectory, settings);
|
|
4548
|
-
return settings;
|
|
4549
|
-
}
|
|
4550
|
-
writeLocalProjectSettingsRecordSync(workingDirectory, raw) {
|
|
4551
|
-
const dirPath = join3(workingDirectory, ".letta");
|
|
4552
|
-
if (!exists(dirPath)) {
|
|
4553
|
-
mkdirSync3(dirPath, { recursive: true });
|
|
4554
|
-
}
|
|
4555
|
-
const normalized = this.normalizeSettingsRecord(raw);
|
|
4556
|
-
writeFileSync(this.getLocalProjectSettingsPath(workingDirectory), JSON.stringify(normalized, null, 2), { encoding: "utf-8", flush: true });
|
|
4557
|
-
this.localProjectSettings.set(workingDirectory, {
|
|
4558
|
-
...DEFAULT_LOCAL_PROJECT_SETTINGS,
|
|
4559
|
-
...normalized
|
|
4560
|
-
});
|
|
4561
|
-
}
|
|
4562
|
-
getLocalPinnedConversations(agentId, workingDirectory = process.cwd()) {
|
|
4563
|
-
const globalSettings = this.readSettingsSnapshot();
|
|
4564
|
-
const serverKey = getCurrentServerKey(globalSettings);
|
|
4565
|
-
const localSettings = this.readLocalProjectSettingsSnapshot(workingDirectory);
|
|
4566
|
-
return localSettings.pinnedConversationsByServer?.[serverKey]?.[agentId] ?? [];
|
|
4567
|
-
}
|
|
4568
|
-
getMergedPinnedConversations(agentId, workingDirectory = process.cwd()) {
|
|
4569
|
-
const localConversations = this.getLocalPinnedConversations(agentId, workingDirectory);
|
|
4570
|
-
const globalConversations = this.getGlobalPinnedConversations(agentId);
|
|
4571
|
-
const result = [];
|
|
4572
|
-
const seenConversationIds = new Set;
|
|
4573
|
-
for (const conversationId of localConversations) {
|
|
4574
|
-
result.push({ conversationId, isLocal: true });
|
|
4575
|
-
seenConversationIds.add(conversationId);
|
|
4576
|
-
}
|
|
4577
|
-
for (const conversationId of globalConversations) {
|
|
4578
|
-
if (!seenConversationIds.has(conversationId)) {
|
|
4579
|
-
result.push({ conversationId, isLocal: false });
|
|
4580
|
-
seenConversationIds.add(conversationId);
|
|
4581
|
-
}
|
|
4582
|
-
}
|
|
4583
|
-
return result;
|
|
4584
|
-
}
|
|
4585
|
-
pinConversationGlobal(agentId, conversationId) {
|
|
4586
|
-
this.ensureInitialized();
|
|
4587
|
-
const raw = this.normalizeSettingsRecord(this.readJsonObjectSync(this.getSettingsPath()));
|
|
4588
|
-
const settings = this.settingsFromRaw(raw);
|
|
4589
|
-
const serverKey = getCurrentServerKey(settings);
|
|
4590
|
-
const current = settings.pinnedConversationsByServer?.[serverKey]?.[agentId] ?? [];
|
|
4591
|
-
if (current.includes(conversationId))
|
|
4592
|
-
return;
|
|
4593
|
-
this.writeSettingsRecordSync({
|
|
4594
|
-
...raw,
|
|
4595
|
-
pinnedConversationsByServer: {
|
|
4596
|
-
...settings.pinnedConversationsByServer ?? {},
|
|
4597
|
-
[serverKey]: {
|
|
4598
|
-
...settings.pinnedConversationsByServer?.[serverKey] ?? {},
|
|
4599
|
-
[agentId]: [...current, conversationId]
|
|
4600
|
-
}
|
|
4601
|
-
}
|
|
4602
|
-
});
|
|
4603
|
-
this.dirtyKeys.delete("pinnedConversationsByServer");
|
|
4604
|
-
}
|
|
4605
|
-
unpinConversationGlobal(agentId, conversationId) {
|
|
4606
|
-
this.ensureInitialized();
|
|
4607
|
-
const raw = this.normalizeSettingsRecord(this.readJsonObjectSync(this.getSettingsPath()));
|
|
4608
|
-
const settings = this.settingsFromRaw(raw);
|
|
4609
|
-
const serverKey = getCurrentServerKey(settings);
|
|
4610
|
-
const current = settings.pinnedConversationsByServer?.[serverKey]?.[agentId] ?? [];
|
|
4611
|
-
this.writeSettingsRecordSync({
|
|
4612
|
-
...raw,
|
|
4613
|
-
pinnedConversationsByServer: {
|
|
4614
|
-
...settings.pinnedConversationsByServer ?? {},
|
|
4615
|
-
[serverKey]: {
|
|
4616
|
-
...settings.pinnedConversationsByServer?.[serverKey] ?? {},
|
|
4617
|
-
[agentId]: current.filter((id) => id !== conversationId)
|
|
4618
|
-
}
|
|
4619
|
-
}
|
|
4620
|
-
});
|
|
4621
|
-
this.dirtyKeys.delete("pinnedConversationsByServer");
|
|
4397
|
+
const normalizedBaseUrl = serverKey === "api.letta.com" ? undefined : serverKey;
|
|
4398
|
+
return settings.agents?.filter((a) => a.pinned && (a.baseUrl ?? undefined) === normalizedBaseUrl).map((a) => a.agentId) ?? [];
|
|
4622
4399
|
}
|
|
4623
|
-
|
|
4624
|
-
|
|
4625
|
-
const serverKey = getCurrentServerKey(globalSettings);
|
|
4626
|
-
const raw = this.normalizeSettingsRecord(this.readJsonObjectSync(this.getLocalProjectSettingsPath(workingDirectory)));
|
|
4627
|
-
const localSettings = {
|
|
4628
|
-
...DEFAULT_LOCAL_PROJECT_SETTINGS,
|
|
4629
|
-
...raw
|
|
4630
|
-
};
|
|
4631
|
-
const current = localSettings.pinnedConversationsByServer?.[serverKey]?.[agentId] ?? [];
|
|
4632
|
-
if (current.includes(conversationId))
|
|
4633
|
-
return;
|
|
4634
|
-
this.writeLocalProjectSettingsRecordSync(workingDirectory, {
|
|
4635
|
-
...raw,
|
|
4636
|
-
pinnedConversationsByServer: {
|
|
4637
|
-
...localSettings.pinnedConversationsByServer ?? {},
|
|
4638
|
-
[serverKey]: {
|
|
4639
|
-
...localSettings.pinnedConversationsByServer?.[serverKey] ?? {},
|
|
4640
|
-
[agentId]: [...current, conversationId]
|
|
4641
|
-
}
|
|
4642
|
-
}
|
|
4643
|
-
});
|
|
4400
|
+
isAgentPinned(agentId) {
|
|
4401
|
+
return this.getPinnedAgents().includes(agentId);
|
|
4644
4402
|
}
|
|
4645
|
-
|
|
4646
|
-
|
|
4647
|
-
const serverKey = getCurrentServerKey(globalSettings);
|
|
4648
|
-
const raw = this.normalizeSettingsRecord(this.readJsonObjectSync(this.getLocalProjectSettingsPath(workingDirectory)));
|
|
4649
|
-
const localSettings = {
|
|
4650
|
-
...DEFAULT_LOCAL_PROJECT_SETTINGS,
|
|
4651
|
-
...raw
|
|
4652
|
-
};
|
|
4653
|
-
const current = localSettings.pinnedConversationsByServer?.[serverKey]?.[agentId] ?? [];
|
|
4654
|
-
this.writeLocalProjectSettingsRecordSync(workingDirectory, {
|
|
4655
|
-
...raw,
|
|
4656
|
-
pinnedConversationsByServer: {
|
|
4657
|
-
...localSettings.pinnedConversationsByServer ?? {},
|
|
4658
|
-
[serverKey]: {
|
|
4659
|
-
...localSettings.pinnedConversationsByServer?.[serverKey] ?? {},
|
|
4660
|
-
[agentId]: current.filter((id) => id !== conversationId)
|
|
4661
|
-
}
|
|
4662
|
-
}
|
|
4663
|
-
});
|
|
4403
|
+
pinAgent(agentId) {
|
|
4404
|
+
this.upsertAgentSettings(agentId, { pinned: true });
|
|
4664
4405
|
}
|
|
4665
|
-
|
|
4666
|
-
this.
|
|
4667
|
-
this.unpinConversationGlobal(agentId, conversationId);
|
|
4406
|
+
unpinAgent(agentId) {
|
|
4407
|
+
this.upsertAgentSettings(agentId, { pinned: false });
|
|
4668
4408
|
}
|
|
4669
4409
|
getGlobalProfiles() {
|
|
4670
4410
|
return this.getSettings().profiles || {};
|
|
@@ -4673,100 +4413,17 @@ class SettingsManager {
|
|
|
4673
4413
|
const localSettings = this.getLocalProjectSettings(workingDirectory);
|
|
4674
4414
|
return localSettings.profiles || {};
|
|
4675
4415
|
}
|
|
4676
|
-
getMergedProfiles(
|
|
4677
|
-
|
|
4678
|
-
return merged.map(({ agentId, isLocal }) => ({
|
|
4416
|
+
getMergedProfiles(_workingDirectory = process.cwd()) {
|
|
4417
|
+
return this.getPinnedAgents().map((agentId) => ({
|
|
4679
4418
|
name: "",
|
|
4680
4419
|
agentId,
|
|
4681
|
-
isLocal
|
|
4420
|
+
isLocal: false
|
|
4682
4421
|
}));
|
|
4683
4422
|
}
|
|
4684
|
-
pinBoth(agentId, workingDirectory = process.cwd()) {
|
|
4685
|
-
this.pinGlobal(agentId);
|
|
4686
|
-
this.pinLocal(agentId, workingDirectory);
|
|
4687
|
-
}
|
|
4688
|
-
saveProfile(_name, agentId, workingDirectory = process.cwd()) {
|
|
4689
|
-
this.pinBoth(agentId, workingDirectory);
|
|
4690
|
-
}
|
|
4691
|
-
pinLocal(agentId, workingDirectory = process.cwd()) {
|
|
4692
|
-
const globalSettings = this.getSettings();
|
|
4693
|
-
const serverKey = getCurrentServerKey(globalSettings);
|
|
4694
|
-
const localSettings = this.getLocalProjectSettings(workingDirectory);
|
|
4695
|
-
const localAgents = this.getLocalPinnedAgents(workingDirectory);
|
|
4696
|
-
if (!localAgents.includes(agentId)) {
|
|
4697
|
-
const newAgents = [...localAgents, agentId];
|
|
4698
|
-
const pinnedAgentsByServer = {
|
|
4699
|
-
...localSettings.pinnedAgentsByServer,
|
|
4700
|
-
[serverKey]: newAgents
|
|
4701
|
-
};
|
|
4702
|
-
this.updateLocalProjectSettings({
|
|
4703
|
-
pinnedAgentsByServer,
|
|
4704
|
-
pinnedAgents: newAgents
|
|
4705
|
-
}, workingDirectory);
|
|
4706
|
-
}
|
|
4707
|
-
}
|
|
4708
|
-
unpinLocal(agentId, workingDirectory = process.cwd()) {
|
|
4709
|
-
const globalSettings = this.getSettings();
|
|
4710
|
-
const serverKey = getCurrentServerKey(globalSettings);
|
|
4711
|
-
const localSettings = this.getLocalProjectSettings(workingDirectory);
|
|
4712
|
-
const localAgents = this.getLocalPinnedAgents(workingDirectory);
|
|
4713
|
-
const newAgents = localAgents.filter((id) => id !== agentId);
|
|
4714
|
-
const pinnedAgentsByServer = {
|
|
4715
|
-
...localSettings.pinnedAgentsByServer,
|
|
4716
|
-
[serverKey]: newAgents
|
|
4717
|
-
};
|
|
4718
|
-
this.updateLocalProjectSettings({
|
|
4719
|
-
pinnedAgentsByServer,
|
|
4720
|
-
pinnedAgents: newAgents
|
|
4721
|
-
}, workingDirectory);
|
|
4722
|
-
}
|
|
4723
4423
|
shouldCreateDefaultAgents() {
|
|
4724
4424
|
const settings = this.getSettings();
|
|
4725
4425
|
return settings.createDefaultAgents !== false;
|
|
4726
4426
|
}
|
|
4727
|
-
pinGlobal(agentId) {
|
|
4728
|
-
const settings = this.getSettings();
|
|
4729
|
-
const serverKey = getCurrentServerKey(settings);
|
|
4730
|
-
const globalAgents = this.getGlobalPinnedAgents();
|
|
4731
|
-
if (!globalAgents.includes(agentId)) {
|
|
4732
|
-
const newAgents = [...globalAgents, agentId];
|
|
4733
|
-
const pinnedAgentsByServer = {
|
|
4734
|
-
...settings.pinnedAgentsByServer,
|
|
4735
|
-
[serverKey]: newAgents
|
|
4736
|
-
};
|
|
4737
|
-
this.updateSettings({
|
|
4738
|
-
pinnedAgentsByServer,
|
|
4739
|
-
pinnedAgents: newAgents
|
|
4740
|
-
});
|
|
4741
|
-
}
|
|
4742
|
-
}
|
|
4743
|
-
unpinGlobal(agentId) {
|
|
4744
|
-
const settings = this.getSettings();
|
|
4745
|
-
const serverKey = getCurrentServerKey(settings);
|
|
4746
|
-
const globalAgents = this.getGlobalPinnedAgents();
|
|
4747
|
-
const newAgents = globalAgents.filter((id) => id !== agentId);
|
|
4748
|
-
const pinnedAgentsByServer = {
|
|
4749
|
-
...settings.pinnedAgentsByServer,
|
|
4750
|
-
[serverKey]: newAgents
|
|
4751
|
-
};
|
|
4752
|
-
this.updateSettings({
|
|
4753
|
-
pinnedAgentsByServer,
|
|
4754
|
-
pinnedAgents: newAgents
|
|
4755
|
-
});
|
|
4756
|
-
}
|
|
4757
|
-
unpinBoth(agentId, workingDirectory = process.cwd()) {
|
|
4758
|
-
this.unpinLocal(agentId, workingDirectory);
|
|
4759
|
-
this.unpinGlobal(agentId);
|
|
4760
|
-
}
|
|
4761
|
-
deleteProfile(_name, _workingDirectory = process.cwd()) {
|
|
4762
|
-
console.warn("deleteProfile is deprecated, use unpinBoth(agentId) instead");
|
|
4763
|
-
}
|
|
4764
|
-
pinProfile(_name, agentId, workingDirectory = process.cwd()) {
|
|
4765
|
-
this.pinLocal(agentId, workingDirectory);
|
|
4766
|
-
}
|
|
4767
|
-
unpinProfile(_name, _workingDirectory = process.cwd()) {
|
|
4768
|
-
console.warn("unpinProfile is deprecated, use unpinLocal(agentId) instead");
|
|
4769
|
-
}
|
|
4770
4427
|
getListenerEnvName(workingDirectory = process.cwd()) {
|
|
4771
4428
|
try {
|
|
4772
4429
|
const localSettings = this.getLocalProjectSettings(workingDirectory);
|
|
@@ -5062,7 +4719,13 @@ var init_settings_manager = __esm(() => {
|
|
|
5062
4719
|
init_debug();
|
|
5063
4720
|
init_fs();
|
|
5064
4721
|
init_secrets();
|
|
5065
|
-
OBSOLETE_SETTINGS_KEYS = [
|
|
4722
|
+
OBSOLETE_SETTINGS_KEYS = [
|
|
4723
|
+
"reflectionBehavior",
|
|
4724
|
+
"enableSleeptime",
|
|
4725
|
+
"pinnedAgents",
|
|
4726
|
+
"pinnedAgentsByServer",
|
|
4727
|
+
"pinnedConversationsByServer"
|
|
4728
|
+
];
|
|
5066
4729
|
DEFAULT_SETTINGS = {
|
|
5067
4730
|
lastAgent: null,
|
|
5068
4731
|
tokenStreaming: false,
|
|
@@ -5094,7 +4757,7 @@ var package_default;
|
|
|
5094
4757
|
var init_package = __esm(() => {
|
|
5095
4758
|
package_default = {
|
|
5096
4759
|
name: "@letta-ai/letta-code",
|
|
5097
|
-
version: "0.27.
|
|
4760
|
+
version: "0.27.14",
|
|
5098
4761
|
description: "Letta Code is a CLI tool for interacting with stateful Letta agents from the terminal.",
|
|
5099
4762
|
type: "module",
|
|
5100
4763
|
packageManager: "bun@1.3.0",
|
|
@@ -140583,9 +140246,9 @@ var init_pi_provider_registry = __esm(() => {
|
|
|
140583
140246
|
import {
|
|
140584
140247
|
chmodSync,
|
|
140585
140248
|
existsSync as existsSync3,
|
|
140586
|
-
mkdirSync as
|
|
140249
|
+
mkdirSync as mkdirSync3,
|
|
140587
140250
|
readFileSync as readFileSync3,
|
|
140588
|
-
writeFileSync
|
|
140251
|
+
writeFileSync
|
|
140589
140252
|
} from "node:fs";
|
|
140590
140253
|
import { dirname as dirname2, join as join4 } from "node:path";
|
|
140591
140254
|
function isLocalProviderTypeSupported(providerType) {
|
|
@@ -140609,8 +140272,8 @@ function readAuthFile(storageDir) {
|
|
|
140609
140272
|
}
|
|
140610
140273
|
function writeAuthFile(file3, storageDir) {
|
|
140611
140274
|
const path5 = getLocalProviderAuthPath(storageDir);
|
|
140612
|
-
|
|
140613
|
-
|
|
140275
|
+
mkdirSync3(dirname2(path5), { recursive: true, mode: 448 });
|
|
140276
|
+
writeFileSync(path5, `${JSON.stringify(file3, null, 2)}
|
|
140614
140277
|
`, {
|
|
140615
140278
|
encoding: "utf8",
|
|
140616
140279
|
mode: 384
|
|
@@ -154025,7 +153688,7 @@ __export(exports_accounts, {
|
|
|
154025
153688
|
__testOverrideLoadChannelAccounts: () => __testOverrideLoadChannelAccounts,
|
|
154026
153689
|
LEGACY_CHANNEL_ACCOUNT_ID: () => LEGACY_CHANNEL_ACCOUNT_ID
|
|
154027
153690
|
});
|
|
154028
|
-
import { existsSync as existsSync7, mkdirSync as
|
|
153691
|
+
import { existsSync as existsSync7, mkdirSync as mkdirSync4, readFileSync as readFileSync6, writeFileSync as writeFileSync2 } from "node:fs";
|
|
154029
153692
|
function isSecretPlaceholder(value) {
|
|
154030
153693
|
return value === SECRET_PRESENT_PLACEHOLDER;
|
|
154031
153694
|
}
|
|
@@ -154380,8 +154043,8 @@ function saveChannelAccounts(channelId) {
|
|
|
154380
154043
|
return;
|
|
154381
154044
|
}
|
|
154382
154045
|
const dir = getChannelDir(channelId);
|
|
154383
|
-
|
|
154384
|
-
|
|
154046
|
+
mkdirSync4(dir, { recursive: true });
|
|
154047
|
+
writeFileSync2(getChannelAccountsPath(channelId), `${JSON.stringify({ accounts: writeAccounts }, null, 2)}
|
|
154385
154048
|
`, "utf-8");
|
|
154386
154049
|
}
|
|
154387
154050
|
async function flushPendingChannelSecretWrites() {
|
|
@@ -156609,7 +156272,7 @@ var init_adapter3 = __esm(() => {
|
|
|
156609
156272
|
});
|
|
156610
156273
|
|
|
156611
156274
|
// src/channels/targets.ts
|
|
156612
|
-
import { existsSync as existsSync8, mkdirSync as
|
|
156275
|
+
import { existsSync as existsSync8, mkdirSync as mkdirSync5, readFileSync as readFileSync7, writeFileSync as writeFileSync3 } from "node:fs";
|
|
156613
156276
|
function getStore2(channelId) {
|
|
156614
156277
|
let store = stores2.get(channelId);
|
|
156615
156278
|
if (!store) {
|
|
@@ -156641,8 +156304,8 @@ function saveTargetStore(channelId) {
|
|
|
156641
156304
|
return;
|
|
156642
156305
|
}
|
|
156643
156306
|
const dir = getChannelDir(channelId);
|
|
156644
|
-
|
|
156645
|
-
|
|
156307
|
+
mkdirSync5(dir, { recursive: true });
|
|
156308
|
+
writeFileSync3(getChannelTargetsPath(channelId), `${JSON.stringify(getStore2(channelId), null, 2)}
|
|
156646
156309
|
`, "utf-8");
|
|
156647
156310
|
}
|
|
156648
156311
|
function listChannelTargets(channelId, accountId) {
|
|
@@ -157231,12 +156894,12 @@ function formatDiscordDeliveryError(error54) {
|
|
|
157231
156894
|
|
|
157232
156895
|
// src/channels/discord/media.ts
|
|
157233
156896
|
import { randomUUID as randomUUID10 } from "node:crypto";
|
|
157234
|
-
import { mkdirSync as
|
|
156897
|
+
import { mkdirSync as mkdirSync6 } from "node:fs";
|
|
157235
156898
|
import { writeFile as writeFile7 } from "node:fs/promises";
|
|
157236
156899
|
import { tmpdir as tmpdir2 } from "node:os";
|
|
157237
156900
|
import { join as join12 } from "node:path";
|
|
157238
156901
|
function ensureAttachmentsDir() {
|
|
157239
|
-
|
|
156902
|
+
mkdirSync6(DISCORD_ATTACHMENTS_DIR, { recursive: true });
|
|
157240
156903
|
return DISCORD_ATTACHMENTS_DIR;
|
|
157241
156904
|
}
|
|
157242
156905
|
function sanitizeDiscordPathSegment(input) {
|
|
@@ -158774,7 +158437,7 @@ var init_state = __esm(() => {
|
|
|
158774
158437
|
});
|
|
158775
158438
|
|
|
158776
158439
|
// src/channels/whatsapp/session.ts
|
|
158777
|
-
import { mkdirSync as
|
|
158440
|
+
import { mkdirSync as mkdirSync7, readFileSync as readFileSync8, rmSync as rmSync2, writeFileSync as writeFileSync4 } from "node:fs";
|
|
158778
158441
|
import { homedir as homedir8 } from "node:os";
|
|
158779
158442
|
import { join as join14 } from "node:path";
|
|
158780
158443
|
function shouldDropLine(line) {
|
|
@@ -158867,8 +158530,8 @@ function acquireWhatsAppSessionLease(accountId, options3 = {}) {
|
|
|
158867
158530
|
}
|
|
158868
158531
|
for (let attempt = 0;attempt < 2; attempt += 1) {
|
|
158869
158532
|
try {
|
|
158870
|
-
|
|
158871
|
-
|
|
158533
|
+
mkdirSync7(lockDir);
|
|
158534
|
+
writeFileSync4(join14(lockDir, "owner.json"), `${JSON.stringify({
|
|
158872
158535
|
accountId,
|
|
158873
158536
|
pid,
|
|
158874
158537
|
command: process.argv.join(" "),
|
|
@@ -158946,7 +158609,7 @@ function renderQrTerminal(qrMod, input) {
|
|
|
158946
158609
|
async function createWhatsAppSocket(params) {
|
|
158947
158610
|
installWhatsAppConsoleFilters();
|
|
158948
158611
|
const authDir = getWhatsAppAuthDir(params.accountId);
|
|
158949
|
-
|
|
158612
|
+
mkdirSync7(authDir, { recursive: true });
|
|
158950
158613
|
const sessionLease = acquireWhatsAppSessionLease(params.accountId);
|
|
158951
158614
|
setWhatsAppConnectionState(params.accountId, { status: "connecting" });
|
|
158952
158615
|
try {
|
|
@@ -160215,7 +159878,7 @@ var init_client5 = __esm(() => {
|
|
|
160215
159878
|
import { randomUUID as randomUUID15 } from "node:crypto";
|
|
160216
159879
|
import {
|
|
160217
159880
|
copyFileSync,
|
|
160218
|
-
mkdirSync as
|
|
159881
|
+
mkdirSync as mkdirSync8,
|
|
160219
159882
|
readdirSync as readdirSync2,
|
|
160220
159883
|
readFileSync as readFileSync9,
|
|
160221
159884
|
realpathSync as realpathSync2,
|
|
@@ -160588,7 +160251,7 @@ function copySignalAttachment(params) {
|
|
|
160588
160251
|
const mimeType = normalizeSignalMimeType(params.attachment.contentType) ?? inferSignalMimeTypeFromName(fileName);
|
|
160589
160252
|
const kind = inferSignalAttachmentKind({ mimeType, fileName });
|
|
160590
160253
|
const inboundDir = join15(getChannelDir("signal"), "inbound", sanitizeSignalPathSegment(params.accountId));
|
|
160591
|
-
|
|
160254
|
+
mkdirSync8(inboundDir, { recursive: true });
|
|
160592
160255
|
const localPath = join15(inboundDir, `${Date.now()}-${randomUUID15()}-${sanitizeSignalPathSegment(fileName)}`);
|
|
160593
160256
|
copyFileSync(params.sourcePath, localPath);
|
|
160594
160257
|
const attachment = {
|
|
@@ -162288,7 +161951,7 @@ __export(exports_pairing, {
|
|
|
162288
161951
|
__testOverrideSavePairingStore: () => __testOverrideSavePairingStore,
|
|
162289
161952
|
__testOverrideLoadPairingStore: () => __testOverrideLoadPairingStore
|
|
162290
161953
|
});
|
|
162291
|
-
import { existsSync as existsSync11, mkdirSync as
|
|
161954
|
+
import { existsSync as existsSync11, mkdirSync as mkdirSync9, readFileSync as readFileSync11, writeFileSync as writeFileSync5 } from "node:fs";
|
|
162292
161955
|
function normalizeAccountId2(accountId) {
|
|
162293
161956
|
return accountId ?? LEGACY_CHANNEL_ACCOUNT_ID;
|
|
162294
161957
|
}
|
|
@@ -162334,8 +161997,8 @@ function savePairingStore(channelId) {
|
|
|
162334
161997
|
return;
|
|
162335
161998
|
}
|
|
162336
161999
|
const dir = getChannelDir(channelId);
|
|
162337
|
-
|
|
162338
|
-
|
|
162000
|
+
mkdirSync9(dir, { recursive: true });
|
|
162001
|
+
writeFileSync5(getChannelPairingPath(channelId), `${JSON.stringify(store, null, 2)}
|
|
162339
162002
|
`, "utf-8");
|
|
162340
162003
|
}
|
|
162341
162004
|
function generateCode(length = 6) {
|
|
@@ -162454,7 +162117,7 @@ var init_pairing = __esm(() => {
|
|
|
162454
162117
|
});
|
|
162455
162118
|
|
|
162456
162119
|
// src/channels/pending-control-requests.ts
|
|
162457
|
-
import { existsSync as existsSync12, mkdirSync as
|
|
162120
|
+
import { existsSync as existsSync12, mkdirSync as mkdirSync10, readFileSync as readFileSync12, writeFileSync as writeFileSync6 } from "node:fs";
|
|
162458
162121
|
import { dirname as dirname5 } from "node:path";
|
|
162459
162122
|
function cloneEvent(event2) {
|
|
162460
162123
|
return structuredClone(event2);
|
|
@@ -162504,8 +162167,8 @@ function saveStore() {
|
|
|
162504
162167
|
return;
|
|
162505
162168
|
}
|
|
162506
162169
|
const storePath = getPendingChannelControlRequestsPath();
|
|
162507
|
-
|
|
162508
|
-
|
|
162170
|
+
mkdirSync10(dirname5(storePath), { recursive: true });
|
|
162171
|
+
writeFileSync6(storePath, `${JSON.stringify(snapshot, null, 2)}
|
|
162509
162172
|
`, "utf-8");
|
|
162510
162173
|
}
|
|
162511
162174
|
function listPendingControlRequests() {
|
|
@@ -162588,7 +162251,7 @@ __export(exports_routing, {
|
|
|
162588
162251
|
__testOverrideSaveRoutes: () => __testOverrideSaveRoutes,
|
|
162589
162252
|
__testOverrideLoadRoutes: () => __testOverrideLoadRoutes
|
|
162590
162253
|
});
|
|
162591
|
-
import { existsSync as existsSync13, mkdirSync as
|
|
162254
|
+
import { existsSync as existsSync13, mkdirSync as mkdirSync11, readFileSync as readFileSync13, writeFileSync as writeFileSync7 } from "node:fs";
|
|
162592
162255
|
function normalizeAccountId3(accountId) {
|
|
162593
162256
|
return accountId ?? LEGACY_CHANNEL_ACCOUNT_ID;
|
|
162594
162257
|
}
|
|
@@ -162666,10 +162329,10 @@ function saveRoutes(channelId) {
|
|
|
162666
162329
|
return;
|
|
162667
162330
|
}
|
|
162668
162331
|
const dir = getChannelDir(channelId);
|
|
162669
|
-
|
|
162332
|
+
mkdirSync11(dir, { recursive: true });
|
|
162670
162333
|
const routes = getRoutesForChannel(channelId);
|
|
162671
162334
|
const data = { routes };
|
|
162672
|
-
|
|
162335
|
+
writeFileSync7(getChannelRoutingPath(channelId), `${JSON.stringify(data, null, 2)}
|
|
162673
162336
|
`, "utf-8");
|
|
162674
162337
|
}
|
|
162675
162338
|
function getRoute(channel, chatId, accountId, threadId) {
|
|
@@ -164374,16 +164037,14 @@ class ChannelRegistry {
|
|
|
164374
164037
|
updatedAt: now
|
|
164375
164038
|
};
|
|
164376
164039
|
addRoute(msg.channel, route);
|
|
164377
|
-
|
|
164378
|
-
|
|
164379
|
-
|
|
164380
|
-
|
|
164381
|
-
|
|
164382
|
-
|
|
164383
|
-
|
|
164384
|
-
|
|
164385
|
-
});
|
|
164386
|
-
}
|
|
164040
|
+
this.eventHandler?.({
|
|
164041
|
+
type: "discord_conversation_created",
|
|
164042
|
+
channelId: "discord",
|
|
164043
|
+
accountId: config3.accountId,
|
|
164044
|
+
agentId: config3.agentId,
|
|
164045
|
+
conversationId,
|
|
164046
|
+
defaultPermissionMode: config3.defaultPermissionMode
|
|
164047
|
+
});
|
|
164387
164048
|
return route;
|
|
164388
164049
|
}
|
|
164389
164050
|
async ensureDiscordRoute(adapter, msg, config3) {
|
|
@@ -169383,9 +169044,9 @@ __export(exports_process_manager, {
|
|
|
169383
169044
|
import {
|
|
169384
169045
|
appendFileSync as appendFileSync2,
|
|
169385
169046
|
chmodSync as chmodSync2,
|
|
169386
|
-
mkdirSync as
|
|
169047
|
+
mkdirSync as mkdirSync12,
|
|
169387
169048
|
mkdtempSync as mkdtempSync2,
|
|
169388
|
-
writeFileSync as
|
|
169049
|
+
writeFileSync as writeFileSync8
|
|
169389
169050
|
} from "node:fs";
|
|
169390
169051
|
import { tmpdir as tmpdir3 } from "node:os";
|
|
169391
169052
|
import { join as join17 } from "node:path";
|
|
@@ -169541,7 +169202,7 @@ function __resetBackgroundOutputDirForTests() {
|
|
|
169541
169202
|
backgroundOutputDir = undefined;
|
|
169542
169203
|
}
|
|
169543
169204
|
function ensureBackgroundOutputDir(dir) {
|
|
169544
|
-
|
|
169205
|
+
mkdirSync12(dir, { recursive: true, mode: 448 });
|
|
169545
169206
|
if (!process.env.LETTA_SCRATCHPAD) {
|
|
169546
169207
|
chmodSync2(dir, 448);
|
|
169547
169208
|
}
|
|
@@ -169550,7 +169211,7 @@ function createBackgroundOutputFile(id2) {
|
|
|
169550
169211
|
const dir = getBackgroundOutputDir();
|
|
169551
169212
|
ensureBackgroundOutputDir(dir);
|
|
169552
169213
|
const filePath = join17(dir, `${id2}.log`);
|
|
169553
|
-
|
|
169214
|
+
writeFileSync8(filePath, "", { mode: 384 });
|
|
169554
169215
|
chmodSync2(filePath, 384);
|
|
169555
169216
|
return filePath;
|
|
169556
169217
|
}
|
|
@@ -169581,7 +169242,7 @@ import {
|
|
|
169581
169242
|
chmodSync as chmodSync3,
|
|
169582
169243
|
createWriteStream as createWriteStream2,
|
|
169583
169244
|
existsSync as existsSync15,
|
|
169584
|
-
mkdirSync as
|
|
169245
|
+
mkdirSync as mkdirSync13,
|
|
169585
169246
|
readdirSync as readdirSync4,
|
|
169586
169247
|
renameSync,
|
|
169587
169248
|
rmSync as rmSync3
|
|
@@ -169785,14 +169446,14 @@ async function downloadRipgrep() {
|
|
|
169785
169446
|
throw new Error(`Unsupported platform: ${plat}/${architecture}`);
|
|
169786
169447
|
}
|
|
169787
169448
|
const toolsDir = getManagedToolsDir();
|
|
169788
|
-
|
|
169449
|
+
mkdirSync13(toolsDir, { recursive: true });
|
|
169789
169450
|
const downloadUrl = `https://github.com/${config3.repo}/releases/download/${config3.tagPrefix}${version2}/${assetName}`;
|
|
169790
169451
|
const archivePath = join18(toolsDir, assetName);
|
|
169791
169452
|
const binaryFileName = binaryName(config3);
|
|
169792
169453
|
const binaryPath = join18(toolsDir, binaryFileName);
|
|
169793
169454
|
await downloadFile2(downloadUrl, archivePath);
|
|
169794
169455
|
const extractDir = join18(toolsDir, `extract_tmp_${config3.binaryName}_${process.pid}_${Date.now()}_${Math.random().toString(36).slice(2, 10)}`);
|
|
169795
|
-
|
|
169456
|
+
mkdirSync13(extractDir, { recursive: true });
|
|
169796
169457
|
try {
|
|
169797
169458
|
if (assetName.endsWith(".tar.gz")) {
|
|
169798
169459
|
extractTarGzArchive(archivePath, extractDir, assetName);
|
|
@@ -169900,7 +169561,7 @@ __export(exports_shell_env, {
|
|
|
169900
169561
|
getShellEnv: () => getShellEnv,
|
|
169901
169562
|
ensureLettaShimDir: () => ensureLettaShimDir
|
|
169902
169563
|
});
|
|
169903
|
-
import { mkdirSync as
|
|
169564
|
+
import { mkdirSync as mkdirSync14, writeFileSync as writeFileSync9 } from "node:fs";
|
|
169904
169565
|
import { createRequire as createRequire4 } from "node:module";
|
|
169905
169566
|
import { tmpdir as tmpdir4 } from "node:os";
|
|
169906
169567
|
import * as path8 from "node:path";
|
|
@@ -169988,19 +169649,19 @@ function ensureLettaShimDir(invocation) {
|
|
|
169988
169649
|
if (!invocation.command)
|
|
169989
169650
|
return null;
|
|
169990
169651
|
const shimDir = path8.join(tmpdir4(), "letta-code-shell-shim");
|
|
169991
|
-
|
|
169652
|
+
mkdirSync14(shimDir, { recursive: true });
|
|
169992
169653
|
if (process.platform === "win32") {
|
|
169993
169654
|
const cmdPath = path8.join(shimDir, "letta.cmd");
|
|
169994
169655
|
const quotedCommand = `"${invocation.command.replaceAll('"', '""')}"`;
|
|
169995
169656
|
const quotedArgs = invocation.args.map((arg) => `"${arg.replaceAll('"', '""')}"`).join(" ");
|
|
169996
|
-
|
|
169657
|
+
writeFileSync9(cmdPath, `@echo off\r
|
|
169997
169658
|
${quotedCommand} ${quotedArgs} %*\r
|
|
169998
169659
|
`);
|
|
169999
169660
|
return shimDir;
|
|
170000
169661
|
}
|
|
170001
169662
|
const shimPath = path8.join(shimDir, "letta");
|
|
170002
169663
|
const commandWithArgs = [invocation.command, ...invocation.args].map(shellEscape).join(" ");
|
|
170003
|
-
|
|
169664
|
+
writeFileSync9(shimPath, `#!/bin/sh
|
|
170004
169665
|
exec ${commandWithArgs} "$@"
|
|
170005
169666
|
`, {
|
|
170006
169667
|
mode: 493
|
|
@@ -171116,6 +170777,15 @@ function setConversationWorkingDirectory(runtime, agentId, conversationId, worki
|
|
|
171116
170777
|
}
|
|
171117
170778
|
persistCwdMap(runtime.workingDirectoryByConversation);
|
|
171118
170779
|
}
|
|
170780
|
+
function seedConversationWorkingDirectory(runtime, agentId, conversationId, workingDirectory) {
|
|
170781
|
+
const scopeKey = getWorkingDirectoryScopeKey(agentId, conversationId);
|
|
170782
|
+
if (runtime.workingDirectoryByConversation.has(scopeKey)) {
|
|
170783
|
+
return false;
|
|
170784
|
+
}
|
|
170785
|
+
runtime.workingDirectoryByConversation.set(scopeKey, workingDirectory);
|
|
170786
|
+
persistCwdMap(runtime.workingDirectoryByConversation);
|
|
170787
|
+
return true;
|
|
170788
|
+
}
|
|
171119
170789
|
var init_cwd = __esm(() => {
|
|
171120
170790
|
init_remote_settings();
|
|
171121
170791
|
});
|
|
@@ -171802,7 +171472,7 @@ function getListenerTransportKind(transport) {
|
|
|
171802
171472
|
var init_transport = () => {};
|
|
171803
171473
|
|
|
171804
171474
|
// src/websocket/listener/protocol-outbound.ts
|
|
171805
|
-
import { appendFileSync as appendFileSync3, mkdirSync as
|
|
171475
|
+
import { appendFileSync as appendFileSync3, mkdirSync as mkdirSync16 } from "node:fs";
|
|
171806
171476
|
import { dirname as dirname8 } from "node:path";
|
|
171807
171477
|
import { performance as performance2 } from "node:perf_hooks";
|
|
171808
171478
|
function getProtocolPerfKey(message) {
|
|
@@ -171853,7 +171523,7 @@ function writeProtocolPerfFile(record5, fallbackLine) {
|
|
|
171853
171523
|
try {
|
|
171854
171524
|
const dir = dirname8(filePath);
|
|
171855
171525
|
if (protocolPerfFileDirEnsured !== dir) {
|
|
171856
|
-
|
|
171526
|
+
mkdirSync16(dir, { recursive: true });
|
|
171857
171527
|
protocolPerfFileDirEnsured = dir;
|
|
171858
171528
|
}
|
|
171859
171529
|
appendFileSync3(filePath, `${JSON.stringify(record5)}
|
|
@@ -172046,7 +171716,7 @@ function buildDeviceStatus(runtime, params) {
|
|
|
172046
171716
|
pending_control_requests: interruptedCacheActive ? [] : getPendingControlRequests(listener, scope),
|
|
172047
171717
|
experiments: experimentManager.list(),
|
|
172048
171718
|
memory_directory: scopedAgentId ? getScopedMemoryFilesystemRoot(scopedAgentId) : null,
|
|
172049
|
-
|
|
171719
|
+
...params === undefined ? {
|
|
172050
171720
|
cwd_map: Object.fromEntries(listener.workingDirectoryByConversation),
|
|
172051
171721
|
boot_working_directory: listener.bootWorkingDirectory
|
|
172052
171722
|
} : {},
|
|
@@ -177734,12 +177404,12 @@ __export(exports_image_resize_magick, {
|
|
|
177734
177404
|
resizeImageIfNeeded: () => resizeImageIfNeeded
|
|
177735
177405
|
});
|
|
177736
177406
|
import { execSync } from "node:child_process";
|
|
177737
|
-
import { readFileSync as readFileSync17, unlinkSync as unlinkSync3, writeFileSync as
|
|
177407
|
+
import { readFileSync as readFileSync17, unlinkSync as unlinkSync3, writeFileSync as writeFileSync11 } from "node:fs";
|
|
177738
177408
|
import { tmpdir as tmpdir5 } from "node:os";
|
|
177739
177409
|
import { join as join24 } from "node:path";
|
|
177740
177410
|
async function getImageDimensions(buffer) {
|
|
177741
177411
|
const tempInput = join24(tmpdir5(), `image-${Date.now()}-${Math.random().toString(36).slice(2)}.tmp`);
|
|
177742
|
-
|
|
177412
|
+
writeFileSync11(tempInput, buffer);
|
|
177743
177413
|
try {
|
|
177744
177414
|
const output = execSync(`magick identify -format "%w %h %m" "${tempInput}"`, {
|
|
177745
177415
|
encoding: "utf-8"
|
|
@@ -177770,7 +177440,7 @@ async function compressToFitByteLimit(buffer, currentWidth, currentHeight) {
|
|
|
177770
177440
|
return null;
|
|
177771
177441
|
}
|
|
177772
177442
|
const tempInput = join24(tmpdir5(), `compress-input-${Date.now()}-${Math.random().toString(36).slice(2)}.tmp`);
|
|
177773
|
-
|
|
177443
|
+
writeFileSync11(tempInput, buffer);
|
|
177774
177444
|
try {
|
|
177775
177445
|
const qualities = [85, 70, 55, 40];
|
|
177776
177446
|
for (const quality of qualities) {
|
|
@@ -177825,7 +177495,7 @@ async function resizeImageIfNeeded(buffer, inputMediaType) {
|
|
|
177825
177495
|
return buildVerifiedResizeResult(buffer, inputMediaType, false, "passthrough image output");
|
|
177826
177496
|
}
|
|
177827
177497
|
const tempInput = join24(tmpdir5(), `resize-input-${Date.now()}-${Math.random().toString(36).slice(2)}.tmp`);
|
|
177828
|
-
|
|
177498
|
+
writeFileSync11(tempInput, buffer);
|
|
177829
177499
|
try {
|
|
177830
177500
|
if (needsResize) {
|
|
177831
177501
|
const tempOutput2 = join24(tmpdir5(), `resize-output-${Date.now()}-${Math.random().toString(36).slice(2)}`);
|
|
@@ -201475,7 +201145,7 @@ __export(exports_memory_filesystem, {
|
|
|
201475
201145
|
MEMORY_FS_MEMORY_DIR: () => MEMORY_FS_MEMORY_DIR,
|
|
201476
201146
|
MEMORY_FS_AGENTS_DIR: () => MEMORY_FS_AGENTS_DIR
|
|
201477
201147
|
});
|
|
201478
|
-
import { existsSync as existsSync25, mkdirSync as
|
|
201148
|
+
import { existsSync as existsSync25, mkdirSync as mkdirSync17 } from "node:fs";
|
|
201479
201149
|
import { homedir as homedir16 } from "node:os";
|
|
201480
201150
|
import { join as join30, resolve as resolve29 } from "node:path";
|
|
201481
201151
|
function getMemoryFilesystemRoot(agentId, homeDir = homedir16()) {
|
|
@@ -201519,10 +201189,10 @@ function ensureMemoryFilesystemDirs(agentId, homeDir = homedir16()) {
|
|
|
201519
201189
|
const root = getMemoryFilesystemRoot(agentId, homeDir);
|
|
201520
201190
|
const systemDir = getMemorySystemDir(agentId, homeDir);
|
|
201521
201191
|
if (!existsSync25(root)) {
|
|
201522
|
-
|
|
201192
|
+
mkdirSync17(root, { recursive: true });
|
|
201523
201193
|
}
|
|
201524
201194
|
if (!existsSync25(systemDir)) {
|
|
201525
|
-
|
|
201195
|
+
mkdirSync17(systemDir, { recursive: true });
|
|
201526
201196
|
}
|
|
201527
201197
|
}
|
|
201528
201198
|
async function hydrateMemfsSettingFromAgent(agent2) {
|
|
@@ -201854,11 +201524,11 @@ import { execFile as execFileCb } from "node:child_process";
|
|
|
201854
201524
|
import {
|
|
201855
201525
|
chmodSync as chmodSync4,
|
|
201856
201526
|
existsSync as existsSync26,
|
|
201857
|
-
mkdirSync as
|
|
201527
|
+
mkdirSync as mkdirSync18,
|
|
201858
201528
|
readFileSync as readFileSync19,
|
|
201859
201529
|
renameSync as renameSync2,
|
|
201860
201530
|
rmSync as rmSync4,
|
|
201861
|
-
writeFileSync as
|
|
201531
|
+
writeFileSync as writeFileSync12
|
|
201862
201532
|
} from "node:fs";
|
|
201863
201533
|
import { homedir as homedir17, platform as platform3 } from "node:os";
|
|
201864
201534
|
import { dirname as dirname16, isAbsolute as isAbsolute20, join as join31 } from "node:path";
|
|
@@ -202093,14 +201763,14 @@ async function runGitWithRetry(cwd, args, token, options3) {
|
|
|
202093
201763
|
for (let attempt = 1;attempt <= attempts; attempt += 1) {
|
|
202094
201764
|
try {
|
|
202095
201765
|
if (!existsSync26(cwd)) {
|
|
202096
|
-
|
|
201766
|
+
mkdirSync18(cwd, { recursive: true });
|
|
202097
201767
|
}
|
|
202098
201768
|
return await runGit3(cwd, args, token, {
|
|
202099
201769
|
timeoutMs: options3?.timeoutMs
|
|
202100
201770
|
});
|
|
202101
201771
|
} catch (error54) {
|
|
202102
201772
|
if (isMissingCwdGitError(error54)) {
|
|
202103
|
-
|
|
201773
|
+
mkdirSync18(cwd, { recursive: true });
|
|
202104
201774
|
if (attempt < attempts) {
|
|
202105
201775
|
continue;
|
|
202106
201776
|
}
|
|
@@ -202131,7 +201801,7 @@ async function configureLocalCredentialHelper(dir, token) {
|
|
|
202131
201801
|
echo username=letta
|
|
202132
201802
|
echo password=${token}
|
|
202133
201803
|
`;
|
|
202134
|
-
|
|
201804
|
+
writeFileSync12(helperScriptPath, batchScript, "utf-8");
|
|
202135
201805
|
helper = formatGitCredentialHelperPath(helperScriptPath);
|
|
202136
201806
|
debugLog("memfs-git", `Wrote Windows credential helper script`);
|
|
202137
201807
|
} else {
|
|
@@ -202162,9 +201832,9 @@ function installPreCommitHook(dir) {
|
|
|
202162
201832
|
const hooksDir = join31(dir, ".git", "hooks");
|
|
202163
201833
|
const hookPath = join31(hooksDir, "pre-commit");
|
|
202164
201834
|
if (!existsSync26(hooksDir)) {
|
|
202165
|
-
|
|
201835
|
+
mkdirSync18(hooksDir, { recursive: true });
|
|
202166
201836
|
}
|
|
202167
|
-
|
|
201837
|
+
writeFileSync12(hookPath, PRE_COMMIT_HOOK_SCRIPT, "utf-8");
|
|
202168
201838
|
chmodSync4(hookPath, 493);
|
|
202169
201839
|
debugLog("memfs-git", "Installed pre-commit hook");
|
|
202170
201840
|
}
|
|
@@ -202172,9 +201842,9 @@ function installPostCommitHook(dir) {
|
|
|
202172
201842
|
const hooksDir = join31(dir, ".git", "hooks");
|
|
202173
201843
|
const hookPath = join31(hooksDir, "post-commit");
|
|
202174
201844
|
if (!existsSync26(hooksDir)) {
|
|
202175
|
-
|
|
201845
|
+
mkdirSync18(hooksDir, { recursive: true });
|
|
202176
201846
|
}
|
|
202177
|
-
|
|
201847
|
+
writeFileSync12(hookPath, POST_COMMIT_HOOK_SCRIPT, "utf-8");
|
|
202178
201848
|
chmodSync4(hookPath, 493);
|
|
202179
201849
|
debugLog("memfs-git", "Installed post-commit memory-repository hook");
|
|
202180
201850
|
}
|
|
@@ -202550,7 +202220,7 @@ async function getMemoryHeadRevision(memoryDir) {
|
|
|
202550
202220
|
}
|
|
202551
202221
|
}
|
|
202552
202222
|
async function initializeLocalMemoryRepo(params) {
|
|
202553
|
-
|
|
202223
|
+
mkdirSync18(params.memoryDir, { recursive: true });
|
|
202554
202224
|
if (!existsSync26(join31(params.memoryDir, ".git"))) {
|
|
202555
202225
|
await runGit3(params.memoryDir, ["init"]);
|
|
202556
202226
|
await runGit3(params.memoryDir, ["symbolic-ref", "HEAD", "refs/heads/main"]);
|
|
@@ -202572,8 +202242,8 @@ async function initializeLocalMemoryRepo(params) {
|
|
|
202572
202242
|
continue;
|
|
202573
202243
|
}
|
|
202574
202244
|
const fullPath = join31(params.memoryDir, relativePath);
|
|
202575
|
-
|
|
202576
|
-
|
|
202245
|
+
mkdirSync18(dirname16(fullPath), { recursive: true });
|
|
202246
|
+
writeFileSync12(fullPath, file3.content, "utf8");
|
|
202577
202247
|
pathspecs.push(relativePath);
|
|
202578
202248
|
}
|
|
202579
202249
|
if (pathspecs.length > 0) {
|
|
@@ -202599,7 +202269,7 @@ async function cloneMemoryRepo(agentId) {
|
|
|
202599
202269
|
const dir = getMemoryRepoDir(agentId);
|
|
202600
202270
|
debugLog("memfs-git", `Cloning ${url2} → ${dir}`);
|
|
202601
202271
|
if (!existsSync26(dir)) {
|
|
202602
|
-
|
|
202272
|
+
mkdirSync18(dir, { recursive: true });
|
|
202603
202273
|
await runGitWithRetry(dir, ["clone", url2, "."], token, {
|
|
202604
202274
|
operation: "clone memory repo",
|
|
202605
202275
|
timeoutMs: GIT_CLONE_TIMEOUT_MS
|
|
@@ -202610,7 +202280,7 @@ async function cloneMemoryRepo(agentId) {
|
|
|
202610
202280
|
if (existsSync26(tmpDir)) {
|
|
202611
202281
|
rmSync4(tmpDir, { recursive: true, force: true });
|
|
202612
202282
|
}
|
|
202613
|
-
|
|
202283
|
+
mkdirSync18(tmpDir, { recursive: true });
|
|
202614
202284
|
await runGitWithRetry(tmpDir, ["clone", url2, "."], token, {
|
|
202615
202285
|
operation: "clone memory repo (tmp migration)",
|
|
202616
202286
|
timeoutMs: GIT_CLONE_TIMEOUT_MS
|
|
@@ -203470,14 +203140,14 @@ import {
|
|
|
203470
203140
|
appendFileSync as appendFileSync4,
|
|
203471
203141
|
closeSync,
|
|
203472
203142
|
existsSync as existsSync27,
|
|
203473
|
-
mkdirSync as
|
|
203143
|
+
mkdirSync as mkdirSync19,
|
|
203474
203144
|
openSync,
|
|
203475
203145
|
readdirSync as readdirSync10,
|
|
203476
203146
|
readFileSync as readFileSync20,
|
|
203477
203147
|
readSync,
|
|
203478
203148
|
rmSync as rmSync5,
|
|
203479
203149
|
statSync as statSync8,
|
|
203480
|
-
writeFileSync as
|
|
203150
|
+
writeFileSync as writeFileSync13
|
|
203481
203151
|
} from "node:fs";
|
|
203482
203152
|
import { join as join32 } from "node:path";
|
|
203483
203153
|
function isStringArray2(value) {
|
|
@@ -203948,7 +203618,7 @@ function validateLocalTranscriptManifest(conversationDir, storageDir) {
|
|
|
203948
203618
|
return manifest;
|
|
203949
203619
|
}
|
|
203950
203620
|
function writeLocalTranscriptManifest(conversationDir, manifest = createLocalTranscriptManifest()) {
|
|
203951
|
-
|
|
203621
|
+
writeFileSync13(transcriptManifestPath(conversationDir), `${JSON.stringify(manifest, null, 2)}
|
|
203952
203622
|
`);
|
|
203953
203623
|
}
|
|
203954
203624
|
function numericSuffix(value, prefix) {
|
|
@@ -205367,8 +205037,8 @@ class LocalStore {
|
|
|
205367
205037
|
if (!agent2)
|
|
205368
205038
|
return;
|
|
205369
205039
|
const agentsDir = join32(this.storageDir, "agents");
|
|
205370
|
-
|
|
205371
|
-
|
|
205040
|
+
mkdirSync19(agentsDir, { recursive: true });
|
|
205041
|
+
writeFileSync13(join32(agentsDir, `${encodePathSegment(agentId)}.json`), `${JSON.stringify(agent2, null, 2)}
|
|
205372
205042
|
`);
|
|
205373
205043
|
}
|
|
205374
205044
|
projectAgent(record5) {
|
|
@@ -205386,8 +205056,8 @@ class LocalStore {
|
|
|
205386
205056
|
if (!conversation)
|
|
205387
205057
|
return;
|
|
205388
205058
|
const conversationDir = join32(this.storageDir, "conversations", encodePathSegment(key));
|
|
205389
|
-
|
|
205390
|
-
|
|
205059
|
+
mkdirSync19(conversationDir, { recursive: true });
|
|
205060
|
+
writeFileSync13(join32(conversationDir, "conversation.json"), `${JSON.stringify(conversation, null, 2)}
|
|
205391
205061
|
`);
|
|
205392
205062
|
this.recordConversationRecordMtime(key, conversationDir);
|
|
205393
205063
|
const messagesPath = transcriptMessagesPath(conversationDir);
|
|
@@ -205458,7 +205128,7 @@ class LocalStore {
|
|
|
205458
205128
|
if (messages.length === 0)
|
|
205459
205129
|
return;
|
|
205460
205130
|
const entries = localTranscriptSessionEntries(conversation, messages);
|
|
205461
|
-
|
|
205131
|
+
writeFileSync13(messagesPath, jsonl(entries));
|
|
205462
205132
|
this.resetPersistedSessionStateFromEntries(key, entries);
|
|
205463
205133
|
}
|
|
205464
205134
|
appendConversationSessionMessageEntry(key, conversation, messagesPath, message) {
|
|
@@ -205510,7 +205180,7 @@ class LocalStore {
|
|
|
205510
205180
|
ensureConversationTranscriptHeader(conversation, messagesPath) {
|
|
205511
205181
|
if (existsSync27(messagesPath) && statSync8(messagesPath).size > 0)
|
|
205512
205182
|
return;
|
|
205513
|
-
|
|
205183
|
+
writeFileSync13(messagesPath, `${JSON.stringify(createLocalTranscriptSessionHeader(conversation))}
|
|
205514
205184
|
`);
|
|
205515
205185
|
}
|
|
205516
205186
|
resetPersistedSessionState(key, messageFormat, transcript) {
|
|
@@ -205568,8 +205238,8 @@ class LocalStore {
|
|
|
205568
205238
|
if (!prompt)
|
|
205569
205239
|
return;
|
|
205570
205240
|
const conversationDir = join32(this.storageDir, "conversations", encodePathSegment(key));
|
|
205571
|
-
|
|
205572
|
-
|
|
205241
|
+
mkdirSync19(conversationDir, { recursive: true });
|
|
205242
|
+
writeFileSync13(join32(conversationDir, "system-prompt.json"), `${JSON.stringify(prompt, null, 2)}
|
|
205573
205243
|
`);
|
|
205574
205244
|
}
|
|
205575
205245
|
ensureConversation(conversationId, agentId) {
|
|
@@ -249118,7 +248788,7 @@ __export(exports_personality, {
|
|
|
249118
248788
|
DEFAULT_CREATE_AGENT_PERSONALITIES: () => DEFAULT_CREATE_AGENT_PERSONALITIES
|
|
249119
248789
|
});
|
|
249120
248790
|
import { execFile as execFileCb3 } from "node:child_process";
|
|
249121
|
-
import { existsSync as existsSync33, mkdirSync as
|
|
248791
|
+
import { existsSync as existsSync33, mkdirSync as mkdirSync21, readFileSync as readFileSync24, writeFileSync as writeFileSync14 } from "node:fs";
|
|
249122
248792
|
import { dirname as dirname18, join as join36 } from "node:path";
|
|
249123
248793
|
import { promisify as promisify7 } from "node:util";
|
|
249124
248794
|
function supportsOnboardingBlock2(personalityId) {
|
|
@@ -249433,8 +249103,8 @@ function applyPersonalityFiles(filesToUpdate) {
|
|
|
249433
249103
|
if (existingContent !== null && normalizeComparableContent(existingContent) === normalizeComparableContent(nextContent)) {
|
|
249434
249104
|
continue;
|
|
249435
249105
|
}
|
|
249436
|
-
|
|
249437
|
-
|
|
249106
|
+
mkdirSync21(dirname18(file3.absolutePath), { recursive: true });
|
|
249107
|
+
writeFileSync14(file3.absolutePath, nextContent, "utf-8");
|
|
249438
249108
|
changedPaths.push(file3.relativePath);
|
|
249439
249109
|
}
|
|
249440
249110
|
return changedPaths;
|
|
@@ -249646,7 +249316,7 @@ function isReflectionSubagentActive(subagents, agentId, conversationId) {
|
|
|
249646
249316
|
}
|
|
249647
249317
|
|
|
249648
249318
|
// src/utils/file-lock.ts
|
|
249649
|
-
import { open as open2, readFile as
|
|
249319
|
+
import { open as open2, readFile as readFile12, stat as stat9, unlink as unlink3 } from "node:fs/promises";
|
|
249650
249320
|
async function withFileLock(lockPath, fn, options3) {
|
|
249651
249321
|
const opts = { ...DEFAULT_OPTIONS, ...options3 };
|
|
249652
249322
|
const release = await acquireFileLock(lockPath, opts);
|
|
@@ -249700,7 +249370,7 @@ async function acquireFileLock(lockPath, opts) {
|
|
|
249700
249370
|
async function tryReapStaleLock(lockPath, staleMs) {
|
|
249701
249371
|
let raw2;
|
|
249702
249372
|
try {
|
|
249703
|
-
raw2 = await
|
|
249373
|
+
raw2 = await readFile12(lockPath, "utf-8");
|
|
249704
249374
|
} catch {
|
|
249705
249375
|
return true;
|
|
249706
249376
|
}
|
|
@@ -249757,7 +249427,7 @@ import {
|
|
|
249757
249427
|
appendFile,
|
|
249758
249428
|
mkdir as mkdir10,
|
|
249759
249429
|
readdir as readdir7,
|
|
249760
|
-
readFile as
|
|
249430
|
+
readFile as readFile13,
|
|
249761
249431
|
writeFile as writeFile12
|
|
249762
249432
|
} from "node:fs/promises";
|
|
249763
249433
|
import { homedir as homedir21 } from "node:os";
|
|
@@ -249800,7 +249470,7 @@ async function collectParentMemoryFiles(memoryDir) {
|
|
|
249800
249470
|
continue;
|
|
249801
249471
|
}
|
|
249802
249472
|
try {
|
|
249803
|
-
const content = await
|
|
249473
|
+
const content = await readFile13(entryPath, "utf-8");
|
|
249804
249474
|
const { frontmatter } = parseFrontmatter(content);
|
|
249805
249475
|
const description = typeof frontmatter.description === "string" ? frontmatter.description : undefined;
|
|
249806
249476
|
files.push({
|
|
@@ -250140,7 +249810,7 @@ async function ensurePaths(paths) {
|
|
|
250140
249810
|
}
|
|
250141
249811
|
async function readTranscriptLines(paths) {
|
|
250142
249812
|
try {
|
|
250143
|
-
const raw2 = await
|
|
249813
|
+
const raw2 = await readFile13(paths.transcriptPath, "utf-8");
|
|
250144
249814
|
return raw2.split(`
|
|
250145
249815
|
`).map((line) => line.trim()).filter((line) => line.length > 0);
|
|
250146
249816
|
} catch {
|
|
@@ -250213,7 +249883,7 @@ function buildUnreflectedStateFromTranscript(lines) {
|
|
|
250213
249883
|
async function readState(paths) {
|
|
250214
249884
|
let raw2 = null;
|
|
250215
249885
|
try {
|
|
250216
|
-
raw2 = await
|
|
249886
|
+
raw2 = await readFile13(paths.statePath, "utf-8");
|
|
250217
249887
|
} catch {
|
|
250218
249888
|
raw2 = null;
|
|
250219
249889
|
}
|
|
@@ -251545,12 +251215,12 @@ var init_parse_interval = __esm(() => {
|
|
|
251545
251215
|
import { randomBytes } from "node:crypto";
|
|
251546
251216
|
import {
|
|
251547
251217
|
existsSync as existsSync34,
|
|
251548
|
-
mkdirSync as
|
|
251218
|
+
mkdirSync as mkdirSync22,
|
|
251549
251219
|
readFileSync as readFileSync25,
|
|
251550
251220
|
renameSync as renameSync4,
|
|
251551
251221
|
rmSync as rmSync7,
|
|
251552
251222
|
statSync as statSync12,
|
|
251553
|
-
writeFileSync as
|
|
251223
|
+
writeFileSync as writeFileSync15
|
|
251554
251224
|
} from "node:fs";
|
|
251555
251225
|
import { join as join38 } from "node:path";
|
|
251556
251226
|
function getLettaDir() {
|
|
@@ -251608,10 +251278,10 @@ function writeCronFile(data) {
|
|
|
251608
251278
|
const path26 = getCronFilePath();
|
|
251609
251279
|
const dir = getLettaDir();
|
|
251610
251280
|
if (!existsSync34(dir)) {
|
|
251611
|
-
|
|
251281
|
+
mkdirSync22(dir, { recursive: true });
|
|
251612
251282
|
}
|
|
251613
251283
|
const tmp = `${path26}.tmp`;
|
|
251614
|
-
|
|
251284
|
+
writeFileSync15(tmp, JSON.stringify(data, null, 2), { flush: true });
|
|
251615
251285
|
renameSync4(tmp, path26);
|
|
251616
251286
|
}
|
|
251617
251287
|
function readLinuxProcessIdentity(pid) {
|
|
@@ -251676,7 +251346,7 @@ function readLockOwner(lockDir) {
|
|
|
251676
251346
|
}
|
|
251677
251347
|
}
|
|
251678
251348
|
function writeLockOwner(lockDir, owner) {
|
|
251679
|
-
|
|
251349
|
+
writeFileSync15(join38(lockDir, LOCK_TOKEN_FILE), JSON.stringify(owner));
|
|
251680
251350
|
}
|
|
251681
251351
|
function isLockStale(lockDir) {
|
|
251682
251352
|
const owner = readLockOwner(lockDir);
|
|
@@ -251703,7 +251373,7 @@ function acquireLock() {
|
|
|
251703
251373
|
const token2 = randomBytes(4).toString("hex");
|
|
251704
251374
|
while (Date.now() < deadline) {
|
|
251705
251375
|
try {
|
|
251706
|
-
|
|
251376
|
+
mkdirSync22(lockDir, { recursive: false });
|
|
251707
251377
|
const owner = {
|
|
251708
251378
|
pid: process.pid,
|
|
251709
251379
|
token: token2,
|
|
@@ -251949,10 +251619,10 @@ import {
|
|
|
251949
251619
|
appendFileSync as appendFileSync5,
|
|
251950
251620
|
chmodSync as chmodSync6,
|
|
251951
251621
|
existsSync as existsSync35,
|
|
251952
|
-
mkdirSync as
|
|
251622
|
+
mkdirSync as mkdirSync23,
|
|
251953
251623
|
readFileSync as readFileSync26,
|
|
251954
251624
|
statSync as statSync13,
|
|
251955
|
-
writeFileSync as
|
|
251625
|
+
writeFileSync as writeFileSync16
|
|
251956
251626
|
} from "node:fs";
|
|
251957
251627
|
import path26 from "node:path";
|
|
251958
251628
|
function assertSafeCronRunLogJobId(jobId) {
|
|
@@ -252002,7 +251672,7 @@ function pruneIfNeeded(filePath, opts) {
|
|
|
252002
251672
|
const lines = raw2.split(`
|
|
252003
251673
|
`).map((line) => line.trim()).filter(Boolean);
|
|
252004
251674
|
const kept = lines.slice(Math.max(0, lines.length - opts.keepLines));
|
|
252005
|
-
|
|
251675
|
+
writeFileSync16(filePath, `${kept.join(`
|
|
252006
251676
|
`)}
|
|
252007
251677
|
`, { mode: 384 });
|
|
252008
251678
|
setSecureFileMode(filePath);
|
|
@@ -252011,7 +251681,7 @@ function appendCronRunLog(filePath, entry, opts) {
|
|
|
252011
251681
|
const resolved = path26.resolve(filePath);
|
|
252012
251682
|
const runDir = path26.dirname(resolved);
|
|
252013
251683
|
if (!existsSync35(runDir)) {
|
|
252014
|
-
|
|
251684
|
+
mkdirSync23(runDir, { recursive: true, mode: 448 });
|
|
252015
251685
|
}
|
|
252016
251686
|
setSecureDirMode(runDir);
|
|
252017
251687
|
appendFileSync5(resolved, `${JSON.stringify(entry)}
|
|
@@ -253118,7 +252788,7 @@ function isGroupMode2(value) {
|
|
|
253118
252788
|
function isPositiveNumber(value) {
|
|
253119
252789
|
return typeof value === "number" && Number.isFinite(value) && value > 0;
|
|
253120
252790
|
}
|
|
253121
|
-
function
|
|
252791
|
+
function normalizeOptionalString2(value) {
|
|
253122
252792
|
if (typeof value !== "string") {
|
|
253123
252793
|
return;
|
|
253124
252794
|
}
|
|
@@ -253153,8 +252823,8 @@ var init_account_config3 = __esm(() => {
|
|
|
253153
252823
|
toAccountPatch(config3) {
|
|
253154
252824
|
return {
|
|
253155
252825
|
baseUrl: isNullableString3(config3.base_url) ? config3.base_url ?? "" : undefined,
|
|
253156
|
-
account: isNullableString3(config3.account) ?
|
|
253157
|
-
accountUuid: isNullableString3(config3.account_uuid) ?
|
|
252826
|
+
account: isNullableString3(config3.account) ? normalizeOptionalString2(config3.account) ?? "" : undefined,
|
|
252827
|
+
accountUuid: isNullableString3(config3.account_uuid) ? normalizeOptionalString2(config3.account_uuid) ?? "" : undefined,
|
|
253158
252828
|
agentId: isNullableString3(config3.agent_id) ? config3.agent_id : undefined,
|
|
253159
252829
|
selfChatMode: isBoolean2(config3.self_chat_mode) ? config3.self_chat_mode : undefined,
|
|
253160
252830
|
groupMode: isGroupMode2(config3.group_mode) ? config3.group_mode : undefined,
|
|
@@ -253544,7 +253214,7 @@ var init_account_config7 = __esm(() => {
|
|
|
253544
253214
|
});
|
|
253545
253215
|
|
|
253546
253216
|
// src/channels/custom/scaffolding.ts
|
|
253547
|
-
import { existsSync as existsSync36, mkdirSync as
|
|
253217
|
+
import { existsSync as existsSync36, mkdirSync as mkdirSync24, rmSync as rmSync8, writeFileSync as writeFileSync17 } from "node:fs";
|
|
253548
253218
|
function removeUserPlugin(channelId) {
|
|
253549
253219
|
if (FIRST_PARTY_SET.has(channelId)) {
|
|
253550
253220
|
return;
|
|
@@ -254072,18 +253742,6 @@ function isConversationCompactCommand(value) {
|
|
|
254072
253742
|
const c = value;
|
|
254073
253743
|
return c.type === "conversation_compact" && typeof c.request_id === "string" && typeof c.conversation_id === "string" && (c.body === undefined || isObjectRecord(c.body));
|
|
254074
253744
|
}
|
|
254075
|
-
function isListConversationPinsCommand(value) {
|
|
254076
|
-
if (!value || typeof value !== "object")
|
|
254077
|
-
return false;
|
|
254078
|
-
const c = value;
|
|
254079
|
-
return c.type === "list_conversation_pins" && typeof c.request_id === "string" && isRuntimeScope(c.runtime);
|
|
254080
|
-
}
|
|
254081
|
-
function isSetConversationPinCommand(value) {
|
|
254082
|
-
if (!value || typeof value !== "object")
|
|
254083
|
-
return false;
|
|
254084
|
-
const c = value;
|
|
254085
|
-
return c.type === "set_conversation_pin" && typeof c.request_id === "string" && isRuntimeScope(c.runtime) && typeof c.conversation_id === "string" && (c.action === "pin" || c.action === "unpin" || c.action === "toggle") && (c.scope === undefined || c.scope === "global" || c.scope === "local_project" || c.scope === "both");
|
|
254086
|
-
}
|
|
254087
253745
|
function isGetReflectionSettingsCommand(value) {
|
|
254088
253746
|
if (!value || typeof value !== "object")
|
|
254089
253747
|
return false;
|
|
@@ -254333,7 +253991,7 @@ function parseServerMessage(data) {
|
|
|
254333
253991
|
try {
|
|
254334
253992
|
const raw2 = typeof data === "string" ? data : data.toString();
|
|
254335
253993
|
const parsed = JSON.parse(raw2);
|
|
254336
|
-
if (isInputCommand(parsed) || isChangeDeviceStateCommand(parsed) || isAbortMessageCommand(parsed) || isSyncCommand(parsed) || isRuntimeStartCommand(parsed) || isExternalToolCallResponseCommand(parsed) || isTerminalSpawnCommand(parsed) || isTerminalInputCommand(parsed) || isTerminalResizeCommand(parsed) || isTerminalKillCommand(parsed) || isSearchFilesCommand(parsed) || isGrepInFilesCommand(parsed) || isListInDirectoryCommand(parsed) || isGetTreeCommand(parsed) || isReadFileCommand(parsed) || isWriteFileCommand(parsed) || isWatchFileCommand(parsed) || isUnwatchFileCommand(parsed) || isEditFileCommand(parsed) || isFileOpsCommand(parsed) || isListMemoryCommand(parsed) || isMemoryHistoryCommand(parsed) || isMemoryFileAtRefCommand(parsed) || isMemoryCommitDiffCommand(parsed) || isReadMemoryFileCommand(parsed) || isWriteMemoryFileCommand(parsed) || isDeleteMemoryFileCommand(parsed) || isEnableMemfsCommand(parsed) || isListModelsCommand(parsed) || isListConnectProvidersCommand(parsed) || isConnectProviderCommand(parsed) || isDisconnectProviderCommand(parsed) || isUpdateModelCommand(parsed) || isUpdateToolsetCommand(parsed) || isCronListCommand(parsed) || isCronAddCommand(parsed) || isCronGetCommand(parsed) || isCronRunsCommand(parsed) || isCronTriggerCommand(parsed) || isCronUpdateCommand(parsed) || isCronDeleteCommand(parsed) || isCronDeleteAllCommand(parsed) || isSkillEnableCommand(parsed) || isSkillDisableCommand(parsed) || isCreateAgentCommand(parsed) || isAgentListCommand(parsed) || isAgentRetrieveCommand(parsed) || isAgentCreateCommand(parsed) || isAgentUpdateCommand(parsed) || isAgentDeleteCommand(parsed) || isConversationListCommand(parsed) || isConversationRetrieveCommand(parsed) || isConversationCreateCommand(parsed) || isConversationUpdateCommand(parsed) || isConversationRecompileCommand(parsed) || isConversationForkCommand(parsed) || isConversationMessagesListCommand(parsed) || isConversationCompactCommand(parsed) || isGetCwdMapCommand(parsed) || isGetExperimentsCommand(parsed) || isSetExperimentCommand(parsed) ||
|
|
253994
|
+
if (isInputCommand(parsed) || isChangeDeviceStateCommand(parsed) || isAbortMessageCommand(parsed) || isSyncCommand(parsed) || isRuntimeStartCommand(parsed) || isExternalToolCallResponseCommand(parsed) || isTerminalSpawnCommand(parsed) || isTerminalInputCommand(parsed) || isTerminalResizeCommand(parsed) || isTerminalKillCommand(parsed) || isSearchFilesCommand(parsed) || isGrepInFilesCommand(parsed) || isListInDirectoryCommand(parsed) || isGetTreeCommand(parsed) || isReadFileCommand(parsed) || isWriteFileCommand(parsed) || isWatchFileCommand(parsed) || isUnwatchFileCommand(parsed) || isEditFileCommand(parsed) || isFileOpsCommand(parsed) || isListMemoryCommand(parsed) || isMemoryHistoryCommand(parsed) || isMemoryFileAtRefCommand(parsed) || isMemoryCommitDiffCommand(parsed) || isReadMemoryFileCommand(parsed) || isWriteMemoryFileCommand(parsed) || isDeleteMemoryFileCommand(parsed) || isEnableMemfsCommand(parsed) || isListModelsCommand(parsed) || isListConnectProvidersCommand(parsed) || isConnectProviderCommand(parsed) || isDisconnectProviderCommand(parsed) || isUpdateModelCommand(parsed) || isUpdateToolsetCommand(parsed) || isCronListCommand(parsed) || isCronAddCommand(parsed) || isCronGetCommand(parsed) || isCronRunsCommand(parsed) || isCronTriggerCommand(parsed) || isCronUpdateCommand(parsed) || isCronDeleteCommand(parsed) || isCronDeleteAllCommand(parsed) || isSkillEnableCommand(parsed) || isSkillDisableCommand(parsed) || isCreateAgentCommand(parsed) || isAgentListCommand(parsed) || isAgentRetrieveCommand(parsed) || isAgentCreateCommand(parsed) || isAgentUpdateCommand(parsed) || isAgentDeleteCommand(parsed) || isConversationListCommand(parsed) || isConversationRetrieveCommand(parsed) || isConversationCreateCommand(parsed) || isConversationUpdateCommand(parsed) || isConversationRecompileCommand(parsed) || isConversationForkCommand(parsed) || isConversationMessagesListCommand(parsed) || isConversationCompactCommand(parsed) || isGetCwdMapCommand(parsed) || isGetExperimentsCommand(parsed) || isSetExperimentCommand(parsed) || isGetReflectionSettingsCommand(parsed) || isSetReflectionSettingsCommand(parsed) || isChannelsListCommand(parsed) || isChannelAccountsListCommand(parsed) || isChannelAccountCreateCommand(parsed) || isChannelAccountUpdateCommand(parsed) || isChannelAccountBindCommand(parsed) || isChannelAccountUnbindCommand(parsed) || isChannelAccountDeleteCommand(parsed) || isChannelAccountStartCommand(parsed) || isChannelAccountStopCommand(parsed) || isChannelGetConfigCommand(parsed) || isChannelSetConfigCommand(parsed) || isChannelStartCommand(parsed) || isChannelStopCommand(parsed) || isChannelPairingsListCommand(parsed) || isChannelPairingBindCommand(parsed) || isChannelRoutesListCommand(parsed) || isChannelTargetsListCommand(parsed) || isChannelTargetBindCommand(parsed) || isChannelRouteUpdateCommand(parsed) || isChannelRouteRemoveCommand(parsed) || isExecuteCommandCommand(parsed) || isRemoveQueueItemCommand(parsed) || isSearchBranchesCommand(parsed) || isCheckoutBranchCommand(parsed) || isSecretListCommand(parsed) || isSecretApplyCommand(parsed)) {
|
|
254337
253995
|
return parsed;
|
|
254338
253996
|
}
|
|
254339
253997
|
const invalidInput = getInvalidInputReason(parsed);
|
|
@@ -256472,14 +256130,21 @@ function handleChannelRegistryEvent(event2, socket, runtime, safeSocketSend) {
|
|
|
256472
256130
|
const permissionModeState = getOrCreateConversationPermissionModeStateRef(runtime, event2.agentId, event2.conversationId);
|
|
256473
256131
|
permissionModeState.mode = event2.defaultPermissionMode;
|
|
256474
256132
|
persistPermissionModeMapForRuntime(runtime);
|
|
256133
|
+
const seededWorkingDirectory = seedConversationWorkingDirectory(runtime, event2.agentId, event2.conversationId, runtime.bootWorkingDirectory);
|
|
256134
|
+
if (seededWorkingDirectory) {
|
|
256135
|
+
emitDeviceStatusUpdate(socket, getOrCreateConversationRuntime(runtime, event2.agentId, event2.conversationId));
|
|
256136
|
+
}
|
|
256475
256137
|
}
|
|
256476
256138
|
var channelsServiceLoaderOverride = null;
|
|
256477
256139
|
var init_channels = __esm(() => {
|
|
256478
256140
|
init_account_config7();
|
|
256479
256141
|
init_scaffolding();
|
|
256480
256142
|
init_plugin_registry();
|
|
256143
|
+
init_cwd();
|
|
256481
256144
|
init_permission_mode();
|
|
256482
256145
|
init_protocol_inbound();
|
|
256146
|
+
init_protocol_outbound();
|
|
256147
|
+
init_runtime6();
|
|
256483
256148
|
});
|
|
256484
256149
|
|
|
256485
256150
|
// src/tools/toolset-labels.ts
|
|
@@ -256767,7 +256432,7 @@ function getModCacheDirectory(homeDirectory = homedir22()) {
|
|
|
256767
256432
|
var init_paths2 = () => {};
|
|
256768
256433
|
|
|
256769
256434
|
// src/mods/mod-diagnostics-file.ts
|
|
256770
|
-
import { mkdirSync as
|
|
256435
|
+
import { mkdirSync as mkdirSync25, writeFileSync as writeFileSync18 } from "node:fs";
|
|
256771
256436
|
import { homedir as homedir23 } from "node:os";
|
|
256772
256437
|
import path28 from "node:path";
|
|
256773
256438
|
function getDefaultModDiagnosticsRoot(homeDirectory = homedir23()) {
|
|
@@ -256785,8 +256450,8 @@ function createModDiagnosticsFile(diagnostics2, generatedAt = Date.now()) {
|
|
|
256785
256450
|
function writeModDiagnosticsLatestFile(diagnostics2, options3 = {}) {
|
|
256786
256451
|
const file3 = createModDiagnosticsFile(diagnostics2, options3.generatedAt);
|
|
256787
256452
|
const filePath = getModDiagnosticsLatestFilePath(options3.rootDirectory);
|
|
256788
|
-
|
|
256789
|
-
|
|
256453
|
+
mkdirSync25(path28.dirname(filePath), { recursive: true });
|
|
256454
|
+
writeFileSync18(filePath, `${JSON.stringify(file3, null, 2)}
|
|
256790
256455
|
`, "utf-8");
|
|
256791
256456
|
return file3;
|
|
256792
256457
|
}
|
|
@@ -264865,7 +264530,7 @@ ${lanes.join(`
|
|
|
264865
264530
|
writeOutputIsTTY() {
|
|
264866
264531
|
return process.stdout.isTTY;
|
|
264867
264532
|
},
|
|
264868
|
-
readFile:
|
|
264533
|
+
readFile: readFile14,
|
|
264869
264534
|
writeFile: writeFile22,
|
|
264870
264535
|
watchFile: watchFile2,
|
|
264871
264536
|
watchDirectory,
|
|
@@ -265058,7 +264723,7 @@ ${lanes.join(`
|
|
|
265058
264723
|
function fsWatchWorker(fileOrDirectory, recursive, callback) {
|
|
265059
264724
|
return _fs.watch(fileOrDirectory, fsSupportsRecursiveFsWatch ? { persistent: true, recursive: !!recursive } : { persistent: true }, callback);
|
|
265060
264725
|
}
|
|
265061
|
-
function
|
|
264726
|
+
function readFile14(fileName, _encoding) {
|
|
265062
264727
|
let buffer;
|
|
265063
264728
|
try {
|
|
265064
264729
|
buffer = _fs.readFileSync(fileName);
|
|
@@ -296005,7 +295670,7 @@ ${lanes.join(`
|
|
|
296005
295670
|
const possibleOption = getSpellingSuggestion(unknownOption, diagnostics2.optionDeclarations, getOptionName);
|
|
296006
295671
|
return possibleOption ? createDiagnosticForNodeInSourceFileOrCompilerDiagnostic(sourceFile, node, diagnostics2.unknownDidYouMeanDiagnostic, unknownOptionErrorText || unknownOption, possibleOption.name) : createDiagnosticForNodeInSourceFileOrCompilerDiagnostic(sourceFile, node, diagnostics2.unknownOptionDiagnostic, unknownOptionErrorText || unknownOption);
|
|
296007
295672
|
}
|
|
296008
|
-
function parseCommandLineWorker(diagnostics2, commandLine,
|
|
295673
|
+
function parseCommandLineWorker(diagnostics2, commandLine, readFile14) {
|
|
296009
295674
|
const options3 = {};
|
|
296010
295675
|
let watchOptions;
|
|
296011
295676
|
const fileNames = [];
|
|
@@ -296043,7 +295708,7 @@ ${lanes.join(`
|
|
|
296043
295708
|
}
|
|
296044
295709
|
}
|
|
296045
295710
|
function parseResponseFile(fileName) {
|
|
296046
|
-
const text2 = tryReadFile(fileName,
|
|
295711
|
+
const text2 = tryReadFile(fileName, readFile14 || ((fileName2) => sys.readFile(fileName2)));
|
|
296047
295712
|
if (!isString5(text2)) {
|
|
296048
295713
|
errors7.push(text2);
|
|
296049
295714
|
return;
|
|
@@ -296146,8 +295811,8 @@ ${lanes.join(`
|
|
|
296146
295811
|
unknownDidYouMeanDiagnostic: Diagnostics.Unknown_compiler_option_0_Did_you_mean_1,
|
|
296147
295812
|
optionTypeMismatchDiagnostic: Diagnostics.Compiler_option_0_expects_an_argument
|
|
296148
295813
|
};
|
|
296149
|
-
function parseCommandLine(commandLine,
|
|
296150
|
-
return parseCommandLineWorker(compilerOptionsDidYouMeanDiagnostics, commandLine,
|
|
295814
|
+
function parseCommandLine(commandLine, readFile14) {
|
|
295815
|
+
return parseCommandLineWorker(compilerOptionsDidYouMeanDiagnostics, commandLine, readFile14);
|
|
296151
295816
|
}
|
|
296152
295817
|
function getOptionFromName(optionName, allowShort) {
|
|
296153
295818
|
return getOptionDeclarationFromName(getOptionsNameMap, optionName, allowShort);
|
|
@@ -296215,8 +295880,8 @@ ${lanes.join(`
|
|
|
296215
295880
|
result.originalFileName = result.fileName;
|
|
296216
295881
|
return parseJsonSourceFileConfigFileContent(result, host, getNormalizedAbsolutePath(getDirectoryPath(configFileName), cwd2), optionsToExtend, getNormalizedAbsolutePath(configFileName, cwd2), undefined, extraFileExtensions, extendedConfigCache, watchOptionsToExtend);
|
|
296217
295882
|
}
|
|
296218
|
-
function readConfigFile(fileName,
|
|
296219
|
-
const textOrDiagnostic = tryReadFile(fileName,
|
|
295883
|
+
function readConfigFile(fileName, readFile14) {
|
|
295884
|
+
const textOrDiagnostic = tryReadFile(fileName, readFile14);
|
|
296220
295885
|
return isString5(textOrDiagnostic) ? parseConfigFileTextToJson(fileName, textOrDiagnostic) : { config: {}, error: textOrDiagnostic };
|
|
296221
295886
|
}
|
|
296222
295887
|
function parseConfigFileTextToJson(fileName, jsonText) {
|
|
@@ -296226,14 +295891,14 @@ ${lanes.join(`
|
|
|
296226
295891
|
error: jsonSourceFile.parseDiagnostics.length ? jsonSourceFile.parseDiagnostics[0] : undefined
|
|
296227
295892
|
};
|
|
296228
295893
|
}
|
|
296229
|
-
function readJsonConfigFile(fileName,
|
|
296230
|
-
const textOrDiagnostic = tryReadFile(fileName,
|
|
295894
|
+
function readJsonConfigFile(fileName, readFile14) {
|
|
295895
|
+
const textOrDiagnostic = tryReadFile(fileName, readFile14);
|
|
296231
295896
|
return isString5(textOrDiagnostic) ? parseJsonText(fileName, textOrDiagnostic) : { fileName, parseDiagnostics: [textOrDiagnostic] };
|
|
296232
295897
|
}
|
|
296233
|
-
function tryReadFile(fileName,
|
|
295898
|
+
function tryReadFile(fileName, readFile14) {
|
|
296234
295899
|
let text2;
|
|
296235
295900
|
try {
|
|
296236
|
-
text2 =
|
|
295901
|
+
text2 = readFile14(fileName);
|
|
296237
295902
|
} catch (e2) {
|
|
296238
295903
|
return createCompilerDiagnostic(Diagnostics.Cannot_read_file_0_Colon_1, fileName, e2.message);
|
|
296239
295904
|
}
|
|
@@ -363663,12 +363328,12 @@ ${lanes.join(`
|
|
|
363663
363328
|
function createCompilerHost(options3, setParentNodes) {
|
|
363664
363329
|
return createCompilerHostWorker(options3, setParentNodes);
|
|
363665
363330
|
}
|
|
363666
|
-
function createGetSourceFile(
|
|
363331
|
+
function createGetSourceFile(readFile14, setParentNodes) {
|
|
363667
363332
|
return (fileName, languageVersionOrOptions, onError) => {
|
|
363668
363333
|
let text2;
|
|
363669
363334
|
try {
|
|
363670
363335
|
mark2("beforeIORead");
|
|
363671
|
-
text2 =
|
|
363336
|
+
text2 = readFile14(fileName);
|
|
363672
363337
|
mark2("afterIORead");
|
|
363673
363338
|
measure("I/O Read", "beforeIORead", "afterIORead");
|
|
363674
363339
|
} catch (e2) {
|
|
@@ -364459,7 +364124,7 @@ ${lanes.join(`
|
|
|
364459
364124
|
getRedirectFromOutput,
|
|
364460
364125
|
forEachResolvedProjectReference: forEachResolvedProjectReference2
|
|
364461
364126
|
});
|
|
364462
|
-
const
|
|
364127
|
+
const readFile14 = host.readFile.bind(host);
|
|
364463
364128
|
(_e = tracing) == null || _e.push(tracing.Phase.Program, "shouldProgramCreateNewSourceFiles", { hasOldProgram: !!oldProgram });
|
|
364464
364129
|
const shouldCreateNewSourceFile = shouldProgramCreateNewSourceFiles(oldProgram, options3);
|
|
364465
364130
|
(_f = tracing) == null || _f.pop();
|
|
@@ -364635,7 +364300,7 @@ ${lanes.join(`
|
|
|
364635
364300
|
shouldTransformImportCall,
|
|
364636
364301
|
emitBuildInfo,
|
|
364637
364302
|
fileExists,
|
|
364638
|
-
readFile:
|
|
364303
|
+
readFile: readFile14,
|
|
364639
364304
|
directoryExists: directoryExists2,
|
|
364640
364305
|
getSymlinkCache,
|
|
364641
364306
|
realpath: (_o = host.realpath) == null ? undefined : _o.bind(host),
|
|
@@ -425516,16 +425181,16 @@ Additional information: BADCLIENT: Bad error code, ${badCode} not found in range
|
|
|
425516
425181
|
});
|
|
425517
425182
|
|
|
425518
425183
|
// src/mods/mod-engine.ts
|
|
425519
|
-
import { createHash as
|
|
425184
|
+
import { createHash as createHash5 } from "node:crypto";
|
|
425520
425185
|
import {
|
|
425521
425186
|
existsSync as existsSync38,
|
|
425522
|
-
mkdirSync as
|
|
425187
|
+
mkdirSync as mkdirSync26,
|
|
425523
425188
|
readdirSync as readdirSync13,
|
|
425524
425189
|
readFileSync as readFileSync27,
|
|
425525
425190
|
statSync as statSync14,
|
|
425526
425191
|
symlinkSync,
|
|
425527
425192
|
unlinkSync as unlinkSync5,
|
|
425528
|
-
writeFileSync as
|
|
425193
|
+
writeFileSync as writeFileSync19
|
|
425529
425194
|
} from "node:fs";
|
|
425530
425195
|
import { createRequire as createRequire5 } from "node:module";
|
|
425531
425196
|
import path29 from "node:path";
|
|
@@ -425664,11 +425329,11 @@ function ensureRuntimeDependencySymlink(cacheDirectory, packageName) {
|
|
|
425664
425329
|
const linkPath = path29.join(nodeModulesDirectory, packageName);
|
|
425665
425330
|
if (existsSync38(linkPath))
|
|
425666
425331
|
return;
|
|
425667
|
-
|
|
425332
|
+
mkdirSync26(nodeModulesDirectory, { recursive: true });
|
|
425668
425333
|
symlinkSync(getRuntimePackageDirectory(packageName), linkPath, process.platform === "win32" ? "junction" : "dir");
|
|
425669
425334
|
}
|
|
425670
425335
|
function ensureModCache(cacheDirectory) {
|
|
425671
|
-
|
|
425336
|
+
mkdirSync26(cacheDirectory, { recursive: true });
|
|
425672
425337
|
ensureRuntimeDependencySymlink(cacheDirectory, "react");
|
|
425673
425338
|
}
|
|
425674
425339
|
function formatTranspileDiagnostic(diagnostic) {
|
|
@@ -425707,13 +425372,13 @@ function prepareModForImport(modPath, source2) {
|
|
|
425707
425372
|
function createImportableModPath(modPath, cacheDirectory) {
|
|
425708
425373
|
ensureModCache(cacheDirectory);
|
|
425709
425374
|
const source2 = readFileSync27(modPath, "utf8");
|
|
425710
|
-
const hash4 =
|
|
425375
|
+
const hash4 = createHash5("sha256").update(source2).digest("hex").slice(0, 16);
|
|
425711
425376
|
const fileExtension = path29.extname(modPath);
|
|
425712
425377
|
const importableSource = prepareModForImport(modPath, source2);
|
|
425713
425378
|
const baseName = path29.basename(modPath, fileExtension).replace(/[^a-zA-Z0-9_-]/g, "-");
|
|
425714
425379
|
const importPath = path29.join(cacheDirectory, `.letta-mod-${baseName}-${hash4}.mjs`);
|
|
425715
425380
|
if (!existsSync38(importPath)) {
|
|
425716
|
-
|
|
425381
|
+
writeFileSync19(importPath, importableSource, "utf8");
|
|
425717
425382
|
}
|
|
425718
425383
|
try {
|
|
425719
425384
|
for (const entry of readdirSync13(cacheDirectory)) {
|
|
@@ -429353,7 +429018,7 @@ var init_accumulator = __esm(async () => {
|
|
|
429353
429018
|
});
|
|
429354
429019
|
|
|
429355
429020
|
// src/utils/tui-perf.ts
|
|
429356
|
-
import { appendFileSync as appendFileSync6, mkdirSync as
|
|
429021
|
+
import { appendFileSync as appendFileSync6, mkdirSync as mkdirSync27 } from "node:fs";
|
|
429357
429022
|
import { dirname as dirname19 } from "node:path";
|
|
429358
429023
|
function ensureExitHook() {
|
|
429359
429024
|
if (tuiPerfExitHookRegistered) {
|
|
@@ -429445,7 +429110,7 @@ function flushTuiPerfTelemetry() {
|
|
|
429445
429110
|
try {
|
|
429446
429111
|
const dir = dirname19(filePath);
|
|
429447
429112
|
if (tuiPerfFileDirEnsured !== dir) {
|
|
429448
|
-
|
|
429113
|
+
mkdirSync27(dir, { recursive: true });
|
|
429449
429114
|
tuiPerfFileDirEnsured = dir;
|
|
429450
429115
|
}
|
|
429451
429116
|
appendFileSync6(filePath, `${JSON.stringify({
|
|
@@ -429477,10 +429142,10 @@ var init_tui_perf = __esm(() => {
|
|
|
429477
429142
|
// src/cli/helpers/chunk-log.ts
|
|
429478
429143
|
import {
|
|
429479
429144
|
existsSync as existsSync39,
|
|
429480
|
-
mkdirSync as
|
|
429145
|
+
mkdirSync as mkdirSync28,
|
|
429481
429146
|
readdirSync as readdirSync14,
|
|
429482
429147
|
unlinkSync as unlinkSync6,
|
|
429483
|
-
writeFileSync as
|
|
429148
|
+
writeFileSync as writeFileSync20
|
|
429484
429149
|
} from "node:fs";
|
|
429485
429150
|
import { homedir as homedir24 } from "node:os";
|
|
429486
429151
|
import { join as join39 } from "node:path";
|
|
@@ -429578,7 +429243,7 @@ class ChunkLog {
|
|
|
429578
429243
|
return;
|
|
429579
429244
|
try {
|
|
429580
429245
|
if (!existsSync39(this.agentDir)) {
|
|
429581
|
-
|
|
429246
|
+
mkdirSync28(this.agentDir, { recursive: true });
|
|
429582
429247
|
}
|
|
429583
429248
|
this.dirCreated = true;
|
|
429584
429249
|
} catch (e2) {
|
|
@@ -429592,7 +429257,7 @@ class ChunkLog {
|
|
|
429592
429257
|
try {
|
|
429593
429258
|
const content = this.buffer.map((entry) => JSON.stringify(entry)).join(`
|
|
429594
429259
|
`);
|
|
429595
|
-
|
|
429260
|
+
writeFileSync20(this.logPath, `${content}
|
|
429596
429261
|
`, "utf8");
|
|
429597
429262
|
} catch (e2) {
|
|
429598
429263
|
debugWarn("chunkLog", `Failed to write ${this.logPath}: ${e2 instanceof Error ? e2.message : String(e2)}`);
|
|
@@ -437066,7 +436731,7 @@ var init_grep_in_files = __esm(() => {
|
|
|
437066
436731
|
});
|
|
437067
436732
|
|
|
437068
436733
|
// src/websocket/listener/file-commands.ts
|
|
437069
|
-
import { readdir as readdir8, readFile as
|
|
436734
|
+
import { readdir as readdir8, readFile as readFile14 } from "node:fs/promises";
|
|
437070
436735
|
import { homedir as homedir25 } from "node:os";
|
|
437071
436736
|
import path33 from "node:path";
|
|
437072
436737
|
function trackListenerError2(errorType, error54, context3) {
|
|
@@ -437121,7 +436786,7 @@ async function getIgnoreConfig(root2) {
|
|
|
437121
436786
|
return cached2;
|
|
437122
436787
|
let patterns2 = [];
|
|
437123
436788
|
try {
|
|
437124
|
-
const content = await
|
|
436789
|
+
const content = await readFile14(path33.join(absRoot, ".letta", ".lettaignore"), "utf-8");
|
|
437125
436790
|
patterns2 = parseLettaIgnore(content);
|
|
437126
436791
|
} catch {
|
|
437127
436792
|
patterns2 = [];
|
|
@@ -437935,7 +437600,7 @@ __export(exports_custom, {
|
|
|
437935
437600
|
COMMANDS_DIR: () => COMMANDS_DIR
|
|
437936
437601
|
});
|
|
437937
437602
|
import { existsSync as existsSync40 } from "node:fs";
|
|
437938
|
-
import { readdir as readdir9, readFile as
|
|
437603
|
+
import { readdir as readdir9, readFile as readFile15 } from "node:fs/promises";
|
|
437939
437604
|
import { basename as basename21, dirname as dirname20, join as join40 } from "node:path";
|
|
437940
437605
|
async function getCustomCommands() {
|
|
437941
437606
|
if (cachedCommands !== null) {
|
|
@@ -437994,7 +437659,7 @@ async function findCommandFiles(currentPath, rootPath, commands, source2) {
|
|
|
437994
437659
|
} catch (_error) {}
|
|
437995
437660
|
}
|
|
437996
437661
|
async function parseCommandFile(filePath, rootPath, source2) {
|
|
437997
|
-
const content = await
|
|
437662
|
+
const content = await readFile15(filePath, "utf-8");
|
|
437998
437663
|
const { frontmatter, body: body3 } = parseFrontmatter(content);
|
|
437999
437664
|
const id2 = basename21(filePath, ".md");
|
|
438000
437665
|
const relativePath = dirname20(filePath).slice(rootPath.length);
|
|
@@ -440438,17 +440103,17 @@ function handleMemoryProtocolCommand(parsed, context3) {
|
|
|
440438
440103
|
ensureLocalMemfsCheckout: ensureLocalMemfsCheckout2,
|
|
440439
440104
|
isMemfsEnabledOnServer: isMemfsEnabledOnServer2
|
|
440440
440105
|
} = await Promise.resolve().then(() => (init_memory_filesystem2(), exports_memory_filesystem));
|
|
440441
|
-
const { readFile:
|
|
440106
|
+
const { readFile: readFile16 } = await import("node:fs/promises");
|
|
440442
440107
|
const { existsSync: existsSync41 } = await import("node:fs");
|
|
440443
|
-
const { isAbsolute:
|
|
440444
|
-
if (
|
|
440108
|
+
const { isAbsolute: isAbsolute23, join: join42, normalize: normalize5, relative: relative10, sep: sep5 } = await import("node:path");
|
|
440109
|
+
if (isAbsolute23(parsed.path) || parsed.path.length === 0) {
|
|
440445
440110
|
sendFailure("path must be a non-empty relative path");
|
|
440446
440111
|
return;
|
|
440447
440112
|
}
|
|
440448
440113
|
const memoryRoot = getScopedMemoryFilesystemRoot2(parsed.agent_id);
|
|
440449
440114
|
const absolutePath = normalize5(join42(memoryRoot, parsed.path));
|
|
440450
440115
|
const rel = relative10(memoryRoot, absolutePath);
|
|
440451
|
-
if (rel.startsWith("..") || rel === "" ||
|
|
440116
|
+
if (rel.startsWith("..") || rel === "" || isAbsolute23(rel) || rel.split(sep5).includes("..")) {
|
|
440452
440117
|
sendFailure("path must resolve inside the memory root");
|
|
440453
440118
|
return;
|
|
440454
440119
|
}
|
|
@@ -440464,7 +440129,7 @@ function handleMemoryProtocolCommand(parsed, context3) {
|
|
|
440464
440129
|
return;
|
|
440465
440130
|
}
|
|
440466
440131
|
}
|
|
440467
|
-
const buffer = await
|
|
440132
|
+
const buffer = await readFile16(absolutePath);
|
|
440468
440133
|
const content = encoding === "base64" ? buffer.toString("base64") : buffer.toString("utf-8");
|
|
440469
440134
|
const pathspec = rel.split(sep5).join("/");
|
|
440470
440135
|
safeSocketSend(socket, {
|
|
@@ -440506,15 +440171,15 @@ function handleMemoryProtocolCommand(parsed, context3) {
|
|
|
440506
440171
|
const { commitMemoryWrite: commitMemoryWrite2 } = await Promise.resolve().then(() => (init_memory_git(), exports_memory_git));
|
|
440507
440172
|
const { writeFile: writeFile13, mkdir: mkdir11 } = await import("node:fs/promises");
|
|
440508
440173
|
const { existsSync: existsSync41 } = await import("node:fs");
|
|
440509
|
-
const { dirname: dirname21, isAbsolute:
|
|
440510
|
-
if (
|
|
440174
|
+
const { dirname: dirname21, isAbsolute: isAbsolute23, join: join42, normalize: normalize5, relative: relative10, sep: sep5 } = await import("node:path");
|
|
440175
|
+
if (isAbsolute23(parsed.path) || parsed.path.length === 0) {
|
|
440511
440176
|
sendFailure("write_memory_file: path must be a non-empty relative path");
|
|
440512
440177
|
return;
|
|
440513
440178
|
}
|
|
440514
440179
|
const memoryRoot = getScopedMemoryFilesystemRoot2(parsed.agent_id);
|
|
440515
440180
|
const absolutePath = normalize5(join42(memoryRoot, parsed.path));
|
|
440516
440181
|
const rel = relative10(memoryRoot, absolutePath);
|
|
440517
|
-
if (rel.startsWith("..") || rel === "" ||
|
|
440182
|
+
if (rel.startsWith("..") || rel === "" || isAbsolute23(rel) || rel.split(sep5).includes("..")) {
|
|
440518
440183
|
sendFailure("write_memory_file: path must resolve inside the memory root");
|
|
440519
440184
|
return;
|
|
440520
440185
|
}
|
|
@@ -440609,15 +440274,15 @@ function handleMemoryProtocolCommand(parsed, context3) {
|
|
|
440609
440274
|
const { commitMemoryWrite: commitMemoryWrite2 } = await Promise.resolve().then(() => (init_memory_git(), exports_memory_git));
|
|
440610
440275
|
const { unlink: unlink4 } = await import("node:fs/promises");
|
|
440611
440276
|
const { existsSync: existsSync41 } = await import("node:fs");
|
|
440612
|
-
const { isAbsolute:
|
|
440613
|
-
if (
|
|
440277
|
+
const { isAbsolute: isAbsolute23, join: join42, normalize: normalize5, relative: relative10, sep: sep5 } = await import("node:path");
|
|
440278
|
+
if (isAbsolute23(parsed.path) || parsed.path.length === 0) {
|
|
440614
440279
|
sendFailure("delete_memory_file: path must be a non-empty relative path");
|
|
440615
440280
|
return;
|
|
440616
440281
|
}
|
|
440617
440282
|
const memoryRoot = getScopedMemoryFilesystemRoot2(parsed.agent_id);
|
|
440618
440283
|
const absolutePath = normalize5(join42(memoryRoot, parsed.path));
|
|
440619
440284
|
const rel = relative10(memoryRoot, absolutePath);
|
|
440620
|
-
if (rel.startsWith("..") || rel === "" ||
|
|
440285
|
+
if (rel.startsWith("..") || rel === "" || isAbsolute23(rel) || rel.split(sep5).includes("..")) {
|
|
440621
440286
|
sendFailure("delete_memory_file: path must resolve inside the memory root");
|
|
440622
440287
|
return;
|
|
440623
440288
|
}
|
|
@@ -440772,7 +440437,7 @@ async function resolveRuntimeStartAgent(parsed, created) {
|
|
|
440772
440437
|
const agent2 = await backend4.createAgent(parsed.create_agent.body);
|
|
440773
440438
|
created.agent = true;
|
|
440774
440439
|
if (parsed.create_agent.pin_global !== false) {
|
|
440775
|
-
settingsManager.
|
|
440440
|
+
settingsManager.pinAgent(agent2.id);
|
|
440776
440441
|
}
|
|
440777
440442
|
return agent2;
|
|
440778
440443
|
}
|
|
@@ -440942,60 +440607,6 @@ async function handleExperimentCommand(parsed, socket, listener, safeSocketSend)
|
|
|
440942
440607
|
}
|
|
440943
440608
|
return true;
|
|
440944
440609
|
}
|
|
440945
|
-
function toConversationPinResponseItems(agentId, workingDirectory) {
|
|
440946
|
-
return settingsManager.getMergedPinnedConversations(agentId, workingDirectory).map((pin) => ({
|
|
440947
|
-
conversation_id: pin.conversationId,
|
|
440948
|
-
is_local: pin.isLocal
|
|
440949
|
-
}));
|
|
440950
|
-
}
|
|
440951
|
-
async function handleConversationPinCommand(parsed, socket, listener, safeSocketSend) {
|
|
440952
|
-
const agentId = parsed.runtime.agent_id;
|
|
440953
|
-
const workingDirectory = getConversationWorkingDirectory(listener, parsed.runtime.agent_id, parsed.runtime.conversation_id);
|
|
440954
|
-
if (parsed.type === "list_conversation_pins") {
|
|
440955
|
-
const response2 = {
|
|
440956
|
-
type: "list_conversation_pins_response",
|
|
440957
|
-
request_id: parsed.request_id,
|
|
440958
|
-
success: true,
|
|
440959
|
-
pins: toConversationPinResponseItems(agentId, workingDirectory)
|
|
440960
|
-
};
|
|
440961
|
-
safeSocketSend(socket, response2, "listener_conversation_pins_send_failed", "listener_conversation_pins");
|
|
440962
|
-
return true;
|
|
440963
|
-
}
|
|
440964
|
-
const scope = parsed.scope ?? "global";
|
|
440965
|
-
const localPinned = settingsManager.getLocalPinnedConversations(agentId, workingDirectory).includes(parsed.conversation_id);
|
|
440966
|
-
const globalPinned = settingsManager.getGlobalPinnedConversations(agentId).includes(parsed.conversation_id);
|
|
440967
|
-
const currentlyPinned = scope === "local_project" ? localPinned : scope === "global" ? globalPinned : localPinned || globalPinned;
|
|
440968
|
-
const shouldPin = parsed.action === "toggle" ? !currentlyPinned : parsed.action === "pin";
|
|
440969
|
-
if (scope === "local_project") {
|
|
440970
|
-
if (shouldPin) {
|
|
440971
|
-
settingsManager.pinConversationLocal(agentId, parsed.conversation_id, workingDirectory);
|
|
440972
|
-
} else {
|
|
440973
|
-
settingsManager.unpinConversationLocal(agentId, parsed.conversation_id, workingDirectory);
|
|
440974
|
-
}
|
|
440975
|
-
} else if (scope === "both") {
|
|
440976
|
-
if (shouldPin) {
|
|
440977
|
-
settingsManager.pinConversationLocal(agentId, parsed.conversation_id, workingDirectory);
|
|
440978
|
-
settingsManager.pinConversationGlobal(agentId, parsed.conversation_id);
|
|
440979
|
-
} else {
|
|
440980
|
-
settingsManager.unpinConversationBoth(agentId, parsed.conversation_id, workingDirectory);
|
|
440981
|
-
}
|
|
440982
|
-
} else if (shouldPin) {
|
|
440983
|
-
settingsManager.pinConversationGlobal(agentId, parsed.conversation_id);
|
|
440984
|
-
} else {
|
|
440985
|
-
settingsManager.unpinConversationGlobal(agentId, parsed.conversation_id);
|
|
440986
|
-
}
|
|
440987
|
-
const pins = toConversationPinResponseItems(agentId, workingDirectory);
|
|
440988
|
-
const response = {
|
|
440989
|
-
type: "set_conversation_pin_response",
|
|
440990
|
-
request_id: parsed.request_id,
|
|
440991
|
-
success: true,
|
|
440992
|
-
conversation_id: parsed.conversation_id,
|
|
440993
|
-
pinned: pins.some((pin) => pin.conversation_id === parsed.conversation_id),
|
|
440994
|
-
pins
|
|
440995
|
-
};
|
|
440996
|
-
safeSocketSend(socket, response, "listener_conversation_pins_send_failed", "listener_conversation_pins");
|
|
440997
|
-
return true;
|
|
440998
|
-
}
|
|
440999
440610
|
async function handleReflectionSettingsCommand(parsed, socket, listener, safeSocketSend) {
|
|
441000
440611
|
const agentId = parsed.runtime.agent_id;
|
|
441001
440612
|
const workingDirectory = getConversationWorkingDirectory(listener, parsed.runtime.agent_id, parsed.runtime.conversation_id);
|
|
@@ -441056,12 +440667,6 @@ function handleSettingsProtocolCommand(parsed, context3) {
|
|
|
441056
440667
|
});
|
|
441057
440668
|
return true;
|
|
441058
440669
|
}
|
|
441059
|
-
if (isListConversationPinsCommand(parsed) || isSetConversationPinCommand(parsed)) {
|
|
441060
|
-
runDetachedListenerTask("conversation_pin_command", async () => {
|
|
441061
|
-
await handleConversationPinCommand(parsed, socket, runtime, safeSocketSend);
|
|
441062
|
-
});
|
|
441063
|
-
return true;
|
|
441064
|
-
}
|
|
441065
440670
|
if (isGetReflectionSettingsCommand(parsed) || isSetReflectionSettingsCommand(parsed)) {
|
|
441066
440671
|
runDetachedListenerTask("reflection_settings_command", async () => {
|
|
441067
440672
|
await handleReflectionSettingsCommand(parsed, socket, runtime, safeSocketSend);
|
|
@@ -441073,7 +440678,6 @@ function handleSettingsProtocolCommand(parsed, context3) {
|
|
|
441073
440678
|
var init_settings3 = __esm(() => {
|
|
441074
440679
|
init_memory_reminder();
|
|
441075
440680
|
init_manager();
|
|
441076
|
-
init_settings_manager();
|
|
441077
440681
|
init_cwd();
|
|
441078
440682
|
init_protocol_inbound();
|
|
441079
440683
|
init_protocol_outbound();
|
|
@@ -441090,7 +440694,7 @@ async function handleSkillCommand(parsed, socket, safeSocketSend) {
|
|
|
441090
440694
|
const {
|
|
441091
440695
|
existsSync: existsSync41,
|
|
441092
440696
|
lstatSync: lstatSync2,
|
|
441093
|
-
mkdirSync:
|
|
440697
|
+
mkdirSync: mkdirSync29,
|
|
441094
440698
|
rmdirSync,
|
|
441095
440699
|
symlinkSync: symlinkSync2,
|
|
441096
440700
|
unlinkSync: unlinkSync7
|
|
@@ -441121,7 +440725,7 @@ async function handleSkillCommand(parsed, socket, safeSocketSend) {
|
|
|
441121
440725
|
}
|
|
441122
440726
|
const linkName = basename22(parsed.skill_path);
|
|
441123
440727
|
const linkPath = join42(globalSkillsDir, linkName);
|
|
441124
|
-
|
|
440728
|
+
mkdirSync29(globalSkillsDir, { recursive: true });
|
|
441125
440729
|
if (existsSync41(linkPath)) {
|
|
441126
440730
|
const stat11 = lstatSync2(linkPath);
|
|
441127
440731
|
if (stat11.isSymbolicLink()) {
|
|
@@ -441227,7 +440831,7 @@ async function handleCreateAgentCommand(parsed, socket, safeSocketSend) {
|
|
|
441227
440831
|
model: parsed.model
|
|
441228
440832
|
});
|
|
441229
440833
|
if (parsed.pin_global !== false) {
|
|
441230
|
-
settingsManager.
|
|
440834
|
+
settingsManager.pinAgent(result.agent.id);
|
|
441231
440835
|
}
|
|
441232
440836
|
safeSocketSend(socket, {
|
|
441233
440837
|
type: "create_agent_response",
|
|
@@ -441269,7 +440873,7 @@ var init_skills_agents = __esm(() => {
|
|
|
441269
440873
|
});
|
|
441270
440874
|
|
|
441271
440875
|
// src/websocket/listener/message-router.ts
|
|
441272
|
-
function
|
|
440876
|
+
function isRecord6(value) {
|
|
441273
440877
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
441274
440878
|
}
|
|
441275
440879
|
function formatLogValue(value) {
|
|
@@ -441295,7 +440899,7 @@ function pushField(fields, key2, value, label = key2) {
|
|
|
441295
440899
|
}
|
|
441296
440900
|
}
|
|
441297
440901
|
function summarizeInputPayload(payload) {
|
|
441298
|
-
if (!
|
|
440902
|
+
if (!isRecord6(payload))
|
|
441299
440903
|
return [];
|
|
441300
440904
|
const fields = [];
|
|
441301
440905
|
pushField(fields, "kind", payload.kind);
|
|
@@ -441314,9 +440918,9 @@ function summarizeRuntimeStartCommand(command) {
|
|
|
441314
440918
|
const fields = [];
|
|
441315
440919
|
pushField(fields, "agent_id", command.agent_id, "agent");
|
|
441316
440920
|
pushField(fields, "conversation_id", command.conversation_id, "conversation");
|
|
441317
|
-
if (
|
|
440921
|
+
if (isRecord6(command.create_agent))
|
|
441318
440922
|
fields.push("create_agent=true");
|
|
441319
|
-
if (
|
|
440923
|
+
if (isRecord6(command.create_conversation)) {
|
|
441320
440924
|
fields.push("create_conversation=true");
|
|
441321
440925
|
}
|
|
441322
440926
|
pushField(fields, "cwd", command.cwd);
|
|
@@ -441325,17 +440929,17 @@ function summarizeRuntimeStartCommand(command) {
|
|
|
441325
440929
|
return fields;
|
|
441326
440930
|
}
|
|
441327
440931
|
function summarizeV2Command(parsed) {
|
|
441328
|
-
if (!
|
|
440932
|
+
if (!isRecord6(parsed) || typeof parsed.type !== "string")
|
|
441329
440933
|
return "unknown";
|
|
441330
440934
|
const fields = [];
|
|
441331
|
-
const runtime =
|
|
440935
|
+
const runtime = isRecord6(parsed.runtime) ? parsed.runtime : null;
|
|
441332
440936
|
if (runtime) {
|
|
441333
440937
|
fields.push(`runtime=${runtime.agent_id ?? "<unknown>"}/${runtime.conversation_id ?? "<unknown>"}`);
|
|
441334
440938
|
}
|
|
441335
440939
|
pushField(fields, "request_id", parsed.request_id);
|
|
441336
440940
|
if (parsed.type === "input") {
|
|
441337
440941
|
fields.push(...summarizeInputPayload(parsed.payload));
|
|
441338
|
-
} else if (parsed.type === "change_device_state" &&
|
|
440942
|
+
} else if (parsed.type === "change_device_state" && isRecord6(parsed.payload)) {
|
|
441339
440943
|
pushField(fields, "mode", parsed.payload.mode);
|
|
441340
440944
|
pushField(fields, "cwd", parsed.payload.cwd);
|
|
441341
440945
|
pushField(fields, "agent_id", parsed.payload.agent_id);
|
|
@@ -442061,6 +441665,10 @@ async function wireChannelIngress(listener, socket, opts, processQueuedTurn) {
|
|
|
442061
441665
|
const rawRuntime = getOrCreateConversationRuntime(listener, delivery.route.agentId, delivery.route.conversationId);
|
|
442062
441666
|
if (!rawRuntime)
|
|
442063
441667
|
return;
|
|
441668
|
+
const seededWorkingDirectory = seedConversationWorkingDirectory(listener, delivery.route.agentId, delivery.route.conversationId, listener.bootWorkingDirectory);
|
|
441669
|
+
if (seededWorkingDirectory) {
|
|
441670
|
+
emitDeviceStatusUpdate(socket, rawRuntime);
|
|
441671
|
+
}
|
|
442064
441672
|
if (delivery.defaultPermissionMode) {
|
|
442065
441673
|
const permissionModeState = getOrCreateConversationPermissionModeStateRef(listener, delivery.route.agentId, delivery.route.conversationId);
|
|
442066
441674
|
if (permissionModeState.mode !== delivery.defaultPermissionMode) {
|
|
@@ -446846,18 +446454,12 @@ function validateAgentName(name) {
|
|
|
446846
446454
|
function isDefaultAgentName(name) {
|
|
446847
446455
|
return name === DEFAULT_AGENT_NAME;
|
|
446848
446456
|
}
|
|
446849
|
-
function PinDialog({
|
|
446850
|
-
currentName,
|
|
446851
|
-
local,
|
|
446852
|
-
onSubmit,
|
|
446853
|
-
onCancel
|
|
446854
|
-
}) {
|
|
446457
|
+
function PinDialog({ currentName, onSubmit, onCancel }) {
|
|
446855
446458
|
const isDefault = isDefaultAgentName(currentName);
|
|
446856
446459
|
const [mode, setMode] = import_react37.useState(isDefault ? "input" : "choose");
|
|
446857
446460
|
const [nameInput, setNameInput] = import_react37.useState("");
|
|
446858
446461
|
const [selectedOption, setSelectedOption] = import_react37.useState(0);
|
|
446859
446462
|
const [error54, setError] = import_react37.useState("");
|
|
446860
|
-
const scopeText = local ? "to this project" : "globally";
|
|
446861
446463
|
use_input_default((input, key2) => {
|
|
446862
446464
|
if (key2.ctrl && input === "c") {
|
|
446863
446465
|
onCancel();
|
|
@@ -446912,12 +446514,8 @@ function PinDialog({
|
|
|
446912
446514
|
marginBottom: 1,
|
|
446913
446515
|
children: /* @__PURE__ */ jsx_dev_runtime16.jsxDEV(Text2, {
|
|
446914
446516
|
dimColor: true,
|
|
446915
|
-
children:
|
|
446916
|
-
|
|
446917
|
-
scopeText,
|
|
446918
|
-
"."
|
|
446919
|
-
]
|
|
446920
|
-
}, undefined, true, undefined, this)
|
|
446517
|
+
children: "Give your agent a memorable name before pinning."
|
|
446518
|
+
}, undefined, false, undefined, this)
|
|
446921
446519
|
}, undefined, false, undefined, this),
|
|
446922
446520
|
/* @__PURE__ */ jsx_dev_runtime16.jsxDEV(Box_default, {
|
|
446923
446521
|
flexDirection: "column",
|
|
@@ -446977,11 +446575,8 @@ function PinDialog({
|
|
|
446977
446575
|
children: /* @__PURE__ */ jsx_dev_runtime16.jsxDEV(Text2, {
|
|
446978
446576
|
color: colors.approval.header,
|
|
446979
446577
|
bold: true,
|
|
446980
|
-
children:
|
|
446981
|
-
|
|
446982
|
-
scopeText
|
|
446983
|
-
]
|
|
446984
|
-
}, undefined, true, undefined, this)
|
|
446578
|
+
children: "Pin agent"
|
|
446579
|
+
}, undefined, false, undefined, this)
|
|
446985
446580
|
}, undefined, false, undefined, this),
|
|
446986
446581
|
/* @__PURE__ */ jsx_dev_runtime16.jsxDEV(Box_default, {
|
|
446987
446582
|
marginBottom: 1,
|
|
@@ -447195,10 +446790,10 @@ function AgentSelector({
|
|
|
447195
446790
|
const loadPinnedAgents = import_react38.useCallback(async () => {
|
|
447196
446791
|
setPinnedLoading(true);
|
|
447197
446792
|
try {
|
|
447198
|
-
const
|
|
446793
|
+
const pinnedIds = settingsManager.getPinnedAgents();
|
|
447199
446794
|
let pinnedData = [];
|
|
447200
|
-
if (
|
|
447201
|
-
pinnedData = await Promise.all(
|
|
446795
|
+
if (pinnedIds.length > 0) {
|
|
446796
|
+
pinnedData = await Promise.all(pinnedIds.map(async (agentId) => {
|
|
447202
446797
|
const backendMode = getPinnedAgentBackendMode(agentId);
|
|
447203
446798
|
try {
|
|
447204
446799
|
if (backendMode === "api" && !hasCloudCredentials()) {
|
|
@@ -447206,22 +446801,20 @@ function AgentSelector({
|
|
|
447206
446801
|
agentId,
|
|
447207
446802
|
agent: null,
|
|
447208
446803
|
error: "Not signed in",
|
|
447209
|
-
backendMode
|
|
447210
|
-
isLocalPin
|
|
446804
|
+
backendMode
|
|
447211
446805
|
};
|
|
447212
446806
|
}
|
|
447213
446807
|
const agentBackend = getBackendForMode(backendMode);
|
|
447214
446808
|
const agent2 = await agentBackend.retrieveAgent(agentId, {
|
|
447215
446809
|
include: ["agent.blocks"]
|
|
447216
446810
|
});
|
|
447217
|
-
return { agentId, agent: agent2, error: null, backendMode
|
|
446811
|
+
return { agentId, agent: agent2, error: null, backendMode };
|
|
447218
446812
|
} catch {
|
|
447219
446813
|
return {
|
|
447220
446814
|
agentId,
|
|
447221
446815
|
agent: null,
|
|
447222
446816
|
error: "Agent not found",
|
|
447223
|
-
backendMode
|
|
447224
|
-
isLocalPin
|
|
446817
|
+
backendMode
|
|
447225
446818
|
};
|
|
447226
446819
|
}
|
|
447227
446820
|
}));
|
|
@@ -447522,11 +447115,7 @@ function AgentSelector({
|
|
|
447522
447115
|
} else if (allowPinActions && activeTab === "pinned" && (input === "p" || input === "P")) {
|
|
447523
447116
|
const selected = pinnedPageAgents[pinnedSelectedIndex];
|
|
447524
447117
|
if (selected) {
|
|
447525
|
-
|
|
447526
|
-
settingsManager.unpinLocal(selected.agentId);
|
|
447527
|
-
} else {
|
|
447528
|
-
settingsManager.unpinGlobal(selected.agentId);
|
|
447529
|
-
}
|
|
447118
|
+
settingsManager.unpinAgent(selected.agentId);
|
|
447530
447119
|
loadPinnedAgents();
|
|
447531
447120
|
}
|
|
447532
447121
|
} else if (allowDelete && input === "D") {
|
|
@@ -447603,7 +447192,7 @@ function AgentSelector({
|
|
|
447603
447192
|
dimColor: true,
|
|
447604
447193
|
children: [
|
|
447605
447194
|
" · ",
|
|
447606
|
-
extra?.
|
|
447195
|
+
extra?.backend ?? backendLabel,
|
|
447607
447196
|
displayId
|
|
447608
447197
|
]
|
|
447609
447198
|
}, undefined, true, undefined, this),
|
|
@@ -447635,9 +447224,7 @@ function AgentSelector({
|
|
|
447635
447224
|
};
|
|
447636
447225
|
const renderPinnedItem = (data, index, isSelected) => {
|
|
447637
447226
|
if (data.agent) {
|
|
447638
|
-
return renderAgentItem(data.agent, index, isSelected, {
|
|
447639
|
-
isLocalPin: data.isLocalPin
|
|
447640
|
-
});
|
|
447227
|
+
return renderAgentItem(data.agent, index, isSelected, {});
|
|
447641
447228
|
}
|
|
447642
447229
|
return /* @__PURE__ */ jsx_dev_runtime18.jsxDEV(Box_default, {
|
|
447643
447230
|
flexDirection: "column",
|
|
@@ -447657,14 +447244,7 @@ function AgentSelector({
|
|
|
447657
447244
|
bold: isSelected,
|
|
447658
447245
|
color: isSelected ? colors.selector.itemHighlighted : undefined,
|
|
447659
447246
|
children: data.agentId.slice(0, 12)
|
|
447660
|
-
}, undefined, false, undefined, this)
|
|
447661
|
-
/* @__PURE__ */ jsx_dev_runtime18.jsxDEV(Text2, {
|
|
447662
|
-
dimColor: true,
|
|
447663
|
-
children: [
|
|
447664
|
-
" · ",
|
|
447665
|
-
data.isLocalPin ? "project" : "global"
|
|
447666
|
-
]
|
|
447667
|
-
}, undefined, true, undefined, this)
|
|
447247
|
+
}, undefined, false, undefined, this)
|
|
447668
447248
|
]
|
|
447669
447249
|
}, undefined, true, undefined, this),
|
|
447670
447250
|
/* @__PURE__ */ jsx_dev_runtime18.jsxDEV(Box_default, {
|
|
@@ -448092,7 +447672,7 @@ __export(exports_debug2, {
|
|
|
448092
447672
|
import {
|
|
448093
447673
|
appendFileSync as appendFileSync8,
|
|
448094
447674
|
existsSync as existsSync46,
|
|
448095
|
-
mkdirSync as
|
|
447675
|
+
mkdirSync as mkdirSync32,
|
|
448096
447676
|
readdirSync as readdirSync19,
|
|
448097
447677
|
readFileSync as readFileSync33,
|
|
448098
447678
|
unlinkSync as unlinkSync8
|
|
@@ -448162,7 +447742,7 @@ class DebugLogFile2 {
|
|
|
448162
447742
|
return;
|
|
448163
447743
|
try {
|
|
448164
447744
|
if (!existsSync46(this.agentDir)) {
|
|
448165
|
-
|
|
447745
|
+
mkdirSync32(this.agentDir, { recursive: true });
|
|
448166
447746
|
}
|
|
448167
447747
|
this.dirCreated = true;
|
|
448168
447748
|
} catch {}
|
|
@@ -448237,7 +447817,7 @@ __export(exports_skills3, {
|
|
|
448237
447817
|
GLOBAL_SKILLS_DIR: () => GLOBAL_SKILLS_DIR2
|
|
448238
447818
|
});
|
|
448239
447819
|
import { existsSync as existsSync47 } from "node:fs";
|
|
448240
|
-
import { readdir as readdir12, readFile as
|
|
447820
|
+
import { readdir as readdir12, readFile as readFile16, realpath as realpath5, stat as stat11 } from "node:fs/promises";
|
|
448241
447821
|
import { dirname as dirname23, join as join49 } from "node:path";
|
|
448242
447822
|
import { fileURLToPath as fileURLToPath8 } from "node:url";
|
|
448243
447823
|
function getBundledSkillsPath2() {
|
|
@@ -448409,7 +447989,7 @@ async function findSkillFiles2(currentPath, rootPath, skills, errors7, source2,
|
|
|
448409
447989
|
}
|
|
448410
447990
|
}
|
|
448411
447991
|
async function parseSkillFile2(filePath, rootPath, source2) {
|
|
448412
|
-
const content = await
|
|
447992
|
+
const content = await readFile16(filePath, "utf-8");
|
|
448413
447993
|
const { frontmatter, body: body3 } = parseFrontmatter(content);
|
|
448414
447994
|
const normalizedRoot = rootPath.endsWith("/") ? rootPath.slice(0, -1) : rootPath;
|
|
448415
447995
|
const relativePath = filePath.slice(normalizedRoot.length + 1);
|
|
@@ -448470,7 +448050,7 @@ __export(exports_fs, {
|
|
|
448470
448050
|
writeJsonFile: () => writeJsonFile,
|
|
448471
448051
|
writeFile: () => writeFile14,
|
|
448472
448052
|
readJsonFile: () => readJsonFile3,
|
|
448473
|
-
readFile: () =>
|
|
448053
|
+
readFile: () => readFile17,
|
|
448474
448054
|
mkdir: () => mkdir12,
|
|
448475
448055
|
exists: () => exists2
|
|
448476
448056
|
});
|
|
@@ -448478,16 +448058,16 @@ import {
|
|
|
448478
448058
|
existsSync as existsSync48,
|
|
448479
448059
|
readFileSync as fsReadFileSync2,
|
|
448480
448060
|
writeFileSync as fsWriteFileSync2,
|
|
448481
|
-
mkdirSync as
|
|
448061
|
+
mkdirSync as mkdirSync33
|
|
448482
448062
|
} from "node:fs";
|
|
448483
448063
|
import { dirname as dirname24 } from "node:path";
|
|
448484
|
-
async function
|
|
448064
|
+
async function readFile17(path35) {
|
|
448485
448065
|
return fsReadFileSync2(path35, { encoding: "utf-8" });
|
|
448486
448066
|
}
|
|
448487
448067
|
async function writeFile14(path35, content) {
|
|
448488
448068
|
const dir = dirname24(path35);
|
|
448489
448069
|
if (!existsSync48(dir)) {
|
|
448490
|
-
|
|
448070
|
+
mkdirSync33(dir, { recursive: true });
|
|
448491
448071
|
}
|
|
448492
448072
|
fsWriteFileSync2(path35, content, { encoding: "utf-8", flush: true });
|
|
448493
448073
|
}
|
|
@@ -448495,10 +448075,10 @@ function exists2(path35) {
|
|
|
448495
448075
|
return existsSync48(path35);
|
|
448496
448076
|
}
|
|
448497
448077
|
async function mkdir12(path35, options3) {
|
|
448498
|
-
|
|
448078
|
+
mkdirSync33(path35, options3);
|
|
448499
448079
|
}
|
|
448500
448080
|
async function readJsonFile3(path35) {
|
|
448501
|
-
const text2 = await
|
|
448081
|
+
const text2 = await readFile17(path35);
|
|
448502
448082
|
return JSON.parse(text2);
|
|
448503
448083
|
}
|
|
448504
448084
|
async function writeJsonFile(path35, data, options3) {
|
|
@@ -449572,7 +449152,7 @@ var exports_bootstrap_tools = {};
|
|
|
449572
449152
|
__export(exports_bootstrap_tools, {
|
|
449573
449153
|
bootstrapBaseToolsIfNeeded: () => bootstrapBaseToolsIfNeeded
|
|
449574
449154
|
});
|
|
449575
|
-
import { existsSync as existsSync50, mkdirSync as
|
|
449155
|
+
import { existsSync as existsSync50, mkdirSync as mkdirSync35, writeFileSync as writeFileSync24 } from "node:fs";
|
|
449576
449156
|
import { homedir as homedir30 } from "node:os";
|
|
449577
449157
|
import { join as join52 } from "node:path";
|
|
449578
449158
|
async function bootstrapBaseToolsIfNeeded() {
|
|
@@ -449582,8 +449162,8 @@ async function bootstrapBaseToolsIfNeeded() {
|
|
|
449582
449162
|
try {
|
|
449583
449163
|
const success2 = await addBaseToolsToServer();
|
|
449584
449164
|
if (success2) {
|
|
449585
|
-
|
|
449586
|
-
|
|
449165
|
+
mkdirSync35(join52(homedir30(), ".letta"), { recursive: true });
|
|
449166
|
+
writeFileSync24(MARKER_PATH, new Date().toISOString(), "utf-8");
|
|
449587
449167
|
}
|
|
449588
449168
|
} catch (err) {
|
|
449589
449169
|
debugWarn("bootstrap", `Failed to bootstrap base tools: ${err instanceof Error ? err.message : String(err)}`);
|
|
@@ -450399,8 +449979,8 @@ __export(exports_import, {
|
|
|
450399
449979
|
extractSkillsFromAf: () => extractSkillsFromAf
|
|
450400
449980
|
});
|
|
450401
449981
|
import { createReadStream as createReadStream2 } from "node:fs";
|
|
450402
|
-
import { access as access2, chmod, mkdir as mkdir13, readFile as
|
|
450403
|
-
import { dirname as dirname26, isAbsolute as
|
|
449982
|
+
import { access as access2, chmod, mkdir as mkdir13, readFile as readFile18, writeFile as writeFile15 } from "node:fs/promises";
|
|
449983
|
+
import { dirname as dirname26, isAbsolute as isAbsolute24, relative as relative10, resolve as resolve36, sep as sep6, win32 as win324 } from "node:path";
|
|
450404
449984
|
function validateImportedSkillName(name) {
|
|
450405
449985
|
const trimmedName = name.trim();
|
|
450406
449986
|
if (trimmedName !== name || trimmedName.length === 0 || trimmedName.length > MAX_SKILL_NAME_LENGTH || trimmedName === "." || trimmedName === ".." || !IMPORTED_SKILL_NAME_PATTERN.test(trimmedName)) {
|
|
@@ -450412,12 +449992,12 @@ function assertPathInside(parent, child) {
|
|
|
450412
449992
|
const parentPath = resolve36(parent);
|
|
450413
449993
|
const childPath = resolve36(child);
|
|
450414
449994
|
const relativePath = relative10(parentPath, childPath);
|
|
450415
|
-
if (relativePath === "" || relativePath === ".." || relativePath.startsWith(`..${sep6}`) ||
|
|
449995
|
+
if (relativePath === "" || relativePath === ".." || relativePath.startsWith(`..${sep6}`) || isAbsolute24(relativePath)) {
|
|
450416
449996
|
throw new Error(`Imported skill file path escapes skill directory: ${child}`);
|
|
450417
449997
|
}
|
|
450418
449998
|
}
|
|
450419
449999
|
function validateImportedSkillFilePath(filePath) {
|
|
450420
|
-
if (filePath.length === 0 || filePath === "." || filePath.includes("\x00") || filePath.includes("\\") ||
|
|
450000
|
+
if (filePath.length === 0 || filePath === "." || filePath.includes("\x00") || filePath.includes("\\") || isAbsolute24(filePath) || win324.isAbsolute(filePath)) {
|
|
450421
450001
|
throw new Error(`Invalid imported skill file path "${filePath}".`);
|
|
450422
450002
|
}
|
|
450423
450003
|
const segments = filePath.split("/");
|
|
@@ -450502,7 +450082,7 @@ async function importAgentFromFile(options3) {
|
|
|
450502
450082
|
}
|
|
450503
450083
|
async function extractSkillsFromAf(afPath, destDir) {
|
|
450504
450084
|
const extracted = [];
|
|
450505
|
-
const content = await
|
|
450085
|
+
const content = await readFile18(afPath, "utf-8");
|
|
450506
450086
|
const afData = JSON.parse(content);
|
|
450507
450087
|
if (!afData.skills || !Array.isArray(afData.skills)) {
|
|
450508
450088
|
return [];
|
|
@@ -450706,7 +450286,7 @@ async function ensureDefaultAgents(backend4, options3) {
|
|
|
450706
450286
|
memoryPromptMode
|
|
450707
450287
|
});
|
|
450708
450288
|
await addTagToAgent(backend4, agent2.id, MEMO_TAG);
|
|
450709
|
-
settingsManager.
|
|
450289
|
+
settingsManager.pinAgent(agent2.id);
|
|
450710
450290
|
if (backend4.capabilities.remoteMemfs) {
|
|
450711
450291
|
enableMemfsIfCloud2(agent2.id, backend4);
|
|
450712
450292
|
}
|
|
@@ -455559,9 +455139,9 @@ __export(exports_terminal_keybinding_installer, {
|
|
|
455559
455139
|
import {
|
|
455560
455140
|
copyFileSync as copyFileSync3,
|
|
455561
455141
|
existsSync as existsSync53,
|
|
455562
|
-
mkdirSync as
|
|
455142
|
+
mkdirSync as mkdirSync37,
|
|
455563
455143
|
readFileSync as readFileSync36,
|
|
455564
|
-
writeFileSync as
|
|
455144
|
+
writeFileSync as writeFileSync26
|
|
455565
455145
|
} from "node:fs";
|
|
455566
455146
|
import { homedir as homedir33, platform as platform9 } from "node:os";
|
|
455567
455147
|
import { dirname as dirname27, join as join55 } from "node:path";
|
|
@@ -455657,7 +455237,7 @@ function installKeybinding(keybindingsPath) {
|
|
|
455657
455237
|
}
|
|
455658
455238
|
const parentDir = dirname27(keybindingsPath);
|
|
455659
455239
|
if (!existsSync53(parentDir)) {
|
|
455660
|
-
|
|
455240
|
+
mkdirSync37(parentDir, { recursive: true });
|
|
455661
455241
|
}
|
|
455662
455242
|
let keybindings = [];
|
|
455663
455243
|
let backupPath = null;
|
|
@@ -455676,7 +455256,7 @@ function installKeybinding(keybindingsPath) {
|
|
|
455676
455256
|
keybindings.push(SHIFT_ENTER_KEYBINDING);
|
|
455677
455257
|
const newContent = `${JSON.stringify(keybindings, null, 2)}
|
|
455678
455258
|
`;
|
|
455679
|
-
|
|
455259
|
+
writeFileSync26(keybindingsPath, newContent, { encoding: "utf-8" });
|
|
455680
455260
|
return {
|
|
455681
455261
|
success: true,
|
|
455682
455262
|
backupPath: backupPath ?? undefined
|
|
@@ -455705,7 +455285,7 @@ function removeKeybinding(keybindingsPath) {
|
|
|
455705
455285
|
const filtered = keybindings.filter((kb) => !(kb.key?.toLowerCase() === "shift+enter" && kb.command === "workbench.action.terminal.sendSequence" && kb.when?.includes("terminalFocus")));
|
|
455706
455286
|
const newContent = `${JSON.stringify(filtered, null, 2)}
|
|
455707
455287
|
`;
|
|
455708
|
-
|
|
455288
|
+
writeFileSync26(keybindingsPath, newContent, { encoding: "utf-8" });
|
|
455709
455289
|
return { success: true };
|
|
455710
455290
|
} catch (error54) {
|
|
455711
455291
|
const message = error54 instanceof Error ? error54.message : String(error54);
|
|
@@ -455893,9 +455473,9 @@ function installWezTermDeleteFix() {
|
|
|
455893
455473
|
content = injectWezTermDeleteFix(content);
|
|
455894
455474
|
const parentDir = dirname27(configPath);
|
|
455895
455475
|
if (!existsSync53(parentDir)) {
|
|
455896
|
-
|
|
455476
|
+
mkdirSync37(parentDir, { recursive: true });
|
|
455897
455477
|
}
|
|
455898
|
-
|
|
455478
|
+
writeFileSync26(configPath, content, { encoding: "utf-8" });
|
|
455899
455479
|
return {
|
|
455900
455480
|
success: true,
|
|
455901
455481
|
backupPath: backupPath ?? undefined
|
|
@@ -456266,14 +455846,14 @@ var init_registry2 = __esm(() => {
|
|
|
456266
455846
|
}
|
|
456267
455847
|
},
|
|
456268
455848
|
"/pin": {
|
|
456269
|
-
desc: "Pin current agent
|
|
455849
|
+
desc: "Pin current agent (/pin [name])",
|
|
456270
455850
|
order: 22,
|
|
456271
455851
|
handler: () => {
|
|
456272
455852
|
return "Pinning agent...";
|
|
456273
455853
|
}
|
|
456274
455854
|
},
|
|
456275
455855
|
"/unpin": {
|
|
456276
|
-
desc: "Unpin current agent
|
|
455856
|
+
desc: "Unpin current agent",
|
|
456277
455857
|
order: 23,
|
|
456278
455858
|
handler: () => {
|
|
456279
455859
|
return "Unpinning agent...";
|
|
@@ -460841,39 +460421,8 @@ var init_ConstellationLoginOverlay = __esm(async () => {
|
|
|
460841
460421
|
});
|
|
460842
460422
|
|
|
460843
460423
|
// src/cli/components/ConversationSelector.tsx
|
|
460844
|
-
function
|
|
460845
|
-
|
|
460846
|
-
return false;
|
|
460847
|
-
if (input === "π" || input === "∏")
|
|
460848
|
-
return true;
|
|
460849
|
-
if (!key2.meta)
|
|
460850
|
-
return false;
|
|
460851
|
-
const normalizedInput = input.replaceAll("\x1B", "");
|
|
460852
|
-
return normalizedInput === "p" || normalizedInput === "P";
|
|
460853
|
-
}
|
|
460854
|
-
function isDefaultConversationId2(conversationId) {
|
|
460855
|
-
return conversationId === "default";
|
|
460856
|
-
}
|
|
460857
|
-
function isConversationPinned2(params) {
|
|
460858
|
-
return isDefaultConversationId2(params.conversationId) ? true : params.pinnedIds.has(params.conversationId);
|
|
460859
|
-
}
|
|
460860
|
-
function buildConversationSelectorHints2(params) {
|
|
460861
|
-
return params.isSelectedDefaultConversation ? "Enter select · ↑↓ navigate · Esc clear/cancel" : "Enter select · ↑↓ navigate · Alt+P pin/unpin · Esc clear/cancel";
|
|
460862
|
-
}
|
|
460863
|
-
function normalizeConversationSearchInput2(value) {
|
|
460864
|
-
return value.replace(/[π∏]/g, "");
|
|
460865
|
-
}
|
|
460866
|
-
function findConversationIndexById2(items3, conversationId) {
|
|
460867
|
-
return items3.findIndex((item) => item.conversation.id === conversationId);
|
|
460868
|
-
}
|
|
460869
|
-
function sortPinnedConversations2(items3) {
|
|
460870
|
-
return [...items3].sort((a2, b3) => {
|
|
460871
|
-
if (a2.conversation.id === "default")
|
|
460872
|
-
return -1;
|
|
460873
|
-
if (b3.conversation.id === "default")
|
|
460874
|
-
return 1;
|
|
460875
|
-
return Number(b3.isPinned) - Number(a2.isPinned);
|
|
460876
|
-
});
|
|
460424
|
+
function buildConversationSelectorHints2() {
|
|
460425
|
+
return "Enter select · ↑↓ navigate · Esc clear/cancel";
|
|
460877
460426
|
}
|
|
460878
460427
|
function paginatedItems5(value) {
|
|
460879
460428
|
return Array.isArray(value) ? value : value.getPaginatedItems();
|
|
@@ -461004,18 +460553,9 @@ function buildDefaultConversationEntry2(agentId, stats, createdAt = null) {
|
|
|
461004
460553
|
previewLines: stats.previewLines,
|
|
461005
460554
|
lastActiveAt: stats.lastActiveAt,
|
|
461006
460555
|
messageCount: stats.messageCount,
|
|
461007
|
-
enriched: true
|
|
461008
|
-
isPinned: false,
|
|
461009
|
-
isPinnedLocal: false
|
|
460556
|
+
enriched: true
|
|
461010
460557
|
};
|
|
461011
460558
|
}
|
|
461012
|
-
function mergePinnedConversationRecords2(listedConversations, pinnedConversations) {
|
|
461013
|
-
const listedIds = new Set(listedConversations.map((conversation) => conversation.id));
|
|
461014
|
-
return [
|
|
461015
|
-
...pinnedConversations.filter((conversation) => !listedIds.has(conversation.id)),
|
|
461016
|
-
...listedConversations
|
|
461017
|
-
];
|
|
461018
|
-
}
|
|
461019
460559
|
function ConversationSelector2({
|
|
461020
460560
|
agentId,
|
|
461021
460561
|
agentName,
|
|
@@ -461040,16 +460580,6 @@ function ConversationSelector2({
|
|
|
461040
460580
|
const [searchInput, setSearchInput] = import_react66.useState("");
|
|
461041
460581
|
const [searchResults, setSearchResults] = import_react66.useState(null);
|
|
461042
460582
|
const [searching, setSearching] = import_react66.useState(false);
|
|
461043
|
-
const [pinNotice, setPinNotice] = import_react66.useState(null);
|
|
461044
|
-
const pinNoticeTimerRef = import_react66.useRef(null);
|
|
461045
|
-
const preserveSelectionIdRef = import_react66.useRef(null);
|
|
461046
|
-
import_react66.useEffect(() => {
|
|
461047
|
-
return () => {
|
|
461048
|
-
if (pinNoticeTimerRef.current) {
|
|
461049
|
-
clearTimeout(pinNoticeTimerRef.current);
|
|
461050
|
-
}
|
|
461051
|
-
};
|
|
461052
|
-
}, []);
|
|
461053
460583
|
const enrichConversation = import_react66.useCallback(async (backend4, convId) => {
|
|
461054
460584
|
try {
|
|
461055
460585
|
const messages = await backend4.listConversationMessages(convId, {
|
|
@@ -461091,9 +460621,6 @@ function ConversationSelector2({
|
|
|
461091
460621
|
setError(null);
|
|
461092
460622
|
try {
|
|
461093
460623
|
const backend4 = selectorBackend();
|
|
461094
|
-
const pinnedRefs = !afterCursor ? settingsManager.getMergedPinnedConversations(agentId) : [];
|
|
461095
|
-
const pinnedIdSet = new Set(pinnedRefs.map((p2) => p2.conversationId));
|
|
461096
|
-
const localPinnedIdSet = new Set(pinnedRefs.filter((p2) => p2.isLocal).map((p2) => p2.conversationId));
|
|
461097
460624
|
const conversationListPromise = backend4.listConversations({
|
|
461098
460625
|
agent_id: agentId,
|
|
461099
460626
|
limit: FETCH_PAGE_SIZE3,
|
|
@@ -461125,53 +460652,20 @@ function ConversationSelector2({
|
|
|
461125
460652
|
conversationListPromise,
|
|
461126
460653
|
defaultPromise
|
|
461127
460654
|
]);
|
|
461128
|
-
const
|
|
461129
|
-
try {
|
|
461130
|
-
const conversation = await backend4.retrieveConversation(pin.conversationId);
|
|
461131
|
-
return conversation.agent_id === agentId ? conversation : null;
|
|
461132
|
-
} catch {
|
|
461133
|
-
return null;
|
|
461134
|
-
}
|
|
461135
|
-
}))).filter((conversation) => conversation !== null) : [];
|
|
461136
|
-
const conversationRecords = mergePinnedConversationRecords2(result, pinnedConversations);
|
|
461137
|
-
const unenrichedList = conversationRecords.map((conv) => ({
|
|
460655
|
+
const unenrichedList = result.map((conv) => ({
|
|
461138
460656
|
conversation: conv,
|
|
461139
460657
|
previewLines: null,
|
|
461140
460658
|
lastActiveAt: conv.updated_at ?? conv.created_at ?? null,
|
|
461141
460659
|
messageCount: -1,
|
|
461142
|
-
enriched: false
|
|
461143
|
-
isPinned: isConversationPinned2({
|
|
461144
|
-
conversationId: conv.id,
|
|
461145
|
-
pinnedIds: pinnedIdSet
|
|
461146
|
-
}),
|
|
461147
|
-
isPinnedLocal: localPinnedIdSet.has(conv.id)
|
|
460660
|
+
enriched: false
|
|
461148
460661
|
}));
|
|
461149
460662
|
const nonEmptyList = unenrichedList;
|
|
461150
460663
|
const newCursor = result.length === FETCH_PAGE_SIZE3 ? result[result.length - 1]?.id ?? null : null;
|
|
461151
460664
|
if (isLoadingMore) {
|
|
461152
460665
|
setConversations((prev) => [...prev, ...nonEmptyList]);
|
|
461153
460666
|
} else {
|
|
461154
|
-
const initialConversations = defaultConversation ? [
|
|
461155
|
-
|
|
461156
|
-
...defaultConversation,
|
|
461157
|
-
isPinned: true,
|
|
461158
|
-
isPinnedLocal: localPinnedIdSet.has("default")
|
|
461159
|
-
},
|
|
461160
|
-
...nonEmptyList
|
|
461161
|
-
] : nonEmptyList;
|
|
461162
|
-
const byId = new Map(initialConversations.map((item) => [item.conversation.id, item]));
|
|
461163
|
-
const defaultItem = byId.get("default");
|
|
461164
|
-
const pinnedOrdered = pinnedRefs.map((p2) => byId.get(p2.conversationId)).filter((item) => item !== undefined && item.conversation.id !== "default");
|
|
461165
|
-
const prioritizedIds = new Set([
|
|
461166
|
-
...defaultItem ? [defaultItem.conversation.id] : [],
|
|
461167
|
-
...pinnedOrdered.map((item) => item.conversation.id)
|
|
461168
|
-
]);
|
|
461169
|
-
const allConversations = [
|
|
461170
|
-
...defaultItem ? [defaultItem] : [],
|
|
461171
|
-
...pinnedOrdered,
|
|
461172
|
-
...initialConversations.filter((item) => !prioritizedIds.has(item.conversation.id))
|
|
461173
|
-
];
|
|
461174
|
-
setConversations(allConversations);
|
|
460667
|
+
const initialConversations = defaultConversation ? [defaultConversation, ...nonEmptyList] : nonEmptyList;
|
|
460668
|
+
setConversations(initialConversations);
|
|
461175
460669
|
setSelectedIndex(0);
|
|
461176
460670
|
}
|
|
461177
460671
|
setCursor(newCursor);
|
|
@@ -461248,12 +460742,7 @@ function ConversationSelector2({
|
|
|
461248
460742
|
searchPreview: conversation.summary || undefined,
|
|
461249
460743
|
lastActiveAt: conversation.updated_at ?? conversation.created_at ?? null,
|
|
461250
460744
|
messageCount: -1,
|
|
461251
|
-
enriched: false
|
|
461252
|
-
isPinned: isConversationPinned2({
|
|
461253
|
-
conversationId: conversation.id,
|
|
461254
|
-
pinnedIds: new Set(settingsManager.getMergedPinnedConversations(agentId).map((pinned) => pinned.conversationId))
|
|
461255
|
-
}),
|
|
461256
|
-
isPinnedLocal: settingsManager.getLocalPinnedConversations(agentId).includes(conversation.id)
|
|
460745
|
+
enriched: false
|
|
461257
460746
|
})));
|
|
461258
460747
|
} catch {
|
|
461259
460748
|
if (!cancelled) {
|
|
@@ -461292,16 +460781,6 @@ function ConversationSelector2({
|
|
|
461292
460781
|
}
|
|
461293
460782
|
return merged;
|
|
461294
460783
|
})() : conversations;
|
|
461295
|
-
import_react66.useEffect(() => {
|
|
461296
|
-
const conversationId = preserveSelectionIdRef.current;
|
|
461297
|
-
if (!conversationId)
|
|
461298
|
-
return;
|
|
461299
|
-
preserveSelectionIdRef.current = null;
|
|
461300
|
-
const nextSelectedIndex = findConversationIndexById2(filteredConversations, conversationId);
|
|
461301
|
-
if (nextSelectedIndex >= 0) {
|
|
461302
|
-
setSelectedIndex(nextSelectedIndex);
|
|
461303
|
-
}
|
|
461304
|
-
}, [filteredConversations]);
|
|
461305
460784
|
const startIndex = Math.max(0, Math.min(selectedIndex - Math.floor(listPageSize / 2), filteredConversations.length - listPageSize));
|
|
461306
460785
|
const visibleConversations = filteredConversations.slice(startIndex, startIndex + listPageSize);
|
|
461307
460786
|
import_react66.useEffect(() => {
|
|
@@ -461320,36 +460799,6 @@ function ConversationSelector2({
|
|
|
461320
460799
|
return;
|
|
461321
460800
|
await loadConversations(cursor);
|
|
461322
460801
|
}, [loadingMore, hasMore, cursor, loadConversations]);
|
|
461323
|
-
const togglePinnedConversation = import_react66.useCallback((selected) => {
|
|
461324
|
-
if (!selected?.conversation.id)
|
|
461325
|
-
return;
|
|
461326
|
-
const conversationId = selected.conversation.id;
|
|
461327
|
-
if (isDefaultConversationId2(conversationId)) {
|
|
461328
|
-
if (pinNoticeTimerRef.current) {
|
|
461329
|
-
clearTimeout(pinNoticeTimerRef.current);
|
|
461330
|
-
}
|
|
461331
|
-
setPinNotice("Default conversation is always pinned.");
|
|
461332
|
-
pinNoticeTimerRef.current = setTimeout(() => {
|
|
461333
|
-
pinNoticeTimerRef.current = null;
|
|
461334
|
-
setPinNotice(null);
|
|
461335
|
-
}, 2000);
|
|
461336
|
-
return;
|
|
461337
|
-
}
|
|
461338
|
-
setPinNotice(null);
|
|
461339
|
-
if (selected.isPinned) {
|
|
461340
|
-
settingsManager.unpinConversationBoth(agentId, conversationId);
|
|
461341
|
-
} else {
|
|
461342
|
-
settingsManager.pinConversationGlobal(agentId, conversationId);
|
|
461343
|
-
}
|
|
461344
|
-
preserveSelectionIdRef.current = conversationId;
|
|
461345
|
-
const updatePinState = (item) => item.conversation.id === conversationId ? {
|
|
461346
|
-
...item,
|
|
461347
|
-
isPinned: !selected.isPinned,
|
|
461348
|
-
isPinnedLocal: false
|
|
461349
|
-
} : item;
|
|
461350
|
-
setConversations((prev) => sortPinnedConversations2(prev.map(updatePinState)));
|
|
461351
|
-
setSearchResults((prev) => prev?.map(updatePinState) ?? null);
|
|
461352
|
-
}, [agentId]);
|
|
461353
460802
|
use_input_default((input, key2) => {
|
|
461354
460803
|
if (key2.ctrl && input === "c") {
|
|
461355
460804
|
onCancel();
|
|
@@ -461378,8 +460827,6 @@ function ConversationSelector2({
|
|
|
461378
460827
|
return;
|
|
461379
460828
|
}
|
|
461380
460829
|
onCancel();
|
|
461381
|
-
} else if (isPinShortcut2(input, key2)) {
|
|
461382
|
-
togglePinnedConversation(filteredConversations[selectedIndex]);
|
|
461383
460830
|
} else if (key2.leftArrow || key2.rightArrow) {
|
|
461384
460831
|
return;
|
|
461385
460832
|
}
|
|
@@ -461392,7 +460839,6 @@ function ConversationSelector2({
|
|
|
461392
460839
|
messageCount
|
|
461393
460840
|
} = enrichedConv;
|
|
461394
460841
|
const isCurrent = conv.id === currentConversationId;
|
|
461395
|
-
const isPinned = enrichedConv.isPinned;
|
|
461396
460842
|
const timestampText = formatConversationTimestampText2({
|
|
461397
460843
|
lastActiveAt,
|
|
461398
460844
|
createdAt: conv.created_at
|
|
@@ -461500,9 +460946,6 @@ function ConversationSelector2({
|
|
|
461500
460946
|
/* @__PURE__ */ jsx_dev_runtime40.jsxDEV(Text2, {
|
|
461501
460947
|
children: " "
|
|
461502
460948
|
}, undefined, false, undefined, this),
|
|
461503
|
-
isPinned && /* @__PURE__ */ jsx_dev_runtime40.jsxDEV(Text2, {
|
|
461504
|
-
children: "\uD83D\uDCCC "
|
|
461505
|
-
}, undefined, false, undefined, this),
|
|
461506
460949
|
/* @__PURE__ */ jsx_dev_runtime40.jsxDEV(Text2, {
|
|
461507
460950
|
bold: isSelected,
|
|
461508
460951
|
color: isSelected ? colors.selector.itemHighlighted : undefined,
|
|
@@ -461532,8 +460975,6 @@ function ConversationSelector2({
|
|
|
461532
460975
|
};
|
|
461533
460976
|
const terminalWidth = useTerminalWidth();
|
|
461534
460977
|
const solidLine = SOLID_LINE10.repeat(Math.max(terminalWidth, 10));
|
|
461535
|
-
const selectedConversation = filteredConversations[selectedIndex];
|
|
461536
|
-
const isSelectedDefaultConversation = selectedConversation ? isDefaultConversationId2(selectedConversation.conversation.id) : false;
|
|
461537
460978
|
return /* @__PURE__ */ jsx_dev_runtime40.jsxDEV(Box_default, {
|
|
461538
460979
|
flexDirection: "column",
|
|
461539
460980
|
children: [
|
|
@@ -461566,10 +461007,9 @@ function ConversationSelector2({
|
|
|
461566
461007
|
/* @__PURE__ */ jsx_dev_runtime40.jsxDEV(PasteAwareTextInput, {
|
|
461567
461008
|
value: searchInput,
|
|
461568
461009
|
onChange: (value) => {
|
|
461569
|
-
|
|
461570
|
-
if (nextSearchInput === searchInput)
|
|
461010
|
+
if (value === searchInput)
|
|
461571
461011
|
return;
|
|
461572
|
-
setSearchInput(
|
|
461012
|
+
setSearchInput(value);
|
|
461573
461013
|
setSelectedIndex(0);
|
|
461574
461014
|
},
|
|
461575
461015
|
placeholder: "search conversation titles"
|
|
@@ -461626,9 +461066,7 @@ function ConversationSelector2({
|
|
|
461626
461066
|
!loading && !error54 && filteredConversations.length > 0 && (() => {
|
|
461627
461067
|
const footerWidth = Math.max(0, terminalWidth - 2);
|
|
461628
461068
|
const pageText = `Showing ${startIndex + 1}-${Math.min(startIndex + visibleConversations.length, filteredConversations.length)} of ${filteredConversations.length}${!normalizedSearch && hasMore ? "+" : ""}${loadingMore ? " (loading...)" : ""}`;
|
|
461629
|
-
const hintsText = buildConversationSelectorHints2(
|
|
461630
|
-
isSelectedDefaultConversation
|
|
461631
|
-
});
|
|
461069
|
+
const hintsText = buildConversationSelectorHints2();
|
|
461632
461070
|
return /* @__PURE__ */ jsx_dev_runtime40.jsxDEV(Box_default, {
|
|
461633
461071
|
flexDirection: "column",
|
|
461634
461072
|
children: [
|
|
@@ -461665,23 +461103,6 @@ function ConversationSelector2({
|
|
|
461665
461103
|
}, undefined, false, undefined, this)
|
|
461666
461104
|
}, undefined, false, undefined, this)
|
|
461667
461105
|
]
|
|
461668
|
-
}, undefined, true, undefined, this),
|
|
461669
|
-
pinNotice && /* @__PURE__ */ jsx_dev_runtime40.jsxDEV(Box_default, {
|
|
461670
|
-
flexDirection: "row",
|
|
461671
|
-
children: [
|
|
461672
|
-
/* @__PURE__ */ jsx_dev_runtime40.jsxDEV(Box_default, {
|
|
461673
|
-
width: 2,
|
|
461674
|
-
flexShrink: 0
|
|
461675
|
-
}, undefined, false, undefined, this),
|
|
461676
|
-
/* @__PURE__ */ jsx_dev_runtime40.jsxDEV(Box_default, {
|
|
461677
|
-
flexGrow: 1,
|
|
461678
|
-
width: footerWidth,
|
|
461679
|
-
children: /* @__PURE__ */ jsx_dev_runtime40.jsxDEV(Text2, {
|
|
461680
|
-
color: "yellow",
|
|
461681
|
-
children: pinNotice
|
|
461682
|
-
}, undefined, false, undefined, this)
|
|
461683
|
-
}, undefined, false, undefined, this)
|
|
461684
|
-
]
|
|
461685
461106
|
}, undefined, true, undefined, this)
|
|
461686
461107
|
]
|
|
461687
461108
|
}, undefined, true, undefined, this);
|
|
@@ -461695,7 +461116,6 @@ var init_ConversationSelector = __esm(async () => {
|
|
|
461695
461116
|
init_glyphs();
|
|
461696
461117
|
init_use_terminal_width();
|
|
461697
461118
|
init_constants();
|
|
461698
|
-
init_settings_manager();
|
|
461699
461119
|
init_colors();
|
|
461700
461120
|
await __promiseAll([
|
|
461701
461121
|
init_build4(),
|
|
@@ -465193,9 +464613,7 @@ var init_AgentInfoBar = __esm(async () => {
|
|
|
465193
464613
|
const isPinned = import_react77.useMemo(() => {
|
|
465194
464614
|
if (!agentId)
|
|
465195
464615
|
return false;
|
|
465196
|
-
|
|
465197
|
-
const globalPinned = settingsManager.getGlobalPinnedAgents();
|
|
465198
|
-
return localPinned.includes(agentId) || globalPinned.includes(agentId);
|
|
464616
|
+
return settingsManager.isAgentPinned(agentId);
|
|
465199
464617
|
}, [agentId]);
|
|
465200
464618
|
const isCloudUser = serverUrl?.includes("api.letta.com");
|
|
465201
464619
|
const isLocalAgent = agentId ? isLocalAgentId3(agentId) : false;
|
|
@@ -465363,7 +464781,7 @@ import {
|
|
|
465363
464781
|
chmodSync as chmodSync7,
|
|
465364
464782
|
createWriteStream as createWriteStream4,
|
|
465365
464783
|
existsSync as existsSync54,
|
|
465366
|
-
mkdirSync as
|
|
464784
|
+
mkdirSync as mkdirSync38,
|
|
465367
464785
|
readdirSync as readdirSync21,
|
|
465368
464786
|
renameSync as renameSync5,
|
|
465369
464787
|
rmSync as rmSync11,
|
|
@@ -465989,7 +465407,7 @@ function SlashCommandAutocomplete({
|
|
|
465989
465407
|
onAutocomplete,
|
|
465990
465408
|
onActiveChange,
|
|
465991
465409
|
agentId,
|
|
465992
|
-
workingDirectory = process.cwd(),
|
|
465410
|
+
workingDirectory: _workingDirectory = process.cwd(),
|
|
465993
465411
|
modCommands = {}
|
|
465994
465412
|
}) {
|
|
465995
465413
|
const columns = useTerminalWidth();
|
|
@@ -466041,17 +465459,12 @@ function SlashCommandAutocomplete({
|
|
|
466041
465459
|
let builtins = _allCommands;
|
|
466042
465460
|
if (agentId) {
|
|
466043
465461
|
try {
|
|
466044
|
-
const
|
|
466045
|
-
const localPinned = settingsManager.getLocalPinnedAgents(workingDirectory);
|
|
466046
|
-
const isPinnedGlobally = globalPinned.includes(agentId);
|
|
466047
|
-
const isPinnedLocally = localPinned.includes(agentId);
|
|
466048
|
-
const isPinnedAnywhere = isPinnedGlobally || isPinnedLocally;
|
|
466049
|
-
const isPinnedBoth = isPinnedGlobally && isPinnedLocally;
|
|
465462
|
+
const isPinned = settingsManager.isAgentPinned(agentId);
|
|
466050
465463
|
builtins = _allCommands.filter((cmd) => {
|
|
466051
|
-
if (cmd.cmd === "/pin" &&
|
|
465464
|
+
if (cmd.cmd === "/pin" && isPinned) {
|
|
466052
465465
|
return false;
|
|
466053
465466
|
}
|
|
466054
|
-
if (cmd.cmd === "/unpin" && !
|
|
465467
|
+
if (cmd.cmd === "/unpin" && !isPinned) {
|
|
466055
465468
|
return false;
|
|
466056
465469
|
}
|
|
466057
465470
|
return true;
|
|
@@ -466081,7 +465494,7 @@ function SlashCommandAutocomplete({
|
|
|
466081
465494
|
...customCommands,
|
|
466082
465495
|
...visibleSkillCommands
|
|
466083
465496
|
].sort((a2, b3) => (a2.order ?? 100) - (b3.order ?? 100));
|
|
466084
|
-
}, [agentId,
|
|
465497
|
+
}, [agentId, modCommands, customCommands, skillCommands]);
|
|
466085
465498
|
const queryInfo = import_react80.useMemo(() => extractSearchQuery(currentInput, cursorPosition), [currentInput, cursorPosition]);
|
|
466086
465499
|
const { matches: matches2, showNoMatches, hideAutocomplete } = import_react80.useMemo(() => {
|
|
466087
465500
|
if (!queryInfo) {
|
|
@@ -468676,11 +468089,11 @@ var init_agents7 = __esm(() => {
|
|
|
468676
468089
|
import { execFileSync as execFileSync7 } from "node:child_process";
|
|
468677
468090
|
import {
|
|
468678
468091
|
existsSync as existsSync55,
|
|
468679
|
-
mkdirSync as
|
|
468092
|
+
mkdirSync as mkdirSync39,
|
|
468680
468093
|
mkdtempSync as mkdtempSync4,
|
|
468681
468094
|
readFileSync as readFileSync37,
|
|
468682
468095
|
rmSync as rmSync12,
|
|
468683
|
-
writeFileSync as
|
|
468096
|
+
writeFileSync as writeFileSync27
|
|
468684
468097
|
} from "node:fs";
|
|
468685
468098
|
import { tmpdir as tmpdir9 } from "node:os";
|
|
468686
468099
|
import { dirname as dirname28, join as join58 } from "node:path";
|
|
@@ -468918,7 +468331,7 @@ function runGit4(args, cwd2) {
|
|
|
468918
468331
|
function writeWorkflow(repoDir, workflowPath, content) {
|
|
468919
468332
|
const absolutePath = join58(repoDir, workflowPath);
|
|
468920
468333
|
if (!existsSync55(dirname28(absolutePath))) {
|
|
468921
|
-
|
|
468334
|
+
mkdirSync39(dirname28(absolutePath), { recursive: true });
|
|
468922
468335
|
}
|
|
468923
468336
|
const next = `${content.trimEnd()}
|
|
468924
468337
|
`;
|
|
@@ -468928,7 +468341,7 @@ function writeWorkflow(repoDir, workflowPath, content) {
|
|
|
468928
468341
|
return false;
|
|
468929
468342
|
}
|
|
468930
468343
|
}
|
|
468931
|
-
|
|
468344
|
+
writeFileSync27(absolutePath, next, "utf8");
|
|
468932
468345
|
return true;
|
|
468933
468346
|
}
|
|
468934
468347
|
function getDefaultBaseBranch(repoDir) {
|
|
@@ -473345,7 +472758,7 @@ __export(exports_generate_memory_viewer, {
|
|
|
473345
472758
|
generateAndOpenMemoryViewer: () => generateAndOpenMemoryViewer
|
|
473346
472759
|
});
|
|
473347
472760
|
import { execFile as execFileCb4 } from "node:child_process";
|
|
473348
|
-
import { chmodSync as chmodSync8, existsSync as existsSync56, mkdirSync as
|
|
472761
|
+
import { chmodSync as chmodSync8, existsSync as existsSync56, mkdirSync as mkdirSync40, writeFileSync as writeFileSync28 } from "node:fs";
|
|
473349
472762
|
import { homedir as homedir37 } from "node:os";
|
|
473350
472763
|
import { join as join59 } from "node:path";
|
|
473351
472764
|
import { promisify as promisify15 } from "node:util";
|
|
@@ -473667,13 +473080,13 @@ async function generateAndOpenMemoryViewer(agentId, options3) {
|
|
|
473667
473080
|
const jsonPayload = JSON.stringify(data).replace(/</g, "\\u003c");
|
|
473668
473081
|
const html5 = memory_viewer_template_default.replace("<!--LETTA_DATA_PLACEHOLDER-->", () => jsonPayload);
|
|
473669
473082
|
if (!existsSync56(VIEWERS_DIR)) {
|
|
473670
|
-
|
|
473083
|
+
mkdirSync40(VIEWERS_DIR, { recursive: true, mode: 448 });
|
|
473671
473084
|
}
|
|
473672
473085
|
try {
|
|
473673
473086
|
chmodSync8(VIEWERS_DIR, 448);
|
|
473674
473087
|
} catch {}
|
|
473675
473088
|
const filePath = join59(VIEWERS_DIR, `memory-${encodeURIComponent(agentId)}.html`);
|
|
473676
|
-
|
|
473089
|
+
writeFileSync28(filePath, html5);
|
|
473677
473090
|
chmodSync8(filePath, 384);
|
|
473678
473091
|
const skipOpen = Boolean(process.env.TMUX) || Boolean(process.env.SSH_CONNECTION) || Boolean(process.env.SSH_TTY);
|
|
473679
473092
|
if (!skipOpen) {
|
|
@@ -476086,7 +475499,7 @@ var init_PersonalitySelector = __esm(async () => {
|
|
|
476086
475499
|
});
|
|
476087
475500
|
|
|
476088
475501
|
// src/utils/aws-credentials.ts
|
|
476089
|
-
import { readFile as
|
|
475502
|
+
import { readFile as readFile19 } from "node:fs/promises";
|
|
476090
475503
|
import { homedir as homedir38 } from "node:os";
|
|
476091
475504
|
import { join as join61 } from "node:path";
|
|
476092
475505
|
async function parseAwsCredentials() {
|
|
@@ -476094,11 +475507,11 @@ async function parseAwsCredentials() {
|
|
|
476094
475507
|
const configPath = join61(homedir38(), ".aws", "config");
|
|
476095
475508
|
const profiles = new Map;
|
|
476096
475509
|
try {
|
|
476097
|
-
const content = await
|
|
475510
|
+
const content = await readFile19(credentialsPath, "utf-8");
|
|
476098
475511
|
parseIniFile(content, profiles, false);
|
|
476099
475512
|
} catch {}
|
|
476100
475513
|
try {
|
|
476101
|
-
const content = await
|
|
475514
|
+
const content = await readFile19(configPath, "utf-8");
|
|
476102
475515
|
parseIniFile(content, profiles, true);
|
|
476103
475516
|
} catch {}
|
|
476104
475517
|
return Array.from(profiles.values());
|
|
@@ -481162,7 +480575,7 @@ function ExitStats({
|
|
|
481162
480575
|
agentId,
|
|
481163
480576
|
conversationId
|
|
481164
480577
|
}) {
|
|
481165
|
-
const isPinned = agentName &&
|
|
480578
|
+
const isPinned = agentName && settingsManager.isAgentPinned(agentId);
|
|
481166
480579
|
return /* @__PURE__ */ jsx_dev_runtime88.jsxDEV(Box_default, {
|
|
481167
480580
|
flexDirection: "column",
|
|
481168
480581
|
marginTop: 1,
|
|
@@ -496676,9 +496089,9 @@ __export(exports_generate_diff_viewer, {
|
|
|
496676
496089
|
generateAndOpenDiffViewer: () => generateAndOpenDiffViewer
|
|
496677
496090
|
});
|
|
496678
496091
|
import { execFile as execFileCb5 } from "node:child_process";
|
|
496679
|
-
import { chmodSync as chmodSync9, existsSync as existsSync58, mkdirSync as
|
|
496092
|
+
import { chmodSync as chmodSync9, existsSync as existsSync58, mkdirSync as mkdirSync41, writeFileSync as writeFileSync29 } from "node:fs";
|
|
496680
496093
|
import { homedir as homedir39 } from "node:os";
|
|
496681
|
-
import { isAbsolute as
|
|
496094
|
+
import { isAbsolute as isAbsolute25, join as join62, resolve as resolve39 } from "node:path";
|
|
496682
496095
|
import { promisify as promisify16 } from "node:util";
|
|
496683
496096
|
async function runGit5(cwd2, args) {
|
|
496684
496097
|
try {
|
|
@@ -496876,7 +496289,7 @@ function escapeHtml2(value) {
|
|
|
496876
496289
|
function resolveTargetPath(targetPath) {
|
|
496877
496290
|
if (!targetPath?.trim())
|
|
496878
496291
|
return process.cwd();
|
|
496879
|
-
return
|
|
496292
|
+
return isAbsolute25(targetPath) ? targetPath : resolve39(process.cwd(), targetPath);
|
|
496880
496293
|
}
|
|
496881
496294
|
function shouldSkipOpen() {
|
|
496882
496295
|
return Boolean(process.env.TMUX) || Boolean(process.env.SSH_CONNECTION) || Boolean(process.env.SSH_TTY);
|
|
@@ -496898,13 +496311,13 @@ async function generateAndOpenDiffViewer(targetPath) {
|
|
|
496898
496311
|
const jsonPayload = JSON.stringify(payload).replace(/</g, "\\u003c");
|
|
496899
496312
|
const html5 = diff_viewer_template_default.replace("<!--LETTA_DIFF_DATA_PLACEHOLDER-->", () => jsonPayload);
|
|
496900
496313
|
if (!existsSync58(VIEWERS_DIR2)) {
|
|
496901
|
-
|
|
496314
|
+
mkdirSync41(VIEWERS_DIR2, { recursive: true, mode: 448 });
|
|
496902
496315
|
}
|
|
496903
496316
|
try {
|
|
496904
496317
|
chmodSync9(VIEWERS_DIR2, 448);
|
|
496905
496318
|
} catch {}
|
|
496906
496319
|
const filePath = join62(VIEWERS_DIR2, `diff-${encodeURIComponent(worktreePath)}.html`);
|
|
496907
|
-
|
|
496320
|
+
writeFileSync29(filePath, html5);
|
|
496908
496321
|
chmodSync9(filePath, 384);
|
|
496909
496322
|
const skipOpen = shouldSkipOpen();
|
|
496910
496323
|
if (!skipOpen) {
|
|
@@ -497071,7 +496484,6 @@ function AppView(props) {
|
|
|
497071
496484
|
pendingApprovals,
|
|
497072
496485
|
pendingConversationSwitchRef,
|
|
497073
496486
|
pendingIds,
|
|
497074
|
-
pinDialogLocal,
|
|
497075
496487
|
precomputedDiffsRef,
|
|
497076
496488
|
profileConfirmPending,
|
|
497077
496489
|
queueDisplay,
|
|
@@ -497892,15 +497304,13 @@ Open /mcp to attach or detach tools for this server.`, true);
|
|
|
497892
497304
|
}, undefined, false, undefined, this),
|
|
497893
497305
|
activeOverlay === "pin" && /* @__PURE__ */ jsx_dev_runtime94.jsxDEV(PinDialog, {
|
|
497894
497306
|
currentName: agentName || "",
|
|
497895
|
-
local: pinDialogLocal,
|
|
497896
497307
|
onSubmit: async (newName) => {
|
|
497897
497308
|
const overlayCommand = completeOverlay("pin");
|
|
497898
497309
|
setCommandRunning(true);
|
|
497899
497310
|
const cmd = overlayCommand ?? commandRunner.start("/pin", "Pinning agent...");
|
|
497900
|
-
const scopeText = pinDialogLocal ? "to this project" : "globally";
|
|
497901
497311
|
const displayName = newName || agentName || agentId.slice(0, 12);
|
|
497902
497312
|
cmd.update({
|
|
497903
|
-
output: `Pinning "${displayName}"
|
|
497313
|
+
output: `Pinning "${displayName}"...`,
|
|
497904
497314
|
phase: "running"
|
|
497905
497315
|
});
|
|
497906
497316
|
try {
|
|
@@ -497910,15 +497320,11 @@ Open /mcp to attach or detach tools for this server.`, true);
|
|
|
497910
497320
|
});
|
|
497911
497321
|
updateAgentName(newName);
|
|
497912
497322
|
}
|
|
497913
|
-
|
|
497914
|
-
settingsManager.pinLocal(agentId);
|
|
497915
|
-
} else {
|
|
497916
|
-
settingsManager.pinGlobal(agentId);
|
|
497917
|
-
}
|
|
497323
|
+
settingsManager.pinAgent(agentId);
|
|
497918
497324
|
if (newName && newName !== agentName) {
|
|
497919
497325
|
cmd.agentHint = `Your name is now "${newName}" — acknowledge this and save your new name to memory.`;
|
|
497920
497326
|
}
|
|
497921
|
-
cmd.finish(`Pinned "${newName || agentName || agentId.slice(0, 12)}"
|
|
497327
|
+
cmd.finish(`Pinned "${newName || agentName || agentId.slice(0, 12)}".`, true);
|
|
497922
497328
|
} catch (error54) {
|
|
497923
497329
|
cmd.fail(`Failed to pin: ${error54}`);
|
|
497924
497330
|
} finally {
|
|
@@ -503265,7 +502671,6 @@ var init_command_routing = __esm(() => {
|
|
|
503265
502671
|
"/search",
|
|
503266
502672
|
"/feedback",
|
|
503267
502673
|
"/pin",
|
|
503268
|
-
"/pin-local",
|
|
503269
502674
|
"/conversations",
|
|
503270
502675
|
"/profile"
|
|
503271
502676
|
]);
|
|
@@ -504563,8 +503968,8 @@ async function handleProfileSave(ctx, msg, profileName) {
|
|
|
504563
503968
|
try {
|
|
504564
503969
|
await getBackend().updateAgent(ctx.agentId, { name: profileName });
|
|
504565
503970
|
ctx.updateAgentName(profileName);
|
|
504566
|
-
settingsManager.
|
|
504567
|
-
updateCommandResult4(ctx.buffersRef, ctx.refreshDerived, cmdId, msg, `Pinned "${profileName}"
|
|
503971
|
+
settingsManager.pinAgent(ctx.agentId);
|
|
503972
|
+
updateCommandResult4(ctx.buffersRef, ctx.refreshDerived, cmdId, msg, `Pinned "${profileName}".`, true);
|
|
504568
503973
|
} catch (error54) {
|
|
504569
503974
|
const errorDetails = formatErrorDetails2(error54, ctx.agentId);
|
|
504570
503975
|
updateCommandResult4(ctx.buffersRef, ctx.refreshDerived, cmdId, msg, `Failed: ${errorDetails}`, false);
|
|
@@ -504624,23 +504029,9 @@ function handleProfileUsage(ctx, msg) {
|
|
|
504624
504029
|
/profile load <name> - load a profile
|
|
504625
504030
|
/profile delete <name> - delete a profile`, false);
|
|
504626
504031
|
}
|
|
504627
|
-
function parsePinArgs(argsStr) {
|
|
504628
|
-
const parts = argsStr.trim().split(/\s+/).filter(Boolean);
|
|
504629
|
-
const nameParts = [];
|
|
504630
|
-
let local = false;
|
|
504631
|
-
for (const part of parts) {
|
|
504632
|
-
if (part === "-l" || part === "--local") {
|
|
504633
|
-
local = true;
|
|
504634
|
-
} else {
|
|
504635
|
-
nameParts.push(part);
|
|
504636
|
-
}
|
|
504637
|
-
}
|
|
504638
|
-
return { local, name: nameParts.join(" ") || undefined };
|
|
504639
|
-
}
|
|
504640
504032
|
async function handlePin(ctx, msg, argsStr) {
|
|
504641
|
-
const
|
|
504642
|
-
const
|
|
504643
|
-
const globalPinned = settingsManager.getGlobalPinnedAgents();
|
|
504033
|
+
const name = argsStr.trim() || undefined;
|
|
504034
|
+
const pinned = settingsManager.getPinnedAgents();
|
|
504644
504035
|
if (name && name !== ctx.agentName) {
|
|
504645
504036
|
try {
|
|
504646
504037
|
await getBackend().updateAgent(ctx.agentId, { name });
|
|
@@ -504651,42 +504042,26 @@ async function handlePin(ctx, msg, argsStr) {
|
|
|
504651
504042
|
}
|
|
504652
504043
|
}
|
|
504653
504044
|
const displayName = name || ctx.agentName || ctx.agentId.slice(0, 12);
|
|
504654
|
-
if (
|
|
504655
|
-
|
|
504656
|
-
|
|
504657
|
-
return;
|
|
504658
|
-
}
|
|
504659
|
-
settingsManager.pinLocal(ctx.agentId);
|
|
504660
|
-
addCommandResult4(ctx.buffersRef, ctx.refreshDerived, msg, `Pinned "${displayName}" to this project.`, true);
|
|
504661
|
-
} else {
|
|
504662
|
-
if (globalPinned.includes(ctx.agentId)) {
|
|
504663
|
-
addCommandResult4(ctx.buffersRef, ctx.refreshDerived, msg, "This agent is already pinned globally.", false);
|
|
504664
|
-
return;
|
|
504665
|
-
}
|
|
504666
|
-
settingsManager.pinGlobal(ctx.agentId);
|
|
504667
|
-
addCommandResult4(ctx.buffersRef, ctx.refreshDerived, msg, `Pinned "${displayName}" globally.`, true);
|
|
504045
|
+
if (pinned.includes(ctx.agentId)) {
|
|
504046
|
+
addCommandResult4(ctx.buffersRef, ctx.refreshDerived, msg, "This agent is already pinned.", false);
|
|
504047
|
+
return;
|
|
504668
504048
|
}
|
|
504049
|
+
settingsManager.pinAgent(ctx.agentId);
|
|
504050
|
+
addCommandResult4(ctx.buffersRef, ctx.refreshDerived, msg, `Pinned "${displayName}".`, true);
|
|
504669
504051
|
}
|
|
504670
504052
|
function handleUnpin(ctx, msg, argsStr) {
|
|
504671
|
-
|
|
504672
|
-
|
|
504673
|
-
|
|
504053
|
+
if (argsStr.trim()) {
|
|
504054
|
+
addCommandResult4(ctx.buffersRef, ctx.refreshDerived, msg, "Usage: /unpin", false);
|
|
504055
|
+
return;
|
|
504056
|
+
}
|
|
504057
|
+
const pinned = settingsManager.getPinnedAgents();
|
|
504674
504058
|
const displayName = ctx.agentName || ctx.agentId.slice(0, 12);
|
|
504675
|
-
if (
|
|
504676
|
-
|
|
504677
|
-
|
|
504678
|
-
return;
|
|
504679
|
-
}
|
|
504680
|
-
settingsManager.unpinLocal(ctx.agentId);
|
|
504681
|
-
addCommandResult4(ctx.buffersRef, ctx.refreshDerived, msg, `Unpinned "${displayName}" from this project.`, true);
|
|
504682
|
-
} else {
|
|
504683
|
-
if (!globalPinned.includes(ctx.agentId)) {
|
|
504684
|
-
addCommandResult4(ctx.buffersRef, ctx.refreshDerived, msg, "This agent isn't pinned globally.", false);
|
|
504685
|
-
return;
|
|
504686
|
-
}
|
|
504687
|
-
settingsManager.unpinGlobal(ctx.agentId);
|
|
504688
|
-
addCommandResult4(ctx.buffersRef, ctx.refreshDerived, msg, `Unpinned "${displayName}" globally.`, true);
|
|
504059
|
+
if (!pinned.includes(ctx.agentId)) {
|
|
504060
|
+
addCommandResult4(ctx.buffersRef, ctx.refreshDerived, msg, "This agent isn't pinned.", false);
|
|
504061
|
+
return;
|
|
504689
504062
|
}
|
|
504063
|
+
settingsManager.unpinAgent(ctx.agentId);
|
|
504064
|
+
addCommandResult4(ctx.buffersRef, ctx.refreshDerived, msg, `Unpinned "${displayName}".`, true);
|
|
504690
504065
|
}
|
|
504691
504066
|
var activeCommandId4 = null;
|
|
504692
504067
|
var init_profile = __esm(() => {
|
|
@@ -504700,13 +504075,11 @@ async function handleProfileCommand(msg, trimmed, ctx) {
|
|
|
504700
504075
|
const {
|
|
504701
504076
|
agentId,
|
|
504702
504077
|
agentName,
|
|
504703
|
-
conversationId,
|
|
504704
504078
|
buffersRef,
|
|
504705
504079
|
commandRunner,
|
|
504706
504080
|
handleAgentSelect,
|
|
504707
504081
|
refreshDerived,
|
|
504708
504082
|
setCommandRunning,
|
|
504709
|
-
setPinDialogLocal,
|
|
504710
504083
|
setProfileConfirmPending,
|
|
504711
504084
|
openOverlay,
|
|
504712
504085
|
updateAgentName
|
|
@@ -504772,68 +504145,8 @@ Press Enter to continue, or type anything to cancel.`, false, "running");
|
|
|
504772
504145
|
}
|
|
504773
504146
|
if (trimmed === "/pin" || trimmed.startsWith("/pin ")) {
|
|
504774
504147
|
const argsStr = trimmed.slice(4).trim();
|
|
504775
|
-
|
|
504776
|
-
|
|
504777
|
-
if (target2 === "help") {
|
|
504778
|
-
const cmd2 = commandRunner.start(trimmed, "Showing pin help...");
|
|
504779
|
-
const output = [
|
|
504780
|
-
"/pin help",
|
|
504781
|
-
"",
|
|
504782
|
-
"Pin agents and conversations.",
|
|
504783
|
-
"",
|
|
504784
|
-
"USAGE",
|
|
504785
|
-
" /pin [name] — pin the current agent globally",
|
|
504786
|
-
" /pin -l [name] — pin the current agent to this project",
|
|
504787
|
-
" /pin agent [name] — pin the current agent",
|
|
504788
|
-
" /pin convo [-l] — pin the current conversation",
|
|
504789
|
-
" /pin help — show this help"
|
|
504790
|
-
].join(`
|
|
504791
|
-
`);
|
|
504792
|
-
cmd2.finish(output, true);
|
|
504793
|
-
return { submitted: true };
|
|
504794
|
-
}
|
|
504795
|
-
if (target2 === "convo" || target2 === "conversation") {
|
|
504796
|
-
const convoArgs = parts.slice(1);
|
|
504797
|
-
const local = convoArgs.some((part) => part === "-l" || part === "--local");
|
|
504798
|
-
const hasUnsupportedArg = convoArgs.some((part) => part !== "-l" && part !== "--local");
|
|
504799
|
-
const cmd2 = commandRunner.start(trimmed, "Pinning conversation...");
|
|
504800
|
-
if (hasUnsupportedArg) {
|
|
504801
|
-
cmd2.fail("Usage: /pin convo [-l]");
|
|
504802
|
-
return { submitted: true };
|
|
504803
|
-
}
|
|
504804
|
-
const pinnedIds = local ? settingsManager.getLocalPinnedConversations(agentId) : settingsManager.getGlobalPinnedConversations(agentId);
|
|
504805
|
-
const scopeText = local ? "to this project" : "globally";
|
|
504806
|
-
if (pinnedIds.includes(conversationId)) {
|
|
504807
|
-
cmd2.fail(`This conversation is already pinned ${scopeText}.`);
|
|
504808
|
-
return { submitted: true };
|
|
504809
|
-
}
|
|
504810
|
-
if (local) {
|
|
504811
|
-
settingsManager.pinConversationLocal(agentId, conversationId);
|
|
504812
|
-
} else {
|
|
504813
|
-
settingsManager.pinConversationGlobal(agentId, conversationId);
|
|
504814
|
-
}
|
|
504815
|
-
cmd2.finish(`Pinned current conversation ${scopeText}.`, true);
|
|
504816
|
-
return { submitted: true };
|
|
504817
|
-
}
|
|
504818
|
-
if (target2 === "convos" || target2 === "conversations" || target2 === "agents") {
|
|
504819
|
-
const cmd2 = commandRunner.start(trimmed, "Checking pin command...");
|
|
504820
|
-
cmd2.fail("Usage: /pin agent [name] or /pin convo [-l]");
|
|
504821
|
-
return { submitted: true };
|
|
504822
|
-
}
|
|
504823
|
-
const currentArgs = target2 === "agent" ? parts.slice(1).join(" ") : argsStr;
|
|
504824
|
-
const currentParts = currentArgs.split(/\s+/).filter(Boolean);
|
|
504825
|
-
let hasNameArg = false;
|
|
504826
|
-
let isLocal = false;
|
|
504827
|
-
for (const part of currentParts) {
|
|
504828
|
-
if (part === "-l" || part === "--local") {
|
|
504829
|
-
isLocal = true;
|
|
504830
|
-
} else {
|
|
504831
|
-
hasNameArg = true;
|
|
504832
|
-
}
|
|
504833
|
-
}
|
|
504834
|
-
if (!hasNameArg && target2 !== "agent") {
|
|
504835
|
-
setPinDialogLocal(isLocal);
|
|
504836
|
-
openOverlay("pin", target2 === "agent" ? "/pin agent" : "/pin", "Opening pin dialog...", "Pin dialog dismissed");
|
|
504148
|
+
if (!argsStr) {
|
|
504149
|
+
openOverlay("pin", "/pin", "Opening pin dialog...", "Pin dialog dismissed");
|
|
504837
504150
|
return { submitted: true };
|
|
504838
504151
|
}
|
|
504839
504152
|
const profileCtx = {
|
|
@@ -504847,30 +504160,13 @@ Press Enter to continue, or type anything to cancel.`, false, "running");
|
|
|
504847
504160
|
const cmd = commandRunner.start(trimmed, "Pinning agent...");
|
|
504848
504161
|
setActiveCommandId4(cmd.id);
|
|
504849
504162
|
try {
|
|
504850
|
-
await handlePin(profileCtx, msg,
|
|
504163
|
+
await handlePin(profileCtx, msg, argsStr);
|
|
504851
504164
|
} finally {
|
|
504852
504165
|
setActiveCommandId4(null);
|
|
504853
504166
|
}
|
|
504854
504167
|
return { submitted: true };
|
|
504855
504168
|
}
|
|
504856
504169
|
if (trimmed === "/unpin" || trimmed.startsWith("/unpin ")) {
|
|
504857
|
-
const unpinArgsStr = trimmed.slice(6).trim();
|
|
504858
|
-
if (unpinArgsStr === "help") {
|
|
504859
|
-
const cmd2 = commandRunner.start(trimmed, "Showing unpin help...");
|
|
504860
|
-
const output = [
|
|
504861
|
-
"/unpin help",
|
|
504862
|
-
"",
|
|
504863
|
-
"Unpin the current agent.",
|
|
504864
|
-
"",
|
|
504865
|
-
"USAGE",
|
|
504866
|
-
" /unpin — unpin globally",
|
|
504867
|
-
" /unpin -l — unpin locally",
|
|
504868
|
-
" /unpin help — show this help"
|
|
504869
|
-
].join(`
|
|
504870
|
-
`);
|
|
504871
|
-
cmd2.finish(output, true);
|
|
504872
|
-
return { submitted: true };
|
|
504873
|
-
}
|
|
504874
504170
|
const profileCtx = {
|
|
504875
504171
|
buffersRef,
|
|
504876
504172
|
refreshDerived,
|
|
@@ -504893,7 +504189,6 @@ Press Enter to continue, or type anything to cancel.`, false, "running");
|
|
|
504893
504189
|
}
|
|
504894
504190
|
var init_submit_profile_commands = __esm(() => {
|
|
504895
504191
|
init_profile();
|
|
504896
|
-
init_settings_manager();
|
|
504897
504192
|
});
|
|
504898
504193
|
|
|
504899
504194
|
// src/web/worktree-diff-list.ts
|
|
@@ -505046,7 +504341,7 @@ var exports_export = {};
|
|
|
505046
504341
|
__export(exports_export, {
|
|
505047
504342
|
packageSkills: () => packageSkills
|
|
505048
504343
|
});
|
|
505049
|
-
import { readdir as readdir14, readFile as
|
|
504344
|
+
import { readdir as readdir14, readFile as readFile20 } from "node:fs/promises";
|
|
505050
504345
|
import { relative as relative13, resolve as resolve40 } from "node:path";
|
|
505051
504346
|
async function packageSkills(agentId, skillsDir) {
|
|
505052
504347
|
const skills = [];
|
|
@@ -505067,7 +504362,7 @@ async function packageSkills(agentId, skillsDir) {
|
|
|
505067
504362
|
const skillDir = resolve40(baseDir, entry.name);
|
|
505068
504363
|
const skillMdPath = resolve40(skillDir, "SKILL.md");
|
|
505069
504364
|
try {
|
|
505070
|
-
await
|
|
504365
|
+
await readFile20(skillMdPath, "utf-8");
|
|
505071
504366
|
} catch {
|
|
505072
504367
|
console.warn(`Skipping invalid skill ${entry.name}: missing SKILL.md`);
|
|
505073
504368
|
continue;
|
|
@@ -505099,7 +504394,7 @@ async function readSkillFiles(skillDir) {
|
|
|
505099
504394
|
if (entry.isDirectory()) {
|
|
505100
504395
|
await walk(fullPath);
|
|
505101
504396
|
} else {
|
|
505102
|
-
const content = await
|
|
504397
|
+
const content = await readFile20(fullPath, "utf-8");
|
|
505103
504398
|
const relativePath = relative13(skillDir, fullPath).replace(/\\/g, "/");
|
|
505104
504399
|
files[relativePath] = content;
|
|
505105
504400
|
}
|
|
@@ -505235,7 +504530,7 @@ var init_conversation_switch_alert = __esm(() => {
|
|
|
505235
504530
|
|
|
505236
504531
|
// src/cli/app/use-submit-handler.ts
|
|
505237
504532
|
import { randomUUID as randomUUID33 } from "node:crypto";
|
|
505238
|
-
import { existsSync as existsSync60, readFileSync as readFileSync39, renameSync as renameSync6, writeFileSync as
|
|
504533
|
+
import { existsSync as existsSync60, readFileSync as readFileSync39, renameSync as renameSync6, writeFileSync as writeFileSync30 } from "node:fs";
|
|
505239
504534
|
import { tmpdir as tmpdir10 } from "node:os";
|
|
505240
504535
|
import { join as join64 } from "node:path";
|
|
505241
504536
|
async function findCustomCommandByName(commandName) {
|
|
@@ -505323,7 +504618,6 @@ function useSubmitHandler(ctx) {
|
|
|
505323
504618
|
markLocalModelsAvailable,
|
|
505324
504619
|
setModelSelectorOptions,
|
|
505325
504620
|
setNeedsEagerApprovalCheck,
|
|
505326
|
-
setPinDialogLocal,
|
|
505327
504621
|
setProfileConfirmPending,
|
|
505328
504622
|
setWorktreeDiffSelectorPending,
|
|
505329
504623
|
setReasoningTabCycleEnabled,
|
|
@@ -506522,14 +505816,12 @@ ${formatGoalSummary(goal)}`, true);
|
|
|
506522
505816
|
const profileCommandResult = await handleProfileCommand(msg, trimmed, {
|
|
506523
505817
|
agentId,
|
|
506524
505818
|
agentName,
|
|
506525
|
-
conversationId,
|
|
506526
505819
|
buffersRef,
|
|
506527
505820
|
commandRunner,
|
|
506528
505821
|
handleAgentSelect,
|
|
506529
505822
|
refreshDerived,
|
|
506530
505823
|
openOverlay,
|
|
506531
505824
|
setCommandRunning,
|
|
506532
|
-
setPinDialogLocal,
|
|
506533
505825
|
setProfileConfirmPending,
|
|
506534
505826
|
updateAgentName
|
|
506535
505827
|
});
|
|
@@ -506575,7 +505867,7 @@ ${formatGoalSummary(goal)}`, true);
|
|
|
506575
505867
|
fileContent.skills = skills;
|
|
506576
505868
|
}
|
|
506577
505869
|
const fileName = exportParams.conversation_id ? `${exportParams.conversation_id}.af` : `${agentId}.af`;
|
|
506578
|
-
|
|
505870
|
+
writeFileSync30(fileName, JSON.stringify(fileContent, null, 2));
|
|
506579
505871
|
let summary = `AgentFile exported to ${fileName}`;
|
|
506580
505872
|
if (skills.length > 0) {
|
|
506581
505873
|
summary += `
|
|
@@ -507662,7 +506954,6 @@ function App2({
|
|
|
507662
506954
|
setModelReasoningPrompt(null);
|
|
507663
506955
|
}, [activeOverlay]);
|
|
507664
506956
|
const [queuedOverlayAction, setQueuedOverlayAction] = import_react123.useState(null);
|
|
507665
|
-
const [pinDialogLocal, setPinDialogLocal] = import_react123.useState(false);
|
|
507666
506957
|
const anySelectorOpen = activeOverlay !== null;
|
|
507667
506958
|
const [currentSystemPromptId, setCurrentSystemPromptId] = import_react123.useState("default");
|
|
507668
506959
|
const [currentPersonalityId, setCurrentPersonalityId] = import_react123.useState(null);
|
|
@@ -509029,7 +508320,7 @@ function App2({
|
|
|
509029
508320
|
}
|
|
509030
508321
|
backfillBuffers(buffersRef.current, messageHistory);
|
|
509031
508322
|
const statusId = `status-resumed-${Date.now().toString(36)}`;
|
|
509032
|
-
const isPinned = agentState?.id ? settingsManager.
|
|
508323
|
+
const isPinned = agentState?.id ? settingsManager.isAgentPinned(agentState.id) : false;
|
|
509033
508324
|
const agentName2 = agentState?.name || "Unnamed Agent";
|
|
509034
508325
|
const isResumingConversation = resumedExistingConversation || messageHistory.length > 0;
|
|
509035
508326
|
if (isDebugEnabled()) {
|
|
@@ -509924,7 +509215,6 @@ Memory may be stale. Try running: git -C ${getScopedMemoryFilesystemRoot(agentId
|
|
|
509924
509215
|
markLocalModelsAvailable,
|
|
509925
509216
|
setModelSelectorOptions,
|
|
509926
509217
|
setNeedsEagerApprovalCheck,
|
|
509927
|
-
setPinDialogLocal,
|
|
509928
509218
|
setProfileConfirmPending,
|
|
509929
509219
|
setWorktreeDiffSelectorPending,
|
|
509930
509220
|
setReasoningTabCycleEnabled: _setReasoningTabCycleEnabled,
|
|
@@ -510353,7 +509643,7 @@ Memory may be stale. Try running: git -C ${getScopedMemoryFilesystemRoot(agentId
|
|
|
510353
509643
|
}
|
|
510354
509644
|
]);
|
|
510355
509645
|
const statusId = `status-agent-${Date.now().toString(36)}`;
|
|
510356
|
-
const isPinned = agentState?.id ? settingsManager.
|
|
509646
|
+
const isPinned = agentState?.id ? settingsManager.isAgentPinned(agentState.id) : false;
|
|
510357
509647
|
const agentName2 = agentState?.name || "Unnamed Agent";
|
|
510358
509648
|
const headerMessage = resumedExistingConversation ? `Resuming new conversation with **${agentName2}**` : continueSession ? `Starting new conversation with **${agentName2}**` : "Creating a new agent";
|
|
510359
509649
|
const commandHints = buildStartupCommandHints({
|
|
@@ -510521,7 +509811,6 @@ Memory may be stale. Try running: git -C ${getScopedMemoryFilesystemRoot(agentId
|
|
|
510521
509811
|
pendingApprovals,
|
|
510522
509812
|
pendingConversationSwitchRef,
|
|
510523
509813
|
pendingIds,
|
|
510524
|
-
pinDialogLocal,
|
|
510525
509814
|
precomputedDiffsRef,
|
|
510526
509815
|
profileConfirmPending,
|
|
510527
509816
|
queueDisplay,
|
|
@@ -510693,9 +509982,9 @@ __export(exports_terminal_keybinding_installer2, {
|
|
|
510693
509982
|
import {
|
|
510694
509983
|
copyFileSync as copyFileSync4,
|
|
510695
509984
|
existsSync as existsSync61,
|
|
510696
|
-
mkdirSync as
|
|
509985
|
+
mkdirSync as mkdirSync42,
|
|
510697
509986
|
readFileSync as readFileSync40,
|
|
510698
|
-
writeFileSync as
|
|
509987
|
+
writeFileSync as writeFileSync31
|
|
510699
509988
|
} from "node:fs";
|
|
510700
509989
|
import { homedir as homedir42, platform as platform11 } from "node:os";
|
|
510701
509990
|
import { dirname as dirname29, join as join65 } from "node:path";
|
|
@@ -510791,7 +510080,7 @@ function installKeybinding2(keybindingsPath) {
|
|
|
510791
510080
|
}
|
|
510792
510081
|
const parentDir = dirname29(keybindingsPath);
|
|
510793
510082
|
if (!existsSync61(parentDir)) {
|
|
510794
|
-
|
|
510083
|
+
mkdirSync42(parentDir, { recursive: true });
|
|
510795
510084
|
}
|
|
510796
510085
|
let keybindings = [];
|
|
510797
510086
|
let backupPath = null;
|
|
@@ -510810,7 +510099,7 @@ function installKeybinding2(keybindingsPath) {
|
|
|
510810
510099
|
keybindings.push(SHIFT_ENTER_KEYBINDING2);
|
|
510811
510100
|
const newContent = `${JSON.stringify(keybindings, null, 2)}
|
|
510812
510101
|
`;
|
|
510813
|
-
|
|
510102
|
+
writeFileSync31(keybindingsPath, newContent, { encoding: "utf-8" });
|
|
510814
510103
|
return {
|
|
510815
510104
|
success: true,
|
|
510816
510105
|
backupPath: backupPath ?? undefined
|
|
@@ -510839,7 +510128,7 @@ function removeKeybinding2(keybindingsPath) {
|
|
|
510839
510128
|
const filtered = keybindings.filter((kb) => !(kb.key?.toLowerCase() === "shift+enter" && kb.command === "workbench.action.terminal.sendSequence" && kb.when?.includes("terminalFocus")));
|
|
510840
510129
|
const newContent = `${JSON.stringify(filtered, null, 2)}
|
|
510841
510130
|
`;
|
|
510842
|
-
|
|
510131
|
+
writeFileSync31(keybindingsPath, newContent, { encoding: "utf-8" });
|
|
510843
510132
|
return { success: true };
|
|
510844
510133
|
} catch (error54) {
|
|
510845
510134
|
const message = error54 instanceof Error ? error54.message : String(error54);
|
|
@@ -511027,9 +510316,9 @@ function installWezTermDeleteFix2() {
|
|
|
511027
510316
|
content = injectWezTermDeleteFix2(content);
|
|
511028
510317
|
const parentDir = dirname29(configPath);
|
|
511029
510318
|
if (!existsSync61(parentDir)) {
|
|
511030
|
-
|
|
510319
|
+
mkdirSync42(parentDir, { recursive: true });
|
|
511031
510320
|
}
|
|
511032
|
-
|
|
510321
|
+
writeFileSync31(configPath, content, { encoding: "utf-8" });
|
|
511033
510322
|
return {
|
|
511034
510323
|
success: true,
|
|
511035
510324
|
backupPath: backupPath ?? undefined
|
|
@@ -511256,15 +510545,15 @@ function resolveStartupTarget(input) {
|
|
|
511256
510545
|
if (input.forceNew) {
|
|
511257
510546
|
return { action: "create" };
|
|
511258
510547
|
}
|
|
511259
|
-
if (input.
|
|
511260
|
-
const conversationId = input.
|
|
510548
|
+
if (input.pinnedAgentId && input.pinnedAgentExists) {
|
|
510549
|
+
const conversationId = input.pinnedAgentId === input.localAgentId ? input.localConversationId ?? undefined : undefined;
|
|
511261
510550
|
return {
|
|
511262
510551
|
action: "resume",
|
|
511263
|
-
agentId: input.
|
|
510552
|
+
agentId: input.pinnedAgentId,
|
|
511264
510553
|
...conversationId ? { conversationId } : {}
|
|
511265
510554
|
};
|
|
511266
510555
|
}
|
|
511267
|
-
if (input.
|
|
510556
|
+
if (input.pinnedCount > 1) {
|
|
511268
510557
|
return { action: "select" };
|
|
511269
510558
|
}
|
|
511270
510559
|
if (input.localAgentId && input.localAgentExists) {
|
|
@@ -511290,7 +510579,7 @@ function resolveStartupTarget(input) {
|
|
|
511290
510579
|
if (input.needsModelPicker) {
|
|
511291
510580
|
return { action: "select" };
|
|
511292
510581
|
}
|
|
511293
|
-
if (input.
|
|
510582
|
+
if (input.pinnedCount > 0) {
|
|
511294
510583
|
return { action: "select" };
|
|
511295
510584
|
}
|
|
511296
510585
|
return { action: "create" };
|
|
@@ -511379,7 +510668,7 @@ async function ensureDefaultAgents2(backend4, options3) {
|
|
|
511379
510668
|
memoryPromptMode
|
|
511380
510669
|
});
|
|
511381
510670
|
await addTagToAgent2(backend4, agent2.id, MEMO_TAG2);
|
|
511382
|
-
settingsManager.
|
|
510671
|
+
settingsManager.pinAgent(agent2.id);
|
|
511383
510672
|
if (backend4.capabilities.remoteMemfs) {
|
|
511384
510673
|
enableMemfsIfCloud2(agent2.id, backend4);
|
|
511385
510674
|
}
|
|
@@ -511641,8 +510930,8 @@ __export(exports_import2, {
|
|
|
511641
510930
|
extractSkillsFromAf: () => extractSkillsFromAf2
|
|
511642
510931
|
});
|
|
511643
510932
|
import { createReadStream as createReadStream3 } from "node:fs";
|
|
511644
|
-
import { access as access3, chmod as chmod2, mkdir as mkdir14, readFile as
|
|
511645
|
-
import { dirname as dirname30, isAbsolute as
|
|
510933
|
+
import { access as access3, chmod as chmod2, mkdir as mkdir14, readFile as readFile21, writeFile as writeFile16 } from "node:fs/promises";
|
|
510934
|
+
import { dirname as dirname30, isAbsolute as isAbsolute26, relative as relative14, resolve as resolve41, sep as sep7, win32 as win325 } from "node:path";
|
|
511646
510935
|
function validateImportedSkillName2(name) {
|
|
511647
510936
|
const trimmedName = name.trim();
|
|
511648
510937
|
if (trimmedName !== name || trimmedName.length === 0 || trimmedName.length > MAX_SKILL_NAME_LENGTH || trimmedName === "." || trimmedName === ".." || !IMPORTED_SKILL_NAME_PATTERN2.test(trimmedName)) {
|
|
@@ -511654,12 +510943,12 @@ function assertPathInside2(parent, child) {
|
|
|
511654
510943
|
const parentPath = resolve41(parent);
|
|
511655
510944
|
const childPath = resolve41(child);
|
|
511656
510945
|
const relativePath = relative14(parentPath, childPath);
|
|
511657
|
-
if (relativePath === "" || relativePath === ".." || relativePath.startsWith(`..${sep7}`) ||
|
|
510946
|
+
if (relativePath === "" || relativePath === ".." || relativePath.startsWith(`..${sep7}`) || isAbsolute26(relativePath)) {
|
|
511658
510947
|
throw new Error(`Imported skill file path escapes skill directory: ${child}`);
|
|
511659
510948
|
}
|
|
511660
510949
|
}
|
|
511661
510950
|
function validateImportedSkillFilePath2(filePath) {
|
|
511662
|
-
if (filePath.length === 0 || filePath === "." || filePath.includes("\x00") || filePath.includes("\\") ||
|
|
510951
|
+
if (filePath.length === 0 || filePath === "." || filePath.includes("\x00") || filePath.includes("\\") || isAbsolute26(filePath) || win325.isAbsolute(filePath)) {
|
|
511663
510952
|
throw new Error(`Invalid imported skill file path "${filePath}".`);
|
|
511664
510953
|
}
|
|
511665
510954
|
const segments = filePath.split("/");
|
|
@@ -511744,7 +511033,7 @@ async function importAgentFromFile2(options3) {
|
|
|
511744
511033
|
}
|
|
511745
511034
|
async function extractSkillsFromAf2(afPath, destDir) {
|
|
511746
511035
|
const extracted = [];
|
|
511747
|
-
const content = await
|
|
511036
|
+
const content = await readFile21(afPath, "utf-8");
|
|
511748
511037
|
const afData = JSON.parse(content);
|
|
511749
511038
|
if (!afData.skills || !Array.isArray(afData.skills)) {
|
|
511750
511039
|
return [];
|
|
@@ -511890,7 +511179,7 @@ __export(exports_memory_filesystem2, {
|
|
|
511890
511179
|
MEMORY_FS_MEMORY_DIR: () => MEMORY_FS_MEMORY_DIR2,
|
|
511891
511180
|
MEMORY_FS_AGENTS_DIR: () => MEMORY_FS_AGENTS_DIR2
|
|
511892
511181
|
});
|
|
511893
|
-
import { existsSync as existsSync62, mkdirSync as
|
|
511182
|
+
import { existsSync as existsSync62, mkdirSync as mkdirSync43 } from "node:fs";
|
|
511894
511183
|
import { homedir as homedir44 } from "node:os";
|
|
511895
511184
|
import { join as join67, resolve as resolve42 } from "node:path";
|
|
511896
511185
|
function getMemoryFilesystemRoot2(agentId, homeDir = homedir44()) {
|
|
@@ -511934,10 +511223,10 @@ function ensureMemoryFilesystemDirs2(agentId, homeDir = homedir44()) {
|
|
|
511934
511223
|
const root2 = getMemoryFilesystemRoot2(agentId, homeDir);
|
|
511935
511224
|
const systemDir = getMemorySystemDir2(agentId, homeDir);
|
|
511936
511225
|
if (!existsSync62(root2)) {
|
|
511937
|
-
|
|
511226
|
+
mkdirSync43(root2, { recursive: true });
|
|
511938
511227
|
}
|
|
511939
511228
|
if (!existsSync62(systemDir)) {
|
|
511940
|
-
|
|
511229
|
+
mkdirSync43(systemDir, { recursive: true });
|
|
511941
511230
|
}
|
|
511942
511231
|
}
|
|
511943
511232
|
async function hydrateMemfsSettingFromAgent2(agent2) {
|
|
@@ -512386,9 +511675,9 @@ __export(exports_system_prompt_versioning2, {
|
|
|
512386
511675
|
LETTA_CODE_SUBAGENT_TAG: () => LETTA_CODE_SUBAGENT_TAG2,
|
|
512387
511676
|
LETTA_CODE_ORIGIN_TAG: () => LETTA_CODE_ORIGIN_TAG2
|
|
512388
511677
|
});
|
|
512389
|
-
import { createHash as
|
|
511678
|
+
import { createHash as createHash6 } from "node:crypto";
|
|
512390
511679
|
function hashSystemPrompt2(content) {
|
|
512391
|
-
const digest =
|
|
511680
|
+
const digest = createHash6("sha256").update(content).digest("base64url");
|
|
512392
511681
|
return `${SYSTEM_PROMPT_HASH_PREFIX2}${digest}`;
|
|
512393
511682
|
}
|
|
512394
511683
|
function managedPrompt2(preset, memoryMode, content = buildSystemPrompt(preset, memoryMode)) {
|
|
@@ -514354,7 +513643,6 @@ init_backend2();
|
|
|
514354
513643
|
init_glyphs();
|
|
514355
513644
|
init_use_terminal_width();
|
|
514356
513645
|
init_constants();
|
|
514357
|
-
init_settings_manager();
|
|
514358
513646
|
init_colors();
|
|
514359
513647
|
await __promiseAll([
|
|
514360
513648
|
init_build4(),
|
|
@@ -514365,16 +513653,6 @@ await __promiseAll([
|
|
|
514365
513653
|
var import_react26 = __toESM(require_react(), 1);
|
|
514366
513654
|
var jsx_dev_runtime6 = __toESM(require_jsx_dev_runtime(), 1);
|
|
514367
513655
|
var SOLID_LINE = "─";
|
|
514368
|
-
function isPinShortcut(input, key2) {
|
|
514369
|
-
if (key2.ctrl)
|
|
514370
|
-
return false;
|
|
514371
|
-
if (input === "π" || input === "∏")
|
|
514372
|
-
return true;
|
|
514373
|
-
if (!key2.meta)
|
|
514374
|
-
return false;
|
|
514375
|
-
const normalizedInput = input.replaceAll("\x1B", "");
|
|
514376
|
-
return normalizedInput === "p" || normalizedInput === "P";
|
|
514377
|
-
}
|
|
514378
513656
|
var MAX_DISPLAY_PAGE_SIZE = 5;
|
|
514379
513657
|
var FETCH_PAGE_SIZE = 20;
|
|
514380
513658
|
var ENRICH_MESSAGE_LIMIT = 20;
|
|
@@ -514382,29 +513660,8 @@ var RESUME_PREVIEW_MESSAGE_TYPES = [
|
|
|
514382
513660
|
"user_message",
|
|
514383
513661
|
"assistant_message"
|
|
514384
513662
|
];
|
|
514385
|
-
function
|
|
514386
|
-
return
|
|
514387
|
-
}
|
|
514388
|
-
function isConversationPinned(params) {
|
|
514389
|
-
return isDefaultConversationId(params.conversationId) ? true : params.pinnedIds.has(params.conversationId);
|
|
514390
|
-
}
|
|
514391
|
-
function buildConversationSelectorHints(params) {
|
|
514392
|
-
return params.isSelectedDefaultConversation ? "Enter select · ↑↓ navigate · Esc clear/cancel" : "Enter select · ↑↓ navigate · Alt+P pin/unpin · Esc clear/cancel";
|
|
514393
|
-
}
|
|
514394
|
-
function normalizeConversationSearchInput(value) {
|
|
514395
|
-
return value.replace(/[π∏]/g, "");
|
|
514396
|
-
}
|
|
514397
|
-
function findConversationIndexById(items3, conversationId) {
|
|
514398
|
-
return items3.findIndex((item) => item.conversation.id === conversationId);
|
|
514399
|
-
}
|
|
514400
|
-
function sortPinnedConversations(items3) {
|
|
514401
|
-
return [...items3].sort((a2, b3) => {
|
|
514402
|
-
if (a2.conversation.id === "default")
|
|
514403
|
-
return -1;
|
|
514404
|
-
if (b3.conversation.id === "default")
|
|
514405
|
-
return 1;
|
|
514406
|
-
return Number(b3.isPinned) - Number(a2.isPinned);
|
|
514407
|
-
});
|
|
513663
|
+
function buildConversationSelectorHints() {
|
|
513664
|
+
return "Enter select · ↑↓ navigate · Esc clear/cancel";
|
|
514408
513665
|
}
|
|
514409
513666
|
function paginatedItems2(value) {
|
|
514410
513667
|
return Array.isArray(value) ? value : value.getPaginatedItems();
|
|
@@ -514535,18 +513792,9 @@ function buildDefaultConversationEntry(agentId, stats, createdAt = null) {
|
|
|
514535
513792
|
previewLines: stats.previewLines,
|
|
514536
513793
|
lastActiveAt: stats.lastActiveAt,
|
|
514537
513794
|
messageCount: stats.messageCount,
|
|
514538
|
-
enriched: true
|
|
514539
|
-
isPinned: false,
|
|
514540
|
-
isPinnedLocal: false
|
|
513795
|
+
enriched: true
|
|
514541
513796
|
};
|
|
514542
513797
|
}
|
|
514543
|
-
function mergePinnedConversationRecords(listedConversations, pinnedConversations) {
|
|
514544
|
-
const listedIds = new Set(listedConversations.map((conversation) => conversation.id));
|
|
514545
|
-
return [
|
|
514546
|
-
...pinnedConversations.filter((conversation) => !listedIds.has(conversation.id)),
|
|
514547
|
-
...listedConversations
|
|
514548
|
-
];
|
|
514549
|
-
}
|
|
514550
513798
|
function ConversationSelector({
|
|
514551
513799
|
agentId,
|
|
514552
513800
|
agentName,
|
|
@@ -514571,16 +513819,6 @@ function ConversationSelector({
|
|
|
514571
513819
|
const [searchInput, setSearchInput] = import_react26.useState("");
|
|
514572
513820
|
const [searchResults, setSearchResults] = import_react26.useState(null);
|
|
514573
513821
|
const [searching, setSearching] = import_react26.useState(false);
|
|
514574
|
-
const [pinNotice, setPinNotice] = import_react26.useState(null);
|
|
514575
|
-
const pinNoticeTimerRef = import_react26.useRef(null);
|
|
514576
|
-
const preserveSelectionIdRef = import_react26.useRef(null);
|
|
514577
|
-
import_react26.useEffect(() => {
|
|
514578
|
-
return () => {
|
|
514579
|
-
if (pinNoticeTimerRef.current) {
|
|
514580
|
-
clearTimeout(pinNoticeTimerRef.current);
|
|
514581
|
-
}
|
|
514582
|
-
};
|
|
514583
|
-
}, []);
|
|
514584
513822
|
const enrichConversation = import_react26.useCallback(async (backend4, convId) => {
|
|
514585
513823
|
try {
|
|
514586
513824
|
const messages = await backend4.listConversationMessages(convId, {
|
|
@@ -514622,9 +513860,6 @@ function ConversationSelector({
|
|
|
514622
513860
|
setError(null);
|
|
514623
513861
|
try {
|
|
514624
513862
|
const backend4 = selectorBackend();
|
|
514625
|
-
const pinnedRefs = !afterCursor ? settingsManager.getMergedPinnedConversations(agentId) : [];
|
|
514626
|
-
const pinnedIdSet = new Set(pinnedRefs.map((p2) => p2.conversationId));
|
|
514627
|
-
const localPinnedIdSet = new Set(pinnedRefs.filter((p2) => p2.isLocal).map((p2) => p2.conversationId));
|
|
514628
513863
|
const conversationListPromise = backend4.listConversations({
|
|
514629
513864
|
agent_id: agentId,
|
|
514630
513865
|
limit: FETCH_PAGE_SIZE,
|
|
@@ -514656,53 +513891,20 @@ function ConversationSelector({
|
|
|
514656
513891
|
conversationListPromise,
|
|
514657
513892
|
defaultPromise
|
|
514658
513893
|
]);
|
|
514659
|
-
const
|
|
514660
|
-
try {
|
|
514661
|
-
const conversation = await backend4.retrieveConversation(pin.conversationId);
|
|
514662
|
-
return conversation.agent_id === agentId ? conversation : null;
|
|
514663
|
-
} catch {
|
|
514664
|
-
return null;
|
|
514665
|
-
}
|
|
514666
|
-
}))).filter((conversation) => conversation !== null) : [];
|
|
514667
|
-
const conversationRecords = mergePinnedConversationRecords(result, pinnedConversations);
|
|
514668
|
-
const unenrichedList = conversationRecords.map((conv) => ({
|
|
513894
|
+
const unenrichedList = result.map((conv) => ({
|
|
514669
513895
|
conversation: conv,
|
|
514670
513896
|
previewLines: null,
|
|
514671
513897
|
lastActiveAt: conv.updated_at ?? conv.created_at ?? null,
|
|
514672
513898
|
messageCount: -1,
|
|
514673
|
-
enriched: false
|
|
514674
|
-
isPinned: isConversationPinned({
|
|
514675
|
-
conversationId: conv.id,
|
|
514676
|
-
pinnedIds: pinnedIdSet
|
|
514677
|
-
}),
|
|
514678
|
-
isPinnedLocal: localPinnedIdSet.has(conv.id)
|
|
513899
|
+
enriched: false
|
|
514679
513900
|
}));
|
|
514680
513901
|
const nonEmptyList = unenrichedList;
|
|
514681
513902
|
const newCursor = result.length === FETCH_PAGE_SIZE ? result[result.length - 1]?.id ?? null : null;
|
|
514682
513903
|
if (isLoadingMore) {
|
|
514683
513904
|
setConversations((prev) => [...prev, ...nonEmptyList]);
|
|
514684
513905
|
} else {
|
|
514685
|
-
const initialConversations = defaultConversation ? [
|
|
514686
|
-
|
|
514687
|
-
...defaultConversation,
|
|
514688
|
-
isPinned: true,
|
|
514689
|
-
isPinnedLocal: localPinnedIdSet.has("default")
|
|
514690
|
-
},
|
|
514691
|
-
...nonEmptyList
|
|
514692
|
-
] : nonEmptyList;
|
|
514693
|
-
const byId = new Map(initialConversations.map((item) => [item.conversation.id, item]));
|
|
514694
|
-
const defaultItem = byId.get("default");
|
|
514695
|
-
const pinnedOrdered = pinnedRefs.map((p2) => byId.get(p2.conversationId)).filter((item) => item !== undefined && item.conversation.id !== "default");
|
|
514696
|
-
const prioritizedIds = new Set([
|
|
514697
|
-
...defaultItem ? [defaultItem.conversation.id] : [],
|
|
514698
|
-
...pinnedOrdered.map((item) => item.conversation.id)
|
|
514699
|
-
]);
|
|
514700
|
-
const allConversations = [
|
|
514701
|
-
...defaultItem ? [defaultItem] : [],
|
|
514702
|
-
...pinnedOrdered,
|
|
514703
|
-
...initialConversations.filter((item) => !prioritizedIds.has(item.conversation.id))
|
|
514704
|
-
];
|
|
514705
|
-
setConversations(allConversations);
|
|
513906
|
+
const initialConversations = defaultConversation ? [defaultConversation, ...nonEmptyList] : nonEmptyList;
|
|
513907
|
+
setConversations(initialConversations);
|
|
514706
513908
|
setSelectedIndex(0);
|
|
514707
513909
|
}
|
|
514708
513910
|
setCursor(newCursor);
|
|
@@ -514779,12 +513981,7 @@ function ConversationSelector({
|
|
|
514779
513981
|
searchPreview: conversation.summary || undefined,
|
|
514780
513982
|
lastActiveAt: conversation.updated_at ?? conversation.created_at ?? null,
|
|
514781
513983
|
messageCount: -1,
|
|
514782
|
-
enriched: false
|
|
514783
|
-
isPinned: isConversationPinned({
|
|
514784
|
-
conversationId: conversation.id,
|
|
514785
|
-
pinnedIds: new Set(settingsManager.getMergedPinnedConversations(agentId).map((pinned) => pinned.conversationId))
|
|
514786
|
-
}),
|
|
514787
|
-
isPinnedLocal: settingsManager.getLocalPinnedConversations(agentId).includes(conversation.id)
|
|
513984
|
+
enriched: false
|
|
514788
513985
|
})));
|
|
514789
513986
|
} catch {
|
|
514790
513987
|
if (!cancelled) {
|
|
@@ -514823,16 +514020,6 @@ function ConversationSelector({
|
|
|
514823
514020
|
}
|
|
514824
514021
|
return merged;
|
|
514825
514022
|
})() : conversations;
|
|
514826
|
-
import_react26.useEffect(() => {
|
|
514827
|
-
const conversationId = preserveSelectionIdRef.current;
|
|
514828
|
-
if (!conversationId)
|
|
514829
|
-
return;
|
|
514830
|
-
preserveSelectionIdRef.current = null;
|
|
514831
|
-
const nextSelectedIndex = findConversationIndexById(filteredConversations, conversationId);
|
|
514832
|
-
if (nextSelectedIndex >= 0) {
|
|
514833
|
-
setSelectedIndex(nextSelectedIndex);
|
|
514834
|
-
}
|
|
514835
|
-
}, [filteredConversations]);
|
|
514836
514023
|
const startIndex = Math.max(0, Math.min(selectedIndex - Math.floor(listPageSize / 2), filteredConversations.length - listPageSize));
|
|
514837
514024
|
const visibleConversations = filteredConversations.slice(startIndex, startIndex + listPageSize);
|
|
514838
514025
|
import_react26.useEffect(() => {
|
|
@@ -514851,36 +514038,6 @@ function ConversationSelector({
|
|
|
514851
514038
|
return;
|
|
514852
514039
|
await loadConversations(cursor);
|
|
514853
514040
|
}, [loadingMore, hasMore, cursor, loadConversations]);
|
|
514854
|
-
const togglePinnedConversation = import_react26.useCallback((selected) => {
|
|
514855
|
-
if (!selected?.conversation.id)
|
|
514856
|
-
return;
|
|
514857
|
-
const conversationId = selected.conversation.id;
|
|
514858
|
-
if (isDefaultConversationId(conversationId)) {
|
|
514859
|
-
if (pinNoticeTimerRef.current) {
|
|
514860
|
-
clearTimeout(pinNoticeTimerRef.current);
|
|
514861
|
-
}
|
|
514862
|
-
setPinNotice("Default conversation is always pinned.");
|
|
514863
|
-
pinNoticeTimerRef.current = setTimeout(() => {
|
|
514864
|
-
pinNoticeTimerRef.current = null;
|
|
514865
|
-
setPinNotice(null);
|
|
514866
|
-
}, 2000);
|
|
514867
|
-
return;
|
|
514868
|
-
}
|
|
514869
|
-
setPinNotice(null);
|
|
514870
|
-
if (selected.isPinned) {
|
|
514871
|
-
settingsManager.unpinConversationBoth(agentId, conversationId);
|
|
514872
|
-
} else {
|
|
514873
|
-
settingsManager.pinConversationGlobal(agentId, conversationId);
|
|
514874
|
-
}
|
|
514875
|
-
preserveSelectionIdRef.current = conversationId;
|
|
514876
|
-
const updatePinState = (item) => item.conversation.id === conversationId ? {
|
|
514877
|
-
...item,
|
|
514878
|
-
isPinned: !selected.isPinned,
|
|
514879
|
-
isPinnedLocal: false
|
|
514880
|
-
} : item;
|
|
514881
|
-
setConversations((prev) => sortPinnedConversations(prev.map(updatePinState)));
|
|
514882
|
-
setSearchResults((prev) => prev?.map(updatePinState) ?? null);
|
|
514883
|
-
}, [agentId]);
|
|
514884
514041
|
use_input_default((input, key2) => {
|
|
514885
514042
|
if (key2.ctrl && input === "c") {
|
|
514886
514043
|
onCancel();
|
|
@@ -514909,8 +514066,6 @@ function ConversationSelector({
|
|
|
514909
514066
|
return;
|
|
514910
514067
|
}
|
|
514911
514068
|
onCancel();
|
|
514912
|
-
} else if (isPinShortcut(input, key2)) {
|
|
514913
|
-
togglePinnedConversation(filteredConversations[selectedIndex]);
|
|
514914
514069
|
} else if (key2.leftArrow || key2.rightArrow) {
|
|
514915
514070
|
return;
|
|
514916
514071
|
}
|
|
@@ -514923,7 +514078,6 @@ function ConversationSelector({
|
|
|
514923
514078
|
messageCount
|
|
514924
514079
|
} = enrichedConv;
|
|
514925
514080
|
const isCurrent = conv.id === currentConversationId;
|
|
514926
|
-
const isPinned = enrichedConv.isPinned;
|
|
514927
514081
|
const timestampText = formatConversationTimestampText({
|
|
514928
514082
|
lastActiveAt,
|
|
514929
514083
|
createdAt: conv.created_at
|
|
@@ -515031,9 +514185,6 @@ function ConversationSelector({
|
|
|
515031
514185
|
/* @__PURE__ */ jsx_dev_runtime6.jsxDEV(Text2, {
|
|
515032
514186
|
children: " "
|
|
515033
514187
|
}, undefined, false, undefined, this),
|
|
515034
|
-
isPinned && /* @__PURE__ */ jsx_dev_runtime6.jsxDEV(Text2, {
|
|
515035
|
-
children: "\uD83D\uDCCC "
|
|
515036
|
-
}, undefined, false, undefined, this),
|
|
515037
514188
|
/* @__PURE__ */ jsx_dev_runtime6.jsxDEV(Text2, {
|
|
515038
514189
|
bold: isSelected,
|
|
515039
514190
|
color: isSelected ? colors.selector.itemHighlighted : undefined,
|
|
@@ -515063,8 +514214,6 @@ function ConversationSelector({
|
|
|
515063
514214
|
};
|
|
515064
514215
|
const terminalWidth = useTerminalWidth();
|
|
515065
514216
|
const solidLine = SOLID_LINE.repeat(Math.max(terminalWidth, 10));
|
|
515066
|
-
const selectedConversation = filteredConversations[selectedIndex];
|
|
515067
|
-
const isSelectedDefaultConversation = selectedConversation ? isDefaultConversationId(selectedConversation.conversation.id) : false;
|
|
515068
514217
|
return /* @__PURE__ */ jsx_dev_runtime6.jsxDEV(Box_default, {
|
|
515069
514218
|
flexDirection: "column",
|
|
515070
514219
|
children: [
|
|
@@ -515097,10 +514246,9 @@ function ConversationSelector({
|
|
|
515097
514246
|
/* @__PURE__ */ jsx_dev_runtime6.jsxDEV(PasteAwareTextInput, {
|
|
515098
514247
|
value: searchInput,
|
|
515099
514248
|
onChange: (value) => {
|
|
515100
|
-
|
|
515101
|
-
if (nextSearchInput === searchInput)
|
|
514249
|
+
if (value === searchInput)
|
|
515102
514250
|
return;
|
|
515103
|
-
setSearchInput(
|
|
514251
|
+
setSearchInput(value);
|
|
515104
514252
|
setSelectedIndex(0);
|
|
515105
514253
|
},
|
|
515106
514254
|
placeholder: "search conversation titles"
|
|
@@ -515157,9 +514305,7 @@ function ConversationSelector({
|
|
|
515157
514305
|
!loading && !error54 && filteredConversations.length > 0 && (() => {
|
|
515158
514306
|
const footerWidth = Math.max(0, terminalWidth - 2);
|
|
515159
514307
|
const pageText = `Showing ${startIndex + 1}-${Math.min(startIndex + visibleConversations.length, filteredConversations.length)} of ${filteredConversations.length}${!normalizedSearch && hasMore ? "+" : ""}${loadingMore ? " (loading...)" : ""}`;
|
|
515160
|
-
const hintsText = buildConversationSelectorHints(
|
|
515161
|
-
isSelectedDefaultConversation
|
|
515162
|
-
});
|
|
514308
|
+
const hintsText = buildConversationSelectorHints();
|
|
515163
514309
|
return /* @__PURE__ */ jsx_dev_runtime6.jsxDEV(Box_default, {
|
|
515164
514310
|
flexDirection: "column",
|
|
515165
514311
|
children: [
|
|
@@ -515196,23 +514342,6 @@ function ConversationSelector({
|
|
|
515196
514342
|
}, undefined, false, undefined, this)
|
|
515197
514343
|
}, undefined, false, undefined, this)
|
|
515198
514344
|
]
|
|
515199
|
-
}, undefined, true, undefined, this),
|
|
515200
|
-
pinNotice && /* @__PURE__ */ jsx_dev_runtime6.jsxDEV(Box_default, {
|
|
515201
|
-
flexDirection: "row",
|
|
515202
|
-
children: [
|
|
515203
|
-
/* @__PURE__ */ jsx_dev_runtime6.jsxDEV(Box_default, {
|
|
515204
|
-
width: 2,
|
|
515205
|
-
flexShrink: 0
|
|
515206
|
-
}, undefined, false, undefined, this),
|
|
515207
|
-
/* @__PURE__ */ jsx_dev_runtime6.jsxDEV(Box_default, {
|
|
515208
|
-
flexGrow: 1,
|
|
515209
|
-
width: footerWidth,
|
|
515210
|
-
children: /* @__PURE__ */ jsx_dev_runtime6.jsxDEV(Text2, {
|
|
515211
|
-
color: "yellow",
|
|
515212
|
-
children: pinNotice
|
|
515213
|
-
}, undefined, false, undefined, this)
|
|
515214
|
-
}, undefined, false, undefined, this)
|
|
515215
|
-
]
|
|
515216
514345
|
}, undefined, true, undefined, this)
|
|
515217
514346
|
]
|
|
515218
514347
|
}, undefined, true, undefined, this);
|
|
@@ -515841,7 +514970,7 @@ import {
|
|
|
515841
514970
|
chmodSync as chmodSync5,
|
|
515842
514971
|
createWriteStream as createWriteStream3,
|
|
515843
514972
|
existsSync as existsSync31,
|
|
515844
|
-
mkdirSync as
|
|
514973
|
+
mkdirSync as mkdirSync20,
|
|
515845
514974
|
readdirSync as readdirSync11,
|
|
515846
514975
|
renameSync as renameSync3,
|
|
515847
514976
|
rmSync as rmSync6,
|
|
@@ -516024,10 +515153,10 @@ async function downloadFd() {
|
|
|
516024
515153
|
if (!assetName) {
|
|
516025
515154
|
throw new Error(`Unsupported platform: ${platform5()}/${arch2()}`);
|
|
516026
515155
|
}
|
|
516027
|
-
|
|
515156
|
+
mkdirSync20(FD_TOOLS_DIR, { recursive: true });
|
|
516028
515157
|
const archivePath = join34(FD_TOOLS_DIR, assetName);
|
|
516029
515158
|
const extractDir = join34(FD_TOOLS_DIR, `extract_tmp_fd_${process.pid}_${Date.now()}_${Math.random().toString(36).slice(2, 10)}`);
|
|
516030
|
-
|
|
515159
|
+
mkdirSync20(extractDir, { recursive: true });
|
|
516031
515160
|
try {
|
|
516032
515161
|
await downloadFile3(`https://github.com/${FD_DOWNLOAD_REPO}/releases/download/v${version2}/${assetName}`, archivePath);
|
|
516033
515162
|
if (assetName.endsWith(".tar.gz")) {
|
|
@@ -516283,42 +515412,37 @@ function formatModel(agent2) {
|
|
|
516283
515412
|
}
|
|
516284
515413
|
return agent2.llm_config?.model || "unknown";
|
|
516285
515414
|
}
|
|
516286
|
-
function getLabel(option2,
|
|
515415
|
+
function getLabel(option2, _freshRepoMode) {
|
|
516287
515416
|
const parts = [];
|
|
516288
515417
|
if (option2.isLru)
|
|
516289
515418
|
parts.push("last used");
|
|
516290
|
-
if (option2.
|
|
515419
|
+
if (!option2.isLru)
|
|
516291
515420
|
parts.push("pinned");
|
|
516292
|
-
else if (!option2.isLru && !freshRepoMode)
|
|
516293
|
-
parts.push("global");
|
|
516294
515421
|
return parts.length > 0 ? ` (${parts.join(", ")})` : "";
|
|
516295
515422
|
}
|
|
516296
515423
|
function buildInitialProfileOptions(lruAgentId) {
|
|
516297
|
-
const
|
|
515424
|
+
const pinned = settingsManager.getPinnedAgents();
|
|
516298
515425
|
const options3 = [];
|
|
516299
515426
|
const seenAgentIds = new Set;
|
|
516300
515427
|
if (lruAgentId) {
|
|
516301
|
-
const matchingPinned = mergedPinned.find((p2) => p2.agentId === lruAgentId);
|
|
516302
515428
|
options3.push({
|
|
516303
515429
|
name: null,
|
|
516304
515430
|
agentId: lruAgentId,
|
|
516305
|
-
isLocal: matchingPinned?.isLocal || false,
|
|
516306
515431
|
isLru: true,
|
|
516307
515432
|
agent: null
|
|
516308
515433
|
});
|
|
516309
515434
|
seenAgentIds.add(lruAgentId);
|
|
516310
515435
|
}
|
|
516311
|
-
for (const
|
|
516312
|
-
if (seenAgentIds.has(
|
|
515436
|
+
for (const agentId of pinned) {
|
|
515437
|
+
if (seenAgentIds.has(agentId))
|
|
516313
515438
|
continue;
|
|
516314
515439
|
options3.push({
|
|
516315
515440
|
name: null,
|
|
516316
|
-
agentId
|
|
516317
|
-
isLocal: pinned.isLocal,
|
|
515441
|
+
agentId,
|
|
516318
515442
|
isLru: false,
|
|
516319
515443
|
agent: null
|
|
516320
515444
|
});
|
|
516321
|
-
seenAgentIds.add(
|
|
515445
|
+
seenAgentIds.add(agentId);
|
|
516322
515446
|
}
|
|
516323
515447
|
return options3;
|
|
516324
515448
|
}
|
|
@@ -516342,30 +515466,27 @@ function ProfileSelectionUI({
|
|
|
516342
515466
|
const [modelReasoningPrompt, setModelReasoningPrompt] = import_react30.useState(null);
|
|
516343
515467
|
const loadOptions = import_react30.useCallback(async () => {
|
|
516344
515468
|
try {
|
|
516345
|
-
const
|
|
515469
|
+
const pinned = settingsManager.getPinnedAgents();
|
|
516346
515470
|
const optionsToFetch = [];
|
|
516347
515471
|
const seenAgentIds = new Set;
|
|
516348
515472
|
if (lruAgentId) {
|
|
516349
|
-
const matchingPinned = mergedPinned.find((p2) => p2.agentId === lruAgentId);
|
|
516350
515473
|
optionsToFetch.push({
|
|
516351
515474
|
name: null,
|
|
516352
515475
|
agentId: lruAgentId,
|
|
516353
|
-
isLocal: matchingPinned?.isLocal || false,
|
|
516354
515476
|
isLru: true,
|
|
516355
515477
|
agent: null
|
|
516356
515478
|
});
|
|
516357
515479
|
seenAgentIds.add(lruAgentId);
|
|
516358
515480
|
}
|
|
516359
|
-
for (const
|
|
516360
|
-
if (!seenAgentIds.has(
|
|
515481
|
+
for (const agentId of pinned) {
|
|
515482
|
+
if (!seenAgentIds.has(agentId)) {
|
|
516361
515483
|
optionsToFetch.push({
|
|
516362
515484
|
name: null,
|
|
516363
|
-
agentId
|
|
516364
|
-
isLocal: pinned.isLocal,
|
|
515485
|
+
agentId,
|
|
516365
515486
|
isLru: false,
|
|
516366
515487
|
agent: null
|
|
516367
515488
|
});
|
|
516368
|
-
seenAgentIds.add(
|
|
515489
|
+
seenAgentIds.add(agentId);
|
|
516369
515490
|
}
|
|
516370
515491
|
}
|
|
516371
515492
|
let fetchedOptions = await Promise.all(optionsToFetch.map(async (opt) => {
|
|
@@ -516392,7 +515513,6 @@ function ProfileSelectionUI({
|
|
|
516392
515513
|
fetchedOptions = recentAgents.map((recent) => ({
|
|
516393
515514
|
name: recent.agent.name,
|
|
516394
515515
|
agentId: recent.agent.id,
|
|
516395
|
-
isLocal: recent.isLocal,
|
|
516396
515516
|
isLru: false,
|
|
516397
515517
|
agent: recent.agent
|
|
516398
515518
|
}));
|
|
@@ -516951,7 +516071,7 @@ async function runCreateAction(values2) {
|
|
|
516951
516071
|
});
|
|
516952
516072
|
}
|
|
516953
516073
|
if (values2.pinned) {
|
|
516954
|
-
settingsManager.
|
|
516074
|
+
settingsManager.pinAgent(agentId);
|
|
516955
516075
|
}
|
|
516956
516076
|
const updatedAgent = await getBackend().retrieveAgent(agentId);
|
|
516957
516077
|
console.log(JSON.stringify(updatedAgent, null, 2));
|
|
@@ -516998,25 +516118,313 @@ import { parseArgs as parseArgs3 } from "node:util";
|
|
|
516998
516118
|
// src/websocket/app-server.ts
|
|
516999
516119
|
init_settings_manager();
|
|
517000
516120
|
init_telemetry();
|
|
517001
|
-
|
|
517002
|
-
await __promiseAll([
|
|
517003
|
-
init_manager4(),
|
|
517004
|
-
init_lifecycle(),
|
|
517005
|
-
init_mod_adapter2()
|
|
517006
|
-
]);
|
|
516121
|
+
await init_manager4();
|
|
517007
516122
|
import { createServer } from "node:http";
|
|
517008
516123
|
import { hostname as hostname4 } from "node:os";
|
|
517009
516124
|
import WebSocket7, { WebSocketServer } from "ws";
|
|
517010
|
-
|
|
517011
|
-
|
|
517012
|
-
|
|
517013
|
-
|
|
516125
|
+
|
|
516126
|
+
// src/websocket/app-server-auth.ts
|
|
516127
|
+
import { createHash as createHash4, createHmac, timingSafeEqual } from "node:crypto";
|
|
516128
|
+
import { readFile as readFile11 } from "node:fs/promises";
|
|
516129
|
+
import { isIP as isIP2 } from "node:net";
|
|
516130
|
+
import { isAbsolute as isAbsolute22 } from "node:path";
|
|
516131
|
+
var INVALID_AUTHORIZATION_HEADER_MESSAGE = "invalid authorization header";
|
|
516132
|
+
var DEFAULT_MAX_CLOCK_SKEW_SECONDS = 30;
|
|
516133
|
+
var MIN_SIGNED_BEARER_SECRET_BYTES = 32;
|
|
516134
|
+
function parseAppServerWebsocketAuthSettings(args) {
|
|
516135
|
+
const hasSignedBearerFlag = Boolean(args.wsSharedSecretFile !== undefined || args.wsIssuer !== undefined || args.wsAudience !== undefined || args.wsMaxClockSkewSeconds !== undefined);
|
|
516136
|
+
switch (args.wsAuth) {
|
|
516137
|
+
case undefined:
|
|
516138
|
+
if (args.wsTokenFile !== undefined || args.wsTokenSha256 !== undefined || hasSignedBearerFlag) {
|
|
516139
|
+
throw new Error("websocket auth flags require `--ws-auth capability-token` or `--ws-auth signed-bearer-token`");
|
|
516140
|
+
}
|
|
516141
|
+
return {};
|
|
516142
|
+
case "capability-token": {
|
|
516143
|
+
if (hasSignedBearerFlag) {
|
|
516144
|
+
throw new Error("`--ws-shared-secret-file`, `--ws-issuer`, `--ws-audience`, and `--ws-max-clock-skew-seconds` require `--ws-auth signed-bearer-token`");
|
|
516145
|
+
}
|
|
516146
|
+
const hasTokenFile = args.wsTokenFile !== undefined;
|
|
516147
|
+
const hasTokenSha256 = args.wsTokenSha256 !== undefined;
|
|
516148
|
+
if (hasTokenFile && hasTokenSha256) {
|
|
516149
|
+
throw new Error("`--ws-token-file` and `--ws-token-sha256` are mutually exclusive");
|
|
516150
|
+
}
|
|
516151
|
+
if (!hasTokenFile && !hasTokenSha256) {
|
|
516152
|
+
throw new Error("`--ws-token-file` or `--ws-token-sha256` is required when `--ws-auth capability-token` is set");
|
|
516153
|
+
}
|
|
516154
|
+
return {
|
|
516155
|
+
config: {
|
|
516156
|
+
mode: "capability-token",
|
|
516157
|
+
source: args.wsTokenFile ? {
|
|
516158
|
+
type: "token-file",
|
|
516159
|
+
tokenFile: absolutePathArg("--ws-token-file", args.wsTokenFile)
|
|
516160
|
+
} : {
|
|
516161
|
+
type: "token-sha256",
|
|
516162
|
+
tokenSha256: sha256DigestArg("--ws-token-sha256", args.wsTokenSha256)
|
|
516163
|
+
}
|
|
516164
|
+
}
|
|
516165
|
+
};
|
|
516166
|
+
}
|
|
516167
|
+
case "signed-bearer-token": {
|
|
516168
|
+
if (args.wsTokenFile !== undefined || args.wsTokenSha256 !== undefined) {
|
|
516169
|
+
throw new Error("`--ws-token-file` and `--ws-token-sha256` require `--ws-auth capability-token`, not `signed-bearer-token`");
|
|
516170
|
+
}
|
|
516171
|
+
if (args.wsSharedSecretFile === undefined) {
|
|
516172
|
+
throw new Error("`--ws-shared-secret-file` is required when `--ws-auth signed-bearer-token` is set");
|
|
516173
|
+
}
|
|
516174
|
+
return {
|
|
516175
|
+
config: {
|
|
516176
|
+
mode: "signed-bearer-token",
|
|
516177
|
+
sharedSecretFile: absolutePathArg("--ws-shared-secret-file", args.wsSharedSecretFile),
|
|
516178
|
+
issuer: normalizeOptionalString(args.wsIssuer),
|
|
516179
|
+
audience: normalizeOptionalString(args.wsAudience),
|
|
516180
|
+
maxClockSkewSeconds: args.wsMaxClockSkewSeconds !== undefined ? nonNegativeIntegerArg("--ws-max-clock-skew-seconds", args.wsMaxClockSkewSeconds) : DEFAULT_MAX_CLOCK_SKEW_SECONDS
|
|
516181
|
+
}
|
|
516182
|
+
};
|
|
516183
|
+
}
|
|
516184
|
+
default:
|
|
516185
|
+
throw new Error(`unsupported --ws-auth mode "${args.wsAuth}"; expected "capability-token" or "signed-bearer-token"`);
|
|
516186
|
+
}
|
|
516187
|
+
}
|
|
516188
|
+
async function policyFromSettings(settings3 = {}) {
|
|
516189
|
+
const config3 = settings3.config;
|
|
516190
|
+
if (!config3) {
|
|
516191
|
+
return {};
|
|
516192
|
+
}
|
|
516193
|
+
switch (config3.mode) {
|
|
516194
|
+
case "capability-token":
|
|
516195
|
+
return {
|
|
516196
|
+
mode: {
|
|
516197
|
+
type: "capability-token",
|
|
516198
|
+
tokenSha256: config3.source.type === "token-file" ? sha256Digest(await readTrimmedSecret(config3.source.tokenFile)) : config3.source.tokenSha256
|
|
516199
|
+
}
|
|
516200
|
+
};
|
|
516201
|
+
case "signed-bearer-token": {
|
|
516202
|
+
const sharedSecret = Buffer.from(await readTrimmedSecret(config3.sharedSecretFile), "utf8");
|
|
516203
|
+
validateSignedBearerSecret(config3.sharedSecretFile, sharedSecret);
|
|
516204
|
+
return {
|
|
516205
|
+
mode: {
|
|
516206
|
+
type: "signed-bearer-token",
|
|
516207
|
+
sharedSecret,
|
|
516208
|
+
issuer: config3.issuer,
|
|
516209
|
+
audience: config3.audience,
|
|
516210
|
+
maxClockSkewSeconds: config3.maxClockSkewSeconds
|
|
516211
|
+
}
|
|
516212
|
+
};
|
|
516213
|
+
}
|
|
516214
|
+
}
|
|
516215
|
+
}
|
|
516216
|
+
function isUnauthenticatedNonLoopbackListener(host, policy) {
|
|
516217
|
+
return !isLoopbackListenHost(host) && !policy.mode;
|
|
516218
|
+
}
|
|
516219
|
+
function isLoopbackListenHost(host) {
|
|
517014
516220
|
const normalized = normalizeListenHost(host);
|
|
517015
|
-
|
|
516221
|
+
if (normalized === "localhost") {
|
|
516222
|
+
return true;
|
|
516223
|
+
}
|
|
516224
|
+
if (isIP2(normalized) === 4) {
|
|
516225
|
+
return normalized.startsWith("127.");
|
|
516226
|
+
}
|
|
516227
|
+
return normalized === "::1";
|
|
517016
516228
|
}
|
|
517017
516229
|
function normalizeListenHost(host) {
|
|
517018
516230
|
return host.toLowerCase().replace(/^\[/, "").replace(/\]$/, "");
|
|
517019
516231
|
}
|
|
516232
|
+
function authorizeUpgrade(headers, policy) {
|
|
516233
|
+
const mode = policy.mode;
|
|
516234
|
+
if (!mode) {
|
|
516235
|
+
return null;
|
|
516236
|
+
}
|
|
516237
|
+
const tokenResult = bearerTokenFromHeaders(headers);
|
|
516238
|
+
if (typeof tokenResult !== "string") {
|
|
516239
|
+
return tokenResult;
|
|
516240
|
+
}
|
|
516241
|
+
switch (mode.type) {
|
|
516242
|
+
case "capability-token": {
|
|
516243
|
+
const actualSha256 = sha256Digest(tokenResult);
|
|
516244
|
+
if (timingSafeEqual(mode.tokenSha256, actualSha256)) {
|
|
516245
|
+
return null;
|
|
516246
|
+
}
|
|
516247
|
+
return unauthorized("invalid websocket bearer token");
|
|
516248
|
+
}
|
|
516249
|
+
case "signed-bearer-token":
|
|
516250
|
+
return verifySignedBearerToken(tokenResult, mode.sharedSecret, mode.issuer, mode.audience, mode.maxClockSkewSeconds);
|
|
516251
|
+
}
|
|
516252
|
+
}
|
|
516253
|
+
function verifySignedBearerToken(token2, sharedSecret, issuer, audience, maxClockSkewSeconds) {
|
|
516254
|
+
const claims = decodeJwtClaims(token2, sharedSecret);
|
|
516255
|
+
if ("error" in claims) {
|
|
516256
|
+
return claims.error;
|
|
516257
|
+
}
|
|
516258
|
+
return validateJwtClaims(claims.claims, issuer, audience, maxClockSkewSeconds);
|
|
516259
|
+
}
|
|
516260
|
+
function decodeJwtClaims(token2, sharedSecret) {
|
|
516261
|
+
const parts = token2.split(".");
|
|
516262
|
+
const encodedHeader = parts[0];
|
|
516263
|
+
const encodedClaims = parts[1];
|
|
516264
|
+
const encodedSignature = parts[2];
|
|
516265
|
+
if (parts.length !== 3 || !encodedHeader || !encodedClaims || !encodedSignature) {
|
|
516266
|
+
return { error: unauthorized("invalid websocket jwt") };
|
|
516267
|
+
}
|
|
516268
|
+
let header;
|
|
516269
|
+
let claims;
|
|
516270
|
+
let actualSignature;
|
|
516271
|
+
try {
|
|
516272
|
+
header = JSON.parse(base64UrlDecode(encodedHeader).toString("utf8"));
|
|
516273
|
+
claims = JSON.parse(base64UrlDecode(encodedClaims).toString("utf8"));
|
|
516274
|
+
actualSignature = base64UrlDecode(encodedSignature);
|
|
516275
|
+
} catch {
|
|
516276
|
+
return { error: unauthorized("invalid websocket jwt") };
|
|
516277
|
+
}
|
|
516278
|
+
if (!isRecord5(header) || header.alg !== "HS256") {
|
|
516279
|
+
return { error: unauthorized("invalid websocket jwt") };
|
|
516280
|
+
}
|
|
516281
|
+
const expectedSignature = createHmac("sha256", sharedSecret).update(`${encodedHeader}.${encodedClaims}`).digest();
|
|
516282
|
+
if (actualSignature.length !== expectedSignature.length || !timingSafeEqual(actualSignature, expectedSignature)) {
|
|
516283
|
+
return { error: unauthorized("invalid websocket jwt") };
|
|
516284
|
+
}
|
|
516285
|
+
if (!isJwtClaims(claims)) {
|
|
516286
|
+
return { error: unauthorized("invalid websocket jwt") };
|
|
516287
|
+
}
|
|
516288
|
+
return { claims };
|
|
516289
|
+
}
|
|
516290
|
+
function validateJwtClaims(claims, issuer, audience, maxClockSkewSeconds) {
|
|
516291
|
+
const now = Math.floor(Date.now() / 1000);
|
|
516292
|
+
if (now > claims.exp + maxClockSkewSeconds) {
|
|
516293
|
+
return unauthorized("expired websocket jwt");
|
|
516294
|
+
}
|
|
516295
|
+
if (claims.nbf !== undefined && now < claims.nbf - maxClockSkewSeconds) {
|
|
516296
|
+
return unauthorized("websocket jwt is not valid yet");
|
|
516297
|
+
}
|
|
516298
|
+
if (issuer !== undefined && claims.iss !== issuer) {
|
|
516299
|
+
return unauthorized("websocket jwt issuer mismatch");
|
|
516300
|
+
}
|
|
516301
|
+
if (audience !== undefined && !audienceMatches(claims.aud, audience)) {
|
|
516302
|
+
return unauthorized("websocket jwt audience mismatch");
|
|
516303
|
+
}
|
|
516304
|
+
return null;
|
|
516305
|
+
}
|
|
516306
|
+
function audienceMatches(actual, expectedAudience) {
|
|
516307
|
+
if (typeof actual === "string") {
|
|
516308
|
+
return actual === expectedAudience;
|
|
516309
|
+
}
|
|
516310
|
+
if (Array.isArray(actual)) {
|
|
516311
|
+
return actual.some((audience) => audience === expectedAudience);
|
|
516312
|
+
}
|
|
516313
|
+
return false;
|
|
516314
|
+
}
|
|
516315
|
+
function isJwtClaims(value) {
|
|
516316
|
+
if (!isRecord5(value) || !Number.isSafeInteger(value.exp)) {
|
|
516317
|
+
return false;
|
|
516318
|
+
}
|
|
516319
|
+
if (value.nbf !== undefined && !Number.isSafeInteger(value.nbf)) {
|
|
516320
|
+
return false;
|
|
516321
|
+
}
|
|
516322
|
+
if (value.iss !== undefined && typeof value.iss !== "string") {
|
|
516323
|
+
return false;
|
|
516324
|
+
}
|
|
516325
|
+
if (value.aud !== undefined) {
|
|
516326
|
+
if (typeof value.aud === "string") {
|
|
516327
|
+
return true;
|
|
516328
|
+
}
|
|
516329
|
+
if (!Array.isArray(value.aud)) {
|
|
516330
|
+
return false;
|
|
516331
|
+
}
|
|
516332
|
+
return value.aud.every((audience) => typeof audience === "string");
|
|
516333
|
+
}
|
|
516334
|
+
return true;
|
|
516335
|
+
}
|
|
516336
|
+
function isRecord5(value) {
|
|
516337
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
516338
|
+
}
|
|
516339
|
+
function base64UrlDecode(value) {
|
|
516340
|
+
if (!/^[A-Za-z0-9_-]*$/.test(value)) {
|
|
516341
|
+
throw new Error("invalid base64url");
|
|
516342
|
+
}
|
|
516343
|
+
const base644 = value.replace(/-/g, "+").replace(/_/g, "/");
|
|
516344
|
+
const padding = "=".repeat((4 - base644.length % 4) % 4);
|
|
516345
|
+
return Buffer.from(`${base644}${padding}`, "base64");
|
|
516346
|
+
}
|
|
516347
|
+
function bearerTokenFromHeaders(headers) {
|
|
516348
|
+
const rawHeader = headers.authorization;
|
|
516349
|
+
if (rawHeader === undefined) {
|
|
516350
|
+
return unauthorized("missing websocket bearer token");
|
|
516351
|
+
}
|
|
516352
|
+
if (Array.isArray(rawHeader)) {
|
|
516353
|
+
return unauthorized(INVALID_AUTHORIZATION_HEADER_MESSAGE);
|
|
516354
|
+
}
|
|
516355
|
+
const separatorIndex = rawHeader.indexOf(" ");
|
|
516356
|
+
if (separatorIndex === -1) {
|
|
516357
|
+
return unauthorized(INVALID_AUTHORIZATION_HEADER_MESSAGE);
|
|
516358
|
+
}
|
|
516359
|
+
const scheme = rawHeader.slice(0, separatorIndex);
|
|
516360
|
+
if (scheme.toLowerCase() !== "bearer") {
|
|
516361
|
+
return unauthorized(INVALID_AUTHORIZATION_HEADER_MESSAGE);
|
|
516362
|
+
}
|
|
516363
|
+
const token2 = rawHeader.slice(separatorIndex + 1).trim();
|
|
516364
|
+
if (!token2) {
|
|
516365
|
+
return unauthorized(INVALID_AUTHORIZATION_HEADER_MESSAGE);
|
|
516366
|
+
}
|
|
516367
|
+
return token2;
|
|
516368
|
+
}
|
|
516369
|
+
async function readTrimmedSecret(path26) {
|
|
516370
|
+
let raw2;
|
|
516371
|
+
try {
|
|
516372
|
+
raw2 = await readFile11(path26, "utf8");
|
|
516373
|
+
} catch (error54) {
|
|
516374
|
+
const message = error54 instanceof Error ? error54.message : String(error54);
|
|
516375
|
+
throw new Error(`failed to read websocket auth secret ${path26}: ${message}`);
|
|
516376
|
+
}
|
|
516377
|
+
const trimmed = raw2.trim();
|
|
516378
|
+
if (!trimmed) {
|
|
516379
|
+
throw new Error(`websocket auth secret ${path26} must not be empty`);
|
|
516380
|
+
}
|
|
516381
|
+
return trimmed;
|
|
516382
|
+
}
|
|
516383
|
+
function absolutePathArg(flagName, path26) {
|
|
516384
|
+
if (!isAbsolute22(path26)) {
|
|
516385
|
+
throw new Error(`${flagName} must be an absolute path`);
|
|
516386
|
+
}
|
|
516387
|
+
return path26;
|
|
516388
|
+
}
|
|
516389
|
+
function nonNegativeIntegerArg(flagName, value) {
|
|
516390
|
+
const parsed = typeof value === "number" ? value : Number(value.trim());
|
|
516391
|
+
if (!Number.isSafeInteger(parsed) || parsed < 0) {
|
|
516392
|
+
throw new Error(`${flagName} must be a non-negative integer`);
|
|
516393
|
+
}
|
|
516394
|
+
return parsed;
|
|
516395
|
+
}
|
|
516396
|
+
function normalizeOptionalString(value) {
|
|
516397
|
+
const trimmed = value?.trim();
|
|
516398
|
+
return trimmed ? trimmed : undefined;
|
|
516399
|
+
}
|
|
516400
|
+
function validateSignedBearerSecret(path26, sharedSecret) {
|
|
516401
|
+
if (sharedSecret.length < MIN_SIGNED_BEARER_SECRET_BYTES) {
|
|
516402
|
+
throw new Error(`signed websocket bearer secret ${path26} must be at least ${MIN_SIGNED_BEARER_SECRET_BYTES} bytes`);
|
|
516403
|
+
}
|
|
516404
|
+
}
|
|
516405
|
+
function sha256DigestArg(flagName, value) {
|
|
516406
|
+
const trimmed = value.trim();
|
|
516407
|
+
if (!/^[0-9a-fA-F]{64}$/.test(trimmed)) {
|
|
516408
|
+
throw new Error(`${flagName} must be a 64-character hex SHA-256 digest`);
|
|
516409
|
+
}
|
|
516410
|
+
return Buffer.from(trimmed, "hex");
|
|
516411
|
+
}
|
|
516412
|
+
function sha256Digest(value) {
|
|
516413
|
+
return createHash4("sha256").update(value).digest();
|
|
516414
|
+
}
|
|
516415
|
+
function unauthorized(message) {
|
|
516416
|
+
return { statusCode: 401, message };
|
|
516417
|
+
}
|
|
516418
|
+
|
|
516419
|
+
// src/websocket/app-server.ts
|
|
516420
|
+
init_runtime6();
|
|
516421
|
+
await __promiseAll([
|
|
516422
|
+
init_lifecycle(),
|
|
516423
|
+
init_mod_adapter2()
|
|
516424
|
+
]);
|
|
516425
|
+
var DEFAULT_LISTEN_URL = "ws://127.0.0.1:0";
|
|
516426
|
+
var DEFAULT_WS_PATH = "/ws";
|
|
516427
|
+
var PENDING_STREAM_TIMEOUT_MS = 5000;
|
|
517020
516428
|
function getRequiredAddressInfo(server2) {
|
|
517021
516429
|
const address = server2.address();
|
|
517022
516430
|
if (!address || typeof address === "string") {
|
|
@@ -517043,12 +516451,11 @@ function terminateSocket(socket) {
|
|
|
517043
516451
|
socket.terminate();
|
|
517044
516452
|
}
|
|
517045
516453
|
function rejectUpgrade(socket, statusCode2, message) {
|
|
517046
|
-
socket.
|
|
516454
|
+
socket.end(`HTTP/1.1 ${statusCode2} ${message}\r
|
|
517047
516455
|
Connection: close\r
|
|
517048
516456
|
Content-Length: 0\r
|
|
517049
516457
|
\r
|
|
517050
516458
|
`);
|
|
517051
|
-
socket.destroy();
|
|
517052
516459
|
}
|
|
517053
516460
|
function getRequestUrl(request, host) {
|
|
517054
516461
|
return new URL(request.url ?? "/", `http://${request.headers.host ?? host}`);
|
|
@@ -517091,9 +516498,6 @@ function parseAppServerListenUrl(listen = DEFAULT_LISTEN_URL) {
|
|
|
517091
516498
|
if (url2.protocol !== "ws:") {
|
|
517092
516499
|
throw new Error("app-server MVP only supports ws:// listen URLs");
|
|
517093
516500
|
}
|
|
517094
|
-
if (!isLoopbackHost(url2.hostname)) {
|
|
517095
|
-
throw new Error("app-server websocket listen host must be loopback for now");
|
|
517096
|
-
}
|
|
517097
516501
|
if (url2.username || url2.password || url2.search || url2.hash) {
|
|
517098
516502
|
throw new Error("app-server listen URL cannot include auth, query, or hash");
|
|
517099
516503
|
}
|
|
@@ -517147,6 +516551,10 @@ async function startControlSession(params) {
|
|
|
517147
516551
|
async function startAppServer(options3 = {}) {
|
|
517148
516552
|
await settingsManager.initialize();
|
|
517149
516553
|
const listen = parseAppServerListenUrl(options3.listen);
|
|
516554
|
+
const authPolicy = await policyFromSettings(options3.websocketAuth);
|
|
516555
|
+
if (isUnauthenticatedNonLoopbackListener(listen.host, authPolicy)) {
|
|
516556
|
+
throw new Error(`refusing to start non-loopback websocket listener ${listen.host}:${listen.port} without auth; configure \`--ws-auth capability-token\` or \`--ws-auth signed-bearer-token\``);
|
|
516557
|
+
}
|
|
517150
516558
|
const wss = new WebSocketServer({ noServer: true });
|
|
517151
516559
|
let activeSession = null;
|
|
517152
516560
|
let pendingStreamSocket = null;
|
|
@@ -517213,6 +516621,12 @@ async function startAppServer(options3 = {}) {
|
|
|
517213
516621
|
};
|
|
517214
516622
|
const server2 = createServer((request, response) => {
|
|
517215
516623
|
const requestUrl = getRequestUrl(request, listen.host);
|
|
516624
|
+
if (request.headers.origin) {
|
|
516625
|
+
options3.onLog?.(`Rejecting app-server request with Origin header: ${request.url ?? "/"}`);
|
|
516626
|
+
response.writeHead(403);
|
|
516627
|
+
response.end();
|
|
516628
|
+
return;
|
|
516629
|
+
}
|
|
517216
516630
|
if (requestUrl.pathname === "/readyz") {
|
|
517217
516631
|
response.writeHead(200, { "content-type": "text/plain" });
|
|
517218
516632
|
response.end(`ok
|
|
@@ -517220,11 +516634,6 @@ async function startAppServer(options3 = {}) {
|
|
|
517220
516634
|
return;
|
|
517221
516635
|
}
|
|
517222
516636
|
if (requestUrl.pathname === "/healthz") {
|
|
517223
|
-
if (request.headers.origin) {
|
|
517224
|
-
response.writeHead(403);
|
|
517225
|
-
response.end();
|
|
517226
|
-
return;
|
|
517227
|
-
}
|
|
517228
516637
|
response.writeHead(200, { "content-type": "text/plain" });
|
|
517229
516638
|
response.end(`ok
|
|
517230
516639
|
`);
|
|
@@ -517235,6 +516644,11 @@ async function startAppServer(options3 = {}) {
|
|
|
517235
516644
|
});
|
|
517236
516645
|
server2.on("upgrade", (request, socket, head2) => {
|
|
517237
516646
|
const requestUrl = getRequestUrl(request, listen.host);
|
|
516647
|
+
if (request.headers.origin) {
|
|
516648
|
+
options3.onLog?.(`Rejecting app-server websocket request with Origin header: ${request.url ?? "/"}`);
|
|
516649
|
+
rejectUpgrade(socket, 403, "Forbidden");
|
|
516650
|
+
return;
|
|
516651
|
+
}
|
|
517238
516652
|
if (requestUrl.pathname !== listen.path && requestUrl.pathname !== "/") {
|
|
517239
516653
|
rejectUpgrade(socket, 404, "Not Found");
|
|
517240
516654
|
return;
|
|
@@ -517244,6 +516658,12 @@ async function startAppServer(options3 = {}) {
|
|
|
517244
516658
|
rejectUpgrade(socket, 400, "Bad Request");
|
|
517245
516659
|
return;
|
|
517246
516660
|
}
|
|
516661
|
+
const authError = authorizeUpgrade(request.headers, authPolicy);
|
|
516662
|
+
if (authError) {
|
|
516663
|
+
options3.onLog?.(`Rejecting app-server websocket client: ${authError.message}`);
|
|
516664
|
+
rejectUpgrade(socket, authError.statusCode, authError.message);
|
|
516665
|
+
return;
|
|
516666
|
+
}
|
|
517247
516667
|
wss.handleUpgrade(request, socket, head2, (websocket) => {
|
|
517248
516668
|
handleWebSocketConnection(websocket, channel);
|
|
517249
516669
|
});
|
|
@@ -517311,11 +516731,20 @@ Run a local Letta Code app-server using native v2 websocket frames.
|
|
|
517311
516731
|
|
|
517312
516732
|
Options:
|
|
517313
516733
|
--listen <url> WebSocket listen URL. Defaults to ws://127.0.0.1:0
|
|
516734
|
+
--ws-auth <mode> WebSocket auth mode for non-loopback listeners. Supported: capability-token, signed-bearer-token
|
|
516735
|
+
--ws-token-file <path> Absolute path to the capability-token file
|
|
516736
|
+
--ws-token-sha256 <hex> Hex-encoded SHA-256 digest of the capability token
|
|
516737
|
+
--ws-shared-secret-file <path> Absolute path to the shared secret file for signed JWT bearer tokens
|
|
516738
|
+
--ws-issuer <issuer> Expected issuer for signed JWT bearer tokens
|
|
516739
|
+
--ws-audience <audience> Expected audience for signed JWT bearer tokens
|
|
516740
|
+
--ws-max-clock-skew-seconds <seconds> Maximum clock skew for signed JWT bearer token validation
|
|
517314
516741
|
-h, --help Show this help message
|
|
517315
516742
|
|
|
517316
516743
|
Examples:
|
|
517317
516744
|
letta app-server
|
|
517318
|
-
letta app-server --listen ws://127.0.0.1:4500
|
|
516745
|
+
letta app-server --listen ws://127.0.0.1:4500
|
|
516746
|
+
letta app-server --listen ws://0.0.0.0:4500 --ws-auth capability-token --ws-token-file /path/to/token
|
|
516747
|
+
letta app-server --listen ws://0.0.0.0:4500 --ws-auth signed-bearer-token --ws-shared-secret-file /path/to/secret`);
|
|
517319
516748
|
}
|
|
517320
516749
|
async function waitForShutdown(close) {
|
|
517321
516750
|
return await new Promise((resolve31) => {
|
|
@@ -517345,7 +516774,14 @@ async function runAppServerSubcommand(argv) {
|
|
|
517345
516774
|
allowPositionals: false,
|
|
517346
516775
|
options: {
|
|
517347
516776
|
help: { type: "boolean", short: "h" },
|
|
517348
|
-
listen: { type: "string" }
|
|
516777
|
+
listen: { type: "string" },
|
|
516778
|
+
"ws-auth": { type: "string" },
|
|
516779
|
+
"ws-token-file": { type: "string" },
|
|
516780
|
+
"ws-token-sha256": { type: "string" },
|
|
516781
|
+
"ws-shared-secret-file": { type: "string" },
|
|
516782
|
+
"ws-issuer": { type: "string" },
|
|
516783
|
+
"ws-audience": { type: "string" },
|
|
516784
|
+
"ws-max-clock-skew-seconds": { type: "string" }
|
|
517349
516785
|
}
|
|
517350
516786
|
});
|
|
517351
516787
|
} catch (error54) {
|
|
@@ -517357,8 +516793,18 @@ async function runAppServerSubcommand(argv) {
|
|
|
517357
516793
|
return 0;
|
|
517358
516794
|
}
|
|
517359
516795
|
try {
|
|
516796
|
+
const websocketAuth = parseAppServerWebsocketAuthSettings({
|
|
516797
|
+
wsAuth: typeof parsed.values["ws-auth"] === "string" ? parsed.values["ws-auth"] : undefined,
|
|
516798
|
+
wsTokenFile: typeof parsed.values["ws-token-file"] === "string" ? parsed.values["ws-token-file"] : undefined,
|
|
516799
|
+
wsTokenSha256: typeof parsed.values["ws-token-sha256"] === "string" ? parsed.values["ws-token-sha256"] : undefined,
|
|
516800
|
+
wsSharedSecretFile: typeof parsed.values["ws-shared-secret-file"] === "string" ? parsed.values["ws-shared-secret-file"] : undefined,
|
|
516801
|
+
wsIssuer: typeof parsed.values["ws-issuer"] === "string" ? parsed.values["ws-issuer"] : undefined,
|
|
516802
|
+
wsAudience: typeof parsed.values["ws-audience"] === "string" ? parsed.values["ws-audience"] : undefined,
|
|
516803
|
+
wsMaxClockSkewSeconds: typeof parsed.values["ws-max-clock-skew-seconds"] === "string" ? parsed.values["ws-max-clock-skew-seconds"] : undefined
|
|
516804
|
+
});
|
|
517360
516805
|
const handle2 = await startAppServer({
|
|
517361
516806
|
listen: typeof parsed.values.listen === "string" ? parsed.values.listen : undefined,
|
|
516807
|
+
websocketAuth,
|
|
517362
516808
|
onListening: (info) => {
|
|
517363
516809
|
console.log(`Listening on ${info.url}`);
|
|
517364
516810
|
console.log(`Control: ${info.controlUrl}`);
|
|
@@ -518817,7 +518263,7 @@ init_telemetry();
|
|
|
518817
518263
|
import {
|
|
518818
518264
|
appendFileSync as appendFileSync7,
|
|
518819
518265
|
existsSync as existsSync41,
|
|
518820
|
-
mkdirSync as
|
|
518266
|
+
mkdirSync as mkdirSync29,
|
|
518821
518267
|
readdirSync as readdirSync16,
|
|
518822
518268
|
unlinkSync as unlinkSync7
|
|
518823
518269
|
} from "node:fs";
|
|
@@ -518883,7 +518329,7 @@ class RemoteSessionLog {
|
|
|
518883
518329
|
return;
|
|
518884
518330
|
try {
|
|
518885
518331
|
if (!existsSync41(REMOTE_LOG_DIR)) {
|
|
518886
|
-
|
|
518332
|
+
mkdirSync29(REMOTE_LOG_DIR, { recursive: true });
|
|
518887
518333
|
}
|
|
518888
518334
|
this.dirCreated = true;
|
|
518889
518335
|
} catch {}
|
|
@@ -519477,10 +518923,10 @@ import { randomUUID as randomUUID23 } from "node:crypto";
|
|
|
519477
518923
|
import {
|
|
519478
518924
|
copyFileSync as copyFileSync2,
|
|
519479
518925
|
existsSync as existsSync42,
|
|
519480
|
-
mkdirSync as
|
|
518926
|
+
mkdirSync as mkdirSync30,
|
|
519481
518927
|
readdirSync as readdirSync17,
|
|
519482
518928
|
readFileSync as readFileSync29,
|
|
519483
|
-
writeFileSync as
|
|
518929
|
+
writeFileSync as writeFileSync21
|
|
519484
518930
|
} from "node:fs";
|
|
519485
518931
|
import { join as join43 } from "node:path";
|
|
519486
518932
|
function readJsonl(path35) {
|
|
@@ -519496,7 +518942,7 @@ function isPiLocalMessage(value) {
|
|
|
519496
518942
|
return isRecord(value) && typeof value.id === "string" && (value.role === "user" || value.role === "assistant" || value.role === "toolResult") && Object.hasOwn(value, "content");
|
|
519497
518943
|
}
|
|
519498
518944
|
function writeJsonl(path35, items3) {
|
|
519499
|
-
|
|
518945
|
+
writeFileSync21(path35, `${items3.map((item) => JSON.stringify(item)).join(`
|
|
519500
518946
|
`)}
|
|
519501
518947
|
`);
|
|
519502
518948
|
}
|
|
@@ -519796,8 +519242,8 @@ function migrateLocalBackendTranscripts(input) {
|
|
|
519796
519242
|
if (legacyMessages.length === 0) {
|
|
519797
519243
|
result.skipped.push({ conversationDir, reason: "empty" });
|
|
519798
519244
|
if (!input.dryRun) {
|
|
519799
|
-
|
|
519800
|
-
|
|
519245
|
+
mkdirSync30(conversationDir, { recursive: true });
|
|
519246
|
+
writeFileSync21(manifestPath, `${JSON.stringify(manifest({}), null, 2)}
|
|
519801
519247
|
`);
|
|
519802
519248
|
}
|
|
519803
519249
|
continue;
|
|
@@ -519850,12 +519296,12 @@ function migrateLocalBackendTranscripts(input) {
|
|
|
519850
519296
|
}
|
|
519851
519297
|
}
|
|
519852
519298
|
conversation.in_context_message_ids = remapped;
|
|
519853
|
-
|
|
519299
|
+
writeFileSync21(conversationPath, `${JSON.stringify(conversation, null, 2)}
|
|
519854
519300
|
`);
|
|
519855
519301
|
}
|
|
519856
519302
|
} catch {}
|
|
519857
519303
|
}
|
|
519858
|
-
|
|
519304
|
+
writeFileSync21(manifestPath, `${JSON.stringify(manifest({
|
|
519859
519305
|
backupPath,
|
|
519860
519306
|
migratedFrom: repairVersioned ? hasLegacyUiRows ? "versioned-pi-transcript-with-legacy-ui-message-rows" : "versioned-pi-ai-message-jsonl" : undefined
|
|
519861
519307
|
}), null, 2)}
|
|
@@ -519932,7 +519378,7 @@ async function runLocalBackendSubcommand(argv) {
|
|
|
519932
519378
|
init_memory_filesystem2();
|
|
519933
519379
|
init_memory_git();
|
|
519934
519380
|
init_paths();
|
|
519935
|
-
import { cpSync, existsSync as existsSync43, mkdirSync as
|
|
519381
|
+
import { cpSync, existsSync as existsSync43, mkdirSync as mkdirSync31, rmSync as rmSync9, statSync as statSync16 } from "node:fs";
|
|
519936
519382
|
import { readdir as readdir10 } from "node:fs/promises";
|
|
519937
519383
|
import { dirname as dirname21, join as join44 } from "node:path";
|
|
519938
519384
|
import { parseArgs as parseArgs9 } from "node:util";
|
|
@@ -520259,7 +519705,7 @@ async function runMemorySubcommand(argv) {
|
|
|
520259
519705
|
return 1;
|
|
520260
519706
|
}
|
|
520261
519707
|
} else {
|
|
520262
|
-
|
|
519708
|
+
mkdirSync31(out, { recursive: true });
|
|
520263
519709
|
}
|
|
520264
519710
|
cpSync(root2, out, { recursive: true });
|
|
520265
519711
|
console.log(JSON.stringify({ exportedFrom: root2, exportedTo: out, agentId }, null, 2));
|
|
@@ -520715,7 +520161,7 @@ import {
|
|
|
520715
520161
|
readFileSync as readFileSync31,
|
|
520716
520162
|
rmSync as rmSync10,
|
|
520717
520163
|
statSync as statSync18,
|
|
520718
|
-
writeFileSync as
|
|
520164
|
+
writeFileSync as writeFileSync22
|
|
520719
520165
|
} from "node:fs";
|
|
520720
520166
|
import { mkdir as mkdir11, readdir as readdir11 } from "node:fs/promises";
|
|
520721
520167
|
import { tmpdir as tmpdir8 } from "node:os";
|
|
@@ -521085,7 +520531,7 @@ async function downloadDirectSkillFileSource(location, options3 = {}) {
|
|
|
521085
520531
|
try {
|
|
521086
520532
|
const sourceDir = join46(tmpDir, "skill");
|
|
521087
520533
|
await mkdir11(sourceDir, { recursive: true });
|
|
521088
|
-
|
|
520534
|
+
writeFileSync22(join46(sourceDir, "SKILL.md"), skillText, "utf8");
|
|
521089
520535
|
return { tmpDir, sourceDir };
|
|
521090
520536
|
} catch (error54) {
|
|
521091
520537
|
rmSync10(tmpDir, { recursive: true, force: true });
|
|
@@ -521137,7 +520583,7 @@ async function downloadClawHubSkillSource(location) {
|
|
|
521137
520583
|
if (!response.ok) {
|
|
521138
520584
|
throw new Error(`ClawHub download failed for ${location.slug}@${version2}: ${response.status}`);
|
|
521139
520585
|
}
|
|
521140
|
-
|
|
520586
|
+
writeFileSync22(zipPath, Buffer.from(await response.arrayBuffer()));
|
|
521141
520587
|
const { stdout } = await execFile15("unzip", ["-Z1", zipPath], {
|
|
521142
520588
|
timeout: 30000
|
|
521143
520589
|
});
|
|
@@ -521614,10 +521060,16 @@ init_debug();
|
|
|
521614
521060
|
init_fs();
|
|
521615
521061
|
init_secrets();
|
|
521616
521062
|
import { randomUUID as randomUUID24 } from "node:crypto";
|
|
521617
|
-
import {
|
|
521063
|
+
import { readFileSync as readFileSync32 } from "node:fs";
|
|
521618
521064
|
import { homedir as homedir27 } from "node:os";
|
|
521619
521065
|
import { join as join47, resolve as resolve33 } from "node:path";
|
|
521620
|
-
var OBSOLETE_SETTINGS_KEYS2 = [
|
|
521066
|
+
var OBSOLETE_SETTINGS_KEYS2 = [
|
|
521067
|
+
"reflectionBehavior",
|
|
521068
|
+
"enableSleeptime",
|
|
521069
|
+
"pinnedAgents",
|
|
521070
|
+
"pinnedAgentsByServer",
|
|
521071
|
+
"pinnedConversationsByServer"
|
|
521072
|
+
];
|
|
521621
521073
|
var DEFAULT_SETTINGS2 = {
|
|
521622
521074
|
lastAgent: null,
|
|
521623
521075
|
tokenStreaming: false,
|
|
@@ -521711,11 +521163,6 @@ class SettingsManager2 {
|
|
|
521711
521163
|
clearSecureTokensCache() {
|
|
521712
521164
|
this.secureTokensCache = {};
|
|
521713
521165
|
}
|
|
521714
|
-
ensureInitialized() {
|
|
521715
|
-
if (!this.initialized || !this.settings) {
|
|
521716
|
-
throw new Error("Settings not initialized. Call settingsManager.initialize() first.");
|
|
521717
|
-
}
|
|
521718
|
-
}
|
|
521719
521166
|
readJsonObjectSync(path35) {
|
|
521720
521167
|
if (!exists(path35))
|
|
521721
521168
|
return {};
|
|
@@ -521725,57 +521172,6 @@ class SettingsManager2 {
|
|
|
521725
521172
|
return {};
|
|
521726
521173
|
}
|
|
521727
521174
|
}
|
|
521728
|
-
normalizeSettingsRecord(raw2) {
|
|
521729
|
-
const normalized = { ...raw2 };
|
|
521730
|
-
for (const key2 of OBSOLETE_SETTINGS_KEYS2) {
|
|
521731
|
-
delete normalized[key2];
|
|
521732
|
-
}
|
|
521733
|
-
return normalized;
|
|
521734
|
-
}
|
|
521735
|
-
settingsFromRaw(raw2) {
|
|
521736
|
-
return {
|
|
521737
|
-
...DEFAULT_SETTINGS2,
|
|
521738
|
-
...this.normalizeSettingsRecord(raw2)
|
|
521739
|
-
};
|
|
521740
|
-
}
|
|
521741
|
-
readSettingsSnapshot() {
|
|
521742
|
-
this.ensureInitialized();
|
|
521743
|
-
const raw2 = this.readJsonObjectSync(this.getSettingsPath());
|
|
521744
|
-
const mergedRaw = this.normalizeSettingsRecord(raw2);
|
|
521745
|
-
if (this.settings) {
|
|
521746
|
-
const currentRecord = this.settings;
|
|
521747
|
-
for (const key2 of this.dirtyKeys) {
|
|
521748
|
-
if (key2 in currentRecord) {
|
|
521749
|
-
mergedRaw[key2] = currentRecord[key2];
|
|
521750
|
-
} else {
|
|
521751
|
-
delete mergedRaw[key2];
|
|
521752
|
-
}
|
|
521753
|
-
}
|
|
521754
|
-
}
|
|
521755
|
-
const settings3 = this.settingsFromRaw(mergedRaw);
|
|
521756
|
-
this.settings = settings3;
|
|
521757
|
-
for (const key2 of Object.keys(mergedRaw)) {
|
|
521758
|
-
this.managedKeys.add(key2);
|
|
521759
|
-
}
|
|
521760
|
-
return settings3;
|
|
521761
|
-
}
|
|
521762
|
-
writeSettingsRecordSync(raw2) {
|
|
521763
|
-
const settingsPath = this.getSettingsPath();
|
|
521764
|
-
const home = process.env.HOME || homedir27();
|
|
521765
|
-
const dirPath = join47(home, ".letta");
|
|
521766
|
-
if (!exists(dirPath)) {
|
|
521767
|
-
mkdirSync33(dirPath, { recursive: true });
|
|
521768
|
-
}
|
|
521769
|
-
const normalized = this.normalizeSettingsRecord(raw2);
|
|
521770
|
-
writeFileSync24(settingsPath, JSON.stringify(normalized, null, 2), {
|
|
521771
|
-
encoding: "utf-8",
|
|
521772
|
-
flush: true
|
|
521773
|
-
});
|
|
521774
|
-
this.settings = this.settingsFromRaw(normalized);
|
|
521775
|
-
for (const key2 of Object.keys(normalized)) {
|
|
521776
|
-
this.managedKeys.add(key2);
|
|
521777
|
-
}
|
|
521778
|
-
}
|
|
521779
521175
|
get isReady() {
|
|
521780
521176
|
return this.initialized;
|
|
521781
521177
|
}
|
|
@@ -521824,7 +521220,6 @@ class SettingsManager2 {
|
|
|
521824
521220
|
if (!isSubagentProcess3()) {
|
|
521825
521221
|
await this.migrateTokensToSecrets();
|
|
521826
521222
|
}
|
|
521827
|
-
this.migrateToAgentsArray();
|
|
521828
521223
|
} catch (error54) {
|
|
521829
521224
|
trackBoundaryError({
|
|
521830
521225
|
errorType: "settings_load_failed",
|
|
@@ -521841,7 +521236,6 @@ class SettingsManager2 {
|
|
|
521841
521236
|
if (!isSubagentProcess3()) {
|
|
521842
521237
|
await this.migrateTokensToSecrets();
|
|
521843
521238
|
}
|
|
521844
|
-
this.migrateToAgentsArray();
|
|
521845
521239
|
}
|
|
521846
521240
|
}
|
|
521847
521241
|
async checkSecretsSupport() {
|
|
@@ -521896,46 +521290,6 @@ class SettingsManager2 {
|
|
|
521896
521290
|
console.warn("Failed to migrate tokens to secrets:", error54);
|
|
521897
521291
|
}
|
|
521898
521292
|
}
|
|
521899
|
-
migrateToAgentsArray() {
|
|
521900
|
-
if (!this.settings)
|
|
521901
|
-
return;
|
|
521902
|
-
if (this.settings.agents)
|
|
521903
|
-
return;
|
|
521904
|
-
const agents = [];
|
|
521905
|
-
const seen = new Set;
|
|
521906
|
-
if (this.settings.pinnedAgentsByServer) {
|
|
521907
|
-
for (const [serverKey, agentIds] of Object.entries(this.settings.pinnedAgentsByServer)) {
|
|
521908
|
-
for (const agentId of agentIds) {
|
|
521909
|
-
const baseUrl = serverKey === "api.letta.com" ? undefined : serverKey;
|
|
521910
|
-
const key2 = `${agentId}@${baseUrl ?? "cloud"}`;
|
|
521911
|
-
if (!seen.has(key2)) {
|
|
521912
|
-
agents.push({
|
|
521913
|
-
agentId,
|
|
521914
|
-
baseUrl,
|
|
521915
|
-
pinned: true
|
|
521916
|
-
});
|
|
521917
|
-
seen.add(key2);
|
|
521918
|
-
}
|
|
521919
|
-
}
|
|
521920
|
-
}
|
|
521921
|
-
}
|
|
521922
|
-
if (this.settings.pinnedAgents) {
|
|
521923
|
-
for (const agentId of this.settings.pinnedAgents) {
|
|
521924
|
-
const key2 = `${agentId}@cloud`;
|
|
521925
|
-
if (!seen.has(key2)) {
|
|
521926
|
-
agents.push({ agentId, pinned: true });
|
|
521927
|
-
seen.add(key2);
|
|
521928
|
-
}
|
|
521929
|
-
}
|
|
521930
|
-
}
|
|
521931
|
-
if (agents.length > 0) {
|
|
521932
|
-
this.settings = { ...this.settings, agents };
|
|
521933
|
-
this.markDirty("agents");
|
|
521934
|
-
this.persistSettings().catch((error54) => {
|
|
521935
|
-
console.warn("Failed to persist agents array migration:", error54);
|
|
521936
|
-
});
|
|
521937
|
-
}
|
|
521938
|
-
}
|
|
521939
521293
|
getSettings() {
|
|
521940
521294
|
if (!this.initialized || !this.settings) {
|
|
521941
521295
|
throw new Error("Settings not initialized. Call settingsManager.initialize() first.");
|
|
@@ -522576,182 +521930,20 @@ class SettingsManager2 {
|
|
|
522576
521930
|
}, workingDirectory);
|
|
522577
521931
|
return hadGoal;
|
|
522578
521932
|
}
|
|
522579
|
-
|
|
521933
|
+
getPinnedAgents() {
|
|
522580
521934
|
const settings3 = this.getSettings();
|
|
522581
521935
|
const serverKey = getCurrentServerKey2(settings3);
|
|
522582
|
-
|
|
522583
|
-
|
|
522584
|
-
}
|
|
522585
|
-
if (settings3.profiles && !settings3.pinnedAgents) {
|
|
522586
|
-
const agentIds = Object.values(settings3.profiles);
|
|
522587
|
-
this.updateSettings({ pinnedAgents: agentIds, profiles: undefined });
|
|
522588
|
-
return agentIds;
|
|
522589
|
-
}
|
|
522590
|
-
return settings3.pinnedAgents || [];
|
|
522591
|
-
}
|
|
522592
|
-
getLocalPinnedAgents(workingDirectory = process.cwd()) {
|
|
522593
|
-
const globalSettings = this.getSettings();
|
|
522594
|
-
const serverKey = getCurrentServerKey2(globalSettings);
|
|
522595
|
-
const localSettings = this.getLocalProjectSettings(workingDirectory);
|
|
522596
|
-
if (localSettings.pinnedAgentsByServer?.[serverKey]) {
|
|
522597
|
-
return localSettings.pinnedAgentsByServer[serverKey];
|
|
522598
|
-
}
|
|
522599
|
-
if (localSettings.profiles && !localSettings.pinnedAgents) {
|
|
522600
|
-
const agentIds = Object.values(localSettings.profiles);
|
|
522601
|
-
this.updateLocalProjectSettings({ pinnedAgents: agentIds, profiles: undefined }, workingDirectory);
|
|
522602
|
-
return agentIds;
|
|
522603
|
-
}
|
|
522604
|
-
return localSettings.pinnedAgents || [];
|
|
522605
|
-
}
|
|
522606
|
-
getMergedPinnedAgents(workingDirectory = process.cwd()) {
|
|
522607
|
-
const globalAgents = this.getGlobalPinnedAgents();
|
|
522608
|
-
const localAgents = this.getLocalPinnedAgents(workingDirectory);
|
|
522609
|
-
const result = [];
|
|
522610
|
-
const seenAgentIds = new Set;
|
|
522611
|
-
for (const agentId of localAgents) {
|
|
522612
|
-
result.push({ agentId, isLocal: true });
|
|
522613
|
-
seenAgentIds.add(agentId);
|
|
522614
|
-
}
|
|
522615
|
-
for (const agentId of globalAgents) {
|
|
522616
|
-
if (!seenAgentIds.has(agentId)) {
|
|
522617
|
-
result.push({ agentId, isLocal: false });
|
|
522618
|
-
seenAgentIds.add(agentId);
|
|
522619
|
-
}
|
|
522620
|
-
}
|
|
522621
|
-
return result;
|
|
522622
|
-
}
|
|
522623
|
-
getGlobalPinnedConversations(agentId) {
|
|
522624
|
-
const settings3 = this.readSettingsSnapshot();
|
|
522625
|
-
const serverKey = getCurrentServerKey2(settings3);
|
|
522626
|
-
return settings3.pinnedConversationsByServer?.[serverKey]?.[agentId] ?? [];
|
|
522627
|
-
}
|
|
522628
|
-
readLocalProjectSettingsSnapshot(workingDirectory) {
|
|
522629
|
-
const raw2 = this.normalizeSettingsRecord(this.readJsonObjectSync(this.getLocalProjectSettingsPath(workingDirectory)));
|
|
522630
|
-
const settings3 = {
|
|
522631
|
-
...DEFAULT_LOCAL_PROJECT_SETTINGS2,
|
|
522632
|
-
...raw2
|
|
522633
|
-
};
|
|
522634
|
-
this.localProjectSettings.set(workingDirectory, settings3);
|
|
522635
|
-
return settings3;
|
|
522636
|
-
}
|
|
522637
|
-
writeLocalProjectSettingsRecordSync(workingDirectory, raw2) {
|
|
522638
|
-
const dirPath = join47(workingDirectory, ".letta");
|
|
522639
|
-
if (!exists(dirPath)) {
|
|
522640
|
-
mkdirSync33(dirPath, { recursive: true });
|
|
522641
|
-
}
|
|
522642
|
-
const normalized = this.normalizeSettingsRecord(raw2);
|
|
522643
|
-
writeFileSync24(this.getLocalProjectSettingsPath(workingDirectory), JSON.stringify(normalized, null, 2), { encoding: "utf-8", flush: true });
|
|
522644
|
-
this.localProjectSettings.set(workingDirectory, {
|
|
522645
|
-
...DEFAULT_LOCAL_PROJECT_SETTINGS2,
|
|
522646
|
-
...normalized
|
|
522647
|
-
});
|
|
522648
|
-
}
|
|
522649
|
-
getLocalPinnedConversations(agentId, workingDirectory = process.cwd()) {
|
|
522650
|
-
const globalSettings = this.readSettingsSnapshot();
|
|
522651
|
-
const serverKey = getCurrentServerKey2(globalSettings);
|
|
522652
|
-
const localSettings = this.readLocalProjectSettingsSnapshot(workingDirectory);
|
|
522653
|
-
return localSettings.pinnedConversationsByServer?.[serverKey]?.[agentId] ?? [];
|
|
522654
|
-
}
|
|
522655
|
-
getMergedPinnedConversations(agentId, workingDirectory = process.cwd()) {
|
|
522656
|
-
const localConversations = this.getLocalPinnedConversations(agentId, workingDirectory);
|
|
522657
|
-
const globalConversations = this.getGlobalPinnedConversations(agentId);
|
|
522658
|
-
const result = [];
|
|
522659
|
-
const seenConversationIds = new Set;
|
|
522660
|
-
for (const conversationId of localConversations) {
|
|
522661
|
-
result.push({ conversationId, isLocal: true });
|
|
522662
|
-
seenConversationIds.add(conversationId);
|
|
522663
|
-
}
|
|
522664
|
-
for (const conversationId of globalConversations) {
|
|
522665
|
-
if (!seenConversationIds.has(conversationId)) {
|
|
522666
|
-
result.push({ conversationId, isLocal: false });
|
|
522667
|
-
seenConversationIds.add(conversationId);
|
|
522668
|
-
}
|
|
522669
|
-
}
|
|
522670
|
-
return result;
|
|
522671
|
-
}
|
|
522672
|
-
pinConversationGlobal(agentId, conversationId) {
|
|
522673
|
-
this.ensureInitialized();
|
|
522674
|
-
const raw2 = this.normalizeSettingsRecord(this.readJsonObjectSync(this.getSettingsPath()));
|
|
522675
|
-
const settings3 = this.settingsFromRaw(raw2);
|
|
522676
|
-
const serverKey = getCurrentServerKey2(settings3);
|
|
522677
|
-
const current = settings3.pinnedConversationsByServer?.[serverKey]?.[agentId] ?? [];
|
|
522678
|
-
if (current.includes(conversationId))
|
|
522679
|
-
return;
|
|
522680
|
-
this.writeSettingsRecordSync({
|
|
522681
|
-
...raw2,
|
|
522682
|
-
pinnedConversationsByServer: {
|
|
522683
|
-
...settings3.pinnedConversationsByServer ?? {},
|
|
522684
|
-
[serverKey]: {
|
|
522685
|
-
...settings3.pinnedConversationsByServer?.[serverKey] ?? {},
|
|
522686
|
-
[agentId]: [...current, conversationId]
|
|
522687
|
-
}
|
|
522688
|
-
}
|
|
522689
|
-
});
|
|
522690
|
-
this.dirtyKeys.delete("pinnedConversationsByServer");
|
|
522691
|
-
}
|
|
522692
|
-
unpinConversationGlobal(agentId, conversationId) {
|
|
522693
|
-
this.ensureInitialized();
|
|
522694
|
-
const raw2 = this.normalizeSettingsRecord(this.readJsonObjectSync(this.getSettingsPath()));
|
|
522695
|
-
const settings3 = this.settingsFromRaw(raw2);
|
|
522696
|
-
const serverKey = getCurrentServerKey2(settings3);
|
|
522697
|
-
const current = settings3.pinnedConversationsByServer?.[serverKey]?.[agentId] ?? [];
|
|
522698
|
-
this.writeSettingsRecordSync({
|
|
522699
|
-
...raw2,
|
|
522700
|
-
pinnedConversationsByServer: {
|
|
522701
|
-
...settings3.pinnedConversationsByServer ?? {},
|
|
522702
|
-
[serverKey]: {
|
|
522703
|
-
...settings3.pinnedConversationsByServer?.[serverKey] ?? {},
|
|
522704
|
-
[agentId]: current.filter((id2) => id2 !== conversationId)
|
|
522705
|
-
}
|
|
522706
|
-
}
|
|
522707
|
-
});
|
|
522708
|
-
this.dirtyKeys.delete("pinnedConversationsByServer");
|
|
521936
|
+
const normalizedBaseUrl = serverKey === "api.letta.com" ? undefined : serverKey;
|
|
521937
|
+
return settings3.agents?.filter((a2) => a2.pinned && (a2.baseUrl ?? undefined) === normalizedBaseUrl).map((a2) => a2.agentId) ?? [];
|
|
522709
521938
|
}
|
|
522710
|
-
|
|
522711
|
-
|
|
522712
|
-
const serverKey = getCurrentServerKey2(globalSettings);
|
|
522713
|
-
const raw2 = this.normalizeSettingsRecord(this.readJsonObjectSync(this.getLocalProjectSettingsPath(workingDirectory)));
|
|
522714
|
-
const localSettings = {
|
|
522715
|
-
...DEFAULT_LOCAL_PROJECT_SETTINGS2,
|
|
522716
|
-
...raw2
|
|
522717
|
-
};
|
|
522718
|
-
const current = localSettings.pinnedConversationsByServer?.[serverKey]?.[agentId] ?? [];
|
|
522719
|
-
if (current.includes(conversationId))
|
|
522720
|
-
return;
|
|
522721
|
-
this.writeLocalProjectSettingsRecordSync(workingDirectory, {
|
|
522722
|
-
...raw2,
|
|
522723
|
-
pinnedConversationsByServer: {
|
|
522724
|
-
...localSettings.pinnedConversationsByServer ?? {},
|
|
522725
|
-
[serverKey]: {
|
|
522726
|
-
...localSettings.pinnedConversationsByServer?.[serverKey] ?? {},
|
|
522727
|
-
[agentId]: [...current, conversationId]
|
|
522728
|
-
}
|
|
522729
|
-
}
|
|
522730
|
-
});
|
|
521939
|
+
isAgentPinned(agentId) {
|
|
521940
|
+
return this.getPinnedAgents().includes(agentId);
|
|
522731
521941
|
}
|
|
522732
|
-
|
|
522733
|
-
|
|
522734
|
-
const serverKey = getCurrentServerKey2(globalSettings);
|
|
522735
|
-
const raw2 = this.normalizeSettingsRecord(this.readJsonObjectSync(this.getLocalProjectSettingsPath(workingDirectory)));
|
|
522736
|
-
const localSettings = {
|
|
522737
|
-
...DEFAULT_LOCAL_PROJECT_SETTINGS2,
|
|
522738
|
-
...raw2
|
|
522739
|
-
};
|
|
522740
|
-
const current = localSettings.pinnedConversationsByServer?.[serverKey]?.[agentId] ?? [];
|
|
522741
|
-
this.writeLocalProjectSettingsRecordSync(workingDirectory, {
|
|
522742
|
-
...raw2,
|
|
522743
|
-
pinnedConversationsByServer: {
|
|
522744
|
-
...localSettings.pinnedConversationsByServer ?? {},
|
|
522745
|
-
[serverKey]: {
|
|
522746
|
-
...localSettings.pinnedConversationsByServer?.[serverKey] ?? {},
|
|
522747
|
-
[agentId]: current.filter((id2) => id2 !== conversationId)
|
|
522748
|
-
}
|
|
522749
|
-
}
|
|
522750
|
-
});
|
|
521942
|
+
pinAgent(agentId) {
|
|
521943
|
+
this.upsertAgentSettings(agentId, { pinned: true });
|
|
522751
521944
|
}
|
|
522752
|
-
|
|
522753
|
-
this.
|
|
522754
|
-
this.unpinConversationGlobal(agentId, conversationId);
|
|
521945
|
+
unpinAgent(agentId) {
|
|
521946
|
+
this.upsertAgentSettings(agentId, { pinned: false });
|
|
522755
521947
|
}
|
|
522756
521948
|
getGlobalProfiles() {
|
|
522757
521949
|
return this.getSettings().profiles || {};
|
|
@@ -522760,100 +521952,17 @@ class SettingsManager2 {
|
|
|
522760
521952
|
const localSettings = this.getLocalProjectSettings(workingDirectory);
|
|
522761
521953
|
return localSettings.profiles || {};
|
|
522762
521954
|
}
|
|
522763
|
-
getMergedProfiles(
|
|
522764
|
-
|
|
522765
|
-
return merged.map(({ agentId, isLocal }) => ({
|
|
521955
|
+
getMergedProfiles(_workingDirectory = process.cwd()) {
|
|
521956
|
+
return this.getPinnedAgents().map((agentId) => ({
|
|
522766
521957
|
name: "",
|
|
522767
521958
|
agentId,
|
|
522768
|
-
isLocal
|
|
521959
|
+
isLocal: false
|
|
522769
521960
|
}));
|
|
522770
521961
|
}
|
|
522771
|
-
pinBoth(agentId, workingDirectory = process.cwd()) {
|
|
522772
|
-
this.pinGlobal(agentId);
|
|
522773
|
-
this.pinLocal(agentId, workingDirectory);
|
|
522774
|
-
}
|
|
522775
|
-
saveProfile(_name, agentId, workingDirectory = process.cwd()) {
|
|
522776
|
-
this.pinBoth(agentId, workingDirectory);
|
|
522777
|
-
}
|
|
522778
|
-
pinLocal(agentId, workingDirectory = process.cwd()) {
|
|
522779
|
-
const globalSettings = this.getSettings();
|
|
522780
|
-
const serverKey = getCurrentServerKey2(globalSettings);
|
|
522781
|
-
const localSettings = this.getLocalProjectSettings(workingDirectory);
|
|
522782
|
-
const localAgents = this.getLocalPinnedAgents(workingDirectory);
|
|
522783
|
-
if (!localAgents.includes(agentId)) {
|
|
522784
|
-
const newAgents = [...localAgents, agentId];
|
|
522785
|
-
const pinnedAgentsByServer = {
|
|
522786
|
-
...localSettings.pinnedAgentsByServer,
|
|
522787
|
-
[serverKey]: newAgents
|
|
522788
|
-
};
|
|
522789
|
-
this.updateLocalProjectSettings({
|
|
522790
|
-
pinnedAgentsByServer,
|
|
522791
|
-
pinnedAgents: newAgents
|
|
522792
|
-
}, workingDirectory);
|
|
522793
|
-
}
|
|
522794
|
-
}
|
|
522795
|
-
unpinLocal(agentId, workingDirectory = process.cwd()) {
|
|
522796
|
-
const globalSettings = this.getSettings();
|
|
522797
|
-
const serverKey = getCurrentServerKey2(globalSettings);
|
|
522798
|
-
const localSettings = this.getLocalProjectSettings(workingDirectory);
|
|
522799
|
-
const localAgents = this.getLocalPinnedAgents(workingDirectory);
|
|
522800
|
-
const newAgents = localAgents.filter((id2) => id2 !== agentId);
|
|
522801
|
-
const pinnedAgentsByServer = {
|
|
522802
|
-
...localSettings.pinnedAgentsByServer,
|
|
522803
|
-
[serverKey]: newAgents
|
|
522804
|
-
};
|
|
522805
|
-
this.updateLocalProjectSettings({
|
|
522806
|
-
pinnedAgentsByServer,
|
|
522807
|
-
pinnedAgents: newAgents
|
|
522808
|
-
}, workingDirectory);
|
|
522809
|
-
}
|
|
522810
521962
|
shouldCreateDefaultAgents() {
|
|
522811
521963
|
const settings3 = this.getSettings();
|
|
522812
521964
|
return settings3.createDefaultAgents !== false;
|
|
522813
521965
|
}
|
|
522814
|
-
pinGlobal(agentId) {
|
|
522815
|
-
const settings3 = this.getSettings();
|
|
522816
|
-
const serverKey = getCurrentServerKey2(settings3);
|
|
522817
|
-
const globalAgents = this.getGlobalPinnedAgents();
|
|
522818
|
-
if (!globalAgents.includes(agentId)) {
|
|
522819
|
-
const newAgents = [...globalAgents, agentId];
|
|
522820
|
-
const pinnedAgentsByServer = {
|
|
522821
|
-
...settings3.pinnedAgentsByServer,
|
|
522822
|
-
[serverKey]: newAgents
|
|
522823
|
-
};
|
|
522824
|
-
this.updateSettings({
|
|
522825
|
-
pinnedAgentsByServer,
|
|
522826
|
-
pinnedAgents: newAgents
|
|
522827
|
-
});
|
|
522828
|
-
}
|
|
522829
|
-
}
|
|
522830
|
-
unpinGlobal(agentId) {
|
|
522831
|
-
const settings3 = this.getSettings();
|
|
522832
|
-
const serverKey = getCurrentServerKey2(settings3);
|
|
522833
|
-
const globalAgents = this.getGlobalPinnedAgents();
|
|
522834
|
-
const newAgents = globalAgents.filter((id2) => id2 !== agentId);
|
|
522835
|
-
const pinnedAgentsByServer = {
|
|
522836
|
-
...settings3.pinnedAgentsByServer,
|
|
522837
|
-
[serverKey]: newAgents
|
|
522838
|
-
};
|
|
522839
|
-
this.updateSettings({
|
|
522840
|
-
pinnedAgentsByServer,
|
|
522841
|
-
pinnedAgents: newAgents
|
|
522842
|
-
});
|
|
522843
|
-
}
|
|
522844
|
-
unpinBoth(agentId, workingDirectory = process.cwd()) {
|
|
522845
|
-
this.unpinLocal(agentId, workingDirectory);
|
|
522846
|
-
this.unpinGlobal(agentId);
|
|
522847
|
-
}
|
|
522848
|
-
deleteProfile(_name, _workingDirectory = process.cwd()) {
|
|
522849
|
-
console.warn("deleteProfile is deprecated, use unpinBoth(agentId) instead");
|
|
522850
|
-
}
|
|
522851
|
-
pinProfile(_name, agentId, workingDirectory = process.cwd()) {
|
|
522852
|
-
this.pinLocal(agentId, workingDirectory);
|
|
522853
|
-
}
|
|
522854
|
-
unpinProfile(_name, _workingDirectory = process.cwd()) {
|
|
522855
|
-
console.warn("unpinProfile is deprecated, use unpinLocal(agentId) instead");
|
|
522856
|
-
}
|
|
522857
521966
|
getListenerEnvName(workingDirectory = process.cwd()) {
|
|
522858
521967
|
try {
|
|
522859
521968
|
const localSettings = this.getLocalProjectSettings(workingDirectory);
|
|
@@ -523690,12 +522799,10 @@ SUBCOMMANDS
|
|
|
523690
522799
|
BEHAVIOR
|
|
523691
522800
|
On startup, Letta Code checks for saved profiles:
|
|
523692
522801
|
- If profiles exist, you'll be prompted to select one or create a new agent
|
|
523693
|
-
-
|
|
522802
|
+
- Agents can be pinned for quick access with /pin
|
|
523694
522803
|
- Use /profile save <name> to bookmark your current agent
|
|
523695
522804
|
|
|
523696
|
-
|
|
523697
|
-
- Global: ~/.letta/settings.json (available everywhere)
|
|
523698
|
-
- Local: .letta/settings.local.json (pinned to project)
|
|
522805
|
+
Agent pins are stored in ~/.letta/settings.json.
|
|
523699
522806
|
|
|
523700
522807
|
If no credentials are configured, you'll be prompted to authenticate via
|
|
523701
522808
|
Letta Cloud OAuth on first run.
|
|
@@ -523710,8 +522817,8 @@ EXAMPLES
|
|
|
523710
522817
|
# inside the interactive session
|
|
523711
522818
|
/profile save MyAgent # Save current agent as profile
|
|
523712
522819
|
/profiles # Open profile selector
|
|
523713
|
-
/pin # Pin current
|
|
523714
|
-
/unpin # Unpin
|
|
522820
|
+
/pin # Pin current agent
|
|
522821
|
+
/unpin # Unpin current agent
|
|
523715
522822
|
/logout # Clear saved credentials and exit
|
|
523716
522823
|
|
|
523717
522824
|
# headless with JSON output (includes stats)
|
|
@@ -523729,17 +522836,12 @@ async function printInfo() {
|
|
|
523729
522836
|
const skillsDir = join68(cwd2, SKILLS_DIR3);
|
|
523730
522837
|
const skillsExist = exists3(skillsDir);
|
|
523731
522838
|
await settingsManager2.loadLocalProjectSettings(cwd2);
|
|
523732
|
-
const
|
|
523733
|
-
const globalPinned = settingsManager2.getGlobalPinnedAgents();
|
|
522839
|
+
const pinned = settingsManager2.getPinnedAgents();
|
|
523734
522840
|
const localSettings = settingsManager2.getLocalProjectSettings(cwd2);
|
|
523735
522841
|
const lastAgent = localSettings.lastAgent;
|
|
523736
522842
|
const agentNames = {};
|
|
523737
522843
|
const allAgentIds = [
|
|
523738
|
-
...new Set([
|
|
523739
|
-
...localPinned,
|
|
523740
|
-
...globalPinned,
|
|
523741
|
-
...lastAgent ? [lastAgent] : []
|
|
523742
|
-
])
|
|
522844
|
+
...new Set([...pinned, ...lastAgent ? [lastAgent] : []])
|
|
523743
522845
|
];
|
|
523744
522846
|
if (allAgentIds.length > 0) {
|
|
523745
522847
|
try {
|
|
@@ -523763,32 +522865,22 @@ async function printInfo() {
|
|
|
523763
522865
|
console.log("");
|
|
523764
522866
|
if (lastAgent) {
|
|
523765
522867
|
console.log(`Will resume: ${formatAgent(lastAgent)}`);
|
|
523766
|
-
} else if (
|
|
522868
|
+
} else if (pinned.length > 0) {
|
|
523767
522869
|
console.log("Will resume: (will show selector)");
|
|
523768
522870
|
} else {
|
|
523769
522871
|
console.log("Will resume: (will create new agent)");
|
|
523770
522872
|
}
|
|
523771
522873
|
console.log("");
|
|
523772
|
-
if (
|
|
523773
|
-
console.log("
|
|
523774
|
-
for (const id2 of
|
|
522874
|
+
if (pinned.length > 0) {
|
|
522875
|
+
console.log("Pinned agents:");
|
|
522876
|
+
for (const id2 of pinned) {
|
|
523775
522877
|
const isLast = id2 === lastAgent;
|
|
523776
522878
|
const prefix = isLast ? "\u2192 " : " ";
|
|
523777
522879
|
const suffix = isLast ? " (last used)" : "";
|
|
523778
522880
|
console.log(` ${prefix}${formatAgent(id2)}${suffix}`);
|
|
523779
522881
|
}
|
|
523780
522882
|
} else {
|
|
523781
|
-
console.log("
|
|
523782
|
-
}
|
|
523783
|
-
console.log("");
|
|
523784
|
-
if (globalPinned.length > 0) {
|
|
523785
|
-
console.log("Globally pinned agents:");
|
|
523786
|
-
for (const id2 of globalPinned) {
|
|
523787
|
-
const isLocal = localPinned.includes(id2);
|
|
523788
|
-
console.log(` ${formatAgent(id2)}${isLocal ? " (also local)" : ""}`);
|
|
523789
|
-
}
|
|
523790
|
-
} else {
|
|
523791
|
-
console.log("Globally pinned agents: (none)");
|
|
522883
|
+
console.log("Pinned agents: (none)");
|
|
523792
522884
|
}
|
|
523793
522885
|
}
|
|
523794
522886
|
function getModelForToolLoading(specifiedModel, specifiedToolset) {
|
|
@@ -523810,7 +522902,7 @@ function getPinnedAgentIdsForBackendMode(backendMode) {
|
|
|
523810
522902
|
const previousBackendMode = getCurrentBackendMode();
|
|
523811
522903
|
configureBackendMode(backendMode);
|
|
523812
522904
|
try {
|
|
523813
|
-
return settingsManager2.
|
|
522905
|
+
return settingsManager2.getPinnedAgents().filter((id2) => isAgentIdCompatibleWithBackend2(id2, backendMode));
|
|
523814
522906
|
} finally {
|
|
523815
522907
|
configureBackendMode(previousBackendMode);
|
|
523816
522908
|
}
|
|
@@ -524662,7 +523754,6 @@ Error: ${message}`);
|
|
|
524662
523754
|
const startupBackendMode = isExperimentalLocalBackendEnabled() ? "local" : "api";
|
|
524663
523755
|
const baseURL2 = process.env.LETTA_BASE_URL || settings3.env?.LETTA_BASE_URL || LETTA_CLOUD_API_URL2;
|
|
524664
523756
|
const isCustomApiBackend = startupBackendMode !== "local" && !baseURL2.includes("api.letta.com");
|
|
524665
|
-
const isCredentiallessLocalStartup = startupBackendMode === "local" && !isCustomApiBackend && !settings3.refreshToken && !apiKey;
|
|
524666
523757
|
setStartupHasCloudCredentials(Boolean(settings3.refreshToken || apiKey));
|
|
524667
523758
|
const startupModelsPromise = startupBackendMode === "local" ? backend4.listModels() : Promise.resolve([]);
|
|
524668
523759
|
if (startupBackendMode === "local") {
|
|
@@ -524752,12 +523843,12 @@ Error: ${message}`);
|
|
|
524752
523843
|
}
|
|
524753
523844
|
const rawLocalAgentId = settingsManager2.getLocalLastAgentId(process.cwd());
|
|
524754
523845
|
const rawGlobalAgentId = settingsManager2.getGlobalLastAgentId();
|
|
524755
|
-
const
|
|
524756
|
-
const
|
|
523846
|
+
const pinnedAgentIds = settingsManager2.getPinnedAgents().filter((agentId2) => isAgentIdCompatibleWithBackend2(agentId2, startupBackendMode));
|
|
523847
|
+
const pinnedAgentId = pinnedAgentIds.length === 1 ? pinnedAgentIds[0] ?? null : null;
|
|
524757
523848
|
const localAgentId = startupBackendMode === "local" && rawLocalAgentId && isAgentIdCompatibleWithBackend2(rawLocalAgentId, "local") ? rawLocalAgentId : null;
|
|
524758
523849
|
const globalAgentId = startupBackendMode === "api" && rawGlobalAgentId && isAgentIdCompatibleWithBackend2(rawGlobalAgentId, "api") ? rawGlobalAgentId : null;
|
|
524759
523850
|
const agentIdsToValidate = [
|
|
524760
|
-
...new Set([
|
|
523851
|
+
...new Set([pinnedAgentId, localAgentId, globalAgentId].filter((agentId2) => Boolean(agentId2)))
|
|
524761
523852
|
];
|
|
524762
523853
|
const validationResults = await Promise.allSettled(agentIdsToValidate.map(async (agentId2) => ({
|
|
524763
523854
|
agentId: agentId2,
|
|
@@ -524771,7 +523862,7 @@ Error: ${message}`);
|
|
|
524771
523862
|
cachedAgents.set(result.value.agentId, result.value.agent);
|
|
524772
523863
|
}
|
|
524773
523864
|
}
|
|
524774
|
-
const
|
|
523865
|
+
const pinnedAgentExists = pinnedAgentId ? cachedAgents.has(pinnedAgentId) : false;
|
|
524775
523866
|
let localAgentExists = false;
|
|
524776
523867
|
let globalAgentExists = false;
|
|
524777
523868
|
if (localAgentId) {
|
|
@@ -524784,14 +523875,14 @@ Error: ${message}`);
|
|
|
524784
523875
|
globalAgentExists = cachedAgents.has(globalAgentId);
|
|
524785
523876
|
}
|
|
524786
523877
|
markMilestone2("STARTUP_LRU_FETCH_DONE");
|
|
524787
|
-
const
|
|
523878
|
+
const pinnedCount = pinnedAgentIds.length;
|
|
524788
523879
|
const fallbackSession = startupBackendMode === "local" && !localAgentExists && !globalAgentExists ? await getLocalBackendStartupFallbackSession(backend4) : null;
|
|
524789
523880
|
const { resolveStartupTarget: resolveStartupTarget2 } = await Promise.resolve().then(() => exports_resolve_startup_agent);
|
|
524790
523881
|
const localSession = settingsManager2.getLocalLastSession(process.cwd());
|
|
524791
523882
|
const target2 = resolveStartupTarget2({
|
|
524792
|
-
|
|
524793
|
-
|
|
524794
|
-
|
|
523883
|
+
pinnedAgentId,
|
|
523884
|
+
pinnedAgentExists,
|
|
523885
|
+
pinnedCount,
|
|
524795
523886
|
localAgentId,
|
|
524796
523887
|
localConversationId: localSession?.conversationId ?? null,
|
|
524797
523888
|
localAgentExists,
|
|
@@ -524799,7 +523890,6 @@ Error: ${message}`);
|
|
|
524799
523890
|
globalAgentExists,
|
|
524800
523891
|
fallbackAgentId: fallbackSession?.agentId ?? null,
|
|
524801
523892
|
fallbackConversationId: fallbackSession?.conversationId ?? null,
|
|
524802
|
-
mergedPinnedCount: mergedPinned.length,
|
|
524803
523893
|
forceNew: false,
|
|
524804
523894
|
needsModelPicker
|
|
524805
523895
|
});
|
|
@@ -525365,4 +524455,4 @@ Error during initialization: ${message}`);
|
|
|
525365
524455
|
}
|
|
525366
524456
|
main2();
|
|
525367
524457
|
|
|
525368
|
-
//# debugId=
|
|
524458
|
+
//# debugId=5CE7DEEA8253909064756E2164756E21
|