@letta-ai/letta-code 0.27.12 → 0.27.13
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.
|
@@ -91,6 +91,16 @@ function messageDataToString(data) {
|
|
|
91
91
|
function parseProtocolMessage(event) {
|
|
92
92
|
return JSON.parse(messageDataToString(event));
|
|
93
93
|
}
|
|
94
|
+
function appServerSocketOptions(authToken) {
|
|
95
|
+
if (authToken === undefined) {
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
const token = authToken.trim();
|
|
99
|
+
if (!token) {
|
|
100
|
+
throw new Error("app-server auth token must not be empty");
|
|
101
|
+
}
|
|
102
|
+
return { headers: { Authorization: `Bearer ${token}` } };
|
|
103
|
+
}
|
|
94
104
|
function sameRuntime(a, b) {
|
|
95
105
|
return a?.agent_id === b.agent_id && a?.conversation_id === b.conversation_id;
|
|
96
106
|
}
|
|
@@ -137,8 +147,9 @@ class AppServerClient {
|
|
|
137
147
|
throw new Error("No WebSocket implementation available");
|
|
138
148
|
}
|
|
139
149
|
this.requestTimeoutMs = options.requestTimeoutMs ?? DEFAULT_REQUEST_TIMEOUT_MS;
|
|
140
|
-
|
|
141
|
-
this.
|
|
150
|
+
const socketOptions = appServerSocketOptions(options.authToken);
|
|
151
|
+
this.control = new WebSocket(resolveAppServerChannelUrl(options.url, "control"), socketOptions);
|
|
152
|
+
this.stream = new WebSocket(resolveAppServerChannelUrl(options.url, "stream"), socketOptions);
|
|
142
153
|
attachSocketListener(this.control, "message", (event) => {
|
|
143
154
|
this.handleMessage(event, "control");
|
|
144
155
|
});
|
|
@@ -397,4 +408,4 @@ export {
|
|
|
397
408
|
AppServerClient
|
|
398
409
|
};
|
|
399
410
|
|
|
400
|
-
//# debugId=
|
|
411
|
+
//# debugId=5B36C9DEF3E6B55264756E2164756E21
|
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src/app-server-client.ts"],
|
|
4
4
|
"sourcesContent": [
|
|
5
|
-
"import type {\n AbortMessageCommand,\n AbortMessageResponseMessage,\n ExternalToolCallRequestMessage,\n ExternalToolCallResult,\n InputCommand,\n LoopStatusUpdateMessage,\n RuntimeScope,\n RuntimeStartCommand,\n RuntimeStartResponseMessage,\n StreamDeltaMessage,\n SyncCommand,\n SyncResponseMessage,\n WsProtocolCommand,\n WsProtocolMessage,\n} from \"./types/app-server-protocol\";\n\nexport type AppServerChannel = \"control\" | \"stream\";\n\n/**\n * Receives every parsed protocol frame from both app-server websocket channels.\n * Treat this as the primary event stream: app-server may emit replay or turn\n * updates on the same channel that sent the triggering command, not only on the\n * stream channel. The channel argument is diagnostic/routing context.\n */\nexport type AppServerMessageHandler = (\n message: WsProtocolMessage,\n channel: AppServerChannel,\n) => void;\n\n/** Called synchronously before a protocol command is written to the control socket. */\nexport type AppServerSendHandler = (command: WsProtocolCommand) => void;\n\nexport type AppServerExternalToolCallHandler = (\n request: ExternalToolCallRequestMessage,\n) => Promise<ExternalToolCallResult> | ExternalToolCallResult;\n\nexport interface AppServerSocketLike {\n readyState: number;\n send(data: string): void;\n close(): void;\n addEventListener?(type: string, listener: (event: unknown) => void): void;\n removeEventListener?(type: string, listener: (event: unknown) => void): void;\n on?(type: string, listener: (event: unknown) => void): void;\n off?(type: string, listener: (event: unknown) => void): void;\n once?(type: string, listener: (event: unknown) => void): void;\n}\n\nexport type AppServerSocketConstructor = new (\n url: string,\n) => AppServerSocketLike;\n\nexport interface AppServerClientOptions {\n /** Base app-server URL, e.g. ws://127.0.0.1:4500 or http://127.0.0.1:4500. */\n url: string;\n /** Optional WebSocket constructor for Node/tests. Browsers use globalThis.WebSocket. */\n WebSocket?: AppServerSocketConstructor;\n /** Default timeout for request_id-correlated control requests. */\n requestTimeoutMs?: number;\n}\n\nexport interface AppServerRequestOptions<TMessage extends WsProtocolMessage> {\n timeoutMs?: number;\n predicate?: (message: WsProtocolMessage) => message is TMessage;\n}\n\nexport type AppServerRequestCommand = Extract<\n WsProtocolCommand,\n { request_id?: string }\n>;\n\nexport type AppServerRequestCommandWithId = AppServerRequestCommand & {\n request_id: string;\n};\n\nexport type AppServerRequestBody = Record<string, unknown> & {\n request_id?: string;\n};\n\ntype PendingRequest = {\n resolve: (message: WsProtocolMessage) => void;\n reject: (error: Error) => void;\n predicate?: (message: WsProtocolMessage) => boolean;\n timeout: ReturnType<typeof setTimeout>;\n};\n\nexport type AppServerTurnCompletionSource =\n | \"stop_reason\"\n | \"loop_status_waiting_on_approval\"\n | \"loop_status_waiting_fallback\";\n\nexport interface AppServerTurnResult {\n runtime: RuntimeScope;\n stopReason: string | null;\n runIds: string[];\n clientMessageIds: string[];\n completedBy: AppServerTurnCompletionSource;\n terminalMessage: WsProtocolMessage;\n}\n\nexport interface AppServerRunTurnOptions {\n timeoutMs?: number;\n /**\n * Prefer explicit stream terminal events. This fallback is only used after\n * the client has seen stream/run evidence for this runtime, never from idle\n * loop status alone.\n */\n allowLoopStatusFallback?: boolean;\n}\n\nconst DEFAULT_REQUEST_TIMEOUT_MS = 30_000;\nconst WEBSOCKET_OPEN_STATE = 1;\n\nfunction getGlobalWebSocket(): AppServerSocketConstructor | undefined {\n return (globalThis as { WebSocket?: AppServerSocketConstructor }).WebSocket;\n}\n\nfunction normalizeBaseUrl(url: string): URL {\n const parsed = new URL(url);\n if (parsed.protocol === \"http:\") parsed.protocol = \"ws:\";\n if (parsed.protocol === \"https:\") parsed.protocol = \"wss:\";\n if (parsed.protocol !== \"ws:\" && parsed.protocol !== \"wss:\") {\n throw new Error(`Unsupported app-server URL protocol: ${parsed.protocol}`);\n }\n if (!parsed.pathname || parsed.pathname === \"/\") {\n parsed.pathname = \"/ws\";\n }\n return parsed;\n}\n\nexport function resolveAppServerChannelUrl(\n url: string,\n channel: AppServerChannel,\n): string {\n const parsed = normalizeBaseUrl(url);\n parsed.searchParams.set(\"channel\", channel);\n return parsed.toString();\n}\n\nfunction attachSocketListener(\n socket: AppServerSocketLike,\n type: string,\n listener: (event: unknown) => void,\n): () => void {\n if (socket.addEventListener && socket.removeEventListener) {\n socket.addEventListener(type, listener);\n return () => socket.removeEventListener?.(type, listener);\n }\n\n if (socket.on) {\n socket.on(type, listener);\n return () => socket.off?.(type, listener);\n }\n\n throw new Error(\"WebSocket implementation does not support event listeners\");\n}\n\nfunction onceSocketEvent(\n socket: AppServerSocketLike,\n type: string,\n listener: (event: unknown) => void,\n): () => void {\n if (socket.once) {\n socket.once(type, listener);\n return () => socket.off?.(type, listener);\n }\n\n let detach = () => {};\n detach = attachSocketListener(socket, type, (event) => {\n detach();\n listener(event);\n });\n return detach;\n}\n\nfunction waitForSocketOpen(socket: AppServerSocketLike): Promise<void> {\n if (socket.readyState === WEBSOCKET_OPEN_STATE) {\n return Promise.resolve();\n }\n\n return new Promise((resolve, reject) => {\n let detachOpen = () => {};\n let detachError = () => {};\n const cleanup = () => {\n detachOpen();\n detachError();\n };\n detachOpen = onceSocketEvent(socket, \"open\", () => {\n cleanup();\n resolve();\n });\n detachError = onceSocketEvent(socket, \"error\", (event) => {\n cleanup();\n reject(\n new Error(`App-server WebSocket failed to open: ${String(event)}`),\n );\n });\n });\n}\n\nfunction rawEventData(event: unknown): unknown {\n if (event && typeof event === \"object\" && \"data\" in event) {\n return (event as { data: unknown }).data;\n }\n return event;\n}\n\nfunction messageDataToString(data: unknown): string {\n const raw = rawEventData(data);\n if (typeof raw === \"string\") return raw;\n if (raw instanceof ArrayBuffer) {\n return new TextDecoder().decode(raw);\n }\n if (raw instanceof Uint8Array) {\n return new TextDecoder().decode(raw);\n }\n if (ArrayBuffer.isView(raw)) {\n return new TextDecoder().decode(\n new Uint8Array(raw.buffer as ArrayBuffer, raw.byteOffset, raw.byteLength),\n );\n }\n return String(raw);\n}\n\nfunction parseProtocolMessage(event: unknown): WsProtocolMessage {\n return JSON.parse(messageDataToString(event)) as WsProtocolMessage;\n}\n\nfunction sameRuntime(a: RuntimeScope | undefined, b: RuntimeScope): boolean {\n return a?.agent_id === b.agent_id && a?.conversation_id === b.conversation_id;\n}\n\nfunction isWaitingLoopStatus(message: LoopStatusUpdateMessage): boolean {\n return message.loop_status.status === \"WAITING_ON_INPUT\";\n}\n\nfunction isWaitingOnApprovalLoopStatus(\n message: LoopStatusUpdateMessage,\n): boolean {\n return message.loop_status.status === \"WAITING_ON_APPROVAL\";\n}\n\nfunction streamDeltaRunId(message: StreamDeltaMessage): string | null {\n const runId = (message.delta as { run_id?: unknown }).run_id;\n return typeof runId === \"string\" ? runId : null;\n}\n\nfunction streamDeltaMessageType(message: StreamDeltaMessage): string | null {\n const messageType = (message.delta as { message_type?: unknown })\n .message_type;\n return typeof messageType === \"string\" ? messageType : null;\n}\n\nfunction streamDeltaStopReason(message: StreamDeltaMessage): string | null {\n const stopReason = (message.delta as { stop_reason?: unknown }).stop_reason;\n return typeof stopReason === \"string\" ? stopReason : null;\n}\n\nfunction streamDeltaErrorMessage(message: StreamDeltaMessage): string {\n const delta = message.delta as {\n message?: unknown;\n api_error?: { message?: unknown; detail?: unknown };\n };\n const apiMessage = delta.api_error?.message ?? delta.api_error?.detail;\n if (typeof apiMessage === \"string\" && apiMessage.length > 0)\n return apiMessage;\n if (typeof delta.message === \"string\" && delta.message.length > 0)\n return delta.message;\n return \"App-server turn failed\";\n}\n\nexport class AppServerClient {\n readonly control: AppServerSocketLike;\n readonly stream: AppServerSocketLike;\n\n private readonly requestTimeoutMs: number;\n private readonly pending = new Map<string, PendingRequest>();\n private readonly messageHandlers = new Set<AppServerMessageHandler>();\n private readonly sendHandlers = new Set<AppServerSendHandler>();\n private readonly activeTurnRuntimes = new Set<string>();\n private nextRequestNumber = 0;\n\n constructor(options: AppServerClientOptions) {\n const WebSocket = options.WebSocket ?? getGlobalWebSocket();\n if (!WebSocket) {\n throw new Error(\"No WebSocket implementation available\");\n }\n\n this.requestTimeoutMs =\n options.requestTimeoutMs ?? DEFAULT_REQUEST_TIMEOUT_MS;\n this.control = new WebSocket(\n resolveAppServerChannelUrl(options.url, \"control\"),\n );\n this.stream = new WebSocket(\n resolveAppServerChannelUrl(options.url, \"stream\"),\n );\n\n attachSocketListener(this.control, \"message\", (event) => {\n this.handleMessage(event, \"control\");\n });\n attachSocketListener(this.stream, \"message\", (event) => {\n this.handleMessage(event, \"stream\");\n });\n const rejectPending = () =>\n this.rejectAllPending(\"App-server socket closed\");\n attachSocketListener(this.control, \"close\", rejectPending);\n attachSocketListener(this.stream, \"close\", rejectPending);\n }\n\n async connect(): Promise<this> {\n await Promise.all([\n waitForSocketOpen(this.control),\n waitForSocketOpen(this.stream),\n ]);\n return this;\n }\n\n close(): void {\n this.rejectAllPending(\"App-server client closed\");\n this.control.close();\n this.stream.close();\n }\n\n onMessage(handler: AppServerMessageHandler): () => void {\n this.messageHandlers.add(handler);\n return () => this.messageHandlers.delete(handler);\n }\n\n onSend(handler: AppServerSendHandler): () => void {\n this.sendHandlers.add(handler);\n return () => this.sendHandlers.delete(handler);\n }\n\n nextRequestId(prefix = \"req\"): string {\n this.nextRequestNumber += 1;\n return `${prefix}-${this.nextRequestNumber}`;\n }\n\n send(command: WsProtocolCommand): void {\n for (const handler of this.sendHandlers) {\n handler(command);\n }\n this.control.send(JSON.stringify(command));\n }\n\n request<TMessage extends WsProtocolMessage = WsProtocolMessage>(\n command: AppServerRequestCommandWithId,\n options?: AppServerRequestOptions<TMessage>,\n ): Promise<TMessage>;\n\n request<\n TType extends AppServerRequestCommand[\"type\"],\n TMessage extends WsProtocolMessage = WsProtocolMessage,\n >(\n type: TType,\n body?: AppServerRequestBody,\n options?: AppServerRequestOptions<TMessage>,\n ): Promise<TMessage>;\n\n request<TMessage extends WsProtocolMessage = WsProtocolMessage>(\n commandOrType:\n | AppServerRequestCommandWithId\n | AppServerRequestCommand[\"type\"],\n bodyOrOptions:\n | AppServerRequestBody\n | AppServerRequestOptions<TMessage> = {},\n maybeOptions: AppServerRequestOptions<TMessage> = {},\n ): Promise<TMessage> {\n const isTypeRequest = typeof commandOrType === \"string\";\n const command = isTypeRequest\n ? ({\n type: commandOrType,\n request_id:\n (bodyOrOptions as { request_id?: string }).request_id ??\n this.nextRequestId(commandOrType),\n ...(bodyOrOptions as object),\n } as AppServerRequestCommandWithId)\n : commandOrType;\n const options = isTypeRequest\n ? maybeOptions\n : (bodyOrOptions as AppServerRequestOptions<TMessage>);\n const timeoutMs = options.timeoutMs ?? this.requestTimeoutMs;\n\n return new Promise((resolve, reject) => {\n const timeout = setTimeout(() => {\n this.pending.delete(command.request_id);\n reject(new Error(`Timed out waiting for ${command.request_id}`));\n }, timeoutMs);\n\n this.pending.set(command.request_id, {\n resolve: (message) => resolve(message as TMessage),\n reject,\n predicate: options.predicate,\n timeout,\n });\n\n try {\n this.send(command);\n } catch (error) {\n clearTimeout(timeout);\n this.pending.delete(command.request_id);\n reject(error instanceof Error ? error : new Error(String(error)));\n }\n });\n }\n\n runtimeStart(\n command: Omit<RuntimeStartCommand, \"type\" | \"request_id\"> & {\n request_id?: string;\n },\n options: Omit<\n AppServerRequestOptions<RuntimeStartResponseMessage>,\n \"predicate\"\n > = {},\n ): Promise<RuntimeStartResponseMessage> {\n return this.request(\n {\n type: \"runtime_start\",\n request_id: command.request_id ?? this.nextRequestId(\"runtime-start\"),\n ...command,\n },\n {\n ...options,\n predicate: (message): message is RuntimeStartResponseMessage =>\n message.type === \"runtime_start_response\",\n },\n );\n }\n\n sync(\n command: Omit<SyncCommand, \"type\" | \"request_id\"> & { request_id?: string },\n options: Omit<\n AppServerRequestOptions<SyncResponseMessage>,\n \"predicate\"\n > = {},\n ): Promise<SyncResponseMessage> {\n return this.request(\n {\n type: \"sync\",\n request_id: command.request_id ?? this.nextRequestId(\"sync\"),\n ...command,\n },\n {\n ...options,\n predicate: (message): message is SyncResponseMessage =>\n message.type === \"sync_response\",\n },\n );\n }\n\n abort(\n command: Omit<AbortMessageCommand, \"type\" | \"request_id\"> & {\n request_id?: string;\n },\n options: Omit<\n AppServerRequestOptions<AbortMessageResponseMessage>,\n \"predicate\"\n > = {},\n ): Promise<AbortMessageResponseMessage> {\n return this.request(\n {\n type: \"abort_message\",\n request_id: command.request_id ?? this.nextRequestId(\"abort\"),\n ...command,\n },\n {\n ...options,\n predicate: (message): message is AbortMessageResponseMessage =>\n message.type === \"abort_message_response\",\n },\n );\n }\n\n onExternalToolCall(handler: AppServerExternalToolCallHandler): () => void {\n return this.onMessage((message, channel) => {\n if (\n channel !== \"control\" ||\n message.type !== \"external_tool_call_request\"\n ) {\n return;\n }\n\n void Promise.resolve(handler(message))\n .then((result) => {\n this.send({\n type: \"external_tool_call_response\",\n request_id: message.request_id,\n result,\n });\n })\n .catch((error) => {\n this.send({\n type: \"external_tool_call_response\",\n request_id: message.request_id,\n error: error instanceof Error ? error.message : String(error),\n });\n });\n });\n }\n\n input(command: Omit<InputCommand, \"type\">): void {\n this.send({ type: \"input\", ...command });\n }\n\n runTurn(\n command: Omit<InputCommand, \"type\">,\n options: AppServerRunTurnOptions = {},\n ): Promise<AppServerTurnResult> {\n const runtimeKey = `${command.runtime.agent_id}/${command.runtime.conversation_id}`;\n if (this.activeTurnRuntimes.has(runtimeKey)) {\n return Promise.reject(\n new Error(`A turn is already in flight for ${runtimeKey}`),\n );\n }\n this.activeTurnRuntimes.add(runtimeKey);\n const timeoutMs = options.timeoutMs ?? this.requestTimeoutMs;\n const commandWithIds = this.withClientMessageIds(command);\n const runIds = new Set<string>();\n let observedTurnEvidence = false;\n let observedRequiresApprovalStop = false;\n\n return new Promise((resolve, reject) => {\n const timeout = setTimeout(() => {\n cleanup();\n reject(\n new Error(\n `Timed out waiting for app-server turn on ${command.runtime.agent_id}/${command.runtime.conversation_id}`,\n ),\n );\n }, timeoutMs);\n\n const cleanup = () => {\n clearTimeout(timeout);\n this.activeTurnRuntimes.delete(runtimeKey);\n offMessage();\n };\n\n const finish = (\n completedBy: AppServerTurnCompletionSource,\n terminalMessage: WsProtocolMessage,\n stopReason: string | null,\n ) => {\n cleanup();\n resolve({\n runtime: command.runtime,\n stopReason,\n runIds: [...runIds],\n clientMessageIds: commandWithIds.clientMessageIds,\n completedBy,\n terminalMessage,\n });\n };\n\n const fail = (error: Error) => {\n cleanup();\n reject(error);\n };\n\n const offMessage = this.onMessage((message) => {\n if (\n !sameRuntime(\n (message as { runtime?: RuntimeScope }).runtime,\n command.runtime,\n )\n ) {\n return;\n }\n\n if (message.type === \"stream_delta\") {\n observedTurnEvidence = true;\n const runId = streamDeltaRunId(message);\n if (runId) runIds.add(runId);\n\n const messageType = streamDeltaMessageType(message);\n if (messageType === \"loop_error\" || messageType === \"error_message\") {\n fail(new Error(streamDeltaErrorMessage(message)));\n return;\n }\n if (messageType === \"stop_reason\") {\n const stopReason = streamDeltaStopReason(message);\n if (stopReason === \"requires_approval\") {\n observedRequiresApprovalStop = true;\n return;\n }\n finish(\"stop_reason\", message, stopReason);\n }\n return;\n }\n\n if (message.type === \"update_loop_status\") {\n for (const runId of message.loop_status.active_run_ids) {\n observedTurnEvidence = true;\n runIds.add(runId);\n }\n if (\n (observedTurnEvidence || observedRequiresApprovalStop) &&\n isWaitingOnApprovalLoopStatus(message)\n ) {\n finish(\n \"loop_status_waiting_on_approval\",\n message,\n \"requires_approval\",\n );\n return;\n }\n if (\n options.allowLoopStatusFallback === true &&\n observedTurnEvidence &&\n isWaitingLoopStatus(message)\n ) {\n finish(\"loop_status_waiting_fallback\", message, null);\n }\n }\n });\n\n try {\n this.input(commandWithIds.command);\n } catch (error) {\n fail(error instanceof Error ? error : new Error(String(error)));\n }\n });\n }\n\n private withClientMessageIds(command: Omit<InputCommand, \"type\">): {\n command: Omit<InputCommand, \"type\">;\n clientMessageIds: string[];\n } {\n if (command.payload.kind !== \"create_message\") {\n return { command, clientMessageIds: [] };\n }\n\n const clientMessageIds: string[] = [];\n const messages = command.payload.messages.map((message) => {\n if (message.role !== \"user\") return message;\n const existing = (message as { client_message_id?: unknown })\n .client_message_id;\n const clientMessageId =\n typeof existing === \"string\" && existing.length > 0\n ? existing\n : this.nextRequestId(\"client-message\");\n clientMessageIds.push(clientMessageId);\n return { ...message, client_message_id: clientMessageId };\n });\n\n return {\n command: {\n ...command,\n payload: { ...command.payload, messages },\n },\n clientMessageIds,\n };\n }\n\n private handleMessage(event: unknown, channel: AppServerChannel): void {\n const message = parseProtocolMessage(event);\n\n for (const handler of this.messageHandlers) {\n handler(message, channel);\n }\n\n const requestId =\n message && typeof message === \"object\" && \"request_id\" in message\n ? (message as { request_id?: unknown }).request_id\n : undefined;\n if (channel !== \"control\" || typeof requestId !== \"string\") {\n return;\n }\n\n const pending = this.pending.get(requestId);\n if (!pending || (pending.predicate && !pending.predicate(message))) {\n return;\n }\n\n clearTimeout(pending.timeout);\n this.pending.delete(requestId);\n pending.resolve(message);\n }\n\n private rejectAllPending(reason: string): void {\n for (const [requestId, pending] of this.pending) {\n clearTimeout(pending.timeout);\n this.pending.delete(requestId);\n pending.reject(new Error(reason));\n }\n }\n}\n\nexport function createAppServerClient(\n options: AppServerClientOptions,\n): AppServerClient {\n return new AppServerClient(options);\n}\n"
|
|
5
|
+
"import type {\n AbortMessageCommand,\n AbortMessageResponseMessage,\n ExternalToolCallRequestMessage,\n ExternalToolCallResult,\n InputCommand,\n LoopStatusUpdateMessage,\n RuntimeScope,\n RuntimeStartCommand,\n RuntimeStartResponseMessage,\n StreamDeltaMessage,\n SyncCommand,\n SyncResponseMessage,\n WsProtocolCommand,\n WsProtocolMessage,\n} from \"./types/app-server-protocol\";\n\nexport type AppServerChannel = \"control\" | \"stream\";\n\n/**\n * Receives every parsed protocol frame from both app-server websocket channels.\n * Treat this as the primary event stream: app-server may emit replay or turn\n * updates on the same channel that sent the triggering command, not only on the\n * stream channel. The channel argument is diagnostic/routing context.\n */\nexport type AppServerMessageHandler = (\n message: WsProtocolMessage,\n channel: AppServerChannel,\n) => void;\n\n/** Called synchronously before a protocol command is written to the control socket. */\nexport type AppServerSendHandler = (command: WsProtocolCommand) => void;\n\nexport type AppServerExternalToolCallHandler = (\n request: ExternalToolCallRequestMessage,\n) => Promise<ExternalToolCallResult> | ExternalToolCallResult;\n\nexport interface AppServerSocketLike {\n readyState: number;\n send(data: string): void;\n close(): void;\n addEventListener?(type: string, listener: (event: unknown) => void): void;\n removeEventListener?(type: string, listener: (event: unknown) => void): void;\n on?(type: string, listener: (event: unknown) => void): void;\n off?(type: string, listener: (event: unknown) => void): void;\n once?(type: string, listener: (event: unknown) => void): void;\n}\n\nexport interface AppServerSocketOptions {\n headers?: Record<string, string>;\n}\n\nexport type AppServerSocketConstructor = new (\n url: string,\n options?: AppServerSocketOptions,\n) => AppServerSocketLike;\n\nexport interface AppServerClientOptions {\n /** Base app-server URL, e.g. ws://127.0.0.1:4500 or http://127.0.0.1:4500. */\n url: string;\n /** Optional capability token sent as Authorization: Bearer <token>; requires a WebSocket implementation with header support. */\n authToken?: string;\n /** Optional WebSocket constructor for Node/tests. Browsers use globalThis.WebSocket. */\n WebSocket?: AppServerSocketConstructor;\n /** Default timeout for request_id-correlated control requests. */\n requestTimeoutMs?: number;\n}\n\nexport interface AppServerRequestOptions<TMessage extends WsProtocolMessage> {\n timeoutMs?: number;\n predicate?: (message: WsProtocolMessage) => message is TMessage;\n}\n\nexport type AppServerRequestCommand = Extract<\n WsProtocolCommand,\n { request_id?: string }\n>;\n\nexport type AppServerRequestCommandWithId = AppServerRequestCommand & {\n request_id: string;\n};\n\nexport type AppServerRequestBody = Record<string, unknown> & {\n request_id?: string;\n};\n\ntype PendingRequest = {\n resolve: (message: WsProtocolMessage) => void;\n reject: (error: Error) => void;\n predicate?: (message: WsProtocolMessage) => boolean;\n timeout: ReturnType<typeof setTimeout>;\n};\n\nexport type AppServerTurnCompletionSource =\n | \"stop_reason\"\n | \"loop_status_waiting_on_approval\"\n | \"loop_status_waiting_fallback\";\n\nexport interface AppServerTurnResult {\n runtime: RuntimeScope;\n stopReason: string | null;\n runIds: string[];\n clientMessageIds: string[];\n completedBy: AppServerTurnCompletionSource;\n terminalMessage: WsProtocolMessage;\n}\n\nexport interface AppServerRunTurnOptions {\n timeoutMs?: number;\n /**\n * Prefer explicit stream terminal events. This fallback is only used after\n * the client has seen stream/run evidence for this runtime, never from idle\n * loop status alone.\n */\n allowLoopStatusFallback?: boolean;\n}\n\nconst DEFAULT_REQUEST_TIMEOUT_MS = 30_000;\nconst WEBSOCKET_OPEN_STATE = 1;\n\nfunction getGlobalWebSocket(): AppServerSocketConstructor | undefined {\n return (globalThis as { WebSocket?: AppServerSocketConstructor }).WebSocket;\n}\n\nfunction normalizeBaseUrl(url: string): URL {\n const parsed = new URL(url);\n if (parsed.protocol === \"http:\") parsed.protocol = \"ws:\";\n if (parsed.protocol === \"https:\") parsed.protocol = \"wss:\";\n if (parsed.protocol !== \"ws:\" && parsed.protocol !== \"wss:\") {\n throw new Error(`Unsupported app-server URL protocol: ${parsed.protocol}`);\n }\n if (!parsed.pathname || parsed.pathname === \"/\") {\n parsed.pathname = \"/ws\";\n }\n return parsed;\n}\n\nexport function resolveAppServerChannelUrl(\n url: string,\n channel: AppServerChannel,\n): string {\n const parsed = normalizeBaseUrl(url);\n parsed.searchParams.set(\"channel\", channel);\n return parsed.toString();\n}\n\nfunction attachSocketListener(\n socket: AppServerSocketLike,\n type: string,\n listener: (event: unknown) => void,\n): () => void {\n if (socket.addEventListener && socket.removeEventListener) {\n socket.addEventListener(type, listener);\n return () => socket.removeEventListener?.(type, listener);\n }\n\n if (socket.on) {\n socket.on(type, listener);\n return () => socket.off?.(type, listener);\n }\n\n throw new Error(\"WebSocket implementation does not support event listeners\");\n}\n\nfunction onceSocketEvent(\n socket: AppServerSocketLike,\n type: string,\n listener: (event: unknown) => void,\n): () => void {\n if (socket.once) {\n socket.once(type, listener);\n return () => socket.off?.(type, listener);\n }\n\n let detach = () => {};\n detach = attachSocketListener(socket, type, (event) => {\n detach();\n listener(event);\n });\n return detach;\n}\n\nfunction waitForSocketOpen(socket: AppServerSocketLike): Promise<void> {\n if (socket.readyState === WEBSOCKET_OPEN_STATE) {\n return Promise.resolve();\n }\n\n return new Promise((resolve, reject) => {\n let detachOpen = () => {};\n let detachError = () => {};\n const cleanup = () => {\n detachOpen();\n detachError();\n };\n detachOpen = onceSocketEvent(socket, \"open\", () => {\n cleanup();\n resolve();\n });\n detachError = onceSocketEvent(socket, \"error\", (event) => {\n cleanup();\n reject(\n new Error(`App-server WebSocket failed to open: ${String(event)}`),\n );\n });\n });\n}\n\nfunction rawEventData(event: unknown): unknown {\n if (event && typeof event === \"object\" && \"data\" in event) {\n return (event as { data: unknown }).data;\n }\n return event;\n}\n\nfunction messageDataToString(data: unknown): string {\n const raw = rawEventData(data);\n if (typeof raw === \"string\") return raw;\n if (raw instanceof ArrayBuffer) {\n return new TextDecoder().decode(raw);\n }\n if (raw instanceof Uint8Array) {\n return new TextDecoder().decode(raw);\n }\n if (ArrayBuffer.isView(raw)) {\n return new TextDecoder().decode(\n new Uint8Array(raw.buffer as ArrayBuffer, raw.byteOffset, raw.byteLength),\n );\n }\n return String(raw);\n}\n\nfunction parseProtocolMessage(event: unknown): WsProtocolMessage {\n return JSON.parse(messageDataToString(event)) as WsProtocolMessage;\n}\n\nfunction appServerSocketOptions(\n authToken: string | undefined,\n): AppServerSocketOptions | undefined {\n if (authToken === undefined) {\n return undefined;\n }\n const token = authToken.trim();\n if (!token) {\n throw new Error(\"app-server auth token must not be empty\");\n }\n return { headers: { Authorization: `Bearer ${token}` } };\n}\n\nfunction sameRuntime(a: RuntimeScope | undefined, b: RuntimeScope): boolean {\n return a?.agent_id === b.agent_id && a?.conversation_id === b.conversation_id;\n}\n\nfunction isWaitingLoopStatus(message: LoopStatusUpdateMessage): boolean {\n return message.loop_status.status === \"WAITING_ON_INPUT\";\n}\n\nfunction isWaitingOnApprovalLoopStatus(\n message: LoopStatusUpdateMessage,\n): boolean {\n return message.loop_status.status === \"WAITING_ON_APPROVAL\";\n}\n\nfunction streamDeltaRunId(message: StreamDeltaMessage): string | null {\n const runId = (message.delta as { run_id?: unknown }).run_id;\n return typeof runId === \"string\" ? runId : null;\n}\n\nfunction streamDeltaMessageType(message: StreamDeltaMessage): string | null {\n const messageType = (message.delta as { message_type?: unknown })\n .message_type;\n return typeof messageType === \"string\" ? messageType : null;\n}\n\nfunction streamDeltaStopReason(message: StreamDeltaMessage): string | null {\n const stopReason = (message.delta as { stop_reason?: unknown }).stop_reason;\n return typeof stopReason === \"string\" ? stopReason : null;\n}\n\nfunction streamDeltaErrorMessage(message: StreamDeltaMessage): string {\n const delta = message.delta as {\n message?: unknown;\n api_error?: { message?: unknown; detail?: unknown };\n };\n const apiMessage = delta.api_error?.message ?? delta.api_error?.detail;\n if (typeof apiMessage === \"string\" && apiMessage.length > 0)\n return apiMessage;\n if (typeof delta.message === \"string\" && delta.message.length > 0)\n return delta.message;\n return \"App-server turn failed\";\n}\n\nexport class AppServerClient {\n readonly control: AppServerSocketLike;\n readonly stream: AppServerSocketLike;\n\n private readonly requestTimeoutMs: number;\n private readonly pending = new Map<string, PendingRequest>();\n private readonly messageHandlers = new Set<AppServerMessageHandler>();\n private readonly sendHandlers = new Set<AppServerSendHandler>();\n private readonly activeTurnRuntimes = new Set<string>();\n private nextRequestNumber = 0;\n\n constructor(options: AppServerClientOptions) {\n const WebSocket = options.WebSocket ?? getGlobalWebSocket();\n if (!WebSocket) {\n throw new Error(\"No WebSocket implementation available\");\n }\n\n this.requestTimeoutMs =\n options.requestTimeoutMs ?? DEFAULT_REQUEST_TIMEOUT_MS;\n const socketOptions = appServerSocketOptions(options.authToken);\n this.control = new WebSocket(\n resolveAppServerChannelUrl(options.url, \"control\"),\n socketOptions,\n );\n this.stream = new WebSocket(\n resolveAppServerChannelUrl(options.url, \"stream\"),\n socketOptions,\n );\n\n attachSocketListener(this.control, \"message\", (event) => {\n this.handleMessage(event, \"control\");\n });\n attachSocketListener(this.stream, \"message\", (event) => {\n this.handleMessage(event, \"stream\");\n });\n const rejectPending = () =>\n this.rejectAllPending(\"App-server socket closed\");\n attachSocketListener(this.control, \"close\", rejectPending);\n attachSocketListener(this.stream, \"close\", rejectPending);\n }\n\n async connect(): Promise<this> {\n await Promise.all([\n waitForSocketOpen(this.control),\n waitForSocketOpen(this.stream),\n ]);\n return this;\n }\n\n close(): void {\n this.rejectAllPending(\"App-server client closed\");\n this.control.close();\n this.stream.close();\n }\n\n onMessage(handler: AppServerMessageHandler): () => void {\n this.messageHandlers.add(handler);\n return () => this.messageHandlers.delete(handler);\n }\n\n onSend(handler: AppServerSendHandler): () => void {\n this.sendHandlers.add(handler);\n return () => this.sendHandlers.delete(handler);\n }\n\n nextRequestId(prefix = \"req\"): string {\n this.nextRequestNumber += 1;\n return `${prefix}-${this.nextRequestNumber}`;\n }\n\n send(command: WsProtocolCommand): void {\n for (const handler of this.sendHandlers) {\n handler(command);\n }\n this.control.send(JSON.stringify(command));\n }\n\n request<TMessage extends WsProtocolMessage = WsProtocolMessage>(\n command: AppServerRequestCommandWithId,\n options?: AppServerRequestOptions<TMessage>,\n ): Promise<TMessage>;\n\n request<\n TType extends AppServerRequestCommand[\"type\"],\n TMessage extends WsProtocolMessage = WsProtocolMessage,\n >(\n type: TType,\n body?: AppServerRequestBody,\n options?: AppServerRequestOptions<TMessage>,\n ): Promise<TMessage>;\n\n request<TMessage extends WsProtocolMessage = WsProtocolMessage>(\n commandOrType:\n | AppServerRequestCommandWithId\n | AppServerRequestCommand[\"type\"],\n bodyOrOptions:\n | AppServerRequestBody\n | AppServerRequestOptions<TMessage> = {},\n maybeOptions: AppServerRequestOptions<TMessage> = {},\n ): Promise<TMessage> {\n const isTypeRequest = typeof commandOrType === \"string\";\n const command = isTypeRequest\n ? ({\n type: commandOrType,\n request_id:\n (bodyOrOptions as { request_id?: string }).request_id ??\n this.nextRequestId(commandOrType),\n ...(bodyOrOptions as object),\n } as AppServerRequestCommandWithId)\n : commandOrType;\n const options = isTypeRequest\n ? maybeOptions\n : (bodyOrOptions as AppServerRequestOptions<TMessage>);\n const timeoutMs = options.timeoutMs ?? this.requestTimeoutMs;\n\n return new Promise((resolve, reject) => {\n const timeout = setTimeout(() => {\n this.pending.delete(command.request_id);\n reject(new Error(`Timed out waiting for ${command.request_id}`));\n }, timeoutMs);\n\n this.pending.set(command.request_id, {\n resolve: (message) => resolve(message as TMessage),\n reject,\n predicate: options.predicate,\n timeout,\n });\n\n try {\n this.send(command);\n } catch (error) {\n clearTimeout(timeout);\n this.pending.delete(command.request_id);\n reject(error instanceof Error ? error : new Error(String(error)));\n }\n });\n }\n\n runtimeStart(\n command: Omit<RuntimeStartCommand, \"type\" | \"request_id\"> & {\n request_id?: string;\n },\n options: Omit<\n AppServerRequestOptions<RuntimeStartResponseMessage>,\n \"predicate\"\n > = {},\n ): Promise<RuntimeStartResponseMessage> {\n return this.request(\n {\n type: \"runtime_start\",\n request_id: command.request_id ?? this.nextRequestId(\"runtime-start\"),\n ...command,\n },\n {\n ...options,\n predicate: (message): message is RuntimeStartResponseMessage =>\n message.type === \"runtime_start_response\",\n },\n );\n }\n\n sync(\n command: Omit<SyncCommand, \"type\" | \"request_id\"> & { request_id?: string },\n options: Omit<\n AppServerRequestOptions<SyncResponseMessage>,\n \"predicate\"\n > = {},\n ): Promise<SyncResponseMessage> {\n return this.request(\n {\n type: \"sync\",\n request_id: command.request_id ?? this.nextRequestId(\"sync\"),\n ...command,\n },\n {\n ...options,\n predicate: (message): message is SyncResponseMessage =>\n message.type === \"sync_response\",\n },\n );\n }\n\n abort(\n command: Omit<AbortMessageCommand, \"type\" | \"request_id\"> & {\n request_id?: string;\n },\n options: Omit<\n AppServerRequestOptions<AbortMessageResponseMessage>,\n \"predicate\"\n > = {},\n ): Promise<AbortMessageResponseMessage> {\n return this.request(\n {\n type: \"abort_message\",\n request_id: command.request_id ?? this.nextRequestId(\"abort\"),\n ...command,\n },\n {\n ...options,\n predicate: (message): message is AbortMessageResponseMessage =>\n message.type === \"abort_message_response\",\n },\n );\n }\n\n onExternalToolCall(handler: AppServerExternalToolCallHandler): () => void {\n return this.onMessage((message, channel) => {\n if (\n channel !== \"control\" ||\n message.type !== \"external_tool_call_request\"\n ) {\n return;\n }\n\n void Promise.resolve(handler(message))\n .then((result) => {\n this.send({\n type: \"external_tool_call_response\",\n request_id: message.request_id,\n result,\n });\n })\n .catch((error) => {\n this.send({\n type: \"external_tool_call_response\",\n request_id: message.request_id,\n error: error instanceof Error ? error.message : String(error),\n });\n });\n });\n }\n\n input(command: Omit<InputCommand, \"type\">): void {\n this.send({ type: \"input\", ...command });\n }\n\n runTurn(\n command: Omit<InputCommand, \"type\">,\n options: AppServerRunTurnOptions = {},\n ): Promise<AppServerTurnResult> {\n const runtimeKey = `${command.runtime.agent_id}/${command.runtime.conversation_id}`;\n if (this.activeTurnRuntimes.has(runtimeKey)) {\n return Promise.reject(\n new Error(`A turn is already in flight for ${runtimeKey}`),\n );\n }\n this.activeTurnRuntimes.add(runtimeKey);\n const timeoutMs = options.timeoutMs ?? this.requestTimeoutMs;\n const commandWithIds = this.withClientMessageIds(command);\n const runIds = new Set<string>();\n let observedTurnEvidence = false;\n let observedRequiresApprovalStop = false;\n\n return new Promise((resolve, reject) => {\n const timeout = setTimeout(() => {\n cleanup();\n reject(\n new Error(\n `Timed out waiting for app-server turn on ${command.runtime.agent_id}/${command.runtime.conversation_id}`,\n ),\n );\n }, timeoutMs);\n\n const cleanup = () => {\n clearTimeout(timeout);\n this.activeTurnRuntimes.delete(runtimeKey);\n offMessage();\n };\n\n const finish = (\n completedBy: AppServerTurnCompletionSource,\n terminalMessage: WsProtocolMessage,\n stopReason: string | null,\n ) => {\n cleanup();\n resolve({\n runtime: command.runtime,\n stopReason,\n runIds: [...runIds],\n clientMessageIds: commandWithIds.clientMessageIds,\n completedBy,\n terminalMessage,\n });\n };\n\n const fail = (error: Error) => {\n cleanup();\n reject(error);\n };\n\n const offMessage = this.onMessage((message) => {\n if (\n !sameRuntime(\n (message as { runtime?: RuntimeScope }).runtime,\n command.runtime,\n )\n ) {\n return;\n }\n\n if (message.type === \"stream_delta\") {\n observedTurnEvidence = true;\n const runId = streamDeltaRunId(message);\n if (runId) runIds.add(runId);\n\n const messageType = streamDeltaMessageType(message);\n if (messageType === \"loop_error\" || messageType === \"error_message\") {\n fail(new Error(streamDeltaErrorMessage(message)));\n return;\n }\n if (messageType === \"stop_reason\") {\n const stopReason = streamDeltaStopReason(message);\n if (stopReason === \"requires_approval\") {\n observedRequiresApprovalStop = true;\n return;\n }\n finish(\"stop_reason\", message, stopReason);\n }\n return;\n }\n\n if (message.type === \"update_loop_status\") {\n for (const runId of message.loop_status.active_run_ids) {\n observedTurnEvidence = true;\n runIds.add(runId);\n }\n if (\n (observedTurnEvidence || observedRequiresApprovalStop) &&\n isWaitingOnApprovalLoopStatus(message)\n ) {\n finish(\n \"loop_status_waiting_on_approval\",\n message,\n \"requires_approval\",\n );\n return;\n }\n if (\n options.allowLoopStatusFallback === true &&\n observedTurnEvidence &&\n isWaitingLoopStatus(message)\n ) {\n finish(\"loop_status_waiting_fallback\", message, null);\n }\n }\n });\n\n try {\n this.input(commandWithIds.command);\n } catch (error) {\n fail(error instanceof Error ? error : new Error(String(error)));\n }\n });\n }\n\n private withClientMessageIds(command: Omit<InputCommand, \"type\">): {\n command: Omit<InputCommand, \"type\">;\n clientMessageIds: string[];\n } {\n if (command.payload.kind !== \"create_message\") {\n return { command, clientMessageIds: [] };\n }\n\n const clientMessageIds: string[] = [];\n const messages = command.payload.messages.map((message) => {\n if (message.role !== \"user\") return message;\n const existing = (message as { client_message_id?: unknown })\n .client_message_id;\n const clientMessageId =\n typeof existing === \"string\" && existing.length > 0\n ? existing\n : this.nextRequestId(\"client-message\");\n clientMessageIds.push(clientMessageId);\n return { ...message, client_message_id: clientMessageId };\n });\n\n return {\n command: {\n ...command,\n payload: { ...command.payload, messages },\n },\n clientMessageIds,\n };\n }\n\n private handleMessage(event: unknown, channel: AppServerChannel): void {\n const message = parseProtocolMessage(event);\n\n for (const handler of this.messageHandlers) {\n handler(message, channel);\n }\n\n const requestId =\n message && typeof message === \"object\" && \"request_id\" in message\n ? (message as { request_id?: unknown }).request_id\n : undefined;\n if (channel !== \"control\" || typeof requestId !== \"string\") {\n return;\n }\n\n const pending = this.pending.get(requestId);\n if (!pending || (pending.predicate && !pending.predicate(message))) {\n return;\n }\n\n clearTimeout(pending.timeout);\n this.pending.delete(requestId);\n pending.resolve(message);\n }\n\n private rejectAllPending(reason: string): void {\n for (const [requestId, pending] of this.pending) {\n clearTimeout(pending.timeout);\n this.pending.delete(requestId);\n pending.reject(new Error(reason));\n }\n }\n}\n\nexport function createAppServerClient(\n options: AppServerClientOptions,\n): AppServerClient {\n return new AppServerClient(options);\n}\n"
|
|
6
6
|
],
|
|
7
|
-
"mappings": ";
|
|
8
|
-
"debugId": "
|
|
7
|
+
"mappings": ";AAqHA,IAAM,6BAA6B;AACnC,IAAM,uBAAuB;AAE7B,SAAS,kBAAkB,GAA2C;AAAA,EACpE,OAAQ,WAA0D;AAAA;AAGpE,SAAS,gBAAgB,CAAC,KAAkB;AAAA,EAC1C,MAAM,SAAS,IAAI,IAAI,GAAG;AAAA,EAC1B,IAAI,OAAO,aAAa;AAAA,IAAS,OAAO,WAAW;AAAA,EACnD,IAAI,OAAO,aAAa;AAAA,IAAU,OAAO,WAAW;AAAA,EACpD,IAAI,OAAO,aAAa,SAAS,OAAO,aAAa,QAAQ;AAAA,IAC3D,MAAM,IAAI,MAAM,wCAAwC,OAAO,UAAU;AAAA,EAC3E;AAAA,EACA,IAAI,CAAC,OAAO,YAAY,OAAO,aAAa,KAAK;AAAA,IAC/C,OAAO,WAAW;AAAA,EACpB;AAAA,EACA,OAAO;AAAA;AAGF,SAAS,0BAA0B,CACxC,KACA,SACQ;AAAA,EACR,MAAM,SAAS,iBAAiB,GAAG;AAAA,EACnC,OAAO,aAAa,IAAI,WAAW,OAAO;AAAA,EAC1C,OAAO,OAAO,SAAS;AAAA;AAGzB,SAAS,oBAAoB,CAC3B,QACA,MACA,UACY;AAAA,EACZ,IAAI,OAAO,oBAAoB,OAAO,qBAAqB;AAAA,IACzD,OAAO,iBAAiB,MAAM,QAAQ;AAAA,IACtC,OAAO,MAAM,OAAO,sBAAsB,MAAM,QAAQ;AAAA,EAC1D;AAAA,EAEA,IAAI,OAAO,IAAI;AAAA,IACb,OAAO,GAAG,MAAM,QAAQ;AAAA,IACxB,OAAO,MAAM,OAAO,MAAM,MAAM,QAAQ;AAAA,EAC1C;AAAA,EAEA,MAAM,IAAI,MAAM,2DAA2D;AAAA;AAG7E,SAAS,eAAe,CACtB,QACA,MACA,UACY;AAAA,EACZ,IAAI,OAAO,MAAM;AAAA,IACf,OAAO,KAAK,MAAM,QAAQ;AAAA,IAC1B,OAAO,MAAM,OAAO,MAAM,MAAM,QAAQ;AAAA,EAC1C;AAAA,EAEA,IAAI,SAAS,MAAM;AAAA,EACnB,SAAS,qBAAqB,QAAQ,MAAM,CAAC,UAAU;AAAA,IACrD,OAAO;AAAA,IACP,SAAS,KAAK;AAAA,GACf;AAAA,EACD,OAAO;AAAA;AAGT,SAAS,iBAAiB,CAAC,QAA4C;AAAA,EACrE,IAAI,OAAO,eAAe,sBAAsB;AAAA,IAC9C,OAAO,QAAQ,QAAQ;AAAA,EACzB;AAAA,EAEA,OAAO,IAAI,QAAQ,CAAC,SAAS,WAAW;AAAA,IACtC,IAAI,aAAa,MAAM;AAAA,IACvB,IAAI,cAAc,MAAM;AAAA,IACxB,MAAM,UAAU,MAAM;AAAA,MACpB,WAAW;AAAA,MACX,YAAY;AAAA;AAAA,IAEd,aAAa,gBAAgB,QAAQ,QAAQ,MAAM;AAAA,MACjD,QAAQ;AAAA,MACR,QAAQ;AAAA,KACT;AAAA,IACD,cAAc,gBAAgB,QAAQ,SAAS,CAAC,UAAU;AAAA,MACxD,QAAQ;AAAA,MACR,OACE,IAAI,MAAM,wCAAwC,OAAO,KAAK,GAAG,CACnE;AAAA,KACD;AAAA,GACF;AAAA;AAGH,SAAS,YAAY,CAAC,OAAyB;AAAA,EAC7C,IAAI,SAAS,OAAO,UAAU,YAAY,UAAU,OAAO;AAAA,IACzD,OAAQ,MAA4B;AAAA,EACtC;AAAA,EACA,OAAO;AAAA;AAGT,SAAS,mBAAmB,CAAC,MAAuB;AAAA,EAClD,MAAM,MAAM,aAAa,IAAI;AAAA,EAC7B,IAAI,OAAO,QAAQ;AAAA,IAAU,OAAO;AAAA,EACpC,IAAI,eAAe,aAAa;AAAA,IAC9B,OAAO,IAAI,YAAY,EAAE,OAAO,GAAG;AAAA,EACrC;AAAA,EACA,IAAI,eAAe,YAAY;AAAA,IAC7B,OAAO,IAAI,YAAY,EAAE,OAAO,GAAG;AAAA,EACrC;AAAA,EACA,IAAI,YAAY,OAAO,GAAG,GAAG;AAAA,IAC3B,OAAO,IAAI,YAAY,EAAE,OACvB,IAAI,WAAW,IAAI,QAAuB,IAAI,YAAY,IAAI,UAAU,CAC1E;AAAA,EACF;AAAA,EACA,OAAO,OAAO,GAAG;AAAA;AAGnB,SAAS,oBAAoB,CAAC,OAAmC;AAAA,EAC/D,OAAO,KAAK,MAAM,oBAAoB,KAAK,CAAC;AAAA;AAG9C,SAAS,sBAAsB,CAC7B,WACoC;AAAA,EACpC,IAAI,cAAc,WAAW;AAAA,IAC3B;AAAA,EACF;AAAA,EACA,MAAM,QAAQ,UAAU,KAAK;AAAA,EAC7B,IAAI,CAAC,OAAO;AAAA,IACV,MAAM,IAAI,MAAM,yCAAyC;AAAA,EAC3D;AAAA,EACA,OAAO,EAAE,SAAS,EAAE,eAAe,UAAU,QAAQ,EAAE;AAAA;AAGzD,SAAS,WAAW,CAAC,GAA6B,GAA0B;AAAA,EAC1E,OAAO,GAAG,aAAa,EAAE,YAAY,GAAG,oBAAoB,EAAE;AAAA;AAGhE,SAAS,mBAAmB,CAAC,SAA2C;AAAA,EACtE,OAAO,QAAQ,YAAY,WAAW;AAAA;AAGxC,SAAS,6BAA6B,CACpC,SACS;AAAA,EACT,OAAO,QAAQ,YAAY,WAAW;AAAA;AAGxC,SAAS,gBAAgB,CAAC,SAA4C;AAAA,EACpE,MAAM,QAAS,QAAQ,MAA+B;AAAA,EACtD,OAAO,OAAO,UAAU,WAAW,QAAQ;AAAA;AAG7C,SAAS,sBAAsB,CAAC,SAA4C;AAAA,EAC1E,MAAM,cAAe,QAAQ,MAC1B;AAAA,EACH,OAAO,OAAO,gBAAgB,WAAW,cAAc;AAAA;AAGzD,SAAS,qBAAqB,CAAC,SAA4C;AAAA,EACzE,MAAM,aAAc,QAAQ,MAAoC;AAAA,EAChE,OAAO,OAAO,eAAe,WAAW,aAAa;AAAA;AAGvD,SAAS,uBAAuB,CAAC,SAAqC;AAAA,EACpE,MAAM,QAAQ,QAAQ;AAAA,EAItB,MAAM,aAAa,MAAM,WAAW,WAAW,MAAM,WAAW;AAAA,EAChE,IAAI,OAAO,eAAe,YAAY,WAAW,SAAS;AAAA,IACxD,OAAO;AAAA,EACT,IAAI,OAAO,MAAM,YAAY,YAAY,MAAM,QAAQ,SAAS;AAAA,IAC9D,OAAO,MAAM;AAAA,EACf,OAAO;AAAA;AAAA;AAGF,MAAM,gBAAgB;AAAA,EAClB;AAAA,EACA;AAAA,EAEQ;AAAA,EACA,UAAU,IAAI;AAAA,EACd,kBAAkB,IAAI;AAAA,EACtB,eAAe,IAAI;AAAA,EACnB,qBAAqB,IAAI;AAAA,EAClC,oBAAoB;AAAA,EAE5B,WAAW,CAAC,SAAiC;AAAA,IAC3C,MAAM,YAAY,QAAQ,aAAa,mBAAmB;AAAA,IAC1D,IAAI,CAAC,WAAW;AAAA,MACd,MAAM,IAAI,MAAM,uCAAuC;AAAA,IACzD;AAAA,IAEA,KAAK,mBACH,QAAQ,oBAAoB;AAAA,IAC9B,MAAM,gBAAgB,uBAAuB,QAAQ,SAAS;AAAA,IAC9D,KAAK,UAAU,IAAI,UACjB,2BAA2B,QAAQ,KAAK,SAAS,GACjD,aACF;AAAA,IACA,KAAK,SAAS,IAAI,UAChB,2BAA2B,QAAQ,KAAK,QAAQ,GAChD,aACF;AAAA,IAEA,qBAAqB,KAAK,SAAS,WAAW,CAAC,UAAU;AAAA,MACvD,KAAK,cAAc,OAAO,SAAS;AAAA,KACpC;AAAA,IACD,qBAAqB,KAAK,QAAQ,WAAW,CAAC,UAAU;AAAA,MACtD,KAAK,cAAc,OAAO,QAAQ;AAAA,KACnC;AAAA,IACD,MAAM,gBAAgB,MACpB,KAAK,iBAAiB,0BAA0B;AAAA,IAClD,qBAAqB,KAAK,SAAS,SAAS,aAAa;AAAA,IACzD,qBAAqB,KAAK,QAAQ,SAAS,aAAa;AAAA;AAAA,OAGpD,QAAO,GAAkB;AAAA,IAC7B,MAAM,QAAQ,IAAI;AAAA,MAChB,kBAAkB,KAAK,OAAO;AAAA,MAC9B,kBAAkB,KAAK,MAAM;AAAA,IAC/B,CAAC;AAAA,IACD,OAAO;AAAA;AAAA,EAGT,KAAK,GAAS;AAAA,IACZ,KAAK,iBAAiB,0BAA0B;AAAA,IAChD,KAAK,QAAQ,MAAM;AAAA,IACnB,KAAK,OAAO,MAAM;AAAA;AAAA,EAGpB,SAAS,CAAC,SAA8C;AAAA,IACtD,KAAK,gBAAgB,IAAI,OAAO;AAAA,IAChC,OAAO,MAAM,KAAK,gBAAgB,OAAO,OAAO;AAAA;AAAA,EAGlD,MAAM,CAAC,SAA2C;AAAA,IAChD,KAAK,aAAa,IAAI,OAAO;AAAA,IAC7B,OAAO,MAAM,KAAK,aAAa,OAAO,OAAO;AAAA;AAAA,EAG/C,aAAa,CAAC,SAAS,OAAe;AAAA,IACpC,KAAK,qBAAqB;AAAA,IAC1B,OAAO,GAAG,UAAU,KAAK;AAAA;AAAA,EAG3B,IAAI,CAAC,SAAkC;AAAA,IACrC,WAAW,WAAW,KAAK,cAAc;AAAA,MACvC,QAAQ,OAAO;AAAA,IACjB;AAAA,IACA,KAAK,QAAQ,KAAK,KAAK,UAAU,OAAO,CAAC;AAAA;AAAA,EAiB3C,OAA+D,CAC7D,eAGA,gBAEwC,CAAC,GACzC,eAAkD,CAAC,GAChC;AAAA,IACnB,MAAM,gBAAgB,OAAO,kBAAkB;AAAA,IAC/C,MAAM,UAAU,gBACX;AAAA,MACC,MAAM;AAAA,MACN,YACG,cAA0C,cAC3C,KAAK,cAAc,aAAa;AAAA,SAC9B;AAAA,IACN,IACA;AAAA,IACJ,MAAM,UAAU,gBACZ,eACC;AAAA,IACL,MAAM,YAAY,QAAQ,aAAa,KAAK;AAAA,IAE5C,OAAO,IAAI,QAAQ,CAAC,SAAS,WAAW;AAAA,MACtC,MAAM,UAAU,WAAW,MAAM;AAAA,QAC/B,KAAK,QAAQ,OAAO,QAAQ,UAAU;AAAA,QACtC,OAAO,IAAI,MAAM,yBAAyB,QAAQ,YAAY,CAAC;AAAA,SAC9D,SAAS;AAAA,MAEZ,KAAK,QAAQ,IAAI,QAAQ,YAAY;AAAA,QACnC,SAAS,CAAC,YAAY,QAAQ,OAAmB;AAAA,QACjD;AAAA,QACA,WAAW,QAAQ;AAAA,QACnB;AAAA,MACF,CAAC;AAAA,MAED,IAAI;AAAA,QACF,KAAK,KAAK,OAAO;AAAA,QACjB,OAAO,OAAO;AAAA,QACd,aAAa,OAAO;AAAA,QACpB,KAAK,QAAQ,OAAO,QAAQ,UAAU;AAAA,QACtC,OAAO,iBAAiB,QAAQ,QAAQ,IAAI,MAAM,OAAO,KAAK,CAAC,CAAC;AAAA;AAAA,KAEnE;AAAA;AAAA,EAGH,YAAY,CACV,SAGA,UAGI,CAAC,GACiC;AAAA,IACtC,OAAO,KAAK,QACV;AAAA,MACE,MAAM;AAAA,MACN,YAAY,QAAQ,cAAc,KAAK,cAAc,eAAe;AAAA,SACjE;AAAA,IACL,GACA;AAAA,SACK;AAAA,MACH,WAAW,CAAC,YACV,QAAQ,SAAS;AAAA,IACrB,CACF;AAAA;AAAA,EAGF,IAAI,CACF,SACA,UAGI,CAAC,GACyB;AAAA,IAC9B,OAAO,KAAK,QACV;AAAA,MACE,MAAM;AAAA,MACN,YAAY,QAAQ,cAAc,KAAK,cAAc,MAAM;AAAA,SACxD;AAAA,IACL,GACA;AAAA,SACK;AAAA,MACH,WAAW,CAAC,YACV,QAAQ,SAAS;AAAA,IACrB,CACF;AAAA;AAAA,EAGF,KAAK,CACH,SAGA,UAGI,CAAC,GACiC;AAAA,IACtC,OAAO,KAAK,QACV;AAAA,MACE,MAAM;AAAA,MACN,YAAY,QAAQ,cAAc,KAAK,cAAc,OAAO;AAAA,SACzD;AAAA,IACL,GACA;AAAA,SACK;AAAA,MACH,WAAW,CAAC,YACV,QAAQ,SAAS;AAAA,IACrB,CACF;AAAA;AAAA,EAGF,kBAAkB,CAAC,SAAuD;AAAA,IACxE,OAAO,KAAK,UAAU,CAAC,SAAS,YAAY;AAAA,MAC1C,IACE,YAAY,aACZ,QAAQ,SAAS,8BACjB;AAAA,QACA;AAAA,MACF;AAAA,MAEK,QAAQ,QAAQ,QAAQ,OAAO,CAAC,EAClC,KAAK,CAAC,WAAW;AAAA,QAChB,KAAK,KAAK;AAAA,UACR,MAAM;AAAA,UACN,YAAY,QAAQ;AAAA,UACpB;AAAA,QACF,CAAC;AAAA,OACF,EACA,MAAM,CAAC,UAAU;AAAA,QAChB,KAAK,KAAK;AAAA,UACR,MAAM;AAAA,UACN,YAAY,QAAQ;AAAA,UACpB,OAAO,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AAAA,QAC9D,CAAC;AAAA,OACF;AAAA,KACJ;AAAA;AAAA,EAGH,KAAK,CAAC,SAA2C;AAAA,IAC/C,KAAK,KAAK,EAAE,MAAM,YAAY,QAAQ,CAAC;AAAA;AAAA,EAGzC,OAAO,CACL,SACA,UAAmC,CAAC,GACN;AAAA,IAC9B,MAAM,aAAa,GAAG,QAAQ,QAAQ,YAAY,QAAQ,QAAQ;AAAA,IAClE,IAAI,KAAK,mBAAmB,IAAI,UAAU,GAAG;AAAA,MAC3C,OAAO,QAAQ,OACb,IAAI,MAAM,mCAAmC,YAAY,CAC3D;AAAA,IACF;AAAA,IACA,KAAK,mBAAmB,IAAI,UAAU;AAAA,IACtC,MAAM,YAAY,QAAQ,aAAa,KAAK;AAAA,IAC5C,MAAM,iBAAiB,KAAK,qBAAqB,OAAO;AAAA,IACxD,MAAM,SAAS,IAAI;AAAA,IACnB,IAAI,uBAAuB;AAAA,IAC3B,IAAI,+BAA+B;AAAA,IAEnC,OAAO,IAAI,QAAQ,CAAC,SAAS,WAAW;AAAA,MACtC,MAAM,UAAU,WAAW,MAAM;AAAA,QAC/B,QAAQ;AAAA,QACR,OACE,IAAI,MACF,4CAA4C,QAAQ,QAAQ,YAAY,QAAQ,QAAQ,iBAC1F,CACF;AAAA,SACC,SAAS;AAAA,MAEZ,MAAM,UAAU,MAAM;AAAA,QACpB,aAAa,OAAO;AAAA,QACpB,KAAK,mBAAmB,OAAO,UAAU;AAAA,QACzC,WAAW;AAAA;AAAA,MAGb,MAAM,SAAS,CACb,aACA,iBACA,eACG;AAAA,QACH,QAAQ;AAAA,QACR,QAAQ;AAAA,UACN,SAAS,QAAQ;AAAA,UACjB;AAAA,UACA,QAAQ,CAAC,GAAG,MAAM;AAAA,UAClB,kBAAkB,eAAe;AAAA,UACjC;AAAA,UACA;AAAA,QACF,CAAC;AAAA;AAAA,MAGH,MAAM,OAAO,CAAC,UAAiB;AAAA,QAC7B,QAAQ;AAAA,QACR,OAAO,KAAK;AAAA;AAAA,MAGd,MAAM,aAAa,KAAK,UAAU,CAAC,YAAY;AAAA,QAC7C,IACE,CAAC,YACE,QAAuC,SACxC,QAAQ,OACV,GACA;AAAA,UACA;AAAA,QACF;AAAA,QAEA,IAAI,QAAQ,SAAS,gBAAgB;AAAA,UACnC,uBAAuB;AAAA,UACvB,MAAM,QAAQ,iBAAiB,OAAO;AAAA,UACtC,IAAI;AAAA,YAAO,OAAO,IAAI,KAAK;AAAA,UAE3B,MAAM,cAAc,uBAAuB,OAAO;AAAA,UAClD,IAAI,gBAAgB,gBAAgB,gBAAgB,iBAAiB;AAAA,YACnE,KAAK,IAAI,MAAM,wBAAwB,OAAO,CAAC,CAAC;AAAA,YAChD;AAAA,UACF;AAAA,UACA,IAAI,gBAAgB,eAAe;AAAA,YACjC,MAAM,aAAa,sBAAsB,OAAO;AAAA,YAChD,IAAI,eAAe,qBAAqB;AAAA,cACtC,+BAA+B;AAAA,cAC/B;AAAA,YACF;AAAA,YACA,OAAO,eAAe,SAAS,UAAU;AAAA,UAC3C;AAAA,UACA;AAAA,QACF;AAAA,QAEA,IAAI,QAAQ,SAAS,sBAAsB;AAAA,UACzC,WAAW,SAAS,QAAQ,YAAY,gBAAgB;AAAA,YACtD,uBAAuB;AAAA,YACvB,OAAO,IAAI,KAAK;AAAA,UAClB;AAAA,UACA,KACG,wBAAwB,iCACzB,8BAA8B,OAAO,GACrC;AAAA,YACA,OACE,mCACA,SACA,mBACF;AAAA,YACA;AAAA,UACF;AAAA,UACA,IACE,QAAQ,4BAA4B,QACpC,wBACA,oBAAoB,OAAO,GAC3B;AAAA,YACA,OAAO,gCAAgC,SAAS,IAAI;AAAA,UACtD;AAAA,QACF;AAAA,OACD;AAAA,MAED,IAAI;AAAA,QACF,KAAK,MAAM,eAAe,OAAO;AAAA,QACjC,OAAO,OAAO;AAAA,QACd,KAAK,iBAAiB,QAAQ,QAAQ,IAAI,MAAM,OAAO,KAAK,CAAC,CAAC;AAAA;AAAA,KAEjE;AAAA;AAAA,EAGK,oBAAoB,CAAC,SAG3B;AAAA,IACA,IAAI,QAAQ,QAAQ,SAAS,kBAAkB;AAAA,MAC7C,OAAO,EAAE,SAAS,kBAAkB,CAAC,EAAE;AAAA,IACzC;AAAA,IAEA,MAAM,mBAA6B,CAAC;AAAA,IACpC,MAAM,WAAW,QAAQ,QAAQ,SAAS,IAAI,CAAC,YAAY;AAAA,MACzD,IAAI,QAAQ,SAAS;AAAA,QAAQ,OAAO;AAAA,MACpC,MAAM,WAAY,QACf;AAAA,MACH,MAAM,kBACJ,OAAO,aAAa,YAAY,SAAS,SAAS,IAC9C,WACA,KAAK,cAAc,gBAAgB;AAAA,MACzC,iBAAiB,KAAK,eAAe;AAAA,MACrC,OAAO,KAAK,SAAS,mBAAmB,gBAAgB;AAAA,KACzD;AAAA,IAED,OAAO;AAAA,MACL,SAAS;AAAA,WACJ;AAAA,QACH,SAAS,KAAK,QAAQ,SAAS,SAAS;AAAA,MAC1C;AAAA,MACA;AAAA,IACF;AAAA;AAAA,EAGM,aAAa,CAAC,OAAgB,SAAiC;AAAA,IACrE,MAAM,UAAU,qBAAqB,KAAK;AAAA,IAE1C,WAAW,WAAW,KAAK,iBAAiB;AAAA,MAC1C,QAAQ,SAAS,OAAO;AAAA,IAC1B;AAAA,IAEA,MAAM,YACJ,WAAW,OAAO,YAAY,YAAY,gBAAgB,UACrD,QAAqC,aACtC;AAAA,IACN,IAAI,YAAY,aAAa,OAAO,cAAc,UAAU;AAAA,MAC1D;AAAA,IACF;AAAA,IAEA,MAAM,UAAU,KAAK,QAAQ,IAAI,SAAS;AAAA,IAC1C,IAAI,CAAC,WAAY,QAAQ,aAAa,CAAC,QAAQ,UAAU,OAAO,GAAI;AAAA,MAClE;AAAA,IACF;AAAA,IAEA,aAAa,QAAQ,OAAO;AAAA,IAC5B,KAAK,QAAQ,OAAO,SAAS;AAAA,IAC7B,QAAQ,QAAQ,OAAO;AAAA;AAAA,EAGjB,gBAAgB,CAAC,QAAsB;AAAA,IAC7C,YAAY,WAAW,YAAY,KAAK,SAAS;AAAA,MAC/C,aAAa,QAAQ,OAAO;AAAA,MAC5B,KAAK,QAAQ,OAAO,SAAS;AAAA,MAC7B,QAAQ,OAAO,IAAI,MAAM,MAAM,CAAC;AAAA,IAClC;AAAA;AAEJ;AAEO,SAAS,qBAAqB,CACnC,SACiB;AAAA,EACjB,OAAO,IAAI,gBAAgB,OAAO;AAAA;",
|
|
8
|
+
"debugId": "5B36C9DEF3E6B55264756E2164756E21",
|
|
9
9
|
"names": []
|
|
10
10
|
}
|
|
@@ -20,10 +20,15 @@ export interface AppServerSocketLike {
|
|
|
20
20
|
off?(type: string, listener: (event: unknown) => void): void;
|
|
21
21
|
once?(type: string, listener: (event: unknown) => void): void;
|
|
22
22
|
}
|
|
23
|
-
export
|
|
23
|
+
export interface AppServerSocketOptions {
|
|
24
|
+
headers?: Record<string, string>;
|
|
25
|
+
}
|
|
26
|
+
export type AppServerSocketConstructor = new (url: string, options?: AppServerSocketOptions) => AppServerSocketLike;
|
|
24
27
|
export interface AppServerClientOptions {
|
|
25
28
|
/** Base app-server URL, e.g. ws://127.0.0.1:4500 or http://127.0.0.1:4500. */
|
|
26
29
|
url: string;
|
|
30
|
+
/** Optional capability token sent as Authorization: Bearer <token>; requires a WebSocket implementation with header support. */
|
|
31
|
+
authToken?: string;
|
|
27
32
|
/** Optional WebSocket constructor for Node/tests. Browsers use globalThis.WebSocket. */
|
|
28
33
|
WebSocket?: AppServerSocketConstructor;
|
|
29
34
|
/** Default timeout for request_id-correlated control requests. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"app-server-client.d.ts","sourceRoot":"","sources":["../../src/app-server-client.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,mBAAmB,EACnB,2BAA2B,EAC3B,8BAA8B,EAC9B,sBAAsB,EACtB,YAAY,EAEZ,YAAY,EACZ,mBAAmB,EACnB,2BAA2B,EAE3B,WAAW,EACX,mBAAmB,EACnB,iBAAiB,EACjB,iBAAiB,EAClB,MAAM,6BAA6B,CAAC;AAErC,MAAM,MAAM,gBAAgB,GAAG,SAAS,GAAG,QAAQ,CAAC;AAEpD;;;;;GAKG;AACH,MAAM,MAAM,uBAAuB,GAAG,CACpC,OAAO,EAAE,iBAAiB,EAC1B,OAAO,EAAE,gBAAgB,KACtB,IAAI,CAAC;AAEV,uFAAuF;AACvF,MAAM,MAAM,oBAAoB,GAAG,CAAC,OAAO,EAAE,iBAAiB,KAAK,IAAI,CAAC;AAExE,MAAM,MAAM,gCAAgC,GAAG,CAC7C,OAAO,EAAE,8BAA8B,KACpC,OAAO,CAAC,sBAAsB,CAAC,GAAG,sBAAsB,CAAC;AAE9D,MAAM,WAAW,mBAAmB;IAClC,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,KAAK,IAAI,IAAI,CAAC;IACd,gBAAgB,CAAC,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,GAAG,IAAI,CAAC;IAC1E,mBAAmB,CAAC,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,GAAG,IAAI,CAAC;IAC7E,EAAE,CAAC,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,GAAG,IAAI,CAAC;IAC5D,GAAG,CAAC,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,GAAG,IAAI,CAAC;IAC7D,IAAI,CAAC,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,GAAG,IAAI,CAAC;CAC/D;AAED,MAAM,MAAM,0BAA0B,GAAG,KACvC,GAAG,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"app-server-client.d.ts","sourceRoot":"","sources":["../../src/app-server-client.ts"],"names":[],"mappings":"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"}
|
package/letta.js
CHANGED
|
@@ -5094,7 +5094,7 @@ var package_default;
|
|
|
5094
5094
|
var init_package = __esm(() => {
|
|
5095
5095
|
package_default = {
|
|
5096
5096
|
name: "@letta-ai/letta-code",
|
|
5097
|
-
version: "0.27.
|
|
5097
|
+
version: "0.27.13",
|
|
5098
5098
|
description: "Letta Code is a CLI tool for interacting with stateful Letta agents from the terminal.",
|
|
5099
5099
|
type: "module",
|
|
5100
5100
|
packageManager: "bun@1.3.0",
|
|
@@ -249646,7 +249646,7 @@ function isReflectionSubagentActive(subagents, agentId, conversationId) {
|
|
|
249646
249646
|
}
|
|
249647
249647
|
|
|
249648
249648
|
// src/utils/file-lock.ts
|
|
249649
|
-
import { open as open2, readFile as
|
|
249649
|
+
import { open as open2, readFile as readFile12, stat as stat9, unlink as unlink3 } from "node:fs/promises";
|
|
249650
249650
|
async function withFileLock(lockPath, fn, options3) {
|
|
249651
249651
|
const opts = { ...DEFAULT_OPTIONS, ...options3 };
|
|
249652
249652
|
const release = await acquireFileLock(lockPath, opts);
|
|
@@ -249700,7 +249700,7 @@ async function acquireFileLock(lockPath, opts) {
|
|
|
249700
249700
|
async function tryReapStaleLock(lockPath, staleMs) {
|
|
249701
249701
|
let raw2;
|
|
249702
249702
|
try {
|
|
249703
|
-
raw2 = await
|
|
249703
|
+
raw2 = await readFile12(lockPath, "utf-8");
|
|
249704
249704
|
} catch {
|
|
249705
249705
|
return true;
|
|
249706
249706
|
}
|
|
@@ -249757,7 +249757,7 @@ import {
|
|
|
249757
249757
|
appendFile,
|
|
249758
249758
|
mkdir as mkdir10,
|
|
249759
249759
|
readdir as readdir7,
|
|
249760
|
-
readFile as
|
|
249760
|
+
readFile as readFile13,
|
|
249761
249761
|
writeFile as writeFile12
|
|
249762
249762
|
} from "node:fs/promises";
|
|
249763
249763
|
import { homedir as homedir21 } from "node:os";
|
|
@@ -249800,7 +249800,7 @@ async function collectParentMemoryFiles(memoryDir) {
|
|
|
249800
249800
|
continue;
|
|
249801
249801
|
}
|
|
249802
249802
|
try {
|
|
249803
|
-
const content = await
|
|
249803
|
+
const content = await readFile13(entryPath, "utf-8");
|
|
249804
249804
|
const { frontmatter } = parseFrontmatter(content);
|
|
249805
249805
|
const description = typeof frontmatter.description === "string" ? frontmatter.description : undefined;
|
|
249806
249806
|
files.push({
|
|
@@ -250140,7 +250140,7 @@ async function ensurePaths(paths) {
|
|
|
250140
250140
|
}
|
|
250141
250141
|
async function readTranscriptLines(paths) {
|
|
250142
250142
|
try {
|
|
250143
|
-
const raw2 = await
|
|
250143
|
+
const raw2 = await readFile13(paths.transcriptPath, "utf-8");
|
|
250144
250144
|
return raw2.split(`
|
|
250145
250145
|
`).map((line) => line.trim()).filter((line) => line.length > 0);
|
|
250146
250146
|
} catch {
|
|
@@ -250213,7 +250213,7 @@ function buildUnreflectedStateFromTranscript(lines) {
|
|
|
250213
250213
|
async function readState(paths) {
|
|
250214
250214
|
let raw2 = null;
|
|
250215
250215
|
try {
|
|
250216
|
-
raw2 = await
|
|
250216
|
+
raw2 = await readFile13(paths.statePath, "utf-8");
|
|
250217
250217
|
} catch {
|
|
250218
250218
|
raw2 = null;
|
|
250219
250219
|
}
|
|
@@ -253118,7 +253118,7 @@ function isGroupMode2(value) {
|
|
|
253118
253118
|
function isPositiveNumber(value) {
|
|
253119
253119
|
return typeof value === "number" && Number.isFinite(value) && value > 0;
|
|
253120
253120
|
}
|
|
253121
|
-
function
|
|
253121
|
+
function normalizeOptionalString2(value) {
|
|
253122
253122
|
if (typeof value !== "string") {
|
|
253123
253123
|
return;
|
|
253124
253124
|
}
|
|
@@ -253153,8 +253153,8 @@ var init_account_config3 = __esm(() => {
|
|
|
253153
253153
|
toAccountPatch(config3) {
|
|
253154
253154
|
return {
|
|
253155
253155
|
baseUrl: isNullableString3(config3.base_url) ? config3.base_url ?? "" : undefined,
|
|
253156
|
-
account: isNullableString3(config3.account) ?
|
|
253157
|
-
accountUuid: isNullableString3(config3.account_uuid) ?
|
|
253156
|
+
account: isNullableString3(config3.account) ? normalizeOptionalString2(config3.account) ?? "" : undefined,
|
|
253157
|
+
accountUuid: isNullableString3(config3.account_uuid) ? normalizeOptionalString2(config3.account_uuid) ?? "" : undefined,
|
|
253158
253158
|
agentId: isNullableString3(config3.agent_id) ? config3.agent_id : undefined,
|
|
253159
253159
|
selfChatMode: isBoolean2(config3.self_chat_mode) ? config3.self_chat_mode : undefined,
|
|
253160
253160
|
groupMode: isGroupMode2(config3.group_mode) ? config3.group_mode : undefined,
|
|
@@ -264865,7 +264865,7 @@ ${lanes.join(`
|
|
|
264865
264865
|
writeOutputIsTTY() {
|
|
264866
264866
|
return process.stdout.isTTY;
|
|
264867
264867
|
},
|
|
264868
|
-
readFile:
|
|
264868
|
+
readFile: readFile14,
|
|
264869
264869
|
writeFile: writeFile22,
|
|
264870
264870
|
watchFile: watchFile2,
|
|
264871
264871
|
watchDirectory,
|
|
@@ -265058,7 +265058,7 @@ ${lanes.join(`
|
|
|
265058
265058
|
function fsWatchWorker(fileOrDirectory, recursive, callback) {
|
|
265059
265059
|
return _fs.watch(fileOrDirectory, fsSupportsRecursiveFsWatch ? { persistent: true, recursive: !!recursive } : { persistent: true }, callback);
|
|
265060
265060
|
}
|
|
265061
|
-
function
|
|
265061
|
+
function readFile14(fileName, _encoding) {
|
|
265062
265062
|
let buffer;
|
|
265063
265063
|
try {
|
|
265064
265064
|
buffer = _fs.readFileSync(fileName);
|
|
@@ -296005,7 +296005,7 @@ ${lanes.join(`
|
|
|
296005
296005
|
const possibleOption = getSpellingSuggestion(unknownOption, diagnostics2.optionDeclarations, getOptionName);
|
|
296006
296006
|
return possibleOption ? createDiagnosticForNodeInSourceFileOrCompilerDiagnostic(sourceFile, node, diagnostics2.unknownDidYouMeanDiagnostic, unknownOptionErrorText || unknownOption, possibleOption.name) : createDiagnosticForNodeInSourceFileOrCompilerDiagnostic(sourceFile, node, diagnostics2.unknownOptionDiagnostic, unknownOptionErrorText || unknownOption);
|
|
296007
296007
|
}
|
|
296008
|
-
function parseCommandLineWorker(diagnostics2, commandLine,
|
|
296008
|
+
function parseCommandLineWorker(diagnostics2, commandLine, readFile14) {
|
|
296009
296009
|
const options3 = {};
|
|
296010
296010
|
let watchOptions;
|
|
296011
296011
|
const fileNames = [];
|
|
@@ -296043,7 +296043,7 @@ ${lanes.join(`
|
|
|
296043
296043
|
}
|
|
296044
296044
|
}
|
|
296045
296045
|
function parseResponseFile(fileName) {
|
|
296046
|
-
const text2 = tryReadFile(fileName,
|
|
296046
|
+
const text2 = tryReadFile(fileName, readFile14 || ((fileName2) => sys.readFile(fileName2)));
|
|
296047
296047
|
if (!isString5(text2)) {
|
|
296048
296048
|
errors7.push(text2);
|
|
296049
296049
|
return;
|
|
@@ -296146,8 +296146,8 @@ ${lanes.join(`
|
|
|
296146
296146
|
unknownDidYouMeanDiagnostic: Diagnostics.Unknown_compiler_option_0_Did_you_mean_1,
|
|
296147
296147
|
optionTypeMismatchDiagnostic: Diagnostics.Compiler_option_0_expects_an_argument
|
|
296148
296148
|
};
|
|
296149
|
-
function parseCommandLine(commandLine,
|
|
296150
|
-
return parseCommandLineWorker(compilerOptionsDidYouMeanDiagnostics, commandLine,
|
|
296149
|
+
function parseCommandLine(commandLine, readFile14) {
|
|
296150
|
+
return parseCommandLineWorker(compilerOptionsDidYouMeanDiagnostics, commandLine, readFile14);
|
|
296151
296151
|
}
|
|
296152
296152
|
function getOptionFromName(optionName, allowShort) {
|
|
296153
296153
|
return getOptionDeclarationFromName(getOptionsNameMap, optionName, allowShort);
|
|
@@ -296215,8 +296215,8 @@ ${lanes.join(`
|
|
|
296215
296215
|
result.originalFileName = result.fileName;
|
|
296216
296216
|
return parseJsonSourceFileConfigFileContent(result, host, getNormalizedAbsolutePath(getDirectoryPath(configFileName), cwd2), optionsToExtend, getNormalizedAbsolutePath(configFileName, cwd2), undefined, extraFileExtensions, extendedConfigCache, watchOptionsToExtend);
|
|
296217
296217
|
}
|
|
296218
|
-
function readConfigFile(fileName,
|
|
296219
|
-
const textOrDiagnostic = tryReadFile(fileName,
|
|
296218
|
+
function readConfigFile(fileName, readFile14) {
|
|
296219
|
+
const textOrDiagnostic = tryReadFile(fileName, readFile14);
|
|
296220
296220
|
return isString5(textOrDiagnostic) ? parseConfigFileTextToJson(fileName, textOrDiagnostic) : { config: {}, error: textOrDiagnostic };
|
|
296221
296221
|
}
|
|
296222
296222
|
function parseConfigFileTextToJson(fileName, jsonText) {
|
|
@@ -296226,14 +296226,14 @@ ${lanes.join(`
|
|
|
296226
296226
|
error: jsonSourceFile.parseDiagnostics.length ? jsonSourceFile.parseDiagnostics[0] : undefined
|
|
296227
296227
|
};
|
|
296228
296228
|
}
|
|
296229
|
-
function readJsonConfigFile(fileName,
|
|
296230
|
-
const textOrDiagnostic = tryReadFile(fileName,
|
|
296229
|
+
function readJsonConfigFile(fileName, readFile14) {
|
|
296230
|
+
const textOrDiagnostic = tryReadFile(fileName, readFile14);
|
|
296231
296231
|
return isString5(textOrDiagnostic) ? parseJsonText(fileName, textOrDiagnostic) : { fileName, parseDiagnostics: [textOrDiagnostic] };
|
|
296232
296232
|
}
|
|
296233
|
-
function tryReadFile(fileName,
|
|
296233
|
+
function tryReadFile(fileName, readFile14) {
|
|
296234
296234
|
let text2;
|
|
296235
296235
|
try {
|
|
296236
|
-
text2 =
|
|
296236
|
+
text2 = readFile14(fileName);
|
|
296237
296237
|
} catch (e2) {
|
|
296238
296238
|
return createCompilerDiagnostic(Diagnostics.Cannot_read_file_0_Colon_1, fileName, e2.message);
|
|
296239
296239
|
}
|
|
@@ -363663,12 +363663,12 @@ ${lanes.join(`
|
|
|
363663
363663
|
function createCompilerHost(options3, setParentNodes) {
|
|
363664
363664
|
return createCompilerHostWorker(options3, setParentNodes);
|
|
363665
363665
|
}
|
|
363666
|
-
function createGetSourceFile(
|
|
363666
|
+
function createGetSourceFile(readFile14, setParentNodes) {
|
|
363667
363667
|
return (fileName, languageVersionOrOptions, onError) => {
|
|
363668
363668
|
let text2;
|
|
363669
363669
|
try {
|
|
363670
363670
|
mark2("beforeIORead");
|
|
363671
|
-
text2 =
|
|
363671
|
+
text2 = readFile14(fileName);
|
|
363672
363672
|
mark2("afterIORead");
|
|
363673
363673
|
measure("I/O Read", "beforeIORead", "afterIORead");
|
|
363674
363674
|
} catch (e2) {
|
|
@@ -364459,7 +364459,7 @@ ${lanes.join(`
|
|
|
364459
364459
|
getRedirectFromOutput,
|
|
364460
364460
|
forEachResolvedProjectReference: forEachResolvedProjectReference2
|
|
364461
364461
|
});
|
|
364462
|
-
const
|
|
364462
|
+
const readFile14 = host.readFile.bind(host);
|
|
364463
364463
|
(_e = tracing) == null || _e.push(tracing.Phase.Program, "shouldProgramCreateNewSourceFiles", { hasOldProgram: !!oldProgram });
|
|
364464
364464
|
const shouldCreateNewSourceFile = shouldProgramCreateNewSourceFiles(oldProgram, options3);
|
|
364465
364465
|
(_f = tracing) == null || _f.pop();
|
|
@@ -364635,7 +364635,7 @@ ${lanes.join(`
|
|
|
364635
364635
|
shouldTransformImportCall,
|
|
364636
364636
|
emitBuildInfo,
|
|
364637
364637
|
fileExists,
|
|
364638
|
-
readFile:
|
|
364638
|
+
readFile: readFile14,
|
|
364639
364639
|
directoryExists: directoryExists2,
|
|
364640
364640
|
getSymlinkCache,
|
|
364641
364641
|
realpath: (_o = host.realpath) == null ? undefined : _o.bind(host),
|
|
@@ -425516,7 +425516,7 @@ Additional information: BADCLIENT: Bad error code, ${badCode} not found in range
|
|
|
425516
425516
|
});
|
|
425517
425517
|
|
|
425518
425518
|
// src/mods/mod-engine.ts
|
|
425519
|
-
import { createHash as
|
|
425519
|
+
import { createHash as createHash5 } from "node:crypto";
|
|
425520
425520
|
import {
|
|
425521
425521
|
existsSync as existsSync38,
|
|
425522
425522
|
mkdirSync as mkdirSync27,
|
|
@@ -425707,7 +425707,7 @@ function prepareModForImport(modPath, source2) {
|
|
|
425707
425707
|
function createImportableModPath(modPath, cacheDirectory) {
|
|
425708
425708
|
ensureModCache(cacheDirectory);
|
|
425709
425709
|
const source2 = readFileSync27(modPath, "utf8");
|
|
425710
|
-
const hash4 =
|
|
425710
|
+
const hash4 = createHash5("sha256").update(source2).digest("hex").slice(0, 16);
|
|
425711
425711
|
const fileExtension = path29.extname(modPath);
|
|
425712
425712
|
const importableSource = prepareModForImport(modPath, source2);
|
|
425713
425713
|
const baseName = path29.basename(modPath, fileExtension).replace(/[^a-zA-Z0-9_-]/g, "-");
|
|
@@ -437066,7 +437066,7 @@ var init_grep_in_files = __esm(() => {
|
|
|
437066
437066
|
});
|
|
437067
437067
|
|
|
437068
437068
|
// src/websocket/listener/file-commands.ts
|
|
437069
|
-
import { readdir as readdir8, readFile as
|
|
437069
|
+
import { readdir as readdir8, readFile as readFile14 } from "node:fs/promises";
|
|
437070
437070
|
import { homedir as homedir25 } from "node:os";
|
|
437071
437071
|
import path33 from "node:path";
|
|
437072
437072
|
function trackListenerError2(errorType, error54, context3) {
|
|
@@ -437121,7 +437121,7 @@ async function getIgnoreConfig(root2) {
|
|
|
437121
437121
|
return cached2;
|
|
437122
437122
|
let patterns2 = [];
|
|
437123
437123
|
try {
|
|
437124
|
-
const content = await
|
|
437124
|
+
const content = await readFile14(path33.join(absRoot, ".letta", ".lettaignore"), "utf-8");
|
|
437125
437125
|
patterns2 = parseLettaIgnore(content);
|
|
437126
437126
|
} catch {
|
|
437127
437127
|
patterns2 = [];
|
|
@@ -437935,7 +437935,7 @@ __export(exports_custom, {
|
|
|
437935
437935
|
COMMANDS_DIR: () => COMMANDS_DIR
|
|
437936
437936
|
});
|
|
437937
437937
|
import { existsSync as existsSync40 } from "node:fs";
|
|
437938
|
-
import { readdir as readdir9, readFile as
|
|
437938
|
+
import { readdir as readdir9, readFile as readFile15 } from "node:fs/promises";
|
|
437939
437939
|
import { basename as basename21, dirname as dirname20, join as join40 } from "node:path";
|
|
437940
437940
|
async function getCustomCommands() {
|
|
437941
437941
|
if (cachedCommands !== null) {
|
|
@@ -437994,7 +437994,7 @@ async function findCommandFiles(currentPath, rootPath, commands, source2) {
|
|
|
437994
437994
|
} catch (_error) {}
|
|
437995
437995
|
}
|
|
437996
437996
|
async function parseCommandFile(filePath, rootPath, source2) {
|
|
437997
|
-
const content = await
|
|
437997
|
+
const content = await readFile15(filePath, "utf-8");
|
|
437998
437998
|
const { frontmatter, body: body3 } = parseFrontmatter(content);
|
|
437999
437999
|
const id2 = basename21(filePath, ".md");
|
|
438000
438000
|
const relativePath = dirname20(filePath).slice(rootPath.length);
|
|
@@ -440438,17 +440438,17 @@ function handleMemoryProtocolCommand(parsed, context3) {
|
|
|
440438
440438
|
ensureLocalMemfsCheckout: ensureLocalMemfsCheckout2,
|
|
440439
440439
|
isMemfsEnabledOnServer: isMemfsEnabledOnServer2
|
|
440440
440440
|
} = await Promise.resolve().then(() => (init_memory_filesystem2(), exports_memory_filesystem));
|
|
440441
|
-
const { readFile:
|
|
440441
|
+
const { readFile: readFile16 } = await import("node:fs/promises");
|
|
440442
440442
|
const { existsSync: existsSync41 } = await import("node:fs");
|
|
440443
|
-
const { isAbsolute:
|
|
440444
|
-
if (
|
|
440443
|
+
const { isAbsolute: isAbsolute23, join: join42, normalize: normalize5, relative: relative10, sep: sep5 } = await import("node:path");
|
|
440444
|
+
if (isAbsolute23(parsed.path) || parsed.path.length === 0) {
|
|
440445
440445
|
sendFailure("path must be a non-empty relative path");
|
|
440446
440446
|
return;
|
|
440447
440447
|
}
|
|
440448
440448
|
const memoryRoot = getScopedMemoryFilesystemRoot2(parsed.agent_id);
|
|
440449
440449
|
const absolutePath = normalize5(join42(memoryRoot, parsed.path));
|
|
440450
440450
|
const rel = relative10(memoryRoot, absolutePath);
|
|
440451
|
-
if (rel.startsWith("..") || rel === "" ||
|
|
440451
|
+
if (rel.startsWith("..") || rel === "" || isAbsolute23(rel) || rel.split(sep5).includes("..")) {
|
|
440452
440452
|
sendFailure("path must resolve inside the memory root");
|
|
440453
440453
|
return;
|
|
440454
440454
|
}
|
|
@@ -440464,7 +440464,7 @@ function handleMemoryProtocolCommand(parsed, context3) {
|
|
|
440464
440464
|
return;
|
|
440465
440465
|
}
|
|
440466
440466
|
}
|
|
440467
|
-
const buffer = await
|
|
440467
|
+
const buffer = await readFile16(absolutePath);
|
|
440468
440468
|
const content = encoding === "base64" ? buffer.toString("base64") : buffer.toString("utf-8");
|
|
440469
440469
|
const pathspec = rel.split(sep5).join("/");
|
|
440470
440470
|
safeSocketSend(socket, {
|
|
@@ -440506,15 +440506,15 @@ function handleMemoryProtocolCommand(parsed, context3) {
|
|
|
440506
440506
|
const { commitMemoryWrite: commitMemoryWrite2 } = await Promise.resolve().then(() => (init_memory_git(), exports_memory_git));
|
|
440507
440507
|
const { writeFile: writeFile13, mkdir: mkdir11 } = await import("node:fs/promises");
|
|
440508
440508
|
const { existsSync: existsSync41 } = await import("node:fs");
|
|
440509
|
-
const { dirname: dirname21, isAbsolute:
|
|
440510
|
-
if (
|
|
440509
|
+
const { dirname: dirname21, isAbsolute: isAbsolute23, join: join42, normalize: normalize5, relative: relative10, sep: sep5 } = await import("node:path");
|
|
440510
|
+
if (isAbsolute23(parsed.path) || parsed.path.length === 0) {
|
|
440511
440511
|
sendFailure("write_memory_file: path must be a non-empty relative path");
|
|
440512
440512
|
return;
|
|
440513
440513
|
}
|
|
440514
440514
|
const memoryRoot = getScopedMemoryFilesystemRoot2(parsed.agent_id);
|
|
440515
440515
|
const absolutePath = normalize5(join42(memoryRoot, parsed.path));
|
|
440516
440516
|
const rel = relative10(memoryRoot, absolutePath);
|
|
440517
|
-
if (rel.startsWith("..") || rel === "" ||
|
|
440517
|
+
if (rel.startsWith("..") || rel === "" || isAbsolute23(rel) || rel.split(sep5).includes("..")) {
|
|
440518
440518
|
sendFailure("write_memory_file: path must resolve inside the memory root");
|
|
440519
440519
|
return;
|
|
440520
440520
|
}
|
|
@@ -440609,15 +440609,15 @@ function handleMemoryProtocolCommand(parsed, context3) {
|
|
|
440609
440609
|
const { commitMemoryWrite: commitMemoryWrite2 } = await Promise.resolve().then(() => (init_memory_git(), exports_memory_git));
|
|
440610
440610
|
const { unlink: unlink4 } = await import("node:fs/promises");
|
|
440611
440611
|
const { existsSync: existsSync41 } = await import("node:fs");
|
|
440612
|
-
const { isAbsolute:
|
|
440613
|
-
if (
|
|
440612
|
+
const { isAbsolute: isAbsolute23, join: join42, normalize: normalize5, relative: relative10, sep: sep5 } = await import("node:path");
|
|
440613
|
+
if (isAbsolute23(parsed.path) || parsed.path.length === 0) {
|
|
440614
440614
|
sendFailure("delete_memory_file: path must be a non-empty relative path");
|
|
440615
440615
|
return;
|
|
440616
440616
|
}
|
|
440617
440617
|
const memoryRoot = getScopedMemoryFilesystemRoot2(parsed.agent_id);
|
|
440618
440618
|
const absolutePath = normalize5(join42(memoryRoot, parsed.path));
|
|
440619
440619
|
const rel = relative10(memoryRoot, absolutePath);
|
|
440620
|
-
if (rel.startsWith("..") || rel === "" ||
|
|
440620
|
+
if (rel.startsWith("..") || rel === "" || isAbsolute23(rel) || rel.split(sep5).includes("..")) {
|
|
440621
440621
|
sendFailure("delete_memory_file: path must resolve inside the memory root");
|
|
440622
440622
|
return;
|
|
440623
440623
|
}
|
|
@@ -441269,7 +441269,7 @@ var init_skills_agents = __esm(() => {
|
|
|
441269
441269
|
});
|
|
441270
441270
|
|
|
441271
441271
|
// src/websocket/listener/message-router.ts
|
|
441272
|
-
function
|
|
441272
|
+
function isRecord6(value) {
|
|
441273
441273
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
441274
441274
|
}
|
|
441275
441275
|
function formatLogValue(value) {
|
|
@@ -441295,7 +441295,7 @@ function pushField(fields, key2, value, label = key2) {
|
|
|
441295
441295
|
}
|
|
441296
441296
|
}
|
|
441297
441297
|
function summarizeInputPayload(payload) {
|
|
441298
|
-
if (!
|
|
441298
|
+
if (!isRecord6(payload))
|
|
441299
441299
|
return [];
|
|
441300
441300
|
const fields = [];
|
|
441301
441301
|
pushField(fields, "kind", payload.kind);
|
|
@@ -441314,9 +441314,9 @@ function summarizeRuntimeStartCommand(command) {
|
|
|
441314
441314
|
const fields = [];
|
|
441315
441315
|
pushField(fields, "agent_id", command.agent_id, "agent");
|
|
441316
441316
|
pushField(fields, "conversation_id", command.conversation_id, "conversation");
|
|
441317
|
-
if (
|
|
441317
|
+
if (isRecord6(command.create_agent))
|
|
441318
441318
|
fields.push("create_agent=true");
|
|
441319
|
-
if (
|
|
441319
|
+
if (isRecord6(command.create_conversation)) {
|
|
441320
441320
|
fields.push("create_conversation=true");
|
|
441321
441321
|
}
|
|
441322
441322
|
pushField(fields, "cwd", command.cwd);
|
|
@@ -441325,17 +441325,17 @@ function summarizeRuntimeStartCommand(command) {
|
|
|
441325
441325
|
return fields;
|
|
441326
441326
|
}
|
|
441327
441327
|
function summarizeV2Command(parsed) {
|
|
441328
|
-
if (!
|
|
441328
|
+
if (!isRecord6(parsed) || typeof parsed.type !== "string")
|
|
441329
441329
|
return "unknown";
|
|
441330
441330
|
const fields = [];
|
|
441331
|
-
const runtime =
|
|
441331
|
+
const runtime = isRecord6(parsed.runtime) ? parsed.runtime : null;
|
|
441332
441332
|
if (runtime) {
|
|
441333
441333
|
fields.push(`runtime=${runtime.agent_id ?? "<unknown>"}/${runtime.conversation_id ?? "<unknown>"}`);
|
|
441334
441334
|
}
|
|
441335
441335
|
pushField(fields, "request_id", parsed.request_id);
|
|
441336
441336
|
if (parsed.type === "input") {
|
|
441337
441337
|
fields.push(...summarizeInputPayload(parsed.payload));
|
|
441338
|
-
} else if (parsed.type === "change_device_state" &&
|
|
441338
|
+
} else if (parsed.type === "change_device_state" && isRecord6(parsed.payload)) {
|
|
441339
441339
|
pushField(fields, "mode", parsed.payload.mode);
|
|
441340
441340
|
pushField(fields, "cwd", parsed.payload.cwd);
|
|
441341
441341
|
pushField(fields, "agent_id", parsed.payload.agent_id);
|
|
@@ -448237,7 +448237,7 @@ __export(exports_skills3, {
|
|
|
448237
448237
|
GLOBAL_SKILLS_DIR: () => GLOBAL_SKILLS_DIR2
|
|
448238
448238
|
});
|
|
448239
448239
|
import { existsSync as existsSync47 } from "node:fs";
|
|
448240
|
-
import { readdir as readdir12, readFile as
|
|
448240
|
+
import { readdir as readdir12, readFile as readFile16, realpath as realpath5, stat as stat11 } from "node:fs/promises";
|
|
448241
448241
|
import { dirname as dirname23, join as join49 } from "node:path";
|
|
448242
448242
|
import { fileURLToPath as fileURLToPath8 } from "node:url";
|
|
448243
448243
|
function getBundledSkillsPath2() {
|
|
@@ -448409,7 +448409,7 @@ async function findSkillFiles2(currentPath, rootPath, skills, errors7, source2,
|
|
|
448409
448409
|
}
|
|
448410
448410
|
}
|
|
448411
448411
|
async function parseSkillFile2(filePath, rootPath, source2) {
|
|
448412
|
-
const content = await
|
|
448412
|
+
const content = await readFile16(filePath, "utf-8");
|
|
448413
448413
|
const { frontmatter, body: body3 } = parseFrontmatter(content);
|
|
448414
448414
|
const normalizedRoot = rootPath.endsWith("/") ? rootPath.slice(0, -1) : rootPath;
|
|
448415
448415
|
const relativePath = filePath.slice(normalizedRoot.length + 1);
|
|
@@ -448470,7 +448470,7 @@ __export(exports_fs, {
|
|
|
448470
448470
|
writeJsonFile: () => writeJsonFile,
|
|
448471
448471
|
writeFile: () => writeFile14,
|
|
448472
448472
|
readJsonFile: () => readJsonFile3,
|
|
448473
|
-
readFile: () =>
|
|
448473
|
+
readFile: () => readFile17,
|
|
448474
448474
|
mkdir: () => mkdir12,
|
|
448475
448475
|
exists: () => exists2
|
|
448476
448476
|
});
|
|
@@ -448481,7 +448481,7 @@ import {
|
|
|
448481
448481
|
mkdirSync as mkdirSync35
|
|
448482
448482
|
} from "node:fs";
|
|
448483
448483
|
import { dirname as dirname24 } from "node:path";
|
|
448484
|
-
async function
|
|
448484
|
+
async function readFile17(path35) {
|
|
448485
448485
|
return fsReadFileSync2(path35, { encoding: "utf-8" });
|
|
448486
448486
|
}
|
|
448487
448487
|
async function writeFile14(path35, content) {
|
|
@@ -448498,7 +448498,7 @@ async function mkdir12(path35, options3) {
|
|
|
448498
448498
|
mkdirSync35(path35, options3);
|
|
448499
448499
|
}
|
|
448500
448500
|
async function readJsonFile3(path35) {
|
|
448501
|
-
const text2 = await
|
|
448501
|
+
const text2 = await readFile17(path35);
|
|
448502
448502
|
return JSON.parse(text2);
|
|
448503
448503
|
}
|
|
448504
448504
|
async function writeJsonFile(path35, data, options3) {
|
|
@@ -450399,8 +450399,8 @@ __export(exports_import, {
|
|
|
450399
450399
|
extractSkillsFromAf: () => extractSkillsFromAf
|
|
450400
450400
|
});
|
|
450401
450401
|
import { createReadStream as createReadStream2 } from "node:fs";
|
|
450402
|
-
import { access as access2, chmod, mkdir as mkdir13, readFile as
|
|
450403
|
-
import { dirname as dirname26, isAbsolute as
|
|
450402
|
+
import { access as access2, chmod, mkdir as mkdir13, readFile as readFile18, writeFile as writeFile15 } from "node:fs/promises";
|
|
450403
|
+
import { dirname as dirname26, isAbsolute as isAbsolute24, relative as relative10, resolve as resolve36, sep as sep6, win32 as win324 } from "node:path";
|
|
450404
450404
|
function validateImportedSkillName(name) {
|
|
450405
450405
|
const trimmedName = name.trim();
|
|
450406
450406
|
if (trimmedName !== name || trimmedName.length === 0 || trimmedName.length > MAX_SKILL_NAME_LENGTH || trimmedName === "." || trimmedName === ".." || !IMPORTED_SKILL_NAME_PATTERN.test(trimmedName)) {
|
|
@@ -450412,12 +450412,12 @@ function assertPathInside(parent, child) {
|
|
|
450412
450412
|
const parentPath = resolve36(parent);
|
|
450413
450413
|
const childPath = resolve36(child);
|
|
450414
450414
|
const relativePath = relative10(parentPath, childPath);
|
|
450415
|
-
if (relativePath === "" || relativePath === ".." || relativePath.startsWith(`..${sep6}`) ||
|
|
450415
|
+
if (relativePath === "" || relativePath === ".." || relativePath.startsWith(`..${sep6}`) || isAbsolute24(relativePath)) {
|
|
450416
450416
|
throw new Error(`Imported skill file path escapes skill directory: ${child}`);
|
|
450417
450417
|
}
|
|
450418
450418
|
}
|
|
450419
450419
|
function validateImportedSkillFilePath(filePath) {
|
|
450420
|
-
if (filePath.length === 0 || filePath === "." || filePath.includes("\x00") || filePath.includes("\\") ||
|
|
450420
|
+
if (filePath.length === 0 || filePath === "." || filePath.includes("\x00") || filePath.includes("\\") || isAbsolute24(filePath) || win324.isAbsolute(filePath)) {
|
|
450421
450421
|
throw new Error(`Invalid imported skill file path "${filePath}".`);
|
|
450422
450422
|
}
|
|
450423
450423
|
const segments = filePath.split("/");
|
|
@@ -450502,7 +450502,7 @@ async function importAgentFromFile(options3) {
|
|
|
450502
450502
|
}
|
|
450503
450503
|
async function extractSkillsFromAf(afPath, destDir) {
|
|
450504
450504
|
const extracted = [];
|
|
450505
|
-
const content = await
|
|
450505
|
+
const content = await readFile18(afPath, "utf-8");
|
|
450506
450506
|
const afData = JSON.parse(content);
|
|
450507
450507
|
if (!afData.skills || !Array.isArray(afData.skills)) {
|
|
450508
450508
|
return [];
|
|
@@ -476086,7 +476086,7 @@ var init_PersonalitySelector = __esm(async () => {
|
|
|
476086
476086
|
});
|
|
476087
476087
|
|
|
476088
476088
|
// src/utils/aws-credentials.ts
|
|
476089
|
-
import { readFile as
|
|
476089
|
+
import { readFile as readFile19 } from "node:fs/promises";
|
|
476090
476090
|
import { homedir as homedir38 } from "node:os";
|
|
476091
476091
|
import { join as join61 } from "node:path";
|
|
476092
476092
|
async function parseAwsCredentials() {
|
|
@@ -476094,11 +476094,11 @@ async function parseAwsCredentials() {
|
|
|
476094
476094
|
const configPath = join61(homedir38(), ".aws", "config");
|
|
476095
476095
|
const profiles = new Map;
|
|
476096
476096
|
try {
|
|
476097
|
-
const content = await
|
|
476097
|
+
const content = await readFile19(credentialsPath, "utf-8");
|
|
476098
476098
|
parseIniFile(content, profiles, false);
|
|
476099
476099
|
} catch {}
|
|
476100
476100
|
try {
|
|
476101
|
-
const content = await
|
|
476101
|
+
const content = await readFile19(configPath, "utf-8");
|
|
476102
476102
|
parseIniFile(content, profiles, true);
|
|
476103
476103
|
} catch {}
|
|
476104
476104
|
return Array.from(profiles.values());
|
|
@@ -496678,7 +496678,7 @@ __export(exports_generate_diff_viewer, {
|
|
|
496678
496678
|
import { execFile as execFileCb5 } from "node:child_process";
|
|
496679
496679
|
import { chmodSync as chmodSync9, existsSync as existsSync58, mkdirSync as mkdirSync43, writeFileSync as writeFileSync31 } from "node:fs";
|
|
496680
496680
|
import { homedir as homedir39 } from "node:os";
|
|
496681
|
-
import { isAbsolute as
|
|
496681
|
+
import { isAbsolute as isAbsolute25, join as join62, resolve as resolve39 } from "node:path";
|
|
496682
496682
|
import { promisify as promisify16 } from "node:util";
|
|
496683
496683
|
async function runGit5(cwd2, args) {
|
|
496684
496684
|
try {
|
|
@@ -496876,7 +496876,7 @@ function escapeHtml2(value) {
|
|
|
496876
496876
|
function resolveTargetPath(targetPath) {
|
|
496877
496877
|
if (!targetPath?.trim())
|
|
496878
496878
|
return process.cwd();
|
|
496879
|
-
return
|
|
496879
|
+
return isAbsolute25(targetPath) ? targetPath : resolve39(process.cwd(), targetPath);
|
|
496880
496880
|
}
|
|
496881
496881
|
function shouldSkipOpen() {
|
|
496882
496882
|
return Boolean(process.env.TMUX) || Boolean(process.env.SSH_CONNECTION) || Boolean(process.env.SSH_TTY);
|
|
@@ -505046,7 +505046,7 @@ var exports_export = {};
|
|
|
505046
505046
|
__export(exports_export, {
|
|
505047
505047
|
packageSkills: () => packageSkills
|
|
505048
505048
|
});
|
|
505049
|
-
import { readdir as readdir14, readFile as
|
|
505049
|
+
import { readdir as readdir14, readFile as readFile20 } from "node:fs/promises";
|
|
505050
505050
|
import { relative as relative13, resolve as resolve40 } from "node:path";
|
|
505051
505051
|
async function packageSkills(agentId, skillsDir) {
|
|
505052
505052
|
const skills = [];
|
|
@@ -505067,7 +505067,7 @@ async function packageSkills(agentId, skillsDir) {
|
|
|
505067
505067
|
const skillDir = resolve40(baseDir, entry.name);
|
|
505068
505068
|
const skillMdPath = resolve40(skillDir, "SKILL.md");
|
|
505069
505069
|
try {
|
|
505070
|
-
await
|
|
505070
|
+
await readFile20(skillMdPath, "utf-8");
|
|
505071
505071
|
} catch {
|
|
505072
505072
|
console.warn(`Skipping invalid skill ${entry.name}: missing SKILL.md`);
|
|
505073
505073
|
continue;
|
|
@@ -505099,7 +505099,7 @@ async function readSkillFiles(skillDir) {
|
|
|
505099
505099
|
if (entry.isDirectory()) {
|
|
505100
505100
|
await walk(fullPath);
|
|
505101
505101
|
} else {
|
|
505102
|
-
const content = await
|
|
505102
|
+
const content = await readFile20(fullPath, "utf-8");
|
|
505103
505103
|
const relativePath = relative13(skillDir, fullPath).replace(/\\/g, "/");
|
|
505104
505104
|
files[relativePath] = content;
|
|
505105
505105
|
}
|
|
@@ -511641,8 +511641,8 @@ __export(exports_import2, {
|
|
|
511641
511641
|
extractSkillsFromAf: () => extractSkillsFromAf2
|
|
511642
511642
|
});
|
|
511643
511643
|
import { createReadStream as createReadStream3 } from "node:fs";
|
|
511644
|
-
import { access as access3, chmod as chmod2, mkdir as mkdir14, readFile as
|
|
511645
|
-
import { dirname as dirname30, isAbsolute as
|
|
511644
|
+
import { access as access3, chmod as chmod2, mkdir as mkdir14, readFile as readFile21, writeFile as writeFile16 } from "node:fs/promises";
|
|
511645
|
+
import { dirname as dirname30, isAbsolute as isAbsolute26, relative as relative14, resolve as resolve41, sep as sep7, win32 as win325 } from "node:path";
|
|
511646
511646
|
function validateImportedSkillName2(name) {
|
|
511647
511647
|
const trimmedName = name.trim();
|
|
511648
511648
|
if (trimmedName !== name || trimmedName.length === 0 || trimmedName.length > MAX_SKILL_NAME_LENGTH || trimmedName === "." || trimmedName === ".." || !IMPORTED_SKILL_NAME_PATTERN2.test(trimmedName)) {
|
|
@@ -511654,12 +511654,12 @@ function assertPathInside2(parent, child) {
|
|
|
511654
511654
|
const parentPath = resolve41(parent);
|
|
511655
511655
|
const childPath = resolve41(child);
|
|
511656
511656
|
const relativePath = relative14(parentPath, childPath);
|
|
511657
|
-
if (relativePath === "" || relativePath === ".." || relativePath.startsWith(`..${sep7}`) ||
|
|
511657
|
+
if (relativePath === "" || relativePath === ".." || relativePath.startsWith(`..${sep7}`) || isAbsolute26(relativePath)) {
|
|
511658
511658
|
throw new Error(`Imported skill file path escapes skill directory: ${child}`);
|
|
511659
511659
|
}
|
|
511660
511660
|
}
|
|
511661
511661
|
function validateImportedSkillFilePath2(filePath) {
|
|
511662
|
-
if (filePath.length === 0 || filePath === "." || filePath.includes("\x00") || filePath.includes("\\") ||
|
|
511662
|
+
if (filePath.length === 0 || filePath === "." || filePath.includes("\x00") || filePath.includes("\\") || isAbsolute26(filePath) || win325.isAbsolute(filePath)) {
|
|
511663
511663
|
throw new Error(`Invalid imported skill file path "${filePath}".`);
|
|
511664
511664
|
}
|
|
511665
511665
|
const segments = filePath.split("/");
|
|
@@ -511744,7 +511744,7 @@ async function importAgentFromFile2(options3) {
|
|
|
511744
511744
|
}
|
|
511745
511745
|
async function extractSkillsFromAf2(afPath, destDir) {
|
|
511746
511746
|
const extracted = [];
|
|
511747
|
-
const content = await
|
|
511747
|
+
const content = await readFile21(afPath, "utf-8");
|
|
511748
511748
|
const afData = JSON.parse(content);
|
|
511749
511749
|
if (!afData.skills || !Array.isArray(afData.skills)) {
|
|
511750
511750
|
return [];
|
|
@@ -512386,9 +512386,9 @@ __export(exports_system_prompt_versioning2, {
|
|
|
512386
512386
|
LETTA_CODE_SUBAGENT_TAG: () => LETTA_CODE_SUBAGENT_TAG2,
|
|
512387
512387
|
LETTA_CODE_ORIGIN_TAG: () => LETTA_CODE_ORIGIN_TAG2
|
|
512388
512388
|
});
|
|
512389
|
-
import { createHash as
|
|
512389
|
+
import { createHash as createHash6 } from "node:crypto";
|
|
512390
512390
|
function hashSystemPrompt2(content) {
|
|
512391
|
-
const digest =
|
|
512391
|
+
const digest = createHash6("sha256").update(content).digest("base64url");
|
|
512392
512392
|
return `${SYSTEM_PROMPT_HASH_PREFIX2}${digest}`;
|
|
512393
512393
|
}
|
|
512394
512394
|
function managedPrompt2(preset, memoryMode, content = buildSystemPrompt(preset, memoryMode)) {
|
|
@@ -516998,25 +516998,313 @@ import { parseArgs as parseArgs3 } from "node:util";
|
|
|
516998
516998
|
// src/websocket/app-server.ts
|
|
516999
516999
|
init_settings_manager();
|
|
517000
517000
|
init_telemetry();
|
|
517001
|
-
|
|
517002
|
-
await __promiseAll([
|
|
517003
|
-
init_manager4(),
|
|
517004
|
-
init_lifecycle(),
|
|
517005
|
-
init_mod_adapter2()
|
|
517006
|
-
]);
|
|
517001
|
+
await init_manager4();
|
|
517007
517002
|
import { createServer } from "node:http";
|
|
517008
517003
|
import { hostname as hostname4 } from "node:os";
|
|
517009
517004
|
import WebSocket7, { WebSocketServer } from "ws";
|
|
517010
|
-
|
|
517011
|
-
|
|
517012
|
-
|
|
517013
|
-
|
|
517005
|
+
|
|
517006
|
+
// src/websocket/app-server-auth.ts
|
|
517007
|
+
import { createHash as createHash4, createHmac, timingSafeEqual } from "node:crypto";
|
|
517008
|
+
import { readFile as readFile11 } from "node:fs/promises";
|
|
517009
|
+
import { isIP as isIP2 } from "node:net";
|
|
517010
|
+
import { isAbsolute as isAbsolute22 } from "node:path";
|
|
517011
|
+
var INVALID_AUTHORIZATION_HEADER_MESSAGE = "invalid authorization header";
|
|
517012
|
+
var DEFAULT_MAX_CLOCK_SKEW_SECONDS = 30;
|
|
517013
|
+
var MIN_SIGNED_BEARER_SECRET_BYTES = 32;
|
|
517014
|
+
function parseAppServerWebsocketAuthSettings(args) {
|
|
517015
|
+
const hasSignedBearerFlag = Boolean(args.wsSharedSecretFile !== undefined || args.wsIssuer !== undefined || args.wsAudience !== undefined || args.wsMaxClockSkewSeconds !== undefined);
|
|
517016
|
+
switch (args.wsAuth) {
|
|
517017
|
+
case undefined:
|
|
517018
|
+
if (args.wsTokenFile !== undefined || args.wsTokenSha256 !== undefined || hasSignedBearerFlag) {
|
|
517019
|
+
throw new Error("websocket auth flags require `--ws-auth capability-token` or `--ws-auth signed-bearer-token`");
|
|
517020
|
+
}
|
|
517021
|
+
return {};
|
|
517022
|
+
case "capability-token": {
|
|
517023
|
+
if (hasSignedBearerFlag) {
|
|
517024
|
+
throw new Error("`--ws-shared-secret-file`, `--ws-issuer`, `--ws-audience`, and `--ws-max-clock-skew-seconds` require `--ws-auth signed-bearer-token`");
|
|
517025
|
+
}
|
|
517026
|
+
const hasTokenFile = args.wsTokenFile !== undefined;
|
|
517027
|
+
const hasTokenSha256 = args.wsTokenSha256 !== undefined;
|
|
517028
|
+
if (hasTokenFile && hasTokenSha256) {
|
|
517029
|
+
throw new Error("`--ws-token-file` and `--ws-token-sha256` are mutually exclusive");
|
|
517030
|
+
}
|
|
517031
|
+
if (!hasTokenFile && !hasTokenSha256) {
|
|
517032
|
+
throw new Error("`--ws-token-file` or `--ws-token-sha256` is required when `--ws-auth capability-token` is set");
|
|
517033
|
+
}
|
|
517034
|
+
return {
|
|
517035
|
+
config: {
|
|
517036
|
+
mode: "capability-token",
|
|
517037
|
+
source: args.wsTokenFile ? {
|
|
517038
|
+
type: "token-file",
|
|
517039
|
+
tokenFile: absolutePathArg("--ws-token-file", args.wsTokenFile)
|
|
517040
|
+
} : {
|
|
517041
|
+
type: "token-sha256",
|
|
517042
|
+
tokenSha256: sha256DigestArg("--ws-token-sha256", args.wsTokenSha256)
|
|
517043
|
+
}
|
|
517044
|
+
}
|
|
517045
|
+
};
|
|
517046
|
+
}
|
|
517047
|
+
case "signed-bearer-token": {
|
|
517048
|
+
if (args.wsTokenFile !== undefined || args.wsTokenSha256 !== undefined) {
|
|
517049
|
+
throw new Error("`--ws-token-file` and `--ws-token-sha256` require `--ws-auth capability-token`, not `signed-bearer-token`");
|
|
517050
|
+
}
|
|
517051
|
+
if (args.wsSharedSecretFile === undefined) {
|
|
517052
|
+
throw new Error("`--ws-shared-secret-file` is required when `--ws-auth signed-bearer-token` is set");
|
|
517053
|
+
}
|
|
517054
|
+
return {
|
|
517055
|
+
config: {
|
|
517056
|
+
mode: "signed-bearer-token",
|
|
517057
|
+
sharedSecretFile: absolutePathArg("--ws-shared-secret-file", args.wsSharedSecretFile),
|
|
517058
|
+
issuer: normalizeOptionalString(args.wsIssuer),
|
|
517059
|
+
audience: normalizeOptionalString(args.wsAudience),
|
|
517060
|
+
maxClockSkewSeconds: args.wsMaxClockSkewSeconds !== undefined ? nonNegativeIntegerArg("--ws-max-clock-skew-seconds", args.wsMaxClockSkewSeconds) : DEFAULT_MAX_CLOCK_SKEW_SECONDS
|
|
517061
|
+
}
|
|
517062
|
+
};
|
|
517063
|
+
}
|
|
517064
|
+
default:
|
|
517065
|
+
throw new Error(`unsupported --ws-auth mode "${args.wsAuth}"; expected "capability-token" or "signed-bearer-token"`);
|
|
517066
|
+
}
|
|
517067
|
+
}
|
|
517068
|
+
async function policyFromSettings(settings3 = {}) {
|
|
517069
|
+
const config3 = settings3.config;
|
|
517070
|
+
if (!config3) {
|
|
517071
|
+
return {};
|
|
517072
|
+
}
|
|
517073
|
+
switch (config3.mode) {
|
|
517074
|
+
case "capability-token":
|
|
517075
|
+
return {
|
|
517076
|
+
mode: {
|
|
517077
|
+
type: "capability-token",
|
|
517078
|
+
tokenSha256: config3.source.type === "token-file" ? sha256Digest(await readTrimmedSecret(config3.source.tokenFile)) : config3.source.tokenSha256
|
|
517079
|
+
}
|
|
517080
|
+
};
|
|
517081
|
+
case "signed-bearer-token": {
|
|
517082
|
+
const sharedSecret = Buffer.from(await readTrimmedSecret(config3.sharedSecretFile), "utf8");
|
|
517083
|
+
validateSignedBearerSecret(config3.sharedSecretFile, sharedSecret);
|
|
517084
|
+
return {
|
|
517085
|
+
mode: {
|
|
517086
|
+
type: "signed-bearer-token",
|
|
517087
|
+
sharedSecret,
|
|
517088
|
+
issuer: config3.issuer,
|
|
517089
|
+
audience: config3.audience,
|
|
517090
|
+
maxClockSkewSeconds: config3.maxClockSkewSeconds
|
|
517091
|
+
}
|
|
517092
|
+
};
|
|
517093
|
+
}
|
|
517094
|
+
}
|
|
517095
|
+
}
|
|
517096
|
+
function isUnauthenticatedNonLoopbackListener(host, policy) {
|
|
517097
|
+
return !isLoopbackListenHost(host) && !policy.mode;
|
|
517098
|
+
}
|
|
517099
|
+
function isLoopbackListenHost(host) {
|
|
517014
517100
|
const normalized = normalizeListenHost(host);
|
|
517015
|
-
|
|
517101
|
+
if (normalized === "localhost") {
|
|
517102
|
+
return true;
|
|
517103
|
+
}
|
|
517104
|
+
if (isIP2(normalized) === 4) {
|
|
517105
|
+
return normalized.startsWith("127.");
|
|
517106
|
+
}
|
|
517107
|
+
return normalized === "::1";
|
|
517016
517108
|
}
|
|
517017
517109
|
function normalizeListenHost(host) {
|
|
517018
517110
|
return host.toLowerCase().replace(/^\[/, "").replace(/\]$/, "");
|
|
517019
517111
|
}
|
|
517112
|
+
function authorizeUpgrade(headers, policy) {
|
|
517113
|
+
const mode = policy.mode;
|
|
517114
|
+
if (!mode) {
|
|
517115
|
+
return null;
|
|
517116
|
+
}
|
|
517117
|
+
const tokenResult = bearerTokenFromHeaders(headers);
|
|
517118
|
+
if (typeof tokenResult !== "string") {
|
|
517119
|
+
return tokenResult;
|
|
517120
|
+
}
|
|
517121
|
+
switch (mode.type) {
|
|
517122
|
+
case "capability-token": {
|
|
517123
|
+
const actualSha256 = sha256Digest(tokenResult);
|
|
517124
|
+
if (timingSafeEqual(mode.tokenSha256, actualSha256)) {
|
|
517125
|
+
return null;
|
|
517126
|
+
}
|
|
517127
|
+
return unauthorized("invalid websocket bearer token");
|
|
517128
|
+
}
|
|
517129
|
+
case "signed-bearer-token":
|
|
517130
|
+
return verifySignedBearerToken(tokenResult, mode.sharedSecret, mode.issuer, mode.audience, mode.maxClockSkewSeconds);
|
|
517131
|
+
}
|
|
517132
|
+
}
|
|
517133
|
+
function verifySignedBearerToken(token2, sharedSecret, issuer, audience, maxClockSkewSeconds) {
|
|
517134
|
+
const claims = decodeJwtClaims(token2, sharedSecret);
|
|
517135
|
+
if ("error" in claims) {
|
|
517136
|
+
return claims.error;
|
|
517137
|
+
}
|
|
517138
|
+
return validateJwtClaims(claims.claims, issuer, audience, maxClockSkewSeconds);
|
|
517139
|
+
}
|
|
517140
|
+
function decodeJwtClaims(token2, sharedSecret) {
|
|
517141
|
+
const parts = token2.split(".");
|
|
517142
|
+
const encodedHeader = parts[0];
|
|
517143
|
+
const encodedClaims = parts[1];
|
|
517144
|
+
const encodedSignature = parts[2];
|
|
517145
|
+
if (parts.length !== 3 || !encodedHeader || !encodedClaims || !encodedSignature) {
|
|
517146
|
+
return { error: unauthorized("invalid websocket jwt") };
|
|
517147
|
+
}
|
|
517148
|
+
let header;
|
|
517149
|
+
let claims;
|
|
517150
|
+
let actualSignature;
|
|
517151
|
+
try {
|
|
517152
|
+
header = JSON.parse(base64UrlDecode(encodedHeader).toString("utf8"));
|
|
517153
|
+
claims = JSON.parse(base64UrlDecode(encodedClaims).toString("utf8"));
|
|
517154
|
+
actualSignature = base64UrlDecode(encodedSignature);
|
|
517155
|
+
} catch {
|
|
517156
|
+
return { error: unauthorized("invalid websocket jwt") };
|
|
517157
|
+
}
|
|
517158
|
+
if (!isRecord5(header) || header.alg !== "HS256") {
|
|
517159
|
+
return { error: unauthorized("invalid websocket jwt") };
|
|
517160
|
+
}
|
|
517161
|
+
const expectedSignature = createHmac("sha256", sharedSecret).update(`${encodedHeader}.${encodedClaims}`).digest();
|
|
517162
|
+
if (actualSignature.length !== expectedSignature.length || !timingSafeEqual(actualSignature, expectedSignature)) {
|
|
517163
|
+
return { error: unauthorized("invalid websocket jwt") };
|
|
517164
|
+
}
|
|
517165
|
+
if (!isJwtClaims(claims)) {
|
|
517166
|
+
return { error: unauthorized("invalid websocket jwt") };
|
|
517167
|
+
}
|
|
517168
|
+
return { claims };
|
|
517169
|
+
}
|
|
517170
|
+
function validateJwtClaims(claims, issuer, audience, maxClockSkewSeconds) {
|
|
517171
|
+
const now = Math.floor(Date.now() / 1000);
|
|
517172
|
+
if (now > claims.exp + maxClockSkewSeconds) {
|
|
517173
|
+
return unauthorized("expired websocket jwt");
|
|
517174
|
+
}
|
|
517175
|
+
if (claims.nbf !== undefined && now < claims.nbf - maxClockSkewSeconds) {
|
|
517176
|
+
return unauthorized("websocket jwt is not valid yet");
|
|
517177
|
+
}
|
|
517178
|
+
if (issuer !== undefined && claims.iss !== issuer) {
|
|
517179
|
+
return unauthorized("websocket jwt issuer mismatch");
|
|
517180
|
+
}
|
|
517181
|
+
if (audience !== undefined && !audienceMatches(claims.aud, audience)) {
|
|
517182
|
+
return unauthorized("websocket jwt audience mismatch");
|
|
517183
|
+
}
|
|
517184
|
+
return null;
|
|
517185
|
+
}
|
|
517186
|
+
function audienceMatches(actual, expectedAudience) {
|
|
517187
|
+
if (typeof actual === "string") {
|
|
517188
|
+
return actual === expectedAudience;
|
|
517189
|
+
}
|
|
517190
|
+
if (Array.isArray(actual)) {
|
|
517191
|
+
return actual.some((audience) => audience === expectedAudience);
|
|
517192
|
+
}
|
|
517193
|
+
return false;
|
|
517194
|
+
}
|
|
517195
|
+
function isJwtClaims(value) {
|
|
517196
|
+
if (!isRecord5(value) || !Number.isSafeInteger(value.exp)) {
|
|
517197
|
+
return false;
|
|
517198
|
+
}
|
|
517199
|
+
if (value.nbf !== undefined && !Number.isSafeInteger(value.nbf)) {
|
|
517200
|
+
return false;
|
|
517201
|
+
}
|
|
517202
|
+
if (value.iss !== undefined && typeof value.iss !== "string") {
|
|
517203
|
+
return false;
|
|
517204
|
+
}
|
|
517205
|
+
if (value.aud !== undefined) {
|
|
517206
|
+
if (typeof value.aud === "string") {
|
|
517207
|
+
return true;
|
|
517208
|
+
}
|
|
517209
|
+
if (!Array.isArray(value.aud)) {
|
|
517210
|
+
return false;
|
|
517211
|
+
}
|
|
517212
|
+
return value.aud.every((audience) => typeof audience === "string");
|
|
517213
|
+
}
|
|
517214
|
+
return true;
|
|
517215
|
+
}
|
|
517216
|
+
function isRecord5(value) {
|
|
517217
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
517218
|
+
}
|
|
517219
|
+
function base64UrlDecode(value) {
|
|
517220
|
+
if (!/^[A-Za-z0-9_-]*$/.test(value)) {
|
|
517221
|
+
throw new Error("invalid base64url");
|
|
517222
|
+
}
|
|
517223
|
+
const base644 = value.replace(/-/g, "+").replace(/_/g, "/");
|
|
517224
|
+
const padding = "=".repeat((4 - base644.length % 4) % 4);
|
|
517225
|
+
return Buffer.from(`${base644}${padding}`, "base64");
|
|
517226
|
+
}
|
|
517227
|
+
function bearerTokenFromHeaders(headers) {
|
|
517228
|
+
const rawHeader = headers.authorization;
|
|
517229
|
+
if (rawHeader === undefined) {
|
|
517230
|
+
return unauthorized("missing websocket bearer token");
|
|
517231
|
+
}
|
|
517232
|
+
if (Array.isArray(rawHeader)) {
|
|
517233
|
+
return unauthorized(INVALID_AUTHORIZATION_HEADER_MESSAGE);
|
|
517234
|
+
}
|
|
517235
|
+
const separatorIndex = rawHeader.indexOf(" ");
|
|
517236
|
+
if (separatorIndex === -1) {
|
|
517237
|
+
return unauthorized(INVALID_AUTHORIZATION_HEADER_MESSAGE);
|
|
517238
|
+
}
|
|
517239
|
+
const scheme = rawHeader.slice(0, separatorIndex);
|
|
517240
|
+
if (scheme.toLowerCase() !== "bearer") {
|
|
517241
|
+
return unauthorized(INVALID_AUTHORIZATION_HEADER_MESSAGE);
|
|
517242
|
+
}
|
|
517243
|
+
const token2 = rawHeader.slice(separatorIndex + 1).trim();
|
|
517244
|
+
if (!token2) {
|
|
517245
|
+
return unauthorized(INVALID_AUTHORIZATION_HEADER_MESSAGE);
|
|
517246
|
+
}
|
|
517247
|
+
return token2;
|
|
517248
|
+
}
|
|
517249
|
+
async function readTrimmedSecret(path26) {
|
|
517250
|
+
let raw2;
|
|
517251
|
+
try {
|
|
517252
|
+
raw2 = await readFile11(path26, "utf8");
|
|
517253
|
+
} catch (error54) {
|
|
517254
|
+
const message = error54 instanceof Error ? error54.message : String(error54);
|
|
517255
|
+
throw new Error(`failed to read websocket auth secret ${path26}: ${message}`);
|
|
517256
|
+
}
|
|
517257
|
+
const trimmed = raw2.trim();
|
|
517258
|
+
if (!trimmed) {
|
|
517259
|
+
throw new Error(`websocket auth secret ${path26} must not be empty`);
|
|
517260
|
+
}
|
|
517261
|
+
return trimmed;
|
|
517262
|
+
}
|
|
517263
|
+
function absolutePathArg(flagName, path26) {
|
|
517264
|
+
if (!isAbsolute22(path26)) {
|
|
517265
|
+
throw new Error(`${flagName} must be an absolute path`);
|
|
517266
|
+
}
|
|
517267
|
+
return path26;
|
|
517268
|
+
}
|
|
517269
|
+
function nonNegativeIntegerArg(flagName, value) {
|
|
517270
|
+
const parsed = typeof value === "number" ? value : Number(value.trim());
|
|
517271
|
+
if (!Number.isSafeInteger(parsed) || parsed < 0) {
|
|
517272
|
+
throw new Error(`${flagName} must be a non-negative integer`);
|
|
517273
|
+
}
|
|
517274
|
+
return parsed;
|
|
517275
|
+
}
|
|
517276
|
+
function normalizeOptionalString(value) {
|
|
517277
|
+
const trimmed = value?.trim();
|
|
517278
|
+
return trimmed ? trimmed : undefined;
|
|
517279
|
+
}
|
|
517280
|
+
function validateSignedBearerSecret(path26, sharedSecret) {
|
|
517281
|
+
if (sharedSecret.length < MIN_SIGNED_BEARER_SECRET_BYTES) {
|
|
517282
|
+
throw new Error(`signed websocket bearer secret ${path26} must be at least ${MIN_SIGNED_BEARER_SECRET_BYTES} bytes`);
|
|
517283
|
+
}
|
|
517284
|
+
}
|
|
517285
|
+
function sha256DigestArg(flagName, value) {
|
|
517286
|
+
const trimmed = value.trim();
|
|
517287
|
+
if (!/^[0-9a-fA-F]{64}$/.test(trimmed)) {
|
|
517288
|
+
throw new Error(`${flagName} must be a 64-character hex SHA-256 digest`);
|
|
517289
|
+
}
|
|
517290
|
+
return Buffer.from(trimmed, "hex");
|
|
517291
|
+
}
|
|
517292
|
+
function sha256Digest(value) {
|
|
517293
|
+
return createHash4("sha256").update(value).digest();
|
|
517294
|
+
}
|
|
517295
|
+
function unauthorized(message) {
|
|
517296
|
+
return { statusCode: 401, message };
|
|
517297
|
+
}
|
|
517298
|
+
|
|
517299
|
+
// src/websocket/app-server.ts
|
|
517300
|
+
init_runtime6();
|
|
517301
|
+
await __promiseAll([
|
|
517302
|
+
init_lifecycle(),
|
|
517303
|
+
init_mod_adapter2()
|
|
517304
|
+
]);
|
|
517305
|
+
var DEFAULT_LISTEN_URL = "ws://127.0.0.1:0";
|
|
517306
|
+
var DEFAULT_WS_PATH = "/ws";
|
|
517307
|
+
var PENDING_STREAM_TIMEOUT_MS = 5000;
|
|
517020
517308
|
function getRequiredAddressInfo(server2) {
|
|
517021
517309
|
const address = server2.address();
|
|
517022
517310
|
if (!address || typeof address === "string") {
|
|
@@ -517043,12 +517331,11 @@ function terminateSocket(socket) {
|
|
|
517043
517331
|
socket.terminate();
|
|
517044
517332
|
}
|
|
517045
517333
|
function rejectUpgrade(socket, statusCode2, message) {
|
|
517046
|
-
socket.
|
|
517334
|
+
socket.end(`HTTP/1.1 ${statusCode2} ${message}\r
|
|
517047
517335
|
Connection: close\r
|
|
517048
517336
|
Content-Length: 0\r
|
|
517049
517337
|
\r
|
|
517050
517338
|
`);
|
|
517051
|
-
socket.destroy();
|
|
517052
517339
|
}
|
|
517053
517340
|
function getRequestUrl(request, host) {
|
|
517054
517341
|
return new URL(request.url ?? "/", `http://${request.headers.host ?? host}`);
|
|
@@ -517091,9 +517378,6 @@ function parseAppServerListenUrl(listen = DEFAULT_LISTEN_URL) {
|
|
|
517091
517378
|
if (url2.protocol !== "ws:") {
|
|
517092
517379
|
throw new Error("app-server MVP only supports ws:// listen URLs");
|
|
517093
517380
|
}
|
|
517094
|
-
if (!isLoopbackHost(url2.hostname)) {
|
|
517095
|
-
throw new Error("app-server websocket listen host must be loopback for now");
|
|
517096
|
-
}
|
|
517097
517381
|
if (url2.username || url2.password || url2.search || url2.hash) {
|
|
517098
517382
|
throw new Error("app-server listen URL cannot include auth, query, or hash");
|
|
517099
517383
|
}
|
|
@@ -517147,6 +517431,10 @@ async function startControlSession(params) {
|
|
|
517147
517431
|
async function startAppServer(options3 = {}) {
|
|
517148
517432
|
await settingsManager.initialize();
|
|
517149
517433
|
const listen = parseAppServerListenUrl(options3.listen);
|
|
517434
|
+
const authPolicy = await policyFromSettings(options3.websocketAuth);
|
|
517435
|
+
if (isUnauthenticatedNonLoopbackListener(listen.host, authPolicy)) {
|
|
517436
|
+
throw new Error(`refusing to start non-loopback websocket listener ${listen.host}:${listen.port} without auth; configure \`--ws-auth capability-token\` or \`--ws-auth signed-bearer-token\``);
|
|
517437
|
+
}
|
|
517150
517438
|
const wss = new WebSocketServer({ noServer: true });
|
|
517151
517439
|
let activeSession = null;
|
|
517152
517440
|
let pendingStreamSocket = null;
|
|
@@ -517213,6 +517501,12 @@ async function startAppServer(options3 = {}) {
|
|
|
517213
517501
|
};
|
|
517214
517502
|
const server2 = createServer((request, response) => {
|
|
517215
517503
|
const requestUrl = getRequestUrl(request, listen.host);
|
|
517504
|
+
if (request.headers.origin) {
|
|
517505
|
+
options3.onLog?.(`Rejecting app-server request with Origin header: ${request.url ?? "/"}`);
|
|
517506
|
+
response.writeHead(403);
|
|
517507
|
+
response.end();
|
|
517508
|
+
return;
|
|
517509
|
+
}
|
|
517216
517510
|
if (requestUrl.pathname === "/readyz") {
|
|
517217
517511
|
response.writeHead(200, { "content-type": "text/plain" });
|
|
517218
517512
|
response.end(`ok
|
|
@@ -517220,11 +517514,6 @@ async function startAppServer(options3 = {}) {
|
|
|
517220
517514
|
return;
|
|
517221
517515
|
}
|
|
517222
517516
|
if (requestUrl.pathname === "/healthz") {
|
|
517223
|
-
if (request.headers.origin) {
|
|
517224
|
-
response.writeHead(403);
|
|
517225
|
-
response.end();
|
|
517226
|
-
return;
|
|
517227
|
-
}
|
|
517228
517517
|
response.writeHead(200, { "content-type": "text/plain" });
|
|
517229
517518
|
response.end(`ok
|
|
517230
517519
|
`);
|
|
@@ -517235,6 +517524,11 @@ async function startAppServer(options3 = {}) {
|
|
|
517235
517524
|
});
|
|
517236
517525
|
server2.on("upgrade", (request, socket, head2) => {
|
|
517237
517526
|
const requestUrl = getRequestUrl(request, listen.host);
|
|
517527
|
+
if (request.headers.origin) {
|
|
517528
|
+
options3.onLog?.(`Rejecting app-server websocket request with Origin header: ${request.url ?? "/"}`);
|
|
517529
|
+
rejectUpgrade(socket, 403, "Forbidden");
|
|
517530
|
+
return;
|
|
517531
|
+
}
|
|
517238
517532
|
if (requestUrl.pathname !== listen.path && requestUrl.pathname !== "/") {
|
|
517239
517533
|
rejectUpgrade(socket, 404, "Not Found");
|
|
517240
517534
|
return;
|
|
@@ -517244,6 +517538,12 @@ async function startAppServer(options3 = {}) {
|
|
|
517244
517538
|
rejectUpgrade(socket, 400, "Bad Request");
|
|
517245
517539
|
return;
|
|
517246
517540
|
}
|
|
517541
|
+
const authError = authorizeUpgrade(request.headers, authPolicy);
|
|
517542
|
+
if (authError) {
|
|
517543
|
+
options3.onLog?.(`Rejecting app-server websocket client: ${authError.message}`);
|
|
517544
|
+
rejectUpgrade(socket, authError.statusCode, authError.message);
|
|
517545
|
+
return;
|
|
517546
|
+
}
|
|
517247
517547
|
wss.handleUpgrade(request, socket, head2, (websocket) => {
|
|
517248
517548
|
handleWebSocketConnection(websocket, channel);
|
|
517249
517549
|
});
|
|
@@ -517311,11 +517611,20 @@ Run a local Letta Code app-server using native v2 websocket frames.
|
|
|
517311
517611
|
|
|
517312
517612
|
Options:
|
|
517313
517613
|
--listen <url> WebSocket listen URL. Defaults to ws://127.0.0.1:0
|
|
517614
|
+
--ws-auth <mode> WebSocket auth mode for non-loopback listeners. Supported: capability-token, signed-bearer-token
|
|
517615
|
+
--ws-token-file <path> Absolute path to the capability-token file
|
|
517616
|
+
--ws-token-sha256 <hex> Hex-encoded SHA-256 digest of the capability token
|
|
517617
|
+
--ws-shared-secret-file <path> Absolute path to the shared secret file for signed JWT bearer tokens
|
|
517618
|
+
--ws-issuer <issuer> Expected issuer for signed JWT bearer tokens
|
|
517619
|
+
--ws-audience <audience> Expected audience for signed JWT bearer tokens
|
|
517620
|
+
--ws-max-clock-skew-seconds <seconds> Maximum clock skew for signed JWT bearer token validation
|
|
517314
517621
|
-h, --help Show this help message
|
|
517315
517622
|
|
|
517316
517623
|
Examples:
|
|
517317
517624
|
letta app-server
|
|
517318
|
-
letta app-server --listen ws://127.0.0.1:4500
|
|
517625
|
+
letta app-server --listen ws://127.0.0.1:4500
|
|
517626
|
+
letta app-server --listen ws://0.0.0.0:4500 --ws-auth capability-token --ws-token-file /path/to/token
|
|
517627
|
+
letta app-server --listen ws://0.0.0.0:4500 --ws-auth signed-bearer-token --ws-shared-secret-file /path/to/secret`);
|
|
517319
517628
|
}
|
|
517320
517629
|
async function waitForShutdown(close) {
|
|
517321
517630
|
return await new Promise((resolve31) => {
|
|
@@ -517345,7 +517654,14 @@ async function runAppServerSubcommand(argv) {
|
|
|
517345
517654
|
allowPositionals: false,
|
|
517346
517655
|
options: {
|
|
517347
517656
|
help: { type: "boolean", short: "h" },
|
|
517348
|
-
listen: { type: "string" }
|
|
517657
|
+
listen: { type: "string" },
|
|
517658
|
+
"ws-auth": { type: "string" },
|
|
517659
|
+
"ws-token-file": { type: "string" },
|
|
517660
|
+
"ws-token-sha256": { type: "string" },
|
|
517661
|
+
"ws-shared-secret-file": { type: "string" },
|
|
517662
|
+
"ws-issuer": { type: "string" },
|
|
517663
|
+
"ws-audience": { type: "string" },
|
|
517664
|
+
"ws-max-clock-skew-seconds": { type: "string" }
|
|
517349
517665
|
}
|
|
517350
517666
|
});
|
|
517351
517667
|
} catch (error54) {
|
|
@@ -517357,8 +517673,18 @@ async function runAppServerSubcommand(argv) {
|
|
|
517357
517673
|
return 0;
|
|
517358
517674
|
}
|
|
517359
517675
|
try {
|
|
517676
|
+
const websocketAuth = parseAppServerWebsocketAuthSettings({
|
|
517677
|
+
wsAuth: typeof parsed.values["ws-auth"] === "string" ? parsed.values["ws-auth"] : undefined,
|
|
517678
|
+
wsTokenFile: typeof parsed.values["ws-token-file"] === "string" ? parsed.values["ws-token-file"] : undefined,
|
|
517679
|
+
wsTokenSha256: typeof parsed.values["ws-token-sha256"] === "string" ? parsed.values["ws-token-sha256"] : undefined,
|
|
517680
|
+
wsSharedSecretFile: typeof parsed.values["ws-shared-secret-file"] === "string" ? parsed.values["ws-shared-secret-file"] : undefined,
|
|
517681
|
+
wsIssuer: typeof parsed.values["ws-issuer"] === "string" ? parsed.values["ws-issuer"] : undefined,
|
|
517682
|
+
wsAudience: typeof parsed.values["ws-audience"] === "string" ? parsed.values["ws-audience"] : undefined,
|
|
517683
|
+
wsMaxClockSkewSeconds: typeof parsed.values["ws-max-clock-skew-seconds"] === "string" ? parsed.values["ws-max-clock-skew-seconds"] : undefined
|
|
517684
|
+
});
|
|
517360
517685
|
const handle2 = await startAppServer({
|
|
517361
517686
|
listen: typeof parsed.values.listen === "string" ? parsed.values.listen : undefined,
|
|
517687
|
+
websocketAuth,
|
|
517362
517688
|
onListening: (info) => {
|
|
517363
517689
|
console.log(`Listening on ${info.url}`);
|
|
517364
517690
|
console.log(`Control: ${info.controlUrl}`);
|
|
@@ -525365,4 +525691,4 @@ Error during initialization: ${message}`);
|
|
|
525365
525691
|
}
|
|
525366
525692
|
main2();
|
|
525367
525693
|
|
|
525368
|
-
//# debugId=
|
|
525694
|
+
//# debugId=5651C9D5C734905164756E2164756E21
|
package/package.json
CHANGED