@xuda.io/ai_module 1.1.5633 → 1.1.5634

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 CHANGED
@@ -8638,6 +8638,63 @@ export const create_avatar = async function (req, job_id, headers) {
8638
8638
  }
8639
8639
  };
8640
8640
 
8641
+ // generate_login_screen: paid-plan alternative to uploading — AI-generate a
8642
+ // full-bleed landscape login background from a text prompt. Credit-gated like
8643
+ // avatar generation (create_image records usage). The PNG render is re-encoded to
8644
+ // WebP to satisfy the 5 MB spec, then handed to the shared drive writer over the
8645
+ // drive_module queue so it is persisted + served publicly exactly like an upload.
8646
+ export const generate_login_screen = async function (req, job_id, headers = {}) {
8647
+ const { uid, prompt } = req;
8648
+ const tempDir = os.tmpdir();
8649
+ const uniqueId = Date.now() + '_' + Math.random().toString(36).substring(7);
8650
+ const tempOutputPath = path.join(tempDir, `login_screen_${uniqueId}.webp`);
8651
+ try {
8652
+ if (!uid) throw new Error('not authorized (no uid)');
8653
+ if (!prompt || typeof prompt !== 'string' || !prompt.trim()) throw new Error('a prompt is required');
8654
+
8655
+ const account_profile_info = await get_active_account_profile_info(uid);
8656
+
8657
+ // credits: validate_credits_limit RETURNS an Error object when over the hard limit
8658
+ const credit_err = await validate_credits_limit(uid);
8659
+ if (credit_err) return { code: -25, data: 'AI credits reached the hard limit' };
8660
+
8661
+ const wrapped_prompt = `Create a full-bleed, decorative LANDSCAPE background image for a login screen. Subject/style: ${prompt.trim()}. It must contain no text, letters, logos, watermarks, UI elements, or human faces; use a cohesive, calm color palette with soft contrast so a login form stays readable on top. Fill the whole frame edge to edge.`;
8662
+
8663
+ // gpt-image landscape render; quality 'low' is fine for a decorative background.
8664
+ const base64 = await create_image(uid, wrapped_prompt, 'gpt-image-1-mini', '1536x1024', 1, 1536, 1024, { purpose: 'login_screen' }, account_profile_info, 'low');
8665
+ if (!base64) throw new Error('image generation failed');
8666
+
8667
+ // create_image emits PNG; re-encode to WebP to stay well under the 5 MB spec.
8668
+ const webp = await sharp(Buffer.from(base64, 'base64')).webp({ quality: 82 }).toBuffer();
8669
+ await fs.promises.writeFile(tempOutputPath, webp);
8670
+
8671
+ const file_obj = { originalname: 'login_screen.webp', path: tempOutputPath, mimetype: 'image/webp' };
8672
+ const store_ret = await drive_ms.store_login_screen_from_path(uid, file_obj, job_id, headers);
8673
+ if (store_ret.code !== 1) return store_ret;
8674
+
8675
+ const o = store_ret.data.login_screen_obj;
8676
+ return {
8677
+ code: 1,
8678
+ data: {
8679
+ login_screen: {
8680
+ source: 'personal',
8681
+ media_type: 'image',
8682
+ file_url: o.file_url,
8683
+ w: o.w,
8684
+ h: o.h,
8685
+ bytes: o.bytes,
8686
+ uploaded_ts: o.uploaded_ts,
8687
+ },
8688
+ },
8689
+ };
8690
+ } catch (err) {
8691
+ try {
8692
+ await fs.promises.unlink(tempOutputPath);
8693
+ } catch (e) {}
8694
+ return { code: -25, data: err.message };
8695
+ }
8696
+ };
8697
+
8641
8698
  export const get_profile_avatar = async function (profile_picture, uid, prompt, account_profile_info, account_type, docType = 'account', _id, metadata = {}, business_size = 'unknown', name, email, job_id, headers) {
8642
8699
  const tempDir = os.tmpdir();
8643
8700
  const uniqueId = Date.now() + '_' + Math.random().toString(36).substring(7);
package/index_ms.mjs CHANGED
@@ -157,6 +157,10 @@ export const create_avatar = async function (...args) {
157
157
  return await broker.send_to_queue("create_avatar", ...args);
158
158
  };
159
159
 
160
+ export const generate_login_screen = async function (...args) {
161
+ return await broker.send_to_queue("generate_login_screen", ...args);
162
+ };
163
+
160
164
  export const get_profile_avatar = async function (...args) {
161
165
  return await broker.send_to_queue("get_profile_avatar", ...args);
162
166
  };
package/index_msa.mjs CHANGED
@@ -157,6 +157,10 @@ export const create_avatar = function (...args) {
157
157
  broker.send_to_queue_async("create_avatar", ...args);
158
158
  };
159
159
 
160
+ export const generate_login_screen = function (...args) {
161
+ broker.send_to_queue_async("generate_login_screen", ...args);
162
+ };
163
+
160
164
  export const get_profile_avatar = function (...args) {
161
165
  broker.send_to_queue_async("get_profile_avatar", ...args);
162
166
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xuda.io/ai_module",
3
- "version": "1.1.5633",
3
+ "version": "1.1.5634",
4
4
  "description": "Xuda AI Module",
5
5
  "main": "index.mjs",
6
6
  "type": "module",
@@ -31,5 +31,8 @@
31
31
  "test:codex": "node tests/execute-codex-request.mjs"
32
32
  },
33
33
  "author": "Xuda Llc",
34
- "license": "ISC"
34
+ "license": "ISC",
35
+ "publishConfig": {
36
+ "access": "restricted"
37
+ }
35
38
  }