lembas -l / --local: everything in the project, nothing written elsewhere
Config, data and state are rooted at <project>/.agent/local/lembas (or .lembas/), kept out of git; a local directory the repository carries is refused. The user's logins and connections.yaml are read, never written; the user's config.yaml is not read. The TUI is started with TMPDIR inside it (the compiled binary unpacks its native library there) and OpenTUI's cache goes there too; the agent's commands keep the user's TMPDIR. An instance serves models, chat, speech and the balance only: the link, /remote, the service and the hub are off, deletes are not sent, and the server library, search, fetch, embeddings and personalization are not used. Self-update and uninstall are refused. hardline_disable is ignored, and tools treat the local directory as outside the project. The smoke test runs a whole local session in the compiled binary and checks that HOME, the XDG directories and TMPDIR gained nothing. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
27 files changed
+636
-105
No files matched your search
+14
-4
@@ -2,7 +2,8 @@
|
||||
// llama-swap's loading banner.
|
||||
import type { ReasoningPart, StreamEvent, TextPart, ToolCallPart, Message } from "./types.ts"
|
||||
import { ProviderError } from "./types.ts"
|
||||
import { env } from "../config/paths.ts"
|
||||
import { resolve } from "node:path"
|
||||
import { env, localRoot } from "../config/paths.ts"
|
||||
|
||||
type Assistant = Extract<Message, { role: "assistant" }>
|
||||
|
||||
@@ -71,12 +72,21 @@ export function statusOf(err: any): number | undefined {
|
||||
return undefined
|
||||
}
|
||||
|
||||
/** LEMBAS_RECORD, where it may be written: in local mode only inside the project's local root. */
|
||||
function recordDir(): string | undefined {
|
||||
const dir = env("RECORD")
|
||||
const root = localRoot()
|
||||
if (!dir || !root) return dir
|
||||
const abs = resolve(dir)
|
||||
return abs === root || abs.startsWith(`${root}/`) ? abs : undefined
|
||||
}
|
||||
|
||||
export function recordName(ref: string) {
|
||||
return `${env("RECORD")}/${new Date().toISOString().replace(/[:.]/g, "-")}-${ref.replace(/[^\w.-]+/g, "_")}`
|
||||
return `${recordDir()}/${new Date().toISOString().replace(/[:.]/g, "-")}-${ref.replace(/[^\w.-]+/g, "_")}`
|
||||
}
|
||||
|
||||
export function recordFailure(ref: string, request: unknown, e: unknown) {
|
||||
if (!env("RECORD")) return
|
||||
if (!recordDir()) return
|
||||
const name = recordName(ref)
|
||||
void Bun.write(`${name}.request.json`, JSON.stringify(request, null, 2))
|
||||
const err = e as ProviderError
|
||||
@@ -85,7 +95,7 @@ export function recordFailure(ref: string, request: unknown, e: unknown) {
|
||||
|
||||
/** LEMBAS_RECORD=<dir>: keep each request body and its raw SSE, to become test fixtures. */
|
||||
export function record(body: ReadableStream<Uint8Array>, ref: string, request: unknown): ReadableStream<Uint8Array> {
|
||||
const dir = env("RECORD")
|
||||
const dir = recordDir()
|
||||
if (!dir) return body
|
||||
const [a, b] = body.tee()
|
||||
const name = recordName(ref)
|
||||
|
||||
Reference in new issue
Block a user