@brightbeamai/chap-coordinator 0.3.2 → 0.3.4
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/dist/index.cjs +248 -62
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +247 -62
- package/dist/index.js.map +1 -1
- package/dist/patch.cjs +195 -61
- package/dist/patch.cjs.map +1 -1
- package/dist/patch.d.cts +16 -2
- package/dist/patch.d.ts +16 -2
- package/dist/patch.js +194 -61
- package/dist/patch.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -22,6 +22,7 @@ var src_exports = {};
|
|
|
22
22
|
__export(src_exports, {
|
|
23
23
|
Coordinator: () => Coordinator,
|
|
24
24
|
CoordinatorError: () => CoordinatorError,
|
|
25
|
+
DEFAULT_MAX_PATCHED_BYTES: () => DEFAULT_MAX_PATCHED_BYTES,
|
|
25
26
|
E: () => E,
|
|
26
27
|
IdFactory: () => IdFactory,
|
|
27
28
|
MemoryStore: () => MemoryStore,
|
|
@@ -553,77 +554,116 @@ function deepEqual(a, b) {
|
|
|
553
554
|
}
|
|
554
555
|
return true;
|
|
555
556
|
}
|
|
556
|
-
function
|
|
557
|
+
function addAt(doc, path, value, size, copied = false, movedFrom) {
|
|
558
|
+
const parts = splitPath(path);
|
|
559
|
+
if (parts.length === 0) {
|
|
560
|
+
if (size) {
|
|
561
|
+
size.reset(value);
|
|
562
|
+
if (copied || movedFrom !== void 0) size.carry(size);
|
|
563
|
+
}
|
|
564
|
+
return value;
|
|
565
|
+
}
|
|
566
|
+
const [parent, key] = navigate(doc, parts);
|
|
567
|
+
let newKey;
|
|
568
|
+
if (Array.isArray(parent)) {
|
|
569
|
+
if (key === "-") {
|
|
570
|
+
parent.push(value);
|
|
571
|
+
} else {
|
|
572
|
+
const idx = key;
|
|
573
|
+
if (idx < 0 || idx > parent.length) {
|
|
574
|
+
throw new PatchError(`Index out of range for add: ${path}`);
|
|
575
|
+
}
|
|
576
|
+
parent.splice(idx, 0, value);
|
|
577
|
+
}
|
|
578
|
+
} else if (parent !== null && typeof parent === "object") {
|
|
579
|
+
if (Object.prototype.hasOwnProperty.call(parent, key)) size?.take(parent[key]);
|
|
580
|
+
else newKey = key;
|
|
581
|
+
parent[key] = value;
|
|
582
|
+
} else {
|
|
583
|
+
throw new PatchError(`Cannot add into ${jsonType(parent)}`);
|
|
584
|
+
}
|
|
585
|
+
if (size) {
|
|
586
|
+
if (movedFrom === void 0) {
|
|
587
|
+
const inserted = size.insert(value, parts.length, newKey);
|
|
588
|
+
if (copied) size.carry(inserted);
|
|
589
|
+
} else {
|
|
590
|
+
if (newKey !== void 0) size.bytes += utf8Length(newKey);
|
|
591
|
+
if (parts.length > movedFrom) {
|
|
592
|
+
const moved = sizeOf(value);
|
|
593
|
+
size.depth = Math.max(size.depth, parts.length + moved.depth);
|
|
594
|
+
size.carry(moved);
|
|
595
|
+
}
|
|
596
|
+
}
|
|
597
|
+
}
|
|
598
|
+
return doc;
|
|
599
|
+
}
|
|
600
|
+
function removeAt(doc, path, size, moved = false) {
|
|
601
|
+
const parts = splitPath(path);
|
|
602
|
+
if (parts.length === 0) throw new PatchError("Cannot remove root.");
|
|
603
|
+
const [parent, key] = navigate(doc, parts);
|
|
604
|
+
if (Array.isArray(parent)) {
|
|
605
|
+
const idx = key === "-" ? -1 : key;
|
|
606
|
+
if (idx < 0 || idx >= parent.length) {
|
|
607
|
+
throw new PatchError(`Index out of range for remove: ${path}`);
|
|
608
|
+
}
|
|
609
|
+
if (size && !moved) size.take(parent[idx]);
|
|
610
|
+
parent.splice(idx, 1);
|
|
611
|
+
} else if (parent !== null && typeof parent === "object") {
|
|
612
|
+
if (!Object.prototype.hasOwnProperty.call(parent, key)) {
|
|
613
|
+
throw new PatchError(`Path not found for remove: ${path}`);
|
|
614
|
+
}
|
|
615
|
+
if (size) {
|
|
616
|
+
if (moved) size.bytes -= utf8Length(key);
|
|
617
|
+
else size.take(parent[key], key);
|
|
618
|
+
}
|
|
619
|
+
delete parent[key];
|
|
620
|
+
} else {
|
|
621
|
+
throw new PatchError(`Cannot remove from ${jsonType(parent)}`);
|
|
622
|
+
}
|
|
623
|
+
return doc;
|
|
624
|
+
}
|
|
625
|
+
function applyOne(doc, op, size) {
|
|
557
626
|
const kind = op.op;
|
|
558
627
|
const path = op.path ?? "";
|
|
559
628
|
if (kind === "add") {
|
|
560
629
|
if (!("value" in op)) throw new PatchError("'add' requires 'value'");
|
|
561
|
-
|
|
562
|
-
if (parts.length === 0) return op.value;
|
|
563
|
-
const [parent, key] = navigate(doc, parts);
|
|
564
|
-
if (Array.isArray(parent)) {
|
|
565
|
-
if (key === "-") {
|
|
566
|
-
parent.push(op.value);
|
|
567
|
-
} else {
|
|
568
|
-
const idx = key;
|
|
569
|
-
if (idx < 0 || idx > parent.length) {
|
|
570
|
-
throw new PatchError(`Index out of range for add: ${path}`);
|
|
571
|
-
}
|
|
572
|
-
parent.splice(idx, 0, op.value);
|
|
573
|
-
}
|
|
574
|
-
} else if (parent !== null && typeof parent === "object") {
|
|
575
|
-
parent[key] = op.value;
|
|
576
|
-
} else {
|
|
577
|
-
throw new PatchError(`Cannot add into ${jsonType(parent)}`);
|
|
578
|
-
}
|
|
579
|
-
return doc;
|
|
630
|
+
return addAt(doc, path, clone(op.value), size);
|
|
580
631
|
}
|
|
581
632
|
if (kind === "replace") {
|
|
582
633
|
if (!("value" in op)) throw new PatchError("'replace' requires 'value'");
|
|
583
634
|
const parts = splitPath(path);
|
|
584
|
-
|
|
635
|
+
const value = clone(op.value);
|
|
636
|
+
if (parts.length === 0) {
|
|
637
|
+
size?.reset(value);
|
|
638
|
+
return value;
|
|
639
|
+
}
|
|
585
640
|
const [parent, key] = navigate(doc, parts);
|
|
586
641
|
if (Array.isArray(parent)) {
|
|
587
642
|
const idx = key === "-" ? -1 : key;
|
|
588
643
|
if (idx < 0 || idx >= parent.length) {
|
|
589
644
|
throw new PatchError(`Path not found for replace: ${path}`);
|
|
590
645
|
}
|
|
591
|
-
parent[idx]
|
|
646
|
+
size?.take(parent[idx]);
|
|
647
|
+
parent[idx] = value;
|
|
592
648
|
} else if (parent !== null && typeof parent === "object") {
|
|
593
649
|
if (!Object.prototype.hasOwnProperty.call(parent, key)) {
|
|
594
650
|
throw new PatchError(`Path not found for replace: ${path}`);
|
|
595
651
|
}
|
|
596
|
-
parent[key]
|
|
652
|
+
size?.take(parent[key]);
|
|
653
|
+
parent[key] = value;
|
|
597
654
|
} else {
|
|
598
655
|
throw new PatchError(`Cannot replace in ${jsonType(parent)}`);
|
|
599
656
|
}
|
|
657
|
+
size?.insert(value, parts.length);
|
|
600
658
|
return doc;
|
|
601
659
|
}
|
|
602
660
|
if (kind === "remove") {
|
|
603
|
-
|
|
604
|
-
if (parts.length === 0) throw new PatchError("Cannot remove root.");
|
|
605
|
-
const [parent, key] = navigate(doc, parts);
|
|
606
|
-
if (Array.isArray(parent)) {
|
|
607
|
-
const idx = key === "-" ? -1 : key;
|
|
608
|
-
if (idx < 0 || idx >= parent.length) {
|
|
609
|
-
throw new PatchError(`Index out of range for remove: ${path}`);
|
|
610
|
-
}
|
|
611
|
-
parent.splice(idx, 1);
|
|
612
|
-
} else if (parent !== null && typeof parent === "object") {
|
|
613
|
-
if (!Object.prototype.hasOwnProperty.call(parent, key)) {
|
|
614
|
-
throw new PatchError(`Path not found for remove: ${path}`);
|
|
615
|
-
}
|
|
616
|
-
delete parent[key];
|
|
617
|
-
} else {
|
|
618
|
-
throw new PatchError(`Cannot remove from ${jsonType(parent)}`);
|
|
619
|
-
}
|
|
620
|
-
return doc;
|
|
661
|
+
return removeAt(doc, path, size);
|
|
621
662
|
}
|
|
622
663
|
if (kind === "copy") {
|
|
623
664
|
const src = op.from;
|
|
624
665
|
if (src === void 0) throw new PatchError("'copy' requires 'from'");
|
|
625
|
-
|
|
626
|
-
return applyOne(doc, { op: "add", path, value });
|
|
666
|
+
return addAt(doc, path, clone(getAt(doc, src)), size, true);
|
|
627
667
|
}
|
|
628
668
|
if (kind === "move") {
|
|
629
669
|
const src = op.from;
|
|
@@ -631,9 +671,9 @@ function applyOne(doc, op) {
|
|
|
631
671
|
if (path.startsWith(src + "/")) {
|
|
632
672
|
throw new PatchError("'move' cannot move a location into its own child.");
|
|
633
673
|
}
|
|
634
|
-
const value =
|
|
635
|
-
doc =
|
|
636
|
-
return
|
|
674
|
+
const value = getAt(doc, src);
|
|
675
|
+
doc = removeAt(doc, src, size, true);
|
|
676
|
+
return addAt(doc, path, value, size, false, splitPath(src).length);
|
|
637
677
|
}
|
|
638
678
|
if (kind === "test") {
|
|
639
679
|
if (!("value" in op)) throw new PatchError("'test' requires 'value'");
|
|
@@ -645,29 +685,122 @@ function applyOne(doc, op) {
|
|
|
645
685
|
}
|
|
646
686
|
var MAX_PATCH_OPS = 1e3;
|
|
647
687
|
var MAX_DOCUMENT_NODES = 1e5;
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
688
|
+
var MAX_DOCUMENT_DEPTH = 64;
|
|
689
|
+
var MAX_CARRIED_TIMES = 3;
|
|
690
|
+
var DEFAULT_MAX_PATCHED_BYTES = 1048576;
|
|
691
|
+
function utf8Length(s) {
|
|
692
|
+
const buffer = globalThis.Buffer;
|
|
693
|
+
if (typeof buffer === "function") {
|
|
694
|
+
return buffer.byteLength(s, "utf8");
|
|
695
|
+
}
|
|
696
|
+
let n = 0;
|
|
697
|
+
for (let i = 0; i < s.length; i++) {
|
|
698
|
+
const c = s.charCodeAt(i);
|
|
699
|
+
if (c < 128) n += 1;
|
|
700
|
+
else if (c < 2048) n += 2;
|
|
701
|
+
else if (c >= 55296 && c <= 56319 && i + 1 < s.length) {
|
|
702
|
+
const d = s.charCodeAt(i + 1);
|
|
703
|
+
if (d >= 56320 && d <= 57343) {
|
|
704
|
+
n += 4;
|
|
705
|
+
i++;
|
|
706
|
+
} else n += 3;
|
|
707
|
+
} else n += 3;
|
|
708
|
+
}
|
|
709
|
+
return n;
|
|
710
|
+
}
|
|
711
|
+
function sizeOf(value) {
|
|
712
|
+
if (value === null || typeof value !== "object") {
|
|
713
|
+
return { nodes: 1, bytes: typeof value === "string" ? utf8Length(value) : 0, depth: 1 };
|
|
714
|
+
}
|
|
715
|
+
let nodes = 0;
|
|
716
|
+
let bytes = 0;
|
|
717
|
+
let depth = 0;
|
|
718
|
+
const values = [value];
|
|
719
|
+
const levels = [1];
|
|
720
|
+
const visit = (x, level) => {
|
|
721
|
+
if (x !== null && typeof x === "object") {
|
|
722
|
+
values.push(x);
|
|
723
|
+
levels.push(level);
|
|
724
|
+
return;
|
|
725
|
+
}
|
|
726
|
+
nodes += 1;
|
|
727
|
+
if (level > depth) depth = level;
|
|
728
|
+
if (typeof x === "string") bytes += utf8Length(x);
|
|
729
|
+
};
|
|
730
|
+
while (values.length > 0) {
|
|
731
|
+
const v = values.pop();
|
|
732
|
+
const level = levels.pop();
|
|
733
|
+
nodes += 1;
|
|
734
|
+
if (level > depth) depth = level;
|
|
735
|
+
if (Array.isArray(v)) {
|
|
736
|
+
for (const x of v) visit(x, level + 1);
|
|
737
|
+
} else {
|
|
738
|
+
const o = v;
|
|
739
|
+
for (const k of Object.keys(o)) {
|
|
740
|
+
bytes += utf8Length(k);
|
|
741
|
+
visit(o[k], level + 1);
|
|
742
|
+
}
|
|
743
|
+
}
|
|
658
744
|
}
|
|
659
|
-
return
|
|
745
|
+
return { nodes, bytes, depth };
|
|
660
746
|
}
|
|
661
|
-
|
|
747
|
+
var Size = class {
|
|
748
|
+
nodes = 0;
|
|
749
|
+
bytes = 0;
|
|
750
|
+
depth = 0;
|
|
751
|
+
/** What copies, and moves to a deeper place or onto the whole document, have carried. */
|
|
752
|
+
carriedNodes = 0;
|
|
753
|
+
carriedBytes = 0;
|
|
754
|
+
constructor(doc) {
|
|
755
|
+
this.reset(doc);
|
|
756
|
+
}
|
|
757
|
+
reset(doc) {
|
|
758
|
+
const s = sizeOf(doc);
|
|
759
|
+
this.nodes = s.nodes;
|
|
760
|
+
this.bytes = s.bytes;
|
|
761
|
+
this.depth = s.depth;
|
|
762
|
+
}
|
|
763
|
+
/** `value` goes in `segments` levels below the top, under a new `key`. */
|
|
764
|
+
insert(value, segments, key) {
|
|
765
|
+
const s = sizeOf(value);
|
|
766
|
+
this.nodes += s.nodes;
|
|
767
|
+
this.bytes += s.bytes + (key === void 0 ? 0 : utf8Length(key));
|
|
768
|
+
this.depth = Math.max(this.depth, segments + s.depth);
|
|
769
|
+
return s;
|
|
770
|
+
}
|
|
771
|
+
carry(s) {
|
|
772
|
+
this.carriedNodes += s.nodes;
|
|
773
|
+
this.carriedBytes += s.bytes;
|
|
774
|
+
}
|
|
775
|
+
/** `value` comes out, with its `key`. */
|
|
776
|
+
take(value, key) {
|
|
777
|
+
const s = sizeOf(value);
|
|
778
|
+
this.nodes -= s.nodes;
|
|
779
|
+
this.bytes -= s.bytes + (key === void 0 ? 0 : utf8Length(key));
|
|
780
|
+
}
|
|
781
|
+
};
|
|
782
|
+
function applyJsonPatch(doc, ops, limits = {}) {
|
|
783
|
+
const maxBytes = limits.maxStringBytes ?? DEFAULT_MAX_PATCHED_BYTES;
|
|
662
784
|
if (ops.length > MAX_PATCH_OPS) {
|
|
663
785
|
throw new PatchError(`Patch has too many operations (${ops.length} > ${MAX_PATCH_OPS})`);
|
|
664
786
|
}
|
|
665
787
|
let out = JSON.parse(JSON.stringify(doc));
|
|
788
|
+
const size = new Size(out);
|
|
666
789
|
for (const op of ops) {
|
|
667
|
-
out = applyOne(out, op);
|
|
668
|
-
if (
|
|
790
|
+
out = applyOne(out, op, size);
|
|
791
|
+
if (size.depth > MAX_DOCUMENT_DEPTH) size.depth = sizeOf(out).depth;
|
|
792
|
+
if (size.nodes > MAX_DOCUMENT_NODES) {
|
|
669
793
|
throw new PatchError(`Patched document exceeds the node limit (${MAX_DOCUMENT_NODES})`);
|
|
670
794
|
}
|
|
795
|
+
if (size.bytes > maxBytes) {
|
|
796
|
+
throw new PatchError(`Patched document exceeds the size limit (${maxBytes} bytes of strings and keys)`);
|
|
797
|
+
}
|
|
798
|
+
if (size.depth > MAX_DOCUMENT_DEPTH) {
|
|
799
|
+
throw new PatchError(`Patched document nests deeper than ${MAX_DOCUMENT_DEPTH} levels`);
|
|
800
|
+
}
|
|
801
|
+
if (size.carriedNodes > MAX_CARRIED_TIMES * MAX_DOCUMENT_NODES || size.carriedBytes > MAX_CARRIED_TIMES * maxBytes) {
|
|
802
|
+
throw new PatchError(`Patch copies or moves more than its limit (${MAX_CARRIED_TIMES * MAX_DOCUMENT_NODES} values or ${MAX_CARRIED_TIMES * maxBytes} bytes of strings and keys)`);
|
|
803
|
+
}
|
|
671
804
|
}
|
|
672
805
|
return out;
|
|
673
806
|
}
|
|
@@ -1400,6 +1533,7 @@ function registerControl(coord) {
|
|
|
1400
1533
|
}
|
|
1401
1534
|
|
|
1402
1535
|
// src/profiles/deliberation.ts
|
|
1536
|
+
var RESERVED_IDS = /* @__PURE__ */ new Set(["__proto__", "constructor", "prototype"]);
|
|
1403
1537
|
function parseRule(rule) {
|
|
1404
1538
|
if (rule.includes(":")) {
|
|
1405
1539
|
const [kind, arg] = rule.split(":", 2);
|
|
@@ -1500,6 +1634,18 @@ function registerDeliberation(coord) {
|
|
|
1500
1634
|
const msg = e instanceof Error ? e.message : String(e);
|
|
1501
1635
|
return { error: rpcError(E.DELIB_UNKNOWN_RULE, msg) };
|
|
1502
1636
|
}
|
|
1637
|
+
const suppliedDeliberationId = p.deliberation_id;
|
|
1638
|
+
if (suppliedDeliberationId !== void 0 && suppliedDeliberationId !== null && suppliedDeliberationId !== "") {
|
|
1639
|
+
if (typeof suppliedDeliberationId !== "string") {
|
|
1640
|
+
return { error: rpcError(E.PARAMS, "deliberation_id must be a string") };
|
|
1641
|
+
}
|
|
1642
|
+
if (RESERVED_IDS.has(suppliedDeliberationId)) {
|
|
1643
|
+
return { error: rpcError(E.PARAMS, `deliberation_id cannot be ${JSON.stringify(suppliedDeliberationId)}`) };
|
|
1644
|
+
}
|
|
1645
|
+
if (ws.deliberations.has(suppliedDeliberationId)) {
|
|
1646
|
+
return { error: rpcError(E.PARAMS, `deliberation_id already in use: ${suppliedDeliberationId}`) };
|
|
1647
|
+
}
|
|
1648
|
+
}
|
|
1503
1649
|
const id = p.deliberation_id || coord.ids.deliberationId();
|
|
1504
1650
|
const delib = {
|
|
1505
1651
|
id,
|
|
@@ -1582,6 +1728,7 @@ function registerDeliberation(coord) {
|
|
|
1582
1728
|
}
|
|
1583
1729
|
|
|
1584
1730
|
// src/profiles/handoff.ts
|
|
1731
|
+
var RESERVED_IDS2 = /* @__PURE__ */ new Set(["__proto__", "constructor", "prototype"]);
|
|
1585
1732
|
function registerHandoff(coord) {
|
|
1586
1733
|
coord.handlers.set("handoff.propose", (p) => {
|
|
1587
1734
|
const ws = coord.workspaces.get(p.workspace);
|
|
@@ -1624,6 +1771,18 @@ function registerHandoff(coord) {
|
|
|
1624
1771
|
blockers: t.blockers ?? []
|
|
1625
1772
|
});
|
|
1626
1773
|
}
|
|
1774
|
+
const suppliedHandoffId = p.handoff_id;
|
|
1775
|
+
if (suppliedHandoffId !== void 0 && suppliedHandoffId !== null && suppliedHandoffId !== "") {
|
|
1776
|
+
if (typeof suppliedHandoffId !== "string") {
|
|
1777
|
+
return { error: rpcError(E.PARAMS, "handoff_id must be a string") };
|
|
1778
|
+
}
|
|
1779
|
+
if (RESERVED_IDS2.has(suppliedHandoffId)) {
|
|
1780
|
+
return { error: rpcError(E.PARAMS, `handoff_id cannot be ${JSON.stringify(suppliedHandoffId)}`) };
|
|
1781
|
+
}
|
|
1782
|
+
if (ws.handoffs.has(suppliedHandoffId)) {
|
|
1783
|
+
return { error: rpcError(E.PARAMS, `handoff_id already in use: ${suppliedHandoffId}`) };
|
|
1784
|
+
}
|
|
1785
|
+
}
|
|
1627
1786
|
const id = p.handoff_id || coord.ids.handoffId();
|
|
1628
1787
|
const ho = {
|
|
1629
1788
|
id,
|
|
@@ -2014,6 +2173,7 @@ function registerSecuritySigned(coord) {
|
|
|
2014
2173
|
}
|
|
2015
2174
|
|
|
2016
2175
|
// src/profiles/whisper.ts
|
|
2176
|
+
var RESERVED_IDS3 = /* @__PURE__ */ new Set(["__proto__", "constructor", "prototype"]);
|
|
2017
2177
|
function parseIso(ts) {
|
|
2018
2178
|
return new Date(ts).getTime();
|
|
2019
2179
|
}
|
|
@@ -2038,6 +2198,18 @@ function registerWhisper(coord) {
|
|
|
2038
2198
|
}
|
|
2039
2199
|
const to = p.to;
|
|
2040
2200
|
const askee = Array.isArray(to) ? to : [to];
|
|
2201
|
+
const suppliedWhisperId = p.whisper_id;
|
|
2202
|
+
if (suppliedWhisperId !== void 0 && suppliedWhisperId !== null && suppliedWhisperId !== "") {
|
|
2203
|
+
if (typeof suppliedWhisperId !== "string") {
|
|
2204
|
+
return { error: rpcError(E.PARAMS, "whisper_id must be a string") };
|
|
2205
|
+
}
|
|
2206
|
+
if (RESERVED_IDS3.has(suppliedWhisperId)) {
|
|
2207
|
+
return { error: rpcError(E.PARAMS, `whisper_id cannot be ${JSON.stringify(suppliedWhisperId)}`) };
|
|
2208
|
+
}
|
|
2209
|
+
if (ws.whispers.has(suppliedWhisperId)) {
|
|
2210
|
+
return { error: rpcError(E.PARAMS, `whisper_id already in use: ${suppliedWhisperId}`) };
|
|
2211
|
+
}
|
|
2212
|
+
}
|
|
2041
2213
|
const id = p.whisper_id || coord.ids.artefactId();
|
|
2042
2214
|
const prompt = {
|
|
2043
2215
|
id,
|
|
@@ -2491,7 +2663,8 @@ var Coordinator = class {
|
|
|
2491
2663
|
let record;
|
|
2492
2664
|
try {
|
|
2493
2665
|
record = { id: ws.id, data: this.snapshotOf(ws), version: next, updated_at: this.now() };
|
|
2494
|
-
} catch {
|
|
2666
|
+
} catch (err) {
|
|
2667
|
+
this.reportStoreError(err, { id: ws.id, version: next });
|
|
2495
2668
|
return;
|
|
2496
2669
|
}
|
|
2497
2670
|
const pending = this.saveChains.get(ws.id);
|
|
@@ -3386,6 +3559,16 @@ var Coordinator = class {
|
|
|
3386
3559
|
) };
|
|
3387
3560
|
}
|
|
3388
3561
|
task.review = { requested_at: now, requested_to: eligible, rule: "any_one_approves", decisions: [] };
|
|
3562
|
+
} else {
|
|
3563
|
+
const author = p.from;
|
|
3564
|
+
const reviewers = task.review.requested_to.filter((r) => r !== author);
|
|
3565
|
+
if (reviewers.length === 0) {
|
|
3566
|
+
return { error: rpcError(
|
|
3567
|
+
E.NOT_AUTHORISED,
|
|
3568
|
+
"Task requires review but has no reviewer other than its completer"
|
|
3569
|
+
) };
|
|
3570
|
+
}
|
|
3571
|
+
task.review = { ...task.review, requested_at: now, requested_to: reviewers, decisions: [] };
|
|
3389
3572
|
}
|
|
3390
3573
|
task.pending_artefact = p.output;
|
|
3391
3574
|
task.state = "review_requested";
|
|
@@ -3601,7 +3784,9 @@ var Coordinator = class {
|
|
|
3601
3784
|
if (base === void 0) return { error: rpcError(E.PARAMS, "No base artefact for override") };
|
|
3602
3785
|
let applied;
|
|
3603
3786
|
try {
|
|
3604
|
-
applied = applyJsonPatch(base, p.diff
|
|
3787
|
+
applied = applyJsonPatch(base, p.diff, {
|
|
3788
|
+
maxStringBytes: this.options.maxEnvelopeBytes ?? DEFAULT_MAX_ENVELOPE_BYTES
|
|
3789
|
+
});
|
|
3605
3790
|
} catch (e) {
|
|
3606
3791
|
const msg = e instanceof Error ? e.message : String(e);
|
|
3607
3792
|
return { error: rpcError(E.PATCH_FAILED, msg) };
|
|
@@ -3938,6 +4123,7 @@ function wrapA2aMessageExchange(coord, workspace, options) {
|
|
|
3938
4123
|
0 && (module.exports = {
|
|
3939
4124
|
Coordinator,
|
|
3940
4125
|
CoordinatorError,
|
|
4126
|
+
DEFAULT_MAX_PATCHED_BYTES,
|
|
3941
4127
|
E,
|
|
3942
4128
|
IdFactory,
|
|
3943
4129
|
MemoryStore,
|