fix: add guard for default conversation id (#1245)
This commit is contained in:
@@ -6,7 +6,7 @@ import { APIError } from "@letta-ai/letta-client/core/error";
|
||||
import type { AgentState } from "@letta-ai/letta-client/resources/agents/agents";
|
||||
import type { Message } from "@letta-ai/letta-client/resources/agents/messages";
|
||||
import type { ApprovalRequest } from "../cli/helpers/stream";
|
||||
import { debugWarn } from "../utils/debug";
|
||||
import { debugLog, debugWarn } from "../utils/debug";
|
||||
|
||||
// Backfill should feel like "the last turn(s)", not "the last N raw messages".
|
||||
// Tool-heavy turns can generate many tool_call/tool_return messages that would
|
||||
@@ -344,16 +344,21 @@ export async function getResumeData(
|
||||
|
||||
// Use conversations API for explicit conversations,
|
||||
// use agents API for "default" or no conversationId (agent's primary message history)
|
||||
const useConversationsApi = conversationId && conversationId !== "default";
|
||||
const useConversationsApi =
|
||||
conversationId &&
|
||||
conversationId !== "default" &&
|
||||
!conversationId.startsWith("agent-");
|
||||
|
||||
if (process.env.DEBUG) {
|
||||
console.log(
|
||||
`[DEBUG] getResumeData: conversationId=${conversationId}, useConversationsApi=${useConversationsApi}, agentId=${agent.id}`,
|
||||
if (conversationId?.startsWith("agent-")) {
|
||||
debugWarn(
|
||||
"check-approval",
|
||||
`getResumeData called with agent ID as conversationId: ${conversationId}\n${new Error().stack}`,
|
||||
);
|
||||
}
|
||||
|
||||
if (useConversationsApi) {
|
||||
// Get conversation to access in_context_message_ids (source of truth)
|
||||
debugLog("conversations", `retrieve(${conversationId}) [getResumeData]`);
|
||||
const conversation = await client.conversations.retrieve(conversationId);
|
||||
inContextMessageIds = conversation.in_context_message_ids;
|
||||
|
||||
|
||||
@@ -3280,6 +3280,10 @@ export default function App({
|
||||
|
||||
try {
|
||||
const client = await getClient();
|
||||
debugLog(
|
||||
"conversations",
|
||||
`retrieve(${conversationId}) [syncConversationModel]`,
|
||||
);
|
||||
const conversation =
|
||||
await client.conversations.retrieve(conversationId);
|
||||
if (cancelled) return;
|
||||
@@ -6154,7 +6158,9 @@ export default function App({
|
||||
// Build success message
|
||||
const agentLabel = agent.name || targetAgentId;
|
||||
const isSpecificConv =
|
||||
opts?.conversationId && opts.conversationId !== "default";
|
||||
opts?.conversationId &&
|
||||
opts.conversationId !== "default" &&
|
||||
!opts?.conversationId.startsWith("agent-");
|
||||
const successOutput = isSpecificConv
|
||||
? [
|
||||
`Switched to **${agentLabel}**`,
|
||||
@@ -8695,7 +8701,7 @@ export default function App({
|
||||
|
||||
// Build export parameters (include conversation_id if in specific conversation)
|
||||
const exportParams: { conversation_id?: string } = {};
|
||||
if (conversationId !== "default") {
|
||||
if (conversationId !== "default" && conversationId !== agentId) {
|
||||
exportParams.conversation_id = conversationId;
|
||||
}
|
||||
|
||||
@@ -12914,15 +12920,16 @@ If using apply_patch, use this exact relative patch path: ${applyPatchRelativePa
|
||||
: `letta --agent ${agentId}`}
|
||||
</Text>
|
||||
{/* Only show conversation hint if not on default (default is resumed automatically) */}
|
||||
{conversationId !== "default" && (
|
||||
<>
|
||||
<Box height={1} />
|
||||
<Text dimColor>Resume this conversation with:</Text>
|
||||
<Text color={colors.link.url}>
|
||||
{`letta --conv ${conversationId}`}
|
||||
</Text>
|
||||
</>
|
||||
)}
|
||||
{conversationId !== "default" &&
|
||||
conversationId !== agentId && (
|
||||
<>
|
||||
<Box height={1} />
|
||||
<Text dimColor>Resume this conversation with:</Text>
|
||||
<Text color={colors.link.url}>
|
||||
{`letta --conv ${conversationId}`}
|
||||
</Text>
|
||||
</>
|
||||
)}
|
||||
</Box>
|
||||
);
|
||||
})()}
|
||||
|
||||
@@ -177,7 +177,9 @@ export const AgentInfoBar = memo(function AgentInfoBar({
|
||||
{/* Phantom alien row + Conversation ID */}
|
||||
<Box>
|
||||
<Text>{alienLines[3]}</Text>
|
||||
{conversationId && conversationId !== "default" ? (
|
||||
{conversationId &&
|
||||
conversationId !== "default" &&
|
||||
!conversationId.startsWith("agent-") ? (
|
||||
<Box width={rightWidth} flexShrink={1}>
|
||||
<Text dimColor wrap="truncate-end">
|
||||
{truncateText(conversationId, rightWidth)}
|
||||
|
||||
@@ -114,6 +114,7 @@ import type {
|
||||
StreamEvent,
|
||||
SystemInitMessage,
|
||||
} from "./types/protocol";
|
||||
import { debugLog } from "./utils/debug";
|
||||
import {
|
||||
markMilestone,
|
||||
measureSinceMilestone,
|
||||
@@ -526,7 +527,10 @@ export async function handleHeadlessCommand(
|
||||
// Validate shared mutual-exclusion rules for startup flags.
|
||||
try {
|
||||
validateFlagConflicts({
|
||||
guard: specifiedConversationId && specifiedConversationId !== "default",
|
||||
guard:
|
||||
specifiedConversationId &&
|
||||
specifiedConversationId !== "default" &&
|
||||
!specifiedConversationId.startsWith("agent-"),
|
||||
checks: [
|
||||
{
|
||||
when: specifiedAgentId,
|
||||
@@ -730,8 +734,16 @@ export async function handleHeadlessCommand(
|
||||
// Priority 0: --conversation derives agent from conversation ID.
|
||||
// "default" is a virtual agent-scoped conversation (not a retrievable conv-*).
|
||||
// It requires --agent and should not hit conversations.retrieve().
|
||||
if (specifiedConversationId && specifiedConversationId !== "default") {
|
||||
if (
|
||||
specifiedConversationId &&
|
||||
specifiedConversationId !== "default" &&
|
||||
!specifiedConversationId.startsWith("agent-")
|
||||
) {
|
||||
try {
|
||||
debugLog(
|
||||
"conversations",
|
||||
`retrieve(${specifiedConversationId}) [headless conv→agent lookup]`,
|
||||
);
|
||||
const conversation = await client.conversations.retrieve(
|
||||
specifiedConversationId,
|
||||
);
|
||||
@@ -1007,6 +1019,10 @@ export async function handleHeadlessCommand(
|
||||
} else {
|
||||
// User specified an explicit conversation to resume - validate it exists
|
||||
try {
|
||||
debugLog(
|
||||
"conversations",
|
||||
`retrieve(${specifiedConversationId}) [headless --conv validate]`,
|
||||
);
|
||||
await client.conversations.retrieve(specifiedConversationId);
|
||||
conversationId = specifiedConversationId;
|
||||
} catch {
|
||||
@@ -1030,6 +1046,10 @@ export async function handleHeadlessCommand(
|
||||
} else {
|
||||
// Verify the conversation still exists
|
||||
try {
|
||||
debugLog(
|
||||
"conversations",
|
||||
`retrieve(${lastSession.conversationId}) [headless lastSession resume]`,
|
||||
);
|
||||
await client.conversations.retrieve(lastSession.conversationId);
|
||||
conversationId = lastSession.conversationId;
|
||||
} catch {
|
||||
|
||||
10
src/index.ts
10
src/index.ts
@@ -47,6 +47,7 @@ import { settingsManager } from "./settings-manager";
|
||||
import { startStartupAutoUpdateCheck } from "./startup-auto-update";
|
||||
import { telemetry } from "./telemetry";
|
||||
import { loadTools } from "./tools/manager";
|
||||
import { debugLog } from "./utils/debug";
|
||||
import { markMilestone } from "./utils/timing";
|
||||
|
||||
// Stable empty array constants to prevent new references on every render
|
||||
@@ -629,7 +630,10 @@ async function main(): Promise<void> {
|
||||
// Validate shared mutual-exclusion rules for startup flags.
|
||||
try {
|
||||
validateFlagConflicts({
|
||||
guard: specifiedConversationId && specifiedConversationId !== "default",
|
||||
guard:
|
||||
specifiedConversationId &&
|
||||
specifiedConversationId !== "default" &&
|
||||
!specifiedConversationId.startsWith("agent-"),
|
||||
checks: [
|
||||
{
|
||||
when: specifiedAgentId,
|
||||
@@ -1193,6 +1197,10 @@ async function main(): Promise<void> {
|
||||
|
||||
// For explicit conversations, derive agent from conversation
|
||||
try {
|
||||
debugLog(
|
||||
"conversations",
|
||||
`retrieve(${specifiedConversationId}) [TUI conv→agent lookup]`,
|
||||
);
|
||||
const conversation = await client.conversations.retrieve(
|
||||
specifiedConversationId,
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user