@agentshouse/mdruntime 0.1.0-cbbae1fff01c6 → 0.1.0-cc00e9289ddf4
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/README.md +17 -15
- package/dist/acceptance.d.ts.map +1 -1
- package/dist/acceptance.js +14 -23
- package/dist/act-lanes.d.ts +30 -0
- package/dist/act-lanes.d.ts.map +1 -0
- package/dist/act-lanes.js +225 -0
- package/dist/actions.d.ts +8 -2
- package/dist/actions.d.ts.map +1 -1
- package/dist/actions.js +114 -63
- package/dist/adapter.d.ts +30 -12
- package/dist/adapter.d.ts.map +1 -1
- package/dist/attached-model.d.ts +0 -1
- package/dist/attached-model.d.ts.map +1 -1
- package/dist/attached-model.js +0 -5
- package/dist/chat-types.d.ts +0 -2
- package/dist/chat-types.d.ts.map +1 -1
- package/dist/chat-types.js +0 -2
- package/dist/client.d.ts +8 -18
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +27 -15
- package/dist/compile.d.ts +2 -0
- package/dist/compile.d.ts.map +1 -1
- package/dist/compile.js +17 -4
- package/dist/connection.d.ts.map +1 -1
- package/dist/connection.js +15 -13
- package/dist/conversation-live.d.ts +23 -8
- package/dist/conversation-live.d.ts.map +1 -1
- package/dist/conversation-live.js +21 -9
- package/dist/conversation-row.d.ts +2 -0
- package/dist/conversation-row.d.ts.map +1 -1
- package/dist/conversation-row.js +2 -0
- package/dist/conversation.d.ts +27 -5
- package/dist/conversation.d.ts.map +1 -1
- package/dist/conversation.js +279 -168
- package/dist/discovery.d.ts.map +1 -1
- package/dist/discovery.js +8 -6
- package/dist/durability.d.ts +4 -0
- package/dist/durability.d.ts.map +1 -1
- package/dist/durability.js +4 -0
- package/dist/entry.js +1 -1
- package/dist/expectation.d.ts +25 -14
- package/dist/expectation.d.ts.map +1 -1
- package/dist/expectation.js +51 -20
- package/dist/failure.d.ts +2 -0
- package/dist/failure.d.ts.map +1 -1
- package/dist/failure.js +3 -0
- package/dist/figures.d.ts.map +1 -1
- package/dist/figures.js +4 -2
- package/dist/file.d.ts.map +1 -1
- package/dist/file.js +2 -1
- package/dist/host.d.ts +1 -0
- package/dist/host.d.ts.map +1 -1
- package/dist/host.js +39 -11
- package/dist/index.d.ts +11 -8
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +9 -6
- package/dist/install.d.ts +10 -4
- package/dist/install.d.ts.map +1 -1
- package/dist/install.js +45 -46
- package/dist/lifecycle.d.ts.map +1 -1
- package/dist/lifecycle.js +22 -16
- package/dist/listing.d.ts +7 -3
- package/dist/listing.d.ts.map +1 -1
- package/dist/listing.js +26 -13
- package/dist/live.d.ts +5 -3
- package/dist/live.d.ts.map +1 -1
- package/dist/live.js +71 -30
- package/dist/locks.d.ts.map +1 -1
- package/dist/locks.js +2 -3
- package/dist/lost.d.ts.map +1 -1
- package/dist/lost.js +2 -3
- package/dist/media.d.ts.map +1 -1
- package/dist/media.js +7 -10
- package/dist/memory.d.ts +3 -1
- package/dist/memory.d.ts.map +1 -1
- package/dist/memory.js +50 -22
- package/dist/messages.d.ts +12 -3
- package/dist/messages.d.ts.map +1 -1
- package/dist/messages.js +24 -10
- package/dist/models.d.ts.map +1 -1
- package/dist/models.js +5 -8
- package/dist/observation.d.ts +27 -12
- package/dist/observation.d.ts.map +1 -1
- package/dist/observation.js +173 -69
- package/dist/opening.d.ts.map +1 -1
- package/dist/opening.js +3 -9
- package/dist/outcome.d.ts +7 -0
- package/dist/outcome.d.ts.map +1 -1
- package/dist/outcome.js +23 -2
- package/dist/overlay.d.ts +3 -0
- package/dist/overlay.d.ts.map +1 -1
- package/dist/overlay.js +8 -4
- package/dist/page-metadata.d.ts +8 -0
- package/dist/page-metadata.d.ts.map +1 -0
- package/dist/page-metadata.js +19 -0
- package/dist/parts.d.ts +2 -9
- package/dist/parts.d.ts.map +1 -1
- package/dist/parts.js +6 -14
- package/dist/preparation.d.ts +27 -6
- package/dist/preparation.d.ts.map +1 -1
- package/dist/preparation.js +137 -56
- package/dist/presence.d.ts +7 -1
- package/dist/presence.d.ts.map +1 -1
- package/dist/presence.js +22 -9
- package/dist/queries.d.ts +2 -2
- package/dist/queries.d.ts.map +1 -1
- package/dist/queries.js +62 -24
- package/dist/questions.d.ts +0 -5
- package/dist/questions.d.ts.map +1 -1
- package/dist/questions.js +0 -7
- package/dist/queue.d.ts +2 -2
- package/dist/queue.d.ts.map +1 -1
- package/dist/queue.js +25 -30
- package/dist/reach.d.ts +2 -3
- package/dist/reach.d.ts.map +1 -1
- package/dist/reach.js +75 -21
- package/dist/react.d.ts +7 -5
- package/dist/react.d.ts.map +1 -1
- package/dist/react.js +28 -5
- package/dist/readiness.d.ts +9 -3
- package/dist/readiness.d.ts.map +1 -1
- package/dist/readiness.js +3 -5
- package/dist/reads.d.ts +3 -1
- package/dist/reads.d.ts.map +1 -1
- package/dist/reads.js +5 -1
- package/dist/recovery.d.ts +3 -1
- package/dist/recovery.d.ts.map +1 -1
- package/dist/recovery.js +29 -7
- package/dist/refusal.d.ts.map +1 -1
- package/dist/refusal.js +1 -3
- package/dist/retried.d.ts +30 -0
- package/dist/retried.d.ts.map +1 -0
- package/dist/retried.js +72 -0
- package/dist/room-draft.d.ts +2 -2
- package/dist/room-draft.d.ts.map +1 -1
- package/dist/room-draft.js +26 -21
- package/dist/rows.d.ts +2 -0
- package/dist/rows.d.ts.map +1 -1
- package/dist/rows.js +3 -0
- package/dist/runtime.d.ts +2 -2
- package/dist/runtime.d.ts.map +1 -1
- package/dist/save.d.ts +1 -0
- package/dist/save.d.ts.map +1 -1
- package/dist/save.js +105 -55
- package/dist/saves.d.ts.map +1 -1
- package/dist/saves.js +3 -6
- package/dist/seed.d.ts.map +1 -1
- package/dist/seed.js +2 -2
- package/dist/shown.d.ts +3 -2
- package/dist/shown.d.ts.map +1 -1
- package/dist/shown.js +58 -39
- package/dist/socket/lanes.d.ts +12 -4
- package/dist/socket/lanes.d.ts.map +1 -1
- package/dist/socket/lanes.js +34 -8
- package/dist/socket.d.ts +3 -3
- package/dist/socket.d.ts.map +1 -1
- package/dist/socket.js +3 -9
- package/dist/source.d.ts +0 -7
- package/dist/source.d.ts.map +1 -1
- package/dist/store/installs.d.ts +2 -2
- package/dist/store/installs.d.ts.map +1 -1
- package/dist/store/installs.js +10 -4
- package/dist/store/readiness.d.ts +5 -4
- package/dist/store/readiness.d.ts.map +1 -1
- package/dist/store/readiness.js +28 -12
- package/dist/store/records.d.ts +11 -4
- package/dist/store/records.d.ts.map +1 -1
- package/dist/store/records.js +56 -20
- package/dist/store/rooms-shown.d.ts +8 -0
- package/dist/store/rooms-shown.d.ts.map +1 -0
- package/dist/store/rooms-shown.js +13 -0
- package/dist/store.d.ts +9 -6
- package/dist/store.d.ts.map +1 -1
- package/dist/store.js +11 -2
- package/dist/stored.d.ts +24 -13
- package/dist/stored.d.ts.map +1 -1
- package/dist/stored.js +73 -17
- package/dist/surface.d.ts +4 -3
- package/dist/surface.d.ts.map +1 -1
- package/dist/surface.js +12 -13
- package/dist/sync.d.ts.map +1 -1
- package/dist/sync.js +31 -17
- package/dist/tables.d.ts +14 -7
- package/dist/tables.d.ts.map +1 -1
- package/dist/tables.js +36 -15
- package/dist/tallies.d.ts.map +1 -1
- package/dist/tallies.js +1 -2
- package/dist/wire.d.ts +40 -3
- package/dist/wire.d.ts.map +1 -1
- package/dist/wire.js +11 -1
- package/package.json +3 -3
- package/dist/attempt.d.ts +0 -16
- package/dist/attempt.d.ts.map +0 -1
- package/dist/attempt.js +0 -70
- package/dist/job.d.ts +0 -5
- package/dist/job.d.ts.map +0 -1
- package/dist/job.js +0 -7
- package/dist/log.d.ts +0 -6
- package/dist/log.d.ts.map +0 -1
- package/dist/log.js +0 -14
package/dist/live.js
CHANGED
|
@@ -1,27 +1,25 @@
|
|
|
1
|
-
import { changeOf, digestOf, } from './observation.js';
|
|
1
|
+
import { changeOf, digestOf, keyedAt, keyedInto, samePending, unchanged, } from './observation.js';
|
|
2
2
|
import { uncaught } from './failure.js';
|
|
3
|
-
import {
|
|
3
|
+
import { roomsOfReach } from './rows.js';
|
|
4
4
|
function narrowed(plan) {
|
|
5
5
|
return (plan.paths !== null &&
|
|
6
6
|
plan.hop === null &&
|
|
7
7
|
plan.backlinks === null &&
|
|
8
8
|
!(plan.shape.kind === 'documents' && plan.shape.backlinks));
|
|
9
9
|
}
|
|
10
|
-
function
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
return (plan.reach.rooms.includes(locator) ||
|
|
18
|
-
plan.reach.documents.some((document) => roomOfKey(document) === locator));
|
|
10
|
+
export function readerOf(plan) {
|
|
11
|
+
const locked = new Set(plan.locked);
|
|
12
|
+
const named = plan.rooms === null ? null : new Set(plan.rooms);
|
|
13
|
+
const reached = plan.reach === null ? null : roomsOfReach(plan.reach);
|
|
14
|
+
return (locator) => !locked.has(locator) &&
|
|
15
|
+
(named === null || named.has(locator)) &&
|
|
16
|
+
(reached === null || reached.has(locator));
|
|
19
17
|
}
|
|
20
|
-
function affected(plan, set) {
|
|
21
|
-
if (set.rooms.some(
|
|
18
|
+
function affected({ plan, reads }, set) {
|
|
19
|
+
if (set.rooms.some(reads))
|
|
22
20
|
return true;
|
|
23
21
|
const paths = narrowed(plan) ? new Set(plan.paths) : null;
|
|
24
|
-
return set.documents.some(({ locator, path }) => reads(
|
|
22
|
+
return set.documents.some(({ locator, path }) => reads(locator) && (paths === null || path === null || paths.has(path)));
|
|
25
23
|
}
|
|
26
24
|
function shown(entry, held) {
|
|
27
25
|
const cover = entry.cover(held);
|
|
@@ -30,11 +28,13 @@ function shown(entry, held) {
|
|
|
30
28
|
export function createLiveQueries(run, holding) {
|
|
31
29
|
const entries = new Map();
|
|
32
30
|
let closed = false;
|
|
33
|
-
let
|
|
34
|
-
let
|
|
31
|
+
let recoveringNow = false;
|
|
32
|
+
let recoveringAll = false;
|
|
33
|
+
const recovering = new Set();
|
|
35
34
|
function deliver(entry, next) {
|
|
36
35
|
const previous = entry.digest;
|
|
37
36
|
entry.digest = digestOf(next);
|
|
37
|
+
entry.pending = 'pending' in entry.digest ? entry.digest.pending : null;
|
|
38
38
|
entry.covered = JSON.stringify('pending' in next.result ? next.result : next.result.coverage);
|
|
39
39
|
const change = previous === undefined ? null : changeOf(previous, next);
|
|
40
40
|
if (change !== null) {
|
|
@@ -87,58 +87,99 @@ export function createLiveQueries(run, holding) {
|
|
|
87
87
|
}
|
|
88
88
|
})();
|
|
89
89
|
}
|
|
90
|
-
function
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
return;
|
|
90
|
+
function pendingMoved(entry, held, rooms) {
|
|
91
|
+
const { pending } = entry;
|
|
92
|
+
if (pending === null || pending.size === 0 || entry.running || entry.fresh.size > 0) {
|
|
93
|
+
return false;
|
|
94
94
|
}
|
|
95
|
-
|
|
95
|
+
const at = entry.pendingAt(held, rooms);
|
|
96
|
+
const change = at === null ? null : keyedAt(pending, at, samePending);
|
|
97
|
+
if (change === null || change.removed.length === pending.size)
|
|
98
|
+
return false;
|
|
99
|
+
keyedInto(pending, change);
|
|
100
|
+
entry.covered = '';
|
|
101
|
+
if (unchanged(change))
|
|
102
|
+
return true;
|
|
103
|
+
for (const listener of entry.ready)
|
|
104
|
+
listener({ pending: change });
|
|
105
|
+
return true;
|
|
106
|
+
}
|
|
107
|
+
function recovered(locators) {
|
|
108
|
+
if (locators === undefined)
|
|
109
|
+
recoveringAll = true;
|
|
110
|
+
else
|
|
111
|
+
for (const locator of locators)
|
|
112
|
+
recovering.add(locator);
|
|
113
|
+
if (recoveringNow)
|
|
114
|
+
return;
|
|
115
|
+
recoveringNow = true;
|
|
96
116
|
void (async () => {
|
|
97
117
|
try {
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
118
|
+
while ((recoveringAll || recovering.size > 0) && !closed) {
|
|
119
|
+
const all = recoveringAll;
|
|
120
|
+
const touched = [...recovering];
|
|
121
|
+
recoveringAll = false;
|
|
122
|
+
recovering.clear();
|
|
123
|
+
const reached = [...entries.values()].filter((entry) => all || touched.some(entry.reads));
|
|
124
|
+
for (const entry of reached) {
|
|
101
125
|
if (entry.running)
|
|
102
126
|
entry.dirty = true;
|
|
103
127
|
}
|
|
104
|
-
const waiting =
|
|
105
|
-
if (waiting.length === 0
|
|
128
|
+
const waiting = reached.filter((entry) => !entry.running);
|
|
129
|
+
if (waiting.length === 0)
|
|
106
130
|
continue;
|
|
107
131
|
const held = await holding();
|
|
108
132
|
for (const entry of waiting) {
|
|
109
133
|
if (entry.running)
|
|
110
134
|
continue;
|
|
135
|
+
const read = all ? [] : touched.filter(entry.reads);
|
|
136
|
+
if (read.length > 0 && pendingMoved(entry, held, read))
|
|
137
|
+
continue;
|
|
111
138
|
if (entry.digest === undefined || shown(entry, held) !== entry.covered)
|
|
112
139
|
schedule(entry);
|
|
113
140
|
}
|
|
114
|
-
}
|
|
141
|
+
}
|
|
115
142
|
}
|
|
116
143
|
catch (error) {
|
|
117
144
|
uncaught(error);
|
|
118
145
|
}
|
|
119
146
|
finally {
|
|
120
|
-
|
|
147
|
+
recoveringNow = false;
|
|
121
148
|
}
|
|
122
149
|
})();
|
|
123
150
|
}
|
|
124
151
|
return {
|
|
125
152
|
touched(set) {
|
|
153
|
+
const pending = new Set();
|
|
126
154
|
for (const entry of entries.values()) {
|
|
127
|
-
if (affected(entry
|
|
155
|
+
if (!affected(entry, set))
|
|
156
|
+
continue;
|
|
157
|
+
if (entry.pending === null || entry.running) {
|
|
128
158
|
schedule(entry);
|
|
159
|
+
continue;
|
|
160
|
+
}
|
|
161
|
+
for (const locator of set.rooms)
|
|
162
|
+
pending.add(locator);
|
|
163
|
+
for (const { locator } of set.documents)
|
|
164
|
+
pending.add(locator);
|
|
129
165
|
}
|
|
166
|
+
if (pending.size > 0)
|
|
167
|
+
recovered([...pending]);
|
|
130
168
|
},
|
|
131
169
|
recover: recovered,
|
|
132
|
-
watch(plan, identity, cover, listener, failed) {
|
|
170
|
+
watch(plan, identity, cover, pendingAt, listener, failed) {
|
|
133
171
|
let entry = entries.get(identity);
|
|
134
172
|
if (entry === undefined) {
|
|
135
173
|
entry = {
|
|
136
174
|
plan,
|
|
175
|
+
reads: readerOf(plan),
|
|
137
176
|
cover,
|
|
177
|
+
pendingAt,
|
|
138
178
|
listeners: new Set(),
|
|
139
179
|
fresh: new Map(),
|
|
140
180
|
ready: new Set(),
|
|
141
181
|
digest: undefined,
|
|
182
|
+
pending: null,
|
|
142
183
|
covered: '',
|
|
143
184
|
dirty: false,
|
|
144
185
|
running: false,
|
package/dist/locks.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"locks.d.ts","sourceRoot":"","sources":["../src/locks.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAG5C,wBAAsB,MAAM,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAE,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAE5F;AAED,wBAAsB,WAAW,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAE,EAAE,OAAO,GAAG,OAAO,CAAC,SAAS,MAAM,EAAE,CAAC,
|
|
1
|
+
{"version":3,"file":"locks.d.ts","sourceRoot":"","sources":["../src/locks.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAG5C,wBAAsB,MAAM,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAE,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAE5F;AAED,wBAAsB,WAAW,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAE,EAAE,OAAO,GAAG,OAAO,CAAC,SAAS,MAAM,EAAE,CAAC,CAG1F;AAED,wBAAsB,QAAQ,CAAC,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,SAAS,MAAM,EAAE,iBAKzE;AAED,wBAAgB,cAAc,CAAC,OAAO,EAAE,OAAO,QAU9C;AAED,wBAAgB,UAAU,CAAC,EAAE,KAAK,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,IAAI,GAAG,MAAM,IAAI,CAE7E"}
|
package/dist/locks.js
CHANGED
|
@@ -4,14 +4,13 @@ export async function locked({ store, presence }, locator) {
|
|
|
4
4
|
return presence.locked(locator, async () => (await store.open()).offline(locator));
|
|
5
5
|
}
|
|
6
6
|
export async function lockedRooms({ store, presence }) {
|
|
7
|
-
const
|
|
8
|
-
return presence.lockedAmong(
|
|
7
|
+
const { rooms, locking } = await store.covering();
|
|
8
|
+
return presence.lockedAmong(rooms, locking);
|
|
9
9
|
}
|
|
10
10
|
export async function relocked(runtime, before) {
|
|
11
11
|
const after = await lockedRooms(runtime);
|
|
12
12
|
if (JSON.stringify(after) === JSON.stringify(before))
|
|
13
13
|
return;
|
|
14
|
-
runtime.journal.record(`locked ${after.length}`);
|
|
15
14
|
emitRooms(runtime);
|
|
16
15
|
runtime.store.tell(LOCKS_TOPIC, undefined);
|
|
17
16
|
}
|
package/dist/lost.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lost.d.ts","sourceRoot":"","sources":["../src/lost.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAK5C,wBAAsB,WAAW,CAAC,EAAE,KAAK,EAAE,EAAE,OAAO,EAAE,QAAQ,EAAE,SAAS,MAAM,EAAE,iBAIhF;AAED,wBAAgB,SAAS,CAAC,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,SAAS,MAAM,EAAE,
|
|
1
|
+
{"version":3,"file":"lost.d.ts","sourceRoot":"","sources":["../src/lost.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAK5C,wBAAsB,WAAW,CAAC,EAAE,KAAK,EAAE,EAAE,OAAO,EAAE,QAAQ,EAAE,SAAS,MAAM,EAAE,iBAIhF;AAED,wBAAgB,SAAS,CAAC,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,SAAS,MAAM,EAAE,QAMtE;AAED,wBAAsB,SAAS,CAAC,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,SAAS,MAAM,EAAE,iBA+B5E"}
|
package/dist/lost.js
CHANGED
|
@@ -10,12 +10,11 @@ export async function eraseFenced({ store }, locators) {
|
|
|
10
10
|
}
|
|
11
11
|
}
|
|
12
12
|
export function fenceLive(runtime, locators) {
|
|
13
|
-
const { store, socket, presence
|
|
13
|
+
const { store, socket, presence } = runtime;
|
|
14
14
|
for (const locator of new Set(locators)) {
|
|
15
15
|
if (!presence.lose(locator, socket.session.now().discoveries))
|
|
16
16
|
continue;
|
|
17
17
|
store.forget(locator);
|
|
18
|
-
journal.record(`room lost ${locator}`);
|
|
19
18
|
}
|
|
20
19
|
}
|
|
21
20
|
export async function loseRooms(runtime, locators) {
|
|
@@ -43,7 +42,7 @@ export async function loseRooms(runtime, locators) {
|
|
|
43
42
|
queue: true,
|
|
44
43
|
drafts: held.filter((draft) => draft.locator === locator).map(({ path }) => path),
|
|
45
44
|
}))));
|
|
46
|
-
recoverReads(runtime);
|
|
45
|
+
recoverReads(runtime, fresh);
|
|
47
46
|
}
|
|
48
47
|
await unpair(runtime);
|
|
49
48
|
await eraseFenced(runtime, fresh);
|
package/dist/media.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"media.d.ts","sourceRoot":"","sources":["../src/media.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"media.d.ts","sourceRoot":"","sources":["../src/media.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AACnD,OAAO,EAAqB,KAAK,WAAW,EAAE,MAAM,cAAc,CAAC;AAEnE,eAAO,MAAM,UAAU,eAAe,CAAC;AAwBvC,KAAK,IAAI,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC,WAAW,CAAC,CAAC;AAIpF,wBAAgB,OAAO,CAAC,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,eAAe,GAAG,eAAe,CAG5E;AAsBD,wBAAgB,eAAe,CAAC,MAAM,EAAE,OAAO,CAAC,eAAe,CAAC,GAAG,eAAe,GAAG,IAAI,CAsLxF"}
|
package/dist/media.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { isAudioType, isImageType, isVideoType } from '@agentshouse/mdmodel';
|
|
2
|
+
import { blobOf, UNCERTAIN } from './outcome.js';
|
|
2
3
|
export const ROOM_MEDIA = 'room-media';
|
|
3
4
|
const ATTRIBUTES = ['room', 'path', 'revision', 'width', 'height', 'alt'];
|
|
4
5
|
const LOADING = new Set(['room', 'path', 'revision']);
|
|
@@ -29,11 +30,11 @@ function refusedForGood(shown) {
|
|
|
29
30
|
return (shown.kind === 'rejected' || shown.kind === 'scoped-refusal') && !shown.retryable;
|
|
30
31
|
}
|
|
31
32
|
function drawnFor(mediaType) {
|
|
32
|
-
if (mediaType
|
|
33
|
+
if (isImageType(mediaType))
|
|
33
34
|
return 'img';
|
|
34
|
-
if (mediaType
|
|
35
|
+
if (isVideoType(mediaType))
|
|
35
36
|
return 'video';
|
|
36
|
-
if (mediaType
|
|
37
|
+
if (isAudioType(mediaType))
|
|
37
38
|
return 'audio';
|
|
38
39
|
return null;
|
|
39
40
|
}
|
|
@@ -129,11 +130,7 @@ export function defineRoomMedia(client) {
|
|
|
129
130
|
this.#unshown(asked);
|
|
130
131
|
return;
|
|
131
132
|
}
|
|
132
|
-
const copy = await
|
|
133
|
-
headers: { 'content-type': shown.mediaType },
|
|
134
|
-
})
|
|
135
|
-
.blob()
|
|
136
|
-
.catch(() => null);
|
|
133
|
+
const copy = await blobOf(shown).catch(() => null);
|
|
137
134
|
if (asked !== this.#asked)
|
|
138
135
|
return;
|
|
139
136
|
if (copy === null)
|
|
@@ -179,7 +176,7 @@ export function defineRoomMedia(client) {
|
|
|
179
176
|
if (drawn instanceof HTMLMediaElement) {
|
|
180
177
|
drawn.controls = true;
|
|
181
178
|
drawn.preload = 'metadata';
|
|
182
|
-
if (drawn instanceof HTMLVideoElement)
|
|
179
|
+
if (drawn instanceof HTMLVideoElement && 'playsInline' in drawn)
|
|
183
180
|
drawn.playsInline = true;
|
|
184
181
|
}
|
|
185
182
|
drawn.addEventListener(drawn instanceof HTMLImageElement ? 'load' : 'loadedmetadata', () => {
|
package/dist/memory.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { type VerifiedModel } from '@agentshouse/mdmodel';
|
|
1
2
|
import type { ModelResult } from './model.js';
|
|
2
3
|
import { type AcceptedMessage, type ActionResult, type Adapter, type BinaryFile, type Capability, type ConversationAction, type ConversationEvent, type DiscoveredRoom, type SavedFacts, type HeadChange, type ListedAgent, type ListedConversation, type Member, type ProviderLimit, type Retention, type ServiceMode, type TypedPath, type TypedSelection } from './adapter.js';
|
|
3
4
|
export type MemoryRoom = Omit<DiscoveredRoom, 'typedSelection' | 'authoredPaths'> & {
|
|
@@ -31,7 +32,7 @@ export type MemoryAdapterOptions = {
|
|
|
31
32
|
retention?: Retention;
|
|
32
33
|
member?: Member;
|
|
33
34
|
unopened?: boolean;
|
|
34
|
-
roomTypes?:
|
|
35
|
+
roomTypes?: VerifiedModel;
|
|
35
36
|
typedPaths?: readonly TypedPath[];
|
|
36
37
|
};
|
|
37
38
|
export type MemoryAdapter = Adapter & {
|
|
@@ -39,6 +40,7 @@ export type MemoryAdapter = Adapter & {
|
|
|
39
40
|
refresh: NonNullable<Adapter['refresh']>;
|
|
40
41
|
setRooms(rooms: readonly MemoryRoom[]): void;
|
|
41
42
|
setConversations(conversations: readonly MemoryConversation[]): void;
|
|
43
|
+
setAgents(agents: readonly ListedAgent[]): void;
|
|
42
44
|
script(operation: keyof Adapter, answer: unknown): void;
|
|
43
45
|
open(): void;
|
|
44
46
|
close(closing?: {
|
package/dist/memory.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"memory.d.ts","sourceRoot":"","sources":["../src/memory.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"memory.d.ts","sourceRoot":"","sources":["../src/memory.ts"],"names":[],"mappings":"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"}
|
package/dist/memory.js
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { definitionAt, documentFacts, parse } from '@agentshouse/mdmodel';
|
|
2
2
|
import { NO_ROOM_TYPES, schemaTypes } from './attached-model.js';
|
|
3
|
+
import { selected } from './collection.js';
|
|
4
|
+
import { declaredType } from './outcome.js';
|
|
3
5
|
import { sameChange } from './overlay.js';
|
|
4
6
|
const ATTACHMENTS = 'attachments';
|
|
5
7
|
function lastName(path) {
|
|
@@ -53,7 +55,7 @@ export function createMemoryAdapter(options = {}) {
|
|
|
53
55
|
const listeners = new Set();
|
|
54
56
|
const modeObservers = new Set();
|
|
55
57
|
const scripted = new Map();
|
|
56
|
-
const
|
|
58
|
+
const repeats = new Map();
|
|
57
59
|
const historyPageSize = options.historyPageSize;
|
|
58
60
|
const attached = new Map();
|
|
59
61
|
const linked = new WeakMap();
|
|
@@ -63,6 +65,7 @@ export function createMemoryAdapter(options = {}) {
|
|
|
63
65
|
const declaredRooms = new Set();
|
|
64
66
|
let replicated = [];
|
|
65
67
|
let heldCursor = null;
|
|
68
|
+
let agents = structuredClone(options.agents ?? []);
|
|
66
69
|
let issued = 0;
|
|
67
70
|
function scriptConversations(entries) {
|
|
68
71
|
scripted.clear();
|
|
@@ -104,8 +107,11 @@ export function createMemoryAdapter(options = {}) {
|
|
|
104
107
|
}
|
|
105
108
|
}
|
|
106
109
|
const saved = new WeakMap();
|
|
110
|
+
const roomTypes = options.roomTypes ?? NO_ROOM_TYPES;
|
|
107
111
|
function factsAt(room, path, content) {
|
|
108
|
-
const types =
|
|
112
|
+
const types = selected({ selection: room.typedSelection ?? null }, path)
|
|
113
|
+
? roomTypes.types
|
|
114
|
+
: schemaTypes(room.model?.kind === 'model' ? room.model.snapshot.schema : null, roomTypes);
|
|
109
115
|
let held = saved.get(types);
|
|
110
116
|
if (held === undefined) {
|
|
111
117
|
held = new Map();
|
|
@@ -261,16 +267,14 @@ export function createMemoryAdapter(options = {}) {
|
|
|
261
267
|
}
|
|
262
268
|
function pageOf(conversation, after) {
|
|
263
269
|
const messages = conversation.messages ?? [];
|
|
264
|
-
const first = typeof after === 'string' ? messages.findIndex((message) => message.
|
|
270
|
+
const first = typeof after === 'string' ? messages.findIndex((message) => message.change > after) : 0;
|
|
265
271
|
const from = first === -1 ? messages.length : first;
|
|
266
272
|
const page = messages.slice(from, from + (historyPageSize ?? messages.length));
|
|
267
273
|
const last = page.at(-1);
|
|
268
274
|
return {
|
|
269
275
|
conversation: conversation.conversation,
|
|
270
276
|
messages: page,
|
|
271
|
-
...(last !== undefined && from + page.length < messages.length
|
|
272
|
-
? { next: last.position }
|
|
273
|
-
: {}),
|
|
277
|
+
...(last !== undefined && from + page.length < messages.length ? { next: last.change } : {}),
|
|
274
278
|
};
|
|
275
279
|
}
|
|
276
280
|
function historiesOf(request) {
|
|
@@ -290,11 +294,20 @@ export function createMemoryAdapter(options = {}) {
|
|
|
290
294
|
function conversationAction(request) {
|
|
291
295
|
const name = request.name;
|
|
292
296
|
const input = (request.input ?? {});
|
|
297
|
+
const operation = typeof input.operation_id === 'string' ? `${name}\u0000${input.operation_id}` : null;
|
|
298
|
+
const first = (answer) => {
|
|
299
|
+
if (operation !== null)
|
|
300
|
+
repeats.set(operation, answer);
|
|
301
|
+
return answer;
|
|
302
|
+
};
|
|
303
|
+
const repeated = operation === null ? undefined : repeats.get(operation);
|
|
293
304
|
if (name === 'conversations/create') {
|
|
305
|
+
if (repeated !== undefined)
|
|
306
|
+
return repeated;
|
|
294
307
|
issued += 1;
|
|
295
308
|
const conversation = `conversation-${issued}`;
|
|
296
309
|
scripted.set(conversation, { conversation });
|
|
297
|
-
return { kind: 'action', result: { conversation_id: conversation } };
|
|
310
|
+
return first({ kind: 'action', result: { conversation_id: conversation } });
|
|
298
311
|
}
|
|
299
312
|
const named = typeof input.conversation_id === 'string' ? input.conversation_id : '';
|
|
300
313
|
const conversation = scripted.get(named);
|
|
@@ -310,26 +323,39 @@ export function createMemoryAdapter(options = {}) {
|
|
|
310
323
|
if (outcome !== undefined)
|
|
311
324
|
return outcome;
|
|
312
325
|
if (name === 'conversations/send') {
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
if (answered !== undefined)
|
|
316
|
-
return { kind: 'action', result: { message_id: answered } };
|
|
326
|
+
if (repeated !== undefined)
|
|
327
|
+
return repeated;
|
|
317
328
|
issued += 1;
|
|
318
|
-
|
|
319
|
-
if (operation !== null)
|
|
320
|
-
sentTurns.set(operation, turn);
|
|
321
|
-
return { kind: 'action', result: { message_id: turn } };
|
|
329
|
+
return first({ kind: 'action', result: { message_id: `turn-${issued}` } });
|
|
322
330
|
}
|
|
323
331
|
if (name === 'conversations/delete')
|
|
324
332
|
scripted.delete(named);
|
|
325
333
|
return { kind: 'action', result: { conversation_id: named } };
|
|
326
334
|
}
|
|
335
|
+
function decided(request) {
|
|
336
|
+
const { request: asked, message, decision, } = (request.input ?? {});
|
|
337
|
+
return {
|
|
338
|
+
kind: 'action',
|
|
339
|
+
result: {
|
|
340
|
+
request: asked,
|
|
341
|
+
...(message === undefined ? {} : { message }),
|
|
342
|
+
state: decision === 'approve' ? 'started' : 'declined',
|
|
343
|
+
},
|
|
344
|
+
};
|
|
345
|
+
}
|
|
327
346
|
function announceList() {
|
|
328
347
|
const entries = [...scripted.values()].flatMap(({ conversation, listed, messages = [] }) => listed === undefined
|
|
329
348
|
? []
|
|
330
|
-
: [{ conversation, ...listed, newest: messages.at(-1)?.
|
|
349
|
+
: [{ conversation, ...listed, newest: messages.at(-1)?.change ?? null }]);
|
|
331
350
|
for (const listener of listeners) {
|
|
332
|
-
listener({
|
|
351
|
+
listener({
|
|
352
|
+
kind: 'list',
|
|
353
|
+
agents: structuredClone(agents),
|
|
354
|
+
entries,
|
|
355
|
+
whole: true,
|
|
356
|
+
more: false,
|
|
357
|
+
cursor: null,
|
|
358
|
+
});
|
|
333
359
|
}
|
|
334
360
|
}
|
|
335
361
|
function discovery() {
|
|
@@ -385,6 +411,9 @@ export function createMemoryAdapter(options = {}) {
|
|
|
385
411
|
setConversations(next) {
|
|
386
412
|
scriptConversations(next);
|
|
387
413
|
},
|
|
414
|
+
setAgents(next) {
|
|
415
|
+
agents = structuredClone(next);
|
|
416
|
+
},
|
|
388
417
|
open() {
|
|
389
418
|
carried.clear();
|
|
390
419
|
announceList();
|
|
@@ -447,9 +476,6 @@ export function createMemoryAdapter(options = {}) {
|
|
|
447
476
|
};
|
|
448
477
|
},
|
|
449
478
|
history: (request) => Promise.resolve(historiesOf(request)),
|
|
450
|
-
...(options.agents === undefined
|
|
451
|
-
? {}
|
|
452
|
-
: { agents: () => Promise.resolve(structuredClone(options.agents)) }),
|
|
453
479
|
},
|
|
454
480
|
serviceMode: {
|
|
455
481
|
observe(notify) {
|
|
@@ -602,7 +628,7 @@ export function createMemoryAdapter(options = {}) {
|
|
|
602
628
|
const blob = heldBlob(room, request.path);
|
|
603
629
|
return blob === undefined
|
|
604
630
|
? { kind: 'rejected', code: 'not_found', fields: {}, retryable: false }
|
|
605
|
-
: { kind: 'binary', body: blob.stream(), mediaType: blob
|
|
631
|
+
: { kind: 'binary', body: blob.stream(), mediaType: declaredType(blob) };
|
|
606
632
|
}, request);
|
|
607
633
|
},
|
|
608
634
|
async link(_authorization, request) {
|
|
@@ -616,7 +642,7 @@ export function createMemoryAdapter(options = {}) {
|
|
|
616
642
|
}
|
|
617
643
|
const url = linked.get(blob) ?? URL.createObjectURL(blob);
|
|
618
644
|
linked.set(blob, url);
|
|
619
|
-
return { kind: 'link', url, name: lastName(request.path), mediaType: blob
|
|
645
|
+
return { kind: 'link', url, name: lastName(request.path), mediaType: declaredType(blob) };
|
|
620
646
|
}, request);
|
|
621
647
|
},
|
|
622
648
|
async attach(_authorization, request) {
|
|
@@ -633,6 +659,8 @@ export function createMemoryAdapter(options = {}) {
|
|
|
633
659
|
return resolveScript(scripts.action, () => {
|
|
634
660
|
if (request.name.startsWith('conversations/'))
|
|
635
661
|
return conversationAction(request);
|
|
662
|
+
if (request.name === 'agent-functions/decide')
|
|
663
|
+
return decided(request);
|
|
636
664
|
return { kind: 'rejected', code: 'unscripted-action', fields: {}, retryable: false };
|
|
637
665
|
}, request).then((answer) => {
|
|
638
666
|
if (answer.kind === 'action' && answer.at !== undefined)
|
package/dist/messages.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { AcceptedMessage } from './adapter.js';
|
|
2
2
|
import type { Connection } from './tables.js';
|
|
3
3
|
export declare const MESSAGE_TABLES: readonly string[];
|
|
4
|
-
export declare const ROWS = "WITH chosen AS (\n SELECT listed.value AS conversation,\n (SELECT id FROM conversation_messages WHERE conversation = listed.value AND json_extract(message, '$.role') = 'assistant' ORDER BY position DESC, identity DESC LIMIT 1) AS answer,\n (SELECT id FROM conversation_messages WHERE conversation = listed.value AND text <> '' ORDER BY position DESC, identity DESC LIMIT 1) AS said,\n (SELECT id FROM conversation_messages WHERE conversation = listed.value AND json_extract(message, '$.role') = 'house' ORDER BY position, identity LIMIT 1) AS opened,\n (SELECT id FROM conversation_messages WHERE conversation = listed.value AND json_extract(message, '$.role') = 'house' AND json_extract(message, '$.waiting') = 1 ORDER BY position, identity LIMIT 1) AS asking\n FROM json_each(?) AS listed\n )\n SELECT chosen.conversation AS conversation,\n substr(said.text, 1, 512) AS said_text,\n json_extract(said.message, '$.role') AS said_role,\n json_extract(said.message, '$.accepted_at') AS said_at,\n substr(json_extract(answer.message, '$.failure'), 1, 512) AS failure,\n json_extract(opened.message, '$.source') AS opened_source,\n json_extract(opened.message, '$.sender') AS opened_sender,\n asking.identity AS asking_identity,\n asking.text AS asking_text,\n json_extract(asking.message, '$.accepted_at') AS asking_at,\n json_extract(asking.message, '$.source') AS asking_source,\n json_extract(asking.message, '$.sender') AS asking_sender\n FROM chosen\n LEFT JOIN conversation_messages said ON said.id = chosen.said\n LEFT JOIN conversation_messages answer ON answer.id = chosen.answer\n LEFT JOIN conversation_messages opened ON opened.id = chosen.opened\n LEFT JOIN conversation_messages asking ON asking.id = chosen.asking";
|
|
4
|
+
export declare const ROWS = "WITH chosen AS (\n SELECT listed.value AS conversation,\n (SELECT id FROM conversation_messages WHERE conversation = listed.value AND json_extract(message, '$.role') = 'assistant' ORDER BY position DESC, identity DESC LIMIT 1) AS answer,\n (SELECT id FROM conversation_messages WHERE conversation = listed.value AND text <> '' ORDER BY position DESC, identity DESC LIMIT 1) AS said,\n (SELECT id FROM conversation_messages WHERE conversation = listed.value AND json_extract(message, '$.role') = 'house' ORDER BY position, identity LIMIT 1) AS opened,\n (SELECT id FROM conversation_messages WHERE conversation = listed.value AND json_extract(message, '$.role') = 'house' AND json_extract(message, '$.waiting') = 1 ORDER BY position, identity LIMIT 1) AS asking\n FROM json_each(?) AS listed\n )\n SELECT chosen.conversation AS conversation,\n substr(said.text, 1, 512) AS said_text,\n json_extract(said.message, '$.role') AS said_role,\n json_extract(said.message, '$.accepted_at') AS said_at,\n answer.turn AS answered,\n substr(json_extract(answer.message, '$.failure'), 1, 512) AS failure,\n (SELECT value FROM conversation_facts WHERE conversation = chosen.conversation AND name = 'openedTurn') AS opened_turn,\n json_extract(opened.message, '$.source') AS opened_source,\n json_extract(opened.message, '$.sender') AS opened_sender,\n asking.identity AS asking_identity,\n asking.text AS asking_text,\n json_extract(asking.message, '$.accepted_at') AS asking_at,\n json_extract(asking.message, '$.source') AS asking_source,\n json_extract(asking.message, '$.sender') AS asking_sender\n FROM chosen\n LEFT JOIN conversation_messages said ON said.id = chosen.said\n LEFT JOIN conversation_messages answer ON answer.id = chosen.answer\n LEFT JOIN conversation_messages opened ON opened.id = chosen.opened\n LEFT JOIN conversation_messages asking ON asking.id = chosen.asking";
|
|
5
5
|
export type HeldConversation = {
|
|
6
6
|
readonly conversation: string;
|
|
7
7
|
readonly read: string | null | undefined;
|
|
@@ -22,6 +22,8 @@ export type HeldRow = {
|
|
|
22
22
|
readonly role: string | null;
|
|
23
23
|
readonly at: string | null;
|
|
24
24
|
} | null;
|
|
25
|
+
readonly answered: string | null;
|
|
26
|
+
readonly openedTurn: string | null;
|
|
25
27
|
readonly failure: string | null;
|
|
26
28
|
readonly opened: HeldSource | null;
|
|
27
29
|
readonly asking: (HeldSource & {
|
|
@@ -30,6 +32,12 @@ export type HeldRow = {
|
|
|
30
32
|
readonly at: string | null;
|
|
31
33
|
}) | null;
|
|
32
34
|
};
|
|
35
|
+
export type ConversationFact = 'openedTurn' | 'dismissedSuggestion';
|
|
36
|
+
export type HeldFact = {
|
|
37
|
+
readonly conversation: string;
|
|
38
|
+
readonly name: ConversationFact;
|
|
39
|
+
readonly value: string;
|
|
40
|
+
};
|
|
33
41
|
export type ConversationWrite = {
|
|
34
42
|
readonly conversation: string;
|
|
35
43
|
readonly messages: readonly AcceptedMessage[];
|
|
@@ -44,6 +52,7 @@ export declare function messageWindow(connection: Connection, conversation: stri
|
|
|
44
52
|
export declare function messageCount(connection: Connection, conversation: string, phrase: string | null): number;
|
|
45
53
|
export declare function conversationRows(connection: Connection, conversations: readonly string[]): HeldRow[];
|
|
46
54
|
export declare function turnArrived(connection: Connection, conversation: string, turn: string): boolean;
|
|
47
|
-
export declare function
|
|
48
|
-
export declare function
|
|
55
|
+
export declare function conversationFacts(connection: Connection): HeldFact[];
|
|
56
|
+
export declare function keptFact(connection: Connection, { conversation, name, value }: HeldFact): null;
|
|
57
|
+
export declare function forgottenConversations(connection: Connection): void;
|
|
49
58
|
//# sourceMappingURL=messages.d.ts.map
|
package/dist/messages.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"messages.d.ts","sourceRoot":"","sources":["../src/messages.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"messages.d.ts","sourceRoot":"","sources":["../src/messages.ts"],"names":[],"mappings":"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"}
|
package/dist/messages.js
CHANGED
|
@@ -1,14 +1,16 @@
|
|
|
1
1
|
import { sql } from '@agentshouse/mdmodel';
|
|
2
2
|
import { EXCERPT } from './read.js';
|
|
3
|
+
import { tablesOf } from './stored.js';
|
|
3
4
|
const SAID_BY_HOUSE = `json_extract(message, '$.role') = 'house'`;
|
|
4
5
|
const ANSWERS_THE_TURN = `json_extract(message, '$.role') = 'assistant'`;
|
|
5
6
|
export const MESSAGE_TABLES = [
|
|
6
7
|
'CREATE TABLE conversation_reads (conversation TEXT PRIMARY KEY, read TEXT, partial INTEGER NOT NULL) WITHOUT ROWID',
|
|
7
|
-
'CREATE TABLE conversation_messages (id INTEGER PRIMARY KEY, conversation TEXT NOT NULL, identity TEXT NOT NULL, turn TEXT NOT NULL, position TEXT NOT NULL, message TEXT NOT NULL, text TEXT NOT NULL)',
|
|
8
|
+
'CREATE TABLE conversation_messages (id INTEGER PRIMARY KEY, conversation TEXT NOT NULL, identity TEXT NOT NULL, turn TEXT NOT NULL, position TEXT NOT NULL, change TEXT NOT NULL, message TEXT NOT NULL, text TEXT NOT NULL)',
|
|
8
9
|
'CREATE UNIQUE INDEX conversation_messages_identity ON conversation_messages (conversation, identity)',
|
|
9
10
|
'CREATE INDEX conversation_messages_position ON conversation_messages (conversation, position, identity)',
|
|
10
11
|
'CREATE INDEX conversation_messages_turn ON conversation_messages (conversation, turn)',
|
|
11
12
|
`CREATE INDEX conversation_messages_house ON conversation_messages (conversation, position, identity) WHERE ${SAID_BY_HOUSE}`,
|
|
13
|
+
'CREATE TABLE conversation_facts (conversation TEXT NOT NULL, name TEXT NOT NULL, value TEXT NOT NULL, PRIMARY KEY (conversation, name)) WITHOUT ROWID',
|
|
12
14
|
];
|
|
13
15
|
const NEWEST_FIRST = 'ORDER BY position DESC, identity DESC LIMIT 1';
|
|
14
16
|
const OLDEST_FIRST = 'ORDER BY position, identity LIMIT 1';
|
|
@@ -25,7 +27,9 @@ export const ROWS = `WITH chosen AS (
|
|
|
25
27
|
substr(said.text, 1, ${EXCERPT}) AS said_text,
|
|
26
28
|
json_extract(said.message, '$.role') AS said_role,
|
|
27
29
|
json_extract(said.message, '$.accepted_at') AS said_at,
|
|
30
|
+
answer.turn AS answered,
|
|
28
31
|
substr(json_extract(answer.message, '$.failure'), 1, ${EXCERPT}) AS failure,
|
|
32
|
+
(SELECT value FROM conversation_facts WHERE conversation = chosen.conversation AND name = 'openedTurn') AS opened_turn,
|
|
29
33
|
json_extract(opened.message, '$.source') AS opened_source,
|
|
30
34
|
json_extract(opened.message, '$.sender') AS opened_sender,
|
|
31
35
|
asking.identity AS asking_identity,
|
|
@@ -63,11 +67,12 @@ export function heldConversations(connection, conversations) {
|
|
|
63
67
|
}
|
|
64
68
|
export function keptMessages(connection, { conversation, messages, read }) {
|
|
65
69
|
for (const message of messages) {
|
|
66
|
-
connection.run('INSERT INTO conversation_messages (conversation, identity, turn, position, message, text) VALUES (?, ?, ?, ?, ?, ?) ON CONFLICT (conversation, identity) DO UPDATE SET turn = excluded.turn, position = excluded.position, message = excluded.message, text = excluded.text', [
|
|
70
|
+
connection.run('INSERT INTO conversation_messages (conversation, identity, turn, position, change, message, text) VALUES (?, ?, ?, ?, ?, ?, ?) ON CONFLICT (conversation, identity) DO UPDATE SET turn = excluded.turn, position = excluded.position, change = excluded.change, message = excluded.message, text = excluded.text', [
|
|
67
71
|
conversation,
|
|
68
72
|
message.identity,
|
|
69
73
|
message.turn,
|
|
70
74
|
message.position,
|
|
75
|
+
message.change,
|
|
71
76
|
JSON.stringify(message.message ?? null),
|
|
72
77
|
message.text,
|
|
73
78
|
]);
|
|
@@ -82,6 +87,7 @@ function accepted(row) {
|
|
|
82
87
|
identity: text(row.identity),
|
|
83
88
|
turn: text(row.turn),
|
|
84
89
|
position: text(row.position),
|
|
90
|
+
change: text(row.change),
|
|
85
91
|
text: text(row.text),
|
|
86
92
|
message: JSON.parse(text(row.message)),
|
|
87
93
|
};
|
|
@@ -93,7 +99,7 @@ function holding(phrase) {
|
|
|
93
99
|
}
|
|
94
100
|
export function messageWindow(connection, conversation, limit, before, phrase) {
|
|
95
101
|
const held = holding(phrase);
|
|
96
|
-
const rows = connection.rows(`SELECT identity, turn, position, message, text FROM conversation_messages WHERE conversation = ?${held.sql}${before === null ? '' : ' AND (position < ? OR (position = ? AND identity < ?))'} ORDER BY position DESC, identity DESC LIMIT ?`, before === null
|
|
102
|
+
const rows = connection.rows(`SELECT identity, turn, position, change, message, text FROM conversation_messages WHERE conversation = ?${held.sql}${before === null ? '' : ' AND (position < ? OR (position = ? AND identity < ?))'} ORDER BY position DESC, identity DESC LIMIT ?`, before === null
|
|
97
103
|
? [conversation, ...held.bind, limit + 1]
|
|
98
104
|
: [conversation, ...held.bind, before[0], before[0], before[1], limit + 1]);
|
|
99
105
|
return { messages: rows.slice(0, limit).map(accepted).reverse(), more: rows.length > limit };
|
|
@@ -122,6 +128,8 @@ export function conversationRows(connection, conversations) {
|
|
|
122
128
|
role: textOrNull(row.said_role),
|
|
123
129
|
at: textOrNull(row.said_at),
|
|
124
130
|
},
|
|
131
|
+
answered: textOrNull(row.answered),
|
|
132
|
+
openedTurn: textOrNull(row.opened_turn),
|
|
125
133
|
failure: textOrNull(row.failure),
|
|
126
134
|
opened: row.opened_source === null ? null : heldSource(row.opened_source, row.opened_sender),
|
|
127
135
|
asking: row.asking_identity === null
|
|
@@ -137,12 +145,18 @@ export function conversationRows(connection, conversations) {
|
|
|
137
145
|
export function turnArrived(connection, conversation, turn) {
|
|
138
146
|
return (connection.rows('SELECT 1 FROM conversation_messages WHERE conversation = ? AND turn = ? LIMIT 1', [conversation, turn]).length > 0);
|
|
139
147
|
}
|
|
140
|
-
export function
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
148
|
+
export function conversationFacts(connection) {
|
|
149
|
+
return connection.rows('SELECT conversation, name, value FROM conversation_facts').map((row) => ({
|
|
150
|
+
conversation: text(row.conversation),
|
|
151
|
+
name: text(row.name),
|
|
152
|
+
value: text(row.value),
|
|
153
|
+
}));
|
|
154
|
+
}
|
|
155
|
+
export function keptFact(connection, { conversation, name, value }) {
|
|
156
|
+
connection.run('INSERT OR REPLACE INTO conversation_facts (conversation, name, value) VALUES (?, ?, ?)', [conversation, name, value]);
|
|
157
|
+
return null;
|
|
144
158
|
}
|
|
145
|
-
export function
|
|
146
|
-
|
|
147
|
-
|
|
159
|
+
export function forgottenConversations(connection) {
|
|
160
|
+
for (const table of tablesOf(MESSAGE_TABLES))
|
|
161
|
+
connection.run(`DELETE FROM ${table}`);
|
|
148
162
|
}
|