@letta-ai/letta-code 0.12.7 → 0.12.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/letta.js +292 -31
- package/package.json +1 -1
package/letta.js
CHANGED
|
@@ -3237,7 +3237,7 @@ var package_default;
|
|
|
3237
3237
|
var init_package = __esm(() => {
|
|
3238
3238
|
package_default = {
|
|
3239
3239
|
name: "@letta-ai/letta-code",
|
|
3240
|
-
version: "0.12.
|
|
3240
|
+
version: "0.12.8",
|
|
3241
3241
|
description: "Letta Code is a CLI tool for interacting with stateful Letta agents from the terminal.",
|
|
3242
3242
|
type: "module",
|
|
3243
3243
|
bin: {
|
|
@@ -47793,6 +47793,7 @@ function SetupUI({ onComplete }) {
|
|
|
47793
47793
|
refreshToken: tokens.refresh_token,
|
|
47794
47794
|
tokenExpiresAt: now + tokens.expires_in * 1000
|
|
47795
47795
|
});
|
|
47796
|
+
await settingsManager.flush();
|
|
47796
47797
|
setMode("done");
|
|
47797
47798
|
setTimeout(() => onComplete(), 1000);
|
|
47798
47799
|
} catch (err) {
|
|
@@ -50592,6 +50593,9 @@ ${after}`;
|
|
|
50592
50593
|
function clipToolReturn(text, maxLines = 3, maxChars = 300) {
|
|
50593
50594
|
if (!text)
|
|
50594
50595
|
return text;
|
|
50596
|
+
if (text.includes("request to call tool denied")) {
|
|
50597
|
+
return text;
|
|
50598
|
+
}
|
|
50595
50599
|
let clipped = text;
|
|
50596
50600
|
if (text.length > maxChars) {
|
|
50597
50601
|
clipped = text.slice(0, maxChars);
|
|
@@ -51935,6 +51939,10 @@ var exports_check_approval = {};
|
|
|
51935
51939
|
__export(exports_check_approval, {
|
|
51936
51940
|
getResumeData: () => getResumeData2
|
|
51937
51941
|
});
|
|
51942
|
+
function isBackfillEnabled2() {
|
|
51943
|
+
const val = process.env.LETTA_BACKFILL;
|
|
51944
|
+
return val !== "0" && val !== "false";
|
|
51945
|
+
}
|
|
51938
51946
|
async function getResumeData2(client, agent) {
|
|
51939
51947
|
try {
|
|
51940
51948
|
const messagesPage = await client.agents.messages.list(agent.id);
|
|
@@ -51957,6 +51965,13 @@ async function getResumeData2(client, agent) {
|
|
|
51957
51965
|
const inContextLastMessageId = agent.message_ids && agent.message_ids.length > 0 ? agent.message_ids[agent.message_ids.length - 1] : null;
|
|
51958
51966
|
if (!inContextLastMessageId) {
|
|
51959
51967
|
debugWarn("check-approval", `No in-context messages (message_ids empty/null) - no pending approvals`);
|
|
51968
|
+
if (!isBackfillEnabled2()) {
|
|
51969
|
+
return {
|
|
51970
|
+
pendingApproval: null,
|
|
51971
|
+
pendingApprovals: [],
|
|
51972
|
+
messageHistory: []
|
|
51973
|
+
};
|
|
51974
|
+
}
|
|
51960
51975
|
const historyCount2 = Math.min(MESSAGE_HISTORY_LIMIT2, messages.length);
|
|
51961
51976
|
let messageHistory2 = messages.slice(-historyCount2);
|
|
51962
51977
|
if (messageHistory2[0]?.message_type === "tool_return_message") {
|
|
@@ -52007,6 +52022,9 @@ async function getResumeData2(client, agent) {
|
|
|
52007
52022
|
}
|
|
52008
52023
|
}
|
|
52009
52024
|
}
|
|
52025
|
+
if (!isBackfillEnabled2()) {
|
|
52026
|
+
return { pendingApproval, pendingApprovals, messageHistory: [] };
|
|
52027
|
+
}
|
|
52010
52028
|
const historyCount = Math.min(MESSAGE_HISTORY_LIMIT2, messages.length);
|
|
52011
52029
|
let messageHistory = messages.slice(-historyCount);
|
|
52012
52030
|
if (messageHistory[0]?.message_type === "tool_return_message") {
|
|
@@ -53012,7 +53030,17 @@ async function handleHeadlessCommand(argv, model, skillsDirectory) {
|
|
|
53012
53030
|
}
|
|
53013
53031
|
process.exit(1);
|
|
53014
53032
|
}
|
|
53015
|
-
|
|
53033
|
+
const nonRetriableReasons = [
|
|
53034
|
+
"cancelled",
|
|
53035
|
+
"requires_approval",
|
|
53036
|
+
"max_steps",
|
|
53037
|
+
"max_tokens_exceeded",
|
|
53038
|
+
"context_window_overflow_in_system_prompt",
|
|
53039
|
+
"end_turn",
|
|
53040
|
+
"tool_rule",
|
|
53041
|
+
"no_tool_call"
|
|
53042
|
+
];
|
|
53043
|
+
if (nonRetriableReasons.includes(stopReason)) {} else if (lastRunId && llmApiErrorRetries < LLM_API_ERROR_MAX_RETRIES) {
|
|
53016
53044
|
try {
|
|
53017
53045
|
const run = await client.runs.retrieve(lastRunId);
|
|
53018
53046
|
const metaError = run.metadata?.error;
|
|
@@ -53026,7 +53054,7 @@ async function handleHeadlessCommand(argv, model, skillsDirectory) {
|
|
|
53026
53054
|
"api_error",
|
|
53027
53055
|
"Network error"
|
|
53028
53056
|
];
|
|
53029
|
-
const isLlmErrorFromDetail =
|
|
53057
|
+
const isLlmErrorFromDetail = llmProviderPatterns.some((pattern) => detail.includes(pattern));
|
|
53030
53058
|
if (errorType === "llm_error" || isLlmErrorFromDetail) {
|
|
53031
53059
|
const attempt = llmApiErrorRetries + 1;
|
|
53032
53060
|
const baseDelayMs = 1000;
|
|
@@ -57518,7 +57546,10 @@ var init_BlinkDot = __esm(async () => {
|
|
|
57518
57546
|
var import_react35, jsx_dev_runtime15, COLLAPSED_LINES = 3, PREFIX_WIDTH = 5, CollapsedOutputDisplay;
|
|
57519
57547
|
var init_CollapsedOutputDisplay = __esm(async () => {
|
|
57520
57548
|
init_useTerminalWidth();
|
|
57521
|
-
await
|
|
57549
|
+
await __promiseAll([
|
|
57550
|
+
init_build2(),
|
|
57551
|
+
init_MarkdownDisplay()
|
|
57552
|
+
]);
|
|
57522
57553
|
import_react35 = __toESM(require_react(), 1);
|
|
57523
57554
|
jsx_dev_runtime15 = __toESM(require_jsx_dev_runtime(), 1);
|
|
57524
57555
|
CollapsedOutputDisplay = import_react35.memo(({ output }) => {
|
|
@@ -57550,9 +57581,8 @@ var init_CollapsedOutputDisplay = __esm(async () => {
|
|
|
57550
57581
|
/* @__PURE__ */ jsx_dev_runtime15.jsxDEV(Box_default, {
|
|
57551
57582
|
flexGrow: 1,
|
|
57552
57583
|
width: contentWidth,
|
|
57553
|
-
children: /* @__PURE__ */ jsx_dev_runtime15.jsxDEV(
|
|
57554
|
-
|
|
57555
|
-
children: visibleLines[0]
|
|
57584
|
+
children: /* @__PURE__ */ jsx_dev_runtime15.jsxDEV(MarkdownDisplay, {
|
|
57585
|
+
text: visibleLines[0] ?? ""
|
|
57556
57586
|
}, undefined, false, undefined, this)
|
|
57557
57587
|
}, undefined, false, undefined, this)
|
|
57558
57588
|
]
|
|
@@ -57570,9 +57600,8 @@ var init_CollapsedOutputDisplay = __esm(async () => {
|
|
|
57570
57600
|
/* @__PURE__ */ jsx_dev_runtime15.jsxDEV(Box_default, {
|
|
57571
57601
|
flexGrow: 1,
|
|
57572
57602
|
width: contentWidth,
|
|
57573
|
-
children: /* @__PURE__ */ jsx_dev_runtime15.jsxDEV(
|
|
57574
|
-
|
|
57575
|
-
children: line
|
|
57603
|
+
children: /* @__PURE__ */ jsx_dev_runtime15.jsxDEV(MarkdownDisplay, {
|
|
57604
|
+
text: line
|
|
57576
57605
|
}, undefined, false, undefined, this)
|
|
57577
57606
|
}, undefined, false, undefined, this)
|
|
57578
57607
|
]
|
|
@@ -59312,14 +59341,14 @@ Location: ${keybindingsPath}`;
|
|
|
59312
59341
|
}
|
|
59313
59342
|
},
|
|
59314
59343
|
"/connect": {
|
|
59315
|
-
desc: "Connect an existing
|
|
59344
|
+
desc: "Connect an existing account (/connect zai <api-key>)",
|
|
59316
59345
|
order: 40,
|
|
59317
59346
|
handler: () => {
|
|
59318
|
-
return "Initiating
|
|
59347
|
+
return "Initiating account connection...";
|
|
59319
59348
|
}
|
|
59320
59349
|
},
|
|
59321
59350
|
"/disconnect": {
|
|
59322
|
-
desc: "Disconnect
|
|
59351
|
+
desc: "Disconnect an existing account (/disconnect zai)",
|
|
59323
59352
|
order: 41,
|
|
59324
59353
|
handler: () => {
|
|
59325
59354
|
return "Disconnecting...";
|
|
@@ -69041,6 +69070,7 @@ var init_StaticPlanApproval = __esm(async () => {
|
|
|
69041
69070
|
onApprove,
|
|
69042
69071
|
onApproveAndAcceptEdits,
|
|
69043
69072
|
onKeepPlanning,
|
|
69073
|
+
onCancel,
|
|
69044
69074
|
isFocused = true
|
|
69045
69075
|
}) => {
|
|
69046
69076
|
const [selectedOption, setSelectedOption] = import_react71.useState(0);
|
|
@@ -69060,7 +69090,7 @@ var init_StaticPlanApproval = __esm(async () => {
|
|
|
69060
69090
|
if (!isFocused)
|
|
69061
69091
|
return;
|
|
69062
69092
|
if (key.ctrl && input === "c") {
|
|
69063
|
-
|
|
69093
|
+
onCancel();
|
|
69064
69094
|
return;
|
|
69065
69095
|
}
|
|
69066
69096
|
if (key.upArrow) {
|
|
@@ -72182,10 +72212,86 @@ var init_useSyncedState = __esm(() => {
|
|
|
72182
72212
|
import_react81 = __toESM(require_react(), 1);
|
|
72183
72213
|
});
|
|
72184
72214
|
|
|
72215
|
+
// src/providers/zai-provider.ts
|
|
72216
|
+
async function getLettaConfig2() {
|
|
72217
|
+
const settings = await settingsManager.getSettingsWithSecureTokens();
|
|
72218
|
+
const baseUrl = process.env.LETTA_BASE_URL || settings.env?.LETTA_BASE_URL || LETTA_CLOUD_API_URL;
|
|
72219
|
+
const apiKey = process.env.LETTA_API_KEY || settings.env?.LETTA_API_KEY || "";
|
|
72220
|
+
return { baseUrl, apiKey };
|
|
72221
|
+
}
|
|
72222
|
+
async function providersRequest2(method, path20, body) {
|
|
72223
|
+
const { baseUrl, apiKey } = await getLettaConfig2();
|
|
72224
|
+
const url = `${baseUrl}${path20}`;
|
|
72225
|
+
const response = await fetch(url, {
|
|
72226
|
+
method,
|
|
72227
|
+
headers: {
|
|
72228
|
+
"Content-Type": "application/json",
|
|
72229
|
+
Authorization: `Bearer ${apiKey}`,
|
|
72230
|
+
"X-Letta-Source": "letta-code"
|
|
72231
|
+
},
|
|
72232
|
+
...body && { body: JSON.stringify(body) }
|
|
72233
|
+
});
|
|
72234
|
+
if (!response.ok) {
|
|
72235
|
+
const errorText = await response.text();
|
|
72236
|
+
throw new Error(`Provider API error (${response.status}): ${errorText}`);
|
|
72237
|
+
}
|
|
72238
|
+
const text = await response.text();
|
|
72239
|
+
if (!text) {
|
|
72240
|
+
return {};
|
|
72241
|
+
}
|
|
72242
|
+
return JSON.parse(text);
|
|
72243
|
+
}
|
|
72244
|
+
async function listProviders2() {
|
|
72245
|
+
try {
|
|
72246
|
+
const response = await providersRequest2("GET", "/v1/providers");
|
|
72247
|
+
return response;
|
|
72248
|
+
} catch {
|
|
72249
|
+
return [];
|
|
72250
|
+
}
|
|
72251
|
+
}
|
|
72252
|
+
async function getZaiProvider() {
|
|
72253
|
+
const providers = await listProviders2();
|
|
72254
|
+
return providers.find((p) => p.name === ZAI_PROVIDER_NAME) || null;
|
|
72255
|
+
}
|
|
72256
|
+
async function createZaiProvider(apiKey) {
|
|
72257
|
+
return providersRequest2("POST", "/v1/providers", {
|
|
72258
|
+
name: ZAI_PROVIDER_NAME,
|
|
72259
|
+
provider_type: "zai",
|
|
72260
|
+
api_key: apiKey
|
|
72261
|
+
});
|
|
72262
|
+
}
|
|
72263
|
+
async function updateZaiProvider(providerId, apiKey) {
|
|
72264
|
+
return providersRequest2("PATCH", `/v1/providers/${providerId}`, {
|
|
72265
|
+
api_key: apiKey
|
|
72266
|
+
});
|
|
72267
|
+
}
|
|
72268
|
+
async function createOrUpdateZaiProvider(apiKey) {
|
|
72269
|
+
const existing = await getZaiProvider();
|
|
72270
|
+
if (existing) {
|
|
72271
|
+
return updateZaiProvider(existing.id, apiKey);
|
|
72272
|
+
}
|
|
72273
|
+
return createZaiProvider(apiKey);
|
|
72274
|
+
}
|
|
72275
|
+
async function deleteZaiProvider(providerId) {
|
|
72276
|
+
await providersRequest2("DELETE", `/v1/providers/${providerId}`);
|
|
72277
|
+
}
|
|
72278
|
+
async function removeZaiProvider() {
|
|
72279
|
+
const existing = await getZaiProvider();
|
|
72280
|
+
if (existing) {
|
|
72281
|
+
await deleteZaiProvider(existing.id);
|
|
72282
|
+
}
|
|
72283
|
+
}
|
|
72284
|
+
var ZAI_PROVIDER_NAME = "zai-coding-plan";
|
|
72285
|
+
var init_zai_provider = __esm(async () => {
|
|
72286
|
+
init_oauth();
|
|
72287
|
+
await init_settings_manager();
|
|
72288
|
+
});
|
|
72289
|
+
|
|
72185
72290
|
// src/cli/commands/connect.ts
|
|
72186
72291
|
var exports_connect = {};
|
|
72187
72292
|
__export(exports_connect, {
|
|
72188
72293
|
handleDisconnect: () => handleDisconnect,
|
|
72294
|
+
handleConnectZai: () => handleConnectZai,
|
|
72189
72295
|
handleConnect: () => handleConnect
|
|
72190
72296
|
});
|
|
72191
72297
|
function uid3(prefix) {
|
|
@@ -72223,16 +72329,22 @@ async function handleConnect(ctx, msg) {
|
|
|
72223
72329
|
const provider = parts[1]?.toLowerCase();
|
|
72224
72330
|
const authCode = parts.slice(2).join("");
|
|
72225
72331
|
if (!provider) {
|
|
72226
|
-
addCommandResult3(ctx.buffersRef, ctx.refreshDerived, msg, `Usage: /connect
|
|
72332
|
+
addCommandResult3(ctx.buffersRef, ctx.refreshDerived, msg, `Usage: /connect <provider> [options]
|
|
72227
72333
|
|
|
72228
|
-
|
|
72334
|
+
Available providers:
|
|
72335
|
+
• claude - Connect via OAuth to authenticate without an API key
|
|
72336
|
+
• zai <api_key> - Connect to Zai with your API key`, false);
|
|
72229
72337
|
return;
|
|
72230
72338
|
}
|
|
72231
|
-
if (provider !== "claude") {
|
|
72339
|
+
if (provider !== "claude" && provider !== "zai") {
|
|
72232
72340
|
addCommandResult3(ctx.buffersRef, ctx.refreshDerived, msg, `Error: Unknown provider "${provider}"
|
|
72233
72341
|
|
|
72234
|
-
|
|
72235
|
-
Usage: /connect
|
|
72342
|
+
Available providers: claude, zai
|
|
72343
|
+
Usage: /connect <provider> [options]`, false);
|
|
72344
|
+
return;
|
|
72345
|
+
}
|
|
72346
|
+
if (provider === "zai") {
|
|
72347
|
+
await handleConnectZai(ctx, msg);
|
|
72236
72348
|
return;
|
|
72237
72349
|
}
|
|
72238
72350
|
if (authCode && authCode.length > 0) {
|
|
@@ -72352,13 +72464,26 @@ If you have an Anthropic API key, you can use it directly by setting:
|
|
|
72352
72464
|
async function handleDisconnect(ctx, msg) {
|
|
72353
72465
|
const parts = msg.trim().split(/\s+/);
|
|
72354
72466
|
const provider = parts[1]?.toLowerCase();
|
|
72355
|
-
if (provider
|
|
72356
|
-
addCommandResult3(ctx.buffersRef, ctx.refreshDerived, msg, `
|
|
72467
|
+
if (!provider) {
|
|
72468
|
+
addCommandResult3(ctx.buffersRef, ctx.refreshDerived, msg, `Usage: /disconnect <provider>
|
|
72357
72469
|
|
|
72358
|
-
|
|
72359
|
-
|
|
72470
|
+
Available providers: claude, zai`, false);
|
|
72471
|
+
return;
|
|
72472
|
+
}
|
|
72473
|
+
if (provider === "zai") {
|
|
72474
|
+
await handleDisconnectZai(ctx, msg);
|
|
72360
72475
|
return;
|
|
72361
72476
|
}
|
|
72477
|
+
if (provider === "claude") {
|
|
72478
|
+
await handleDisconnectClaude(ctx, msg);
|
|
72479
|
+
return;
|
|
72480
|
+
}
|
|
72481
|
+
addCommandResult3(ctx.buffersRef, ctx.refreshDerived, msg, `Error: Unknown provider "${provider}"
|
|
72482
|
+
|
|
72483
|
+
Available providers: claude, zai
|
|
72484
|
+
Usage: /disconnect <provider>`, false);
|
|
72485
|
+
}
|
|
72486
|
+
async function handleDisconnectClaude(ctx, msg) {
|
|
72362
72487
|
if (!settingsManager.hasAnthropicOAuth()) {
|
|
72363
72488
|
addCommandResult3(ctx.buffersRef, ctx.refreshDerived, msg, `Not currently connected to Claude via OAuth.
|
|
72364
72489
|
|
|
@@ -72383,10 +72508,58 @@ Your local OAuth tokens have been removed.`, true, "finished");
|
|
|
72383
72508
|
ctx.setCommandRunning(false);
|
|
72384
72509
|
}
|
|
72385
72510
|
}
|
|
72511
|
+
async function handleDisconnectZai(ctx, msg) {
|
|
72512
|
+
const existing = await getZaiProvider();
|
|
72513
|
+
if (!existing) {
|
|
72514
|
+
addCommandResult3(ctx.buffersRef, ctx.refreshDerived, msg, `Not currently connected to Zai.
|
|
72515
|
+
|
|
72516
|
+
Use /connect zai <api_key> to connect.`, false);
|
|
72517
|
+
return;
|
|
72518
|
+
}
|
|
72519
|
+
const cmdId = addCommandResult3(ctx.buffersRef, ctx.refreshDerived, msg, "Disconnecting from Zai...", true, "running");
|
|
72520
|
+
ctx.setCommandRunning(true);
|
|
72521
|
+
try {
|
|
72522
|
+
await removeZaiProvider();
|
|
72523
|
+
updateCommandResult3(ctx.buffersRef, ctx.refreshDerived, cmdId, msg, `✓ Disconnected from Zai.
|
|
72524
|
+
|
|
72525
|
+
` + `Provider '${ZAI_PROVIDER_NAME}' removed from Letta.`, true, "finished");
|
|
72526
|
+
} catch (error) {
|
|
72527
|
+
updateCommandResult3(ctx.buffersRef, ctx.refreshDerived, cmdId, msg, `✗ Failed to disconnect from Zai: ${getErrorMessage(error)}`, false, "finished");
|
|
72528
|
+
} finally {
|
|
72529
|
+
ctx.setCommandRunning(false);
|
|
72530
|
+
}
|
|
72531
|
+
}
|
|
72532
|
+
async function handleConnectZai(ctx, msg) {
|
|
72533
|
+
const parts = msg.trim().split(/\s+/);
|
|
72534
|
+
const apiKey = parts.slice(2).join("");
|
|
72535
|
+
if (!apiKey || apiKey.length === 0) {
|
|
72536
|
+
addCommandResult3(ctx.buffersRef, ctx.refreshDerived, msg, `Usage: /connect zai <api_key>
|
|
72537
|
+
|
|
72538
|
+
Connect to Zai by providing your API key.
|
|
72539
|
+
|
|
72540
|
+
Example: /connect zai <api_key>...`, false);
|
|
72541
|
+
return;
|
|
72542
|
+
}
|
|
72543
|
+
const cmdId = addCommandResult3(ctx.buffersRef, ctx.refreshDerived, msg, "Creating Zai coding plan provider...", true, "running");
|
|
72544
|
+
ctx.setCommandRunning(true);
|
|
72545
|
+
try {
|
|
72546
|
+
await createOrUpdateZaiProvider(apiKey);
|
|
72547
|
+
updateCommandResult3(ctx.buffersRef, ctx.refreshDerived, cmdId, msg, `✓ Successfully connected to Zai!
|
|
72548
|
+
|
|
72549
|
+
` + `Provider '${ZAI_PROVIDER_NAME}' created in Letta.
|
|
72550
|
+
|
|
72551
|
+
` + `The models are populated in /model → "All Available Models"`, true, "finished");
|
|
72552
|
+
} catch (error) {
|
|
72553
|
+
updateCommandResult3(ctx.buffersRef, ctx.refreshDerived, cmdId, msg, `✗ Failed to create Zai provider: ${getErrorMessage(error)}`, false, "finished");
|
|
72554
|
+
} finally {
|
|
72555
|
+
ctx.setCommandRunning(false);
|
|
72556
|
+
}
|
|
72557
|
+
}
|
|
72386
72558
|
var init_connect = __esm(async () => {
|
|
72387
72559
|
init_anthropic_oauth();
|
|
72388
72560
|
await __promiseAll([
|
|
72389
72561
|
init_anthropic_provider(),
|
|
72562
|
+
init_zai_provider(),
|
|
72390
72563
|
init_settings_manager()
|
|
72391
72564
|
]);
|
|
72392
72565
|
});
|
|
@@ -72578,7 +72751,19 @@ function sendDesktopNotification() {
|
|
|
72578
72751
|
async function isRetriableError(stopReason, lastRunId) {
|
|
72579
72752
|
if (stopReason === "llm_api_error")
|
|
72580
72753
|
return true;
|
|
72581
|
-
|
|
72754
|
+
const nonRetriableReasons = [
|
|
72755
|
+
"cancelled",
|
|
72756
|
+
"requires_approval",
|
|
72757
|
+
"max_steps",
|
|
72758
|
+
"max_tokens_exceeded",
|
|
72759
|
+
"context_window_overflow_in_system_prompt",
|
|
72760
|
+
"end_turn",
|
|
72761
|
+
"tool_rule",
|
|
72762
|
+
"no_tool_call"
|
|
72763
|
+
];
|
|
72764
|
+
if (nonRetriableReasons.includes(stopReason))
|
|
72765
|
+
return false;
|
|
72766
|
+
if (lastRunId) {
|
|
72582
72767
|
try {
|
|
72583
72768
|
const client = await getClient2();
|
|
72584
72769
|
const run = await client.runs.retrieve(lastRunId);
|
|
@@ -72595,7 +72780,7 @@ async function isRetriableError(stopReason, lastRunId) {
|
|
|
72595
72780
|
"api_error",
|
|
72596
72781
|
"Network error"
|
|
72597
72782
|
];
|
|
72598
|
-
if (
|
|
72783
|
+
if (llmProviderPatterns.some((pattern) => detail.includes(pattern))) {
|
|
72599
72784
|
return true;
|
|
72600
72785
|
}
|
|
72601
72786
|
return false;
|
|
@@ -74510,6 +74695,15 @@ ${newState.originalPrompt}`
|
|
|
74510
74695
|
const parts = msg.trim().split(/\s+/);
|
|
74511
74696
|
const provider = parts[1]?.toLowerCase();
|
|
74512
74697
|
const hasCode = parts.length > 2;
|
|
74698
|
+
if (provider === "zai") {
|
|
74699
|
+
const { handleConnectZai: handleConnectZai2 } = await init_connect().then(() => exports_connect);
|
|
74700
|
+
await handleConnectZai2({
|
|
74701
|
+
buffersRef,
|
|
74702
|
+
refreshDerived,
|
|
74703
|
+
setCommandRunning
|
|
74704
|
+
}, msg);
|
|
74705
|
+
return { submitted: true };
|
|
74706
|
+
}
|
|
74513
74707
|
if (provider === "claude" && !hasCode) {
|
|
74514
74708
|
setActiveOverlay("oauth");
|
|
74515
74709
|
return { submitted: true };
|
|
@@ -76551,14 +76745,47 @@ Consider switching to a different system prompt using /system to match.` : null;
|
|
|
76551
76745
|
import_react82.useEffect(() => {
|
|
76552
76746
|
const currentIndex = approvalResults.length;
|
|
76553
76747
|
const approval = pendingApprovals[currentIndex];
|
|
76554
|
-
if (approval?.toolName === "ExitPlanMode"
|
|
76555
|
-
|
|
76556
|
-
|
|
76557
|
-
|
|
76748
|
+
if (approval?.toolName === "ExitPlanMode") {
|
|
76749
|
+
if (permissionMode2.getMode() !== "plan") {
|
|
76750
|
+
const statusId = uid4("status");
|
|
76751
|
+
buffersRef.current.byId.set(statusId, {
|
|
76752
|
+
kind: "status",
|
|
76753
|
+
id: statusId,
|
|
76754
|
+
lines: ["⚠️ Plan mode session expired (use /plan to re-enter)"]
|
|
76755
|
+
});
|
|
76756
|
+
buffersRef.current.order.push(statusId);
|
|
76757
|
+
const denialResults = [
|
|
76758
|
+
{
|
|
76759
|
+
type: "approval",
|
|
76760
|
+
tool_call_id: approval.toolCallId,
|
|
76761
|
+
approve: false,
|
|
76762
|
+
reason: "Plan mode session expired (CLI restarted). Use EnterPlanMode to re-enter plan mode, or request the user to re-enter plan mode."
|
|
76763
|
+
}
|
|
76764
|
+
];
|
|
76765
|
+
setQueuedApprovalResults(denialResults);
|
|
76766
|
+
markIncompleteToolsAsCancelled(buffersRef.current);
|
|
76767
|
+
refreshDerived();
|
|
76768
|
+
setPendingApprovals([]);
|
|
76769
|
+
setApprovalContexts([]);
|
|
76770
|
+
setApprovalResults([]);
|
|
76771
|
+
setAutoHandledResults([]);
|
|
76772
|
+
setAutoDeniedApprovals([]);
|
|
76773
|
+
return;
|
|
76774
|
+
}
|
|
76775
|
+
if (!planFileExists()) {
|
|
76776
|
+
const planFilePath = permissionMode2.getPlanFilePath();
|
|
76777
|
+
const plansDir = join20(homedir11(), ".letta", "plans");
|
|
76778
|
+
handlePlanKeepPlanning(`You must write your plan to a plan file before exiting plan mode.
|
|
76558
76779
|
` + (planFilePath ? `Plan file path: ${planFilePath}
|
|
76559
76780
|
` : "") + `Use a write tool to create your plan in ${plansDir}, then use ExitPlanMode to present the plan to the user.`);
|
|
76781
|
+
}
|
|
76560
76782
|
}
|
|
76561
|
-
}, [
|
|
76783
|
+
}, [
|
|
76784
|
+
pendingApprovals,
|
|
76785
|
+
approvalResults.length,
|
|
76786
|
+
handlePlanKeepPlanning,
|
|
76787
|
+
refreshDerived
|
|
76788
|
+
]);
|
|
76562
76789
|
const handleQuestionSubmit = import_react82.useCallback(async (answers) => {
|
|
76563
76790
|
const currentIndex = approvalResults.length;
|
|
76564
76791
|
const approval = pendingApprovals[currentIndex];
|
|
@@ -76588,6 +76815,9 @@ Consider switching to a different system prompt using /system to match.` : null;
|
|
|
76588
76815
|
});
|
|
76589
76816
|
setThinkingMessage(getRandomThinkingVerb());
|
|
76590
76817
|
refreshDerived();
|
|
76818
|
+
if (approval.toolCallId) {
|
|
76819
|
+
eagerCommittedPreviewsRef.current.add(approval.toolCallId);
|
|
76820
|
+
}
|
|
76591
76821
|
const decision = {
|
|
76592
76822
|
type: "approve",
|
|
76593
76823
|
approval,
|
|
@@ -76761,11 +76991,13 @@ Plan file path: ${planFilePath}`;
|
|
|
76761
76991
|
});
|
|
76762
76992
|
buffersRef.current.order.push(statusId);
|
|
76763
76993
|
refreshDerived();
|
|
76994
|
+
commitEligibleLines(buffersRef.current);
|
|
76764
76995
|
}
|
|
76765
76996
|
}, [
|
|
76766
76997
|
loadingState,
|
|
76767
76998
|
continueSession,
|
|
76768
76999
|
messageHistory.length,
|
|
77000
|
+
commitEligibleLines,
|
|
76769
77001
|
columns,
|
|
76770
77002
|
agentProvenance,
|
|
76771
77003
|
agentState,
|
|
@@ -76921,6 +77153,7 @@ Plan file path: ${planFilePath}`;
|
|
|
76921
77153
|
onApprove: () => handlePlanApprove(false),
|
|
76922
77154
|
onApproveAndAcceptEdits: () => handlePlanApprove(true),
|
|
76923
77155
|
onKeepPlanning: handlePlanKeepPlanning,
|
|
77156
|
+
onCancel: handleCancelApprovals,
|
|
76924
77157
|
isFocused: true
|
|
76925
77158
|
}, undefined, false, undefined, this) : isFileEditApproval && fileEditInfo ? /* @__PURE__ */ jsx_dev_runtime59.jsxDEV(InlineFileEditApproval, {
|
|
76926
77159
|
fileEdit: fileEditInfo,
|
|
@@ -77000,6 +77233,20 @@ Plan file path: ${planFilePath}`;
|
|
|
77000
77233
|
}, ln.id, false, undefined, this);
|
|
77001
77234
|
})
|
|
77002
77235
|
}, undefined, false, undefined, this),
|
|
77236
|
+
liveItems.length === 0 && currentApproval && /* @__PURE__ */ jsx_dev_runtime59.jsxDEV(Box_default, {
|
|
77237
|
+
flexDirection: "column",
|
|
77238
|
+
children: /* @__PURE__ */ jsx_dev_runtime59.jsxDEV(InlineGenericApproval, {
|
|
77239
|
+
toolName: currentApproval.toolName,
|
|
77240
|
+
toolArgs: currentApproval.toolArgs,
|
|
77241
|
+
onApprove: () => handleApproveCurrent(),
|
|
77242
|
+
onApproveAlways: (scope) => handleApproveAlways(scope),
|
|
77243
|
+
onDeny: (reason) => handleDenyCurrent(reason),
|
|
77244
|
+
onCancel: handleCancelApprovals,
|
|
77245
|
+
isFocused: true,
|
|
77246
|
+
approveAlwaysText: currentApprovalContext?.approveAlwaysText,
|
|
77247
|
+
allowPersistence: currentApprovalContext?.allowPersistence ?? true
|
|
77248
|
+
}, undefined, false, undefined, this)
|
|
77249
|
+
}, undefined, false, undefined, this),
|
|
77003
77250
|
/* @__PURE__ */ jsx_dev_runtime59.jsxDEV(SubagentGroupDisplay, {}, undefined, false, undefined, this)
|
|
77004
77251
|
]
|
|
77005
77252
|
}, undefined, true, undefined, this),
|
|
@@ -78158,6 +78405,10 @@ import { parseArgs as parseArgs2 } from "util";
|
|
|
78158
78405
|
|
|
78159
78406
|
// src/agent/check-approval.ts
|
|
78160
78407
|
var MESSAGE_HISTORY_LIMIT = 15;
|
|
78408
|
+
function isBackfillEnabled() {
|
|
78409
|
+
const val = process.env.LETTA_BACKFILL;
|
|
78410
|
+
return val !== "0" && val !== "false";
|
|
78411
|
+
}
|
|
78161
78412
|
async function getResumeData(client, agent) {
|
|
78162
78413
|
try {
|
|
78163
78414
|
const messagesPage = await client.agents.messages.list(agent.id);
|
|
@@ -78180,6 +78431,13 @@ async function getResumeData(client, agent) {
|
|
|
78180
78431
|
const inContextLastMessageId = agent.message_ids && agent.message_ids.length > 0 ? agent.message_ids[agent.message_ids.length - 1] : null;
|
|
78181
78432
|
if (!inContextLastMessageId) {
|
|
78182
78433
|
debugWarn("check-approval", `No in-context messages (message_ids empty/null) - no pending approvals`);
|
|
78434
|
+
if (!isBackfillEnabled()) {
|
|
78435
|
+
return {
|
|
78436
|
+
pendingApproval: null,
|
|
78437
|
+
pendingApprovals: [],
|
|
78438
|
+
messageHistory: []
|
|
78439
|
+
};
|
|
78440
|
+
}
|
|
78183
78441
|
const historyCount2 = Math.min(MESSAGE_HISTORY_LIMIT, messages.length);
|
|
78184
78442
|
let messageHistory2 = messages.slice(-historyCount2);
|
|
78185
78443
|
if (messageHistory2[0]?.message_type === "tool_return_message") {
|
|
@@ -78230,6 +78488,9 @@ async function getResumeData(client, agent) {
|
|
|
78230
78488
|
}
|
|
78231
78489
|
}
|
|
78232
78490
|
}
|
|
78491
|
+
if (!isBackfillEnabled()) {
|
|
78492
|
+
return { pendingApproval, pendingApprovals, messageHistory: [] };
|
|
78493
|
+
}
|
|
78233
78494
|
const historyCount = Math.min(MESSAGE_HISTORY_LIMIT, messages.length);
|
|
78234
78495
|
let messageHistory = messages.slice(-historyCount);
|
|
78235
78496
|
if (messageHistory[0]?.message_type === "tool_return_message") {
|
|
@@ -80638,4 +80899,4 @@ Error during initialization: ${message}`);
|
|
|
80638
80899
|
}
|
|
80639
80900
|
main();
|
|
80640
80901
|
|
|
80641
|
-
//# debugId=
|
|
80902
|
+
//# debugId=C1C8E8CD6D145E1A64756E2164756E21
|