Prompt is too long
This commit is contained in:
@@ -505,18 +505,10 @@ export class AgentManager {
|
||||
return Array.from(this.agents.values()).map((agent) => {
|
||||
const status = getAgentStatusFromState(agent.state);
|
||||
const error = getAgentError(agent.state);
|
||||
const sessionId =
|
||||
agent.state.type !== "uninitialized" && agent.state.type !== "killed" && agent.state.type !== "failed"
|
||||
? agent.state.runtime.sessionId
|
||||
: null;
|
||||
const currentModeId =
|
||||
agent.state.type !== "uninitialized" && agent.state.type !== "killed" && agent.state.type !== "failed"
|
||||
? agent.state.runtime.currentModeId
|
||||
: null;
|
||||
const availableModes =
|
||||
agent.state.type !== "uninitialized" && agent.state.type !== "killed" && agent.state.type !== "failed"
|
||||
? agent.state.runtime.availableModes
|
||||
: null;
|
||||
const runtime = this.getRuntime(agent);
|
||||
const sessionId = runtime?.sessionId ?? null;
|
||||
const currentModeId = runtime?.currentModeId ?? null;
|
||||
const availableModes = runtime?.availableModes ?? null;
|
||||
|
||||
return {
|
||||
id: agent.id,
|
||||
@@ -564,6 +556,43 @@ export class AgentManager {
|
||||
return [...agent.updates];
|
||||
}
|
||||
|
||||
/**
|
||||
* Lazily initialize an agent and return its info and existing history
|
||||
* Used by clients to opt-in to agent startup on demand
|
||||
*/
|
||||
async initializeAgentAndGetHistory(
|
||||
agentId: string
|
||||
): Promise<{ info: AgentInfo; updates: AgentUpdate[] }> {
|
||||
await this.ensureInitialized(agentId);
|
||||
|
||||
const agent = this.agents.get(agentId);
|
||||
if (!agent) {
|
||||
throw new Error(`Agent ${agentId} not found`);
|
||||
}
|
||||
|
||||
const status = getAgentStatusFromState(agent.state);
|
||||
const error = getAgentError(agent.state);
|
||||
const runtime = this.getRuntime(agent);
|
||||
|
||||
const info: AgentInfo = {
|
||||
id: agent.id,
|
||||
status,
|
||||
createdAt: agent.createdAt,
|
||||
type: "claude",
|
||||
sessionId: runtime?.sessionId ?? null,
|
||||
error: error ?? null,
|
||||
currentModeId: runtime?.currentModeId ?? null,
|
||||
availableModes: runtime?.availableModes ?? null,
|
||||
title: agent.title,
|
||||
cwd: agent.cwd,
|
||||
};
|
||||
|
||||
return {
|
||||
info,
|
||||
updates: [...agent.updates],
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current session mode for an agent
|
||||
*/
|
||||
@@ -645,6 +674,8 @@ export class AgentManager {
|
||||
case "initializing":
|
||||
agent.state = {
|
||||
type: "initializing",
|
||||
persistedSessionId: agent.state.persistedSessionId,
|
||||
initPromise: agent.state.initPromise,
|
||||
runtime: updatedRuntime,
|
||||
initStartedAt: agent.state.initStartedAt,
|
||||
};
|
||||
@@ -755,7 +786,7 @@ export class AgentManager {
|
||||
}
|
||||
|
||||
if (agent.state.type === "initializing") {
|
||||
return agent.state.runtime;
|
||||
return agent.state.runtime ?? null;
|
||||
}
|
||||
|
||||
if (agent.state.type === "failed" && agent.state.runtime) {
|
||||
@@ -820,10 +851,16 @@ export class AgentManager {
|
||||
availableModes: null,
|
||||
};
|
||||
|
||||
if (agent.state.type !== "initializing") {
|
||||
throw new Error(`Agent ${agentId} must be initializing before starting runtime`);
|
||||
}
|
||||
|
||||
agent.state = {
|
||||
type: "initializing",
|
||||
persistedSessionId: agent.state.persistedSessionId,
|
||||
initPromise: agent.state.initPromise,
|
||||
initStartedAt: agent.state.initStartedAt,
|
||||
runtime,
|
||||
initStartedAt: new Date(),
|
||||
};
|
||||
|
||||
agentProcess.on("error", (error) => {
|
||||
|
||||
@@ -65,7 +65,13 @@ export interface AgentRuntime {
|
||||
*/
|
||||
export type ManagedAgentState =
|
||||
| { type: "uninitialized"; persistedSessionId: string | null; lastError?: string }
|
||||
| { type: "initializing"; persistedSessionId: string | null; initPromise: Promise<void>; initStartedAt: Date }
|
||||
| {
|
||||
type: "initializing";
|
||||
persistedSessionId: string | null;
|
||||
initPromise: Promise<void>;
|
||||
initStartedAt: Date;
|
||||
runtime?: AgentRuntime;
|
||||
}
|
||||
| { type: "ready"; runtime: AgentRuntime }
|
||||
| { type: "processing"; runtime: AgentRuntime }
|
||||
| { type: "completed"; runtime: AgentRuntime; stopReason?: string }
|
||||
|
||||
@@ -1,5 +1,30 @@
|
||||
import { z } from "zod";
|
||||
|
||||
const AgentModeSchema = z.object({
|
||||
id: z.string(),
|
||||
name: z.string(),
|
||||
description: z.string().nullable().optional(),
|
||||
});
|
||||
|
||||
const AgentInfoSchema = z.object({
|
||||
id: z.string(),
|
||||
status: z.string(),
|
||||
createdAt: z.date(),
|
||||
type: z.literal("claude"),
|
||||
sessionId: z.string().nullable(),
|
||||
error: z.string().nullable(),
|
||||
currentModeId: z.string().nullable(),
|
||||
availableModes: z.array(AgentModeSchema).nullable(),
|
||||
title: z.string().nullable(),
|
||||
cwd: z.string(),
|
||||
});
|
||||
|
||||
const AgentUpdatePayloadSchema = z.object({
|
||||
agentId: z.string(),
|
||||
timestamp: z.date(),
|
||||
notification: z.any(),
|
||||
});
|
||||
|
||||
// ============================================================================
|
||||
// Session Inbound Messages (Session receives these)
|
||||
// ============================================================================
|
||||
@@ -66,6 +91,12 @@ export const CreateAgentRequestMessageSchema = z.object({
|
||||
requestId: z.string().optional(),
|
||||
});
|
||||
|
||||
export const InitializeAgentRequestMessageSchema = z.object({
|
||||
type: z.literal("initialize_agent_request"),
|
||||
agentId: z.string(),
|
||||
requestId: z.string().optional(),
|
||||
});
|
||||
|
||||
export const SetAgentModeMessageSchema = z.object({
|
||||
type: z.literal("set_agent_mode"),
|
||||
agentId: z.string(),
|
||||
@@ -91,6 +122,7 @@ export const SessionInboundMessageSchema = z.discriminatedUnion("type", [
|
||||
SendAgentMessageSchema,
|
||||
SendAgentAudioSchema,
|
||||
CreateAgentRequestMessageSchema,
|
||||
InitializeAgentRequestMessageSchema,
|
||||
SetAgentModeMessageSchema,
|
||||
AgentPermissionResponseMessageSchema,
|
||||
]);
|
||||
@@ -182,11 +214,7 @@ export const AgentCreatedMessageSchema = z.object({
|
||||
status: z.string(),
|
||||
type: z.literal("claude"),
|
||||
currentModeId: z.string().optional(),
|
||||
availableModes: z.array(z.object({
|
||||
id: z.string(),
|
||||
name: z.string(),
|
||||
description: z.string().nullable().optional(),
|
||||
})).optional(),
|
||||
availableModes: z.array(AgentModeSchema).optional(),
|
||||
title: z.string().optional(),
|
||||
cwd: z.string(),
|
||||
requestId: z.string().optional(),
|
||||
@@ -195,12 +223,7 @@ export const AgentCreatedMessageSchema = z.object({
|
||||
|
||||
export const AgentUpdateMessageSchema = z.object({
|
||||
type: z.literal("agent_update"),
|
||||
payload: z.object({
|
||||
agentId: z.string(),
|
||||
timestamp: z.date(),
|
||||
// Runtime validation with z.any(), TypeScript enforces AgentNotification type
|
||||
notification: z.any(),
|
||||
}),
|
||||
payload: AgentUpdatePayloadSchema,
|
||||
});
|
||||
|
||||
export const AgentStatusMessageSchema = z.object({
|
||||
@@ -208,46 +231,14 @@ export const AgentStatusMessageSchema = z.object({
|
||||
payload: z.object({
|
||||
agentId: z.string(),
|
||||
status: z.string(),
|
||||
info: z.object({
|
||||
id: z.string(),
|
||||
status: z.string(),
|
||||
createdAt: z.date(),
|
||||
type: z.literal("claude"),
|
||||
sessionId: z.string().optional(),
|
||||
error: z.string().optional(),
|
||||
currentModeId: z.string().optional(),
|
||||
availableModes: z.array(z.object({
|
||||
id: z.string(),
|
||||
name: z.string(),
|
||||
description: z.string().nullable().optional(),
|
||||
})).optional(),
|
||||
title: z.string().optional(),
|
||||
cwd: z.string(),
|
||||
}),
|
||||
info: AgentInfoSchema,
|
||||
}),
|
||||
});
|
||||
|
||||
export const SessionStateMessageSchema = z.object({
|
||||
type: z.literal("session_state"),
|
||||
payload: z.object({
|
||||
agents: z.array(
|
||||
z.object({
|
||||
id: z.string(),
|
||||
status: z.string(),
|
||||
createdAt: z.date(),
|
||||
type: z.literal("claude"),
|
||||
sessionId: z.string().nullable(),
|
||||
error: z.string().nullable(),
|
||||
currentModeId: z.string().nullable(),
|
||||
availableModes: z.array(z.object({
|
||||
id: z.string(),
|
||||
name: z.string(),
|
||||
description: z.string().nullable().optional(),
|
||||
})).nullable(),
|
||||
title: z.string().nullable(),
|
||||
cwd: z.string(),
|
||||
})
|
||||
),
|
||||
agents: z.array(AgentInfoSchema),
|
||||
commands: z.array(
|
||||
z.object({
|
||||
id: z.string(),
|
||||
@@ -261,6 +252,16 @@ export const SessionStateMessageSchema = z.object({
|
||||
}),
|
||||
});
|
||||
|
||||
export const AgentInitializedMessageSchema = z.object({
|
||||
type: z.literal("agent_initialized"),
|
||||
payload: z.object({
|
||||
agentId: z.string(),
|
||||
info: AgentInfoSchema,
|
||||
updates: z.array(AgentUpdatePayloadSchema),
|
||||
requestId: z.string().optional(),
|
||||
}),
|
||||
});
|
||||
|
||||
export const ListConversationsResponseMessageSchema = z.object({
|
||||
type: z.literal("list_conversations_response"),
|
||||
payload: z.object({
|
||||
@@ -319,6 +320,7 @@ export const SessionOutboundMessageSchema = z.discriminatedUnion("type", [
|
||||
AgentUpdateMessageSchema,
|
||||
AgentStatusMessageSchema,
|
||||
SessionStateMessageSchema,
|
||||
AgentInitializedMessageSchema,
|
||||
ListConversationsResponseMessageSchema,
|
||||
DeleteConversationResponseMessageSchema,
|
||||
AgentPermissionRequestMessageSchema,
|
||||
@@ -341,6 +343,7 @@ export type AgentCreatedMessage = z.infer<typeof AgentCreatedMessageSchema>;
|
||||
export type AgentUpdateMessage = z.infer<typeof AgentUpdateMessageSchema>;
|
||||
export type AgentStatusMessage = z.infer<typeof AgentStatusMessageSchema>;
|
||||
export type SessionStateMessage = z.infer<typeof SessionStateMessageSchema>;
|
||||
export type AgentInitializedMessage = z.infer<typeof AgentInitializedMessageSchema>;
|
||||
export type ListConversationsResponseMessage = z.infer<typeof ListConversationsResponseMessageSchema>;
|
||||
export type DeleteConversationResponseMessage = z.infer<typeof DeleteConversationResponseMessageSchema>;
|
||||
export type AgentPermissionRequestMessage = z.infer<typeof AgentPermissionRequestMessageSchema>;
|
||||
@@ -355,6 +358,7 @@ export type RealtimeAudioChunkMessage = z.infer<typeof RealtimeAudioChunkMessage
|
||||
export type SendAgentMessage = z.infer<typeof SendAgentMessageSchema>;
|
||||
export type SendAgentAudio = z.infer<typeof SendAgentAudioSchema>;
|
||||
export type CreateAgentRequestMessage = z.infer<typeof CreateAgentRequestMessageSchema>;
|
||||
export type InitializeAgentRequestMessage = z.infer<typeof InitializeAgentRequestMessageSchema>;
|
||||
export type SetAgentModeMessage = z.infer<typeof SetAgentModeMessageSchema>;
|
||||
export type AgentPermissionResponseMessage = z.infer<typeof AgentPermissionResponseMessageSchema>;
|
||||
|
||||
|
||||
@@ -222,18 +222,7 @@ export class Session {
|
||||
payload: {
|
||||
agentId,
|
||||
status,
|
||||
info: {
|
||||
id: info.id,
|
||||
status: info.status,
|
||||
createdAt: info.createdAt,
|
||||
type: info.type,
|
||||
sessionId: info.sessionId ?? undefined,
|
||||
error: info.error ?? undefined,
|
||||
currentModeId: info.currentModeId ?? undefined,
|
||||
availableModes: info.availableModes ?? undefined,
|
||||
title: info.title ?? undefined,
|
||||
cwd: info.cwd,
|
||||
},
|
||||
info,
|
||||
},
|
||||
});
|
||||
console.log(
|
||||
@@ -331,18 +320,7 @@ export class Session {
|
||||
payload: {
|
||||
agentId,
|
||||
status: updatedInfo.status,
|
||||
info: {
|
||||
id: updatedInfo.id,
|
||||
status: updatedInfo.status,
|
||||
createdAt: updatedInfo.createdAt,
|
||||
type: updatedInfo.type,
|
||||
sessionId: updatedInfo.sessionId ?? undefined,
|
||||
error: updatedInfo.error ?? undefined,
|
||||
currentModeId: updatedInfo.currentModeId ?? undefined,
|
||||
availableModes: updatedInfo.availableModes ?? undefined,
|
||||
title: updatedInfo.title ?? undefined,
|
||||
cwd: updatedInfo.cwd,
|
||||
},
|
||||
info: updatedInfo,
|
||||
},
|
||||
});
|
||||
}
|
||||
@@ -492,6 +470,13 @@ export class Session {
|
||||
await this.handleCreateAgentRequest(msg.cwd, msg.initialMode, msg.requestId);
|
||||
break;
|
||||
|
||||
case "initialize_agent_request":
|
||||
await this.handleInitializeAgentRequest(
|
||||
msg.agentId,
|
||||
msg.requestId
|
||||
);
|
||||
break;
|
||||
|
||||
case "set_agent_mode":
|
||||
await this.handleSetAgentMode(msg.agentId, msg.modeId);
|
||||
break;
|
||||
@@ -715,6 +700,61 @@ export class Session {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle on-demand agent initialization request from client
|
||||
*/
|
||||
private async handleInitializeAgentRequest(
|
||||
agentId: string,
|
||||
requestId?: string
|
||||
): Promise<void> {
|
||||
console.log(
|
||||
`[Session ${this.clientId}] Initializing agent ${agentId} on demand`
|
||||
);
|
||||
|
||||
try {
|
||||
this.subscribeToAgent(agentId);
|
||||
|
||||
const { info, updates } =
|
||||
await this.agentManager.initializeAgentAndGetHistory(agentId);
|
||||
|
||||
this.emit({
|
||||
type: "agent_initialized",
|
||||
payload: {
|
||||
agentId,
|
||||
info,
|
||||
updates: updates.map((update) => ({
|
||||
agentId: update.agentId,
|
||||
timestamp:
|
||||
update.timestamp instanceof Date
|
||||
? update.timestamp
|
||||
: new Date(update.timestamp),
|
||||
notification: update.notification,
|
||||
})),
|
||||
requestId,
|
||||
},
|
||||
});
|
||||
|
||||
console.log(
|
||||
`[Session ${this.clientId}] Agent ${agentId} initialized with ${updates.length} historical updates`
|
||||
);
|
||||
} catch (error: any) {
|
||||
console.error(
|
||||
`[Session ${this.clientId}] Failed to initialize agent ${agentId}:`,
|
||||
error
|
||||
);
|
||||
this.emit({
|
||||
type: "activity_log",
|
||||
payload: {
|
||||
id: uuidv4(),
|
||||
timestamp: new Date(),
|
||||
type: "error",
|
||||
content: `Failed to initialize agent: ${error.message}`,
|
||||
},
|
||||
});
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle create agent request
|
||||
*/
|
||||
@@ -749,23 +789,27 @@ export class Session {
|
||||
// Subscribe to agent updates
|
||||
this.subscribeToAgent(agentId);
|
||||
|
||||
// Emit agent_created message
|
||||
// Auto-initialize agent immediately on explicit creation so it's ready to use
|
||||
console.log(`[Session ${this.clientId}] Auto-initializing agent ${agentId}`);
|
||||
const { info } = await this.agentManager.initializeAgentAndGetHistory(agentId);
|
||||
|
||||
// Emit agent_created message with initialized info
|
||||
this.emit({
|
||||
type: "agent_created",
|
||||
payload: {
|
||||
agentId,
|
||||
status: agentInfo?.status || "initializing",
|
||||
status: info.status,
|
||||
type: "claude",
|
||||
currentModeId: agentInfo?.currentModeId ?? undefined,
|
||||
availableModes: agentInfo?.availableModes ?? undefined,
|
||||
title: agentInfo?.title ?? undefined,
|
||||
cwd: agentInfo?.cwd || cwd,
|
||||
currentModeId: info.currentModeId ?? undefined,
|
||||
availableModes: info.availableModes ?? undefined,
|
||||
title: info.title ?? undefined,
|
||||
cwd: info.cwd,
|
||||
requestId,
|
||||
},
|
||||
});
|
||||
console.log(
|
||||
`[Session ${this.clientId}] Emitted agent_created with currentModeId:`,
|
||||
agentInfo?.currentModeId
|
||||
`[Session ${this.clientId}] Emitted agent_created with status: ${info.status}, currentModeId:`,
|
||||
info.currentModeId
|
||||
);
|
||||
} catch (error: any) {
|
||||
console.error(
|
||||
@@ -810,18 +854,7 @@ export class Session {
|
||||
payload: {
|
||||
agentId,
|
||||
status: info.status,
|
||||
info: {
|
||||
id: info.id,
|
||||
status: info.status,
|
||||
createdAt: info.createdAt,
|
||||
type: info.type,
|
||||
title: info.title ?? undefined,
|
||||
cwd: info.cwd,
|
||||
sessionId: info.sessionId ?? undefined,
|
||||
error: info.error ?? undefined,
|
||||
currentModeId: info.currentModeId ?? undefined,
|
||||
availableModes: info.availableModes ?? undefined,
|
||||
},
|
||||
info,
|
||||
},
|
||||
});
|
||||
}
|
||||
@@ -886,30 +919,9 @@ export class Session {
|
||||
// Get live agents with session modes
|
||||
const agents = this.agentManager?.listAgents() || [];
|
||||
|
||||
// Subscribe to all existing agents and send their history (in case of reconnection)
|
||||
// Subscribe to all existing agents so future updates stream through
|
||||
for (const agent of agents) {
|
||||
this.subscribeToAgent(agent.id);
|
||||
|
||||
// Get historical updates from AgentManager
|
||||
const history = this.agentManager.getAgentUpdates(agent.id);
|
||||
|
||||
// Send each historical update to client
|
||||
console.log(
|
||||
`[Session ${this.clientId}] Sending ${history.length} historical updates for agent ${agent.id}`
|
||||
);
|
||||
for (const update of history) {
|
||||
this.emit({
|
||||
type: "agent_update",
|
||||
payload: {
|
||||
agentId: update.agentId,
|
||||
timestamp:
|
||||
update.timestamp instanceof Date
|
||||
? update.timestamp
|
||||
: new Date(update.timestamp),
|
||||
notification: update.notification,
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Get live commands from terminal manager
|
||||
|
||||
Reference in New Issue
Block a user