@triflux/core 10.62.0 → 10.64.0

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.
@@ -272,6 +272,7 @@ export async function readClaudeTranscript(transcriptPath, { requestId } = {}) {
272
272
  model: state.model,
273
273
  measuredAt: state.measuredAt,
274
274
  },
275
+ enqueued: state.queuedContent !== null,
275
276
  userSeen: state.userSeen,
276
277
  response: state.response,
277
278
  error: state.error,
@@ -23,14 +23,21 @@ const MODEL_CONTEXT = [
23
23
  },
24
24
  ];
25
25
 
26
- export const CONTEXT_THRESHOLDS = {
26
+ const CONTEXT_THRESHOLDS = {
27
27
  claude: { warnContextPct: 60, maxContextPct: 90 },
28
- codex: { warnContextPct: 15, maxContextPct: 22 },
28
+ codex: { warnContextPct: 60, maxContextPct: 85 },
29
29
  };
30
+ // rollout 실행 창을 못 읽으면 1.05M 표 값이 분모라 실제 창보다 비율이 작게 나온다.
31
+ const CODEX_MODEL_WINDOW_THRESHOLDS = { warnContextPct: 15, maxContextPct: 22 };
30
32
 
31
33
  const rolloutCache = new Map();
32
34
 
33
- export function modelContext(cli, model, estimatedContextTokens = null) {
35
+ export function modelContext(
36
+ cli,
37
+ model,
38
+ estimatedContextTokens = null,
39
+ rolloutContextWindow = null,
40
+ ) {
34
41
  const entry = MODEL_CONTEXT.find(
35
42
  (item) => item.cli === cli && item.model.test(model || ""),
36
43
  );
@@ -38,18 +45,20 @@ export function modelContext(cli, model, estimatedContextTokens = null) {
38
45
  const executionContextLimitTokens =
39
46
  cli === "claude" && process.env.CLAUDE_CODE_DISABLE_1M_CONTEXT === "1"
40
47
  ? 200_000
41
- : null;
42
- const effectiveLimit = Math.min(
43
- contextLimitTokens ?? Infinity,
44
- executionContextLimitTokens ?? Infinity,
45
- );
48
+ : rolloutContextWindow;
49
+ // Codex 는 rollout 이 보고한 창이 실제 실행 한도라 표 값과 무관하게 그 창을 쓴다.
50
+ const effectiveLimit =
51
+ cli === "codex"
52
+ ? (executionContextLimitTokens ?? contextLimitTokens)
53
+ : contextLimitTokens &&
54
+ Math.min(contextLimitTokens, executionContextLimitTokens ?? Infinity);
46
55
  return {
47
56
  estimatedContextTokens,
48
57
  contextLimitTokens,
49
58
  contextLimitSource: entry?.source ?? null,
50
59
  ...(executionContextLimitTokens ? { executionContextLimitTokens } : {}),
51
60
  contextPct:
52
- contextLimitTokens && Number.isFinite(estimatedContextTokens)
61
+ effectiveLimit && Number.isFinite(estimatedContextTokens)
53
62
  ? (estimatedContextTokens / effectiveLimit) * 100
54
63
  : null,
55
64
  };
@@ -60,7 +69,10 @@ export function contextGuard(
60
69
  context,
61
70
  { warnContextPct, maxContextPct } = {},
62
71
  ) {
63
- const defaults = CONTEXT_THRESHOLDS[cli];
72
+ const defaults =
73
+ cli === "codex" && !context?.executionContextLimitTokens
74
+ ? CODEX_MODEL_WINDOW_THRESHOLDS
75
+ : CONTEXT_THRESHOLDS[cli];
64
76
  const warn = warnContextPct ?? defaults?.warnContextPct ?? 0;
65
77
  const max = maxContextPct ?? defaults?.maxContextPct ?? 0;
66
78
  const fields = {
@@ -90,6 +102,7 @@ export function contextGuard(
90
102
  inputSent: false,
91
103
  hint: "세션을 승계한 뒤 새 세션에 요청하라.",
92
104
  ...fields,
105
+ thresholdPct: max,
93
106
  };
94
107
  }
95
108
  return warn > 0 && fields.contextPct >= warn
@@ -137,12 +150,19 @@ function acceptCodexLine(state, line) {
137
150
  } catch {
138
151
  return false;
139
152
  }
153
+ if (entry?.type === "compacted") {
154
+ state.compactCount += 1;
155
+ state.compact = { preTokens: state.tokens, postTokens: null };
156
+ }
140
157
  if (entry?.type === "turn_context")
141
158
  state.model = entry.payload?.model || state.model;
142
159
  if (entry?.type === "event_msg" && entry.payload?.type === "token_count") {
143
160
  const info = entry.payload.info;
144
- if (Number.isFinite(info?.last_token_usage?.total_tokens))
161
+ if (Number.isFinite(info?.last_token_usage?.total_tokens)) {
145
162
  state.tokens = info.last_token_usage.total_tokens;
163
+ if (state.compact && state.compact.postTokens === null)
164
+ state.compact.postTokens = state.tokens;
165
+ }
146
166
  if (Number.isFinite(info?.model_context_window))
147
167
  state.executionContextLimitTokens = info.model_context_window;
148
168
  }
@@ -172,6 +192,8 @@ export async function readCodexContext(rolloutPath, threadId) {
172
192
  decoder: new StringDecoder("utf8"),
173
193
  model: null,
174
194
  tokens: null,
195
+ compactCount: 0,
196
+ compact: null,
175
197
  executionContextLimitTokens: null,
176
198
  };
177
199
  }
@@ -197,8 +219,15 @@ export async function readCodexContext(rolloutPath, threadId) {
197
219
  state.mtimeMs = stat.mtimeMs;
198
220
  rolloutCache.set(rolloutPath, state);
199
221
  return {
200
- ...modelContext("codex", state.model, state.tokens),
222
+ ...modelContext(
223
+ "codex",
224
+ state.model,
225
+ state.tokens,
226
+ state.executionContextLimitTokens,
227
+ ),
201
228
  model: state.model,
229
+ compactCount: state.compactCount,
230
+ compact: state.compact,
202
231
  executionContextLimitTokens: state.executionContextLimitTokens,
203
232
  };
204
233
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@triflux/core",
3
- "version": "10.62.0",
3
+ "version": "10.64.0",
4
4
  "description": "triflux core — CLI routing, adapters. Zero native dependencies.",
5
5
  "type": "module",
6
6
  "main": "hub/index.mjs",