synartesis 0.3.1 → 0.3.2
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 +25 -0
- package/README.md +0 -4
- package/dist/{chunk-COIPI27I.js → chunk-LNR5GXPG.js} +2 -2
- package/dist/{chunk-K3QIPVBY.js → chunk-WNLRMSDB.js} +66 -3
- package/dist/chunk-WNLRMSDB.js.map +1 -0
- package/dist/cli.js +2 -2
- package/dist/proxy.js +2 -2
- package/package.json +1 -1
- package/dist/chunk-K3QIPVBY.js.map +0 -1
- /package/dist/{chunk-COIPI27I.js.map → chunk-LNR5GXPG.js.map} +0 -0
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,31 @@
|
|
|
2
2
|
|
|
3
3
|
What changed, and why it mattered. Dates are release dates.
|
|
4
4
|
|
|
5
|
+
## 0.3.2 — 2026-08-30
|
|
6
|
+
|
|
7
|
+
### Fixed
|
|
8
|
+
|
|
9
|
+
- **A drift halt shows what changed, not both documents.** Halting on drift
|
|
10
|
+
printed the expected and actual contents of the resource in full. On a
|
|
11
|
+
200-line file that is two screens of escaped JSON with the one line that
|
|
12
|
+
matters buried inside, which is the same as not saying. It now trims the head
|
|
13
|
+
and tail the two sides agree on and prints only the region that differs,
|
|
14
|
+
capped at eight lines a side:
|
|
15
|
+
|
|
16
|
+
```
|
|
17
|
+
drift at sequence 4: the resource is not in the state this run left it in.
|
|
18
|
+
at line 123:
|
|
19
|
+
+ // A HUMAN FIXED THIS BY HAND.
|
|
20
|
+
0 removed, 1 added.
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
Both values are still on the row, and `synartesis show` prints them.
|
|
24
|
+
- **And it no longer crashes on a snapshot it cannot walk.** Finding the text
|
|
25
|
+
to diff, and the fallback for when there is none, both recursed — so a
|
|
26
|
+
snapshot nested a few thousand levels deep turned a drift halt into a stack
|
|
27
|
+
trace, at exactly the moment a person needs to be told their work is at risk.
|
|
28
|
+
Walked with an explicit stack now, with a node cap, and the fallback catches.
|
|
29
|
+
|
|
5
30
|
## 0.3.1 — 2026-08-30
|
|
6
31
|
|
|
7
32
|
### Fixed
|
package/README.md
CHANGED
|
@@ -282,10 +282,6 @@ than reporting an opaque failure.
|
|
|
282
282
|
|
|
283
283
|
## Real servers
|
|
284
284
|
|
|
285
|
-
If you would rather follow steps than read about it, there is a
|
|
286
|
-
[guide to running this against your own files](TESTING-ON-A-REAL-SYSTEM.md),
|
|
287
|
-
with the gate and the drift check as the two things worth testing on purpose.
|
|
288
|
-
|
|
289
285
|
Synartesis has nothing to do with email in particular. It sits on the MCP
|
|
290
286
|
protocol, so its subject is whatever the servers you have connected can do:
|
|
291
287
|
your files, your repositories, your database, your tickets, your agent's own
|
|
@@ -4,7 +4,7 @@ import {
|
|
|
4
4
|
SnapshotError,
|
|
5
5
|
UpstreamError,
|
|
6
6
|
describe
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-WNLRMSDB.js";
|
|
8
8
|
|
|
9
9
|
// src/invocation.ts
|
|
10
10
|
import { accessSync, constants } from "fs";
|
|
@@ -1479,4 +1479,4 @@ export {
|
|
|
1479
1479
|
observeState,
|
|
1480
1480
|
connectStdioUpstream
|
|
1481
1481
|
};
|
|
1482
|
-
//# sourceMappingURL=chunk-
|
|
1482
|
+
//# sourceMappingURL=chunk-LNR5GXPG.js.map
|
|
@@ -35,12 +35,75 @@ var SnapshotError = class extends SynartesisError {
|
|
|
35
35
|
code = "SNAPSHOT_ERROR";
|
|
36
36
|
absent;
|
|
37
37
|
};
|
|
38
|
+
function longestString(value) {
|
|
39
|
+
const pending = [value];
|
|
40
|
+
let best = "";
|
|
41
|
+
let visited = 0;
|
|
42
|
+
while (pending.length > 0 && visited < MAX_SNAPSHOT_NODES) {
|
|
43
|
+
const item = pending.pop();
|
|
44
|
+
visited += 1;
|
|
45
|
+
if (typeof item === "string") {
|
|
46
|
+
if (item.length > best.length) {
|
|
47
|
+
best = item;
|
|
48
|
+
}
|
|
49
|
+
} else if (Array.isArray(item)) {
|
|
50
|
+
for (const child of item) {
|
|
51
|
+
pending.push(child);
|
|
52
|
+
}
|
|
53
|
+
} else if (typeof item === "object" && item !== null) {
|
|
54
|
+
for (const child of Object.values(item)) {
|
|
55
|
+
pending.push(child);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
return best;
|
|
60
|
+
}
|
|
61
|
+
var MAX_SNAPSHOT_NODES = 5e4;
|
|
62
|
+
var DIFF_BUDGET = 8;
|
|
63
|
+
function lineDiff(before, after) {
|
|
64
|
+
const a = before.split("\n");
|
|
65
|
+
const b = after.split("\n");
|
|
66
|
+
let head = 0;
|
|
67
|
+
while (head < a.length && head < b.length && a[head] === b[head]) {
|
|
68
|
+
head += 1;
|
|
69
|
+
}
|
|
70
|
+
let tail = 0;
|
|
71
|
+
while (tail < a.length - head && tail < b.length - head && a[a.length - 1 - tail] === b[b.length - 1 - tail]) {
|
|
72
|
+
tail += 1;
|
|
73
|
+
}
|
|
74
|
+
const removed = a.slice(head, a.length - tail);
|
|
75
|
+
const added = b.slice(head, b.length - tail);
|
|
76
|
+
const show = (lines, mark) => [
|
|
77
|
+
...lines.slice(0, DIFF_BUDGET).map((line) => ` ${mark} ${line}`),
|
|
78
|
+
...lines.length > DIFF_BUDGET ? [` ${mark} ... ${String(lines.length - DIFF_BUDGET)} more`] : []
|
|
79
|
+
];
|
|
80
|
+
return [
|
|
81
|
+
` at line ${String(head + 1)}:`,
|
|
82
|
+
...show(removed, "-"),
|
|
83
|
+
...show(added, "+"),
|
|
84
|
+
` ${String(removed.length)} removed, ${String(added.length)} added.`
|
|
85
|
+
].join("\n");
|
|
86
|
+
}
|
|
87
|
+
function brief(value) {
|
|
88
|
+
if (value === void 0) {
|
|
89
|
+
return "undefined";
|
|
90
|
+
}
|
|
91
|
+
try {
|
|
92
|
+
const text = JSON.stringify(value);
|
|
93
|
+
return text.length <= 160 ? text : `${text.slice(0, 157)}...`;
|
|
94
|
+
} catch {
|
|
95
|
+
return "(a value too deeply nested to print)";
|
|
96
|
+
}
|
|
97
|
+
}
|
|
38
98
|
var DriftConflict = class extends SynartesisError {
|
|
39
99
|
constructor(seq, expected, actual) {
|
|
100
|
+
const before = longestString(expected);
|
|
101
|
+
const after = longestString(actual);
|
|
102
|
+
const body = before !== "" && after !== "" && before !== after ? lineDiff(before, after) : ` expected: ${brief(expected)}
|
|
103
|
+
actual: ${brief(actual)}`;
|
|
40
104
|
super(
|
|
41
105
|
`drift at sequence ${String(seq)}: the resource is not in the state this run left it in.
|
|
42
|
-
|
|
43
|
-
actual: ${JSON.stringify(actual)}`
|
|
106
|
+
${body}`
|
|
44
107
|
);
|
|
45
108
|
this.seq = seq;
|
|
46
109
|
this.expected = expected;
|
|
@@ -82,4 +145,4 @@ export {
|
|
|
82
145
|
JournalError,
|
|
83
146
|
describe
|
|
84
147
|
};
|
|
85
|
-
//# sourceMappingURL=chunk-
|
|
148
|
+
//# sourceMappingURL=chunk-WNLRMSDB.js.map
|
|
@@ -0,0 +1 @@
|
|
|
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":";AAIO,IAAe,kBAAf,cAAuC,MAAM;AAAA,EAGlD,YAAY,SAAiB,SAA+B;AAC1D,UAAM,SAAS,OAAO;AACtB,SAAK,OAAO,WAAW;AAAA,EACzB;AACF;AAaO,IAAM,gBAAN,cAA4B,gBAAgB;AAAA,EAGjD,YACE,SACS,UACT;AACA;AAAA,MACE,aAAa,SACT,UACA,GAAG,SAAS,IAAI,IAAI,OAAO,SAAS,IAAI,CAAC,IAAI,OAAO,SAAS,MAAM,CAAC,KAAK,OAAO;AAAA,IACtF;AANS;AAAA,EAOX;AAAA,EAPW;AAAA,EAJF,OAAO;AAYlB;AAGO,IAAM,gBAAN,cAA4B,gBAAgB;AAAA,EAGjD,YACW,QACA,WACT,OACA;AACA,UAAM,YAAY,MAAM,kBAAkB,SAAS,KAAK,SAAS,KAAK,CAAC,IAAI,EAAE,MAAM,CAAC;AAJ3E;AACA;AAAA,EAIX;AAAA,EALW;AAAA,EACA;AAAA,EAJF,OAAO;AASlB;AAOO,IAAM,gBAAN,cAA4B,gBAAgB;AAAA,EAGjD,YACW,MACT,QACA,SACA;AACA,UAAM,gBAAgB,IAAI,YAAY,MAAM,IAAI,OAAO;AAJ9C;AAUT,SAAK,SAAS,SAAS,UAAU;AAAA,EACnC;AAAA,EAXW;AAAA,EAHF,OAAO;AAAA,EAgBP;AACX;AASA,SAAS,cAAc,OAAwB;AAM7C,QAAM,UAAqB,CAAC,KAAK;AACjC,MAAI,OAAO;AACX,MAAI,UAAU;AAEd,SAAO,QAAQ,SAAS,KAAK,UAAU,oBAAoB;AACzD,UAAM,OAAO,QAAQ,IAAI;AACzB,eAAW;AAEX,QAAI,OAAO,SAAS,UAAU;AAC5B,UAAI,KAAK,SAAS,KAAK,QAAQ;AAC7B,eAAO;AAAA,MACT;AAAA,IACF,WAAW,MAAM,QAAQ,IAAI,GAAG;AAE9B,iBAAW,SAAS,MAAM;AACxB,gBAAQ,KAAK,KAAK;AAAA,MACpB;AAAA,IACF,WAAW,OAAO,SAAS,YAAY,SAAS,MAAM;AACpD,iBAAW,SAAS,OAAO,OAAO,IAAI,GAAG;AACvC,gBAAQ,KAAK,KAAK;AAAA,MACpB;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AACT;AAOA,IAAM,qBAAqB;AAG3B,IAAM,cAAc;AAMpB,SAAS,SAAS,QAAgB,OAAuB;AACvD,QAAM,IAAI,OAAO,MAAM,IAAI;AAC3B,QAAM,IAAI,MAAM,MAAM,IAAI;AAE1B,MAAI,OAAO;AACX,SAAO,OAAO,EAAE,UAAU,OAAO,EAAE,UAAU,EAAE,IAAI,MAAM,EAAE,IAAI,GAAG;AAChE,YAAQ;AAAA,EACV;AACA,MAAI,OAAO;AACX,SACE,OAAO,EAAE,SAAS,QAClB,OAAO,EAAE,SAAS,QAClB,EAAE,EAAE,SAAS,IAAI,IAAI,MAAM,EAAE,EAAE,SAAS,IAAI,IAAI,GAChD;AACA,YAAQ;AAAA,EACV;AAEA,QAAM,UAAU,EAAE,MAAM,MAAM,EAAE,SAAS,IAAI;AAC7C,QAAM,QAAQ,EAAE,MAAM,MAAM,EAAE,SAAS,IAAI;AAC3C,QAAM,OAAO,CAAC,OAA0B,SAA2B;AAAA,IACjE,GAAG,MAAM,MAAM,GAAG,WAAW,EAAE,IAAI,CAAC,SAAS,KAAK,IAAI,IAAI,IAAI,EAAE;AAAA,IAChE,GAAI,MAAM,SAAS,cACf,CAAC,KAAK,IAAI,QAAQ,OAAO,MAAM,SAAS,WAAW,CAAC,OAAO,IAC3D,CAAC;AAAA,EACP;AAEA,SAAO;AAAA,IACL,aAAa,OAAO,OAAO,CAAC,CAAC;AAAA,IAC7B,GAAG,KAAK,SAAS,GAAG;AAAA,IACpB,GAAG,KAAK,OAAO,GAAG;AAAA,IAClB,KAAK,OAAO,QAAQ,MAAM,CAAC,aAAa,OAAO,MAAM,MAAM,CAAC;AAAA,EAC9D,EAAE,KAAK,IAAI;AACb;AAGA,SAAS,MAAM,OAAwB;AAIrC,MAAI,UAAU,QAAW;AACvB,WAAO;AAAA,EACT;AACA,MAAI;AACF,UAAM,OAAO,KAAK,UAAU,KAAK;AACjC,WAAO,KAAK,UAAU,MAAM,OAAO,GAAG,KAAK,MAAM,GAAG,GAAG,CAAC;AAAA,EAC1D,QAAQ;AAIN,WAAO;AAAA,EACT;AACF;AAYO,IAAM,gBAAN,cAA4B,gBAAgB;AAAA,EAGjD,YACW,KACA,UACA,QACT;AACA,UAAM,SAAS,cAAc,QAAQ;AACrC,UAAM,QAAQ,cAAc,MAAM;AAIlC,UAAM,OACJ,WAAW,MAAM,UAAU,MAAM,WAAW,QACxC,SAAS,QAAQ,KAAK,IACtB,eAAe,MAAM,QAAQ,CAAC;AAAA,cAAiB,MAAM,MAAM,CAAC;AAElE;AAAA,MACE,qBAAqB,OAAO,GAAG,CAAC;AAAA,EAA4D,IAAI;AAAA,IAClG;AAhBS;AACA;AACA;AAAA,EAeX;AAAA,EAjBW;AAAA,EACA;AAAA,EACA;AAAA,EALF,OAAO;AAqBlB;AAMO,IAAM,iBAAN,cAA6B,gBAAgB;AAAA,EAGlD,YACW,KACT,QACA,SACA;AACA,UAAM,+BAA+B,OAAO,GAAG,CAAC,KAAK,MAAM,IAAI,OAAO;AAJ7D;AAAA,EAKX;AAAA,EALW;AAAA,EAHF,OAAO;AASlB;AAOO,IAAM,eAAN,cAA2B,gBAAgB;AAAA,EACvC,OAAO;AAAA,EAEhB,YAAY,WAAmB,OAAgB;AAC7C,UAAM,WAAW,SAAS,YAAY,SAAS,KAAK,CAAC,IAAI,EAAE,MAAM,CAAC;AAAA,EACpE;AACF;AAEO,SAAS,SAAS,OAAwB;AAC/C,MAAI,iBAAiB,OAAO;AAC1B,WAAO,MAAM;AAAA,EACf;AACA,SAAO,OAAO,UAAU,WAAW,QAAQ,KAAK,UAAU,KAAK;AACjE;","names":[]}
|
package/dist/cli.js
CHANGED
|
@@ -24,7 +24,7 @@ import {
|
|
|
24
24
|
toPayload,
|
|
25
25
|
verifyAgainstServers,
|
|
26
26
|
wasRefused
|
|
27
|
-
} from "./chunk-
|
|
27
|
+
} from "./chunk-LNR5GXPG.js";
|
|
28
28
|
import {
|
|
29
29
|
DriftConflict,
|
|
30
30
|
ManifestError,
|
|
@@ -32,7 +32,7 @@ import {
|
|
|
32
32
|
SynartesisError,
|
|
33
33
|
UpstreamError,
|
|
34
34
|
describe
|
|
35
|
-
} from "./chunk-
|
|
35
|
+
} from "./chunk-WNLRMSDB.js";
|
|
36
36
|
|
|
37
37
|
// src/cli.ts
|
|
38
38
|
import { existsSync as existsSync4, mkdirSync, readFileSync as readFileSync2, statSync, writeFileSync } from "fs";
|
package/dist/proxy.js
CHANGED
|
@@ -19,12 +19,12 @@ import {
|
|
|
19
19
|
runRead,
|
|
20
20
|
toPayload,
|
|
21
21
|
verifyAgainstServers
|
|
22
|
-
} from "./chunk-
|
|
22
|
+
} from "./chunk-LNR5GXPG.js";
|
|
23
23
|
import {
|
|
24
24
|
SnapshotError,
|
|
25
25
|
UpstreamError,
|
|
26
26
|
describe
|
|
27
|
-
} from "./chunk-
|
|
27
|
+
} from "./chunk-WNLRMSDB.js";
|
|
28
28
|
|
|
29
29
|
// src/proxy/stdio.ts
|
|
30
30
|
import { resolve } from "path";
|
package/package.json
CHANGED
|
@@ -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 resource changed after the agent touched it. Writing the old value back\n * would silently destroy whatever happened in between, so both values are\n * carried here for a human to judge.\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 super(\n `drift at sequence ${String(seq)}: the resource is not in the state this run left it in.\\n` +\n ` expected: ${JSON.stringify(expected)}\\n` +\n ` actual: ${JSON.stringify(actual)}`,\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":";AAIO,IAAe,kBAAf,cAAuC,MAAM;AAAA,EAGlD,YAAY,SAAiB,SAA+B;AAC1D,UAAM,SAAS,OAAO;AACtB,SAAK,OAAO,WAAW;AAAA,EACzB;AACF;AAaO,IAAM,gBAAN,cAA4B,gBAAgB;AAAA,EAGjD,YACE,SACS,UACT;AACA;AAAA,MACE,aAAa,SACT,UACA,GAAG,SAAS,IAAI,IAAI,OAAO,SAAS,IAAI,CAAC,IAAI,OAAO,SAAS,MAAM,CAAC,KAAK,OAAO;AAAA,IACtF;AANS;AAAA,EAOX;AAAA,EAPW;AAAA,EAJF,OAAO;AAYlB;AAGO,IAAM,gBAAN,cAA4B,gBAAgB;AAAA,EAGjD,YACW,QACA,WACT,OACA;AACA,UAAM,YAAY,MAAM,kBAAkB,SAAS,KAAK,SAAS,KAAK,CAAC,IAAI,EAAE,MAAM,CAAC;AAJ3E;AACA;AAAA,EAIX;AAAA,EALW;AAAA,EACA;AAAA,EAJF,OAAO;AASlB;AAOO,IAAM,gBAAN,cAA4B,gBAAgB;AAAA,EAGjD,YACW,MACT,QACA,SACA;AACA,UAAM,gBAAgB,IAAI,YAAY,MAAM,IAAI,OAAO;AAJ9C;AAUT,SAAK,SAAS,SAAS,UAAU;AAAA,EACnC;AAAA,EAXW;AAAA,EAHF,OAAO;AAAA,EAgBP;AACX;AAOO,IAAM,gBAAN,cAA4B,gBAAgB;AAAA,EAGjD,YACW,KACA,UACA,QACT;AACA;AAAA,MACE,qBAAqB,OAAO,GAAG,CAAC;AAAA,cACf,KAAK,UAAU,QAAQ,CAAC;AAAA,cACxB,KAAK,UAAU,MAAM,CAAC;AAAA,IACzC;AARS;AACA;AACA;AAAA,EAOX;AAAA,EATW;AAAA,EACA;AAAA,EACA;AAAA,EALF,OAAO;AAalB;AAMO,IAAM,iBAAN,cAA6B,gBAAgB;AAAA,EAGlD,YACW,KACT,QACA,SACA;AACA,UAAM,+BAA+B,OAAO,GAAG,CAAC,KAAK,MAAM,IAAI,OAAO;AAJ7D;AAAA,EAKX;AAAA,EALW;AAAA,EAHF,OAAO;AASlB;AAOO,IAAM,eAAN,cAA2B,gBAAgB;AAAA,EACvC,OAAO;AAAA,EAEhB,YAAY,WAAmB,OAAgB;AAC7C,UAAM,WAAW,SAAS,YAAY,SAAS,KAAK,CAAC,IAAI,EAAE,MAAM,CAAC;AAAA,EACpE;AACF;AAEO,SAAS,SAAS,OAAwB;AAC/C,MAAI,iBAAiB,OAAO;AAC1B,WAAO,MAAM;AAAA,EACf;AACA,SAAO,OAAO,UAAU,WAAW,QAAQ,KAAK,UAAU,KAAK;AACjE;","names":[]}
|
|
File without changes
|