synartesis 0.3.2 → 0.3.3

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.
package/CHANGELOG.md CHANGED
@@ -2,6 +2,32 @@
2
2
 
3
3
  What changed, and why it mattered. Dates are release dates.
4
4
 
5
+ ## 0.3.3 — 2026-09-03
6
+
7
+ ### Changed
8
+
9
+ - **Source maps no longer ship.** They were 385 kB of a 603 kB install and
10
+ nothing ever read them: no `--enable-source-maps` in the shebang, nothing
11
+ calling `setSourceMapsEnabled`, nothing in `package.json`, so Node never
12
+ consulted them. Verified they are not load-bearing by deleting them and
13
+ running the CLI, the error paths and the proxy, with and without
14
+ `--enable-source-maps`: no warning, no error, identical output. The package
15
+ goes from 17 files to 13, 164 kB to 61 kB packed, 603 kB to 219 kB
16
+ unpacked. They are still generated for local development.
17
+
18
+ ### Fixed
19
+
20
+ - **The documented snapshot ceiling was wrong.** The README and the site both
21
+ said a resource over roughly three megabytes cannot be captured and the
22
+ write is refused. Measured against the bundled filesystem policy: a 4 MB
23
+ file was captured whole and restored byte for byte, and 8 MB and above was
24
+ refused with the file untouched. The number was wrong in the user's favour,
25
+ which is still wrong on the one page whose job is to be exact about limits.
26
+ Where the ceiling falls depends on the server and its transport, so the
27
+ text now says a few megabytes and carries the measured figures. The
28
+ behaviour was never in doubt: when the pre-read cannot complete, the write
29
+ does not happen.
30
+
5
31
  ## 0.3.2 — 2026-08-30
6
32
 
7
33
  ### Fixed
package/README.md CHANGED
@@ -466,12 +466,17 @@ one. Every policy bundled here declares it.
466
466
 
467
467
  ### The size of what you can snapshot
468
468
 
469
- A resource of more than roughly three megabytes cannot be read back through a
470
- stdio MCP connection — the reply is too large to carry, and the connection
471
- closes. Synartesis reconnects and says so, and refuses the write rather than
472
- applying a change it could not capture. That is the right answer, but it does
473
- mean **writes to very large files are refused, not undone**. Nothing is lost;
474
- the call simply does not go through.
469
+ Past a few megabytes a resource cannot be read back through a stdio MCP
470
+ connection — the reply is too large to carry, and the connection closes.
471
+ Synartesis reconnects and says so, and refuses the write rather than applying a
472
+ change it could not capture. That is the right answer, but it does mean
473
+ **writes to very large files are refused, not undone**. Nothing is lost; the
474
+ call simply does not go through.
475
+
476
+ Where the ceiling falls depends on the server and its transport, so no exact
477
+ figure here would be true of every one. Measured against the bundled
478
+ filesystem policy: a 4 MB file was captured and restored intact; 8 MB and above
479
+ was refused with the file untouched.
475
480
 
476
481
  ## Commands
477
482
 
package/dist/cli.js CHANGED
@@ -1429,6 +1429,9 @@ ${listed(candidates)}`
1429
1429
  }
1430
1430
  return only;
1431
1431
  }
1432
+ if (given === "") {
1433
+ throw new UsageError(`no ${noun.one} was named; an empty id is usually an unset variable`);
1434
+ }
1432
1435
  const exact = candidates.find((item) => item.id === given);
1433
1436
  if (exact !== void 0) {
1434
1437
  return exact;
@@ -1672,8 +1675,14 @@ function runPrune(argv, journal, journalPath) {
1672
1675
  return 0;
1673
1676
  }
1674
1677
  function runClose(argv, journal) {
1675
- const active = journal.listRuns().filter((candidate) => candidate.status === "active");
1676
- const run = pick([...active].reverse(), positional(argv)[1], RUN, true);
1678
+ const all = journal.listRuns();
1679
+ const given = positional(argv)[1];
1680
+ const run = given === void 0 ? pick(
1681
+ [...all.filter((candidate) => candidate.status === "active")].reverse(),
1682
+ void 0,
1683
+ RUN,
1684
+ true
1685
+ ) : pick([...all].reverse(), given, RUN, true);
1677
1686
  const closed = journal.closeAbandonedRun(run.id);
1678
1687
  out("");
1679
1688
  out(
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "synartesis",
3
- "version": "0.3.2",
3
+ "version": "0.3.3",
4
4
  "description": "An undo layer for AI agents.",
5
5
  "type": "module",
6
6
  "private": false,
@@ -30,6 +30,7 @@
30
30
  "dist",
31
31
  "!dist/toy-crm.*",
32
32
  "!dist/demo-agent.*",
33
+ "!dist/*.map",
33
34
  "manifests",
34
35
  "!manifests/toy-crm.yaml",
35
36
  "README.md",
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/invocation.ts","../src/locate.ts","../src/style.ts","../src/journal/journal.ts","../src/canonical.ts","../src/journal/schema.ts","../src/manifest/load.ts","../src/manifest/template.ts","../src/manifest/verify.ts","../src/manifest/types.ts","../src/proxy/routing.ts","../src/proxy/upstream.ts","../src/manifest/match.ts","../src/proxy/snapshot.ts"],"sourcesContent":["import { accessSync, constants } from \"node:fs\";\nimport { basename, delimiter, join } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\n\n/**\n * How to invoke this CLI, as the reader would have to type it.\n *\n * Printing `synartesis approve ...` is only useful advice if that command\n * exists. Until someone installs it globally it does not, and telling a person\n * to run something that is not there is worse than saying nothing.\n */\nfunction onPath(command: string): boolean {\n const dirs = (process.env[\"PATH\"] ?? \"\").split(delimiter).filter((dir) => dir !== \"\");\n return dirs.some((dir) => {\n try {\n accessSync(join(dir, command), constants.X_OK);\n return true;\n } catch {\n return false;\n }\n });\n}\n\nlet cached: string | undefined;\n\nexport function cliCommand(): string {\n if (cached !== undefined) {\n return cached;\n }\n\n // Installed globally: the shim is a file named for the command itself.\n const invokedAs = process.argv[1];\n if (invokedAs !== undefined && basename(invokedAs) === \"synartesis\") {\n cached = \"synartesis\";\n return cached;\n }\n if (onPath(\"synartesis\")) {\n cached = \"synartesis\";\n return cached;\n }\n\n // Run straight out of a checkout. Spell out what actually works.\n cached = `node ${invokedAs ?? \"dist/cli.js\"}`;\n return cached;\n}\n\n/**\n * The same, worked out from inside the proxy, which lives beside the cli in\n * whatever directory the build put them.\n */\nexport function cliCommandFrom(moduleUrl: string): string {\n if (onPath(\"synartesis\")) {\n return \"synartesis\";\n }\n return `node ${fileURLToPath(new URL(\"cli.js\", moduleUrl))}`;\n}\n\n/**\n * How to start the proxy, as the reader would have to type it.\n *\n * `synartesis proxy` where the cli is reachable: one package and one word is\n * the line people paste into a client config, and it is the same line whether\n * this was installed or is being fetched on the spot. The separate\n * synartesis-proxy binary still exists and is still what an existing config\n * points at; it is simply no longer the shortest way to say it.\n */\nexport function proxyCommand(): string {\n if (onPath(\"synartesis\")) {\n return \"synartesis proxy\";\n }\n if (onPath(\"synartesis-proxy\")) {\n return \"synartesis-proxy\";\n }\n const invokedAs = process.argv[1];\n if (invokedAs !== undefined && invokedAs.endsWith(\"cli.js\")) {\n return `node ${invokedAs} proxy`;\n }\n return `node ${fileURLToPath(new URL(\"cli.js\", import.meta.url))} proxy`;\n}\n","import { existsSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { dirname, join, resolve } from \"node:path\";\n\n/**\n * Where the policy and the journal are, when nobody said.\n *\n * Typing --manifest and --journal on every command is the friction people\n * actually feel. A policy that belongs to a project sits in it, so both are\n * looked for the way a version control tool looks for its root: from here,\n * upwards, until found.\n *\n * And when there is nothing above you either, there is one home. Most of what\n * anyone guards -- an agent's memory, a notes directory, an account somewhere\n * -- does not belong to a project at all, and making each one its own\n * directory with its own manifest and its own journal is how a home ends up\n * with synartesis-this and synartesis-that in it and no single place that\n * knows what an agent has done.\n */\nexport const MANIFEST_NAME = \"synartesis.yaml\";\nexport const JOURNAL_NAME = \"journal.db\";\nconst NESTED_JOURNAL = join(\".synartesis\", JOURNAL_NAME);\n\n/** Overridable, so a test never has to touch the real one. */\nexport function home(): string {\n return process.env[\"SYNARTESIS_HOME\"] ?? join(homedir(), \".synartesis\");\n}\n\nfunction walkUp(from: string, name: string): string | undefined {\n let dir = resolve(from);\n for (;;) {\n const candidate = join(dir, name);\n if (existsSync(candidate)) {\n return candidate;\n }\n const parent = dirname(dir);\n if (parent === dir) {\n return undefined;\n }\n dir = parent;\n }\n}\n\nexport function findManifest(given?: string): string {\n if (given !== undefined) {\n return given;\n }\n return walkUp(process.cwd(), MANIFEST_NAME) ?? join(home(), MANIFEST_NAME);\n}\n\n/**\n * A journal beside the manifest, since that is where a proxy started from that\n * manifest will have been told to put one. Falls back to the nested default so\n * an existing setup keeps working.\n */\nexport function findJournal(given?: string, manifest?: string): string {\n if (given !== undefined) {\n return given;\n }\n\n const near = manifest === undefined ? undefined : dirname(resolve(manifest));\n for (const dir of [near, process.cwd()]) {\n if (dir === undefined) {\n continue;\n }\n for (const name of [JOURNAL_NAME, NESTED_JOURNAL]) {\n const candidate = join(dir, name);\n if (existsSync(candidate)) {\n return candidate;\n }\n }\n }\n\n const found = walkUp(process.cwd(), NESTED_JOURNAL) ?? walkUp(process.cwd(), JOURNAL_NAME);\n if (found !== undefined) {\n return found;\n }\n\n // Nothing exists yet. Beside the policy, so the proxy that creates it and the\n // cli that reads it agree without either being told where to look.\n return near === undefined ? join(home(), JOURNAL_NAME) : join(near, JOURNAL_NAME);\n}\n","/**\n * The house style, translated for a terminal.\n *\n * Oxblood and a warm off-white, uppercase letterspaced labels, everything\n * quiet except the one thing that matters. A terminal has no serif and no\n * engraving, so what carries over is the palette, the capitals and the\n * restraint.\n */\nconst ESC = \"\\u001b[\";\nconst ACCENT = `${ESC}38;2;226;134;118m`;\n// Deep oxblood with a warm off-white on it, which holds on a light terminal\n// as well as a dark one.\nconst ON_ACCENT = `${ESC}48;2;94;20;32m${ESC}38;2;246;233;229m`;\nconst BRIGHT = `${ESC}38;2;246;233;229m`;\nconst DIM = `${ESC}2m`;\nconst BOLD = `${ESC}1m`;\nconst RESET = `${ESC}0m`;\n\n/**\n * Colour is for people. Piped output goes to a program that wants the text and\n * not the escape codes, and NO_COLOR is the convention for saying so outright.\n */\nconst enabled =\n process.env[\"NO_COLOR\"] === undefined &&\n process.env[\"TERM\"] !== \"dumb\" &&\n process.stdout.isTTY;\n\nfunction paint(codes: string, text: string): string {\n return enabled ? `${codes}${text}${RESET}` : text;\n}\n\n/**\n * Letterspacing, the one typographic move a terminal can actually make. Only\n * ever applied to the plain ascii labels below, so splitting by code unit is\n * safe here in a way it would not be for arbitrary text.\n */\nexport function spaced(text: string): string {\n return Array.from(text).join(\" \");\n}\n\nexport const style = {\n /** A section label: small, capital, spaced out. */\n label: (text: string): string => paint(ACCENT + DIM, spaced(text.toUpperCase())),\n heading: (text: string): string => paint(BRIGHT + BOLD, text.toUpperCase()),\n accent: (text: string): string => paint(ACCENT, text),\n strong: (text: string): string => paint(BOLD, text),\n quiet: (text: string): string => paint(DIM, text),\n /** Off-white on oxblood, the way the wordmark is set. */\n plate: (text: string): string => paint(ON_ACCENT + BOLD, ` ${text} `),\n};\n\nexport const WORDMARK = spaced(\"SYNARTESIS\");\n\n/**\n * A meander, the Greek fret. A single line that turns back on itself without\n * ever breaking, which is the same idea the name carries and the same idea the\n * product does.\n */\nexport function meander(width: number): string {\n const unit = \"\\u2517\\u2501\\u2513\\u250f\\u2501\\u251b\";\n return unit.repeat(Math.max(1, Math.ceil(width / unit.length))).slice(0, width);\n}\n\n/** A dim fret rule, for separating one region of output from the next. */\nexport function rule(width = 48): string {\n return style.quiet(meander(width));\n}\n\n/**\n * Greek sunartesis, a fastening together. The whole idea in one word: every\n * action is bound to the action that undoes it.\n */\nexport const GREEK = spaced(\"\\u03a3\\u03a5\\u039d\\u0391\\u03a1\\u03a4\\u0397\\u03a3\\u0399\\u03a3\");\nexport const MEANING = \"a fastening together\";\nexport const TAGLINE = \"an undo layer for AI agents\";\n\n/** One compact line, for a process whose real output is something else. */\nexport function mark(): string {\n return `\\n ${style.plate(WORDMARK)} ${style.quiet(MEANING)}\\n\\n`;\n}\n\nexport function banner(): string {\n return [\n \"\",\n ` ${style.plate(WORDMARK)}`,\n ` ${style.accent(meander(24))}`,\n \"\",\n ` ${style.quiet(GREEK)} ${style.quiet(\"\\u00b7\")} ${style.quiet(MEANING)}`,\n \"\",\n ` ${style.accent(spaced(TAGLINE.toUpperCase()))}`,\n ` ${style.quiet(\"Every action is bound to the action that undoes it.\")}`,\n \"\",\n ].join(\"\\n\");\n}\n\n/**\n * What to say when there is no journal yet.\n *\n * The screen and `watch` have always said this; the scriptable commands aborted\n * with \"there is no journal at <path>\" instead, which is true and leads\n * nowhere. Someone who types `synartesis list` before pointing an agent at\n * anything has not made a mistake -- they are early.\n */\nexport const NOTHING_RECORDED_YET = [\n \"One appears the first time an agent calls a tool through the proxy.\",\n \"Point your client at it, then work as usual; this will fill in.\",\n];\n","import { chmodSync, existsSync, mkdirSync } from \"node:fs\";\nimport { dirname } from \"node:path\";\n\nimport Database from \"better-sqlite3\";\nimport { z } from \"zod\";\n\nimport { canonical } from \"../canonical.js\";\nimport { JournalError } from \"../errors.js\";\nimport { SCHEMA_SQL, SCHEMA_VERSION } from \"./schema.js\";\n\nexport type RunStatus = \"active\" | \"complete\" | \"rolled_back\" | \"partial\";\n\n/**\n * How a row says its approval was moved onto the action that ran. There is no\n * status for it -- adding one would change the schema, and an older journal\n * cannot be read under a newer schema -- so the row is denied and this is how\n * it is told apart from a person having said no.\n */\nexport const SPENT_APPROVAL = \"approval was used by action\";\n\nexport type ActionStatus =\n | \"pending\"\n | \"gated\"\n /** A person said yes; the agent has not made the call again yet. */\n | \"approved\"\n | \"denied\"\n | \"applied\"\n | \"failed\"\n | \"rolling_back\"\n | \"rolled_back\"\n | \"unrecoverable\";\n\nexport type ActionClass =\n | \"unclassified\"\n | \"readonly\"\n | \"reversible\"\n | \"compensable\"\n | \"irreversible\";\n\nexport interface RunRow {\n readonly id: string;\n readonly label: string | undefined;\n readonly startedAt: string;\n readonly endedAt: string | undefined;\n readonly status: RunStatus;\n}\n\nexport interface ActionRow {\n readonly id: string;\n readonly runId: string;\n readonly seq: number;\n readonly server: string;\n readonly tool: string;\n readonly args: unknown;\n readonly class: ActionClass;\n readonly snapshot: unknown;\n readonly postSnapshot: unknown;\n readonly result: unknown;\n readonly inverse: unknown;\n /** The read that detects drift, resolved at capture time. */\n readonly verify: unknown;\n readonly error: string | undefined;\n readonly idempotencyKey: string;\n readonly status: ActionStatus;\n readonly approvedBy: string | undefined;\n readonly approvedAt: string | undefined;\n readonly ts: string;\n}\n\nexport interface RecordPendingInput {\n readonly runId: string;\n readonly server: string;\n readonly tool: string;\n readonly args: unknown;\n readonly class: ActionClass;\n}\n\nexport interface AppliedOutcome {\n readonly result: unknown;\n /** Fully resolved at capture time (D5); absent when the class has no inverse. */\n readonly inverse?: unknown;\n /** The resolved read used to detect drift later. */\n readonly verify?: unknown;\n /** Post-state for drift detection; absent when the post-read could not run. */\n readonly postSnapshot?: unknown;\n /**\n * A non-fatal problem. `status` says what happened to the call; `error` says\n * what went wrong, and the two are independent: an applied call whose inverse\n * could not be built is both applied and no longer safely reversible.\n */\n readonly warning?: string;\n}\n\nexport interface PendingAction {\n readonly actionId: string;\n readonly seq: number;\n readonly idempotencyKey: string;\n}\n\nconst runSchema = z.object({\n id: z.string(),\n label: z.string().nullable(),\n started_at: z.string(),\n ended_at: z.string().nullable(),\n status: z.enum([\"active\", \"complete\", \"rolled_back\", \"partial\"]),\n});\n\nconst actionSchema = z.object({\n id: z.string(),\n run_id: z.string(),\n seq: z.number(),\n server: z.string(),\n tool: z.string(),\n args_json: z.string(),\n class: z.enum([\"unclassified\", \"readonly\", \"reversible\", \"compensable\", \"irreversible\"]),\n snapshot_json: z.string().nullable(),\n post_snapshot_json: z.string().nullable(),\n result_json: z.string().nullable(),\n inverse_json: z.string().nullable(),\n verify_json: z.string().nullable(),\n error: z.string().nullable(),\n idempotency_key: z.string(),\n status: z.enum([\n \"pending\",\n \"gated\",\n \"approved\",\n \"denied\",\n \"applied\",\n \"failed\",\n \"rolling_back\",\n \"rolled_back\",\n \"unrecoverable\",\n ]),\n approved_by: z.string().nullable(),\n approved_at: z.string().nullable(),\n ts: z.string(),\n});\n\nfunction decode(value: string | null): unknown {\n return value === null ? undefined : (JSON.parse(value) as unknown);\n}\n\nfunction orUndefined(value: string | null): string | undefined {\n return value === null ? undefined : value;\n}\n\nfunction toRun(raw: unknown): RunRow {\n const row = runSchema.parse(raw);\n return {\n id: row.id,\n label: orUndefined(row.label),\n startedAt: row.started_at,\n endedAt: orUndefined(row.ended_at),\n status: row.status,\n };\n}\n\nfunction toAction(raw: unknown): ActionRow {\n const row = actionSchema.parse(raw);\n return {\n id: row.id,\n runId: row.run_id,\n seq: row.seq,\n server: row.server,\n tool: row.tool,\n args: decode(row.args_json),\n class: row.class,\n snapshot: decode(row.snapshot_json),\n postSnapshot: decode(row.post_snapshot_json),\n result: decode(row.result_json),\n inverse: decode(row.inverse_json),\n verify: decode(row.verify_json),\n error: orUndefined(row.error),\n idempotencyKey: row.idempotency_key,\n status: row.status,\n approvedBy: orUndefined(row.approved_by),\n approvedAt: orUndefined(row.approved_at),\n ts: row.ts,\n };\n}\n\nexport interface Journal {\n beginRun(label: string | undefined): string;\n endRun(runId: string, status: RunStatus): void;\n /**\n * Closes a run whose proxy went away without saying so. Only a person can\n * ask for this: several proxies may share one journal, so a run left active\n * is indistinguishable from a run still being worked on, and closing one\n * that is live would make its remaining actions land in a finished run.\n *\n * Returns false when the run is already closed. Ends it at its last action\n * rather than now, since that is when anything last actually happened.\n */\n closeAbandonedRun(runId: string): boolean;\n setRunLabel(runId: string, label: string): void;\n recordPending(input: RecordPendingInput): PendingAction;\n attachSnapshot(actionId: string, snapshot: unknown): void;\n markApplied(actionId: string, outcome: AppliedOutcome): void;\n markFailed(actionId: string, error: string): void;\n markUnknown(actionId: string, error: string): void;\n /**\n * Claims an action for this rollback. Returns false when it was not this\n * call that moved it out of `applied`, which is how two undos running at\n * once are told apart from one resuming after a crash.\n */\n markRollingBack(actionId: string): boolean;\n markRolledBack(actionId: string): void;\n markUnrecoverable(actionId: string, error: string): void;\n markInverseRejected(actionId: string, error: string): void;\n markUnknownInverse(actionId: string, error: string): void;\n /**\n * `why` is kept on the row so the person deciding can see the reason\n * without the proxy running. It goes in `error`, which is already where a\n * row explains the state it is in.\n */\n markGated(actionId: string, why?: string): void;\n /** About to go out: from here on its outcome is genuinely unknown. */\n markInFlight(actionId: string): void;\n /** Returns false when the action is no longer awaiting a decision. */\n approve(actionId: string, by: string): boolean;\n deny(actionId: string, by: string | undefined, reason: string): boolean;\n /**\n * Records a refusal whatever state the row is in. `deny` is conditional\n * because an operator's decision must not overwrite one already settled; the\n * proxy needs the opposite, to record that an action it had approval for was\n * still not carried out.\n */\n settleAsDenied(actionId: string, by: string | undefined, reason: string): void;\n /**\n * Moves an approval granted in an earlier session onto the action that is\n * about to run, and spends the original so it cannot be used twice.\n */\n adoptApproval(actionId: string, granted: ActionRow): void;\n listGated(): readonly ActionRow[];\n /**\n * An approval that was granted but never carried out, for this exact call.\n * A retry after an out-of-band approval reuses that row rather than opening\n * a second one, so the approval sits on the action that actually ran.\n */\n findApproval(query: {\n server: string;\n tool: string;\n args: unknown;\n /** ISO timestamp; approvals older than this are ignored. */\n notBefore: string;\n }): ActionRow | undefined;\n /**\n * A call in this run that is already waiting for a decision. An agent told\n * to try again will often try again before anyone has answered, and a second\n * row for one decision is worse than useless: `approve` then refuses to act\n * without an id, and approving either one leaves its twin waiting for ever.\n */\n findGated(query: {\n runId: string;\n server: string;\n tool: string;\n args: unknown;\n }): ActionRow | undefined;\n getAction(actionId: string): ActionRow | undefined;\n listRuns(): readonly RunRow[];\n getRun(runId: string): RunRow | undefined;\n getActions(runId: string): readonly ActionRow[];\n /** The newest actions across every run, for watching work as it happens. */\n recentActions(limit: number): readonly ActionRow[];\n /**\n * Runs old enough to discard and finished enough that discarding one loses\n * nothing anybody can still act on. Everything still in play is excluded\n * whatever its age: an active run, and any run holding an action that is\n * `pending` (a call went out and nobody knows what it did), `gated` (a\n * person has not decided yet) or `rolling_back` (an inverse may be half\n * applied). Age is not a reason to throw away an unanswered question.\n */\n prunableRuns(before: string): readonly PrunableRun[];\n /** Removes runs and their actions. Returns what actually went. */\n deleteRuns(runIds: readonly string[]): { runs: number; actions: number };\n /**\n * Reclaims the space the deletes freed. Deleting rows leaves a SQLite file\n * exactly as large as it was, so without this a prune frees nothing a user\n * can see. Cannot run inside a transaction.\n */\n vacuum(): void;\n pragma(name: string): unknown;\n close(): void;\n}\n\nexport interface PrunableRun {\n readonly id: string;\n readonly label: string | undefined;\n /** When it last did anything, which is what its age is measured from. */\n readonly at: string;\n readonly status: RunStatus;\n readonly actions: number;\n}\n\n/**\n * A journal is not a log. To put a file back, its previous contents have to be\n * kept, so this database holds a verbatim copy of everything an agent\n * overwrote -- and, in the arguments, everything it wrote. A key that was\n * sitting in a file the agent touched is in here in plain text.\n *\n * SQLite creates its file with whatever the umask allows, which is 0644 on an\n * ordinary machine: readable by every other account, and by anything walking\n * $HOME. This is the ~/.ssh case, and it gets the ~/.ssh answer.\n *\n * On every open rather than only on create, because the journals that most\n * need this are the ones already sitting on disk. Nothing legitimate wants a\n * shared journal: several proxies sharing one are several processes of one\n * person, which 0600 allows.\n */\nfunction restrictToOwner(path: string): void {\n // The sidecars carry the same content. WAL is enabled just after this, so\n // they may not exist yet -- SQLite gives a new one the mode of the database\n // file, and the next open catches any that were made before this ran.\n for (const file of [path, `${path}-wal`, `${path}-shm`]) {\n try {\n if (existsSync(file)) {\n chmodSync(file, 0o600);\n }\n } catch {\n // Windows chmod only moves a read-only bit, and some network mounts\n // refuse it outright. Neither is a reason to stop a working tool: the\n // warning belongs in the docs, not in a crash here.\n }\n }\n}\n\n/**\n * Opening, with the failures named. better-sqlite3 reports \"file is not a\n * database\" and \"unable to open database file\" and leaves out which file it\n * meant, which is unhelpful precisely when the path was the mistake.\n */\nfunction openDatabase(path: string): Database.Database {\n try {\n const db = new Database(path);\n // Before the first pragma, so the window in which the file exists at the\n // umask's mode is as short as it can be made from here.\n if (path !== \":memory:\") {\n restrictToOwner(path);\n }\n // The pragmas, not the constructor: better-sqlite3 opens lazily, so a file\n // that is not a database is only found out on the first read.\n db.pragma(\"journal_mode = WAL\");\n db.pragma(\"foreign_keys = ON\");\n // WAL lets readers and one writer work at once; a second writer still has\n // to wait its turn, and without this SQLite does not wait at all -- it\n // fails immediately with \"database is locked\". Six agents sharing one\n // journal lost two of their calls that way, which is the arrangement this\n // tool recommends. Writes here are tiny, so the wait is milliseconds; the\n // five seconds is the ceiling before something is genuinely wedged.\n db.pragma(\"busy_timeout = 5000\");\n // Again, because turning WAL on is what creates the sidecars, and they\n // hold the same content as the database they belong to.\n if (path !== \":memory:\") {\n restrictToOwner(path);\n }\n return db;\n } catch (error) {\n const detail = error instanceof Error ? error.message : String(error);\n if (detail.includes(\"not a database\")) {\n throw new JournalError(\n \"open\",\n `${path} is not a Synartesis journal. Point --journal at a journal, or at a new file to start one.`,\n );\n }\n throw new JournalError(\"open\", `the journal at ${path} could not be opened: ${detail}`);\n }\n}\n\nclass SqliteJournal implements Journal {\n readonly #db: Database.Database;\n\n constructor(path: string) {\n if (path !== \":memory:\") {\n // 0700 for the same reason the journal is 0600. A umask can only clear\n // bits, never set them, so this is the mode on any ordinary machine.\n mkdirSync(dirname(path), { recursive: true, mode: 0o700 });\n }\n // Opening is the one step a user is most likely to get wrong -- a typo in\n // --journal, a path that is a directory, a file that is something else\n // entirely -- and it was the one step whose errors went out raw, as a bare\n // \"file is not a database\" naming neither the file nor the tool.\n // WAL so a reader (the CLI) never blocks the proxy mid-run.\n this.#db = openDatabase(path);\n\n const existing = z.number().parse(this.#db.pragma(\"user_version\", { simple: true }));\n const populated =\n z\n .object({ count: z.number() })\n .parse(\n this.#db\n .prepare(\"SELECT COUNT(*) AS count FROM sqlite_master WHERE type = 'table' AND name = 'runs'\")\n .get(),\n ).count > 0;\n if (populated && existing !== SCHEMA_VERSION) {\n // Reinterpreting an older journal under a newer schema would risk\n // reading a rollback state that was never written.\n throw new JournalError(\n \"open\",\n `journal at ${path} was written by schema version ${String(existing)}, but this build expects ${String(SCHEMA_VERSION)}. ` +\n `Point --journal at a new file to carry on, and keep this one: everything an agent did is in it. Delete it only once you are sure you do not want that history.`,\n );\n }\n\n this.#db.exec(SCHEMA_SQL);\n this.#db.pragma(`user_version = ${String(SCHEMA_VERSION)}`);\n }\n\n beginRun(label: string | undefined): string {\n const id = crypto.randomUUID();\n this.#run(\"beginRun\", () => {\n this.#db\n .prepare(\"INSERT INTO runs (id, label, started_at, status) VALUES (?, ?, ?, 'active')\")\n .run(id, label ?? null, new Date().toISOString());\n });\n return id;\n }\n\n endRun(runId: string, status: RunStatus): void {\n this.#run(\"endRun\", () => {\n this.#db\n .prepare(\"UPDATE runs SET ended_at = ?, status = ? WHERE id = ?\")\n .run(new Date().toISOString(), status, runId);\n });\n }\n\n closeAbandonedRun(runId: string): boolean {\n return this.#run(\"closeAbandonedRun\", () => {\n const last = z\n .object({ ts: z.string().nullable() })\n .parse(\n this.#db\n .prepare(\"SELECT MAX(ts) AS ts FROM actions WHERE run_id = ?\")\n .get(runId) ?? { ts: null },\n ).ts;\n const result = this.#db\n .prepare(\"UPDATE runs SET ended_at = ?, status = 'complete' WHERE id = ? AND status = 'active'\")\n .run(last ?? new Date().toISOString(), runId);\n return result.changes === 1;\n });\n }\n\n setRunLabel(runId: string, label: string): void {\n this.#run(\"setRunLabel\", () => {\n this.#db.prepare(\"UPDATE runs SET label = ? WHERE id = ?\").run(label, runId);\n });\n }\n\n recordPending(input: RecordPendingInput): PendingAction {\n return this.#run(\"recordPending\", () => {\n const insert = this.#db.transaction((): PendingAction => {\n const next = this.#db\n .prepare(\"SELECT COALESCE(MAX(seq), 0) + 1 AS seq FROM actions WHERE run_id = ?\")\n .get(input.runId);\n const seq = z.object({ seq: z.number() }).parse(next).seq;\n const actionId = crypto.randomUUID();\n // Derived rather than random: a retried rollback must present the same\n // key for the same action, which is the whole point of D7.\n const idempotencyKey = `${input.runId}:${String(seq)}`;\n\n this.#db\n .prepare(\n `INSERT INTO actions\n (id, run_id, seq, server, tool, args_json, class, idempotency_key, status, ts)\n VALUES (?, ?, ?, ?, ?, ?, ?, ?, 'pending', ?)`,\n )\n .run(\n actionId,\n input.runId,\n seq,\n input.server,\n input.tool,\n JSON.stringify(input.args ?? {}),\n input.class,\n idempotencyKey,\n new Date().toISOString(),\n );\n\n return { actionId, seq, idempotencyKey };\n });\n // immediate, not deferred. This reads the highest seq and then inserts,\n // and SQLite will not upgrade a read lock to a write one while another\n // writer has committed in between -- it returns \"database is locked\"\n // straight away, and busy_timeout does not apply to that case. Taking\n // the write lock up front is what makes the wait actually happen.\n return insert.immediate();\n });\n }\n\n attachSnapshot(actionId: string, snapshot: unknown): void {\n this.#run(\"attachSnapshot\", () => {\n this.#db\n .prepare(\"UPDATE actions SET snapshot_json = ? WHERE id = ?\")\n .run(JSON.stringify(snapshot ?? null), actionId);\n });\n }\n\n markApplied(actionId: string, outcome: AppliedOutcome): void {\n this.#run(\"markApplied\", () => {\n this.#db\n .prepare(\n `UPDATE actions\n SET status = 'applied',\n result_json = ?,\n inverse_json = ?,\n verify_json = ?,\n post_snapshot_json = ?,\n error = ?\n WHERE id = ?`,\n )\n .run(\n JSON.stringify(outcome.result ?? null),\n outcome.inverse === undefined ? null : JSON.stringify(outcome.inverse),\n outcome.verify === undefined ? null : JSON.stringify(outcome.verify),\n outcome.postSnapshot === undefined ? null : JSON.stringify(outcome.postSnapshot),\n outcome.warning ?? null,\n actionId,\n );\n });\n }\n\n markFailed(actionId: string, error: string): void {\n this.#run(\"markFailed\", () => {\n this.#db\n .prepare(\"UPDATE actions SET status = 'failed', error = ? WHERE id = ?\")\n .run(error, actionId);\n });\n }\n\n /**\n * The call was interrupted, so whether the upstream applied it is genuinely\n * unknown. The row deliberately stays `pending`: recording it as failed\n * would assert something we cannot know, and section 3.1 wants exactly this\n * case surfaced rather than resolved by guesswork.\n */\n markUnknown(actionId: string, error: string): void {\n this.#run(\"markUnknown\", () => {\n this.#db\n .prepare(\"UPDATE actions SET status = 'pending', error = ? WHERE id = ?\")\n .run(error, actionId);\n });\n }\n\n markRollingBack(actionId: string): boolean {\n return this.#run(\"markRollingBack\", () => {\n // Conditional, so the transition is a claim rather than an announcement.\n // Two rollbacks of one run both read the action as applied and both sent\n // its inverse; for a compensating call rather than a restore, that is a\n // second real change to the world.\n const result = this.#db\n .prepare(\"UPDATE actions SET status = 'rolling_back' WHERE id = ? AND status = 'applied'\")\n .run(actionId);\n return result.changes === 1;\n });\n }\n\n markRolledBack(actionId: string): void {\n this.#run(\"markRolledBack\", () => {\n this.#db.prepare(\"UPDATE actions SET status = 'rolled_back' WHERE id = ?\").run(actionId);\n });\n }\n\n /**\n * The upstream processed the inverse and refused it, so nothing was applied\n * and the action still needs undoing. Distinct from `unrecoverable`, which\n * means a human has to look: a refused inverse may simply be a server that\n * was briefly unwell, and rollback is expected to be retried (D7).\n */\n markInverseRejected(actionId: string, error: string): void {\n this.#run(\"markInverseRejected\", () => {\n this.#db\n .prepare(\"UPDATE actions SET status = 'applied', error = ? WHERE id = ?\")\n .run(error, actionId);\n });\n }\n\n /**\n * The inverse may or may not have reached the upstream. The row stays in\n * `rolling_back` so the next attempt knows to resolve it by reading the\n * current state rather than assuming either way.\n */\n markUnknownInverse(actionId: string, error: string): void {\n this.#run(\"markUnknownInverse\", () => {\n this.#db\n .prepare(\"UPDATE actions SET status = 'rolling_back', error = ? WHERE id = ?\")\n .run(error, actionId);\n });\n }\n\n markGated(actionId: string, why?: string): void {\n this.#run(\"markGated\", () => {\n this.#db\n .prepare(\"UPDATE actions SET status = 'gated', error = ? WHERE id = ?\")\n .run(why ?? null, actionId);\n });\n }\n\n markInFlight(actionId: string): void {\n this.#run(\"markInFlight\", () => {\n this.#db.prepare(\"UPDATE actions SET status = 'pending' WHERE id = ?\").run(actionId);\n });\n }\n\n /**\n * Conditional on the row still being gated, so a decision made at the same\n * moment as a timeout resolves one way rather than both.\n */\n approve(actionId: string, by: string): boolean {\n return this.#run(\"approve\", () => {\n const result = this.#db\n .prepare(\n `UPDATE actions SET status = 'approved', approved_by = ?, approved_at = ?, error = NULL\n WHERE id = ? AND status = 'gated'`,\n )\n .run(by, new Date().toISOString(), actionId);\n return result.changes === 1;\n });\n }\n\n deny(actionId: string, by: string | undefined, reason: string): boolean {\n return this.#run(\"deny\", () => {\n const result = this.#db\n .prepare(\n `UPDATE actions SET status = 'denied', approved_by = ?, approved_at = ?, error = ?\n WHERE id = ? AND status = 'gated'`,\n )\n .run(by ?? null, new Date().toISOString(), reason, actionId);\n return result.changes === 1;\n });\n }\n\n settleAsDenied(actionId: string, by: string | undefined, reason: string): void {\n this.#run(\"settleAsDenied\", () => {\n this.#db\n .prepare(\n \"UPDATE actions SET status = 'denied', approved_by = ?, approved_at = ?, error = ? WHERE id = ?\",\n )\n .run(by ?? null, new Date().toISOString(), reason, actionId);\n });\n }\n\n adoptApproval(actionId: string, granted: ActionRow): void {\n this.#run(\"adoptApproval\", () => {\n // Also immediate: adopting an approval reads one row and writes two.\n const move = this.#db.transaction((): void => {\n this.#db\n .prepare(\"UPDATE actions SET approved_by = ?, approved_at = ? WHERE id = ?\")\n .run(granted.approvedBy ?? null, granted.approvedAt ?? null, actionId);\n this.#db\n .prepare(\"UPDATE actions SET status = 'denied', error = ? WHERE id = ?\")\n .run(`${SPENT_APPROVAL} ${actionId}`, granted.id);\n });\n move.immediate();\n });\n }\n\n listGated(): readonly ActionRow[] {\n return this.#run(\"listGated\", () =>\n this.#db.prepare(\"SELECT * FROM actions WHERE status = 'gated' ORDER BY ts\").all().map(toAction),\n );\n }\n\n findApproval(query: {\n server: string;\n tool: string;\n args: unknown;\n notBefore: string;\n }): ActionRow | undefined {\n return this.#run(\"findApproval\", () => {\n // Not scoped to one run: people restart their client, and an approval\n // stranded in a dead session is the same as no approval at all. Bounded\n // by time and by being single use instead, so a decision made this\n // morning cannot silently authorise the same call tomorrow.\n const rows = this.#db\n .prepare(\n `SELECT * FROM actions\n WHERE server = ? AND tool = ?\n AND status = 'approved'\n AND approved_at >= ?\n ORDER BY approved_at DESC`,\n )\n .all(query.server, query.tool, query.notBefore)\n .map(toAction);\n // Matched on meaning rather than on spelling: an agent that re-emits the\n // same arguments in a different key order is making the same call, and\n // sending a person back to approve what they just approved would teach\n // them to stop reading what they are approving.\n const wanted = canonical(query.args ?? {});\n return rows.find((row) => canonical(row.args) === wanted);\n });\n }\n\n findGated(query: {\n runId: string;\n server: string;\n tool: string;\n args: unknown;\n }): ActionRow | undefined {\n return this.#run(\"findGated\", () => {\n // Scoped to the run, unlike an approval: a gated row belongs to the run\n // that raised it, and adopting one from a dead session would hang the\n // decision on an action that undoing this run would never reach.\n const rows = this.#db\n .prepare(\n `SELECT * FROM actions\n WHERE run_id = ? AND server = ? AND tool = ? AND status = 'gated'\n ORDER BY seq`,\n )\n .all(query.runId, query.server, query.tool)\n .map(toAction);\n const wanted = canonical(query.args ?? {});\n return rows.find((row) => canonical(row.args) === wanted);\n });\n }\n\n getAction(actionId: string): ActionRow | undefined {\n return this.#run(\"getAction\", () => {\n const raw = this.#db.prepare(\"SELECT * FROM actions WHERE id = ?\").get(actionId);\n return raw === undefined ? undefined : toAction(raw);\n });\n }\n\n markUnrecoverable(actionId: string, error: string): void {\n this.#run(\"markUnrecoverable\", () => {\n this.#db\n .prepare(\"UPDATE actions SET status = 'unrecoverable', error = ? WHERE id = ?\")\n .run(error, actionId);\n });\n }\n\n listRuns(): readonly RunRow[] {\n return this.#run(\"listRuns\", () =>\n // Insertion order as the tiebreak, not the id. Two runs that start in\n // the same millisecond have equal timestamps, and a uuid orders them at\n // random -- which decides which one `show` and `undo` mean by \"the most\n // recent\", so the answer has to come from when they were written rather\n // than from what they happen to be called.\n this.#db.prepare(\"SELECT * FROM runs ORDER BY started_at, rowid\").all().map(toRun),\n );\n }\n\n getRun(runId: string): RunRow | undefined {\n return this.#run(\"getRun\", () => {\n const raw = this.#db.prepare(\"SELECT * FROM runs WHERE id = ?\").get(runId);\n return raw === undefined ? undefined : toRun(raw);\n });\n }\n\n getActions(runId: string): readonly ActionRow[] {\n return this.#run(\"getActions\", () =>\n this.#db\n .prepare(\"SELECT * FROM actions WHERE run_id = ? ORDER BY seq\")\n .all(runId)\n .map(toAction),\n );\n }\n\n recentActions(limit: number): readonly ActionRow[] {\n return this.#run(\"recentActions\", () =>\n this.#db\n .prepare(\"SELECT * FROM actions ORDER BY ts DESC, seq DESC LIMIT ?\")\n .all(limit)\n .map(toAction)\n .reverse(),\n );\n }\n\n pragma(name: string): unknown {\n return this.#db.pragma(name, { simple: true });\n }\n\n close(): void {\n this.#db.close();\n }\n\n prunableRuns(before: string): readonly PrunableRun[] {\n return this.#run(\"prunableRuns\", () =>\n this.#db\n .prepare(\n // COALESCE, because a run that was closed is dated by when it\n // finished and one that was not is dated by when it began.\n `SELECT r.id, r.label, r.status, COALESCE(r.ended_at, r.started_at) AS at,\n (SELECT COUNT(*) FROM actions a WHERE a.run_id = r.id) AS actions\n FROM runs r\n WHERE r.status != 'active'\n AND COALESCE(r.ended_at, r.started_at) < ?\n AND NOT EXISTS (\n SELECT 1 FROM actions a\n WHERE a.run_id = r.id\n AND a.status IN ('pending','gated','rolling_back'))\n ORDER BY at, r.rowid`,\n )\n .all(before)\n .map((row) =>\n z\n .object({\n id: z.string(),\n label: z.string().nullable(),\n status: z.enum([\"complete\", \"rolled_back\", \"partial\"]),\n at: z.string(),\n actions: z.number(),\n })\n .parse(row),\n )\n .map((row) => ({\n id: row.id,\n label: row.label ?? undefined,\n at: row.at,\n status: row.status,\n actions: row.actions,\n })),\n );\n }\n\n deleteRuns(runIds: readonly string[]): { runs: number; actions: number } {\n return this.#run(\"deleteRuns\", () => {\n const remove = this.#db.transaction((ids: readonly string[]) => {\n let runs = 0;\n let actions = 0;\n const dropActions = this.#db.prepare(\"DELETE FROM actions WHERE run_id = ?\");\n const dropRun = this.#db.prepare(\"DELETE FROM runs WHERE id = ?\");\n for (const id of ids) {\n // Actions first: they carry the foreign key onto the run, so the\n // other order is rejected rather than cascading.\n actions += dropActions.run(id).changes;\n runs += dropRun.run(id).changes;\n }\n return { runs, actions };\n });\n // immediate, for the same reason recordPending is: this reads before it\n // writes, and a deferred transaction cannot take the write lock later.\n return remove.immediate(runIds);\n });\n }\n\n vacuum(): void {\n this.#run(\"vacuum\", () => {\n this.#db.exec(\"VACUUM\");\n // And then fold the log back in. In WAL mode the rebuilt database is\n // written to the write-ahead log, so until this runs the file on disk is\n // exactly the size it was and the prune appears to have freed nothing --\n // which, to anyone looking at df, is the same as not working.\n this.#db.pragma(\"wal_checkpoint(TRUNCATE)\");\n });\n }\n\n /**\n * A failed journal write means the record of what the agent did is\n * incomplete. It is never swallowed and never merely logged.\n */\n #run<T>(operation: string, body: () => T): T {\n try {\n return body();\n } catch (error: unknown) {\n throw new JournalError(operation, error);\n }\n }\n}\n\nexport interface OpenOptions {\n /**\n * Refuse to create the file. Reading commands should say a journal is not\n * there rather than conjure an empty one and report that nothing happened,\n * which looks identical to a real answer and leaves a stray file behind.\n */\n readonly mustExist?: boolean;\n}\n\nexport function openJournal(path: string, options: OpenOptions = {}): Journal {\n if (options.mustExist === true && path !== \":memory:\" && !existsSync(path)) {\n throw new JournalError(\"open\", `there is no journal at ${path}`);\n }\n return new SqliteJournal(path);\n}\n\n/**\n * A row denied because its approval was spent on the call that actually ran is\n * not a refusal, and `watch` reported one as \"denied\" moments after the person\n * had said yes and the call had gone through.\n */\nexport function labelFor(action: ActionRow): string {\n return action.status === \"denied\" && (action.error ?? \"\").startsWith(SPENT_APPROVAL)\n ? \"used\"\n : action.status;\n}\n\nexport function wasRefused(action: ActionRow): boolean {\n return action.status === \"unrecoverable\" || labelFor(action) === \"denied\";\n}\n","/**\n * A stable text form of a json value.\n *\n * Key order carries no meaning in json, and nothing obliges an agent to\n * serialise the same arguments the same way twice. Anywhere two values are\n * compared for sameness -- state against recorded state, a retried call\n * against the approval that was granted for it -- the comparison has to be on\n * meaning rather than on spelling.\n */\nexport function canonical(value: unknown): string {\n if (value === undefined) {\n return \"undefined\";\n }\n if (value === null || typeof value !== \"object\") {\n return JSON.stringify(value);\n }\n if (Array.isArray(value)) {\n return `[${value.map(canonical).join(\",\")}]`;\n }\n const entries = Object.entries(value)\n .filter(([, item]) => item !== undefined)\n .sort(([a], [b]) => (a < b ? -1 : a > b ? 1 : 0));\n return `{${entries.map(([key, item]) => `${JSON.stringify(key)}:${canonical(item)}`).join(\",\")}}`;\n}\n","/**\n * Schema version is stored in SQLite's user_version.\n *\n * Version 2 adds `rolling_back`, written before an inverse is sent. On resume,\n * a row still in that state means the inverse may already have been applied,\n * which is the difference between a correct resume and a double-application.\n * It also adds `verify_json`, the read used to detect drift, resolved to\n * literal arguments at capture time for the same reason the inverse is (D5):\n * the manifest may have been edited by the time anyone rolls back.\n *\n * Version 3 adds `approved`: granted by a person but not yet carried out.\n * That was `pending` at first, which also means a call went out and its\n * outcome is unknown. Undo has to halt on the second and step past the first,\n * so they cannot share a name.\n *\n * There is no migration path yet, and inventing one before anything needs\n * migrating would mean shipping untested machinery. An older journal is\n * refused with instructions instead of being silently reinterpreted.\n */\nexport const SCHEMA_VERSION = 3;\n\nexport const SCHEMA_SQL = `\nCREATE TABLE IF NOT EXISTS runs (\n id TEXT PRIMARY KEY,\n label TEXT,\n started_at TEXT NOT NULL,\n ended_at TEXT,\n status TEXT NOT NULL CHECK (status IN ('active','complete','rolled_back','partial'))\n);\n\nCREATE TABLE IF NOT EXISTS actions (\n id TEXT PRIMARY KEY,\n run_id TEXT NOT NULL REFERENCES runs(id),\n seq INTEGER NOT NULL,\n server TEXT NOT NULL,\n tool TEXT NOT NULL,\n args_json TEXT NOT NULL,\n class TEXT NOT NULL,\n snapshot_json TEXT,\n post_snapshot_json TEXT,\n result_json TEXT,\n inverse_json TEXT,\n verify_json TEXT,\n error TEXT,\n idempotency_key TEXT NOT NULL UNIQUE,\n status TEXT NOT NULL CHECK (status IN\n ('pending','gated','approved','denied','applied','failed',\n 'rolling_back','rolled_back','unrecoverable')),\n approved_by TEXT,\n approved_at TEXT,\n ts TEXT NOT NULL,\n UNIQUE(run_id, seq)\n);\n\nCREATE INDEX IF NOT EXISTS actions_by_run ON actions(run_id, seq);\n`;\n","import { readFileSync } from \"node:fs\";\n\nimport { LineCounter, isNode, parseDocument, type Document } from \"yaml\";\nimport { z } from \"zod\";\n\nimport { ManifestError, describe as describeCause, type SourceLocation } from \"../errors.js\";\nimport { referencesIn } from \"./template.js\";\nimport type { CallTemplate, Manifest, TemplateValue, ToolPolicy } from \"./types.js\";\n\nconst templateValue: z.ZodType<TemplateValue> = z.lazy(() =>\n z.union([\n z.string(),\n z.number(),\n z.boolean(),\n z.null(),\n z.array(templateValue),\n z.record(z.string(), templateValue),\n ]),\n);\n\nconst callTemplate = z.strictObject({\n tool: z.string().min(1),\n args: z.record(z.string(), templateValue).default({}),\n absent_when: z\n .union([z.string().min(1), z.array(z.string().min(1)).min(1)])\n .optional(),\n});\n\nconst toolPolicy = z.strictObject({\n match: z.string().min(1),\n class: z.enum([\"readonly\", \"reversible\", \"compensable\", \"irreversible\"]),\n gate: z.enum([\"always\", \"on_write\", \"never\"]).optional(),\n snapshot: callTemplate.optional(),\n inverse: callTemplate.optional(),\n});\n\nconst serverSpec = z.strictObject({\n command: z.string().min(1),\n args: z.array(z.string()).default([]),\n env: z.record(z.string(), z.string()).optional(),\n});\n\nconst manifestSchema = z.strictObject({\n version: z.literal(1),\n servers: z.record(z.string(), serverSpec),\n tools: z.array(toolPolicy).default([]),\n});\n\ntype Path = readonly (string | number)[];\n\nclass Source {\n constructor(\n private readonly doc: Document.Parsed,\n private readonly lines: LineCounter,\n private readonly file: string,\n ) {}\n\n /** Narrows to the deepest node that still exists, so a location is always given. */\n locate(path: Path): SourceLocation {\n for (let depth = path.length; depth >= 0; depth -= 1) {\n const node: unknown =\n depth === 0 ? this.doc.contents : this.doc.getIn(path.slice(0, depth), true);\n const range = isNode(node) ? node.range : undefined;\n if (range != null) {\n const position = this.lines.linePos(range[0]);\n return { file: this.file, line: position.line, column: position.col };\n }\n }\n return { file: this.file, line: 1, column: 1 };\n }\n\n fail(path: Path, message: string): never {\n throw new ManifestError(message, this.locate(path));\n }\n}\n\n/**\n * `${VAR}` in a server's environment, taken from the shell the proxy was\n * started from.\n *\n * This is how a token stays out of a file that gets committed, which is what\n * the shipped manifests tell people to do. Without expansion the server\n * receives the reference itself and fails with an authentication error that\n * says nothing about the cause. A variable that is not set is refused at load\n * time rather than passed on empty, for the same reason: never start with a\n * policy that cannot work.\n */\nconst REFERENCE = /\\$\\{([A-Za-z_][A-Za-z0-9_]*)\\}/g;\n\nfunction expandEnvironment(\n source: Source,\n path: Path,\n env: Readonly<Record<string, string>>,\n): Record<string, string> {\n const expanded: Record<string, string> = {};\n for (const [key, value] of Object.entries(env)) {\n expanded[key] = value.replace(REFERENCE, (whole, name: string) => {\n const found = process.env[name];\n if (found === undefined) {\n source.fail(\n [...path, \"env\", key],\n `${whole} is not set in this environment; export ${name} before starting, or write the value here`,\n );\n }\n return found;\n });\n }\n return expanded;\n}\n\nfunction serverSegment(pattern: string): string {\n const dot = pattern.indexOf(\".\");\n return dot === -1 ? \"\" : pattern.slice(0, dot);\n}\n\nfunction matchesAnyServer(segment: string, servers: readonly string[]): boolean {\n if (!segment.includes(\"*\")) {\n return servers.includes(segment);\n }\n const source = segment\n .split(\"*\")\n .map((literal) => literal.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\"))\n .join(\"[^.]*\");\n const test = new RegExp(`^${source}$`);\n return servers.some((name) => test.test(name));\n}\n\nfunction checkCall(\n source: Source,\n path: Path,\n call: CallTemplate,\n servers: readonly string[],\n allowed: readonly string[],\n): void {\n const segment = serverSegment(call.tool);\n if (segment === \"\" || call.tool.endsWith(\".\")) {\n source.fail([...path, \"tool\"], `${call.tool} must be qualified as server.tool`);\n }\n if (segment.includes(\"*\")) {\n source.fail([...path, \"tool\"], `${call.tool} must name one server, not a pattern`);\n }\n if (!servers.includes(segment)) {\n source.fail([...path, \"tool\"], `${call.tool} names server ${segment}, which is not declared`);\n }\n\n for (const reference of referencesIn(call.args)) {\n // Matches `$ns.field`, `$ns[0]` and a bare `$ns`, so a whole-value or\n // subscripted reference is checked rather than silently treated as `$.`\n // and failing at run time.\n const namespace = /^\\$(\\w*)(?:[.[]|$)/.exec(reference)?.[1] ?? \"\";\n const label = namespace === \"\" ? \"$.\" : `$${namespace}.`;\n if (!allowed.includes(label)) {\n source.fail(\n [...path, \"args\"],\n `${reference} uses ${label}, which is not available here; allowed: ${allowed.join(\", \")}`,\n );\n }\n }\n}\n\n/**\n * Cross-field rules the shape alone cannot express. These are the difference\n * between a manifest that parses and a policy that can actually be executed,\n * and every one of them fails startup rather than surfacing mid-run.\n */\nfunction validate(source: Source, manifest: Manifest): void {\n const servers = Object.keys(manifest.servers);\n if (servers.length === 0) {\n source.fail([\"servers\"], \"at least one server must be declared\");\n }\n\n const seen = new Map<string, number>();\n manifest.tools.forEach((policy, index) => {\n const path: Path = [\"tools\", index];\n const previous = seen.get(policy.match);\n if (previous !== undefined) {\n source.fail(\n [...path, \"match\"],\n `duplicate match pattern ${policy.match}; it is already declared at tools[${String(previous)}]`,\n );\n }\n seen.set(policy.match, index);\n\n const segment = serverSegment(policy.match);\n if (segment === \"\") {\n source.fail([...path, \"match\"], `${policy.match} must be qualified as server.tool`);\n }\n if (!matchesAnyServer(segment, servers)) {\n source.fail(\n [...path, \"match\"],\n `${policy.match} names server ${segment}, which is not declared`,\n );\n }\n\n const needsInverse = policy.class === \"reversible\" || policy.class === \"compensable\";\n if (needsInverse && policy.inverse === undefined) {\n source.fail(path, `a ${policy.class} tool must declare an inverse`);\n }\n if (!needsInverse && policy.inverse !== undefined) {\n source.fail([...path, \"inverse\"], `a ${policy.class} tool must not declare an inverse`);\n }\n // A snapshot is required only when the inverse actually depends on one.\n // Some actions are reversible from their arguments alone: the inverse of\n // moving a file from A to B is moving it from B to A, and no pre-read\n // could tell you anything the arguments do not already say.\n const needsSnapshot =\n policy.inverse !== undefined &&\n referencesIn(policy.inverse.args).some(\n (reference) => reference === \"$snapshot\" || reference.startsWith(\"$snapshot.\"),\n );\n if (policy.class === \"reversible\" && needsSnapshot && policy.snapshot === undefined) {\n // Without a pre-read such a reversible action is silently irreversible.\n source.fail(path, \"this inverse reads $snapshot, so a snapshot must be declared\");\n }\n if (policy.class === \"readonly\" && policy.snapshot !== undefined) {\n source.fail([...path, \"snapshot\"], \"a readonly tool must not declare a snapshot\");\n }\n\n if (policy.snapshot !== undefined) {\n // The snapshot runs before the forward call, so neither the result nor a\n // snapshot exists yet.\n checkCall(source, [...path, \"snapshot\"], policy.snapshot, servers, [\"$.\"]);\n }\n if (policy.inverse !== undefined) {\n const allowed = [\"$.\", \"$result.\"];\n if (policy.snapshot !== undefined) {\n allowed.push(\"$snapshot.\");\n }\n checkCall(source, [...path, \"inverse\"], policy.inverse, servers, allowed);\n }\n });\n}\n\nfunction withGate(policy: z.infer<typeof toolPolicy>): ToolPolicy {\n // D4: irreversible is gated unless the manifest deliberately says otherwise.\n // `absent_when` in the file, absentWhen in the type: the one place a name is\n // translated, so a single string and a list read the same way afterwards.\n const toCall = (call: {\n tool: string;\n args: Record<string, TemplateValue>;\n absent_when?: string | string[] | undefined;\n }): CallTemplate => ({\n tool: call.tool,\n args: call.args,\n ...(call.absent_when === undefined\n ? {}\n : {\n absentWhen:\n typeof call.absent_when === \"string\" ? [call.absent_when] : [...call.absent_when],\n }),\n });\n\n const gate = policy.gate ?? (policy.class === \"irreversible\" ? \"always\" : \"never\");\n return {\n match: policy.match,\n class: policy.class,\n gate,\n ...(policy.snapshot === undefined ? {} : { snapshot: toCall(policy.snapshot) }),\n ...(policy.inverse === undefined ? {} : { inverse: toCall(policy.inverse) }),\n };\n}\n\nexport function parseManifest(text: string, file: string): Manifest {\n const lines = new LineCounter();\n const doc = parseDocument(text, { lineCounter: lines });\n\n const syntaxError = doc.errors[0];\n if (syntaxError !== undefined) {\n const position = lines.linePos(syntaxError.pos[0]);\n throw new ManifestError(syntaxError.message, {\n file,\n line: position.line,\n column: position.col,\n });\n }\n\n const source = new Source(doc, lines, file);\n const parsed = manifestSchema.safeParse(doc.toJS());\n if (!parsed.success) {\n const issue = parsed.error.issues[0];\n if (issue === undefined) {\n throw new ManifestError(\"manifest failed validation\", source.locate([]));\n }\n const path = issue.path.filter(\n (segment): segment is string | number => typeof segment !== \"symbol\",\n );\n const where = path.length === 0 ? \"\" : `${path.join(\".\")}: `;\n throw new ManifestError(`${where}${issue.message}`, source.locate(path));\n }\n\n const manifest: Manifest = {\n version: parsed.data.version,\n servers: Object.fromEntries(\n Object.entries(parsed.data.servers).map(([name, spec]) => [\n name,\n {\n command: spec.command,\n args: spec.args,\n ...(spec.env === undefined\n ? {}\n : { env: expandEnvironment(source, [\"servers\", name], spec.env) }),\n },\n ]),\n ),\n tools: parsed.data.tools.map(withGate),\n };\n validate(source, manifest);\n return manifest;\n}\n\n/** Node reports a missing file with code ENOENT and no type to narrow on. */\nfunction isMissing(error: unknown): boolean {\n return (\n typeof error === \"object\" &&\n error !== null &&\n \"code\" in error &&\n (error as { code?: unknown }).code === \"ENOENT\"\n );\n}\n\nexport function loadManifest(path: string): Manifest {\n let text: string;\n try {\n text = readFileSync(path, \"utf8\");\n } catch (error: unknown) {\n // A policy that is simply not there yet is the commonest way this fails,\n // and it has an answer. Saying only \"ENOENT\" leaves someone who has not\n // run init with no idea that init is the thing that writes this file.\n if (isMissing(error)) {\n throw new ManifestError(\n `there is no policy at ${path}. Write one with: synartesis init <name> -- <the server's command>`,\n );\n }\n throw new ManifestError(`cannot read manifest at ${path}: ${describeCause(error)}`);\n }\n return parseManifest(text, path);\n}\n","import { ManifestError } from \"../errors.js\";\nimport type { TemplateValue } from \"./types.js\";\n\nexport interface TemplateContext {\n readonly args: unknown;\n readonly snapshot?: unknown;\n readonly result?: unknown;\n}\n\nconst NAMESPACES = [\"snapshot\", \"result\"] as const;\n\ninterface Reference {\n readonly namespace: \"args\" | \"snapshot\" | \"result\";\n readonly path: string;\n}\n\n/**\n * Three namespaces and dotted paths, nothing else. Spec 3.2 is explicit that\n * the manifest must not become a language: the moment it grows expressions,\n * it stops being writable in fifteen minutes by someone who has never seen it.\n */\nfunction parseReference(raw: string): Reference | undefined {\n if (!raw.startsWith(\"$\")) {\n return undefined;\n }\n // A bare namespace means the whole value. Writing a file back needs the\n // entire captured contents, which is not a field of anything.\n if (raw === \"$\") {\n return { namespace: \"args\", path: \"\" };\n }\n // A namespace may be followed by a dot or straight by a subscript. Servers\n // that answer with a bare list are common -- the memory server's\n // create_entities returns the entities it actually created -- and\n // $result[].name is the only safe thing for its inverse to name.\n if (raw.startsWith(\"$.\") || raw.startsWith(\"$[\")) {\n return { namespace: \"args\", path: raw.slice(raw[1] === \".\" ? 2 : 1) };\n }\n for (const namespace of NAMESPACES) {\n if (raw === `$${namespace}`) {\n return { namespace, path: \"\" };\n }\n const head = `$${namespace}`;\n const after = raw.startsWith(head) ? raw.slice(head.length) : undefined;\n if (after !== undefined && (after.startsWith(\".\") || after.startsWith(\"[\"))) {\n return { namespace, path: after.startsWith(\".\") ? after.slice(1) : after };\n }\n }\n throw new ManifestError(\n `unknown interpolation namespace in ${raw}; expected $., $snapshot. or $result.`,\n );\n}\n\ntype Segment =\n | { readonly kind: \"key\"; readonly key: string }\n | { readonly kind: \"index\"; readonly index: number }\n /** `[]`: apply the rest of the path to every element. */\n | { readonly kind: \"each\" };\n\n/** Splits `items[1].id` and `labels[].name` into their steps. */\nfunction segments(path: string, reference: string): Segment[] {\n const parts: Segment[] = [];\n for (const chunk of path.split(\".\")) {\n const match = /^([^[\\]]*)((?:\\[\\d*\\])*)$/.exec(chunk);\n if (match === null) {\n throw new ManifestError(`malformed path in ${reference}`);\n }\n const [, head = \"\", brackets = \"\"] = match;\n if (head !== \"\") {\n parts.push({ kind: \"key\", key: head });\n }\n for (const bracket of brackets.matchAll(/\\[(\\d*)\\]/g)) {\n const index = bracket[1] ?? \"\";\n parts.push(index === \"\" ? { kind: \"each\" } : { kind: \"index\", index: Number(index) });\n }\n }\n if (parts.length === 0) {\n throw new ManifestError(`empty path in ${reference}`);\n }\n return parts;\n}\n\nfunction walk(current: unknown, parts: readonly Segment[], at: number, reference: string): unknown {\n const segment = parts[at];\n if (segment === undefined) {\n return current;\n }\n if (current === null || current === undefined) {\n throw new ManifestError(`${reference} is unresolvable: nothing to read from`);\n }\n\n switch (segment.kind) {\n case \"each\": {\n if (!Array.isArray(current)) {\n throw new ManifestError(`${reference} is unresolvable: [] needs a list to walk`);\n }\n // Projection, not a transform. It reads the same field from each element\n // and nothing more, which is what an API that returns objects and\n // accepts names needs, and is still only a path.\n return current.map((item) => walk(item, parts, at + 1, reference));\n }\n case \"index\": {\n if (!Array.isArray(current) || segment.index >= current.length) {\n throw new ManifestError(\n `${reference} is unresolvable: index ${String(segment.index)} is absent`,\n );\n }\n return walk(current[segment.index], parts, at + 1, reference);\n }\n case \"key\": {\n if (typeof current !== \"object\" || !(segment.key in current)) {\n throw new ManifestError(`${reference} is unresolvable: ${segment.key} is absent`);\n }\n const next: unknown = Object.getOwnPropertyDescriptor(current, segment.key)?.value;\n return walk(next, parts, at + 1, reference);\n }\n }\n}\n\nfunction read(root: unknown, path: string, reference: string): unknown {\n return walk(root, segments(path, reference), 0, reference);\n}\n\n/**\n * A reference appearing inside a larger string, such as a commit message that\n * names the path it is reverting. Only the dotted forms are recognised here: a\n * bare `$result` in the middle of a sentence is far more likely to be prose\n * than an interpolation.\n */\nconst EMBEDDED =\n /\\$(?:snapshot|result)?\\.[A-Za-z_][A-Za-z0-9_]*(?:\\.[A-Za-z_][A-Za-z0-9_]*|\\[\\d*\\])*/g;\n\nconst ESCAPE = \"\\u0000synartesis-dollar\\u0000\";\n\nfunction stringify(value: unknown): string {\n return typeof value === \"string\" ? value : JSON.stringify(value);\n}\n\nfunction resolveString(raw: string, context: TemplateContext): unknown {\n // A string that is nothing but a reference keeps the referenced value's\n // type. Anything else is text with references substituted into it, which is\n // what people write without being told they can.\n const whole = raw.startsWith(\"$$\") ? undefined : parseReference(raw);\n if (whole !== undefined) {\n return readNamespace(whole, raw, context);\n }\n\n const escaped = raw.split(\"$$\").join(ESCAPE);\n const substituted = escaped.replace(EMBEDDED, (token) => {\n const reference = parseReference(token);\n if (reference === undefined) {\n return token;\n }\n return stringify(readNamespace(reference, token, context));\n });\n return substituted.split(ESCAPE).join(\"$\");\n}\n\nfunction readNamespace(reference: Reference, raw: string, context: TemplateContext): unknown {\n const root = context[reference.namespace];\n if (root === undefined) {\n throw new ManifestError(\n `${raw} refers to ${reference.namespace}, which is not available at this point`,\n );\n }\n return reference.path === \"\" ? root : read(root, reference.path, raw);\n}\n\n/** Array.isArray widens a readonly union to any[]; this keeps the element type. */\nfunction isTemplateArray(value: TemplateValue): value is readonly TemplateValue[] {\n return Array.isArray(value);\n}\n\nexport function resolveTemplate(template: TemplateValue, context: TemplateContext): unknown {\n if (typeof template === \"string\") {\n return resolveString(template, context);\n }\n if (isTemplateArray(template)) {\n return template.map((item) => resolveTemplate(item, context));\n }\n if (template !== null && typeof template === \"object\") {\n return Object.fromEntries(\n Object.entries(template).map(([key, value]) => [key, resolveTemplate(value, context)]),\n );\n }\n return template;\n}\n\n/** Every reference a template contains, used for load-time validation. */\nexport function referencesIn(template: TemplateValue): string[] {\n if (typeof template === \"string\") {\n if (template.startsWith(\"$$\")) {\n return [];\n }\n if (parseReference(template) !== undefined) {\n return [template];\n }\n // Embedded references are validated too, so a namespace that is not\n // available at that point is reported when the manifest loads rather than\n // silently producing the wrong text at run time.\n return template.split(\"$$\").join(ESCAPE).match(EMBEDDED) ?? [];\n }\n if (isTemplateArray(template)) {\n return template.flatMap(referencesIn);\n }\n if (template !== null && typeof template === \"object\") {\n return Object.values(template).flatMap(referencesIn);\n }\n return [];\n}\n","import { z } from \"zod\";\n\nimport { ManifestError } from \"../errors.js\";\nimport type { Upstream } from \"../proxy/upstream.js\";\nimport { splitQualified, type Manifest } from \"./types.js\";\n\nconst listSchema = z.looseObject({\n tools: z.array(z.looseObject({ name: z.string() })),\n nextCursor: z.string().optional(),\n});\n\nasync function toolNames(upstream: Upstream): Promise<Set<string>> {\n const names = new Set<string>();\n let cursor: string | undefined;\n do {\n const page = listSchema.parse(\n await upstream.client.request(\n { method: \"tools/list\", params: cursor === undefined ? {} : { cursor } },\n z.looseObject({}),\n ),\n );\n for (const tool of page.tools) {\n names.add(tool.name);\n }\n cursor = page.nextCursor;\n } while (cursor !== undefined);\n return names;\n}\n\n/**\n * Checks that every tool a policy calls actually exists on the server it names.\n *\n * This cannot be done when the manifest is parsed, because it needs the servers\n * running. It matters because a mistyped snapshot tool is otherwise\n * indistinguishable at run time from the resource simply not being there: both\n * come back as a tool-level error. Catching it at startup keeps that inference\n * safe, and keeps a broken policy from ever serving a request.\n */\nexport async function verifyAgainstServers(\n upstreams: readonly Upstream[],\n manifest: Manifest,\n): Promise<void> {\n const available = new Map<string, Set<string>>();\n for (const upstream of upstreams) {\n available.set(upstream.name, await toolNames(upstream));\n }\n\n const problems: string[] = [];\n const check = (qualified: string, role: string, match: string): void => {\n const target = splitQualified(qualified);\n if (target === undefined) {\n return;\n }\n const names = available.get(target.server);\n if (names === undefined) {\n problems.push(`${match}: its ${role} names server ${target.server}, which is not connected`);\n return;\n }\n if (!names.has(target.tool)) {\n problems.push(\n `${match}: its ${role} calls ${qualified}, which ${target.server} does not expose`,\n );\n }\n };\n\n for (const policy of manifest.tools) {\n if (policy.snapshot !== undefined) {\n check(policy.snapshot.tool, \"snapshot\", policy.match);\n }\n if (policy.inverse !== undefined) {\n check(policy.inverse.tool, \"inverse\", policy.match);\n }\n }\n\n if (problems.length > 0) {\n throw new ManifestError(`the manifest calls tools that do not exist:\\n ${problems.join(\"\\n \")}`);\n }\n}\n","/** The four behaviours from spec 1.4. */\nexport type ToolClass = \"readonly\" | \"reversible\" | \"compensable\" | \"irreversible\";\n\n/**\n * `on_write` is a heuristic for tools whose destructiveness cannot be decided\n * statically, such as a raw SQL runner. The heuristic itself lands with the\n * gate in Phase 5; the manifest only has to carry the intent.\n */\nexport type GateMode = \"always\" | \"on_write\" | \"never\";\n\nexport interface ServerSpec {\n readonly command: string;\n readonly args: readonly string[];\n readonly env?: Readonly<Record<string, string>>;\n}\n\nexport type TemplateValue =\n | string\n | number\n | boolean\n | null\n | readonly TemplateValue[]\n | { readonly [key: string]: TemplateValue };\n\nexport interface CallTemplate {\n /** Qualified as `server.tool`. */\n readonly tool: string;\n readonly args: Readonly<Record<string, TemplateValue>>;\n /**\n * What this server says when the thing is not there, as substrings of its\n * error text. Only meaningful on a snapshot.\n *\n * Without it every failed pre-read has to be read as absence, because the\n * protocol gives no way to tell the two apart -- which means a resource that\n * exists and could not be read is offered for approval as a creation. With\n * it, anything that is not one of these is a failed snapshot and the write\n * is refused outright.\n */\n readonly absentWhen?: readonly string[];\n}\n\nexport interface ToolPolicy {\n readonly match: string;\n readonly class: ToolClass;\n readonly gate: GateMode;\n readonly snapshot?: CallTemplate;\n readonly inverse?: CallTemplate;\n}\n\nexport interface Manifest {\n readonly version: 1;\n readonly servers: Readonly<Record<string, ServerSpec>>;\n readonly tools: readonly ToolPolicy[];\n}\n\n/** Qualified name used everywhere policy is looked up. */\nexport function qualify(server: string, tool: string): string {\n return `${server}.${tool}`;\n}\n\nexport interface QualifiedName {\n readonly server: string;\n readonly tool: string;\n}\n\n/** Splits on the first dot only; tool names may contain further dots. */\nexport function splitQualified(qualified: string): QualifiedName | undefined {\n const dot = qualified.indexOf(\".\");\n if (dot <= 0 || dot === qualified.length - 1) {\n return undefined;\n }\n return { server: qualified.slice(0, dot), tool: qualified.slice(dot + 1) };\n}\n","import { ManifestError } from \"../errors.js\";\nimport type { Manifest } from \"../manifest/types.js\";\nimport type { Upstream } from \"./upstream.js\";\n\n/**\n * A dot cannot be used to namespace tool names: many MCP clients constrain\n * tool names to [A-Za-z0-9_-], and a name the client rejects is a tool the\n * agent cannot call at all.\n */\nexport const SEPARATOR = \"__\";\n\nexport interface Route {\n readonly upstream: Upstream;\n /** The name as the upstream knows it, with any prefix removed. */\n readonly tool: string;\n}\n\nexport interface Router {\n readonly prefixed: boolean;\n readonly upstreams: readonly Upstream[];\n expose(server: string, name: string): string;\n route(exposed: string): Route | undefined;\n byName(server: string): Upstream | undefined;\n}\n\nexport function createRouter(upstreams: readonly Upstream[], manifest: Manifest): Router {\n if (upstreams.length === 0) {\n throw new ManifestError(\"no upstream servers were connected\");\n }\n\n for (const upstream of upstreams) {\n if (!(upstream.name in manifest.servers)) {\n throw new ManifestError(\n `upstream ${upstream.name} is connected but not declared in the manifest`,\n );\n }\n if (upstream.name.includes(SEPARATOR) || upstream.name.includes(\".\")) {\n throw new ManifestError(\n `server name ${upstream.name} may not contain \".\" or \"${SEPARATOR}\"; both are reserved for qualifying tool names`,\n );\n }\n }\n\n const byName = new Map(upstreams.map((upstream) => [upstream.name, upstream]));\n if (byName.size !== upstreams.length) {\n throw new ManifestError(\"two upstreams were connected under the same name\");\n }\n\n // With one server there is nothing to disambiguate, so names pass through\n // untouched and the proxy stays invisible. Adding a second server is an\n // explicit edit to the manifest, so the rename that comes with it is not a\n // surprise; what would be surprising is a name whose meaning depends on\n // which other servers happen to be configured beside it.\n const prefixed = upstreams.length > 1;\n\n // Longest first so that servers named `a` and `a_b` cannot both claim the\n // same exposed name.\n const keys = [...byName.keys()].sort((a, b) => b.length - a.length);\n\n return {\n prefixed,\n upstreams,\n expose(server: string, name: string): string {\n return prefixed ? `${server}${SEPARATOR}${name}` : name;\n },\n route(exposed: string): Route | undefined {\n if (!prefixed) {\n const only = upstreams[0];\n if (only === undefined) {\n return undefined;\n }\n // The qualified name works here too. Guarding one server advertises\n // `write_file` and guarding two advertises `fs__write_file`, so a name\n // written down against one setup was rejected by the other -- and in\n // this direction it was not even rejected: any unknown name routed to\n // the only server, missed the policy written for `fs.write_file`, and\n // was held for a human to approve as something that could not be\n // undone. A read, held for approval, because it was spelled the way\n // the other setup spells it.\n //\n // Only this server's own name is unwrapped; a tool whose real name\n // begins with it would be written `fs.fs__write_file` in the manifest.\n const prefix = `${only.name}${SEPARATOR}`;\n return exposed.startsWith(prefix)\n ? { upstream: only, tool: exposed.slice(prefix.length) }\n : { upstream: only, tool: exposed };\n }\n for (const key of keys) {\n const prefix = `${key}${SEPARATOR}`;\n if (exposed.startsWith(prefix)) {\n const upstream = byName.get(key);\n if (upstream !== undefined) {\n return { upstream, tool: exposed.slice(prefix.length) };\n }\n }\n }\n return undefined;\n },\n byName(server: string): Upstream | undefined {\n return byName.get(server);\n },\n };\n}\n","import { Client } from \"@modelcontextprotocol/sdk/client/index.js\";\nimport { StdioClientTransport } from \"@modelcontextprotocol/sdk/client/stdio.js\";\n\nimport { UpstreamError } from \"../errors.js\";\n\nfunction describeError(error: unknown): string {\n return error instanceof Error ? error.message : String(error);\n}\n\nexport interface UpstreamSpec {\n /** Key the manifest uses to qualify this server's tools, e.g. `crm`. */\n readonly name: string;\n readonly command: string;\n readonly args?: readonly string[];\n readonly env?: Readonly<Record<string, string>>;\n /**\n * Where the server's own stderr goes. The proxy inherits it, so a server\n * that fails to boot says why in the client's logs. The CLI captures it, so\n * that reason can be repeated back in the error rather than shown as a\n * banner: a report for a person should not be interleaved with a server's\n * own logging, but it must not throw away the one line that explains the\n * failure either.\n */\n readonly stderr?: \"inherit\" | \"ignore\" | \"capture\";\n}\n\nexport interface Upstream {\n readonly name: string;\n readonly client: Client;\n /**\n * Start the server again after its transport has died. A single oversized\n * response is enough to close a stdio connection, and without this the\n * proxy stayed connected to nothing for the rest of the session: every call\n * after it failed with \"Not connected\", whatever it was.\n *\n * Absent on an upstream that was not spawned from a command, which has\n * nothing to respawn.\n */\n reconnect?(): Promise<void>;\n close(): Promise<void>;\n}\n\nexport const PROXY_CLIENT_INFO = { name: \"synartesis-proxy\", version: \"0.0.0\" } as const;\n\n/**\n * Whatever a stream has buffered, without asserting it into a shape. The sdk\n * types stderr as Stream, which has no read(); what it hands back is a\n * Readable, and a wrong guess here would be a crash while reporting a crash.\n */\nfunction bufferedText(stream: unknown): string {\n if (typeof stream !== \"object\" || stream === null || !(\"read\" in stream)) {\n return \"\";\n }\n const read: unknown = stream.read;\n if (typeof read !== \"function\") {\n return \"\";\n }\n const chunk: unknown = read.call(stream);\n if (typeof chunk === \"string\") {\n return chunk;\n }\n return Buffer.isBuffer(chunk) ? chunk.toString(\"utf8\") : \"\";\n}\n\n/** The tail of what a server said, tidied for repeating back in one error. */\nfunction lastWords(text: string): string | undefined {\n const lines = text\n .split(\"\\n\")\n .map((line) => line.trimEnd())\n .filter((line) => line.trim() !== \"\");\n const kept = lines.slice(-4).join(\"; \");\n return kept === \"\" ? undefined : kept;\n}\n\nexport async function connectStdioUpstream(spec: UpstreamSpec): Promise<Upstream> {\n const started = await start(spec);\n let current = started;\n return {\n name: spec.name,\n get client(): Client {\n return current.client;\n },\n async reconnect(): Promise<void> {\n // Best effort: the old one is already broken, and failing to close a\n // broken thing must not stop the new one being made.\n await current.client.close().catch(() => undefined);\n current = await start(spec);\n },\n close: async (): Promise<void> => {\n await current.client.close();\n },\n };\n}\n\nasync function start(spec: UpstreamSpec): Promise<{ client: Client }> {\n const wanted = spec.stderr ?? \"inherit\";\n const transport = new StdioClientTransport({\n command: spec.command,\n args: [...(spec.args ?? [])],\n ...(spec.env === undefined ? {} : { env: { ...spec.env } }),\n // \"pipe\" is what the sdk calls it; captured here so a failure can quote it.\n stderr: wanted === \"capture\" ? \"pipe\" : wanted,\n });\n\n const client = new Client({ ...PROXY_CLIENT_INFO });\n let said = \"\";\n try {\n await client.connect(transport);\n } catch (error: unknown) {\n // Read after the failure: the stream is only attached once the child is\n // spawned, and by the time connect rejects the server has already spoken.\n said = bufferedText(transport.stderr);\n const reason = lastWords(said);\n throw new UpstreamError(\n spec.name,\n \"connect\",\n reason === undefined ? error : `${describeError(error)} — the server said: ${reason}`,\n );\n }\n\n return { client };\n}\n","import type { Manifest, ToolPolicy } from \"./types.js\";\n\nexport interface PolicyMatch {\n readonly policy: ToolPolicy;\n /** False when the fail-closed default was synthesised instead of matched. */\n readonly matched: boolean;\n}\n\nexport interface PolicyResolver {\n resolve(qualifiedName: string): PolicyMatch;\n}\n\n/** `*` stands for any run of characters that is not a dot. */\nfunction toRegExp(pattern: string): RegExp {\n const source = pattern\n .split(\"*\")\n .map((literal) => literal.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\"))\n .join(\"[^.]*\");\n return new RegExp(`^${source}$`);\n}\n\nfunction literalLength(pattern: string): number {\n return pattern.length - pattern.split(\"*\").length + 1;\n}\n\ninterface CompiledPolicy {\n readonly policy: ToolPolicy;\n readonly test: RegExp;\n readonly specificity: number;\n readonly wildcards: number;\n}\n\n/**\n * D4. An unrecognised tool is irreversible and gated. A silent passthrough on\n * an unknown destructive tool is worse than having no product at all.\n */\nfunction failClosed(qualifiedName: string): ToolPolicy {\n return { match: qualifiedName, class: \"irreversible\", gate: \"always\" };\n}\n\nexport function createPolicyResolver(manifest: Manifest): PolicyResolver {\n const compiled: CompiledPolicy[] = manifest.tools\n .map((policy) => ({\n policy,\n test: toRegExp(policy.match),\n specificity: literalLength(policy.match),\n wildcards: policy.match.split(\"*\").length - 1,\n }))\n // Longest literal wins, ties broken by fewer wildcards. Ordering is a\n // property of the patterns, never of the order they were written in.\n .sort((a, b) => b.specificity - a.specificity || a.wildcards - b.wildcards);\n\n const cache = new Map<string, PolicyMatch>();\n\n return {\n resolve(qualifiedName: string): PolicyMatch {\n const cached = cache.get(qualifiedName);\n if (cached !== undefined) {\n return cached;\n }\n const hit = compiled.find((candidate) => candidate.test.test(qualifiedName));\n const match: PolicyMatch =\n hit === undefined\n ? { policy: failClosed(qualifiedName), matched: false }\n : { policy: hit.policy, matched: true };\n cache.set(qualifiedName, match);\n return match;\n },\n };\n}\n","import { z } from \"zod\";\n\nimport { ManifestError, SnapshotError, describe } from \"../errors.js\";\nimport { resolveTemplate, type TemplateContext } from \"../manifest/template.js\";\nimport { splitQualified, type CallTemplate } from \"../manifest/types.js\";\nimport type { Router } from \"./routing.js\";\n\n/**\n * What a read saw. Absence is a real state, not a failure: after a successful\n * delete the record is gone, and that is precisely the post-state Phase 4 has\n * to compare against.\n */\nexport type StateObservation = { readonly present: true; readonly value: unknown } | { readonly present: false };\n\n/** A fully resolved call, carrying literal values only (D5). */\nexport interface InversePlan {\n readonly server: string;\n readonly tool: string;\n readonly args: Record<string, unknown>;\n}\n\nconst ToolResult = z.looseObject({\n isError: z.boolean().default(false),\n content: z.array(z.looseObject({ type: z.string() })).default([]),\n});\n\n/**\n * The message an upstream sent when it refused a call, or undefined when it\n * did not refuse.\n *\n * A tool-level error arrives as an ordinary successful response carrying\n * `isError`, so nothing on the forward path notices it unless it looks. It\n * means the server received the call, understood it, and did not do it, which\n * is the same reading `runRead` gives a refused pre-read and `executeInverse`\n * gives a refused inverse.\n */\nexport function refusal(result: unknown): string | undefined {\n const parsed = ToolResult.safeParse(result);\n if (!parsed.success || !parsed.data.isError) {\n return undefined;\n }\n const said = parsed.data.content\n .map((block) => (typeof block[\"text\"] === \"string\" ? block[\"text\"] : \"\"))\n .filter((text) => text !== \"\")\n .join(\" \");\n return said === \"\" ? JSON.stringify(result) : said;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\n/**\n * The logical value a tool returned, rather than its MCP envelope. Manifests\n * say `$snapshot.plan`, not `$snapshot.content[0].text`, so the envelope has to\n * be unwrapped before interpolation sees it.\n */\nexport function toPayload(result: unknown): unknown {\n if (!isRecord(result)) {\n return result;\n }\n const structured = result[\"structuredContent\"];\n if (structured !== undefined) {\n return structured;\n }\n const content = result[\"content\"];\n if (Array.isArray(content) && content.length === 1) {\n const block: unknown = content[0];\n if (isRecord(block) && block[\"type\"] === \"text\" && typeof block[\"text\"] === \"string\") {\n const text = block[\"text\"];\n try {\n return JSON.parse(text) as unknown;\n } catch {\n // Not every server returns json. The raw text is still the payload.\n return text;\n }\n }\n }\n return result;\n}\n\nfunction resolveArgs(call: CallTemplate, context: TemplateContext): Record<string, unknown> {\n const resolved = resolveTemplate(call.args, context);\n if (!isRecord(resolved)) {\n throw new ManifestError(`${call.tool} resolved to arguments that are not an object`);\n }\n return resolved;\n}\n\n/**\n * Resolves the inverse while the run is still in progress (D5). At rollback\n * time the upstream may have drifted and the old value may no longer be\n * readable anywhere.\n */\nexport function planInverse(call: CallTemplate, context: TemplateContext): InversePlan {\n const target = splitQualified(call.tool);\n if (target === undefined) {\n throw new ManifestError(`inverse tool ${call.tool} is not qualified as server.tool`);\n }\n return { server: target.server, tool: target.tool, args: resolveArgs(call, context) };\n}\n\n/** The snapshot read with its arguments already reduced to literals. */\nexport interface ResolvedRead {\n readonly server: string;\n readonly tool: string;\n readonly args: Record<string, unknown>;\n /** What this server's error says when the thing is simply not there. */\n readonly absentWhen?: readonly string[];\n}\n\n/**\n * Resolves a declared pre-read against the current context. Stored on the\n * action so that drift can be checked later without consulting a manifest\n * that may have been edited in the meantime.\n */\nexport function planRead(call: CallTemplate, context: TemplateContext): ResolvedRead {\n const target = splitQualified(call.tool);\n if (target === undefined) {\n throw new SnapshotError(call.tool, \"the snapshot tool is not qualified as server.tool\");\n }\n try {\n return {\n server: target.server,\n tool: target.tool,\n args: resolveArgs(call, context),\n ...(call.absentWhen === undefined ? {} : { absentWhen: call.absentWhen }),\n };\n } catch (error: unknown) {\n throw new SnapshotError(call.tool, describe(error), { cause: error });\n }\n}\n\n/**\n * Runs a resolved pre-read. Deliberately not journalled: this is the proxy's\n * own traffic, and recording it would bury the actions an operator needs.\n */\n/**\n * Whether an error says the connection is gone rather than that the call was\n * refused. Matched on the message because the sdk reports both of these as\n * plain errors with no code to tell them apart.\n */\nexport function isDisconnected(error: unknown): boolean {\n const message = error instanceof Error ? error.message : String(error);\n return message.includes(\"Not connected\") || message.includes(\"Connection closed\");\n}\n\n/**\n * Whether the call may already have arrived. The sdk says \"Not connected\" when\n * there was no transport to write to, which means it was never sent; it says\n * \"Connection closed\" when the transport went while a reply was still owed,\n * which says nothing at all about whether the far end acted on it.\n */\nexport function mayHaveArrived(error: unknown): boolean {\n const message = error instanceof Error ? error.message : String(error);\n return message.includes(\"Connection closed\");\n}\n\nexport async function runRead(\n router: Router,\n read: ResolvedRead,\n signal: AbortSignal,\n): Promise<unknown> {\n const label = `${read.server}.${read.tool}`;\n const upstream = router.byName(read.server);\n if (upstream === undefined) {\n throw new SnapshotError(label, `server ${read.server} is not connected`);\n }\n const { tool, args } = read;\n\n const ask = (): Promise<unknown> =>\n upstream.client.request(\n { method: \"tools/call\", params: { name: tool, arguments: args } },\n z.looseObject({}),\n { signal },\n );\n\n let raw: unknown;\n try {\n raw = await ask();\n } catch (error: unknown) {\n // A single oversized response closes a stdio connection, and every call\n // after it -- reads, writes, anything -- then failed with \"Not connected\"\n // for the rest of the session: one large file bricked the run. Reading is\n // safe to do again, so the server is started back up and asked once more.\n if (!isDisconnected(error) || upstream.reconnect === undefined) {\n throw new SnapshotError(label, describe(error), { cause: error });\n }\n try {\n await upstream.reconnect();\n raw = await ask();\n } catch (retry: unknown) {\n // The second attempt can kill the connection the same way the first did\n // -- the response is still too large -- so leave a live one behind. The\n // call that caused it fails either way; the rest of the session should\n // not have to.\n if (isDisconnected(retry)) {\n await upstream.reconnect().catch(() => undefined);\n }\n // Twice, the same way, on a fresh connection: the request is fine and\n // the reply is what cannot be carried. Saying so is the difference\n // between a diagnosis and a shrug, because nothing else about\n // \"Connection closed\" points at the size of a file.\n const twice = isDisconnected(error) && isDisconnected(retry);\n throw new SnapshotError(\n label,\n twice\n ? `the connection to ${read.server} closed while reading, and again on a fresh one. ` +\n `A reply too large to carry does this: if the resource is more than a few megabytes, ` +\n `it cannot be snapshotted, and a write that cannot be snapshotted is refused rather than risked.`\n : `${describe(error)} (the connection to ${read.server} was restarted and the read failed again: ${describe(retry)})`,\n { cause: retry },\n );\n }\n }\n\n const parsed = ToolResult.safeParse(raw);\n if (parsed.success && parsed.data.isError) {\n // A tool-level error is a failed read either way: whatever the write is\n // about to overwrite, we did not capture it. What it means is the\n // question. Where the policy says what absence looks like on this server,\n // anything else is a failure and the write is refused rather than offered\n // for approval as a creation. Where it says nothing, every error has to be\n // read as absence, because the protocol gives no way to tell.\n const said = JSON.stringify(raw);\n const absent =\n read.absentWhen === undefined ||\n read.absentWhen.some((phrase) => said.toLowerCase().includes(phrase.toLowerCase()));\n throw new SnapshotError(label, `the read reported an error: ${said}`, { absent });\n }\n return toPayload(raw);\n}\n\n/**\n * The post-write read. Unlike the pre-read, a tool-level error here is\n * meaningful rather than fatal: the same read with the same arguments\n * succeeded moments earlier, so an error now says the resource is gone, which\n * is exactly what a delete is supposed to produce. Transport and protocol\n * failures still throw, because those say nothing about the resource.\n */\nexport async function observeState(\n router: Router,\n read: ResolvedRead,\n signal: AbortSignal,\n): Promise<StateObservation> {\n try {\n return { present: true, value: await runRead(router, read, signal) };\n } catch (error: unknown) {\n if (error instanceof SnapshotError && error.absent) {\n return { present: false };\n }\n throw error;\n }\n}\n"],"mappings":"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","names":["join","existsSync","dirname","existsSync","dirname","z","z","z","z","read","cached","z","z","read"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/errors.ts"],"sourcesContent":["/**\n * The taxonomy from spec 3.5. Classes are added as the phase that raises them\n * lands, so every class here has a live throw site.\n */\nexport abstract class SynartesisError extends Error {\n abstract readonly code: string;\n\n constructor(message: string, options?: { cause?: unknown }) {\n super(message, options);\n this.name = new.target.name;\n }\n}\n\nexport interface SourceLocation {\n readonly file: string;\n readonly line: number;\n readonly column: number;\n}\n\n/**\n * An invalid or unmatched policy. Carries a source location wherever the\n * manifest is at fault, because \"never start with a broken policy\" is only\n * useful if the operator is told which line to fix.\n */\nexport class ManifestError extends SynartesisError {\n readonly code = \"MANIFEST_ERROR\";\n\n constructor(\n message: string,\n readonly location?: SourceLocation,\n ) {\n super(\n location === undefined\n ? message\n : `${location.file}:${String(location.line)}:${String(location.column)}: ${message}`,\n );\n }\n}\n\n/** The wrapped server failed, or could not be reached at all. */\nexport class UpstreamError extends SynartesisError {\n readonly code = \"UPSTREAM_ERROR\";\n\n constructor(\n readonly server: string,\n readonly operation: string,\n cause: unknown,\n ) {\n super(`upstream ${server} failed during ${operation}: ${describe(cause)}`, { cause });\n }\n}\n\n/**\n * The pre-read failed, so the action must not proceed. A reversible action\n * without a snapshot is silently irreversible, which is the one outcome this\n * product exists to prevent.\n */\nexport class SnapshotError extends SynartesisError {\n readonly code = \"SNAPSHOT_ERROR\";\n\n constructor(\n readonly tool: string,\n reason: string,\n options?: { cause?: unknown; absent?: boolean },\n ) {\n super(`snapshot via ${tool} failed: ${reason}`, options);\n /**\n * The read reached the server and the server said no such resource, as\n * opposed to the read not completing at all. Only the former tells us\n * anything about the resource itself.\n */\n this.absent = options?.absent ?? false;\n }\n\n readonly absent: boolean;\n}\n\n/**\n * The longest string anywhere in a snapshot, which for anything file-shaped is\n * the contents. Found by looking rather than by field name: a snapshot is\n * whatever the server's read returned, and servers nest the payload\n * differently. Short strings are ignored so a path or an id is never mistaken\n * for the body.\n */\nfunction longestString(value: unknown): string {\n // Walked with an explicit stack rather than by recursion. A snapshot is\n // whatever an upstream server sent back, and a recursive walk overflowed on\n // one nested about five thousand deep -- which would turn a drift halt, the\n // moment a person most needs a clear message, into a stack trace. The visit\n // cap is the same argument applied to breadth.\n const pending: unknown[] = [value];\n let best = \"\";\n let visited = 0;\n\n while (pending.length > 0 && visited < MAX_SNAPSHOT_NODES) {\n const item = pending.pop();\n visited += 1;\n\n if (typeof item === \"string\") {\n if (item.length > best.length) {\n best = item;\n }\n } else if (Array.isArray(item)) {\n // One at a time: push(...huge) exceeds the argument limit and throws.\n for (const child of item) {\n pending.push(child);\n }\n } else if (typeof item === \"object\" && item !== null) {\n for (const child of Object.values(item)) {\n pending.push(child);\n }\n }\n }\n\n return best;\n}\n\n/**\n * A ceiling on how much of a snapshot is worth walking to find its text. Any\n * real payload is found long before this; anything past it is a server sending\n * something pathological, and a drift report is the wrong place to hang.\n */\nconst MAX_SNAPSHOT_NODES = 50_000;\n\n/** How many changed lines are worth printing before it stops being readable. */\nconst DIFF_BUDGET = 8;\n\n/**\n * What changed, as lines, rather than both documents in full. Trims the common\n * head and tail so only the region that actually differs is shown.\n */\nfunction lineDiff(before: string, after: string): string {\n const a = before.split(\"\\n\");\n const b = after.split(\"\\n\");\n\n let head = 0;\n while (head < a.length && head < b.length && a[head] === b[head]) {\n head += 1;\n }\n let tail = 0;\n while (\n tail < a.length - head &&\n tail < b.length - head &&\n a[a.length - 1 - tail] === b[b.length - 1 - tail]\n ) {\n tail += 1;\n }\n\n const removed = a.slice(head, a.length - tail);\n const added = b.slice(head, b.length - tail);\n const show = (lines: readonly string[], mark: string): string[] => [\n ...lines.slice(0, DIFF_BUDGET).map((line) => ` ${mark} ${line}`),\n ...(lines.length > DIFF_BUDGET\n ? [` ${mark} ... ${String(lines.length - DIFF_BUDGET)} more`]\n : []),\n ];\n\n return [\n ` at line ${String(head + 1)}:`,\n ...show(removed, \"-\"),\n ...show(added, \"+\"),\n ` ${String(removed.length)} removed, ${String(added.length)} added.`,\n ].join(\"\\n\");\n}\n\n/** A value with no text in it, kept short enough to read. */\nfunction brief(value: unknown): string {\n // JSON.stringify returns undefined rather than a string for a top-level\n // undefined, and .length on that throws. Journal values are parsed JSON, so\n // this is the only one of its cases that can reach here.\n if (value === undefined) {\n return \"undefined\";\n }\n try {\n const text = JSON.stringify(value);\n return text.length <= 160 ? text : `${text.slice(0, 157)}...`;\n } catch {\n // JSON.stringify recurses, so it overflows on a deeply nested value and\n // throws on a circular one. Saying less is better than a stack trace in\n // place of the drift report.\n return \"(a value too deeply nested to print)\";\n }\n}\n\n/**\n * The resource changed after the agent touched it. Writing the old value back\n * would silently destroy whatever happened in between, so what differs is\n * carried here for a human to judge.\n *\n * What differs, not both documents in full: printing the whole expected and\n * actual contents of a 200-line file buried the one line that mattered in two\n * screens of escaped JSON. Both values are still on the row, and\n * `synartesis show <run>` prints them.\n */\nexport class DriftConflict extends SynartesisError {\n readonly code = \"DRIFT_CONFLICT\";\n\n constructor(\n readonly seq: number,\n readonly expected: unknown,\n readonly actual: unknown,\n ) {\n const before = longestString(expected);\n const after = longestString(actual);\n // Two texts to compare, and they are not the same text. Anything else --\n // a resource that is simply gone, a snapshot with no body in it -- has no\n // lines to diff, so it says what it has.\n const body =\n before !== \"\" && after !== \"\" && before !== after\n ? lineDiff(before, after)\n : ` expected: ${brief(expected)}\\n actual: ${brief(actual)}`;\n\n super(\n `drift at sequence ${String(seq)}: the resource is not in the state this run left it in.\\n${body}`,\n );\n }\n}\n\n/**\n * An inverse failed, so the run is partially reverted. Continuing past it would\n * produce a state that is neither the before nor the after (D6).\n */\nexport class RollbackHalted extends SynartesisError {\n readonly code = \"ROLLBACK_HALTED\";\n\n constructor(\n readonly seq: number,\n reason: string,\n options?: { cause?: unknown },\n ) {\n super(`rollback halted at sequence ${String(seq)}: ${reason}`, options);\n }\n}\n\n/**\n * Not in spec 3.5, which covers failures on the proxy's forward path. A journal\n * write failing is different in kind: it means the record of what the agent did\n * is incomplete, so the call must not proceed. Always fatal, never swallowed.\n */\nexport class JournalError extends SynartesisError {\n readonly code = \"JOURNAL_ERROR\";\n\n constructor(operation: string, cause: unknown) {\n super(`journal ${operation} failed: ${describe(cause)}`, { cause });\n }\n}\n\nexport function describe(cause: unknown): string {\n if (cause instanceof Error) {\n return cause.message;\n }\n return typeof cause === \"string\" ? cause : JSON.stringify(cause);\n}\n"],"mappings":"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","names":[]}
package/dist/cli.js.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/cli.ts","../src/init/draft.ts","../src/init/known.ts","../src/rollback/rollback.ts","../src/watch.ts","../src/keys.ts","../src/console.ts"],"sourcesContent":["#!/usr/bin/env node\n/**\n * better-sqlite3 requires Node 22, and on Node 20 it does not fail politely:\n * it segfaults the moment a database is opened. Saying so is better than\n * letting somebody meet exit code 139.\n */\nconst NODE_MAJOR = Number(process.versions.node.split(\".\")[0]);\nif (NODE_MAJOR < 22) {\n process.stderr.write(\n `synartesis: needs Node 22 or newer, and this is ${process.version}.\\n`,\n );\n process.exit(2);\n}\n\nimport { existsSync, mkdirSync, readFileSync, statSync, writeFileSync } from \"node:fs\";\nimport { dirname, join, resolve } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\n\nimport { ManifestError, SynartesisError, describe } from \"./errors.js\";\nimport { draftManifest } from \"./init/draft.js\";\nimport { loadManifest, parseManifest } from \"./manifest/load.js\";\nimport { labelFor, openJournal, wasRefused, type ActionClass, type ActionRow, type Journal } from \"./journal/journal.js\";\nimport { verifyAgainstServers } from \"./manifest/verify.js\";\nimport { createRouter } from \"./proxy/routing.js\";\nimport { connectStdioUpstream, type Upstream } from \"./proxy/upstream.js\";\nimport { rollback, type RollbackReport } from \"./rollback/rollback.js\";\nimport { banner, NOTHING_RECORDED_YET, rule, style } from \"./style.js\";\nimport { findJournal, findManifest } from \"./locate.js\";\nimport { watch } from \"./watch.js\";\nimport { openConsole } from \"./console.js\";\nimport { cliCommand, proxyCommand } from \"./invocation.js\";\n\nconst COMMANDS = `\n synartesis the screen; everything below,\n driven with the arrow keys\n synartesis init <server> -- <command> [args...] [--manifest <path>]\n synartesis check [--manifest <path>]\n synartesis list [--journal <path>]\n synartesis show <runId> [--journal <path>]\n synartesis gates [--journal <path>]\n synartesis close [runId] [--journal <path>]\n synartesis prune [--older-than <days>] [--dry-run] [--journal <path>]\n synartesis proxy --manifest <path> [--journal <path>] what your agent runs\n [--http <port> --token <secret>] for a client that\n cannot start one\n synartesis watch [--by <name>] [--journal <path>]\n synartesis approve [actionId|--all] [--by <name>] [--journal <path>]\n synartesis deny [actionId|--all] [--by <name>] [--reason <text>] [--journal <path>]\n synartesis undo [runId] [--to <seq>] [--dry-run] [--replan]\n [--manifest <path>] [--journal <path>]\n\nclose ends a run left active by a proxy that was killed; nothing guesses at\nthat, since several proxies can share one journal.\n\nprune reclaims space. Putting a file back means keeping what was in it, so a\njournal grows at several times what an agent writes and never shrinks by\nitself. Nothing still active or still waiting on a person is ever pruned.\n\nIds may be shortened to any unambiguous prefix. show and undo default to the\nmost recent run; approve and deny default to the only request waiting. init\nadds to an existing manifest rather than replacing it.\n\nwatch is the one to leave running. Anything held for approval appears there,\nand a and d answer it without a second terminal or an id to copy.\n\n --manifest synartesis.yaml, looked for here and upwards, then in the home\n --journal beside the manifest, or the one in the home\n --to lowest sequence to undo; earlier actions are left alone\n --by who is deciding; defaults to the logged-in user\n --all approve or deny everything currently waiting\n --once watch prints the current state and exits\n --json machine-readable output for list, show and gates\n --dry-run read current state and print the plan without changing anything\n --replan rebuild each undo from the current manifest, for a run recorded\n under a policy that turned out to be wrong\n --older-than days of history prune keeps; defaults to 30\n --version print the version and exit\n\nNeither path usually needs giving. A policy that belongs to a project sits in\nit and is found from any directory inside it, the way a version control tool\nfinds its root; anything else lives in ~/.synartesis, which is where the\njournal is too. Set SYNARTESIS_HOME to put that somewhere else.\n\nExit codes: 0 complete, 1 halted or partial, 2 bad usage or configuration.\n`;\n\nclass UsageError extends Error {}\n\nfunction flag(argv: readonly string[], name: string): string | undefined {\n const at = argv.indexOf(name);\n if (at === -1) {\n return undefined;\n }\n const value = argv[at + 1];\n if (value === undefined || value.startsWith(\"--\")) {\n throw new UsageError(`${name} needs a value`);\n }\n return value;\n}\n\nfunction positional(argv: readonly string[]): string[] {\n const skip = new Set([\"--manifest\", \"--journal\", \"--to\", \"--by\", \"--reason\", \"--gate-timeout\", \"--older-than\"]);\n const values: string[] = [];\n // Everything after `--` belongs to the wrapped command, not to us.\n const end = argv.indexOf(\"--\");\n const ours = end === -1 ? argv : argv.slice(0, end);\n for (let i = 0; i < ours.length; i += 1) {\n const token = ours[i] ?? \"\";\n if (skip.has(token)) {\n i += 1;\n continue;\n }\n if (!token.startsWith(\"--\")) {\n values.push(token);\n }\n }\n return values;\n}\n\n/**\n * Loads a manifest and checks it against the servers it names, without\n * touching a journal or serving anything. This is what you run before wiring\n * a policy into a client, rather than finding out from a client that will not\n * start.\n */\nasync function runCheck(argv: readonly string[]): Promise<number> {\n const path = findManifest(flag(argv, \"--manifest\"));\n const manifest = loadManifest(path);\n\n const upstreams: Upstream[] = [];\n try {\n for (const [name, spec] of Object.entries(manifest.servers)) {\n upstreams.push(\n await connectStdioUpstream({\n name,\n command: spec.command,\n args: spec.args,\n stderr: \"capture\",\n ...(spec.env === undefined ? {} : { env: spec.env }),\n }),\n );\n }\n await verifyAgainstServers(upstreams, manifest);\n } finally {\n for (const upstream of upstreams) {\n await upstream.close();\n }\n }\n\n const counts = new Map<string, number>();\n for (const policy of manifest.tools) {\n counts.set(policy.class, (counts.get(policy.class) ?? 0) + 1);\n }\n const gated = manifest.tools.filter((policy) => policy.gate !== \"never\").length;\n\n out(\"\");\n out(` ${style.label(\"policy\")} ${style.strong(path)}`);\n out(` ${rule(54)}`);\n out(\"\");\n out(` ${style.quiet(\"servers \")} ${Object.keys(manifest.servers).join(\", \")}`);\n out(` ${style.quiet(\"policies\")} ${[...counts].map(([k, v]) => `${String(v)} ${k}`).join(\", \")}`);\n out(` ${style.quiet(\"guarded \")} ${style.accent(String(gated))}`);\n out(\"\");\n out(` ${style.quiet(\"Anything not mentioned here is treated as irreversible and guarded.\")}`);\n out(\"\");\n return 0;\n}\n\nasync function runInit(argv: readonly string[]): Promise<number> {\n const name = positional(argv)[1];\n const separator = argv.indexOf(\"--\");\n const command = separator === -1 ? undefined : argv[separator + 1];\n if (name === undefined || command === undefined) {\n throw new UsageError(\"init needs a server name and a command, as: init crm -- npx -y some-mcp-server\");\n }\n if (name.includes(\".\") || name.includes(\"__\")) {\n throw new UsageError(`server name ${name} may not contain \".\" or \"__\"; both qualify tool names`);\n }\n\n // The home unless a project already has one above where you are standing.\n // Setting a server up should not mean choosing a directory to keep it in.\n const path = findManifest(flag(argv, \"--manifest\"));\n const force = argv.includes(\"--force\");\n const present = existsSync(path);\n if (present && force) {\n throw new UsageError(\n `--force would discard ${path}. Delete it yourself if that is what you want; init will otherwise add to it.`,\n );\n }\n\n const draft = await draftManifest({\n name,\n command,\n args: argv.slice(separator + 2),\n ...(present ? { existing: readFileSync(path, \"utf8\") } : {}),\n });\n\n // Never write a manifest that would not start: a drafted policy that fails\n // to load is worse than no policy, because it looks finished.\n parseManifest(draft.yaml, path);\n // 0700: the journal that lands in here holds the previous contents of every\n // file an agent writes, and the directory is the first thing guarding it.\n mkdirSync(dirname(resolve(path)), { recursive: true, mode: 0o700 });\n writeFileSync(path, draft.yaml);\n\n out(\"\");\n out(` ${style.label(present ? \"extended\" : \"wrote\")} ${style.strong(path)}`);\n out(` ${rule(54)}`);\n out(\"\");\n if (draft.adopted === undefined) {\n out(` ${style.quiet(\"Every tool is guarded until you say how to undo it.\")}`);\n out(` ${style.quiet(\"Work through the TODOs, then point your MCP client at:\")}`);\n } else {\n out(\n ` ${style.quiet(`Recognised ${String(draft.adopted.tools)} tools, so the policy that ships for`)} ` +\n `${style.strong(draft.adopted.server)} ${style.quiet(\"was used.\")}`,\n );\n out(` ${style.quiet(\"Read it before you trust it, then point your MCP client at:\")}`);\n }\n out(\"\");\n out(` ${style.accent(`${proxyCommand()} --manifest ${resolve(path)}`)}`);\n out(\"\");\n return 0;\n}\n\n/**\n * Ids are uuids, and copying one between two terminals is the clunkiest part\n * of using this. Any unambiguous prefix will do, and where there is only one\n * sensible answer, no id is needed at all.\n */\ninterface Noun {\n readonly one: string;\n readonly many: string;\n}\n\n/**\n * `newest` is for the commands whose default is a run rather than the only\n * candidate. show and undo have always been documented as defaulting to the\n * most recent run; without this that held only until a second run existed,\n * after which both refused and listed every id -- offering --all, which\n * neither of them takes. approve and deny stay strict: \"the only one waiting\"\n * is a different promise, and guessing which of several to allow is not a\n * guess anything should make.\n */\nfunction pick<T extends { id: string }>(\n candidates: readonly T[],\n given: string | undefined,\n noun: Noun,\n newest = false,\n): T {\n const listed = (items: readonly T[]): string =>\n items.map((item) => ` ${item.id}`).join(\"\\n\");\n\n if (given === undefined) {\n const [only, ...rest] = candidates;\n if (only === undefined) {\n throw new UsageError(`there is no ${noun.one} to act on`);\n }\n if (rest.length > 0 && !newest) {\n throw new UsageError(\n `there are ${String(candidates.length)} ${noun.many}; name one, or use --all:\\n${listed(candidates)}`,\n );\n }\n return only;\n }\n\n const exact = candidates.find((item) => item.id === given);\n if (exact !== undefined) {\n return exact;\n }\n const matches = candidates.filter((item) => item.id.startsWith(given));\n const [first, ...rest] = matches;\n if (first === undefined) {\n throw new UsageError(`no ${noun.one} matches ${given}`);\n }\n if (rest.length > 0) {\n throw new UsageError(\n `${given} matches ${String(matches.length)} ${noun.many}:\\n${listed(matches)}`,\n );\n }\n return first;\n}\n\nconst RUN: Noun = { one: \"run\", many: \"runs\" };\nconst WAITING: Noun = { one: \"action awaiting approval\", many: \"actions awaiting approval\" };\n\n// Piping into head or less closes the pipe early. That is the reader saying it\n// has seen enough, not an error, and a stack trace there is pure noise.\nprocess.stdout.on(\"error\", (error: NodeJS.ErrnoException) => {\n if (error.code === \"EPIPE\") {\n process.exit(0);\n }\n throw error;\n});\n\nfunction out(line: string): void {\n process.stdout.write(`${line}\\n`);\n}\n\nfunction runList(journal: Journal, asJson: boolean, journalPath: string): number {\n // Most recent first: the run someone wants to undo is nearly always the last\n // thing that happened.\n const runs = [...journal.listRuns()].reverse();\n if (asJson) {\n out(JSON.stringify(runs.map((run) => ({ ...run, actions: journal.getActions(run.id).length }))));\n return 0;\n }\n if (runs.length === 0) {\n out(\"no runs recorded\");\n return 0;\n }\n out(\"\");\n out(` ${style.label(\"runs\")} ${style.quiet(\"most recent first\")}`);\n out(` ${rule(96)}`);\n out(\"\");\n out(\n style.quiet(\n ` ${\"run\".padEnd(36)} ${\"started\".padEnd(24)} ${\"status\".padEnd(12)} actions agent`,\n ),\n );\n for (const run of runs) {\n const actions = journal.getActions(run.id);\n const unknown = actions.filter((action) => action.status === \"pending\").length;\n const waiting = actions.filter((action) => action.status === \"gated\").length;\n const notes = [\n unknown === 0 ? \"\" : `${String(unknown)} of unknown outcome`,\n waiting === 0 ? \"\" : `${String(waiting)} awaiting approval`,\n ].filter((note) => note !== \"\");\n const note =\n notes.length === 0 ? \"\" : ` ${style.accent(`(${notes.join(\"; \")})`)}`;\n out(\n ` ${style.strong(run.id)} ${style.quiet(run.startedAt)} ${run.status.padEnd(12)} ` +\n `${String(actions.length).padStart(7)} ${run.label ?? \"-\"}${note}`,\n );\n }\n out(\"\");\n // Only once it is big enough to be worth a sentence. Keeping what was in\n // every file an agent wrote adds up quietly, and finding out from df is\n // finding out too late.\n if ((bytesOf(journalPath) ?? 0) > PRUNE_NAG_BYTES) {\n out(` ${style.quiet(`This journal is ${sizeOf(journalPath)}; synartesis prune reclaims what is old enough to lose.`)}`);\n out(\"\");\n }\n return 0;\n}\n\nfunction runShow(argv: readonly string[], journal: Journal, asJson: boolean): number {\n const runs = [...journal.listRuns()].reverse();\n const run = pick(runs, positional(argv)[1], RUN, true);\n const runId = run.id;\n\n if (asJson) {\n out(JSON.stringify({ run, actions: journal.getActions(runId) }));\n return 0;\n }\n\n out(\"\");\n out(` ${style.label(\"run\")} ${style.strong(run.id)}`);\n out(` ${rule(54)}`);\n out(\"\");\n out(` ${style.quiet(\"agent \")} ${run.label ?? \"-\"}`);\n out(` ${style.quiet(\"started\")} ${run.startedAt}`);\n out(\n ` ${style.quiet(\"status \")} ${run.status}` +\n (run.endedAt === undefined ? \"\" : style.quiet(` ended ${run.endedAt}`)),\n );\n\n const actions = journal.getActions(runId);\n if (actions.length === 0) {\n out(\"\");\n out(\"no actions recorded\");\n return 0;\n }\n\n out(\"\");\n out(\"\");\n out(` ${style.label(\"timeline\")}`);\n out(` ${rule(72)}`);\n out(\"\");\n for (const action of actions) {\n out(\n ` ${style.quiet(String(action.seq).padStart(3))} ${badgeOf(action)} ` +\n `${statusOf(action)} ${style.strong(`${action.server}.${action.tool}`)}`,\n );\n out(` ${style.quiet(truncate(JSON.stringify(action.args), 96))}`);\n if (action.approvedAt !== undefined) {\n const verb = action.status === \"denied\" ? \"denied\" : \"approved\";\n out(\n ` ${style.accent(`${verb} by ${action.approvedBy ?? \"nobody\"}`)} ${style.quiet(`at ${action.approvedAt}`)}`,\n );\n }\n if (action.error !== undefined) {\n out(` ${style.quiet(`note: ${truncate(action.error, 200)}`)}`);\n }\n if (action.inverse !== undefined) {\n out(` ${style.quiet(\"undo:\")} ${truncate(JSON.stringify(action.inverse), 200)}`);\n }\n }\n\n out(\"\");\n out(` ${summarise(actions)}`);\n out(\"\");\n return 0;\n}\n\nconst CLASS_MARK: Record<ActionClass, string> = {\n readonly: \"\\u00b7\",\n reversible: \"\\u2190\",\n compensable: \"\\u2248\",\n irreversible: \"!\",\n unclassified: \"?\",\n};\n\n/** Wide enough for the longest class name plus its marker. */\nconst BADGE_WIDTH = \"irreversible\".length + 2;\n\n/** Padded before it is coloured: escape codes are not printable width. */\nfunction badgeOf(action: ActionRow): string {\n const plain = `${CLASS_MARK[action.class]} ${action.class}`.padEnd(BADGE_WIDTH);\n return action.class === \"irreversible\" ? style.accent(plain) : style.quiet(plain);\n}\n\nfunction statusOf(action: ActionRow): string {\n const text = labelFor(action).padEnd(13);\n if (wasRefused(action)) {\n return style.accent(text);\n }\n if (action.status === \"gated\") {\n return style.strong(text);\n }\n return style.quiet(text);\n}\n\n/**\n * Broken over lines rather than cut off. The reason a call is being held ends\n * with the server's own words, so truncating it removes the only part that\n * says anything the tool name did not already.\n */\nfunction wrapped(text: string, width: number): string[] {\n const lines: string[] = [];\n let line = \"\";\n for (const word of text.split(/\\s+/).filter((part) => part !== \"\")) {\n if (line === \"\") {\n line = word;\n } else if (line.length + 1 + word.length <= width) {\n line = `${line} ${word}`;\n } else {\n lines.push(line);\n line = word;\n }\n }\n if (line !== \"\") {\n lines.push(line);\n }\n return lines;\n}\n\nfunction truncate(text: string, limit: number): string {\n return text.length <= limit ? text : `${text.slice(0, limit - 3)}...`;\n}\n\nfunction summarise(actions: readonly ActionRow[]): string {\n const counts = new Map<string, number>();\n for (const action of actions) {\n counts.set(action.status, (counts.get(action.status) ?? 0) + 1);\n }\n const parts = [...counts].sort(([a], [b]) => (a < b ? -1 : 1)).map(([k, v]) => `${String(v)} ${k}`);\n const undoable = actions.filter((a) => a.inverse !== undefined).length;\n return `${String(actions.length)} actions: ${parts.join(\", \")} | ${String(undoable)} with a recorded undo`;\n}\n\n/**\n * Repeated back in any command this prints, because whoever copies the line may\n * well be in a different directory than the one it was printed from.\n */\nlet journalArg = \"\";\n\n/** Past this, a journal is worth mentioning without being asked. */\nconst PRUNE_NAG_BYTES = 100 * 1024 * 1024;\n\n/** Undefined rather than zero, so \"cannot read it\" stays distinct from \"empty\". */\nfunction bytesOf(path: string): number | undefined {\n try {\n return statSync(path).size;\n } catch {\n return undefined;\n }\n}\n\n/** Bytes as something a person reads, since this is the point of the command. */\nfunction sizeOf(path: string): string {\n const bytes = bytesOf(path);\n if (bytes === undefined) {\n return \"unknown\";\n }\n if (bytes < 1024 * 1024) {\n return `${String(Math.max(1, Math.round(bytes / 1024)))} kB`;\n }\n return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;\n}\n\nconst PRUNE_DEFAULT_DAYS = 30;\n\n/**\n * A hundred years, which is not a limit anybody will meet and is well inside\n * the range a Date can hold. Without a ceiling, --older-than 999999999 puts\n * the cutoff before the earliest representable date, toISOString throws a\n * RangeError, and the user is told \"Invalid time value\" -- which names neither\n * the flag nor the problem, and exits 1 as though the prune had failed partway\n * rather than 2 as though they had mistyped a flag.\n */\nconst PRUNE_MAX_DAYS = 36500;\n\n/**\n * Every write keeps the file as it was, the file as it became, and the call\n * that did it, so a journal grows at several times the bytes an agent writes\n * and never shrinks on its own. This is the way to get that space back.\n *\n * It is asked for, never automatic. A tool whose whole purpose is that you can\n * still undo what happened has no business deleting that history on a timer.\n */\nfunction runPrune(argv: readonly string[], journal: Journal, journalPath: string): number {\n const given = flag(argv, \"--older-than\");\n const days = given === undefined ? PRUNE_DEFAULT_DAYS : Number(given);\n if (!Number.isFinite(days) || days < 0 || days > PRUNE_MAX_DAYS) {\n throw new UsageError(\n `--older-than takes a number of days from 0 to ${String(PRUNE_MAX_DAYS)}, not ${given ?? \"\"}`,\n );\n }\n\n const before = new Date(Date.now() - days * 24 * 60 * 60 * 1000).toISOString();\n const stale = journal.prunableRuns(before);\n const planned = argv.includes(\"--dry-run\");\n const sizeBefore = sizeOf(journalPath);\n\n out(\"\");\n out(` ${style.label(planned ? \"would prune\" : \"prune\")} ${style.quiet(`older than ${String(days)} days`)}`);\n out(` ${rule(54)}`);\n out(\"\");\n // Named, because a journal is found by walking up from here and this is the\n // one command that throws history away. Being told afterwards which file\n // that was is too late.\n out(` ${style.quiet(journalPath)}`);\n out(\"\");\n\n if (stale.length === 0) {\n out(` ${style.quiet(`Nothing is older than ${String(days)} days and finished with.`)}`);\n out(\"\");\n out(` ${style.quiet(`The journal is ${sizeBefore}. Runs still active, and any`)}`);\n out(` ${style.quiet(\"holding a call that is waiting or in flight, are never pruned.\")}`);\n out(\"\");\n return 0;\n }\n\n let actions = 0;\n for (const run of stale) {\n actions += run.actions;\n out(\n ` ${style.strong((run.label ?? \"an agent\").padEnd(24))} ` +\n `${style.quiet(run.at.slice(0, 19).replace(\"T\", \" \"))} ` +\n `${style.quiet(run.status.padEnd(11))} ${style.quiet(`${String(run.actions)} actions`)}`,\n );\n }\n out(\"\");\n\n if (planned) {\n out(\n ` ${style.accent(`${String(stale.length)} runs`)} ${style.quiet(`and ${String(actions)} actions would go. Nothing was changed.`)}`,\n );\n out(\"\");\n return 0;\n }\n\n const removed = journal.deleteRuns(stale.map((run) => run.id));\n // After the delete and outside its transaction, which is the only place\n // VACUUM can run -- and without it the file stays exactly as big as it was.\n journal.vacuum();\n\n out(\n ` ${style.accent(`${String(removed.runs)} runs`)} ${style.quiet(`and ${String(removed.actions)} actions removed.`)}`,\n );\n out(` ${style.quiet(`Journal ${sizeBefore} \\u2192 ${sizeOf(journalPath)}.`)}`);\n out(\"\");\n return 0;\n}\n\nfunction runClose(argv: readonly string[], journal: Journal): number {\n // Left active by a proxy that was killed rather than disconnected. Nothing\n // can tell that apart from a run still going, so this is asked for, never\n // guessed: several proxies can share one journal.\n const active = journal.listRuns().filter((candidate) => candidate.status === \"active\");\n const run = pick([...active].reverse(), positional(argv)[1], RUN, true);\n const closed = journal.closeAbandonedRun(run.id);\n out(\"\");\n out(\n closed\n ? ` ${style.label(\"closed\")} ${style.strong(run.id)}`\n : ` ${style.quiet(`${run.id} was not active.`)}`,\n );\n out(\"\");\n return closed ? 0 : 1;\n}\n\nfunction runGates(journal: Journal, asJson: boolean): number {\n const waiting = journal.listGated();\n if (asJson) {\n out(JSON.stringify(waiting));\n return 0;\n }\n if (waiting.length === 0) {\n out(\"\");\n out(` ${style.quiet(\"Nothing is waiting for a decision.\")}`);\n out(\"\");\n return 0;\n }\n out(\"\");\n out(` ${style.label(\"awaiting approval\")}`);\n out(` ${rule(72)}`);\n out(\"\");\n for (const action of waiting) {\n out(` ${style.strong(action.id)} ${style.quiet(action.ts)}`);\n out(` ${style.accent(`${action.server}.${action.tool}`)} ${style.quiet(truncate(JSON.stringify(action.args), 88))}`);\n // The reason, because approving is the decision this screen exists for and\n // it was being made on a tool name and a bag of arguments alone.\n for (const [at, line] of wrapped(action.error ?? \"held by policy\", 76).entries()) {\n out(` ${at === 0 ? style.quiet(action.class) : \" \".repeat(action.class.length)} ${style.quiet(line)}`);\n }\n out(\"\");\n }\n const self = cliCommand();\n out(\n ` ${style.quiet(`${self} approve`)} ${style.accent(waiting[0]?.id.slice(0, 8) ?? \"<id>\")} ${style.quiet(`--by <name>${journalArg}`)}`,\n );\n out(` ${style.quiet(`${self} approve --all --by <name>${journalArg}`)}`);\n out(\"\");\n return 0;\n}\n\nfunction runDecision(argv: readonly string[], journal: Journal, approving: boolean): number {\n const waiting = journal.listGated();\n const given = positional(argv)[1];\n // \"unknown\" is a poor thing to find in an audit trail when the machine knows\n // perfectly well who is logged in. --by still wins, for approving on behalf\n // of someone else.\n const by =\n flag(argv, \"--by\") ?? process.env[\"USER\"] ?? process.env[\"LOGNAME\"] ?? \"unknown\";\n const reason = flag(argv, \"--reason\") ?? \"denied by operator\";\n\n // Looked up among everything first, so an action that has already been\n // settled gets told what became of it rather than \"no such action\".\n if (given !== undefined) {\n const settled = journal.getAction(given);\n if (settled !== undefined && settled.status !== \"gated\") {\n process.stderr.write(\n `synartesis: ${given} is no longer awaiting approval (it is ${settled.status})\\n`,\n );\n return 1;\n }\n }\n\n const targets = argv.includes(\"--all\")\n ? waiting\n : [pick(waiting, given, WAITING)];\n if (targets.length === 0) {\n out(\"nothing is awaiting approval\");\n return 0;\n }\n\n let failed = 0;\n for (const action of targets) {\n const changed = approving\n ? journal.approve(action.id, by)\n : journal.deny(action.id, by, reason);\n if (!changed) {\n // A decision that lands after the action settled must not look like it\n // took effect.\n const now = journal.getAction(action.id);\n process.stderr.write(\n `synartesis: ${action.id} is no longer awaiting approval (it is ${now?.status ?? \"gone\"})\\n`,\n );\n failed += 1;\n continue;\n }\n out(\n ` ${style.accent(approving ? \"approved\" : \"denied\")} ${style.strong(`${action.server}.${action.tool}`)} ${style.quiet(action.id)}`,\n );\n }\n return failed === 0 ? 0 : 1;\n}\n\nfunction report(result: RollbackReport): number {\n out(\"\");\n out(` ${style.label(result.dryRun ? \"dry run\" : \"undo\")} ${style.strong(result.runId)}`);\n out(` ${rule(72)}`);\n out(\"\");\n let separated = false;\n for (const step of result.steps) {\n // Set apart by a rule rather than mixed in: these are the ones --to is\n // leaving alone, and reading them as part of the plan would invert what\n // they mean.\n if (step.kind === \"kept\" && !separated) {\n separated = true;\n out(\"\");\n out(` ${style.quiet(\"left alone\")}`);\n }\n const unverified =\n step.kind === \"revert\" && !step.verified ? ` ${style.accent(\"[unverified]\")}` : \"\";\n const kind =\n step.kind === \"halt\" || step.kind === \"permanent\"\n ? style.accent(step.kind.padEnd(16))\n : step.kind.padEnd(16);\n out(\n ` ${style.quiet(String(step.seq).padStart(3))} ${kind} ` +\n `${style.strong(`${step.server}.${step.tool}`)} ${style.quiet(step.reason)}${unverified}`,\n );\n if (step.plan !== undefined && step.kind === \"revert\") {\n const verb = `${step.replanned === true ? \"replanned, \" : \"\"}${result.dryRun ? \"would call\" : \"called\"}`;\n out(\n ` ${style.quiet(verb)} ${step.plan.server}.${step.plan.tool} ` +\n style.quiet(truncate(JSON.stringify(step.plan.args), 120)),\n );\n }\n }\n if (result.halted !== undefined) {\n out(\"\");\n out(\n ` ${style.accent(\"halted\")} ${style.quiet(`at sequence ${String(result.halted.seq)}`)} ${result.halted.reason}`,\n );\n if (result.halted.detail !== \"\") {\n for (const line of result.halted.detail.split(\"\\n\")) {\n out(` ${style.quiet(line)}`);\n }\n }\n }\n const permanent = result.steps.filter((step) => step.kind === \"permanent\");\n if (permanent.length > 0) {\n out(\"\");\n out(\n ` ${style.quiet(`${String(permanent.length)} action${permanent.length === 1 ? \"\" : \"s\"} could not be undone and ${permanent.length === 1 ? \"was\" : \"were\"} left in place.`)}`,\n );\n }\n out(\"\");\n out(\n ` ${style.label(\"result\")} ${result.status === \"rolled_back\" ? result.status : style.accent(result.status)}`,\n );\n out(\"\");\n return result.status === \"rolled_back\" ? 0 : 1;\n}\n\n/**\n * Starting every server the manifest names, undoing, and shutting them down\n * again. Shared, because the console does exactly this when somebody presses\n * u and there must not be two answers to what undo means.\n */\nasync function performUndo(\n manifestPath: string,\n journal: Journal,\n runId: string,\n options: { dryRun: boolean; toSeq?: number; replan?: boolean },\n): Promise<RollbackReport> {\n const manifest = loadManifest(manifestPath);\n const upstreams: Upstream[] = [];\n try {\n for (const [name, spec] of Object.entries(manifest.servers)) {\n upstreams.push(\n await connectStdioUpstream({\n name,\n command: spec.command,\n args: spec.args,\n stderr: \"capture\",\n ...(spec.env === undefined ? {} : { env: spec.env }),\n }),\n );\n }\n return await rollback({\n journal,\n router: createRouter(upstreams, manifest),\n runId,\n ...(options.toSeq === undefined ? {} : { toSeq: options.toSeq }),\n dryRun: options.dryRun,\n ...(options.replan === true ? { replanWith: manifest } : {}),\n });\n } finally {\n for (const upstream of upstreams) {\n await upstream.close();\n }\n }\n}\n\nasync function runUndo(argv: readonly string[], journal: Journal): Promise<number> {\n // Defaults to the most recent run: the thing anyone wants to undo is\n // almost always the last thing that happened.\n const runId = pick([...journal.listRuns()].reverse(), positional(argv)[1], RUN, true).id;\n\n const rawTo = flag(argv, \"--to\");\n const toSeq = rawTo === undefined ? undefined : Number(rawTo);\n if (toSeq !== undefined && (!Number.isInteger(toSeq) || toSeq < 1)) {\n throw new UsageError(\"--to needs a positive whole number\");\n }\n // Past the end, every action is below the floor, so nothing is planned and\n // the empty plan reads exactly like a run with nothing left to undo. A typed\n // digit too many looked like a result.\n if (toSeq !== undefined) {\n const highest = journal.getActions(runId).reduce((top, action) => Math.max(top, action.seq), 0);\n if (toSeq > highest) {\n throw new UsageError(\n `--to ${String(toSeq)} is past the end of this run, which goes up to ${String(highest)}`,\n );\n }\n }\n\n return report(\n await performUndo(findManifest(flag(argv, \"--manifest\")), journal, runId, {\n dryRun: argv.includes(\"--dry-run\"),\n ...(toSeq === undefined ? {} : { toSeq }),\n replan: argv.includes(\"--replan\"),\n }),\n );\n}\n\n/**\n * Every flag any command takes. Checked as one set rather than per command:\n * the failure worth catching is a typo, and `list --to 3` being tolerated is a\n * far smaller problem than `undo --jounral other.db` silently reading the\n * default journal and reversing whatever happened to be in it.\n */\nconst FLAGS = new Set([\n \"--manifest\",\n \"--journal\",\n \"--to\",\n \"--by\",\n \"--all\",\n \"--once\",\n \"--json\",\n \"--dry-run\",\n \"--replan\",\n \"--reason\",\n \"--force\",\n \"--older-than\",\n \"--help\",\n \"-h\",\n \"--version\",\n \"-V\",\n]);\n\n/**\n * The version, which is the first thing anybody is asked for when they report\n * something. Read from the package rather than baked in, so it cannot drift\n * from what npm thinks was installed. From dist/cli.js that is one directory\n * up, which holds in a clone and in an install alike.\n */\nfunction version(): string {\n try {\n const root = dirname(fileURLToPath(import.meta.url));\n const parsed: unknown = JSON.parse(readFileSync(join(root, \"..\", \"package.json\"), \"utf8\"));\n const found =\n typeof parsed === \"object\" && parsed !== null\n ? (parsed as { version?: unknown }).version\n : undefined;\n return typeof found === \"string\" ? found : \"unknown\";\n } catch {\n // Reporting \"unknown\" is still an answer. Refusing to start because a\n // version string could not be found would not be.\n return \"unknown\";\n }\n}\n\nfunction rejectUnknownFlags(argv: readonly string[]): void {\n for (const token of argv) {\n // Everything past a bare `--` belongs to the command init is starting, and\n // that command has flags of its own.\n if (token === \"--\") {\n return;\n }\n if (token.startsWith(\"-\") && token !== \"-\" && !FLAGS.has(token)) {\n throw new UsageError(`unknown flag ${token}`);\n }\n }\n}\n\n/**\n * The same open, with the one thing the error was missing: where a journal\n * comes from. \"There is no journal at <path>\" is true and leads nowhere.\n */\nfunction openJournalOrExplain(journalPath: string): Journal {\n if (!existsSync(journalPath)) {\n throw new UsageError(\n `nothing has been recorded yet: there is no journal at ${journalPath}. ` +\n `One appears the first time an agent calls a tool through synartesis proxy.`,\n );\n }\n return openJournal(journalPath, { mustExist: true });\n}\n\nasync function main(argv: readonly string[]): Promise<number> {\n const command = positional(argv)[0];\n if (command === \"proxy\") {\n // The proxy, run through this command rather than its own binary, so the\n // line people paste into a client config is one package and one word:\n // npx -y synartesis proxy --manifest ... . Loaded only here, and before\n // anything else in this file runs, because from this point stdout carries\n // protocol frames and a banner on it would corrupt the stream.\n await import(\"./proxy/stdio.js\");\n return 0;\n }\n if (argv.includes(\"--help\") || argv.includes(\"-h\")) {\n process.stdout.write(`${banner()}\\n${COMMANDS}`);\n return 0;\n }\n if (argv.includes(\"--version\") || argv.includes(\"-V\")) {\n // Bare, with no styling around it: this is read by people filing issues\n // and by scripts, and both want the string and nothing else.\n process.stdout.write(`${version()}\\n`);\n return 0;\n }\n rejectUnknownFlags(argv);\n // Nothing typed opens the screen. Being handed a page of eight commands is a\n // fine answer for a script and a poor one for a person, who wants to see\n // what happened rather than be told the names of the words for asking.\n if (command === undefined) {\n const manifestPath = findManifest(flag(argv, \"--manifest\"));\n const journalPath = findJournal(flag(argv, \"--journal\"), manifestPath);\n return await openConsole({\n journalPath,\n write: (text) => process.stdout.write(text),\n live: process.stdout.isTTY,\n decideAs: flag(argv, \"--by\") ?? process.env[\"USER\"] ?? process.env[\"LOGNAME\"] ?? \"unknown\",\n undo: async (runId, dryRun) => {\n const journal = openJournal(journalPath, { mustExist: true });\n try {\n return await performUndo(manifestPath, journal, runId, { dryRun });\n } finally {\n journal.close();\n }\n },\n });\n }\n\n // None of these needs an existing journal, and none should create one.\n if (command === \"init\") {\n return await runInit(argv);\n }\n if (command === \"check\") {\n return await runCheck(argv);\n }\n\n const asJson = argv.includes(\"--json\");\n const given = flag(argv, \"--journal\");\n const journalPath = findJournal(given, findManifest(flag(argv, \"--manifest\")));\n\n // Watching is the one thing you do before anything has happened, so it opens\n // its own handle when there is one and waits when there is not.\n if (command === \"watch\") {\n const live = process.stdout.isTTY && !argv.includes(\"--once\");\n return await watch({\n journalPath,\n approveWith: cliCommand(),\n write: (text) => process.stdout.write(text),\n live,\n // A decision has to be attributable, so the view can only make one when\n // it knows whose it is.\n decideAs: flag(argv, \"--by\") ?? process.env[\"USER\"] ?? process.env[\"LOGNAME\"] ?? \"unknown\",\n });\n }\n\n // Repeated back only when it was not the obvious one, so a copied command\n // works from anywhere without being cluttered when it need not be.\n journalArg = given === undefined ? \"\" : ` --journal ${resolve(given)}`;\n // Reading commands, before anything has been recorded. Being early is not an\n // error, and the screen has always said so; these aborted with \"there is no\n // journal at <path>\" instead. Answered without opening anything, so looking\n // does not leave a journal behind either.\n if (!existsSync(journalPath) && (command === \"list\" || command === \"show\" || command === \"gates\")) {\n if (asJson) {\n out(JSON.stringify(command === \"show\" ? { run: null, actions: [] } : []));\n return 0;\n }\n out(\"\");\n out(` ${style.quiet(\"nothing has been recorded yet\")}`);\n out(\"\");\n for (const line of NOTHING_RECORDED_YET) {\n out(` ${style.quiet(line)}`);\n }\n out(\"\");\n return 0;\n }\n\n // Every remaining command reads an existing journal. Only the proxy makes one.\n const journal = openJournalOrExplain(journalPath);\n try {\n switch (command) {\n case \"list\":\n return runList(journal, asJson, journalPath);\n case \"show\":\n return runShow(argv, journal, asJson);\n case \"close\":\n return runClose(argv, journal);\n case \"prune\":\n return runPrune(argv, journal, journalPath);\n case \"gates\":\n return runGates(journal, asJson);\n case \"approve\":\n return runDecision(argv, journal, true);\n case \"deny\":\n return runDecision(argv, journal, false);\n case \"undo\":\n return await runUndo(argv, journal);\n default:\n throw new UsageError(`unknown command ${command}`);\n }\n } finally {\n journal.close();\n }\n}\n\ntry {\n process.exitCode = await main(process.argv.slice(2));\n} catch (error: unknown) {\n if (error instanceof UsageError) {\n process.stderr.write(`synartesis: ${error.message}\\n\\n${COMMANDS}`);\n process.exitCode = 2;\n } else if (error instanceof ManifestError) {\n process.stderr.write(`synartesis: ${error.message}\\n`);\n process.exitCode = 2;\n } else if (error instanceof SynartesisError) {\n // Without the code. It read as synartesis: JOURNAL_ERROR: journal open\n // failed: ... -- three prefixes before the sentence that says what is\n // wrong. The exit code is the part a script reads.\n process.stderr.write(`synartesis: ${error.message}\\n`);\n process.exitCode = 1;\n } else {\n process.stderr.write(`synartesis: ${describe(error)}\\n`);\n process.exitCode = 1;\n }\n}\n","import { z } from \"zod\";\n\nimport { ManifestError, UpstreamError, describe } from \"../errors.js\";\nimport { connectStdioUpstream } from \"../proxy/upstream.js\";\nimport { knownPolicyFor, toolsReferencedBy } from \"./known.js\";\n\nexport interface Draft {\n readonly yaml: string;\n /** The bundled policy this used, if one fitted. */\n readonly adopted?: { readonly server: string; readonly tools: number };\n}\n\nexport interface DraftOptions {\n readonly name: string;\n readonly command: string;\n readonly args: readonly string[];\n /** Existing manifest source to extend rather than replace. */\n readonly existing?: string;\n}\n\nconst toolSchema = z.looseObject({\n name: z.string(),\n description: z.string().optional(),\n annotations: z\n .looseObject({\n readOnlyHint: z.boolean().optional(),\n destructiveHint: z.boolean().optional(),\n idempotentHint: z.boolean().optional(),\n })\n .optional(),\n});\n\nconst listSchema = z.looseObject({\n tools: z.array(toolSchema),\n nextCursor: z.string().optional(),\n});\n\ntype Tool = z.infer<typeof toolSchema>;\n\nfunction quote(value: string): string {\n return JSON.stringify(value);\n}\n\n/** Keeps a description readable on one comment line. */\nfunction summarise(text: string | undefined): string {\n if (text === undefined) {\n return \"\";\n }\n const single = text.replace(/\\s+/g, \" \").trim();\n return single.length > 96 ? `${single.slice(0, 93)}...` : single;\n}\n\nfunction draftTool(server: string, tool: Tool): string {\n const match = `${server}.${tool.name}`;\n const lines: string[] = [];\n const description = summarise(tool.description);\n if (description !== \"\") {\n lines.push(` # ${description}`);\n }\n\n // A server's own readOnlyHint is the one claim worth taking at face value:\n // it is the server saying it does not write. Everything else is a hint about\n // intent, not a guarantee, and D4 says an unproven tool is irreversible.\n if (tool.annotations?.readOnlyHint === true) {\n lines.push(` # classified readonly from the server's readOnlyHint; verify it before relying on it.`);\n lines.push(` - match: ${quote(match)}`);\n lines.push(` class: readonly`);\n return lines.join(\"\\n\");\n }\n\n lines.push(` # TODO: this is gated on every call until you describe how to undo it.`);\n lines.push(` # reversible needs a snapshot (a pre-read) and an inverse.`);\n lines.push(` # compensable needs an inverse only, usually built from $result.`);\n lines.push(` # irreversible is correct when neither exists; leave gate: always.`);\n lines.push(` - match: ${quote(match)}`);\n lines.push(` class: irreversible`);\n lines.push(` gate: always`);\n return lines.join(\"\\n\");\n}\n\n\n/** `*` stands for any run of characters that is not a dot, as in the matcher. */\nfunction patternFor(match: string): RegExp {\n const source = match\n .split(\"*\")\n .map((literal) => literal.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\"))\n .join(\"[^.]*\");\n return new RegExp(`^${source}$`);\n}\n\n/**\n * The finished policy for this server, if we ship one and it still fits.\n *\n * \"Fits\" is checked against the tools the server actually advertises rather\n * than assumed from the command line: a server that has since renamed or\n * dropped a tool would otherwise get a policy whose inverses cannot be called,\n * which is worse than a policy of TODOs because it looks done.\n */\nfunction adopt(\n known: NonNullable<ReturnType<typeof knownPolicyFor>>,\n name: string,\n tools: readonly Tool[],\n): { readonly source: string; readonly covered: number } | undefined {\n const advertised = new Set(tools.map((tool) => tool.name));\n const covered = new Set<string>();\n for (const rule of known.rules) {\n for (const needed of toolsReferencedBy(rule, known.key)) {\n if (!advertised.has(needed)) {\n return undefined;\n }\n }\n const test = patternFor(rule.match);\n for (const tool of tools) {\n if (test.test(`${known.key}.${tool.name}`)) {\n covered.add(tool.name);\n }\n }\n }\n if (covered.size === 0) {\n return undefined;\n }\n\n // Renamed to whatever this server was called here. Anchored on the quote so\n // a description mentioning the old key is left alone.\n const renamed = known.source.replaceAll(`\"${known.key}.`, `\"${name}.`);\n const missing = tools.filter((tool) => !covered.has(tool.name));\n const extra =\n missing.length === 0\n ? \"\"\n : [\n \"\",\n ` # Not mentioned by the bundled ${known.name} policy, so gated until you say otherwise.`,\n ...missing.map((tool) => draftTool(name, tool)),\n ].join(\"\\n\");\n return { source: `${renamed}${extra}`, covered: covered.size };\n}\n\n/**\n * Introspects a server and writes a starting policy for it. The draft is\n * deliberately unhelpful in one direction only: everything it cannot vouch for\n * is gated, so an unfinished manifest is annoying rather than dangerous.\n */\nexport async function draftManifest(options: DraftOptions): Promise<Draft> {\n const upstream = await connectStdioUpstream({\n name: options.name,\n command: options.command,\n args: options.args,\n stderr: \"capture\",\n });\n\n let tools: Tool[];\n try {\n const collected: Tool[] = [];\n let cursor: string | undefined;\n do {\n const page = listSchema.parse(\n await upstream.client.request(\n { method: \"tools/list\", params: cursor === undefined ? {} : { cursor } },\n z.looseObject({}),\n ),\n );\n collected.push(...page.tools);\n cursor = page.nextCursor;\n } while (cursor !== undefined);\n tools = collected;\n } catch (error: unknown) {\n throw new UpstreamError(options.name, \"tools/list\", error);\n } finally {\n await upstream.close();\n }\n\n if (tools.length === 0) {\n throw new ManifestError(`${options.name} exposes no tools, so there is no policy to write`);\n }\n\n const existing = options.existing?.trimEnd();\n if (existing !== undefined && existing.includes(`\\n ${options.name}:`)) {\n throw new ManifestError(\n `${options.name} is already declared in the manifest; remove it first or choose another name`,\n );\n }\n\n const server = [\n ` ${options.name}:`,\n ` command: ${quote(options.command)}`,\n ` args: [${options.args.map(quote).join(\", \")}]`,\n ].join(\"\\n\");\n\n const known = knownPolicyFor(options.command, options.args);\n const adopted = known === undefined ? undefined : adopt(known, options.name, tools);\n const policies =\n adopted?.source ?? tools.map((tool) => draftTool(options.name, tool)).join(\"\\n\\n\");\n\n if (existing === undefined) {\n const yaml = [\n `# Generated by synartesis init from ${options.name}'s tools/list.`,\n ...(adopted === undefined\n ? [\n `# Every tool starts gated. Working through the TODOs is the whole job:`,\n `# a tool with no inverse is one an agent cannot use unsupervised.`,\n ]\n : [\n `# ${String(adopted.covered)} of its tools were recognised, so the policy that ships`,\n `# with Synartesis for ${known?.name ?? \"this server\"} was used and checked against what this`,\n `# server actually advertises. Read it before trusting it: it is a starting`,\n `# point that happens to be finished, not a promise about your setup.`,\n ]),\n ``,\n `version: 1`,\n ``,\n `servers:`,\n server,\n ``,\n `tools:`,\n policies,\n ``,\n ].join(\"\\n\");\n return adopted === undefined || known === undefined\n ? { yaml }\n : { yaml, adopted: { server: known.name, tools: adopted.covered } };\n }\n\n const merged = mergeInto(existing, server, policies, options.name);\n return adopted === undefined || known === undefined\n ? { yaml: merged }\n : { yaml: merged, adopted: { server: known.name, tools: adopted.covered } };\n}\n\n/**\n * Textual merge rather than parse-and-reserialise: a round trip through the\n * YAML AST would strip the author's comments, which in this format carry the\n * reasoning behind every classification.\n */\nfunction mergeInto(existing: string, server: string, policies: string, name: string): string {\n const serversAt = existing.indexOf(\"\\nservers:\");\n const toolsAt = existing.indexOf(\"\\ntools:\");\n if (serversAt === -1 || toolsAt === -1 || toolsAt < serversAt) {\n throw new ManifestError(\n \"the existing manifest does not have a servers: block followed by a tools: block, so it cannot be extended automatically\",\n );\n }\n\n const head = existing.slice(0, toolsAt);\n const tail = existing.slice(toolsAt);\n return [\n head.trimEnd(),\n server,\n tail.trimEnd(),\n ``,\n ` # --- added by synartesis init for ${name} ---`,\n policies,\n ``,\n ].join(\"\\n\");\n}\n\nexport { describe };\n","import { existsSync, readFileSync } from \"node:fs\";\nimport { fileURLToPath } from \"node:url\";\n\nimport { parseManifest } from \"../manifest/load.js\";\nimport type { ToolPolicy } from \"../manifest/types.js\";\n\n/**\n * Policies that already exist, for the servers most people start with.\n *\n * Writing a snapshot and an inverse for every write a server offers is the\n * whole barrier to getting anything out of this, and for these four that work\n * is done and ships in manifests/. init was asking people to do it again from\n * scratch, fourteen TODOs at a time, against a file already in the package.\n *\n * Matched on the command line, because that is the part a person typed and can\n * see. Longest marker first: server-github must not be read as server-git.\n */\nconst KNOWN: readonly { readonly marker: string; readonly manifest: string }[] = [\n { marker: \"server-filesystem\", manifest: \"filesystem\" },\n { marker: \"server-github\", manifest: \"github\" },\n { marker: \"github-mcp-server\", manifest: \"github\" },\n { marker: \"server-memory\", manifest: \"memory\" },\n { marker: \"mcp-server-git\", manifest: \"git\" },\n { marker: \"server-git\", manifest: \"git\" },\n];\n\n/** The bundled manifests, whether running from dist/ or from src/. */\nfunction manifestsDir(): string | undefined {\n for (const up of [\"../manifests/\", \"../../manifests/\"]) {\n const candidate = fileURLToPath(new URL(up, import.meta.url));\n if (existsSync(candidate)) {\n return candidate;\n }\n }\n return undefined;\n}\n\nexport interface KnownPolicy {\n /** What the bundled file calls this server, e.g. `fs`. */\n readonly key: string;\n readonly rules: readonly ToolPolicy[];\n readonly name: string;\n /** The file's own `tools:` block, comments and all. */\n readonly source: string;\n}\n\nexport function knownPolicyFor(command: string, args: readonly string[]): KnownPolicy | undefined {\n const line = [command, ...args].join(\" \");\n const hit = KNOWN.find((entry) => line.includes(entry.marker));\n const dir = manifestsDir();\n if (hit === undefined || dir === undefined) {\n return undefined;\n }\n const path = `${dir}${hit.manifest}.yaml`;\n if (!existsSync(path)) {\n return undefined;\n }\n // A bundled policy that no longer parses must not stop init working; the\n // drafted TODOs are always a correct answer, just a slower one.\n try {\n const text = readFileSync(path, \"utf8\");\n const source = toolsBlock(text);\n const key = serverKey(text);\n if (source === undefined || key === undefined) {\n return undefined;\n }\n // Parsed with a stand-in servers block rather than the file's own. Two of\n // these read the environment -- memory wants MEMORY_FILE_PATH, github a\n // token -- and loading the real one fails when those are unset, which is\n // right for running a server and pointless for reading its tool rules.\n const rules = parseManifest(\n `version: 1\\nservers:\\n ${key}:\\n command: \"true\"\\ntools:\\n${source}\\n`,\n path,\n ).tools;\n return { key, rules, name: hit.manifest, source };\n } catch {\n return undefined;\n }\n}\n\n/**\n * The file's tools: section verbatim. Taken as text rather than re-serialised\n * from the parsed rules, because the comments are the most useful thing in\n * these files: they say why a move is gated and why an inverse reads $result\n * instead of $. Losing them would make an adopted policy harder to edit than\n * one written by hand.\n */\nfunction toolsBlock(text: string): string | undefined {\n const at = text.search(/^tools:[ \\t]*$/m);\n if (at === -1) {\n return undefined;\n }\n const body = text.slice(text.indexOf(\"\\n\", at) + 1);\n const lines: string[] = [];\n for (const line of body.split(\"\\n\")) {\n // A new top-level key ends the block.\n if (/^[^\\s#]/.test(line)) {\n break;\n }\n lines.push(line);\n }\n return lines.join(\"\\n\").replace(/\\s+$/, \"\");\n}\n\n/** The first server the file declares, which is the one its rules qualify. */\nfunction serverKey(text: string): string | undefined {\n const at = text.search(/^servers:[ \\t]*$/m);\n if (at === -1) {\n return undefined;\n }\n const body = text.slice(text.indexOf(\"\\n\", at) + 1);\n for (const line of body.split(\"\\n\")) {\n if (/^[^\\s#]/.test(line)) {\n return undefined;\n }\n const named = /^ {2}([A-Za-z0-9_-]+):[ \\t]*$/.exec(line);\n if (named?.[1] !== undefined) {\n return named[1];\n }\n }\n return undefined;\n}\n\n/** Every tool name a rule needs to exist: the one it matches, and its own calls. */\nexport function toolsReferencedBy(rule: ToolPolicy, key: string): readonly string[] {\n const local = (qualified: string | undefined): string | undefined =>\n qualified === undefined || !qualified.startsWith(`${key}.`)\n ? undefined\n : qualified.slice(key.length + 1);\n return [local(rule.snapshot?.tool), local(rule.inverse?.tool)].filter(\n (name): name is string => name !== undefined,\n );\n}\n","import { z } from \"zod\";\n\nimport { canonical } from \"../canonical.js\";\nimport { DriftConflict, RollbackHalted, describe } from \"../errors.js\";\nimport type { ActionRow, Journal } from \"../journal/journal.js\";\nimport type { Router } from \"../proxy/routing.js\";\nimport {\n observeState,\n planInverse,\n planRead,\n toPayload,\n type InversePlan,\n type StateObservation,\n} from \"../proxy/snapshot.js\";\nimport { createPolicyResolver } from \"../manifest/match.js\";\nimport { qualify, type Manifest } from \"../manifest/types.js\";\n\n/**\n * D7. Derived from the action rather than generated, so a retried rollback\n * presents the same key for the same action. It rides in `_meta`, which is\n * advisory: a server that ignores it gives no protection, which is why the\n * journal's own state transitions are the real guard against re-applying.\n */\nexport const IDEMPOTENCY_META_KEY = \"synartesis.dev/idempotency-key\";\n\nexport type StepKind =\n | \"revert\"\n | \"skip\"\n | \"already-reverted\"\n /** Known to be permanent. Not an obstacle to stop at, a fact to report. */\n | \"permanent\"\n /** Below the --to floor: deliberately left alone, and listed so you can see it. */\n | \"kept\"\n | \"halt\";\n\nexport interface RollbackStep {\n readonly seq: number;\n readonly server: string;\n readonly tool: string;\n readonly kind: StepKind;\n readonly reason: string;\n /** Whether drift could be ruled out before acting. */\n readonly verified: boolean;\n readonly plan?: InversePlan;\n /** True when the inverse came from a corrected manifest, not the journal. */\n readonly replanned?: boolean;\n}\n\nexport interface RollbackHalt {\n readonly seq: number;\n readonly reason: string;\n readonly detail: string;\n}\n\nexport interface RollbackReport {\n readonly runId: string;\n readonly status: \"rolled_back\" | \"partial\";\n readonly dryRun: boolean;\n readonly steps: readonly RollbackStep[];\n readonly halted?: RollbackHalt;\n}\n\nexport interface RollbackOptions {\n readonly journal: Journal;\n readonly router: Router;\n readonly runId: string;\n /** Lowest sequence to undo. Sequences below it are left in place. */\n readonly toSeq?: number;\n readonly dryRun?: boolean;\n /**\n * Re-resolve each inverse from this manifest instead of using the one\n * recorded at capture time. For recovering from a policy that was wrong when\n * the run happened: the captured pre-state and result are replayed through\n * the corrected template, so no upstream state is re-read and D5 still holds.\n */\n readonly replanWith?: Manifest;\n readonly signal?: AbortSignal;\n}\n\nconst inversePlan = z.object({\n server: z.string(),\n tool: z.string(),\n args: z.record(z.string(), z.unknown()),\n});\n\nconst observation = z.union([\n z.object({ present: z.literal(true), value: z.unknown() }),\n z.object({ present: z.literal(false) }),\n]);\n\nconst toolResult = z.looseObject({ isError: z.boolean().default(false) });\n\nfunction sameState(a: unknown, b: unknown): boolean {\n return canonical(a) === canonical(b);\n}\n\ninterface Decision {\n readonly kind: StepKind;\n readonly reason: string;\n readonly verified: boolean;\n}\n\n/**\n * Decides what to do with one action without touching any upstream. Statuses\n * that mean \"never applied\" are skipped; statuses that mean \"we cannot know\"\n * halt, because continuing past them produces a state that is neither the\n * before nor the after (D6).\n */\nfunction classify(action: ActionRow, replanning: boolean): Decision | undefined {\n switch (action.status) {\n case \"rolled_back\":\n return { kind: \"already-reverted\", reason: \"already rolled back\", verified: true };\n case \"failed\":\n case \"denied\":\n return { kind: \"skip\", reason: `never applied (${action.status})`, verified: true };\n case \"pending\":\n return {\n kind: \"halt\",\n reason: \"outcome unknown: the process died mid-call, so whether this applied cannot be determined\",\n verified: false,\n };\n case \"gated\":\n return { kind: \"skip\", reason: \"never applied (awaiting approval)\", verified: true };\n case \"approved\":\n // Somebody said yes and the agent never made the call again, so it never\n // went out. Distinct from `pending`, where it did and we cannot say what\n // happened.\n return { kind: \"skip\", reason: \"never applied (approved, never retried)\", verified: true };\n case \"unrecoverable\":\n // With no inverse there is nothing that could be wrongly re-applied and\n // nothing for a person to decide. An earlier run having labelled it does\n // not make a permanent action any less permanent, and halting here would\n // keep a whole run stuck behind something that can never be undone.\n if (action.inverse === undefined) {\n return undefined;\n }\n // Otherwise it is genuine uncertainty. A replan is a person saying they\n // corrected the policy and want it tried again; every check still runs,\n // so real drift halts on it a second time.\n return replanning\n ? undefined\n : { kind: \"halt\", reason: \"halted here on an earlier attempt\", verified: false };\n case \"applied\":\n case \"rolling_back\":\n return undefined;\n }\n}\n\nexport async function rollback(options: RollbackOptions): Promise<RollbackReport> {\n const { journal, router, runId } = options;\n const dryRun = options.dryRun ?? false;\n const signal = options.signal ?? new AbortController().signal;\n\n const policies = options.replanWith === undefined ? undefined : createPolicyResolver(options.replanWith);\n\n /**\n * Rebuilds an action's inverse and verify read from a corrected policy,\n * using only what was already captured.\n */\n const replan = (\n action: ActionRow,\n ): { inverse?: InversePlan; verify?: InversePlan; error?: string } => {\n if (policies === undefined) {\n return {};\n }\n const policy = policies.resolve(qualify(action.server, action.tool)).policy;\n const context = {\n args: action.args,\n ...(action.snapshot === undefined ? {} : { snapshot: action.snapshot }),\n ...(action.result === undefined ? {} : { result: toPayload(action.result) }),\n };\n try {\n return {\n ...(policy.inverse === undefined ? {} : { inverse: planInverse(policy.inverse, context) }),\n ...(policy.snapshot === undefined\n ? {}\n : { verify: planRead(policy.snapshot, { args: action.args }) }),\n };\n } catch (error: unknown) {\n return { error: describe(error) };\n }\n };\n\n const all = journal.getActions(runId);\n const floor = options.toSeq;\n const inScope = [...all]\n .filter((action) => floor === undefined || action.seq >= floor)\n .sort((a, b) => b.seq - a.seq);\n\n const steps: RollbackStep[] = [];\n // Everything --to excludes, reported rather than silently dropped: choosing\n // where to stop is the whole reason for the flag, and a plan that lists only\n // what it will touch shows you every part of that decision except the part\n // you are making.\n const kept = (floor === undefined ? [] : [...all].filter((action) => action.seq < floor)).sort(\n (a, b) => b.seq - a.seq,\n );\n let halted: RollbackHalt | undefined;\n /** Something permanent was stepped over, so the run is not fully reverted. */\n let leftInPlace = false;\n\n for (const action of inScope) {\n const early = classify(action, policies !== undefined);\n if (early?.kind === \"halt\") {\n // Deliberately not written back. Every halt classify can reach was read\n // off the row's own status, so there is nothing here this rollback\n // learned. Relabelling a `pending` action as `unrecoverable` destroyed\n // the one fact that mattered about it -- that its outcome is unknown --\n // and the next attempt, seeing an unrecoverable row with no inverse,\n // stepped straight over it. Running undo twice undid more than running\n // it once, which is the last thing this command may do.\n // What it saw then, said as that. Reading the stored conflict out as\n // \"actual\" states a fact about a moment that has passed as a fact about\n // now, and after the conflict is resolved that reading is simply false.\n // The way on was --replan, which nothing said.\n const seen = action.error ?? \"\";\n const detail =\n action.status === \"unrecoverable\" && seen !== \"\"\n ? `what it saw when it halted, which may no longer hold:\\n${seen}\\n` +\n `Resolve the conflict, then run undo --replan to check it against the world as it is now.`\n : seen;\n halted = { seq: action.seq, reason: early.reason, detail };\n steps.push({ ...describeStep(action), ...early });\n break;\n }\n if (early !== undefined) {\n steps.push({ ...describeStep(action), ...early });\n continue;\n }\n\n if (action.class === \"readonly\") {\n steps.push({ ...describeStep(action), kind: \"skip\", reason: \"readonly\", verified: true });\n continue;\n }\n\n const rebuilt = replan(action);\n const parsedPlan = inversePlan.safeParse(rebuilt.inverse ?? action.inverse);\n if (!parsedPlan.success) {\n // An applied action with nothing to undo. Nothing here is uncertain: the\n // email was sent, and no amount of stopping un-sends it. Stopping only\n // decides whether everything older stays wrong as well, and when the\n // permanent action is the newest one that means undoing nothing at all.\n // So it is reported and stepped over, and the run is marked partial.\n const approved =\n action.approvedBy === undefined ? \"\" : `, approved by ${action.approvedBy}`;\n const reason =\n action.class === \"irreversible\"\n ? `cannot be undone${approved}; left in place`\n : `no usable inverse was recorded${action.error === undefined ? \"\" : `: ${action.error}`}; left in place`;\n steps.push({ ...describeStep(action), kind: \"permanent\", reason, verified: false });\n leftInPlace = true;\n continue;\n }\n const plan = parsedPlan.data;\n\n // Drift check. Only possible where a pre-read was declared, which is what\n // produced both the stored verify call and the post-state.\n const verifyRead = inversePlan.safeParse(rebuilt.verify ?? action.verify);\n const recordedPost = observation.safeParse(action.postSnapshot);\n let verified = false;\n\n if (recordedPost.success && verifyRead.success) {\n let current: StateObservation;\n try {\n current = await observeState(router, verifyRead.data, signal);\n } catch (error: unknown) {\n const reason = `could not read current state to check for drift: ${describe(error)}`;\n halted = { seq: action.seq, reason, detail: \"\" };\n steps.push({ ...describeStep(action), kind: \"halt\", reason, verified: false });\n if (!dryRun) {\n journal.markUnrecoverable(action.id, reason);\n }\n break;\n }\n\n if (sameState(current, recordedPost.data)) {\n verified = true;\n } else if (sameState(current, intendedAfterInverse(action))) {\n // The inverse has already taken effect, whether by an interrupted\n // rollback or by someone doing it by hand.\n steps.push({\n ...describeStep(action),\n kind: \"already-reverted\",\n reason: \"the resource is already in the state this inverse would produce\",\n verified: true,\n plan,\n });\n if (!dryRun) {\n journal.markRolledBack(action.id);\n }\n continue;\n } else {\n const conflict = new DriftConflict(action.seq, recordedPost.data, current);\n halted = { seq: action.seq, reason: \"drift detected\", detail: conflict.message };\n steps.push({\n ...describeStep(action),\n kind: \"halt\",\n reason: \"drift detected\",\n verified: false,\n plan,\n });\n if (!dryRun) {\n journal.markUnrecoverable(action.id, conflict.message);\n }\n break;\n }\n }\n\n if (!verified && action.status === \"rolling_back\") {\n // An inverse was already sent for this action before something\n // interrupted us, and there is no declared read to tell us whether it\n // landed. Sending it again could double-apply, so a human decides.\n const reason =\n \"an inverse was already sent before an interruption and no pre-read is declared, so whether it applied cannot be determined\";\n halted = { seq: action.seq, reason, detail: action.error ?? \"\" };\n steps.push({ ...describeStep(action), kind: \"halt\", reason, verified: false, plan });\n if (!dryRun) {\n journal.markUnrecoverable(action.id, reason);\n }\n break;\n }\n\n steps.push({\n ...describeStep(action),\n kind: \"revert\",\n reason: verified ? \"state matches; applying inverse\" : unverifiedBecause(action),\n verified,\n plan,\n ...(rebuilt.inverse === undefined ? {} : { replanned: true }),\n });\n\n if (dryRun) {\n continue;\n }\n\n // Written before the call so a resume can tell \"possibly applied\" from\n // \"definitely not applied\", and claimed rather than announced: if this was\n // not the call that moved it out of `applied`, another rollback is already\n // working on it and sending the inverse again would apply it twice. An\n // action already in `rolling_back` is the other case -- a resume, which\n // has been checked for drift above -- and goes ahead.\n const claimed = journal.markRollingBack(action.id);\n if (!claimed && action.status === \"applied\") {\n const reason = \"another undo is already working on this action\";\n halted = { seq: action.seq, reason, detail: \"\" };\n steps[steps.length - 1] = {\n ...describeStep(action),\n kind: \"halt\",\n reason,\n verified,\n plan,\n };\n break;\n }\n const outcome = await executeInverse(router, plan, action.idempotencyKey, signal);\n\n if (outcome.ok) {\n journal.markRolledBack(action.id);\n continue;\n }\n\n const halt = new RollbackHalted(action.seq, outcome.message);\n if (outcome.rejected) {\n // Nothing was applied, so the action still needs undoing. Retrying is\n // the right move once whatever refused it is healthy again.\n journal.markInverseRejected(action.id, halt.message);\n } else {\n // The row stays in rolling_back: whether the call arrived is unknown,\n // and the next attempt resolves it by reading the current state.\n journal.markUnknownInverse(action.id, halt.message);\n }\n halted = { seq: action.seq, reason: \"the inverse failed\", detail: halt.message };\n steps[steps.length - 1] = {\n ...describeStep(action),\n kind: \"halt\",\n reason: \"the inverse failed\",\n verified,\n plan,\n };\n break;\n }\n\n for (const action of kept) {\n steps.push({\n ...describeStep(action),\n kind: \"kept\",\n reason: `below --to ${String(floor ?? 0)}, so it is left as it is`,\n verified: true,\n });\n }\n\n const completedWholeRun =\n halted === undefined && !leftInPlace && options.toSeq === undefined;\n const status = completedWholeRun ? \"rolled_back\" : \"partial\";\n if (!dryRun) {\n journal.endRun(runId, status);\n }\n\n return {\n runId,\n status,\n dryRun,\n steps,\n ...(halted === undefined ? {} : { halted }),\n };\n}\n\n/**\n * Why drift could not be ruled out. The two cases are not the same thing to\n * read at the moment you are deciding whether to let an unverified revert\n * proceed: one is a policy that never claimed it could check, the other is a\n * check that was supposed to happen and did not.\n */\nfunction unverifiedBecause(action: ActionRow): string {\n return action.verify === undefined\n ? \"no pre-read declared, so drift could not be ruled out\"\n : \"the post-state was never captured, so drift could not be ruled out\";\n}\n\nfunction describeStep(action: ActionRow): { seq: number; server: string; tool: string } {\n return { seq: action.seq, server: action.server, tool: action.tool };\n}\n\n/** The state the recorded inverse is expected to leave behind. */\nfunction intendedAfterInverse(action: ActionRow): StateObservation | undefined {\n return action.snapshot === undefined ? undefined : { present: true, value: action.snapshot };\n}\n\n/**\n * `rejected` separates the two failures that matter. A tool-level error means\n * the upstream processed the inverse and refused it, so nothing was applied.\n * Anything else means the call may never have arrived, and whether it applied\n * is unknown.\n */\ntype InverseOutcome =\n | { readonly ok: true }\n | { readonly ok: false; readonly rejected: boolean; readonly message: string };\n\nasync function executeInverse(\n router: Router,\n plan: InversePlan,\n idempotencyKey: string,\n signal: AbortSignal,\n): Promise<InverseOutcome> {\n const upstream = router.byName(plan.server);\n if (upstream === undefined) {\n return { ok: false, rejected: false, message: `server ${plan.server} is not connected` };\n }\n\n let raw: unknown;\n try {\n raw = await upstream.client.request(\n {\n method: \"tools/call\",\n params: {\n name: plan.tool,\n arguments: plan.args,\n _meta: { [IDEMPOTENCY_META_KEY]: idempotencyKey },\n },\n },\n z.looseObject({}),\n { signal },\n );\n } catch (error: unknown) {\n return { ok: false, rejected: false, message: describe(error) };\n }\n\n const parsed = toolResult.safeParse(raw);\n if (parsed.success && parsed.data.isError) {\n return {\n ok: false,\n rejected: true,\n message: `the inverse was refused: ${JSON.stringify(raw)}`,\n };\n }\n return { ok: true };\n}\n","import { existsSync } from \"node:fs\";\n\nimport { labelFor, openJournal, wasRefused, type ActionRow, type Journal } from \"./journal/journal.js\";\nimport { keysIn } from \"./keys.js\";\nimport { NOTHING_RECORDED_YET, rule, style, WORDMARK } from \"./style.js\";\n\n/**\n * A live view of the journal.\n *\n * Synartesis is not a daemon and cannot be one: an MCP client spawns a stdio\n * server itself and owns its lifetime, so nothing long-running could sit in\n * between and see those calls. What a person actually wants from a daemon is\n * the reassurance that it is there and doing something, and that does not\n * require a background process. It requires somewhere to look.\n */\n\nconst FRAMES = [\"\\u280b\", \"\\u2819\", \"\\u2839\", \"\\u2838\", \"\\u283c\", \"\\u2834\", \"\\u2826\", \"\\u2827\", \"\\u2807\", \"\\u280f\"];\n\nconst MARK: Record<string, string> = {\n readonly: \"\\u00b7\",\n reversible: \"\\u2190\",\n compensable: \"\\u2248\",\n irreversible: \"!\",\n unclassified: \"?\",\n};\n\nexport interface WatchOptions {\n readonly journalPath: string;\n readonly approveWith: string;\n readonly intervalMs?: number;\n /** Stop after this many ticks. Only tests pass it. */\n readonly maxTicks?: number;\n readonly write: (text: string) => void;\n readonly live: boolean;\n /**\n * Who a decision made from here is recorded as. Absent means the view is\n * read-only, which is what a pipe gets.\n */\n readonly decideAs?: string;\n /** Key presses. Defaults to the terminal; tests drive it directly. */\n readonly keys?: AsyncIterable<string>;\n}\n\ninterface View {\n stop: boolean;\n /** Which waiting call the keys act on. */\n cursor: number;\n notice: string;\n /** The tick the notice stops being shown at. */\n noticeUntil: number;\n}\n\n/**\n * How long a confirmation stays up, in ticks. Measured from when it was shown\n * rather than to a fixed boundary: clearing on every twenty-fourth tick meant\n * a decision made on the twenty-third was confirmed for a single frame, and\n * how long you got to read it came down to when you happened to press.\n */\nconst NOTICE_TICKS = 26;\n\nfunction line(action: ActionRow): string {\n const mark = MARK[action.class] ?? \"?\";\n const badge = `${mark} ${action.class}`.padEnd(14);\n const when = action.ts.slice(11, 19);\n const label = labelFor(action).padEnd(13);\n const status =\n action.status === \"gated\"\n ? style.strong(label)\n : wasRefused(action)\n ? style.accent(label)\n : style.quiet(label);\n return ` ${style.quiet(when)} ${style.quiet(badge)} ${status} ${action.server}.${action.tool}`;\n}\n\n/**\n * What there is to look at before the proxy has run once.\n *\n * Refusing to start was the wrong answer for this one command. Every other\n * command answers a question, and inventing an empty journal to answer it with\n * would look exactly like a real answer of \"nothing happened\". Watching is not\n * a question: the ordinary way round is to start watching, then point an agent\n * at the proxy, and the proxy is what creates the journal. A watch that will\n * not begin until something has already happened is no use at the only moment\n * anyone wants one.\n */\nfunction waitingForJournal(options: WatchOptions, tick: number): string {\n const spinner = options.live ? `${style.accent(FRAMES[tick % FRAMES.length] ?? \"\")} ` : \"\";\n return [\n \"\",\n ` ${style.plate(WORDMARK)} ${style.quiet(options.journalPath)}`,\n ` ${rule(64)}`,\n \"\",\n ` ${spinner}${style.quiet(\"no journal here yet\")}`,\n \"\",\n ...NOTHING_RECORDED_YET.map((line) => ` ${style.quiet(line)}`),\n \"\",\n ].join(\"\\n\");\n}\n\nfunction render(journal: Journal, options: WatchOptions, tick: number, view: View): string {\n const runs = journal.listRuns();\n const recent = journal.recentActions(12);\n const waiting = journal.listGated();\n const active = runs.filter((run) => run.status === \"active\").length;\n\n const out: string[] = [];\n out.push(\"\");\n out.push(` ${style.plate(WORDMARK)} ${style.quiet(options.journalPath)}`);\n out.push(` ${rule(64)}`);\n out.push(\"\");\n\n const spinner = options.live ? `${style.accent(FRAMES[tick % FRAMES.length] ?? \"\")} ` : \"\";\n out.push(\n ` ${spinner}${style.quiet(\"watching\")} ` +\n `${String(runs.length)} runs, ${String(active)} live ` +\n `${style.quiet(\"\\u00b7\")} ${String(recent.length)} recent actions ` +\n `${style.quiet(\"\\u00b7\")} ${waiting.length > 0 ? style.accent(`${String(waiting.length)} awaiting approval`) : style.quiet(\"nothing waiting\")}`,\n );\n out.push(\"\");\n\n if (recent.length === 0) {\n out.push(` ${style.quiet(\"No agent has done anything through this journal yet.\")}`);\n } else {\n for (const action of recent) {\n out.push(line(action));\n }\n }\n\n if (waiting.length > 0) {\n const at = Math.min(view.cursor, waiting.length - 1);\n out.push(\"\");\n out.push(` ${style.label(\"awaiting approval\")}`);\n waiting.forEach((action, index) => {\n // A cursor rather than a key that acts on all of them. One keystroke\n // that approves everything waiting is one keystroke away from\n // approving something nobody read.\n const here = index === at && canDecide(options);\n const mark = here ? style.accent(\"\\u276f\") : \" \";\n const name = here\n ? style.accent(`${action.server}.${action.tool}`)\n : style.quiet(`${action.server}.${action.tool}`);\n out.push(` ${mark} ${name} ${style.quiet(truncate(JSON.stringify(action.args), 56))}`);\n });\n out.push(\"\");\n out.push(\n canDecide(options)\n ? ` ${keyHint(\"a\", \"approve\")} ${keyHint(\"d\", \"deny\")} ${keyHint(\"j/k\", \"move\")} ${keyHint(\"q\", \"quit\")}`\n : ` ${style.quiet(`${options.approveWith} approve --all`)}`,\n );\n }\n\n if (view.notice !== \"\") {\n out.push(\"\");\n out.push(` ${style.accent(view.notice)}`);\n }\n\n out.push(\"\");\n return out.join(\"\\n\");\n}\n\nfunction truncate(text: string, limit: number): string {\n return text.length <= limit ? text : `${text.slice(0, limit - 3)}...`;\n}\n\nfunction keyHint(key: string, what: string): string {\n return `${style.strong(`[${key}]`)} ${style.quiet(what)}`;\n}\n\n/**\n * Deciding needs both a name to record it under and a keyboard to press. A\n * piped view is a report, and a report must not be able to approve anything.\n */\n/**\n * Node declares isTTY as a boolean and then leaves it undefined whenever there\n * is no terminal. Taking it as unknown is the only way to test the value that\n * is actually there rather than the one the types promise.\n */\nfunction isTerminal(value: unknown): boolean {\n return value === true;\n}\n\nfunction canDecide(options: WatchOptions): boolean {\n // stdout can be a terminal while stdin is not -- `synartesis watch\n // < /dev/null` -- and offering [a] approve there promises a key that can\n // never be pressed.\n const keyboard = options.keys !== undefined || isTerminal(process.stdin.isTTY);\n return options.live && options.decideAs !== undefined && keyboard;\n}\n\n/** Raw keystrokes from the terminal, as an iterable the loop below can read. */\nasync function* terminalKeys(): AsyncIterable<string> {\n const input = process.stdin;\n if (!input.isTTY) {\n return;\n }\n input.setRawMode(true);\n input.resume();\n try {\n for await (const chunk of input) {\n // The stream's iterator is untyped, so the shape is checked rather than\n // asserted: a wrong guess here would be a key nobody can press.\n const raw: unknown = chunk;\n const text =\n typeof raw === \"string\" ? raw : Buffer.isBuffer(raw) ? raw.toString(\"utf8\") : \"\";\n // Split, because a read is not a keypress: a terminal hands over\n // everything that has accumulated, so two quick presses arrive together.\n for (const key of keysIn(text)) {\n yield key;\n }\n }\n } finally {\n input.setRawMode(false);\n input.pause();\n }\n}\n\nexport async function watch(options: WatchOptions): Promise<number> {\n // Opened lazily, and only once there is something to open.\n let journal: Journal | undefined;\n const open = (): Journal | undefined => {\n if (journal === undefined && existsSync(options.journalPath)) {\n journal = openJournal(options.journalPath, { mustExist: true });\n }\n return journal;\n };\n\n const interval = options.intervalMs ?? 120;\n const clear = \"\\u001b[H\\u001b[2J\\u001b[3J\";\n // A holder, not plain locals: these are written from a signal handler and a\n // key loop, neither of which narrowing can see.\n const view: View = { stop: false, cursor: 0, notice: \"\", noticeUntil: 0 };\n let tick = 0;\n\n const frame = (tick: number): string => {\n const ready = open();\n return ready === undefined\n ? waitingForJournal(options, tick)\n : render(ready, options, tick, view);\n };\n\n /**\n * Answering from here rather than from a second terminal.\n *\n * The loop it removes is the one that actually hurts: an agent stops, you\n * notice, you switch window, you list what is waiting, you copy an id, you\n * run approve, you switch back. Six moves to say yes once, and every one of\n * them a chance to approve the wrong thing because you are working from an\n * id rather than from the call itself.\n */\n const decide = (approve: boolean): void => {\n const ready = open();\n if (ready === undefined || options.decideAs === undefined) {\n return;\n }\n const waiting = ready.listGated();\n const action = waiting[Math.min(view.cursor, waiting.length - 1)];\n if (action === undefined) {\n return;\n }\n const changed = approve\n ? ready.approve(action.id, options.decideAs)\n : ready.deny(action.id, options.decideAs, \"denied from the watch view\");\n // Approving is not the call. The agent was refused and is not waiting on\n // anything, so nothing happens until somebody asks it again -- and a view\n // that says only \"approved\" leaves you watching a screen that has already\n // done everything it is going to do.\n view.notice = !changed\n ? `${action.server}.${action.tool} was already settled`\n : approve\n ? `approved ${action.server}.${action.tool} \\u00b7 now tell the agent to try again`\n : `denied ${action.server}.${action.tool} \\u00b7 it will not go through`;\n view.noticeUntil = tick + NOTICE_TICKS;\n view.cursor = 0;\n };\n\n const press = (key: string): void => {\n switch (key) {\n case \"q\":\n case \"\\u0003\":\n // Ctrl-C does not raise a signal while the terminal is raw, so the\n // key that everyone reaches for has to be handled here or the view\n // cannot be left at all.\n view.stop = true;\n return;\n case \"a\":\n decide(true);\n return;\n case \"d\":\n decide(false);\n return;\n case \"j\":\n case \"\\u001b[B\":\n view.cursor += 1;\n return;\n case \"k\":\n case \"\\u001b[A\":\n view.cursor = Math.max(0, view.cursor - 1);\n return;\n default:\n return;\n }\n };\n\n // Read through a call rather than touched directly: the compiler narrows a\n // property once it has been tested and does not un-narrow it across a call\n // that could have changed it, so the check that actually matters -- the one\n // after a key has been pressed -- was being read as dead.\n const stopped = (): boolean => view.stop;\n\n const onSignal = (): void => {\n view.stop = true;\n };\n process.on(\"SIGINT\", onSignal);\n process.on(\"SIGTERM\", onSignal);\n\n const source = canDecide(options) ? (options.keys ?? terminalKeys()) : undefined;\n // Held rather than left inside a for-await. The loop only closes the\n // iterator when the loop itself ends, so a view that stopped for any other\n // reason -- a signal, a client going away -- left the reader sitting on a\n // terminal that was still in raw mode, with stdin still flowing. The\n // terminal never got its echo back and the process had a live handle it\n // would not let go of.\n const reader = source?.[Symbol.asyncIterator]();\n const reading =\n reader === undefined\n ? Promise.resolve()\n : (async (): Promise<void> => {\n for (;;) {\n const next = await reader.next();\n if (next.done === true || stopped()) {\n return;\n }\n press(next.value);\n if (stopped()) {\n return;\n }\n }\n })();\n\n try {\n if (!options.live) {\n // Not a terminal: print the state once and leave, so this is still\n // usable from a script without spraying escape codes into a pipe.\n options.write(`${frame(0)}\\n`);\n return 0;\n }\n\n options.write(\"\\u001b[?25l\");\n for (; !view.stop; tick += 1) {\n if (view.notice !== \"\" && tick >= view.noticeUntil) {\n view.notice = \"\";\n }\n options.write(clear + frame(tick));\n if (options.maxTicks !== undefined && tick + 1 >= options.maxTicks) {\n break;\n }\n await new Promise<void>((resolve) => setTimeout(resolve, interval));\n }\n return 0;\n } finally {\n if (options.live) {\n options.write(\"\\u001b[?25h\\n\");\n }\n process.off(\"SIGINT\", onSignal);\n process.off(\"SIGTERM\", onSignal);\n view.stop = true;\n // Asked to close, but not waited on indefinitely: a source blocked on a\n // read it will never get would otherwise hold the view open at exactly the\n // moment it is trying to leave.\n await Promise.race([\n (async (): Promise<void> => {\n await reader?.return?.(undefined);\n await reading;\n })(),\n new Promise<void>((resolve) => setTimeout(resolve, 50).unref()),\n ]);\n journal?.close();\n }\n}\n","/**\n * Splitting what a terminal actually hands over into the keys a person pressed.\n *\n * A raw terminal delivers whatever has accumulated since the last read, not one\n * keypress per event. Two quick presses arrive as one string, and a paste\n * arrives as a hundred. Matched whole, \"uy\" is neither u nor y, so both are\n * lost -- which is how confirming an undo by typing u and then y quickly did\n * nothing at all.\n */\n\n/**\n * ESC [ params final, or ESC O final. Everything a keyboard sends that is more\n * than one character is one of these two shapes; anything else beginning with\n * an escape is a lone escape, which is a key in its own right here.\n */\nconst SEQUENCE = /^\\u001b(\\[[0-9;?]*[ -\\/]*[@-~]|O[@-~])/;\n\nexport function keysIn(chunk: string): string[] {\n const keys: string[] = [];\n let at = 0;\n while (at < chunk.length) {\n const rest = chunk.slice(at);\n const sequence = rest.startsWith(\"\\u001b\") ? SEQUENCE.exec(rest) : null;\n const key = sequence?.[0] ?? rest.slice(0, 1);\n keys.push(key);\n at += key.length;\n }\n return keys;\n}\n","import { existsSync } from \"node:fs\";\n\nimport { labelFor, openJournal, wasRefused, type ActionRow, type Journal, type RunRow } from \"./journal/journal.js\";\nimport type { RollbackReport } from \"./rollback/rollback.js\";\nimport { keysIn } from \"./keys.js\";\nimport { NOTHING_RECORDED_YET, rule, style, WORDMARK } from \"./style.js\";\n\n/**\n * One screen you drive, rather than eight commands you have to remember.\n *\n * The commands are still there and still what a script uses. But a person\n * looking at what an agent just did should not have to know that runs are\n * listed by one word, opened by a second and undone by a third, nor carry an\n * id between them by hand. Everything here acts on the thing under the cursor,\n * which is the thing you are already looking at.\n */\n\nconst FRAMES = [\n \"⠋\",\n \"⠙\",\n \"⠹\",\n \"⠸\",\n \"⠼\",\n \"⠴\",\n \"⠦\",\n \"⠧\",\n \"⠇\",\n \"⠏\",\n];\n\nconst MARK: Record<string, string> = {\n readonly: \"·\",\n reversible: \"←\",\n compensable: \"≈\",\n irreversible: \"!\",\n unclassified: \"?\",\n};\n\nconst CURSOR = \"❯\";\nconst DOT = \"·\";\nconst ESC = \"\\u001b\";\n\n/** How long a confirmation stays up, in ticks, counted from when it appeared. */\nconst NOTICE_TICKS = 26;\n\nexport type Undo = (runId: string, dryRun: boolean) => Promise<RollbackReport>;\n\nexport interface ConsoleOptions {\n readonly journalPath: string;\n readonly write: (text: string) => void;\n readonly live: boolean;\n /** Who a decision made here is recorded as. */\n readonly decideAs: string;\n readonly intervalMs?: number;\n /** Terminal height. Defaults to the real one, or a conservative 24. */\n readonly rows?: number;\n /** Stop after this many ticks. Only tests pass it. */\n readonly maxTicks?: number;\n /** Key presses. Defaults to the terminal; tests drive it directly. */\n readonly keys?: AsyncIterable<string>;\n /**\n * How an undo is actually carried out. Injected because performing one means\n * starting every server the manifest names, which a test of what the screen\n * does has no business doing.\n */\n readonly undo?: Undo;\n}\n\ntype Mode = \"runs\" | \"run\" | \"gates\";\n\ninterface Screen {\n stop: boolean;\n mode: Mode;\n cursor: number;\n openRun: string | undefined;\n /** An undo waiting on a yes. */\n confirming: string | undefined;\n busy: string | undefined;\n notice: string;\n noticeUntil: number;\n}\n\n/**\n * The rows a list may use, once the header, the footer and a little air are\n * taken out. A frame taller than the terminal scrolls its own top away, and\n * the top of a list is where the cursor starts, so the thing you are about to\n * act on is the first thing to disappear.\n */\nfunction roomFor(options: ConsoleOptions): number {\n const rows = options.rows ?? rowsOf(process.stdout.rows) ?? 24;\n return Math.max(3, rows - 11);\n}\n\n/**\n * A window of a long list, moved so the cursor is always inside it, with a\n * count of what is out of sight in either direction.\n */\nfunction windowed(lines: readonly string[], at: number, room: number): string[] {\n if (lines.length <= room) {\n return [...lines];\n }\n const start = Math.max(0, Math.min(at - Math.floor(room / 2), lines.length - room));\n const shown = lines.slice(start, start + room);\n const above = start;\n const below = lines.length - (start + room);\n return [\n ...(above === 0 ? [] : [` ${style.quiet(`${String(above)} more above`)}`]),\n ...shown.slice(above === 0 ? 0 : 1, below === 0 ? undefined : -1),\n ...(below === 0 ? [] : [` ${style.quiet(`${String(below)} more below`)}`]),\n ];\n}\n\nfunction truncate(text: string, limit: number): string {\n return text.length <= limit ? text : `${text.slice(0, limit - 3)}...`;\n}\n\nfunction keyHint(key: string, what: string): string {\n return `${style.strong(`[${key}]`)} ${style.quiet(what)}`;\n}\n\n/**\n * Node declares isTTY as a boolean and then leaves it undefined whenever there\n * is no terminal. Taking it as unknown is the only way to test the value that\n * is actually there rather than the one the types promise.\n */\nfunction isTerminal(value: unknown): boolean {\n return value === true;\n}\n\n/** The same for rows, which Node declares a number and leaves undefined. */\nfunction rowsOf(value: unknown): number | undefined {\n return typeof value === \"number\" && Number.isFinite(value) && value > 0 ? value : undefined;\n}\n\nfunction canPress(options: ConsoleOptions): boolean {\n return options.live && (options.keys !== undefined || isTerminal(process.stdin.isTTY));\n}\n\nfunction modeLabel(screen: Screen): string {\n switch (screen.mode) {\n case \"runs\":\n return \"everything an agent has done through this journal\";\n case \"run\":\n return \"one run, in the order it happened\";\n case \"gates\":\n return \"held until a person decides\";\n }\n}\n\nfunction header(options: ConsoleOptions, screen: Screen, tick: number): string[] {\n const spinner = options.live ? `${style.accent(FRAMES[tick % FRAMES.length] ?? \"\")} ` : \"\";\n return [\n \"\",\n ` ${style.plate(WORDMARK)} ${style.quiet(options.journalPath)}`,\n ` ${rule(70)}`,\n \"\",\n ` ${spinner}${style.quiet(screen.busy ?? modeLabel(screen))}`,\n \"\",\n ];\n}\n\nfunction runsView(journal: Journal, screen: Screen, options: ConsoleOptions): string[] {\n const runs = [...journal.listRuns()].reverse();\n if (runs.length === 0) {\n return [\n ` ${style.quiet(\"No agent has done anything through this journal yet.\")}`,\n \"\",\n ` ${style.quiet(\"A run appears the first time one calls a tool through the proxy.\")}`,\n ];\n }\n\n const at = Math.min(screen.cursor, runs.length - 1);\n return runs.map((run, index) => {\n const actions = journal.getActions(run.id);\n const held = actions.filter((action) => action.status === \"gated\").length;\n const here = index === at && canPress(options);\n const name = (run.label ?? \"an agent\").padEnd(24);\n const note = held === 0 ? \"\" : ` ${style.accent(`${String(held)} awaiting approval`)}`;\n return (\n ` ${here ? style.accent(CURSOR) : \" \"} ${here ? style.accent(name) : style.strong(name)} ` +\n `${style.quiet(run.startedAt.slice(0, 19).replace(\"T\", \" \"))} ` +\n `${style.quiet(run.status.padEnd(11))} ${style.quiet(`${String(actions.length)} actions`)}${note}`\n );\n });\n}\n\nfunction statusOf(action: ActionRow): string {\n const text = labelFor(action).padEnd(13);\n if (wasRefused(action)) {\n return style.accent(text);\n }\n return action.status === \"gated\" ? style.strong(text) : style.quiet(text);\n}\n\nfunction runView(journal: Journal, screen: Screen): string[] {\n const runId = screen.openRun;\n if (runId === undefined) {\n return [` ${style.quiet(\"no run selected\")}`];\n }\n const run = journal.getRun(runId);\n const actions = journal.getActions(runId);\n const out = [\n ` ${style.label(\"run\")} ${style.strong(run?.label ?? \"an agent\")} ${style.quiet(runId.slice(0, 8))}`,\n \"\",\n ];\n if (actions.length === 0) {\n out.push(` ${style.quiet(\"nothing was recorded in this run\")}`);\n return out;\n }\n for (const action of actions) {\n const badge = `${MARK[action.class] ?? \"?\"} ${action.class}`.padEnd(14);\n out.push(\n ` ${style.quiet(String(action.seq).padStart(3))} ${style.quiet(badge)} ` +\n `${statusOf(action)} ${style.strong(`${action.server}.${action.tool}`)}`,\n );\n out.push(` ${style.quiet(truncate(JSON.stringify(action.args), 62))}`);\n if (action.inverse !== undefined) {\n out.push(` ${style.quiet(`undo: ${truncate(JSON.stringify(action.inverse), 56)}`)}`);\n }\n }\n return out;\n}\n\nfunction gatesView(journal: Journal, screen: Screen, options: ConsoleOptions): string[] {\n const waiting = journal.listGated();\n if (waiting.length === 0) {\n return [` ${style.quiet(\"Nothing is waiting for a decision.\")}`];\n }\n const at = Math.min(screen.cursor, waiting.length - 1);\n return waiting.map((action, index) => {\n const here = index === at && canPress(options);\n const name = `${action.server}.${action.tool}`;\n const shown = here ? style.accent(name) : style.quiet(name);\n const args = style.quiet(truncate(JSON.stringify(action.args), 54));\n return ` ${here ? style.accent(CURSOR) : \" \"} ${shown} ${args}`;\n });\n}\n\nfunction footer(screen: Screen, options: ConsoleOptions): string[] {\n if (!canPress(options)) {\n return [];\n }\n if (screen.confirming !== undefined) {\n return [\n \"\",\n ` ${style.accent(\"undo this whole run?\")} ${keyHint(\"y\", \"yes\")} ${keyHint(\"n\", \"no\")}`,\n ];\n }\n const keys =\n screen.mode === \"gates\"\n ? [keyHint(\"a\", \"approve\"), keyHint(\"d\", \"deny\"), keyHint(\"j/k\", \"move\"), keyHint(\"r\", \"runs\")]\n : screen.mode === \"run\"\n ? [\n keyHint(\"p\", \"preview undo\"),\n keyHint(\"u\", \"undo\"),\n keyHint(\"esc\", \"back\"),\n keyHint(\"g\", \"held\"),\n ]\n : [\n keyHint(\"enter\", \"open\"),\n keyHint(\"p\", \"preview undo\"),\n keyHint(\"u\", \"undo\"),\n keyHint(\"j/k\", \"move\"),\n keyHint(\"g\", \"held\"),\n ];\n return [\"\", ` ${keys.join(\" \")} ${keyHint(\"q\", \"quit\")}`];\n}\n\nfunction waitingForJournal(options: ConsoleOptions, tick: number): string {\n const spinner = options.live ? `${style.accent(FRAMES[tick % FRAMES.length] ?? \"\")} ` : \"\";\n return [\n \"\",\n ` ${style.plate(WORDMARK)} ${style.quiet(options.journalPath)}`,\n ` ${rule(70)}`,\n \"\",\n ` ${spinner}${style.quiet(\"no journal here yet\")}`,\n \"\",\n ...NOTHING_RECORDED_YET.map((line) => ` ${style.quiet(line)}`),\n \"\",\n ].join(\"\\n\");\n}\n\n/** Raw keystrokes from the terminal, as an iterable the loop below can read. */\nasync function* terminalKeys(): AsyncIterable<string> {\n const input = process.stdin;\n if (!isTerminal(input.isTTY)) {\n return;\n }\n input.setRawMode(true);\n input.resume();\n try {\n for await (const chunk of input) {\n // The stream's iterator is untyped, so the shape is checked rather than\n // asserted: a wrong guess here would be a key nobody can press.\n const raw: unknown = chunk;\n const text =\n typeof raw === \"string\" ? raw : Buffer.isBuffer(raw) ? raw.toString(\"utf8\") : \"\";\n // Split, because a read is not a keypress: a terminal hands over\n // everything that has accumulated, so two quick presses arrive together.\n for (const key of keysIn(text)) {\n yield key;\n }\n }\n } finally {\n input.setRawMode(false);\n input.pause();\n }\n}\n\n// Named openConsole, not console: an export called console shadows the global\n// inside its own module, so the first console.log anyone reaches for in here\n// would call this function instead.\nexport async function openConsole(options: ConsoleOptions): Promise<number> {\n let journal: Journal | undefined;\n const open = (): Journal | undefined => {\n if (journal === undefined && existsSync(options.journalPath)) {\n journal = openJournal(options.journalPath, { mustExist: true });\n }\n return journal;\n };\n\n const screen: Screen = {\n stop: false,\n mode: \"runs\",\n cursor: 0,\n openRun: undefined,\n confirming: undefined,\n busy: undefined,\n notice: \"\",\n noticeUntil: 0,\n };\n let tick = 0;\n // Read through a call rather than touched directly: the compiler narrows a\n // property once it has been tested and does not un-narrow it across a call\n // that could have changed it.\n const stopped = (): boolean => screen.stop;\n\n const say = (text: string): void => {\n screen.notice = text;\n screen.noticeUntil = tick + NOTICE_TICKS;\n };\n\n const frame = (): string => {\n const ready = open();\n if (ready === undefined) {\n return waitingForJournal(options, tick);\n }\n const room = roomFor(options);\n const body =\n screen.mode === \"runs\"\n ? windowed(runsView(ready, screen, options), screen.cursor, room)\n : screen.mode === \"run\"\n ? windowed(runView(ready, screen), 0, room)\n : windowed(gatesView(ready, screen, options), screen.cursor, room);\n const notice = screen.notice === \"\" ? [] : [\"\", ` ${style.accent(screen.notice)}`];\n return [\n ...header(options, screen, tick),\n ...body,\n ...notice,\n ...footer(screen, options),\n \"\",\n ].join(\"\\n\");\n };\n\n /** The run the cursor is on, or the one already open. */\n const selectedRun = (ready: Journal): RunRow | undefined => {\n if (screen.mode === \"run\" && screen.openRun !== undefined) {\n return ready.getRun(screen.openRun);\n }\n const runs = [...ready.listRuns()].reverse();\n return runs[Math.min(screen.cursor, runs.length - 1)];\n };\n\n const decide = (approve: boolean): void => {\n const ready = open();\n if (ready === undefined) {\n return;\n }\n const waiting = ready.listGated();\n const action = waiting[Math.min(screen.cursor, waiting.length - 1)];\n if (action === undefined) {\n return;\n }\n const changed = approve\n ? ready.approve(action.id, options.decideAs)\n : ready.deny(action.id, options.decideAs, \"denied from the console\");\n // Approving is not the call. The agent was refused and is not waiting on\n // anything, so nothing happens until somebody asks it again.\n say(\n !changed\n ? `${action.server}.${action.tool} was already settled`\n : approve\n ? `approved ${action.server}.${action.tool} ${DOT} now tell the agent to try again`\n : `denied ${action.server}.${action.tool} ${DOT} it will not go through`,\n );\n screen.cursor = 0;\n };\n\n const perform = async (runId: string, dryRun: boolean): Promise<void> => {\n if (options.undo === undefined) {\n say(\"no way to undo was configured\");\n return;\n }\n // One at a time. Undoing is slow -- it starts every server the manifest\n // names -- and a key is easy to lean on, so without this a second rollback\n // of the same run began while the first was mid-flight and both of them\n // sent the same inverses.\n if (screen.busy !== undefined) {\n say(\"still working on the last one\");\n return;\n }\n screen.busy = dryRun ? \"reading the current state...\" : \"putting it back...\";\n try {\n const report = await options.undo(runId, dryRun);\n const reverted = report.steps.filter((step) => step.kind === \"revert\").length;\n const halted = report.halted === undefined ? \"\" : ` ${DOT} halted: ${report.halted.reason}`;\n say(\n dryRun\n ? `${String(reverted)} would be reverted ${DOT} nothing changed${halted}`\n : `${report.status} ${DOT} ${String(reverted)} reverted${halted}`,\n );\n } catch (error: unknown) {\n say(error instanceof Error ? error.message : \"the undo failed\");\n } finally {\n screen.busy = undefined;\n }\n };\n\n const press = (key: string): void => {\n if (screen.confirming !== undefined) {\n const runId = screen.confirming;\n screen.confirming = undefined;\n if (key === \"y\") {\n void perform(runId, false);\n } else {\n say(\"left alone\");\n }\n return;\n }\n\n switch (key) {\n case \"q\":\n case \"\\u0003\":\n // Ctrl-C raises no signal while the terminal is raw, so the key\n // everyone reaches for has to be handled here.\n screen.stop = true;\n return;\n case \"j\":\n case `${ESC}[B`:\n screen.cursor += 1;\n return;\n case \"k\":\n case `${ESC}[A`:\n screen.cursor = Math.max(0, screen.cursor - 1);\n return;\n case \"g\":\n screen.mode = \"gates\";\n screen.cursor = 0;\n return;\n case \"r\":\n screen.mode = \"runs\";\n screen.cursor = 0;\n return;\n case ESC:\n case \"h\":\n screen.mode = \"runs\";\n screen.openRun = undefined;\n return;\n case \"\\r\":\n case \"\\n\": {\n const ready = open();\n const run = ready === undefined ? undefined : selectedRun(ready);\n if (run !== undefined) {\n screen.openRun = run.id;\n screen.mode = \"run\";\n }\n return;\n }\n case \"a\":\n if (screen.mode === \"gates\") {\n decide(true);\n }\n return;\n case \"d\":\n if (screen.mode === \"gates\") {\n decide(false);\n }\n return;\n case \"p\": {\n const ready = open();\n const run = ready === undefined ? undefined : selectedRun(ready);\n if (run !== undefined) {\n void perform(run.id, true);\n }\n return;\n }\n case \"u\": {\n if (screen.busy !== undefined) {\n say(\"still working on the last one\");\n return;\n }\n const ready = open();\n const run = ready === undefined ? undefined : selectedRun(ready);\n if (run !== undefined) {\n // Undo is the one direction that cannot itself be taken back, so it\n // is the one thing here that asks twice.\n screen.confirming = run.id;\n }\n return;\n }\n default:\n return;\n }\n };\n\n const onSignal = (): void => {\n screen.stop = true;\n };\n process.on(\"SIGINT\", onSignal);\n process.on(\"SIGTERM\", onSignal);\n\n const source = canPress(options) ? (options.keys ?? terminalKeys()) : undefined;\n // Held rather than left inside a for-await, so it can be closed however the\n // screen stops: a reader left on a raw terminal never gives the shell its\n // echo back and keeps a handle the process will not let go of.\n const reader = source?.[Symbol.asyncIterator]();\n const reading =\n reader === undefined\n ? Promise.resolve()\n : (async (): Promise<void> => {\n for (;;) {\n const next = await reader.next();\n if (next.done === true || stopped()) {\n return;\n }\n press(next.value);\n if (stopped()) {\n return;\n }\n }\n })();\n\n const interval = options.intervalMs ?? 120;\n const clear = `${ESC}[H${ESC}[2J${ESC}[3J`;\n\n try {\n if (!options.live) {\n options.write(`${frame()}\\n`);\n return 0;\n }\n options.write(`${ESC}[?25l`);\n for (; !screen.stop; tick += 1) {\n if (screen.notice !== \"\" && tick >= screen.noticeUntil) {\n screen.notice = \"\";\n }\n options.write(clear + frame());\n if (options.maxTicks !== undefined && tick + 1 >= options.maxTicks) {\n break;\n }\n await new Promise<void>((resolve) => setTimeout(resolve, interval));\n }\n return 0;\n } finally {\n if (options.live) {\n options.write(`${ESC}[?25h\\n`);\n }\n process.off(\"SIGINT\", onSignal);\n process.off(\"SIGTERM\", onSignal);\n screen.stop = true;\n // Asked to close, but not waited on indefinitely: a source blocked on a\n // read it will never get would otherwise hold the screen open at exactly\n // the moment it is trying to leave.\n await Promise.race([\n (async (): Promise<void> => {\n await reader?.return?.(undefined);\n await reading;\n })(),\n new Promise<void>((resolve) => setTimeout(resolve, 50).unref()),\n ]);\n journal?.close();\n }\n}\n"],"mappings":"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","names":["existsSync","readFileSync","fileURLToPath","line","rule","rule","z","z","existsSync","line","out","existsSync","tick","resolve","existsSync","FRAMES","MARK","NOTICE_TICKS","truncate","keyHint","isTerminal","out","waitingForJournal","line","terminalKeys","existsSync","report","resolve","existsSync","readFileSync","rest","line","note","statusOf","truncate","summarise","fileURLToPath","journalPath","journal"]}
package/dist/proxy.js.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/proxy/stdio.ts","../src/proxy/http.ts","../src/gate/gate.ts","../src/logging.ts","../src/proxy/proxy.ts","../src/gate/heuristic.ts"],"sourcesContent":["#!/usr/bin/env node\n/**\n * better-sqlite3 requires Node 22, and on Node 20 it does not fail politely:\n * it segfaults the moment a database is opened. Saying so is better than\n * letting somebody meet exit code 139.\n */\nconst NODE_MAJOR = Number(process.versions.node.split(\".\")[0]);\nif (NODE_MAJOR < 22) {\n process.stderr.write(\n `synartesis: needs Node 22 or newer, and this is ${process.version}.\\n`,\n );\n process.exit(2);\n}\n\nimport { resolve } from \"node:path\";\n\nimport { StdioServerTransport } from \"@modelcontextprotocol/sdk/server/stdio.js\";\n\nimport { serveHttp } from \"./http.js\";\n\nimport { describe } from \"../errors.js\";\nimport { DEFAULT_GATE_TIMEOUT_MS } from \"../gate/gate.js\";\nimport { cliCommandFrom } from \"../invocation.js\";\nimport { findJournal, findManifest } from \"../locate.js\";\nimport { createLogger, isLogLevel, LOG_LEVELS, type LogLevel } from \"../logging.js\";\nimport { mark } from \"../style.js\";\nimport { openJournal } from \"../journal/journal.js\";\nimport { loadManifest } from \"../manifest/load.js\";\nimport { verifyAgainstServers } from \"../manifest/verify.js\";\nimport { createProxyServer } from \"./proxy.js\";\nimport { connectStdioUpstream, type Upstream } from \"./upstream.js\";\n\n/**\n * The manifest is the configuration (D3): it already declares every server and\n * how to start it, so there is nothing left for flags to say.\n *\n * synartesis-proxy [--manifest synartesis.yaml] [--journal .synartesis/journal.db]\n * [--gate-timeout <seconds>] [--log-level <level>]\n */\ninterface Argv {\n readonly manifest: string;\n readonly journal: string;\n readonly gateTimeoutMs: number;\n /** Whether --gate-timeout was actually typed, as against defaulted. */\n readonly gateTimeoutGiven: boolean;\n /** Serve over http instead of stdio, for a client that will not start one. */\n readonly http?: {\n readonly port: number;\n readonly host: string;\n readonly token: string;\n readonly idleSeconds: number;\n };\n readonly logLevel: LogLevel;\n}\n\nfunction parseArgv(argv: readonly string[]): Argv {\n const read = (flag: string): string | undefined => {\n const at = argv.indexOf(flag);\n return at === -1 ? undefined : argv[at + 1];\n };\n const known = [\"--manifest\", \"--journal\", \"--gate-timeout\", \"--log-level\", \"--http\", \"--http-host\", \"--http-idle\", \"--token\"];\n const unknown = argv.find((token) => token.startsWith(\"--\") && !known.includes(token));\n if (unknown !== undefined) {\n throw new Error(`unknown flag ${unknown}; expected one of ${known.join(\", \")}`);\n }\n\n const rawTimeout = read(\"--gate-timeout\");\n const seconds = rawTimeout === undefined ? undefined : Number(rawTimeout);\n if (seconds !== undefined && (!Number.isFinite(seconds) || seconds <= 0)) {\n throw new Error(\"--gate-timeout needs a positive number of seconds\");\n }\n\n const level = read(\"--log-level\") ?? \"info\";\n if (!isLogLevel(level)) {\n throw new Error(`--log-level must be one of ${LOG_LEVELS.join(\", \")}`);\n }\n\n const httpPort = read(\"--http\");\n let http: Argv[\"http\"];\n if (httpPort !== undefined) {\n const port = Number(httpPort);\n if (!Number.isInteger(port) || port < 1 || port > 65535) {\n throw new Error(\"--http needs a port number\");\n }\n // Refused rather than defaulted. What is served here can write through\n // every server in the policy, and a default of \"no auth\" is the kind of\n // convenience that ends up on someone's public tunnel.\n const token = read(\"--token\") ?? process.env[\"SYNARTESIS_TOKEN\"];\n if (token === undefined || token.length < 16) {\n throw new Error(\n \"--http needs --token, or SYNARTESIS_TOKEN, of at least 16 characters: this serves write access over a socket\",\n );\n }\n const rawIdle = read(\"--http-idle\");\n const idleSeconds = rawIdle === undefined ? 1800 : Number(rawIdle);\n if (!Number.isFinite(idleSeconds) || idleSeconds <= 0) {\n throw new Error(\"--http-idle needs a positive number of seconds\");\n }\n http = { port, host: read(\"--http-host\") ?? \"127.0.0.1\", token, idleSeconds };\n }\n\n const manifest = findManifest(read(\"--manifest\"));\n return {\n manifest,\n journal: findJournal(read(\"--journal\"), manifest),\n gateTimeoutMs: seconds === undefined ? DEFAULT_GATE_TIMEOUT_MS : seconds * 1000,\n gateTimeoutGiven: seconds !== undefined,\n ...(http === undefined ? {} : { http }),\n logLevel: level,\n };\n}\n\nasync function main(): Promise<void> {\n const argv = parseArgv(process.argv.slice(2));\n const log = createLogger(argv.logLevel);\n if (argv.gateTimeoutGiven) {\n // Accepted, validated, threaded through, and read by nothing: this proxy\n // refuses a held call straight away rather than holding the connection\n // open, so there is no wait for a timeout to cut short. Saying so is\n // better than a flag that quietly does nothing, and better than rejecting\n // one that earlier versions took.\n log.warn(\n \"--gate-timeout has no effect: a held call is refused immediately and the agent makes it again once you approve\",\n );\n }\n // Only on a real terminal. A client collecting our stderr into a log file\n // wants the structured records and nothing else.\n if (process.stderr.isTTY) {\n process.stderr.write(mark());\n }\n // Loaded before anything is spawned: never start with a broken policy.\n const manifest = loadManifest(argv.manifest);\n const journal = openJournal(argv.journal);\n\n const upstreams: Upstream[] = [];\n for (const [name, spec] of Object.entries(manifest.servers)) {\n upstreams.push(\n await connectStdioUpstream({\n name,\n command: spec.command,\n args: spec.args,\n ...(spec.env === undefined ? {} : { env: spec.env }),\n }),\n );\n }\n\n // Never serve a request under a policy that calls tools the servers do not\n // have: at run time that is indistinguishable from a missing resource.\n await verifyAgainstServers(upstreams, manifest);\n\n log.info(\n {\n manifest: argv.manifest,\n journal: argv.journal,\n servers: upstreams.map((upstream) => upstream.name),\n policies: manifest.tools.length,\n },\n \"proxy ready\",\n );\n\n const build = (): ReturnType<typeof createProxyServer> =>\n createProxyServer({\n upstreams,\n manifest,\n journal,\n gateTimeoutMs: argv.gateTimeoutMs,\n logger: log,\n // Absolute, because whoever approves may be in any directory at all.\n approveHint: (actionId: string): string =>\n `${cliCommandFrom(import.meta.url)} approve ${actionId.slice(0, 8)} --journal ${resolve(argv.journal)}`,\n });\n\n if (argv.http !== undefined) {\n // One server, many sessions. Each session is a connection and a connection\n // is a run, so each gets a proxy of its own; the upstreams and the journal\n // are shared, which is what makes them one story.\n const served = await serveHttp({\n ...argv.http,\n create: build,\n log: {\n info: (data, message) => {\n log.info(data, message);\n },\n warn: (message) => {\n log.warn(message);\n },\n },\n });\n const stop = (): void => {\n void (async (): Promise<void> => {\n await served.close();\n for (const upstream of upstreams) {\n await upstream.close();\n }\n journal.close();\n process.exit(0);\n })();\n };\n process.on(\"SIGINT\", stop);\n process.on(\"SIGTERM\", stop);\n return;\n }\n\n const proxy = build();\n\n let shuttingDown = false;\n const shutdown = (code: number): void => {\n if (shuttingDown) {\n return;\n }\n shuttingDown = true;\n void (async (): Promise<void> => {\n // Let in-flight calls settle before tearing the connection down. An\n // aborted write leaves the journal unable to say whether it applied.\n await Promise.race([\n proxy.whenIdle(),\n new Promise<void>((resolve) => setTimeout(resolve, 5000).unref()),\n ]);\n await proxy.server.close();\n for (const upstream of upstreams) {\n await upstream.close();\n }\n journal.close();\n process.exit(code);\n })();\n };\n\n process.on(\"SIGINT\", () => {\n shutdown(0);\n });\n process.on(\"SIGTERM\", () => {\n shutdown(0);\n });\n\n // StdioServerTransport only reports a close that we initiate; it never\n // reacts to the parent closing the pipe. Without these listeners the proxy\n // survives its own client, holding every upstream child open until whoever\n // spawned us escalates to a signal.\n // The pipe closing means no more requests are coming, not that the ones\n // already delivered can be dropped. The transport hands only a few buffered\n // frames to handlers per turn of the event loop, so wait until the proxy has\n // been quiet for several consecutive turns rather than yielding a fixed\n // number of times, which is guesswork. The cap stops a wedged upstream from\n // holding the process open.\n const pipeClosed = (): void => {\n const giveUpAt = Date.now() + 5000;\n let quiet = 0;\n const settle = (): void => {\n quiet = proxy.busy() ? 0 : quiet + 1;\n if (quiet >= 10 || Date.now() > giveUpAt) {\n shutdown(0);\n return;\n }\n setImmediate(settle);\n };\n setImmediate(settle);\n };\n process.stdin.on(\"end\", pipeClosed);\n process.stdin.on(\"close\", pipeClosed);\n\n const inner = proxy.server.server;\n const onclose = inner.onclose;\n inner.onclose = (): void => {\n onclose?.();\n shutdown(0);\n };\n\n await proxy.server.connect(new StdioServerTransport());\n}\n\ntry {\n await main();\n} catch (error: unknown) {\n // stdout carries protocol frames only; diagnostics must not corrupt it.\n process.stderr.write(`synartesis: ${describe(error)}\\n`);\n process.exit(1);\n}\n","import { createServer, type IncomingMessage, type ServerResponse } from \"node:http\";\nimport { randomUUID, timingSafeEqual } from \"node:crypto\";\n\nimport { WebStandardStreamableHTTPServerTransport } from \"@modelcontextprotocol/sdk/server/webStandardStreamableHttp.js\";\n\nimport type { ProxyServer } from \"./proxy.js\";\n\n/**\n * Serving the proxy over HTTP, for clients that will not start a process.\n *\n * ChatGPT's connectors are the reason this exists: they take a remote https\n * endpoint and nothing else, so stdio -- which every other client speaks -- is\n * not an option there.\n *\n * What is served is an undo layer with write access to real systems, so this\n * refuses to run without a token and binds to the loopback interface unless\n * told otherwise. Reaching it from the internet is a tunnel in front of it,\n * deliberately: that is a decision someone should have to make out loud.\n */\nexport interface HttpOptions {\n readonly port: number;\n readonly host: string;\n readonly token: string;\n /** Seconds a session may sit untouched before it is closed. */\n readonly idleSeconds: number;\n /** A fresh proxy per session, since a run belongs to one client's connection. */\n readonly create: () => ProxyServer;\n readonly log: {\n info: (data: Record<string, unknown>, message: string) => void;\n warn: (message: string) => void;\n };\n}\n\nexport interface HttpServer {\n readonly port: number;\n close(): Promise<void>;\n}\n\n\n/**\n * Node's request and response, in the shapes the sdk's transport speaks.\n *\n * The node-native transport in this sdk declares onclose as a getter/setter\n * pair typed `(() => void) | undefined`, which an exactOptionalPropertyTypes\n * project cannot accept without an assertion. The web-standard one declares it\n * plainly, so it is used instead and the twenty lines below are the price.\n */\nfunction toRequest(req: IncomingMessage, body: Buffer, origin: string): Request {\n const headers = new Headers();\n for (const [key, value] of Object.entries(req.headers)) {\n if (typeof value === \"string\") {\n headers.set(key, value);\n } else if (Array.isArray(value)) {\n for (const one of value) {\n headers.append(key, one);\n }\n }\n }\n const method = req.method ?? \"GET\";\n return new Request(new URL(req.url ?? \"/\", origin), {\n method,\n headers,\n // A GET or HEAD may not carry one, and node sends an empty buffer anyway.\n ...(method === \"GET\" || method === \"HEAD\" ? {} : { body }),\n });\n}\n\nasync function writeResponse(res: ServerResponse, response: Response): Promise<void> {\n const headers: Record<string, string> = {};\n response.headers.forEach((value, key) => {\n headers[key] = value;\n });\n res.writeHead(response.status, headers);\n if (response.body === null) {\n res.end();\n return;\n }\n // Streamed rather than buffered: this is how an SSE reply stays live.\n for await (const chunk of response.body) {\n res.write(Buffer.from(chunk));\n }\n res.end();\n}\n\n/** Constant time, so a wrong token cannot be found one character at a time. */\nfunction tokenMatches(given: string, expected: string): boolean {\n const a = Buffer.from(given);\n const b = Buffer.from(expected);\n return a.length === b.length && timingSafeEqual(a, b);\n}\n\nfunction bearer(req: IncomingMessage): string | undefined {\n const header = req.headers.authorization;\n if (typeof header !== \"string\") {\n return undefined;\n }\n const match = /^Bearer[ ]+(.+)$/i.exec(header.trim());\n return match?.[1];\n}\n\nfunction refuse(res: ServerResponse, status: number, message: string): void {\n res.writeHead(status, {\n \"content-type\": \"application/json\",\n // Told the same way twice: the header is what a client acts on, the body\n // is what a person reads in a terminal.\n ...(status === 401 ? { \"www-authenticate\": 'Bearer realm=\"synartesis\"' } : {}),\n });\n res.end(JSON.stringify({ error: message }));\n}\n\nasync function readRaw(req: IncomingMessage): Promise<Buffer> {\n const chunks: Buffer[] = [];\n let size = 0;\n for await (const chunk of req) {\n const buffer = Buffer.isBuffer(chunk) ? chunk : Buffer.from(String(chunk));\n size += buffer.length;\n // A cap, because this listens on a socket: an unbounded body is a way to\n // exhaust memory without ever authenticating.\n if (size > 8 * 1024 * 1024) {\n throw new Error(\"request body too large\");\n }\n chunks.push(buffer);\n }\n return Buffer.concat(chunks);\n}\n\nfunction isInitialize(body: unknown): boolean {\n const one = (message: unknown): boolean =>\n typeof message === \"object\" &&\n message !== null &&\n \"method\" in message &&\n message.method === \"initialize\";\n return Array.isArray(body) ? body.some(one) : one(body);\n}\n\nexport async function serveHttp(options: HttpOptions): Promise<HttpServer> {\n interface Live {\n readonly transport: WebStandardStreamableHTTPServerTransport;\n readonly proxy: ProxyServer;\n lastSeen: number;\n }\n const sessions = new Map<string, Live>();\n\n // A client that drops without closing -- a network blip, a connector that\n // gives up -- used to leave its session, and the proxy and upstream handles\n // behind it, in this map for the life of the process. unref'd so an idle\n // server still exits when nothing else is holding it open.\n const sweep = setInterval(() => {\n const deadline = Date.now() - options.idleSeconds * 1000;\n for (const [id, live] of sessions) {\n if (live.lastSeen < deadline) {\n sessions.delete(id);\n options.log.info({ session: id }, \"http session swept after going quiet\");\n void live.transport.close().catch(() => undefined);\n }\n }\n }, Math.max(1000, (options.idleSeconds * 1000) / 4));\n sweep.unref();\n\n const server = createServer((req, res) => {\n void (async (): Promise<void> => {\n try {\n const token = bearer(req);\n if (token === undefined || !tokenMatches(token, options.token)) {\n // Before anything is parsed or routed. An unauthenticated request\n // must not be able to reach the proxy, the journal or an upstream.\n refuse(res, 401, \"a bearer token is required\");\n return;\n }\n if (req.url !== undefined && !req.url.startsWith(\"/mcp\")) {\n refuse(res, 404, \"the endpoint is /mcp\");\n return;\n }\n\n const origin = `http://${options.host}:${String(options.port)}`;\n const raw = await readRaw(req);\n const sessionId = req.headers[\"mcp-session-id\"];\n const existing = typeof sessionId === \"string\" ? sessions.get(sessionId) : undefined;\n if (existing !== undefined) {\n existing.lastSeen = Date.now();\n await writeResponse(res, await existing.transport.handleRequest(toRequest(req, raw, origin)));\n return;\n }\n\n const body: unknown =\n req.method === \"POST\" && raw.length > 0 ? JSON.parse(raw.toString(\"utf8\")) : undefined;\n if (req.method !== \"POST\" || !isInitialize(body)) {\n refuse(res, 400, \"no such session; start one with an initialize request\");\n return;\n }\n\n // A session is a connection, and a connection is a run: each one gets\n // its own proxy so its actions are journalled as one story.\n const proxy = options.create();\n const transport = new WebStandardStreamableHTTPServerTransport({\n sessionIdGenerator: () => randomUUID(),\n onsessioninitialized: (id: string) => {\n sessions.set(id, { transport, proxy, lastSeen: Date.now() });\n options.log.info({ session: id }, \"http session opened\");\n },\n });\n await proxy.server.connect(transport);\n transport.onclose = (): void => {\n const id = transport.sessionId;\n if (id !== undefined) {\n sessions.delete(id);\n }\n };\n await writeResponse(res, await transport.handleRequest(toRequest(req, raw, origin)));\n } catch (error: unknown) {\n const message = error instanceof Error ? error.message : String(error);\n if (!res.headersSent) {\n refuse(res, 400, message);\n } else {\n res.end();\n }\n }\n })();\n });\n\n await new Promise<void>((resolve) => {\n server.listen(options.port, options.host, resolve);\n });\n const address = server.address();\n const port = typeof address === \"object\" && address !== null ? address.port : options.port;\n\n if (options.host !== \"127.0.0.1\" && options.host !== \"localhost\") {\n options.log.warn(\n `listening on ${options.host}, which is not loopback: anything that can reach this port and holds the token can write through your servers`,\n );\n }\n options.log.info({ host: options.host, port, endpoint: \"/mcp\" }, \"http proxy ready\");\n\n return {\n port,\n close: async (): Promise<void> => {\n clearInterval(sweep);\n for (const { transport } of sessions.values()) {\n await transport.close().catch(() => undefined);\n }\n sessions.clear();\n await new Promise<void>((resolve) => {\n server.close(() => {\n resolve();\n });\n });\n },\n };\n}\n","import type { Journal } from \"../journal/journal.js\";\n\nexport interface GateRequest {\n readonly actionId: string;\n readonly runId: string;\n readonly seq: number;\n readonly server: string;\n readonly tool: string;\n readonly args: unknown;\n /** Why this is being asked about, in the words the agent is given. */\n readonly why: string;\n readonly signal: AbortSignal;\n}\n\nexport type GateDecision =\n | { readonly approved: true; readonly by: string }\n | {\n readonly approved: false;\n readonly by?: string;\n readonly reason: string;\n /**\n * Nobody has refused; the request is simply waiting for a person. The\n * agent should tell its user how to approve and then try again.\n */\n readonly awaiting?: boolean;\n };\n\nexport interface Gate {\n decide(request: GateRequest): Promise<GateDecision>;\n}\n\nexport const DEFAULT_GATE_TIMEOUT_MS = 300_000;\n\n/**\n * Records the request and refuses immediately, rather than holding the call\n * open until someone answers.\n *\n * Holding it open cannot work against a real client. Measured against Claude\n * Code: a suspended call sat for the full five minutes while the client had\n * long since reported it as failed, and any approval in that gap would have\n * sent something the agent had already said it had not sent. Every useful\n * window for a person to notice, open a terminal and decide is longer than a\n * client will wait, so the two cannot be reconciled by choosing a better\n * timeout. Refusing at once and letting the agent retry removes the conflict\n * instead of tuning it.\n */\n/**\n * `approveHint` builds the command a person on this machine would actually\n * run, journal path and all. A hint that omits an argument the caller needs is\n * an instruction that fails the moment somebody follows it.\n */\nexport type ApproveHint = (actionId: string) => string;\n\nconst DEFAULT_HINT: ApproveHint = (actionId) => `synartesis approve ${actionId.slice(0, 8)}`;\n\nexport function createRetryGate(journal: Journal, approveHint: ApproveHint = DEFAULT_HINT): Gate {\n return {\n decide(request: GateRequest): Promise<GateDecision> {\n journal.markGated(request.actionId, request.why);\n return Promise.resolve({\n approved: false,\n awaiting: true,\n reason:\n \"it is waiting for a person to approve it. Ask them to run: \" +\n approveHint(request.actionId) +\n \" --- then make this exact call again.\",\n });\n },\n };\n}\n\nexport interface JournalGateOptions {\n readonly timeoutMs?: number;\n readonly pollMs?: number;\n /** Where the operator is told that something is waiting. */\n readonly notify?: (request: GateRequest) => void;\n}\n\n/**\n * Approval arrives out of band, through the journal, rather than from a prompt\n * on stdin.\n *\n * The proxy speaks MCP over stdin and stdout: that pipe carries protocol\n * frames, so there is nothing to prompt on. A prompt written to the\n * controlling terminal would work only when one exists, which rules out every\n * desktop client. The journal is already a transactional, WAL-mode, multi\n * process store, so `synartesis approve` in any other terminal is the natural\n * channel, and it behaves identically wherever the proxy was launched from.\n */\nexport function createJournalGate(journal: Journal, options: JournalGateOptions = {}): Gate {\n const timeoutMs = options.timeoutMs ?? DEFAULT_GATE_TIMEOUT_MS;\n const pollMs = options.pollMs ?? 100;\n const notify = options.notify ?? ((): void => undefined);\n\n return {\n async decide(request: GateRequest): Promise<GateDecision> {\n journal.markGated(request.actionId, request.why);\n notify(request);\n\n const deadline = Date.now() + timeoutMs;\n for (;;) {\n const action = journal.getAction(request.actionId);\n if (action === undefined) {\n return { approved: false, reason: \"the journal entry disappeared while awaiting approval\" };\n }\n if (action.status !== \"gated\") {\n return action.status === \"denied\"\n ? {\n approved: false,\n ...(action.approvedBy === undefined ? {} : { by: action.approvedBy }),\n reason: action.error ?? \"denied\",\n }\n : { approved: true, by: action.approvedBy ?? \"unknown\" };\n }\n\n if (request.signal.aborted) {\n journal.deny(request.actionId, undefined, \"the client disconnected before a decision\");\n return { approved: false, reason: \"the client disconnected before a decision\" };\n }\n if (Date.now() >= deadline) {\n // Deny by default (3.4): silence is not consent.\n const reason = `no answer within ${String(Math.round(timeoutMs / 1000))}s, so it was denied`;\n journal.deny(request.actionId, undefined, reason);\n return { approved: false, reason };\n }\n\n await new Promise<void>((resolve) => setTimeout(resolve, pollMs).unref());\n }\n },\n };\n}\n","import pino, { type Logger } from \"pino\";\n\nexport type { Logger };\n\nexport const LOG_LEVELS = [\"trace\", \"debug\", \"info\", \"warn\", \"error\", \"silent\"] as const;\nexport type LogLevel = (typeof LOG_LEVELS)[number];\n\nexport function isLogLevel(value: string): value is LogLevel {\n return LOG_LEVELS.some((level) => level === value);\n}\n\n/**\n * Always fd 2. stdout carries MCP protocol frames, and a single stray log line\n * on it corrupts the session for every client. Synchronous so that the last\n * lines before an exit are not lost, which is exactly when they matter.\n */\nexport function createLogger(level: LogLevel): Logger {\n return pino(\n { level, base: { name: \"synartesis\" } },\n pino.destination({ dest: 2, sync: true }),\n );\n}\n","import { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport {\n CallToolRequestSchema,\n CompleteRequestSchema,\n ErrorCode,\n GetPromptRequestSchema,\n ListPromptsRequestSchema,\n ListResourceTemplatesRequestSchema,\n ListResourcesRequestSchema,\n ListToolsRequestSchema,\n McpError,\n ReadResourceRequestSchema,\n SetLevelRequestSchema,\n SubscribeRequestSchema,\n UnsubscribeRequestSchema,\n} from \"@modelcontextprotocol/sdk/types.js\";\nimport type {\n Implementation,\n Request,\n ServerCapabilities,\n} from \"@modelcontextprotocol/sdk/types.js\";\nimport { z } from \"zod\";\n\nimport { SnapshotError, UpstreamError, describe } from \"../errors.js\";\nimport { createRetryGate, type ApproveHint, type Gate } from \"../gate/gate.js\";\nimport { shouldGateOnWrite } from \"../gate/heuristic.js\";\nimport type { Journal } from \"../journal/journal.js\";\nimport type { Logger } from \"../logging.js\";\nimport {\n createPolicyResolver,\n type PolicyResolver,\n} from \"../manifest/match.js\";\nimport { qualify, type Manifest } from \"../manifest/types.js\";\nimport { createRouter, type Router } from \"./routing.js\";\nimport {\n observeState,\n planInverse,\n isDisconnected,\n mayHaveArrived,\n planRead,\n refusal,\n runRead,\n toPayload,\n type ResolvedRead,\n} from \"./snapshot.js\";\nimport type { Upstream } from \"./upstream.js\";\n\nexport interface ProxyOptions {\n readonly upstreams: readonly Upstream[];\n readonly manifest: Manifest;\n readonly journal: Journal;\n /** Defaults to out-of-band approval through the journal. */\n readonly gate?: Gate;\n readonly gateTimeoutMs?: number;\n readonly logger?: Logger;\n /** Builds the exact command a person here would run to approve an action. */\n readonly approveHint?: ApproveHint;\n}\n\nexport interface ProxyServer {\n readonly server: McpServer;\n /** Resolves with the run id once the client session is initialized. */\n readonly ready: Promise<string>;\n /** Resolves when no tool call is in flight, so shutdown can drain first. */\n whenIdle(): Promise<void>;\n /** The open run, once the session has initialized. */\n readonly runId: string | undefined;\n /** Whether any forwarded request is currently in flight. */\n busy(): boolean;\n}\n\ntype Passthrough = { [key: string]: unknown };\n\n/**\n * How long an approval stays usable. Long enough to survive a client restart\n * and a person walking away from their desk, short enough that a decision made\n * this morning cannot quietly authorise the same call tomorrow.\n */\nconst APPROVAL_WINDOW_MS = 60 * 60 * 1000;\n\n/**\n * Results are read through loose schemas. The SDK's typed schemas strip fields\n * they do not know about, which would quietly erase any metadata an upstream\n * added; only the names this proxy has to rewrite are described here.\n */\nconst PassthroughResult = z.looseObject({});\nconst ToolList = z.looseObject({\n tools: z.array(z.looseObject({ name: z.string() })),\n nextCursor: z.string().optional(),\n});\nconst PromptList = z.looseObject({\n prompts: z.array(z.looseObject({ name: z.string() })),\n nextCursor: z.string().optional(),\n});\nconst ResourceList = z.looseObject({\n resources: z.array(z.looseObject({ uri: z.string() })),\n nextCursor: z.string().optional(),\n});\nconst TemplateList = z.looseObject({\n resourceTemplates: z.array(z.looseObject({ uriTemplate: z.string() })),\n nextCursor: z.string().optional(),\n});\n\nfunction unwrap(error: McpError): string {\n const prefix = `MCP error ${String(error.code)}: `;\n return error.message.startsWith(prefix)\n ? error.message.slice(prefix.length)\n : error.message;\n}\n\nfunction rethrow(server: string, operation: string, error: unknown): never {\n if (error instanceof McpError) {\n throw new McpError(error.code, unwrap(error), error.data);\n }\n throw new UpstreamError(server, operation, error);\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\n/**\n * The client sees one logical server, so it must be told about anything any\n * upstream can do. Sub-objects are merged rather than replaced so that, for\n * example, one server's resources.subscribe survives another's resources {}.\n */\nfunction mergeCapabilities(\n all: readonly ServerCapabilities[],\n): ServerCapabilities {\n const merged: Record<string, unknown> = {};\n for (const capabilities of all) {\n for (const [key, value] of Object.entries(capabilities)) {\n const existing = merged[key];\n merged[key] =\n isRecord(existing) && isRecord(value)\n ? { ...existing, ...value }\n : value;\n }\n }\n return merged;\n}\n\nfunction identityFor(router: Router): Implementation {\n const only = router.upstreams[0];\n if (!router.prefixed && only !== undefined) {\n const upstream = only.client.getServerVersion();\n if (upstream !== undefined) {\n return upstream;\n }\n }\n // With several servers behind it there is no single identity to mirror.\n return { name: \"synartesis\", version: \"0.0.0\" };\n}\n\n/**\n * Told to the agent at connect time. Without it a gated call is just an opaque\n * failure, and the person watching has no idea why their agent stopped or what\n * they are supposed to do about it. With it, the agent explains itself.\n */\nconst SYNARTESIS_INSTRUCTIONS = [\n \"These tools are guarded by Synartesis, which records every change so it can be undone later.\",\n \"\",\n \"Some actions cannot be undone. Those are held until a person approves them, and the call\",\n \"will fail with a message beginning \\\"Synartesis is holding this call for approval\\\".\",\n \"When that happens:\",\n \" 1. Tell the user plainly that you are asking Synartesis for approval, and what for.\",\n \" 2. Give them the exact `synartesis approve ...` command from the error.\",\n \" 3. Once they say they have approved it, make the same call again. It will go through.\",\n \"Do not try to work around a held call by using a different tool to achieve the same thing.\",\n].join(\"\\n\");\n\nfunction instructionsFor(router: Router): string {\n const sections = router.upstreams\n .map((upstream) => ({\n name: upstream.name,\n text: upstream.client.getInstructions(),\n }))\n .filter(\n (section): section is { name: string; text: string } => section.text !== undefined,\n );\n\n const upstream = router.prefixed\n ? sections.map((section) => `Tools prefixed ${section.name}__:\\n${section.text}`).join(\"\\n\\n\")\n : (sections[0]?.text ?? \"\");\n\n return upstream === \"\" ? SYNARTESIS_INSTRUCTIONS : `${SYNARTESIS_INSTRUCTIONS}\\n\\n${upstream}`;\n}\n\n/** Walks every page so that aggregation across servers is never partial. */\nasync function drain<T>(\n fetch: (\n cursor: string | undefined,\n ) => Promise<{ items: T[]; nextCursor: string | undefined }>,\n): Promise<T[]> {\n const collected: T[] = [];\n let cursor: string | undefined;\n do {\n const page = await fetch(cursor);\n collected.push(...page.items);\n cursor = page.nextCursor;\n } while (cursor !== undefined);\n return collected;\n}\n\nexport function createProxyServer(options: ProxyOptions): ProxyServer {\n const { upstreams, manifest, journal } = options;\n const router = createRouter(upstreams, manifest);\n const policies: PolicyResolver = createPolicyResolver(manifest);\n\n const log = options.logger;\n\n const gate = options.gate ?? createRetryGate(journal, options.approveHint);\n\n const capabilities = mergeCapabilities(\n upstreams.map((upstream) => upstream.client.getServerCapabilities() ?? {}),\n );\n const instructions = instructionsFor(router);\n\n const wrapper = new McpServer(identityFor(router), { capabilities, instructions });\n const server = wrapper.server;\n\n let runId: string | undefined;\n let resolveReady: (id: string) => void = () => undefined;\n const ready = new Promise<string>((resolve) => {\n resolveReady = resolve;\n });\n\n let inflight = 0;\n const idle: (() => void)[] = [];\n const enter = (): void => {\n inflight += 1;\n };\n /**\n * Every decrement goes through here, including the one that parks a call at\n * the gate. A decrement that reached zero without waking the waiters would\n * leave a shutdown draining for ever against a counter that is already idle.\n */\n const leave = (): void => {\n inflight -= 1;\n if (inflight === 0) {\n for (const resolve of idle.splice(0)) {\n resolve();\n }\n }\n };\n const whenIdle = async (): Promise<void> => {\n if (inflight === 0) {\n return;\n }\n await new Promise<void>((resolve) => idle.push(resolve));\n };\n\n // A client that pipelines notifications/initialized ahead of the initialize\n // response can reach oninitialized before its own identity is recorded, so\n // the label is filled in at the first opportunity rather than once.\n let labelled = false;\n const ensureLabel = (): void => {\n if (labelled || runId === undefined) {\n return;\n }\n const name = server.getClientVersion()?.name;\n if (name !== undefined) {\n journal.setRunLabel(runId, name);\n labelled = true;\n }\n };\n\n const supports = (\n upstream: Upstream,\n key: keyof ServerCapabilities,\n ): boolean => upstream.client.getServerCapabilities()?.[key] !== undefined;\n\n const ask = async (\n upstream: Upstream,\n request: Request,\n signal: AbortSignal,\n ): Promise<Passthrough> => {\n try {\n return await upstream.client.request(request, PassthroughResult, {\n signal,\n });\n } catch (error: unknown) {\n return rethrow(upstream.name, request.method, error);\n }\n };\n\n // --- resource ownership -------------------------------------------------\n // A resource uri is an opaque identifier the client hands back verbatim, so\n // unlike a tool name it cannot be namespaced. Ownership therefore has to be\n // discovered from what each server advertises.\n let owners: Map<string, string> | undefined;\n let schemes: Map<string, string> | undefined;\n let conflict: string | undefined;\n\n const refreshResources = async (signal: AbortSignal): Promise<void> => {\n const nextOwners = new Map<string, string>();\n const nextSchemes = new Map<string, string>();\n let nextConflict: string | undefined;\n\n for (const upstream of router.upstreams) {\n if (!supports(upstream, \"resources\")) {\n continue;\n }\n const resources = await drain(async (cursor) => {\n const raw = await ask(\n upstream,\n {\n method: \"resources/list\",\n params: cursor === undefined ? {} : { cursor },\n },\n signal,\n );\n const page = ResourceList.parse(raw);\n return { items: page.resources, nextCursor: page.nextCursor };\n });\n for (const resource of resources) {\n const existing = nextOwners.get(resource.uri);\n if (existing !== undefined && existing !== upstream.name) {\n nextConflict ??= `resource ${resource.uri} is advertised by both ${existing} and ${upstream.name}; a uri cannot be namespaced, so one of them must stop exposing it`;\n }\n nextOwners.set(resource.uri, existing ?? upstream.name);\n const scheme = resource.uri.split(\":\")[0] ?? \"\";\n if (scheme !== \"\" && !nextSchemes.has(scheme)) {\n nextSchemes.set(scheme, upstream.name);\n }\n }\n\n const templates = await drain(async (cursor) => {\n const raw = await ask(\n upstream,\n {\n method: \"resources/templates/list\",\n params: cursor === undefined ? {} : { cursor },\n },\n signal,\n );\n const page = TemplateList.parse(raw);\n return { items: page.resourceTemplates, nextCursor: page.nextCursor };\n });\n for (const template of templates) {\n const scheme = template.uriTemplate.split(\":\")[0] ?? \"\";\n if (scheme !== \"\" && !nextSchemes.has(scheme)) {\n nextSchemes.set(scheme, upstream.name);\n }\n }\n }\n\n owners = nextOwners;\n schemes = nextSchemes;\n conflict = nextConflict;\n };\n\n const ensureResources = async (signal: AbortSignal): Promise<void> => {\n if (owners === undefined) {\n await refreshResources(signal);\n }\n if (conflict !== undefined) {\n throw new McpError(ErrorCode.InternalError, conflict);\n }\n };\n\n const ownerOf = async (\n uri: string,\n signal: AbortSignal,\n ): Promise<Upstream> => {\n await ensureResources(signal);\n const direct = owners?.get(uri);\n const scheme = uri.split(\":\")[0] ?? \"\";\n const name = direct ?? schemes?.get(scheme);\n const upstream = name === undefined ? undefined : router.byName(name);\n if (upstream === undefined) {\n throw new McpError(\n ErrorCode.InvalidParams,\n `no configured server provides ${uri}`,\n );\n }\n return upstream;\n };\n\n // --- handlers -----------------------------------------------------------\n if (capabilities.tools !== undefined) {\n server.setRequestHandler(\n ListToolsRequestSchema,\n async (_request, extra) => {\n const tools: Passthrough[] = [];\n for (const upstream of router.upstreams) {\n if (!supports(upstream, \"tools\")) {\n continue;\n }\n const items = await drain(async (cursor) => {\n const raw = await ask(\n upstream,\n {\n method: \"tools/list\",\n params: cursor === undefined ? {} : { cursor },\n },\n extra.signal,\n );\n const page = ToolList.parse(raw);\n return { items: page.tools, nextCursor: page.nextCursor };\n });\n for (const tool of items) {\n tools.push({\n ...tool,\n name: router.expose(upstream.name, tool.name),\n });\n }\n }\n // Pagination is flattened: a cursor would have to encode a position\n // across several independent servers, and the client gains nothing.\n return { tools };\n },\n );\n\n server.setRequestHandler(CallToolRequestSchema, async (request, extra) => {\n if (runId === undefined) {\n throw new UpstreamError(\"proxy\", \"tools/call\", \"no active run\");\n }\n // Captured: narrowing does not survive into the closures below.\n const activeRun = runId;\n ensureLabel();\n const route = router.route(request.params.name);\n if (route === undefined) {\n throw new McpError(\n ErrorCode.InvalidParams,\n `no configured server provides tool ${request.params.name}`,\n );\n }\n\n const { policy } = policies.resolve(qualify(route.upstream.name, route.tool));\n const args = request.params.arguments ?? {};\n // Counted from here, not from the forward call: the pre-read is part of\n // the action, and a shutdown that aborts it blocks a legitimate write.\n enter();\n try {\n const wantsGate =\n policy.gate === \"always\" || (policy.gate === \"on_write\" && shouldGateOnWrite(args));\n\n // A retry after an out-of-band approval reuses the row that was\n // approved, so the approval ends up on the action that actually ran\n // rather than on an abandoned twin of it.\n const granted = wantsGate\n ? journal.findApproval({\n server: route.upstream.name,\n tool: route.tool,\n args,\n notBefore: new Date(Date.now() - APPROVAL_WINDOW_MS).toISOString(),\n })\n : undefined;\n\n // An approval granted in an earlier session cannot simply be adopted:\n // the action belongs to the run happening now, or undoing this run\n // would not include it.\n const inherited =\n granted !== undefined && granted.runId !== activeRun ? granted : undefined;\n\n // Nobody has answered yet and the agent is asking again. Reusing the\n // row it is already waiting on keeps one call to one decision, which\n // is what `synartesis gates` and `approve` both assume.\n const waiting =\n granted === undefined && wantsGate\n ? journal.findGated({\n runId: activeRun,\n server: route.upstream.name,\n tool: route.tool,\n args,\n })\n : undefined;\n\n const reusable = waiting ?? (inherited === undefined ? granted : undefined);\n const pending =\n reusable === undefined\n ? journal.recordPending({\n runId: activeRun,\n server: route.upstream.name,\n tool: route.tool,\n args,\n class: policy.class,\n })\n : {\n actionId: reusable.id,\n seq: reusable.seq,\n idempotencyKey: reusable.idempotencyKey,\n };\n\n if (inherited !== undefined) {\n journal.adoptApproval(pending.actionId, inherited);\n } else if (granted !== undefined && waiting === undefined) {\n // Reusing the approved row itself: from here its outcome stops being\n // known, so it stops being `approved`.\n journal.markInFlight(granted.id);\n }\n if (granted !== undefined) {\n log?.info(\n { action: pending.actionId, by: granted.approvedBy, from: granted.runId },\n \"proceeding on a standing approval\",\n );\n }\n\n const decide = async (why: string): Promise<void> => {\n // Parked, not working: a suspended call must not hold up shutdown,\n // and the drain exists to let real work finish.\n leave();\n let decision;\n try {\n decision = await gate.decide({\n actionId: pending.actionId,\n runId: activeRun,\n seq: pending.seq,\n server: route.upstream.name,\n tool: route.tool,\n args,\n why,\n signal: extra.signal,\n });\n } finally {\n enter();\n }\n log?.info(\n { action: pending.actionId, approved: decision.approved },\n decision.approved ? \"approved\" : \"denied\",\n );\n // An approval that lands after the client has given up would send\n // a real email that the agent has already reported as not sent.\n // Nobody is waiting for the result, so the safe reading of an\n // approval nobody can hear is that it did not happen.\n if (decision.approved && extra.signal.aborted) {\n journal.settleAsDenied(\n pending.actionId,\n decision.by,\n \"approved, but the client had already stopped waiting, so it was not sent\",\n );\n throw new McpError(\n ErrorCode.InvalidRequest,\n `synartesis blocked ${request.params.name}: it was approved after the client stopped waiting, so it was not sent. Ask the agent to try again.`,\n );\n }\n if (!decision.approved) {\n if (decision.awaiting === true) {\n log?.warn(\n {\n action: pending.actionId,\n tool: `${route.upstream.name}.${route.tool}`,\n approve: options.approveHint?.(pending.actionId) ?? pending.actionId,\n },\n \"awaiting approval\",\n );\n throw new McpError(\n ErrorCode.InvalidRequest,\n `Synartesis is holding this call for approval, because ${why}. ${decision.reason}`,\n );\n }\n const who = decision.by === undefined ? \"\" : ` by ${decision.by}`;\n throw new McpError(\n ErrorCode.InvalidRequest,\n `synartesis blocked ${request.params.name}: ${why} and was denied${who}. ${decision.reason}`,\n );\n }\n };\n\n // D4/3.4: a policy gate suspends before anything is read or written, so\n // a gated action never even looks at the resource.\n // decide() throws on refusal, so getting past this means approved.\n const askedAlready = wantsGate;\n if (wantsGate && granted === undefined) {\n await decide(\"this action cannot be undone\");\n }\n\n // The pre-read happens before the write goes out, and a failure stops\n // the write entirely: a reversible action without a snapshot is\n // silently irreversible, which is worse than the action not happening.\n let snapshot: unknown;\n let verify: ResolvedRead | undefined;\n let missingPriorState: string | undefined;\n if (policy.snapshot !== undefined) {\n try {\n verify = planRead(policy.snapshot, { args });\n snapshot = await runRead(router, verify, extra.signal);\n journal.attachSnapshot(pending.actionId, snapshot);\n } catch (error: unknown) {\n const reason = describe(error);\n if (error instanceof SnapshotError && error.absent) {\n // Nothing exists here yet, so this call creates rather than\n // replaces and there is nothing to put back. It is an\n // irreversible action wearing a reversible policy. Refusing\n // outright would mean an agent could never create anything, so\n // it falls through to the same question the gate asks.\n missingPriorState = reason;\n verify = undefined;\n } else {\n journal.markFailed(pending.actionId, reason);\n log?.error(\n { seq: pending.seq, tool: route.tool, reason },\n \"write blocked: snapshot failed\",\n );\n throw new McpError(\n ErrorCode.InternalError,\n `synartesis blocked ${request.params.name}: ${reason}`,\n );\n }\n }\n }\n\n if (missingPriorState !== undefined && !askedAlready) {\n // An approval granted out of band counts here too. It was only ever\n // looked up for a policy that asked to be gated, so a write whose\n // prior state was missing -- an agent creating a file, the commonest\n // thing an agent does -- asked, was approved, and asked again, and\n // no number of approvals ever let it through. The instructions this\n // proxy sends to every agent promise the opposite.\n const standing = journal.findApproval({\n server: route.upstream.name,\n tool: route.tool,\n args,\n notBefore: new Date(Date.now() - APPROVAL_WINDOW_MS).toISOString(),\n });\n if (standing === undefined) {\n // Not \"nothing exists here\": every tool-level error on a pre-read\n // arrives here, so a file that exists and merely could not be read\n // came out as one that was not there. The person approving an\n // unundoable write was shown absence and given no way to learn\n // otherwise until after they had allowed it. Say what happened and\n // hand over the server's own words.\n await decide(\n `nothing was captured to restore, so this cannot be undone — the read said: ${missingPriorState}`,\n );\n } else {\n // Moved onto the row that actually runs, which also spends it: an\n // approval answers one call, not every call that looks like it.\n journal.adoptApproval(pending.actionId, standing);\n log?.info(\n { action: pending.actionId, by: standing.approvedBy, from: standing.runId },\n \"proceeding on a standing approval\",\n );\n }\n }\n\n const forwarded: Request = {\n method: \"tools/call\",\n params: { ...request.params, name: route.tool },\n };\n\n try {\n const result = await route.upstream.client.request(forwarded, PassthroughResult, {\n signal: extra.signal,\n });\n\n // The server understood the call and did not do it. Recording that\n // as an action would be worse than not recording it at all: an\n // inverse resolved from a refusal is a compensating call for\n // something that never happened, and undo would faithfully carry it\n // out. The agent still sees the refusal exactly as sent.\n const refused = refusal(result);\n if (refused !== undefined) {\n journal.markFailed(pending.actionId, `the upstream refused the call: ${refused}`);\n log?.debug(\n { seq: pending.seq, tool: route.tool, reason: refused },\n \"refused by the upstream\",\n );\n return result;\n }\n\n const context = { args, snapshot, result: toPayload(result) };\n const warnings: string[] = [];\n if (missingPriorState !== undefined) {\n warnings.push(\n `no prior state existed, so there is nothing to restore: ${missingPriorState}`,\n );\n }\n\n // Resolved now rather than at rollback time (D5).\n let inverse: unknown;\n if (policy.inverse !== undefined && missingPriorState === undefined) {\n try {\n inverse = planInverse(policy.inverse, context);\n } catch (error: unknown) {\n warnings.push(`inverse could not be resolved: ${describe(error)}`);\n }\n }\n\n // Best effort: the write has already applied, so a failed post-read\n // cannot undo it. Phase 4 fails closed when the post-state is\n // missing. A resource that is now absent is a captured post-state,\n // not a missing one.\n let postSnapshot: unknown;\n if (verify !== undefined) {\n try {\n postSnapshot = await observeState(router, verify, extra.signal);\n } catch (error: unknown) {\n warnings.push(`post-state could not be captured: ${describe(error)}`);\n }\n }\n\n if (warnings.length > 0) {\n log?.warn({ seq: pending.seq, tool: route.tool, warnings }, \"applied with reservations\");\n }\n log?.debug(\n { seq: pending.seq, server: route.upstream.name, tool: route.tool, class: policy.class },\n \"applied\",\n );\n journal.markApplied(pending.actionId, {\n result,\n ...(inverse === undefined ? {} : { inverse }),\n ...(verify === undefined ? {} : { verify }),\n ...(postSnapshot === undefined ? {} : { postSnapshot }),\n ...(warnings.length === 0 ? {} : { warning: warnings.join(\"; \") }),\n });\n return result;\n } catch (error: unknown) {\n const disconnected = isDisconnected(error);\n if (extra.signal.aborted || mayHaveArrived(error)) {\n // A transport that closed while a reply was still owed says\n // nothing about whether the call arrived. Recording that as failed\n // asserts it did not, and undo would then step over an action that\n // may well have applied. Having had no connection to write to at\n // all is the other case, and that one really did not happen.\n journal.markUnknown(pending.actionId, describe(error));\n } else {\n journal.markFailed(pending.actionId, describe(error));\n }\n if (disconnected && route.upstream.reconnect !== undefined) {\n // Not to retry this call -- a write must never be sent twice on a\n // guess -- but so the rest of the session is not lost with it.\n await route.upstream.reconnect().catch(() => undefined);\n }\n return rethrow(route.upstream.name, \"tools/call\", error);\n }\n } finally {\n leave();\n }\n });\n }\n\n if (capabilities.resources !== undefined) {\n server.setRequestHandler(\n ListResourcesRequestSchema,\n async (_request, extra) => {\n await refreshResources(extra.signal);\n await ensureResources(extra.signal);\n const resources: Passthrough[] = [];\n for (const upstream of router.upstreams) {\n if (!supports(upstream, \"resources\")) {\n continue;\n }\n const items = await drain(async (cursor) => {\n const raw = await ask(\n upstream,\n {\n method: \"resources/list\",\n params: cursor === undefined ? {} : { cursor },\n },\n extra.signal,\n );\n const page = ResourceList.parse(raw);\n return { items: page.resources, nextCursor: page.nextCursor };\n });\n resources.push(...items);\n }\n return { resources };\n },\n );\n\n server.setRequestHandler(\n ListResourceTemplatesRequestSchema,\n async (_request, extra) => {\n const resourceTemplates: Passthrough[] = [];\n for (const upstream of router.upstreams) {\n if (!supports(upstream, \"resources\")) {\n continue;\n }\n const items = await drain(async (cursor) => {\n const raw = await ask(\n upstream,\n {\n method: \"resources/templates/list\",\n params: cursor === undefined ? {} : { cursor },\n },\n extra.signal,\n );\n const page = TemplateList.parse(raw);\n return {\n items: page.resourceTemplates,\n nextCursor: page.nextCursor,\n };\n });\n resourceTemplates.push(...items);\n }\n return { resourceTemplates };\n },\n );\n\n server.setRequestHandler(\n ReadResourceRequestSchema,\n async (request, extra) => {\n const upstream = await ownerOf(request.params.uri, extra.signal);\n return ask(upstream, request, extra.signal);\n },\n );\n\n if (capabilities.resources.subscribe === true) {\n for (const schema of [SubscribeRequestSchema, UnsubscribeRequestSchema]) {\n server.setRequestHandler(schema, async (request, extra) => {\n const upstream = await ownerOf(request.params.uri, extra.signal);\n return ask(upstream, request, extra.signal);\n });\n }\n }\n }\n\n if (capabilities.prompts !== undefined) {\n server.setRequestHandler(\n ListPromptsRequestSchema,\n async (_request, extra) => {\n const prompts: Passthrough[] = [];\n for (const upstream of router.upstreams) {\n if (!supports(upstream, \"prompts\")) {\n continue;\n }\n const items = await drain(async (cursor) => {\n const raw = await ask(\n upstream,\n {\n method: \"prompts/list\",\n params: cursor === undefined ? {} : { cursor },\n },\n extra.signal,\n );\n const page = PromptList.parse(raw);\n return { items: page.prompts, nextCursor: page.nextCursor };\n });\n for (const prompt of items) {\n prompts.push({\n ...prompt,\n name: router.expose(upstream.name, prompt.name),\n });\n }\n }\n return { prompts };\n },\n );\n\n server.setRequestHandler(GetPromptRequestSchema, async (request, extra) => {\n const route = router.route(request.params.name);\n if (route === undefined) {\n throw new McpError(\n ErrorCode.InvalidParams,\n `no configured server provides prompt ${request.params.name}`,\n );\n }\n return ask(\n route.upstream,\n {\n method: \"prompts/get\",\n params: { ...request.params, name: route.tool },\n },\n extra.signal,\n );\n });\n }\n\n if (capabilities.completions !== undefined) {\n server.setRequestHandler(CompleteRequestSchema, async (request, extra) => {\n const reference = request.params.ref;\n if (reference.type === \"ref/prompt\") {\n const route = router.route(reference.name);\n if (route === undefined) {\n throw new McpError(\n ErrorCode.InvalidParams,\n `unknown prompt ${reference.name}`,\n );\n }\n return ask(\n route.upstream,\n {\n method: \"completion/complete\",\n params: {\n ...request.params,\n ref: { ...reference, name: route.tool },\n },\n },\n extra.signal,\n );\n }\n const upstream = await ownerOf(reference.uri, extra.signal);\n return ask(upstream, request, extra.signal);\n });\n }\n\n if (capabilities.logging !== undefined) {\n server.setRequestHandler(SetLevelRequestSchema, async (request, extra) => {\n // Broadcast: the client is configuring one logical server.\n for (const upstream of router.upstreams) {\n if (supports(upstream, \"logging\")) {\n await ask(upstream, request, extra.signal);\n }\n }\n return {};\n });\n }\n\n // --- lifecycle ----------------------------------------------------------\n let connected = false;\n for (const upstream of router.upstreams) {\n upstream.client.fallbackNotificationHandler = async (\n notification,\n ): Promise<void> => {\n if (notification.method.endsWith(\"list_changed\")) {\n owners = undefined;\n schemes = undefined;\n conflict = undefined;\n }\n if (connected) {\n await server.notification(notification);\n }\n };\n }\n\n server.oninitialized = (): void => {\n connected = true;\n const name = server.getClientVersion()?.name;\n const id = journal.beginRun(name);\n runId = id;\n labelled = name !== undefined;\n resolveReady(id);\n };\n\n const previousOnClose = server.onclose;\n server.onclose = (): void => {\n connected = false;\n if (runId !== undefined) {\n journal.endRun(runId, \"complete\");\n runId = undefined;\n }\n previousOnClose?.();\n };\n\n return {\n server: wrapper,\n ready,\n whenIdle,\n busy: (): boolean => inflight > 0,\n get runId(): string | undefined {\n return runId;\n },\n };\n}\n","/**\n * The `on_write` heuristic for tools whose destructiveness cannot be decided\n * statically, such as a raw SQL runner.\n *\n * This is a heuristic and is documented as one. It exists because the\n * alternative for `postgres.query` is to gate every SELECT, which no operator\n * would tolerate for long. Anything it cannot confidently read as a read is\n * gated (D4): failing to recognise a statement is not evidence that it is safe.\n * `always` remains the correct choice wherever certainty matters.\n */\nconst READ_ONLY = /^(select|with|show|explain|describe|desc|values|table)\\b/;\n\nfunction isReadOnlyStatement(text: string): boolean {\n const stripped = text\n .replace(/--[^\\n]*/g, \" \")\n .replace(/\\/\\*[\\s\\S]*?\\*\\//g, \" \")\n .trim();\n if (!READ_ONLY.test(stripped.toLowerCase())) {\n return false;\n }\n // More than one statement means the leading SELECT says nothing about what\n // follows it.\n return stripped.replace(/;\\s*$/, \"\").indexOf(\";\") === -1;\n}\n\nexport function shouldGateOnWrite(args: unknown): boolean {\n if (typeof args !== \"object\" || args === null) {\n return true;\n }\n const strings = Object.values(args).filter(\n (value): value is string => typeof value === \"string\",\n );\n if (strings.length === 0) {\n return true;\n }\n return !strings.every(isReadOnlyStatement);\n}\n"],"mappings":"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","names":["resolve","upstream","resolve","resolve"]}