lindoai-cli 1.4.9 → 1.4.10

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/dist/index.js CHANGED
@@ -1,23 +1,23 @@
1
1
  #!/usr/bin/env node
2
- import*as ct from'http';import*as S from'fs';import*as A from'path';import*as Re from'os';import {platform}from'os';import {Command}from'commander';import {AuthenticationError,LindoClient}from'lindoai';import {spawn,exec,execSync}from'child_process';import*as Ee from'cheerio';import {marked}from'marked';import {URL}from'url';import*as xt from'crypto';import {createRequire}from'module';var Tt=Object.defineProperty;var Pt=(o=>typeof require<"u"?require:typeof Proxy<"u"?new Proxy(o,{get:(t,i)=>(typeof require<"u"?require:t)[i]}):o)(function(o){if(typeof require<"u")return require.apply(this,arguments);throw Error('Dynamic require of "'+o+'" is not supported')});var It=(o,t)=>()=>(o&&(t=o(o=0)),t);var At=(o,t)=>{for(var i in t)Tt(o,i,{get:t[i],enumerable:true});};var Ne={};At(Ne,{LIVE_RELOAD_SCRIPT:()=>De,injectLiveReload:()=>dt,startLivePreviewServer:()=>uo});function dt(o){let t=/<\/body>/i,i=o.match(t);return i&&i.index!==void 0?o.slice(0,i.index)+De+o.slice(i.index):o+De}function uo(o){return new Promise((t,i)=>{let e=A.resolve(o),n=new Set,r=null,a=100;function s(){for(let m of n)try{m.write(`data: reload
2
+ import*as ct from'http';import*as S from'fs';import*as A from'path';import*as De from'os';import {platform}from'os';import {Command}from'commander';import {AuthenticationError,LindoClient}from'lindoai';import {spawn,exec,execSync}from'child_process';import*as Ee from'cheerio';import {marked}from'marked';import {URL}from'url';import*as vt from'crypto';import {createRequire}from'module';var Pt=Object.defineProperty;var It=(t=>typeof require<"u"?require:typeof Proxy<"u"?new Proxy(t,{get:(o,i)=>(typeof require<"u"?require:o)[i]}):t)(function(t){if(typeof require<"u")return require.apply(this,arguments);throw Error('Dynamic require of "'+t+'" is not supported')});var At=(t,o)=>()=>(t&&(o=t(t=0)),o);var Et=(t,o)=>{for(var i in o)Pt(t,i,{get:o[i],enumerable:true});};var Ne={};Et(Ne,{LIVE_RELOAD_SCRIPT:()=>Re,injectLiveReload:()=>dt,startLivePreviewServer:()=>go});function dt(t){let o=/<\/body>/i,i=t.match(o);return i&&i.index!==void 0?t.slice(0,i.index)+Re+t.slice(i.index):t+Re}function go(t){return new Promise((o,i)=>{let e=A.resolve(t),n=new Set,r=null,a=100;function s(){for(let m of n)try{m.write(`data: reload
3
3
 
4
- `);}catch{n.delete(m);}}function d(){r&&clearTimeout(r),r=setTimeout(()=>{s(),r=null;},a);}function p(m,y){let w=m.url||"/";if((m.method||"GET")!=="GET"){y.writeHead(405,{"Content-Type":"text/plain"}),y.end("Method Not Allowed");return}if(w==="/__live-reload"){y.writeHead(200,{"Content-Type":"text/event-stream","Cache-Control":"no-cache",Connection:"keep-alive","Access-Control-Allow-Origin":"*"}),y.write(`data: connected
4
+ `);}catch{n.delete(m);}}function d(){r&&clearTimeout(r),r=setTimeout(()=>{s(),r=null;},a);}function p(m,w){let y=m.url||"/";if((m.method||"GET")!=="GET"){w.writeHead(405,{"Content-Type":"text/plain"}),w.end("Method Not Allowed");return}if(y==="/__live-reload"){w.writeHead(200,{"Content-Type":"text/event-stream","Cache-Control":"no-cache",Connection:"keep-alive","Access-Control-Allow-Origin":"*"}),w.write(`data: connected
5
5
 
6
- `),n.add(y),m.on("close",()=>{n.delete(y);});return}if(w==="/"||w==="/index.html"){try{let g=S.readFileSync(e,"utf-8"),k=dt(g);y.writeHead(200,{"Content-Type":"text/html; charset=utf-8","Cache-Control":"no-cache"}),y.end(k);}catch(g){let k=g instanceof Error?g.message:"Unknown error";y.writeHead(500,{"Content-Type":"text/html; charset=utf-8"}),y.end(`<!DOCTYPE html>
6
+ `),n.add(w),m.on("close",()=>{n.delete(w);});return}if(y==="/"||y==="/index.html"){try{let g=S.readFileSync(e,"utf-8"),k=dt(g);w.writeHead(200,{"Content-Type":"text/html; charset=utf-8","Cache-Control":"no-cache"}),w.end(k);}catch(g){let k=g instanceof Error?g.message:"Unknown error";w.writeHead(500,{"Content-Type":"text/html; charset=utf-8"}),w.end(`<!DOCTYPE html>
7
7
  <html>
8
8
  <head><title>Error</title></head>
9
9
  <body>
10
10
  <h1>Error loading file</h1>
11
11
  <p>${k}</p>
12
12
  </body>
13
- </html>`);}return}y.writeHead(404,{"Content-Type":"text/html; charset=utf-8"}),y.end(`<!DOCTYPE html>
13
+ </html>`);}return}w.writeHead(404,{"Content-Type":"text/html; charset=utf-8"}),w.end(`<!DOCTYPE html>
14
14
  <html>
15
15
  <head><title>Not Found</title></head>
16
16
  <body>
17
17
  <h1>404 Not Found</h1>
18
18
  <p>The requested resource was not found.</p>
19
19
  </body>
20
- </html>`);}let v=ct.createServer(p),b=null;v.on("error",m=>{i(new Error(`Failed to start preview server: ${m.message}`));}),v.listen(0,"127.0.0.1",()=>{let m=v.address();if(!m||typeof m=="string"){i(new Error("Failed to get server address"));return}let y=m.port;try{b=S.watch(e,f=>{f==="change"&&d();}),b.on("error",f=>{console.error(`[Live Preview] File watcher error: ${f.message}`);});}catch(f){let g=f instanceof Error?f.message:"Unknown error";console.error(`[Live Preview] Failed to watch file: ${g}`);}let w=()=>{b&&(b.close(),b=null),r&&(clearTimeout(r),r=null);for(let k of n)try{k.end();}catch{}n.clear();let f=A.join(Re.tmpdir(),"lindoai-pages-preview.pid"),g=A.join(Re.tmpdir(),"lindoai-pages-preview.port");try{S.existsSync(f)&&S.unlinkSync(f);}catch{}try{S.existsSync(g)&&S.unlinkSync(g);}catch{}v.close(()=>{process.exit(0);}),setTimeout(()=>{process.exit(0);},1e3);};process.on("SIGTERM",w),process.on("SIGINT",w),t(y);});})}var De,Ue=It(()=>{De=`<script>
20
+ </html>`);}let v=ct.createServer(p),b=null;v.on("error",m=>{i(new Error(`Failed to start preview server: ${m.message}`));}),v.listen(0,"127.0.0.1",()=>{let m=v.address();if(!m||typeof m=="string"){i(new Error("Failed to get server address"));return}let w=m.port;try{b=S.watch(e,u=>{u==="change"&&d();}),b.on("error",u=>{console.error(`[Live Preview] File watcher error: ${u.message}`);});}catch(u){let g=u instanceof Error?u.message:"Unknown error";console.error(`[Live Preview] Failed to watch file: ${g}`);}let y=()=>{b&&(b.close(),b=null),r&&(clearTimeout(r),r=null);for(let k of n)try{k.end();}catch{}n.clear();let u=A.join(De.tmpdir(),"lindoai-pages-preview.pid"),g=A.join(De.tmpdir(),"lindoai-pages-preview.port");try{S.existsSync(u)&&S.unlinkSync(u);}catch{}try{S.existsSync(g)&&S.unlinkSync(g);}catch{}v.close(()=>{process.exit(0);}),setTimeout(()=>{process.exit(0);},1e3);};process.on("SIGTERM",y),process.on("SIGINT",y),o(w);});})}var Re,Ue=At(()=>{Re=`<script>
21
21
  (function() {
22
22
  var eventSource = new EventSource('/__live-reload');
23
23
  eventSource.onmessage = function(event) {
@@ -29,13 +29,13 @@ import*as ct from'http';import*as S from'fs';import*as A from'path';import*as Re
29
29
  console.log('[Live Reload] Connection lost, attempting to reconnect...');
30
30
  };
31
31
  })();
32
- </script>`;});var Et="LINDO_API_KEY",Lt="LINDO_BASE_URL",jt=".lindo",Rt="config.json",Dt="https://api.lindo.ai";function et(){return A.join(Re.homedir(),jt)}function q(){return A.join(et(),Rt)}function ve(){let o=q();try{if(S.existsSync(o)){let t=S.readFileSync(o,"utf-8");return JSON.parse(t)}}catch{}return {}}function tt(o){let t=et(),i=q();S.existsSync(t)||S.mkdirSync(t,{recursive:true}),S.writeFileSync(i,JSON.stringify(o,null,2),"utf-8");}function $(){let o=ve(),t=process.env[Et]||o.apiKey,i=process.env[Lt]||o.baseUrl||Dt;return {apiKey:t,baseUrl:i}}function ot(o){let t=ve();t.apiKey=o,tt(t);}function it(o,t){let i=ve();switch(o){case "apiKey":i.apiKey=t;break;case "baseUrl":i.baseUrl=t;break;default:throw new Error(`Unknown configuration key: ${o}`)}tt(i);}function nt(o){let t=$();switch(o){case "apiKey":return t.apiKey;case "baseUrl":return t.baseUrl;default:return}}function T(){return !!$().apiKey}var K={reset:"\x1B[0m",red:"\x1B[31m",green:"\x1B[32m",blue:"\x1B[34m",cyan:"\x1B[36m",gray:"\x1B[90m",bold:"\x1B[1m"};function Nt(){return !process.env.NO_COLOR&&process.stdout.isTTY!==false}function G(o,t){return Nt()?`${t}${o}${K.reset}`:o}function h(o){console.log(G(`\u2713 ${o}`,K.green));}function c(o){console.error(G(`\u2717 ${o}`,K.red));}function l(o){console.log(G(`\u2139 ${o}`,K.blue));}function Ut(o){return JSON.stringify(o,null,2)}function Mt(o){if(o==null)return "";if(Array.isArray(o)){if(o.length===0)return "No data";let t=new Set;for(let e of o)typeof e=="object"&&e!==null&&Object.keys(e).forEach(n=>t.add(n));if(t.size===0)return o.map(e=>String(e)).join(`
33
- `);let i=Array.from(t);return Ht(i,o)}if(typeof o=="object"){let i=Object.entries(o);if(i.length===0)return "No data";let e=Math.max(...i.map(([n])=>n.length));return i.map(([n,r])=>{let a=n.padEnd(e),s=ke(r);return `${G(a,K.cyan)} ${s}`}).join(`
34
- `)}return String(o)}function Ht(o,t){let i={};for(let a of o)i[a]=a.length;for(let a of t)if(typeof a=="object"&&a!==null){let s=a;for(let d of o){let p=ke(s[d]);i[d]=Math.max(i[d],p.length);}}let e=o.map(a=>G(a.padEnd(i[a]),K.bold)).join(" "),n=o.map(a=>"-".repeat(i[a])).join(" "),r=t.map(a=>{if(typeof a=="object"&&a!==null){let s=a;return o.map(d=>ke(s[d]).padEnd(i[d])).join(" ")}return String(a)});return [e,n,...r].join(`
35
- `)}function ke(o){return o==null?G("-",K.gray):typeof o=="boolean"?o?G("true",K.green):G("false",K.red):typeof o=="number"?String(o):typeof o=="object"?Array.isArray(o)?`[${o.length} items]`:JSON.stringify(o):String(o)}function u(o,t){console.log(t==="json"?Ut(o):Mt(o));}var rt=["apiKey","baseUrl"];function _e(){let o=new Command("config").description("Manage CLI configuration");return o.command("set <key> <value>").description("Set a configuration value").action((t,i)=>{rt.includes(t)||(c(`Invalid configuration key: ${t}`),l(`Valid keys: ${rt.join(", ")}`),process.exit(1));try{it(t,i),h(`Configuration saved: ${t}`),l(`Config file: ${q()}`);}catch(e){c(`Failed to save configuration: ${e instanceof Error?e.message:String(e)}`),process.exit(1);}}),o.command("get <key>").description("Get a configuration value").option("-f, --format <format>","Output format (json, table)","table").action((t,i)=>{let e=nt(t);if(e===void 0){i.format==="json"?u({key:t,value:null},i.format):l(`Configuration key '${t}' is not set`);return}if(i.format==="json")u({key:t,value:e},i.format);else {let n=t==="apiKey"?Ce(e):e;console.log(`${t}: ${n}`);}}),o.command("list").description("List all configuration values").option("-f, --format <format>","Output format (json, table)","table").action(t=>{let i=$(),e={apiKey:i.apiKey?Ce(i.apiKey):"(not set)",baseUrl:i.baseUrl,configFile:q()};t.format==="json"?u({apiKey:i.apiKey?Ce(i.apiKey):null,baseUrl:i.baseUrl,configFile:q()},t.format):u(e,t.format);}),o.command("path").description("Show the config file path").action(()=>{console.log(q());}),o}function Ce(o){return o.length<=8?"*".repeat(o.length):`${o.slice(0,4)}${"*".repeat(o.length-8)}${o.slice(-4)}`}function Se(){let o=new Command("agents").description("Run AI agents");return o.command("run <agent-id>").description("Run an AI agent").option("-i, --input <json>","Input data as JSON string","{}").option("-s, --stream","Stream the response",false).option("-f, --format <format>","Output format (json, table)","table").action(async(t,i)=>{T()||(c("API key not configured"),l("Run: lindo config set apiKey <your-api-key>"),l("Or set the LINDO_API_KEY environment variable"),process.exit(1));let e=$(),n=new LindoClient({apiKey:e.apiKey,baseUrl:e.baseUrl}),r;try{r=JSON.parse(i.input);}catch{c("Invalid JSON input"),l(`Example: --input '{"prompt": "Hello!"}'`),process.exit(1);}try{l(`Running agent: ${t}`);let a=await n.agents.run({agent_id:t,input:r,stream:i.stream});a.success?(h("Agent run completed"),u(a,i.format)):(c(`Agent run failed: ${a.error||"Unknown error"}`),u(a,i.format),process.exit(1));}catch(a){Gt(a);}}),o}function Gt(o){o instanceof AuthenticationError&&(c("Authentication failed"),l("Your API key may be invalid or expired"),l("Run: lindo config set apiKey <your-api-key>"),process.exit(1)),o instanceof Error?c(o.message):c("An unexpected error occurred"),process.exit(1);}function Oe(){let o=new Command("workflows").description("Manage workflows");o.command("list").description("List workflow logs").option("-n, --name <name>","Filter by workflow name").option("-s, --status <status>","Filter by status").option("-w, --website <id>","Filter by website ID").option("-c, --client <id>","Filter by client ID").option("-l, --limit <number>","Maximum number of results","50").option("-f, --format <format>","Output format (json, table)","table").action(async i=>{let e=P();try{let n=await e.workflows.list({workflow_name:i.name,status:i.status,website_id:i.website,client_id:i.client,limit:parseInt(i.limit)});n.success?u(n.data,i.format):(c("Failed to list workflows"),process.exit(1));}catch(n){I(n);}}),o.command("start <workflow-name>").description("Start a workflow").option("-p, --params <json>","Workflow parameters as JSON string","{}").option("-f, --format <format>","Output format (json, table)","table").action(async(i,e)=>{let n=P(),r;try{r=JSON.parse(e.params);}catch{c("Invalid JSON params"),l(`Example: --params '{"page_id": "page-123"}'`),process.exit(1);}try{l(`Starting workflow: ${i}`);let a=await n.workflows.start({workflow_name:i,params:r});a.success?(h(`Workflow started: ${a.instance_id}`),u(a,e.format)):(c("Failed to start workflow"),u(a,e.format),process.exit(1));}catch(a){I(a);}}),o.command("status <instance-id>").description("Get workflow status").option("-f, --format <format>","Output format (json, table)","table").action(async(i,e)=>{let n=P();try{let r=await n.workflows.getStatus(i);u(r,e.format);}catch(r){I(r);}}),o.command("status-website <workflow-id>").description("Check the status of a website-creation workflow (started via create-website)").option("-f, --format <format>","Output format (json, table)","table").action(async(i,e)=>{let n=P();try{let r=await n.workflows.getWebsiteStatus(i),a=r.result;a&&!a.done?l(`Status: ${a.status} \u2014 ${a.message}`):a&&h(a.message),u(r,e.format);}catch(r){I(r);}}),o.command("status-page <workflow-id>").description("Check the status of a page-creation workflow (started via create-page)").option("-f, --format <format>","Output format (json, table)","table").action(async(i,e)=>{let n=P();try{let r=await n.workflows.getPageStatus(i),a=r.result;a&&!a.done?l(`Status: ${a.status} \u2014 ${a.message}`):a&&h(a.message),u(r,e.format);}catch(r){I(r);}}),o.command("status-blog <workflow-id>").description("Check the status of a blog-creation workflow (started via create-blog)").option("-f, --format <format>","Output format (json, table)","table").action(async(i,e)=>{let n=P();try{let r=await n.workflows.getBlogStatus(i),a=r.result;a&&!a.done?l(`Status: ${a.status} \u2014 ${a.message}`):a&&h(a.message),u(r,e.format);}catch(r){I(r);}}),o.command("pause <instance-id>").description("Pause a running workflow").option("-f, --format <format>","Output format (json, table)","table").action(async(i,e)=>{let n=P();try{l(`Pausing workflow: ${i}`);let r=await n.workflows.pause(i);r.success?h(r.message):(c(r.message),process.exit(1)),u(r,e.format);}catch(r){I(r);}}),o.command("resume <instance-id>").description("Resume a paused workflow").option("-f, --format <format>","Output format (json, table)","table").action(async(i,e)=>{let n=P();try{l(`Resuming workflow: ${i}`);let r=await n.workflows.resume(i);r.success?h(r.message):(c(r.message),process.exit(1)),u(r,e.format);}catch(r){I(r);}}),o.command("terminate <instance-id>").description("Terminate a workflow").option("-f, --format <format>","Output format (json, table)","table").action(async(i,e)=>{let n=P();try{l(`Terminating workflow: ${i}`);let r=await n.workflows.terminate(i);r.success?h(r.message):(c(r.message),process.exit(1)),u(r,e.format);}catch(r){I(r);}});function t(i){let e;try{let r=Pt("fs");r.existsSync(i)?e=r.readFileSync(i,"utf8"):e=i;}catch{e=i;}let n=JSON.parse(e);if(!Array.isArray(n))throw new Error("Items must be a JSON array");return n}return o.command("batch-create-websites <items>").description("Create up to 25 websites at once. Pass a JSON array file path or inline JSON.").option("-f, --format <format>","Output format (json, table)","table").action(async(i,e)=>{let n=P(),r;try{r=t(i);}catch(a){c(`Invalid items JSON: ${a.message}`),l(`Example: --items '[{"prompt":"..."},{"prompt":"..."}]'`),process.exit(1);}try{l(`Starting batch of ${r.length} websites\u2026`);let a=await n.workflows.batchCreateWebsites(r),s=a.result;s&&h(`Batch accepted: ${s.succeeded} succeeded, ${s.failed} failed of ${s.total}.`),u(a,e.format);}catch(a){I(a);}}),o.command("batch-create-pages <website-id> <items>").description("Create up to 25 pages on a website at once. Pass a JSON array file path or inline JSON.").option("-f, --format <format>","Output format (json, table)","table").action(async(i,e,n)=>{let r=P(),a;try{a=t(e);}catch(s){c(`Invalid items JSON: ${s.message}`),process.exit(1);}try{l(`Starting batch of ${a.length} pages on ${i}\u2026`);let s=await r.workflows.batchCreatePages(i,a),d=s.result;d&&h(`Batch accepted: ${d.succeeded} succeeded, ${d.failed} failed of ${d.total}.`),u(s,n.format);}catch(s){I(s);}}),o.command("batch-create-blogs <website-id> <items>").description("Create up to 25 blog posts on a website at once. Pass a JSON array file path or inline JSON.").option("-f, --format <format>","Output format (json, table)","table").action(async(i,e,n)=>{let r=P(),a;try{a=t(e);}catch(s){c(`Invalid items JSON: ${s.message}`),process.exit(1);}try{l(`Starting batch of ${a.length} blog posts on ${i}\u2026`);let s=await r.workflows.batchCreateBlogs(i,a),d=s.result;d&&h(`Batch accepted: ${d.succeeded} succeeded, ${d.failed} failed of ${d.total}.`),u(s,n.format);}catch(s){I(s);}}),o.command("batch-status-websites <workflow-ids...>").description("Check the status of up to 25 website workflows at once.").option("-f, --format <format>","Output format (json, table)","table").action(async(i,e)=>{let n=P();try{let r=await n.workflows.batchCheckWebsiteStatus(i),a=r.result;a&&!a.done?l(`Batch status: ${a.status} \u2014 ${a.message}`):a&&h(a.message),u(r,e.format);}catch(r){I(r);}}),o.command("batch-status-pages <workflow-ids...>").description("Check the status of up to 25 page workflows at once.").option("-f, --format <format>","Output format (json, table)","table").action(async(i,e)=>{let n=P();try{let r=await n.workflows.batchCheckPageStatus(i),a=r.result;a&&!a.done?l(`Batch status: ${a.status} \u2014 ${a.message}`):a&&h(a.message),u(r,e.format);}catch(r){I(r);}}),o.command("batch-status-blogs <workflow-ids...>").description("Check the status of up to 25 blog workflows at once.").option("-f, --format <format>","Output format (json, table)","table").action(async(i,e)=>{let n=P();try{let r=await n.workflows.batchCheckBlogStatus(i),a=r.result;a&&!a.done?l(`Batch status: ${a.status} \u2014 ${a.message}`):a&&h(a.message),u(r,e.format);}catch(r){I(r);}}),o}function P(){T()||(c("API key not configured"),l("Run: lindo config set apiKey <your-api-key>"),l("Or set the LINDO_API_KEY environment variable"),process.exit(1));let o=$();return new LindoClient({apiKey:o.apiKey,baseUrl:o.baseUrl})}function I(o){o instanceof AuthenticationError&&(c("Authentication failed"),l("Your API key may be invalid or expired"),l("Run: lindo config set apiKey <your-api-key>"),process.exit(1)),o instanceof Error?c(o.message):c("An unexpected error occurred"),process.exit(1);}function $e(){let o=new Command("workspace").description("Workspace operations");return o.command("get").description("Get workspace details").option("-f, --format <format>","Output format (json, table)","table").action(async t=>{let i=N();try{let e=await i.workspace.get();u(e,t.format);}catch(e){U(e);}}),o.command("credits").description("Get workspace credit balance").option("-f, --format <format>","Output format (json, table)","table").action(async t=>{let i=N();try{let e=await i.workspace.getCredits();u(e,t.format);}catch(e){U(e);}}),o.command("client-credits").description("Get credit balance for a specific client").requiredOption("-c, --client <id>","Client ID").option("-f, --format <format>","Output format (json, table)","table").action(async t=>{let i=N();try{let e=await i.workspace.getClientCredits(t.client);u(e,t.format);}catch(e){U(e);}}),o.command("allocate-credits").description("Allocate credits from your workspace to a client").requiredOption("-c, --client <id>","Client ID to allocate credits to").requiredOption("-t, --type <type>","Credit type (monthly | purchased | daily)").requiredOption("-a, --amount <amount>","Number of credits to allocate (positive integer)").option("-s, --source <source>","Allocation source (e.g. bonus, purchase, promotion)").option("-n, --notes <notes>","Optional notes for the allocation record").option("-f, --format <format>","Output format (json, table)","table").action(async t=>{let i=t.type;["monthly","purchased","daily"].includes(i)||(c("Invalid credit type. Must be one of: monthly, purchased, daily"),process.exit(1));let e=Number.parseInt(t.amount,10);(!Number.isFinite(e)||e<=0)&&(c("Amount must be a positive integer"),process.exit(1));let n=N();try{let r=await n.workspace.allocateClientCredits({client_id:t.client,credit_type:i,amount:e,source:t.source,notes:t.notes});r.success&&h("Credits allocated"),u(r,t.format);}catch(r){U(r);}}),o.command("update").description("Update workspace settings").option("-n, --name <name>","Workspace name").option("-l, --language <lang>","Workspace language").option("-w, --webhook <url>","Webhook URL").option("-f, --format <format>","Output format (json, table)","table").action(async t=>{let i=N();try{let e=await i.workspace.update({workspace_name:t.name,workspace_language:t.language,webhook_url:t.webhook});e.success&&h("Workspace updated"),u(e,t.format);}catch(e){U(e);}}),o.command("team-add").description("Add a team member to the workspace").requiredOption("-e, --email <email>","Team member email").option("-r, --role <role>","Role (Team)","Team").option("-f, --format <format>","Output format (json, table)","table").action(async t=>{let i=N();try{let e=await i.workspace.addTeamMember(t.email,t.role);e.success&&h("Team member added"),u(e,t.format);}catch(e){U(e);}}),o.command("team-remove").description("Remove a team member from the workspace").requiredOption("-m, --member <id>","Member ID").option("-f, --format <format>","Output format (json, table)","table").action(async t=>{let i=N();try{let e=await i.workspace.removeTeamMember(t.member);e.success&&h("Team member removed"),u(e,t.format);}catch(e){U(e);}}),o.command("integration-add").description("Add an integration to the workspace").requiredOption("-t, --type <type>","Integration type (e.g., matomo)").requiredOption("-c, --config <json>","Integration config as JSON").option("-f, --format <format>","Output format (json, table)","table").action(async t=>{let i=N(),e;try{e=JSON.parse(t.config);}catch{c("Invalid JSON config"),process.exit(1);}try{let n=await i.workspace.addIntegration({integration_type:t.type,config:e});n.success&&h("Integration added"),u(n,t.format);}catch(n){U(n);}}),o.command("integration-remove").description("Remove an integration from the workspace").requiredOption("-t, --type <type>","Integration type").option("-f, --format <format>","Output format (json, table)","table").action(async t=>{let i=N();try{let e=await i.workspace.removeIntegration(t.type);e.success&&h("Integration removed"),u(e,t.format);}catch(e){U(e);}}),o.command("whitelabel").description("Setup or update whitelabel settings").option("-d, --domain <domain>","Custom domain").option("-s, --subdomain <domain>","Subdomain domain").option("-e, --email-sender <email>","Email sender address").option("--enable-register","Enable client registration").option("--disable-register","Disable client registration").option("-f, --format <format>","Output format (json, table)","table").action(async t=>{let i=N();try{let e=await i.workspace.setupWhitelabel({domain:t.domain,subdomain_domain:t.subdomain,email_sender:t.emailSender,wl_client_register:t.enableRegister?!0:t.disableRegister?!1:void 0});e.success&&h("Whitelabel settings updated"),u(e,t.format);}catch(e){U(e);}}),o.command("appearance").description("Update workspace appearance settings").option("-p, --primary <color>","Primary color (hex)").option("-s, --secondary <color>","Secondary color (hex)").option("-m, --mode <mode>","Theme mode (light/dark)").option("-f, --format <format>","Output format (json, table)","table").action(async t=>{let i=N();try{let e=await i.workspace.updateAppearance({primary_color:t.primary,secondary_color:t.secondary,theme_mode:t.mode});e.success&&h("Appearance settings updated"),u(e,t.format);}catch(e){U(e);}}),o}function N(){T()||(c("API key not configured"),l("Run: lindo config set apiKey <your-api-key>"),l("Or set the LINDO_API_KEY environment variable"),process.exit(1));let o=$();return new LindoClient({apiKey:o.apiKey,baseUrl:o.baseUrl})}function U(o){o instanceof AuthenticationError&&(c("Authentication failed"),l("Your API key may be invalid or expired"),l("Run: lindo config set apiKey <your-api-key>"),process.exit(1)),o instanceof Error?c(o.message):c("An unexpected error occurred"),process.exit(1);}function Fe(){let o=new Command("analytics").description("Analytics operations");return o.command("workspace").description("Get workspace analytics").option("--from <date>","Start date (ISO format)").option("--to <date>","End date (ISO format)").option("-f, --format <format>","Output format (json, table)","table").action(async t=>{let i=at();try{let e=await i.analytics.getWorkspace({from:t.from,to:t.to});u(e,t.format);}catch(e){st(e);}}),o.command("website").description("Get website analytics").requiredOption("-w, --website <id>","Website ID (required)").option("--from <date>","Start date (ISO format)").option("--to <date>","End date (ISO format)").option("-f, --format <format>","Output format (json, table)","table").action(async t=>{let i=at();try{let e=await i.analytics.getWebsite({website_id:t.website,from:t.from,to:t.to});u(e,t.format);}catch(e){st(e);}}),o}function at(){T()||(c("API key not configured"),l("Run: lindo config set apiKey <your-api-key>"),l("Or set the LINDO_API_KEY environment variable"),process.exit(1));let o=$();return new LindoClient({apiKey:o.apiKey,baseUrl:o.baseUrl})}function st(o){o instanceof AuthenticationError&&(c("Authentication failed"),l("Your API key may be invalid or expired"),l("Run: lindo config set apiKey <your-api-key>"),process.exit(1)),o instanceof Error?c(o.message):c("An unexpected error occurred"),process.exit(1);}function Te(){let o=new Command("clients").description("Client management operations");return o.command("list").description("List all workspace clients").option("-p, --page <page>","Page number","1").option("-s, --search <search>","Search term").option("-f, --format <format>","Output format (json, table)","table").action(async t=>{let i=de();try{let e=await i.clients.list({page:parseInt(t.page,10),search:t.search});if(t.format==="json")u(e,"json");else if(e.clients&&e.clients.length>0){console.log(`
36
- Clients:`),console.log("--------");for(let n of e.clients)console.log(` ID: ${n.record_id}`),console.log(` Email: ${n.email}`),console.log(` Website Limit: ${n.website_limit??"N/A"}`),console.log(` Suspended: ${n.suspended??!1}`),console.log("");console.log(`Total: ${e.total??e.clients.length}`);}else l("No clients found");}catch(e){me(e);}}),o.command("create").description("Create a new workspace client").requiredOption("-e, --email <email>","Client email address").option("-l, --limit <limit>","Website limit","5").option("-f, --format <format>","Output format (json, table)","table").action(async t=>{let i=de();try{let e=await i.clients.create({email:t.email,website_limit:parseInt(t.limit,10)});if(e.success&&e.client)h(`Client created: ${e.client.record_id}`),u(e.client,t.format);else if(c("Failed to create client"),e.errors)for(let n of e.errors)c(` ${n}`);}catch(e){me(e);}}),o.command("update").description("Update a workspace client").requiredOption("-i, --id <id>","Client ID").option("-l, --limit <limit>","Website limit").option("--suspend","Suspend the client").option("--unsuspend","Unsuspend the client").option("-f, --format <format>","Output format (json, table)","table").action(async t=>{let i=de();try{let e=await i.clients.update({client_id:t.id,website_limit:t.limit?parseInt(t.limit,10):void 0,suspended:t.suspend?!0:t.unsuspend?!1:void 0});if(e.success)h("Client updated"),e.client&&u(e.client,t.format);else if(c("Failed to update client"),e.errors)for(let n of e.errors)c(` ${n}`);}catch(e){me(e);}}),o.command("delete").description("Delete a workspace client").requiredOption("-i, --id <id>","Client ID").action(async t=>{let i=de();try{let e=await i.clients.delete(t.id);if(e.success)h("Client deleted");else if(c("Failed to delete client"),e.errors)for(let n of e.errors)c(` ${n}`);}catch(e){me(e);}}),o.command("magic-link").description("Create a magic link for client authentication").requiredOption("-e, --email <email>","Client email address").option("-f, --format <format>","Output format (json, table)","table").action(async t=>{let i=de();try{let e=await i.clients.createMagicLink(t.email);if(e.success)h("Magic link created"),u(e,t.format);else if(c("Failed to create magic link"),e.errors)for(let n of e.errors)c(` ${n}`);}catch(e){me(e);}}),o}function de(){T()||(c("API key not configured"),l("Run: lindo config set apiKey <your-api-key>"),l("Or set the LINDO_API_KEY environment variable"),process.exit(1));let o=$();return new LindoClient({apiKey:o.apiKey,baseUrl:o.baseUrl})}function me(o){o instanceof AuthenticationError&&(c("Authentication failed"),l("Your API key may be invalid or expired"),l("Run: lindo config set apiKey <your-api-key>"),process.exit(1)),o instanceof Error?c(o.message):c("An unexpected error occurred"),process.exit(1);}function Pe(){let o=new Command("websites").description("Website management operations");return o.command("list").description("List all workspace websites").option("-p, --page <page>","Page number","1").option("-s, --search <search>","Search term").option("-f, --format <format>","Output format (json, table)","table").action(async t=>{let i=E();try{let e=await i.websites.list({page:parseInt(t.page,10),search:t.search});if(t.format==="json")u(e,"json");else {let n=e.result?.list??[];if(n.length>0){console.log(`
37
- Websites:`),console.log("---------");for(let r of n)console.log(` ID: ${r.website_id}`),console.log(` Name: ${r.website_name??"N/A"}`),console.log(` Domain: ${r.domain??"N/A"}`),console.log(` Activated: ${r.activated??!1}`),console.log("");console.log(`Total: ${e.result?.total??n.length}`);}else l("No websites found");}}catch(e){L(e);}}),o.command("get").description("Get website details").requiredOption("-i, --id <id>","Website ID").option("-f, --format <format>","Output format (json, table)","table").action(async t=>{let i=E();try{let e=await i.websites.getDetails(t.id);u(e,t.format);}catch(e){L(e);}}),o.command("update").description("Update a website").requiredOption("-i, --id <id>","Website ID").option("-n, --name <name>","Business name").option("--activate","Activate the website").option("--deactivate","Deactivate the website").option("-f, --format <format>","Output format (json, table)","table").action(async t=>{let i=E();try{let e=await i.websites.update({website_id:t.id,business_name:t.name,activated:t.activate?!0:t.deactivate?!1:void 0});if(e.success)h("Website updated"),e.website&&u(e.website,t.format);else if(c("Failed to update website"),e.errors)for(let n of e.errors)c(` ${n}`);}catch(e){L(e);}}),o.command("settings").description("Update website settings").requiredOption("-i, --id <id>","Website ID").option("-n, --name <name>","Business name").option("-l, --language <lang>","Language").option("-d, --description <desc>","Business description").option("-f, --format <format>","Output format (json, table)","table").action(async t=>{let i=E();try{let e=await i.websites.updateSettings(t.id,{business_name:t.name,language:t.language,business_description:t.description});e.success&&h("Website settings updated"),u(e,t.format);}catch(e){L(e);}}),o.command("delete").description("Delete a website").requiredOption("-i, --id <id>","Website ID").action(async t=>{let i=E();try{let e=await i.websites.delete(t.id);if(e.success)h("Website deleted");else if(c("Failed to delete website"),e.errors)for(let n of e.errors)c(` ${n}`);}catch(e){L(e);}}),o.command("assign").description("Assign a website to a client").requiredOption("-w, --website <id>","Website ID").requiredOption("-c, --client <id>","Client ID").action(async t=>{let i=E();try{let e=await i.websites.assign({website_id:t.website,client_id:t.client});if(e.success)h("Website assigned to client");else if(c("Failed to assign website"),e.errors)for(let n of e.errors)c(` ${n}`);}catch(e){L(e);}}),o.command("domain-add").description("Add a custom domain to a website").requiredOption("-i, --id <id>","Website ID").requiredOption("-d, --domain <domain>","Custom domain").option("-f, --format <format>","Output format (json, table)","table").action(async t=>{let i=E();try{let e=await i.websites.addDomain(t.id,t.domain);if(e.success&&(h("Domain added"),e.result?.dns_records)){console.log(`
38
- DNS Records to configure:`);for(let n of e.result.dns_records)console.log(` ${n.record_type} ${n.host} -> ${n.value}`);}u(e,t.format);}catch(e){L(e);}}),o.command("domain-remove").description("Remove a custom domain from a website").requiredOption("-i, --id <id>","Website ID").option("-f, --format <format>","Output format (json, table)","table").action(async t=>{let i=E();try{let e=await i.websites.removeDomain(t.id);e.success&&h("Domain removed"),u(e,t.format);}catch(e){L(e);}}),o.command("integration-add").description("Add an integration to a website").requiredOption("-i, --id <id>","Website ID").requiredOption("-t, --type <type>","Integration type (e.g., matomo)").requiredOption("-c, --config <json>","Integration config as JSON").option("-f, --format <format>","Output format (json, table)","table").action(async t=>{let i=E(),e;try{e=JSON.parse(t.config);}catch{c("Invalid JSON config"),process.exit(1);}try{let n=await i.websites.addIntegration(t.id,{integration_type:t.type,config:e});n.success&&h("Integration added"),u(n,t.format);}catch(n){L(n);}}),o.command("integration-remove").description("Remove an integration from a website").requiredOption("-i, --id <id>","Website ID").requiredOption("-t, --type <type>","Integration type").option("-f, --format <format>","Output format (json, table)","table").action(async t=>{let i=E();try{let e=await i.websites.removeIntegration(t.id,t.type);e.success&&h("Integration removed"),u(e,t.format);}catch(e){L(e);}}),o.command("team-add").description("Add a team member to a website").requiredOption("-i, --id <id>","Website ID").requiredOption("-e, --email <email>","Team member email").requiredOption("-r, --role <role>","Role (Editor or Commenter)").option("-f, --format <format>","Output format (json, table)","table").action(async t=>{let i=E();try{let e=await i.websites.addTeamMember(t.id,t.email,t.role);e.success&&h("Team member added"),u(e,t.format);}catch(e){L(e);}}),o.command("team-remove").description("Remove a team member from a website").requiredOption("-i, --id <id>","Website ID").requiredOption("-m, --member <memberId>","Member ID").option("-f, --format <format>","Output format (json, table)","table").action(async t=>{let i=E();try{let e=await i.websites.removeTeamMember(t.id,t.member);e.success&&h("Team member removed"),u(e,t.format);}catch(e){L(e);}}),o}function E(){T()||(c("API key not configured"),l("Run: lindo config set apiKey <your-api-key>"),l("Or set the LINDO_API_KEY environment variable"),process.exit(1));let o=$();return new LindoClient({apiKey:o.apiKey,baseUrl:o.baseUrl})}function L(o){o instanceof AuthenticationError&&(c("Authentication failed"),l("Your API key may be invalid or expired"),l("Run: lindo config set apiKey <your-api-key>"),process.exit(1)),o instanceof Error?c(o.message):c("An unexpected error occurred"),process.exit(1);}function J(o){return new Promise(t=>{let i=platform(),e;switch(i){case "darwin":e=`open "${o}"`;break;case "win32":e=`start "" "${o}"`;break;default:e=`xdg-open "${o}"`;break}exec(e,n=>{t(!n);});})}function mo(o){let t=o.filter(e=>!!(e&&e.trim()));return t.length===0?"":`https://fonts.googleapis.com/css2?family=${t.map(e=>`${e.trim().replace(/ /g,"+")}:wght@300;400;700`).join("&family=")}&display=swap`}function pe(o){let t=[o.font,o.title_font].filter(Boolean);if(t.length===0)return "";let i=mo(t);if(!i)return "";let e=o.font||o.title_font,n=o.title_font||o.font,r=`
32
+ </script>`;});var Lt="LINDO_API_KEY",jt="LINDO_BASE_URL",Dt=".lindo",Rt="config.json",Nt="https://api.lindo.ai";function et(){return A.join(De.homedir(),Dt)}function q(){return A.join(et(),Rt)}function ve(){let t=q();try{if(S.existsSync(t)){let o=S.readFileSync(t,"utf-8");return JSON.parse(o)}}catch{}return {}}function tt(t){let o=et(),i=q();S.existsSync(o)||S.mkdirSync(o,{recursive:true}),S.writeFileSync(i,JSON.stringify(t,null,2),"utf-8");}function $(){let t=ve(),o=process.env[Lt]||t.apiKey,i=process.env[jt]||t.baseUrl||Nt;return {apiKey:o,baseUrl:i}}function ot(t){let o=ve();o.apiKey=t,tt(o);}function it(t,o){let i=ve();switch(t){case "apiKey":i.apiKey=o;break;case "baseUrl":i.baseUrl=o;break;default:throw new Error(`Unknown configuration key: ${t}`)}tt(i);}function nt(t){let o=$();switch(t){case "apiKey":return o.apiKey;case "baseUrl":return o.baseUrl;default:return}}function T(){return !!$().apiKey}var K={reset:"\x1B[0m",red:"\x1B[31m",green:"\x1B[32m",blue:"\x1B[34m",cyan:"\x1B[36m",gray:"\x1B[90m",bold:"\x1B[1m"};function Ut(){return !process.env.NO_COLOR&&process.stdout.isTTY!==false}function G(t,o){return Ut()?`${o}${t}${K.reset}`:t}function h(t){console.log(G(`\u2713 ${t}`,K.green));}function c(t){console.error(G(`\u2717 ${t}`,K.red));}function l(t){console.log(G(`\u2139 ${t}`,K.blue));}function Mt(t){return JSON.stringify(t,null,2)}function Ht(t){if(t==null)return "";if(Array.isArray(t)){if(t.length===0)return "No data";let o=new Set;for(let e of t)typeof e=="object"&&e!==null&&Object.keys(e).forEach(n=>o.add(n));if(o.size===0)return t.map(e=>String(e)).join(`
33
+ `);let i=Array.from(o);return Wt(i,t)}if(typeof t=="object"){let i=Object.entries(t);if(i.length===0)return "No data";let e=Math.max(...i.map(([n])=>n.length));return i.map(([n,r])=>{let a=n.padEnd(e),s=ke(r);return `${G(a,K.cyan)} ${s}`}).join(`
34
+ `)}return String(t)}function Wt(t,o){let i={};for(let a of t)i[a]=a.length;for(let a of o)if(typeof a=="object"&&a!==null){let s=a;for(let d of t){let p=ke(s[d]);i[d]=Math.max(i[d],p.length);}}let e=t.map(a=>G(a.padEnd(i[a]),K.bold)).join(" "),n=t.map(a=>"-".repeat(i[a])).join(" "),r=o.map(a=>{if(typeof a=="object"&&a!==null){let s=a;return t.map(d=>ke(s[d]).padEnd(i[d])).join(" ")}return String(a)});return [e,n,...r].join(`
35
+ `)}function ke(t){return t==null?G("-",K.gray):typeof t=="boolean"?t?G("true",K.green):G("false",K.red):typeof t=="number"?String(t):typeof t=="object"?Array.isArray(t)?`[${t.length} items]`:JSON.stringify(t):String(t)}function f(t,o){console.log(o==="json"?Mt(t):Ht(t));}var rt=["apiKey","baseUrl"];function _e(){let t=new Command("config").description("Manage CLI configuration");return t.command("set <key> <value>").description("Set a configuration value").action((o,i)=>{rt.includes(o)||(c(`Invalid configuration key: ${o}`),l(`Valid keys: ${rt.join(", ")}`),process.exit(1));try{it(o,i),h(`Configuration saved: ${o}`),l(`Config file: ${q()}`);}catch(e){c(`Failed to save configuration: ${e instanceof Error?e.message:String(e)}`),process.exit(1);}}),t.command("get <key>").description("Get a configuration value").option("-f, --format <format>","Output format (json, table)","table").action((o,i)=>{let e=nt(o);if(e===void 0){i.format==="json"?f({key:o,value:null},i.format):l(`Configuration key '${o}' is not set`);return}if(i.format==="json")f({key:o,value:e},i.format);else {let n=o==="apiKey"?Ce(e):e;console.log(`${o}: ${n}`);}}),t.command("list").description("List all configuration values").option("-f, --format <format>","Output format (json, table)","table").action(o=>{let i=$(),e={apiKey:i.apiKey?Ce(i.apiKey):"(not set)",baseUrl:i.baseUrl,configFile:q()};o.format==="json"?f({apiKey:i.apiKey?Ce(i.apiKey):null,baseUrl:i.baseUrl,configFile:q()},o.format):f(e,o.format);}),t.command("path").description("Show the config file path").action(()=>{console.log(q());}),t}function Ce(t){return t.length<=8?"*".repeat(t.length):`${t.slice(0,4)}${"*".repeat(t.length-8)}${t.slice(-4)}`}function Se(){let t=new Command("agents").description("Run AI agents");return t.command("run <agent-id>").description("Run an AI agent").option("-i, --input <json>","Input data as JSON string","{}").option("-s, --stream","Stream the response",false).option("-f, --format <format>","Output format (json, table)","table").action(async(o,i)=>{T()||(c("API key not configured"),l("Run: lindo config set apiKey <your-api-key>"),l("Or set the LINDO_API_KEY environment variable"),process.exit(1));let e=$(),n=new LindoClient({apiKey:e.apiKey,baseUrl:e.baseUrl}),r;try{r=JSON.parse(i.input);}catch{c("Invalid JSON input"),l(`Example: --input '{"prompt": "Hello!"}'`),process.exit(1);}try{l(`Running agent: ${o}`);let a=await n.agents.run({agent_id:o,input:r,stream:i.stream});a.success?(h("Agent run completed"),f(a,i.format)):(c(`Agent run failed: ${a.error||"Unknown error"}`),f(a,i.format),process.exit(1));}catch(a){Jt(a);}}),t}function Jt(t){t instanceof AuthenticationError&&(c("Authentication failed"),l("Your API key may be invalid or expired"),l("Run: lindo config set apiKey <your-api-key>"),process.exit(1)),t instanceof Error?c(t.message):c("An unexpected error occurred"),process.exit(1);}function Oe(){let t=new Command("workflows").description("Manage workflows");t.command("list").description("List workflow logs").option("-n, --name <name>","Filter by workflow name").option("-s, --status <status>","Filter by status").option("-w, --website <id>","Filter by website ID").option("-c, --client <id>","Filter by client ID").option("-l, --limit <number>","Maximum number of results","50").option("-f, --format <format>","Output format (json, table)","table").action(async i=>{let e=P();try{let n=await e.workflows.list({workflow_name:i.name,status:i.status,website_id:i.website,client_id:i.client,limit:parseInt(i.limit)});n.success?f(n.data,i.format):(c("Failed to list workflows"),process.exit(1));}catch(n){I(n);}}),t.command("start <workflow-name>").description("Start a workflow").option("-p, --params <json>","Workflow parameters as JSON string","{}").option("-f, --format <format>","Output format (json, table)","table").action(async(i,e)=>{let n=P(),r;try{r=JSON.parse(e.params);}catch{c("Invalid JSON params"),l(`Example: --params '{"page_id": "page-123"}'`),process.exit(1);}try{l(`Starting workflow: ${i}`);let a=await n.workflows.start({workflow_name:i,params:r});a.success?(h(`Workflow started: ${a.instance_id}`),f(a,e.format)):(c("Failed to start workflow"),f(a,e.format),process.exit(1));}catch(a){I(a);}}),t.command("status <instance-id>").description("Get workflow status").option("-f, --format <format>","Output format (json, table)","table").action(async(i,e)=>{let n=P();try{let r=await n.workflows.getStatus(i);f(r,e.format);}catch(r){I(r);}}),t.command("status-website <workflow-id>").description("Check the status of a website-creation workflow (started via create-website)").option("-f, --format <format>","Output format (json, table)","table").action(async(i,e)=>{let n=P();try{let r=await n.workflows.getWebsiteStatus(i),a=r.result;a&&!a.done?l(`Status: ${a.status} \u2014 ${a.message}`):a&&h(a.message),f(r,e.format);}catch(r){I(r);}}),t.command("status-page <workflow-id>").description("Check the status of a page-creation workflow (started via create-page)").option("-f, --format <format>","Output format (json, table)","table").action(async(i,e)=>{let n=P();try{let r=await n.workflows.getPageStatus(i),a=r.result;a&&!a.done?l(`Status: ${a.status} \u2014 ${a.message}`):a&&h(a.message),f(r,e.format);}catch(r){I(r);}}),t.command("status-blog <workflow-id>").description("Check the status of a blog-creation workflow (started via create-blog)").option("-f, --format <format>","Output format (json, table)","table").action(async(i,e)=>{let n=P();try{let r=await n.workflows.getBlogStatus(i),a=r.result;a&&!a.done?l(`Status: ${a.status} \u2014 ${a.message}`):a&&h(a.message),f(r,e.format);}catch(r){I(r);}}),t.command("pause <instance-id>").description("Pause a running workflow").option("-f, --format <format>","Output format (json, table)","table").action(async(i,e)=>{let n=P();try{l(`Pausing workflow: ${i}`);let r=await n.workflows.pause(i);r.success?h(r.message):(c(r.message),process.exit(1)),f(r,e.format);}catch(r){I(r);}}),t.command("resume <instance-id>").description("Resume a paused workflow").option("-f, --format <format>","Output format (json, table)","table").action(async(i,e)=>{let n=P();try{l(`Resuming workflow: ${i}`);let r=await n.workflows.resume(i);r.success?h(r.message):(c(r.message),process.exit(1)),f(r,e.format);}catch(r){I(r);}}),t.command("terminate <instance-id>").description("Terminate a workflow").option("-f, --format <format>","Output format (json, table)","table").action(async(i,e)=>{let n=P();try{l(`Terminating workflow: ${i}`);let r=await n.workflows.terminate(i);r.success?h(r.message):(c(r.message),process.exit(1)),f(r,e.format);}catch(r){I(r);}});function o(i){let e;try{let r=It("fs");r.existsSync(i)?e=r.readFileSync(i,"utf8"):e=i;}catch{e=i;}let n=JSON.parse(e);if(!Array.isArray(n))throw new Error("Items must be a JSON array");return n}return t.command("batch-create-websites <items>").description("Create up to 25 websites at once. Pass a JSON array file path or inline JSON.").option("-f, --format <format>","Output format (json, table)","table").action(async(i,e)=>{let n=P(),r;try{r=o(i);}catch(a){c(`Invalid items JSON: ${a.message}`),l(`Example: --items '[{"prompt":"..."},{"prompt":"..."}]'`),process.exit(1);}try{l(`Starting batch of ${r.length} websites\u2026`);let a=await n.workflows.batchCreateWebsites(r),s=a.result;s&&h(`Batch accepted: ${s.succeeded} succeeded, ${s.failed} failed of ${s.total}.`),f(a,e.format);}catch(a){I(a);}}),t.command("batch-create-pages <website-id> <items>").description("Create up to 25 pages on a website at once. Pass a JSON array file path or inline JSON.").option("-f, --format <format>","Output format (json, table)","table").action(async(i,e,n)=>{let r=P(),a;try{a=o(e);}catch(s){c(`Invalid items JSON: ${s.message}`),process.exit(1);}try{l(`Starting batch of ${a.length} pages on ${i}\u2026`);let s=await r.workflows.batchCreatePages(i,a),d=s.result;d&&h(`Batch accepted: ${d.succeeded} succeeded, ${d.failed} failed of ${d.total}.`),f(s,n.format);}catch(s){I(s);}}),t.command("batch-create-blogs <website-id> <items>").description("Create up to 25 blog posts on a website at once. Pass a JSON array file path or inline JSON.").option("-f, --format <format>","Output format (json, table)","table").action(async(i,e,n)=>{let r=P(),a;try{a=o(e);}catch(s){c(`Invalid items JSON: ${s.message}`),process.exit(1);}try{l(`Starting batch of ${a.length} blog posts on ${i}\u2026`);let s=await r.workflows.batchCreateBlogs(i,a),d=s.result;d&&h(`Batch accepted: ${d.succeeded} succeeded, ${d.failed} failed of ${d.total}.`),f(s,n.format);}catch(s){I(s);}}),t.command("batch-status-websites <workflow-ids...>").description("Check the status of up to 25 website workflows at once.").option("-f, --format <format>","Output format (json, table)","table").action(async(i,e)=>{let n=P();try{let r=await n.workflows.batchCheckWebsiteStatus(i),a=r.result;a&&!a.done?l(`Batch status: ${a.status} \u2014 ${a.message}`):a&&h(a.message),f(r,e.format);}catch(r){I(r);}}),t.command("batch-status-pages <workflow-ids...>").description("Check the status of up to 25 page workflows at once.").option("-f, --format <format>","Output format (json, table)","table").action(async(i,e)=>{let n=P();try{let r=await n.workflows.batchCheckPageStatus(i),a=r.result;a&&!a.done?l(`Batch status: ${a.status} \u2014 ${a.message}`):a&&h(a.message),f(r,e.format);}catch(r){I(r);}}),t.command("batch-status-blogs <workflow-ids...>").description("Check the status of up to 25 blog workflows at once.").option("-f, --format <format>","Output format (json, table)","table").action(async(i,e)=>{let n=P();try{let r=await n.workflows.batchCheckBlogStatus(i),a=r.result;a&&!a.done?l(`Batch status: ${a.status} \u2014 ${a.message}`):a&&h(a.message),f(r,e.format);}catch(r){I(r);}}),t}function P(){T()||(c("API key not configured"),l("Run: lindo config set apiKey <your-api-key>"),l("Or set the LINDO_API_KEY environment variable"),process.exit(1));let t=$();return new LindoClient({apiKey:t.apiKey,baseUrl:t.baseUrl})}function I(t){t instanceof AuthenticationError&&(c("Authentication failed"),l("Your API key may be invalid or expired"),l("Run: lindo config set apiKey <your-api-key>"),process.exit(1)),t instanceof Error?c(t.message):c("An unexpected error occurred"),process.exit(1);}function $e(){let t=new Command("workspace").description("Workspace operations");return t.command("get").description("Get workspace details").option("-f, --format <format>","Output format (json, table)","table").action(async o=>{let i=N();try{let e=await i.workspace.get();f(e,o.format);}catch(e){U(e);}}),t.command("credits").description("Get workspace credit balance").option("-f, --format <format>","Output format (json, table)","table").action(async o=>{let i=N();try{let e=await i.workspace.getCredits();f(e,o.format);}catch(e){U(e);}}),t.command("client-credits").description("Get credit balance for a specific client").requiredOption("-c, --client <id>","Client ID").option("-f, --format <format>","Output format (json, table)","table").action(async o=>{let i=N();try{let e=await i.workspace.getClientCredits(o.client);f(e,o.format);}catch(e){U(e);}}),t.command("allocate-credits").description("Allocate credits from your workspace to a client").requiredOption("-c, --client <id>","Client ID to allocate credits to").requiredOption("-t, --type <type>","Credit type (monthly | purchased | daily)").requiredOption("-a, --amount <amount>","Number of credits to allocate (positive integer)").option("-s, --source <source>","Allocation source (e.g. bonus, purchase, promotion)").option("-n, --notes <notes>","Optional notes for the allocation record").option("-f, --format <format>","Output format (json, table)","table").action(async o=>{let i=o.type;["monthly","purchased","daily"].includes(i)||(c("Invalid credit type. Must be one of: monthly, purchased, daily"),process.exit(1));let e=Number.parseInt(o.amount,10);(!Number.isFinite(e)||e<=0)&&(c("Amount must be a positive integer"),process.exit(1));let n=N();try{let r=await n.workspace.allocateClientCredits({client_id:o.client,credit_type:i,amount:e,source:o.source,notes:o.notes});r.success&&h("Credits allocated"),f(r,o.format);}catch(r){U(r);}}),t.command("update").description("Update workspace settings").option("-n, --name <name>","Workspace name").option("-l, --language <lang>","Workspace language").option("-w, --webhook <url>","Webhook URL").option("-f, --format <format>","Output format (json, table)","table").action(async o=>{let i=N();try{let e=await i.workspace.update({workspace_name:o.name,workspace_language:o.language,webhook_url:o.webhook});e.success&&h("Workspace updated"),f(e,o.format);}catch(e){U(e);}}),t.command("team-add").description("Add a team member to the workspace").requiredOption("-e, --email <email>","Team member email").option("-r, --role <role>","Role (Team)","Team").option("-f, --format <format>","Output format (json, table)","table").action(async o=>{let i=N();try{let e=await i.workspace.addTeamMember(o.email,o.role);e.success&&h("Team member added"),f(e,o.format);}catch(e){U(e);}}),t.command("team-remove").description("Remove a team member from the workspace").requiredOption("-m, --member <id>","Member ID").option("-f, --format <format>","Output format (json, table)","table").action(async o=>{let i=N();try{let e=await i.workspace.removeTeamMember(o.member);e.success&&h("Team member removed"),f(e,o.format);}catch(e){U(e);}}),t.command("integration-add").description("Add an integration to the workspace").requiredOption("-t, --type <type>","Integration type (e.g., matomo)").requiredOption("-c, --config <json>","Integration config as JSON").option("-f, --format <format>","Output format (json, table)","table").action(async o=>{let i=N(),e;try{e=JSON.parse(o.config);}catch{c("Invalid JSON config"),process.exit(1);}try{let n=await i.workspace.addIntegration({integration_type:o.type,config:e});n.success&&h("Integration added"),f(n,o.format);}catch(n){U(n);}}),t.command("integration-remove").description("Remove an integration from the workspace").requiredOption("-t, --type <type>","Integration type").option("-f, --format <format>","Output format (json, table)","table").action(async o=>{let i=N();try{let e=await i.workspace.removeIntegration(o.type);e.success&&h("Integration removed"),f(e,o.format);}catch(e){U(e);}}),t.command("whitelabel").description("Setup or update whitelabel settings").option("-d, --domain <domain>","Custom domain").option("-s, --subdomain <domain>","Subdomain domain").option("-e, --email-sender <email>","Email sender address").option("--enable-register","Enable client registration").option("--disable-register","Disable client registration").option("-f, --format <format>","Output format (json, table)","table").action(async o=>{let i=N();try{let e=await i.workspace.setupWhitelabel({domain:o.domain,subdomain_domain:o.subdomain,email_sender:o.emailSender,wl_client_register:o.enableRegister?!0:o.disableRegister?!1:void 0});e.success&&h("Whitelabel settings updated"),f(e,o.format);}catch(e){U(e);}}),t.command("appearance").description("Update workspace appearance settings").option("-p, --primary <color>","Primary color (hex)").option("-s, --secondary <color>","Secondary color (hex)").option("-m, --mode <mode>","Theme mode (light/dark)").option("-f, --format <format>","Output format (json, table)","table").action(async o=>{let i=N();try{let e=await i.workspace.updateAppearance({primary_color:o.primary,secondary_color:o.secondary,theme_mode:o.mode});e.success&&h("Appearance settings updated"),f(e,o.format);}catch(e){U(e);}}),t}function N(){T()||(c("API key not configured"),l("Run: lindo config set apiKey <your-api-key>"),l("Or set the LINDO_API_KEY environment variable"),process.exit(1));let t=$();return new LindoClient({apiKey:t.apiKey,baseUrl:t.baseUrl})}function U(t){t instanceof AuthenticationError&&(c("Authentication failed"),l("Your API key may be invalid or expired"),l("Run: lindo config set apiKey <your-api-key>"),process.exit(1)),t instanceof Error?c(t.message):c("An unexpected error occurred"),process.exit(1);}function Fe(){let t=new Command("analytics").description("Analytics operations");return t.command("workspace").description("Get workspace analytics").option("--from <date>","Start date (ISO format)").option("--to <date>","End date (ISO format)").option("-f, --format <format>","Output format (json, table)","table").action(async o=>{let i=at();try{let e=await i.analytics.getWorkspace({from:o.from,to:o.to});f(e,o.format);}catch(e){st(e);}}),t.command("website").description("Get website analytics").requiredOption("-w, --website <id>","Website ID (required)").option("--from <date>","Start date (ISO format)").option("--to <date>","End date (ISO format)").option("-f, --format <format>","Output format (json, table)","table").action(async o=>{let i=at();try{let e=await i.analytics.getWebsite({website_id:o.website,from:o.from,to:o.to});f(e,o.format);}catch(e){st(e);}}),t}function at(){T()||(c("API key not configured"),l("Run: lindo config set apiKey <your-api-key>"),l("Or set the LINDO_API_KEY environment variable"),process.exit(1));let t=$();return new LindoClient({apiKey:t.apiKey,baseUrl:t.baseUrl})}function st(t){t instanceof AuthenticationError&&(c("Authentication failed"),l("Your API key may be invalid or expired"),l("Run: lindo config set apiKey <your-api-key>"),process.exit(1)),t instanceof Error?c(t.message):c("An unexpected error occurred"),process.exit(1);}function Te(){let t=new Command("clients").description("Client management operations");return t.command("list").description("List all workspace clients").option("-p, --page <page>","Page number","1").option("-s, --search <search>","Search term").option("-f, --format <format>","Output format (json, table)","table").action(async o=>{let i=de();try{let e=await i.clients.list({page:parseInt(o.page,10),search:o.search});if(o.format==="json")f(e,"json");else if(e.clients&&e.clients.length>0){console.log(`
36
+ Clients:`),console.log("--------");for(let n of e.clients)console.log(` ID: ${n.record_id}`),console.log(` Email: ${n.email}`),console.log(` Website Limit: ${n.website_limit??"N/A"}`),console.log(` Suspended: ${n.suspended??!1}`),console.log("");console.log(`Total: ${e.total??e.clients.length}`);}else l("No clients found");}catch(e){me(e);}}),t.command("create").description("Create a new workspace client").requiredOption("-e, --email <email>","Client email address").option("-l, --limit <limit>","Website limit","5").option("-f, --format <format>","Output format (json, table)","table").action(async o=>{let i=de();try{let e=await i.clients.create({email:o.email,website_limit:parseInt(o.limit,10)});if(e.success&&e.client)h(`Client created: ${e.client.record_id}`),f(e.client,o.format);else if(c("Failed to create client"),e.errors)for(let n of e.errors)c(` ${n}`);}catch(e){me(e);}}),t.command("update").description("Update a workspace client").requiredOption("-i, --id <id>","Client ID").option("-l, --limit <limit>","Website limit").option("--suspend","Suspend the client").option("--unsuspend","Unsuspend the client").option("-f, --format <format>","Output format (json, table)","table").action(async o=>{let i=de();try{let e=await i.clients.update({client_id:o.id,website_limit:o.limit?parseInt(o.limit,10):void 0,suspended:o.suspend?!0:o.unsuspend?!1:void 0});if(e.success)h("Client updated"),e.client&&f(e.client,o.format);else if(c("Failed to update client"),e.errors)for(let n of e.errors)c(` ${n}`);}catch(e){me(e);}}),t.command("delete").description("Delete a workspace client").requiredOption("-i, --id <id>","Client ID").action(async o=>{let i=de();try{let e=await i.clients.delete(o.id);if(e.success)h("Client deleted");else if(c("Failed to delete client"),e.errors)for(let n of e.errors)c(` ${n}`);}catch(e){me(e);}}),t.command("magic-link").description("Create a magic link for client authentication").requiredOption("-e, --email <email>","Client email address").option("-f, --format <format>","Output format (json, table)","table").action(async o=>{let i=de();try{let e=await i.clients.createMagicLink(o.email);if(e.success)h("Magic link created"),f(e,o.format);else if(c("Failed to create magic link"),e.errors)for(let n of e.errors)c(` ${n}`);}catch(e){me(e);}}),t}function de(){T()||(c("API key not configured"),l("Run: lindo config set apiKey <your-api-key>"),l("Or set the LINDO_API_KEY environment variable"),process.exit(1));let t=$();return new LindoClient({apiKey:t.apiKey,baseUrl:t.baseUrl})}function me(t){t instanceof AuthenticationError&&(c("Authentication failed"),l("Your API key may be invalid or expired"),l("Run: lindo config set apiKey <your-api-key>"),process.exit(1)),t instanceof Error?c(t.message):c("An unexpected error occurred"),process.exit(1);}function Pe(){let t=new Command("websites").description("Website management operations");return t.command("list").description("List all workspace websites").option("-p, --page <page>","Page number","1").option("-s, --search <search>","Search term").option("-f, --format <format>","Output format (json, table)","table").action(async o=>{let i=E();try{let e=await i.websites.list({page:parseInt(o.page,10),search:o.search});if(o.format==="json")f(e,"json");else {let n=e.result?.list??[];if(n.length>0){console.log(`
37
+ Websites:`),console.log("---------");for(let r of n)console.log(` ID: ${r.website_id}`),console.log(` Name: ${r.website_name??"N/A"}`),console.log(` Domain: ${r.domain??"N/A"}`),console.log(` Activated: ${r.activated??!1}`),console.log("");console.log(`Total: ${e.result?.total??n.length}`);}else l("No websites found");}}catch(e){L(e);}}),t.command("get").description("Get website details").requiredOption("-i, --id <id>","Website ID").option("-f, --format <format>","Output format (json, table)","table").action(async o=>{let i=E();try{let e=await i.websites.getDetails(o.id);f(e,o.format);}catch(e){L(e);}}),t.command("update").description("Update a website").requiredOption("-i, --id <id>","Website ID").option("-n, --name <name>","Business name").option("--activate","Activate the website").option("--deactivate","Deactivate the website").option("-f, --format <format>","Output format (json, table)","table").action(async o=>{let i=E();try{let e=await i.websites.update({website_id:o.id,business_name:o.name,activated:o.activate?!0:o.deactivate?!1:void 0});if(e.success)h("Website updated"),e.website&&f(e.website,o.format);else if(c("Failed to update website"),e.errors)for(let n of e.errors)c(` ${n}`);}catch(e){L(e);}}),t.command("settings").description("Update website settings").requiredOption("-i, --id <id>","Website ID").option("-n, --name <name>","Business name").option("-l, --language <lang>","Language").option("-d, --description <desc>","Business description").option("-f, --format <format>","Output format (json, table)","table").action(async o=>{let i=E();try{let e=await i.websites.updateSettings(o.id,{business_name:o.name,language:o.language,business_description:o.description});e.success&&h("Website settings updated"),f(e,o.format);}catch(e){L(e);}}),t.command("delete").description("Delete a website").requiredOption("-i, --id <id>","Website ID").action(async o=>{let i=E();try{let e=await i.websites.delete(o.id);if(e.success)h("Website deleted");else if(c("Failed to delete website"),e.errors)for(let n of e.errors)c(` ${n}`);}catch(e){L(e);}}),t.command("assign").description("Assign a website to a client").requiredOption("-w, --website <id>","Website ID").requiredOption("-c, --client <id>","Client ID").action(async o=>{let i=E();try{let e=await i.websites.assign({website_id:o.website,client_id:o.client});if(e.success)h("Website assigned to client");else if(c("Failed to assign website"),e.errors)for(let n of e.errors)c(` ${n}`);}catch(e){L(e);}}),t.command("domain-add").description("Add a custom domain to a website").requiredOption("-i, --id <id>","Website ID").requiredOption("-d, --domain <domain>","Custom domain").option("-f, --format <format>","Output format (json, table)","table").action(async o=>{let i=E();try{let e=await i.websites.addDomain(o.id,o.domain);if(e.success&&(h("Domain added"),e.result?.dns_records)){console.log(`
38
+ DNS Records to configure:`);for(let n of e.result.dns_records)console.log(` ${n.record_type} ${n.host} -> ${n.value}`);}f(e,o.format);}catch(e){L(e);}}),t.command("domain-remove").description("Remove a custom domain from a website").requiredOption("-i, --id <id>","Website ID").option("-f, --format <format>","Output format (json, table)","table").action(async o=>{let i=E();try{let e=await i.websites.removeDomain(o.id);e.success&&h("Domain removed"),f(e,o.format);}catch(e){L(e);}}),t.command("integration-add").description("Add an integration to a website").requiredOption("-i, --id <id>","Website ID").requiredOption("-t, --type <type>","Integration type (e.g., matomo)").requiredOption("-c, --config <json>","Integration config as JSON").option("-f, --format <format>","Output format (json, table)","table").action(async o=>{let i=E(),e;try{e=JSON.parse(o.config);}catch{c("Invalid JSON config"),process.exit(1);}try{let n=await i.websites.addIntegration(o.id,{integration_type:o.type,config:e});n.success&&h("Integration added"),f(n,o.format);}catch(n){L(n);}}),t.command("integration-remove").description("Remove an integration from a website").requiredOption("-i, --id <id>","Website ID").requiredOption("-t, --type <type>","Integration type").option("-f, --format <format>","Output format (json, table)","table").action(async o=>{let i=E();try{let e=await i.websites.removeIntegration(o.id,o.type);e.success&&h("Integration removed"),f(e,o.format);}catch(e){L(e);}}),t.command("team-add").description("Add a team member to a website").requiredOption("-i, --id <id>","Website ID").requiredOption("-e, --email <email>","Team member email").requiredOption("-r, --role <role>","Role (Editor or Commenter)").option("-f, --format <format>","Output format (json, table)","table").action(async o=>{let i=E();try{let e=await i.websites.addTeamMember(o.id,o.email,o.role);e.success&&h("Team member added"),f(e,o.format);}catch(e){L(e);}}),t.command("team-remove").description("Remove a team member from a website").requiredOption("-i, --id <id>","Website ID").requiredOption("-m, --member <memberId>","Member ID").option("-f, --format <format>","Output format (json, table)","table").action(async o=>{let i=E();try{let e=await i.websites.removeTeamMember(o.id,o.member);e.success&&h("Team member removed"),f(e,o.format);}catch(e){L(e);}}),t}function E(){T()||(c("API key not configured"),l("Run: lindo config set apiKey <your-api-key>"),l("Or set the LINDO_API_KEY environment variable"),process.exit(1));let t=$();return new LindoClient({apiKey:t.apiKey,baseUrl:t.baseUrl})}function L(t){t instanceof AuthenticationError&&(c("Authentication failed"),l("Your API key may be invalid or expired"),l("Run: lindo config set apiKey <your-api-key>"),process.exit(1)),t instanceof Error?c(t.message):c("An unexpected error occurred"),process.exit(1);}function J(t){return new Promise(o=>{let i=platform(),e;switch(i){case "darwin":e=`open "${t}"`;break;case "win32":e=`start "" "${t}"`;break;default:e=`xdg-open "${t}"`;break}exec(e,n=>{o(!n);});})}function po(t){let o=t.filter(e=>!!(e&&e.trim()));return o.length===0?"":`https://fonts.googleapis.com/css2?family=${o.map(e=>`${e.trim().replace(/ /g,"+")}:wght@300;400;700`).join("&family=")}&display=swap`}function pe(t){let o=[t.font,t.title_font].filter(Boolean);if(o.length===0)return "";let i=po(o);if(!i)return "";let e=t.font||t.title_font,n=t.title_font||t.font,r=`
39
39
  <style>
40
40
  /* Apply website fonts from theme */
41
41
  body, main, .prose {
@@ -46,12 +46,12 @@ DNS Records to configure:`);for(let n of e.result.dns_records)console.log(` ${n
46
46
  }
47
47
  </style>`;return `<link rel="preconnect" href="https://fonts.googleapis.com">
48
48
  <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
49
- <link href="${i}" rel="stylesheet">${r}`}function lt(o,t){let i=new RegExp(`<${t}\\b[^>]*>`,"gi"),e,n=null;for(;(e=i.exec(o))!==null;){let O=o.slice(0,e.index);if(po(O)){n=e;break}}if(!n||n.index===void 0)return {section:void 0,remainingHtml:o};let r=n.index,a=r+n[0].length,s=`</${t}>`,d=o.slice(a),p=new RegExp(`<${t}\\b`,"gi"),v=new RegExp(`</${t}>`,"gi"),b=[],m=[],y;for(;(y=p.exec(d))!==null;)b.push(y.index+a);for(;(y=v.exec(d))!==null;)m.push(y.index+a);let w=[...b.map(O=>({pos:O,type:"open"})),...m.map(O=>({pos:O,type:"close"}))].sort((O,M)=>O.pos-M.pos),f=1,g=-1;for(let O of w)if(O.type==="open")f++;else if(f--,f===0){g=O.pos+s.length;break}if(g===-1)return {section:void 0,remainingHtml:o};let k=o.slice(r,g),x=o.slice(0,r),C=o.slice(g),F=(x+C).replace(/\n\s*\n\s*\n/g,`
49
+ <link href="${i}" rel="stylesheet">${r}`}function lt(t,o){let i=new RegExp(`<${o}\\b[^>]*>`,"gi"),e,n=null;for(;(e=i.exec(t))!==null;){let O=t.slice(0,e.index);if(uo(O)){n=e;break}}if(!n||n.index===void 0)return {section:void 0,remainingHtml:t};let r=n.index,a=r+n[0].length,s=`</${o}>`,d=t.slice(a),p=new RegExp(`<${o}\\b`,"gi"),v=new RegExp(`</${o}>`,"gi"),b=[],m=[],w;for(;(w=p.exec(d))!==null;)b.push(w.index+a);for(;(w=v.exec(d))!==null;)m.push(w.index+a);let y=[...b.map(O=>({pos:O,type:"open"})),...m.map(O=>({pos:O,type:"close"}))].sort((O,M)=>O.pos-M.pos),u=1,g=-1;for(let O of y)if(O.type==="open")u++;else if(u--,u===0){g=O.pos+s.length;break}if(g===-1)return {section:void 0,remainingHtml:t};let k=t.slice(r,g),x=t.slice(0,r),C=t.slice(g),F=(x+C).replace(/\n\s*\n\s*\n/g,`
50
50
 
51
- `);return {section:k,remainingHtml:F}}function po(o){let t=["section","header","footer"],i=0;for(let e of t){let n=new RegExp(`<${e}\\b`,"gi"),r=new RegExp(`</${e}>`,"gi"),a=(o.match(n)||[]).length,s=(o.match(r)||[]).length;i+=a-s;}return i===0}function he(o){let t=lt(o,"header"),i=lt(t.remainingHtml,"footer");return {globalHeader:t.section,globalFooter:i.section,mainContent:i.remainingHtml.trim()}}function Ie(o,t,i){let e=[];return t&&t.trim()&&e.push(t.trim()),o.trim()&&e.push(o.trim()),i&&i.trim()&&e.push(i.trim()),e.join(`
52
- `)}function ne(o){return !(!o||o.startsWith("http://")||o.startsWith("https://")||o.startsWith("//")||o.startsWith("data:")||o.startsWith("blob:")||o.startsWith("#"))}function be(o){let t=o.toLowerCase().split(".").pop()||"",i=["jpg","jpeg","png","gif","webp","svg","ico","avif","bmp","tiff"],e=["mp4","webm","mov","avi","mkv","ogv"],n=["woff","woff2","ttf","otf","eot"];return i.includes(t)?"images":e.includes(t)?"videos":n.includes(t)?"fonts":"documents"}function re(o){let t=o.toLowerCase().split(".").pop()||"";return {jpg:"image/jpeg",jpeg:"image/jpeg",png:"image/png",gif:"image/gif",webp:"image/webp",svg:"image/svg+xml",ico:"image/x-icon",avif:"image/avif",bmp:"image/bmp",tiff:"image/tiff",mp4:"video/mp4",webm:"video/webm",mov:"video/quicktime",avi:"video/x-msvideo",mkv:"video/x-matroska",ogv:"video/ogg",pdf:"application/pdf",doc:"application/msword",docx:"application/vnd.openxmlformats-officedocument.wordprocessingml.document",woff:"font/woff",woff2:"font/woff2",ttf:"font/ttf",otf:"font/otf",eot:"application/vnd.ms-fontobject"}[t]||"application/octet-stream"}function fo(o,t){let i=Ee.load(o),e=[],n=new Set;return i("img[src]").each((r,a)=>{let s=i(a).attr("src");if(s&&ne(s)&&!n.has(s)){n.add(s);let d=A.resolve(t,s);S.existsSync(d)&&e.push({originalPath:s,absolutePath:d,fileName:A.basename(s),mediaType:be(s),contentType:re(s)});}}),i("img[srcset]").each((r,a)=>{let s=i(a).attr("srcset");if(s){let d=s.split(",").map(p=>p.trim().split(/\s+/)[0]);for(let p of d)if(p&&ne(p)&&!n.has(p)){n.add(p);let v=A.resolve(t,p);S.existsSync(v)&&e.push({originalPath:p,absolutePath:v,fileName:A.basename(p),mediaType:be(p),contentType:re(p)});}}}),i("source[src]").each((r,a)=>{let s=i(a).attr("src");if(s&&ne(s)&&!n.has(s)){n.add(s);let d=A.resolve(t,s);S.existsSync(d)&&e.push({originalPath:s,absolutePath:d,fileName:A.basename(s),mediaType:be(s),contentType:re(s)});}}),i("video[poster]").each((r,a)=>{let s=i(a).attr("poster");if(s&&ne(s)&&!n.has(s)){n.add(s);let d=A.resolve(t,s);S.existsSync(d)&&e.push({originalPath:s,absolutePath:d,fileName:A.basename(s),mediaType:"images",contentType:re(s)});}}),i('[style*="background"]').each((r,a)=>{let d=(i(a).attr("style")||"").match(/url\(['"]?([^'")\s]+)['"]?\)/);if(d&&d[1]){let p=d[1];if(ne(p)&&!n.has(p)){n.add(p);let v=A.resolve(t,p);S.existsSync(v)&&e.push({originalPath:p,absolutePath:v,fileName:A.basename(p),mediaType:be(p),contentType:re(p)});}}}),i('link[href][rel*="icon"]').each((r,a)=>{let s=i(a).attr("href");if(s&&ne(s)&&!n.has(s)){n.add(s);let d=A.resolve(t,s);S.existsSync(d)&&e.push({originalPath:s,absolutePath:d,fileName:A.basename(s),mediaType:"images",contentType:re(s)});}}),e}async function Le(o,t,i,e,n,r){let a=fo(o,t);if(a.length===0)return {html:o,uploadedCount:0,failedCount:0,urlMap:new Map,sourceFileUpdated:false};n?.(`Found ${a.length} local asset(s) to upload`);let s=new Map,d=0,p=0,v=10;for(let w=0;w<a.length;w+=v){let f=a.slice(w,w+v),g=f.map(k=>({file_base64:S.readFileSync(k.absolutePath).toString("base64"),file_name:k.fileName,media_type:k.mediaType,content_type:k.contentType}));try{if(g.length>1&&e.media.uploadBatch){let k=await e.media.uploadBatch(i,{files:g});for(let x=0;x<k.result.uploaded.length;x++){let C=k.result.uploaded[x],F=f[x];C.success?(s.set(F.originalPath,C.url),d++,n?.(`Uploaded: ${F.fileName} \u2192 ${C.url}`)):(p++,n?.(`Failed: ${F.fileName} - ${C.error}`));}}else for(let k=0;k<g.length;k++){let x=g[k],C=f[k];try{let F=await e.media.upload(i,x);s.set(C.originalPath,F.result.url),d++,n?.(`Uploaded: ${C.fileName} \u2192 ${F.result.url}`);}catch(F){p++,n?.(`Failed: ${C.fileName} - ${F instanceof Error?F.message:"Unknown error"}`);}}}catch{for(let x=0;x<g.length;x++){let C=g[x],F=f[x];try{let O=await e.media.upload(i,C);s.set(F.originalPath,O.result.url),d++,n?.(`Uploaded: ${F.fileName} \u2192 ${O.result.url}`);}catch(O){p++,n?.(`Failed: ${F.fileName} - ${O instanceof Error?O.message:"Unknown error"}`);}}}}let b=Ee.load(o);b("img[src]").each((w,f)=>{let g=b(f).attr("src");g&&s.has(g)&&b(f).attr("src",s.get(g));}),b("img[srcset]").each((w,f)=>{let g=b(f).attr("srcset");if(g){let k=g;for(let[x,C]of s)k=k.replace(new RegExp(Ae(x),"g"),C);b(f).attr("srcset",k);}}),b("source[src]").each((w,f)=>{let g=b(f).attr("src");g&&s.has(g)&&b(f).attr("src",s.get(g));}),b("video[poster]").each((w,f)=>{let g=b(f).attr("poster");g&&s.has(g)&&b(f).attr("poster",s.get(g));}),b('[style*="background"]').each((w,f)=>{let g=b(f).attr("style")||"";for(let[k,x]of s)g=g.replace(new RegExp(Ae(k),"g"),x);b(f).attr("style",g);}),b("link[href]").each((w,f)=>{let g=b(f).attr("href");g&&s.has(g)&&b(f).attr("href",s.get(g));});let m=b.html(),y=false;if(r&&d>0)try{let w=S.readFileSync(r,"utf-8"),f=w;for(let[g,k]of s)f=f.replace(new RegExp(Ae(g),"g"),k);f!==w&&(S.writeFileSync(r,f,"utf-8"),y=!0,n?.(`Updated source file with CDN URLs: ${r}`));}catch(w){n?.(`Warning: Could not update source file: ${w instanceof Error?w.message:"Unknown error"}`);}return {html:m,uploadedCount:d,failedCount:p,urlMap:s,sourceFileUpdated:y}}function Ae(o){return o.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}function je(o,t){let i,e=o.match(/<main[^>]*>([\s\S]*)<\/main>/i),n=o.match(/<body[^>]*>([\s\S]*)<\/body>/i);e?i=e[1].trim():n?i=n[1].trim():i=o;let r=he(i),a=r.mainContent,s=o.match(/<title>([^<]*)<\/title>/i),d=s?s[1].trim():t,p="",v="",b=o.match(/<!-- Page Custom Code \(Header\) -->\s*([\s\S]*?)\s*<!-- End Page Custom Code \(Header\) -->/i);b&&b[1].trim()&&(p=b[1].trim());let m=o.match(/<!-- Page Custom Code \(Footer\) -->\s*([\s\S]*?)\s*<!-- End Page Custom Code \(Footer\) -->/i);m&&m[1].trim()&&(v=m[1].trim());let y=o.match(/<html[^>]*class="([^"]*)"/i),w=y?y[1].includes("dark"):true,f=o.match(/<main[^>]*>/i),g="ltr",k="";if(f){let Z=f[0].match(/dir="([^"]*)"/i);Z&&(g=Z[1]);let Qe=f[0].match(/class="([^"]*)"/i);Qe&&(k=Qe[1]);}let x=!o.includes("motion@latest"),C=o.match(/<meta\s+name="description"\s+content="([^"]*)"/i),F=o.match(/<meta\s+property="og:title"\s+content="([^"]*)"/i),O=o.match(/<meta\s+property="og:description"\s+content="([^"]*)"/i),M=o.match(/<meta\s+property="og:image"\s+content="([^"]*)"/i),oe=o.match(/<link\s+rel="canonical"\s+href="([^"]*)"/i),ce=o.match(/noindex/i),Q=o.match(/nofollow/i),D={};d&&(D.page_title=d),C&&C[1]&&(D.meta_description=C[1]),F&&F[1]&&(D.social_title=F[1]),O&&O[1]&&(D.social_description=O[1]),M&&M[1]&&(D.social_image=M[1]),oe&&oe[1]&&(D.canonical_url=oe[1]),D.noindex=!!ce,D.nofollow=!!Q;let ye={theme:{mode:w?"Dark":"Light",direction:g,main_classes:k,animations_deactivated:x},should_convert:true},ie=p||v?{}:void 0;return ie&&(p&&(ie.header=p),v&&(ie.footer=v)),{html:a,globalHeader:r.globalHeader,globalFooter:r.globalFooter,templateName:d,headerCode:p||void 0,footerCode:v||void 0,settings:ye,seo:D,customCodes:ie}}var ee=A.join(Re.tmpdir(),"lindoai-pages-preview.pid"),ue=A.join(Re.tmpdir(),"lindoai-pages-preview.port");function We(){let o=new Command("pages").description("Page management operations");return o.command("list").description("List all pages for a website").requiredOption("-w, --website <id>","Website ID").option("-p, --page <page>","Page number","1").option("-s, --search <search>","Search term").option("-f, --format <format>","Output format (json, table)","table").action(async t=>{let i=Y();try{let e=await i.pages.list(t.website,{page:parseInt(t.page,10),search:t.search});if(t.format==="json")u(e,"json");else {let n=e.result;if(n?.list&&n.list.length>0){console.log(`
53
- Pages:`),console.log("------");for(let r of n.list)console.log(` ID: ${r.page_id}`),console.log(` Name: ${r.name??"N/A"}`),console.log(` Path: ${r.path??"N/A"}`),console.log(` Status: ${r.status??"N/A"}`),console.log(` Published: ${r.publish_date?"Yes":"No"}`),console.log("");console.log(`Total: ${n.total??n.list.length}`);}else l("No pages found");}}catch(e){z(e);}}),o.command("get").description("Get details of a specific page").requiredOption("-w, --website <id>","Website ID").requiredOption("-i, --id <id>","Page ID").option("-f, --format <format>","Output format (json, table)","table").action(async t=>{let i=Y();try{let e=await i.pages.get(t.website,t.id);if(t.format==="json")u(e,"json");else {let n=e.result;n?(console.log(`
54
- Page Details:`),console.log("-------------"),console.log(` ID: ${n.page_id}`),console.log(` Name: ${n.name??"N/A"}`),console.log(` Path: ${n.path??"N/A"}`),console.log(` Status: ${n.status??"N/A"}`),console.log(` Published: ${n.publish_date?"Yes":"No"}`),console.log(` Created: ${n.created_date??"N/A"}`)):c("Page not found");}}catch(e){z(e);}}),o.command("unpublish").description("Unpublish a page").requiredOption("-w, --website <id>","Website ID").requiredOption("-i, --id <id>","Page ID").option("-f, --format <format>","Output format (json, table)","table").action(async t=>{let i=Y();try{let e=await i.pages.unpublish(t.website,t.id);t.format==="json"?u(e,"json"):e.success?(h("Page unpublished successfully"),console.log(` Page ID: ${e.result?.page_id}`)):c("Failed to unpublish page");}catch(e){z(e);}}),o.command("delete").description("Delete a page").requiredOption("-w, --website <id>","Website ID").requiredOption("-i, --id <id>","Page ID").option("-f, --format <format>","Output format (json, table)","table").action(async t=>{let i=Y();try{let e=await i.pages.deletePage(t.website,t.id);if(t.format==="json")u(e,"json");else if(e.success){if(h("Page deleted successfully"),console.log(` Page ID: ${e.result?.page_id}`),e.result?.warnings&&e.result.warnings.length>0){console.log(" Warnings:");for(let n of e.result.warnings)console.log(` - ${n}`);}}else c("Failed to delete page");}catch(e){z(e);}}),o.command("create-empty").description("Create a new empty page with starter template and live preview").argument("<website_id>","Website ID").argument("<path>","URL path for the page (e.g., /about-us)").option("--title <title>","Page title","New Page").option("--file <path>","Output file path","./page.html").option("--background","Run preview server in background").action(async(t,i,e)=>{let n=Y();try{l("Fetching website details...");let a=(await n.websites.getDetails(t)).result,s=a?.theme||{},d=a?.global_header||null,p=a?.global_footer||null,v=a?.custom_codes||{header:null,footer:null},b={font:s.font,title_font:s.title_font},m=e.title,y=`<!-- Hero Section -->
51
+ `);return {section:k,remainingHtml:F}}function uo(t){let o=["section","header","footer"],i=0;for(let e of o){let n=new RegExp(`<${e}\\b`,"gi"),r=new RegExp(`</${e}>`,"gi"),a=(t.match(n)||[]).length,s=(t.match(r)||[]).length;i+=a-s;}return i===0}function he(t){let o,i,e=t,n=e.match(/<!-- ========== GLOBAL HEADER[^>]*-->\s*([\s\S]*?)\s*<!-- ========== END GLOBAL HEADER[^>]*-->/i);n&&(o=n[1].trim()||void 0,e=e.replace(n[0],"").trim());let r=e.match(/<!-- ========== GLOBAL FOOTER[^>]*-->\s*([\s\S]*?)\s*<!-- ========== END GLOBAL FOOTER[^>]*-->/i);r&&(i=r[1].trim()||void 0,e=e.replace(r[0],"").trim());let a=e.match(/<!-- ========== PAGE CONTENT[^>]*-->\s*([\s\S]*?)\s*<!-- ========== END PAGE CONTENT[^>]*-->/i);if(a&&(e=a[1].trim()),!n&&!r){let s=lt(e,"header");o=s.section;let d=lt(s.remainingHtml,"footer");i=d.section,e=d.remainingHtml.trim();}return {globalHeader:o,globalFooter:i,mainContent:e}}function Ie(t,o,i){let e=[];return o&&o.trim()&&(e.push("<!-- ========== GLOBAL HEADER (shared across all pages) ========== -->"),e.push(o.trim()),e.push("<!-- ========== END GLOBAL HEADER ========== -->"),e.push("")),e.push("<!-- ========== PAGE CONTENT (edit below) ========== -->"),t.trim()&&e.push(t.trim()),e.push("<!-- ========== END PAGE CONTENT ========== -->"),i&&i.trim()&&(e.push(""),e.push("<!-- ========== GLOBAL FOOTER (shared across all pages) ========== -->"),e.push(i.trim()),e.push("<!-- ========== END GLOBAL FOOTER ========== -->")),e.join(`
52
+ `)}function ne(t){return !(!t||t.startsWith("http://")||t.startsWith("https://")||t.startsWith("//")||t.startsWith("data:")||t.startsWith("blob:")||t.startsWith("#"))}function be(t){let o=t.toLowerCase().split(".").pop()||"",i=["jpg","jpeg","png","gif","webp","svg","ico","avif","bmp","tiff"],e=["mp4","webm","mov","avi","mkv","ogv"],n=["woff","woff2","ttf","otf","eot"];return i.includes(o)?"images":e.includes(o)?"videos":n.includes(o)?"fonts":"documents"}function re(t){let o=t.toLowerCase().split(".").pop()||"";return {jpg:"image/jpeg",jpeg:"image/jpeg",png:"image/png",gif:"image/gif",webp:"image/webp",svg:"image/svg+xml",ico:"image/x-icon",avif:"image/avif",bmp:"image/bmp",tiff:"image/tiff",mp4:"video/mp4",webm:"video/webm",mov:"video/quicktime",avi:"video/x-msvideo",mkv:"video/x-matroska",ogv:"video/ogg",pdf:"application/pdf",doc:"application/msword",docx:"application/vnd.openxmlformats-officedocument.wordprocessingml.document",woff:"font/woff",woff2:"font/woff2",ttf:"font/ttf",otf:"font/otf",eot:"application/vnd.ms-fontobject"}[o]||"application/octet-stream"}function fo(t,o){let i=Ee.load(t),e=[],n=new Set;return i("img[src]").each((r,a)=>{let s=i(a).attr("src");if(s&&ne(s)&&!n.has(s)){n.add(s);let d=A.resolve(o,s);S.existsSync(d)&&e.push({originalPath:s,absolutePath:d,fileName:A.basename(s),mediaType:be(s),contentType:re(s)});}}),i("img[srcset]").each((r,a)=>{let s=i(a).attr("srcset");if(s){let d=s.split(",").map(p=>p.trim().split(/\s+/)[0]);for(let p of d)if(p&&ne(p)&&!n.has(p)){n.add(p);let v=A.resolve(o,p);S.existsSync(v)&&e.push({originalPath:p,absolutePath:v,fileName:A.basename(p),mediaType:be(p),contentType:re(p)});}}}),i("source[src]").each((r,a)=>{let s=i(a).attr("src");if(s&&ne(s)&&!n.has(s)){n.add(s);let d=A.resolve(o,s);S.existsSync(d)&&e.push({originalPath:s,absolutePath:d,fileName:A.basename(s),mediaType:be(s),contentType:re(s)});}}),i("video[poster]").each((r,a)=>{let s=i(a).attr("poster");if(s&&ne(s)&&!n.has(s)){n.add(s);let d=A.resolve(o,s);S.existsSync(d)&&e.push({originalPath:s,absolutePath:d,fileName:A.basename(s),mediaType:"images",contentType:re(s)});}}),i('[style*="background"]').each((r,a)=>{let d=(i(a).attr("style")||"").match(/url\(['"]?([^'")\s]+)['"]?\)/);if(d&&d[1]){let p=d[1];if(ne(p)&&!n.has(p)){n.add(p);let v=A.resolve(o,p);S.existsSync(v)&&e.push({originalPath:p,absolutePath:v,fileName:A.basename(p),mediaType:be(p),contentType:re(p)});}}}),i('link[href][rel*="icon"]').each((r,a)=>{let s=i(a).attr("href");if(s&&ne(s)&&!n.has(s)){n.add(s);let d=A.resolve(o,s);S.existsSync(d)&&e.push({originalPath:s,absolutePath:d,fileName:A.basename(s),mediaType:"images",contentType:re(s)});}}),e}async function Le(t,o,i,e,n,r){let a=fo(t,o);if(a.length===0)return {html:t,uploadedCount:0,failedCount:0,urlMap:new Map,sourceFileUpdated:false};n?.(`Found ${a.length} local asset(s) to upload`);let s=new Map,d=0,p=0,v=10;for(let y=0;y<a.length;y+=v){let u=a.slice(y,y+v),g=u.map(k=>({file_base64:S.readFileSync(k.absolutePath).toString("base64"),file_name:k.fileName,media_type:k.mediaType,content_type:k.contentType}));try{if(g.length>1&&e.media.uploadBatch){let k=await e.media.uploadBatch(i,{files:g});for(let x=0;x<k.result.uploaded.length;x++){let C=k.result.uploaded[x],F=u[x];C.success?(s.set(F.originalPath,C.url),d++,n?.(`Uploaded: ${F.fileName} \u2192 ${C.url}`)):(p++,n?.(`Failed: ${F.fileName} - ${C.error}`));}}else for(let k=0;k<g.length;k++){let x=g[k],C=u[k];try{let F=await e.media.upload(i,x);s.set(C.originalPath,F.result.url),d++,n?.(`Uploaded: ${C.fileName} \u2192 ${F.result.url}`);}catch(F){p++,n?.(`Failed: ${C.fileName} - ${F instanceof Error?F.message:"Unknown error"}`);}}}catch{for(let x=0;x<g.length;x++){let C=g[x],F=u[x];try{let O=await e.media.upload(i,C);s.set(F.originalPath,O.result.url),d++,n?.(`Uploaded: ${F.fileName} \u2192 ${O.result.url}`);}catch(O){p++,n?.(`Failed: ${F.fileName} - ${O instanceof Error?O.message:"Unknown error"}`);}}}}let b=Ee.load(t);b("img[src]").each((y,u)=>{let g=b(u).attr("src");g&&s.has(g)&&b(u).attr("src",s.get(g));}),b("img[srcset]").each((y,u)=>{let g=b(u).attr("srcset");if(g){let k=g;for(let[x,C]of s)k=k.replace(new RegExp(Ae(x),"g"),C);b(u).attr("srcset",k);}}),b("source[src]").each((y,u)=>{let g=b(u).attr("src");g&&s.has(g)&&b(u).attr("src",s.get(g));}),b("video[poster]").each((y,u)=>{let g=b(u).attr("poster");g&&s.has(g)&&b(u).attr("poster",s.get(g));}),b('[style*="background"]').each((y,u)=>{let g=b(u).attr("style")||"";for(let[k,x]of s)g=g.replace(new RegExp(Ae(k),"g"),x);b(u).attr("style",g);}),b("link[href]").each((y,u)=>{let g=b(u).attr("href");g&&s.has(g)&&b(u).attr("href",s.get(g));});let m=b.html(),w=false;if(r&&d>0)try{let y=S.readFileSync(r,"utf-8"),u=y;for(let[g,k]of s)u=u.replace(new RegExp(Ae(g),"g"),k);u!==y&&(S.writeFileSync(r,u,"utf-8"),w=!0,n?.(`Updated source file with CDN URLs: ${r}`));}catch(y){n?.(`Warning: Could not update source file: ${y instanceof Error?y.message:"Unknown error"}`);}return {html:m,uploadedCount:d,failedCount:p,urlMap:s,sourceFileUpdated:w}}function Ae(t){return t.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}function je(t,o){let i,e=t.match(/<main[^>]*>([\s\S]*)<\/main>/i),n=t.match(/<body[^>]*>([\s\S]*)<\/body>/i);e?i=e[1].trim():n?i=n[1].trim():i=t;let r=he(i),a=r.mainContent,s=t.match(/<title>([^<]*)<\/title>/i),d=s?s[1].trim():o,p="",v="",b=t.match(/<!-- Page Custom Code \(Header\) -->\s*([\s\S]*?)\s*<!-- End Page Custom Code \(Header\) -->/i);b&&b[1].trim()&&(p=b[1].trim());let m=t.match(/<!-- Page Custom Code \(Footer\) -->\s*([\s\S]*?)\s*<!-- End Page Custom Code \(Footer\) -->/i);m&&m[1].trim()&&(v=m[1].trim());let w=t.match(/<html[^>]*class="([^"]*)"/i),y=w?w[1].includes("dark"):true,u=t.match(/<main[^>]*>/i),g="ltr",k="";if(u){let Z=u[0].match(/dir="([^"]*)"/i);Z&&(g=Z[1]);let Qe=u[0].match(/class="([^"]*)"/i);Qe&&(k=Qe[1]);}let x=!t.includes("motion@latest"),C=t.match(/<meta\s+name="description"\s+content="([^"]*)"/i),F=t.match(/<meta\s+property="og:title"\s+content="([^"]*)"/i),O=t.match(/<meta\s+property="og:description"\s+content="([^"]*)"/i),M=t.match(/<meta\s+property="og:image"\s+content="([^"]*)"/i),oe=t.match(/<link\s+rel="canonical"\s+href="([^"]*)"/i),ce=t.match(/noindex/i),Q=t.match(/nofollow/i),R={};d&&(R.page_title=d),C&&C[1]&&(R.meta_description=C[1]),F&&F[1]&&(R.social_title=F[1]),O&&O[1]&&(R.social_description=O[1]),M&&M[1]&&(R.social_image=M[1]),oe&&oe[1]&&(R.canonical_url=oe[1]),R.noindex=!!ce,R.nofollow=!!Q;let we={theme:{mode:y?"Dark":"Light",direction:g,main_classes:k,animations_deactivated:x},should_convert:true},ie=p||v?{}:void 0;return ie&&(p&&(ie.header=p),v&&(ie.footer=v)),{html:a,globalHeader:r.globalHeader,globalFooter:r.globalFooter,templateName:d,headerCode:p||void 0,footerCode:v||void 0,settings:we,seo:R,customCodes:ie}}var ee=A.join(De.tmpdir(),"lindoai-pages-preview.pid"),fe=A.join(De.tmpdir(),"lindoai-pages-preview.port");function We(){let t=new Command("pages").description("Page management operations");return t.command("list").description("List all pages for a website").requiredOption("-w, --website <id>","Website ID").option("-p, --page <page>","Page number","1").option("-s, --search <search>","Search term").option("-f, --format <format>","Output format (json, table)","table").action(async o=>{let i=Y();try{let e=await i.pages.list(o.website,{page:parseInt(o.page,10),search:o.search});if(o.format==="json")f(e,"json");else {let n=e.result;if(n?.list&&n.list.length>0){console.log(`
53
+ Pages:`),console.log("------");for(let r of n.list)console.log(` ID: ${r.page_id}`),console.log(` Name: ${r.name??"N/A"}`),console.log(` Path: ${r.path??"N/A"}`),console.log(` Status: ${r.status??"N/A"}`),console.log(` Published: ${r.publish_date?"Yes":"No"}`),console.log("");console.log(`Total: ${n.total??n.list.length}`);}else l("No pages found");}}catch(e){z(e);}}),t.command("get").description("Get details of a specific page").requiredOption("-w, --website <id>","Website ID").requiredOption("-i, --id <id>","Page ID").option("-f, --format <format>","Output format (json, table)","table").action(async o=>{let i=Y();try{let e=await i.pages.get(o.website,o.id);if(o.format==="json")f(e,"json");else {let n=e.result;n?(console.log(`
54
+ Page Details:`),console.log("-------------"),console.log(` ID: ${n.page_id}`),console.log(` Name: ${n.name??"N/A"}`),console.log(` Path: ${n.path??"N/A"}`),console.log(` Status: ${n.status??"N/A"}`),console.log(` Published: ${n.publish_date?"Yes":"No"}`),console.log(` Created: ${n.created_date??"N/A"}`)):c("Page not found");}}catch(e){z(e);}}),t.command("unpublish").description("Unpublish a page").requiredOption("-w, --website <id>","Website ID").requiredOption("-i, --id <id>","Page ID").option("-f, --format <format>","Output format (json, table)","table").action(async o=>{let i=Y();try{let e=await i.pages.unpublish(o.website,o.id);o.format==="json"?f(e,"json"):e.success?(h("Page unpublished successfully"),console.log(` Page ID: ${e.result?.page_id}`)):c("Failed to unpublish page");}catch(e){z(e);}}),t.command("delete").description("Delete a page").requiredOption("-w, --website <id>","Website ID").requiredOption("-i, --id <id>","Page ID").option("-f, --format <format>","Output format (json, table)","table").action(async o=>{let i=Y();try{let e=await i.pages.deletePage(o.website,o.id);if(o.format==="json")f(e,"json");else if(e.success){if(h("Page deleted successfully"),console.log(` Page ID: ${e.result?.page_id}`),e.result?.warnings&&e.result.warnings.length>0){console.log(" Warnings:");for(let n of e.result.warnings)console.log(` - ${n}`);}}else c("Failed to delete page");}catch(e){z(e);}}),t.command("create-empty").description("Create a new empty page with starter template and live preview").argument("<website_id>","Website ID").argument("<path>","URL path for the page (e.g., /about-us)").option("--title <title>","Page title","New Page").option("--file <path>","Output file path (relative to current directory)","./page.html").option("--no-background","Run preview server in foreground (blocks terminal)").action(async(o,i,e)=>{let n=Y();try{l("Fetching website details...");let a=(await n.websites.getDetails(o)).result,s=a?.theme||{},d=a?.global_header||null,p=a?.global_footer||null;mt(a);let v=a?.custom_codes||{header:null,footer:null},b={font:s.font,title_font:s.title_font},m=e.title,w=`<!-- Hero Section -->
55
55
  <section class="relative min-h-[80vh] flex items-center justify-center bg-gradient-to-br from-neutral-50 to-neutral-100 dark:from-neutral-900 dark:to-neutral-800">
56
56
  <div class="max-w-4xl mx-auto px-4 sm:px-6 lg:px-8 text-center">
57
57
  <h1 class="text-4xl sm:text-5xl lg:text-6xl font-bold text-neutral-900 dark:text-white mb-6">
@@ -127,7 +127,7 @@ Page Details:`),console.log("-------------"),console.log(` ID: ${n.page_id}`),c
127
127
  Contact Us
128
128
  </a>
129
129
  </div>
130
- </section>`,f={theme:{mode:s.mode?.toLowerCase()==="dark"?"Dark":"Light",direction:"ltr",main_classes:"bg-white dark:bg-neutral-900 text-neutral-900 dark:text-neutral-100",animations_deactivated:!1},should_convert:!0},g={page_title:m,meta_description:"",social_title:m,social_description:"",noindex:!1,nofollow:!1};l("Creating page...");let k=await n.pages.create(t,{html:y,path:i,settings:f,template_name:m,seo:g});k.success||(c("Failed to create page"),process.exit(1));let x=k.result.page_id,C=k.result.published_url;h(`Page created: ${x}`),C&&console.log(` Published URL: ${C}`);let F=pe(b),O=Ie(y,d??void 0,p??void 0),M={header:v.header||"",footer:v.footer||""},ce=`<!DOCTYPE html>
130
+ </section>`,u={theme:{mode:s.mode?.toLowerCase()==="dark"?"Dark":"Light",direction:"ltr",main_classes:"bg-white dark:bg-neutral-900 text-neutral-900 dark:text-neutral-100",animations_deactivated:!1},should_convert:!0},g={page_title:m,meta_description:"",social_title:m,social_description:"",noindex:!1,nofollow:!1};l("Creating page...");let k=await n.pages.create(o,{html:w,path:i,settings:u,template_name:m,seo:g});k.success||(c("Failed to create page"),process.exit(1));let x=k.result.page_id,C=k.result.published_url;h(`Page created: ${x}`),C&&console.log(` Published URL: ${C}`);let F=pe(b),O=Ie(w,d??void 0,p??void 0),M={header:v.header||"",footer:v.footer||""},ce=`<!DOCTYPE html>
131
131
  <html class="${s.mode?.toLowerCase()==="dark"?"dark":""}" lang="en">
132
132
  <head>
133
133
  <meta charset="UTF-8">
@@ -179,26 +179,26 @@ ${O}
179
179
  ${M.footer}
180
180
  <!-- End Page Custom Code (Footer) -->
181
181
  </body>
182
- </html>`,Q=A.resolve(e.file);S.writeFileSync(Q,ce,"utf-8"),h(`HTML saved to ${Q}`),await mt(),e.background?await pt(Q):await ft(Q),console.log(""),l(`To save changes: lindoai pages update ${t} ${x} --html-file ${e.file}`);}catch(r){z(r);}}),o.command("edit").description("Edit a page with live preview").argument("<website_id>","Website ID").argument("<page_id>","Page ID").option("--file <path>","Output file path","./page.html").option("--background","Run preview server in background").action(async(t,i,e)=>{let n=Y();try{l("Fetching page HTML...");let r=await n.pages.getHtml(t,i);r.result||(c("Page not found"),process.exit(1));let a=r.result.html;a||(c("Page has no HTML content"),l("Make sure the page has been created with HTML content"),process.exit(1)),l("Fetching website details...");let d=(await n.websites.getDetails(t)).result,p=d?.theme||{},v=d?.global_header||null,b=d?.global_footer||null,m=d?.custom_codes||{header:null,footer:null},y=r.result.name||"Page",w=r.result.seo||{},f=r.result.settings||{},g=r.result.custom_codes||{},k={header:g.header||m.header||"",footer:g.footer||m.footer||""},x=f.theme||{},C=x.mode!=="Light",F=x.direction||"ltr",O=x.main_classes||"",M=x.animations_deactivated||!1,oe={font:x.font||p.font,title_font:x.title_font||p.title_font},ce=pe(oe),D=he(a).mainContent,ye=Ie(D,v??void 0,b??void 0),ie=`<!DOCTYPE html>
182
+ </html>`,Q=A.resolve(e.file);S.writeFileSync(Q,ce,"utf-8"),h(`HTML saved to ${Q}`),await pt(),e.background?await ut(Q):await ft(Q),console.log(""),l(`File: ${e.file}`),l(`To publish changes: lindoai pages update ${o} ${x} --html-file ${e.file}`),l("To stop the server: lindoai pages stop-preview");}catch(r){z(r);}}),t.command("edit").description("Edit a page with live preview").argument("<website_id>","Website ID").argument("<page_id>","Page ID").option("--file <path>","Output file path (relative to current directory)","./page.html").option("--no-background","Run preview server in foreground (blocks terminal)").action(async(o,i,e)=>{let n=Y();try{l("Fetching page HTML...");let r=await n.pages.getHtml(o,i);r.result||(c("Page not found"),process.exit(1));let a=r.result.html;a||(c("Page has no HTML content"),l("Make sure the page has been created with HTML content"),process.exit(1)),l("Fetching website details...");let d=(await n.websites.getDetails(o)).result,p=d?.theme||{},v=d?.global_header||null,b=d?.global_footer||null;mt(d);let m=d?.custom_codes||{header:null,footer:null},w=r.result.name||"Page",y=r.result.seo||{},u=r.result.settings||{},g=r.result.custom_codes||{},k={header:g.header||m.header||"",footer:g.footer||m.footer||""},x=u.theme||{},C=x.mode!=="Light",F=x.direction||"ltr",O=x.main_classes||"",M=x.animations_deactivated||!1,oe={font:x.font||p.font,title_font:x.title_font||p.title_font},ce=pe(oe),R=he(a).mainContent,we=Ie(R,v??void 0,b??void 0),ie=`<!DOCTYPE html>
183
183
  <html class="${C?"dark":""}" lang="en">
184
184
  <head>
185
185
  <meta charset="UTF-8">
186
- <meta name="robots" content="max-snippet:-1, max-image-preview:large, max-video-preview:-1 ${w.noindex?"noindex":""} ${w.nofollow?"nofollow":""}">
186
+ <meta name="robots" content="max-snippet:-1, max-image-preview:large, max-video-preview:-1 ${y.noindex?"noindex":""} ${y.nofollow?"nofollow":""}">
187
187
  <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
188
188
 
189
- <title>${w.page_title||y}</title>
190
- <meta name="description" content="${w.meta_description||""}">
189
+ <title>${y.page_title||w}</title>
190
+ <meta name="description" content="${y.meta_description||""}">
191
191
 
192
- <meta property="og:title" content="${w.social_title||w.page_title||y}">
193
- <meta property="og:description" content="${w.social_description||w.meta_description||""}">
194
- ${w.social_image?`<meta property="og:image" content="${w.social_image}">`:""}
192
+ <meta property="og:title" content="${y.social_title||y.page_title||w}">
193
+ <meta property="og:description" content="${y.social_description||y.meta_description||""}">
194
+ ${y.social_image?`<meta property="og:image" content="${y.social_image}">`:""}
195
195
  <meta property="og:type" content="website">
196
- ${w.canonical_url?`<meta property="og:url" content="${w.canonical_url}">`:""}
196
+ ${y.canonical_url?`<meta property="og:url" content="${y.canonical_url}">`:""}
197
197
 
198
198
  <meta name="twitter:card" content="summary_large_image">
199
- <meta name="twitter:title" content="${w.social_title||w.page_title||y}">
200
- <meta name="twitter:description" content="${w.social_description||w.meta_description||""}">
201
- ${w.social_image?`<meta name="twitter:image" content="${w.social_image}">`:""}
199
+ <meta name="twitter:title" content="${y.social_title||y.page_title||w}">
200
+ <meta name="twitter:description" content="${y.social_description||y.meta_description||""}">
201
+ ${y.social_image?`<meta name="twitter:image" content="${y.social_image}">`:""}
202
202
 
203
203
  <!-- Google Fonts -->
204
204
  ${ce}
@@ -215,7 +215,7 @@ ${O}
215
215
  <script src="https://lnui.pages.dev/motion-animate.js"></script>
216
216
  `}
217
217
 
218
- ${w.canonical_url?`<link rel="canonical" href="${w.canonical_url}">`:""}
218
+ ${y.canonical_url?`<link rel="canonical" href="${y.canonical_url}">`:""}
219
219
 
220
220
  <!-- Page Custom Code (Header) -->
221
221
  ${k.header}
@@ -226,7 +226,7 @@ ${O}
226
226
  <!-- ========== MAIN CONTENT ========== -->
227
227
  <main dir="${F}" lindo-main-content id="content" role="main" class="${O}">
228
228
 
229
- ${ye}
229
+ ${we}
230
230
 
231
231
  </main>
232
232
  <!-- ========== END MAIN CONTENT ========== -->
@@ -238,10 +238,10 @@ ${ye}
238
238
  ${k.footer}
239
239
  <!-- End Page Custom Code (Footer) -->
240
240
  </body>
241
- </html>`,Z=A.resolve(e.file);S.writeFileSync(Z,ie,"utf-8"),h(`HTML saved to ${Z}`),await mt(),e.background?await pt(Z):await ft(Z);}catch(r){z(r);}}),o.command("update").description("Update a page from HTML file (note: global header/footer changes are page-specific only)").argument("<website_id>","Website ID").argument("<page_id>","Page ID").option("--html-file <path>","Path to local HTML file to upload").option("--upload-assets","Upload local images/assets to CDN before publishing").option("-f, --format <format>","Output format (json, table)","table").action(async(t,i,e)=>{let n=Y();try{e.htmlFile||(c("--html-file option is required"),l("Usage: lindoai pages update <website_id> <page_id> --html-file <path>"),process.exit(1));let r=A.resolve(e.htmlFile);S.existsSync(r)||(c(`File not found: ${r}`),process.exit(1));let a=S.readFileSync(r,"utf-8");if(l(`Read ${a.length} bytes from ${r}`),e.uploadAssets){let m=A.dirname(r);l("Processing local assets...");let y=await Le(a,m,t,n,w=>l(w),r);y.uploadedCount>0&&(a=y.html,h(`Uploaded ${y.uploadedCount} asset(s) to CDN`),y.failedCount>0&&l(`Warning: ${y.failedCount} asset(s) failed to upload`),y.sourceFileUpdated&&l("Source file updated with CDN URLs (prevents duplicate uploads)"));}let s=je(a);s.globalHeader&&l("Detected global header section"),s.globalFooter&&l("Detected global footer section"),s.templateName&&l(`Extracted page title: ${s.templateName}`),s.headerCode&&l("Extracted header custom code"),s.footerCode&&l("Extracted footer custom code"),Object.keys(s.seo).length>2&&l("Extracted SEO metadata");let d=await n.pages.get(t,i);d.result||(c("Page not found"),process.exit(1));let p=d.result.path,v={...d.result.settings||{},theme:{...d.result.settings?.theme||{},...s.settings.theme},should_convert:!0};l("Updating page...");let b=await n.pages.publish(t,i,{html:s.html,path:p,settings:v,template_name:s.templateName,custom_codes:s.customCodes,seo:Object.keys(s.seo).length>0?s.seo:void 0,global_header:s.globalHeader,global_footer:s.globalFooter});e.format==="json"?u(b,"json"):b.success?(h("Page updated successfully"),console.log(` Page ID: ${b.result?.page_id}`),b.result?.published_url&&console.log(` Published URL: ${b.result.published_url}`)):c("Failed to update page");}catch(r){z(r);}}),o.command("stop-preview").description("Stop the background preview server").action(async()=>{try{if(!S.existsSync(ee)){l("No preview server is running");return}let t=parseInt(S.readFileSync(ee,"utf-8").trim(),10);if(isNaN(t)){c("Invalid PID file"),Me();return}try{process.kill(t,"SIGTERM"),h(`Preview server (PID ${t}) stopped`);}catch(i){i.code==="ESRCH"?l("Preview server process not found (may have already stopped)"):c(`Failed to stop preview server: ${i.message}`);}Me();}catch(t){t instanceof Error?c(t.message):c("An unexpected error occurred"),process.exit(1);}}),o.command("create-with-content").description("Create pages from HTML files in a local folder with automatic asset upload").argument("<website_id>","Website ID").argument("<folder>","Path to folder containing HTML files").option("--path-prefix <prefix>","URL path prefix for pages (e.g., /blog)","").option("--dry-run","Show what would be created without actually creating").option("-f, --format <format>","Output format (json, table)","table").action(async(t,i,e)=>{let n=Y();try{let r=A.resolve(i);S.existsSync(r)||(c(`Folder not found: ${r}`),process.exit(1)),S.statSync(r).isDirectory()||(c(`Not a directory: ${r}`),process.exit(1));let d=S.readdirSync(r).filter(m=>m.endsWith(".html"));if(d.length===0&&(c("No HTML files found in folder"),process.exit(1)),l(`Found ${d.length} HTML file(s) to create`),e.dryRun){console.log(`
242
- Dry run - would create:`);for(let m of d){let y=m==="index.html"?e.pathPrefix||"/":`${e.pathPrefix}/${m.replace(".html","")}`;console.log(` ${m} \u2192 ${y}`);}return}let p=[];for(let m of d){let y=A.join(r,m),w=S.readFileSync(y,"utf-8");l(`
243
- Processing: ${m}`),l("Uploading local assets...");let f=await Le(w,r,t,n,x=>l(` ${x}`));f.uploadedCount>0&&(w=f.html,h(` Uploaded ${f.uploadedCount} asset(s)`));let g=je(w,m.replace(".html",""));g.globalHeader&&l(" Detected global header section"),g.globalFooter&&l(" Detected global footer section"),g.templateName&&l(` Extracted page title: ${g.templateName}`),g.headerCode&&l(" Extracted header custom code"),g.footerCode&&l(" Extracted footer custom code"),Object.keys(g.seo).length>2&&l(" Extracted SEO metadata");let k=m==="index.html"?e.pathPrefix||"/":`${e.pathPrefix}/${m.replace(".html","")}`;try{l(` Creating page at ${k}...`);let x=await n.pages.create(t,{html:g.html,path:k,template_name:g.templateName,seo:Object.keys(g.seo).length>0?g.seo:void 0,settings:g.settings,custom_codes:g.customCodes,global_header:g.globalHeader,global_footer:g.globalFooter});if(x.success){let C=x.result.published_url;h(` Created: ${m} \u2192 ${k} (${x.result.page_id})`),C&&console.log(` URL: ${C}`),p.push({file:m,pageId:x.result.page_id,success:!0});}else c(` Failed to create: ${m}`),p.push({file:m,success:!1,error:"API returned failure"});}catch(x){let C=x instanceof Error?x.message:"Unknown error";c(` Failed to create: ${m} - ${C}`),p.push({file:m,success:!1,error:C});}}console.log(`
244
- --- Summary ---`);let v=p.filter(m=>m.success).length,b=p.filter(m=>!m.success).length;if(e.format==="json")u({results:p,successCount:v,failCount:b},"json");else if(console.log(`Created: ${v}/${p.length} pages`),b>0){console.log(`Failed: ${b} pages`);for(let m of p.filter(y=>!y.success))console.log(` - ${m.file}: ${m.error}`);}}catch(r){z(r);}}),o}function Y(){T()||(c("API key not configured"),l("Run: lindo config set apiKey <your-api-key>"),l("Or set the LINDO_API_KEY environment variable"),process.exit(1));let o=$();return new LindoClient({apiKey:o.apiKey,baseUrl:o.baseUrl})}function z(o){o instanceof AuthenticationError&&(c("Authentication failed"),l("Your API key may be invalid or expired"),l("Run: lindo config set apiKey <your-api-key>"),process.exit(1)),o instanceof Error?c(o.message):c("An unexpected error occurred"),process.exit(1);}function Me(){try{S.existsSync(ee)&&S.unlinkSync(ee);}catch{}try{S.existsSync(ue)&&S.unlinkSync(ue);}catch{}}async function mt(){if(S.existsSync(ee)){try{let o=parseInt(S.readFileSync(ee,"utf-8").trim(),10);if(!isNaN(o))try{process.kill(o,"SIGTERM"),l(`Terminated existing preview server (PID ${o})`),await new Promise(t=>setTimeout(t,500));}catch{}}catch{}Me();}}async function pt(o){let t=A.resolve(o),i=`
241
+ </html>`,Z=A.resolve(e.file);S.writeFileSync(Z,ie,"utf-8"),h(`HTML saved to ${Z}`),await pt(),e.background?(await ut(Z),console.log(""),l(`File: ${e.file}`),l(`To publish changes: lindoai pages update ${o} ${i} --html-file ${e.file}`),l("To stop the server: lindoai pages stop-preview")):await ft(Z);}catch(r){z(r);}}),t.command("update").description("Update a page from HTML file (note: global header/footer changes are page-specific only)").argument("<website_id>","Website ID").argument("<page_id>","Page ID").option("--html-file <path>","Path to local HTML file to upload").option("--upload-assets","Upload local images/assets to CDN before publishing").option("-f, --format <format>","Output format (json, table)","table").action(async(o,i,e)=>{let n=Y();try{e.htmlFile||(c("--html-file option is required"),l("Usage: lindoai pages update <website_id> <page_id> --html-file <path>"),process.exit(1));let r=A.resolve(e.htmlFile);S.existsSync(r)||(c(`File not found: ${r}`),process.exit(1));let a=S.readFileSync(r,"utf-8");if(l(`Read ${a.length} bytes from ${r}`),e.uploadAssets){let m=A.dirname(r);l("Processing local assets...");let w=await Le(a,m,o,n,y=>l(y),r);w.uploadedCount>0&&(a=w.html,h(`Uploaded ${w.uploadedCount} asset(s) to CDN`),w.failedCount>0&&l(`Warning: ${w.failedCount} asset(s) failed to upload`),w.sourceFileUpdated&&l("Source file updated with CDN URLs (prevents duplicate uploads)"));}let s=je(a);s.globalHeader&&l("Detected global header section"),s.globalFooter&&l("Detected global footer section"),s.templateName&&l(`Extracted page title: ${s.templateName}`),s.headerCode&&l("Extracted header custom code"),s.footerCode&&l("Extracted footer custom code"),Object.keys(s.seo).length>2&&l("Extracted SEO metadata");let d=await n.pages.get(o,i);d.result||(c("Page not found"),process.exit(1));let p=d.result.path,v={...d.result.settings||{},theme:{...d.result.settings?.theme||{},...s.settings.theme},should_convert:!0};l("Updating page...");let b=await n.pages.publish(o,i,{html:s.html,path:p,settings:v,template_name:s.templateName,custom_codes:s.customCodes,seo:Object.keys(s.seo).length>0?s.seo:void 0,global_header:s.globalHeader,global_footer:s.globalFooter});e.format==="json"?f(b,"json"):b.success?(h("Page updated successfully"),console.log(` Page ID: ${b.result?.page_id}`),b.result?.published_url&&console.log(` Published URL: ${b.result.published_url}`)):c("Failed to update page");}catch(r){z(r);}}),t.command("stop-preview").description("Stop the background preview server").action(async()=>{try{if(!S.existsSync(ee)){l("No preview server is running");return}let o=parseInt(S.readFileSync(ee,"utf-8").trim(),10);if(isNaN(o)){c("Invalid PID file"),Me();return}try{process.kill(o,"SIGTERM"),h(`Preview server (PID ${o}) stopped`);}catch(i){i.code==="ESRCH"?l("Preview server process not found (may have already stopped)"):c(`Failed to stop preview server: ${i.message}`);}Me();}catch(o){o instanceof Error?c(o.message):c("An unexpected error occurred"),process.exit(1);}}),t.command("create-with-content").description("Create pages from HTML files in a local folder with automatic asset upload").argument("<website_id>","Website ID").argument("<folder>","Path to folder containing HTML files").option("--path-prefix <prefix>","URL path prefix for pages (e.g., /blog)","").option("--dry-run","Show what would be created without actually creating").option("-f, --format <format>","Output format (json, table)","table").action(async(o,i,e)=>{let n=Y();try{let r=A.resolve(i);S.existsSync(r)||(c(`Folder not found: ${r}`),process.exit(1)),S.statSync(r).isDirectory()||(c(`Not a directory: ${r}`),process.exit(1));let d=S.readdirSync(r).filter(m=>m.endsWith(".html"));if(d.length===0&&(c("No HTML files found in folder"),process.exit(1)),l(`Found ${d.length} HTML file(s) to create`),e.dryRun){console.log(`
242
+ Dry run - would create:`);for(let m of d){let w=m==="index.html"?e.pathPrefix||"/":`${e.pathPrefix}/${m.replace(".html","")}`;console.log(` ${m} \u2192 ${w}`);}return}let p=[];for(let m of d){let w=A.join(r,m),y=S.readFileSync(w,"utf-8");l(`
243
+ Processing: ${m}`),l("Uploading local assets...");let u=await Le(y,r,o,n,x=>l(` ${x}`));u.uploadedCount>0&&(y=u.html,h(` Uploaded ${u.uploadedCount} asset(s)`));let g=je(y,m.replace(".html",""));g.globalHeader&&l(" Detected global header section"),g.globalFooter&&l(" Detected global footer section"),g.templateName&&l(` Extracted page title: ${g.templateName}`),g.headerCode&&l(" Extracted header custom code"),g.footerCode&&l(" Extracted footer custom code"),Object.keys(g.seo).length>2&&l(" Extracted SEO metadata");let k=m==="index.html"?e.pathPrefix||"/":`${e.pathPrefix}/${m.replace(".html","")}`;try{l(` Creating page at ${k}...`);let x=await n.pages.create(o,{html:g.html,path:k,template_name:g.templateName,seo:Object.keys(g.seo).length>0?g.seo:void 0,settings:g.settings,custom_codes:g.customCodes,global_header:g.globalHeader,global_footer:g.globalFooter});if(x.success){let C=x.result.published_url;h(` Created: ${m} \u2192 ${k} (${x.result.page_id})`),C&&console.log(` URL: ${C}`),p.push({file:m,pageId:x.result.page_id,success:!0});}else c(` Failed to create: ${m}`),p.push({file:m,success:!1,error:"API returned failure"});}catch(x){let C=x instanceof Error?x.message:"Unknown error";c(` Failed to create: ${m} - ${C}`),p.push({file:m,success:!1,error:C});}}console.log(`
244
+ --- Summary ---`);let v=p.filter(m=>m.success).length,b=p.filter(m=>!m.success).length;if(e.format==="json")f({results:p,successCount:v,failCount:b},"json");else if(console.log(`Created: ${v}/${p.length} pages`),b>0){console.log(`Failed: ${b} pages`);for(let m of p.filter(w=>!w.success))console.log(` - ${m.file}: ${m.error}`);}}catch(r){z(r);}}),t}function mt(t){console.log(""),console.log("--- Website Context ---"),t?.business_name&&console.log(`Business: ${t.business_name}`),t?.business_description&&console.log(`Description: ${t.business_description}`),t?.theme_md&&console.log(`Design: ${t.theme_md}`),t?.language&&console.log(`Language: ${t.language}`),console.log("---"),console.log("");}function Y(){T()||(c("API key not configured"),l("Run: lindo config set apiKey <your-api-key>"),l("Or set the LINDO_API_KEY environment variable"),process.exit(1));let t=$();return new LindoClient({apiKey:t.apiKey,baseUrl:t.baseUrl})}function z(t){t instanceof AuthenticationError&&(c("Authentication failed"),l("Your API key may be invalid or expired"),l("Run: lindo config set apiKey <your-api-key>"),process.exit(1)),t instanceof Error?c(t.message):c("An unexpected error occurred"),process.exit(1);}function Me(){try{S.existsSync(ee)&&S.unlinkSync(ee);}catch{}try{S.existsSync(fe)&&S.unlinkSync(fe);}catch{}}async function pt(){if(S.existsSync(ee)){try{let t=parseInt(S.readFileSync(ee,"utf-8").trim(),10);if(!isNaN(t))try{process.kill(t,"SIGTERM"),l(`Terminated existing preview server (PID ${t})`),await new Promise(o=>setTimeout(o,500));}catch{}}catch{}Me();}}async function ut(t){let o=A.resolve(t),i=`
245
245
  const http = require('node:http');
246
246
  const fs = require('node:fs');
247
247
  const path = require('node:path');
@@ -261,7 +261,7 @@ Processing: ${m}`),l("Uploading local assets...");let f=await Le(w,r,t,n,x=>l(`
261
261
  })();
262
262
  </script>\`;
263
263
 
264
- const filePath = ${JSON.stringify(t)};
264
+ const filePath = ${JSON.stringify(o)};
265
265
  const pidFile = path.join(os.tmpdir(), 'lindoai-pages-preview.pid');
266
266
  const portFile = path.join(os.tmpdir(), 'lindoai-pages-preview.port');
267
267
  const sseClients = new Set();
@@ -361,9 +361,9 @@ Processing: ${m}`),l("Uploading local assets...");let f=await Le(w,r,t,n,x=>l(`
361
361
  });
362
362
  } catch {}
363
363
  });
364
- `,e=spawn(process.execPath,["-e",i],{detached:true,stdio:"ignore"});e.unref();let n=null;for(let s=0;s<50;s++)if(await new Promise(d=>setTimeout(d,100)),S.existsSync(ue))try{if(n=parseInt(S.readFileSync(ue,"utf-8").trim(),10),!isNaN(n))break}catch{}n||(c("Failed to start preview server"),process.exit(1));let r=`http://127.0.0.1:${n}/`;await J(r)||l(`Could not open browser. Visit: ${r}`),h("Preview server started in background"),console.log(` URL: ${r}`),console.log(` PID: ${e.pid}`),console.log(""),l("To update the page: lindoai pages update <website_id> <page_id> --html-file <path>"),l("To stop the server: lindoai pages stop-preview");}async function ft(o){let{startLivePreviewServer:t}=await Promise.resolve().then(()=>(Ue(),Ne));l("Starting preview server...");let i=await t(o),e=`http://127.0.0.1:${i}/`;S.writeFileSync(ee,process.pid.toString(),"utf-8"),S.writeFileSync(ue,i.toString(),"utf-8"),await J(e)||l(`Could not open browser. Visit: ${e}`),h("Preview server started"),console.log(` URL: ${e}`),console.log(""),l("Press Ctrl+C to stop the server"),l("Edit the HTML file and save to see changes in the browser");}var te=A.join(Re.tmpdir(),"lindoai-blogs-preview.pid"),ge=A.join(Re.tmpdir(),"lindoai-blogs-preview.port");function Ke(){let o=new Command("blogs").description("Blog management operations");return o.command("list").description("List all blogs for a website").requiredOption("-w, --website <id>","Website ID").option("-p, --page <page>","Page number","1").option("-s, --search <search>","Search term").option("-f, --format <format>","Output format (json, table)","table").action(async t=>{let i=V();try{let e=await i.blogs.list(t.website,{page:parseInt(t.page,10),search:t.search});if(t.format==="json")u(e,"json");else {let n=e.result;if(n?.list&&n.list.length>0){console.log(`
365
- Blogs:`),console.log("------");for(let r of n.list)console.log(` ID: ${r.blog_id}`),console.log(` Name: ${r.name??"N/A"}`),console.log(` Path: ${r.path??"N/A"}`),console.log(` Status: ${r.status??"N/A"}`),console.log(` Published: ${r.publish_date?new Date(r.publish_date*1e3).toISOString():"No"}`),console.log("");console.log(`Total: ${n.total??n.list.length}`);}else l("No blogs found");}}catch(e){X(e);}}),o.command("get").description("Get details of a specific blog").requiredOption("-w, --website <id>","Website ID").requiredOption("-i, --id <id>","Blog ID").option("-f, --format <format>","Output format (json, table)","table").action(async t=>{let i=V();try{let e=await i.blogs.get(t.website,t.id);if(t.format==="json")u(e,"json");else {let n=e.result;n?(console.log(`
366
- Blog Details:`),console.log("-------------"),console.log(` ID: ${n.blog_id}`),console.log(` Name: ${n.name??"N/A"}`),console.log(` Path: ${n.path??"N/A"}`),console.log(` Status: ${n.status??"N/A"}`),console.log(` Published: ${n.publish_date?new Date(n.publish_date*1e3).toISOString():"No"}`),console.log(` Created: ${n.created_date??"N/A"}`)):c("Blog not found");}}catch(e){X(e);}}),o.command("publish").description("Publish a blog").requiredOption("-w, --website <id>","Website ID").requiredOption("-i, --id <id>","Blog ID").option("-f, --format <format>","Output format (json, table)","table").action(async t=>{let i=V();try{let e=await i.blogs.publish(t.website,t.id);t.format==="json"?u(e,"json"):e.success?(h("Blog published successfully"),console.log(` Blog ID: ${e.result?.blog_id}`),console.log(` Published at: ${e.result?.publish_date?new Date(e.result.publish_date*1e3).toISOString():"N/A"}`),e.result?.published_url&&console.log(` Published URL: ${e.result.published_url}`)):c("Failed to publish blog");}catch(e){X(e);}}),o.command("unpublish").description("Unpublish a blog").requiredOption("-w, --website <id>","Website ID").requiredOption("-i, --id <id>","Blog ID").option("-f, --format <format>","Output format (json, table)","table").action(async t=>{let i=V();try{let e=await i.blogs.unpublish(t.website,t.id);t.format==="json"?u(e,"json"):e.success?(h("Blog unpublished successfully"),console.log(` Blog ID: ${e.result?.blog_id}`)):c("Failed to unpublish blog");}catch(e){X(e);}}),o.command("delete").description("Delete a blog").requiredOption("-w, --website <id>","Website ID").requiredOption("-i, --id <id>","Blog ID").option("-f, --format <format>","Output format (json, table)","table").action(async t=>{let i=V();try{let e=await i.blogs.delete(t.website,t.id);if(t.format==="json")u(e,"json");else if(e.success){if(h("Blog deleted successfully"),console.log(` Blog ID: ${e.result?.blog_id}`),e.result?.warnings&&e.result.warnings.length>0){console.log(" Warnings:");for(let n of e.result.warnings)console.log(` - ${n}`);}}else c("Failed to delete blog");}catch(e){X(e);}}),o.command("edit").description("Edit a blog with live preview").argument("<website_id>","Website ID").argument("<blog_id>","Blog ID").option("--file <path>","Output file path","./blog.html").option("--background","Run preview server in background").action(async(t,i,e)=>{let n=V();try{l("Fetching blog content...");let r=await n.blogs.getHtml(t,i);r.result||(c("Blog not found"),process.exit(1));let a=r.result,s=await n.websites.getDetails(t);s.result||(c("Website not found"),process.exit(1));let d=s.result,p=d,v=p?.theme||{},b=p?.custom_codes||{header:null,footer:null},m={font:v.font,title_font:v.title_font},y=a.seo||{},w=a.blog_settings||{},f=a.blog_content||"<p>Start writing your blog content here...</p>",g=Fo({seo:y,blogSettings:w,blogContent:f,websiteName:d.business_name||"Blog",blogPath:v.blog_path||"blog",websiteTheme:m,customCodes:{header:b.header||void 0,footer:b.footer||void 0}}),k=A.resolve(e.file);S.writeFileSync(k,g,"utf-8"),h(`HTML saved to ${k}`),await _o(),e.background?await So(k):await Oo(k),console.log(""),l(`To save changes: lindoai blogs update ${t} ${i} --html-file ${e.file}`);}catch(r){X(r);}}),o.command("update").description(`Update and publish a blog post.
364
+ `,e=spawn(process.execPath,["-e",i],{detached:true,stdio:"ignore"});e.unref();let n=null;for(let s=0;s<50;s++)if(await new Promise(d=>setTimeout(d,100)),S.existsSync(fe))try{if(n=parseInt(S.readFileSync(fe,"utf-8").trim(),10),!isNaN(n))break}catch{}n||(c("Failed to start preview server"),process.exit(1));let r=`http://127.0.0.1:${n}/`;await J(r)||l(`Could not open browser. Visit: ${r}`),h("Preview server started in background"),console.log(` URL: ${r}`),console.log(` PID: ${e.pid}`),console.log(""),l("To stop the server: lindoai pages stop-preview");}async function ft(t){let{startLivePreviewServer:o}=await Promise.resolve().then(()=>(Ue(),Ne));l("Starting preview server...");let i=await o(t),e=`http://127.0.0.1:${i}/`;S.writeFileSync(ee,process.pid.toString(),"utf-8"),S.writeFileSync(fe,i.toString(),"utf-8"),await J(e)||l(`Could not open browser. Visit: ${e}`),h("Preview server started"),console.log(` URL: ${e}`),console.log(""),l("Press Ctrl+C to stop the server"),l("Edit the HTML file and save to see changes in the browser");}var te=A.join(De.tmpdir(),"lindoai-blogs-preview.pid"),ge=A.join(De.tmpdir(),"lindoai-blogs-preview.port");function Ke(){let t=new Command("blogs").description("Blog management operations");return t.command("list").description("List all blogs for a website").requiredOption("-w, --website <id>","Website ID").option("-p, --page <page>","Page number","1").option("-s, --search <search>","Search term").option("-f, --format <format>","Output format (json, table)","table").action(async o=>{let i=V();try{let e=await i.blogs.list(o.website,{page:parseInt(o.page,10),search:o.search});if(o.format==="json")f(e,"json");else {let n=e.result;if(n?.list&&n.list.length>0){console.log(`
365
+ Blogs:`),console.log("------");for(let r of n.list)console.log(` ID: ${r.blog_id}`),console.log(` Name: ${r.name??"N/A"}`),console.log(` Path: ${r.path??"N/A"}`),console.log(` Status: ${r.status??"N/A"}`),console.log(` Published: ${r.publish_date?new Date(r.publish_date*1e3).toISOString():"No"}`),console.log("");console.log(`Total: ${n.total??n.list.length}`);}else l("No blogs found");}}catch(e){X(e);}}),t.command("get").description("Get details of a specific blog").requiredOption("-w, --website <id>","Website ID").requiredOption("-i, --id <id>","Blog ID").option("-f, --format <format>","Output format (json, table)","table").action(async o=>{let i=V();try{let e=await i.blogs.get(o.website,o.id);if(o.format==="json")f(e,"json");else {let n=e.result;n?(console.log(`
366
+ Blog Details:`),console.log("-------------"),console.log(` ID: ${n.blog_id}`),console.log(` Name: ${n.name??"N/A"}`),console.log(` Path: ${n.path??"N/A"}`),console.log(` Status: ${n.status??"N/A"}`),console.log(` Published: ${n.publish_date?new Date(n.publish_date*1e3).toISOString():"No"}`),console.log(` Created: ${n.created_date??"N/A"}`)):c("Blog not found");}}catch(e){X(e);}}),t.command("publish").description("Publish a blog").requiredOption("-w, --website <id>","Website ID").requiredOption("-i, --id <id>","Blog ID").option("-f, --format <format>","Output format (json, table)","table").action(async o=>{let i=V();try{let e=await i.blogs.publish(o.website,o.id);o.format==="json"?f(e,"json"):e.success?(h("Blog published successfully"),console.log(` Blog ID: ${e.result?.blog_id}`),console.log(` Published at: ${e.result?.publish_date?new Date(e.result.publish_date*1e3).toISOString():"N/A"}`),e.result?.published_url&&console.log(` Published URL: ${e.result.published_url}`)):c("Failed to publish blog");}catch(e){X(e);}}),t.command("unpublish").description("Unpublish a blog").requiredOption("-w, --website <id>","Website ID").requiredOption("-i, --id <id>","Blog ID").option("-f, --format <format>","Output format (json, table)","table").action(async o=>{let i=V();try{let e=await i.blogs.unpublish(o.website,o.id);o.format==="json"?f(e,"json"):e.success?(h("Blog unpublished successfully"),console.log(` Blog ID: ${e.result?.blog_id}`)):c("Failed to unpublish blog");}catch(e){X(e);}}),t.command("delete").description("Delete a blog").requiredOption("-w, --website <id>","Website ID").requiredOption("-i, --id <id>","Blog ID").option("-f, --format <format>","Output format (json, table)","table").action(async o=>{let i=V();try{let e=await i.blogs.delete(o.website,o.id);if(o.format==="json")f(e,"json");else if(e.success){if(h("Blog deleted successfully"),console.log(` Blog ID: ${e.result?.blog_id}`),e.result?.warnings&&e.result.warnings.length>0){console.log(" Warnings:");for(let n of e.result.warnings)console.log(` - ${n}`);}}else c("Failed to delete blog");}catch(e){X(e);}}),t.command("edit").description("Edit a blog with live preview").argument("<website_id>","Website ID").argument("<blog_id>","Blog ID").option("--file <path>","Output file path","./blog.html").option("--background","Run preview server in background").action(async(o,i,e)=>{let n=V();try{l("Fetching blog content...");let r=await n.blogs.getHtml(o,i);r.result||(c("Blog not found"),process.exit(1));let a=r.result,s=await n.websites.getDetails(o);s.result||(c("Website not found"),process.exit(1));let d=s.result,p=d,v=p?.theme||{},b=p?.custom_codes||{header:null,footer:null},m={font:v.font,title_font:v.title_font},w=a.seo||{},y=a.blog_settings||{},u=a.blog_content||"<p>Start writing your blog content here...</p>",g=To({seo:w,blogSettings:y,blogContent:u,websiteName:d.business_name||"Blog",blogPath:v.blog_path||"blog",websiteTheme:m,customCodes:{header:b.header||void 0,footer:b.footer||void 0}}),k=A.resolve(e.file);S.writeFileSync(k,g,"utf-8"),h(`HTML saved to ${k}`),await So(),e.background?await Oo(k):await $o(k),console.log(""),l(`To save changes: lindoai blogs update ${o} ${i} --html-file ${e.file}`);}catch(r){X(r);}}),t.command("update").description(`Update and publish a blog post.
367
367
 
368
368
  Content can be provided as Markdown (--md-file) or raw HTML (--html-file).
369
369
  Markdown files support frontmatter for metadata, but CLI flags always take priority.
@@ -393,7 +393,7 @@ Markdown frontmatter format:
393
393
  category: Tech
394
394
  date: January 15, 2025
395
395
  ---
396
- Your markdown content here...`).argument("<website_id>","Website ID").argument("<blog_id>","Blog ID").option("--md-file <path>","Path to Markdown file (converted to HTML before publishing)").option("--html-file <path>","Path to HTML file (used as blog_content directly)").option("--title <title>","Blog title (SEO page_title) [required]").option("--description <text>","Meta description for SEO").option("--excerpt <text>","Blog excerpt/summary shown in blog listings [required]").option("--social-image <url>","Social image URL for og:image/twitter:image (full URL) [required]").option("--author <name>","Author name [required]").option("--category <name>","Blog category [required]").option("--date <date>",'Publish date (e.g. "January 15, 2025")').option("--read-time <time>",'Read time (e.g. "5 min read")').option("-f, --format <format>","Output format (json, table)","table").action(async(t,i,e)=>{let n=V();try{!e.mdFile&&!e.htmlFile&&(c("Either --md-file or --html-file is required"),l("Usage: lindoai blogs update <website_id> <blog_id> --md-file <path> [options]"),process.exit(1));let r,a={},s={};if(e.mdFile){let f=A.resolve(e.mdFile);S.existsSync(f)||(c(`File not found: ${f}`),process.exit(1));let g=S.readFileSync(f,"utf-8");l(`Read ${g.length} bytes from ${f}`);let{content:k,frontmatter:x}=ut(g);r=gt(k),x.title&&(a.page_title=x.title),x.description&&(a.meta_description=x.description),x.image&&(a.social_image=x.image),x.author&&(s.author=x.author),x.excerpt&&(s.excerpt=x.excerpt),x.category&&(s.category=x.category),x.date&&(s.publish_date=x.date);}else {let f=A.resolve(e.htmlFile);S.existsSync(f)||(c(`File not found: ${f}`),process.exit(1)),r=S.readFileSync(f,"utf-8"),l(`Read ${r.length} bytes from ${f}`);}e.title&&(a.page_title=e.title),e.description&&(a.meta_description=e.description),e.socialImage&&(a.social_image=e.socialImage),e.author&&(s.author=e.author),e.excerpt&&(s.excerpt=e.excerpt),e.category&&(s.category=e.category),e.date&&(s.publish_date=e.date),e.readTime&&(s.read_time=e.readTime);let d=await n.blogs.get(t,i);d.result||(c("Blog not found"),process.exit(1));let p=d.result,v=p.path,b={page_title:a.page_title||p.seo?.page_title,meta_description:a.meta_description||p.seo?.meta_description,social_title:a.page_title||p.seo?.social_title,social_description:a.meta_description||p.seo?.social_description,social_image:a.social_image||p.seo?.social_image},m={author:s.author||p.blog_settings?.author,excerpt:s.excerpt||p.blog_settings?.excerpt,category:s.category||p.blog_settings?.category,publish_date:s.publish_date||p.blog_settings?.publish_date,read_time:s.read_time||p.blog_settings?.read_time,author_image:s.author_image||p.blog_settings?.author_image},y=[];b.page_title||y.push("--title"),b.social_image||y.push("--social-image"),m.author||y.push("--author"),m.excerpt||y.push("--excerpt"),m.category||y.push("--category"),y.length>0&&(c(`Missing required fields: ${y.join(", ")}`),l("These can be set via CLI flags or Markdown frontmatter."),l("If the blog already has these values, they will be preserved."),process.exit(1)),l("Updating blog...");let w=await n.blogs.publish(t,i,{path:v,blog_content:r,seo:b,blog_settings:m});e.format==="json"?u(w,"json"):w.success?(h("Blog updated successfully"),console.log(` Blog ID: ${w.result?.blog_id}`),w.result?.published_url&&console.log(` Published URL: ${w.result.published_url}`)):c("Failed to update blog");}catch(r){X(r);}}),o.command("create").description(`Create and publish a new blog post.
396
+ Your markdown content here...`).argument("<website_id>","Website ID").argument("<blog_id>","Blog ID").option("--md-file <path>","Path to Markdown file (converted to HTML before publishing)").option("--html-file <path>","Path to HTML file (used as blog_content directly)").option("--title <title>","Blog title (SEO page_title) [required]").option("--description <text>","Meta description for SEO").option("--excerpt <text>","Blog excerpt/summary shown in blog listings [required]").option("--social-image <url>","Social image URL for og:image/twitter:image (full URL) [required]").option("--author <name>","Author name [required]").option("--category <name>","Blog category [required]").option("--date <date>",'Publish date (e.g. "January 15, 2025")').option("--read-time <time>",'Read time (e.g. "5 min read")').option("-f, --format <format>","Output format (json, table)","table").action(async(o,i,e)=>{let n=V();try{!e.mdFile&&!e.htmlFile&&(c("Either --md-file or --html-file is required"),l("Usage: lindoai blogs update <website_id> <blog_id> --md-file <path> [options]"),process.exit(1));let r,a={},s={};if(e.mdFile){let u=A.resolve(e.mdFile);S.existsSync(u)||(c(`File not found: ${u}`),process.exit(1));let g=S.readFileSync(u,"utf-8");l(`Read ${g.length} bytes from ${u}`);let{content:k,frontmatter:x}=gt(g);r=ht(k),x.title&&(a.page_title=x.title),x.description&&(a.meta_description=x.description),x.image&&(a.social_image=x.image),x.author&&(s.author=x.author),x.excerpt&&(s.excerpt=x.excerpt),x.category&&(s.category=x.category),x.date&&(s.publish_date=x.date);}else {let u=A.resolve(e.htmlFile);S.existsSync(u)||(c(`File not found: ${u}`),process.exit(1)),r=S.readFileSync(u,"utf-8"),l(`Read ${r.length} bytes from ${u}`);}e.title&&(a.page_title=e.title),e.description&&(a.meta_description=e.description),e.socialImage&&(a.social_image=e.socialImage),e.author&&(s.author=e.author),e.excerpt&&(s.excerpt=e.excerpt),e.category&&(s.category=e.category),e.date&&(s.publish_date=e.date),e.readTime&&(s.read_time=e.readTime);let d=await n.blogs.get(o,i);d.result||(c("Blog not found"),process.exit(1));let p=d.result,v=p.path,b={page_title:a.page_title||p.seo?.page_title,meta_description:a.meta_description||p.seo?.meta_description,social_title:a.page_title||p.seo?.social_title,social_description:a.meta_description||p.seo?.social_description,social_image:a.social_image||p.seo?.social_image},m={author:s.author||p.blog_settings?.author,excerpt:s.excerpt||p.blog_settings?.excerpt,category:s.category||p.blog_settings?.category,publish_date:s.publish_date||p.blog_settings?.publish_date,read_time:s.read_time||p.blog_settings?.read_time,author_image:s.author_image||p.blog_settings?.author_image},w=[];b.page_title||w.push("--title"),b.social_image||w.push("--social-image"),m.author||w.push("--author"),m.excerpt||w.push("--excerpt"),m.category||w.push("--category"),w.length>0&&(c(`Missing required fields: ${w.join(", ")}`),l("These can be set via CLI flags or Markdown frontmatter."),l("If the blog already has these values, they will be preserved."),process.exit(1)),l("Updating blog...");let y=await n.blogs.publish(o,i,{path:v,blog_content:r,seo:b,blog_settings:m});e.format==="json"?f(y,"json"):y.success?(h("Blog updated successfully"),console.log(` Blog ID: ${y.result?.blog_id}`),y.result?.published_url&&console.log(` Published URL: ${y.result.published_url}`)):c("Failed to update blog");}catch(r){X(r);}}),t.command("create").description(`Create and publish a new blog post.
397
397
 
398
398
  Content can be provided as Markdown (--md-file) or raw HTML (--html-file).
399
399
  Markdown is converted to HTML before publishing. Frontmatter is supported for metadata.
@@ -425,7 +425,7 @@ Markdown frontmatter format:
425
425
  category: Tech
426
426
  date: January 15, 2025
427
427
  ---
428
- Your markdown content here...`).argument("<website_id>","Website ID").argument("<path>","URL path for the blog (e.g., /blog/my-first-post)").option("--md-file <path>","Path to Markdown file (converted to HTML before publishing)").option("--html-file <path>","Path to HTML file (used as blog_content directly)").option("--title <title>","Blog title (SEO page_title) [required]").option("--description <text>","Meta description for SEO").option("--excerpt <text>","Blog excerpt/summary shown in blog listings [required]").option("--social-image <url>","Social image URL for og:image/twitter:image (full URL) [required]").option("--author <name>","Author name [required]").option("--category <name>","Blog category [required]").option("--date <date>",'Publish date (e.g. "January 15, 2025")').option("--read-time <time>",'Read time (e.g. "5 min read")').option("-f, --format <format>","Output format (json, table)","table").action(async(t,i,e)=>{let n=V();try{!e.mdFile&&!e.htmlFile&&(c("Either --md-file or --html-file is required"),l("Usage: lindoai blogs create <website_id> <path> --md-file <path> [options]"),process.exit(1));let r,a={},s={};if(e.mdFile){let m=A.resolve(e.mdFile);S.existsSync(m)||(c(`File not found: ${m}`),process.exit(1));let y=S.readFileSync(m,"utf-8");l(`Read ${y.length} bytes from ${m}`);let{content:w,frontmatter:f}=ut(y);r=gt(w),f.title&&(a.page_title=f.title),f.description&&(a.meta_description=f.description),f.image&&(a.social_image=f.image),f.author&&(s.author=f.author),f.excerpt&&(s.excerpt=f.excerpt),f.category&&(s.category=f.category),f.date&&(s.publish_date=f.date);}else {let m=A.resolve(e.htmlFile);S.existsSync(m)||(c(`File not found: ${m}`),process.exit(1)),r=S.readFileSync(m,"utf-8"),l(`Read ${r.length} bytes from ${m}`);}e.title&&(a.page_title=e.title),e.description&&(a.meta_description=e.description),e.socialImage&&(a.social_image=e.socialImage),e.author&&(s.author=e.author),e.excerpt&&(s.excerpt=e.excerpt),e.category&&(s.category=e.category),e.date&&(s.publish_date=e.date),e.readTime&&(s.read_time=e.readTime),s.publish_date||(s.publish_date=new Date().toLocaleDateString("en-US",{year:"numeric",month:"long",day:"numeric"}));let d=[];a.page_title||d.push("--title"),a.social_image||d.push("--social-image"),s.author||d.push("--author"),s.excerpt||d.push("--excerpt"),s.category||d.push("--category"),d.length>0&&(c(`Missing required fields: ${d.join(", ")}`),l("Set these via CLI flags or Markdown frontmatter."),process.exit(1));let p={page_title:a.page_title,meta_description:a.meta_description||a.page_title,social_title:a.page_title,social_description:a.meta_description||a.page_title,social_image:a.social_image},v={author:s.author,excerpt:s.excerpt,category:s.category,publish_date:s.publish_date,read_time:s.read_time};l("Creating blog...");let b=await n.blogs.create(t,{path:i,blog_content:r,seo:p,blog_settings:v});e.format==="json"?u(b,"json"):b.success?(h("Blog created successfully"),console.log(` Blog ID: ${b.result?.blog_id}`),b.result?.published_url&&console.log(` Published URL: ${b.result.published_url}`)):c("Failed to create blog");}catch(r){X(r);}}),o.command("stop-preview").description("Stop the background preview server").action(async()=>{try{if(!S.existsSync(te)){l("No preview server is running");return}let t=parseInt(S.readFileSync(te,"utf-8").trim(),10);if(isNaN(t)){c("Invalid PID file"),Be();return}try{process.kill(t,"SIGTERM"),h(`Preview server (PID ${t}) stopped`);}catch(i){i.code==="ESRCH"?l("Preview server process not found (may have already stopped)"):c(`Failed to stop preview server: ${i.message}`);}Be();}catch(t){t instanceof Error?c(t.message):c("An unexpected error occurred"),process.exit(1);}}),o}function V(){T()||(c("API key not configured"),l("Run: lindo config set apiKey <your-api-key>"),l("Or set the LINDO_API_KEY environment variable"),process.exit(1));let o=$();return new LindoClient({apiKey:o.apiKey,baseUrl:o.baseUrl})}function X(o){o instanceof AuthenticationError&&(c("Authentication failed"),l("Your API key may be invalid or expired"),l("Run: lindo config set apiKey <your-api-key>"),process.exit(1)),o instanceof Error?c(o.message):c("An unexpected error occurred"),process.exit(1);}function Be(){try{S.existsSync(te)&&S.unlinkSync(te);}catch{}try{S.existsSync(ge)&&S.unlinkSync(ge);}catch{}}async function _o(){if(S.existsSync(te)){try{let o=parseInt(S.readFileSync(te,"utf-8").trim(),10);if(!isNaN(o))try{process.kill(o,"SIGTERM"),l(`Terminated existing preview server (PID ${o})`),await new Promise(t=>setTimeout(t,500));}catch{}}catch{}Be();}}async function So(o){let t=A.resolve(o),i=`
428
+ Your markdown content here...`).argument("<website_id>","Website ID").argument("<path>","URL path for the blog (e.g., /blog/my-first-post)").option("--md-file <path>","Path to Markdown file (converted to HTML before publishing)").option("--html-file <path>","Path to HTML file (used as blog_content directly)").option("--title <title>","Blog title (SEO page_title) [required]").option("--description <text>","Meta description for SEO").option("--excerpt <text>","Blog excerpt/summary shown in blog listings [required]").option("--social-image <url>","Social image URL for og:image/twitter:image (full URL) [required]").option("--author <name>","Author name [required]").option("--category <name>","Blog category [required]").option("--date <date>",'Publish date (e.g. "January 15, 2025")').option("--read-time <time>",'Read time (e.g. "5 min read")').option("-f, --format <format>","Output format (json, table)","table").action(async(o,i,e)=>{let n=V();try{!e.mdFile&&!e.htmlFile&&(c("Either --md-file or --html-file is required"),l("Usage: lindoai blogs create <website_id> <path> --md-file <path> [options]"),process.exit(1));let r,a={},s={};if(e.mdFile){let m=A.resolve(e.mdFile);S.existsSync(m)||(c(`File not found: ${m}`),process.exit(1));let w=S.readFileSync(m,"utf-8");l(`Read ${w.length} bytes from ${m}`);let{content:y,frontmatter:u}=gt(w);r=ht(y),u.title&&(a.page_title=u.title),u.description&&(a.meta_description=u.description),u.image&&(a.social_image=u.image),u.author&&(s.author=u.author),u.excerpt&&(s.excerpt=u.excerpt),u.category&&(s.category=u.category),u.date&&(s.publish_date=u.date);}else {let m=A.resolve(e.htmlFile);S.existsSync(m)||(c(`File not found: ${m}`),process.exit(1)),r=S.readFileSync(m,"utf-8"),l(`Read ${r.length} bytes from ${m}`);}e.title&&(a.page_title=e.title),e.description&&(a.meta_description=e.description),e.socialImage&&(a.social_image=e.socialImage),e.author&&(s.author=e.author),e.excerpt&&(s.excerpt=e.excerpt),e.category&&(s.category=e.category),e.date&&(s.publish_date=e.date),e.readTime&&(s.read_time=e.readTime),s.publish_date||(s.publish_date=new Date().toLocaleDateString("en-US",{year:"numeric",month:"long",day:"numeric"}));let d=[];a.page_title||d.push("--title"),a.social_image||d.push("--social-image"),s.author||d.push("--author"),s.excerpt||d.push("--excerpt"),s.category||d.push("--category"),d.length>0&&(c(`Missing required fields: ${d.join(", ")}`),l("Set these via CLI flags or Markdown frontmatter."),process.exit(1));let p={page_title:a.page_title,meta_description:a.meta_description||a.page_title,social_title:a.page_title,social_description:a.meta_description||a.page_title,social_image:a.social_image},v={author:s.author,excerpt:s.excerpt,category:s.category,publish_date:s.publish_date,read_time:s.read_time};l("Creating blog...");let b=await n.blogs.create(o,{path:i,blog_content:r,seo:p,blog_settings:v});e.format==="json"?f(b,"json"):b.success?(h("Blog created successfully"),console.log(` Blog ID: ${b.result?.blog_id}`),b.result?.published_url&&console.log(` Published URL: ${b.result.published_url}`)):c("Failed to create blog");}catch(r){X(r);}}),t.command("stop-preview").description("Stop the background preview server").action(async()=>{try{if(!S.existsSync(te)){l("No preview server is running");return}let o=parseInt(S.readFileSync(te,"utf-8").trim(),10);if(isNaN(o)){c("Invalid PID file"),Be();return}try{process.kill(o,"SIGTERM"),h(`Preview server (PID ${o}) stopped`);}catch(i){i.code==="ESRCH"?l("Preview server process not found (may have already stopped)"):c(`Failed to stop preview server: ${i.message}`);}Be();}catch(o){o instanceof Error?c(o.message):c("An unexpected error occurred"),process.exit(1);}}),t}function V(){T()||(c("API key not configured"),l("Run: lindo config set apiKey <your-api-key>"),l("Or set the LINDO_API_KEY environment variable"),process.exit(1));let t=$();return new LindoClient({apiKey:t.apiKey,baseUrl:t.baseUrl})}function X(t){t instanceof AuthenticationError&&(c("Authentication failed"),l("Your API key may be invalid or expired"),l("Run: lindo config set apiKey <your-api-key>"),process.exit(1)),t instanceof Error?c(t.message):c("An unexpected error occurred"),process.exit(1);}function Be(){try{S.existsSync(te)&&S.unlinkSync(te);}catch{}try{S.existsSync(ge)&&S.unlinkSync(ge);}catch{}}async function So(){if(S.existsSync(te)){try{let t=parseInt(S.readFileSync(te,"utf-8").trim(),10);if(!isNaN(t))try{process.kill(t,"SIGTERM"),l(`Terminated existing preview server (PID ${t})`),await new Promise(o=>setTimeout(o,500));}catch{}}catch{}Be();}}async function Oo(t){let o=A.resolve(t),i=`
429
429
  const http = require('node:http');
430
430
  const fs = require('node:fs');
431
431
  const path = require('node:path');
@@ -445,7 +445,7 @@ Markdown frontmatter format:
445
445
  })();
446
446
  </script>\`;
447
447
 
448
- const filePath = ${JSON.stringify(t)};
448
+ const filePath = ${JSON.stringify(o)};
449
449
  const pidFile = path.join(os.tmpdir(), 'lindoai-blogs-preview.pid');
450
450
  const portFile = path.join(os.tmpdir(), 'lindoai-blogs-preview.port');
451
451
  const sseClients = new Set();
@@ -545,24 +545,24 @@ Markdown frontmatter format:
545
545
  });
546
546
  } catch {}
547
547
  });
548
- `,e=spawn(process.execPath,["-e",i],{detached:true,stdio:"ignore"});e.unref();let n=null;for(let s=0;s<50;s++)if(await new Promise(d=>setTimeout(d,100)),S.existsSync(ge))try{if(n=parseInt(S.readFileSync(ge,"utf-8").trim(),10),!isNaN(n))break}catch{}n||(c("Failed to start preview server"),process.exit(1));let r=`http://127.0.0.1:${n}/`;await J(r)||l(`Could not open browser. Visit: ${r}`),h("Preview server started in background"),console.log(` URL: ${r}`),console.log(` PID: ${e.pid}`),console.log(""),l("To update the blog: lindoai blogs update <website_id> <blog_id> --html-file <path>"),l("To stop the server: lindoai blogs stop-preview");}async function Oo(o){let{startLivePreviewServer:t}=await Promise.resolve().then(()=>(Ue(),Ne));l("Starting preview server...");let i=await t(o),e=`http://127.0.0.1:${i}/`;S.writeFileSync(te,process.pid.toString(),"utf-8"),S.writeFileSync(ge,i.toString(),"utf-8"),await J(e)||l(`Could not open browser. Visit: ${e}`),h("Preview server started"),console.log(` URL: ${e}`),console.log(""),l("Press Ctrl+C to stop the server"),l("Edit the HTML file and save to see changes in the browser");}function $o(o){return o?o.split(" ").map(t=>t.charAt(0).toUpperCase()).slice(0,2).join(""):"?"}function Fo(o){let{seo:t,blogSettings:i,blogContent:e,websiteName:n,blogPath:r,websiteTheme:a,customCodes:s}=o,d=a?pe(a):"";return `<!DOCTYPE html>
548
+ `,e=spawn(process.execPath,["-e",i],{detached:true,stdio:"ignore"});e.unref();let n=null;for(let s=0;s<50;s++)if(await new Promise(d=>setTimeout(d,100)),S.existsSync(ge))try{if(n=parseInt(S.readFileSync(ge,"utf-8").trim(),10),!isNaN(n))break}catch{}n||(c("Failed to start preview server"),process.exit(1));let r=`http://127.0.0.1:${n}/`;await J(r)||l(`Could not open browser. Visit: ${r}`),h("Preview server started in background"),console.log(` URL: ${r}`),console.log(` PID: ${e.pid}`),console.log(""),l("To update the blog: lindoai blogs update <website_id> <blog_id> --html-file <path>"),l("To stop the server: lindoai blogs stop-preview");}async function $o(t){let{startLivePreviewServer:o}=await Promise.resolve().then(()=>(Ue(),Ne));l("Starting preview server...");let i=await o(t),e=`http://127.0.0.1:${i}/`;S.writeFileSync(te,process.pid.toString(),"utf-8"),S.writeFileSync(ge,i.toString(),"utf-8"),await J(e)||l(`Could not open browser. Visit: ${e}`),h("Preview server started"),console.log(` URL: ${e}`),console.log(""),l("Press Ctrl+C to stop the server"),l("Edit the HTML file and save to see changes in the browser");}function Fo(t){return t?t.split(" ").map(o=>o.charAt(0).toUpperCase()).slice(0,2).join(""):"?"}function To(t){let{seo:o,blogSettings:i,blogContent:e,websiteName:n,blogPath:r,websiteTheme:a,customCodes:s}=t,d=a?pe(a):"";return `<!DOCTYPE html>
549
549
  <html class="dark" lang="en">
550
550
  <head>
551
551
  <meta charset="UTF-8">
552
552
  <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
553
553
 
554
- <title>${t.page_title||"Blog Post"}</title>
555
- <meta name="description" content="${t.meta_description||""}">
554
+ <title>${o.page_title||"Blog Post"}</title>
555
+ <meta name="description" content="${o.meta_description||""}">
556
556
 
557
- <meta property="og:title" content="${t.social_title||t.page_title||""}">
558
- <meta property="og:description" content="${t.social_description||t.meta_description||""}">
559
- ${t.social_image?`<meta property="og:image" content="${t.social_image}">`:""}
557
+ <meta property="og:title" content="${o.social_title||o.page_title||""}">
558
+ <meta property="og:description" content="${o.social_description||o.meta_description||""}">
559
+ ${o.social_image?`<meta property="og:image" content="${o.social_image}">`:""}
560
560
  <meta property="og:type" content="article">
561
561
 
562
562
  <meta name="twitter:card" content="summary_large_image">
563
- <meta name="twitter:title" content="${t.social_title||t.page_title||""}">
564
- <meta name="twitter:description" content="${t.social_description||t.meta_description||""}">
565
- ${t.social_image?`<meta name="twitter:image" content="${t.social_image}">`:""}
563
+ <meta name="twitter:title" content="${o.social_title||o.page_title||""}">
564
+ <meta name="twitter:description" content="${o.social_description||o.meta_description||""}">
565
+ ${o.social_image?`<meta name="twitter:image" content="${o.social_image}">`:""}
566
566
 
567
567
  <!-- Google Fonts -->
568
568
  ${d}
@@ -648,13 +648,13 @@ Markdown frontmatter format:
648
648
  `:""}
649
649
 
650
650
  <h1 class="text-3xl sm:text-4xl lg:text-5xl font-bold font-display leading-tight mb-6 text-gray-900 dark:text-neutral-100">
651
- ${t.page_title||"Untitled"}
651
+ ${o.page_title||"Untitled"}
652
652
  </h1>
653
653
 
654
654
  <div class="flex flex-wrap items-center gap-4 text-sm text-gray-500 dark:text-neutral-400 mb-8">
655
655
  <div class="flex items-center space-x-2">
656
656
  <div id="blog-author-avatar" class="w-8 h-8 rounded-full bg-blue-500 flex items-center justify-center text-white text-xs font-semibold">
657
- ${$o(i.author||"Anonymous")}
657
+ ${Fo(i.author||"Anonymous")}
658
658
  </div>
659
659
  <span id="blog-author-display" class="font-medium text-neutral-200">
660
660
  ${i.author||"Anonymous"}
@@ -666,9 +666,9 @@ Markdown frontmatter format:
666
666
  <span>${i.read_time||"4 min read"}</span>
667
667
  </div>
668
668
 
669
- ${t.social_image?`
669
+ ${o.social_image?`
670
670
  <div class="aspect-video rounded-xl overflow-hidden mb-8">
671
- <img src="${t.social_image}" alt="" class="w-full h-full object-cover">
671
+ <img src="${o.social_image}" alt="" class="w-full h-full object-cover">
672
672
  </div>
673
673
  `:""}
674
674
 
@@ -731,8 +731,8 @@ Markdown frontmatter format:
731
731
  <!-- Custom Code (Footer) -->
732
732
  ${s?.footer||""}
733
733
  </body>
734
- </html>`}function ut(o){let t={},i=o;if(o.startsWith("---")){let e=o.indexOf("---",3);if(e!==-1){let n=o.slice(3,e).trim();i=o.slice(e+3).trim();for(let r of n.split(`
735
- `)){let a=r.indexOf(":");if(a!==-1){let s=r.slice(0,a).trim(),d=r.slice(a+1).trim();(d.startsWith('"')&&d.endsWith('"')||d.startsWith("'")&&d.endsWith("'"))&&(d=d.slice(1,-1)),t[s]=d;}}}}return {content:i,frontmatter:t}}function gt(o){return marked.parse(o,{async:false})}function ht(o){let t=o.toLowerCase().split(".").pop()||"";return {jpg:"image/jpeg",jpeg:"image/jpeg",png:"image/png",gif:"image/gif",webp:"image/webp",svg:"image/svg+xml",ico:"image/x-icon",avif:"image/avif",mp4:"video/mp4",webm:"video/webm",mov:"video/quicktime",pdf:"application/pdf",woff:"font/woff",woff2:"font/woff2",ttf:"font/ttf",otf:"font/otf"}[t]||"application/octet-stream"}function bt(o){let t=o.toLowerCase().split(".").pop()||"",i=["jpg","jpeg","png","gif","webp","svg","ico","avif","bmp","tiff"],e=["mp4","webm","mov","avi","mkv"],n=["woff","woff2","ttf","otf","eot"];return i.includes(t)?"images":e.includes(t)?"videos":n.includes(t)?"fonts":"documents"}function Ge(){let o=new Command("media").description("Media upload operations");return o.command("upload").description("Upload a single media file to website CDN").argument("<website_id>","Website ID").argument("<file_path>","Path to the file to upload").option("-t, --type <type>","Media type (images, videos, documents, fonts)").option("-n, --name <name>","Override file name for CDN").option("-f, --format <format>","Output format (json, table)","table").action(async(t,i,e)=>{let n=wt();try{let r=A.resolve(i);S.existsSync(r)||(c(`File not found: ${r}`),process.exit(1));let a=e.name||A.basename(r),d=S.readFileSync(r).toString("base64"),p=e.type||bt(a),v=ht(a);l(`Uploading ${a} (${p}) to website ${t}...`);let b=await n.media.upload(t,{file_base64:d,file_name:a,media_type:p,content_type:v});h(`Uploaded: ${b.result.url}`),u(b.result,e.format);}catch(r){yt(r);}}),o.command("upload-batch").description("Upload multiple media files to website CDN (max 20)").argument("<website_id>","Website ID").argument("<file_paths...>","Paths to files to upload").option("-t, --type <type>","Media type override for all files").option("-f, --format <format>","Output format (json, table)","table").action(async(t,i,e)=>{let n=wt();try{i.length>20&&(c("Maximum 20 files per batch upload"),process.exit(1));let r=i.map(s=>{let d=A.resolve(s);S.existsSync(d)||(c(`File not found: ${d}`),process.exit(1));let p=A.basename(d),b=S.readFileSync(d).toString("base64"),m=e.type||bt(p),y=ht(p);return {file_base64:b,file_name:p,media_type:m,content_type:y}});l(`Uploading ${r.length} file(s) to website ${t}...`);let a=await n.media.uploadBatch(t,{files:r});h(`Uploaded ${a.result.successful} of ${a.result.total} files`),a.result.failed>0&&l(`${a.result.failed} file(s) failed`),u(a.result,e.format);}catch(r){yt(r);}}),o}function wt(){T()||(c("API key not configured"),l("Run: lindo config set apiKey <your-api-key>"),l("Or set the LINDO_API_KEY environment variable"),process.exit(1));let o=$();return new LindoClient({apiKey:o.apiKey,baseUrl:o.baseUrl})}function yt(o){o instanceof AuthenticationError&&(c("Authentication failed"),l("Your API key may be invalid or expired"),l("Run: lindo config set apiKey <your-api-key>"),process.exit(1)),o instanceof Error?c(o.message):c("An unexpected error occurred"),process.exit(1);}function vt(){return xt.randomBytes(32).toString("hex")}function kt(o,t){return o===t}function Eo(o){try{let t=o.startsWith("http")?o:`http://localhost${o}`,e=new URL(t).searchParams;return {key:e.get("key")??void 0,state:e.get("state")??void 0,error:e.get("error")??void 0,message:e.get("message")??void 0}}catch{return {}}}function Lo(){return `<!DOCTYPE html>
734
+ </html>`}function gt(t){let o={},i=t;if(t.startsWith("---")){let e=t.indexOf("---",3);if(e!==-1){let n=t.slice(3,e).trim();i=t.slice(e+3).trim();for(let r of n.split(`
735
+ `)){let a=r.indexOf(":");if(a!==-1){let s=r.slice(0,a).trim(),d=r.slice(a+1).trim();(d.startsWith('"')&&d.endsWith('"')||d.startsWith("'")&&d.endsWith("'"))&&(d=d.slice(1,-1)),o[s]=d;}}}}return {content:i,frontmatter:o}}function ht(t){return marked.parse(t,{async:false})}function bt(t){let o=t.toLowerCase().split(".").pop()||"";return {jpg:"image/jpeg",jpeg:"image/jpeg",png:"image/png",gif:"image/gif",webp:"image/webp",svg:"image/svg+xml",ico:"image/x-icon",avif:"image/avif",mp4:"video/mp4",webm:"video/webm",mov:"video/quicktime",pdf:"application/pdf",woff:"font/woff",woff2:"font/woff2",ttf:"font/ttf",otf:"font/otf"}[o]||"application/octet-stream"}function yt(t){let o=t.toLowerCase().split(".").pop()||"",i=["jpg","jpeg","png","gif","webp","svg","ico","avif","bmp","tiff"],e=["mp4","webm","mov","avi","mkv"],n=["woff","woff2","ttf","otf","eot"];return i.includes(o)?"images":e.includes(o)?"videos":n.includes(o)?"fonts":"documents"}function Ge(){let t=new Command("media").description("Media upload operations");return t.command("upload").description("Upload a single media file to website CDN").argument("<website_id>","Website ID").argument("<file_path>","Path to the file to upload").option("-t, --type <type>","Media type (images, videos, documents, fonts)").option("-n, --name <name>","Override file name for CDN").option("-f, --format <format>","Output format (json, table)","table").action(async(o,i,e)=>{let n=wt();try{let r=A.resolve(i);S.existsSync(r)||(c(`File not found: ${r}`),process.exit(1));let a=e.name||A.basename(r),d=S.readFileSync(r).toString("base64"),p=e.type||yt(a),v=bt(a);l(`Uploading ${a} (${p}) to website ${o}...`);let b=await n.media.upload(o,{file_base64:d,file_name:a,media_type:p,content_type:v});h(`Uploaded: ${b.result.url}`),f(b.result,e.format);}catch(r){xt(r);}}),t.command("upload-batch").description("Upload multiple media files to website CDN (max 20)").argument("<website_id>","Website ID").argument("<file_paths...>","Paths to files to upload").option("-t, --type <type>","Media type override for all files").option("-f, --format <format>","Output format (json, table)","table").action(async(o,i,e)=>{let n=wt();try{i.length>20&&(c("Maximum 20 files per batch upload"),process.exit(1));let r=i.map(s=>{let d=A.resolve(s);S.existsSync(d)||(c(`File not found: ${d}`),process.exit(1));let p=A.basename(d),b=S.readFileSync(d).toString("base64"),m=e.type||yt(p),w=bt(p);return {file_base64:b,file_name:p,media_type:m,content_type:w}});l(`Uploading ${r.length} file(s) to website ${o}...`);let a=await n.media.uploadBatch(o,{files:r});h(`Uploaded ${a.result.successful} of ${a.result.total} files`),a.result.failed>0&&l(`${a.result.failed} file(s) failed`),f(a.result,e.format);}catch(r){xt(r);}}),t}function wt(){T()||(c("API key not configured"),l("Run: lindo config set apiKey <your-api-key>"),l("Or set the LINDO_API_KEY environment variable"),process.exit(1));let t=$();return new LindoClient({apiKey:t.apiKey,baseUrl:t.baseUrl})}function xt(t){t instanceof AuthenticationError&&(c("Authentication failed"),l("Your API key may be invalid or expired"),l("Run: lindo config set apiKey <your-api-key>"),process.exit(1)),t instanceof Error?c(t.message):c("An unexpected error occurred"),process.exit(1);}function kt(){return vt.randomBytes(32).toString("hex")}function Ct(t,o){return t===o}function Lo(t){try{let o=t.startsWith("http")?t:`http://localhost${t}`,e=new URL(o).searchParams;return {key:e.get("key")??void 0,state:e.get("state")??void 0,error:e.get("error")??void 0,message:e.get("message")??void 0}}catch{return {}}}function jo(){return `<!DOCTYPE html>
736
736
  <html lang="en">
737
737
  <head>
738
738
  <meta charset="UTF-8">
@@ -778,7 +778,7 @@ ${s?.footer||""}
778
778
  <p>You can close this window and return to your terminal.</p>
779
779
  </div>
780
780
  </body>
781
- </html>`}function we(o){return `<!DOCTYPE html>
781
+ </html>`}function ye(t){return `<!DOCTYPE html>
782
782
  <html lang="en">
783
783
  <head>
784
784
  <meta charset="UTF-8">
@@ -830,10 +830,10 @@ ${s?.footer||""}
830
830
  <div class="icon">\u2717</div>
831
831
  <h1>Authorization Failed</h1>
832
832
  <p>Something went wrong during authorization.</p>
833
- <div class="error-message">${o.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;").replace(/'/g,"&#039;")}</div>
833
+ <div class="error-message">${t.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;").replace(/'/g,"&#039;")}</div>
834
834
  </div>
835
835
  </body>
836
- </html>`}function jo(){return `<!DOCTYPE html>
836
+ </html>`}function Do(){return `<!DOCTYPE html>
837
837
  <html lang="en">
838
838
  <head>
839
839
  <meta charset="UTF-8">
@@ -871,13 +871,13 @@ ${s?.footer||""}
871
871
  <p>This endpoint is not available.</p>
872
872
  </div>
873
873
  </body>
874
- </html>`}function _t(){let o=null,t=null;function i(e,n){let r=e.url||"/",a=e.method||"GET",s=r==="/callback"||r.startsWith("/callback?");if(a!=="GET"||!s){n.writeHead(404,{"Content-Type":"text/html; charset=utf-8"}),n.end(jo());return}let d=Eo(r);if(!t){n.writeHead(400,{"Content-Type":"text/html; charset=utf-8"}),n.end(we("No pending authorization request"));return}let{expectedState:p,resolve:v,timeoutId:b}=t;if(clearTimeout(b),t=null,d.error){let m=d.message||d.error;n.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),n.end(we(m)),v({success:false,error:m});return}if(!d.state||!kt(d.state,p)){let m="State token mismatch - possible CSRF attack";n.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),n.end(we(m)),v({success:false,error:m});return}if(!d.key){let m="No API key received";n.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),n.end(we(m)),v({success:false,error:m});return}n.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),n.end(Lo()),v({success:true,apiKey:d.key});}return {async start(){return new Promise((e,n)=>{o=ct.createServer(i),o.on("error",r=>{n(new Error(`Failed to start callback server: ${r.message}`));}),o.listen(0,"127.0.0.1",()=>{let r=o.address();if(!r||typeof r=="string"){n(new Error("Failed to get server address"));return}let a=r.port,s=`http://127.0.0.1:${a}/callback`;e({port:a,url:s});});})},waitForCallback(e,n){return new Promise(r=>{let a=setTimeout(()=>{t&&(t=null,r({success:false,error:"Login timed out waiting for authorization"}));},n);t={expectedState:e,resolve:r,timeoutId:a};})},async stop(){return new Promise(e=>{t&&(clearTimeout(t.timeoutId),t=null),o?o.close(()=>{o=null,e();}):e();})}}}var Do="https://app.lindo.ai",No=120;function Uo(o,t){let i=`http://127.0.0.1:${t}/callback`,e=new URLSearchParams({state:o,callback_url:i});return `${Do}/cli/authorize?${e.toString()}`}function Je(){return new Command("login").description("Authenticate via browser to configure your API key").option("-t, --timeout <seconds>","Timeout in seconds for the login flow",String(No)).option("--no-browser","Display the authorization URL without opening the browser").action(async t=>{let i=parseInt(t.timeout,10),e=i*1e3,n=t.browser,r=_t(),a=false;try{l("Starting authentication flow...");let{port:s}=await r.start();a=!0;let d=vt(),p=Uo(d,s);n?(l("Opening browser for authorization..."),await J(p)||(l("Could not open browser automatically."),console.log(`
874
+ </html>`}function St(){let t=null,o=null;function i(e,n){let r=e.url||"/",a=e.method||"GET",s=r==="/callback"||r.startsWith("/callback?");if(a!=="GET"||!s){n.writeHead(404,{"Content-Type":"text/html; charset=utf-8"}),n.end(Do());return}let d=Lo(r);if(!o){n.writeHead(400,{"Content-Type":"text/html; charset=utf-8"}),n.end(ye("No pending authorization request"));return}let{expectedState:p,resolve:v,timeoutId:b}=o;if(clearTimeout(b),o=null,d.error){let m=d.message||d.error;n.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),n.end(ye(m)),v({success:false,error:m});return}if(!d.state||!Ct(d.state,p)){let m="State token mismatch - possible CSRF attack";n.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),n.end(ye(m)),v({success:false,error:m});return}if(!d.key){let m="No API key received";n.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),n.end(ye(m)),v({success:false,error:m});return}n.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),n.end(jo()),v({success:true,apiKey:d.key});}return {async start(){return new Promise((e,n)=>{t=ct.createServer(i),t.on("error",r=>{n(new Error(`Failed to start callback server: ${r.message}`));}),t.listen(0,"127.0.0.1",()=>{let r=t.address();if(!r||typeof r=="string"){n(new Error("Failed to get server address"));return}let a=r.port,s=`http://127.0.0.1:${a}/callback`;e({port:a,url:s});});})},waitForCallback(e,n){return new Promise(r=>{let a=setTimeout(()=>{o&&(o=null,r({success:false,error:"Login timed out waiting for authorization"}));},n);o={expectedState:e,resolve:r,timeoutId:a};})},async stop(){return new Promise(e=>{o&&(clearTimeout(o.timeoutId),o=null),t?t.close(()=>{t=null,e();}):e();})}}}var No="https://app.lindo.ai",Uo=120;function Mo(t,o){let i=`http://127.0.0.1:${o}/callback`,e=new URLSearchParams({state:t,callback_url:i});return `${No}/cli/authorize?${e.toString()}`}function Je(){return new Command("login").description("Authenticate via browser to configure your API key").option("-t, --timeout <seconds>","Timeout in seconds for the login flow",String(Uo)).option("--no-browser","Display the authorization URL without opening the browser").action(async o=>{let i=parseInt(o.timeout,10),e=i*1e3,n=o.browser,r=St(),a=false;try{l("Starting authentication flow...");let{port:s}=await r.start();a=!0;let d=kt(),p=Mo(d,s);n?(l("Opening browser for authorization..."),await J(p)||(l("Could not open browser automatically."),console.log(`
875
875
  Please open this URL in your browser:`),console.log(`
876
876
  ${p}
877
877
  `))):(console.log(`
878
878
  Please open this URL in your browser:`),console.log(`
879
879
  ${p}
880
- `)),l(`Waiting for authorization (timeout: ${i}s)...`);let v=await r.waitForCallback(d,e);v.success&&v.apiKey?(ot(v.apiKey),h("Successfully authenticated!"),l(`API key saved to: ${q()}`)):(c(v.error||"Authentication failed"),process.exit(1));}catch(s){c(s instanceof Error?s.message:"An unexpected error occurred"),process.exit(1);}finally{a&&await r.stop();}})}var St=`---
880
+ `)),l(`Waiting for authorization (timeout: ${i}s)...`);let v=await r.waitForCallback(d,e);v.success&&v.apiKey?(ot(v.apiKey),h("Successfully authenticated!"),l(`API key saved to: ${q()}`)):(c(v.error||"Authentication failed"),process.exit(1));}catch(s){c(s instanceof Error?s.message:"An unexpected error occurred"),process.exit(1);}finally{a&&await r.stop();}})}var Ot=`---
881
881
  name: lindoai
882
882
  description: Lindo AI CLI - Command-line interface for the Lindo API
883
883
  ---
@@ -1253,5 +1253,5 @@ Follow these core rules when building pages:
1253
1253
  6. **Container patterns**:
1254
1254
  - Use \`container mx-auto px-4\` for consistent content width
1255
1255
  - Apply consistent vertical padding: \`py-12 md:py-16 lg:py-20\`
1256
- `;var Ye=A.join(Re.homedir(),".config","opencode","skills","lindoai"),Ft=A.join(Ye,"SKILL.md");function Bo(){try{let o=process.platform==="win32"?"where opencode":"which opencode";return execSync(o,{stdio:"ignore"}),!0}catch{return false}}function qo(){try{return l("Installing OpenCode..."),execSync("npm install -g opencode-ai@latest",{stdio:"inherit"}),!0}catch{return false}}function Ko(){S.existsSync(Ye)||S.mkdirSync(Ye,{recursive:true}),S.writeFileSync(Ft,St,"utf-8");}function Ve(){return new Command("agent").description("Launch an AI agent that understands all CLI commands").option("--install","Install OpenCode if not already installed").option("--model <model>","Specify the model to use with OpenCode").action(async t=>{Bo()||(t.install?(qo()||(c("Failed to install OpenCode"),l("Please install manually: npm install -g opencode-ai@latest"),process.exit(1)),h("OpenCode installed successfully")):(c("OpenCode is not installed"),l(""),l("To install OpenCode, run one of the following:"),l(" lindoai agent --install"),l(" npm install -g opencode-ai@latest"),process.exit(1)));try{Ko(),l(`Skill file installed to: ${Ft}`);}catch(n){c(`Failed to install skill file: ${n instanceof Error?n.message:"Unknown error"}`),process.exit(1);}let i=[];t.model&&i.push("--model",t.model),l("Launching OpenCode...");let e=spawn("opencode",i,{stdio:"inherit",shell:true});e.on("error",n=>{c(`Failed to launch OpenCode: ${n.message}`),process.exit(1);}),e.on("close",n=>{process.exit(n??0);});})}function Xe(){return new Command("whoami").description("Show the current authenticated workspace").option("-f, --format <format>","Output format (json, table)","table").action(async t=>{T()||(c("Not logged in"),l("Run: lindo login"),l("Or: lindo config set apiKey <your-api-key>"),process.exit(1));let i=$(),e=new LindoClient({apiKey:i.apiKey,baseUrl:i.baseUrl});try{let n=await e.workspace.get();u(n,t.format);}catch(n){n instanceof AuthenticationError&&(c("Authentication failed \u2014 API key may be invalid or expired"),l("Run: lindo login"),process.exit(1)),n instanceof Error?c(n.message):c("An unexpected error occurred"),process.exit(1);}})}var Qo=createRequire(import.meta.url),Zo=Qo("../package.json"),ei=Zo.version;function ti(){let o=new Command;return o.name("lindo").description("Command-line interface for the Lindo API").version(ei,"-v, --version","Output the current version").helpOption("-h, --help","Display help for command"),o.addCommand(_e()),o.addCommand(Se()),o.addCommand(Oe()),o.addCommand($e()),o.addCommand(Fe()),o.addCommand(Te()),o.addCommand(Pe()),o.addCommand(We()),o.addCommand(Ke()),o.addCommand(Ge()),o.addCommand(Je()),o.addCommand(Ve()),o.addCommand(Xe()),o.exitOverride(t=>{throw t.code==="commander.help"&&process.exit(0),t.code==="commander.version"&&process.exit(0),t.code==="commander.missingArgument"&&(c(t.message),process.exit(1)),t.code==="commander.unknownCommand"&&(c(t.message),l('Run "lindo --help" for available commands'),process.exit(1)),t}),o}function oi(o){c("Authentication failed"),l(""),l("Your API key may be invalid or expired."),l(""),l("To configure your API key:"),l(" 1. Run: lindo config set apiKey <your-api-key>"),l(" 2. Or set the LINDO_API_KEY environment variable"),l(""),l("To get an API key:"),l(" Visit https://app.lindo.ai/settings/api-keys");}async function ii(){let o=ti();try{await o.parseAsync(process.argv);}catch(t){throw t instanceof AuthenticationError&&(oi(),process.exit(1)),t}}ii().catch(o=>{o instanceof Error?c(`Unexpected error: ${o.message}`):c("An unexpected error occurred"),process.exit(1);});
1257
- export{ti as createProgram};
1256
+ `;var Ye=A.join(De.homedir(),".config","opencode","skills","lindoai"),Tt=A.join(Ye,"SKILL.md");function qo(){try{let t=process.platform==="win32"?"where opencode":"which opencode";return execSync(t,{stdio:"ignore"}),!0}catch{return false}}function Ko(){try{return l("Installing OpenCode..."),execSync("npm install -g opencode-ai@latest",{stdio:"inherit"}),!0}catch{return false}}function Go(){S.existsSync(Ye)||S.mkdirSync(Ye,{recursive:true}),S.writeFileSync(Tt,Ot,"utf-8");}function Ve(){return new Command("agent").description("Launch an AI agent that understands all CLI commands").option("--install","Install OpenCode if not already installed").option("--model <model>","Specify the model to use with OpenCode").action(async o=>{qo()||(o.install?(Ko()||(c("Failed to install OpenCode"),l("Please install manually: npm install -g opencode-ai@latest"),process.exit(1)),h("OpenCode installed successfully")):(c("OpenCode is not installed"),l(""),l("To install OpenCode, run one of the following:"),l(" lindoai agent --install"),l(" npm install -g opencode-ai@latest"),process.exit(1)));try{Go(),l(`Skill file installed to: ${Tt}`);}catch(n){c(`Failed to install skill file: ${n instanceof Error?n.message:"Unknown error"}`),process.exit(1);}let i=[];o.model&&i.push("--model",o.model),l("Launching OpenCode...");let e=spawn("opencode",i,{stdio:"inherit",shell:true});e.on("error",n=>{c(`Failed to launch OpenCode: ${n.message}`),process.exit(1);}),e.on("close",n=>{process.exit(n??0);});})}function Xe(){return new Command("whoami").description("Show the current authenticated workspace").option("-f, --format <format>","Output format (json, table)","table").action(async o=>{T()||(c("Not logged in"),l("Run: lindo login"),l("Or: lindo config set apiKey <your-api-key>"),process.exit(1));let i=$(),e=new LindoClient({apiKey:i.apiKey,baseUrl:i.baseUrl});try{let n=await e.workspace.get();f(n,o.format);}catch(n){n instanceof AuthenticationError&&(c("Authentication failed \u2014 API key may be invalid or expired"),l("Run: lindo login"),process.exit(1)),n instanceof Error?c(n.message):c("An unexpected error occurred"),process.exit(1);}})}var Zo=createRequire(import.meta.url),ei=Zo("../package.json"),ti=ei.version;function oi(){let t=new Command;return t.name("lindo").description("Command-line interface for the Lindo API").version(ti,"-v, --version","Output the current version").helpOption("-h, --help","Display help for command"),t.addCommand(_e()),t.addCommand(Se()),t.addCommand(Oe()),t.addCommand($e()),t.addCommand(Fe()),t.addCommand(Te()),t.addCommand(Pe()),t.addCommand(We()),t.addCommand(Ke()),t.addCommand(Ge()),t.addCommand(Je()),t.addCommand(Ve()),t.addCommand(Xe()),t.exitOverride(o=>{throw o.code==="commander.help"&&process.exit(0),o.code==="commander.version"&&process.exit(0),o.code==="commander.missingArgument"&&(c(o.message),process.exit(1)),o.code==="commander.unknownCommand"&&(c(o.message),l('Run "lindo --help" for available commands'),process.exit(1)),o}),t}function ii(t){c("Authentication failed"),l(""),l("Your API key may be invalid or expired."),l(""),l("To configure your API key:"),l(" 1. Run: lindo config set apiKey <your-api-key>"),l(" 2. Or set the LINDO_API_KEY environment variable"),l(""),l("To get an API key:"),l(" Visit https://app.lindo.ai/settings/api-keys");}async function ni(){let t=oi();try{await t.parseAsync(process.argv);}catch(o){throw o instanceof AuthenticationError&&(ii(),process.exit(1)),o}}ni().catch(t=>{t instanceof Error?c(`Unexpected error: ${t.message}`):c("An unexpected error occurred"),process.exit(1);});
1257
+ export{oi as createProgram};