@xuda.io/ai_module 1.1.5605 → 1.1.5607

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/index.mjs +72 -4
  2. package/package.json +1 -1
package/index.mjs CHANGED
@@ -111,6 +111,26 @@ const parse_codex_jsonl = function (stdout) {
111
111
  return events;
112
112
  };
113
113
 
114
+ const get_number_value = function (...values) {
115
+ for (const value of values) {
116
+ if (typeof value === 'number' && Number.isFinite(value)) return value;
117
+ if (typeof value === 'string' && value.trim() && Number.isFinite(Number(value))) return Number(value);
118
+ }
119
+
120
+ return 0;
121
+ };
122
+
123
+ const normalize_codex_usage = function (usage) {
124
+ if (!usage || typeof usage !== 'object') {
125
+ return { input_tokens: 0, output_tokens: 0 };
126
+ }
127
+
128
+ const input_tokens = get_number_value(usage.input_tokens, usage.inputTokens, usage.prompt_tokens, usage.promptTokens, usage.total_input_tokens, usage.totalInputTokens, usage.total_token_usage?.input_tokens, usage.totalTokenUsage?.inputTokens);
129
+ const output_tokens = get_number_value(usage.output_tokens, usage.outputTokens, usage.completion_tokens, usage.completionTokens, usage.total_output_tokens, usage.totalOutputTokens, usage.total_token_usage?.output_tokens, usage.totalTokenUsage?.outputTokens);
130
+
131
+ return { input_tokens, output_tokens };
132
+ };
133
+
114
134
  const create_codex_jsonl_stream_parser = function (onEvent) {
115
135
  let buffer = '';
116
136
 
@@ -137,11 +157,24 @@ const get_openai_codex_cli_command = function () {
137
157
  return _conf.openai_codex_command || 'codex';
138
158
  };
139
159
 
140
- const get_openai_codex_exec_args = function () {
160
+ const get_openai_codex_model = function () {
161
+ return _conf.openai_codex_model || _conf.ai_models?.openai_codex_model?.model || null;
162
+ };
163
+
164
+ const get_openai_codex_usage_model = function (codex_model, requested_codex_model) {
165
+ if (requested_codex_model) return codex_model;
166
+ return _conf.ai_models?.openai_codex_model ? 'openai_codex_model' : codex_model || _conf.openai_codex_command || 'openai_codex_cli';
167
+ };
168
+
169
+ const get_openai_codex_exec_args = function (codex_model) {
141
170
  const args = ['exec', '--json'];
142
171
  const bypass_approvals_and_sandbox = typeof _conf.openai_codex_bypass_approvals_and_sandbox === 'undefined' ? true : _conf.openai_codex_bypass_approvals_and_sandbox;
143
172
  const sandbox = _conf.openai_codex_sandbox;
144
173
 
174
+ if (codex_model) {
175
+ args.push('--model', codex_model);
176
+ }
177
+
145
178
  if (bypass_approvals_and_sandbox) {
146
179
  args.push('--dangerously-bypass-approvals-and-sandbox');
147
180
  } else if (sandbox) {
@@ -1216,11 +1249,14 @@ export const execute_codex_request = async function (req_or_ip, prompt_arg, atta
1216
1249
  const prompt = is_req_call ? req_or_ip.prompt : prompt_arg;
1217
1250
  let attachments = is_req_call ? req_or_ip.attachments || [] : attachments_arg;
1218
1251
  const uid = is_req_call ? req_or_ip.uid : undefined;
1252
+ const account_profile_info = is_req_call && uid ? req_or_ip.account_profile_info || (await get_active_account_profile_info(uid, req_or_ip.profile_id)) : undefined;
1253
+ const requested_codex_model = is_req_call ? req_or_ip.codex_model || req_or_ip.model : null;
1254
+ const codex_model = requested_codex_model || get_openai_codex_model();
1219
1255
  const conversation_id = is_req_call ? req_or_ip.conversation_id || req_or_ip.conversation_doc?._id : undefined;
1220
1256
  const job_id = is_req_call ? prompt_arg || req_or_ip.job_id : undefined;
1221
1257
  stream_enabled = is_req_call ? req_or_ip.stream !== false && req_or_ip.stream !== 'false' : false;
1222
- const prompt_conversation_item_id = is_req_call ? await _common.xuda_get_uuid('chat_conversation_item') : undefined;
1223
- const response_conversation_item_id = is_req_call ? await _common.xuda_get_uuid('chat_conversation_item') : undefined;
1258
+ const prompt_conversation_item_id = is_req_call && uid ? await _common.xuda_get_uuid('chat_conversation_item') : undefined;
1259
+ const response_conversation_item_id = is_req_call && uid ? await _common.xuda_get_uuid('chat_conversation_item') : undefined;
1224
1260
 
1225
1261
  let stream_delta_seq = 0;
1226
1262
  let stream_delta_text = '';
@@ -1286,6 +1322,7 @@ export const execute_codex_request = async function (req_or_ip, prompt_arg, atta
1286
1322
  }
1287
1323
 
1288
1324
  const reasoning = [];
1325
+ let codex_usage = { input_tokens: 0, output_tokens: 0 };
1289
1326
  let streamed_agent_messages = new Set();
1290
1327
  const pushReasoning = function (type, text, metadata = {}) {
1291
1328
  if (!text) return;
@@ -1345,6 +1382,7 @@ export const execute_codex_request = async function (req_or_ip, prompt_arg, atta
1345
1382
  emitToDashboard('stream_phase', event.message, { update: true, error: true });
1346
1383
  break;
1347
1384
  case 'turn.completed':
1385
+ codex_usage = normalize_codex_usage(event.usage);
1348
1386
  emitToDashboard('stream_phase', 'Codex request completed', { update: true, usage: event.usage });
1349
1387
  break;
1350
1388
  case 'turn.failed':
@@ -1401,7 +1439,7 @@ ${prompt}`;
1401
1439
  }
1402
1440
 
1403
1441
  const openai_codex_command = get_openai_codex_cli_command();
1404
- const codex_args = get_openai_codex_exec_args();
1442
+ const codex_args = get_openai_codex_exec_args(codex_model);
1405
1443
  for (const image_path of image_paths) {
1406
1444
  codex_args.push('--image', image_path);
1407
1445
  }
@@ -1415,6 +1453,29 @@ ${prompt}`;
1415
1453
  onStdout: create_codex_jsonl_stream_parser(handleCodexEvent),
1416
1454
  });
1417
1455
  const events = parse_codex_jsonl(ret.stdout);
1456
+ if (!codex_usage.input_tokens && !codex_usage.output_tokens && Array.isArray(events)) {
1457
+ const completed_event_with_usage = events.findLast((event) => event?.type === 'turn.completed' && event.usage);
1458
+ codex_usage = normalize_codex_usage(completed_event_with_usage?.usage);
1459
+ }
1460
+
1461
+ if (uid && account_profile_info && (codex_usage.input_tokens || codex_usage.output_tokens)) {
1462
+ account_msa.record_ai_usage(
1463
+ uid,
1464
+ codex_usage.input_tokens,
1465
+ codex_usage.output_tokens,
1466
+ 'execute codex request',
1467
+ prompt,
1468
+ get_openai_codex_usage_model(codex_model, requested_codex_model),
1469
+ {
1470
+ conversation_id,
1471
+ job_id,
1472
+ remote_host: get_codex_remote_host(ip),
1473
+ exit_code: ret.exit_code,
1474
+ attachments_count: attachments.length,
1475
+ },
1476
+ account_profile_info,
1477
+ );
1478
+ }
1418
1479
 
1419
1480
  if (ret.exit_code !== 0) {
1420
1481
  emitToDashboard('stream_phase', 'Codex request failed', { update: true });
@@ -1432,6 +1493,7 @@ ${prompt}`;
1432
1493
  stderr: ret.stderr,
1433
1494
  events,
1434
1495
  reasoning,
1496
+ usage: codex_usage,
1435
1497
  },
1436
1498
  };
1437
1499
  }
@@ -1448,6 +1510,7 @@ ${prompt}`;
1448
1510
  stderr: ret.stderr,
1449
1511
  events,
1450
1512
  reasoning,
1513
+ usage: codex_usage,
1451
1514
  },
1452
1515
  };
1453
1516
  } catch (err) {
@@ -4382,6 +4445,11 @@ export const submit_chat_conversation = async function (req, job_id, headers) {
4382
4445
  break;
4383
4446
  }
4384
4447
 
4448
+ case 'account_profiles': {
4449
+ ret = await ai_chat_conversation(req, job_id, headers);
4450
+ break;
4451
+ }
4452
+
4385
4453
  case 'studio': {
4386
4454
  ret = await chat_studio(req, job_id, headers);
4387
4455
  break;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xuda.io/ai_module",
3
- "version": "1.1.5605",
3
+ "version": "1.1.5607",
4
4
  "description": "Xuda AI Module",
5
5
  "main": "index.mjs",
6
6
  "type": "module",