@quantiya/codevibe-core 2.0.78 → 2.0.79

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.
@@ -77487,6 +77487,7 @@ function validateOutboxLocation(value, generation, file) {
77487
77487
  }
77488
77488
  function definitiveRejectionCode(error) {
77489
77489
  if (!(error instanceof AppSyncGraphQLError)) return null;
77490
+ if (error.errorType === "SYNC_QUOTA_EXHAUSTED") return "SYNC_QUOTA_EXHAUSTED";
77490
77491
  let values = [error.errorType, error.message.replace(/^GraphQL error: /, "")].filter(
77491
77492
  (value) => typeof value == "string"
77492
77493
  );
@@ -77549,14 +77550,14 @@ var WorkspaceTerminalCoordinator = class {
77549
77550
  throw new Error("WorkspaceTerminalCoordinator: record exceeds size limit");
77550
77551
  return bytes;
77551
77552
  }
77552
- async readJson(filePath) {
77553
+ async readJson(filePath, missing = null) {
77553
77554
  try {
77554
77555
  let stat14 = await import_node_fs34.promises.lstat(filePath);
77555
77556
  if (!stat14.isFile() || stat14.isSymbolicLink() || stat14.size > MAX_RECORD_BYTES2)
77556
77557
  throw new Error("WorkspaceTerminalCoordinator: unsafe or oversized record");
77557
77558
  return JSON.parse(await import_node_fs34.promises.readFile(filePath, "utf8"));
77558
77559
  } catch (error) {
77559
- if (error.code === "ENOENT") return null;
77560
+ if (error.code === "ENOENT") return missing;
77560
77561
  throw error;
77561
77562
  }
77562
77563
  }
@@ -77949,6 +77950,7 @@ var WorkspaceTerminalCoordinator = class {
77949
77950
  ]);
77950
77951
  }
77951
77952
  async flushTerminalIntent(intent) {
77953
+ if (await this.settleQuarantined(intent.nonce, intent.sessionGenerationId)) return;
77952
77954
  intent.subjectKind === "task" ? (validateTerminal(intent), await this.prepareExactInput(intent, "outbox")) : (validateGroupTerminal(intent), await this.prepareExactInput(intent, "draft"), await this.promoteDraftToOutbox(intent));
77953
77955
  let row3 = await this.readJson(
77954
77956
  this.outboxPath(intent.nonce, intent.sessionGenerationId)
@@ -77956,25 +77958,64 @@ var WorkspaceTerminalCoordinator = class {
77956
77958
  if (!row3) throw new Error("WorkspaceTerminalCoordinator: exact outbox row is unavailable");
77957
77959
  await this.sendOutbox(validateOutboxForIntent(row3, intent));
77958
77960
  }
77959
- async acknowledge(nonce, generation = this.generation()) {
77961
+ async syncSettlementDirectory(directory) {
77962
+ let handle;
77963
+ try {
77964
+ handle = await import_node_fs34.promises.open(directory, import_node_fs34.constants.O_RDONLY | import_node_fs34.constants.O_DIRECTORY | import_node_fs34.constants.O_NOFOLLOW);
77965
+ } catch (error) {
77966
+ if (error.code === "ENOENT") return;
77967
+ throw error;
77968
+ }
77969
+ try {
77970
+ await handle.sync();
77971
+ } finally {
77972
+ await handle.close();
77973
+ }
77974
+ }
77975
+ async persistSettlementMarker(file, record2) {
77976
+ await atomicWriteFileSync2(file, this.serialize(record2), { requireDirectorySync: !0 });
77977
+ for (let directory of [this.quarantineRoot(), path74.join(this.rootDir, "quarantine"), this.rootDir]) {
77978
+ let handle = await import_node_fs34.promises.open(directory, import_node_fs34.constants.O_RDONLY | import_node_fs34.constants.O_DIRECTORY | import_node_fs34.constants.O_NOFOLLOW);
77979
+ try {
77980
+ await handle.sync();
77981
+ } finally {
77982
+ await handle.close();
77983
+ }
77984
+ }
77985
+ }
77986
+ async acknowledge(nonce, generation = this.generation(), settlement = !1) {
77987
+ let sync = (directory) => settlement ? this.syncSettlementDirectory(directory) : fsyncDir(directory);
77960
77988
  await import_node_fs34.promises.unlink(this.outboxPath(nonce, generation)).catch((error) => {
77961
77989
  if (error.code !== "ENOENT") throw error;
77962
- }), await fsyncDir(this.outboxDir(generation)), await import_node_fs34.promises.unlink(this.draftPath(nonce, generation)).catch((error) => {
77990
+ }), await sync(this.outboxDir(generation)), await import_node_fs34.promises.unlink(this.draftPath(nonce, generation)).catch((error) => {
77963
77991
  if (error.code !== "ENOENT") throw error;
77964
- }), await fsyncDir(this.draftDir(generation)), await import_node_fs34.promises.unlink(this.intentPath(nonce, generation)).catch((error) => {
77992
+ }), await sync(this.draftDir(generation)), await import_node_fs34.promises.unlink(this.intentPath(nonce, generation)).catch((error) => {
77965
77993
  if (error.code !== "ENOENT") throw error;
77966
- }), await fsyncDir(this.intentDir(generation));
77994
+ }), await sync(this.intentDir(generation));
77967
77995
  }
77968
77996
  async quarantine(nonce, rejectionCode, generation = this.generation()) {
77969
77997
  let raw = await this.readJson(this.outboxPath(nonce, generation));
77970
77998
  if (!raw) return;
77971
- let row3 = validateOutbox(raw), directory = this.quarantineDir(generation), files = await this.listRecordsAcrossGenerations(this.quarantineRoot());
77999
+ let row3 = validateOutbox(raw);
78000
+ if (await this.settleQuarantined(nonce, generation, row3.inputHash)) return;
78001
+ let directory = this.quarantineDir(generation), files = await this.listRecordsAcrossGenerations(this.quarantineRoot());
77972
78002
  if (files.length >= MAX_QUARANTINE_RECORDS) {
77973
- let oldest = (await Promise.all(files.map(async (record2) => ({
78003
+ let pending2 = /* @__PURE__ */ new Set();
78004
+ for (let root of [this.intentRoot(), this.outboxRoot(), this.draftRoot()])
78005
+ for (let record2 of await this.listRecordsAcrossGenerations(root))
78006
+ pending2.add(`${record2.generation}/${sha2563(path74.basename(record2.file, ".json"))}`);
78007
+ let disposable = files.filter((record2) => !pending2.has(`${record2.generation}/${path74.basename(record2.file, ".json")}`)), oldest = (await Promise.all(disposable.map(async (record2) => ({
77974
78008
  ...record2,
77975
78009
  mtimeMs: (await import_node_fs34.promises.stat(record2.file)).mtimeMs
77976
78010
  })))).sort((left, right) => left.mtimeMs - right.mtimeMs || left.file.localeCompare(right.file))[0];
77977
- await import_node_fs34.promises.unlink(oldest.file), await fsyncDir(path74.dirname(oldest.file));
78011
+ if (!oldest) throw new Error("WorkspaceTerminalCoordinator: pending settlement capacity is full");
78012
+ for (let directory2 of [this.intentDir(oldest.generation), this.outboxDir(oldest.generation), this.draftDir(oldest.generation)]) {
78013
+ await this.syncSettlementDirectory(directory2);
78014
+ for (let file of await this.listRecords(directory2))
78015
+ if (sha2563(path74.basename(file, ".json")) === path74.basename(oldest.file, ".json"))
78016
+ throw new Error("WorkspaceTerminalCoordinator: settlement cleanup is still pending");
78017
+ }
78018
+ await import_node_fs34.promises.unlink(oldest.file), await this.syncSettlementDirectory(path74.dirname(oldest.file));
77978
78019
  }
77979
78020
  let diagnostic = {
77980
78021
  version: QUARANTINE_VERSION,
@@ -77983,10 +78024,37 @@ var WorkspaceTerminalCoordinator = class {
77983
78024
  rejectionCode,
77984
78025
  quarantinedAt: this.now().toISOString()
77985
78026
  };
77986
- await atomicWriteFileSync2(
78027
+ await this.persistSettlementMarker(
77987
78028
  path74.join(directory, `${sha2563(nonce)}.json`),
77988
- this.serialize(diagnostic)
77989
- ), await this.acknowledge(nonce, generation), this.reportSyncIssue(`Workspace result could not be synchronized (${rejectionCode}).`);
78029
+ diagnostic
78030
+ ), await this.acknowledge(nonce, generation, !0), this.reportSyncIssue(`Workspace result could not be synchronized (${rejectionCode}).`);
78031
+ }
78032
+ async settleQuarantined(nonce, generation, inputHash) {
78033
+ let markerPath = path74.join(this.quarantineDir(generation), `${sha2563(nonce)}.json`), missing = /* @__PURE__ */ Symbol("absent settlement record"), raw = await this.readJson(markerPath, missing);
78034
+ if (raw === missing) return !1;
78035
+ if (raw === null || typeof raw != "object" || Array.isArray(raw))
78036
+ throw new Error("WorkspaceTerminalCoordinator: invalid settlement barrier");
78037
+ let record2 = raw;
78038
+ if (record2.version !== QUARANTINE_VERSION || record2.nonceHash !== sha2563(nonce) || typeof record2.inputHash != "string" || !SHA256_RE2.test(record2.inputHash) || inputHash !== void 0 && record2.inputHash !== inputHash || typeof record2.rejectionCode != "string" || ![
78039
+ "SYNC_QUOTA_EXHAUSTED",
78040
+ "OUTCOME_ADMISSION_EXPIRED",
78041
+ "OUTCOME_ADMISSION_CONFLICT",
78042
+ "GENERATION_MISMATCH",
78043
+ "ACCOUNT_DELETING"
78044
+ ].includes(record2.rejectionCode) || typeof record2.quarantinedAt != "string")
78045
+ throw new Error("WorkspaceTerminalCoordinator: invalid settlement barrier");
78046
+ let intentValue = await this.readJson(this.intentPath(nonce, generation), missing), intent = intentValue === missing ? void 0 : validateAnyIntent(intentValue);
78047
+ if (intent && (intent.nonce !== nonce || intent.sessionId !== this.session.sessionId || intent.sessionGenerationId !== generation))
78048
+ throw new Error("WorkspaceTerminalCoordinator: settlement intent identity changed");
78049
+ for (let file of [this.outboxPath(nonce, generation), this.draftPath(nonce, generation)]) {
78050
+ let saved = await this.readJson(file, missing);
78051
+ if (saved === missing) continue;
78052
+ let row3 = validateOutboxLocation(saved, generation, file);
78053
+ if (row3.sessionId !== this.session.sessionId || row3.inputHash !== record2.inputHash)
78054
+ throw new Error("WorkspaceTerminalCoordinator: settlement identity changed");
78055
+ intent && validateOutboxForIntent(row3, intent);
78056
+ }
78057
+ return await this.persistSettlementMarker(markerPath, record2), await this.acknowledge(nonce, generation, !0), this.reportSyncIssue(`Workspace result could not be synchronized (${record2.rejectionCode}).`), !0;
77990
78058
  }
77991
78059
  reportSyncIssue(message2) {
77992
78060
  this.reportedSyncIssues.has(message2) || (this.reportedSyncIssues.add(message2), this.onSyncIssue?.(message2));
@@ -77994,6 +78062,7 @@ var WorkspaceTerminalCoordinator = class {
77994
78062
  async sendOutbox(row3) {
77995
78063
  for (let attempt = 1; attempt <= 2; attempt += 1)
77996
78064
  try {
78065
+ if (await this.settleQuarantined(row3.nonce, row3.sessionGenerationId, row3.inputHash)) return;
77997
78066
  let target2 = this.outboxPath(row3.nonce, row3.sessionGenerationId), current = validateOutboxLocation(await this.readJson(target2), row3.sessionGenerationId, target2), { syncProtocol: priorProtocol, ...original } = row3, { syncProtocol: currentProtocol, ...persisted } = current;
77998
78067
  if (canonicalJson3(original) !== canonicalJson3(persisted) || priorProtocol === "SYNC_V2" && currentProtocol !== "SYNC_V2")
77999
78068
  throw new Error("WorkspaceTerminalCoordinator: outbox identity or protocol changed");
@@ -107,8 +107,11 @@ export declare class WorkspaceTerminalCoordinator implements WorkspaceOutcomeSin
107
107
  private prepareExactInput;
108
108
  private promoteDraftToOutbox;
109
109
  private flushTerminalIntent;
110
+ private syncSettlementDirectory;
111
+ private persistSettlementMarker;
110
112
  private acknowledge;
111
113
  private quarantine;
114
+ private settleQuarantined;
112
115
  private reportSyncIssue;
113
116
  private sendOutbox;
114
117
  /** Reconcile terminal receipts first, then replay exact encrypted bytes. */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@quantiya/codevibe-core",
3
- "version": "2.0.78",
3
+ "version": "2.0.79",
4
4
  "description": "Core library for CodeVibe plugins - shared keychain, crypto, AppSync, and auth functionality",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",