@agentshouse/mdruntime 0.1.0-alpha.4 → 0.1.0-alpha.40

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.
Files changed (125) hide show
  1. package/AGENTS.md +191 -0
  2. package/README.md +44 -0
  3. package/dist/adapter.d.ts +174 -18
  4. package/dist/adapter.d.ts.map +1 -1
  5. package/dist/adapter.js +2 -1
  6. package/dist/adapter.js.map +1 -1
  7. package/dist/bootstrap.d.ts +7 -7
  8. package/dist/bootstrap.d.ts.map +1 -1
  9. package/dist/bootstrap.js +14 -9
  10. package/dist/bootstrap.js.map +1 -1
  11. package/dist/change-set.d.ts +33 -0
  12. package/dist/change-set.d.ts.map +1 -0
  13. package/dist/change-set.js +89 -0
  14. package/dist/change-set.js.map +1 -0
  15. package/dist/change.d.ts +10 -0
  16. package/dist/change.d.ts.map +1 -1
  17. package/dist/change.js.map +1 -1
  18. package/dist/client.d.ts +74 -0
  19. package/dist/client.d.ts.map +1 -0
  20. package/dist/client.js +232 -0
  21. package/dist/client.js.map +1 -0
  22. package/dist/collection.d.ts +25 -12
  23. package/dist/collection.d.ts.map +1 -1
  24. package/dist/collection.js +113 -31
  25. package/dist/collection.js.map +1 -1
  26. package/dist/connection.d.ts +84 -27
  27. package/dist/connection.d.ts.map +1 -1
  28. package/dist/connection.js +1685 -336
  29. package/dist/connection.js.map +1 -1
  30. package/dist/conversation.d.ts +79 -0
  31. package/dist/conversation.d.ts.map +1 -0
  32. package/dist/conversation.js +593 -0
  33. package/dist/conversation.js.map +1 -0
  34. package/dist/durability.d.ts +9 -0
  35. package/dist/durability.d.ts.map +1 -0
  36. package/dist/durability.js +11 -0
  37. package/dist/durability.js.map +1 -0
  38. package/dist/file.d.ts +20 -0
  39. package/dist/file.d.ts.map +1 -0
  40. package/dist/file.js +149 -0
  41. package/dist/file.js.map +1 -0
  42. package/dist/host.d.ts +14 -0
  43. package/dist/host.d.ts.map +1 -0
  44. package/dist/host.js +211 -0
  45. package/dist/host.js.map +1 -0
  46. package/dist/identity.d.ts +3 -0
  47. package/dist/identity.d.ts.map +1 -0
  48. package/dist/identity.js +23 -0
  49. package/dist/identity.js.map +1 -0
  50. package/dist/index.d.ts +15 -7
  51. package/dist/index.d.ts.map +1 -1
  52. package/dist/index.js +1 -0
  53. package/dist/index.js.map +1 -1
  54. package/dist/memory.d.ts +17 -2
  55. package/dist/memory.d.ts.map +1 -1
  56. package/dist/memory.js +201 -15
  57. package/dist/memory.js.map +1 -1
  58. package/dist/model.d.ts +55 -0
  59. package/dist/model.d.ts.map +1 -0
  60. package/dist/model.js +36 -0
  61. package/dist/model.js.map +1 -0
  62. package/dist/observation.d.ts +25 -0
  63. package/dist/observation.d.ts.map +1 -0
  64. package/dist/observation.js +92 -0
  65. package/dist/observation.js.map +1 -0
  66. package/dist/outcome.d.ts +22 -18
  67. package/dist/outcome.d.ts.map +1 -1
  68. package/dist/outcome.js +1 -11
  69. package/dist/outcome.js.map +1 -1
  70. package/dist/overlay.d.ts +2 -0
  71. package/dist/overlay.d.ts.map +1 -1
  72. package/dist/overlay.js +107 -1
  73. package/dist/overlay.js.map +1 -1
  74. package/dist/paths.d.ts +0 -1
  75. package/dist/paths.d.ts.map +1 -1
  76. package/dist/paths.js +0 -4
  77. package/dist/paths.js.map +1 -1
  78. package/dist/query.d.ts +209 -0
  79. package/dist/query.d.ts.map +1 -0
  80. package/dist/query.js +467 -0
  81. package/dist/query.js.map +1 -0
  82. package/dist/read-side.d.ts +14 -0
  83. package/dist/read-side.d.ts.map +1 -0
  84. package/dist/read-side.js +451 -0
  85. package/dist/read-side.js.map +1 -0
  86. package/dist/refresh.d.ts +3 -3
  87. package/dist/refresh.d.ts.map +1 -1
  88. package/dist/refresh.js +10 -7
  89. package/dist/refresh.js.map +1 -1
  90. package/dist/replica.d.ts +23 -4
  91. package/dist/replica.d.ts.map +1 -1
  92. package/dist/replica.js +224 -13
  93. package/dist/replica.js.map +1 -1
  94. package/dist/room-draft.d.ts +124 -0
  95. package/dist/room-draft.d.ts.map +1 -0
  96. package/dist/room-draft.js +406 -0
  97. package/dist/room-draft.js.map +1 -0
  98. package/dist/rows.d.ts +39 -0
  99. package/dist/rows.d.ts.map +1 -0
  100. package/dist/rows.js +100 -0
  101. package/dist/rows.js.map +1 -0
  102. package/dist/save.d.ts +11 -2
  103. package/dist/save.d.ts.map +1 -1
  104. package/dist/save.js +116 -128
  105. package/dist/save.js.map +1 -1
  106. package/dist/search.d.ts +61 -0
  107. package/dist/search.d.ts.map +1 -0
  108. package/dist/search.js +155 -0
  109. package/dist/search.js.map +1 -0
  110. package/dist/status.d.ts +9 -2
  111. package/dist/status.d.ts.map +1 -1
  112. package/dist/status.js +5 -4
  113. package/dist/status.js.map +1 -1
  114. package/dist/store.d.ts +89 -18
  115. package/dist/store.d.ts.map +1 -1
  116. package/dist/store.js +445 -57
  117. package/dist/store.js.map +1 -1
  118. package/dist/transfer.d.ts +5 -0
  119. package/dist/transfer.d.ts.map +1 -1
  120. package/dist/transfer.js.map +1 -1
  121. package/dist/wire.d.ts +64 -0
  122. package/dist/wire.d.ts.map +1 -0
  123. package/dist/wire.js +144 -0
  124. package/dist/wire.js.map +1 -0
  125. package/package.json +15 -13
@@ -0,0 +1,92 @@
1
+ export function rowsOf(result) {
2
+ return 'groups' in result ? result.groups : result.documents;
3
+ }
4
+ function keyedResult(first) {
5
+ const grouped = 'groups' in first.result;
6
+ const rows = rowsOf(first.result);
7
+ const byKey = new Map(first.keys.map((key, index)=>[
8
+ key,
9
+ rows[index]
10
+ ]));
11
+ let keys = first.keys;
12
+ return {
13
+ value: first.result,
14
+ next (message) {
15
+ const change = message;
16
+ for (const key of change.removed)byKey.delete(key);
17
+ for (const [key, row] of change.changed)byKey.set(key, row);
18
+ keys = change.order ?? keys.filter((key)=>byKey.has(key));
19
+ const next = keys.map((key)=>byKey.get(key));
20
+ return grouped ? {
21
+ groups: next
22
+ } : {
23
+ documents: next
24
+ };
25
+ }
26
+ };
27
+ }
28
+ function whole(first) {
29
+ return {
30
+ value: first,
31
+ next: (message)=>message
32
+ };
33
+ }
34
+ export function observed(first, stop, keyed) {
35
+ const reducer = keyed ? keyedResult(first) : whole(first);
36
+ let value = reducer.value;
37
+ let open = true;
38
+ const listeners = new Set();
39
+ const end = ()=>{
40
+ open = false;
41
+ listeners.clear();
42
+ };
43
+ return {
44
+ observation: {
45
+ current: ()=>value,
46
+ subscribe (listener) {
47
+ const entry = {
48
+ hear: listener
49
+ };
50
+ if (open) listeners.add(entry);
51
+ return ()=>{
52
+ listeners.delete(entry);
53
+ };
54
+ },
55
+ close () {
56
+ if (!open) return;
57
+ end();
58
+ stop();
59
+ }
60
+ },
61
+ receive (message) {
62
+ if (!open) return;
63
+ value = reducer.next(message);
64
+ for (const entry of [
65
+ ...listeners
66
+ ]){
67
+ if (listeners.has(entry)) entry.hear(value);
68
+ }
69
+ },
70
+ end
71
+ };
72
+ }
73
+ export function opened(watch, keyed) {
74
+ return new Promise((resolve, reject)=>{
75
+ let handle;
76
+ let stop = ()=>{};
77
+ try {
78
+ stop = watch((message)=>{
79
+ if (handle !== undefined) {
80
+ handle.receive(message);
81
+ return;
82
+ }
83
+ handle = observed(message, ()=>stop(), keyed);
84
+ resolve(handle.observation);
85
+ });
86
+ } catch (error) {
87
+ reject(error);
88
+ }
89
+ });
90
+ }
91
+
92
+ //# sourceMappingURL=observation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["/workspace/packages/mdruntime/src/observation.ts"],"sourcesContent":["import type { QueryDocument, QueryGroup, QueryResult } from './query.js';\n\nexport type Observation<T> = {\n current(): T;\n subscribe(listener: (value: T) => void): () => void;\n close(): void;\n};\n\nexport type RowKey = string | number;\n\nexport type KeyedResult = { result: QueryResult; keys: readonly RowKey[] };\n\nexport type QueryChange = {\n changed: readonly (readonly [RowKey, QueryDocument | QueryGroup])[];\n removed: readonly RowKey[];\n order: readonly RowKey[] | null;\n};\n\nexport type Observed = {\n observation: Observation<unknown>;\n receive(message: unknown): void;\n end(): void;\n};\n\nexport function rowsOf(result: QueryResult): readonly (QueryDocument | QueryGroup)[] {\n return 'groups' in result ? result.groups : result.documents;\n}\n\nfunction keyedResult(first: KeyedResult) {\n const grouped = 'groups' in first.result;\n const rows = rowsOf(first.result);\n const byKey = new Map(first.keys.map((key, index) => [key, rows[index]]));\n let keys = first.keys;\n return {\n value: first.result,\n next(message: unknown): QueryResult {\n const change = message as QueryChange;\n for (const key of change.removed) byKey.delete(key);\n for (const [key, row] of change.changed) byKey.set(key, row);\n keys = change.order ?? keys.filter((key) => byKey.has(key));\n const next = keys.map((key) => byKey.get(key) as QueryDocument | QueryGroup);\n return grouped\n ? { groups: next as readonly QueryGroup[] }\n : { documents: next as readonly QueryDocument[] };\n },\n };\n}\n\nfunction whole(first: unknown) {\n return { value: first, next: (message: unknown) => message };\n}\n\nexport function observed(first: unknown, stop: () => void, keyed: boolean): Observed {\n const reducer = keyed ? keyedResult(first as KeyedResult) : whole(first);\n let value = reducer.value;\n let open = true;\n const listeners = new Set<{ hear: (value: unknown) => void }>();\n const end = () => {\n open = false;\n listeners.clear();\n };\n return {\n observation: {\n current: () => value,\n subscribe(listener) {\n const entry = { hear: listener };\n if (open) listeners.add(entry);\n return () => {\n listeners.delete(entry);\n };\n },\n close() {\n if (!open) return;\n end();\n stop();\n },\n },\n receive(message) {\n if (!open) return;\n value = reducer.next(message);\n for (const entry of [...listeners]) {\n if (listeners.has(entry)) entry.hear(value);\n }\n },\n end,\n };\n}\n\nexport function opened(\n watch: (deliver: (message: unknown) => void) => () => void,\n keyed: boolean,\n): Promise<Observation<unknown>> {\n return new Promise((resolve, reject) => {\n let handle: Observed | undefined;\n let stop = () => {};\n try {\n stop = watch((message) => {\n if (handle !== undefined) {\n handle.receive(message);\n return;\n }\n handle = observed(message, () => stop(), keyed);\n resolve(handle.observation);\n });\n } catch (error) {\n reject(error);\n }\n });\n}\n"],"names":["rowsOf","result","groups","documents","keyedResult","first","grouped","rows","byKey","Map","keys","map","key","index","value","next","message","change","removed","delete","row","changed","set","order","filter","has","get","whole","observed","stop","keyed","reducer","open","listeners","Set","end","clear","observation","current","subscribe","listener","entry","hear","add","close","receive","opened","watch","Promise","resolve","reject","handle","undefined","error"],"mappings":"AAwBA,OAAO,SAASA,OAAOC,MAAmB;IACxC,OAAO,YAAYA,SAASA,OAAOC,MAAM,GAAGD,OAAOE,SAAS;AAC9D;AAEA,SAASC,YAAYC,KAAkB;IACrC,MAAMC,UAAU,YAAYD,MAAMJ,MAAM;IACxC,MAAMM,OAAOP,OAAOK,MAAMJ,MAAM;IAChC,MAAMO,QAAQ,IAAIC,IAAIJ,MAAMK,IAAI,CAACC,GAAG,CAAC,CAACC,KAAKC,QAAU;YAACD;YAAKL,IAAI,CAACM,MAAM;SAAC;IACvE,IAAIH,OAAOL,MAAMK,IAAI;IACrB,OAAO;QACLI,OAAOT,MAAMJ,MAAM;QACnBc,MAAKC,OAAgB;YACnB,MAAMC,SAASD;YACf,KAAK,MAAMJ,OAAOK,OAAOC,OAAO,CAAEV,MAAMW,MAAM,CAACP;YAC/C,KAAK,MAAM,CAACA,KAAKQ,IAAI,IAAIH,OAAOI,OAAO,CAAEb,MAAMc,GAAG,CAACV,KAAKQ;YACxDV,OAAOO,OAAOM,KAAK,IAAIb,KAAKc,MAAM,CAAC,CAACZ,MAAQJ,MAAMiB,GAAG,CAACb;YACtD,MAAMG,OAAOL,KAAKC,GAAG,CAAC,CAACC,MAAQJ,MAAMkB,GAAG,CAACd;YACzC,OAAON,UACH;gBAAEJ,QAAQa;YAA8B,IACxC;gBAAEZ,WAAWY;YAAiC;QACpD;IACF;AACF;AAEA,SAASY,MAAMtB,KAAc;IAC3B,OAAO;QAAES,OAAOT;QAAOU,MAAM,CAACC,UAAqBA;IAAQ;AAC7D;AAEA,OAAO,SAASY,SAASvB,KAAc,EAAEwB,IAAgB,EAAEC,KAAc;IACvE,MAAMC,UAAUD,QAAQ1B,YAAYC,SAAwBsB,MAAMtB;IAClE,IAAIS,QAAQiB,QAAQjB,KAAK;IACzB,IAAIkB,OAAO;IACX,MAAMC,YAAY,IAAIC;IACtB,MAAMC,MAAM;QACVH,OAAO;QACPC,UAAUG,KAAK;IACjB;IACA,OAAO;QACLC,aAAa;YACXC,SAAS,IAAMxB;YACfyB,WAAUC,QAAQ;gBAChB,MAAMC,QAAQ;oBAAEC,MAAMF;gBAAS;gBAC/B,IAAIR,MAAMC,UAAUU,GAAG,CAACF;gBACxB,OAAO;oBACLR,UAAUd,MAAM,CAACsB;gBACnB;YACF;YACAG;gBACE,IAAI,CAACZ,MAAM;gBACXG;gBACAN;YACF;QACF;QACAgB,SAAQ7B,OAAO;YACb,IAAI,CAACgB,MAAM;YACXlB,QAAQiB,QAAQhB,IAAI,CAACC;YACrB,KAAK,MAAMyB,SAAS;mBAAIR;aAAU,CAAE;gBAClC,IAAIA,UAAUR,GAAG,CAACgB,QAAQA,MAAMC,IAAI,CAAC5B;YACvC;QACF;QACAqB;IACF;AACF;AAEA,OAAO,SAASW,OACdC,KAA0D,EAC1DjB,KAAc;IAEd,OAAO,IAAIkB,QAAQ,CAACC,SAASC;QAC3B,IAAIC;QACJ,IAAItB,OAAO,KAAO;QAClB,IAAI;YACFA,OAAOkB,MAAM,CAAC/B;gBACZ,IAAImC,WAAWC,WAAW;oBACxBD,OAAON,OAAO,CAAC7B;oBACf;gBACF;gBACAmC,SAASvB,SAASZ,SAAS,IAAMa,QAAQC;gBACzCmB,QAAQE,OAAOd,WAAW;YAC5B;QACF,EAAE,OAAOgB,OAAO;YACdH,OAAOG;QACT;IACF;AACF"}
package/dist/outcome.d.ts CHANGED
@@ -1,30 +1,34 @@
1
+ import type { ActionResult, ProviderRefusal } from './adapter.js';
1
2
  import type { ChangeBatch } from './change.js';
2
3
  export type AffectedState = Readonly<Record<string, string>>;
3
- export type QueueOutcome = {
4
- kind: 'pending';
5
- } | {
6
- kind: 'conflicted';
4
+ export type CallResult = ActionResult | {
5
+ kind: 'undeclared';
6
+ };
7
+ export type AcceptedOutcome = {
8
+ kind: 'accepted';
7
9
  roomVersion: string;
10
+ author?: string;
11
+ time?: string;
12
+ };
13
+ export type SubmissionOutcome = AcceptedOutcome | (ProviderRefusal & {
14
+ kind: 'conflicted';
15
+ roomVersion?: string;
8
16
  affected: AffectedState;
9
- text: string;
10
- } | {
17
+ }) | (ProviderRefusal & {
11
18
  kind: 'rejected';
12
19
  affected: AffectedState;
13
- text: string;
14
- } | {
20
+ }) | {
15
21
  kind: 'expired';
22
+ } | {
23
+ kind: 'withdrawn';
16
24
  };
17
- export type AcceptedOutcome = {
18
- kind: 'accepted';
19
- roomVersion: string;
20
- author: string;
21
- time: string;
25
+ export type Submission = {
26
+ readonly state: 'waiting' | 'submitted';
27
+ } | {
28
+ readonly state: 'reset';
29
+ readonly reset: string;
22
30
  };
23
- export type SubmissionOutcome = QueueOutcome | AcceptedOutcome;
24
31
  export type QueueEntry = {
25
32
  readonly batch: ChangeBatch;
26
- readonly outcome: QueueOutcome;
27
- };
28
- export declare function refused(outcome: SubmissionOutcome | undefined): boolean;
29
- export declare function queuedOutcome(outcome: SubmissionOutcome | undefined): QueueOutcome;
33
+ } & Submission;
30
34
  //# sourceMappingURL=outcome.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"outcome.d.ts","sourceRoot":"","sources":["../src/outcome.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE/C,MAAM,MAAM,aAAa,GAAG,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;AAE7D,MAAM,MAAM,YAAY,GACpB;IAAE,IAAI,EAAE,SAAS,CAAA;CAAE,GACnB;IACE,IAAI,EAAE,YAAY,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,aAAa,CAAC;IACxB,IAAI,EAAE,MAAM,CAAC;CACd,GACD;IACE,IAAI,EAAE,UAAU,CAAC;IACjB,QAAQ,EAAE,aAAa,CAAC;IACxB,IAAI,EAAE,MAAM,CAAC;CACd,GACD;IAAE,IAAI,EAAE,SAAS,CAAA;CAAE,CAAC;AAExB,MAAM,MAAM,eAAe,GAAG;IAC5B,IAAI,EAAE,UAAU,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;CACd,CAAC;AAEF,MAAM,MAAM,iBAAiB,GAAG,YAAY,GAAG,eAAe,CAAC;AAE/D,MAAM,MAAM,UAAU,GAAG;IACvB,QAAQ,CAAC,KAAK,EAAE,WAAW,CAAC;IAC5B,QAAQ,CAAC,OAAO,EAAE,YAAY,CAAC;CAChC,CAAC;AAEF,wBAAgB,OAAO,CAAC,OAAO,EAAE,iBAAiB,GAAG,SAAS,GAAG,OAAO,CAIvE;AAED,wBAAgB,aAAa,CAAC,OAAO,EAAE,iBAAiB,GAAG,SAAS,GAAG,YAAY,CAKlF"}
1
+ {"version":3,"file":"outcome.d.ts","sourceRoot":"","sources":["../src/outcome.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAClE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE/C,MAAM,MAAM,aAAa,GAAG,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;AAE7D,MAAM,MAAM,UAAU,GAAG,YAAY,GAAG;IAAE,IAAI,EAAE,YAAY,CAAA;CAAE,CAAC;AAE/D,MAAM,MAAM,eAAe,GAAG;IAC5B,IAAI,EAAE,UAAU,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf,CAAC;AAEF,MAAM,MAAM,iBAAiB,GACzB,eAAe,GACf,CAAC,eAAe,GAAG;IACjB,IAAI,EAAE,YAAY,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,aAAa,CAAC;CACzB,CAAC,GACF,CAAC,eAAe,GAAG;IACjB,IAAI,EAAE,UAAU,CAAC;IACjB,QAAQ,EAAE,aAAa,CAAC;CACzB,CAAC,GACF;IAAE,IAAI,EAAE,SAAS,CAAA;CAAE,GACnB;IAAE,IAAI,EAAE,WAAW,CAAA;CAAE,CAAC;AAE1B,MAAM,MAAM,UAAU,GAClB;IAAE,QAAQ,CAAC,KAAK,EAAE,SAAS,GAAG,WAAW,CAAA;CAAE,GAC3C;IAAE,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AAExD,MAAM,MAAM,UAAU,GAAG;IAAE,QAAQ,CAAC,KAAK,EAAE,WAAW,CAAA;CAAE,GAAG,UAAU,CAAC"}
package/dist/outcome.js CHANGED
@@ -1,13 +1,3 @@
1
- export function refused(outcome) {
2
- return outcome?.kind === 'conflicted' || outcome?.kind === 'rejected' || outcome?.kind === 'expired';
3
- }
4
- export function queuedOutcome(outcome) {
5
- if (outcome === undefined || outcome.kind === 'accepted' || outcome.kind === 'pending') {
6
- return {
7
- kind: 'pending'
8
- };
9
- }
10
- return outcome;
11
- }
1
+ export { };
12
2
 
13
3
  //# sourceMappingURL=outcome.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["/workspace/packages/mdruntime/src/outcome.ts"],"sourcesContent":["import type { ChangeBatch } from './change.js';\n\nexport type AffectedState = Readonly<Record<string, string>>;\n\nexport type QueueOutcome =\n | { kind: 'pending' }\n | {\n kind: 'conflicted';\n roomVersion: string;\n affected: AffectedState;\n text: string;\n }\n | {\n kind: 'rejected';\n affected: AffectedState;\n text: string;\n }\n | { kind: 'expired' };\n\nexport type AcceptedOutcome = {\n kind: 'accepted';\n roomVersion: string;\n author: string;\n time: string;\n};\n\nexport type SubmissionOutcome = QueueOutcome | AcceptedOutcome;\n\nexport type QueueEntry = {\n readonly batch: ChangeBatch;\n readonly outcome: QueueOutcome;\n};\n\nexport function refused(outcome: SubmissionOutcome | undefined): boolean {\n return (\n outcome?.kind === 'conflicted' || outcome?.kind === 'rejected' || outcome?.kind === 'expired'\n );\n}\n\nexport function queuedOutcome(outcome: SubmissionOutcome | undefined): QueueOutcome {\n if (outcome === undefined || outcome.kind === 'accepted' || outcome.kind === 'pending') {\n return { kind: 'pending' };\n }\n return outcome;\n}\n"],"names":["refused","outcome","kind","queuedOutcome","undefined"],"mappings":"AAiCA,OAAO,SAASA,QAAQC,OAAsC;IAC5D,OACEA,SAASC,SAAS,gBAAgBD,SAASC,SAAS,cAAcD,SAASC,SAAS;AAExF;AAEA,OAAO,SAASC,cAAcF,OAAsC;IAClE,IAAIA,YAAYG,aAAaH,QAAQC,IAAI,KAAK,cAAcD,QAAQC,IAAI,KAAK,WAAW;QACtF,OAAO;YAAEA,MAAM;QAAU;IAC3B;IACA,OAAOD;AACT"}
1
+ {"version":3,"sources":["/workspace/packages/mdruntime/src/outcome.ts"],"sourcesContent":["import type { ActionResult, ProviderRefusal } from './adapter.js';\nimport type { ChangeBatch } from './change.js';\n\nexport type AffectedState = Readonly<Record<string, string>>;\n\nexport type CallResult = ActionResult | { kind: 'undeclared' };\n\nexport type AcceptedOutcome = {\n kind: 'accepted';\n roomVersion: string;\n author?: string;\n time?: string;\n};\n\nexport type SubmissionOutcome =\n | AcceptedOutcome\n | (ProviderRefusal & {\n kind: 'conflicted';\n roomVersion?: string;\n affected: AffectedState;\n })\n | (ProviderRefusal & {\n kind: 'rejected';\n affected: AffectedState;\n })\n | { kind: 'expired' }\n | { kind: 'withdrawn' };\n\nexport type Submission =\n | { readonly state: 'waiting' | 'submitted' }\n | { readonly state: 'reset'; readonly reset: string };\n\nexport type QueueEntry = { readonly batch: ChangeBatch } & Submission;\n"],"names":[],"mappings":"AAgCA,WAAsE"}
package/dist/overlay.d.ts CHANGED
@@ -5,4 +5,6 @@ export type Layer = {
5
5
  revisions: Readonly<Record<string, string>>;
6
6
  };
7
7
  export declare function overlay(base: Layer, queue: readonly ChangeBatch[]): Layer;
8
+ export declare function sameLayerText(left: Layer, right: Layer): boolean;
9
+ export declare function overlayChanged(base: Layer, queue: readonly ChangeBatch[], previousBase: Layer, previousQueue: readonly ChangeBatch[], previousVisible: Layer): Layer;
8
10
  //# sourceMappingURL=overlay.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"overlay.d.ts","sourceRoot":"","sources":["../src/overlay.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAU,WAAW,EAAgB,MAAM,aAAa,CAAC;AAErE,MAAM,MAAM,KAAK,GAAG;IAClB,SAAS,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IAC5C,aAAa,EAAE,SAAS,MAAM,EAAE,CAAC;IACjC,SAAS,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;CAC7C,CAAC;AAyIF,wBAAgB,OAAO,CAAC,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,SAAS,WAAW,EAAE,GAAG,KAAK,CAezE"}
1
+ {"version":3,"file":"overlay.d.ts","sourceRoot":"","sources":["../src/overlay.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAU,WAAW,EAAgB,MAAM,aAAa,CAAC;AAErE,MAAM,MAAM,KAAK,GAAG;IAClB,SAAS,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IAC5C,aAAa,EAAE,SAAS,MAAM,EAAE,CAAC;IACjC,SAAS,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;CAC7C,CAAC;AA0IF,wBAAgB,OAAO,CAAC,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,SAAS,WAAW,EAAE,GAAG,KAAK,CAezE;AAQD,wBAAgB,aAAa,CAAC,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,GAAG,OAAO,CAQhE;AAqBD,wBAAgB,cAAc,CAC5B,IAAI,EAAE,KAAK,EACX,KAAK,EAAE,SAAS,WAAW,EAAE,EAC7B,YAAY,EAAE,KAAK,EACnB,aAAa,EAAE,SAAS,WAAW,EAAE,EACrC,eAAe,EAAE,KAAK,GACrB,KAAK,CAkFP"}
package/dist/overlay.js CHANGED
@@ -99,7 +99,7 @@ function stage(staged, change, priors) {
99
99
  return;
100
100
  }
101
101
  if (change.kind === 'create') {
102
- staged.documents[change.path] = compose(change.fields, change.sections);
102
+ staged.documents[change.path] = 'content' in change ? change.content : compose(change.fields, change.sections);
103
103
  return;
104
104
  }
105
105
  if (change.kind === 'replace') {
@@ -135,5 +135,111 @@ export function overlay(base, queue) {
135
135
  revisions: staged.revisions
136
136
  };
137
137
  }
138
+ function pathsOf(batch) {
139
+ return batch.changes.flatMap((change)=>change.kind === 'move' ? [
140
+ change.path,
141
+ change.to
142
+ ] : [
143
+ change.path
144
+ ]);
145
+ }
146
+ export function sameLayerText(left, right) {
147
+ const paths = Object.keys(left.documents);
148
+ return paths.length === Object.keys(right.documents).length && paths.every((path)=>left.documents[path] === right.documents[path]) && left.binaryTargets.length === right.binaryTargets.length && left.binaryTargets.every((path)=>right.binaryTargets.includes(path));
149
+ }
150
+ function replayRevisions(base, queue) {
151
+ const revisions = {
152
+ ...base
153
+ };
154
+ for (const batch of queue){
155
+ for (const change of batch.changes){
156
+ if (change.kind === 'remove') {
157
+ delete revisions[change.path];
158
+ } else if (change.kind === 'move') {
159
+ const revision = revisions[change.path];
160
+ delete revisions[change.path];
161
+ if (revision !== undefined) revisions[change.to] = revision;
162
+ }
163
+ }
164
+ }
165
+ return revisions;
166
+ }
167
+ export function overlayChanged(base, queue, previousBase, previousQueue, previousVisible) {
168
+ const before = previousQueue.map((batch)=>JSON.stringify(batch));
169
+ const after = queue.map((batch)=>JSON.stringify(batch));
170
+ if (before.length === after.length && before.every((id, index)=>id === after[index]) && sameLayerText(base, previousBase)) {
171
+ return {
172
+ documents: previousVisible.documents,
173
+ binaryTargets: previousVisible.binaryTargets,
174
+ revisions: replayRevisions(base.revisions, queue)
175
+ };
176
+ }
177
+ const affected = new Set();
178
+ const paths = new Set([
179
+ ...Object.keys(base.documents),
180
+ ...Object.keys(previousBase.documents),
181
+ ...Object.keys(base.revisions),
182
+ ...Object.keys(previousBase.revisions),
183
+ ...base.binaryTargets,
184
+ ...previousBase.binaryTargets
185
+ ]);
186
+ for (const path of paths){
187
+ if (base.documents[path] !== previousBase.documents[path] || base.revisions[path] !== previousBase.revisions[path] || base.binaryTargets.includes(path) !== previousBase.binaryTargets.includes(path)) affected.add(path);
188
+ }
189
+ const oldIds = new Set(before);
190
+ const newIds = new Set(after);
191
+ for (const batch of previousQueue){
192
+ if (!newIds.has(JSON.stringify(batch))) for (const path of pathsOf(batch))affected.add(path);
193
+ }
194
+ for (const batch of queue){
195
+ if (!oldIds.has(JSON.stringify(batch))) for (const path of pathsOf(batch))affected.add(path);
196
+ }
197
+ let expanded = true;
198
+ while(expanded){
199
+ expanded = false;
200
+ for (const batch of queue){
201
+ const touched = pathsOf(batch);
202
+ if (!touched.some((path)=>affected.has(path))) continue;
203
+ for (const path of touched){
204
+ if (affected.has(path)) continue;
205
+ affected.add(path);
206
+ expanded = true;
207
+ }
208
+ }
209
+ }
210
+ const documents = {};
211
+ const revisions = {};
212
+ for (const path of affected){
213
+ if (base.documents[path] !== undefined) documents[path] = base.documents[path];
214
+ if (base.revisions[path] !== undefined) revisions[path] = base.revisions[path];
215
+ }
216
+ const staged = overlay({
217
+ documents,
218
+ revisions,
219
+ binaryTargets: base.binaryTargets.filter((path)=>affected.has(path))
220
+ }, queue.filter((batch)=>pathsOf(batch).some((path)=>affected.has(path))));
221
+ const mergedDocuments = {
222
+ ...previousVisible.documents
223
+ };
224
+ const mergedRevisions = {
225
+ ...previousVisible.revisions
226
+ };
227
+ const mergedTargets = new Set(previousVisible.binaryTargets);
228
+ for (const path of affected){
229
+ delete mergedDocuments[path];
230
+ delete mergedRevisions[path];
231
+ mergedTargets.delete(path);
232
+ }
233
+ Object.assign(mergedDocuments, staged.documents);
234
+ Object.assign(mergedRevisions, staged.revisions);
235
+ for (const path of staged.binaryTargets)mergedTargets.add(path);
236
+ return {
237
+ documents: mergedDocuments,
238
+ revisions: mergedRevisions,
239
+ binaryTargets: [
240
+ ...mergedTargets
241
+ ].sort()
242
+ };
243
+ }
138
244
 
139
245
  //# sourceMappingURL=overlay.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["/workspace/packages/mdruntime/src/overlay.ts"],"sourcesContent":["import { apply, parse, serialize, type Document } from '@agentshouse/mdmodel';\nimport type { Change, ChangeBatch, Precondition } from './change.js';\n\nexport type Layer = {\n documents: Readonly<Record<string, string>>;\n binaryTargets: readonly string[];\n revisions: Readonly<Record<string, string>>;\n};\n\ntype Staged = {\n documents: Record<string, string>;\n binaryTargets: Set<string>;\n revisions: Record<string, string>;\n};\n\ntype Priors = {\n field(path: string, name: string): unknown;\n section(path: string, name: string): string;\n preamble(path: string): string;\n};\n\nconst EMPTY_FRONTMATTER = '---\\n---\\n';\n\nfunction at(path: string, name: string) {\n return `${path} ${name}`;\n}\n\nfunction priorsOf(preconditions: readonly Precondition[]): Priors {\n const fields = new Map<string, unknown>();\n const sections = new Map<string, string>();\n const preambles = new Map<string, string>();\n for (const precondition of preconditions) {\n if (precondition.kind === 'field') {\n fields.set(at(precondition.path, precondition.name), precondition.value);\n }\n if (precondition.kind === 'section') {\n sections.set(at(precondition.path, precondition.name), precondition.value);\n }\n if (precondition.kind === 'preamble') {\n preambles.set(precondition.path, precondition.value);\n }\n }\n return {\n field: (path, name) => fields.get(at(path, name)),\n section: (path, name) => sections.get(at(path, name)) ?? '',\n preamble: (path) => preambles.get(path) ?? '',\n };\n}\n\nfunction compose(\n fields: Readonly<Record<string, unknown>>,\n sections: Readonly<Record<string, string>>,\n): string {\n const body = Object.entries(sections)\n .map(([name, value]) => `\\n## ${name}\\n${value}`)\n .join('');\n const skeleton = `${EMPTY_FRONTMATTER}${body}`;\n const opened = parse(skeleton);\n if (!opened.ok) return skeleton;\n let document: Document = opened.document;\n for (const [name, value] of Object.entries(fields)) {\n const next = apply(document, { kind: 'field', name, value, prior: undefined });\n if (next.outcome === 'applied') document = next.document;\n }\n return serialize(document);\n}\n\nfunction edited(document: Document, change: Change, priors: Priors) {\n if (change.kind === 'field') {\n return apply(document, {\n kind: 'field',\n name: change.name,\n value: change.value,\n prior: priors.field(change.path, change.name),\n });\n }\n if (change.kind === 'preamble') {\n return apply(document, {\n kind: 'preamble',\n value: change.value,\n prior: priors.preamble(change.path),\n });\n }\n if (change.kind !== 'section') return null;\n return apply(document, {\n kind: 'section',\n name: change.name,\n value: change.value,\n prior: priors.section(change.path, change.name),\n });\n}\n\nfunction edit(staged: Staged, change: Change, priors: Priors) {\n const text = staged.documents[change.path];\n if (text === undefined) return;\n const parsed = parse(text, change.path);\n if (!parsed.ok) return;\n const next = edited(parsed.document, change, priors);\n if (next?.outcome === 'applied') staged.documents[change.path] = serialize(next.document);\n}\n\nfunction relocate(staged: Staged, from: string, to: string) {\n const text = staged.documents[from];\n if (text !== undefined) {\n delete staged.documents[from];\n staged.documents[to] = text;\n } else if (staged.binaryTargets.delete(from)) {\n staged.binaryTargets.add(to);\n } else {\n return;\n }\n const revision = staged.revisions[from];\n if (revision === undefined) return;\n delete staged.revisions[from];\n staged.revisions[to] = revision;\n}\n\nfunction erase(staged: Staged, path: string) {\n delete staged.documents[path];\n delete staged.revisions[path];\n staged.binaryTargets.delete(path);\n}\n\nfunction stage(staged: Staged, change: Change, priors: Priors) {\n if (change.kind === 'field' || change.kind === 'section' || change.kind === 'preamble') {\n edit(staged, change, priors);\n return;\n }\n if (change.kind === 'create') {\n staged.documents[change.path] = compose(change.fields, change.sections);\n return;\n }\n if (change.kind === 'replace') {\n if (staged.documents[change.path] === undefined) return;\n staged.documents[change.path] = change.content;\n return;\n }\n if (change.kind === 'move') {\n relocate(staged, change.path, change.to);\n return;\n }\n erase(staged, change.path);\n}\n\nexport function overlay(base: Layer, queue: readonly ChangeBatch[]): Layer {\n const staged: Staged = {\n documents: { ...base.documents },\n binaryTargets: new Set(base.binaryTargets),\n revisions: { ...base.revisions },\n };\n for (const batch of queue) {\n const priors = priorsOf(batch.preconditions);\n for (const change of batch.changes) stage(staged, change, priors);\n }\n return {\n documents: staged.documents,\n binaryTargets: [...staged.binaryTargets].sort(),\n revisions: staged.revisions,\n };\n}\n"],"names":["apply","parse","serialize","EMPTY_FRONTMATTER","at","path","name","priorsOf","preconditions","fields","Map","sections","preambles","precondition","kind","set","value","field","get","section","preamble","compose","body","Object","entries","map","join","skeleton","opened","ok","document","next","prior","undefined","outcome","edited","change","priors","edit","staged","text","documents","parsed","relocate","from","to","binaryTargets","delete","add","revision","revisions","erase","stage","content","overlay","base","queue","Set","batch","changes","sort"],"mappings":"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"}
1
+ {"version":3,"sources":["/workspace/packages/mdruntime/src/overlay.ts"],"sourcesContent":["import { apply, parse, serialize, type Document } from '@agentshouse/mdmodel';\nimport type { Change, ChangeBatch, Precondition } from './change.js';\n\nexport type Layer = {\n documents: Readonly<Record<string, string>>;\n binaryTargets: readonly string[];\n revisions: Readonly<Record<string, string>>;\n};\n\ntype Staged = {\n documents: Record<string, string>;\n binaryTargets: Set<string>;\n revisions: Record<string, string>;\n};\n\ntype Priors = {\n field(path: string, name: string): unknown;\n section(path: string, name: string): string;\n preamble(path: string): string;\n};\n\nconst EMPTY_FRONTMATTER = '---\\n---\\n';\n\nfunction at(path: string, name: string) {\n return `${path} ${name}`;\n}\n\nfunction priorsOf(preconditions: readonly Precondition[]): Priors {\n const fields = new Map<string, unknown>();\n const sections = new Map<string, string>();\n const preambles = new Map<string, string>();\n for (const precondition of preconditions) {\n if (precondition.kind === 'field') {\n fields.set(at(precondition.path, precondition.name), precondition.value);\n }\n if (precondition.kind === 'section') {\n sections.set(at(precondition.path, precondition.name), precondition.value);\n }\n if (precondition.kind === 'preamble') {\n preambles.set(precondition.path, precondition.value);\n }\n }\n return {\n field: (path, name) => fields.get(at(path, name)),\n section: (path, name) => sections.get(at(path, name)) ?? '',\n preamble: (path) => preambles.get(path) ?? '',\n };\n}\n\nfunction compose(\n fields: Readonly<Record<string, unknown>>,\n sections: Readonly<Record<string, string>>,\n): string {\n const body = Object.entries(sections)\n .map(([name, value]) => `\\n## ${name}\\n${value}`)\n .join('');\n const skeleton = `${EMPTY_FRONTMATTER}${body}`;\n const opened = parse(skeleton);\n if (!opened.ok) return skeleton;\n let document: Document = opened.document;\n for (const [name, value] of Object.entries(fields)) {\n const next = apply(document, { kind: 'field', name, value, prior: undefined });\n if (next.outcome === 'applied') document = next.document;\n }\n return serialize(document);\n}\n\nfunction edited(document: Document, change: Change, priors: Priors) {\n if (change.kind === 'field') {\n return apply(document, {\n kind: 'field',\n name: change.name,\n value: change.value,\n prior: priors.field(change.path, change.name),\n });\n }\n if (change.kind === 'preamble') {\n return apply(document, {\n kind: 'preamble',\n value: change.value,\n prior: priors.preamble(change.path),\n });\n }\n if (change.kind !== 'section') return null;\n return apply(document, {\n kind: 'section',\n name: change.name,\n value: change.value,\n prior: priors.section(change.path, change.name),\n });\n}\n\nfunction edit(staged: Staged, change: Change, priors: Priors) {\n const text = staged.documents[change.path];\n if (text === undefined) return;\n const parsed = parse(text, change.path);\n if (!parsed.ok) return;\n const next = edited(parsed.document, change, priors);\n if (next?.outcome === 'applied') staged.documents[change.path] = serialize(next.document);\n}\n\nfunction relocate(staged: Staged, from: string, to: string) {\n const text = staged.documents[from];\n if (text !== undefined) {\n delete staged.documents[from];\n staged.documents[to] = text;\n } else if (staged.binaryTargets.delete(from)) {\n staged.binaryTargets.add(to);\n } else {\n return;\n }\n const revision = staged.revisions[from];\n if (revision === undefined) return;\n delete staged.revisions[from];\n staged.revisions[to] = revision;\n}\n\nfunction erase(staged: Staged, path: string) {\n delete staged.documents[path];\n delete staged.revisions[path];\n staged.binaryTargets.delete(path);\n}\n\nfunction stage(staged: Staged, change: Change, priors: Priors) {\n if (change.kind === 'field' || change.kind === 'section' || change.kind === 'preamble') {\n edit(staged, change, priors);\n return;\n }\n if (change.kind === 'create') {\n staged.documents[change.path] =\n 'content' in change ? change.content : compose(change.fields, change.sections);\n return;\n }\n if (change.kind === 'replace') {\n if (staged.documents[change.path] === undefined) return;\n staged.documents[change.path] = change.content;\n return;\n }\n if (change.kind === 'move') {\n relocate(staged, change.path, change.to);\n return;\n }\n erase(staged, change.path);\n}\n\nexport function overlay(base: Layer, queue: readonly ChangeBatch[]): Layer {\n const staged: Staged = {\n documents: { ...base.documents },\n binaryTargets: new Set(base.binaryTargets),\n revisions: { ...base.revisions },\n };\n for (const batch of queue) {\n const priors = priorsOf(batch.preconditions);\n for (const change of batch.changes) stage(staged, change, priors);\n }\n return {\n documents: staged.documents,\n binaryTargets: [...staged.binaryTargets].sort(),\n revisions: staged.revisions,\n };\n}\n\nfunction pathsOf(batch: ChangeBatch): readonly string[] {\n return batch.changes.flatMap((change) =>\n change.kind === 'move' ? [change.path, change.to] : [change.path],\n );\n}\n\nexport function sameLayerText(left: Layer, right: Layer): boolean {\n const paths = Object.keys(left.documents);\n return (\n paths.length === Object.keys(right.documents).length &&\n paths.every((path) => left.documents[path] === right.documents[path]) &&\n left.binaryTargets.length === right.binaryTargets.length &&\n left.binaryTargets.every((path) => right.binaryTargets.includes(path))\n );\n}\n\nfunction replayRevisions(\n base: Readonly<Record<string, string>>,\n queue: readonly ChangeBatch[],\n): Readonly<Record<string, string>> {\n const revisions = { ...base };\n for (const batch of queue) {\n for (const change of batch.changes) {\n if (change.kind === 'remove') {\n delete revisions[change.path];\n } else if (change.kind === 'move') {\n const revision = revisions[change.path];\n delete revisions[change.path];\n if (revision !== undefined) revisions[change.to] = revision;\n }\n }\n }\n return revisions;\n}\n\nexport function overlayChanged(\n base: Layer,\n queue: readonly ChangeBatch[],\n previousBase: Layer,\n previousQueue: readonly ChangeBatch[],\n previousVisible: Layer,\n): Layer {\n const before = previousQueue.map((batch) => JSON.stringify(batch));\n const after = queue.map((batch) => JSON.stringify(batch));\n if (\n before.length === after.length &&\n before.every((id, index) => id === after[index]) &&\n sameLayerText(base, previousBase)\n ) {\n return {\n documents: previousVisible.documents,\n binaryTargets: previousVisible.binaryTargets,\n revisions: replayRevisions(base.revisions, queue),\n };\n }\n const affected = new Set<string>();\n const paths = new Set([\n ...Object.keys(base.documents),\n ...Object.keys(previousBase.documents),\n ...Object.keys(base.revisions),\n ...Object.keys(previousBase.revisions),\n ...base.binaryTargets,\n ...previousBase.binaryTargets,\n ]);\n for (const path of paths) {\n if (\n base.documents[path] !== previousBase.documents[path] ||\n base.revisions[path] !== previousBase.revisions[path] ||\n base.binaryTargets.includes(path) !== previousBase.binaryTargets.includes(path)\n )\n affected.add(path);\n }\n const oldIds = new Set(before);\n const newIds = new Set(after);\n for (const batch of previousQueue) {\n if (!newIds.has(JSON.stringify(batch))) for (const path of pathsOf(batch)) affected.add(path);\n }\n for (const batch of queue) {\n if (!oldIds.has(JSON.stringify(batch))) for (const path of pathsOf(batch)) affected.add(path);\n }\n let expanded = true;\n while (expanded) {\n expanded = false;\n for (const batch of queue) {\n const touched = pathsOf(batch);\n if (!touched.some((path) => affected.has(path))) continue;\n for (const path of touched) {\n if (affected.has(path)) continue;\n affected.add(path);\n expanded = true;\n }\n }\n }\n const documents: Record<string, string> = {};\n const revisions: Record<string, string> = {};\n for (const path of affected) {\n if (base.documents[path] !== undefined) documents[path] = base.documents[path];\n if (base.revisions[path] !== undefined) revisions[path] = base.revisions[path];\n }\n const staged = overlay(\n {\n documents,\n revisions,\n binaryTargets: base.binaryTargets.filter((path) => affected.has(path)),\n },\n queue.filter((batch) => pathsOf(batch).some((path) => affected.has(path))),\n );\n const mergedDocuments = { ...previousVisible.documents };\n const mergedRevisions = { ...previousVisible.revisions };\n const mergedTargets = new Set(previousVisible.binaryTargets);\n for (const path of affected) {\n delete mergedDocuments[path];\n delete mergedRevisions[path];\n mergedTargets.delete(path);\n }\n Object.assign(mergedDocuments, staged.documents);\n Object.assign(mergedRevisions, staged.revisions);\n for (const path of staged.binaryTargets) mergedTargets.add(path);\n return {\n documents: mergedDocuments,\n revisions: mergedRevisions,\n binaryTargets: [...mergedTargets].sort(),\n };\n}\n"],"names":["apply","parse","serialize","EMPTY_FRONTMATTER","at","path","name","priorsOf","preconditions","fields","Map","sections","preambles","precondition","kind","set","value","field","get","section","preamble","compose","body","Object","entries","map","join","skeleton","opened","ok","document","next","prior","undefined","outcome","edited","change","priors","edit","staged","text","documents","parsed","relocate","from","to","binaryTargets","delete","add","revision","revisions","erase","stage","content","overlay","base","queue","Set","batch","changes","sort","pathsOf","flatMap","sameLayerText","left","right","paths","keys","length","every","includes","replayRevisions","overlayChanged","previousBase","previousQueue","previousVisible","before","JSON","stringify","after","id","index","affected","oldIds","newIds","has","expanded","touched","some","filter","mergedDocuments","mergedRevisions","mergedTargets","assign"],"mappings":"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"}
package/dist/paths.d.ts CHANGED
@@ -1,5 +1,4 @@
1
1
  export declare function normalize(path: string): string | null;
2
- export declare function resolve(from: string, reference: string): string | null;
3
2
  export declare function relative(from: string, target: string): string;
4
3
  export declare function beneath(prefix: string, path: string): boolean;
5
4
  export declare function covered(prefixes: readonly string[], path: string): boolean;
@@ -1 +1 @@
1
- {"version":3,"file":"paths.d.ts","sourceRoot":"","sources":["../src/paths.ts"],"names":[],"mappings":"AAKA,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAYrD;AAED,wBAAgB,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAGtE;AAED,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAW7D;AAED,wBAAgB,OAAO,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAE7D;AAED,wBAAgB,OAAO,CAAC,QAAQ,EAAE,SAAS,MAAM,EAAE,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAK1E"}
1
+ {"version":3,"file":"paths.d.ts","sourceRoot":"","sources":["../src/paths.ts"],"names":[],"mappings":"AAKA,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAYrD;AAED,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAW7D;AAED,wBAAgB,OAAO,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAE7D;AAED,wBAAgB,OAAO,CAAC,QAAQ,EAAE,SAAS,MAAM,EAAE,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAK1E"}
package/dist/paths.js CHANGED
@@ -15,10 +15,6 @@ export function normalize(path) {
15
15
  }
16
16
  return parts.join('/');
17
17
  }
18
- export function resolve(from, reference) {
19
- const base = dirname(from);
20
- return normalize(base === '' ? reference : `${base}/${reference}`);
21
- }
22
18
  export function relative(from, target) {
23
19
  const base = dirname(from).split('/').filter((part)=>part !== '');
24
20
  const parts = target.split('/');
package/dist/paths.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["/workspace/packages/mdruntime/src/paths.ts"],"sourcesContent":["function dirname(path: string): string {\n const index = path.lastIndexOf('/');\n return index === -1 ? '' : path.slice(0, index);\n}\n\nexport function normalize(path: string): string | null {\n const parts: string[] = [];\n for (const part of path.split('/')) {\n if (part === '' || part === '.') continue;\n if (part === '..') {\n if (parts.length === 0) return null;\n parts.pop();\n continue;\n }\n parts.push(part);\n }\n return parts.join('/');\n}\n\nexport function resolve(from: string, reference: string): string | null {\n const base = dirname(from);\n return normalize(base === '' ? reference : `${base}/${reference}`);\n}\n\nexport function relative(from: string, target: string): string {\n const base = dirname(from)\n .split('/')\n .filter((part) => part !== '');\n const parts = target.split('/');\n let shared = 0;\n while (shared < base.length && shared + 1 < parts.length && base[shared] === parts[shared]) {\n shared += 1;\n }\n const up = Array.from({ length: base.length - shared }, () => '..');\n return [...up, ...parts.slice(shared)].join('/');\n}\n\nexport function beneath(prefix: string, path: string): boolean {\n return path === prefix || path.startsWith(`${prefix}/`);\n}\n\nexport function covered(prefixes: readonly string[], path: string): boolean {\n return prefixes.some((prefix) => {\n const normalized = normalize(prefix);\n return normalized !== null && (normalized === '' || beneath(normalized, path));\n });\n}\n"],"names":["dirname","path","index","lastIndexOf","slice","normalize","parts","part","split","length","pop","push","join","resolve","from","reference","base","relative","target","filter","shared","up","Array","beneath","prefix","startsWith","covered","prefixes","some","normalized"],"mappings":"AAAA,SAASA,QAAQC,IAAY;IAC3B,MAAMC,QAAQD,KAAKE,WAAW,CAAC;IAC/B,OAAOD,UAAU,CAAC,IAAI,KAAKD,KAAKG,KAAK,CAAC,GAAGF;AAC3C;AAEA,OAAO,SAASG,UAAUJ,IAAY;IACpC,MAAMK,QAAkB,EAAE;IAC1B,KAAK,MAAMC,QAAQN,KAAKO,KAAK,CAAC,KAAM;QAClC,IAAID,SAAS,MAAMA,SAAS,KAAK;QACjC,IAAIA,SAAS,MAAM;YACjB,IAAID,MAAMG,MAAM,KAAK,GAAG,OAAO;YAC/BH,MAAMI,GAAG;YACT;QACF;QACAJ,MAAMK,IAAI,CAACJ;IACb;IACA,OAAOD,MAAMM,IAAI,CAAC;AACpB;AAEA,OAAO,SAASC,QAAQC,IAAY,EAAEC,SAAiB;IACrD,MAAMC,OAAOhB,QAAQc;IACrB,OAAOT,UAAUW,SAAS,KAAKD,YAAY,GAAGC,KAAK,CAAC,EAAED,WAAW;AACnE;AAEA,OAAO,SAASE,SAASH,IAAY,EAAEI,MAAc;IACnD,MAAMF,OAAOhB,QAAQc,MAClBN,KAAK,CAAC,KACNW,MAAM,CAAC,CAACZ,OAASA,SAAS;IAC7B,MAAMD,QAAQY,OAAOV,KAAK,CAAC;IAC3B,IAAIY,SAAS;IACb,MAAOA,SAASJ,KAAKP,MAAM,IAAIW,SAAS,IAAId,MAAMG,MAAM,IAAIO,IAAI,CAACI,OAAO,KAAKd,KAAK,CAACc,OAAO,CAAE;QAC1FA,UAAU;IACZ;IACA,MAAMC,KAAKC,MAAMR,IAAI,CAAC;QAAEL,QAAQO,KAAKP,MAAM,GAAGW;IAAO,GAAG,IAAM;IAC9D,OAAO;WAAIC;WAAOf,MAAMF,KAAK,CAACgB;KAAQ,CAACR,IAAI,CAAC;AAC9C;AAEA,OAAO,SAASW,QAAQC,MAAc,EAAEvB,IAAY;IAClD,OAAOA,SAASuB,UAAUvB,KAAKwB,UAAU,CAAC,GAAGD,OAAO,CAAC,CAAC;AACxD;AAEA,OAAO,SAASE,QAAQC,QAA2B,EAAE1B,IAAY;IAC/D,OAAO0B,SAASC,IAAI,CAAC,CAACJ;QACpB,MAAMK,aAAaxB,UAAUmB;QAC7B,OAAOK,eAAe,QAASA,CAAAA,eAAe,MAAMN,QAAQM,YAAY5B,KAAI;IAC9E;AACF"}
1
+ {"version":3,"sources":["/workspace/packages/mdruntime/src/paths.ts"],"sourcesContent":["function dirname(path: string): string {\n const index = path.lastIndexOf('/');\n return index === -1 ? '' : path.slice(0, index);\n}\n\nexport function normalize(path: string): string | null {\n const parts: string[] = [];\n for (const part of path.split('/')) {\n if (part === '' || part === '.') continue;\n if (part === '..') {\n if (parts.length === 0) return null;\n parts.pop();\n continue;\n }\n parts.push(part);\n }\n return parts.join('/');\n}\n\nexport function relative(from: string, target: string): string {\n const base = dirname(from)\n .split('/')\n .filter((part) => part !== '');\n const parts = target.split('/');\n let shared = 0;\n while (shared < base.length && shared + 1 < parts.length && base[shared] === parts[shared]) {\n shared += 1;\n }\n const up = Array.from({ length: base.length - shared }, () => '..');\n return [...up, ...parts.slice(shared)].join('/');\n}\n\nexport function beneath(prefix: string, path: string): boolean {\n return path === prefix || path.startsWith(`${prefix}/`);\n}\n\nexport function covered(prefixes: readonly string[], path: string): boolean {\n return prefixes.some((prefix) => {\n const normalized = normalize(prefix);\n return normalized !== null && (normalized === '' || beneath(normalized, path));\n });\n}\n"],"names":["dirname","path","index","lastIndexOf","slice","normalize","parts","part","split","length","pop","push","join","relative","from","target","base","filter","shared","up","Array","beneath","prefix","startsWith","covered","prefixes","some","normalized"],"mappings":"AAAA,SAASA,QAAQC,IAAY;IAC3B,MAAMC,QAAQD,KAAKE,WAAW,CAAC;IAC/B,OAAOD,UAAU,CAAC,IAAI,KAAKD,KAAKG,KAAK,CAAC,GAAGF;AAC3C;AAEA,OAAO,SAASG,UAAUJ,IAAY;IACpC,MAAMK,QAAkB,EAAE;IAC1B,KAAK,MAAMC,QAAQN,KAAKO,KAAK,CAAC,KAAM;QAClC,IAAID,SAAS,MAAMA,SAAS,KAAK;QACjC,IAAIA,SAAS,MAAM;YACjB,IAAID,MAAMG,MAAM,KAAK,GAAG,OAAO;YAC/BH,MAAMI,GAAG;YACT;QACF;QACAJ,MAAMK,IAAI,CAACJ;IACb;IACA,OAAOD,MAAMM,IAAI,CAAC;AACpB;AAEA,OAAO,SAASC,SAASC,IAAY,EAAEC,MAAc;IACnD,MAAMC,OAAOhB,QAAQc,MAClBN,KAAK,CAAC,KACNS,MAAM,CAAC,CAACV,OAASA,SAAS;IAC7B,MAAMD,QAAQS,OAAOP,KAAK,CAAC;IAC3B,IAAIU,SAAS;IACb,MAAOA,SAASF,KAAKP,MAAM,IAAIS,SAAS,IAAIZ,MAAMG,MAAM,IAAIO,IAAI,CAACE,OAAO,KAAKZ,KAAK,CAACY,OAAO,CAAE;QAC1FA,UAAU;IACZ;IACA,MAAMC,KAAKC,MAAMN,IAAI,CAAC;QAAEL,QAAQO,KAAKP,MAAM,GAAGS;IAAO,GAAG,IAAM;IAC9D,OAAO;WAAIC;WAAOb,MAAMF,KAAK,CAACc;KAAQ,CAACN,IAAI,CAAC;AAC9C;AAEA,OAAO,SAASS,QAAQC,MAAc,EAAErB,IAAY;IAClD,OAAOA,SAASqB,UAAUrB,KAAKsB,UAAU,CAAC,GAAGD,OAAO,CAAC,CAAC;AACxD;AAEA,OAAO,SAASE,QAAQC,QAA2B,EAAExB,IAAY;IAC/D,OAAOwB,SAASC,IAAI,CAAC,CAACJ;QACpB,MAAMK,aAAatB,UAAUiB;QAC7B,OAAOK,eAAe,QAASA,CAAAA,eAAe,MAAMN,QAAQM,YAAY1B,KAAI;IAC9E;AACF"}
@@ -0,0 +1,209 @@
1
+ import type { Definition } from '@agentshouse/mdmodel';
2
+ export type Value = string | number | boolean | null;
3
+ export type Predicate = Value | {
4
+ $eq: Value;
5
+ } | {
6
+ $ne: Value;
7
+ } | {
8
+ $in: readonly Value[];
9
+ } | {
10
+ $nin: readonly Value[];
11
+ } | {
12
+ $gt?: Value;
13
+ $gte?: Value;
14
+ $lt?: Value;
15
+ $lte?: Value;
16
+ } | {
17
+ $all: readonly Value[];
18
+ } | {
19
+ $size: number;
20
+ } | {
21
+ $exists: boolean;
22
+ };
23
+ export type Where = {
24
+ $and?: readonly Where[];
25
+ $or?: readonly Where[];
26
+ [field: string]: Predicate | readonly Where[] | undefined;
27
+ };
28
+ export type Related = {
29
+ types?: readonly string[];
30
+ where?: Where;
31
+ pathPrefix?: string;
32
+ };
33
+ export type Filter = {
34
+ rooms?: readonly string[];
35
+ types?: readonly string[];
36
+ where?: Where;
37
+ pathPrefix?: string;
38
+ hop?: Related & {
39
+ field: string;
40
+ };
41
+ backlinks?: Related & {
42
+ field?: string;
43
+ };
44
+ };
45
+ export type Key = 'room' | 'path' | 'type' | {
46
+ field: string;
47
+ };
48
+ export type Select = 'all' | {
49
+ fields?: 'all' | readonly string[];
50
+ sections?: 'all' | readonly string[];
51
+ preamble?: true;
52
+ markdown?: true;
53
+ backlinks?: true;
54
+ };
55
+ export type OrderOptions = {
56
+ nulls?: 'first' | 'last';
57
+ stringSort?: 'lexical' | 'locale';
58
+ locale?: string;
59
+ localeOptions?: Readonly<Record<string, unknown>>;
60
+ };
61
+ export type Direction = 'asc' | 'desc';
62
+ export type DocumentQuery = Filter & {
63
+ select: Select;
64
+ orderBy?: readonly ({
65
+ by: Key;
66
+ direction?: Direction;
67
+ } & OrderOptions)[];
68
+ limit?: number;
69
+ };
70
+ export type GroupQuery = Filter & {
71
+ groupBy: readonly Exclude<Key, 'path'>[];
72
+ orderBy?: readonly {
73
+ by: 'count' | Exclude<Key, 'path'>;
74
+ direction?: Direction;
75
+ }[];
76
+ limit?: number;
77
+ };
78
+ export type LocalQuery = DocumentQuery | GroupQuery;
79
+ export type Backlink = {
80
+ path: string;
81
+ type: string;
82
+ field: string;
83
+ };
84
+ export type QueryDocument = {
85
+ room: string;
86
+ path: string;
87
+ type?: string;
88
+ fields?: Readonly<Record<string, unknown>>;
89
+ sections?: Readonly<Record<string, string>>;
90
+ preamble?: string;
91
+ markdown?: string;
92
+ backlinks?: readonly Backlink[];
93
+ };
94
+ export type QueryGroup = {
95
+ key: readonly unknown[];
96
+ count: number;
97
+ };
98
+ export type DocumentResult = {
99
+ documents: readonly QueryDocument[];
100
+ };
101
+ export type GroupResult = {
102
+ groups: readonly QueryGroup[];
103
+ };
104
+ export type QueryResult = DocumentResult | GroupResult;
105
+ export type QueryErrorCode = 'invalid-query' | 'unknown-type' | 'unknown-field' | 'wrong-kind';
106
+ export type RoomFacts = {
107
+ locator: string;
108
+ available: boolean;
109
+ types: readonly Definition[];
110
+ };
111
+ export type HeldRooms = {
112
+ listed: boolean;
113
+ rooms: readonly RoomFacts[];
114
+ };
115
+ export type Test = {
116
+ op: 'eq';
117
+ value: Value;
118
+ } | {
119
+ op: 'ne';
120
+ value: Value;
121
+ } | {
122
+ op: 'in';
123
+ values: readonly Value[];
124
+ } | {
125
+ op: 'nin';
126
+ values: readonly Value[];
127
+ } | {
128
+ op: 'range';
129
+ bounds: readonly (readonly ['gt' | 'gte' | 'lt' | 'lte', Value])[];
130
+ } | {
131
+ op: 'all';
132
+ values: readonly Value[];
133
+ } | {
134
+ op: 'size';
135
+ size: number;
136
+ } | {
137
+ op: 'exists';
138
+ exists: boolean;
139
+ };
140
+ export type Condition = {
141
+ every: readonly Condition[];
142
+ } | {
143
+ some: readonly Condition[];
144
+ } | {
145
+ field: string;
146
+ test: Test;
147
+ };
148
+ export type Scope = {
149
+ types: readonly string[] | null;
150
+ where: Condition | null;
151
+ pathPrefix: string | null;
152
+ };
153
+ export type KeyPlan = {
154
+ of: 'room';
155
+ } | {
156
+ of: 'path';
157
+ } | {
158
+ of: 'type';
159
+ } | {
160
+ of: 'field';
161
+ field: string;
162
+ };
163
+ export type DocumentShape = {
164
+ kind: 'documents';
165
+ fields: 'all' | readonly string[] | null;
166
+ sections: 'all' | readonly string[] | null;
167
+ preamble: boolean;
168
+ markdown: boolean;
169
+ backlinks: boolean;
170
+ orderBy: readonly {
171
+ key: KeyPlan;
172
+ options: OrderOptions & {
173
+ direction: Direction;
174
+ };
175
+ }[];
176
+ };
177
+ export type GroupShape = {
178
+ kind: 'groups';
179
+ groupBy: readonly KeyPlan[];
180
+ orderBy: readonly {
181
+ by: 'count' | number;
182
+ direction: Direction;
183
+ }[];
184
+ };
185
+ export type Plan = {
186
+ rooms: readonly string[] | null;
187
+ root: Scope;
188
+ hop: (Scope & {
189
+ field: string;
190
+ }) | null;
191
+ backlinks: (Scope & {
192
+ field: string | null;
193
+ }) | null;
194
+ shape: DocumentShape | GroupShape;
195
+ limit: number | null;
196
+ };
197
+ export declare class QueryError extends Error {
198
+ constructor(code: QueryErrorCode, at: string, problem: string);
199
+ }
200
+ type Entries = Readonly<Record<string, unknown>>;
201
+ export declare function invalid(at: string, problem: string): never;
202
+ export declare function plain(value: unknown): value is Entries;
203
+ export declare function known(value: Entries, allowed: readonly string[], at: string): void;
204
+ export declare function planOf(input: unknown, facts: HeldRooms): Plan;
205
+ export declare function limitOf(input: unknown): number | null;
206
+ export declare function filterOf(input: unknown, facts: HeldRooms): Plan;
207
+ export declare function identityOf(plan: Plan): string;
208
+ export {};
209
+ //# sourceMappingURL=query.d.ts.map