@tinycloud/cli 1.1.0-beta.16 → 1.1.0-beta.18

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.
@@ -2052,6 +2052,7 @@ var ACCOUNT_REGISTRY_PATH = "applications/";
2052
2052
  var SECRETS_SPACE = "secrets";
2053
2053
  var BOOTSTRAP_DEFAULT_SPACE = "default";
2054
2054
  var BOOTSTRAP_PUBLIC_SPACE = "public";
2055
+ var AGENTS_SPACE = "agents";
2055
2056
  var BOOTSTRAP_ENCRYPTION_NETWORK_NAME = "default";
2056
2057
  var BOOTSTRAP_ENCRYPTION_NETWORK_RESOURCE_TEMPLATE = `urn:tinycloud:encryption:{ownerDid}:${BOOTSTRAP_ENCRYPTION_NETWORK_NAME}`;
2057
2058
  var DEFAULT_EXPIRY_MS = 30 * 24 * 60 * 60 * 1e3;
@@ -2064,7 +2065,8 @@ var BOOTSTRAP_SPACE_NAMES = [
2064
2065
  DEFAULT_MANIFEST_SPACE,
2065
2066
  ACCOUNT_REGISTRY_SPACE,
2066
2067
  SECRETS_SPACE,
2067
- BOOTSTRAP_PUBLIC_SPACE
2068
+ BOOTSTRAP_PUBLIC_SPACE,
2069
+ AGENTS_SPACE
2068
2070
  ];
2069
2071
  var TINYCLOUD_DEFAULT_SPACE_MANIFEST = {
2070
2072
  app_id: "xyz.tinycloud.default",
@@ -2205,12 +2207,29 @@ var TINYCLOUD_PUBLIC_SPACE_MANIFEST = {
2205
2207
  }
2206
2208
  ]
2207
2209
  };
2210
+ var TINYCLOUD_AGENTS_SPACE_MANIFEST = {
2211
+ app_id: "xyz.tinycloud.agents",
2212
+ name: "TinyCloud Agents Space",
2213
+ space: AGENTS_SPACE,
2214
+ prefix: "",
2215
+ defaults: false,
2216
+ includePublicSpace: false,
2217
+ permissions: [
2218
+ {
2219
+ service: "tinycloud.kv",
2220
+ space: AGENTS_SPACE,
2221
+ path: "",
2222
+ actions: ["get", "put", "del", "list", "metadata"]
2223
+ }
2224
+ ]
2225
+ };
2208
2226
  var BOOTSTRAP_SPACE_MANIFESTS = {
2209
2227
  [BOOTSTRAP_DEFAULT_SPACE]: TINYCLOUD_DEFAULT_SPACE_MANIFEST,
2210
2228
  [DEFAULT_MANIFEST_SPACE]: TINYCLOUD_APPLICATIONS_SPACE_MANIFEST,
2211
2229
  [ACCOUNT_REGISTRY_SPACE]: TINYCLOUD_ACCOUNT_SPACE_MANIFEST,
2212
2230
  [SECRETS_SPACE]: TINYCLOUD_SECRETS_BOOTSTRAP_MANIFEST,
2213
- [BOOTSTRAP_PUBLIC_SPACE]: TINYCLOUD_PUBLIC_SPACE_MANIFEST
2231
+ [BOOTSTRAP_PUBLIC_SPACE]: TINYCLOUD_PUBLIC_SPACE_MANIFEST,
2232
+ [AGENTS_SPACE]: TINYCLOUD_AGENTS_SPACE_MANIFEST
2214
2233
  };
2215
2234
  var BOOTSTRAP_PERSISTED_APPLICATION_MANIFESTS = [
2216
2235
  TINYCLOUD_SECRETS_BOOTSTRAP_MANIFEST
@@ -20399,6 +20418,8 @@ var ReplicaErrorCode = {
20399
20418
  CONFIG_MISMATCH: "REPLICA_CONFIG_MISMATCH",
20400
20419
  /** The runtime has no supported durable store (e.g. Node < 22.13). */
20401
20420
  RUNTIME_UNSUPPORTED: "RUNTIME_UNSUPPORTED",
20421
+ /** A required open() argument is missing or malformed (e.g. `principal`). */
20422
+ INVALID_ARGUMENT: "REPLICA_INVALID_ARGUMENT",
20402
20423
  /** The local store failed (I/O, corruption, schema). */
20403
20424
  STORAGE_ERROR: "STORAGE_ERROR",
20404
20425
  /** The local disk is full. */
@@ -20439,7 +20460,9 @@ var ReplicaErrorCode = {
20439
20460
  /** Fetched bytes do not hash to the ETag the node attested for them. */
20440
20461
  CONTENT_MISMATCH: "CONTENT_MISMATCH",
20441
20462
  /** A stored blob no longer hashes to its name. */
20442
- INTEGRITY_ERROR: "INTEGRITY_ERROR"
20463
+ INTEGRITY_ERROR: "INTEGRITY_ERROR",
20464
+ /** The replica handle was closed; in-flight calls settle with this code. */
20465
+ CLOSED: "REPLICA_CLOSED"
20443
20466
  };
20444
20467
  var REPLICA_ERROR = /* @__PURE__ */ Symbol.for("tinycloud.replica.error");
20445
20468
  var ReplicaError = class extends Error {
@@ -20549,12 +20572,14 @@ var Replica = class {
20549
20572
  #transportFor;
20550
20573
  #now;
20551
20574
  #leaseTtlMs;
20575
+ #onCommit;
20552
20576
  constructor(options) {
20553
20577
  this.#store = options.store;
20554
20578
  const transport = options.transport;
20555
20579
  this.#transportFor = options.transportFor ?? (transport === void 0 ? void 0 : () => transport);
20556
20580
  this.#now = options.now ?? Date.now;
20557
20581
  this.#leaseTtlMs = options.leaseTtlMs ?? DEFAULT_LEASE_TTL_MS;
20582
+ this.#onCommit = options.onCommit;
20558
20583
  }
20559
20584
  async #state() {
20560
20585
  const state = await this.#store.open();
@@ -20749,9 +20774,10 @@ var Replica = class {
20749
20774
  let cursor = state.cursor;
20750
20775
  let pinned = state.nodeDid;
20751
20776
  let coverage = state.coverage;
20777
+ const retentionGrantCid = config.retentionGrantCid;
20752
20778
  for (; ; ) {
20753
20779
  let page;
20754
- const retentionGrant = config.retentionGrantCid;
20780
+ const retentionGrant = retentionGrantCid;
20755
20781
  try {
20756
20782
  page = await attempt.transport.syncPage({
20757
20783
  prefix: config.prefix,
@@ -20787,6 +20813,7 @@ var Replica = class {
20787
20813
  authority: page.authority,
20788
20814
  coverage,
20789
20815
  at,
20816
+ retentionGrantCid: retentionGrant,
20790
20817
  window,
20791
20818
  complete: !page.more,
20792
20819
  promoteGrant: attempt.promote
@@ -20796,6 +20823,7 @@ var Replica = class {
20796
20823
  attempt.promote = null;
20797
20824
  }
20798
20825
  report.pages += 1;
20826
+ this.#onCommit?.();
20799
20827
  report.changes += page.changes.length;
20800
20828
  report.deleted += page.changes.filter((change) => change.deleted).length;
20801
20829
  report.fetched += verified.fetched;
@@ -20805,7 +20833,7 @@ var Replica = class {
20805
20833
  await this.#store.renewLease(attempt.lease, this.#leaseTtlMs);
20806
20834
  if (!page.more) break;
20807
20835
  }
20808
- report.repaired = await this.#repair(attempt, cursor, pinned, coverage);
20836
+ report.repaired = await this.#repair(attempt, cursor, pinned, coverage, retentionGrantCid);
20809
20837
  report.blobsCollected = await this.#store.collectGarbage(attempt.lease);
20810
20838
  report.coverage = coverage;
20811
20839
  report.contentMissing = (await this.#store.pendingRepairs(Number.MAX_SAFE_INTEGER)).length;
@@ -20887,7 +20915,7 @@ var Replica = class {
20887
20915
  }
20888
20916
  return { changes, blobs, fetched: fetched2 };
20889
20917
  }
20890
- async #repair(attempt, cursor, nodeDid, coverage) {
20918
+ async #repair(attempt, cursor, nodeDid, coverage, retentionGrantCid) {
20891
20919
  const pending = await this.#store.pendingRepairs(Number.MAX_SAFE_INTEGER);
20892
20920
  let repaired = 0;
20893
20921
  for (let start = 0; start < pending.length; start += REPAIR_BATCH) {
@@ -20915,11 +20943,13 @@ var Replica = class {
20915
20943
  authority: null,
20916
20944
  coverage,
20917
20945
  at: new Date(this.#now()).toISOString(),
20946
+ retentionGrantCid,
20918
20947
  window: this.#syncWindow(state.authority, attempt.grant),
20919
20948
  complete: false,
20920
20949
  promoteGrant: null
20921
20950
  });
20922
20951
  repaired += changes.length;
20952
+ this.#onCommit?.();
20923
20953
  }
20924
20954
  return repaired;
20925
20955
  }
@@ -21267,6 +21297,8 @@ var ReplicaErrorCode2 = {
21267
21297
  CONFIG_MISMATCH: "REPLICA_CONFIG_MISMATCH",
21268
21298
  /** The runtime has no supported durable store (e.g. Node < 22.13). */
21269
21299
  RUNTIME_UNSUPPORTED: "RUNTIME_UNSUPPORTED",
21300
+ /** A required open() argument is missing or malformed (e.g. `principal`). */
21301
+ INVALID_ARGUMENT: "REPLICA_INVALID_ARGUMENT",
21270
21302
  /** The local store failed (I/O, corruption, schema). */
21271
21303
  STORAGE_ERROR: "STORAGE_ERROR",
21272
21304
  /** The local disk is full. */
@@ -21307,7 +21339,9 @@ var ReplicaErrorCode2 = {
21307
21339
  /** Fetched bytes do not hash to the ETag the node attested for them. */
21308
21340
  CONTENT_MISMATCH: "CONTENT_MISMATCH",
21309
21341
  /** A stored blob no longer hashes to its name. */
21310
- INTEGRITY_ERROR: "INTEGRITY_ERROR"
21342
+ INTEGRITY_ERROR: "INTEGRITY_ERROR",
21343
+ /** The replica handle was closed; in-flight calls settle with this code. */
21344
+ CLOSED: "REPLICA_CLOSED"
21311
21345
  };
21312
21346
  var REPLICA_ERROR2 = /* @__PURE__ */ Symbol.for("tinycloud.replica.error");
21313
21347
  var ReplicaError2 = class extends Error {
@@ -21710,9 +21744,10 @@ var SqliteReplicaStore = class _SqliteReplicaStore {
21710
21744
  async setRetentionGrant(cid) {
21711
21745
  await this.#guardedWrite("Updating the retention grant", () => {
21712
21746
  this.#db.run(
21713
- "UPDATE replica SET retention_grant_cid = ?, local_read_policy = ? WHERE id = 1",
21747
+ "UPDATE replica SET retention_grant_cid = ?, local_read_policy = ?, retain_until = NULL WHERE id = 1 AND retention_grant_cid IS NOT ?",
21714
21748
  cid,
21715
- cid === null ? "whileGrantValid" : "retainAfterExpiry"
21749
+ cid === null ? "whileGrantValid" : "retainAfterExpiry",
21750
+ cid
21716
21751
  );
21717
21752
  });
21718
21753
  }
@@ -21915,9 +21950,13 @@ var SqliteReplicaStore = class _SqliteReplicaStore {
21915
21950
  const sets = ["cursor = ?", "coverage = ?"];
21916
21951
  const params = [p.cursor, p.coverage];
21917
21952
  if (p.authority !== null) {
21918
- sets.push("node_did = ?", "attested = 1", "not_before = ?", "expires_at = ?", "retain_until = ?", "last_sync_at = ?");
21919
- params.push(p.source.nodeDid, p.authority.notBefore, p.authority.expiresAt, p.authority.retainUntil, p.at);
21920
- if (p.authority.retainUntil !== null) sets.push("retention_revoked = NULL");
21953
+ sets.push("node_did = ?", "attested = 1", "not_before = ?", "expires_at = ?", "last_sync_at = ?");
21954
+ params.push(p.source.nodeDid, p.authority.notBefore, p.authority.expiresAt, p.at);
21955
+ if (this.#row().retention_grant_cid === p.retentionGrantCid) {
21956
+ sets.push("retain_until = ?");
21957
+ params.push(p.authority.retainUntil);
21958
+ if (p.authority.retainUntil !== null) sets.push("retention_revoked = NULL");
21959
+ }
21921
21960
  }
21922
21961
  if (p.complete) {
21923
21962
  sets.push("last_complete_at = ?", "last_error = NULL");