@llmnative/react 1.18.1 → 1.19.1
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 +2 -0
- package/dist/index.css +1 -1
- package/dist/index.js +15 -15
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1531 -1472
- 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/types/src/Theme.d.ts +7 -0
- package/dist/types/src/components/index.d.ts +2 -0
- package/dist/types/src/components/ui/DescriptionList.d.ts +38 -0
- 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/package.json +43 -42
- package/themes/cyber.ts +488 -481
- package/themes/default.ts +502 -495
- package/themes/flat.ts +488 -481
- 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"}
|
|
@@ -337,6 +337,13 @@ export interface ThemeConfig {
|
|
|
337
337
|
wrapperClassName?: string;
|
|
338
338
|
className?: string;
|
|
339
339
|
};
|
|
340
|
+
DescriptionList?: {
|
|
341
|
+
wrapperClassName?: string;
|
|
342
|
+
className?: string;
|
|
343
|
+
itemClassName?: string;
|
|
344
|
+
labelClassName?: string;
|
|
345
|
+
valueClassName?: string;
|
|
346
|
+
};
|
|
340
347
|
Tab?: {
|
|
341
348
|
wrapperClassName?: string;
|
|
342
349
|
className?: string;
|
|
@@ -15,6 +15,8 @@ export type { ProviderSwitcherProps, ProviderSwitcherItem } from './blocks/Provi
|
|
|
15
15
|
export { default as Alert } from './ui/Alert';
|
|
16
16
|
export type { AlertProps } from './ui/Alert';
|
|
17
17
|
export { default as Badge } from './ui/Badge';
|
|
18
|
+
export { default as DescriptionList } from './ui/DescriptionList';
|
|
19
|
+
export type { DescriptionListItem, DescriptionListLayout, DescriptionListColumns, DescriptionListProps } from './ui/DescriptionList';
|
|
18
20
|
export * from './ui/Badge';
|
|
19
21
|
export * from './ui/Buttons';
|
|
20
22
|
export { default as Card } from './ui/Card';
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
/** One label → value pair of a `<DescriptionList>`. */
|
|
3
|
+
export interface DescriptionListItem {
|
|
4
|
+
/** Stable React key; defaults to the label when it is a string, otherwise the index. */
|
|
5
|
+
key?: string;
|
|
6
|
+
label: React.ReactNode;
|
|
7
|
+
/** `null`, `undefined` and `''` render as the list's `emptyValue`. */
|
|
8
|
+
value?: React.ReactNode;
|
|
9
|
+
/** Tooltip for the value; defaults to the value itself when it is a string and `truncate` is on. */
|
|
10
|
+
title?: string;
|
|
11
|
+
}
|
|
12
|
+
export type DescriptionListLayout = "horizontal" | "stacked";
|
|
13
|
+
export type DescriptionListColumns = 1 | 2 | 3 | 4 | 5 | 6;
|
|
14
|
+
export interface DescriptionListProps {
|
|
15
|
+
items: readonly DescriptionListItem[];
|
|
16
|
+
/** `"horizontal"` (default): label column on the left, stacked on small screens.
|
|
17
|
+
* `"stacked"`: label above its value, laid out in `columns`. */
|
|
18
|
+
layout?: DescriptionListLayout;
|
|
19
|
+
/** Stacked layout only: number of columns from the `lg` breakpoint (1–6, default 1). */
|
|
20
|
+
columns?: DescriptionListColumns;
|
|
21
|
+
/** Horizontal layout only: width of the label column (any CSS length, default `"12rem"`). */
|
|
22
|
+
labelWidth?: string;
|
|
23
|
+
/** Shown for empty values (default `"—"`). */
|
|
24
|
+
emptyValue?: React.ReactNode;
|
|
25
|
+
/** Keep each value on one line with an ellipsis. */
|
|
26
|
+
truncate?: boolean;
|
|
27
|
+
wrapperClassName?: string;
|
|
28
|
+
className?: string;
|
|
29
|
+
itemClassName?: string;
|
|
30
|
+
labelClassName?: string;
|
|
31
|
+
valueClassName?: string;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Read-only label → value pairs (profile data, a record's facts, summaries), rendered as a
|
|
35
|
+
* semantic `<dl>`. Use it instead of hand-written `<dl>`/`<dt>`/`<dd>` markup; for editable data use
|
|
36
|
+
* `<Form>` fields, for many records use `<Table>` or `<Grid>`.
|
|
37
|
+
*/
|
|
38
|
+
export default function DescriptionList({ items, layout, columns, labelWidth, emptyValue, truncate, wrapperClassName, className, itemClassName, labelClassName, valueClassName, }: DescriptionListProps): React.JSX.Element;
|
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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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@llmnative/react",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.19.1",
|
|
4
4
|
"description": "LLM-native React framework for deterministic UI generation. Data-driven by default, schema-driven optional. Ultra-low token consumption — built for AI agents, not just humans.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"module": "dist/index.mjs",
|
|
@@ -92,69 +92,70 @@
|
|
|
92
92
|
}
|
|
93
93
|
},
|
|
94
94
|
"devDependencies": {
|
|
95
|
-
"@firebase/rules-unit-testing": "^5.0.
|
|
95
|
+
"@firebase/rules-unit-testing": "^5.0.2",
|
|
96
96
|
"@phosphor-icons/react": "^2.1.10",
|
|
97
|
-
"@playwright/test": "^1.
|
|
98
|
-
"@supabase/supabase-js": "^2.
|
|
97
|
+
"@playwright/test": "^1.63.0",
|
|
98
|
+
"@supabase/supabase-js": "^2.117.2",
|
|
99
99
|
"@tailwindcss/postcss": "^4.3.3",
|
|
100
|
-
"@testing-library/dom": "^10.4.
|
|
101
|
-
"@testing-library/jest-dom": "^7.0.
|
|
102
|
-
"@testing-library/react": "^16.3.
|
|
103
|
-
"@testing-library/user-event": "^14.6.
|
|
104
|
-
"@types/google.maps": "^3.
|
|
100
|
+
"@testing-library/dom": "^10.4.2",
|
|
101
|
+
"@testing-library/jest-dom": "^7.0.1",
|
|
102
|
+
"@testing-library/react": "^16.3.3",
|
|
103
|
+
"@testing-library/user-event": "^14.6.7",
|
|
104
|
+
"@types/google.maps": "^3.66.4",
|
|
105
105
|
"@types/papaparse": "^5.5.2",
|
|
106
106
|
"@types/prismjs": "^1.26.6",
|
|
107
|
-
"@types/react": "^19.
|
|
108
|
-
"@types/react-dom": "^19.
|
|
109
|
-
"@
|
|
110
|
-
"
|
|
111
|
-
"
|
|
112
|
-
"
|
|
113
|
-
"
|
|
114
|
-
"
|
|
115
|
-
"
|
|
116
|
-
"
|
|
117
|
-
"react
|
|
118
|
-
"react-
|
|
107
|
+
"@types/react": "^19.3.0",
|
|
108
|
+
"@types/react-dom": "^19.3.0",
|
|
109
|
+
"@typescript/typescript6": "^6.0.2",
|
|
110
|
+
"@vitest/coverage-v8": "^5.0.3",
|
|
111
|
+
"autoprefixer": "^10.6.1",
|
|
112
|
+
"firebase": "^12.19.0",
|
|
113
|
+
"happy-dom": "^20.14.5",
|
|
114
|
+
"jsdom": "^30.1.1",
|
|
115
|
+
"lucide-react": "^1.49.0",
|
|
116
|
+
"postcss": "^8.5.28",
|
|
117
|
+
"react": "^19.3.0",
|
|
118
|
+
"react-dom": "^19.3.0",
|
|
119
|
+
"react-router-dom": "^7.18.4",
|
|
119
120
|
"tailwindcss": "^4.3.3",
|
|
120
|
-
"typescript": "
|
|
121
|
-
"vite": "^8.
|
|
122
|
-
"vitest": "
|
|
123
|
-
"ws": "^8.
|
|
121
|
+
"typescript": "^7.0.2",
|
|
122
|
+
"vite": "^8.3.2",
|
|
123
|
+
"vitest": "^5.0.3",
|
|
124
|
+
"ws": "^8.22.0"
|
|
124
125
|
},
|
|
125
126
|
"dependencies": {
|
|
126
127
|
"@codemirror/autocomplete": "^6.20.3",
|
|
127
|
-
"@codemirror/commands": "^6.
|
|
128
|
+
"@codemirror/commands": "^6.11.1",
|
|
128
129
|
"@codemirror/lang-css": "^6.3.1",
|
|
129
|
-
"@codemirror/lang-html": "^6.4.
|
|
130
|
+
"@codemirror/lang-html": "^6.4.12",
|
|
130
131
|
"@codemirror/lang-javascript": "^6.2.5",
|
|
131
132
|
"@codemirror/lang-json": "^6.0.2",
|
|
132
|
-
"@codemirror/lang-liquid": "^6.3.
|
|
133
|
+
"@codemirror/lang-liquid": "^6.3.3",
|
|
133
134
|
"@codemirror/language": "^6.12.4",
|
|
134
135
|
"@codemirror/lint": "^6.9.7",
|
|
135
|
-
"@codemirror/search": "^6.7.
|
|
136
|
-
"@codemirror/state": "^6.7.
|
|
137
|
-
"@codemirror/view": "^6.43.
|
|
138
|
-
"@tiptap/extension-character-count": "^3.
|
|
139
|
-
"@tiptap/extension-image": "^3.
|
|
140
|
-
"@tiptap/extension-link": "^3.
|
|
141
|
-
"@tiptap/extension-placeholder": "^3.
|
|
142
|
-
"@tiptap/extension-table": "^3.
|
|
143
|
-
"@tiptap/extension-underline": "^3.
|
|
144
|
-
"@tiptap/react": "^3.
|
|
145
|
-
"@tiptap/starter-kit": "^3.
|
|
136
|
+
"@codemirror/search": "^6.7.2",
|
|
137
|
+
"@codemirror/state": "^6.7.6",
|
|
138
|
+
"@codemirror/view": "^6.43.13",
|
|
139
|
+
"@tiptap/extension-character-count": "^3.31.4",
|
|
140
|
+
"@tiptap/extension-image": "^3.31.4",
|
|
141
|
+
"@tiptap/extension-link": "^3.31.4",
|
|
142
|
+
"@tiptap/extension-placeholder": "^3.31.4",
|
|
143
|
+
"@tiptap/extension-table": "^3.31.4",
|
|
144
|
+
"@tiptap/extension-underline": "^3.31.4",
|
|
145
|
+
"@tiptap/react": "^3.31.4",
|
|
146
|
+
"@tiptap/starter-kit": "^3.31.4",
|
|
146
147
|
"buffer": "^6.0.3",
|
|
147
148
|
"clsx": "^2.1.1",
|
|
148
149
|
"codemirror": "^6.0.2",
|
|
149
|
-
"liquidjs": "^10.
|
|
150
|
-
"papaparse": "^5.
|
|
150
|
+
"liquidjs": "^10.30.0",
|
|
151
|
+
"papaparse": "^5.7.0",
|
|
151
152
|
"prismjs": "^1.30.0",
|
|
152
153
|
"react-markdown": "^10.1.0",
|
|
153
154
|
"rehype-autolink-headings": "^7.1.0",
|
|
154
155
|
"rehype-sanitize": "^6.0.0",
|
|
155
156
|
"rehype-slug": "^6.0.0",
|
|
156
157
|
"remark-gfm": "^4.0.1",
|
|
157
|
-
"tailwind-merge": "^3.
|
|
158
|
+
"tailwind-merge": "^3.7.0",
|
|
158
159
|
"tui-image-editor": "^3.15.3"
|
|
159
160
|
},
|
|
160
161
|
"publishConfig": {
|