lindoai-cli 1.1.0 → 1.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/dist/index.cjs +290 -59
  2. package/dist/index.js +290 -59
  3. package/package.json +3 -2
package/dist/index.cjs CHANGED
@@ -1,23 +1,23 @@
1
1
  #!/usr/bin/env node
2
- 'use strict';var Ye=require('http'),k=require('fs'),L=require('path'),ke=require('os'),commander=require('commander'),lindoai=require('lindoai'),child_process=require('child_process'),url=require('url'),ot=require('crypto');function _interopNamespace(e){if(e&&e.__esModule)return e;var n=Object.create(null);if(e){Object.keys(e).forEach(function(k){if(k!=='default'){var d=Object.getOwnPropertyDescriptor(e,k);Object.defineProperty(n,k,d.get?d:{enumerable:true,get:function(){return e[k]}});}})}n.default=e;return Object.freeze(n)}var Ye__namespace=/*#__PURE__*/_interopNamespace(Ye);var k__namespace=/*#__PURE__*/_interopNamespace(k);var L__namespace=/*#__PURE__*/_interopNamespace(L);var ke__namespace=/*#__PURE__*/_interopNamespace(ke);var ot__namespace=/*#__PURE__*/_interopNamespace(ot);var ft=Object.defineProperty;var gt=(o,e)=>()=>(o&&(e=o(o=0)),e);var ht=(o,e)=>{for(var n in e)ft(o,n,{get:e[n],enumerable:true});};var _e={};ht(_e,{LIVE_RELOAD_SCRIPT:()=>Ce,injectLiveReload:()=>ze,startLivePreviewServer:()=>zt});function ze(o){let e=/<\/body>/i,n=o.match(e);return n&&n.index!==void 0?o.slice(0,n.index)+Ce+o.slice(n.index):o+Ce}function zt(o){return new Promise((e,n)=>{let t=L__namespace.resolve(o),i=new Set,a=null,c=100;function m(){for(let u of i)try{u.write(`data: reload
2
+ 'use strict';var ct=require('http'),O=require('fs'),A=require('path'),Ue=require('os'),commander=require('commander'),lindoai=require('lindoai'),child_process=require('child_process'),De=require('cheerio'),url=require('url'),wt=require('crypto');function _interopNamespace(e){if(e&&e.__esModule)return e;var n=Object.create(null);if(e){Object.keys(e).forEach(function(k){if(k!=='default'){var d=Object.getOwnPropertyDescriptor(e,k);Object.defineProperty(n,k,d.get?d:{enumerable:true,get:function(){return e[k]}});}})}n.default=e;return Object.freeze(n)}var ct__namespace=/*#__PURE__*/_interopNamespace(ct);var O__namespace=/*#__PURE__*/_interopNamespace(O);var A__namespace=/*#__PURE__*/_interopNamespace(A);var Ue__namespace=/*#__PURE__*/_interopNamespace(Ue);var De__namespace=/*#__PURE__*/_interopNamespace(De);var wt__namespace=/*#__PURE__*/_interopNamespace(wt);var It=Object.defineProperty;var At=(o,e)=>()=>(o&&(e=o(o=0)),e);var Et=(o,e)=>{for(var n in e)It(o,n,{get:e[n],enumerable:true});};var He={};Et(He,{LIVE_RELOAD_SCRIPT:()=>Me,injectLiveReload:()=>dt,startLivePreviewServer:()=>go});function dt(o){let e=/<\/body>/i,n=o.match(e);return n&&n.index!==void 0?o.slice(0,n.index)+Me+o.slice(n.index):o+Me}function go(o){return new Promise((e,n)=>{let t=A__namespace.resolve(o),i=new Set,r=null,c=100;function a(){for(let f of i)try{f.write(`data: reload
3
3
 
4
- `);}catch{i.delete(u);}}function l(){a&&clearTimeout(a),a=setTimeout(()=>{m(),a=null;},c);}function f(u,h){let v=u.url||"/";if((u.method||"GET")!=="GET"){h.writeHead(405,{"Content-Type":"text/plain"}),h.end("Method Not Allowed");return}if(v==="/__live-reload"){h.writeHead(200,{"Content-Type":"text/event-stream","Cache-Control":"no-cache",Connection:"keep-alive","Access-Control-Allow-Origin":"*"}),h.write(`data: connected
4
+ `);}catch{i.delete(f);}}function d(){r&&clearTimeout(r),r=setTimeout(()=>{a(),r=null;},c);}function p(f,x){let m=f.url||"/";if((f.method||"GET")!=="GET"){x.writeHead(405,{"Content-Type":"text/plain"}),x.end("Method Not Allowed");return}if(m==="/__live-reload"){x.writeHead(200,{"Content-Type":"text/event-stream","Cache-Control":"no-cache",Connection:"keep-alive","Access-Control-Allow-Origin":"*"}),x.write(`data: connected
5
5
 
6
- `),i.add(h),u.on("close",()=>{i.delete(h);});return}if(v==="/"||v==="/index.html"){try{let x=k__namespace.readFileSync(t,"utf-8"),w=ze(x);h.writeHead(200,{"Content-Type":"text/html; charset=utf-8","Cache-Control":"no-cache"}),h.end(w);}catch(x){let w=x instanceof Error?x.message:"Unknown error";h.writeHead(500,{"Content-Type":"text/html; charset=utf-8"}),h.end(`<!DOCTYPE html>
6
+ `),i.add(x),f.on("close",()=>{i.delete(x);});return}if(m==="/"||m==="/index.html"){try{let g=O__namespace.readFileSync(t,"utf-8"),h=dt(g);x.writeHead(200,{"Content-Type":"text/html; charset=utf-8","Cache-Control":"no-cache"}),x.end(h);}catch(g){let h=g instanceof Error?g.message:"Unknown error";x.writeHead(500,{"Content-Type":"text/html; charset=utf-8"}),x.end(`<!DOCTYPE html>
7
7
  <html>
8
8
  <head><title>Error</title></head>
9
9
  <body>
10
10
  <h1>Error loading file</h1>
11
- <p>${w}</p>
11
+ <p>${h}</p>
12
12
  </body>
13
- </html>`);}return}h.writeHead(404,{"Content-Type":"text/html; charset=utf-8"}),h.end(`<!DOCTYPE html>
13
+ </html>`);}return}x.writeHead(404,{"Content-Type":"text/html; charset=utf-8"}),x.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 g=Ye__namespace.createServer(f),y=null;g.on("error",u=>{n(new Error(`Failed to start preview server: ${u.message}`));}),g.listen(0,"127.0.0.1",()=>{let u=g.address();if(!u||typeof u=="string"){n(new Error("Failed to get server address"));return}let h=u.port;try{y=k__namespace.watch(t,b=>{b==="change"&&l();}),y.on("error",b=>{console.error(`[Live Preview] File watcher error: ${b.message}`);});}catch(b){let x=b instanceof Error?b.message:"Unknown error";console.error(`[Live Preview] Failed to watch file: ${x}`);}let v=()=>{y&&(y.close(),y=null),a&&(clearTimeout(a),a=null);for(let w of i)try{w.end();}catch{}i.clear();let b=L__namespace.join(ke__namespace.tmpdir(),"lindoai-pages-preview.pid"),x=L__namespace.join(ke__namespace.tmpdir(),"lindoai-pages-preview.port");try{k__namespace.existsSync(b)&&k__namespace.unlinkSync(b);}catch{}try{k__namespace.existsSync(x)&&k__namespace.unlinkSync(x);}catch{}g.close(()=>{process.exit(0);}),setTimeout(()=>{process.exit(0);},1e3);};process.on("SIGTERM",v),process.on("SIGINT",v),e(h);});})}var Ce,Se=gt(()=>{Ce=`<script>
20
+ </html>`);}let v=ct__namespace.createServer(p),y=null;v.on("error",f=>{n(new Error(`Failed to start preview server: ${f.message}`));}),v.listen(0,"127.0.0.1",()=>{let f=v.address();if(!f||typeof f=="string"){n(new Error("Failed to get server address"));return}let x=f.port;try{y=O__namespace.watch(t,u=>{u==="change"&&d();}),y.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 m=()=>{y&&(y.close(),y=null),r&&(clearTimeout(r),r=null);for(let h of i)try{h.end();}catch{}i.clear();let u=A__namespace.join(Ue__namespace.tmpdir(),"lindoai-pages-preview.pid"),g=A__namespace.join(Ue__namespace.tmpdir(),"lindoai-pages-preview.port");try{O__namespace.existsSync(u)&&O__namespace.unlinkSync(u);}catch{}try{O__namespace.existsSync(g)&&O__namespace.unlinkSync(g);}catch{}v.close(()=>{process.exit(0);}),setTimeout(()=>{process.exit(0);},1e3);};process.on("SIGTERM",m),process.on("SIGINT",m),e(x);});})}var Me,We=At(()=>{Me=`<script>
21
21
  (function() {
22
22
  var eventSource = new EventSource('/__live-reload');
23
23
  eventSource.onmessage = function(event) {
@@ -29,19 +29,33 @@
29
29
  console.log('[Live Reload] Connection lost, attempting to reconnect...');
30
30
  };
31
31
  })();
32
- </script>`;});var bt="LINDO_API_KEY",wt="LINDO_BASE_URL",yt=".lindo",vt="config.json",xt="https://api.lindo.ai";function Me(){return L__namespace.join(ke__namespace.homedir(),yt)}function E(){return L__namespace.join(Me(),vt)}function pe(){let o=E();try{if(k__namespace.existsSync(o)){let e=k__namespace.readFileSync(o,"utf-8");return JSON.parse(e)}}catch{}return {}}function Ue(o){let e=Me(),n=E();k__namespace.existsSync(e)||k__namespace.mkdirSync(e,{recursive:true}),k__namespace.writeFileSync(n,JSON.stringify(o,null,2),"utf-8");}function C(){let o=pe(),e=process.env[bt]||o.apiKey,n=process.env[wt]||o.baseUrl||xt;return {apiKey:e,baseUrl:n}}function Ke(o){let e=pe();e.apiKey=o,Ue(e);}function We(o,e){let n=pe();switch(o){case "apiKey":n.apiKey=e;break;case "baseUrl":n.baseUrl=e;break;default:throw new Error(`Unknown configuration key: ${o}`)}Ue(n);}function He(o){let e=C();switch(o){case "apiKey":return e.apiKey;case "baseUrl":return e.baseUrl;default:return}}function S(){return !!C().apiKey}var j={reset:"\x1B[0m",red:"\x1B[31m",green:"\x1B[32m",blue:"\x1B[34m",cyan:"\x1B[36m",gray:"\x1B[90m",bold:"\x1B[1m"};function kt(){return !process.env.NO_COLOR&&process.stdout.isTTY!==false}function D(o,e){return kt()?`${e}${o}${j.reset}`:o}function p(o){console.log(D(`\u2713 ${o}`,j.green));}function s(o){console.error(D(`\u2717 ${o}`,j.red));}function r(o){console.log(D(`\u2139 ${o}`,j.blue));}function Ct(o){return JSON.stringify(o,null,2)}function _t(o){if(o==null)return "";if(Array.isArray(o)){if(o.length===0)return "No data";let e=new Set;for(let t of o)typeof t=="object"&&t!==null&&Object.keys(t).forEach(i=>e.add(i));if(e.size===0)return o.map(t=>String(t)).join(`
33
- `);let n=Array.from(e);return St(n,o)}if(typeof o=="object"){let n=Object.entries(o);if(n.length===0)return "No data";let t=Math.max(...n.map(([i])=>i.length));return n.map(([i,a])=>{let c=i.padEnd(t),m=ue(a);return `${D(c,j.cyan)} ${m}`}).join(`
34
- `)}return String(o)}function St(o,e){let n={};for(let c of o)n[c]=c.length;for(let c of e)if(typeof c=="object"&&c!==null){let m=c;for(let l of o){let f=ue(m[l]);n[l]=Math.max(n[l],f.length);}}let t=o.map(c=>D(c.padEnd(n[c]),j.bold)).join(" "),i=o.map(c=>"-".repeat(n[c])).join(" "),a=e.map(c=>{if(typeof c=="object"&&c!==null){let m=c;return o.map(l=>ue(m[l]).padEnd(n[l])).join(" ")}return String(c)});return [t,i,...a].join(`
35
- `)}function ue(o){return o==null?D("-",j.gray):typeof o=="boolean"?o?D("true",j.green):D("false",j.red):typeof o=="number"?String(o):typeof o=="object"?Array.isArray(o)?`[${o.length} items]`:JSON.stringify(o):String(o)}function d(o,e){console.log(e==="json"?Ct(o):_t(o));}var qe=["apiKey","baseUrl"];function ge(){let o=new commander.Command("config").description("Manage CLI configuration");return o.command("set <key> <value>").description("Set a configuration value").action((e,n)=>{qe.includes(e)||(s(`Invalid configuration key: ${e}`),r(`Valid keys: ${qe.join(", ")}`),process.exit(1));try{We(e,n),p(`Configuration saved: ${e}`),r(`Config file: ${E()}`);}catch(t){s(`Failed to save configuration: ${t instanceof Error?t.message:String(t)}`),process.exit(1);}}),o.command("get <key>").description("Get a configuration value").option("-f, --format <format>","Output format (json, table)","table").action((e,n)=>{let t=He(e);if(t===void 0){n.format==="json"?d({key:e,value:null},n.format):r(`Configuration key '${e}' is not set`);return}if(n.format==="json")d({key:e,value:t},n.format);else {let i=e==="apiKey"?fe(t):t;console.log(`${e}: ${i}`);}}),o.command("list").description("List all configuration values").option("-f, --format <format>","Output format (json, table)","table").action(e=>{let n=C(),t={apiKey:n.apiKey?fe(n.apiKey):"(not set)",baseUrl:n.baseUrl,configFile:E()};e.format==="json"?d({apiKey:n.apiKey?fe(n.apiKey):null,baseUrl:n.baseUrl,configFile:E()},e.format):d(t,e.format);}),o.command("path").description("Show the config file path").action(()=>{console.log(E());}),o}function fe(o){return o.length<=8?"*".repeat(o.length):`${o.slice(0,4)}${"*".repeat(o.length-8)}${o.slice(-4)}`}function he(){let o=new commander.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(e,n)=>{S()||(s("API key not configured"),r("Run: lindo config set apiKey <your-api-key>"),r("Or set the LINDO_API_KEY environment variable"),process.exit(1));let t=C(),i=new lindoai.LindoClient({apiKey:t.apiKey,baseUrl:t.baseUrl}),a;try{a=JSON.parse(n.input);}catch{s("Invalid JSON input"),r(`Example: --input '{"prompt": "Hello!"}'`),process.exit(1);}try{r(`Running agent: ${e}`);let c=await i.agents.run({agent_id:e,input:a,stream:n.stream});c.success?(p("Agent run completed"),d(c,n.format)):(s(`Agent run failed: ${c.error||"Unknown error"}`),d(c,n.format),process.exit(1));}catch(c){Ft(c);}}),o}function Ft(o){o instanceof lindoai.AuthenticationError&&(s("Authentication failed"),r("Your API key may be invalid or expired"),r("Run: lindo config set apiKey <your-api-key>"),process.exit(1)),o instanceof Error?s(o.message):s("An unexpected error occurred"),process.exit(1);}function be(){let o=new commander.Command("workflows").description("Manage workflows");return 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 e=>{let n=J();try{let t=await n.workflows.list({workflow_name:e.name,status:e.status,website_id:e.website,client_id:e.client,limit:parseInt(e.limit)});t.success?d(t.data,e.format):(s("Failed to list workflows"),process.exit(1));}catch(t){Q(t);}}),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(e,n)=>{let t=J(),i;try{i=JSON.parse(n.params);}catch{s("Invalid JSON params"),r(`Example: --params '{"page_id": "page-123"}'`),process.exit(1);}try{r(`Starting workflow: ${e}`);let a=await t.workflows.start({workflow_name:e,params:i});a.success?(p(`Workflow started: ${a.instance_id}`),d(a,n.format)):(s("Failed to start workflow"),d(a,n.format),process.exit(1));}catch(a){Q(a);}}),o.command("status <instance-id>").description("Get workflow status").option("-f, --format <format>","Output format (json, table)","table").action(async(e,n)=>{let t=J();try{let i=await t.workflows.getStatus(e);d(i,n.format);}catch(i){Q(i);}}),o.command("pause <instance-id>").description("Pause a running workflow").option("-f, --format <format>","Output format (json, table)","table").action(async(e,n)=>{let t=J();try{r(`Pausing workflow: ${e}`);let i=await t.workflows.pause(e);i.success?p(i.message):(s(i.message),process.exit(1)),d(i,n.format);}catch(i){Q(i);}}),o.command("resume <instance-id>").description("Resume a paused workflow").option("-f, --format <format>","Output format (json, table)","table").action(async(e,n)=>{let t=J();try{r(`Resuming workflow: ${e}`);let i=await t.workflows.resume(e);i.success?p(i.message):(s(i.message),process.exit(1)),d(i,n.format);}catch(i){Q(i);}}),o.command("terminate <instance-id>").description("Terminate a workflow").option("-f, --format <format>","Output format (json, table)","table").action(async(e,n)=>{let t=J();try{r(`Terminating workflow: ${e}`);let i=await t.workflows.terminate(e);i.success?p(i.message):(s(i.message),process.exit(1)),d(i,n.format);}catch(i){Q(i);}}),o}function J(){S()||(s("API key not configured"),r("Run: lindo config set apiKey <your-api-key>"),r("Or set the LINDO_API_KEY environment variable"),process.exit(1));let o=C();return new lindoai.LindoClient({apiKey:o.apiKey,baseUrl:o.baseUrl})}function Q(o){o instanceof lindoai.AuthenticationError&&(s("Authentication failed"),r("Your API key may be invalid or expired"),r("Run: lindo config set apiKey <your-api-key>"),process.exit(1)),o instanceof Error?s(o.message):s("An unexpected error occurred"),process.exit(1);}function we(){let o=new commander.Command("workspace").description("Workspace operations");return o.command("get").description("Get workspace details").option("-f, --format <format>","Output format (json, table)","table").action(async e=>{let n=P();try{let t=await n.workspace.get();d(t,e.format);}catch(t){F(t);}}),o.command("credits").description("Get workspace credit balance").option("-f, --format <format>","Output format (json, table)","table").action(async e=>{let n=P();try{let t=await n.workspace.getCredits();d(t,e.format);}catch(t){F(t);}}),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 e=>{let n=P();try{let t=await n.workspace.getClientCredits(e.client);d(t,e.format);}catch(t){F(t);}}),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 e=>{let n=P();try{let t=await n.workspace.update({workspace_name:e.name,workspace_language:e.language,webhook_url:e.webhook});t.success&&p("Workspace updated"),d(t,e.format);}catch(t){F(t);}}),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 e=>{let n=P();try{let t=await n.workspace.addTeamMember(e.email,e.role);t.success&&p("Team member added"),d(t,e.format);}catch(t){F(t);}}),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 e=>{let n=P();try{let t=await n.workspace.removeTeamMember(e.member);t.success&&p("Team member removed"),d(t,e.format);}catch(t){F(t);}}),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 e=>{let n=P(),t;try{t=JSON.parse(e.config);}catch{s("Invalid JSON config"),process.exit(1);}try{let i=await n.workspace.addIntegration({integration_type:e.type,config:t});i.success&&p("Integration added"),d(i,e.format);}catch(i){F(i);}}),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 e=>{let n=P();try{let t=await n.workspace.removeIntegration(e.type);t.success&&p("Integration removed"),d(t,e.format);}catch(t){F(t);}}),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 e=>{let n=P();try{let t=await n.workspace.setupWhitelabel({domain:e.domain,subdomain_domain:e.subdomain,email_sender:e.emailSender,wl_client_register:e.enableRegister?!0:e.disableRegister?!1:void 0});t.success&&p("Whitelabel settings updated"),d(t,e.format);}catch(t){F(t);}}),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 e=>{let n=P();try{let t=await n.workspace.updateAppearance({primary_color:e.primary,secondary_color:e.secondary,theme_mode:e.mode});t.success&&p("Appearance settings updated"),d(t,e.format);}catch(t){F(t);}}),o}function P(){S()||(s("API key not configured"),r("Run: lindo config set apiKey <your-api-key>"),r("Or set the LINDO_API_KEY environment variable"),process.exit(1));let o=C();return new lindoai.LindoClient({apiKey:o.apiKey,baseUrl:o.baseUrl})}function F(o){o instanceof lindoai.AuthenticationError&&(s("Authentication failed"),r("Your API key may be invalid or expired"),r("Run: lindo config set apiKey <your-api-key>"),process.exit(1)),o instanceof Error?s(o.message):s("An unexpected error occurred"),process.exit(1);}function ye(){let o=new commander.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 e=>{let n=Be();try{let t=await n.analytics.getWorkspace({from:e.from,to:e.to});d(t,e.format);}catch(t){Ge(t);}}),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 e=>{let n=Be();try{let t=await n.analytics.getWebsite({website_id:e.website,from:e.from,to:e.to});d(t,e.format);}catch(t){Ge(t);}}),o}function Be(){S()||(s("API key not configured"),r("Run: lindo config set apiKey <your-api-key>"),r("Or set the LINDO_API_KEY environment variable"),process.exit(1));let o=C();return new lindoai.LindoClient({apiKey:o.apiKey,baseUrl:o.baseUrl})}function Ge(o){o instanceof lindoai.AuthenticationError&&(s("Authentication failed"),r("Your API key may be invalid or expired"),r("Run: lindo config set apiKey <your-api-key>"),process.exit(1)),o instanceof Error?s(o.message):s("An unexpected error occurred"),process.exit(1);}function ve(){let o=new commander.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 e=>{let n=te();try{let t=await n.clients.list({page:parseInt(e.page,10),search:e.search});if(e.format==="json")d(t,"json");else if(t.clients&&t.clients.length>0){console.log(`
36
- Clients:`),console.log("--------");for(let i of t.clients)console.log(` ID: ${i.record_id}`),console.log(` Email: ${i.email}`),console.log(` Website Limit: ${i.website_limit??"N/A"}`),console.log(` Suspended: ${i.suspended??!1}`),console.log("");console.log(`Total: ${t.total??t.clients.length}`);}else r("No clients found");}catch(t){oe(t);}}),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 e=>{let n=te();try{let t=await n.clients.create({email:e.email,website_limit:parseInt(e.limit,10)});if(t.success&&t.client)p(`Client created: ${t.client.record_id}`),d(t.client,e.format);else if(s("Failed to create client"),t.errors)for(let i of t.errors)s(` ${i}`);}catch(t){oe(t);}}),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 e=>{let n=te();try{let t=await n.clients.update({client_id:e.id,website_limit:e.limit?parseInt(e.limit,10):void 0,suspended:e.suspend?!0:e.unsuspend?!1:void 0});if(t.success)p("Client updated"),t.client&&d(t.client,e.format);else if(s("Failed to update client"),t.errors)for(let i of t.errors)s(` ${i}`);}catch(t){oe(t);}}),o.command("delete").description("Delete a workspace client").requiredOption("-i, --id <id>","Client ID").action(async e=>{let n=te();try{let t=await n.clients.delete(e.id);if(t.success)p("Client deleted");else if(s("Failed to delete client"),t.errors)for(let i of t.errors)s(` ${i}`);}catch(t){oe(t);}}),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 e=>{let n=te();try{let t=await n.clients.createMagicLink(e.email);if(t.success)p("Magic link created"),d(t,e.format);else if(s("Failed to create magic link"),t.errors)for(let i of t.errors)s(` ${i}`);}catch(t){oe(t);}}),o}function te(){S()||(s("API key not configured"),r("Run: lindo config set apiKey <your-api-key>"),r("Or set the LINDO_API_KEY environment variable"),process.exit(1));let o=C();return new lindoai.LindoClient({apiKey:o.apiKey,baseUrl:o.baseUrl})}function oe(o){o instanceof lindoai.AuthenticationError&&(s("Authentication failed"),r("Your API key may be invalid or expired"),r("Run: lindo config set apiKey <your-api-key>"),process.exit(1)),o instanceof Error?s(o.message):s("An unexpected error occurred"),process.exit(1);}function xe(){let o=new commander.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 e=>{let n=O();try{let t=await n.websites.list({page:parseInt(e.page,10),search:e.search});if(e.format==="json")d(t,"json");else {let i=t.result?.list??[];if(i.length>0){console.log(`
37
- Websites:`),console.log("---------");for(let a of i)console.log(` ID: ${a.website_id}`),console.log(` Name: ${a.website_name??"N/A"}`),console.log(` Domain: ${a.domain??"N/A"}`),console.log(` Activated: ${a.activated??!1}`),console.log("");console.log(`Total: ${t.result?.total??i.length}`);}else r("No websites found");}}catch(t){I(t);}}),o.command("get").description("Get website details").requiredOption("-i, --id <id>","Website ID").option("-f, --format <format>","Output format (json, table)","table").action(async e=>{let n=O();try{let t=await n.websites.getDetails(e.id);d(t,e.format);}catch(t){I(t);}}),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 e=>{let n=O();try{let t=await n.websites.update({website_id:e.id,business_name:e.name,activated:e.activate?!0:e.deactivate?!1:void 0});if(t.success)p("Website updated"),t.website&&d(t.website,e.format);else if(s("Failed to update website"),t.errors)for(let i of t.errors)s(` ${i}`);}catch(t){I(t);}}),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 e=>{let n=O();try{let t=await n.websites.updateSettings(e.id,{business_name:e.name,language:e.language,business_description:e.description});t.success&&p("Website settings updated"),d(t,e.format);}catch(t){I(t);}}),o.command("delete").description("Delete a website").requiredOption("-i, --id <id>","Website ID").action(async e=>{let n=O();try{let t=await n.websites.delete(e.id);if(t.success)p("Website deleted");else if(s("Failed to delete website"),t.errors)for(let i of t.errors)s(` ${i}`);}catch(t){I(t);}}),o.command("assign").description("Assign a website to a client").requiredOption("-w, --website <id>","Website ID").requiredOption("-c, --client <id>","Client ID").action(async e=>{let n=O();try{let t=await n.websites.assign({website_id:e.website,client_id:e.client});if(t.success)p("Website assigned to client");else if(s("Failed to assign website"),t.errors)for(let i of t.errors)s(` ${i}`);}catch(t){I(t);}}),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 e=>{let n=O();try{let t=await n.websites.addDomain(e.id,e.domain);if(t.success&&(p("Domain added"),t.result?.dns_records)){console.log(`
38
- DNS Records to configure:`);for(let i of t.result.dns_records)console.log(` ${i.record_type} ${i.host} -> ${i.value}`);}d(t,e.format);}catch(t){I(t);}}),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 e=>{let n=O();try{let t=await n.websites.removeDomain(e.id);t.success&&p("Domain removed"),d(t,e.format);}catch(t){I(t);}}),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 e=>{let n=O(),t;try{t=JSON.parse(e.config);}catch{s("Invalid JSON config"),process.exit(1);}try{let i=await n.websites.addIntegration(e.id,{integration_type:e.type,config:t});i.success&&p("Integration added"),d(i,e.format);}catch(i){I(i);}}),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 e=>{let n=O();try{let t=await n.websites.removeIntegration(e.id,e.type);t.success&&p("Integration removed"),d(t,e.format);}catch(t){I(t);}}),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 e=>{let n=O();try{let t=await n.websites.addTeamMember(e.id,e.email,e.role);t.success&&p("Team member added"),d(t,e.format);}catch(t){I(t);}}),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 e=>{let n=O();try{let t=await n.websites.removeTeamMember(e.id,e.member);t.success&&p("Team member removed"),d(t,e.format);}catch(t){I(t);}}),o}function O(){S()||(s("API key not configured"),r("Run: lindo config set apiKey <your-api-key>"),r("Or set the LINDO_API_KEY environment variable"),process.exit(1));let o=C();return new lindoai.LindoClient({apiKey:o.apiKey,baseUrl:o.baseUrl})}function I(o){o instanceof lindoai.AuthenticationError&&(s("Authentication failed"),r("Your API key may be invalid or expired"),r("Run: lindo config set apiKey <your-api-key>"),process.exit(1)),o instanceof Error?s(o.message):s("An unexpected error occurred"),process.exit(1);}function R(o){return new Promise(e=>{let n=ke.platform(),t;switch(n){case "darwin":t=`open "${o}"`;break;case "win32":t=`start "" "${o}"`;break;default:t=`xdg-open "${o}"`;break}child_process.exec(t,i=>{e(!i);});})}var H=L__namespace.join(ke__namespace.tmpdir(),"lindoai-pages-preview.pid"),ie=L__namespace.join(ke__namespace.tmpdir(),"lindoai-pages-preview.port");function $e(){let o=new commander.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 e=>{let n=K();try{let t=await n.pages.list(e.website,{page:parseInt(e.page,10),search:e.search});if(e.format==="json")d(t,"json");else {let i=t.result;if(i?.list&&i.list.length>0){console.log(`
39
- Pages:`),console.log("------");for(let a of i.list)console.log(` ID: ${a.page_id}`),console.log(` Name: ${a.name??"N/A"}`),console.log(` Path: ${a.path??"N/A"}`),console.log(` Status: ${a.status??"N/A"}`),console.log(` Published: ${a.publish_date?"Yes":"No"}`),console.log("");console.log(`Total: ${i.total??i.list.length}`);}else r("No pages found");}}catch(t){W(t);}}),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 e=>{let n=K();try{let t=await n.pages.get(e.website,e.id);if(e.format==="json")d(t,"json");else {let i=t.result;i?(console.log(`
40
- Page Details:`),console.log("-------------"),console.log(` ID: ${i.page_id}`),console.log(` Name: ${i.name??"N/A"}`),console.log(` Path: ${i.path??"N/A"}`),console.log(` Status: ${i.status??"N/A"}`),console.log(` Published: ${i.publish_date?"Yes":"No"}`),console.log(` Created: ${i.created_date??"N/A"}`)):s("Page not found");}}catch(t){W(t);}}),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 e=>{let n=K();try{let t=await n.pages.unpublish(e.website,e.id);e.format==="json"?d(t,"json"):t.success?(p("Page unpublished successfully"),console.log(` Page ID: ${t.result?.page_id}`)):s("Failed to unpublish page");}catch(t){W(t);}}),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 e=>{let n=K();try{let t=await n.pages.deletePage(e.website,e.id);if(e.format==="json")d(t,"json");else if(t.success){if(p("Page deleted successfully"),console.log(` Page ID: ${t.result?.page_id}`),t.result?.warnings&&t.result.warnings.length>0){console.log(" Warnings:");for(let i of t.result.warnings)console.log(` - ${i}`);}}else s("Failed to delete page");}catch(t){W(t);}}),o.command("create").description("Create a new page with 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(e,n,t)=>{let i=K();try{let a=t.title,c=`<!-- Hero Section -->
32
+ </script>`;});var Lt="LINDO_API_KEY",Rt="LINDO_BASE_URL",jt=".lindo",Dt="config.json",Nt="https://api.lindo.ai";function et(){return A__namespace.join(Ue__namespace.homedir(),jt)}function q(){return A__namespace.join(et(),Dt)}function _e(){let o=q();try{if(O__namespace.existsSync(o)){let e=O__namespace.readFileSync(o,"utf-8");return JSON.parse(e)}}catch{}return {}}function tt(o){let e=et(),n=q();O__namespace.existsSync(e)||O__namespace.mkdirSync(e,{recursive:true}),O__namespace.writeFileSync(n,JSON.stringify(o,null,2),"utf-8");}function T(){let o=_e(),e=process.env[Lt]||o.apiKey,n=process.env[Rt]||o.baseUrl||Nt;return {apiKey:e,baseUrl:n}}function ot(o){let e=_e();e.apiKey=o,tt(e);}function nt(o,e){let n=_e();switch(o){case "apiKey":n.apiKey=e;break;case "baseUrl":n.baseUrl=e;break;default:throw new Error(`Unknown configuration key: ${o}`)}tt(n);}function it(o){let e=T();switch(o){case "apiKey":return e.apiKey;case "baseUrl":return e.baseUrl;default:return}}function P(){return !!T().apiKey}var G={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 J(o,e){return Ut()?`${e}${o}${G.reset}`:o}function b(o){console.log(J(`\u2713 ${o}`,G.green));}function l(o){console.error(J(`\u2717 ${o}`,G.red));}function s(o){console.log(J(`\u2139 ${o}`,G.blue));}function Mt(o){return JSON.stringify(o,null,2)}function Ht(o){if(o==null)return "";if(Array.isArray(o)){if(o.length===0)return "No data";let e=new Set;for(let t of o)typeof t=="object"&&t!==null&&Object.keys(t).forEach(i=>e.add(i));if(e.size===0)return o.map(t=>String(t)).join(`
33
+ `);let n=Array.from(e);return Wt(n,o)}if(typeof o=="object"){let n=Object.entries(o);if(n.length===0)return "No data";let t=Math.max(...n.map(([i])=>i.length));return n.map(([i,r])=>{let c=i.padEnd(t),a=Se(r);return `${J(c,G.cyan)} ${a}`}).join(`
34
+ `)}return String(o)}function Wt(o,e){let n={};for(let c of o)n[c]=c.length;for(let c of e)if(typeof c=="object"&&c!==null){let a=c;for(let d of o){let p=Se(a[d]);n[d]=Math.max(n[d],p.length);}}let t=o.map(c=>J(c.padEnd(n[c]),G.bold)).join(" "),i=o.map(c=>"-".repeat(n[c])).join(" "),r=e.map(c=>{if(typeof c=="object"&&c!==null){let a=c;return o.map(d=>Se(a[d]).padEnd(n[d])).join(" ")}return String(c)});return [t,i,...r].join(`
35
+ `)}function Se(o){return o==null?J("-",G.gray):typeof o=="boolean"?o?J("true",G.green):J("false",G.red):typeof o=="number"?String(o):typeof o=="object"?Array.isArray(o)?`[${o.length} items]`:JSON.stringify(o):String(o)}function w(o,e){console.log(e==="json"?Mt(o):Ht(o));}var rt=["apiKey","baseUrl"];function $e(){let o=new commander.Command("config").description("Manage CLI configuration");return o.command("set <key> <value>").description("Set a configuration value").action((e,n)=>{rt.includes(e)||(l(`Invalid configuration key: ${e}`),s(`Valid keys: ${rt.join(", ")}`),process.exit(1));try{nt(e,n),b(`Configuration saved: ${e}`),s(`Config file: ${q()}`);}catch(t){l(`Failed to save configuration: ${t instanceof Error?t.message:String(t)}`),process.exit(1);}}),o.command("get <key>").description("Get a configuration value").option("-f, --format <format>","Output format (json, table)","table").action((e,n)=>{let t=it(e);if(t===void 0){n.format==="json"?w({key:e,value:null},n.format):s(`Configuration key '${e}' is not set`);return}if(n.format==="json")w({key:e,value:t},n.format);else {let i=e==="apiKey"?Oe(t):t;console.log(`${e}: ${i}`);}}),o.command("list").description("List all configuration values").option("-f, --format <format>","Output format (json, table)","table").action(e=>{let n=T(),t={apiKey:n.apiKey?Oe(n.apiKey):"(not set)",baseUrl:n.baseUrl,configFile:q()};e.format==="json"?w({apiKey:n.apiKey?Oe(n.apiKey):null,baseUrl:n.baseUrl,configFile:q()},e.format):w(t,e.format);}),o.command("path").description("Show the config file path").action(()=>{console.log(q());}),o}function Oe(o){return o.length<=8?"*".repeat(o.length):`${o.slice(0,4)}${"*".repeat(o.length-8)}${o.slice(-4)}`}function Te(){let o=new commander.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(e,n)=>{P()||(l("API key not configured"),s("Run: lindo config set apiKey <your-api-key>"),s("Or set the LINDO_API_KEY environment variable"),process.exit(1));let t=T(),i=new lindoai.LindoClient({apiKey:t.apiKey,baseUrl:t.baseUrl}),r;try{r=JSON.parse(n.input);}catch{l("Invalid JSON input"),s(`Example: --input '{"prompt": "Hello!"}'`),process.exit(1);}try{s(`Running agent: ${e}`);let c=await i.agents.run({agent_id:e,input:r,stream:n.stream});c.success?(b("Agent run completed"),w(c,n.format)):(l(`Agent run failed: ${c.error||"Unknown error"}`),w(c,n.format),process.exit(1));}catch(c){zt(c);}}),o}function zt(o){o instanceof lindoai.AuthenticationError&&(l("Authentication failed"),s("Your API key may be invalid or expired"),s("Run: lindo config set apiKey <your-api-key>"),process.exit(1)),o instanceof Error?l(o.message):l("An unexpected error occurred"),process.exit(1);}function Fe(){let o=new commander.Command("workflows").description("Manage workflows");return 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 e=>{let n=re();try{let t=await n.workflows.list({workflow_name:e.name,status:e.status,website_id:e.website,client_id:e.client,limit:parseInt(e.limit)});t.success?w(t.data,e.format):(l("Failed to list workflows"),process.exit(1));}catch(t){se(t);}}),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(e,n)=>{let t=re(),i;try{i=JSON.parse(n.params);}catch{l("Invalid JSON params"),s(`Example: --params '{"page_id": "page-123"}'`),process.exit(1);}try{s(`Starting workflow: ${e}`);let r=await t.workflows.start({workflow_name:e,params:i});r.success?(b(`Workflow started: ${r.instance_id}`),w(r,n.format)):(l("Failed to start workflow"),w(r,n.format),process.exit(1));}catch(r){se(r);}}),o.command("status <instance-id>").description("Get workflow status").option("-f, --format <format>","Output format (json, table)","table").action(async(e,n)=>{let t=re();try{let i=await t.workflows.getStatus(e);w(i,n.format);}catch(i){se(i);}}),o.command("pause <instance-id>").description("Pause a running workflow").option("-f, --format <format>","Output format (json, table)","table").action(async(e,n)=>{let t=re();try{s(`Pausing workflow: ${e}`);let i=await t.workflows.pause(e);i.success?b(i.message):(l(i.message),process.exit(1)),w(i,n.format);}catch(i){se(i);}}),o.command("resume <instance-id>").description("Resume a paused workflow").option("-f, --format <format>","Output format (json, table)","table").action(async(e,n)=>{let t=re();try{s(`Resuming workflow: ${e}`);let i=await t.workflows.resume(e);i.success?b(i.message):(l(i.message),process.exit(1)),w(i,n.format);}catch(i){se(i);}}),o.command("terminate <instance-id>").description("Terminate a workflow").option("-f, --format <format>","Output format (json, table)","table").action(async(e,n)=>{let t=re();try{s(`Terminating workflow: ${e}`);let i=await t.workflows.terminate(e);i.success?b(i.message):(l(i.message),process.exit(1)),w(i,n.format);}catch(i){se(i);}}),o}function re(){P()||(l("API key not configured"),s("Run: lindo config set apiKey <your-api-key>"),s("Or set the LINDO_API_KEY environment variable"),process.exit(1));let o=T();return new lindoai.LindoClient({apiKey:o.apiKey,baseUrl:o.baseUrl})}function se(o){o instanceof lindoai.AuthenticationError&&(l("Authentication failed"),s("Your API key may be invalid or expired"),s("Run: lindo config set apiKey <your-api-key>"),process.exit(1)),o instanceof Error?l(o.message):l("An unexpected error occurred"),process.exit(1);}function Pe(){let o=new commander.Command("workspace").description("Workspace operations");return o.command("get").description("Get workspace details").option("-f, --format <format>","Output format (json, table)","table").action(async e=>{let n=M();try{let t=await n.workspace.get();w(t,e.format);}catch(t){H(t);}}),o.command("credits").description("Get workspace credit balance").option("-f, --format <format>","Output format (json, table)","table").action(async e=>{let n=M();try{let t=await n.workspace.getCredits();w(t,e.format);}catch(t){H(t);}}),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 e=>{let n=M();try{let t=await n.workspace.getClientCredits(e.client);w(t,e.format);}catch(t){H(t);}}),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 e=>{let n=M();try{let t=await n.workspace.update({workspace_name:e.name,workspace_language:e.language,webhook_url:e.webhook});t.success&&b("Workspace updated"),w(t,e.format);}catch(t){H(t);}}),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 e=>{let n=M();try{let t=await n.workspace.addTeamMember(e.email,e.role);t.success&&b("Team member added"),w(t,e.format);}catch(t){H(t);}}),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 e=>{let n=M();try{let t=await n.workspace.removeTeamMember(e.member);t.success&&b("Team member removed"),w(t,e.format);}catch(t){H(t);}}),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 e=>{let n=M(),t;try{t=JSON.parse(e.config);}catch{l("Invalid JSON config"),process.exit(1);}try{let i=await n.workspace.addIntegration({integration_type:e.type,config:t});i.success&&b("Integration added"),w(i,e.format);}catch(i){H(i);}}),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 e=>{let n=M();try{let t=await n.workspace.removeIntegration(e.type);t.success&&b("Integration removed"),w(t,e.format);}catch(t){H(t);}}),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 e=>{let n=M();try{let t=await n.workspace.setupWhitelabel({domain:e.domain,subdomain_domain:e.subdomain,email_sender:e.emailSender,wl_client_register:e.enableRegister?!0:e.disableRegister?!1:void 0});t.success&&b("Whitelabel settings updated"),w(t,e.format);}catch(t){H(t);}}),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 e=>{let n=M();try{let t=await n.workspace.updateAppearance({primary_color:e.primary,secondary_color:e.secondary,theme_mode:e.mode});t.success&&b("Appearance settings updated"),w(t,e.format);}catch(t){H(t);}}),o}function M(){P()||(l("API key not configured"),s("Run: lindo config set apiKey <your-api-key>"),s("Or set the LINDO_API_KEY environment variable"),process.exit(1));let o=T();return new lindoai.LindoClient({apiKey:o.apiKey,baseUrl:o.baseUrl})}function H(o){o instanceof lindoai.AuthenticationError&&(l("Authentication failed"),s("Your API key may be invalid or expired"),s("Run: lindo config set apiKey <your-api-key>"),process.exit(1)),o instanceof Error?l(o.message):l("An unexpected error occurred"),process.exit(1);}function Ie(){let o=new commander.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 e=>{let n=st();try{let t=await n.analytics.getWorkspace({from:e.from,to:e.to});w(t,e.format);}catch(t){at(t);}}),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 e=>{let n=st();try{let t=await n.analytics.getWebsite({website_id:e.website,from:e.from,to:e.to});w(t,e.format);}catch(t){at(t);}}),o}function st(){P()||(l("API key not configured"),s("Run: lindo config set apiKey <your-api-key>"),s("Or set the LINDO_API_KEY environment variable"),process.exit(1));let o=T();return new lindoai.LindoClient({apiKey:o.apiKey,baseUrl:o.baseUrl})}function at(o){o instanceof lindoai.AuthenticationError&&(l("Authentication failed"),s("Your API key may be invalid or expired"),s("Run: lindo config set apiKey <your-api-key>"),process.exit(1)),o instanceof Error?l(o.message):l("An unexpected error occurred"),process.exit(1);}function Ae(){let o=new commander.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 e=>{let n=me();try{let t=await n.clients.list({page:parseInt(e.page,10),search:e.search});if(e.format==="json")w(t,"json");else if(t.clients&&t.clients.length>0){console.log(`
36
+ Clients:`),console.log("--------");for(let i of t.clients)console.log(` ID: ${i.record_id}`),console.log(` Email: ${i.email}`),console.log(` Website Limit: ${i.website_limit??"N/A"}`),console.log(` Suspended: ${i.suspended??!1}`),console.log("");console.log(`Total: ${t.total??t.clients.length}`);}else s("No clients found");}catch(t){pe(t);}}),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 e=>{let n=me();try{let t=await n.clients.create({email:e.email,website_limit:parseInt(e.limit,10)});if(t.success&&t.client)b(`Client created: ${t.client.record_id}`),w(t.client,e.format);else if(l("Failed to create client"),t.errors)for(let i of t.errors)l(` ${i}`);}catch(t){pe(t);}}),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 e=>{let n=me();try{let t=await n.clients.update({client_id:e.id,website_limit:e.limit?parseInt(e.limit,10):void 0,suspended:e.suspend?!0:e.unsuspend?!1:void 0});if(t.success)b("Client updated"),t.client&&w(t.client,e.format);else if(l("Failed to update client"),t.errors)for(let i of t.errors)l(` ${i}`);}catch(t){pe(t);}}),o.command("delete").description("Delete a workspace client").requiredOption("-i, --id <id>","Client ID").action(async e=>{let n=me();try{let t=await n.clients.delete(e.id);if(t.success)b("Client deleted");else if(l("Failed to delete client"),t.errors)for(let i of t.errors)l(` ${i}`);}catch(t){pe(t);}}),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 e=>{let n=me();try{let t=await n.clients.createMagicLink(e.email);if(t.success)b("Magic link created"),w(t,e.format);else if(l("Failed to create magic link"),t.errors)for(let i of t.errors)l(` ${i}`);}catch(t){pe(t);}}),o}function me(){P()||(l("API key not configured"),s("Run: lindo config set apiKey <your-api-key>"),s("Or set the LINDO_API_KEY environment variable"),process.exit(1));let o=T();return new lindoai.LindoClient({apiKey:o.apiKey,baseUrl:o.baseUrl})}function pe(o){o instanceof lindoai.AuthenticationError&&(l("Authentication failed"),s("Your API key may be invalid or expired"),s("Run: lindo config set apiKey <your-api-key>"),process.exit(1)),o instanceof Error?l(o.message):l("An unexpected error occurred"),process.exit(1);}function Ee(){let o=new commander.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 e=>{let n=E();try{let t=await n.websites.list({page:parseInt(e.page,10),search:e.search});if(e.format==="json")w(t,"json");else {let i=t.result?.list??[];if(i.length>0){console.log(`
37
+ Websites:`),console.log("---------");for(let r of i)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: ${t.result?.total??i.length}`);}else s("No websites found");}}catch(t){L(t);}}),o.command("get").description("Get website details").requiredOption("-i, --id <id>","Website ID").option("-f, --format <format>","Output format (json, table)","table").action(async e=>{let n=E();try{let t=await n.websites.getDetails(e.id);w(t,e.format);}catch(t){L(t);}}),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 e=>{let n=E();try{let t=await n.websites.update({website_id:e.id,business_name:e.name,activated:e.activate?!0:e.deactivate?!1:void 0});if(t.success)b("Website updated"),t.website&&w(t.website,e.format);else if(l("Failed to update website"),t.errors)for(let i of t.errors)l(` ${i}`);}catch(t){L(t);}}),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 e=>{let n=E();try{let t=await n.websites.updateSettings(e.id,{business_name:e.name,language:e.language,business_description:e.description});t.success&&b("Website settings updated"),w(t,e.format);}catch(t){L(t);}}),o.command("delete").description("Delete a website").requiredOption("-i, --id <id>","Website ID").action(async e=>{let n=E();try{let t=await n.websites.delete(e.id);if(t.success)b("Website deleted");else if(l("Failed to delete website"),t.errors)for(let i of t.errors)l(` ${i}`);}catch(t){L(t);}}),o.command("assign").description("Assign a website to a client").requiredOption("-w, --website <id>","Website ID").requiredOption("-c, --client <id>","Client ID").action(async e=>{let n=E();try{let t=await n.websites.assign({website_id:e.website,client_id:e.client});if(t.success)b("Website assigned to client");else if(l("Failed to assign website"),t.errors)for(let i of t.errors)l(` ${i}`);}catch(t){L(t);}}),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 e=>{let n=E();try{let t=await n.websites.addDomain(e.id,e.domain);if(t.success&&(b("Domain added"),t.result?.dns_records)){console.log(`
38
+ DNS Records to configure:`);for(let i of t.result.dns_records)console.log(` ${i.record_type} ${i.host} -> ${i.value}`);}w(t,e.format);}catch(t){L(t);}}),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 e=>{let n=E();try{let t=await n.websites.removeDomain(e.id);t.success&&b("Domain removed"),w(t,e.format);}catch(t){L(t);}}),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 e=>{let n=E(),t;try{t=JSON.parse(e.config);}catch{l("Invalid JSON config"),process.exit(1);}try{let i=await n.websites.addIntegration(e.id,{integration_type:e.type,config:t});i.success&&b("Integration added"),w(i,e.format);}catch(i){L(i);}}),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 e=>{let n=E();try{let t=await n.websites.removeIntegration(e.id,e.type);t.success&&b("Integration removed"),w(t,e.format);}catch(t){L(t);}}),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 e=>{let n=E();try{let t=await n.websites.addTeamMember(e.id,e.email,e.role);t.success&&b("Team member added"),w(t,e.format);}catch(t){L(t);}}),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 e=>{let n=E();try{let t=await n.websites.removeTeamMember(e.id,e.member);t.success&&b("Team member removed"),w(t,e.format);}catch(t){L(t);}}),o}function E(){P()||(l("API key not configured"),s("Run: lindo config set apiKey <your-api-key>"),s("Or set the LINDO_API_KEY environment variable"),process.exit(1));let o=T();return new lindoai.LindoClient({apiKey:o.apiKey,baseUrl:o.baseUrl})}function L(o){o instanceof lindoai.AuthenticationError&&(l("Authentication failed"),s("Your API key may be invalid or expired"),s("Run: lindo config set apiKey <your-api-key>"),process.exit(1)),o instanceof Error?l(o.message):l("An unexpected error occurred"),process.exit(1);}function X(o){return new Promise(e=>{let n=Ue.platform(),t;switch(n){case "darwin":t=`open "${o}"`;break;case "win32":t=`start "" "${o}"`;break;default:t=`xdg-open "${o}"`;break}child_process.exec(t,i=>{e(!i);});})}function po(o){let e=o.filter(t=>!!(t&&t.trim()));return e.length===0?"":`https://fonts.googleapis.com/css2?family=${e.map(t=>`${t.trim().replace(/ /g,"+")}:wght@300;400;700`).join("&family=")}&display=swap`}function ue(o){let e=[o.font,o.title_font].filter(Boolean);if(e.length===0)return "";let n=po(e);if(!n)return "";let t=o.font||o.title_font,i=o.title_font||o.font,r=`
39
+ <style>
40
+ /* Apply website fonts from theme */
41
+ body, main, .prose {
42
+ font-family: '${t}', system-ui, sans-serif !important;
43
+ }
44
+ h1, h2, h3, h4, h5, h6, .font-display, .font-serif {
45
+ font-family: '${i}', system-ui, serif !important;
46
+ }
47
+ </style>`;return `<link rel="preconnect" href="https://fonts.googleapis.com">
48
+ <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
49
+ <link href="${n}" rel="stylesheet">${r}`}function lt(o,e){let n=new RegExp(`<${e}\\b[^>]*>`,"gi"),t,i=null;for(;(t=n.exec(o))!==null;){let S=o.slice(0,t.index);if(uo(S)){i=t;break}}if(!i||i.index===void 0)return {section:void 0,remainingHtml:o};let r=i.index,c=r+i[0].length,a=`</${e}>`,d=o.slice(c),p=new RegExp(`<${e}\\b`,"gi"),v=new RegExp(`</${e}>`,"gi"),y=[],f=[],x;for(;(x=p.exec(d))!==null;)y.push(x.index+c);for(;(x=v.exec(d))!==null;)f.push(x.index+c);let m=[...y.map(S=>({pos:S,type:"open"})),...f.map(S=>({pos:S,type:"close"}))].sort((S,F)=>S.pos-F.pos),u=1,g=-1;for(let S of m)if(S.type==="open")u++;else if(u--,u===0){g=S.pos+a.length;break}if(g===-1)return {section:void 0,remainingHtml:o};let h=o.slice(r,g),k=o.slice(0,r),_=o.slice(g),C=(k+_).replace(/\n\s*\n\s*\n/g,`
50
+
51
+ `);return {section:h,remainingHtml:C}}function uo(o){let e=["section","header","footer"],n=0;for(let t of e){let i=new RegExp(`<${t}\\b`,"gi"),r=new RegExp(`</${t}>`,"gi"),c=(o.match(i)||[]).length,a=(o.match(r)||[]).length;n+=c-a;}return n===0}function Le(o){let e=lt(o,"header"),n=lt(e.remainingHtml,"footer");return {globalHeader:e.section,globalFooter:n.section,mainContent:n.remainingHtml.trim()}}function Re(o,e,n){let t=[];return e&&e.trim()&&t.push(e.trim()),o.trim()&&t.push(o.trim()),n&&n.trim()&&t.push(n.trim()),t.join(`
52
+ `)}function ae(o){return !(!o||o.startsWith("http://")||o.startsWith("https://")||o.startsWith("//")||o.startsWith("data:")||o.startsWith("blob:")||o.startsWith("#"))}function xe(o){let e=o.toLowerCase().split(".").pop()||"",n=["jpg","jpeg","png","gif","webp","svg","ico","avif","bmp","tiff"],t=["mp4","webm","mov","avi","mkv","ogv"],i=["woff","woff2","ttf","otf","eot"];return n.includes(e)?"images":t.includes(e)?"videos":i.includes(e)?"fonts":"documents"}function le(o){let e=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"}[e]||"application/octet-stream"}function fo(o,e){let n=De__namespace.load(o),t=[],i=new Set;return n("img[src]").each((r,c)=>{let a=n(c).attr("src");if(a&&ae(a)&&!i.has(a)){i.add(a);let d=A__namespace.resolve(e,a);O__namespace.existsSync(d)&&t.push({originalPath:a,absolutePath:d,fileName:A__namespace.basename(a),mediaType:xe(a),contentType:le(a)});}}),n("img[srcset]").each((r,c)=>{let a=n(c).attr("srcset");if(a){let d=a.split(",").map(p=>p.trim().split(/\s+/)[0]);for(let p of d)if(p&&ae(p)&&!i.has(p)){i.add(p);let v=A__namespace.resolve(e,p);O__namespace.existsSync(v)&&t.push({originalPath:p,absolutePath:v,fileName:A__namespace.basename(p),mediaType:xe(p),contentType:le(p)});}}}),n("source[src]").each((r,c)=>{let a=n(c).attr("src");if(a&&ae(a)&&!i.has(a)){i.add(a);let d=A__namespace.resolve(e,a);O__namespace.existsSync(d)&&t.push({originalPath:a,absolutePath:d,fileName:A__namespace.basename(a),mediaType:xe(a),contentType:le(a)});}}),n("video[poster]").each((r,c)=>{let a=n(c).attr("poster");if(a&&ae(a)&&!i.has(a)){i.add(a);let d=A__namespace.resolve(e,a);O__namespace.existsSync(d)&&t.push({originalPath:a,absolutePath:d,fileName:A__namespace.basename(a),mediaType:"images",contentType:le(a)});}}),n('[style*="background"]').each((r,c)=>{let d=(n(c).attr("style")||"").match(/url\(['"]?([^'")\s]+)['"]?\)/);if(d&&d[1]){let p=d[1];if(ae(p)&&!i.has(p)){i.add(p);let v=A__namespace.resolve(e,p);O__namespace.existsSync(v)&&t.push({originalPath:p,absolutePath:v,fileName:A__namespace.basename(p),mediaType:xe(p),contentType:le(p)});}}}),n('link[href][rel*="icon"]').each((r,c)=>{let a=n(c).attr("href");if(a&&ae(a)&&!i.has(a)){i.add(a);let d=A__namespace.resolve(e,a);O__namespace.existsSync(d)&&t.push({originalPath:a,absolutePath:d,fileName:A__namespace.basename(a),mediaType:"images",contentType:le(a)});}}),t}async function Ne(o,e,n,t,i,r){let c=fo(o,e);if(c.length===0)return {html:o,uploadedCount:0,failedCount:0,urlMap:new Map,sourceFileUpdated:false};i?.(`Found ${c.length} local asset(s) to upload`);let a=new Map,d=0,p=0,v=10;for(let m=0;m<c.length;m+=v){let u=c.slice(m,m+v),g=u.map(h=>({file_base64:O__namespace.readFileSync(h.absolutePath).toString("base64"),file_name:h.fileName,media_type:h.mediaType,content_type:h.contentType}));try{if(g.length>1&&t.media.uploadBatch){let h=await t.media.uploadBatch(n,{files:g});for(let k=0;k<h.result.uploaded.length;k++){let _=h.result.uploaded[k],C=u[k];_.success?(a.set(C.originalPath,_.url),d++,i?.(`Uploaded: ${C.fileName} \u2192 ${_.url}`)):(p++,i?.(`Failed: ${C.fileName} - ${_.error}`));}}else for(let h=0;h<g.length;h++){let k=g[h],_=u[h];try{let C=await t.media.upload(n,k);a.set(_.originalPath,C.result.url),d++,i?.(`Uploaded: ${_.fileName} \u2192 ${C.result.url}`);}catch(C){p++,i?.(`Failed: ${_.fileName} - ${C instanceof Error?C.message:"Unknown error"}`);}}}catch{for(let k=0;k<g.length;k++){let _=g[k],C=u[k];try{let S=await t.media.upload(n,_);a.set(C.originalPath,S.result.url),d++,i?.(`Uploaded: ${C.fileName} \u2192 ${S.result.url}`);}catch(S){p++,i?.(`Failed: ${C.fileName} - ${S instanceof Error?S.message:"Unknown error"}`);}}}}let y=De__namespace.load(o);y("img[src]").each((m,u)=>{let g=y(u).attr("src");g&&a.has(g)&&y(u).attr("src",a.get(g));}),y("img[srcset]").each((m,u)=>{let g=y(u).attr("srcset");if(g){let h=g;for(let[k,_]of a)h=h.replace(new RegExp(je(k),"g"),_);y(u).attr("srcset",h);}}),y("source[src]").each((m,u)=>{let g=y(u).attr("src");g&&a.has(g)&&y(u).attr("src",a.get(g));}),y("video[poster]").each((m,u)=>{let g=y(u).attr("poster");g&&a.has(g)&&y(u).attr("poster",a.get(g));}),y('[style*="background"]').each((m,u)=>{let g=y(u).attr("style")||"";for(let[h,k]of a)g=g.replace(new RegExp(je(h),"g"),k);y(u).attr("style",g);}),y("link[href]").each((m,u)=>{let g=y(u).attr("href");g&&a.has(g)&&y(u).attr("href",a.get(g));});let f=y.html(),x=false;if(r&&d>0)try{let m=O__namespace.readFileSync(r,"utf-8"),u=m;for(let[g,h]of a)u=u.replace(new RegExp(je(g),"g"),h);u!==m&&(O__namespace.writeFileSync(r,u,"utf-8"),x=!0,i?.(`Updated source file with CDN URLs: ${r}`));}catch(m){i?.(`Warning: Could not update source file: ${m instanceof Error?m.message:"Unknown error"}`);}return {html:f,uploadedCount:d,failedCount:p,urlMap:a,sourceFileUpdated:x}}function je(o){return o.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}var oe=A__namespace.join(Ue__namespace.tmpdir(),"lindoai-pages-preview.pid"),ge=A__namespace.join(Ue__namespace.tmpdir(),"lindoai-pages-preview.port");function qe(){let o=new commander.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 e=>{let n=Q();try{let t=await n.pages.list(e.website,{page:parseInt(e.page,10),search:e.search});if(e.format==="json")w(t,"json");else {let i=t.result;if(i?.list&&i.list.length>0){console.log(`
53
+ Pages:`),console.log("------");for(let r of i.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: ${i.total??i.list.length}`);}else s("No pages found");}}catch(t){Z(t);}}),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 e=>{let n=Q();try{let t=await n.pages.get(e.website,e.id);if(e.format==="json")w(t,"json");else {let i=t.result;i?(console.log(`
54
+ Page Details:`),console.log("-------------"),console.log(` ID: ${i.page_id}`),console.log(` Name: ${i.name??"N/A"}`),console.log(` Path: ${i.path??"N/A"}`),console.log(` Status: ${i.status??"N/A"}`),console.log(` Published: ${i.publish_date?"Yes":"No"}`),console.log(` Created: ${i.created_date??"N/A"}`)):l("Page not found");}}catch(t){Z(t);}}),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 e=>{let n=Q();try{let t=await n.pages.unpublish(e.website,e.id);e.format==="json"?w(t,"json"):t.success?(b("Page unpublished successfully"),console.log(` Page ID: ${t.result?.page_id}`)):l("Failed to unpublish page");}catch(t){Z(t);}}),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 e=>{let n=Q();try{let t=await n.pages.deletePage(e.website,e.id);if(e.format==="json")w(t,"json");else if(t.success){if(b("Page deleted successfully"),console.log(` Page ID: ${t.result?.page_id}`),t.result?.warnings&&t.result.warnings.length>0){console.log(" Warnings:");for(let i of t.result.warnings)console.log(` - ${i}`);}}else l("Failed to delete page");}catch(t){Z(t);}}),o.command("create").description("Create a new page with 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(e,n,t)=>{let i=Q();try{s("Fetching website details...");let c=(await i.websites.getDetails(e)).result,a=c?.theme||{},d=c?.global_header||null,p=c?.global_footer||null,v=c?.custom_codes||{header:null,footer:null},y={font:a.font,title_font:a.title_font},f=t.title,x=`<!-- Hero Section -->
41
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">
42
56
  <div class="max-w-4xl mx-auto px-4 sm:px-6 lg:px-8 text-center">
43
57
  <h1 class="text-4xl sm:text-5xl lg:text-6xl font-bold text-neutral-900 dark:text-white mb-6">
44
- ${a}
58
+ ${f}
45
59
  </h1>
46
60
  <p class="text-lg sm:text-xl text-neutral-600 dark:text-neutral-300 mb-8 max-w-2xl mx-auto">
47
61
  Start building your page by editing this template. Add sections, customize styles, and create something amazing.
@@ -113,24 +127,27 @@ Page Details:`),console.log("-------------"),console.log(` ID: ${i.page_id}`),c
113
127
  Contact Us
114
128
  </a>
115
129
  </div>
116
- </section>`,m={theme:{mode:"Dark",direction:"ltr",main_classes:"bg-white dark:bg-neutral-900 text-neutral-900 dark:text-neutral-100",animations_deactivated:!1},should_convert:!0},l={page_title:a,meta_description:"",social_title:a,social_description:"",noindex:!1,nofollow:!1};r("Creating page...");let f=await i.pages.create(e,{html:c,path:n,settings:m,template_name:a,seo:l});f.success||(s("Failed to create page"),process.exit(1));let g=f.result.page_id;p(`Page created: ${g}`);let y=`<!DOCTYPE html>
130
+ </section>`,m={theme:{mode:"Dark",direction:"ltr",main_classes:"bg-white dark:bg-neutral-900 text-neutral-900 dark:text-neutral-100",animations_deactivated:!1},should_convert:!0},u={page_title:f,meta_description:"",social_title:f,social_description:"",noindex:!1,nofollow:!1};s("Creating page...");let g=await i.pages.create(e,{html:x,path:n,settings:m,template_name:f,seo:u});g.success||(l("Failed to create page"),process.exit(1));let h=g.result.page_id;b(`Page created: ${h}`);let k=ue(y),_=Re(x,d??void 0,p??void 0),C={header:v.header||"",footer:v.footer||""},S=`<!DOCTYPE html>
117
131
  <html class="dark" lang="en">
118
132
  <head>
119
133
  <meta charset="UTF-8">
120
134
  <meta name="robots" content="max-snippet:-1, max-image-preview:large, max-video-preview:-1">
121
135
  <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
122
136
 
123
- <title>${a}</title>
137
+ <title>${f}</title>
124
138
  <meta name="description" content="">
125
139
 
126
- <meta property="og:title" content="${a}">
140
+ <meta property="og:title" content="${f}">
127
141
  <meta property="og:description" content="">
128
142
  <meta property="og:type" content="website">
129
143
 
130
144
  <meta name="twitter:card" content="summary_large_image">
131
- <meta name="twitter:title" content="${a}">
145
+ <meta name="twitter:title" content="${f}">
132
146
  <meta name="twitter:description" content="">
133
147
 
148
+ <!-- Google Fonts -->
149
+ ${k}
150
+
134
151
  <!-- Tailwind CSS v4 CDN for preview -->
135
152
  <script src="https://cdn.jsdelivr.net/npm/@tailwindcss/browser@4"></script>
136
153
 
@@ -139,13 +156,15 @@ Page Details:`),console.log("-------------"),console.log(` ID: ${i.page_id}`),c
139
156
  <script src="https://lnui.pages.dev/motion-animate.js"></script>
140
157
 
141
158
  <!-- Page Custom Code (Header) -->
159
+ ${C.header}
160
+ <!-- End Page Custom Code (Header) -->
142
161
 
143
162
  </head>
144
163
  <body>
145
164
  <!-- ========== MAIN CONTENT ========== -->
146
165
  <main dir="ltr" lindo-main-content id="content" role="main" class="bg-white dark:bg-neutral-900 text-neutral-900 dark:text-neutral-100">
147
166
 
148
- ${c}
167
+ ${_}
149
168
 
150
169
  </main>
151
170
  <!-- ========== END MAIN CONTENT ========== -->
@@ -154,48 +173,54 @@ ${c}
154
173
  <script src="https://cdn.ln-cdn.com/staging/js/config2.js"></script>
155
174
 
156
175
  <!-- Page Custom Code (Footer) -->
176
+ ${C.footer}
177
+ <!-- End Page Custom Code (Footer) -->
157
178
  </body>
158
- </html>`,u=L__namespace.resolve(t.file);k__namespace.writeFileSync(u,y,"utf-8"),p(`HTML saved to ${u}`),await Ve(),t.background?await Je(u):await Qe(u),console.log(""),r(`To save changes: lindoai pages update ${e} ${g} --html-file ${t.file}`);}catch(a){W(a);}}),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(e,n,t)=>{let i=K();try{r("Fetching page HTML...");let a=await i.pages.getHtml(e,n);a.result||(s("Page not found"),process.exit(1));let c=a.result.html;c||(s("Page has no HTML content"),r("Make sure the page has been created with HTML content"),process.exit(1));let m=a.result.name||"Page",l=a.result.seo||{},f=a.result.settings||{},g=a.result.custom_codes||{},y=f.theme||{},u=y.mode!=="Light",h=y.direction||"ltr",v=y.main_classes||"",b=y.animations_deactivated||!1,x=`<!DOCTYPE html>
159
- <html class="${u?"dark":""}" lang="en">
179
+ </html>`,F=A__namespace.resolve(t.file);O__namespace.writeFileSync(F,S,"utf-8"),b(`HTML saved to ${F}`),await mt(),t.background?await pt(F):await ut(F),console.log(""),s(`To save changes: lindoai pages update ${e} ${h} --html-file ${t.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(e,n,t)=>{let i=Q();try{s("Fetching page HTML...");let r=await i.pages.getHtml(e,n);r.result||(l("Page not found"),process.exit(1));let c=r.result.html;c||(l("Page has no HTML content"),s("Make sure the page has been created with HTML content"),process.exit(1)),s("Fetching website details...");let d=(await i.websites.getDetails(e)).result,p=d?.theme||{},v=d?.global_header||null,y=d?.global_footer||null,f=d?.custom_codes||{header:null,footer:null},x=r.result.name||"Page",m=r.result.seo||{},u=r.result.settings||{},g=r.result.custom_codes||{},h={header:g.header||f.header||"",footer:g.footer||f.footer||""},k=u.theme||{},_=k.mode!=="Light",C=k.direction||"ltr",S=k.main_classes||"",F=k.animations_deactivated||!1,D={font:k.font||p.font,title_font:k.title_font||p.title_font},I=ue(D),ie=Le(c).mainContent,Y=Re(ie,v??void 0,y??void 0),de=`<!DOCTYPE html>
180
+ <html class="${_?"dark":""}" lang="en">
160
181
  <head>
161
182
  <meta charset="UTF-8">
162
- <meta name="robots" content="max-snippet:-1, max-image-preview:large, max-video-preview:-1 ${l.noindex?"noindex":""} ${l.nofollow?"nofollow":""}">
183
+ <meta name="robots" content="max-snippet:-1, max-image-preview:large, max-video-preview:-1 ${m.noindex?"noindex":""} ${m.nofollow?"nofollow":""}">
163
184
  <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
164
185
 
165
- <title>${l.page_title||m}</title>
166
- <meta name="description" content="${l.meta_description||""}">
186
+ <title>${m.page_title||x}</title>
187
+ <meta name="description" content="${m.meta_description||""}">
167
188
 
168
- <meta property="og:title" content="${l.social_title||l.page_title||m}">
169
- <meta property="og:description" content="${l.social_description||l.meta_description||""}">
170
- ${l.social_image?`<meta property="og:image" content="${l.social_image}">`:""}
189
+ <meta property="og:title" content="${m.social_title||m.page_title||x}">
190
+ <meta property="og:description" content="${m.social_description||m.meta_description||""}">
191
+ ${m.social_image?`<meta property="og:image" content="${m.social_image}">`:""}
171
192
  <meta property="og:type" content="website">
172
- ${l.canonical_url?`<meta property="og:url" content="${l.canonical_url}">`:""}
193
+ ${m.canonical_url?`<meta property="og:url" content="${m.canonical_url}">`:""}
173
194
 
174
195
  <meta name="twitter:card" content="summary_large_image">
175
- <meta name="twitter:title" content="${l.social_title||l.page_title||m}">
176
- <meta name="twitter:description" content="${l.social_description||l.meta_description||""}">
177
- ${l.social_image?`<meta name="twitter:image" content="${l.social_image}">`:""}
196
+ <meta name="twitter:title" content="${m.social_title||m.page_title||x}">
197
+ <meta name="twitter:description" content="${m.social_description||m.meta_description||""}">
198
+ ${m.social_image?`<meta name="twitter:image" content="${m.social_image}">`:""}
199
+
200
+ <!-- Google Fonts -->
201
+ ${I}
178
202
 
179
203
  <!-- Tailwind CSS v4 CDN for preview -->
180
204
  <script src="https://cdn.jsdelivr.net/npm/@tailwindcss/browser@4"></script>
181
205
 
182
- ${b?"":`
206
+ ${F?"":`
183
207
  <!-- Motion for animations -->
184
208
  <script src="https://cdn.jsdelivr.net/npm/motion@latest/dist/motion.js"></script>
185
209
  <script src="https://lnui.pages.dev/motion-animate.js"></script>
186
210
  `}
187
211
 
188
- ${l.canonical_url?`<link rel="canonical" href="${l.canonical_url}">`:""}
212
+ ${m.canonical_url?`<link rel="canonical" href="${m.canonical_url}">`:""}
189
213
 
190
214
  <!-- Page Custom Code (Header) -->
191
- ${g.header||""}
215
+ ${h.header}
216
+ <!-- End Page Custom Code (Header) -->
192
217
 
193
218
  </head>
194
219
  <body>
195
220
  <!-- ========== MAIN CONTENT ========== -->
196
- <main dir="${h}" lindo-main-content id="content" role="main" class="${v}">
221
+ <main dir="${C}" lindo-main-content id="content" role="main" class="${S}">
197
222
 
198
- ${c}
223
+ ${Y}
199
224
 
200
225
  </main>
201
226
  <!-- ========== END MAIN CONTENT ========== -->
@@ -204,9 +229,13 @@ ${c}
204
229
  <script src="https://cdn.ln-cdn.com/staging/js/config2.js"></script>
205
230
 
206
231
  <!-- Page Custom Code (Footer) -->
207
- ${g.footer||""}
232
+ ${h.footer}
233
+ <!-- End Page Custom Code (Footer) -->
208
234
  </body>
209
- </html>`,w=L__namespace.resolve(t.file);k__namespace.writeFileSync(w,x,"utf-8"),p(`HTML saved to ${w}`),await Ve(),t.background?await Je(w):await Qe(w);}catch(a){W(a);}}),o.command("update").description("Update a page").argument("<website_id>","Website ID").argument("<page_id>","Page ID").option("--html-file <path>","Path to local HTML file to upload").option("-f, --format <format>","Output format (json, table)","table").action(async(e,n,t)=>{let i=K();try{t.htmlFile||(s("--html-file option is required"),r("Usage: lindoai pages update <website_id> <page_id> --html-file <path>"),process.exit(1));let a=L__namespace.resolve(t.htmlFile);k__namespace.existsSync(a)||(s(`File not found: ${a}`),process.exit(1));let c=k__namespace.readFileSync(a,"utf-8");r(`Read ${c.length} bytes from ${a}`);let m=c.match(/<main[^>]*>([\s\S]*)<\/main>/i),l=m?m[1].trim():c;m&&r("Extracted content from <main> tag");let f=c.match(/<title>([^<]*)<\/title>/i),g=f?f[1].trim():void 0;g&&r(`Extracted page title: ${g}`);let y="",u="",h=c.match(/<!-- Page Custom Code \(Header\) -->\s*([\s\S]*?)\s*<\/head>/i);h&&h[1].trim()&&(y=h[1].trim(),r("Extracted header custom code"));let v=c.match(/<!-- Page Custom Code \(Footer\) -->\s*([\s\S]*?)\s*<\/body>/i);v&&v[1].trim()&&(u=v[1].trim(),r("Extracted footer custom code"));let b=c.match(/<html[^>]*class="([^"]*)"/i),x=b?b[1].includes("dark"):!0,w=c.match(/<main[^>]*>/i),Z="ltr",ee="";if(w){let De=w[0].match(/dir="([^"]*)"/i);De&&(Z=De[1]);let Re=w[0].match(/class="([^"]*)"/i);Re&&(ee=Re[1]);}let ae=!c.includes("motion@latest"),B=c.match(/<meta\s+name="description"\s+content="([^"]*)"/i),G=c.match(/<meta\s+property="og:title"\s+content="([^"]*)"/i),Y=c.match(/<meta\s+property="og:description"\s+content="([^"]*)"/i),z=c.match(/<meta\s+property="og:image"\s+content="([^"]*)"/i),V=c.match(/<link\s+rel="canonical"\s+href="([^"]*)"/i),dt=c.match(/noindex/i),mt=c.match(/nofollow/i),$={};g&&($.page_title=g),B&&B[1]&&($.meta_description=B[1]),G&&G[1]&&($.social_title=G[1]),Y&&Y[1]&&($.social_description=Y[1]),z&&z[1]&&($.social_image=z[1]),V&&V[1]&&($.canonical_url=V[1]),$.noindex=!!dt,$.nofollow=!!mt,Object.keys($).length>2&&r("Extracted SEO metadata");let se=await i.pages.get(e,n);se.result||(s("Page not found"),process.exit(1));let pt=se.result.path,ut={...se.result.settings||{},theme:{...se.result.settings?.theme||{},mode:x?"Dark":"Light",direction:Z,main_classes:ee,animations_deactivated:ae},should_convert:!0},ce={};y&&(ce.header=y),u&&(ce.footer=u),r("Updating page...");let de=await i.pages.publish(e,n,{html:l,path:pt,settings:ut,template_name:g,custom_codes:Object.keys(ce).length>0?ce:void 0,seo:Object.keys($).length>0?$:void 0});t.format==="json"?d(de,"json"):de.success?(p("Page updated successfully"),console.log(` Page ID: ${de.result?.page_id}`)):s("Failed to update page");}catch(a){W(a);}}),o.command("stop-preview").description("Stop the background preview server").action(async()=>{try{if(!k__namespace.existsSync(H)){r("No preview server is running");return}let e=parseInt(k__namespace.readFileSync(H,"utf-8").trim(),10);if(isNaN(e)){s("Invalid PID file"),Oe();return}try{process.kill(e,"SIGTERM"),p(`Preview server (PID ${e}) stopped`);}catch(n){n.code==="ESRCH"?r("Preview server process not found (may have already stopped)"):s(`Failed to stop preview server: ${n.message}`);}Oe();}catch(e){e instanceof Error?s(e.message):s("An unexpected error occurred"),process.exit(1);}}),o}function K(){S()||(s("API key not configured"),r("Run: lindo config set apiKey <your-api-key>"),r("Or set the LINDO_API_KEY environment variable"),process.exit(1));let o=C();return new lindoai.LindoClient({apiKey:o.apiKey,baseUrl:o.baseUrl})}function W(o){o instanceof lindoai.AuthenticationError&&(s("Authentication failed"),r("Your API key may be invalid or expired"),r("Run: lindo config set apiKey <your-api-key>"),process.exit(1)),o instanceof Error?s(o.message):s("An unexpected error occurred"),process.exit(1);}function Oe(){try{k__namespace.existsSync(H)&&k__namespace.unlinkSync(H);}catch{}try{k__namespace.existsSync(ie)&&k__namespace.unlinkSync(ie);}catch{}}async function Ve(){if(k__namespace.existsSync(H)){try{let o=parseInt(k__namespace.readFileSync(H,"utf-8").trim(),10);if(!isNaN(o))try{process.kill(o,"SIGTERM"),r(`Terminated existing preview server (PID ${o})`),await new Promise(e=>setTimeout(e,500));}catch{}}catch{}Oe();}}async function Je(o){let e=L__namespace.resolve(o),n=`
235
+ </html>`,V=A__namespace.resolve(t.file);O__namespace.writeFileSync(V,de,"utf-8"),b(`HTML saved to ${V}`),await mt(),t.background?await pt(V):await ut(V);}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(e,n,t)=>{let i=Q();try{t.htmlFile||(l("--html-file option is required"),s("Usage: lindoai pages update <website_id> <page_id> --html-file <path>"),process.exit(1));let r=A__namespace.resolve(t.htmlFile);O__namespace.existsSync(r)||(l(`File not found: ${r}`),process.exit(1));let c=O__namespace.readFileSync(r,"utf-8");if(s(`Read ${c.length} bytes from ${r}`),t.uploadAssets){let ye=A__namespace.dirname(r);s("Processing local assets...");let K=await Ne(c,ye,e,i,Pt=>s(Pt),r);K.uploadedCount>0&&(c=K.html,b(`Uploaded ${K.uploadedCount} asset(s) to CDN`),K.failedCount>0&&s(`Warning: ${K.failedCount} asset(s) failed to upload`),K.sourceFileUpdated&&s("Source file updated with CDN URLs (prevents duplicate uploads)"));}let a=c.match(/<main[^>]*>([\s\S]*)<\/main>/i),d=a?a[1].trim():c;a&&s("Extracted content from <main> tag");let p=Le(d),v=p.mainContent,y=p.globalHeader,f=p.globalFooter;y&&s("Detected global header section"),f&&s("Detected global footer section");let x=c.match(/<title>([^<]*)<\/title>/i),m=x?x[1].trim():void 0;m&&s(`Extracted page title: ${m}`);let u="",g="",h=c.match(/<!-- Page Custom Code \(Header\) -->\s*([\s\S]*?)\s*<!-- End Page Custom Code \(Header\) -->/i);h&&h[1].trim()&&(u=h[1].trim(),s("Extracted header custom code"));let k=c.match(/<!-- Page Custom Code \(Footer\) -->\s*([\s\S]*?)\s*<!-- End Page Custom Code \(Footer\) -->/i);k&&k[1].trim()&&(g=k[1].trim(),s("Extracted footer custom code"));let _=c.match(/<html[^>]*class="([^"]*)"/i),C=_?_[1].includes("dark"):!0,S=c.match(/<main[^>]*>/i),F="ltr",D="";if(S){let ye=S[0].match(/dir="([^"]*)"/i);ye&&(F=ye[1]);let K=S[0].match(/class="([^"]*)"/i);K&&(D=K[1]);}let I=!c.includes("motion@latest"),U=c.match(/<meta\s+name="description"\s+content="([^"]*)"/i),ie=c.match(/<meta\s+property="og:title"\s+content="([^"]*)"/i),Y=c.match(/<meta\s+property="og:description"\s+content="([^"]*)"/i),de=c.match(/<meta\s+property="og:image"\s+content="([^"]*)"/i),V=c.match(/<link\s+rel="canonical"\s+href="([^"]*)"/i),Ot=c.match(/noindex/i),$t=c.match(/nofollow/i),N={};m&&(N.page_title=m),U&&U[1]&&(N.meta_description=U[1]),ie&&ie[1]&&(N.social_title=ie[1]),Y&&Y[1]&&(N.social_description=Y[1]),de&&de[1]&&(N.social_image=de[1]),V&&V[1]&&(N.canonical_url=V[1]),N.noindex=!!Ot,N.nofollow=!!$t,Object.keys(N).length>2&&s("Extracted SEO metadata");let be=await i.pages.get(e,n);be.result||(l("Page not found"),process.exit(1));let Tt=be.result.path,Ft={...be.result.settings||{},theme:{...be.result.settings?.theme||{},mode:C?"Dark":"Light",direction:F,main_classes:D,animations_deactivated:I},should_convert:!0},we={};u&&(we.header=u),g&&(we.footer=g),s("Updating page...");let ke=await i.pages.publish(e,n,{html:v,path:Tt,settings:Ft,template_name:m,custom_codes:Object.keys(we).length>0?we:void 0,seo:Object.keys(N).length>0?N:void 0,global_header:y,global_footer:f});t.format==="json"?w(ke,"json"):ke.success?(b("Page updated successfully"),console.log(` Page ID: ${ke.result?.page_id}`)):l("Failed to update page");}catch(r){Z(r);}}),o.command("stop-preview").description("Stop the background preview server").action(async()=>{try{if(!O__namespace.existsSync(oe)){s("No preview server is running");return}let e=parseInt(O__namespace.readFileSync(oe,"utf-8").trim(),10);if(isNaN(e)){l("Invalid PID file"),Ke();return}try{process.kill(e,"SIGTERM"),b(`Preview server (PID ${e}) stopped`);}catch(n){n.code==="ESRCH"?s("Preview server process not found (may have already stopped)"):l(`Failed to stop preview server: ${n.message}`);}Ke();}catch(e){e instanceof Error?l(e.message):l("An unexpected error occurred"),process.exit(1);}}),o.command("publish-folder").description("Publish HTML pages from 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 published without actually publishing").option("-f, --format <format>","Output format (json, table)","table").action(async(e,n,t)=>{let i=Q();try{let r=A__namespace.resolve(n);O__namespace.existsSync(r)||(l(`Folder not found: ${r}`),process.exit(1)),O__namespace.statSync(r).isDirectory()||(l(`Not a directory: ${r}`),process.exit(1));let d=O__namespace.readdirSync(r).filter(f=>f.endsWith(".html"));if(d.length===0&&(l("No HTML files found in folder"),process.exit(1)),s(`Found ${d.length} HTML file(s) to publish`),t.dryRun){console.log(`
236
+ Dry run - would publish:`);for(let f of d){let x=f==="index.html"?t.pathPrefix||"/":`${t.pathPrefix}/${f.replace(".html","")}`;console.log(` ${f} \u2192 ${x}`);}return}let p=[];for(let f of d){let x=A__namespace.join(r,f),m=O__namespace.readFileSync(x,"utf-8");s(`
237
+ Processing: ${f}`),s("Uploading local assets...");let u=await Ne(m,r,e,i,I=>s(` ${I}`));u.uploadedCount>0&&(m=u.html,b(` Uploaded ${u.uploadedCount} asset(s)`));let g,h=m.match(/<main[^>]*>([\s\S]*)<\/main>/i),k=m.match(/<body[^>]*>([\s\S]*)<\/body>/i);h?g=h[1].trim():k?g=k[1].trim():g=m;let _=m.match(/<title>([^<]*)<\/title>/i),C=_?_[1].trim():f.replace(".html",""),S=m.match(/<meta\s+name="description"\s+content="([^"]*)"/i),F={page_title:C,meta_description:S?.[1]||""},D=f==="index.html"?t.pathPrefix||"/":`${t.pathPrefix}/${f.replace(".html","")}`;try{s(` Creating page at ${D}...`);let I=await i.pages.create(e,{html:g,path:D,template_name:C,seo:F,settings:{theme:{mode:"Dark",direction:"ltr"},should_convert:!0}});I.success?(b(` Published: ${f} \u2192 ${D} (${I.result.page_id})`),p.push({file:f,pageId:I.result.page_id,success:!0})):(l(` Failed to publish: ${f}`),p.push({file:f,success:!1,error:"API returned failure"}));}catch(I){let U=I instanceof Error?I.message:"Unknown error";l(` Failed to publish: ${f} - ${U}`),p.push({file:f,success:!1,error:U});}}console.log(`
238
+ --- Summary ---`);let v=p.filter(f=>f.success).length,y=p.filter(f=>!f.success).length;if(t.format==="json")w({results:p,successCount:v,failCount:y},"json");else if(console.log(`Published: ${v}/${p.length} pages`),y>0){console.log(`Failed: ${y} pages`);for(let f of p.filter(x=>!x.success))console.log(` - ${f.file}: ${f.error}`);}}catch(r){Z(r);}}),o}function Q(){P()||(l("API key not configured"),s("Run: lindo config set apiKey <your-api-key>"),s("Or set the LINDO_API_KEY environment variable"),process.exit(1));let o=T();return new lindoai.LindoClient({apiKey:o.apiKey,baseUrl:o.baseUrl})}function Z(o){o instanceof lindoai.AuthenticationError&&(l("Authentication failed"),s("Your API key may be invalid or expired"),s("Run: lindo config set apiKey <your-api-key>"),process.exit(1)),o instanceof Error?l(o.message):l("An unexpected error occurred"),process.exit(1);}function Ke(){try{O__namespace.existsSync(oe)&&O__namespace.unlinkSync(oe);}catch{}try{O__namespace.existsSync(ge)&&O__namespace.unlinkSync(ge);}catch{}}async function mt(){if(O__namespace.existsSync(oe)){try{let o=parseInt(O__namespace.readFileSync(oe,"utf-8").trim(),10);if(!isNaN(o))try{process.kill(o,"SIGTERM"),s(`Terminated existing preview server (PID ${o})`),await new Promise(e=>setTimeout(e,500));}catch{}}catch{}Ke();}}async function pt(o){let e=A__namespace.resolve(o),n=`
210
239
  const http = require('node:http');
211
240
  const fs = require('node:fs');
212
241
  const path = require('node:path');
@@ -326,9 +355,9 @@ ${c}
326
355
  });
327
356
  } catch {}
328
357
  });
329
- `,t=child_process.spawn(process.execPath,["-e",n],{detached:true,stdio:"ignore"});t.unref();let i=null;for(let m=0;m<50;m++)if(await new Promise(l=>setTimeout(l,100)),k__namespace.existsSync(ie))try{if(i=parseInt(k__namespace.readFileSync(ie,"utf-8").trim(),10),!isNaN(i))break}catch{}i||(s("Failed to start preview server"),process.exit(1));let a=`http://127.0.0.1:${i}/`;await R(a)||r(`Could not open browser. Visit: ${a}`),p("Preview server started in background"),console.log(` URL: ${a}`),console.log(` PID: ${t.pid}`),console.log(""),r("To update the page: lindoai pages update <website_id> <page_id> --html-file <path>"),r("To stop the server: lindoai pages stop-preview");}async function Qe(o){let{startLivePreviewServer:e}=await Promise.resolve().then(()=>(Se(),_e));r("Starting preview server...");let n=await e(o),t=`http://127.0.0.1:${n}/`;k__namespace.writeFileSync(H,process.pid.toString(),"utf-8"),k__namespace.writeFileSync(ie,n.toString(),"utf-8"),await R(t)||r(`Could not open browser. Visit: ${t}`),p("Preview server started"),console.log(` URL: ${t}`),console.log(""),r("Press Ctrl+C to stop the server"),r("Edit the HTML file and save to see changes in the browser");}var q=L__namespace.join(ke__namespace.tmpdir(),"lindoai-blogs-preview.pid"),re=L__namespace.join(ke__namespace.tmpdir(),"lindoai-blogs-preview.port");function Te(){let o=new commander.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 e=>{let n=M();try{let t=await n.blogs.list(e.website,{page:parseInt(e.page,10),search:e.search});if(e.format==="json")d(t,"json");else {let i=t.result;if(i?.list&&i.list.length>0){console.log(`
330
- Blogs:`),console.log("------");for(let a of i.list)console.log(` ID: ${a.blog_id}`),console.log(` Name: ${a.name??"N/A"}`),console.log(` Path: ${a.path??"N/A"}`),console.log(` Status: ${a.status??"N/A"}`),console.log(` Published: ${a.publish_date?new Date(a.publish_date*1e3).toISOString():"No"}`),console.log("");console.log(`Total: ${i.total??i.list.length}`);}else r("No blogs found");}}catch(t){U(t);}}),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 e=>{let n=M();try{let t=await n.blogs.get(e.website,e.id);if(e.format==="json")d(t,"json");else {let i=t.result;i?(console.log(`
331
- Blog Details:`),console.log("-------------"),console.log(` ID: ${i.blog_id}`),console.log(` Name: ${i.name??"N/A"}`),console.log(` Path: ${i.path??"N/A"}`),console.log(` Status: ${i.status??"N/A"}`),console.log(` Published: ${i.publish_date?new Date(i.publish_date*1e3).toISOString():"No"}`),console.log(` Created: ${i.created_date??"N/A"}`)):s("Blog not found");}}catch(t){U(t);}}),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 e=>{let n=M();try{let t=await n.blogs.publish(e.website,e.id);e.format==="json"?d(t,"json"):t.success?(p("Blog published successfully"),console.log(` Blog ID: ${t.result?.blog_id}`),console.log(` Published at: ${t.result?.publish_date?new Date(t.result.publish_date*1e3).toISOString():"N/A"}`)):s("Failed to publish blog");}catch(t){U(t);}}),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 e=>{let n=M();try{let t=await n.blogs.unpublish(e.website,e.id);e.format==="json"?d(t,"json"):t.success?(p("Blog unpublished successfully"),console.log(` Blog ID: ${t.result?.blog_id}`)):s("Failed to unpublish blog");}catch(t){U(t);}}),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 e=>{let n=M();try{let t=await n.blogs.delete(e.website,e.id);if(e.format==="json")d(t,"json");else if(t.success){if(p("Blog deleted successfully"),console.log(` Blog ID: ${t.result?.blog_id}`),t.result?.warnings&&t.result.warnings.length>0){console.log(" Warnings:");for(let i of t.result.warnings)console.log(` - ${i}`);}}else s("Failed to delete blog");}catch(t){U(t);}}),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(e,n,t)=>{let i=M();try{r("Fetching blog content...");let a=await i.blogs.getHtml(e,n);a.result||(s("Blog not found"),process.exit(1));let c=a.result,m=await i.websites.getDetails(e);m.result||(s("Website not found"),process.exit(1));let l=m.result,f=c.seo||{},g=c.blog_settings||{},y=c.blog_content||"<p>Start writing your blog content here...</p>",u=tt({seo:f,blogSettings:g,blogContent:y,websiteName:l.business_name||"Blog",blogPath:l.theme?.blog_path||"blog"}),h=L__namespace.resolve(t.file);k__namespace.writeFileSync(h,u,"utf-8"),p(`HTML saved to ${h}`),await Xe(),t.background?await Ze(h):await et(h),console.log(""),r(`To save changes: lindoai blogs update ${e} ${n} --html-file ${t.file}`);}catch(a){U(a);}}),o.command("update").description("Update a blog from HTML file").argument("<website_id>","Website ID").argument("<blog_id>","Blog ID").option("--html-file <path>","Path to local HTML file").option("--md-file <path>","Path to local Markdown file").option("-f, --format <format>","Output format (json, table)","table").action(async(e,n,t)=>{let i=M();try{!t.htmlFile&&!t.mdFile&&(s("Either --html-file or --md-file option is required"),r("Usage: lindoai blogs update <website_id> <blog_id> --html-file <path>"),r(" or: lindoai blogs update <website_id> <blog_id> --md-file <path>"),process.exit(1));let a,c={},m={};if(t.mdFile){let v=L__namespace.resolve(t.mdFile);k__namespace.existsSync(v)||(s(`File not found: ${v}`),process.exit(1));let b=k__namespace.readFileSync(v,"utf-8");r(`Read ${b.length} bytes from ${v}`);let{content:x,frontmatter:w}=io(b);a=ro(x),w.title&&(c.page_title=w.title),w.description&&(c.meta_description=w.description),w.image&&(c.social_image=w.image),w.author&&(m.author=w.author),w.excerpt&&(m.excerpt=w.excerpt),w.category&&(m.category=w.category),w.date&&(m.publish_date=w.date);}else {let v=L__namespace.resolve(t.htmlFile);k__namespace.existsSync(v)||(s(`File not found: ${v}`),process.exit(1));let b=k__namespace.readFileSync(v,"utf-8");r(`Read ${b.length} bytes from ${v}`);let x=b.match(/<article[^>]*class="[^"]*prose[^"]*"[^>]*>([\s\S]*?)<\/article>/i);a=x?x[1].trim():"",a||(s("Could not extract blog content from HTML"),r('Make sure the blog content is inside <article class="...prose...">...</article>'),process.exit(1));let w=b.match(/<title>([^<]*)<\/title>/i),Z=b.match(/<meta\s+name="description"\s+content="([^"]*)"/i),ee=b.match(/<meta\s+property="og:image"\s+content="([^"]*)"/i);w&&(c.page_title=w[1].trim()),Z&&(c.meta_description=Z[1]),ee&&(c.social_image=ee[1]);let ae=b.match(/id="blog-author-display"[^>]*>([^<]*)</i),B=b.match(/class="[^"]*bg-blue-500\/10[^"]*"[^>]*>([^<]*)</i),G=b.match(/class="[^"]*border-l-4 border-blue-500[^"]*"[^>]*>([\s\S]*?)<\/div>/i),Y=b.match(/<time[^>]*>([^<]*)<\/time>/i),z=b.match(/<span>(\d+\s*min\s*read)<\/span>/i),V=b.match(/<div class="aspect-video[^"]*"[^>]*>\s*<img[^>]*src="([^"]*)"/i);ae&&(m.author=ae[1].trim()),B&&(m.category=B[1].trim()),G&&(m.excerpt=G[1].trim()),Y&&(m.publish_date=Y[1].trim()),z&&(m.read_time=z[1].trim()),V&&!c.social_image&&(c.social_image=V[1]),r("Extracted blog content and metadata");}let l=await i.blogs.get(e,n);l.result||(s("Blog not found"),process.exit(1));let f=l.result,g=f.path,y={page_title:c.page_title||f.seo?.page_title||"Untitled",meta_description:c.meta_description||f.seo?.meta_description,social_title:c.social_title||f.seo?.social_title,social_description:c.social_description||f.seo?.social_description,social_image:c.social_image||f.seo?.social_image},u={author:m.author||f.blog_settings?.author||"Anonymous",excerpt:m.excerpt||f.blog_settings?.excerpt,category:m.category||f.blog_settings?.category,publish_date:m.publish_date||f.blog_settings?.publish_date,read_time:m.read_time||f.blog_settings?.read_time,author_image:m.author_image||f.blog_settings?.author_image};r("Updating blog...");let h=await i.blogs.publish(e,n,{path:g,blog_content:a,seo:y,blog_settings:u});t.format==="json"?d(h,"json"):h.success?(p("Blog updated successfully"),console.log(` Blog ID: ${h.result?.blog_id}`)):s("Failed to update blog");}catch(a){U(a);}}),o.command("create").description("Create a new blog with live preview").argument("<website_id>","Website ID").argument("<path>","URL path for the blog (e.g., /blog/my-first-post)").option("--title <title>","Blog title","New Blog Post").option("--author <author>","Author name","Anonymous").option("--file <path>","Output file path","./blog.html").option("--background","Run preview server in background").action(async(e,n,t)=>{let i=M();try{let a=await i.websites.getDetails(e);a.result||(s("Website not found"),process.exit(1));let c=a.result,m=t.title,l=t.author,f=new Date().toLocaleDateString("en-US",{year:"numeric",month:"long",day:"numeric"}),g=`<h2>Introduction</h2>
358
+ `,t=child_process.spawn(process.execPath,["-e",n],{detached:true,stdio:"ignore"});t.unref();let i=null;for(let a=0;a<50;a++)if(await new Promise(d=>setTimeout(d,100)),O__namespace.existsSync(ge))try{if(i=parseInt(O__namespace.readFileSync(ge,"utf-8").trim(),10),!isNaN(i))break}catch{}i||(l("Failed to start preview server"),process.exit(1));let r=`http://127.0.0.1:${i}/`;await X(r)||s(`Could not open browser. Visit: ${r}`),b("Preview server started in background"),console.log(` URL: ${r}`),console.log(` PID: ${t.pid}`),console.log(""),s("To update the page: lindoai pages update <website_id> <page_id> --html-file <path>"),s("To stop the server: lindoai pages stop-preview");}async function ut(o){let{startLivePreviewServer:e}=await Promise.resolve().then(()=>(We(),He));s("Starting preview server...");let n=await e(o),t=`http://127.0.0.1:${n}/`;O__namespace.writeFileSync(oe,process.pid.toString(),"utf-8"),O__namespace.writeFileSync(ge,n.toString(),"utf-8"),await X(t)||s(`Could not open browser. Visit: ${t}`),b("Preview server started"),console.log(` URL: ${t}`),console.log(""),s("Press Ctrl+C to stop the server"),s("Edit the HTML file and save to see changes in the browser");}var ne=A__namespace.join(Ue__namespace.tmpdir(),"lindoai-blogs-preview.pid"),he=A__namespace.join(Ue__namespace.tmpdir(),"lindoai-blogs-preview.port");function Ye(){let o=new commander.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 e=>{let n=ee();try{let t=await n.blogs.list(e.website,{page:parseInt(e.page,10),search:e.search});if(e.format==="json")w(t,"json");else {let i=t.result;if(i?.list&&i.list.length>0){console.log(`
359
+ Blogs:`),console.log("------");for(let r of i.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: ${i.total??i.list.length}`);}else s("No blogs found");}}catch(t){te(t);}}),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 e=>{let n=ee();try{let t=await n.blogs.get(e.website,e.id);if(e.format==="json")w(t,"json");else {let i=t.result;i?(console.log(`
360
+ Blog Details:`),console.log("-------------"),console.log(` ID: ${i.blog_id}`),console.log(` Name: ${i.name??"N/A"}`),console.log(` Path: ${i.path??"N/A"}`),console.log(` Status: ${i.status??"N/A"}`),console.log(` Published: ${i.publish_date?new Date(i.publish_date*1e3).toISOString():"No"}`),console.log(` Created: ${i.created_date??"N/A"}`)):l("Blog not found");}}catch(t){te(t);}}),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 e=>{let n=ee();try{let t=await n.blogs.publish(e.website,e.id);e.format==="json"?w(t,"json"):t.success?(b("Blog published successfully"),console.log(` Blog ID: ${t.result?.blog_id}`),console.log(` Published at: ${t.result?.publish_date?new Date(t.result.publish_date*1e3).toISOString():"N/A"}`)):l("Failed to publish blog");}catch(t){te(t);}}),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 e=>{let n=ee();try{let t=await n.blogs.unpublish(e.website,e.id);e.format==="json"?w(t,"json"):t.success?(b("Blog unpublished successfully"),console.log(` Blog ID: ${t.result?.blog_id}`)):l("Failed to unpublish blog");}catch(t){te(t);}}),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 e=>{let n=ee();try{let t=await n.blogs.delete(e.website,e.id);if(e.format==="json")w(t,"json");else if(t.success){if(b("Blog deleted successfully"),console.log(` Blog ID: ${t.result?.blog_id}`),t.result?.warnings&&t.result.warnings.length>0){console.log(" Warnings:");for(let i of t.result.warnings)console.log(` - ${i}`);}}else l("Failed to delete blog");}catch(t){te(t);}}),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(e,n,t)=>{let i=ee();try{s("Fetching blog content...");let r=await i.blogs.getHtml(e,n);r.result||(l("Blog not found"),process.exit(1));let c=r.result,a=await i.websites.getDetails(e);a.result||(l("Website not found"),process.exit(1));let d=a.result,p=d,v=p?.theme||{},y=p?.custom_codes||{header:null,footer:null},f={font:v.font,title_font:v.title_font},x=c.seo||{},m=c.blog_settings||{},u=c.blog_content||"<p>Start writing your blog content here...</p>",g=bt({seo:x,blogSettings:m,blogContent:u,websiteName:d.business_name||"Blog",blogPath:v.blog_path||"blog",websiteTheme:f,customCodes:{header:y.header||void 0,footer:y.footer||void 0}}),h=A__namespace.resolve(t.file);O__namespace.writeFileSync(h,g,"utf-8"),b(`HTML saved to ${h}`),await ft(),t.background?await gt(h):await ht(h),console.log(""),s(`To save changes: lindoai blogs update ${e} ${n} --html-file ${t.file}`);}catch(r){te(r);}}),o.command("update").description("Update a blog from HTML file").argument("<website_id>","Website ID").argument("<blog_id>","Blog ID").option("--html-file <path>","Path to local HTML file").option("--md-file <path>","Path to local Markdown file").option("-f, --format <format>","Output format (json, table)","table").action(async(e,n,t)=>{let i=ee();try{!t.htmlFile&&!t.mdFile&&(l("Either --html-file or --md-file option is required"),s("Usage: lindoai blogs update <website_id> <blog_id> --html-file <path>"),s(" or: lindoai blogs update <website_id> <blog_id> --md-file <path>"),process.exit(1));let r,c={},a={};if(t.mdFile){let m=A__namespace.resolve(t.mdFile);O__namespace.existsSync(m)||(l(`File not found: ${m}`),process.exit(1));let u=O__namespace.readFileSync(m,"utf-8");s(`Read ${u.length} bytes from ${m}`);let{content:g,frontmatter:h}=So(u);r=Oo(g),h.title&&(c.page_title=h.title),h.description&&(c.meta_description=h.description),h.image&&(c.social_image=h.image),h.author&&(a.author=h.author),h.excerpt&&(a.excerpt=h.excerpt),h.category&&(a.category=h.category),h.date&&(a.publish_date=h.date);}else {let m=A__namespace.resolve(t.htmlFile);O__namespace.existsSync(m)||(l(`File not found: ${m}`),process.exit(1));let u=O__namespace.readFileSync(m,"utf-8");s(`Read ${u.length} bytes from ${m}`);let g=u.match(/<article[^>]*class="[^"]*prose[^"]*"[^>]*>([\s\S]*?)<\/article>/i);r=g?g[1].trim():"",r||(l("Could not extract blog content from HTML"),s('Make sure the blog content is inside <article class="...prose...">...</article>'),process.exit(1));let h=u.match(/<title>([^<]*)<\/title>/i),k=u.match(/<meta\s+name="description"\s+content="([^"]*)"/i),_=u.match(/<meta\s+property="og:image"\s+content="([^"]*)"/i);h&&(c.page_title=h[1].trim()),k&&(c.meta_description=k[1]),_&&(c.social_image=_[1]);let C=u.match(/id="blog-author-display"[^>]*>([\s\S]*?)<\/span>/i),S=u.match(/class="[^"]*bg-blue-500\/10[^"]*"[^>]*>([^<]*)</i),F=u.match(/class="[^"]*border-l-4 border-blue-500[^"]*"[^>]*>([\s\S]*?)<\/div>/i),D=u.match(/<time[^>]*>([^<]*)<\/time>/i),I=u.match(/<span>(\d+\s*min\s*read)<\/span>/i),U=u.match(/<div class="aspect-video[^"]*"[^>]*>\s*<img[^>]*src="([^"]*)"/i);if(C){let Y=C[1].replace(/<[^>]*>/g,"").trim();Y&&(a.author=Y);}S&&(a.category=S[1].trim()),F&&(a.excerpt=F[1].trim()),D&&(a.publish_date=D[1].trim()),I&&(a.read_time=I[1].trim()),U&&!c.social_image&&(c.social_image=U[1]),s("Extracted blog content and metadata");}let d=await i.blogs.get(e,n);d.result||(l("Blog not found"),process.exit(1));let p=d.result,v=p.path,y={page_title:c.page_title||p.seo?.page_title||"Untitled",meta_description:c.meta_description||p.seo?.meta_description,social_title:c.social_title||p.seo?.social_title,social_description:c.social_description||p.seo?.social_description,social_image:c.social_image||p.seo?.social_image},f={author:a.author||p.blog_settings?.author||"Anonymous",excerpt:a.excerpt||p.blog_settings?.excerpt,category:a.category||p.blog_settings?.category,publish_date:a.publish_date||p.blog_settings?.publish_date,read_time:a.read_time||p.blog_settings?.read_time,author_image:a.author_image||p.blog_settings?.author_image};s("Updating blog...");let x=await i.blogs.publish(e,n,{path:v,blog_content:r,seo:y,blog_settings:f});t.format==="json"?w(x,"json"):x.success?(b("Blog updated successfully"),console.log(` Blog ID: ${x.result?.blog_id}`)):l("Failed to update blog");}catch(r){te(r);}}),o.command("create").description("Create a new blog with live preview").argument("<website_id>","Website ID").argument("<path>","URL path for the blog (e.g., /blog/my-first-post)").option("--title <title>","Blog title","New Blog Post").option("--author <author>","Author name","Anonymous").option("--file <path>","Output file path","./blog.html").option("--background","Run preview server in background").action(async(e,n,t)=>{let i=ee();try{let r=await i.websites.getDetails(e);r.result||(l("Website not found"),process.exit(1));let c=r.result,a=c,d=a?.theme||{},p=a?.custom_codes||{header:null,footer:null},v={font:d.font,title_font:d.title_font},y=t.title,f=t.author,x=new Date().toLocaleDateString("en-US",{year:"numeric",month:"long",day:"numeric"}),m=`<h2>Introduction</h2>
332
361
  <p>Welcome to your new blog post! This is a starter template to help you get started. Edit this content to create your own amazing blog post.</p>
333
362
 
334
363
  <h2>Getting Started</h2>
@@ -350,7 +379,7 @@ Blog Details:`),console.log("-------------"),console.log(` ID: ${i.blog_id}`),c
350
379
  console.log(greet('World'));</code></pre>
351
380
 
352
381
  <h2>Conclusion</h2>
353
- <p>Now it's your turn! Replace this content with your own ideas and publish your blog post to share it with the world.</p>`,y={page_title:m,meta_description:`Read ${m} by ${l}`,social_title:m,social_description:`Read ${m} by ${l}`},u={author:l,excerpt:"A new blog post. Edit this excerpt to provide a summary of your content.",publish_date:f,read_time:"3 min read"};r("Creating blog...");let h=await i.blogs.create(e,{path:n,blog_content:g,seo:y,blog_settings:u});h.success||(s("Failed to create blog"),process.exit(1));let v=h.result.blog_id;p(`Blog created: ${v}`);let b=tt({seo:y,blogSettings:u,blogContent:g,websiteName:c.business_name||"Blog",blogPath:c.theme?.blog_path||"blog"}),x=L__namespace.resolve(t.file);k__namespace.writeFileSync(x,b,"utf-8"),p(`HTML saved to ${x}`),await Xe(),t.background?await Ze(x):await et(x),console.log(""),r(`To save changes: lindoai blogs update ${e} ${v} --html-file ${t.file}`);}catch(a){U(a);}}),o.command("stop-preview").description("Stop the background preview server").action(async()=>{try{if(!k__namespace.existsSync(q)){r("No preview server is running");return}let e=parseInt(k__namespace.readFileSync(q,"utf-8").trim(),10);if(isNaN(e)){s("Invalid PID file"),Pe();return}try{process.kill(e,"SIGTERM"),p(`Preview server (PID ${e}) stopped`);}catch(n){n.code==="ESRCH"?r("Preview server process not found (may have already stopped)"):s(`Failed to stop preview server: ${n.message}`);}Pe();}catch(e){e instanceof Error?s(e.message):s("An unexpected error occurred"),process.exit(1);}}),o}function M(){S()||(s("API key not configured"),r("Run: lindo config set apiKey <your-api-key>"),r("Or set the LINDO_API_KEY environment variable"),process.exit(1));let o=C();return new lindoai.LindoClient({apiKey:o.apiKey,baseUrl:o.baseUrl})}function U(o){o instanceof lindoai.AuthenticationError&&(s("Authentication failed"),r("Your API key may be invalid or expired"),r("Run: lindo config set apiKey <your-api-key>"),process.exit(1)),o instanceof Error?s(o.message):s("An unexpected error occurred"),process.exit(1);}function Pe(){try{k__namespace.existsSync(q)&&k__namespace.unlinkSync(q);}catch{}try{k__namespace.existsSync(re)&&k__namespace.unlinkSync(re);}catch{}}async function Xe(){if(k__namespace.existsSync(q)){try{let o=parseInt(k__namespace.readFileSync(q,"utf-8").trim(),10);if(!isNaN(o))try{process.kill(o,"SIGTERM"),r(`Terminated existing preview server (PID ${o})`),await new Promise(e=>setTimeout(e,500));}catch{}}catch{}Pe();}}async function Ze(o){let e=L__namespace.resolve(o),n=`
382
+ <p>Now it's your turn! Replace this content with your own ideas and publish your blog post to share it with the world.</p>`,u={page_title:y,meta_description:`Read ${y} by ${f}`,social_title:y,social_description:`Read ${y} by ${f}`},g={author:f,excerpt:"A new blog post. Edit this excerpt to provide a summary of your content.",publish_date:x,read_time:"3 min read"};s("Creating blog...");let h=await i.blogs.create(e,{path:n,blog_content:m,seo:u,blog_settings:g});h.success||(l("Failed to create blog"),process.exit(1));let k=h.result.blog_id;b(`Blog created: ${k}`);let _=bt({seo:u,blogSettings:g,blogContent:m,websiteName:c.business_name||"Blog",blogPath:d.blog_path||"blog",websiteTheme:v,customCodes:{header:p.header||void 0,footer:p.footer||void 0}}),C=A__namespace.resolve(t.file);O__namespace.writeFileSync(C,_,"utf-8"),b(`HTML saved to ${C}`),await ft(),t.background?await gt(C):await ht(C),console.log(""),s(`To save changes: lindoai blogs update ${e} ${k} --html-file ${t.file}`);}catch(r){te(r);}}),o.command("stop-preview").description("Stop the background preview server").action(async()=>{try{if(!O__namespace.existsSync(ne)){s("No preview server is running");return}let e=parseInt(O__namespace.readFileSync(ne,"utf-8").trim(),10);if(isNaN(e)){l("Invalid PID file"),Ge();return}try{process.kill(e,"SIGTERM"),b(`Preview server (PID ${e}) stopped`);}catch(n){n.code==="ESRCH"?s("Preview server process not found (may have already stopped)"):l(`Failed to stop preview server: ${n.message}`);}Ge();}catch(e){e instanceof Error?l(e.message):l("An unexpected error occurred"),process.exit(1);}}),o}function ee(){P()||(l("API key not configured"),s("Run: lindo config set apiKey <your-api-key>"),s("Or set the LINDO_API_KEY environment variable"),process.exit(1));let o=T();return new lindoai.LindoClient({apiKey:o.apiKey,baseUrl:o.baseUrl})}function te(o){o instanceof lindoai.AuthenticationError&&(l("Authentication failed"),s("Your API key may be invalid or expired"),s("Run: lindo config set apiKey <your-api-key>"),process.exit(1)),o instanceof Error?l(o.message):l("An unexpected error occurred"),process.exit(1);}function Ge(){try{O__namespace.existsSync(ne)&&O__namespace.unlinkSync(ne);}catch{}try{O__namespace.existsSync(he)&&O__namespace.unlinkSync(he);}catch{}}async function ft(){if(O__namespace.existsSync(ne)){try{let o=parseInt(O__namespace.readFileSync(ne,"utf-8").trim(),10);if(!isNaN(o))try{process.kill(o,"SIGTERM"),s(`Terminated existing preview server (PID ${o})`),await new Promise(e=>setTimeout(e,500));}catch{}}catch{}Ge();}}async function gt(o){let e=A__namespace.resolve(o),n=`
354
383
  const http = require('node:http');
355
384
  const fs = require('node:fs');
356
385
  const path = require('node:path');
@@ -470,7 +499,7 @@ console.log(greet('World'));</code></pre>
470
499
  });
471
500
  } catch {}
472
501
  });
473
- `,t=child_process.spawn(process.execPath,["-e",n],{detached:true,stdio:"ignore"});t.unref();let i=null;for(let m=0;m<50;m++)if(await new Promise(l=>setTimeout(l,100)),k__namespace.existsSync(re))try{if(i=parseInt(k__namespace.readFileSync(re,"utf-8").trim(),10),!isNaN(i))break}catch{}i||(s("Failed to start preview server"),process.exit(1));let a=`http://127.0.0.1:${i}/`;await R(a)||r(`Could not open browser. Visit: ${a}`),p("Preview server started in background"),console.log(` URL: ${a}`),console.log(` PID: ${t.pid}`),console.log(""),r("To update the blog: lindoai blogs update <website_id> <blog_id> --html-file <path>"),r("To stop the server: lindoai blogs stop-preview");}async function et(o){let{startLivePreviewServer:e}=await Promise.resolve().then(()=>(Se(),_e));r("Starting preview server...");let n=await e(o),t=`http://127.0.0.1:${n}/`;k__namespace.writeFileSync(q,process.pid.toString(),"utf-8"),k__namespace.writeFileSync(re,n.toString(),"utf-8"),await R(t)||r(`Could not open browser. Visit: ${t}`),p("Preview server started"),console.log(` URL: ${t}`),console.log(""),r("Press Ctrl+C to stop the server"),r("Edit the HTML file and save to see changes in the browser");}function no(o){return o?o.split(" ").map(e=>e.charAt(0).toUpperCase()).slice(0,2).join(""):"?"}function tt(o){let{seo:e,blogSettings:n,blogContent:t,websiteName:i,blogPath:a}=o;return `<!DOCTYPE html>
502
+ `,t=child_process.spawn(process.execPath,["-e",n],{detached:true,stdio:"ignore"});t.unref();let i=null;for(let a=0;a<50;a++)if(await new Promise(d=>setTimeout(d,100)),O__namespace.existsSync(he))try{if(i=parseInt(O__namespace.readFileSync(he,"utf-8").trim(),10),!isNaN(i))break}catch{}i||(l("Failed to start preview server"),process.exit(1));let r=`http://127.0.0.1:${i}/`;await X(r)||s(`Could not open browser. Visit: ${r}`),b("Preview server started in background"),console.log(` URL: ${r}`),console.log(` PID: ${t.pid}`),console.log(""),s("To update the blog: lindoai blogs update <website_id> <blog_id> --html-file <path>"),s("To stop the server: lindoai blogs stop-preview");}async function ht(o){let{startLivePreviewServer:e}=await Promise.resolve().then(()=>(We(),He));s("Starting preview server...");let n=await e(o),t=`http://127.0.0.1:${n}/`;O__namespace.writeFileSync(ne,process.pid.toString(),"utf-8"),O__namespace.writeFileSync(he,n.toString(),"utf-8"),await X(t)||s(`Could not open browser. Visit: ${t}`),b("Preview server started"),console.log(` URL: ${t}`),console.log(""),s("Press Ctrl+C to stop the server"),s("Edit the HTML file and save to see changes in the browser");}function _o(o){return o?o.split(" ").map(e=>e.charAt(0).toUpperCase()).slice(0,2).join(""):"?"}function bt(o){let{seo:e,blogSettings:n,blogContent:t,websiteName:i,blogPath:r,websiteTheme:c,customCodes:a}=o,d=c?ue(c):"";return `<!DOCTYPE html>
474
503
  <html class="dark" lang="en">
475
504
  <head>
476
505
  <meta charset="UTF-8">
@@ -489,9 +518,15 @@ console.log(greet('World'));</code></pre>
489
518
  <meta name="twitter:description" content="${e.social_description||e.meta_description||""}">
490
519
  ${e.social_image?`<meta name="twitter:image" content="${e.social_image}">`:""}
491
520
 
521
+ <!-- Google Fonts -->
522
+ ${d}
523
+
492
524
  <!-- Tailwind CSS v4 CDN for preview -->
493
525
  <script src="https://cdn.jsdelivr.net/npm/@tailwindcss/browser@4"></script>
494
526
 
527
+ <!-- Custom Code (Header) -->
528
+ ${a?.header||""}
529
+
495
530
  <style>
496
531
  /* Required default styles for content */
497
532
  blockquote, dd, dl, figure, h1, h2, h3, h4, h5, h6, hr, p, pre {
@@ -530,7 +565,7 @@ console.log(greet('World'));</code></pre>
530
565
  <div class="max-w-4xl mx-auto px-4 sm:px-6 lg:px-8">
531
566
  <div class="flex justify-between items-center py-4">
532
567
  <div class="flex items-center space-x-2">
533
- <a href="/${a}" class="flex items-center space-x-2 text-gray-600 dark:text-neutral-300 hover:text-gray-900 dark:hover:text-white transition-colors">
568
+ <a href="/${r}" class="flex items-center space-x-2 text-gray-600 dark:text-neutral-300 hover:text-gray-900 dark:hover:text-white transition-colors">
534
569
  <svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
535
570
  <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10 19l-7-7m0 0l7-7m-7 7h18"></path>
536
571
  </svg>
@@ -573,7 +608,7 @@ console.log(greet('World'));</code></pre>
573
608
  <div class="flex flex-wrap items-center gap-4 text-sm text-gray-500 dark:text-neutral-400 mb-8">
574
609
  <div class="flex items-center space-x-2">
575
610
  <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">
576
- ${no(n.author||"Anonymous")}
611
+ ${_o(n.author||"Anonymous")}
577
612
  </div>
578
613
  <span id="blog-author-display" class="font-medium text-neutral-200">
579
614
  ${n.author||"Anonymous"}
@@ -646,11 +681,14 @@ console.log(greet('World'));</code></pre>
646
681
 
647
682
  <!-- Config script -->
648
683
  <script src="https://cdn.ln-cdn.com/staging/js/config2.js"></script>
684
+
685
+ <!-- Custom Code (Footer) -->
686
+ ${a?.footer||""}
649
687
  </body>
650
- </html>`}function io(o){let e={},n=o;if(o.startsWith("---")){let t=o.indexOf("---",3);if(t!==-1){let i=o.slice(3,t).trim();n=o.slice(t+3).trim();for(let a of i.split(`
651
- `)){let c=a.indexOf(":");if(c!==-1){let m=a.slice(0,c).trim(),l=a.slice(c+1).trim();(l.startsWith('"')&&l.endsWith('"')||l.startsWith("'")&&l.endsWith("'"))&&(l=l.slice(1,-1)),e[m]=l;}}}}return {content:n,frontmatter:e}}function ro(o){let e=o;return e=e.replace(/^### (.+)$/gm,"<h3>$1</h3>"),e=e.replace(/^## (.+)$/gm,"<h2>$1</h2>"),e=e.replace(/^# (.+)$/gm,"<h1>$1</h1>"),e=e.replace(/\*\*\*(.+?)\*\*\*/g,"<strong><em>$1</em></strong>"),e=e.replace(/\*\*(.+?)\*\*/g,"<strong>$1</strong>"),e=e.replace(/\*(.+?)\*/g,"<em>$1</em>"),e=e.replace(/```(\w*)\n([\s\S]*?)```/g,"<pre><code>$2</code></pre>"),e=e.replace(/`([^`]+)`/g,"<code>$1</code>"),e=e.replace(/\[([^\]]+)\]\(([^)]+)\)/g,'<a href="$2">$1</a>'),e=e.replace(/!\[([^\]]*)\]\(([^)]+)\)/g,'<img src="$2" alt="$1">'),e=e.replace(/^- (.+)$/gm,"<li>$1</li>"),e=e.replace(/(<li>.*<\/li>\n?)+/g,"<ul>$&</ul>"),e=e.replace(/^\d+\. (.+)$/gm,"<li>$1</li>"),e=e.split(`
652
- `).map(i=>{let a=i.trim();return a?a.startsWith("<")?i:`<p>${a}</p>`:""}).join(`
653
- `),e=e.replace(/<p><\/p>/g,""),e}function nt(){return ot__namespace.randomBytes(32).toString("hex")}function it(o,e){return o===e}function so(o){try{let e=o.startsWith("http")?o:`http://localhost${o}`,t=new url.URL(e).searchParams;return {key:t.get("key")??void 0,state:t.get("state")??void 0,error:t.get("error")??void 0,message:t.get("message")??void 0}}catch{return {}}}function co(){return `<!DOCTYPE html>
688
+ </html>`}function So(o){let e={},n=o;if(o.startsWith("---")){let t=o.indexOf("---",3);if(t!==-1){let i=o.slice(3,t).trim();n=o.slice(t+3).trim();for(let r of i.split(`
689
+ `)){let c=r.indexOf(":");if(c!==-1){let a=r.slice(0,c).trim(),d=r.slice(c+1).trim();(d.startsWith('"')&&d.endsWith('"')||d.startsWith("'")&&d.endsWith("'"))&&(d=d.slice(1,-1)),e[a]=d;}}}}return {content:n,frontmatter:e}}function Oo(o){let e=o;return e=e.replace(/^### (.+)$/gm,"<h3>$1</h3>"),e=e.replace(/^## (.+)$/gm,"<h2>$1</h2>"),e=e.replace(/^# (.+)$/gm,"<h1>$1</h1>"),e=e.replace(/\*\*\*(.+?)\*\*\*/g,"<strong><em>$1</em></strong>"),e=e.replace(/\*\*(.+?)\*\*/g,"<strong>$1</strong>"),e=e.replace(/\*(.+?)\*/g,"<em>$1</em>"),e=e.replace(/```(\w*)\n([\s\S]*?)```/g,"<pre><code>$2</code></pre>"),e=e.replace(/`([^`]+)`/g,"<code>$1</code>"),e=e.replace(/\[([^\]]+)\]\(([^)]+)\)/g,'<a href="$2">$1</a>'),e=e.replace(/!\[([^\]]*)\]\(([^)]+)\)/g,'<img src="$2" alt="$1">'),e=e.replace(/^- (.+)$/gm,"<li>$1</li>"),e=e.replace(/(<li>.*<\/li>\n?)+/g,"<ul>$&</ul>"),e=e.replace(/^\d+\. (.+)$/gm,"<li>$1</li>"),e=e.split(`
690
+ `).map(i=>{let r=i.trim();return r?r.startsWith("<")?i:`<p>${r}</p>`:""}).join(`
691
+ `),e=e.replace(/<p><\/p>/g,""),e}function yt(){return wt__namespace.randomBytes(32).toString("hex")}function xt(o,e){return o===e}function To(o){try{let e=o.startsWith("http")?o:`http://localhost${o}`,t=new url.URL(e).searchParams;return {key:t.get("key")??void 0,state:t.get("state")??void 0,error:t.get("error")??void 0,message:t.get("message")??void 0}}catch{return {}}}function Fo(){return `<!DOCTYPE html>
654
692
  <html lang="en">
655
693
  <head>
656
694
  <meta charset="UTF-8">
@@ -696,7 +734,7 @@ console.log(greet('World'));</code></pre>
696
734
  <p>You can close this window and return to your terminal.</p>
697
735
  </div>
698
736
  </body>
699
- </html>`}function le(o){return `<!DOCTYPE html>
737
+ </html>`}function ve(o){return `<!DOCTYPE html>
700
738
  <html lang="en">
701
739
  <head>
702
740
  <meta charset="UTF-8">
@@ -751,7 +789,7 @@ console.log(greet('World'));</code></pre>
751
789
  <div class="error-message">${o.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;").replace(/'/g,"&#039;")}</div>
752
790
  </div>
753
791
  </body>
754
- </html>`}function lo(){return `<!DOCTYPE html>
792
+ </html>`}function Po(){return `<!DOCTYPE html>
755
793
  <html lang="en">
756
794
  <head>
757
795
  <meta charset="UTF-8">
@@ -789,13 +827,13 @@ console.log(greet('World'));</code></pre>
789
827
  <p>This endpoint is not available.</p>
790
828
  </div>
791
829
  </body>
792
- </html>`}function at(){let o=null,e=null;function n(t,i){let a=t.url||"/",c=t.method||"GET",m=a==="/callback"||a.startsWith("/callback?");if(c!=="GET"||!m){i.writeHead(404,{"Content-Type":"text/html; charset=utf-8"}),i.end(lo());return}let l=so(a);if(!e){i.writeHead(400,{"Content-Type":"text/html; charset=utf-8"}),i.end(le("No pending authorization request"));return}let{expectedState:f,resolve:g,timeoutId:y}=e;if(clearTimeout(y),e=null,l.error){let u=l.message||l.error;i.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),i.end(le(u)),g({success:false,error:u});return}if(!l.state||!it(l.state,f)){let u="State token mismatch - possible CSRF attack";i.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),i.end(le(u)),g({success:false,error:u});return}if(!l.key){let u="No API key received";i.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),i.end(le(u)),g({success:false,error:u});return}i.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),i.end(co()),g({success:true,apiKey:l.key});}return {async start(){return new Promise((t,i)=>{o=Ye__namespace.createServer(n),o.on("error",a=>{i(new Error(`Failed to start callback server: ${a.message}`));}),o.listen(0,"127.0.0.1",()=>{let a=o.address();if(!a||typeof a=="string"){i(new Error("Failed to get server address"));return}let c=a.port,m=`http://127.0.0.1:${c}/callback`;t({port:c,url:m});});})},waitForCallback(t,i){return new Promise(a=>{let c=setTimeout(()=>{e&&(e=null,a({success:false,error:"Login timed out waiting for authorization"}));},i);e={expectedState:t,resolve:a,timeoutId:c};})},async stop(){return new Promise(t=>{e&&(clearTimeout(e.timeoutId),e=null),o?o.close(()=>{o=null,t();}):t();})}}}var po="https://app.lindo.ai",uo=120;function fo(o,e){let n=`http://127.0.0.1:${e}/callback`,t=new URLSearchParams({state:o,callback_url:n});return `${po}/cli/authorize?${t.toString()}`}function Ae(){return new commander.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 e=>{let n=parseInt(e.timeout,10),t=n*1e3,i=e.browser,a=at(),c=false;try{r("Starting authentication flow...");let{port:m}=await a.start();c=!0;let l=nt(),f=fo(l,m);i?(r("Opening browser for authorization..."),await R(f)||(r("Could not open browser automatically."),console.log(`
830
+ </html>`}function kt(){let o=null,e=null;function n(t,i){let r=t.url||"/",c=t.method||"GET",a=r==="/callback"||r.startsWith("/callback?");if(c!=="GET"||!a){i.writeHead(404,{"Content-Type":"text/html; charset=utf-8"}),i.end(Po());return}let d=To(r);if(!e){i.writeHead(400,{"Content-Type":"text/html; charset=utf-8"}),i.end(ve("No pending authorization request"));return}let{expectedState:p,resolve:v,timeoutId:y}=e;if(clearTimeout(y),e=null,d.error){let f=d.message||d.error;i.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),i.end(ve(f)),v({success:false,error:f});return}if(!d.state||!xt(d.state,p)){let f="State token mismatch - possible CSRF attack";i.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),i.end(ve(f)),v({success:false,error:f});return}if(!d.key){let f="No API key received";i.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),i.end(ve(f)),v({success:false,error:f});return}i.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),i.end(Fo()),v({success:true,apiKey:d.key});}return {async start(){return new Promise((t,i)=>{o=ct__namespace.createServer(n),o.on("error",r=>{i(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"){i(new Error("Failed to get server address"));return}let c=r.port,a=`http://127.0.0.1:${c}/callback`;t({port:c,url:a});});})},waitForCallback(t,i){return new Promise(r=>{let c=setTimeout(()=>{e&&(e=null,r({success:false,error:"Login timed out waiting for authorization"}));},i);e={expectedState:t,resolve:r,timeoutId:c};})},async stop(){return new Promise(t=>{e&&(clearTimeout(e.timeoutId),e=null),o?o.close(()=>{o=null,t();}):t();})}}}var Ao="https://app.lindo.ai",Eo=120;function Lo(o,e){let n=`http://127.0.0.1:${e}/callback`,t=new URLSearchParams({state:o,callback_url:n});return `${Ao}/cli/authorize?${t.toString()}`}function Ve(){return new commander.Command("login").description("Authenticate via browser to configure your API key").option("-t, --timeout <seconds>","Timeout in seconds for the login flow",String(Eo)).option("--no-browser","Display the authorization URL without opening the browser").action(async e=>{let n=parseInt(e.timeout,10),t=n*1e3,i=e.browser,r=kt(),c=false;try{s("Starting authentication flow...");let{port:a}=await r.start();c=!0;let d=yt(),p=Lo(d,a);i?(s("Opening browser for authorization..."),await X(p)||(s("Could not open browser automatically."),console.log(`
793
831
  Please open this URL in your browser:`),console.log(`
794
- ${f}
832
+ ${p}
795
833
  `))):(console.log(`
796
834
  Please open this URL in your browser:`),console.log(`
797
- ${f}
798
- `)),r(`Waiting for authorization (timeout: ${n}s)...`);let g=await a.waitForCallback(l,t);g.success&&g.apiKey?(Ke(g.apiKey),p("Successfully authenticated!"),r(`API key saved to: ${E()}`)):(s(g.error||"Authentication failed"),process.exit(1));}catch(m){s(m instanceof Error?m.message:"An unexpected error occurred"),process.exit(1);}finally{c&&await a.stop();}})}var Ee=L__namespace.join(ke__namespace.homedir(),".config","opencode","skills","lindoai"),lt=L__namespace.join(Ee,"SKILL.md"),bo=`---
835
+ ${p}
836
+ `)),s(`Waiting for authorization (timeout: ${n}s)...`);let v=await r.waitForCallback(d,t);v.success&&v.apiKey?(ot(v.apiKey),b("Successfully authenticated!"),s(`API key saved to: ${q()}`)):(l(v.error||"Authentication failed"),process.exit(1));}catch(a){l(a instanceof Error?a.message:"An unexpected error occurred"),process.exit(1);}finally{c&&await r.stop();}})}var Je=A__namespace.join(Ue__namespace.homedir(),".config","opencode","skills","lindoai"),St=A__namespace.join(Je,"SKILL.md"),Do=`---
799
837
  name: lindoai
800
838
  description: Lindo AI CLI - Command-line interface for the Lindo API
801
839
  ---
@@ -869,6 +907,16 @@ lindoai pages update <website_id> <page_id> --html-file ./page.html
869
907
  lindoai pages stop-preview
870
908
  \`\`\`
871
909
 
910
+ ### Important: Global Header/Footer Limitation
911
+
912
+ **Global header and footer sections cannot be updated via the CLI.** When you edit a page locally:
913
+ - The preview shows the website's global header/footer for visual context
914
+ - Any changes you make to global sections are saved with the page only
915
+ - Changes do NOT propagate to other pages or the website settings
916
+ - To update global header/footer across all pages, use the Lindo webapp
917
+
918
+ This is by design - global sections are website-wide settings managed through the webapp.
919
+
872
920
  ## Blog Management
873
921
 
874
922
  ### List Blogs
@@ -963,5 +1011,188 @@ lindoai config set baseUrl <value>
963
1011
  3. **Run preview servers in background mode** (\`--background\`) to keep the terminal available.
964
1012
  4. **Remember to stop preview servers** when done editing with \`stop-preview\`.
965
1013
  5. **Use JSON format** (\`--format json\`) when you need to parse command output programmatically.
966
- `;function wo(){try{let o=process.platform==="win32"?"where opencode":"which opencode";return child_process.execSync(o,{stdio:"ignore"}),!0}catch{return false}}function yo(){try{return r("Installing OpenCode..."),child_process.execSync("npm install -g opencode-ai@latest",{stdio:"inherit"}),!0}catch{return false}}function vo(){k__namespace.existsSync(Ee)||k__namespace.mkdirSync(Ee,{recursive:true}),k__namespace.writeFileSync(lt,bo,"utf-8");}function Le(){return new commander.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 e=>{wo()||(e.install?(yo()||(s("Failed to install OpenCode"),r("Please install manually: npm install -g opencode-ai@latest"),process.exit(1)),p("OpenCode installed successfully")):(s("OpenCode is not installed"),r(""),r("To install OpenCode, run one of the following:"),r(" lindoai agent --install"),r(" npm install -g opencode-ai@latest"),process.exit(1)));try{vo(),r(`Skill file installed to: ${lt}`);}catch(i){s(`Failed to install skill file: ${i instanceof Error?i.message:"Unknown error"}`),process.exit(1);}let n=[];e.model&&n.push("--model",e.model),r("Launching OpenCode...");let t=child_process.spawn("opencode",n,{stdio:"inherit",shell:true});t.on("error",i=>{s(`Failed to launch OpenCode: ${i.message}`),process.exit(1);}),t.on("close",i=>{process.exit(i??0);});})}var Co="1.0.0";function _o(){let o=new commander.Command;return o.name("lindo").description("Command-line interface for the Lindo API").version(Co,"-v, --version","Output the current version").helpOption("-h, --help","Display help for command"),o.addCommand(ge()),o.addCommand(he()),o.addCommand(be()),o.addCommand(we()),o.addCommand(ye()),o.addCommand(ve()),o.addCommand(xe()),o.addCommand($e()),o.addCommand(Te()),o.addCommand(Ae()),o.addCommand(Le()),o.exitOverride(e=>{throw e.code==="commander.help"&&process.exit(0),e.code==="commander.version"&&process.exit(0),e.code==="commander.missingArgument"&&(s(e.message),process.exit(1)),e.code==="commander.unknownCommand"&&(s(e.message),r('Run "lindo --help" for available commands'),process.exit(1)),e}),o}function So(o){s("Authentication failed"),r(""),r("Your API key may be invalid or expired."),r(""),r("To configure your API key:"),r(" 1. Run: lindo config set apiKey <your-api-key>"),r(" 2. Or set the LINDO_API_KEY environment variable"),r(""),r("To get an API key:"),r(" Visit https://app.lindo.ai/settings/api-keys");}async function Oo(){let o=_o();try{await o.parseAsync(process.argv);}catch(e){throw e instanceof lindoai.AuthenticationError&&(So(),process.exit(1)),e}}Oo().catch(o=>{o instanceof Error?s(`Unexpected error: ${o.message}`):s("An unexpected error occurred"),process.exit(1);});
967
- exports.createProgram=_o;
1014
+
1015
+ ## Page Building Guidelines
1016
+
1017
+ ### Structure Requirements
1018
+
1019
+ When building or editing Lindo pages, follow these structure requirements:
1020
+
1021
+ - **Output ONLY content HTML**: Generate only \`<header>\`, \`<section>\` elements, and \`<footer>\`
1022
+ - **NO document wrapper tags**: Do NOT include \`<!DOCTYPE html>\`, \`<html>\`, \`<head>\`, or \`<body>\` tags
1023
+ - **Unique section IDs**: Each section must have a unique id following the pattern: \`_block_name_###\` (e.g., \`_hero_001\`, \`_features_002\`)
1024
+ - **Semantic structure**: Use proper HTML5 semantic elements for accessibility
1025
+
1026
+ Example structure:
1027
+ \`\`\`html
1028
+ <header id="_header_001" class="...">
1029
+ <!-- Navigation content -->
1030
+ </header>
1031
+
1032
+ <section id="_hero_001" class="...">
1033
+ <!-- Hero content -->
1034
+ </section>
1035
+
1036
+ <section id="_features_002" class="...">
1037
+ <!-- Features content -->
1038
+ </section>
1039
+
1040
+ <footer id="_footer_001" class="...">
1041
+ <!-- Footer content -->
1042
+ </footer>
1043
+ \`\`\`
1044
+
1045
+ ### Tailwind CSS v3.4 Usage
1046
+
1047
+ Lindo pages use Tailwind CSS v3.4 for styling:
1048
+
1049
+ - **Utility-first approach**: Use Tailwind utility classes for all styling
1050
+ - **No custom CSS**: Avoid writing custom CSS; use Tailwind utilities instead
1051
+ - **NO font family classes**: Do NOT use \`font-sans\`, \`font-serif\`, \`font-mono\`, or any \`font-[family]\` classes - fonts are managed by the theme system
1052
+ - **Responsive design**: Use responsive prefixes (\`sm:\`, \`md:\`, \`lg:\`, \`xl:\`, \`2xl:\`) for all breakpoints
1053
+ - **Dark mode support**: Always include dark mode variants using the \`dark:\` prefix
1054
+ - **Neutral shades**: Use neutral color shades for text and surfaces (e.g., \`text-neutral-900 dark:text-neutral-100\`)
1055
+
1056
+ Example:
1057
+ \`\`\`html
1058
+ <div class="px-4 py-8 md:px-8 lg:px-16 bg-white dark:bg-neutral-900">
1059
+ <h1 class="text-3xl md:text-4xl lg:text-5xl text-neutral-900 dark:text-white">
1060
+ Welcome
1061
+ </h1>
1062
+ </div>
1063
+ \`\`\`
1064
+
1065
+ ### Animation System
1066
+
1067
+ Lindo uses a custom animation system with \`data-motion\` attributes for scroll-triggered animations:
1068
+
1069
+ **Available animation types:**
1070
+ - \`fade\` - Simple fade in
1071
+ - \`fade-up\` - Fade in while moving up
1072
+ - \`fade-down\` - Fade in while moving down
1073
+ - \`fade-left\` - Fade in while moving from left
1074
+ - \`fade-right\` - Fade in while moving from right
1075
+ - \`scale\` - Scale up while fading in
1076
+ - \`card\` - Card entrance animation
1077
+ - \`heading\` - Heading text animation
1078
+ - \`text\` - Body text animation
1079
+ - \`image\` - Image reveal animation
1080
+ - \`button\` - Button entrance animation
1081
+
1082
+ **Usage:**
1083
+ \`\`\`html
1084
+ <section data-motion="fade-up">
1085
+ <h2 data-motion="heading">Section Title</h2>
1086
+ <p data-motion="text">Section description text.</p>
1087
+ <img data-motion="image" src="..." alt="..." />
1088
+ <button data-motion="button">Click Me</button>
1089
+ </section>
1090
+ \`\`\`
1091
+
1092
+ **Animation delays:** Use \`data-motion-delay\` for staggered animations:
1093
+ \`\`\`html
1094
+ <div data-motion="fade-up" data-motion-delay="0">First item</div>
1095
+ <div data-motion="fade-up" data-motion-delay="100">Second item</div>
1096
+ <div data-motion="fade-up" data-motion-delay="200">Third item</div>
1097
+ \`\`\`
1098
+
1099
+ ### Logo Requirements
1100
+
1101
+ When adding logos to pages, use the \`lindo-image-logo\` attribute:
1102
+
1103
+ **Logo types:**
1104
+ - \`full\` - Full logo (icon + text)
1105
+ - \`icon\` - Icon only
1106
+ - \`text\` - Text only
1107
+
1108
+ **Usage:**
1109
+ \`\`\`html
1110
+ <!-- Full logo -->
1111
+ <img lindo-image-logo="full" src="https://cdn.ln-cdn.com/image/placeholder-logo-full.png" alt="Logo" class="h-8" />
1112
+
1113
+ <!-- Icon only -->
1114
+ <img lindo-image-logo="icon" src="https://cdn.ln-cdn.com/image/placeholder-logo-icon.png" alt="Logo" class="h-8 w-8" />
1115
+
1116
+ <!-- Text only -->
1117
+ <img lindo-image-logo="text" src="https://cdn.ln-cdn.com/image/placeholder-logo-text.png" alt="Logo" class="h-6" />
1118
+ \`\`\`
1119
+
1120
+ **Important:**
1121
+ - Do NOT add text or brand names as logo alternatives
1122
+ - Always use the \`lindo-image-logo\` attribute for logos
1123
+ - The actual logo will be replaced with the website's configured logo
1124
+
1125
+ ### Theme Guidelines
1126
+
1127
+ Follow these theme guidelines for consistent light and dark mode support:
1128
+
1129
+ **Light and Dark Mode:**
1130
+ - Every element must specify both light and dark styles
1131
+ - Use the \`dark:\` prefix for dark mode variants
1132
+ - Test both modes to ensure readability and contrast
1133
+
1134
+ **Color Palette:**
1135
+ - Use Tailwind's default color palette
1136
+ - Primary colors: Use brand colors from the theme
1137
+ - Text colors: \`text-neutral-900 dark:text-white\` for headings, \`text-neutral-600 dark:text-neutral-400\` for body text
1138
+ - Background colors: \`bg-white dark:bg-neutral-900\` for main backgrounds
1139
+ - Surface colors: \`bg-neutral-50 dark:bg-neutral-800\` for cards and elevated surfaces
1140
+
1141
+ **Gradients:**
1142
+ - Apply gradient backgrounds where appropriate for visual interest
1143
+ - Example: \`bg-gradient-to-br from-blue-500 to-purple-600\`
1144
+
1145
+ **Example with full theme support:**
1146
+ \`\`\`html
1147
+ <section class="py-16 bg-white dark:bg-neutral-900">
1148
+ <div class="container mx-auto px-4">
1149
+ <h2 class="text-3xl text-neutral-900 dark:text-white mb-4">
1150
+ Section Title
1151
+ </h2>
1152
+ <p class="text-neutral-600 dark:text-neutral-400 mb-8">
1153
+ Section description with proper contrast in both modes.
1154
+ </p>
1155
+ <div class="bg-neutral-50 dark:bg-neutral-800 rounded-lg p-6">
1156
+ <p class="text-neutral-700 dark:text-neutral-300">
1157
+ Card content with elevated surface.
1158
+ </p>
1159
+ </div>
1160
+ </div>
1161
+ </section>
1162
+ \`\`\`
1163
+
1164
+ ### Core Rules
1165
+
1166
+ Follow these core rules when building pages:
1167
+
1168
+ 1. **No font family classes**: Never use \`font-sans\`, \`font-serif\`, \`font-mono\`, or custom font classes. The theme system manages fonts.
1169
+
1170
+ 2. **Responsive design is required**: All pages must be fully responsive. Use Tailwind's responsive prefixes:
1171
+ - Mobile first: Start with base styles
1172
+ - \`sm:\` - Small screens (640px+)
1173
+ - \`md:\` - Medium screens (768px+)
1174
+ - \`lg:\` - Large screens (1024px+)
1175
+ - \`xl:\` - Extra large screens (1280px+)
1176
+ - \`2xl:\` - 2X large screens (1536px+)
1177
+
1178
+ 3. **Accessibility considerations**:
1179
+ - Use semantic HTML elements (\`<header>\`, \`<nav>\`, \`<main>\`, \`<section>\`, \`<footer>\`)
1180
+ - Include \`alt\` attributes on all images
1181
+ - Ensure sufficient color contrast (WCAG AA minimum)
1182
+ - Use proper heading hierarchy (h1 \u2192 h2 \u2192 h3)
1183
+ - Add \`aria-label\` attributes to interactive elements without visible text
1184
+
1185
+ 4. **Image handling**:
1186
+ - Use responsive images with appropriate sizes
1187
+ - Include descriptive \`alt\` text
1188
+ - Use lazy loading for below-the-fold images: \`loading="lazy"\`
1189
+
1190
+ 5. **Link handling**:
1191
+ - Use descriptive link text (avoid "click here")
1192
+ - External links should have \`target="_blank"\` and \`rel="noopener noreferrer"\`
1193
+
1194
+ 6. **Container patterns**:
1195
+ - Use \`container mx-auto px-4\` for consistent content width
1196
+ - Apply consistent vertical padding: \`py-12 md:py-16 lg:py-20\`
1197
+ `;function No(){try{let o=process.platform==="win32"?"where opencode":"which opencode";return child_process.execSync(o,{stdio:"ignore"}),!0}catch{return false}}function Uo(){try{return s("Installing OpenCode..."),child_process.execSync("npm install -g opencode-ai@latest",{stdio:"inherit"}),!0}catch{return false}}function Mo(){O__namespace.existsSync(Je)||O__namespace.mkdirSync(Je,{recursive:true}),O__namespace.writeFileSync(St,Do,"utf-8");}function Qe(){return new commander.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 e=>{No()||(e.install?(Uo()||(l("Failed to install OpenCode"),s("Please install manually: npm install -g opencode-ai@latest"),process.exit(1)),b("OpenCode installed successfully")):(l("OpenCode is not installed"),s(""),s("To install OpenCode, run one of the following:"),s(" lindoai agent --install"),s(" npm install -g opencode-ai@latest"),process.exit(1)));try{Mo(),s(`Skill file installed to: ${St}`);}catch(i){l(`Failed to install skill file: ${i instanceof Error?i.message:"Unknown error"}`),process.exit(1);}let n=[];e.model&&n.push("--model",e.model),s("Launching OpenCode...");let t=child_process.spawn("opencode",n,{stdio:"inherit",shell:true});t.on("error",i=>{l(`Failed to launch OpenCode: ${i.message}`),process.exit(1);}),t.on("close",i=>{process.exit(i??0);});})}var Ko="1.0.0";function Bo(){let o=new commander.Command;return o.name("lindo").description("Command-line interface for the Lindo API").version(Ko,"-v, --version","Output the current version").helpOption("-h, --help","Display help for command"),o.addCommand($e()),o.addCommand(Te()),o.addCommand(Fe()),o.addCommand(Pe()),o.addCommand(Ie()),o.addCommand(Ae()),o.addCommand(Ee()),o.addCommand(qe()),o.addCommand(Ye()),o.addCommand(Ve()),o.addCommand(Qe()),o.exitOverride(e=>{throw e.code==="commander.help"&&process.exit(0),e.code==="commander.version"&&process.exit(0),e.code==="commander.missingArgument"&&(l(e.message),process.exit(1)),e.code==="commander.unknownCommand"&&(l(e.message),s('Run "lindo --help" for available commands'),process.exit(1)),e}),o}function qo(o){l("Authentication failed"),s(""),s("Your API key may be invalid or expired."),s(""),s("To configure your API key:"),s(" 1. Run: lindo config set apiKey <your-api-key>"),s(" 2. Or set the LINDO_API_KEY environment variable"),s(""),s("To get an API key:"),s(" Visit https://app.lindo.ai/settings/api-keys");}async function Go(){let o=Bo();try{await o.parseAsync(process.argv);}catch(e){throw e instanceof lindoai.AuthenticationError&&(qo(),process.exit(1)),e}}Go().catch(o=>{o instanceof Error?l(`Unexpected error: ${o.message}`):l("An unexpected error occurred"),process.exit(1);});
1198
+ exports.createProgram=Bo;