@supen-ai/cli 1.3.3 → 1.3.4

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.
@@ -31,10 +31,6 @@ const MIRRORED_THREAD_LIMIT = 80;
31
31
  const MIRRORED_THREAD_HISTORY_LIMIT = 100;
32
32
  const MIRRORED_THREAD_HISTORY_MAX_BYTES = 64 * 1024 * 1024;
33
33
  const MIRRORED_THREAD_TEXT_LIMIT = 48_000;
34
- const MIRRORED_THREAD_TOOL_STRING_LIMIT = 24_000;
35
- const MIRRORED_THREAD_OBJECT_DEPTH_LIMIT = 4;
36
- const MIRRORED_THREAD_OBJECT_KEY_LIMIT = 80;
37
- const MIRRORED_THREAD_OBJECT_ARRAY_LIMIT = 80;
38
34
  const MIRRORED_THREAD_INLINE_DATA_URL_LIMIT = 120_000;
39
35
  const MIRRORED_THREAD_STREAM_REPLAY_LIMIT = 500;
40
36
  const MIRRORED_THREAD_STREAM_REPLAY_MAX_BYTES = 8 * 1024 * 1024;
@@ -44,7 +40,7 @@ const require = createRequire(import.meta.url);
44
40
  const HOST_DAEMON_INSTALL_DIR = path.join(SUPEN_HOME, 'daemon');
45
41
  const HOST_DAEMON_CLI_PACKAGE_ROOT = path.join(HOST_DAEMON_INSTALL_DIR, 'node_modules', '@supen-ai', 'cli');
46
42
  const HOST_DAEMON_BIN_PATH = path.join(HOST_DAEMON_CLI_PACKAGE_ROOT, 'daemon', 'scripts', 'supen-daemon.js');
47
- const HOST_DAEMON_PACKAGE_SPEC = '@supen-ai/cli';
43
+ const HOST_DAEMON_PACKAGE_SPEC = '@supen-ai/cli@latest';
48
44
  function readSqliteRows(dbPath, query) {
49
45
  try {
50
46
  const { DatabaseSync } = require('node:sqlite');
@@ -953,34 +949,6 @@ function truncateMirroredHistoryString(value, limit, label) {
953
949
  const omitted = value.length - limit;
954
950
  return `${value.slice(0, limit)}\n\n[${label} truncated: ${omitted.toLocaleString()} more characters omitted]`;
955
951
  }
956
- function sanitizeMirroredHistoryPayload(value, depth = 0) {
957
- if (typeof value === 'string') {
958
- return truncateMirroredHistoryString(value, MIRRORED_THREAD_TOOL_STRING_LIMIT, 'Tool output');
959
- }
960
- if (value === null || typeof value !== 'object')
961
- return value;
962
- if (depth >= MIRRORED_THREAD_OBJECT_DEPTH_LIMIT) {
963
- return Array.isArray(value) ? '[Nested array omitted]' : '[Nested object omitted]';
964
- }
965
- if (Array.isArray(value)) {
966
- const visibleItems = value
967
- .slice(0, MIRRORED_THREAD_OBJECT_ARRAY_LIMIT)
968
- .map((item) => sanitizeMirroredHistoryPayload(item, depth + 1));
969
- if (value.length > MIRRORED_THREAD_OBJECT_ARRAY_LIMIT) {
970
- visibleItems.push(`[${value.length - MIRRORED_THREAD_OBJECT_ARRAY_LIMIT} more items omitted]`);
971
- }
972
- return visibleItems;
973
- }
974
- const result = {};
975
- const entries = Object.entries(value);
976
- for (const [key, entryValue] of entries.slice(0, MIRRORED_THREAD_OBJECT_KEY_LIMIT)) {
977
- result[key] = sanitizeMirroredHistoryPayload(entryValue, depth + 1);
978
- }
979
- if (entries.length > MIRRORED_THREAD_OBJECT_KEY_LIMIT) {
980
- result.__truncated_keys = `${entries.length - MIRRORED_THREAD_OBJECT_KEY_LIMIT} more keys omitted`;
981
- }
982
- return result;
983
- }
984
952
  function safeMirroredHistoryAttachmentUrl(url) {
985
953
  const trimmed = url.trim();
986
954
  if (trimmed.startsWith('data:') &&
@@ -1088,111 +1056,6 @@ function isMirroredGoalContextMessage(text) {
1088
1056
  const trimmed = text.trim();
1089
1057
  return trimmed.startsWith('<goal_context>') && trimmed.endsWith('</goal_context>');
1090
1058
  }
1091
- function parseJsonObject(value) {
1092
- if (typeof value !== 'string')
1093
- return value;
1094
- try {
1095
- return JSON.parse(value);
1096
- }
1097
- catch {
1098
- return value;
1099
- }
1100
- }
1101
- function readableOutputFromMcpResult(result) {
1102
- if (!result || typeof result !== 'object')
1103
- return result;
1104
- const ok = result.Ok;
1105
- const error = result.Err;
1106
- const payload = ok && typeof ok === 'object' ? ok : error;
1107
- if (!payload || typeof payload !== 'object')
1108
- return result;
1109
- const content = payload.content;
1110
- if (!Array.isArray(content))
1111
- return payload;
1112
- const text = content
1113
- .map((entry) => {
1114
- if (typeof entry === 'string')
1115
- return entry;
1116
- if (entry && typeof entry === 'object' && typeof entry.text === 'string') {
1117
- return entry.text;
1118
- }
1119
- return '';
1120
- })
1121
- .filter(Boolean)
1122
- .join('\n');
1123
- return text || payload;
1124
- }
1125
- function fileNameFromPath(value) {
1126
- const trimmed = value.trim();
1127
- if (!trimmed)
1128
- return '';
1129
- return path.basename(trimmed);
1130
- }
1131
- function displayPatchPath(filePath, workspacePath) {
1132
- const trimmed = filePath.trim();
1133
- if (!trimmed || !workspacePath || !path.isAbsolute(trimmed))
1134
- return trimmed;
1135
- const relativePath = path.relative(workspacePath, trimmed);
1136
- if (!relativePath || relativePath.startsWith('..') || path.isAbsolute(relativePath))
1137
- return trimmed;
1138
- return relativePath;
1139
- }
1140
- function diffStatsFromText(value) {
1141
- let additions = 0;
1142
- let deletions = 0;
1143
- for (const line of value.split(/\r?\n/)) {
1144
- if (line.startsWith('+++') || line.startsWith('---'))
1145
- continue;
1146
- if (line.startsWith('+'))
1147
- additions += 1;
1148
- if (line.startsWith('-'))
1149
- deletions += 1;
1150
- }
1151
- return { additions, deletions };
1152
- }
1153
- function extractPatchFiles(input) {
1154
- if (typeof input !== 'string')
1155
- return [];
1156
- const files = [];
1157
- const seen = new Set();
1158
- for (const line of input.split(/\r?\n/)) {
1159
- const match = line.match(/^\*\*\* (?:Update|Add|Delete) File:\s+(.+?)\s*$/);
1160
- if (!match)
1161
- continue;
1162
- const filePath = match[1]?.trim();
1163
- if (!filePath || seen.has(filePath))
1164
- continue;
1165
- seen.add(filePath);
1166
- files.push({ path: filePath, name: fileNameFromPath(filePath) || filePath });
1167
- }
1168
- return files;
1169
- }
1170
- function extractPatchEndFiles(changes, workspacePath) {
1171
- if (!changes || typeof changes !== 'object')
1172
- return [];
1173
- return Object.entries(changes).map(([filePath, change]) => {
1174
- const diff = typeof change?.unified_diff === 'string' ? change.unified_diff : '';
1175
- const displayPath = displayPatchPath(filePath, workspacePath);
1176
- return {
1177
- path: displayPath,
1178
- name: fileNameFromPath(displayPath) || displayPath,
1179
- ...(diff ? { diff } : {}),
1180
- ...diffStatsFromText(diff),
1181
- };
1182
- });
1183
- }
1184
- function codexReplayEvent(eventId, timestamp, taskId, raw) {
1185
- return {
1186
- id: eventId,
1187
- timestamp,
1188
- task_id: taskId,
1189
- chunk: {
1190
- type: 'data-codex-event',
1191
- id: eventId,
1192
- data: { raw },
1193
- },
1194
- };
1195
- }
1196
1059
  function mirroredThreadWorkspacePath(sessionPath, stateEntry) {
1197
1060
  const stateCwd = typeof stateEntry?.cwd === 'string' ? stateEntry.cwd : null;
1198
1061
  const sessionWorkspace = readThreadWorkspacePath(sessionPath);
@@ -1216,10 +1079,8 @@ export function readCodexThreadHistory(threadId, limit = MIRRORED_THREAD_HISTORY
1216
1079
  const messages = [];
1217
1080
  const events = [];
1218
1081
  let messageIndex = 0;
1219
- let eventIndex = 0;
1220
1082
  let latestTimestamp = indexEntry?.updated_at || '';
1221
1083
  let recentGoalContext = null;
1222
- const toolCalls = new Map();
1223
1084
  const mirroredUserMessageKey = (text) => sanitizeMirroredUserText(text)
1224
1085
  .replace(/\s+/g, ' ')
1225
1086
  .trim();
@@ -1309,39 +1170,6 @@ export function readCodexThreadHistory(threadId, limit = MIRRORED_THREAD_HISTORY
1309
1170
  const messageId = typeof payload.id === 'string' ? payload.id : `${threadId}-web-user-${event.sequence}`;
1310
1171
  pushUserMessage(text, timestamp, messageId, attachments);
1311
1172
  };
1312
- const pushEvent = (timestamp, chunk) => {
1313
- eventIndex += 1;
1314
- events.push({
1315
- id: `${threadId}-event-${eventIndex}`,
1316
- timestamp,
1317
- task_id: threadId,
1318
- chunk,
1319
- });
1320
- };
1321
- const pushToolInput = (timestamp, toolCallId, toolName, input) => {
1322
- const sanitizedInput = sanitizeMirroredHistoryPayload(input);
1323
- toolCalls.set(toolCallId, { toolName, input: sanitizedInput });
1324
- pushEvent(timestamp, {
1325
- type: 'tool-input-available',
1326
- toolCallId,
1327
- toolName,
1328
- input: sanitizedInput,
1329
- });
1330
- };
1331
- const pushToolOutput = (timestamp, toolCallId, output, fallbackToolName, fallbackInput, failed = false) => {
1332
- const toolCall = toolCalls.get(toolCallId);
1333
- const toolName = toolCall?.toolName || fallbackToolName;
1334
- const input = toolCall?.input ?? (fallbackInput === undefined ? undefined : sanitizeMirroredHistoryPayload(fallbackInput));
1335
- pushEvent(timestamp, {
1336
- type: failed ? 'tool-output-error' : 'tool-output-available',
1337
- toolCallId,
1338
- ...(toolName ? { toolName } : {}),
1339
- ...(input !== undefined ? { input } : {}),
1340
- ...(failed
1341
- ? { errorText: typeof output === 'string' ? output : 'Tool failed' }
1342
- : { output: sanitizeMirroredHistoryPayload(parseJsonObject(output)) }),
1343
- });
1344
- };
1345
1173
  for (const line of lines) {
1346
1174
  const parsed = parseJsonLine(line);
1347
1175
  if (typeof parsed?.timestamp === 'string')
@@ -1356,146 +1184,11 @@ export function readCodexThreadHistory(threadId, limit = MIRRORED_THREAD_HISTORY
1356
1184
  if (payload.type === 'user_message') {
1357
1185
  const text = typeof payload.message === 'string' ? payload.message.trim() : '';
1358
1186
  pushUserMessage(text, timestamp, undefined, imageAttachmentsFromUnknown(payload.images));
1359
- continue;
1360
- }
1361
- if (payload.type === 'turn_aborted') {
1362
- if (eventLogThreadId !== threadId) {
1363
- events.push(codexReplayEvent(`${threadId}-turn-aborted-${eventIndex + 1}`, timestamp, threadId, {
1364
- method: 'turn/completed',
1365
- params: {
1366
- turn: {
1367
- id: payload.turn_id || payload.turnId || 'turn',
1368
- status: 'interrupted',
1369
- },
1370
- },
1371
- }));
1372
- eventIndex += 1;
1373
- }
1374
- continue;
1375
- }
1376
- if (payload.type === 'context_compacted') {
1377
- events.push(codexReplayEvent(`${threadId}-context-compacted-${eventIndex + 1}`, timestamp, threadId, {
1378
- method: 'contextCompaction/completed',
1379
- params: {
1380
- threadId,
1381
- messageCount: payload.message_count || payload.messageCount,
1382
- tokensSaved: payload.tokens_saved || payload.tokensSaved,
1383
- },
1384
- }));
1385
- eventIndex += 1;
1386
- continue;
1387
1187
  }
1388
- if (payload.type === 'web_search_end') {
1389
- const toolCallId = typeof payload.call_id === 'string' ? payload.call_id : `${threadId}-web-search-${eventIndex + 1}`;
1390
- const input = {
1391
- query: payload.query,
1392
- action: payload.action,
1393
- };
1394
- pushToolInput(timestamp, toolCallId, 'web_search', input);
1395
- pushToolOutput(timestamp, toolCallId, payload.action || payload.query || 'completed');
1396
- continue;
1397
- }
1398
- if (payload.type === 'mcp_tool_call_end') {
1399
- const toolCallId = typeof payload.call_id === 'string' ? payload.call_id : `${threadId}-mcp-tool-${eventIndex + 1}`;
1400
- const invocation = payload.invocation && typeof payload.invocation === 'object'
1401
- ? payload.invocation
1402
- : {};
1403
- const server = typeof invocation.server === 'string' ? invocation.server : '';
1404
- const tool = typeof invocation.tool === 'string' ? invocation.tool : '';
1405
- const toolName = [server, tool].filter(Boolean).join('.') || 'mcpToolCall';
1406
- const input = invocation.arguments;
1407
- const result = payload.result && typeof payload.result === 'object'
1408
- ? payload.result
1409
- : payload.result;
1410
- const failed = Boolean(result && typeof result === 'object' && 'Err' in result);
1411
- pushToolInput(timestamp, toolCallId, toolName, input);
1412
- pushToolOutput(timestamp, toolCallId, readableOutputFromMcpResult(result), toolName, input, failed);
1413
- continue;
1414
- }
1415
- if (payload.type === 'patch_apply_end') {
1416
- const files = extractPatchEndFiles(payload.changes, workspacePath);
1417
- const additions = files.reduce((sum, file) => sum + file.additions, 0);
1418
- const deletions = files.reduce((sum, file) => sum + file.deletions, 0);
1419
- events.push(codexReplayEvent(`${threadId}-patch-end-${eventIndex + 1}`, timestamp, threadId, {
1420
- method: 'codex/patchApply/completed',
1421
- params: {
1422
- callId: payload.call_id,
1423
- success: payload.success !== false,
1424
- files,
1425
- fileCount: files.length,
1426
- additions,
1427
- deletions,
1428
- status: payload.status,
1429
- },
1430
- }));
1431
- eventIndex += 1;
1432
- continue;
1433
- }
1434
- }
1435
- if (parsed?.type === 'compacted') {
1436
- events.push(codexReplayEvent(`${threadId}-context-compacted-${eventIndex + 1}`, timestamp, threadId, {
1437
- method: 'contextCompaction/completed',
1438
- params: { threadId },
1439
- }));
1440
- eventIndex += 1;
1441
1188
  continue;
1442
1189
  }
1443
1190
  if (parsed?.type !== 'response_item')
1444
1191
  continue;
1445
- if (payload.type === 'function_call') {
1446
- const toolCallId = typeof payload.call_id === 'string' ? payload.call_id : `${threadId}-tool-${eventIndex + 1}`;
1447
- const toolName = typeof payload.name === 'string' ? payload.name : 'tool';
1448
- const input = sanitizeMirroredHistoryPayload(parseJsonObject(payload.arguments));
1449
- pushToolInput(timestamp, toolCallId, toolName, input);
1450
- continue;
1451
- }
1452
- if (payload.type === 'function_call_output') {
1453
- const toolCallId = typeof payload.call_id === 'string' ? payload.call_id : `${threadId}-tool-${eventIndex + 1}`;
1454
- pushToolOutput(timestamp, toolCallId, payload.output);
1455
- continue;
1456
- }
1457
- if (payload.type === 'tool_search_call') {
1458
- const toolCallId = typeof payload.call_id === 'string' ? payload.call_id : `${threadId}-tool-search-${eventIndex + 1}`;
1459
- pushToolInput(timestamp, toolCallId, 'tool_search', payload.arguments);
1460
- continue;
1461
- }
1462
- if (payload.type === 'tool_search_output') {
1463
- const toolCallId = typeof payload.call_id === 'string' ? payload.call_id : `${threadId}-tool-search-${eventIndex + 1}`;
1464
- pushToolOutput(timestamp, toolCallId, {
1465
- status: payload.status,
1466
- tools: payload.tools,
1467
- }, 'tool_search');
1468
- continue;
1469
- }
1470
- if (payload.type === 'custom_tool_call') {
1471
- const toolName = typeof payload.name === 'string' ? payload.name : 'custom_tool';
1472
- const toolCallId = typeof payload.call_id === 'string' ? payload.call_id : `${threadId}-tool-${eventIndex + 1}`;
1473
- if (toolName === 'apply_patch') {
1474
- const input = typeof payload.input === 'string' ? payload.input : '';
1475
- const files = extractPatchFiles(input);
1476
- events.push(codexReplayEvent(`${threadId}-patch-start-${eventIndex + 1}`, timestamp, threadId, {
1477
- method: 'codex/patchApply/started',
1478
- params: {
1479
- callId: payload.call_id,
1480
- files,
1481
- fileCount: files.length,
1482
- ...diffStatsFromText(input),
1483
- },
1484
- }));
1485
- eventIndex += 1;
1486
- }
1487
- else {
1488
- pushToolInput(timestamp, toolCallId, toolName, parseJsonObject(payload.input));
1489
- }
1490
- continue;
1491
- }
1492
- if (payload.type === 'custom_tool_call_output') {
1493
- const toolCallId = typeof payload.call_id === 'string' ? payload.call_id : `${threadId}-tool-${eventIndex + 1}`;
1494
- if (toolCalls.has(toolCallId)) {
1495
- pushToolOutput(timestamp, toolCallId, payload.output);
1496
- }
1497
- continue;
1498
- }
1499
1192
  if (payload.type !== 'message')
1500
1193
  continue;
1501
1194
  messageIndex += 1;
@@ -1708,7 +1401,7 @@ function threadStreamChunkForEvent(event) {
1708
1401
  !Array.isArray(event.raw_payload) &&
1709
1402
  typeof event.raw_payload.type === 'string' &&
1710
1403
  String(event.raw_payload.type).trim()) {
1711
- return normalizeStoredCodexThreadChunk(event.raw_payload);
1404
+ return event.raw_payload;
1712
1405
  }
1713
1406
  return {
1714
1407
  type: 'data-codex-event',
@@ -1718,28 +1411,6 @@ function threadStreamChunkForEvent(event) {
1718
1411
  },
1719
1412
  };
1720
1413
  }
1721
- function normalizeStoredCodexThreadChunk(chunk) {
1722
- if (chunk.type !== 'data-supen-event')
1723
- return chunk;
1724
- const data = chunk.data && typeof chunk.data === 'object' && !Array.isArray(chunk.data)
1725
- ? chunk.data
1726
- : {};
1727
- const raw = data.raw && typeof data.raw === 'object' && !Array.isArray(data.raw)
1728
- ? data.raw
1729
- : {};
1730
- return {
1731
- ...chunk,
1732
- type: 'data-codex-event',
1733
- data: {
1734
- ...data,
1735
- eventType: typeof data.eventType === 'string' && data.eventType.trim()
1736
- ? data.eventType
1737
- : typeof raw.method === 'string' && raw.method.trim()
1738
- ? raw.method
1739
- : 'codex-event',
1740
- },
1741
- };
1742
- }
1743
1414
  function buildMcpSettingsResponse() {
1744
1415
  const overrides = getMcpEnvOverrides();
1745
1416
  const runtimeEnv = { ...process.env };
@@ -1902,7 +1573,6 @@ function readPackageVersion(packageRoot) {
1902
1573
  }
1903
1574
  }
1904
1575
  function detectDaemonPackageStatus() {
1905
- const envVersion = process.env.SUPEN_DAEMON_VERSION || process.env.npm_package_version || null;
1906
1576
  let packageRoot = null;
1907
1577
  try {
1908
1578
  packageRoot = findPackageRootFrom(require.resolve('@supen-ai/daemon'), '@supen-ai/daemon');
@@ -1945,7 +1615,7 @@ function detectDaemonPackageStatus() {
1945
1615
  ? 'local-package'
1946
1616
  : null;
1947
1617
  return {
1948
- version: envVersion || bundledDaemonVersion || packageVersion,
1618
+ version: bundledDaemonVersion || packageVersion,
1949
1619
  package_root: packageRoot || bundledDaemonRoot,
1950
1620
  install_source: installSource,
1951
1621
  update_supported: installSource === 'supen-cli-bundle' || installSource === 'npm-global',
@@ -2341,6 +2011,47 @@ function readInstalledAppsPayload() {
2341
2011
  }),
2342
2012
  };
2343
2013
  }
2014
+ const CODEX_SUBSCRIPTION_STATUS_WAIT_MS = 1800;
2015
+ const CODEX_SUBSCRIPTION_CACHE_TTL_MS = 5 * 60 * 1000;
2016
+ let cachedCodexSubscription = null;
2017
+ let codexSubscriptionRefreshInFlight = null;
2018
+ function refreshCodexSubscriptionStatus() {
2019
+ if (codexSubscriptionRefreshInFlight)
2020
+ return codexSubscriptionRefreshInFlight;
2021
+ codexSubscriptionRefreshInFlight = readCodexSubscription()
2022
+ .then((payload) => {
2023
+ cachedCodexSubscription = { payload, cachedAt: Date.now() };
2024
+ return payload;
2025
+ })
2026
+ .finally(() => {
2027
+ codexSubscriptionRefreshInFlight = null;
2028
+ });
2029
+ return codexSubscriptionRefreshInFlight;
2030
+ }
2031
+ async function readCodexSubscriptionForStatus() {
2032
+ if (cachedCodexSubscription &&
2033
+ Date.now() - cachedCodexSubscription.cachedAt < CODEX_SUBSCRIPTION_CACHE_TTL_MS) {
2034
+ return { payload: cachedCodexSubscription.payload, error: null };
2035
+ }
2036
+ const refresh = refreshCodexSubscriptionStatus();
2037
+ const timeout = new Promise((resolve) => {
2038
+ setTimeout(() => resolve(null), CODEX_SUBSCRIPTION_STATUS_WAIT_MS).unref?.();
2039
+ });
2040
+ try {
2041
+ const payload = await Promise.race([refresh, timeout]);
2042
+ if (payload)
2043
+ return { payload, error: null };
2044
+ }
2045
+ catch (err) {
2046
+ if (cachedCodexSubscription)
2047
+ return { payload: cachedCodexSubscription.payload, error: null };
2048
+ return { payload: null, error: err?.message || 'Unable to read Codex subscription details.' };
2049
+ }
2050
+ if (cachedCodexSubscription)
2051
+ return { payload: cachedCodexSubscription.payload, error: null };
2052
+ refresh.catch(() => undefined);
2053
+ return { payload: null, error: null };
2054
+ }
2344
2055
  function readCachedCodingCliStatusPayload(options) {
2345
2056
  startCodingCliStatusCache({
2346
2057
  build: () => ({
@@ -2415,14 +2126,22 @@ function codexSubscriptionSummary(subscription) {
2415
2126
  : {};
2416
2127
  return {
2417
2128
  plan_type: typeof rateLimits.planType === 'string' && rateLimits.planType.trim() ? rateLimits.planType.trim() : null,
2418
- credits_balance: typeof credits.balance === 'string' && credits.balance.trim() ? credits.balance.trim() : null,
2129
+ credits_balance: typeof credits.balance === 'string' && credits.balance.trim()
2130
+ ? credits.balance.trim()
2131
+ : typeof credits.balance === 'number' && Number.isFinite(credits.balance)
2132
+ ? String(credits.balance)
2133
+ : null,
2419
2134
  };
2420
2135
  }
2421
2136
  async function readCodexAgentStatusPayload() {
2422
- const status = readCachedCodingCliStatusPayload();
2137
+ const status = {
2138
+ ...readCachedCodingCliStatusPayload(),
2139
+ daemon: detectDaemonPackageStatus(),
2140
+ };
2423
2141
  const quotaStatus = readLatestSpaceQuotaStatus();
2424
- try {
2425
- const subscription = await readCodexSubscription();
2142
+ const subscriptionResult = await readCodexSubscriptionForStatus();
2143
+ const subscription = subscriptionResult.payload;
2144
+ if (subscription) {
2426
2145
  const subscriptionWindows = mergeQuotaWindows(normalizeCodexSubscriptionQuotaWindows(subscription), normalizeQuotaWindows(subscription.rate_limits), normalizeQuotaWindows(subscription.rate_limits_by_limit_id));
2427
2146
  return {
2428
2147
  ...status,
@@ -2437,23 +2156,21 @@ async function readCodexAgentStatusPayload() {
2437
2156
  quota_windows: mergeQuotaWindows(quotaStatus.windows, subscriptionWindows),
2438
2157
  };
2439
2158
  }
2440
- catch (err) {
2441
- return {
2442
- ...status,
2443
- subscription: {
2444
- ok: false,
2445
- fetched_at: null,
2446
- payload: null,
2447
- error: err?.message || 'Unable to read Codex subscription details.',
2448
- },
2449
- subscription_summary: {
2450
- plan_type: null,
2451
- credits_balance: null,
2452
- },
2453
- quota_status: quotaStatus,
2454
- quota_windows: quotaStatus.windows,
2455
- };
2456
- }
2159
+ return {
2160
+ ...status,
2161
+ subscription: {
2162
+ ok: false,
2163
+ fetched_at: null,
2164
+ payload: null,
2165
+ error: subscriptionResult.error,
2166
+ },
2167
+ subscription_summary: {
2168
+ plan_type: null,
2169
+ credits_balance: null,
2170
+ },
2171
+ quota_status: quotaStatus,
2172
+ quota_windows: quotaStatus.windows,
2173
+ };
2457
2174
  }
2458
2175
  function readRuntimeModelStatusPayload() {
2459
2176
  const selected_cli = process.env.SUPEN_CODING_CLI || readConfigSummary().coding_cli || 'codex';