@llmnative/react 1.19.0 → 1.19.2
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/README.md +4 -2
- package/dist/index.css +1 -1
- package/dist/index.js +10 -10
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +150 -139
- package/dist/index.mjs.map +1 -1
- package/dist/logHeader-Busbc8OO.mjs.map +1 -1
- package/dist/logHeader-CUsdmGAo.js +2 -0
- package/dist/{logHeader-CbzOhx-u.js.map → logHeader-CUsdmGAo.js.map} +1 -1
- package/dist/vite.js +2 -2
- package/dist/vite.js.map +1 -1
- package/dist/vite.mjs +1 -1
- package/dist/vite.mjs.map +1 -1
- package/llms-full.txt +1140 -0
- package/llms.txt +82 -0
- package/package.json +48 -43
- package/scripts/cli/setup-project.js +60 -36
- package/templates/_shared/layouts/Default.tsx +23 -0
- package/templates/_shared/sections/Footer.tsx +9 -0
- package/templates/_shared/sections/Header.tsx +24 -0
- package/templates/_shared/sections/PageHeader.tsx +10 -0
- package/templates/_shared/sections/Sidebar.tsx +22 -0
- package/templates/admin/conf/menu.ts +14 -0
- package/templates/admin/data/mockData.ts +21 -0
- package/templates/admin/pages/home/HomePage.tsx +32 -0
- package/templates/admin/pages/roles/RolesPage.tsx +25 -0
- package/templates/admin/pages/settings/SettingsPage.tsx +24 -0
- package/templates/admin/pages/users/UsersPage.tsx +54 -0
- package/templates/blank/conf/menu.ts +8 -0
- package/templates/blank/data/mockData.ts +6 -0
- package/templates/blank/pages/home/HomePage.tsx +25 -0
- package/templates/crm/conf/menu.ts +14 -0
- package/templates/crm/data/mockData.ts +24 -0
- package/templates/crm/pages/companies/CompaniesPage.tsx +42 -0
- package/templates/crm/pages/contacts/ContactsPage.tsx +48 -0
- package/templates/crm/pages/deals/DealsPage.tsx +61 -0
- package/templates/crm/pages/home/HomePage.tsx +35 -0
- package/templates/inventory/conf/menu.ts +12 -0
- package/templates/inventory/data/mockData.ts +16 -0
- package/templates/inventory/pages/categories/CategoriesPage.tsx +23 -0
- package/templates/inventory/pages/home/HomePage.tsx +35 -0
- package/templates/inventory/pages/products/ProductsPage.tsx +56 -0
- package/templates/project/conf/menu.ts +14 -0
- package/templates/project/data/mockData.ts +21 -0
- package/templates/project/pages/home/HomePage.tsx +33 -0
- package/templates/project/pages/projects/ProjectsPage.tsx +50 -0
- package/templates/project/pages/tasks/TasksPage.tsx +67 -0
- package/templates/project/pages/team/TeamPage.tsx +25 -0
- package/dist/logHeader-CbzOhx-u.js +0 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"logHeader-Busbc8OO.mjs","names":[],"sources":["../src/providers/proxy/logHeader.ts"],"sourcesContent":["/** Nome dell'header che trasporta l'id di conversazione dal client (provider AI, via\n * `AICompleteRequest.logId`) al proxy dev di Vite (`vite.ts`), che lo usa per accodare\n * request/response allo stesso file di log per l'intera conversazione. File separato e\n * privo di import Node-specific — i provider AI lato browser (anthropic.ts/gemini.ts/\n * openaiCompatible.ts) lo importano per impostare l'header, senza portarsi dietro le\n * dipendenze Node di vite.ts nel proprio bundle. */\nexport const LLM_LOG_ID_HEADER = 'x-llmnative-log-id';\n"],"mappings":";AAMA,
|
|
1
|
+
{"version":3,"file":"logHeader-Busbc8OO.mjs","names":["LLM_LOG_ID_HEADER"],"sources":["../src/providers/proxy/logHeader.ts"],"sourcesContent":["/** Nome dell'header che trasporta l'id di conversazione dal client (provider AI, via\n * `AICompleteRequest.logId`) al proxy dev di Vite (`vite.ts`), che lo usa per accodare\n * request/response allo stesso file di log per l'intera conversazione. File separato e\n * privo di import Node-specific — i provider AI lato browser (anthropic.ts/gemini.ts/\n * openaiCompatible.ts) lo importano per impostare l'header, senza portarsi dietro le\n * dipendenze Node di vite.ts nel proprio bundle. */\nexport const LLM_LOG_ID_HEADER = 'x-llmnative-log-id';\n"],"mappings":";AAMA,IAAaA,IAAoB"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
var e=Object.create,t=Object.defineProperty,n=Object.getOwnPropertyDescriptor,r=Object.getOwnPropertyNames,i=Object.getPrototypeOf,a=Object.prototype.hasOwnProperty,o=(e,n)=>{let r={};for(var i in e)t(r,i,{get:e[i],enumerable:!0});return n||t(r,Symbol.toStringTag,{value:`Module`}),r},s=(e,i,o,s)=>{if(i&&typeof i==`object`||typeof i==`function`)for(var c=r(i),l=0,u=c.length,d;l<u;l++)d=c[l],!a.call(e,d)&&d!==o&&t(e,d,{get:(e=>i[e]).bind(null,d),enumerable:!(s=n(i,d))||s.enumerable});return e},c=(n,r,o)=>(o=n==null?{}:e(i(n)),s(r||!n||!n.__esModule||!a.call(n,`default`)?t(o,`default`,{value:n,enumerable:!0}):o,n)),l=`x-llmnative-log-id`;Object.defineProperty(exports,"n",{enumerable:!0,get:function(){return o}}),Object.defineProperty(exports,"r",{enumerable:!0,get:function(){return c}}),Object.defineProperty(exports,"t",{enumerable:!0,get:function(){return l}});
|
|
2
|
+
//# sourceMappingURL=logHeader-CUsdmGAo.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"logHeader-
|
|
1
|
+
{"version":3,"file":"logHeader-CUsdmGAo.js","names":["__create","__defProp","__getOwnPropDesc","__getOwnPropNames","__getProtoOf","__hasOwnProp","__exportAll","target","name","all","no_symbols","__copyProps","from","keys","i","n","key","to","except","k","desc","__toESM","mod","isNodeMode","LLM_LOG_ID_HEADER"],"sources":["../src/providers/proxy/logHeader.ts"],"sourcesContent":["/** Nome dell'header che trasporta l'id di conversazione dal client (provider AI, via\n * `AICompleteRequest.logId`) al proxy dev di Vite (`vite.ts`), che lo usa per accodare\n * request/response allo stesso file di log per l'intera conversazione. File separato e\n * privo di import Node-specific — i provider AI lato browser (anthropic.ts/gemini.ts/\n * openaiCompatible.ts) lo importano per impostare l'header, senza portarsi dietro le\n * dipendenze Node di vite.ts nel proprio bundle. */\nexport const LLM_LOG_ID_HEADER = 'x-llmnative-log-id';\n"],"mappings":"4mBAMawB,EAAoB"}
|
package/dist/vite.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./logHeader-
|
|
2
|
-
`);await(0,t.appendFile)(n.default.join(e.dir,`${o(r)}.txt`),u,`utf-8`)}catch(e){console.warn(`[llmnative-dev-proxy] Failed to write LLM log:`,e)}}var l=async(t,n,i,o)=>{let s=new URL(t.url||`/`,`http://localhost`).searchParams.get(`url`);if(t.headers[r]!==`1`){n.statusCode=403,n.setHeader(`Content-Type`,`application/json`),n.end(JSON.stringify({error:`Proxy access denied.`}));return}if(!s){n.statusCode=400,n.setHeader(`Content-Type`,`application/json`),n.end(JSON.stringify({error:`Missing "url" query parameter.`}));return}try{let l=new URL(s);if(l.pathname.startsWith(i)&&[`localhost`,`127.0.0.1`].includes(l.hostname)){n.statusCode=508,n.setHeader(`Content-Type`,`application/json`),n.end(JSON.stringify({error:`Recursive proxy target detected.`,target:s}));return}let u=await a(t),d=t.headers[e.t],f=new Headers,p=new Set([r,e.t,`host`,`origin`,`referer`,`content-length`,`transfer-encoding`,`connection`]);Object.entries(t.headers).forEach(([e,t])=>{
|
|
1
|
+
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./logHeader-CUsdmGAo.js");let t=require("node:fs/promises"),n=require("node:path");n=e.r(n);var r=`x-llmnative-proxy`,i=`/api/proxy`,a=async e=>{let t=[];for await(let n of e)t.push(Buffer.isBuffer(n)?n:Buffer.from(n));return t.length===0?void 0:Buffer.concat(t)};function o(e){return e.replace(/[^a-zA-Z0-9_-]/g,``).slice(0,128)||`unknown`}function s(e){if(!e.trim())return`(empty body)`;try{return JSON.stringify(JSON.parse(e),null,2)}catch{return e}}async function c(e,r,i,a,c,l){try{await(0,t.mkdir)(e.dir,{recursive:!0});let u=[``,`=`.repeat(80),`Turn @ ${new Date().toISOString()}`,`Target: ${i}`,`--- REQUEST BODY ---`,s(a),`--- RESPONSE BODY (status ${c}) ---`,s(l),`=`.repeat(80),``].join(`
|
|
2
|
+
`);await(0,t.appendFile)(n.default.join(e.dir,`${o(r)}.txt`),u,`utf-8`)}catch(e){console.warn(`[llmnative-dev-proxy] Failed to write LLM log:`,e)}}var l=async(t,n,i,o)=>{let s=new URL(t.url||`/`,`http://localhost`).searchParams.get(`url`);if(t.headers[r]!==`1`){n.statusCode=403,n.setHeader(`Content-Type`,`application/json`),n.end(JSON.stringify({error:`Proxy access denied.`}));return}if(!s){n.statusCode=400,n.setHeader(`Content-Type`,`application/json`),n.end(JSON.stringify({error:`Missing "url" query parameter.`}));return}try{let l=new URL(s);if(l.pathname.startsWith(i)&&[`localhost`,`127.0.0.1`].includes(l.hostname)){n.statusCode=508,n.setHeader(`Content-Type`,`application/json`),n.end(JSON.stringify({error:`Recursive proxy target detected.`,target:s}));return}let u=await a(t),d=t.headers[e.t],f=new Headers,p=new Set([r,e.t,`host`,`origin`,`referer`,`content-length`,`transfer-encoding`,`connection`]);Object.entries(t.headers).forEach(([e,t])=>{t&&!p.has(e.toLowerCase())&&f.set(e,Array.isArray(t)?t.join(`, `):t)});let m=await fetch(s,{method:t.method||`GET`,headers:f,body:u&&![`GET`,`HEAD`].includes((t.method||`GET`).toUpperCase())?Uint8Array.from(u):void 0,redirect:`follow`}),h=Buffer.from(await m.arrayBuffer());o?.enabled&&typeof d==`string`&&d&&c(o,d,s,u?.toString(`utf-8`)??``,m.status,h.toString(`utf-8`)),n.statusCode=m.status,m.headers.forEach((e,t)=>{t.toLowerCase()!==`content-encoding`&&n.setHeader(t,e)}),n.end(h)}catch(e){n.statusCode=502,n.setHeader(`Content-Type`,`application/json`),n.end(JSON.stringify({error:e instanceof Error?e.message:`Proxy request failed.`}))}},u=(e=i,t)=>({name:`llmnative-dev-proxy`,configureServer(n){n.middlewares.use(e,(n,r)=>{l(n,r,e,t)})},configurePreviewServer(n){n.middlewares.use(e,(n,r)=>{l(n,r,e,t)})}});exports.PROXY_PATH=i,exports.createProxyPlugin=u;
|
|
3
3
|
//# sourceMappingURL=vite.js.map
|
package/dist/vite.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"vite.js","names":[],"sources":["../src/providers/proxy/vite.ts"],"sourcesContent":["import { appendFile, mkdir } from 'node:fs/promises';\nimport path from 'node:path';\nimport type { IncomingMessage, ServerResponse } from 'node:http';\nimport type { Plugin } from 'vite';\nimport { LLM_LOG_ID_HEADER } from './logHeader';\n\nconst PROXY_CALLER_HEADER = 'x-llmnative-proxy';\nexport const PROXY_PATH = '/api/proxy';\n\n/** Logging file di richiesta/risposta LLM — SOLO dev, mai attivo di default. Un file per\n * conversazione: il client (useAgent, CMS) genera un `logId` stabile per l'intera sessione e\n * lo manda su ogni chiamata come header `x-llmnative-log-id`; il proxy accoda ogni turno allo\n * stesso file, non lo sovrascrive. Vedi AICompleteRequest.logId per il lato client. */\nexport interface ProxyLogOptions {\n enabled: boolean;\n /** Cartella di destinazione, relativa alla cwd del dev server (il progetto consumer, es.\n * il CMS) o assoluta. Creata se assente. */\n dir: string;\n}\n\nconst readRequestBody = async (req: IncomingMessage): Promise<Buffer | undefined> => {\n const chunks: Buffer[] = [];\n for await (const chunk of req) {\n chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));\n }\n return chunks.length === 0 ? undefined : Buffer.concat(chunks);\n};\n\n/** Solo caratteri sicuri per un nome file — l'id è generato da noi (crypto.randomUUID() lato\n * client), ma niente path traversal per costruzione anche se un client si comportasse male. */\nfunction sanitizeLogId(logId: string): string {\n return logId.replace(/[^a-zA-Z0-9_-]/g, '').slice(0, 128) || 'unknown';\n}\n\nfunction prettyJsonOrRaw(text: string): string {\n if (!text.trim()) return '(empty body)';\n try {\n return JSON.stringify(JSON.parse(text), null, 2);\n } catch {\n return text;\n }\n}\n\nasync function appendLogBlock(logOptions: ProxyLogOptions, logId: string, target: string, requestBody: string, status: number, responseBody: string) {\n try {\n await mkdir(logOptions.dir, { recursive: true });\n const block = [\n '',\n '='.repeat(80),\n `Turn @ ${new Date().toISOString()}`,\n `Target: ${target}`,\n '--- REQUEST BODY ---',\n prettyJsonOrRaw(requestBody),\n `--- RESPONSE BODY (status ${status}) ---`,\n prettyJsonOrRaw(responseBody),\n '='.repeat(80),\n '',\n ].join('\\n');\n await appendFile(path.join(logOptions.dir, `${sanitizeLogId(logId)}.txt`), block, 'utf-8');\n } catch (error) {\n // Un log fallito non deve mai far fallire la vera richiesta — solo un avviso in console.\n console.warn('[llmnative-dev-proxy] Failed to write LLM log:', error);\n }\n}\n\nconst writeProxyResponse = async (req: IncomingMessage, res: ServerResponse, route: string, logOptions?: ProxyLogOptions) => {\n const requestUrl = new URL(req.url || '/', 'http://localhost');\n const target = requestUrl.searchParams.get('url');\n\n if (req.headers[PROXY_CALLER_HEADER] !== '1') {\n res.statusCode = 403;\n res.setHeader('Content-Type', 'application/json');\n res.end(JSON.stringify({ error: 'Proxy access denied.' }));\n return;\n }\n\n if (!target) {\n res.statusCode = 400;\n res.setHeader('Content-Type', 'application/json');\n res.end(JSON.stringify({ error: 'Missing \"url\" query parameter.' }));\n return;\n }\n\n try {\n const targetUrl = new URL(target);\n if (targetUrl.pathname.startsWith(route) && ['localhost', '127.0.0.1'].includes(targetUrl.hostname)) {\n res.statusCode = 508;\n res.setHeader('Content-Type', 'application/json');\n res.end(JSON.stringify({ error: 'Recursive proxy target detected.', target }));\n return;\n }\n\n const body = await readRequestBody(req);\n const logId = req.headers[LLM_LOG_ID_HEADER];\n const headers = new Headers();\n // L'header di log è consumato QUI, mai inoltrato al provider upstream (stesso\n // trattamento del PROXY_CALLER_HEADER) — è un dettaglio nostro, non dell'API esterna.\n const skipHeaders = new Set([PROXY_CALLER_HEADER, LLM_LOG_ID_HEADER, 'host', 'origin', 'referer', 'content-length', 'transfer-encoding', 'connection']);\n\n Object.entries(req.headers).forEach(([key, value]) => {\n if (!value || skipHeaders.has(key.toLowerCase())) return;\n headers.set(key, Array.isArray(value) ? value.join(', ') : value);\n });\n\n const upstream = await fetch(target, {\n method: req.method || 'GET',\n headers,\n body: body && !['GET', 'HEAD'].includes((req.method || 'GET').toUpperCase())\n ? Uint8Array.from(body)\n : undefined,\n redirect: 'follow',\n });\n\n const responseBuffer = Buffer.from(await upstream.arrayBuffer());\n\n if (logOptions?.enabled && typeof logId === 'string' && logId) {\n void appendLogBlock(logOptions, logId, target, body?.toString('utf-8') ?? '', upstream.status, responseBuffer.toString('utf-8'));\n }\n\n res.statusCode = upstream.status;\n upstream.headers.forEach((value, key) => {\n if (key.toLowerCase() === 'content-encoding') return;\n res.setHeader(key, value);\n });\n res.end(responseBuffer);\n } catch (error) {\n res.statusCode = 502;\n res.setHeader('Content-Type', 'application/json');\n res.end(JSON.stringify({ error: error instanceof Error ? error.message : 'Proxy request failed.' }));\n }\n};\n\nexport const createProxyPlugin = (route = PROXY_PATH, logOptions?: ProxyLogOptions): Plugin => ({\n name: 'llmnative-dev-proxy',\n configureServer(server) {\n server.middlewares.use(route, (req, res) => { void writeProxyResponse(req, res, route, logOptions); });\n },\n configurePreviewServer(server) {\n server.middlewares.use(route, (req, res) => { void writeProxyResponse(req, res, route, logOptions); });\n },\n});\n"],"mappings":"gLAMA,
|
|
1
|
+
{"version":3,"file":"vite.js","names":["mkdir","appendFile","path","LLM_LOG_ID_HEADER","require_logHeader","node_fs_promises","node_path","PROXY_CALLER_HEADER","PROXY_PATH","readRequestBody","chunks","chunk","req","sanitizeLogId","logId","prettyJsonOrRaw","text","appendLogBlock","logOptions","block","target","requestBody","status","responseBody","error","writeProxyResponse","res","targetUrl","route","body","headers","skipHeaders","key","value","upstream","responseBuffer","createProxyPlugin","server"],"sources":["../src/providers/proxy/vite.ts"],"sourcesContent":["import { appendFile, mkdir } from 'node:fs/promises';\nimport path from 'node:path';\nimport type { IncomingMessage, ServerResponse } from 'node:http';\nimport type { Plugin } from 'vite';\nimport { LLM_LOG_ID_HEADER } from './logHeader';\n\nconst PROXY_CALLER_HEADER = 'x-llmnative-proxy';\nexport const PROXY_PATH = '/api/proxy';\n\n/** Logging file di richiesta/risposta LLM — SOLO dev, mai attivo di default. Un file per\n * conversazione: il client (useAgent, CMS) genera un `logId` stabile per l'intera sessione e\n * lo manda su ogni chiamata come header `x-llmnative-log-id`; il proxy accoda ogni turno allo\n * stesso file, non lo sovrascrive. Vedi AICompleteRequest.logId per il lato client. */\nexport interface ProxyLogOptions {\n enabled: boolean;\n /** Cartella di destinazione, relativa alla cwd del dev server (il progetto consumer, es.\n * il CMS) o assoluta. Creata se assente. */\n dir: string;\n}\n\nconst readRequestBody = async (req: IncomingMessage): Promise<Buffer | undefined> => {\n const chunks: Buffer[] = [];\n for await (const chunk of req) {\n chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));\n }\n return chunks.length === 0 ? undefined : Buffer.concat(chunks);\n};\n\n/** Solo caratteri sicuri per un nome file — l'id è generato da noi (crypto.randomUUID() lato\n * client), ma niente path traversal per costruzione anche se un client si comportasse male. */\nfunction sanitizeLogId(logId: string): string {\n return logId.replace(/[^a-zA-Z0-9_-]/g, '').slice(0, 128) || 'unknown';\n}\n\nfunction prettyJsonOrRaw(text: string): string {\n if (!text.trim()) return '(empty body)';\n try {\n return JSON.stringify(JSON.parse(text), null, 2);\n } catch {\n return text;\n }\n}\n\nasync function appendLogBlock(logOptions: ProxyLogOptions, logId: string, target: string, requestBody: string, status: number, responseBody: string) {\n try {\n await mkdir(logOptions.dir, { recursive: true });\n const block = [\n '',\n '='.repeat(80),\n `Turn @ ${new Date().toISOString()}`,\n `Target: ${target}`,\n '--- REQUEST BODY ---',\n prettyJsonOrRaw(requestBody),\n `--- RESPONSE BODY (status ${status}) ---`,\n prettyJsonOrRaw(responseBody),\n '='.repeat(80),\n '',\n ].join('\\n');\n await appendFile(path.join(logOptions.dir, `${sanitizeLogId(logId)}.txt`), block, 'utf-8');\n } catch (error) {\n // Un log fallito non deve mai far fallire la vera richiesta — solo un avviso in console.\n console.warn('[llmnative-dev-proxy] Failed to write LLM log:', error);\n }\n}\n\nconst writeProxyResponse = async (req: IncomingMessage, res: ServerResponse, route: string, logOptions?: ProxyLogOptions) => {\n const requestUrl = new URL(req.url || '/', 'http://localhost');\n const target = requestUrl.searchParams.get('url');\n\n if (req.headers[PROXY_CALLER_HEADER] !== '1') {\n res.statusCode = 403;\n res.setHeader('Content-Type', 'application/json');\n res.end(JSON.stringify({ error: 'Proxy access denied.' }));\n return;\n }\n\n if (!target) {\n res.statusCode = 400;\n res.setHeader('Content-Type', 'application/json');\n res.end(JSON.stringify({ error: 'Missing \"url\" query parameter.' }));\n return;\n }\n\n try {\n const targetUrl = new URL(target);\n if (targetUrl.pathname.startsWith(route) && ['localhost', '127.0.0.1'].includes(targetUrl.hostname)) {\n res.statusCode = 508;\n res.setHeader('Content-Type', 'application/json');\n res.end(JSON.stringify({ error: 'Recursive proxy target detected.', target }));\n return;\n }\n\n const body = await readRequestBody(req);\n const logId = req.headers[LLM_LOG_ID_HEADER];\n const headers = new Headers();\n // L'header di log è consumato QUI, mai inoltrato al provider upstream (stesso\n // trattamento del PROXY_CALLER_HEADER) — è un dettaglio nostro, non dell'API esterna.\n const skipHeaders = new Set([PROXY_CALLER_HEADER, LLM_LOG_ID_HEADER, 'host', 'origin', 'referer', 'content-length', 'transfer-encoding', 'connection']);\n\n Object.entries(req.headers).forEach(([key, value]) => {\n if (!value || skipHeaders.has(key.toLowerCase())) return;\n headers.set(key, Array.isArray(value) ? value.join(', ') : value);\n });\n\n const upstream = await fetch(target, {\n method: req.method || 'GET',\n headers,\n body: body && !['GET', 'HEAD'].includes((req.method || 'GET').toUpperCase())\n ? Uint8Array.from(body)\n : undefined,\n redirect: 'follow',\n });\n\n const responseBuffer = Buffer.from(await upstream.arrayBuffer());\n\n if (logOptions?.enabled && typeof logId === 'string' && logId) {\n void appendLogBlock(logOptions, logId, target, body?.toString('utf-8') ?? '', upstream.status, responseBuffer.toString('utf-8'));\n }\n\n res.statusCode = upstream.status;\n upstream.headers.forEach((value, key) => {\n if (key.toLowerCase() === 'content-encoding') return;\n res.setHeader(key, value);\n });\n res.end(responseBuffer);\n } catch (error) {\n res.statusCode = 502;\n res.setHeader('Content-Type', 'application/json');\n res.end(JSON.stringify({ error: error instanceof Error ? error.message : 'Proxy request failed.' }));\n }\n};\n\nexport const createProxyPlugin = (route = PROXY_PATH, logOptions?: ProxyLogOptions): Plugin => ({\n name: 'llmnative-dev-proxy',\n configureServer(server) {\n server.middlewares.use(route, (req, res) => { void writeProxyResponse(req, res, route, logOptions); });\n },\n configurePreviewServer(server) {\n server.middlewares.use(route, (req, res) => { void writeProxyResponse(req, res, route, logOptions); });\n },\n});\n"],"mappings":"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"}
|
package/dist/vite.mjs
CHANGED
|
@@ -68,7 +68,7 @@ var u = async (t, n, r, a) => {
|
|
|
68
68
|
"connection"
|
|
69
69
|
]);
|
|
70
70
|
Object.entries(t.headers).forEach(([e, t]) => {
|
|
71
|
-
|
|
71
|
+
t && !p.has(e.toLowerCase()) && f.set(e, Array.isArray(t) ? t.join(", ") : t);
|
|
72
72
|
});
|
|
73
73
|
let m = await fetch(s, {
|
|
74
74
|
method: t.method || "GET",
|
package/dist/vite.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"vite.mjs","names":[],"sources":["../src/providers/proxy/vite.ts"],"sourcesContent":["import { appendFile, mkdir } from 'node:fs/promises';\nimport path from 'node:path';\nimport type { IncomingMessage, ServerResponse } from 'node:http';\nimport type { Plugin } from 'vite';\nimport { LLM_LOG_ID_HEADER } from './logHeader';\n\nconst PROXY_CALLER_HEADER = 'x-llmnative-proxy';\nexport const PROXY_PATH = '/api/proxy';\n\n/** Logging file di richiesta/risposta LLM — SOLO dev, mai attivo di default. Un file per\n * conversazione: il client (useAgent, CMS) genera un `logId` stabile per l'intera sessione e\n * lo manda su ogni chiamata come header `x-llmnative-log-id`; il proxy accoda ogni turno allo\n * stesso file, non lo sovrascrive. Vedi AICompleteRequest.logId per il lato client. */\nexport interface ProxyLogOptions {\n enabled: boolean;\n /** Cartella di destinazione, relativa alla cwd del dev server (il progetto consumer, es.\n * il CMS) o assoluta. Creata se assente. */\n dir: string;\n}\n\nconst readRequestBody = async (req: IncomingMessage): Promise<Buffer | undefined> => {\n const chunks: Buffer[] = [];\n for await (const chunk of req) {\n chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));\n }\n return chunks.length === 0 ? undefined : Buffer.concat(chunks);\n};\n\n/** Solo caratteri sicuri per un nome file — l'id è generato da noi (crypto.randomUUID() lato\n * client), ma niente path traversal per costruzione anche se un client si comportasse male. */\nfunction sanitizeLogId(logId: string): string {\n return logId.replace(/[^a-zA-Z0-9_-]/g, '').slice(0, 128) || 'unknown';\n}\n\nfunction prettyJsonOrRaw(text: string): string {\n if (!text.trim()) return '(empty body)';\n try {\n return JSON.stringify(JSON.parse(text), null, 2);\n } catch {\n return text;\n }\n}\n\nasync function appendLogBlock(logOptions: ProxyLogOptions, logId: string, target: string, requestBody: string, status: number, responseBody: string) {\n try {\n await mkdir(logOptions.dir, { recursive: true });\n const block = [\n '',\n '='.repeat(80),\n `Turn @ ${new Date().toISOString()}`,\n `Target: ${target}`,\n '--- REQUEST BODY ---',\n prettyJsonOrRaw(requestBody),\n `--- RESPONSE BODY (status ${status}) ---`,\n prettyJsonOrRaw(responseBody),\n '='.repeat(80),\n '',\n ].join('\\n');\n await appendFile(path.join(logOptions.dir, `${sanitizeLogId(logId)}.txt`), block, 'utf-8');\n } catch (error) {\n // Un log fallito non deve mai far fallire la vera richiesta — solo un avviso in console.\n console.warn('[llmnative-dev-proxy] Failed to write LLM log:', error);\n }\n}\n\nconst writeProxyResponse = async (req: IncomingMessage, res: ServerResponse, route: string, logOptions?: ProxyLogOptions) => {\n const requestUrl = new URL(req.url || '/', 'http://localhost');\n const target = requestUrl.searchParams.get('url');\n\n if (req.headers[PROXY_CALLER_HEADER] !== '1') {\n res.statusCode = 403;\n res.setHeader('Content-Type', 'application/json');\n res.end(JSON.stringify({ error: 'Proxy access denied.' }));\n return;\n }\n\n if (!target) {\n res.statusCode = 400;\n res.setHeader('Content-Type', 'application/json');\n res.end(JSON.stringify({ error: 'Missing \"url\" query parameter.' }));\n return;\n }\n\n try {\n const targetUrl = new URL(target);\n if (targetUrl.pathname.startsWith(route) && ['localhost', '127.0.0.1'].includes(targetUrl.hostname)) {\n res.statusCode = 508;\n res.setHeader('Content-Type', 'application/json');\n res.end(JSON.stringify({ error: 'Recursive proxy target detected.', target }));\n return;\n }\n\n const body = await readRequestBody(req);\n const logId = req.headers[LLM_LOG_ID_HEADER];\n const headers = new Headers();\n // L'header di log è consumato QUI, mai inoltrato al provider upstream (stesso\n // trattamento del PROXY_CALLER_HEADER) — è un dettaglio nostro, non dell'API esterna.\n const skipHeaders = new Set([PROXY_CALLER_HEADER, LLM_LOG_ID_HEADER, 'host', 'origin', 'referer', 'content-length', 'transfer-encoding', 'connection']);\n\n Object.entries(req.headers).forEach(([key, value]) => {\n if (!value || skipHeaders.has(key.toLowerCase())) return;\n headers.set(key, Array.isArray(value) ? value.join(', ') : value);\n });\n\n const upstream = await fetch(target, {\n method: req.method || 'GET',\n headers,\n body: body && !['GET', 'HEAD'].includes((req.method || 'GET').toUpperCase())\n ? Uint8Array.from(body)\n : undefined,\n redirect: 'follow',\n });\n\n const responseBuffer = Buffer.from(await upstream.arrayBuffer());\n\n if (logOptions?.enabled && typeof logId === 'string' && logId) {\n void appendLogBlock(logOptions, logId, target, body?.toString('utf-8') ?? '', upstream.status, responseBuffer.toString('utf-8'));\n }\n\n res.statusCode = upstream.status;\n upstream.headers.forEach((value, key) => {\n if (key.toLowerCase() === 'content-encoding') return;\n res.setHeader(key, value);\n });\n res.end(responseBuffer);\n } catch (error) {\n res.statusCode = 502;\n res.setHeader('Content-Type', 'application/json');\n res.end(JSON.stringify({ error: error instanceof Error ? error.message : 'Proxy request failed.' }));\n }\n};\n\nexport const createProxyPlugin = (route = PROXY_PATH, logOptions?: ProxyLogOptions): Plugin => ({\n name: 'llmnative-dev-proxy',\n configureServer(server) {\n server.middlewares.use(route, (req, res) => { void writeProxyResponse(req, res, route, logOptions); });\n },\n configurePreviewServer(server) {\n server.middlewares.use(route, (req, res) => { void writeProxyResponse(req, res, route, logOptions); });\n },\n});\n"],"mappings":";;;;AAMA,
|
|
1
|
+
{"version":3,"file":"vite.mjs","names":["LLM_LOG_ID_HEADER","path","PROXY_CALLER_HEADER","PROXY_PATH","readRequestBody","chunks","chunk","req","sanitizeLogId","logId","prettyJsonOrRaw","text","appendLogBlock","mkdir","logOptions","block","target","requestBody","status","responseBody","appendFile","error","writeProxyResponse","res","targetUrl","route","body","headers","skipHeaders","key","value","upstream","responseBuffer","createProxyPlugin"],"sources":["../src/providers/proxy/vite.ts"],"sourcesContent":["import { appendFile, mkdir } from 'node:fs/promises';\nimport path from 'node:path';\nimport type { IncomingMessage, ServerResponse } from 'node:http';\nimport type { Plugin } from 'vite';\nimport { LLM_LOG_ID_HEADER } from './logHeader';\n\nconst PROXY_CALLER_HEADER = 'x-llmnative-proxy';\nexport const PROXY_PATH = '/api/proxy';\n\n/** Logging file di richiesta/risposta LLM — SOLO dev, mai attivo di default. Un file per\n * conversazione: il client (useAgent, CMS) genera un `logId` stabile per l'intera sessione e\n * lo manda su ogni chiamata come header `x-llmnative-log-id`; il proxy accoda ogni turno allo\n * stesso file, non lo sovrascrive. Vedi AICompleteRequest.logId per il lato client. */\nexport interface ProxyLogOptions {\n enabled: boolean;\n /** Cartella di destinazione, relativa alla cwd del dev server (il progetto consumer, es.\n * il CMS) o assoluta. Creata se assente. */\n dir: string;\n}\n\nconst readRequestBody = async (req: IncomingMessage): Promise<Buffer | undefined> => {\n const chunks: Buffer[] = [];\n for await (const chunk of req) {\n chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));\n }\n return chunks.length === 0 ? undefined : Buffer.concat(chunks);\n};\n\n/** Solo caratteri sicuri per un nome file — l'id è generato da noi (crypto.randomUUID() lato\n * client), ma niente path traversal per costruzione anche se un client si comportasse male. */\nfunction sanitizeLogId(logId: string): string {\n return logId.replace(/[^a-zA-Z0-9_-]/g, '').slice(0, 128) || 'unknown';\n}\n\nfunction prettyJsonOrRaw(text: string): string {\n if (!text.trim()) return '(empty body)';\n try {\n return JSON.stringify(JSON.parse(text), null, 2);\n } catch {\n return text;\n }\n}\n\nasync function appendLogBlock(logOptions: ProxyLogOptions, logId: string, target: string, requestBody: string, status: number, responseBody: string) {\n try {\n await mkdir(logOptions.dir, { recursive: true });\n const block = [\n '',\n '='.repeat(80),\n `Turn @ ${new Date().toISOString()}`,\n `Target: ${target}`,\n '--- REQUEST BODY ---',\n prettyJsonOrRaw(requestBody),\n `--- RESPONSE BODY (status ${status}) ---`,\n prettyJsonOrRaw(responseBody),\n '='.repeat(80),\n '',\n ].join('\\n');\n await appendFile(path.join(logOptions.dir, `${sanitizeLogId(logId)}.txt`), block, 'utf-8');\n } catch (error) {\n // Un log fallito non deve mai far fallire la vera richiesta — solo un avviso in console.\n console.warn('[llmnative-dev-proxy] Failed to write LLM log:', error);\n }\n}\n\nconst writeProxyResponse = async (req: IncomingMessage, res: ServerResponse, route: string, logOptions?: ProxyLogOptions) => {\n const requestUrl = new URL(req.url || '/', 'http://localhost');\n const target = requestUrl.searchParams.get('url');\n\n if (req.headers[PROXY_CALLER_HEADER] !== '1') {\n res.statusCode = 403;\n res.setHeader('Content-Type', 'application/json');\n res.end(JSON.stringify({ error: 'Proxy access denied.' }));\n return;\n }\n\n if (!target) {\n res.statusCode = 400;\n res.setHeader('Content-Type', 'application/json');\n res.end(JSON.stringify({ error: 'Missing \"url\" query parameter.' }));\n return;\n }\n\n try {\n const targetUrl = new URL(target);\n if (targetUrl.pathname.startsWith(route) && ['localhost', '127.0.0.1'].includes(targetUrl.hostname)) {\n res.statusCode = 508;\n res.setHeader('Content-Type', 'application/json');\n res.end(JSON.stringify({ error: 'Recursive proxy target detected.', target }));\n return;\n }\n\n const body = await readRequestBody(req);\n const logId = req.headers[LLM_LOG_ID_HEADER];\n const headers = new Headers();\n // L'header di log è consumato QUI, mai inoltrato al provider upstream (stesso\n // trattamento del PROXY_CALLER_HEADER) — è un dettaglio nostro, non dell'API esterna.\n const skipHeaders = new Set([PROXY_CALLER_HEADER, LLM_LOG_ID_HEADER, 'host', 'origin', 'referer', 'content-length', 'transfer-encoding', 'connection']);\n\n Object.entries(req.headers).forEach(([key, value]) => {\n if (!value || skipHeaders.has(key.toLowerCase())) return;\n headers.set(key, Array.isArray(value) ? value.join(', ') : value);\n });\n\n const upstream = await fetch(target, {\n method: req.method || 'GET',\n headers,\n body: body && !['GET', 'HEAD'].includes((req.method || 'GET').toUpperCase())\n ? Uint8Array.from(body)\n : undefined,\n redirect: 'follow',\n });\n\n const responseBuffer = Buffer.from(await upstream.arrayBuffer());\n\n if (logOptions?.enabled && typeof logId === 'string' && logId) {\n void appendLogBlock(logOptions, logId, target, body?.toString('utf-8') ?? '', upstream.status, responseBuffer.toString('utf-8'));\n }\n\n res.statusCode = upstream.status;\n upstream.headers.forEach((value, key) => {\n if (key.toLowerCase() === 'content-encoding') return;\n res.setHeader(key, value);\n });\n res.end(responseBuffer);\n } catch (error) {\n res.statusCode = 502;\n res.setHeader('Content-Type', 'application/json');\n res.end(JSON.stringify({ error: error instanceof Error ? error.message : 'Proxy request failed.' }));\n }\n};\n\nexport const createProxyPlugin = (route = PROXY_PATH, logOptions?: ProxyLogOptions): Plugin => ({\n name: 'llmnative-dev-proxy',\n configureServer(server) {\n server.middlewares.use(route, (req, res) => { void writeProxyResponse(req, res, route, logOptions); });\n },\n configurePreviewServer(server) {\n server.middlewares.use(route, (req, res) => { void writeProxyResponse(req, res, route, logOptions); });\n },\n});\n"],"mappings":"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"}
|