replicas-engine 0.1.682 → 0.1.683

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.
@@ -747,6 +747,44 @@ function coerceAuthFallbackPayload(payload) {
747
747
  ...typeof detail === "string" && detail ? { detail } : {}
748
748
  };
749
749
  }
750
+ var CHAT_GOAL_STATUSES = [
751
+ "active",
752
+ "paused",
753
+ "blocked",
754
+ "usageLimited",
755
+ "budgetLimited",
756
+ "complete"
757
+ ];
758
+ function isChatGoalStatus(value) {
759
+ return typeof value === "string" && CHAT_GOAL_STATUSES.some((status) => status === value);
760
+ }
761
+ function coerceChatGoalPayload(payload) {
762
+ const goal = payload.goal;
763
+ if (goal === null || goal === void 0) return null;
764
+ if (typeof goal !== "object") return null;
765
+ const candidate = goal;
766
+ const threadId = candidate.threadId;
767
+ const objective = candidate.objective;
768
+ const status = candidate.status;
769
+ const tokensUsed = candidate.tokensUsed;
770
+ const timeUsedSeconds = candidate.timeUsedSeconds;
771
+ const createdAt = candidate.createdAt;
772
+ const updatedAt = candidate.updatedAt;
773
+ const tokenBudget = candidate.tokenBudget ?? null;
774
+ if (typeof threadId !== "string" || typeof objective !== "string" || !isChatGoalStatus(status) || typeof tokensUsed !== "number" || typeof timeUsedSeconds !== "number" || typeof createdAt !== "string" || typeof updatedAt !== "string" || tokenBudget !== null && typeof tokenBudget !== "number") {
775
+ return null;
776
+ }
777
+ return {
778
+ threadId,
779
+ objective,
780
+ status,
781
+ tokenBudget,
782
+ tokensUsed,
783
+ timeUsedSeconds,
784
+ createdAt,
785
+ updatedAt
786
+ };
787
+ }
750
788
  var CONTEXT_USAGE_EVENT_TYPE = "context-usage";
751
789
 
752
790
  // ../shared/src/engine/v1.ts
@@ -6704,7 +6742,7 @@ var DEFAULT_CODEX_ARGS = [
6704
6742
  var MIN_CODEX_CLI_VERSION = "0.144.6";
6705
6743
  var CODEX_UPGRADE_TIMEOUT_MS = 12e4;
6706
6744
  var codexCliVersionEnsured = null;
6707
- var ENGINE_PACKAGE_VERSION = "0.1.682";
6745
+ var ENGINE_PACKAGE_VERSION = "0.1.683";
6708
6746
  var INITIALIZE_METHOD = "initialize";
6709
6747
  var INITIALIZED_NOTIFICATION = "initialized";
6710
6748
  var ACCOUNT_LOGIN_START_METHOD = "account/login/start";
@@ -6985,6 +7023,7 @@ export {
6985
7023
  AUTH_RETRY_STATUS_EVENT_TYPE,
6986
7024
  CURSOR_CONNECTION_STATUS_EVENT_TYPE,
6987
7025
  AUTH_FALLBACK_EVENT_TYPE,
7026
+ coerceChatGoalPayload,
6988
7027
  CONTEXT_USAGE_EVENT_TYPE,
6989
7028
  detectLanguageByPath,
6990
7029
  ASTER_PROVIDER,
@@ -7085,6 +7124,7 @@ export {
7085
7124
  parseChatHistoryCursor,
7086
7125
  createChatHistoryCursor,
7087
7126
  chatHistoryPageParamsFromQuery,
7127
+ getChatHistoryPageWindow,
7088
7128
  paginateChatHistory,
7089
7129
  CODEX_AUTH_ENV_KEYS,
7090
7130
  codexAuthEnvFromResponse,
@@ -7,7 +7,7 @@ import {
7
7
  headlessAgentRequestSchema,
8
8
  putPresignedFile,
9
9
  recoverCompletedTurn
10
- } from "./chunk-U5PW2XBP.js";
10
+ } from "./chunk-TQJ3KKVC.js";
11
11
 
12
12
  // src/headless-agent.ts
13
13
  import { createHash } from "crypto";
package/dist/src/index.js CHANGED
@@ -106,6 +106,7 @@ import {
106
106
  codexAuthEnvFromResponse,
107
107
  codexReasoningEffortForThinkingLevel,
108
108
  coerceBackgroundTaskPayload,
109
+ coerceChatGoalPayload,
109
110
  coerceClaudeResultPayload,
110
111
  createAcceptedUserMessageEvent,
111
112
  createChatHistoryCursor,
@@ -127,6 +128,7 @@ import {
127
128
  findGitCommitSignals,
128
129
  findPrMergeSignals,
129
130
  getChatHistoryPageSenders,
131
+ getChatHistoryPageWindow,
130
132
  getChatTranscriptHistorySize,
131
133
  getClaudeModelContextWindow,
132
134
  getCodexAspTurnResponse,
@@ -190,7 +192,7 @@ import {
190
192
  serializeCanvasContentResponse,
191
193
  shellQuotePosix,
192
194
  stripAgentDiagnosticErrors
193
- } from "./chunk-U5PW2XBP.js";
195
+ } from "./chunk-TQJ3KKVC.js";
194
196
 
195
197
  // src/index.ts
196
198
  import { serve } from "@hono/node-server";
@@ -5772,7 +5774,6 @@ var DEFAULT_MODEL = DEFAULT_CODEX_MODEL;
5772
5774
  var THREAD_START_METHOD = "thread/start";
5773
5775
  var THREAD_RESUME_METHOD = "thread/resume";
5774
5776
  var THREAD_READ_METHOD = "thread/read";
5775
- var THREAD_TURNS_LIST_METHOD = "thread/turns/list";
5776
5777
  var THREAD_GOAL_SET_METHOD = "thread/goal/set";
5777
5778
  var THREAD_GOAL_GET_METHOD = "thread/goal/get";
5778
5779
  var THREAD_GOAL_CLEAR_METHOD = "thread/goal/clear";
@@ -6510,6 +6511,7 @@ var CodexAspManager = class extends CodingAgentManager {
6510
6511
  codexAspSequence = 0;
6511
6512
  quotaStatus = new CodexQuotaStatusTracker();
6512
6513
  currentGoal = null;
6514
+ goalHistoryKnown = false;
6513
6515
  transcriptUpdateCoalescer = new TranscriptUpdateCoalescer((threadId) => {
6514
6516
  this.flushTranscriptUpdated(threadId);
6515
6517
  });
@@ -6530,6 +6532,11 @@ var CodexAspManager = class extends CodingAgentManager {
6530
6532
  if (replayed?.transcript && (!this.initialSessionId || replayed.transcript.threadId === this.initialSessionId)) {
6531
6533
  this.mergeTranscriptSnapshot(replayed.transcript);
6532
6534
  }
6535
+ const goalEvent = replayed?.events.findLast((event) => event.type === CHAT_GOAL_EVENT_TYPE);
6536
+ if (goalEvent) {
6537
+ this.currentGoal = coerceChatGoalPayload(goalEvent.payload);
6538
+ this.goalHistoryKnown = true;
6539
+ }
6533
6540
  this.currentThreadId = this.initialSessionId ?? replayed?.transcript?.threadId ?? null;
6534
6541
  }
6535
6542
  getHistorySink() {
@@ -6614,38 +6621,45 @@ var CodexAspManager = class extends CodingAgentManager {
6614
6621
  return true;
6615
6622
  }
6616
6623
  async getHistory(page = {}) {
6624
+ await this.initialized;
6617
6625
  await this.historyFile?.flush();
6626
+ const transcript = await this.ensureTranscriptHistory();
6627
+ const events = await this.historyFile?.loadEventsPage(page) ?? { events: [], beforeCursor: null };
6618
6628
  if (page.limit === void 0) {
6619
- const local = async () => {
6620
- const history = await this.historyFile?.load();
6621
- return {
6622
- thread_id: this.currentThreadId,
6623
- events: history?.events ?? [],
6624
- codexAspTranscript: this.currentThreadId ? history?.transcriptsByThreadId.get(this.currentThreadId) ?? null : null,
6625
- goal: this.currentGoal
6626
- };
6629
+ return {
6630
+ thread_id: this.currentThreadId,
6631
+ events: events.events,
6632
+ codexAspTranscript: transcript,
6633
+ goal: this.currentGoal
6627
6634
  };
6628
- if (!this.currentThreadId) return local();
6629
- return this.readFullNativeHistory().catch(local);
6630
6635
  }
6631
- const events = await this.historyFile?.loadEventsPage(page) ?? { events: [], beforeCursor: null };
6632
6636
  if (!this.currentThreadId) return { thread_id: null, ...events, goal: this.currentGoal };
6633
6637
  const cursor = parseChatHistoryCursor(page.beforeCursor);
6634
6638
  if (page.beforeCursor !== void 0 && cursor?.mode !== "range") throw new RangeError("Invalid chat history cursor");
6635
- let transcript = null;
6639
+ if (page.beforeCursor === void 0 && !this.goalHistoryKnown) {
6640
+ try {
6641
+ await this.refreshThreadGoal(await getCodexAspHost(), this.currentThreadId);
6642
+ } catch (error) {
6643
+ console.warn("[CodexAspManager] Failed to connect while refreshing thread goal:", error);
6644
+ }
6645
+ }
6646
+ let transcriptPage = null;
6636
6647
  let turnsBefore = null;
6637
- if (cursor?.turns !== null) {
6638
- const host = await getCodexAspHost();
6639
- if (page.beforeCursor === void 0) await this.refreshThreadGoal(host, this.currentThreadId);
6640
- const turns = await this.readNativeTurnsPage(page.limit, cursor?.turns, host);
6641
- transcript = turns.transcript;
6642
- turnsBefore = turns.before;
6648
+ if (cursor?.turns !== null && transcript) {
6649
+ const before = cursor?.turns === void 0 ? transcript.turns.length : /^\d+$/.test(cursor.turns) ? Number(cursor.turns) : Number.NaN;
6650
+ if (!Number.isSafeInteger(before) || before < 0) throw new RangeError("Invalid chat history cursor");
6651
+ const { startIndex, endIndex } = getChatHistoryPageWindow(transcript.turns.length, page.limit, before);
6652
+ transcriptPage = {
6653
+ ...transcript,
6654
+ turns: transcript.turns.slice(startIndex, endIndex)
6655
+ };
6656
+ turnsBefore = startIndex > 0 ? String(startIndex) : null;
6643
6657
  }
6644
6658
  const eventCursor = parseChatHistoryCursor(events.beforeCursor ?? void 0);
6645
6659
  return {
6646
6660
  thread_id: this.currentThreadId,
6647
6661
  ...events,
6648
- codexAspTranscript: transcript,
6662
+ codexAspTranscript: transcriptPage,
6649
6663
  goal: this.currentGoal,
6650
6664
  beforeCursor: createChatHistoryCursor({
6651
6665
  events: eventCursor?.events ?? null,
@@ -6653,54 +6667,14 @@ var CodexAspManager = class extends CodingAgentManager {
6653
6667
  })
6654
6668
  };
6655
6669
  }
6656
- async readFullNativeHistory() {
6657
- if (!this.currentThreadId) {
6658
- return { thread_id: null, events: [], goal: this.currentGoal };
6659
- }
6670
+ async ensureTranscriptHistory() {
6671
+ if (this.codexAspTranscript || !this.currentThreadId) return this.codexAspTranscript;
6660
6672
  const host = await getCodexAspHost();
6661
- const [response, history] = await Promise.all([
6662
- host.client.request(
6663
- THREAD_READ_METHOD,
6664
- { threadId: this.currentThreadId, includeTurns: true }
6665
- ),
6666
- this.historyFile?.load()
6667
- ]);
6668
- const transcript = this.mergeTranscriptSnapshot(threadToAspTranscript(response.thread));
6669
- return {
6670
- thread_id: this.currentThreadId,
6671
- events: history?.events ?? [],
6672
- codexAspTranscript: transcript,
6673
- goal: this.currentGoal
6674
- };
6675
- }
6676
- async readNativeTurnsPage(limit, cursor, host) {
6677
- if (!this.currentThreadId) throw new Error("A thread is required for native turn pagination");
6678
6673
  const response = await host.client.request(
6679
- THREAD_TURNS_LIST_METHOD,
6680
- {
6681
- threadId: this.currentThreadId,
6682
- cursor: cursor ?? null,
6683
- limit,
6684
- sortDirection: "desc",
6685
- itemsView: "full"
6686
- }
6687
- );
6688
- const nativeTranscript = turnsToAspTranscript(
6689
- this.currentThreadId,
6690
- (/* @__PURE__ */ new Date()).toISOString(),
6691
- response.data
6674
+ THREAD_READ_METHOD,
6675
+ { threadId: this.currentThreadId, includeTurns: true }
6692
6676
  );
6693
- const mergedTranscript = mergeCodexAspTranscripts(this.codexAspTranscript, nativeTranscript) ?? nativeTranscript;
6694
- this.codexAspTranscript = mergedTranscript;
6695
- this.syncTranscriptSequence(mergedTranscript);
6696
- const turnIds = new Set(response.data.map((turn) => turn.id));
6697
- return {
6698
- transcript: {
6699
- ...mergedTranscript,
6700
- turns: mergedTranscript.turns.filter((turn) => turnIds.has(turn.id))
6701
- },
6702
- before: response.nextCursor
6703
- };
6677
+ return this.mergeTranscriptSnapshot(threadToAspTranscript(response.thread));
6704
6678
  }
6705
6679
  getGoal() {
6706
6680
  return this.currentGoal;
@@ -7619,6 +7593,7 @@ var CodexAspManager = class extends CodingAgentManager {
7619
7593
  { threadId }
7620
7594
  );
7621
7595
  this.currentGoal = response.goal ? aspGoalToChatGoal(response.goal) : null;
7596
+ this.goalHistoryKnown = true;
7622
7597
  } catch (error) {
7623
7598
  console.warn("[CodexAspManager] Failed to read ASP thread goal:", error);
7624
7599
  }
@@ -7629,6 +7604,7 @@ var CodexAspManager = class extends CodingAgentManager {
7629
7604
  return;
7630
7605
  }
7631
7606
  this.currentGoal = nextGoal;
7607
+ this.goalHistoryKnown = true;
7632
7608
  const event = this.recordCodexHistoryEvent(
7633
7609
  CHAT_GOAL_EVENT_TYPE,
7634
7610
  { goal: nextGoal }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "replicas-engine",
3
- "version": "0.1.682",
3
+ "version": "0.1.683",
4
4
  "description": "Lightweight API server for Replicas workspaces",
5
5
  "type": "module",
6
6
  "main": "dist/src/index.js",