Add /link and /unlink commands for managing agent tools (#59)
Co-authored-by: Letta <noreply@letta.com>
This commit is contained in:
@@ -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, {
|
||||
|
||||
@@ -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...";
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -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 && (
|
||||
|
||||
@@ -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...";
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user