@framers/agentos-ext-account-sources 0.9.2 → 0.9.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -138,25 +138,33 @@ export interface SourceSyncSweep {
138
138
  }
139
139
  /**
140
140
  * Thrown by `expire` when it fails after removing at least one source. Each removal committed in a transaction of its
141
- * own, so `partial` counts them in `removed`, with the failure itself in `failed`; `cause` holds the failure, whose
142
- * message this error carries.
141
+ * own, so `partial` counts them in `removed` and names their sources in `sourceIds`, in the order they were removed,
142
+ * with the failure itself in `failed`; `cause` holds the failure, whose message this error carries. The removals stand:
143
+ * a host that counts what `expire` removed adds `partial.removed` in its catch, as `AccountSourceSync.maintain` does.
143
144
  */
144
145
  export declare class SourceSyncExpiryError extends Error {
145
146
  readonly partial: {
146
147
  readonly removed: number;
147
148
  readonly failed: number;
149
+ readonly sourceIds: readonly string[];
148
150
  };
149
- constructor(removed: number, cause: unknown);
151
+ /**
152
+ * @param removed - How many sources were removed before the failure.
153
+ * @param cause - The failure.
154
+ * @param sourceIds - The ids of those sources, in the order they were removed; `expire` always gives them.
155
+ */
156
+ constructor(removed: number, cause: unknown, sourceIds?: readonly string[]);
150
157
  }
151
158
  /**
152
159
  * Durable synchronization state for account sources on PostgreSQL. Every change to an owner's content runs under
153
160
  * that owner's fence (`fence`), and a change made with a handle checks its lease, generation and host liveness in
154
161
  * the same transaction. Applying a changed source purges its old copy and every derived result that depends on it
155
- * before the replacement is written. A read that repeats the text of a copy the store holds is never charged again,
156
- * one that changes it is charged, by the hash the store keeps of each message's text, its new and changed messages and
157
- * the text beside them, and with the host's `refresh` binding a read of that very copy keeps it in place. Provider
158
- * reads, embedding and model calls stay outside the store. The constructor runs no DDL: the host's migration runs
159
- * `sourceSyncSchema` and core's `sourceDerivationSchema` first.
162
+ * before the replacement is written; a read that answers gone or a skip withdraws the copy in a commit of its own
163
+ * before purging it, so a purge that fails leaves nothing derived from it deliverable. A read that repeats the text of
164
+ * a copy the store holds is never charged again, one that changes it is charged, by the hash the store keeps of each
165
+ * message's text, its new and changed messages and the text beside them, and with the host's `refresh` binding a read
166
+ * of that very copy keeps it in place. Provider reads, embedding and model calls stay outside the store. The
167
+ * constructor runs no DDL: the host's migration runs `sourceSyncSchema` and core's `sourceDerivationSchema` first.
160
168
  *
161
169
  * @typeParam Prepared - The host's in-memory value for one document, passed through to its `write` binding.
162
170
  */
@@ -291,8 +299,10 @@ export declare class SqlAccountSourceSyncStore<Prepared = unknown> {
291
299
  /**
292
300
  * Applies one read result for a work item taken in this cycle, under a live lease and the owner fence. A retry
293
301
  * keeps the work unresolved. A document is weighed first: excluded, outside the retained limits or over the
294
- * indexing allowance with the characters it adds to index, it is recorded as a skip with its reason. A document
295
- * that fits replaces the source's old copy in the same transaction (host write, indexing charge and provenance),
302
+ * indexing allowance with the characters it adds to index, it is recorded as a skip with its reason, and so is one
303
+ * whose cache lifetime has ended by the store's clock when it is weighed (`expired`), as a document admitted with
304
+ * seconds of it left and applied again after a longer preparation: an expired read is never refused as malformed. A
305
+ * document that fits replaces the source's old copy in the same transaction (host write, indexing charge and provenance),
296
306
  * after the old copy and every result derived from it are purged, evicting this connection's older sources the
297
307
  * limits no longer admit. A read that repeats the text and message spans of a copy the store still holds, within
298
308
  * its expiry and window, adds nothing to index and is never charged. Any other read of such a copy adds its new and
@@ -318,6 +328,13 @@ export declare class SqlAccountSourceSyncStore<Prepared = unknown> {
318
328
  * does not begin with the copy's text, so with the allowance spent it removes the thread's copy, and the thread stays
319
329
  * out of the store until a read of it fits the allowance whole.
320
330
  *
331
+ * A `gone` result and a skip the provider answers withdraw the old copy before that, in a transaction of their own
332
+ * (`withdraw`), and so does an `expired` skip, before its application runs again: the copy's expiry moves to the
333
+ * store's clock, so from then on `readCurrent` answers it expired and the fence neither commits nor delivers a result
334
+ * derived from it, even when the purge that follows fails, as when the host's `purge` binding throws. A failing
335
+ * binding rolls the rest of the application back; the withdrawn copy is past its expiry, so the next `expire` or
336
+ * `sweepExpired` removes it, as does a later application of the read.
337
+ *
321
338
  * @param prepared - The host's prepared value for a document result; null for any other result, and for a document
322
339
  * weighed before its preparation.
323
340
  * @returns The disposition and the handle later calls use, whose ticket reflects any purge; `pending` with the same
@@ -329,6 +346,20 @@ export declare class SqlAccountSourceSyncStore<Prepared = unknown> {
329
346
  * ordered spans of a valid read and an intact copy rule out; nothing is charged or written.
330
347
  */
331
348
  applyResult(h: SourceSyncHandle, work: SourceSyncWork, result: SourceSyncReadResult, prepared: Prepared | null): Promise<SourceSyncApplication | null>;
349
+ /** Whether the connection holds a copy of the source within its expiry, read without a lock. */
350
+ private holds;
351
+ /**
352
+ * Withdraws the copy the store holds of a source a read answered `gone` or skipped, in a transaction of its own,
353
+ * before the one that removes it: the copy's expiry, and its dependency's, move to the store's clock. `readCurrent`
354
+ * then answers it expired, so the fence neither commits nor delivers a result derived from it, and `expire` and
355
+ * `sweepExpired` remove it should the removal fail. The handle, the work item and the result are checked as
356
+ * `applyResult` checks them, and a copy already past its expiry is left as it is.
357
+ *
358
+ * @returns True once the copy is withdrawn or none is held within its expiry; null for a stale handle or work item.
359
+ * @throws {SourceSyncFault} `invalid_response` for a result that does not match its work item or a skip reason the
360
+ * store does not know, with nothing withdrawn.
361
+ */
362
+ private withdraw;
332
363
  private summary;
333
364
  /**
334
365
  * Records the cycle's progress, counted from its stored work and the retained documents.
@@ -399,7 +430,8 @@ export declare class SqlAccountSourceSyncStore<Prepared = unknown> {
399
430
  /**
400
431
  * The current state of each of the derivation's retained sources, read in the given transaction for the fence's
401
432
  * commit and delivery checks; not an authorization answer of its own. An owner the host's `active` binding refuses
402
- * has no sources, and a connection with a barrier or pending revalidation reads as disconnected.
433
+ * has no sources, and a connection with a barrier or pending revalidation reads as disconnected. A copy a `gone` read
434
+ * or a skip withdrew reads as expired until it is removed.
403
435
  */
404
436
  readCurrent(tx: StorageAdapter, derivation: SourceDerivation): Promise<readonly SourceDependencyState[]>;
405
437
  /** Removes the host's content and this store's provenance in the affected scope; the fence calls it inside an invalidation. */
@@ -472,7 +504,7 @@ export declare class SqlAccountSourceSyncStore<Prepared = unknown> {
472
504
  * @returns How many sources were removed.
473
505
  * @throws {Error} `invalid_sync_batch` for another limit, and the failure itself when a removal or the results'
474
506
  * expiry fails: once a source was removed, a `SourceSyncExpiryError` with the failure's message, the failure as its
475
- * `cause` and the removals made before it in `partial`.
507
+ * `cause` and the removals made before it in `partial`, counted in `removed` and named in `sourceIds`.
476
508
  */
477
509
  expire(scope: SourceSyncScope, limit?: number): Promise<number>;
478
510
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"SqlAccountSourceSyncStore.d.ts","sourceRoot":"","sources":["../../src/sync/SqlAccountSourceSyncStore.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"SqlAccountSourceSyncStore.d.ts","sourceRoot":"","sources":["../../src/sync/SqlAccountSourceSyncStore.ts"],"names":[],"mappings":"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"}
@@ -10,20 +10,34 @@ import { createSourceSyncState, transitionSourceSync, sourceSyncDue, openSourceS
10
10
  import { sourceSyncTables } from './schema.js';
11
11
  /**
12
12
  * Thrown by `expire` when it fails after removing at least one source. Each removal committed in a transaction of its
13
- * own, so `partial` counts them in `removed`, with the failure itself in `failed`; `cause` holds the failure, whose
14
- * message this error carries.
13
+ * own, so `partial` counts them in `removed` and names their sources in `sourceIds`, in the order they were removed,
14
+ * with the failure itself in `failed`; `cause` holds the failure, whose message this error carries. The removals stand:
15
+ * a host that counts what `expire` removed adds `partial.removed` in its catch, as `AccountSourceSync.maintain` does.
15
16
  */
16
17
  export class SourceSyncExpiryError extends Error {
17
18
  partial;
18
- constructor(removed, cause) {
19
+ /**
20
+ * @param removed - How many sources were removed before the failure.
21
+ * @param cause - The failure.
22
+ * @param sourceIds - The ids of those sources, in the order they were removed; `expire` always gives them.
23
+ */
24
+ constructor(removed, cause, sourceIds = []) {
19
25
  super(cause instanceof Error ? cause.message : String(cause), { cause });
20
26
  this.name = 'SourceSyncExpiryError';
21
- this.partial = { removed, failed: 1 };
27
+ this.partial = { removed, failed: 1, sourceIds: Object.freeze([...sourceIds]) };
22
28
  }
23
29
  }
24
30
  class StaleSync extends Error {
25
31
  constructor() { super('stale_source_sync'); }
26
32
  }
33
+ /**
34
+ * Thrown inside an application, before anything is written, by a read the store records as an `expired` skip while it
35
+ * still holds the source's copy within its expiry: the copy is withdrawn in a commit of its own and the read applied
36
+ * again, so a purge that fails cannot leave the copy deliverable.
37
+ */
38
+ class WithdrawFirst extends Error {
39
+ constructor() { super('source_sync_withdraw_first'); }
40
+ }
27
41
  const params = (s) => [s.tenantId, s.ownerId, s.connectionId];
28
42
  const validNumber = (n) => Number.isSafeInteger(n) && n >= 0;
29
43
  const validId = (s) => typeof s === 'string' && s.length > 0 && s.length <= 512;
@@ -113,11 +127,12 @@ const sameCopy = (stored, read) => sameText(stored, read) && stored.dependency.v
113
127
  * Durable synchronization state for account sources on PostgreSQL. Every change to an owner's content runs under
114
128
  * that owner's fence (`fence`), and a change made with a handle checks its lease, generation and host liveness in
115
129
  * the same transaction. Applying a changed source purges its old copy and every derived result that depends on it
116
- * before the replacement is written. A read that repeats the text of a copy the store holds is never charged again,
117
- * one that changes it is charged, by the hash the store keeps of each message's text, its new and changed messages and
118
- * the text beside them, and with the host's `refresh` binding a read of that very copy keeps it in place. Provider
119
- * reads, embedding and model calls stay outside the store. The constructor runs no DDL: the host's migration runs
120
- * `sourceSyncSchema` and core's `sourceDerivationSchema` first.
130
+ * before the replacement is written; a read that answers gone or a skip withdraws the copy in a commit of its own
131
+ * before purging it, so a purge that fails leaves nothing derived from it deliverable. A read that repeats the text of
132
+ * a copy the store holds is never charged again, one that changes it is charged, by the hash the store keeps of each
133
+ * message's text, its new and changed messages and the text beside them, and with the host's `refresh` binding a read
134
+ * of that very copy keeps it in place. Provider reads, embedding and model calls stay outside the store. The
135
+ * constructor runs no DDL: the host's migration runs `sourceSyncSchema` and core's `sourceDerivationSchema` first.
121
136
  *
122
137
  * @typeParam Prepared - The host's in-memory value for one document, passed through to its `write` binding.
123
138
  */
@@ -508,7 +523,7 @@ export class SqlAccountSourceSyncStore {
508
523
  || !validId(work.sourceId) || typeof text !== 'string' || text.length === 0 || text.length > 1_048_576
509
524
  || typeof doc.contentHash !== 'string' || !doc.contentHash || doc.contentHash.length > 512
510
525
  || doc.cache.kind !== 'cache' || !doc.cache.evidenceId || !validNumber(doc.cache.expiresAt)
511
- || doc.cache.expiresAt <= now || !validNumber(doc.activityAt) || doc.activityAt > now
526
+ || !validNumber(doc.activityAt) || doc.activityAt > now
512
527
  || !doc.messages.length || doc.messages.length > 1000)
513
528
  fail();
514
529
  let end = 0;
@@ -572,8 +587,10 @@ export class SqlAccountSourceSyncStore {
572
587
  /**
573
588
  * Applies one read result for a work item taken in this cycle, under a live lease and the owner fence. A retry
574
589
  * keeps the work unresolved. A document is weighed first: excluded, outside the retained limits or over the
575
- * indexing allowance with the characters it adds to index, it is recorded as a skip with its reason. A document
576
- * that fits replaces the source's old copy in the same transaction (host write, indexing charge and provenance),
590
+ * indexing allowance with the characters it adds to index, it is recorded as a skip with its reason, and so is one
591
+ * whose cache lifetime has ended by the store's clock when it is weighed (`expired`), as a document admitted with
592
+ * seconds of it left and applied again after a longer preparation: an expired read is never refused as malformed. A
593
+ * document that fits replaces the source's old copy in the same transaction (host write, indexing charge and provenance),
577
594
  * after the old copy and every result derived from it are purged, evicting this connection's older sources the
578
595
  * limits no longer admit. A read that repeats the text and message spans of a copy the store still holds, within
579
596
  * its expiry and window, adds nothing to index and is never charged. Any other read of such a copy adds its new and
@@ -599,6 +616,13 @@ export class SqlAccountSourceSyncStore {
599
616
  * does not begin with the copy's text, so with the allowance spent it removes the thread's copy, and the thread stays
600
617
  * out of the store until a read of it fits the allowance whole.
601
618
  *
619
+ * A `gone` result and a skip the provider answers withdraw the old copy before that, in a transaction of their own
620
+ * (`withdraw`), and so does an `expired` skip, before its application runs again: the copy's expiry moves to the
621
+ * store's clock, so from then on `readCurrent` answers it expired and the fence neither commits nor delivers a result
622
+ * derived from it, even when the purge that follows fails, as when the host's `purge` binding throws. A failing
623
+ * binding rolls the rest of the application back; the withdrawn copy is past its expiry, so the next `expire` or
624
+ * `sweepExpired` removes it, as does a later application of the read.
625
+ *
602
626
  * @param prepared - The host's prepared value for a document result; null for any other result, and for a document
603
627
  * weighed before its preparation.
604
628
  * @returns The disposition and the handle later calls use, whose ticket reflects any purge; `pending` with the same
@@ -610,7 +634,14 @@ export class SqlAccountSourceSyncStore {
610
634
  * ordered spans of a valid read and an intact copy rule out; nothing is charged or written.
611
635
  */
612
636
  async applyResult(h, work, result, prepared) {
613
- return this.withHandle(h, async (tx, row) => {
637
+ // The purge below runs in the transaction that records the result, so a binding that throws rolls the copy's
638
+ // invalidation back with it. The withdrawal commits first and survives that rollback. Only this lease writes the
639
+ // connection's copies, so a copy not held at this read cannot appear before the purge.
640
+ if ((result.kind === 'gone' || result.kind === 'skipped') && await this.holds(h.lease.scope, work.sourceId)
641
+ && await this.withdraw(h, work, result) === null)
642
+ return null;
643
+ // `withdrawn` once the copy of a read the weighing below finds expired has been withdrawn (`WithdrawFirst`).
644
+ const apply = (withdrawn) => this.withHandle(h, async (tx, row) => {
614
645
  const s = h.lease.scope;
615
646
  await this.currentWork(tx, s, row.checkpoint, work);
616
647
  if (result.kind === "skipped" && !skipReasons.includes(result.reason))
@@ -668,7 +699,18 @@ export class SqlAccountSourceSyncStore {
668
699
  // a negative or fractional one would mean a malformed copy, and is refused rather than charged.
669
700
  if (!validNumber(indexed))
670
701
  throw new Error('invalid_source_sync_charge');
671
- if (!selected.includes(read)) {
702
+ // A read whose cache lifetime has ended by the time it is weighed is an ordinary expired result, never a
703
+ // malformed one: a document admitted with seconds of its lifetime left and prepared for longer comes back past
704
+ // it, and refusing it as `invalid_response` would end the run with `sync_failed`, which clears the schedule.
705
+ // The skip is terminal, so the cycle commits, and the source is read again when it is listed again. It removes
706
+ // the copy the store holds, which a skip the provider answers withdraws before the purge: the copy still within
707
+ // its expiry is withdrawn the same way, in a commit of its own, and the read applied again.
708
+ if (read.dependency.expiresAt <= now) {
709
+ if (!withdrawn && old !== undefined && old.dependency.expiresAt > now)
710
+ throw new WithdrawFirst();
711
+ disposition = { kind: 'skipped', reason: 'expired' };
712
+ }
713
+ else if (!selected.includes(read)) {
672
714
  const reason = selected.length >= Math.min(row.policy.maxRetainedDocuments, maximumDocuments)
673
715
  ? 'document_limit' : 'held_limit';
674
716
  disposition = { kind: 'skipped', reason };
@@ -739,6 +781,52 @@ export class SqlAccountSourceSyncStore {
739
781
  await this.putWork(tx, s, { ...work, disposition });
740
782
  return { handle: { ...h, ticket }, disposition };
741
783
  });
784
+ try {
785
+ return await apply(false);
786
+ }
787
+ catch (error) {
788
+ if (!(error instanceof WithdrawFirst))
789
+ throw error;
790
+ if (await this.withdraw(h, work, { kind: 'skipped', id: work.sourceId, reason: 'expired' }) === null)
791
+ return null;
792
+ return apply(true);
793
+ }
794
+ }
795
+ /** Whether the connection holds a copy of the source within its expiry, read without a lock. */
796
+ async holds(scope, sourceId) {
797
+ return !!await this.db.get(`SELECT 1 FROM ${this.t.documents} WHERE tenant_id=$1 AND owner_id=$2
798
+ AND connection_id=$3 AND source_id=$4 AND expires_at>$5`, [...params(scope), sourceId, this.now()]);
799
+ }
800
+ /**
801
+ * Withdraws the copy the store holds of a source a read answered `gone` or skipped, in a transaction of its own,
802
+ * before the one that removes it: the copy's expiry, and its dependency's, move to the store's clock. `readCurrent`
803
+ * then answers it expired, so the fence neither commits nor delivers a result derived from it, and `expire` and
804
+ * `sweepExpired` remove it should the removal fail. The handle, the work item and the result are checked as
805
+ * `applyResult` checks them, and a copy already past its expiry is left as it is.
806
+ *
807
+ * @returns True once the copy is withdrawn or none is held within its expiry; null for a stale handle or work item.
808
+ * @throws {SourceSyncFault} `invalid_response` for a result that does not match its work item or a skip reason the
809
+ * store does not know, with nothing withdrawn.
810
+ */
811
+ async withdraw(h, work, result) {
812
+ return this.withHandle(h, async (tx, row) => {
813
+ const s = h.lease.scope;
814
+ await this.currentWork(tx, s, row.checkpoint, work);
815
+ if (result.kind === 'skipped' && !skipReasons.includes(result.reason))
816
+ throw new SourceSyncFault('invalid_response');
817
+ if (result.id !== work.sourceId)
818
+ throw new SourceSyncFault('invalid_response');
819
+ const now = this.now();
820
+ const held = await tx.get(`SELECT document FROM ${this.t.documents}
821
+ WHERE tenant_id=$1 AND owner_id=$2 AND connection_id=$3 AND source_id=$4 AND expires_at>$5`, [...params(s), work.sourceId, now]);
822
+ if (held) {
823
+ const withdrawn = { ...held.document,
824
+ dependency: { ...held.document.dependency, expiresAt: now } };
825
+ await tx.run(`UPDATE ${this.t.documents} SET document=$5::jsonb,expires_at=$6
826
+ WHERE tenant_id=$1 AND owner_id=$2 AND connection_id=$3 AND source_id=$4`, [...params(s), work.sourceId, JSON.stringify(withdrawn), now]);
827
+ }
828
+ return true;
829
+ });
742
830
  }
743
831
  async summary(tx, scope, cp) {
744
832
  const rows = await tx.all(`SELECT work FROM ${this.t.work}
@@ -941,7 +1029,8 @@ export class SqlAccountSourceSyncStore {
941
1029
  /**
942
1030
  * The current state of each of the derivation's retained sources, read in the given transaction for the fence's
943
1031
  * commit and delivery checks; not an authorization answer of its own. An owner the host's `active` binding refuses
944
- * has no sources, and a connection with a barrier or pending revalidation reads as disconnected.
1032
+ * has no sources, and a connection with a barrier or pending revalidation reads as disconnected. A copy a `gone` read
1033
+ * or a skip withdrew reads as expired until it is removed.
945
1034
  */
946
1035
  async readCurrent(tx, derivation) {
947
1036
  if (!await this.options.bindings.active(tx, derivation))
@@ -1207,7 +1296,7 @@ export class SqlAccountSourceSyncStore {
1207
1296
  * @returns How many sources were removed.
1208
1297
  * @throws {Error} `invalid_sync_batch` for another limit, and the failure itself when a removal or the results'
1209
1298
  * expiry fails: once a source was removed, a `SourceSyncExpiryError` with the failure's message, the failure as its
1210
- * `cause` and the removals made before it in `partial`.
1299
+ * `cause` and the removals made before it in `partial`, counted in `removed` and named in `sourceIds`.
1211
1300
  */
1212
1301
  async expire(scope, limit = 100) {
1213
1302
  if (!Number.isInteger(limit) || limit < 1 || limit > 1000)
@@ -1215,18 +1304,18 @@ export class SqlAccountSourceSyncStore {
1215
1304
  const rows = await this.db.all(`SELECT source_id FROM ${this.t.documents}
1216
1305
  WHERE tenant_id=$1 AND owner_id=$2 AND connection_id=$3 AND expires_at <= $4
1217
1306
  ORDER BY expires_at,source_id LIMIT $5`, [...params(scope), this.now(), limit]);
1218
- let removed = 0;
1307
+ const removed = [];
1219
1308
  try {
1220
1309
  for (const row of rows)
1221
1310
  if (await this.expireSource(scope, row.source_id))
1222
- removed++;
1311
+ removed.push(row.source_id);
1223
1312
  await this.fence.expireResults(scope, limit);
1224
1313
  }
1225
1314
  catch (error) {
1226
- // The removals before the failure have committed, so their count goes to the caller with it.
1227
- throw removed > 0 ? new SourceSyncExpiryError(removed, error) : error;
1315
+ // The removals before the failure have committed, so their count and their sources go to the caller with it.
1316
+ throw removed.length > 0 ? new SourceSyncExpiryError(removed.length, error, removed) : error;
1228
1317
  }
1229
- return removed;
1318
+ return removed.length;
1230
1319
  }
1231
1320
  /**
1232
1321
  * Removes one retained source whose expiry has passed, with every result derived from it, under its owner's row