Files
letta-code/src/runtime-context.ts
Charles Packer 3edaf91ee4 feat(listen): add protocol_v2, move ws server to v2 (#1387)
Co-authored-by: Shubham Naik <shub@letta.com>
Co-authored-by: Letta Code <noreply@letta.com>
2026-03-16 14:46:56 -07:00

72 lines
1.8 KiB
TypeScript

import { AsyncLocalStorage } from "node:async_hooks";
import type { SkillSource } from "./agent/skills";
export type RuntimePermissionMode =
| "default"
| "acceptEdits"
| "plan"
| "bypassPermissions";
export interface RuntimeContextSnapshot {
agentId?: string | null;
conversationId?: string | null;
skillsDirectory?: string | null;
skillSources?: SkillSource[];
workingDirectory?: string | null;
permissionMode?: RuntimePermissionMode;
planFilePath?: string | null;
modeBeforePlan?: RuntimePermissionMode | null;
}
const runtimeContextStorage = new AsyncLocalStorage<RuntimeContextSnapshot>();
export function getRuntimeContext(): RuntimeContextSnapshot | undefined {
return runtimeContextStorage.getStore();
}
export function runWithRuntimeContext<T>(
snapshot: RuntimeContextSnapshot,
fn: () => T,
): T {
const parent = runtimeContextStorage.getStore();
return runtimeContextStorage.run(
{
...parent,
...snapshot,
...(snapshot.skillSources
? { skillSources: [...snapshot.skillSources] }
: {}),
},
fn,
);
}
export function runOutsideRuntimeContext<T>(fn: () => T): T {
return runtimeContextStorage.exit(fn);
}
export function updateRuntimeContext(
update: Partial<RuntimeContextSnapshot>,
): void {
const current = runtimeContextStorage.getStore();
if (!current) {
return;
}
Object.assign(
current,
update,
update.skillSources && {
skillSources: [...update.skillSources],
},
);
}
export function getCurrentWorkingDirectory(): string {
const workingDirectory = runtimeContextStorage.getStore()?.workingDirectory;
if (typeof workingDirectory === "string" && workingDirectory.length > 0) {
return workingDirectory;
}
return process.env.USER_CWD || process.cwd();
}