{"version":3,"file":"index.mjs","names":[],"sources":["../src/sandbox/run.ts","../src/export/sandbox-dts.ts","../src/export/prompt.ts","../src/sandbox/commit.ts","../src/sandbox/lineage.ts","../src/schema.ts","../src/host-tool.ts"],"sourcesContent":["/// <reference types=\"node\" />\nimport { Worker } from 'node:worker_threads';\n\nimport type { DslAudit, StoredFile } from '@mengine/medeo-client';\n\nimport type { EntityAssetContent, SandboxEntity } from '../api/types.ts';\nimport type { ChangePlan } from './types.ts';\nimport type { WorkerData, WorkerMessage } from './worker.ts';\n\n/**\n * Host API for running an agent edit script in an isolated Node worker.\n *\n * Requires Node.js >= 24.15 (engines) so the worker can load TypeScript via\n * `--experimental-transform-types`. Do not inherit `process.execArgv` — vitest\n * injects loaders that break worker boot.\n */\nexport interface RunEditScriptOptions {\n  /** Document the plan will be committed against; stated by the host. */\n  docId: string;\n  /** The document as the script reads it: a native Loro snapshot. */\n  snapshot: Uint8Array;\n  /** The snapshot's version, base64; the plan applies on top of it. */\n  baseVersion: string;\n  script: string;\n  /** Who the plan's audit names. */\n  audit?: Omit<DslAudit, 'payload'>;\n  /** Reads a medium's or a transcript's stored file: for `materialize`, and before the plan for every file it names. */\n  loadEntityAsset?: (entity: SandboxEntity) => Promise<EntityAssetContent>;\n  /** Stores raw text in Memota: a PhoneticScript's phonemeScript, whenever a plan writes one. */\n  uploadText?: (text: string) => Promise<StoredFile>;\n  /** Deterministic id label for tests; omit for random ids. */\n  idLabel?: string;\n  /** Hard wall-clock timeout from when the script starts; default 2000 ms. */\n  timeoutMs?: number;\n  /** V8 old-generation ceiling for the worker; default 256 MB. */\n  memoryLimitMb?: number;\n  /** Override worker module URL (defaults to sibling `worker.ts`). */\n  workerEntryUrl?: URL;\n}\n\nexport type EditScriptResult =\n  | {\n      ok: true;\n      plan: ChangePlan;\n      /** Script execution time after worker readiness; excludes cold start. */\n      durationMs: number;\n    }\n  | {\n      ok: false;\n      phase: 'parse' | 'runtime' | 'timeout' | 'memory';\n      error: { message: string; line?: number; column?: number; stack?: string };\n      partial: { commandsCount: number; logs: string[] };\n    };\n\nconst DEFAULT_TIMEOUT_MS = 2000;\nconst DEFAULT_MEMORY_MB = 256;\nconst DEFAULT_AUDIT: Omit<DslAudit, 'payload'> = { semantic_op: 'medeo.script', actor: null };\n\n/**\n * Source runs load the checked-in TypeScript worker; packed runs load the\n * sibling JavaScript chunk emitted as a second package entry. Keeping this\n * branch explicit avoids shipping a `dist/*.ts` URL in the npm artifact.\n */\nfunction sourceSibling(fileName: string): URL {\n  const selfUrl = new URL(import.meta.url);\n  const extension = selfUrl.pathname.endsWith('.ts') ? 'ts' : 'mjs';\n  return new URL(`./${fileName}.${extension}`, selfUrl);\n}\n\n/** Run `script` against a fork of the snapshot; always resolves (never rejects). */\nexport function runEditScript(options: RunEditScriptOptions): Promise<EditScriptResult> {\n  // Keep the clock separate from worker boot so timing matches the timeout boundary.\n  let scriptStartedAt = performance.now();\n  const timeoutMs = options.timeoutMs ?? DEFAULT_TIMEOUT_MS;\n  const workerEntryUrl = options.workerEntryUrl ?? sourceSibling('worker');\n  const resolveRegisterUrl = sourceSibling('esm-register');\n  const logs: string[] = [];\n  let commandsCount = 0;\n  const partial = () => ({ commandsCount, logs: logs.slice() });\n\n  return new Promise<EditScriptResult>((resolve) => {\n    let settled = false;\n    let timedOut = false;\n    let timer: ReturnType<typeof setTimeout> | undefined;\n    const workerData: WorkerData = {\n      snapshot: options.snapshot,\n      script: options.script,\n      audit: options.audit ?? DEFAULT_AUDIT,\n      ...(options.idLabel === undefined ? {} : { idLabel: options.idLabel }),\n      readsFiles: options.loadEntityAsset !== undefined,\n    };\n    const worker = new Worker(workerEntryUrl, {\n      workerData,\n      // A script has no business with the host's environment, and the worker needs none of it.\n      env: {},\n      // Explicit argv only — never inherit process.execArgv (vitest loaders). Source workers need\n      // the TypeScript transform plus the resolver hook; packed JavaScript workers need neither.\n      execArgv: resolveRegisterUrl.pathname.endsWith('.ts')\n        ? [\n            '--experimental-transform-types',\n            '--disable-warning=ExperimentalWarning',\n            `--import=${resolveRegisterUrl.href}`,\n          ]\n        : [],\n      resourceLimits: { maxOldGenerationSizeMb: options.memoryLimitMb ?? DEFAULT_MEMORY_MB },\n    });\n\n    /** Run host I/O the worker asked for and send back its result or failure. */\n    const answer = (requestId: number, io: () => Promise<unknown>): void =>\n      void (async () => {\n        try {\n          const result = await io();\n          if (!settled) worker.postMessage({ t: 'host-result', requestId, result });\n        } catch (error) {\n          if (!settled)\n            worker.postMessage({\n              t: 'host-result',\n              requestId,\n              error: error instanceof Error ? error.message : String(error),\n            });\n        }\n      })();\n    const finish = (result: EditScriptResult): void => {\n      if (settled) return;\n      settled = true;\n      if (timer != null) clearTimeout(timer);\n      void worker.terminate();\n      resolve(result.ok ? { ...result, durationMs: performance.now() - scriptStartedAt } : result);\n    };\n\n    worker.on('message', (message: WorkerMessage) => {\n      if (settled) return;\n      switch (message.t) {\n        case 'ready':\n          scriptStartedAt = performance.now();\n          timer ??= setTimeout(() => {\n            timedOut = true;\n            finish({\n              ok: false,\n              phase: 'timeout',\n              error: { message: `edit script exceeded timeout of ${timeoutMs}ms` },\n              partial: partial(),\n            });\n          }, timeoutMs);\n          return;\n        case 'read-file':\n          answer(message.requestId, () => {\n            if (!options.loadEntityAsset) throw new Error('This host reads no files');\n            return options.loadEntityAsset(message.entity);\n          });\n          return;\n        case 'upload-text':\n          answer(message.requestId, () => {\n            if (!options.uploadText) throw new Error('This host stores no files');\n            return options.uploadText(message.text);\n          });\n          return;\n        case 'write':\n          commandsCount++;\n          return;\n        case 'log':\n          logs.push(message.line);\n          return;\n        case 'done':\n          finish({\n            ok: true,\n            plan: {\n              doc_id: options.docId,\n              base_version: options.baseVersion,\n              ...(message.loroUpdate ? { loro_update: message.loroUpdate } : {}),\n              preview: message.preview,\n              logs: logs.slice(),\n              commands_count: commandsCount,\n              created_media: message.createdMedia,\n            },\n            durationMs: 0,\n          });\n          return;\n        case 'fail':\n          finish({ ok: false, phase: message.phase, error: message.error, partial: partial() });\n      }\n    });\n    worker.on('error', (error: Error) => {\n      if (settled) return;\n      const text = error.message ?? String(error);\n      finish({\n        ok: false,\n        phase: /memory limit/i.test(text) ? 'memory' : 'runtime',\n        error: { message: text, stack: error.stack },\n        partial: partial(),\n      });\n    });\n    worker.on('exit', (code: number) => {\n      if (settled || timedOut) return;\n      finish({\n        ok: false,\n        phase: 'runtime',\n        error: { message: `worker exited with code ${code ?? 'null'} before completion` },\n        partial: partial(),\n      });\n    });\n  });\n}\n","/**\n * Synced by hand from `packages/medeo-dsl/src/sandbox.d.ts`: the contract text the\n * model is handed, that file verbatim plus the two module bindings a script\n * imports. Edit the contract there, then copy it here unchanged.\n *\n * The copy exists because `prompt.ts` needs the text at runtime, and neither\n * the private DSL package nor a `.d.ts` file's text is shipped in `dist`.\n * `__tests__/prompt-contract.spec.ts` fails if the two ever diverge.\n */\nexport const SANDBOX_API_DTS = `/** Kinds a script can author. */\nexport type EntityKind =\n  | 'timeline'\n  | 'track'\n  | 'clip'\n  | 'sequence-marker'\n  | 'video'\n  | 'audio'\n  | 'voiceover-recording'\n  | 'image'\n  | 'voice'\n  | 'audio-script'\n  | 'phonetic-script'\n  | 'caption';\n\nexport type RelationKind = 'contain' | 'marker' | 'clip-anchor' | 'voice-timbre' | 'derived-from';\n\n/**\n * Kinds whose Relations are ordered within their container.\n *\n * A Timeline's Tracks and a Track's Clips play in the order their \\`contain\\`\n * Relations sit in, and that order is the only statement of it — no entity\n * carries a copy of its own position.\n */\nexport type OrderedRelationKind = 'contain';\n\n/** One segment of an AudioScript, addressed by its index. */\nexport interface ScriptSegment {\n  text: string;\n  language?: string;\n  /**\n   * A transcript's segment: where its words were spoken in the medium, as its transcription file\n   * gave them. Both or neither, stated when the segment is added and never edited afterwards.\n   */\n  startMs?: number;\n  endMs?: number;\n}\n\n/** One segment of the base script by index, or a half-open code-point range inside it. */\nexport interface SegmentSelection {\n  segment: number;\n  textRange?: { start: number; end: number };\n}\n\n/**\n * Sequence: content that can be placed on a Track. It always has a length;\n * \\`null\\` means it has none of its own, and the Clip's marker decides how long it shows.\n */\nexport interface Sequence {\n  durationMs: number | null;\n}\n\n/** The stored file a medium is. A document holds one medium per system and key. */\nexport interface MediaFile {\n  /** Speech results (ids starting \\`sph_\\`) are memota-speech; every other resource is memota. */\n  system: 'memota' | 'memota-speech';\n  /** The file's id in that store. */\n  key: string;\n  /** Where the bytes live in storage; a fact the host records from the store, never written by a script. */\n  storageKey?: string;\n  /** Fingerprint of the bytes; a fact the host records from the store, never written by a script. */\n  digest?: string;\n}\n\n/**\n * A variant names its base; every field it does not state reads through to\n * the base. Variants exist only where a variant relation is defined: a\n * PhoneticScript has exactly one AudioScript base, and a Caption has at most one —\n * none when it states its own \\`text\\`. \\`bases\\` alone links a variant to its base.\n */\nexport interface Composed {\n  bases: string[];\n}\n\n/** Every style field a Caption may own; anything else is refused. */\nexport interface CaptionStyle {\n  font?: { system: 'font-library'; key: string };\n  fontSize?: number;\n  fontColor?: string;\n  fontWeight?: number;\n  entranceAnimation?: string;\n  entranceAnimationDurationMs?: number;\n  strokeColor?: string;\n  strokeWidth?: number;\n  /** The caption's center across the frame, from 0 at the left edge to 1 at the right. */\n  positionX?: number;\n  /** The caption's center down the frame, from 0 at the top edge to 1 at the bottom. */\n  positionY?: number;\n}\n\n/** A kind, or a relation, with no fields of its own. */\nexport type Empty = Record<never, never>;\n\n/** Own fields by kind. A kind states these and nothing else. */\nexport interface Payload {\n  /** Structure only: its Tracks are its content. */\n  timeline: Empty;\n  /** What the Track is for; the roles a document starts with come with its snapshot. */\n  track: { role: string; hidden?: boolean };\n  /** Where it sits in its Track is the order of its contain Relation; a Marker startMs overrides where it begins. volume is decibels, -60 to 20, 0 the source's own level. */\n  clip: { volume?: number };\n  'sequence-marker': {\n    /** In point on the source, from 0. */\n    inMs: number;\n    /** Out point on the source. outMs - inMs is how long this content runs. */\n    outMs: number;\n    /** Where the Clip begins, overriding its order: on the Track, or inside the Clip named by clip-anchor. */\n    startMs?: number;\n    /** Linear speed; omitted means 1. Played length is (outMs - inMs) / rate. Video and audio only. */\n    rate?: number;\n    /** BGM only: run as long as the Timeline instead of the source. */\n    fillTimeline?: true;\n  };\n  video: Sequence & MediaFile;\n  /** Sound that carries no language: BGM, sound effects, a video's own track. Spoken language is a voiceover-recording. */\n  audio: Sequence & MediaFile;\n  /** Speech. It states the PhoneticScript it was spoken from through derived-from. */\n  'voiceover-recording': Sequence & MediaFile;\n  /** An image has no length of its own: durationMs is null. */\n  image: Sequence & MediaFile;\n  /** A timbre identity, never playable; the take rendered with it is a voiceover-recording. */\n  voice: { voice: { system: 'voice-library'; key: string; name?: string } };\n  /**\n   * Segmented text. A written script names no file. One read off media states that media through\n   * derived-from and names the transcription file (\\`system\\`, \\`key\\`) its words and times came from;\n   * the file is fixed once named.\n   */\n  'audio-script': Partial<MediaFile> & { segments: ScriptSegment[] };\n  /**\n   * What a take is synthesized from, for one segment of its base script or a run of it: its\n   * phonemeScript where the voice takes markup, otherwise the selection's words.\n   */\n  'phonetic-script': Composed & {\n    /** The segment it is written for; absent only once that segment is gone. */\n    selection: SegmentSelection;\n    /**\n     * Phoneme content — markup — stated only where the voice takes it, and never empty. Without it\n     * there is none, and TTS reads the selection's words from the base script.\n     */\n    phonemeScript?: string;\n  };\n  /**\n   * Words on screen: a selection of its base script, or its own \\`text\\`. A Caption has no\n   * length of its own (durationMs is null); its Clip's marker decides how long it shows.\n   */\n  caption: Sequence &\n    Composed & {\n      selection?: SegmentSelection;\n      /** The Caption's own words; stating them drops the selection and the base. */\n      text?: string;\n      style?: CaptionStyle;\n    };\n}\n\n/** Stated in full, or stated by a variant over its base. */\nexport type StoredPayload<K extends EntityKind> = Payload[K] | (Partial<Payload[K]> & Composed);\n\nexport interface Entity<K extends EntityKind = EntityKind> {\n  entityId: string;\n  entityKind: K;\n  /** Assembled: a variant reads with its base already applied. */\n  payload: Payload[K];\n}\n\n/** Endpoints keep their positions; each kind states what endpoint 0 and endpoint 1 are to each other. */\nexport interface Relation<K extends RelationKind = RelationKind> {\n  relationId: string;\n  relationKind: K;\n  endpoint0EntityId: string;\n  endpoint1EntityId: string;\n}\n\n/** Starts at a payload field; a list member is addressed by its index. */\nexport type FieldPath = readonly (string | number)[];\n\nexport type FieldChange =\n  /** value is JSON-serializable; the field being set decides its shape. */\n  | { op: 'set'; path: FieldPath; value: unknown }\n  | { op: 'unset'; path: FieldPath }\n  /** index and deleteCount count Unicode code points. */\n  | { op: 'text.splice'; path: FieldPath; index: number; deleteCount: number; text: string }\n  /** index is where the new member lands; the list's length appends. */\n  | { op: 'list.insert'; path: FieldPath; index: number; value: unknown }\n  | { op: 'list.move'; path: FieldPath; from: number; to: number }\n  | { op: 'list.remove'; path: FieldPath; index: number };\n\nexport interface ScriptEntities {\n  list(): Entity[];\n  get(entityId: string): Entity | null;\n  create<K extends EntityKind>(entityKind: K, payload: StoredPayload<K>): string;\n  update(entityId: string, changes: FieldChange[]): void;\n  /** Establish own fields or an override; not the normal way to edit inherited content. */\n  declareFields(entityId: string, payload: Partial<Payload[EntityKind]>): void;\n  /**\n   * Unlink its Relations first. A Clip takes its own sequence-marker with it — the one it holds,\n   * or held until this run unlinked it; a marker linked to another Clip stays.\n   */\n  delete(entityId: string): void;\n  /**\n   * Read a medium's own stored file, or the transcription file a transcript names.\n   * \\`assetId\\` is the file's key. What the bytes hold is their own business and no\n   * two kinds agree, so \\`content\\` is inspected, never assumed. Nothing of \\`content\\`\n   * is filled in on the entity: state what it needs — a take's length, say — yourself.\n   * Only \\`storageKey\\` and \\`digest\\` are recorded from the read, by the host.\n   */\n  materialize(entityId: string): Promise<{ assetId: string; content: unknown }>;\n}\n\nexport interface ScriptRelations {\n  list(): Relation[];\n  /** Ordered kinds come back in container order: a Track's Clips play in this order. */\n  of(entityId: string, relationKind?: RelationKind): Relation[];\n  /**\n   * contain(container, contained), marker(marked, marker), clip-anchor(child, host),\n   * voice-timbre(recording, voice), derived-from(product, source). voice-timbre names the Voice of\n   * the voice the take was synthesized with; the plan is refused otherwise. derived-from is what a\n   * product was made from: a recording from its PhoneticScript, a transcript from its media.\n   * A variant's base is its \\`bases\\`, never a derived-from.\n   */\n  link(relationKind: RelationKind, endpoint0EntityId: string, endpoint1EntityId: string): string;\n  /**\n   * Move an ordered Relation within its container: \\`beforeRelationId\\` names the\n   * Relation it goes in front of, or null to put it last.\n   */\n  move(relationId: string, beforeRelationId: string | null): void;\n  unlink(relationId: string): void;\n}\n\nexport declare const entities: ScriptEntities;\nexport declare const relations: ScriptRelations;\n`;\n","import { SANDBOX_API_DTS } from './sandbox-dts.ts';\n\nexport const MEDEO_TOOL_DESCRIPTION = `\nEdit the Medeo Entity/Relation graph in an isolated JavaScript sandbox.\n\nOperations:\n- snapshot: read the entities, relations and current document version. Reading never initializes or changes the document.\n- run-edit-script: run a script against a causal working view of that snapshot. It returns preview, logs and plan_id; nothing is published yet.\n- commit-plan: publish the plan's operations against the baseline it was built on. Independent concurrent edits merge. Failed transport is unconfirmed, so retry the same plan_id rather than re-running the script: that preserves operation identity.\n\nDefault flow: snapshot, run-edit-script with auto_commit=false, read preview, commit-plan. Use auto_commit=true only for edits that need no confirmation. On a conflict, take a fresh snapshot and decide explicitly what the merged state should be; never overwrite the document or replay an old plan against a new snapshot.\n`.trim();\n\n/**\n * What the declarations cannot state.\n *\n * The types say which fields exist and which pairs a Relation accepts. This\n * says what is checked once the plan is whole, and which of several shapes the\n * type system allows is the one the domain means. Anything already legible in\n * the `.d.ts` below is deliberately absent here.\n */\nconst MEDEO_TOOL_EXECUTION_RULES = `\nThe host supplies the document; never invent or ask for a document id. The script runs with entities, relations and console in scope and nothing else: no network, no generation, no storage, and no compiling code from strings. Hold anything it needs to remember in its own variables. Ids minted in a run are that run's; refresh after a commit.\n\nReads are assembled snapshots, and mutating a returned object persists nothing. Every write lands whole or not at all and is checked as it lands, so a refused write throws at the call that made it. update applies its ordered changes atomically; list members are addressed by index, and text.splice counts code points. A field a variant reads from its base is edited on the base. delete never cascades: unlink the entity's relations first, except that a Clip takes its own SequenceMarker with it. Every millisecond value is a whole number. No payload holds another entity's id except a variant's bases — every other reference is a Relation.\n\nmaterialize(entityId) reads a medium's own stored file, or the transcription file a transcript names. Nothing is filled in for you: take what the entity needs from content — a take's length, say — and state it yourself. A medium names its file by system and key, and a document holds one medium per file: entities.create returns the one it already has. storageKey and digest are facts the host records: every file the plan names is read from the store before the plan is built, whether or not the script read it, and a file the store cannot read prevents publication; never write them. An unawaited read still completes before the plan is built, and its failure prevents publication.\n\nStructure is contain: the Timeline holds Tracks, a Track holds Clips, a Clip holds its content. Placing content is a Clip, a SequenceMarker and the content: contain(track,clip), marker(clip,marker), contain(clip,content). A Clip needs all three before the plan is built. The document has exactly one Timeline; playback supports one video Track.\n\nA Clip is placed exactly one way. In flow: it plays after the Clip before it, in the order of its Track's contain Relations — relations.move changes that order — and its Marker states no startMs. Absolutely: marker.startMs on the Track. Following another Clip: clip-anchor(child,host), with marker.startMs measured inside the host, which an anchor requires. A Clip follows at most one host, and anchors may not form a cycle. inMs/outMs must stay inside the length the content states; an image or a Caption states none, so its Marker alone decides how long it shows. Move or stretch a placement by editing its Marker, never the content. Caption visibility is the caption Track's hidden field.\n\nSpeech has two origins and they take different work.\n\nWritten, then spoken. Write the AudioScript: the plain words to be read. Every take is synthesized from a PhoneticScript: for the segment, or run of one, the take says, find one or author one with bases [script] and selection { segment, textRange? }; bases is its whole link to the script, so it takes no derived-from. Its phonemeScript is phoneme content — markup for pronunciation, emphasis and pacing — and is stated only where the TTS model's mcap model-profile lists phonetic_script; otherwise it states none, and the selection's words in its base script are all there is to read. A new voice rewrites or removes it first. Synthesize from the PhoneticScript as the document holds it, never an id: with a phonemeScript, pass it as phonetic_script and the selection's words as audio_script; without one, pass the selection's words as audio_script. The take comes back as a speech result id: create a voiceover-recording with system memota-speech and that key, materialize it for the take's length, and state its durationMs. The recording requires derived-from(recording,phoneticScript), and states its timbre with voice-timbre(recording,voice): the Voice of the voice it was synthesized with, checked against the synthesis before the plan is built. Several takes may name one PhoneticScript.\n\nRead from media. The words were already spoken, so nothing is synthesized: no PhoneticScript and no voiceover-recording are involved. A transcription comes back as a Memota file key. Create the AudioScript naming that file, { system: 'memota', key }, link derived-from(script,media) — the text says which words, only that Relation says whose — and materialize(script) to read the file. Its segments become the script's segments exactly as the file gives them — one segment per file segment, text, spacing and punctuation untouched, never merged or split — each with the startMs and endMs it was spoken at in the medium; nothing is filled in from another script, and a later correction edits a segment's text, keeping its time. A Caption selecting a segment is placed where its words were spoken.\n\nSound that carries no language is an audio and is asked for none of this. Never fabricate a sound resource: if narration is required and no medium carries it, synthesize it through the path above.\n\nAn AudioScript owns multi-segment text, has no time of its own, and is never Clip content. A Caption is words on screen: either a selection of one segment of its base script — bases [script] and selection { segment, textRange? } — or its own text, which drops the selection and the base. A Caption is Clip content directly and has no length of its own: its durationMs is null, and its Clip's Marker decides how long it shows and where it starts, for example following the speech Clip with clip-anchor(captionClip,speechClip) and marker.startMs. A selection follows edits to its segment's text and stays with the segment when segments move.\n\nA project may hold several complete independent AudioScripts, for example a written one and an uploaded video's transcript. Material transcribed before this script ran is already in the document with its Captions: find it with entities.list and place what is there instead of transcribing a second copy. Project initialization creates the Timeline and the standard Tracks and no AudioScript.\n\nVariants exist only where the contract defines them: a PhoneticScript has exactly one AudioScript base, and a Caption at most one. A variant states only its own fields; its base's segments read through it. Deleting a base is allowed, and its variants stop assembling. Never clone an entity to version it.\n\nA change reaches what depends on it in one of three ways. Text and fields are edited in place, and concurrent edits merge. A variant composes its base: a base edit reads through the fields the variant does not state and leaves the ones it states as they are, so editing a script never makes its PhoneticScript stale — whether to rewrite the pronunciation is a choice. A product made from a source never changes: a recording keeps the pronunciation it was spoken from, so after its PhoneticScript is rewritten it no longer matches, and the remedy is a new take, never an edit to the old one.\n`.trim();\n\nexport interface RenderMedeoModelContextInput {\n  documentVersion: string;\n  updatedSincePreviousModelCall: boolean | null;\n}\n\n/** MEngine owns API disclosure; Harness only supplies the changing document context. */\nexport function renderMedeoModelContext(input: RenderMedeoModelContextInput): string {\n  const updated =\n    input.updatedSincePreviousModelCall == null\n      ? 'unknown (first model call)'\n      : String(input.updatedSincePreviousModelCall);\n  return `\n${MEDEO_TOOL_DESCRIPTION}\n\n${MEDEO_TOOL_EXECUTION_RULES}\n\nCurrent MEngine document state (sampled immediately before this model call):\n- document_version: ${JSON.stringify(input.documentVersion)}\n- updated_since_previous_model_call: ${updated}\n\nWhen updated_since_previous_model_call is true, take a fresh snapshot before planning further edits.\n\nSandbox TypeScript interface:\n\\`\\`\\`ts\n${SANDBOX_API_DTS}\n\\`\\`\\`\n`.trim();\n}\n","import { toVideoDraft, type ManualSyncDoc } from '@mengine/medeo-client';\n\nimport type { ChangePlan } from './types.ts';\n\nexport type CommitPlanResult =\n  | { kind: 'committed'; commands_applied: number; collaborated: boolean }\n  /** The server holds the merge, but the merged document no longer projects: look again. */\n  | { kind: 'conflicted'; accepted: true; collaborated: boolean; message: string }\n  /** The push was not confirmed; publish the same plan again. */\n  | { kind: 'unconfirmed'; reason: 'push_failed'; message: string }\n  | { kind: 'rejected'; code?: string; message: string };\n\n/**\n * Publish a plan: merge its native update into the synced document and push.\n * Importing the same update twice changes nothing, so retrying an unconfirmed\n * plan re-sends exactly the operations it first carried.\n */\nexport async function commitPlan(doc: ManualSyncDoc, plan: ChangePlan): Promise<CommitPlanResult> {\n  if (plan.loro_update) doc.dsl.doc.import(Buffer.from(plan.loro_update, 'base64'));\n  const push = await doc.push();\n  if (push.kind === 'failed')\n    return { kind: 'unconfirmed', reason: 'push_failed', message: push.error?.message ?? 'The push was not confirmed' };\n  if (push.kind === 'rejected')\n    return {\n      kind: 'rejected',\n      ...(push.code === undefined ? {} : { code: push.code }),\n      message: push.error?.message ?? 'The server refused the update',\n    };\n  try {\n    toVideoDraft(doc.snapshot());\n  } catch (error) {\n    return {\n      kind: 'conflicted',\n      accepted: true,\n      collaborated: push.collaborated,\n      message: error instanceof Error ? error.message : String(error),\n    };\n  }\n  return { kind: 'committed', commands_applied: plan.commands_count, collaborated: push.collaborated };\n}\n","import { relationId, type DslMutation, type ManualSyncDoc } from '@mengine/medeo-client';\n\n/** A generation record the host knows, by file key: what was made, from what. */\nexport interface AssetGenerationFact {\n  outputAssetId: string;\n  inputAssetIds: readonly string[];\n}\n\n/** Every known generation record involving the given file keys, in either role. */\nexport type GenerationFactsLoader = (\n  docId: string,\n  assetIds: readonly string[],\n) => Promise<readonly AssetGenerationFact[]>;\n\nexport type GenerationSyncOutcome = { status: 'synced'; linked: number } | { status: 'failed'; message: string };\n\n/**\n * After a confirmed commit, link media the plan created to the media they were\n * generated from, as derived-from(product, source). Only records whose both\n * ends are media in the document are linked; the commit is already durable, so\n * a failure here is reported, never thrown.\n */\nexport async function syncGeneratedRelations(\n  doc: ManualSyncDoc,\n  docId: string,\n  created: readonly { id: string; key: string }[],\n  load: GenerationFactsLoader,\n): Promise<GenerationSyncOutcome> {\n  if (!created.length) return { status: 'synced', linked: 0 };\n  try {\n    const facts = await load(\n      docId,\n      created.map((media) => media.key),\n    );\n    const snapshot = doc.snapshot();\n    const byKey = new Map<string, string>();\n    for (const [id, media] of Object.entries(snapshot['media-entities']))\n      if (!byKey.has(media.key)) byKey.set(media.key, id);\n    const mutations: DslMutation[] = [];\n    const seen = new Set<string>();\n    for (const fact of facts) {\n      const product = byKey.get(fact.outputAssetId);\n      if (product === undefined) continue;\n      for (const input of fact.inputAssetIds) {\n        const source = byKey.get(input);\n        if (source === undefined || source === product) continue;\n        const value = { entityId: product, sourceId: source };\n        const id = relationId('derived-from-relations', value);\n        if (seen.has(id) || snapshot['derived-from-relations'][id]) continue;\n        seen.add(id);\n        mutations.push({ type: 'set-relation', table: 'derived-from-relations', value });\n      }\n    }\n    if (!mutations.length) return { status: 'synced', linked: 0 };\n    doc.dsl.applyMutations(mutations, { semantic_op: 'medeo.generationLineage', payload: { facts }, actor: null });\n    const push = await doc.push();\n    if (push.kind === 'failed' || push.kind === 'rejected')\n      return { status: 'failed', message: push.error?.message ?? `lineage push ${push.kind}` };\n    return { status: 'synced', linked: mutations.length };\n  } catch (error) {\n    return { status: 'failed', message: error instanceof Error ? error.message : String(error) };\n  }\n}\n","export const MEDEO_TOOL_NAME = 'medeo';\n\nexport type MedeoToolOp = 'snapshot' | 'run-edit-script' | 'commit-plan';\n\n/**\n * JSON Schema for the host-facing `medeo` tool surface.\n *\n * The schema intentionally does not return or accept the full op journal:\n * journals stay in the tool process and are referenced by `plan_id`. This keeps\n * large intermediate products out of model context while preserving the exact\n * journal used for commit.\n */\nexport const MEDEO_TOOL_PARAMETERS = {\n  type: 'object',\n  required: ['op', 'doc_id'],\n  additionalProperties: false,\n  properties: {\n    op: {\n      type: 'string',\n      enum: ['snapshot', 'run-edit-script', 'commit-plan'],\n      description: 'Which Medeo document operation to run.',\n    },\n    doc_id: {\n      type: 'string',\n      minLength: 1,\n      description: 'Medeo document id. Copy it from the host context; never invent it.',\n    },\n    script: {\n      type: 'string',\n      minLength: 1,\n      description:\n        'JavaScript body for run-edit-script. It runs with entities, relations and console in scope; everything it does becomes one entity plan.',\n    },\n    timeout_ms: {\n      type: 'integer',\n      minimum: 1,\n      description: 'Maximum script wall-clock time after worker startup (default 30000).',\n    },\n    memory_limit_mb: {\n      type: 'integer',\n      minimum: 16,\n      description: 'Worker old-generation memory ceiling in MB (default 256).',\n    },\n    auto_commit: {\n      type: 'boolean',\n      description:\n        'Commit the returned plan immediately after the sandbox succeeds. Default false: return preview plus plan_id for explicit commit.',\n    },\n    plan_id: {\n      type: 'string',\n      minLength: 1,\n      description: 'Plan id returned by run-edit-script; required by commit-plan.',\n    },\n    validation: {\n      type: 'string',\n      enum: ['preflight'],\n      description: 'Publish the native update already validated on its causal Loro fork.',\n    },\n  },\n  oneOf: [\n    {\n      required: ['op', 'doc_id'],\n      properties: {\n        op: { const: 'snapshot' },\n        doc_id: { $ref: '#/properties/doc_id' },\n      },\n      additionalProperties: false,\n    },\n    {\n      required: ['op', 'doc_id', 'script'],\n      properties: {\n        op: { const: 'run-edit-script' },\n        doc_id: { $ref: '#/properties/doc_id' },\n        script: { $ref: '#/properties/script' },\n        timeout_ms: { $ref: '#/properties/timeout_ms' },\n        memory_limit_mb: { $ref: '#/properties/memory_limit_mb' },\n        auto_commit: { $ref: '#/properties/auto_commit' },\n      },\n      additionalProperties: false,\n    },\n    {\n      required: ['op', 'doc_id', 'plan_id'],\n      properties: {\n        op: { const: 'commit-plan' },\n        doc_id: { $ref: '#/properties/doc_id' },\n        plan_id: { $ref: '#/properties/plan_id' },\n        validation: { $ref: '#/properties/validation' },\n      },\n      additionalProperties: false,\n    },\n  ],\n} as const;\n","/// <reference types=\"node\" />\nimport { randomUUID } from 'node:crypto';\n\nimport {\n  ManualSyncDoc,\n  MengineHttpClient,\n  type DocVersionMark,\n  type ManualSyncDocOptions,\n  type StoredFile,\n} from '@mengine/medeo-client';\n\nimport type { EntityAssetLoader } from './api/types.ts';\nimport { interpret } from './dsl/interpret.ts';\nimport { loadState } from './dsl/state.ts';\nimport { MEDEO_TOOL_DESCRIPTION, renderMedeoModelContext } from './export/prompt.ts';\nimport { commitPlan, type CommitPlanResult } from './sandbox/commit.ts';\nimport { syncGeneratedRelations, type GenerationFactsLoader, type GenerationSyncOutcome } from './sandbox/lineage.ts';\nimport { runEditScript } from './sandbox/run.ts';\nimport type { ChangePlan } from './sandbox/types.ts';\nimport { MEDEO_TOOL_NAME, MEDEO_TOOL_PARAMETERS, type MedeoToolOp } from './schema.ts';\n\ntype ContextualValue<T> = T | ((docId: string) => T | undefined);\n\nexport interface CreateMedeoToolOptions {\n  /**\n   * Mengine HTTP origin for a document. The host owns environment routing\n   * (local/stg/prd/lane) and may return a different origin per document.\n   * Documents cache by doc id, so the origin must remain stable for that doc.\n   */\n  httpOrigin: ContextualValue<string>;\n  /** Optional bearer token, evaluated for each HTTP request. */\n  authToken?: ContextualValue<string>;\n  /** Optional end-user id header, evaluated for each HTTP request; also the plan audit's actor. */\n  userId?: ContextualValue<string>;\n  /** Loro peer for the tool's own follow-up writes; plans are authored on a fresh peer each run. */\n  peerId?: ContextualValue<string>;\n  /**\n   * Resolve generation lineage by file key after a confirmed commit. Return\n   * every known record involving the given keys, in either role; an empty array\n   * means none is known, and a rejection is surfaced as a warning.\n   */\n  loadGenerationFacts?: GenerationFactsLoader;\n  /** Read a medium's own file, or a transcript's transcription file: for `materialize`, and before every plan for each file it names. */\n  loadEntityAsset?: EntityAssetLoader;\n  /**\n   * Store raw text in Memota as a text file and return its facts. A plan that writes a\n   * PhoneticScript's phonemeScript stores it here first and writes the file's facts with it (D177).\n   */\n  uploadText?: (docId: string, text: string) => Promise<StoredFile>;\n  fetchImpl?: typeof fetch;\n  /** Defaults passed to runEditScript; each call may override them. */\n  sandbox?: { timeoutMs?: number; memoryLimitMb?: number };\n  /** Maximum cached plans; oldest plans are evicted (default 16). */\n  maxPlans?: number;\n  /** Maximum model-call version baselines retained across host contexts (default 128). */\n  maxModelContexts?: number;\n}\n\nexport interface MedeoModelContextInput {\n  /** Internal MEngine document id. This is host-supplied and never model-facing. */\n  doc_id: string;\n  /** Stable host conversation/session key used to compare consecutive model calls. */\n  context_id: string;\n}\n\nexport interface MedeoModelContext {\n  /** Complete MEngine-owned prompt: workflow, runtime state, and sandbox TypeScript interface. */\n  prompt: string;\n  document_version: string;\n  updated_since_previous_model_call: boolean | null;\n}\n\nexport type MedeoToolInput =\n  | { op: 'snapshot'; doc_id: string }\n  | {\n      op: 'run-edit-script';\n      doc_id: string;\n      script: string;\n      timeout_ms?: number;\n      memory_limit_mb?: number;\n      auto_commit?: boolean;\n    }\n  | { op: 'commit-plan'; doc_id: string; plan_id: string; validation?: 'preflight' };\n\nexport type MedeoToolWarning =\n  | { kind: 'pull_failed'; message: string }\n  | { kind: 'generation_sync_failed'; message: string };\n\nexport type MedeoCommitResult = CommitPlanResult & {\n  /** Present only when the host supplies loadGenerationFacts and the commit was confirmed. */\n  generation_sync?: GenerationSyncOutcome;\n  warnings?: MedeoToolWarning[];\n};\n\nexport type MedeoToolResult =\n  | {\n      ok: true;\n      op: 'snapshot';\n      doc_id: string;\n      version: string;\n      preview: string;\n      collaborated?: boolean;\n      warnings?: MedeoToolWarning[];\n    }\n  | {\n      ok: true;\n      op: 'run-edit-script';\n      doc_id: string;\n      plan_id: string;\n      base_version: string;\n      ops_count: number;\n      preview: string;\n      logs: string[];\n      duration_ms: number;\n      committed?: boolean;\n      commit_result?: MedeoCommitResult;\n      collaborated?: boolean;\n      warnings?: MedeoToolWarning[];\n    }\n  | {\n      ok: false;\n      op: 'run-edit-script';\n      doc_id: string;\n      phase: 'parse' | 'runtime' | 'timeout' | 'memory';\n      error: { message: string; line?: number; column?: number; stack?: string };\n      partial: { ops_count: number; logs: string[] };\n    }\n  | {\n      ok: true;\n      op: 'commit-plan';\n      doc_id: string;\n      plan_id: string;\n      committed: boolean;\n      result: MedeoCommitResult;\n      warnings?: MedeoToolWarning[];\n    }\n  | { ok: false; op: MedeoToolOp; error: string };\n\nexport interface MedeoTool {\n  name: typeof MEDEO_TOOL_NAME;\n  description: typeof MEDEO_TOOL_DESCRIPTION;\n  parameters: typeof MEDEO_TOOL_PARAMETERS;\n  getModelContext(input: MedeoModelContextInput): Promise<MedeoModelContext>;\n  handle(input: unknown): Promise<MedeoToolResult>;\n  close(): Promise<void>;\n}\n\ninterface CachedPlan {\n  docId: string;\n  plan: ChangePlan;\n}\n\nconst DEFAULT_MAX_PLANS = 16;\nconst DEFAULT_MAX_MODEL_CONTEXTS = 128;\nconst SNAPSHOT_ROWS = 200;\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n  return value !== null && typeof value === 'object' && !Array.isArray(value);\n}\n\nfunction optionalContext<T>(value: ContextualValue<T> | undefined, docId: string): T | undefined {\n  if (value === undefined) return undefined;\n  return typeof value === 'function' ? (value as (id: string) => T | undefined)(docId) : value;\n}\n\nfunction requiredContext(value: ContextualValue<string>, docId: string, field: string): string {\n  const resolved = optionalContext(value, docId)?.trim();\n  if (resolved == null || resolved.length === 0)\n    throw new Error(`${field} must resolve to a non-empty string for doc ${docId}`);\n  return resolved;\n}\n\nfunction versionOf(doc: ManualSyncDoc): string {\n  return Buffer.from(doc.dsl.doc.oplogVersion().encode()).toString('base64');\n}\n\n/** The document as a script reads it: the first rows of every entity and Relation. */\nfunction renderSnapshot(doc: ManualSyncDoc): string {\n  const view = interpret(loadState(doc.snapshot()));\n  const rows = [...view.entities, ...view.relations].map((row) => JSON.stringify(row));\n  const shown = rows.slice(0, SNAPSHOT_ROWS);\n  return [\n    `entities=${view.entities.length} relations=${view.relations.length}`,\n    ...shown,\n    ...(shown.length < rows.length ? ['[truncated; inspect entities/relations in the sandbox]'] : []),\n  ].join('\\n');\n}\n\nfunction parseInput(value: unknown): MedeoToolInput {\n  if (!isRecord(value)) throw new Error('input must be an object');\n  const op = value.op;\n  const docId = value.doc_id;\n  if (typeof op !== 'string') throw new Error('op must be a string');\n  if (typeof docId !== 'string' || docId.trim().length === 0) throw new Error('doc_id must be a non-empty string');\n  if (op === 'snapshot') return { op, doc_id: docId };\n  if (op === 'run-edit-script') {\n    if (typeof value.script !== 'string' || value.script.length === 0)\n      throw new Error('script must be a non-empty string');\n    const timeoutMs = value.timeout_ms;\n    if (timeoutMs !== undefined && (typeof timeoutMs !== 'number' || !Number.isInteger(timeoutMs) || timeoutMs <= 0))\n      throw new Error('timeout_ms must be a positive integer');\n    const memoryLimitMb = value.memory_limit_mb;\n    if (\n      memoryLimitMb !== undefined &&\n      (typeof memoryLimitMb !== 'number' || !Number.isInteger(memoryLimitMb) || memoryLimitMb < 16)\n    )\n      throw new Error('memory_limit_mb must be an integer >= 16');\n    if (value.auto_commit !== undefined && typeof value.auto_commit !== 'boolean')\n      throw new Error('auto_commit must be a boolean');\n    return {\n      op,\n      doc_id: docId,\n      script: value.script,\n      ...(timeoutMs !== undefined ? { timeout_ms: timeoutMs } : {}),\n      ...(memoryLimitMb !== undefined ? { memory_limit_mb: memoryLimitMb } : {}),\n      ...(value.auto_commit !== undefined ? { auto_commit: value.auto_commit } : {}),\n    };\n  }\n  if (op === 'commit-plan') {\n    if (typeof value.plan_id !== 'string' || value.plan_id.length === 0)\n      throw new Error('plan_id must be a non-empty string');\n    if (value.validation !== undefined && value.validation !== 'preflight')\n      throw new Error('validation must be \"preflight\"');\n    return {\n      op,\n      doc_id: docId,\n      plan_id: value.plan_id,\n      ...(value.validation !== undefined ? { validation: value.validation } : {}),\n    };\n  }\n  throw new Error(`unknown op: ${op}`);\n}\n\n/**\n * Create the Medeo LLM tool. The package owns reading and syncing documents,\n * running scripts, caching plans and publishing them; the host supplies\n * routing, credentials and resource I/O.\n */\nexport function createMedeoTool(options: CreateMedeoToolOptions): MedeoTool {\n  const documents = new Map<string, Promise<ManualSyncDoc>>();\n  const documentTails = new Map<string, Promise<void>>();\n  const pendingPushes = new Map<string, string>();\n  const plans = new Map<string, CachedPlan>();\n  const modelContextMarks = new Map<string, DocVersionMark>();\n  const maxPlans = options.maxPlans ?? DEFAULT_MAX_PLANS;\n  const maxModelContexts = options.maxModelContexts ?? DEFAULT_MAX_MODEL_CONTEXTS;\n  let closed = false;\n\n  /**\n   * Open an existing Mengine document. Creation belongs to Director, which\n   * initializes every project's document before any agent edit, so a 404 here\n   * is a real missing document.\n   */\n  async function getDocument(docId: string): Promise<ManualSyncDoc> {\n    if (closed) throw new Error('medeo tool is closed');\n    const existing = documents.get(docId);\n    if (existing != null) return await existing;\n    const created = (async () => {\n      const client = new MengineHttpClient({\n        docId,\n        httpOrigin: requiredContext(options.httpOrigin, docId, 'httpOrigin'),\n        ...(options.authToken !== undefined ? { authToken: () => optionalContext(options.authToken, docId) } : {}),\n        ...(options.userId !== undefined ? { userId: () => optionalContext(options.userId, docId) } : {}),\n        ...(options.fetchImpl !== undefined ? { fetchImpl: options.fetchImpl } : {}),\n      });\n      const peerId = optionalContext(options.peerId, docId) as ManualSyncDocOptions['peerId'] | undefined;\n      return await ManualSyncDoc.open({ client, ...(peerId !== undefined ? { peerId } : {}) });\n    })();\n    documents.set(docId, created);\n    try {\n      return await created;\n    } catch (error) {\n      if (documents.get(docId) === created) documents.delete(docId);\n      throw error;\n    }\n  }\n\n  /** Calls on one document run one at a time. */\n  async function runExclusive<T>(docId: string, use: (doc: ManualSyncDoc) => Promise<T>): Promise<T> {\n    const previous = documentTails.get(docId) ?? Promise.resolve();\n    let release!: () => void;\n    const gate = new Promise<void>((resolve) => {\n      release = resolve;\n    });\n    const tail = previous.catch(() => {}).then(() => gate);\n    documentTails.set(docId, tail);\n    await previous.catch(() => {});\n    try {\n      return await use(await getDocument(docId));\n    } finally {\n      release();\n      if (documentTails.get(docId) === tail) documentTails.delete(docId);\n    }\n  }\n\n  /** Bring the document up to date before reading or editing it; a failure is a warning. */\n  async function pull(doc: ManualSyncDoc): Promise<{ collaborated: boolean; warnings?: MedeoToolWarning[] }> {\n    const result = await doc.pull();\n    if (result.ok) return { collaborated: result.changed };\n    return { collaborated: false, warnings: [{ kind: 'pull_failed', message: result.error.message }] };\n  }\n\n  function rememberPlan(docId: string, plan: ChangePlan): string {\n    const planId = randomUUID();\n    plans.set(planId, { docId, plan });\n    while (plans.size > maxPlans) {\n      // A plan awaiting a confirmed push, and the one just returned, stay usable.\n      const kept = new Set([...pendingPushes.values(), planId]);\n      const oldest = [...plans.keys()].find((candidate) => !kept.has(candidate));\n      if (oldest === undefined) break;\n      plans.delete(oldest);\n    }\n    return planId;\n  }\n\n  function assertNoPendingPush(docId: string, planId?: string): void {\n    const pending = pendingPushes.get(docId);\n    if (pending !== undefined && pending !== planId)\n      throw new Error(`doc ${docId} has an unconfirmed push; retry plan_id ${pending} before continuing`);\n  }\n\n  async function commit(\n    docId: string,\n    doc: ManualSyncDoc,\n    planId: string,\n    plan: ChangePlan,\n  ): Promise<MedeoCommitResult> {\n    const result: MedeoCommitResult = await commitPlan(doc, plan);\n    if (result.kind === 'unconfirmed') {\n      pendingPushes.set(docId, planId);\n      return result;\n    }\n    pendingPushes.delete(docId);\n    // The local document now holds operations the server refused; read it afresh next time.\n    if (result.kind === 'rejected') {\n      documents.delete(docId);\n      doc.dispose();\n      return result;\n    }\n    if (options.loadGenerationFacts === undefined) return result;\n    const sync = await syncGeneratedRelations(doc, docId, plan.created_media, options.loadGenerationFacts);\n    return {\n      ...result,\n      generation_sync: sync,\n      ...(sync.status === 'failed'\n        ? { warnings: [{ kind: 'generation_sync_failed' as const, message: sync.message }] }\n        : {}),\n    };\n  }\n\n  async function handleInput(input: MedeoToolInput): Promise<MedeoToolResult> {\n    switch (input.op) {\n      case 'snapshot':\n        return await runExclusive(input.doc_id, async (doc) => {\n          assertNoPendingPush(input.doc_id);\n          const pulled = await pull(doc);\n          return {\n            ok: true,\n            op: 'snapshot',\n            doc_id: input.doc_id,\n            version: versionOf(doc),\n            preview: renderSnapshot(doc),\n            collaborated: pulled.collaborated,\n            ...(pulled.warnings ? { warnings: pulled.warnings } : {}),\n          };\n        });\n      case 'run-edit-script':\n        return await runExclusive(input.doc_id, async (doc) => {\n          assertNoPendingPush(input.doc_id);\n          const pulled = await pull(doc);\n          const baseVersion = versionOf(doc);\n          const userId = optionalContext(options.userId, input.doc_id);\n          const run = await runEditScript({\n            docId: input.doc_id,\n            snapshot: doc.dsl.doc.export({ mode: 'snapshot' }),\n            baseVersion,\n            script: input.script,\n            audit: {\n              semantic_op: 'medeo.script',\n              actor: userId ? { user_id: userId, role: 'agent' } : null,\n            },\n            ...(options.loadEntityAsset\n              ? { loadEntityAsset: (entity) => options.loadEntityAsset!(input.doc_id, entity) }\n              : {}),\n            ...(options.uploadText ? { uploadText: (text) => options.uploadText!(input.doc_id, text) } : {}),\n            timeoutMs: input.timeout_ms ?? options.sandbox?.timeoutMs ?? 30_000,\n            memoryLimitMb: input.memory_limit_mb ?? options.sandbox?.memoryLimitMb ?? 256,\n          });\n          if (!run.ok)\n            return {\n              ok: false,\n              op: 'run-edit-script',\n              doc_id: input.doc_id,\n              phase: run.phase,\n              error: run.error,\n              partial: { ops_count: run.partial.commandsCount, logs: run.partial.logs },\n            };\n          const planId = rememberPlan(input.doc_id, run.plan);\n          const committed = input.auto_commit ? await commit(input.doc_id, doc, planId, run.plan) : undefined;\n          return {\n            ok: true,\n            op: 'run-edit-script',\n            doc_id: input.doc_id,\n            plan_id: planId,\n            base_version: baseVersion,\n            ops_count: run.plan.commands_count,\n            preview: run.plan.preview,\n            logs: run.plan.logs,\n            duration_ms: run.durationMs,\n            collaborated: pulled.collaborated,\n            ...(committed ? { committed: committed.kind === 'committed', commit_result: committed } : {}),\n            ...(pulled.warnings || committed?.warnings\n              ? { warnings: [...(pulled.warnings ?? []), ...(committed?.warnings ?? [])] }\n              : {}),\n          };\n        });\n      case 'commit-plan':\n        return await runExclusive(input.doc_id, async (doc) => {\n          const cached = plans.get(input.plan_id);\n          if (!cached || cached.docId !== input.doc_id) throw new Error(`unknown plan_id ${input.plan_id}`);\n          assertNoPendingPush(input.doc_id, input.plan_id);\n          const result = await commit(input.doc_id, doc, input.plan_id, cached.plan);\n          if (result.kind !== 'unconfirmed') plans.delete(input.plan_id);\n          return {\n            ok: true,\n            op: 'commit-plan',\n            doc_id: input.doc_id,\n            plan_id: input.plan_id,\n            committed: result.kind === 'committed',\n            result,\n            ...(result.warnings ? { warnings: result.warnings } : {}),\n          };\n        });\n    }\n  }\n\n  return {\n    name: MEDEO_TOOL_NAME,\n    description: MEDEO_TOOL_DESCRIPTION,\n    parameters: MEDEO_TOOL_PARAMETERS,\n    async getModelContext(input) {\n      if (!isRecord(input) || typeof input.doc_id !== 'string' || typeof input.context_id !== 'string')\n        throw new Error('getModelContext requires doc_id and context_id');\n      return await runExclusive(input.doc_id, async (doc) => {\n        await pull(doc);\n        const key = `${input.doc_id}\\u0000${input.context_id}`;\n        const previous = modelContextMarks.get(key);\n        const updated = previous === undefined ? null : doc.hasChangedSince(previous);\n        modelContextMarks.delete(key);\n        modelContextMarks.set(key, doc.versionMark());\n        while (modelContextMarks.size > maxModelContexts)\n          modelContextMarks.delete(modelContextMarks.keys().next().value!);\n        const version = versionOf(doc);\n        return {\n          prompt: renderMedeoModelContext({ documentVersion: version, updatedSincePreviousModelCall: updated }),\n          document_version: version,\n          updated_since_previous_model_call: updated,\n        };\n      });\n    },\n    async handle(raw) {\n      let input: MedeoToolInput;\n      try {\n        input = parseInput(raw);\n      } catch (error) {\n        const op = isRecord(raw) && typeof raw.op === 'string' ? (raw.op as MedeoToolOp) : 'snapshot';\n        return { ok: false, op, error: error instanceof Error ? error.message : String(error) };\n      }\n      try {\n        return await handleInput(input);\n      } catch (error) {\n        return { ok: false, op: input.op, error: error instanceof Error ? error.message : String(error) };\n      }\n    },\n    async close() {\n      if (closed) return;\n      closed = true;\n      const docs = await Promise.allSettled(documents.values());\n      documents.clear();\n      for (const doc of docs) if (doc.status === 'fulfilled') doc.value.dispose();\n      plans.clear();\n      pendingPushes.clear();\n    },\n  };\n}\n"],"mappings":"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"}