klaudius 0.17.4 → 0.18.0

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.
@@ -0,0 +1,6 @@
1
+ import{appendFileSync as g}from"fs";import{tmpdir as k}from"os";import{join as b}from"path";var u=b(k(),"klaudius-wizard-debug.log"),y=process.env.KLAUDIUS_WIZARD_DEBUG==="1",h=!1;function T(e,t){if(y)try{h||(h=!0,g(u,`
2
+ === klaudius wizard debug session \u2014 ${new Date().toISOString()} ===
3
+ node ${process.version}, platform ${process.platform}, tty=${process.stdin.isTTY}
4
+ `));let n=`${Date.now()} `,o=t===void 0?"":" "+JSON.stringify(t,null,0).slice(0,400);g(u,n+e+o+`
5
+ `)}catch{}}var E=u,p=!1;function G(){if(p)return;p=!0;let e=process.exit.bind(process);process.exit=(t=>{let n=new Error("process.exit called").stack??"(no stack)";return T("process.exit called",{code:t,stack:n.split(`
6
+ `).slice(0,8).join(" | ")}),e(t)})}function c(e){if(!(e instanceof Error))return String(e);let t=e.cause;if(!t||!(t instanceof Error))return e.message;let n=t.code,o=t.message;return n&&o&&o!==n?`${e.message} (${n}: ${o})`:n?`${e.message} (${n})`:o?`${e.message} (${o})`:e.message}async function O(e){let t;try{let s=await fetch(`https://api.telegram.org/bot${encodeURIComponent(e.botToken)}/getUpdates`);if(t=await s.json(),!t.ok){let r=t.description??`HTTP ${s.status}`;return/webhook/i.test(r)?{ok:!1,reason:"webhook_set",message:"This bot has a webhook set, so getUpdates is unavailable. Auto-detect can't run; you'll need to paste the chat ID manually."}:{ok:!1,reason:"bad_token",message:`Telegram rejected the bot token: ${r}. Double-check the token from @BotFather.`}}}catch(s){return{ok:!1,reason:"network",message:`Could not reach Telegram: ${c(s)}`}}let n=t.result??[];if(n.length===0)return{ok:!1,reason:"no_messages",message:"No messages yet. Send your bot a regular text message in Telegram, then retry."};let o=n[n.length-1],a=o?.message?.chat?.id??o?.edited_message?.chat?.id??o?.channel_post?.chat?.id;return a===void 0?{ok:!1,reason:"no_messages",message:"Got an update from Telegram but couldn't find a chat ID in it. Send another text message and retry."}:{ok:!0,chatId:String(a)}}async function $(e){try{let t=await fetch(`https://api.telegram.org/bot${encodeURIComponent(e.botToken)}/getMe`),n=await t.json();return n.ok?{ok:!0,botHandle:n.result?.username?`@${n.result.username}`:n.result?.first_name}:{ok:!1,failedAt:"token",message:`Telegram rejected the bot token: ${n.description??`HTTP ${t.status}`}. Generate a new token by messaging @BotFather \u2192 /mytoken or /newbot.`}}catch(t){return{ok:!1,failedAt:"token",message:`Could not reach Telegram: ${c(t)}`}}}async function H(e){let t=await $({botToken:e.botToken});if(!t.ok)return t;let n=t.botHandle;try{let o=await fetch(`https://api.telegram.org/bot${encodeURIComponent(e.botToken)}/sendMessage`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({chat_id:e.chatId,text:"\u2713 Klaudius connected. You'll get a notification here whenever outreach lands or a candidate replies. (You can ignore this setup message.)",disable_notification:!0})}),a=await o.json();if(!a.ok){let s=a.description??`HTTP ${o.status}`,r="";return/chat not found/i.test(s)?r=" The chat_id is wrong, or the bot hasn't been added to that chat yet. If it's a group, you must add the bot to the group first; then send /start to it.":(/bot was blocked/i.test(s)||/forbidden/i.test(s))&&(r=" The bot has been blocked by the chat, or never received a /start. Open Telegram, find your bot, and send /start to wake it up."),{ok:!1,failedAt:"chat",botHandle:n,message:`Telegram delivered the bot token check but couldn't send to chat_id ${e.chatId}: ${s}.${r}`}}}catch(o){return{ok:!1,failedAt:"chat",botHandle:n,message:`Could not reach Telegram for chat_id check: ${c(o)}`}}return{ok:!0,botHandle:n}}var x={\u0410:"A",\u0430:"a",\u0412:"B",\u0432:"b",\u0415:"E",\u0435:"e",\u041A:"K",\u043A:"k",\u041C:"M",\u043C:"m",\u041D:"H",\u043D:"h",\u041E:"O",\u043E:"o",\u0420:"P",\u0440:"p",\u0421:"C",\u0441:"c",\u0422:"T",\u0442:"t",\u0423:"Y",\u0443:"y",\u0425:"X",\u0445:"x",\u0406:"I",\u0456:"i",\u0405:"S",\u0455:"s",\u0408:"J",\u0458:"j",\u0417:"3",\u0437:"3",\u0427:"4",\u0431:"6",\u0391:"A",\u03B1:"a",\u0392:"B",\u03B2:"b",\u0395:"E",\u03B5:"e",\u0396:"Z",\u0397:"H",\u0399:"I",\u03B9:"i",\u039A:"K",\u03BA:"k",\u039C:"M",\u039D:"N",\u039F:"O",\u03BF:"o",\u03A1:"P",\u03C1:"p",\u03A4:"T",\u03C4:"t",\u03A5:"Y",\u03A7:"X",\u03C7:"x",\u03BD:"v","\u2010":"-","\u2011":"-","\u2012":"-","\u2013":"-","\u2014":"-","\u2015":"-","\u2212":"-","\uFF3F":"_"},C=/[\u200B-\u200F\u202A-\u202E\u2060\uFEFF\u00AD]/g,w=/[\u0000-\u001F\u007F]/g;function I(e){let t=e.replace(C,"").replace(w,"").trim();return{value:t,changed:t!==e,repairs:[],unrepairable:[]}}function f(e){let n=I(e).value.normalize("NFKC").replace(/\s+/g,"");n.length>=2&&(n[0]==='"'&&n.at(-1)==='"'||n[0]==="'"&&n.at(-1)==="'")&&(n=n.slice(1,-1).trim());let o=[],a=[],s="";for(let r of n){let i=r.codePointAt(0);if(i<128){s+=r;continue}let l=x[r],d=s.length+1;l?(o.push(`position ${d}: '${r}' (${v(i)}, U+${m(i)}) \u2192 '${l}'`),s+=l):(a.push({position:d,char:r,code:i}),s+=r)}return{value:s,changed:s!==e,repairs:o,unrepairable:a}}var A=/^AIza[0-9A-Za-z_-]{35}$/;function _(e){return A.test(e)}function B(e){let t=f(e);if(t.value.length===0)return"Required \u2014 without this Klaudius can't find candidates.";if(t.unrepairable.length>0){let n=t.unrepairable[0];return`Character ${n.position} of this key is '${n.char}' (U+${m(n.code)}), which isn't a character a Google key can contain. Copy the key with the copy button next to it in the Cloud Console \u2014 reading it off a screenshot or retyping it introduces look-alike characters.`}}function j(e){let t=f(e).value;if(!_(t))return t.startsWith("AIza")?t.length!==39?`A Google API key is normally 39 characters \u2014 this one is ${t.length}. `+(t.length>39?"It looks like two keys ran together, so paste just the one key.":"It looks truncated, so copy it again with the copy button next to it in the Cloud Console."):"This key contains characters a Google key normally doesn't. Re-copy it with the copy button in the Cloud Console.":`A Google API key normally starts with "AIza" \u2014 this one starts with "${t.slice(0,4)}". Check you copied the API key itself (Cloud Console \u2192 Credentials), not a project ID or client ID.`}function m(e){return e.toString(16).toUpperCase().padStart(4,"0")}function v(e){return e>=1024&&e<=1279?"Cyrillic":e>=880&&e<=1023?"Greek":"non-Latin"}export{T as a,E as b,G as c,c as d,O as e,$ as f,H as g,I as h,f as i,B as j,j as k};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "klaudius",
3
- "version": "0.17.4",
3
+ "version": "0.18.0",
4
4
  "description": "Scaffold and maintain a Klaudius project — an autonomous web agency pipeline that runs on Claude Code (find, build, deploy, outreach end-to-end).",
5
5
  "homepage": "https://klaudius.dev",
6
6
  "bugs": {
@@ -26,6 +26,7 @@
26
26
  "scripts": {
27
27
  "build": "tsup",
28
28
  "dev": "tsx src/bin.ts",
29
+ "test": "npm run build && tsx test/lib-tests.ts && tsx test/masked-prefill-pty-test.ts && tsx test/configure-outro-test.ts && tsx test/init-scaffolded-test.ts",
29
30
  "prepublishOnly": "npm run build"
30
31
  },
31
32
  "engines": {
@@ -1,6 +0,0 @@
1
- import{appendFileSync as d}from"fs";import{tmpdir as g}from"os";import{join as m}from"path";var c=m(g(),"klaudius-wizard-debug.log"),h=process.env.KLAUDIUS_WIZARD_DEBUG==="1",l=!1;function f(o,e){if(h)try{l||(l=!0,d(c,`
2
- === klaudius wizard debug session \u2014 ${new Date().toISOString()} ===
3
- node ${process.version}, platform ${process.platform}, tty=${process.stdin.isTTY}
4
- `));let t=`${Date.now()} `,s=e===void 0?"":" "+JSON.stringify(e,null,0).slice(0,400);d(c,t+o+s+`
5
- `)}catch{}}var y=c,u=!1;function w(){if(u)return;u=!0;let o=process.exit.bind(process);process.exit=(e=>{let t=new Error("process.exit called").stack??"(no stack)";return f("process.exit called",{code:e,stack:t.split(`
6
- `).slice(0,8).join(" | ")}),o(e)})}function i(o){if(!(o instanceof Error))return String(o);let e=o.cause;if(!e||!(e instanceof Error))return o.message;let t=e.code,s=e.message;return t&&s&&s!==t?`${o.message} (${t}: ${s})`:t?`${o.message} (${t})`:s?`${o.message} (${s})`:o.message}async function I(o){let e;try{let n=await fetch(`https://api.telegram.org/bot${encodeURIComponent(o.botToken)}/getUpdates`);if(e=await n.json(),!e.ok){let a=e.description??`HTTP ${n.status}`;return/webhook/i.test(a)?{ok:!1,reason:"webhook_set",message:"This bot has a webhook set, so getUpdates is unavailable. Auto-detect can't run; you'll need to paste the chat ID manually."}:{ok:!1,reason:"bad_token",message:`Telegram rejected the bot token: ${a}. Double-check the token from @BotFather.`}}}catch(n){return{ok:!1,reason:"network",message:`Could not reach Telegram: ${i(n)}`}}let t=e.result??[];if(t.length===0)return{ok:!1,reason:"no_messages",message:"No messages yet. Send your bot a regular text message in Telegram, then retry."};let s=t[t.length-1],r=s?.message?.chat?.id??s?.edited_message?.chat?.id??s?.channel_post?.chat?.id;return r===void 0?{ok:!1,reason:"no_messages",message:"Got an update from Telegram but couldn't find a chat ID in it. Send another text message and retry."}:{ok:!0,chatId:String(r)}}async function p(o){try{let e=await fetch(`https://api.telegram.org/bot${encodeURIComponent(o.botToken)}/getMe`),t=await e.json();return t.ok?{ok:!0,botHandle:t.result?.username?`@${t.result.username}`:t.result?.first_name}:{ok:!1,failedAt:"token",message:`Telegram rejected the bot token: ${t.description??`HTTP ${e.status}`}. Generate a new token by messaging @BotFather \u2192 /mytoken or /newbot.`}}catch(e){return{ok:!1,failedAt:"token",message:`Could not reach Telegram: ${i(e)}`}}}async function A(o){let e=await p({botToken:o.botToken});if(!e.ok)return e;let t=e.botHandle;try{let s=await fetch(`https://api.telegram.org/bot${encodeURIComponent(o.botToken)}/sendMessage`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({chat_id:o.chatId,text:"\u2713 Klaudius connected. You'll get a notification here whenever outreach lands or a candidate replies. (You can ignore this setup message.)",disable_notification:!0})}),r=await s.json();if(!r.ok){let n=r.description??`HTTP ${s.status}`,a="";return/chat not found/i.test(n)?a=" The chat_id is wrong, or the bot hasn't been added to that chat yet. If it's a group, you must add the bot to the group first; then send /start to it.":(/bot was blocked/i.test(n)||/forbidden/i.test(n))&&(a=" The bot has been blocked by the chat, or never received a /start. Open Telegram, find your bot, and send /start to wake it up."),{ok:!1,failedAt:"chat",botHandle:t,message:`Telegram delivered the bot token check but couldn't send to chat_id ${o.chatId}: ${n}.${a}`}}}catch(s){return{ok:!1,failedAt:"chat",botHandle:t,message:`Could not reach Telegram for chat_id check: ${i(s)}`}}return{ok:!0,botHandle:t}}export{f as a,y as b,w as c,i as d,I as e,p as f,A as g};