Add /link and /unlink commands for managing agent tools (#59)

Co-authored-by: Letta <noreply@letta.com>
This commit is contained in:
Cameron
2025-11-05 18:11:51 -08:00
committed by GitHub
parent 424fabaed4
commit 79bc3c2d98
10 changed files with 701 additions and 4 deletions

View File

@@ -15,6 +15,7 @@ import { useCallback, useEffect, useMemo, useRef, useState } from "react";
import { getResumeData } from "../agent/check-approval";
import { getClient } from "../agent/client";
import { sendMessageStream } from "../agent/message";
import { linkToolsToAgent, unlinkToolsFromAgent } from "../agent/modify";
import { SessionStats } from "../agent/stats";
import type { ApprovalContext } from "../permissions/analyzer";
import { permissionMode } from "../permissions/mode";
@@ -111,6 +112,8 @@ export default function App({
loadingState?:
| "assembling"
| "upserting"
| "linking"
| "unlinking"
| "initializing"
| "checking"
| "ready";
@@ -837,6 +840,92 @@ export default function App({
return { submitted: true };
}
// Special handling for /link command - attach Letta Code tools
if (msg.trim() === "/link") {
const cmdId = uid("cmd");
buffersRef.current.byId.set(cmdId, {
kind: "command",
id: cmdId,
input: msg,
output: "Attaching Letta Code tools to agent...",
phase: "running",
});
buffersRef.current.order.push(cmdId);
refreshDerived();
setCommandRunning(true);
try {
const result = await linkToolsToAgent(agentId);
buffersRef.current.byId.set(cmdId, {
kind: "command",
id: cmdId,
input: msg,
output: result.message,
phase: "finished",
success: result.success,
});
refreshDerived();
} catch (error) {
buffersRef.current.byId.set(cmdId, {
kind: "command",
id: cmdId,
input: msg,
output: `Failed: ${error instanceof Error ? error.message : String(error)}`,
phase: "finished",
success: false,
});
refreshDerived();
} finally {
setCommandRunning(false);
}
return { submitted: true };
}
// Special handling for /unlink command - remove Letta Code tools
if (msg.trim() === "/unlink") {
const cmdId = uid("cmd");
buffersRef.current.byId.set(cmdId, {
kind: "command",
id: cmdId,
input: msg,
output: "Removing Letta Code tools from agent...",
phase: "running",
});
buffersRef.current.order.push(cmdId);
refreshDerived();
setCommandRunning(true);
try {
const result = await unlinkToolsFromAgent(agentId);
buffersRef.current.byId.set(cmdId, {
kind: "command",
id: cmdId,
input: msg,
output: result.message,
phase: "finished",
success: result.success,
});
refreshDerived();
} catch (error) {
buffersRef.current.byId.set(cmdId, {
kind: "command",
id: cmdId,
input: msg,
output: `Failed: ${error instanceof Error ? error.message : String(error)}`,
phase: "finished",
success: false,
});
refreshDerived();
} finally {
setCommandRunning(false);
}
return { submitted: true };
}
// Immediately add command to transcript with "running" phase
const cmdId = uid("cmd");
buffersRef.current.byId.set(cmdId, {

View File

@@ -50,6 +50,20 @@ export const commands: Record<string, Command> = {
return "Clearing credentials...";
},
},
"/link": {
desc: "Attach Letta Code tools to current agent",
handler: () => {
// Handled specially in App.tsx to access agent ID and client
return "Attaching tools...";
},
},
"/unlink": {
desc: "Remove Letta Code tools from current agent",
handler: () => {
// Handled specially in App.tsx to access agent ID and client
return "Removing tools...";
},
},
};
/**

View File

@@ -34,9 +34,10 @@ export function CommandPreview({
paddingX={1}
>
{commandList.map((item) => (
<Box key={item.cmd} justifyContent="space-between" width={40}>
<Text>{item.cmd}</Text>
<Text dimColor>{item.desc}</Text>
<Box key={item.cmd}>
<Text>
{item.cmd.padEnd(15)} <Text dimColor>{item.desc}</Text>
</Text>
</Box>
))}
{showAgentUrl && (

View File

@@ -9,6 +9,8 @@ import { colors } from "./colors";
type LoadingState =
| "assembling"
| "upserting"
| "linking"
| "unlinking"
| "initializing"
| "checking"
| "ready";
@@ -82,6 +84,12 @@ export function WelcomeScreen({
if (loadingState === "upserting") {
return "Upserting tools...";
}
if (loadingState === "linking") {
return "Attaching Letta Code tools...";
}
if (loadingState === "unlinking") {
return "Removing Letta Code tools...";
}
if (loadingState === "checking") {
return "Checking for pending approvals...";
}