@letta-ai/letta-code 0.11.2-next.4 → 0.12.1
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 +305 -38
- 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.
|
|
3240
|
+
version: "0.12.1",
|
|
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: {
|
|
@@ -29951,6 +29951,10 @@ var init_WelcomeScreen = __esm(async () => {
|
|
|
29951
29951
|
});
|
|
29952
29952
|
|
|
29953
29953
|
// src/permissions/readOnlyShell.ts
|
|
29954
|
+
function isReadOnlySkillScript(scriptPath) {
|
|
29955
|
+
const normalized = scriptPath.replace(/\\/g, "/");
|
|
29956
|
+
return BUNDLED_READ_ONLY_SCRIPTS.some((pattern) => normalized.endsWith(pattern));
|
|
29957
|
+
}
|
|
29954
29958
|
function isReadOnlyShellCommand(command) {
|
|
29955
29959
|
if (!command) {
|
|
29956
29960
|
return false;
|
|
@@ -30018,6 +30022,13 @@ function isSafeSegment(segment) {
|
|
|
30018
30022
|
if (command === "sort") {
|
|
30019
30023
|
return !/\s-o\b/.test(segment);
|
|
30020
30024
|
}
|
|
30025
|
+
if (command === "npx" && tokens[1] === "tsx") {
|
|
30026
|
+
const scriptPath = tokens[2];
|
|
30027
|
+
if (scriptPath && isReadOnlySkillScript(scriptPath)) {
|
|
30028
|
+
return true;
|
|
30029
|
+
}
|
|
30030
|
+
return false;
|
|
30031
|
+
}
|
|
30021
30032
|
return false;
|
|
30022
30033
|
}
|
|
30023
30034
|
return true;
|
|
@@ -30050,7 +30061,7 @@ function extractDashCArgument(tokens) {
|
|
|
30050
30061
|
}
|
|
30051
30062
|
return;
|
|
30052
30063
|
}
|
|
30053
|
-
var ALWAYS_SAFE_COMMANDS, SAFE_GIT_SUBCOMMANDS, DANGEROUS_OPERATOR_PATTERN;
|
|
30064
|
+
var ALWAYS_SAFE_COMMANDS, SAFE_GIT_SUBCOMMANDS, BUNDLED_READ_ONLY_SCRIPTS, DANGEROUS_OPERATOR_PATTERN;
|
|
30054
30065
|
var init_readOnlyShell = __esm(() => {
|
|
30055
30066
|
ALWAYS_SAFE_COMMANDS = new Set([
|
|
30056
30067
|
"cat",
|
|
@@ -30113,6 +30124,12 @@ var init_readOnlyShell = __esm(() => {
|
|
|
30113
30124
|
"tag",
|
|
30114
30125
|
"remote"
|
|
30115
30126
|
]);
|
|
30127
|
+
BUNDLED_READ_ONLY_SCRIPTS = [
|
|
30128
|
+
"/skills/searching-messages/scripts/search-messages.ts",
|
|
30129
|
+
"/skills/searching-messages/scripts/get-messages.ts",
|
|
30130
|
+
"/skills/builtin/searching-messages/scripts/search-messages.ts",
|
|
30131
|
+
"/skills/builtin/searching-messages/scripts/get-messages.ts"
|
|
30132
|
+
];
|
|
30116
30133
|
DANGEROUS_OPERATOR_PATTERN = /(>>|>|\$\(|`)/;
|
|
30117
30134
|
});
|
|
30118
30135
|
|
|
@@ -31629,6 +31646,46 @@ Remember: You're planning, not implementing. Don't make changes, just create a r
|
|
|
31629
31646
|
`;
|
|
31630
31647
|
var init_plan = () => {};
|
|
31631
31648
|
|
|
31649
|
+
// src/agent/subagents/builtin/recall.md
|
|
31650
|
+
var recall_default = `---
|
|
31651
|
+
name: recall
|
|
31652
|
+
description: Search conversation history to recall past discussions, decisions, and context
|
|
31653
|
+
tools: Skill, Bash, Read, BashOutput
|
|
31654
|
+
model: haiku
|
|
31655
|
+
memoryBlocks: human, persona
|
|
31656
|
+
mode: stateless
|
|
31657
|
+
---
|
|
31658
|
+
|
|
31659
|
+
You are a subagent launched via the Task tool to search conversation history. You run autonomously and return a single final report when done. You CANNOT ask questions mid-execution.
|
|
31660
|
+
|
|
31661
|
+
## Instructions
|
|
31662
|
+
|
|
31663
|
+
### Step 1: Load the searching-messages skill
|
|
31664
|
+
\`\`\`
|
|
31665
|
+
Skill({ command: "load", skills: ["searching-messages"] })
|
|
31666
|
+
\`\`\`
|
|
31667
|
+
|
|
31668
|
+
The skill content will appear in your loaded_skills block with script paths and search strategies.
|
|
31669
|
+
|
|
31670
|
+
### Step 2: Search the parent agent's history
|
|
31671
|
+
|
|
31672
|
+
**CRITICAL - Two rules:**
|
|
31673
|
+
|
|
31674
|
+
1. **DO NOT use \`conversation_search\`** - That tool only searches YOUR history (empty). You MUST use the Bash scripts from the skill.
|
|
31675
|
+
|
|
31676
|
+
2. **ALWAYS add \`--agent-id $LETTA_PARENT_AGENT_ID\`** - This searches the parent agent's history. The only exception is \`--all-agents\` searches.
|
|
31677
|
+
|
|
31678
|
+
Follow the strategies documented in the loaded skill.
|
|
31679
|
+
|
|
31680
|
+
## Output Format
|
|
31681
|
+
|
|
31682
|
+
1. **Direct answer** - What the user asked about
|
|
31683
|
+
2. **Key findings** - Relevant quotes or summaries from past conversations
|
|
31684
|
+
3. **When discussed** - Timestamps of relevant discussions
|
|
31685
|
+
4. **Outcome/Decision** - What was decided or concluded (if applicable)
|
|
31686
|
+
`;
|
|
31687
|
+
var init_recall = () => {};
|
|
31688
|
+
|
|
31632
31689
|
// src/agent/subagents/index.ts
|
|
31633
31690
|
var exports_subagents = {};
|
|
31634
31691
|
__export(exports_subagents, {
|
|
@@ -31793,7 +31850,13 @@ var init_subagents = __esm(() => {
|
|
|
31793
31850
|
init_explore();
|
|
31794
31851
|
init_general_purpose();
|
|
31795
31852
|
init_plan();
|
|
31796
|
-
|
|
31853
|
+
init_recall();
|
|
31854
|
+
BUILTIN_SOURCES = [
|
|
31855
|
+
explore_default,
|
|
31856
|
+
general_purpose_default,
|
|
31857
|
+
plan_default,
|
|
31858
|
+
recall_default
|
|
31859
|
+
];
|
|
31797
31860
|
GLOBAL_AGENTS_DIR = join3(process.env.HOME || process.env.USERPROFILE || "~", ".letta/agents");
|
|
31798
31861
|
VALID_MEMORY_BLOCKS = new Set(MEMORY_BLOCK_LABELS);
|
|
31799
31862
|
cache3 = {
|
|
@@ -43281,11 +43344,16 @@ async function executeSubagent(type, config, model, userPrompt, baseURL, subagen
|
|
|
43281
43344
|
try {
|
|
43282
43345
|
const cliArgs = buildSubagentArgs(type, config, model, userPrompt);
|
|
43283
43346
|
const lettaCmd = process.env.LETTA_CODE_BIN || "letta";
|
|
43347
|
+
let parentAgentId;
|
|
43348
|
+
try {
|
|
43349
|
+
parentAgentId = getCurrentAgentId();
|
|
43350
|
+
} catch {}
|
|
43284
43351
|
const proc2 = spawn3(lettaCmd, cliArgs, {
|
|
43285
43352
|
cwd: process.cwd(),
|
|
43286
43353
|
env: {
|
|
43287
43354
|
...process.env,
|
|
43288
|
-
LETTA_CODE_AGENT_ROLE: "subagent"
|
|
43355
|
+
LETTA_CODE_AGENT_ROLE: "subagent",
|
|
43356
|
+
...parentAgentId && { LETTA_PARENT_AGENT_ID: parentAgentId }
|
|
43289
43357
|
}
|
|
43290
43358
|
});
|
|
43291
43359
|
let wasAborted = false;
|
|
@@ -45644,7 +45712,13 @@ var init_subagents2 = __esm(() => {
|
|
|
45644
45712
|
init_explore();
|
|
45645
45713
|
init_general_purpose();
|
|
45646
45714
|
init_plan();
|
|
45647
|
-
|
|
45715
|
+
init_recall();
|
|
45716
|
+
BUILTIN_SOURCES2 = [
|
|
45717
|
+
explore_default,
|
|
45718
|
+
general_purpose_default,
|
|
45719
|
+
plan_default,
|
|
45720
|
+
recall_default
|
|
45721
|
+
];
|
|
45648
45722
|
GLOBAL_AGENTS_DIR2 = join10(process.env.HOME || process.env.USERPROFILE || "~", ".letta/agents");
|
|
45649
45723
|
VALID_MEMORY_BLOCKS2 = new Set(MEMORY_BLOCK_LABELS);
|
|
45650
45724
|
cache4 = {
|
|
@@ -48326,7 +48400,9 @@ var init_checker = __esm(() => {
|
|
|
48326
48400
|
"explore",
|
|
48327
48401
|
"Explore",
|
|
48328
48402
|
"plan",
|
|
48329
|
-
"Plan"
|
|
48403
|
+
"Plan",
|
|
48404
|
+
"recall",
|
|
48405
|
+
"Recall"
|
|
48330
48406
|
]);
|
|
48331
48407
|
});
|
|
48332
48408
|
|
|
@@ -49510,7 +49586,7 @@ var init_create = __esm(async () => {
|
|
|
49510
49586
|
});
|
|
49511
49587
|
|
|
49512
49588
|
// src/agent/message.ts
|
|
49513
|
-
async function sendMessageStream(agentId, messages, opts = { streamTokens: true, background: true }) {
|
|
49589
|
+
async function sendMessageStream(agentId, messages, opts = { streamTokens: true, background: true }, requestOptions = { maxRetries: 0 }) {
|
|
49514
49590
|
const client = await getClient2();
|
|
49515
49591
|
return client.agents.messages.create(agentId, {
|
|
49516
49592
|
messages,
|
|
@@ -49518,7 +49594,7 @@ async function sendMessageStream(agentId, messages, opts = { streamTokens: true,
|
|
|
49518
49594
|
stream_tokens: opts.streamTokens ?? true,
|
|
49519
49595
|
background: opts.background ?? true,
|
|
49520
49596
|
client_tools: getClientToolsFromRegistry()
|
|
49521
|
-
});
|
|
49597
|
+
}, requestOptions);
|
|
49522
49598
|
}
|
|
49523
49599
|
var init_message = __esm(async () => {
|
|
49524
49600
|
await __promiseAll([
|
|
@@ -49636,8 +49712,10 @@ function markCurrentLineAsFinished(b) {
|
|
|
49636
49712
|
markAsFinished(b, b.lastOtid);
|
|
49637
49713
|
} else {}
|
|
49638
49714
|
}
|
|
49639
|
-
function markIncompleteToolsAsCancelled(b) {
|
|
49640
|
-
|
|
49715
|
+
function markIncompleteToolsAsCancelled(b, setInterruptedFlag = true) {
|
|
49716
|
+
if (setInterruptedFlag) {
|
|
49717
|
+
b.interrupted = true;
|
|
49718
|
+
}
|
|
49641
49719
|
let anyToolsCancelled = false;
|
|
49642
49720
|
for (const [id, line] of b.byId.entries()) {
|
|
49643
49721
|
if (line.kind === "tool_call" && line.phase !== "finished") {
|
|
@@ -50032,6 +50110,10 @@ async function drainStream(stream2, buffers, refresh, abortSignal, onFirstMessag
|
|
|
50032
50110
|
queueMicrotask(refresh);
|
|
50033
50111
|
break;
|
|
50034
50112
|
}
|
|
50113
|
+
const errObj = chunk.error;
|
|
50114
|
+
if (errObj?.detail?.includes("No tool call is currently awaiting approval")) {
|
|
50115
|
+
continue;
|
|
50116
|
+
}
|
|
50035
50117
|
onChunk(buffers, chunk);
|
|
50036
50118
|
queueMicrotask(refresh);
|
|
50037
50119
|
if (chunk.message_type === "stop_reason") {
|
|
@@ -50113,7 +50195,7 @@ async function drainStreamWithResume(stream2, buffers, refresh, abortSignal, onF
|
|
|
50113
50195
|
const resumeStream = await client.runs.messages.stream(result.lastRunId, {
|
|
50114
50196
|
starting_after: result.lastSeqId,
|
|
50115
50197
|
batch_size: 1000
|
|
50116
|
-
});
|
|
50198
|
+
}, { maxRetries: 0 });
|
|
50117
50199
|
const resumeResult = await drainStream(resumeStream, buffers, refresh, abortSignal);
|
|
50118
50200
|
result = resumeResult;
|
|
50119
50201
|
} catch (_e) {
|
|
@@ -70528,6 +70610,7 @@ function App2({
|
|
|
70528
70610
|
}, [agentId]);
|
|
70529
70611
|
const [streaming, setStreaming, streamingRef] = useSyncedState(false);
|
|
70530
70612
|
const processingConversationRef = import_react76.useRef(0);
|
|
70613
|
+
const conversationGenerationRef = import_react76.useRef(0);
|
|
70531
70614
|
const [interruptRequested, setInterruptRequested] = import_react76.useState(false);
|
|
70532
70615
|
const [commandRunning, setCommandRunning, commandRunningRef] = useSyncedState(false);
|
|
70533
70616
|
const [profileConfirmPending, setProfileConfirmPending] = import_react76.useState(null);
|
|
@@ -70917,6 +71000,10 @@ function App2({
|
|
|
70917
71000
|
const processConversation = import_react76.useCallback(async (initialInput, options) => {
|
|
70918
71001
|
const currentInput = [...initialInput];
|
|
70919
71002
|
const allowReentry = options?.allowReentry ?? false;
|
|
71003
|
+
const myGeneration = options?.submissionGeneration ?? conversationGenerationRef.current;
|
|
71004
|
+
if (myGeneration !== conversationGenerationRef.current) {
|
|
71005
|
+
return;
|
|
71006
|
+
}
|
|
70920
71007
|
if (processingConversationRef.current > 0 && !allowReentry) {
|
|
70921
71008
|
return;
|
|
70922
71009
|
}
|
|
@@ -70930,20 +71017,29 @@ function App2({
|
|
|
70930
71017
|
userCancelledRef.current = false;
|
|
70931
71018
|
return;
|
|
70932
71019
|
}
|
|
71020
|
+
if (myGeneration !== conversationGenerationRef.current) {
|
|
71021
|
+
return;
|
|
71022
|
+
}
|
|
70933
71023
|
setStreaming(true);
|
|
70934
71024
|
abortControllerRef.current = new AbortController;
|
|
70935
|
-
markIncompleteToolsAsCancelled(buffersRef.current);
|
|
71025
|
+
markIncompleteToolsAsCancelled(buffersRef.current, false);
|
|
70936
71026
|
buffersRef.current.interrupted = false;
|
|
70937
71027
|
clearCompletedSubagents();
|
|
70938
71028
|
while (true) {
|
|
70939
71029
|
const signal = abortControllerRef.current?.signal;
|
|
70940
71030
|
if (signal?.aborted) {
|
|
70941
|
-
|
|
71031
|
+
const isStaleAtAbort = myGeneration !== conversationGenerationRef.current;
|
|
71032
|
+
if (!isStaleAtAbort) {
|
|
71033
|
+
setStreaming(false);
|
|
71034
|
+
}
|
|
70942
71035
|
return;
|
|
70943
71036
|
}
|
|
70944
71037
|
const stream2 = await sendMessageStream(agentIdRef.current, currentInput);
|
|
70945
71038
|
if (signal?.aborted) {
|
|
70946
|
-
|
|
71039
|
+
const isStaleAtAbort = myGeneration !== conversationGenerationRef.current;
|
|
71040
|
+
if (!isStaleAtAbort) {
|
|
71041
|
+
setStreaming(false);
|
|
71042
|
+
}
|
|
70947
71043
|
return;
|
|
70948
71044
|
}
|
|
70949
71045
|
const syncAgentState = async () => {
|
|
@@ -70987,6 +71083,10 @@ function App2({
|
|
|
70987
71083
|
const wasInterrupted = !!buffersRef.current.interrupted;
|
|
70988
71084
|
const wasAborted = !!signal?.aborted;
|
|
70989
71085
|
let stopReasonToHandle = wasAborted ? "cancelled" : stopReason;
|
|
71086
|
+
const isStaleAfterDrain = myGeneration !== conversationGenerationRef.current;
|
|
71087
|
+
if (isStaleAfterDrain) {
|
|
71088
|
+
return;
|
|
71089
|
+
}
|
|
70990
71090
|
if (!wasInterrupted) {
|
|
70991
71091
|
refreshDerived();
|
|
70992
71092
|
}
|
|
@@ -71306,7 +71406,8 @@ function App2({
|
|
|
71306
71406
|
sendDesktopNotification();
|
|
71307
71407
|
return;
|
|
71308
71408
|
}
|
|
71309
|
-
const
|
|
71409
|
+
const hasApprovalInPayload = currentInput.some((item) => item?.type === "approval");
|
|
71410
|
+
const isApprovalOnlyPayload = hasApprovalInPayload && currentInput.length === 1;
|
|
71310
71411
|
let latestErrorText = null;
|
|
71311
71412
|
for (let i = buffersRef.current.order.length - 1;i >= 0; i -= 1) {
|
|
71312
71413
|
const id = buffersRef.current.order[i];
|
|
@@ -71321,7 +71422,7 @@ function App2({
|
|
|
71321
71422
|
const detailFromRun = await fetchRunErrorDetail(lastRunId);
|
|
71322
71423
|
const desyncDetected = isApprovalStateDesyncError(detailFromRun) || isApprovalStateDesyncError(latestErrorText);
|
|
71323
71424
|
const lastFailureMessage = latestErrorText || detailFromRun || null;
|
|
71324
|
-
if (
|
|
71425
|
+
if (hasApprovalInPayload && desyncDetected) {
|
|
71325
71426
|
if (llmApiErrorRetriesRef.current < LLM_API_ERROR_MAX_RETRIES2) {
|
|
71326
71427
|
llmApiErrorRetriesRef.current += 1;
|
|
71327
71428
|
const statusId = uid4("status");
|
|
@@ -71334,10 +71435,20 @@ function App2({
|
|
|
71334
71435
|
});
|
|
71335
71436
|
buffersRef.current.order.push(statusId);
|
|
71336
71437
|
refreshDerived();
|
|
71337
|
-
|
|
71438
|
+
if (isApprovalOnlyPayload) {
|
|
71439
|
+
currentInput.splice(0, currentInput.length, buildApprovalRecoveryMessage());
|
|
71440
|
+
} else {
|
|
71441
|
+
const messageItems = currentInput.filter((item) => item?.type !== "approval");
|
|
71442
|
+
if (messageItems.length > 0) {
|
|
71443
|
+
currentInput.splice(0, currentInput.length, ...messageItems);
|
|
71444
|
+
} else {
|
|
71445
|
+
currentInput.splice(0, currentInput.length, buildApprovalRecoveryMessage());
|
|
71446
|
+
}
|
|
71447
|
+
}
|
|
71338
71448
|
buffersRef.current.byId.delete(statusId);
|
|
71339
71449
|
buffersRef.current.order = buffersRef.current.order.filter((id) => id !== statusId);
|
|
71340
71450
|
refreshDerived();
|
|
71451
|
+
buffersRef.current.interrupted = false;
|
|
71341
71452
|
continue;
|
|
71342
71453
|
}
|
|
71343
71454
|
const errorToShow = lastFailureMessage || `An error occurred during agent execution
|
|
@@ -71377,6 +71488,7 @@ function App2({
|
|
|
71377
71488
|
buffersRef.current.order = buffersRef.current.order.filter((id) => id !== statusId);
|
|
71378
71489
|
refreshDerived();
|
|
71379
71490
|
if (!cancelled) {
|
|
71491
|
+
buffersRef.current.interrupted = false;
|
|
71380
71492
|
continue;
|
|
71381
71493
|
}
|
|
71382
71494
|
}
|
|
@@ -71449,8 +71561,11 @@ function App2({
|
|
|
71449
71561
|
sendDesktopNotification();
|
|
71450
71562
|
refreshDerived();
|
|
71451
71563
|
} finally {
|
|
71564
|
+
const isStale = myGeneration !== conversationGenerationRef.current;
|
|
71452
71565
|
abortControllerRef.current = null;
|
|
71453
|
-
|
|
71566
|
+
if (!isStale) {
|
|
71567
|
+
processingConversationRef.current = Math.max(0, processingConversationRef.current - 1);
|
|
71568
|
+
}
|
|
71454
71569
|
}
|
|
71455
71570
|
}, [
|
|
71456
71571
|
appendError,
|
|
@@ -71493,8 +71608,9 @@ function App2({
|
|
|
71493
71608
|
}, 50);
|
|
71494
71609
|
return;
|
|
71495
71610
|
}
|
|
71496
|
-
if (!streaming || interruptRequested)
|
|
71611
|
+
if (!streaming || interruptRequested) {
|
|
71497
71612
|
return;
|
|
71613
|
+
}
|
|
71498
71614
|
if (waitingForQueueCancelRef.current) {
|
|
71499
71615
|
setRestoreQueueOnCancel(true);
|
|
71500
71616
|
}
|
|
@@ -71507,11 +71623,22 @@ function App2({
|
|
|
71507
71623
|
abortControllerRef.current = null;
|
|
71508
71624
|
}
|
|
71509
71625
|
userCancelledRef.current = true;
|
|
71626
|
+
conversationGenerationRef.current += 1;
|
|
71627
|
+
processingConversationRef.current = 0;
|
|
71510
71628
|
setStreaming(false);
|
|
71511
71629
|
if (!toolsCancelled) {
|
|
71512
71630
|
appendError(INTERRUPT_MESSAGE, true);
|
|
71513
71631
|
}
|
|
71514
71632
|
refreshDerived();
|
|
71633
|
+
if (pendingApprovals.length > 0) {
|
|
71634
|
+
const denialResults = pendingApprovals.map((approval) => ({
|
|
71635
|
+
type: "approval",
|
|
71636
|
+
tool_call_id: approval.toolCallId,
|
|
71637
|
+
approve: false,
|
|
71638
|
+
reason: "User interrupted the stream"
|
|
71639
|
+
}));
|
|
71640
|
+
setQueuedApprovalResults(denialResults);
|
|
71641
|
+
}
|
|
71515
71642
|
setPendingApprovals([]);
|
|
71516
71643
|
setApprovalContexts([]);
|
|
71517
71644
|
setApprovalResults([]);
|
|
@@ -71544,7 +71671,8 @@ function App2({
|
|
|
71544
71671
|
appendError,
|
|
71545
71672
|
isExecutingTool,
|
|
71546
71673
|
refreshDerived,
|
|
71547
|
-
setStreaming
|
|
71674
|
+
setStreaming,
|
|
71675
|
+
pendingApprovals
|
|
71548
71676
|
]);
|
|
71549
71677
|
const processConversationRef = import_react76.useRef(processConversation);
|
|
71550
71678
|
import_react76.useEffect(() => {
|
|
@@ -71759,6 +71887,96 @@ function App2({
|
|
|
71759
71887
|
}
|
|
71760
71888
|
refreshDerived();
|
|
71761
71889
|
}, [refreshDerived]);
|
|
71890
|
+
const checkPendingApprovalsForSlashCommand = import_react76.useCallback(async () => {
|
|
71891
|
+
if (!CHECK_PENDING_APPROVALS_BEFORE_SEND) {
|
|
71892
|
+
return { blocked: false };
|
|
71893
|
+
}
|
|
71894
|
+
try {
|
|
71895
|
+
const client = await getClient2();
|
|
71896
|
+
const agent = await client.agents.retrieve(agentId);
|
|
71897
|
+
const { pendingApprovals: existingApprovals } = await getResumeData2(client, agent);
|
|
71898
|
+
if (!existingApprovals || existingApprovals.length === 0) {
|
|
71899
|
+
return { blocked: false };
|
|
71900
|
+
}
|
|
71901
|
+
const approvalResults2 = await Promise.all(existingApprovals.map(async (approvalItem) => {
|
|
71902
|
+
if (!approvalItem.toolName) {
|
|
71903
|
+
return {
|
|
71904
|
+
approval: approvalItem,
|
|
71905
|
+
permission: {
|
|
71906
|
+
decision: "deny",
|
|
71907
|
+
reason: "Tool call incomplete - missing name"
|
|
71908
|
+
},
|
|
71909
|
+
context: null
|
|
71910
|
+
};
|
|
71911
|
+
}
|
|
71912
|
+
const parsedArgs = safeJsonParseOr(approvalItem.toolArgs, {});
|
|
71913
|
+
const permission = await checkToolPermission(approvalItem.toolName, parsedArgs);
|
|
71914
|
+
const context3 = await analyzeToolApproval(approvalItem.toolName, parsedArgs);
|
|
71915
|
+
return { approval: approvalItem, permission, context: context3 };
|
|
71916
|
+
}));
|
|
71917
|
+
const needsUserInput = [];
|
|
71918
|
+
const autoAllowed = [];
|
|
71919
|
+
const autoDenied = [];
|
|
71920
|
+
for (const ac of approvalResults2) {
|
|
71921
|
+
const { approval, permission } = ac;
|
|
71922
|
+
let decision = permission.decision;
|
|
71923
|
+
if (alwaysRequiresUserInput(approval.toolName) && decision === "allow") {
|
|
71924
|
+
decision = "ask";
|
|
71925
|
+
}
|
|
71926
|
+
if (decision === "ask") {
|
|
71927
|
+
needsUserInput.push(ac);
|
|
71928
|
+
} else if (decision === "deny") {
|
|
71929
|
+
autoDenied.push(ac);
|
|
71930
|
+
} else {
|
|
71931
|
+
autoAllowed.push(ac);
|
|
71932
|
+
}
|
|
71933
|
+
}
|
|
71934
|
+
if (needsUserInput.length > 0) {
|
|
71935
|
+
setPendingApprovals(needsUserInput.map((ac) => ac.approval));
|
|
71936
|
+
setApprovalContexts(needsUserInput.map((ac) => ac.context).filter((ctx) => ctx !== null));
|
|
71937
|
+
return { blocked: true };
|
|
71938
|
+
}
|
|
71939
|
+
const allResults = [];
|
|
71940
|
+
if (autoAllowed.length > 0) {
|
|
71941
|
+
const autoAllowedResults = await executeAutoAllowedTools(autoAllowed, (chunk) => onChunk(buffersRef.current, chunk));
|
|
71942
|
+
allResults.push(...autoAllowedResults.map((ar) => ({
|
|
71943
|
+
type: "tool",
|
|
71944
|
+
tool_call_id: ar.toolCallId,
|
|
71945
|
+
tool_return: ar.result.toolReturn,
|
|
71946
|
+
status: ar.result.status,
|
|
71947
|
+
stdout: ar.result.stdout,
|
|
71948
|
+
stderr: ar.result.stderr
|
|
71949
|
+
})));
|
|
71950
|
+
}
|
|
71951
|
+
for (const ac of autoDenied) {
|
|
71952
|
+
const reason = ac.permission.reason || "Permission denied";
|
|
71953
|
+
onChunk(buffersRef.current, {
|
|
71954
|
+
message_type: "tool_return_message",
|
|
71955
|
+
id: "dummy",
|
|
71956
|
+
date: new Date().toISOString(),
|
|
71957
|
+
tool_call_id: ac.approval.toolCallId,
|
|
71958
|
+
tool_return: `Error: request to call tool denied. User reason: ${reason}`,
|
|
71959
|
+
status: "error",
|
|
71960
|
+
stdout: null,
|
|
71961
|
+
stderr: null
|
|
71962
|
+
});
|
|
71963
|
+
allResults.push({
|
|
71964
|
+
type: "approval",
|
|
71965
|
+
tool_call_id: ac.approval.toolCallId,
|
|
71966
|
+
approve: false,
|
|
71967
|
+
reason
|
|
71968
|
+
});
|
|
71969
|
+
}
|
|
71970
|
+
if (allResults.length > 0) {
|
|
71971
|
+
await processConversation([
|
|
71972
|
+
{ type: "approval", approvals: allResults }
|
|
71973
|
+
]);
|
|
71974
|
+
}
|
|
71975
|
+
return { blocked: false };
|
|
71976
|
+
} catch {
|
|
71977
|
+
return { blocked: false };
|
|
71978
|
+
}
|
|
71979
|
+
}, [agentId, processConversation]);
|
|
71762
71980
|
const onSubmit = import_react76.useCallback(async (message) => {
|
|
71763
71981
|
const msg = message?.trim() ?? "";
|
|
71764
71982
|
if (profileConfirmPending && !msg) {
|
|
@@ -71787,6 +72005,7 @@ function App2({
|
|
|
71787
72005
|
}
|
|
71788
72006
|
if (!msg)
|
|
71789
72007
|
return { submitted: false };
|
|
72008
|
+
const submissionGeneration = conversationGenerationRef.current;
|
|
71790
72009
|
telemetry2.trackUserInput(msg, "user", currentModelId || "unknown");
|
|
71791
72010
|
if (pendingApprovals.length > 0) {
|
|
71792
72011
|
return { submitted: false };
|
|
@@ -71799,6 +72018,9 @@ function App2({
|
|
|
71799
72018
|
if (!isSlashCommand && streamingRef.current && !waitingForQueueCancelRef.current) {
|
|
71800
72019
|
waitingForQueueCancelRef.current = true;
|
|
71801
72020
|
queueSnapshotRef.current = [...newQueue];
|
|
72021
|
+
if (toolAbortControllerRef.current) {
|
|
72022
|
+
toolAbortControllerRef.current.abort();
|
|
72023
|
+
}
|
|
71802
72024
|
getClient2().then((client) => client.agents.messages.cancel(agentId)).then(() => {}).catch(() => {
|
|
71803
72025
|
waitingForQueueCancelRef.current = false;
|
|
71804
72026
|
});
|
|
@@ -72477,6 +72699,10 @@ Press Enter to continue, or type anything to cancel.`, false, "running");
|
|
|
72477
72699
|
return { submitted: true };
|
|
72478
72700
|
}
|
|
72479
72701
|
if (trimmed.startsWith("/skill")) {
|
|
72702
|
+
const approvalCheck = await checkPendingApprovalsForSlashCommand();
|
|
72703
|
+
if (approvalCheck.blocked) {
|
|
72704
|
+
return { submitted: false };
|
|
72705
|
+
}
|
|
72480
72706
|
const cmdId2 = uid4("cmd");
|
|
72481
72707
|
const [, ...rest] = trimmed.split(/\s+/);
|
|
72482
72708
|
const description = rest.join(" ").trim();
|
|
@@ -72535,6 +72761,10 @@ ${SKILL_CREATOR_PROMPT3}${userDescriptionLine}
|
|
|
72535
72761
|
return { submitted: true };
|
|
72536
72762
|
}
|
|
72537
72763
|
if (trimmed.startsWith("/remember")) {
|
|
72764
|
+
const approvalCheck = await checkPendingApprovalsForSlashCommand();
|
|
72765
|
+
if (approvalCheck.blocked) {
|
|
72766
|
+
return { submitted: false };
|
|
72767
|
+
}
|
|
72538
72768
|
const cmdId2 = uid4("cmd");
|
|
72539
72769
|
const [, ...rest] = trimmed.split(/\s+/);
|
|
72540
72770
|
const userText = rest.join(" ").trim();
|
|
@@ -72591,6 +72821,10 @@ The user did not specify what to remember. Look at the recent conversation conte
|
|
|
72591
72821
|
return { submitted: true };
|
|
72592
72822
|
}
|
|
72593
72823
|
if (trimmed === "/init") {
|
|
72824
|
+
const approvalCheck = await checkPendingApprovalsForSlashCommand();
|
|
72825
|
+
if (approvalCheck.blocked) {
|
|
72826
|
+
return { submitted: false };
|
|
72827
|
+
}
|
|
72594
72828
|
const cmdId2 = uid4("cmd");
|
|
72595
72829
|
buffersRef.current.byId.set(cmdId2, {
|
|
72596
72830
|
kind: "command",
|
|
@@ -72707,6 +72941,10 @@ ${gitContext}
|
|
|
72707
72941
|
const commandName = trimmed.split(/\s+/)[0]?.slice(1) || "";
|
|
72708
72942
|
const matchedCustom = await findCustomCommand2(commandName);
|
|
72709
72943
|
if (matchedCustom) {
|
|
72944
|
+
const approvalCheck = await checkPendingApprovalsForSlashCommand();
|
|
72945
|
+
if (approvalCheck.blocked) {
|
|
72946
|
+
return { submitted: false };
|
|
72947
|
+
}
|
|
72710
72948
|
const cmdId2 = uid4("cmd");
|
|
72711
72949
|
const args = trimmed.slice(`/${matchedCustom.id}`.length).trim();
|
|
72712
72950
|
let prompt = substituteArguments2(matchedCustom.content, args);
|
|
@@ -73106,7 +73344,7 @@ DO NOT respond to these messages or otherwise consider them in your response unl
|
|
|
73106
73344
|
role: "user",
|
|
73107
73345
|
content: messageContent
|
|
73108
73346
|
});
|
|
73109
|
-
await processConversation(initialInput);
|
|
73347
|
+
await processConversation(initialInput, { submissionGeneration });
|
|
73110
73348
|
clearPlaceholdersInText(msg);
|
|
73111
73349
|
return { submitted: true };
|
|
73112
73350
|
}, [
|
|
@@ -73228,6 +73466,8 @@ DO NOT respond to these messages or otherwise consider them in your response unl
|
|
|
73228
73466
|
setQueuedApprovalResults(allResults);
|
|
73229
73467
|
}
|
|
73230
73468
|
setStreaming(false);
|
|
73469
|
+
waitingForQueueCancelRef.current = false;
|
|
73470
|
+
queueSnapshotRef.current = [];
|
|
73231
73471
|
} else {
|
|
73232
73472
|
await processConversation([
|
|
73233
73473
|
{
|
|
@@ -73330,7 +73570,11 @@ DO NOT respond to these messages or otherwise consider them in your response unl
|
|
|
73330
73570
|
}
|
|
73331
73571
|
}
|
|
73332
73572
|
setIsExecutingTool(true);
|
|
73573
|
+
const approvalResultsSnapshot = [...approvalResults];
|
|
73574
|
+
const autoHandledSnapshot = [...autoHandledResults];
|
|
73575
|
+
const autoDeniedSnapshot = [...autoDeniedApprovals];
|
|
73333
73576
|
const allDecisions = [
|
|
73577
|
+
...approvalResultsSnapshot,
|
|
73334
73578
|
{ type: "approve", approval: currentApproval2 },
|
|
73335
73579
|
...nowAutoAllowed.map((r) => ({
|
|
73336
73580
|
type: "approve",
|
|
@@ -73350,12 +73594,29 @@ DO NOT respond to these messages or otherwise consider them in your response unl
|
|
|
73350
73594
|
onChunk(buffersRef.current, chunk);
|
|
73351
73595
|
refreshDerived();
|
|
73352
73596
|
});
|
|
73597
|
+
const allResults = [
|
|
73598
|
+
...autoHandledSnapshot.map((ar) => ({
|
|
73599
|
+
type: "tool",
|
|
73600
|
+
tool_call_id: ar.toolCallId,
|
|
73601
|
+
tool_return: ar.result.toolReturn,
|
|
73602
|
+
status: ar.result.status,
|
|
73603
|
+
stdout: ar.result.stdout,
|
|
73604
|
+
stderr: ar.result.stderr
|
|
73605
|
+
})),
|
|
73606
|
+
...autoDeniedSnapshot.map((ad) => ({
|
|
73607
|
+
type: "approval",
|
|
73608
|
+
tool_call_id: ad.approval.toolCallId,
|
|
73609
|
+
approve: false,
|
|
73610
|
+
reason: ad.reason
|
|
73611
|
+
})),
|
|
73612
|
+
...executedResults
|
|
73613
|
+
];
|
|
73353
73614
|
setThinkingMessage(getRandomThinkingVerb());
|
|
73354
73615
|
refreshDerived();
|
|
73355
73616
|
await processConversation([
|
|
73356
73617
|
{
|
|
73357
73618
|
type: "approval",
|
|
73358
|
-
approvals:
|
|
73619
|
+
approvals: allResults
|
|
73359
73620
|
}
|
|
73360
73621
|
]);
|
|
73361
73622
|
} finally {
|
|
@@ -73369,6 +73630,8 @@ DO NOT respond to these messages or otherwise consider them in your response unl
|
|
|
73369
73630
|
approvalResults,
|
|
73370
73631
|
approvalContexts,
|
|
73371
73632
|
pendingApprovals,
|
|
73633
|
+
autoHandledResults,
|
|
73634
|
+
autoDeniedApprovals,
|
|
73372
73635
|
handleApproveCurrent,
|
|
73373
73636
|
processConversation,
|
|
73374
73637
|
refreshDerived,
|
|
@@ -73976,7 +74239,6 @@ Plan file path: ${planFilePath}`;
|
|
|
73976
74239
|
]);
|
|
73977
74240
|
return /* @__PURE__ */ jsx_dev_runtime56.jsxDEV(Box_default, {
|
|
73978
74241
|
flexDirection: "column",
|
|
73979
|
-
gap: 1,
|
|
73980
74242
|
children: [
|
|
73981
74243
|
/* @__PURE__ */ jsx_dev_runtime56.jsxDEV(Static, {
|
|
73982
74244
|
items: staticItems,
|
|
@@ -74022,7 +74284,6 @@ Plan file path: ${planFilePath}`;
|
|
|
74022
74284
|
}, staticRenderEpoch, false, undefined, this),
|
|
74023
74285
|
/* @__PURE__ */ jsx_dev_runtime56.jsxDEV(Box_default, {
|
|
74024
74286
|
flexDirection: "column",
|
|
74025
|
-
gap: 1,
|
|
74026
74287
|
children: [
|
|
74027
74288
|
loadingState !== "ready" && /* @__PURE__ */ jsx_dev_runtime56.jsxDEV(WelcomeScreen, {
|
|
74028
74289
|
loadingState,
|
|
@@ -74217,7 +74478,7 @@ Plan file path: ${planFilePath}`;
|
|
|
74217
74478
|
]
|
|
74218
74479
|
}, undefined, true, undefined, this),
|
|
74219
74480
|
/* @__PURE__ */ jsx_dev_runtime56.jsxDEV(Box_default, {
|
|
74220
|
-
marginTop:
|
|
74481
|
+
marginTop: 1,
|
|
74221
74482
|
children: /* @__PURE__ */ jsx_dev_runtime56.jsxDEV(Input, {
|
|
74222
74483
|
visible: !showExitStats && pendingApprovals.length === 0 && !anySelectorOpen,
|
|
74223
74484
|
streaming: streaming && !abortControllerRef.current?.signal.aborted,
|
|
@@ -77531,13 +77792,19 @@ Error: ${message}`);
|
|
|
77531
77792
|
try {
|
|
77532
77793
|
await client.agents.retrieve(localProjectSettings.lastAgent);
|
|
77533
77794
|
resumingAgentId = localProjectSettings.lastAgent;
|
|
77534
|
-
} catch {
|
|
77795
|
+
} catch {
|
|
77796
|
+
setLoadingState("selecting_global");
|
|
77797
|
+
return;
|
|
77798
|
+
}
|
|
77535
77799
|
}
|
|
77536
77800
|
if (!resumingAgentId && continueSession && settings.lastAgent) {
|
|
77537
77801
|
try {
|
|
77538
77802
|
await client.agents.retrieve(settings.lastAgent);
|
|
77539
77803
|
resumingAgentId = settings.lastAgent;
|
|
77540
|
-
} catch {
|
|
77804
|
+
} catch {
|
|
77805
|
+
setLoadingState("selecting_global");
|
|
77806
|
+
return;
|
|
77807
|
+
}
|
|
77541
77808
|
}
|
|
77542
77809
|
if (!resumingAgentId && selectedGlobalAgentId) {
|
|
77543
77810
|
try {
|
|
@@ -77592,22 +77859,22 @@ Error: ${message}`);
|
|
|
77592
77859
|
agent = result.agent;
|
|
77593
77860
|
setAgentProvenance(result.provenance);
|
|
77594
77861
|
}
|
|
77595
|
-
if (!agent) {
|
|
77596
|
-
|
|
77597
|
-
|
|
77598
|
-
|
|
77599
|
-
|
|
77600
|
-
|
|
77601
|
-
|
|
77602
|
-
console.error(`Project agent ${localProjectSettings.lastAgent} not found (error: ${JSON.stringify(error)}), creating new one...`);
|
|
77603
|
-
}
|
|
77862
|
+
if (!agent && resumingAgentId) {
|
|
77863
|
+
try {
|
|
77864
|
+
agent = await client.agents.retrieve(resumingAgentId);
|
|
77865
|
+
} catch (error) {
|
|
77866
|
+
console.error(`Agent ${resumingAgentId} not found (error: ${JSON.stringify(error)})`);
|
|
77867
|
+
setLoadingState("selecting_global");
|
|
77868
|
+
return;
|
|
77604
77869
|
}
|
|
77605
77870
|
}
|
|
77606
77871
|
if (!agent && continueSession && settings.lastAgent) {
|
|
77607
77872
|
try {
|
|
77608
77873
|
agent = await client.agents.retrieve(settings.lastAgent);
|
|
77609
77874
|
} catch (error) {
|
|
77610
|
-
console.error(`Previous agent ${settings.lastAgent} not found (error: ${JSON.stringify(error)})
|
|
77875
|
+
console.error(`Previous agent ${settings.lastAgent} not found (error: ${JSON.stringify(error)})`);
|
|
77876
|
+
setLoadingState("selecting_global");
|
|
77877
|
+
return;
|
|
77611
77878
|
}
|
|
77612
77879
|
}
|
|
77613
77880
|
if (!agent) {
|
|
@@ -77770,4 +78037,4 @@ Error during initialization: ${message}`);
|
|
|
77770
78037
|
}
|
|
77771
78038
|
main();
|
|
77772
78039
|
|
|
77773
|
-
//# debugId=
|
|
78040
|
+
//# debugId=D2E37E4C34BABD1E64756E2164756E21
|