replicas-engine 0.1.455 → 0.1.460

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 (2) hide show
  1. package/dist/src/index.js +50 -34
  2. package/package.json +1 -1
package/dist/src/index.js CHANGED
@@ -543,7 +543,7 @@ var WORKSPACE_SIZES = ["small", "large"];
543
543
  var INVALID_WORKSPACE_SIZE_ERROR = `Invalid size: must be one of ${WORKSPACE_SIZES.join(", ")}`;
544
544
 
545
545
  // ../shared/src/e2b.ts
546
- var E2B_TEMPLATE_NAME = "replicas-sandbox-2026-07-19-v7";
546
+ var E2B_TEMPLATE_NAME = "replicas-sandbox-2026-07-19-v12";
547
547
 
548
548
  // ../shared/src/runtime-env.ts
549
549
  function shellQuotePosix(value) {
@@ -8604,7 +8604,7 @@ var DEFAULT_CODEX_ARGS = ["app-server", "--listen", "stdio://"];
8604
8604
  var MIN_CODEX_CLI_VERSION = "0.144.0";
8605
8605
  var CODEX_UPGRADE_TIMEOUT_MS = 12e4;
8606
8606
  var codexCliVersionEnsured = null;
8607
- var ENGINE_PACKAGE_VERSION = "0.1.455";
8607
+ var ENGINE_PACKAGE_VERSION = "0.1.460";
8608
8608
  var INITIALIZE_METHOD = "initialize";
8609
8609
  var INITIALIZED_NOTIFICATION = "initialized";
8610
8610
  var ACCOUNT_LOGIN_START_METHOD = "account/login/start";
@@ -8847,24 +8847,32 @@ function buildCodexRateLimitsSnapshot(fields) {
8847
8847
  var CodexQuotaStatusTracker = class {
8848
8848
  lastEmittedQuotaState = "ok";
8849
8849
  latestQuotaSnapshot = null;
8850
- quotaBlocked = false;
8851
- get blocked() {
8852
- return this.quotaBlocked;
8853
- }
8854
- get latestSnapshot() {
8855
- return this.latestQuotaSnapshot;
8856
- }
8857
- prime(snapshot) {
8850
+ // OpenAI keeps `rate_limit_reached_type` set in snapshots even while requests
8851
+ // still succeed (the flag is sticky until an authoritative snapshot clears it),
8852
+ // so an out_of_credits reading on its own is not trustworthy. Record it here,
8853
+ // and only surface it via confirmOutOfCredits() once a turn actually fails
8854
+ // with a quota error.
8855
+ observe(snapshot) {
8858
8856
  this.latestQuotaSnapshot = snapshot;
8859
- this.quotaBlocked = snapshot.state === "out_of_credits";
8857
+ if (snapshot.state === "out_of_credits") return null;
8858
+ if (snapshot.state === this.lastEmittedQuotaState) return null;
8859
+ return this.emit(snapshot);
8860
+ }
8861
+ confirmOutOfCredits() {
8862
+ if (this.latestQuotaSnapshot?.state !== "out_of_credits") return null;
8863
+ return this.emit(this.latestQuotaSnapshot);
8864
+ }
8865
+ recordTurnSuccess() {
8866
+ if (this.lastEmittedQuotaState === "ok") return null;
8867
+ return this.emit({
8868
+ state: "ok",
8869
+ balance: this.latestQuotaSnapshot?.balance ?? null,
8870
+ rateLimitResetType: null,
8871
+ planType: this.latestQuotaSnapshot?.planType ?? null
8872
+ });
8860
8873
  }
8861
- apply(snapshot, force = false) {
8862
- const stateChanged = snapshot.state !== this.lastEmittedQuotaState;
8863
- if (!stateChanged && !force) {
8864
- return null;
8865
- }
8874
+ emit(snapshot) {
8866
8875
  this.lastEmittedQuotaState = snapshot.state;
8867
- this.quotaBlocked = snapshot.state === "out_of_credits";
8868
8876
  this.latestQuotaSnapshot = snapshot;
8869
8877
  const payload = {
8870
8878
  state: snapshot.state,
@@ -8872,12 +8880,11 @@ var CodexQuotaStatusTracker = class {
8872
8880
  rateLimitResetType: snapshot.rateLimitResetType,
8873
8881
  planType: snapshot.planType
8874
8882
  };
8875
- const event = {
8883
+ return {
8876
8884
  timestamp: (/* @__PURE__ */ new Date()).toISOString(),
8877
8885
  type: CODEX_QUOTA_STATUS_EVENT_TYPE,
8878
8886
  payload
8879
8887
  };
8880
- return event;
8881
8888
  }
8882
8889
  };
8883
8890
 
@@ -9145,6 +9152,18 @@ function aspGoalToChatGoal(goal) {
9145
9152
  updatedAt: timestampFromSeconds(goal.updatedAt)
9146
9153
  };
9147
9154
  }
9155
+ function isQuotaTurnFailure(turn) {
9156
+ const info = turn.error?.codexErrorInfo;
9157
+ if (!info) return false;
9158
+ if (info === "usageLimitExceeded") return true;
9159
+ if (typeof info === "object") {
9160
+ return Object.values(info).some((detail) => isRecord4(detail) && detail.httpStatusCode === 429);
9161
+ }
9162
+ return false;
9163
+ }
9164
+ function isQuotaErrorMessage(error) {
9165
+ return error instanceof Error && /\b429\b|rate.?limit|usage.?limit|quota|out.of.credits|credits?.?(?:depleted|exhausted|remaining)/i.test(error.message);
9166
+ }
9148
9167
  function formatTurnFailure(turn) {
9149
9168
  const turnError = turn.error;
9150
9169
  if (!turnError) {
@@ -9840,14 +9859,6 @@ var CodexAspManager = class extends CodingAgentManager {
9840
9859
  }
9841
9860
  async executeAspTurn(request, recordUserMessage, options = {}) {
9842
9861
  const host = await getCodexAspHost();
9843
- if (this.quotaStatus.blocked && this.quotaStatus.latestSnapshot) {
9844
- await this.refreshQuotaSnapshot(host);
9845
- if (this.quotaStatus.blocked && this.quotaStatus.latestSnapshot) {
9846
- recordUserMessage(options.userMessagePayload);
9847
- this.emitQuotaStatus(this.quotaStatus.latestSnapshot, true);
9848
- return;
9849
- }
9850
- }
9851
9862
  const developerInstructions = this.buildCombinedInstructions(request.customInstructions);
9852
9863
  recordUserMessage(options.userMessagePayload);
9853
9864
  const threadId = await this.ensureThread(host, request, developerInstructions);
@@ -9858,19 +9869,18 @@ var CodexAspManager = class extends CodingAgentManager {
9858
9869
  try {
9859
9870
  completedTurn = await runTurn(host, threadId);
9860
9871
  } catch (error) {
9861
- await this.refreshQuotaSnapshot(host);
9862
- if (this.quotaStatus.blocked) {
9872
+ if (isQuotaErrorMessage(error) && await this.confirmOutOfCredits(host)) {
9863
9873
  return;
9864
9874
  }
9865
9875
  throw error;
9866
9876
  }
9867
9877
  if (completedTurn.status === "failed") {
9868
- await this.refreshQuotaSnapshot(host);
9869
- if (this.quotaStatus.blocked) {
9878
+ if (isQuotaTurnFailure(completedTurn) && await this.confirmOutOfCredits(host)) {
9870
9879
  return;
9871
9880
  }
9872
9881
  throw new Error(formatTurnFailure(completedTurn));
9873
9882
  }
9883
+ this.emitQuotaEvent(this.quotaStatus.recordTurnSuccess());
9874
9884
  }
9875
9885
  async ensureThread(host, request, developerInstructions) {
9876
9886
  await this.applySkillRegistries(host);
@@ -10694,7 +10704,7 @@ var CodexAspManager = class extends CodingAgentManager {
10694
10704
  handleRateLimits(rateLimits) {
10695
10705
  const snapshot = extractRateLimitsSnapshot(rateLimits);
10696
10706
  if (snapshot) {
10697
- this.emitQuotaStatus(snapshot);
10707
+ this.emitQuotaEvent(this.quotaStatus.observe(snapshot));
10698
10708
  }
10699
10709
  }
10700
10710
  async refreshQuotaSnapshot(host) {
@@ -10707,8 +10717,14 @@ var CodexAspManager = class extends CodingAgentManager {
10707
10717
  } catch {
10708
10718
  }
10709
10719
  }
10710
- emitQuotaStatus(snapshot, force = false) {
10711
- const event = this.quotaStatus.apply(snapshot, force);
10720
+ async confirmOutOfCredits(host) {
10721
+ await this.refreshQuotaSnapshot(host);
10722
+ const event = this.quotaStatus.confirmOutOfCredits();
10723
+ if (!event) return false;
10724
+ this.emitQuotaEvent(event);
10725
+ return true;
10726
+ }
10727
+ emitQuotaEvent(event) {
10712
10728
  if (!event) return;
10713
10729
  this.trackHistoryEvent(event);
10714
10730
  this.onEvent(event);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "replicas-engine",
3
- "version": "0.1.455",
3
+ "version": "0.1.460",
4
4
  "description": "Lightweight API server for Replicas workspaces",
5
5
  "type": "module",
6
6
  "main": "dist/src/index.js",