@xuda.io/ai_module 1.1.5643 → 1.1.5645
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.
- package/index.mjs +73 -8
- package/package.json +1 -1
package/index.mjs
CHANGED
|
@@ -253,7 +253,19 @@ const get_openai_codex_exec_args = function (codex_model, opts = {}) {
|
|
|
253
253
|
// end-user prompts can't run Codex with full host access. The studio/vibe flow
|
|
254
254
|
// passes nothing and keeps the global setting.
|
|
255
255
|
const sandbox = opts.sandbox || _conf.openai_codex_sandbox;
|
|
256
|
-
|
|
256
|
+
// Precedence: an explicit per-call sandbox always confines the run; opts.bypass_sandbox is
|
|
257
|
+
// the one deliberate escape hatch (the customer-VPS vibe build, which runs on the
|
|
258
|
+
// customer's OWN box and needs to install and restart things there); otherwise the config
|
|
259
|
+
// decides. The config default is now false, so a new call site that forgets to say
|
|
260
|
+
// anything gets a CONFINED run instead of full host access, which is how the mentor Codex
|
|
261
|
+
// tool ended up unsandboxed.
|
|
262
|
+
const bypass_approvals_and_sandbox = opts.sandbox
|
|
263
|
+
? false
|
|
264
|
+
: opts.bypass_sandbox === true
|
|
265
|
+
? true
|
|
266
|
+
: typeof _conf.openai_codex_bypass_approvals_and_sandbox === 'undefined'
|
|
267
|
+
? true
|
|
268
|
+
: _conf.openai_codex_bypass_approvals_and_sandbox;
|
|
257
269
|
|
|
258
270
|
if (codex_model) {
|
|
259
271
|
// codex_model is a catalog code (user pick or cheapest default); the Codex CLI
|
|
@@ -333,6 +345,7 @@ const LIST_SORT_PATHS = {
|
|
|
333
345
|
};
|
|
334
346
|
|
|
335
347
|
const account_ms = await import(`${module_path}/account_module/index_ms.mjs`);
|
|
348
|
+
const ticket_ms = await import(`${module_path}/ticket_module/index_ms.mjs`);
|
|
336
349
|
const drive_ms = await import(`${module_path}/drive_module/index_ms.mjs`);
|
|
337
350
|
const jobs_ms = await import(`${module_path}/jobs_module/index_ms.mjs`);
|
|
338
351
|
const team_ms = await import(`${module_path}/team_module/index_ms.mjs`);
|
|
@@ -1386,6 +1399,9 @@ export const execute_codex_request = async function (req_or_ip, prompt_arg, atta
|
|
|
1386
1399
|
// Optional per-call hardening (used by the AI site generator for untrusted
|
|
1387
1400
|
// prompts): a confined sandbox + a hard wall-clock timeout on the codex run.
|
|
1388
1401
|
const sandbox = is_req_call ? req_or_ip.sandbox : undefined;
|
|
1402
|
+
// Explicit opt-out of the confined default, for runs that legitimately need full access
|
|
1403
|
+
// on a box the customer owns. Never set this for anything running on Xuda infrastructure.
|
|
1404
|
+
const bypass_sandbox = is_req_call ? req_or_ip.bypass_sandbox === true : false;
|
|
1389
1405
|
const codex_timeout = is_req_call ? req_or_ip.codex_timeout : undefined;
|
|
1390
1406
|
// Optional: a scoped MCP server exposed to codex (the in-app vibe's Xuda
|
|
1391
1407
|
// platform actions). { url, bearer_env_var, bearer_value } — the bearer is
|
|
@@ -1594,7 +1610,7 @@ ${prompt}`;
|
|
|
1594
1610
|
}
|
|
1595
1611
|
|
|
1596
1612
|
const openai_codex_command = get_openai_codex_cli_command();
|
|
1597
|
-
let codex_args = get_openai_codex_exec_args(codex_model, { sandbox });
|
|
1613
|
+
let codex_args = get_openai_codex_exec_args(codex_model, { sandbox, bypass_sandbox });
|
|
1598
1614
|
if (agent_mcp && agent_mcp.url) {
|
|
1599
1615
|
// Register the Xuda MCP server for this run. Global `-c` overrides must
|
|
1600
1616
|
// precede the `exec` subcommand (args[0]), so prepend them. The bearer
|
|
@@ -4696,7 +4712,7 @@ export const classify_external_app_scan = async (req) => {
|
|
|
4696
4712
|
}
|
|
4697
4713
|
};
|
|
4698
4714
|
|
|
4699
|
-
// Triage a CPI error incident for the central error resolver (
|
|
4715
|
+
// Triage a CPI error incident for the central error resolver (ticket_module).
|
|
4700
4716
|
// The Zod schema lives here because zodTextFormat schemas cannot cross the
|
|
4701
4717
|
// message broker (it JSON-serializes args and strips functions). The resolver
|
|
4702
4718
|
// passes a plain-JSON { incident, catalog_entry } payload and gets back a plain
|
|
@@ -4987,10 +5003,17 @@ const get_error_message = function (err, fallback = 'Unknown error') {
|
|
|
4987
5003
|
};
|
|
4988
5004
|
|
|
4989
5005
|
const get_plugin_import_specifier = function (app_id, plugin_name, resource, dev = true) {
|
|
4990
|
-
|
|
5006
|
+
// `dev` asks for the repo working copy under $XUDA_HOME/plugins, which only
|
|
5007
|
+
// exists on the debug box. Anywhere else (master, the regions) that directory
|
|
5008
|
+
// is absent, so the plugin has to be the npm copy installed into the app's own
|
|
5009
|
+
// plugins folder. Without the is_debug gate every plugin-backed agent tool
|
|
5010
|
+
// resolved to a path that does not exist in production.
|
|
5011
|
+
const use_source = dev && _conf.is_debug;
|
|
5012
|
+
const absolute_path = use_source ? path.join(process.env.XUDA_HOME, 'plugins', plugin_name, resource) : path.join(_conf.plugins_drive_path, app_id, 'node_modules', plugin_name, resource);
|
|
4991
5013
|
|
|
4992
5014
|
const file_url = pathToFileURL(absolute_path);
|
|
4993
|
-
if (
|
|
5015
|
+
if (use_source) {
|
|
5016
|
+
// Cache-bust so an edit to the working copy is picked up without a restart.
|
|
4994
5017
|
file_url.searchParams.set('ts', `${Date.now()}`);
|
|
4995
5018
|
}
|
|
4996
5019
|
|
|
@@ -7037,6 +7060,11 @@ ${conversation_history || `User (dashboard): ${prompt}`}
|
|
|
7037
7060
|
prompt: codex_prompt,
|
|
7038
7061
|
attachments,
|
|
7039
7062
|
stream: false,
|
|
7063
|
+
// Deliberate: this build runs on the CUSTOMER'S OWN VPS over SSH and has to install
|
|
7064
|
+
// packages, write outside a workspace and restart services there, so it keeps full
|
|
7065
|
+
// access. Stated explicitly now that the global default is confined, so the choice
|
|
7066
|
+
// is visible instead of inherited. Nothing on Xuda infrastructure may set this.
|
|
7067
|
+
bypass_sandbox: true,
|
|
7040
7068
|
...(agent_key ? { agent_mcp: { url: 'http://localhost:3012/mcp', bearer_env_var: 'XUDA_AGENT_KEY', bearer_value: agent_key } } : {}),
|
|
7041
7069
|
},
|
|
7042
7070
|
job_id,
|
|
@@ -9092,7 +9120,9 @@ const run_plugin = async function (app_id, uid, plugin_name, method, prop_data,
|
|
|
9092
9120
|
const fields = await get_fields_data(methods[method].fields, prop_data);
|
|
9093
9121
|
const params = fields;
|
|
9094
9122
|
const env = { couch, app_id, uid, userName, agent_info };
|
|
9095
|
-
|
|
9123
|
+
// Platform credentials come from the box's secrets at call time, never from
|
|
9124
|
+
// the plugin package or a stored per-app copy. See with_platform_plugin_secrets.
|
|
9125
|
+
const setup_doc = _common.with_platform_plugin_secrets(plugin_doc.setup);
|
|
9096
9126
|
|
|
9097
9127
|
///////////////////////
|
|
9098
9128
|
const execute_server_script = async function (req, app_id_reference, server_script, method, params, setup_doc) {
|
|
@@ -9217,7 +9247,9 @@ const get_plugin_tool = async function (app_id, uid, plugin_name, method, prop_d
|
|
|
9217
9247
|
const fields = await get_fields_data(_method.fields, prop_data);
|
|
9218
9248
|
const params = fields;
|
|
9219
9249
|
const env = { couch, app_id, uid, userName, agent_info, account_profile_obj };
|
|
9220
|
-
|
|
9250
|
+
// Platform credentials come from the box's secrets at call time, never from
|
|
9251
|
+
// the plugin package or a stored per-app copy. See with_platform_plugin_secrets.
|
|
9252
|
+
const setup_doc = _common.with_platform_plugin_secrets(plugin_doc.setup);
|
|
9221
9253
|
|
|
9222
9254
|
///////////////////////
|
|
9223
9255
|
const execute_server_script = async function (req, app_id_reference, server_script, method, params, setup_doc) {
|
|
@@ -17387,7 +17419,40 @@ export const contact_form_submit = async function (req, job_id, headers) {
|
|
|
17387
17419
|
const body_parts = [message];
|
|
17388
17420
|
const detail_bits = [phone && `Phone: ${phone}`, company && `Company: ${company}`].filter(Boolean);
|
|
17389
17421
|
if (detail_bits.length) body_parts.push(detail_bits.join(' | '));
|
|
17390
|
-
await _contact_form_create_ticket(account_profile_info, contact_id, subject, body_parts.join('\n\n'), origin);
|
|
17422
|
+
const _conv = await _contact_form_create_ticket(account_profile_info, contact_id, subject, body_parts.join('\n\n'), origin);
|
|
17423
|
+
|
|
17424
|
+
// Source 6 of docs/plans/xuda-tickets.md. The conversation above stays the
|
|
17425
|
+
// human-readable thread and the contact mirror; this ALSO files the uniform
|
|
17426
|
+
// ticket so a contact-form submission shows up in the Tickets manager next
|
|
17427
|
+
// to every other source, with the same status, topic, action and SLA. Best
|
|
17428
|
+
// effort on purpose: the visitor already has their conversation, so a
|
|
17429
|
+
// ticketing failure must never fail the submission.
|
|
17430
|
+
try {
|
|
17431
|
+
const _tk = await ticket_ms.ticket_submit({
|
|
17432
|
+
source: 'profile_contact_form',
|
|
17433
|
+
channel: 'form',
|
|
17434
|
+
owner_uid: account_profile_info.uid,
|
|
17435
|
+
owner_profile_id: account_profile_info.account_profile_id,
|
|
17436
|
+
name,
|
|
17437
|
+
email,
|
|
17438
|
+
phone,
|
|
17439
|
+
company,
|
|
17440
|
+
subject,
|
|
17441
|
+
details: body_parts.join('\n\n'),
|
|
17442
|
+
origin: String(origin || '').slice(0, 200),
|
|
17443
|
+
});
|
|
17444
|
+
// Link both ways so the manager can jump to the thread and vice versa.
|
|
17445
|
+
if (_tk?.code > 0 && _tk.data?._id && _conv?._id) {
|
|
17446
|
+
const _c = await db_module.get_app_couch_doc(account_profile_info.app_id, _conv._id);
|
|
17447
|
+
if (_c.code > -1 && _c.data) {
|
|
17448
|
+
_c.data.ticket_id = _tk.data._id;
|
|
17449
|
+
_c.data.ticket_no = _tk.data.ticket_no;
|
|
17450
|
+
await db_module.save_app_couch_doc(account_profile_info.app_id, _c.data);
|
|
17451
|
+
}
|
|
17452
|
+
}
|
|
17453
|
+
} catch (tk_err) {
|
|
17454
|
+
console.warn('[contact_form] uniform ticket not filed:', tk_err.message);
|
|
17455
|
+
}
|
|
17391
17456
|
|
|
17392
17457
|
// Owner notification email (platform template).
|
|
17393
17458
|
if (config.notify_email !== false) {
|