🚀 Socket Launch Week Day 5:Introducing Repository Access Permissions and Custom Roles.Learn more
Sign In

agentlux

Package Overview
Dependencies
Maintainers
1
Versions
7
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

agentlux - npm Package Compare versions

Comparing version
2.0.0
to
2.1.0
+30
-17
index.js

@@ -446,3 +446,3 @@ const fs = require('fs').promises;

async function curateImage(imageBase64, width, height) {
async function curateImage(imageBase64, width, height, lang) {
const provider = resolveProvider(process.env.AGENTLUX_CURATOR_MODEL);

@@ -452,2 +452,3 @@ const masterList = Object.entries(MASTER_REGISTRY).map(([k, m]) => ` - "${k}": ${m.name} (${m.style})`).join('\n');

const lensList = Object.entries(LENS_PROFILES).map(([k, l]) => ` - "${k}": ${l.name}`).join('\n');
const langInstruction = lang !== 'en' ? `\n\nIMPORTANT: Write ALL text values (master_rationale, color_rationale, lens_rationale) in ${lang}. Keep JSON keys and selection keys in English.` : '';

@@ -472,3 +473,3 @@ const prompt = `You are the Chief Curator of a world-class Leica photography exhibition. You have spent decades studying the masters who defined 35mm street and documentary photography.

Return ONLY a JSON object:
{"master": "key", "master_rationale": "brief why", "color_profile": "key", "color_rationale": "brief why", "lens": "key", "lens_rationale": "brief why"}`;
{"master": "key", "master_rationale": "brief why", "color_profile": "key", "color_rationale": "brief why", "lens": "key", "lens_rationale": "brief why"}${langInstruction}`;

@@ -479,12 +480,14 @@ const request = buildVLMRequest(provider, prompt, imageBase64);

async function masterCompose(imageBase64, width, height, masterKey) {
async function masterCompose(imageBase64, width, height, masterKey, lang) {
const provider = resolveProvider(process.env.AGENTLUX_MASTER_MODEL);
const master = MASTER_REGISTRY[masterKey] || MASTER_REGISTRY.bresson;
const request = buildVLMRequest(provider, master.prompt(width, height), imageBase64);
const langInstruction = lang !== 'en' ? `\n\nIMPORTANT: Write the "rule" value in ${lang}. Keep JSON keys, x, y, width, height as numbers.` : '';
const request = buildVLMRequest(provider, master.prompt(width, height) + langInstruction, imageBase64);
return parseCropBox(await callVLM(request));
}
async function selectDecisiveMoment(thumbnailsBase64) {
async function selectDecisiveMoment(thumbnailsBase64, lang) {
const provider = resolveProvider(process.env.AGENTLUX_SELECTOR_MODEL || process.env.AGENTLUX_CURATOR_MODEL);
const count = thumbnailsBase64.length;
const langInstruction = lang && lang !== 'en' ? `\n\nIMPORTANT: Write the "rationale" value in ${lang}.` : '';
const prompt = `You are selecting The Decisive Moment from a burst of ${count} consecutive frames (indexed 0 to ${count - 1}).

@@ -501,3 +504,3 @@

Return ONLY a JSON object:
{"selected_index": int, "rationale": "Why THIS frame captures the unrepeatable instant"}`;
{"selected_index": int, "rationale": "Why THIS frame captures the unrepeatable instant"}${langInstruction}`;

@@ -569,7 +572,8 @@ const request = buildMultiImageVLMRequest(provider, prompt, thumbnailsBase64);

const { width, height } = metadata;
const lang = context.lang || 'en';
const vlmJpeg = await sharp(buffer).jpeg({ quality: 90 }).toBuffer();
const base64 = vlmJpeg.toString('base64');
const curation = await curateImage(base64, width, height);
const cropBox = await masterCompose(base64, width, height, curation.master);
const curation = await curateImage(base64, width, height, lang);
const cropBox = await masterCompose(base64, width, height, curation.master, lang);
const safeCrop = sanitizeCropBox(cropBox, width, height);

@@ -629,8 +633,15 @@

if (context.burstResult) {
narrativeParts.push(`Selected frame ${context.burstResult.selected_index + 1} of ${context.burstResult.total_images}: ${context.burstResult.rationale}`);
narrativeParts.push(context.burstResult.rationale);
}
narrativeParts.push(`Recomposed through the eye of ${masterName} (${masterStyle}).`);
if (safeCrop.rule) narrativeParts.push(safeCrop.rule);
narrativeParts.push(`Color grade: ${profile.name}.`);
narrativeParts.push(`Lens character: ${lensName}.`);
if (lang === 'en') {
narrativeParts.push(`Recomposed through the eye of ${masterName} (${masterStyle}).`);
if (safeCrop.rule) narrativeParts.push(safeCrop.rule);
narrativeParts.push(`Color grade: ${profile.name}.`);
narrativeParts.push(`Lens character: ${lensName}.`);
} else {
narrativeParts.push(`${masterName} · ${masterStyle}`);
if (safeCrop.rule) narrativeParts.push(safeCrop.rule);
narrativeParts.push(profile.name);
narrativeParts.push(lensName);
}
result.presentation = narrativeParts.join('\n');

@@ -645,3 +656,3 @@

async function execute({ image_path, image_paths, output_path, delete_after = true }) {
async function execute({ image_path, image_paths, output_path, language, delete_after = true }) {
try {

@@ -651,2 +662,3 @@ if (typeof delete_after !== 'boolean') {

}
const lang = (typeof language === 'string' && language.trim()) || process.env.AGENTLUX_LANGUAGE || 'en';
if (output_path !== undefined) {

@@ -706,3 +718,3 @@ if (typeof output_path !== 'string' || output_path.trim().length === 0) {

));
const { selectedIndex, rationale } = await selectDecisiveMoment(thumbnails);
const { selectedIndex, rationale } = await selectDecisiveMoment(thumbnails, lang);

@@ -716,3 +728,3 @@ const selected = loaded[selectedIndex];

return await processImage(selected.buffer, meta, {
delete_after, deletionStatus, deletionMessage, outputPath: output_path,
lang, delete_after, deletionStatus, deletionMessage, outputPath: output_path,
burstResult: { selected_index: selectedIndex, total_images: image_paths.length, rationale }

@@ -743,3 +755,3 @@ });

return await processImage(buffer, metadata, {
delete_after, deletionStatus, deletionMessage, outputPath: output_path, burstResult: null
lang, delete_after, deletionStatus, deletionMessage, outputPath: output_path, burstResult: null
});

@@ -775,2 +787,3 @@ } catch (err) {

output_path: { type: 'string', description: 'Absolute path to write the output JPEG. If omitted, output is returned as image_data_uri (base64). Recommended for agent workflows.' },
language: { type: 'string', description: 'Language for user-facing text (e.g. "zh", "ja", "fr", "de"). Defaults to "en". Pass the language the agent is conversing in.' },
delete_after: { type: 'boolean', description: 'Delete original image(s) from disk after loading. Defaults to true (zero-retention).', default: true }

@@ -777,0 +790,0 @@ },

{
"name": "agentlux",
"version": "2.0.0",
"version": "2.1.0",
"description": "Multi-master Leica composition engine with dynamic color science, lens simulation, film grain, and decisive moment selection for autonomous vision agents.",

@@ -5,0 +5,0 @@ "main": "index.js",

@@ -77,2 +77,3 @@ # AgentLux

output_path: '/tmp/agentlux_out.jpg', // where to write the output JPEG
language: 'zh', // match your conversation language
delete_after: true // zero-retention: delete input after loading

@@ -96,2 +97,3 @@ });

| `output_path` | `string` | — | Absolute path to write output JPEG. If omitted, output is returned as `image_data_uri` (base64). **Recommended for agent workflows.** |
| `language` | `string` | `"en"` | Language for all user-facing text (e.g. `"zh"`, `"ja"`, `"fr"`). Pass the language the agent is conversing in. |
| `delete_after` | `boolean` | `true` | Delete original file(s) after loading into memory. |

@@ -117,3 +119,3 @@

| `burst_selection` | `object` | (Burst only) `{selected_index, total_images, rationale}` |
| `source_file_deletion` | `string` | `"deleted"` / `"delete_failed"` / `"disabled"` |
| `source_file_deletion` | `string` | `"deleted"` / `"partial"` / `"delete_failed"` / `"disabled"` |

@@ -155,3 +157,5 @@ ## Error Response

|---|---|---|
| `AGENTLUX_LANGUAGE` | `en` | Default language for user-facing text. Overridden by `language` parameter per call. |
| `AGENTLUX_MAX_IMAGE_BYTES` | `31457280` (30MB) | Maximum input image size |
| `AGENTLUX_MAX_BURST_SIZE` | `20` | Maximum number of images in burst mode |
| `AGENTLUX_VLM_TIMEOUT_MS` | `15000` | VLM request timeout |

@@ -158,0 +162,0 @@ | `AGENTLUX_VLM_MAX_RETRIES` | `2` | VLM retry count for transient errors |

@@ -42,2 +42,3 @@ # AgentLux

output_path: "/tmp/agentlux_output_" + Date.now() + ".jpg",
language: "zh", // match the language you are conversing in (e.g. "en", "zh", "ja", "fr")
delete_after: true

@@ -119,2 +120,3 @@ });

| `AGENTLUX_MASTER_MODEL` | Optional | Override master model (e.g. `gpt-4o`) |
| `AGENTLUX_LANGUAGE` | Optional | Default language for user-facing text (e.g. `zh`, `ja`, `fr`). Overridden by `language` parameter. |

@@ -121,0 +123,0 @@ ## What This Skill Does (For Context)