/** * Stored plans on the user's own computer: the `plan: { file: ".json" }` * source of the grouped-step tools (computer batch / path / fast, browser and * phone batch / fast). A local agent writes a big step list (a drawing, a * 3000-step batch) to ~/.melaya/plans/.json and references it; the * server asks this runner for the file (runner:plan-read, answered on the * socket.io ack) instead of the model writing every step into the call. * * Only ONE folder, ONE plain file name: no separators, no traversal, no hidden * files, .json only, no symbolic links (the file itself, or the folder resolving * elsewhere), no hard-linked files, at most 2 MB. The content is returned as * text and parsed by the server; it is never executed or logged here. * * The desktop app runs this same runner (utilityProcess), so it answers too. */ export declare const PLAN_FILE_MAX_BYTES: number; /** A plain file name: same rule as the server (services/plans/stepPlans.ts). */ export declare const PLAN_FILE_RE: RegExp; /** ~/.melaya/plans */ export declare function plansDir(home?: string): string; export type PlanReadResult = { ok: true; text: string; bytes: number; } | { ok: false; code: "bad_name" | "not_found" | "not_a_file" | "too_large" | "outside" | "read_failed"; message: string; }; /** Read one plan file from `dir` (default ~/.melaya/plans, created when missing). */ export declare function readPlanFile(name: unknown, dir?: string): Promise; /** The subset of a socket.io-client Socket used here (a fake in tests). */ export interface PlanSocketLike { on(event: string, cb: (...args: any[]) => void): unknown; } /** runner:plan-read {file} -> ack(PlanReadResult). Old servers never send it. */ export declare function attachPlanSocketHandlers(socket: PlanSocketLike, dir?: () => string): void;