@spfunctions/cli 2.0.15 → 2.0.18
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/12.index.js +1 -1
- package/dist/160.index.js +1 -1
- package/dist/174.index.js +1 -1
- package/dist/582.index.js +1 -1
- package/dist/641.index.js +1 -1
- package/dist/669.index.js +1 -1
- package/dist/index.js +1 -1
- package/package.json +2 -2
- package/dist/278.index.js +0 -6
- package/dist/830.index.js +0 -1
package/dist/12.index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";exports.id=12,exports.ids=[12],exports.modules={6012:function(e,t,a){var s=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0}),t.startBot=async function(e){const t=(0,l.loadConfig)(),s=e.token||t.telegramBotToken||process.env.TELEGRAM_BOT_TOKEN;s||(console.error("No Telegram bot token. Use --token, set TELEGRAM_BOT_TOKEN, or add to ~/.sf/config.json"),process.exit(1));const o=new c.SFClient(t.apiKey,t.apiUrl),f=new i.Bot(s),y=e.chatId||null,m=new Map;function w(e){return!y||e===y}async function $(e,t){const a=g(e);a.thesisId=t.id,a.agentMessages=[],a.agent=void 0,m.has(e)&&clearInterval(m.get(e)),m.set(e,(0,p.startPoller)(f,e,o,a.thesisId))}f.command("start",async e=>{if(!w(e.chat.id))return;g(e.chat.id);try{const{theses:t}=await o.listTheses(),a=(t||[]).filter(e=>"active"===e.status);if(0===a.length)return void await e.reply('No active theses found. Create one with `sf create "your thesis"`');if(1===a.length)await $(e.chat.id,a[0]),await e.reply(`✅ Connected\n\nThesis: <b>${(a[0].rawThesis||"").slice(0,80)}</b>\nID: <code>${a[0].id.slice(0,8)}</code>\n\nType naturally, send voice, or use /help`,{parse_mode:"HTML"});else{const t=new i.InlineKeyboard;for(const e of a.slice(0,8)){const a=`${(e.rawThesis||e.id).slice(0,40)}`;t.text(a,`pick_thesis:${e.id}`).row()}await e.reply(`✅ Connected — ${a.length} active theses\n\nPick one:`,{parse_mode:"HTML",reply_markup:t})}}catch(t){await e.reply(`❌ Connection failed: ${t.message}\nCheck SF_API_KEY in ~/.sf/config.json`)}}),f.on("callback_query:data",async e=>{const n=e.callbackQuery.data;if(n.startsWith("pick_thesis:")){const t=n.slice(12);try{const{theses:a}=await o.listTheses(),s=(a||[]).find(e=>e.id===t);if(!s)return void await e.answerCallbackQuery({text:"Thesis not found"});await $(e.chat.id,s),await e.answerCallbackQuery({text:`Selected: ${(s.rawThesis||"").slice(0,30)}`}),await e.editMessageText(`✅ Active: <b>${(s.rawThesis||"").slice(0,80)}</b>\nID: <code>${s.id.slice(0,8)}</code>\n\nType naturally, send voice, or use /help`,{parse_mode:"HTML"})}catch(t){await e.answerCallbackQuery({text:`Error: ${t.message}`})}return}f.command("context",async e=>{if(!w(e.chat.id))return;const t=g(e.chat.id);if(t.thesisId)try{const a=await(0,h.handleContext)(o,t.thesisId);for(const t of(0,d.splitMessage)(a))await e.reply(t,{parse_mode:"HTML"})}catch(t){await e.reply(`❌ ${t.message}`)}else await e.reply("No thesis selected. Use /start or /switch <id>")}),f.command("positions",async e=>{if(w(e.chat.id))try{const t=await(0,h.handlePositions)();for(const a of(0,d.splitMessage)(t))await e.reply(a,{parse_mode:"HTML"})}catch(t){await e.reply(`❌ ${t.message}`)}}),f.command("edges",async e=>{if(w(e.chat.id))try{const t=await(0,h.handleEdges)(o);for(const a of(0,d.splitMessage)(t))await e.reply(a,{parse_mode:"HTML"})}catch(t){await e.reply(`❌ ${t.message}`)}}),f.command("balance",async e=>{if(w(e.chat.id))try{const t=await(0,h.handleBalance)();await e.reply(t,{parse_mode:"HTML"})}catch(t){await e.reply(`❌ ${t.message}`)}}),f.command("orders",async e=>{if(w(e.chat.id))try{const t=await(0,h.handleOrders)();for(const a of(0,d.splitMessage)(t))await e.reply(a,{parse_mode:"HTML"})}catch(t){await e.reply(`❌ ${t.message}`)}}),f.command("eval",async e=>{if(!w(e.chat.id))return;const t=g(e.chat.id);if(t.thesisId)try{const a=await(0,h.handleEval)(o,t.thesisId);await e.reply(a)}catch(t){await e.reply(`❌ ${t.message}`)}else await e.reply("No thesis selected.")}),f.command("help",async e=>{w(e.chat.id)&&await e.reply("<b>Commands</b>\n/context — thesis snapshot\n/positions — Kalshi positions\n/edges — top edges\n/balance — account balance\n/orders — resting orders\n/eval — trigger evaluation\n/list — all theses\n/switch <id> — switch thesis\n\n🎤 Send a voice message to talk\n💬 Or just type naturally",{parse_mode:"HTML"})}),f.command("list",async e=>{if(w(e.chat.id))try{const t=await(0,h.handleList)(o);for(const a of(0,d.splitMessage)(t))await e.reply(a,{parse_mode:"HTML"})}catch(t){await e.reply(`❌ ${t.message}`)}}),f.command("switch",async e=>{if(!w(e.chat.id))return;const t=g(e.chat.id),a=e.match?.trim();if(a)try{const{theses:s}=await o.listTheses(),i=(s||[]).find(e=>e.id.startsWith(a));i?(t.thesisId=i.id,t.agentMessages=[],t.agent=void 0,m.has(e.chat.id)&&clearInterval(m.get(e.chat.id)),m.set(e.chat.id,(0,p.startPoller)(f,e.chat.id,o,t.thesisId)),await e.reply(`Switched to: <code>${i.id.slice(0,8)}</code> — ${(i.rawThesis||"").slice(0,60)}`,{parse_mode:"HTML"})):await e.reply(`No thesis found matching "${a}". Use /list to see all.`)}catch(t){await e.reply(`❌ ${t.message}`)}else await e.reply("Usage: /switch <thesis_id>")}),f.on("message:text",async e=>{if(!w(e.chat.id))return;const t=g(e.chat.id),s=e.message.text;if(!s.startsWith("/")){if(!t.thesisId)try{const{theses:a}=await o.listTheses(),s=(a||[]).filter(e=>"active"===e.status);if(!(s.length>0))return void await e.reply('No active theses. Create one with `sf create "your thesis"` then /start');t.thesisId=s[0].id}catch{return void await e.reply("Could not connect. Use /start first.")}try{const i=await e.reply("⏳ Thinking..."),n=[];let r=0;const c=setInterval(()=>{e.replyWithChatAction("typing").catch(()=>{})},4e3);await e.replyWithChatAction("typing");const{runAgentMessage:l}=await a.e(160).then(a.bind(a,28160)),h=new Promise((e,t)=>setTimeout(()=>t(new Error("Response timeout (90s)")),9e4)),p=t=>{n.push(t);const a=Date.now();if(a-r>1e3){r=a;const t=n.map(e=>`⚡ ${e}`).join(" → ");e.api.editMessageText(e.chat.id,i.message_id,`⏳ ${t}...`).catch(()=>{})}};let u;try{u=await Promise.race([l(o,t,s,p),h])}finally{clearInterval(c)}try{await e.api.deleteMessage(e.chat.id,i.message_id)}catch{}if(u&&0!==u.trim().length)for(const t of(0,d.splitMessage)(u))try{await e.reply(t,{parse_mode:"HTML"})}catch{await e.reply(t)}else await e.reply("No response generated. Try rephrasing or use a slash command.")}catch(t){console.error("[Telegram] Agent error:",t.message),await e.reply(`❌ ${t.message}`)}}}),f.on(["message:voice","message:audio"],async e=>{if(!w(e.chat.id))return;const n=g(e.chat.id);if(!n.thesisId)try{const{theses:t}=await o.listTheses(),a=(t||[]).filter(e=>"active"===e.status);if(!(a.length>0))return void await e.reply("No active theses. Create one first.");n.thesisId=a[0].id}catch{return void await e.reply("Could not connect. Use /start first.")}try{await e.replyWithChatAction("typing");const r=e.message.voice||e.message.audio;if(!r)return void await e.reply("Could not read audio.");const c=await e.api.getFile(r.file_id);if(!c.file_path)return void await e.reply("Could not download audio.");const l=`https://api.telegram.org/file/bot${s}/${c.file_path}`,h=await fetch(l);if(!h.ok)return void await e.reply("Failed to download voice message.");const p=Buffer.from(await h.arrayBuffer()),u=t.apiKey||process.env.SF_API_KEY,f=t.apiUrl||process.env.SF_API_URL||"https://simplefunctions.dev";if(!u)return void await e.reply("SF API key required for voice transcription.");const g=new Blob([p],{type:"audio/ogg"}),y=new FormData;y.append("audio",g,"voice.ogg");const m=await fetch(`${f}/api/proxy/stt`,{method:"POST",headers:{Authorization:`Bearer ${u}`},body:y,signal:AbortSignal.timeout(3e4)});if(!m.ok)return void await e.reply("Transcription failed.");const w=(await m.json()).text;if(!w||0===w.trim().length)return void await e.reply("Could not transcribe voice message.");const $=await e.reply(`🎤 "${w}"\n⏳ Thinking...`),T=[];let b=0;const _=setInterval(()=>{e.replyWithChatAction("typing").catch(()=>{})},4e3);await e.replyWithChatAction("typing");const{runAgentMessage:v}=await a.e(160).then(a.bind(a,28160)),M=t=>{T.push(t);const a=Date.now();if(a-b>1e3){b=a;const t=T.map(e=>`⚡ ${e}`).join(" → ");e.api.editMessageText(e.chat.id,$.message_id,`🎤 "${w}"\n⏳ ${t}...`).catch(()=>{})}};let S;try{S=await Promise.race([v(o,n,w,M),new Promise((e,t)=>setTimeout(()=>t(new Error("Timeout")),9e4))])}finally{clearInterval(_)}try{await e.api.editMessageText(e.chat.id,$.message_id,`🎤 "${w}"`)}catch{}if(S&&S.trim().length>0){for(const t of(0,d.splitMessage)(S))try{await e.reply(t,{parse_mode:"HTML"})}catch{await e.reply(t)}const t=S.replace(/<[^>]*>/g,"").trim();if(t.length>0&&t.length<500)try{const a=await fetch(`${f}/api/proxy/tts`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${u}`},body:JSON.stringify({text:t.slice(0,500)}),signal:AbortSignal.timeout(15e3)});if(a.ok){const t=Buffer.from(await a.arrayBuffer());await e.replyWithVoice(new i.InputFile(t,"reply.mp3"))}}catch{}}}catch(t){console.error("[Telegram] Voice error:",t.message),await e.reply(`❌ Voice: ${t.message}`)}}),n.startsWith("order_confirm:")?await e.answerCallbackQuery({text:"Order execution coming soon"}):"order_cancel"===n&&(await e.answerCallbackQuery({text:"Order cancelled"}),await e.editMessageText("❌ Order cancelled."))}),console.log("🤖 SimpleFunctions Telegram bot starting..."),console.log(" SF API: "+(t.apiKey?"✓":"✗")),console.log(" Kalshi: "+(process.env.KALSHI_API_KEY_ID?"✓":"✗")),console.log(" OpenRouter: "+(t.openrouterKey?"✓":"✗")),y&&console.log(` Restricted to chat: ${y}`);function T(){for(const e of m.values())clearInterval(e);f.stop();try{n.default.unlinkSync(u)}catch{}}console.log(" Press Ctrl+C to stop.\n"),n.default.mkdirSync(r.default.dirname(u),{recursive:!0}),n.default.writeFileSync(u,String(process.pid)),process.on("uncaughtException",e=>{console.error("[Telegram] Uncaught exception:",e.message)}),process.on("unhandledRejection",e=>{console.error("[Telegram] Unhandled rejection:",e?.message||e)}),process.on("SIGINT",()=>{T(),process.exit(0)}),process.on("SIGTERM",()=>{T(),process.exit(0)}),process.on("exit",()=>{try{n.default.unlinkSync(u)}catch{}});for(let e=0;e<=5;e++)try{await f.start({onStart:()=>console.log("[Telegram] Polling started successfully")});break}catch(t){if((t?.message?.includes("409")||409===t?.error_code)&&e<5){const t=5*(e+1);console.error(`[Telegram] 409 conflict — retrying in ${t}s (${e+1}/5)`),await new Promise(e=>setTimeout(e,1e3*t));continue}console.error(`[Telegram] Fatal: ${t.message}`),T(),process.exit(1)}};const i=a(53278),n=s(a(79896)),r=s(a(16928)),o=s(a(70857)),c=a(19218),l=a(11627),d=a(76342),h=a(77499),p=a(55875),u=r.default.join(o.default.homedir(),".sf","telegram.pid"),f=new Map;function g(e){return f.has(e)||f.set(e,{thesisId:null,agentMessages:[]}),f.get(e)}},77499:(e,t,a)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.handleContext=async function(e,t){const a=await e.getContext(t),s="number"==typeof a.confidence?Math.round(100*a.confidence):"?",n=a.thesis||a.rawThesis||"N/A";let r=`📋 <b>${(0,i.escapeHtml)(n.slice(0,80))}</b>\n`;r+=`Confidence: <b>${s}%</b> | Status: ${a.status}\n\n`;const o=(a.edges||[]).slice(0,8);if(o.length>0){r+="<b>Top Edges:</b>\n<pre>";for(const e of o){r+=`${(e.market||e.marketTitle||"???").slice(0,35).padEnd(36)} ${String(e.edge||0).padStart(3)}¢ ${e.direction||"yes"}\n`}r+="</pre>"}return r},t.handlePositions=async function(){if(!(0,s.isKalshiConfigured)())return"⚠️ Kalshi not configured. Run <code>sf setup --kalshi</code>";const e=await(0,s.getPositions)();if(!e||0===e.length)return"No open positions.";let t=0;const a=[];for(const n of e){const e=await(0,s.getMarketPrice)(n.ticker)??n.average_price_paid,r=(e-n.average_price_paid)*n.quantity;t+=r;const o=(0,i.fmtDollar)(r);a.push(`${n.ticker.slice(0,28).padEnd(29)} ${String(n.quantity).padStart(5)} ${String(n.average_price_paid).padStart(3)}¢→${String(e).padStart(3)}¢ ${o}`)}let n="📊 <b>Positions</b>\n<pre>";return n+=a.join("\n"),n+=`\n${"─".repeat(50)}\nTotal P&L: ${(0,i.fmtDollar)(t)}`,n+="</pre>",n},t.handleEdges=async function(e){const{theses:t}=await e.listTheses(),a=(t||[]).filter(e=>"active"===e.status),s=await Promise.allSettled(a.map(async t=>((await e.getContext(t.id)).edges||[]).map(e=>({...e,thesisId:t.id})))),i=[];for(const e of s)"fulfilled"===e.status&&i.push(...e.value);i.sort((e,t)=>Math.abs(t.edge||0)-Math.abs(e.edge||0));const n=i.slice(0,10);if(0===n.length)return"No edges found.";let r="📈 <b>Top Edges</b>\n<pre>";for(const e of n){const t=(e.market||"???").slice(0,35),a=e.orderbook?.liquidityScore||"?";r+=`${t.padEnd(36)} +${String(e.edge||0).padStart(2)}¢ ${a}\n`}return r+="</pre>",r},t.handleBalance=async function(){if(!(0,s.isKalshiConfigured)())return"⚠️ Kalshi not configured.";const e=await(0,s.getBalance)();return e?`💰 Balance: <b>$${e.balance.toFixed(2)}</b> | Portfolio: <b>$${e.portfolioValue.toFixed(2)}</b>`:"⚠️ Failed to fetch balance."},t.handleOrders=async function(){if(!(0,s.isKalshiConfigured)())return"⚠️ Kalshi not configured.";const e=await(0,s.getOrders)({status:"resting",limit:20});if(!e||!e.orders||0===e.orders.length)return"No resting orders.";let t="📋 <b>Resting Orders</b>\n<pre>";for(const a of e.orders){const e=Math.round(parseFloat(a.remaining_count_fp||"0")),s=Math.round(100*parseFloat(a.yes_price_dollars||"0")),i=(a.ticker||"???").slice(0,25);t+=`${a.action} ${e}x ${i} @ ${s}¢\n`}return t+="</pre>",t},t.handleEval=async function(e,t){return await e.evaluate(t),"⚡ Evaluation triggered. Results in ~2 minutes."},t.handleList=async function(e){const{theses:t}=await e.listTheses();if(!t||0===t.length)return"No theses.";let a="📝 <b>Theses</b>\n<pre>";for(const e of t){const t="number"==typeof e.confidence?Math.round(100*e.confidence):0,s=(e.rawThesis||e.thesis||"").slice(0,50);a+=`${e.id.slice(0,8)} ${String(t).padStart(3)}% ${e.status.padEnd(8)} ${s}\n`}return a+="</pre>",a};const s=a(96139),i=a(76342)},76342:(e,t)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.splitMessage=function(e,t=4e3){if(e.length<=t)return[e];const a=[];let s=e;for(;s.length>0;){if(s.length<=t){a.push(s);break}let e=s.lastIndexOf("\n",t);e<.5*t&&(e=t),a.push(s.slice(0,e)),s=s.slice(e)}return a},t.fmtDollar=function(e){const t=e/100;return t>=0?`+$${t.toFixed(2)}`:`-$${Math.abs(t).toFixed(2)}`},t.sparkline=function(e){if(0===e.length)return"";const t=Math.min(...e),a=Math.max(...e)-t||1;return e.map(e=>"▁▂▃▄▅▆▇█"[Math.round((e-t)/a*7)]).join("")},t.escapeHtml=function(e){return e.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">")}},55875:(e,t,a)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.startPoller=function(e,t,a,i){let n=(new Date).toISOString();return setInterval(async()=>{try{const r=await a.getChanges(i,n);if(n=(new Date).toISOString(),!r||!r.changed)return;const o=r.confidenceDelta??r.delta??0;if(Math.abs(o)<.02)return;const c="number"==typeof r.confidence?Math.round(100*r.confidence):"?",l=o>0?"📈":"📉",d=o>0?"+":"",h=r.summary||r.latestSummary||"";let p=`${l} <b>Confidence ${d}${Math.round(100*o)}% → ${c}%</b>\n`;h&&(p+=`${(0,s.escapeHtml)(h.slice(0,200))}`),await e.api.sendMessage(t,p,{parse_mode:"HTML"})}catch{}},6e4)};const s=a(76342)}};
|
|
1
|
+
"use strict";exports.id=12,exports.ids=[12],exports.modules={6012:function(e,t,a){var s=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0}),t.startBot=async function(e){const t=(0,l.loadConfig)(),s=e.token||t.telegramBotToken||process.env.TELEGRAM_BOT_TOKEN;s||(console.error("No Telegram bot token. Use --token, set TELEGRAM_BOT_TOKEN, or add to ~/.sf/config.json"),process.exit(1));const o=new c.SFClient(t.apiKey,t.apiUrl),f=new i.Bot(s),y=e.chatId||null,m=new Map;function w(e){return!y||e===y}async function $(e,t){const a=g(e);a.thesisId=t.id,a.agentMessages=[],a.agent=void 0,m.has(e)&&clearInterval(m.get(e)),m.set(e,(0,p.startPoller)(f,e,o,a.thesisId))}f.command("start",async e=>{if(!w(e.chat.id))return;g(e.chat.id);try{const{theses:t}=await o.listTheses(),a=(t||[]).filter(e=>"active"===e.status);if(0===a.length)return void await e.reply('No active theses found. Create one with `sf create "your thesis"`');if(1===a.length)await $(e.chat.id,a[0]),await e.reply(`✅ Connected\n\nThesis: <b>${(a[0].rawThesis||"").slice(0,80)}</b>\nID: <code>${a[0].id.slice(0,8)}</code>\n\nType naturally, send voice, or use /help`,{parse_mode:"HTML"});else{const t=new i.InlineKeyboard;for(const e of a.slice(0,8)){const a=`${(e.rawThesis||e.id).slice(0,40)}`;t.text(a,`pick_thesis:${e.id}`).row()}await e.reply(`✅ Connected — ${a.length} active theses\n\nPick one:`,{parse_mode:"HTML",reply_markup:t})}}catch(t){await e.reply(`❌ Connection failed: ${t.message}\nCheck SF_API_KEY in ~/.sf/config.json`)}}),f.on("callback_query:data",async e=>{const t=e.callbackQuery.data;if(t.startsWith("pick_thesis:")){const a=t.slice(12);try{const{theses:t}=await o.listTheses(),s=(t||[]).find(e=>e.id===a);if(!s)return void await e.answerCallbackQuery({text:"Thesis not found"});await $(e.chat.id,s),await e.answerCallbackQuery({text:`Selected: ${(s.rawThesis||"").slice(0,30)}`}),await e.editMessageText(`✅ Active: <b>${(s.rawThesis||"").slice(0,80)}</b>\nID: <code>${s.id.slice(0,8)}</code>\n\nType naturally, send voice, or use /help`,{parse_mode:"HTML"})}catch(t){await e.answerCallbackQuery({text:`Error: ${t.message}`})}return}t.startsWith("order_confirm:")?await e.answerCallbackQuery({text:"Order execution coming soon"}):"order_cancel"===t&&(await e.answerCallbackQuery({text:"Order cancelled"}),await e.editMessageText("❌ Order cancelled."))}),f.command("context",async e=>{if(!w(e.chat.id))return;const t=g(e.chat.id);if(t.thesisId)try{const a=await(0,h.handleContext)(o,t.thesisId);for(const t of(0,d.splitMessage)(a))await e.reply(t,{parse_mode:"HTML"})}catch(t){await e.reply(`❌ ${t.message}`)}else await e.reply("No thesis selected. Use /start or /switch <id>")}),f.command("positions",async e=>{if(w(e.chat.id))try{const t=await(0,h.handlePositions)();for(const a of(0,d.splitMessage)(t))await e.reply(a,{parse_mode:"HTML"})}catch(t){await e.reply(`❌ ${t.message}`)}}),f.command("edges",async e=>{if(w(e.chat.id))try{const t=await(0,h.handleEdges)(o);for(const a of(0,d.splitMessage)(t))await e.reply(a,{parse_mode:"HTML"})}catch(t){await e.reply(`❌ ${t.message}`)}}),f.command("balance",async e=>{if(w(e.chat.id))try{const t=await(0,h.handleBalance)();await e.reply(t,{parse_mode:"HTML"})}catch(t){await e.reply(`❌ ${t.message}`)}}),f.command("orders",async e=>{if(w(e.chat.id))try{const t=await(0,h.handleOrders)();for(const a of(0,d.splitMessage)(t))await e.reply(a,{parse_mode:"HTML"})}catch(t){await e.reply(`❌ ${t.message}`)}}),f.command("eval",async e=>{if(!w(e.chat.id))return;const t=g(e.chat.id);if(t.thesisId)try{const a=await(0,h.handleEval)(o,t.thesisId);await e.reply(a)}catch(t){await e.reply(`❌ ${t.message}`)}else await e.reply("No thesis selected.")}),f.command("help",async e=>{w(e.chat.id)&&await e.reply("<b>Commands</b>\n/context — thesis snapshot\n/positions — Kalshi positions\n/edges — top edges\n/balance — account balance\n/orders — resting orders\n/eval — trigger evaluation\n/list — all theses\n/switch <id> — switch thesis\n\n🎤 Send a voice message to talk\n💬 Or just type naturally",{parse_mode:"HTML"})}),f.command("list",async e=>{if(w(e.chat.id))try{const t=await(0,h.handleList)(o);for(const a of(0,d.splitMessage)(t))await e.reply(a,{parse_mode:"HTML"})}catch(t){await e.reply(`❌ ${t.message}`)}}),f.command("switch",async e=>{if(!w(e.chat.id))return;const t=g(e.chat.id),a=e.match?.trim();if(a)try{const{theses:s}=await o.listTheses(),i=(s||[]).find(e=>e.id.startsWith(a));i?(t.thesisId=i.id,t.agentMessages=[],t.agent=void 0,m.has(e.chat.id)&&clearInterval(m.get(e.chat.id)),m.set(e.chat.id,(0,p.startPoller)(f,e.chat.id,o,t.thesisId)),await e.reply(`Switched to: <code>${i.id.slice(0,8)}</code> — ${(i.rawThesis||"").slice(0,60)}`,{parse_mode:"HTML"})):await e.reply(`No thesis found matching "${a}". Use /list to see all.`)}catch(t){await e.reply(`❌ ${t.message}`)}else await e.reply("Usage: /switch <thesis_id>")}),f.on("message:text",async e=>{if(!w(e.chat.id))return;const t=g(e.chat.id),s=e.message.text;if(!s.startsWith("/")){if(!t.thesisId)try{const{theses:a}=await o.listTheses(),s=(a||[]).filter(e=>"active"===e.status);if(!(s.length>0))return void await e.reply('No active theses. Create one with `sf create "your thesis"` then /start');t.thesisId=s[0].id}catch(t){return console.error("[TG] listTheses error:",t.message),void await e.reply("Could not connect. Use /start first.")}try{await e.replyWithChatAction("typing");const i=setInterval(()=>{e.replyWithChatAction("typing").catch(()=>{})},4e3),n=await e.reply("⏳ Thinking..."),r=[];let c=0;const{runAgentMessage:l}=await a.e(160).then(a.bind(a,28160)),h=new Promise((e,t)=>setTimeout(()=>t(new Error("Response timeout (90s)")),9e4)),p=t=>{r.push(t);const a=Date.now();if(a-c>1e3){c=a;const t=r.map(e=>`⚡ ${e}`).join(" → ");e.api.editMessageText(e.chat.id,n.message_id,`⏳ ${t}...`).catch(()=>{})}};let u;try{u=await Promise.race([l(o,t,s,p),h])}finally{clearInterval(i)}try{await e.api.deleteMessage(e.chat.id,n.message_id)}catch{}if(u&&0!==u.trim().length)for(const t of(0,d.splitMessage)(u))try{await e.reply(t,{parse_mode:"HTML"})}catch{await e.reply(t)}else await e.reply("No response generated. Try rephrasing or use a slash command.")}catch(t){console.error("[Telegram] Agent error:",t.message),await e.reply(`❌ ${t.message}`)}}}),f.on(["message:voice","message:audio"],async e=>{if(!w(e.chat.id))return;const n=g(e.chat.id);if(!n.thesisId)try{const{theses:t}=await o.listTheses(),a=(t||[]).filter(e=>"active"===e.status);if(!(a.length>0))return void await e.reply("No active theses. Create one first.");n.thesisId=a[0].id}catch{return void await e.reply("Could not connect. Use /start first.")}try{await e.replyWithChatAction("typing");const r=e.message.voice||e.message.audio;if(!r)return void await e.reply("Could not read audio.");const c=await e.api.getFile(r.file_id);if(!c.file_path)return void await e.reply("Could not download audio.");const l=`https://api.telegram.org/file/bot${s}/${c.file_path}`,h=await fetch(l);if(!h.ok)return void await e.reply("Failed to download voice message.");const p=Buffer.from(await h.arrayBuffer()),u=t.apiKey||process.env.SF_API_KEY,f=t.apiUrl||process.env.SF_API_URL||"https://simplefunctions.dev";if(!u)return void await e.reply("SF API key required for voice transcription.");const g=new Blob([p],{type:"audio/ogg"}),y=new FormData;y.append("audio",g,"voice.ogg");const m=await fetch(`${f}/api/proxy/stt`,{method:"POST",headers:{Authorization:`Bearer ${u}`},body:y,signal:AbortSignal.timeout(3e4)});if(!m.ok)return void await e.reply("Transcription failed.");const w=(await m.json()).text;if(!w||0===w.trim().length)return void await e.reply("Could not transcribe voice message.");const $=await e.reply(`🎤 "${w}"\n⏳ Thinking...`),T=[];let b=0;const _=setInterval(()=>{e.replyWithChatAction("typing").catch(()=>{})},4e3);await e.replyWithChatAction("typing");const{runAgentMessage:v}=await a.e(160).then(a.bind(a,28160)),M=t=>{T.push(t);const a=Date.now();if(a-b>1e3){b=a;const t=T.map(e=>`⚡ ${e}`).join(" → ");e.api.editMessageText(e.chat.id,$.message_id,`🎤 "${w}"\n⏳ ${t}...`).catch(()=>{})}};let S;try{S=await Promise.race([v(o,n,w,M),new Promise((e,t)=>setTimeout(()=>t(new Error("Timeout")),9e4))])}finally{clearInterval(_)}try{await e.api.editMessageText(e.chat.id,$.message_id,`🎤 "${w}"`)}catch{}if(S&&S.trim().length>0){for(const t of(0,d.splitMessage)(S))try{await e.reply(t,{parse_mode:"HTML"})}catch{await e.reply(t)}const t=S.replace(/<[^>]*>/g,"").trim();if(t.length>0&&t.length<500)try{const a=await fetch(`${f}/api/proxy/tts`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${u}`},body:JSON.stringify({text:t.slice(0,500)}),signal:AbortSignal.timeout(15e3)});if(a.ok){const t=Buffer.from(await a.arrayBuffer());await e.replyWithVoice(new i.InputFile(t,"reply.mp3"))}}catch{}}}catch(t){console.error("[Telegram] Voice error:",t.message),await e.reply(`❌ Voice: ${t.message}`)}}),f.catch(e=>{console.error("[Telegram] Handler error:",e.message||e)}),console.log("🤖 SimpleFunctions Telegram bot starting..."),console.log(" SF API: "+(t.apiKey?"✓":"✗")),console.log(" Kalshi: "+(process.env.KALSHI_API_KEY_ID?"✓":"✗")),console.log(" OpenRouter: "+(t.openrouterKey?"✓":"✗")),y&&console.log(` Restricted to chat: ${y}`);function T(){for(const e of m.values())clearInterval(e);f.stop();try{n.default.unlinkSync(u)}catch{}}console.log(" Press Ctrl+C to stop.\n"),n.default.mkdirSync(r.default.dirname(u),{recursive:!0}),n.default.writeFileSync(u,String(process.pid)),process.on("uncaughtException",e=>{console.error("[Telegram] Uncaught exception:",e.message)}),process.on("unhandledRejection",e=>{console.error("[Telegram] Unhandled rejection:",e?.message||e)}),process.on("SIGINT",()=>{T(),process.exit(0)}),process.on("SIGTERM",()=>{T(),process.exit(0)}),process.on("exit",()=>{try{n.default.unlinkSync(u)}catch{}});for(let e=0;e<=5;e++)try{await f.start({onStart:()=>console.log("[Telegram] Polling started successfully")});break}catch(t){if((t?.message?.includes("409")||409===t?.error_code)&&e<5){const t=5*(e+1);console.error(`[Telegram] 409 conflict — retrying in ${t}s (${e+1}/5)`),await new Promise(e=>setTimeout(e,1e3*t));continue}console.error(`[Telegram] Fatal: ${t.message}`),T(),process.exit(1)}};const i=a(18654),n=s(a(79896)),r=s(a(16928)),o=s(a(70857)),c=a(19218),l=a(11627),d=a(76342),h=a(77499),p=a(55875),u=r.default.join(o.default.homedir(),".sf","telegram.pid"),f=new Map;function g(e){return f.has(e)||f.set(e,{thesisId:null,agentMessages:[]}),f.get(e)}},77499:(e,t,a)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.handleContext=async function(e,t){const a=await e.getContext(t),s="number"==typeof a.confidence?Math.round(100*a.confidence):"?",n=a.thesis||a.rawThesis||"N/A";let r=`📋 <b>${(0,i.escapeHtml)(n.slice(0,80))}</b>\n`;r+=`Confidence: <b>${s}%</b> | Status: ${a.status}\n\n`;const o=(a.edges||[]).slice(0,8);if(o.length>0){r+="<b>Top Edges:</b>\n<pre>";for(const e of o){r+=`${(e.market||e.marketTitle||"???").slice(0,35).padEnd(36)} ${String(e.edge||0).padStart(3)}¢ ${e.direction||"yes"}\n`}r+="</pre>"}return r},t.handlePositions=async function(){if(!(0,s.isKalshiConfigured)())return"⚠️ Kalshi not configured. Run <code>sf setup --kalshi</code>";const e=await(0,s.getPositions)();if(!e||0===e.length)return"No open positions.";let t=0;const a=[];for(const n of e){const e=await(0,s.getMarketPrice)(n.ticker)??n.average_price_paid,r=(e-n.average_price_paid)*n.quantity;t+=r;const o=(0,i.fmtDollar)(r);a.push(`${n.ticker.slice(0,28).padEnd(29)} ${String(n.quantity).padStart(5)} ${String(n.average_price_paid).padStart(3)}¢→${String(e).padStart(3)}¢ ${o}`)}let n="📊 <b>Positions</b>\n<pre>";return n+=a.join("\n"),n+=`\n${"─".repeat(50)}\nTotal P&L: ${(0,i.fmtDollar)(t)}`,n+="</pre>",n},t.handleEdges=async function(e){const{theses:t}=await e.listTheses(),a=(t||[]).filter(e=>"active"===e.status),s=await Promise.allSettled(a.map(async t=>((await e.getContext(t.id)).edges||[]).map(e=>({...e,thesisId:t.id})))),i=[];for(const e of s)"fulfilled"===e.status&&i.push(...e.value);i.sort((e,t)=>Math.abs(t.edge||0)-Math.abs(e.edge||0));const n=i.slice(0,10);if(0===n.length)return"No edges found.";let r="📈 <b>Top Edges</b>\n<pre>";for(const e of n){const t=(e.market||"???").slice(0,35),a=e.orderbook?.liquidityScore||"?";r+=`${t.padEnd(36)} +${String(e.edge||0).padStart(2)}¢ ${a}\n`}return r+="</pre>",r},t.handleBalance=async function(){if(!(0,s.isKalshiConfigured)())return"⚠️ Kalshi not configured.";const e=await(0,s.getBalance)();return e?`💰 Balance: <b>$${e.balance.toFixed(2)}</b> | Portfolio: <b>$${e.portfolioValue.toFixed(2)}</b>`:"⚠️ Failed to fetch balance."},t.handleOrders=async function(){if(!(0,s.isKalshiConfigured)())return"⚠️ Kalshi not configured.";const e=await(0,s.getOrders)({status:"resting",limit:20});if(!e||!e.orders||0===e.orders.length)return"No resting orders.";let t="📋 <b>Resting Orders</b>\n<pre>";for(const a of e.orders){const e=Math.round(parseFloat(a.remaining_count_fp||"0")),s=Math.round(100*parseFloat(a.yes_price_dollars||"0")),i=(a.ticker||"???").slice(0,25);t+=`${a.action} ${e}x ${i} @ ${s}¢\n`}return t+="</pre>",t},t.handleEval=async function(e,t){return await e.evaluate(t),"⚡ Evaluation triggered. Results in ~2 minutes."},t.handleList=async function(e){const{theses:t}=await e.listTheses();if(!t||0===t.length)return"No theses.";let a="📝 <b>Theses</b>\n<pre>";for(const e of t){const t="number"==typeof e.confidence?Math.round(100*e.confidence):0,s=(e.rawThesis||e.thesis||"").slice(0,50);a+=`${e.id.slice(0,8)} ${String(t).padStart(3)}% ${e.status.padEnd(8)} ${s}\n`}return a+="</pre>",a};const s=a(96139),i=a(76342)},76342:(e,t)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.splitMessage=function(e,t=4e3){if(e.length<=t)return[e];const a=[];let s=e;for(;s.length>0;){if(s.length<=t){a.push(s);break}let e=s.lastIndexOf("\n",t);e<.5*t&&(e=t),a.push(s.slice(0,e)),s=s.slice(e)}return a},t.fmtDollar=function(e){const t=e/100;return t>=0?`+$${t.toFixed(2)}`:`-$${Math.abs(t).toFixed(2)}`},t.sparkline=function(e){if(0===e.length)return"";const t=Math.min(...e),a=Math.max(...e)-t||1;return e.map(e=>"▁▂▃▄▅▆▇█"[Math.round((e-t)/a*7)]).join("")},t.escapeHtml=function(e){return e.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">")}},55875:(e,t,a)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.startPoller=function(e,t,a,i){let n=(new Date).toISOString();return setInterval(async()=>{try{const r=await a.getChanges(i,n);if(n=(new Date).toISOString(),!r||!r.changed)return;const o=r.confidenceDelta??r.delta??0;if(Math.abs(o)<.02)return;const c="number"==typeof r.confidence?Math.round(100*r.confidence):"?",l=o>0?"📈":"📉",d=o>0?"+":"",h=r.summary||r.latestSummary||"";let p=`${l} <b>Confidence ${d}${Math.round(100*o)}% → ${c}%</b>\n`;h&&(p+=`${(0,s.escapeHtml)(h.slice(0,200))}`),await e.api.sendMessage(t,p,{parse_mode:"HTML"})}catch{}},6e4)};const s=a(76342)}};
|
package/dist/160.index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";exports.id=160,exports.ids=[160],exports.modules={28160:(e,t,n)=>{t.runAgentMessage=async function(e,t,n,i){const s=await o(e,t);if(t.thesisId)try{const n=await Promise.race([e.getContext(t.thesisId),new Promise((e,t)=>setTimeout(t,3e3))]);if(n){const e="number"==typeof n.confidence?Math.round(100*n.confidence):"?",t=(n.edges||[]).sort((e,t)=>Math.abs(t.edge)-Math.abs(e.edge)).slice(0,3),i=`\n\n## Live State\nConfidence: ${e}%\nTop edges: ${t.map(e=>`${(e.market||"").slice(0,20)} ${e.edge>0?"+":""}${e.edge}¢`).join(" | ")||"none"}`,a=s.state?.systemPrompt||"";a.includes("## Live State")?s.setSystemPrompt(a.replace(/\n\n## Live State[\s\S]*$/,i)):s.setSystemPrompt(a+i)}}catch{}return new Promise((e,r)=>{let o="",c="",l=!1;function d(i){if(!l){l=!0,t.agentMessages=s.state.messages||[];try{t.thesisId&&((0,a.appendContext)(t.thesisId,{ts:(new Date).toISOString(),role:"user",content:n,source:"telegram"}),i&&(0,a.appendContext)(t.thesisId,{ts:(new Date).toISOString(),role:"assistant",content:i.slice(0,5e3),source:"telegram"}))}catch{}e(i||"(no response)")}}const p=setTimeout(()=>{d(o||c||"Response timeout. Try a simpler question or follow up.")},12e4),u=s.subscribe(e=>{if("message_update"===e.type){const t=e.assistantMessageEvent;"text_delta"===t.type&&(o+=t.delta)}"tool_execution_start"===e.type&&(c+=`⚡ ${e.toolName}\n`,i&&i(e.toolName)),"agent_end"===e.type&&(clearTimeout(p),u?.(),d(o||c))});s.prompt(n).catch(e=>{clearTimeout(p),u?.(),l||r(e)})})};const i=n(11627),a=n(73600);let s=null;async function r(){if(s)return s;const[e,t]=await Promise.all([Promise.all([n.e(788),n.e(641),n.e(582)]).then(n.bind(n,65653)),Promise.all([n.e(788),n.e(641),n.e(174)]).then(n.bind(n,99641))]),i=await Promise.all([n.e(788),n.e(722)]).then(n.bind(n,85722));return s={Agent:e.Agent,streamSimple:t.streamSimple,Type:i.Type},s}async function o(e,t){if(t.agent)return t.agent;const{Agent:s,streamSimple:o}=await r(),c=await Promise.all([n.e(788),n.e(641),n.e(174)]).then(n.bind(n,99641)),{getModel:l}=c,d=(0,i.loadConfig)(),p=d.openrouterKey||process.env.OPENROUTER_API_KEY,u=d.apiKey||process.env.SF_API_KEY,m=d.apiUrl||process.env.SF_API_URL||"https://simplefunctions.dev",g=!p&&!!u,h=p||u;if(!h)throw new Error("Need API key. Run sf login or sf setup.");const y=await e.getContext(t.thesisId),x="number"==typeof y.confidence?Math.round(100*y.confidence):50,f=await async function(e,t,s){const{Type:o}=await r(),c=(0,i.loadConfig)(),l=o.Object({}),d=await Promise.resolve().then(n.t.bind(n,96139,23)),{kalshiFetchAllSeries:p,kalshiFetchMarketsBySeries:u,kalshiFetchMarket:m}=await Promise.resolve().then(n.bind(n,19218)),g=[{name:"get_context",label:"Context",description:"Get thesis snapshot with causal tree, edges, evaluation",parameters:l,execute:async()=>{const n=await e.getContext(t);return{content:[{type:"text",text:JSON.stringify(n,null,2)}],details:{}}}},{name:"global_context",label:"Snapshot",description:"Global market snapshot — movers, expiring, milestones, liquidity, signals. No thesis needed.",parameters:l,execute:async()=>{const{fetchGlobalContext:e}=await Promise.resolve().then(n.bind(n,19218)),t=await e();return{content:[{type:"text",text:JSON.stringify(t,null,2)}],details:{}}}},{name:"query",label:"Query",description:"LLM-enhanced prediction market search. Returns answer, live prices, key factors.",parameters:o.Object({q:o.String({description:"Question"})}),execute:async(e,t)=>{const{fetchQuery:i}=await Promise.resolve().then(n.bind(n,19218)),a=await i(t.q);return{content:[{type:"text",text:JSON.stringify(a,null,2)}],details:{}}}},{name:"get_markets",label:"Markets",description:"Traditional market prices: SPY, VIX, Treasury, Gold, Oil.",parameters:l,execute:async()=>{const{fetchTraditionalMarkets:e}=await Promise.resolve().then(n.bind(n,19218)),t=await e();return{content:[{type:"text",text:JSON.stringify(t,null,2)}],details:{}}}},{name:"inject_signal",label:"Signal",description:"Inject a signal (news, note, observation) into the thesis",parameters:o.Object({content:o.String({description:"Signal content"}),type:o.Optional(o.String({description:"news | user_note | external"}))}),execute:async(n,i)=>(await e.injectSignal(t,i.type||"user_note",i.content,"telegram"),{content:[{type:"text",text:"Signal injected."}],details:{}})},{name:"trigger_evaluation",label:"Evaluate",description:"Trigger a deep evaluation cycle",parameters:l,execute:async()=>(await e.evaluate(t),{content:[{type:"text",text:"Evaluation triggered. Results in ~2 minutes."}],details:{}})},{name:"scan_markets",label:"Scan",description:"Search Kalshi markets by keyword, series, or ticker",parameters:o.Object({query:o.Optional(o.String({description:"Keyword search"})),series:o.Optional(o.String({description:"Series ticker"})),market:o.Optional(o.String({description:"Market ticker"}))}),execute:async(e,t)=>{let n;if(t.market)n=await m(t.market);else if(t.series)n=await u(t.series);else if(t.query){const e=await p(),i=t.query.toLowerCase().split(/\s+/);n=e.filter(e=>i.every(t=>((e.title||"")+(e.ticker||"")).toLowerCase().includes(t))).filter(e=>parseFloat(e.volume_fp||"0")>1e3).sort((e,t)=>parseFloat(t.volume_fp||"0")-parseFloat(e.volume_fp||"0")).slice(0,10)}else n={error:"Provide query, series, or market"};return{content:[{type:"text",text:JSON.stringify(n,null,2)}],details:{}}}},{name:"list_theses",label:"List",description:"List all theses",parameters:l,execute:async()=>{const t=await e.listTheses();return{content:[{type:"text",text:JSON.stringify(t,null,2)}],details:{}}}},{name:"get_positions",label:"Positions",description:"Get Kalshi positions with live prices and P&L",parameters:l,execute:async()=>{const e=await d.getPositions();if(!e)return{content:[{type:"text",text:"Kalshi not configured."}],details:{}};for(const t of e){const e=await d.getMarketPrice(t.ticker);null!=e&&(t.current_value=e,t.unrealized_pnl=Math.round((e-t.average_price_paid)*t.quantity))}const t=e.map(e=>({ticker:e.ticker,qty:e.quantity,avg_price:`${e.average_price_paid}¢`,current:`${e.current_value}¢`,pnl:`$${((e.unrealized_pnl||0)/100).toFixed(2)}`}));return{content:[{type:"text",text:JSON.stringify(t,null,2)}],details:{}}}},{name:"get_balance",label:"Balance",description:"Get Kalshi account balance",parameters:l,execute:async()=>{const e=await d.getBalance();return e?{content:[{type:"text",text:JSON.stringify(e,null,2)}],details:{}}:{content:[{type:"text",text:"Kalshi not configured."}],details:{}}}},{name:"get_orders",label:"Orders",description:"Get resting orders on Kalshi",parameters:l,execute:async()=>{const e=await d.getOrders({status:"resting",limit:50});return e?{content:[{type:"text",text:JSON.stringify(e.orders,null,2)}],details:{}}:{content:[{type:"text",text:"Kalshi not configured."}],details:{}}}},{name:"get_fills",label:"Fills",description:"Get recent trade fills",parameters:o.Object({ticker:o.Optional(o.String())}),execute:async(e,t)=>{const n=await d.getFills({ticker:t.ticker,limit:20});return n?{content:[{type:"text",text:JSON.stringify(n.fills,null,2)}],details:{}}:{content:[{type:"text",text:"Kalshi not configured."}],details:{}}}},{name:"get_settlements",label:"Settlements",description:"Get settled contracts with P&L",parameters:l,execute:async()=>{const e=await d.getSettlements({limit:50});return e?{content:[{type:"text",text:JSON.stringify(e.settlements,null,2)}],details:{}}:{content:[{type:"text",text:"Kalshi not configured."}],details:{}}}},{name:"get_edges",label:"Edges",description:"Top 10 edges across all active theses",parameters:l,execute:async()=>{const{theses:t}=await e.listTheses(),n=(t||[]).filter(e=>"active"===e.status),i=await Promise.allSettled(n.map(async t=>((await e.getContext(t.id)).edges||[]).map(e=>({...e,thesisId:t.id})))),a=[];for(const e of i)"fulfilled"===e.status&&a.push(...e.value);return a.sort((e,t)=>Math.abs(t.edge||0)-Math.abs(e.edge||0)),{content:[{type:"text",text:JSON.stringify(a.slice(0,10),null,2)}],details:{}}}},{name:"get_schedule",label:"Schedule",description:"Exchange status (open/closed) and trading hours",parameters:l,execute:async()=>{const e=await fetch("https://api.elections.kalshi.com/trade-api/v2/exchange/status",{headers:{Accept:"application/json"}});if(!e.ok)return{content:[{type:"text",text:`API error: ${e.status}`}],details:{}};const t=await e.json();return{content:[{type:"text",text:JSON.stringify(t,null,2)}],details:{}}}},{name:"get_feed",label:"Feed",description:"Recent evaluation history",parameters:o.Object({hours:o.Optional(o.Number({description:"Hours of history (default 24)"}))}),execute:async(t,n)=>{const i=await e.getFeed(n.hours||24);return{content:[{type:"text",text:JSON.stringify(i,null,2)}],details:{}}}},{name:"web_search",label:"Search",description:"Search the web for latest news",parameters:o.Object({query:o.String({description:"Search query"})}),execute:async(e,t)=>{const n=process.env.TAVILY_API_KEY||c.tavilyKey,i=c.apiKey||process.env.SF_API_KEY,a=c.apiUrl||process.env.SF_API_URL||"https://simplefunctions.dev";if(!n&&(n||!i))return{content:[{type:"text",text:"Web search not available. Run sf login or set TAVILY_API_KEY."}],details:{}};let s;if(s=n?await fetch("https://api.tavily.com/search",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({api_key:n,query:t.query,max_results:3,search_depth:"basic",include_answer:!0})}):await fetch(`${a}/api/proxy/search`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${i}`},body:JSON.stringify({query:t.query,max_results:3,search_depth:"basic",include_answer:!0})}),!s.ok)return{content:[{type:"text",text:`Search failed: ${s.status}`}],details:{}};const r=await s.json();return{content:[{type:"text",text:`${r.answer?`Summary: ${r.answer}\n\n`:""}${(r.results||[]).map(e=>`${e.title}: ${(e.content||"").slice(0,150)}`).join("\n\n")}`}],details:{}}}},{name:"create_thesis",label:"Create",description:"Create a new thesis",parameters:o.Object({rawThesis:o.String({description:"Thesis statement"})}),execute:async(t,n)=>{const i=await e.createThesis(n.rawThesis,!0);return{content:[{type:"text",text:`Created: ${i.id}\nConfidence: ${Math.round(100*(i.confidence||.5))}%`}],details:{}}}},{name:"what_if",label:"What-If",description:"Override causal tree node probabilities and see how edges change. Zero LLM cost.",parameters:o.Object({overrides:o.Array(o.Object({nodeId:o.String({description:"Node ID (e.g. n1, n3.1)"}),newProbability:o.Number({description:"New probability 0-1"})}))}),execute:async(e,t)=>{const n=s,i=[];!function e(t){for(const n of t)i.push(n),n.children?.length&&e(n.children)}(n?.causalTree?.nodes||[]);const a=new Map(t.overrides.map(e=>[e.nodeId,e.newProbability])),r=(n?.causalTree?.nodes||[]).filter(e=>!e.parentId||0===e.depth),o=r.reduce((e,t)=>e+(t.probability||.5),0)/Math.max(r.length,1);for(const e of i)a.has(e.id)&&(e.probability=a.get(e.id));const c=r.reduce((e,t)=>e+(t.probability||.5),0)/Math.max(r.length,1),l=(n?.edges||[]).slice(0,10).map(e=>{const t=i.find(t=>t.id===e.relatedNodeId);if(!t||!a.has(t.id))return{market:e.market,oldEdge:e.edge,newEdge:e.edge,signal:"unchanged"};const n=t.probability/(e.confidence||.5),s=Math.round(e.thesisPrice*n)-e.marketPrice;return{market:e.market,oldEdge:e.edge,newEdge:s,signal:Math.abs(s-e.edge)<1?"unchanged":"changed"}}).filter(e=>"unchanged"!==e.signal);return{content:[{type:"text",text:JSON.stringify({confidence:{old:Math.round(100*o),new:Math.round(100*c)},edges:l},null,2)}],details:{}}}}];g.push({name:"search_x",label:"X Search",description:"Search X (Twitter) for recent discussions. Returns posts, sentiment, themes.",parameters:o.Object({query:o.String({description:"Search query"}),mode:o.Optional(o.String({description:'"summary" or "raw"'})),hours:o.Optional(o.Number({description:"Hours (default 24)"}))}),execute:async(t,n)=>{const i=await e.searchX(n.query,{mode:n.mode,hours:n.hours});return{content:[{type:"text",text:JSON.stringify(i,null,2)}],details:{}}}},{name:"x_volume",label:"X Volume",description:"X discussion volume trend — total posts, velocity, peak time.",parameters:o.Object({query:o.String({description:"Search query"}),hours:o.Optional(o.Number({description:"Hours (default 72)"}))}),execute:async(t,n)=>{const i=await e.getXVolume(n.query,{hours:n.hours});return{content:[{type:"text",text:JSON.stringify(i,null,2)}],details:{}}}},{name:"x_news",label:"X News",description:"News stories trending on X — titles, summaries, tickers.",parameters:o.Object({query:o.String({description:"Search query"}),limit:o.Optional(o.Number({description:"Max stories (default 10)"}))}),execute:async(t,n)=>{const i=await e.searchXNews(n.query,{limit:n.limit});return{content:[{type:"text",text:JSON.stringify(i,null,2)}],details:{}}}},{name:"x_account",label:"X Account",description:"Recent posts from a specific X account.",parameters:o.Object({username:o.String({description:"X username (with or without @)"}),hours:o.Optional(o.Number({description:"Hours (default 24)"}))}),execute:async(t,n)=>{const i=await e.getXAccount(n.username,{hours:n.hours});return{content:[{type:"text",text:JSON.stringify(i,null,2)}],details:{}}}},{name:"heartbeat_config",label:"Heartbeat Config",description:"View or update heartbeat settings: scan intervals, model tier, budget cap, pause/resume. Shows cost breakdown.",parameters:o.Object({thesisId:o.String({description:"Thesis ID"}),newsIntervalMin:o.Optional(o.Number({description:"News scan interval (15-1440 min)"})),xIntervalMin:o.Optional(o.Number({description:"X scan interval (60-1440 min)"})),evalModelTier:o.Optional(o.String({description:"cheap, medium, or heavy"})),monthlyBudgetUsd:o.Optional(o.Number({description:"Monthly budget (0 = unlimited)"})),paused:o.Optional(o.Boolean({description:"Pause or resume heartbeat"}))}),execute:async(t,n)=>{if(n.newsIntervalMin||n.xIntervalMin||n.evalModelTier||void 0!==n.monthlyBudgetUsd||void 0!==n.paused){const t={};n.newsIntervalMin&&(t.newsIntervalMin=n.newsIntervalMin),n.xIntervalMin&&(t.xIntervalMin=n.xIntervalMin),n.evalModelTier&&(t.evalModelTier=n.evalModelTier),void 0!==n.monthlyBudgetUsd&&(t.monthlyBudgetUsd=n.monthlyBudgetUsd),void 0!==n.paused&&(t.paused=n.paused),await e.updateHeartbeatConfig(n.thesisId,t)}const i=await e.getHeartbeatConfig(n.thesisId);return{content:[{type:"text",text:JSON.stringify(i,null,2)}],details:{}}}});const h=process.env.SF_API_URL||c.apiUrl||"https://simplefunctions.dev";g.push({name:"get_world_state",label:"World",description:"Real-time world model (~800 tokens). Geopolitics, economy, energy, elections, crypto, tech.",parameters:o.Object({focus:o.Optional(o.String({description:"Comma-separated topics"}))}),execute:async(e,t)=>{const n=new URLSearchParams;t.focus&&n.set("focus",t.focus);const i=await fetch(`${h}/api/agent/world?${n}`);return{content:[{type:"text",text:await i.text()}],details:{}}}},{name:"monitor_the_situation",label:"Monitor",description:"Scrape any URL (Firecrawl), analyze with any LLM, cross-reference with 9,706 markets, push to webhook.",parameters:o.Object({sourceAction:o.String({description:"scrape|crawl|search|map|extract"}),url:o.Optional(o.String()),query:o.Optional(o.String()),topics:o.Optional(o.String({description:"Comma-separated topics for market enrichment"}))}),execute:async(e,t)=>{const n={source:{action:t.sourceAction}};t.url&&(n.source.url=t.url),t.query&&(n.source.query=t.query),t.topics&&(n.enrich={enabled:!0,topics:t.topics.split(",").map(e=>e.trim()),includeIndex:!0});const i=await fetch(`${h}/api/monitor-the-situation`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(n)}),a=await i.json();return{content:[{type:"text",text:JSON.stringify(a,null,2)}],details:{}}}},{name:"enrich_content",label:"Enrich",description:"Cross-reference any text with 9,706 prediction markets. Returns divergences.",parameters:o.Object({content:o.String({description:"Text to cross-reference"}),topics:o.Optional(o.String({description:"Comma-separated topics"}))}),execute:async(e,t)=>{const n={content:t.content};t.topics?n.topics=t.topics.split(",").map(e=>e.trim()):n.topics=["general"];const i=await fetch(`${h}/api/monitor-the-situation/enrich`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(n)}),a=await i.json();return{content:[{type:"text",text:JSON.stringify(a,null,2)}],details:{}}}},{name:"create_skill",label:"Create Skill",description:"Create a custom agent skill.",parameters:o.Object({name:o.String(),trigger:o.String(),description:o.String(),prompt:o.String(),category:o.Optional(o.String())}),execute:async(e,t)=>{const n=await fetch(`${h}/api/skill`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${c.apiKey}`},body:JSON.stringify(t)}),i=await n.json();return{content:[{type:"text",text:JSON.stringify(i,null,2)}],details:{}}}},{name:"list_skills",label:"Skills",description:"List built-in + custom skills.",parameters:l,execute:async()=>{const e=await fetch(`${h}/api/skill`,{headers:{Authorization:`Bearer ${c.apiKey}`}}),t=await e.json();return{content:[{type:"text",text:JSON.stringify(t,null,2)}],details:{}}}},{name:"browse_public_skills",label:"Public Skills",description:"Browse community skills.",parameters:o.Object({q:o.Optional(o.String()),sort:o.Optional(o.String())}),execute:async(e,t)=>{const n=new URLSearchParams;t.q&&n.set("q",t.q),t.sort&&n.set("sort",t.sort);const i=await fetch(`${h}/api/public/skills?${n}`),a=await i.json();return{content:[{type:"text",text:JSON.stringify(a,null,2)}],details:{}}}},{name:"fork_skill",label:"Fork Skill",description:"Fork a public skill into your collection.",parameters:o.Object({skillId:o.String()}),execute:async(e,t)=>{const n=await fetch(`${h}/api/skill/${t.skillId}/fork`,{method:"POST",headers:{Authorization:`Bearer ${c.apiKey}`}}),i=await n.json();return{content:[{type:"text",text:JSON.stringify(i,null,2)}],details:{}}}},{name:"fork_thesis",label:"Fork Thesis",description:"Fork a public thesis. Copies thesis + causal tree.",parameters:o.Object({slug:o.String()}),execute:async(e,t)=>{const n=await fetch(`${h}/api/thesis/${t.slug}/fork`,{method:"POST",headers:{Authorization:`Bearer ${c.apiKey}`}}),i=await n.json();return{content:[{type:"text",text:JSON.stringify(i,null,2)}],details:{}}}}),c.tradingEnabled&&g.push({name:"place_order",label:"Place Order",description:"Place a buy or sell order on Kalshi. Requires trading to be enabled. Always confirm with user before placing.",parameters:o.Object({ticker:o.String({description:"Market ticker (e.g. KXWTIMAX-26DEC31-T135)"}),side:o.String({description:"yes or no"}),action:o.String({description:"buy or sell"}),count:o.Number({description:"Number of contracts"}),yes_price:o.Number({description:"Price in cents (1-99)"})}),execute:async(e,t)=>{try{const e=await d.createOrder({ticker:t.ticker,side:t.side,action:t.action,type:"limit",count:t.count,yes_price:t.yes_price});return{content:[{type:"text",text:`✓ Order placed: ${(e.order||e).order_id||"OK"}\n${t.action.toUpperCase()} ${t.count}x ${t.ticker} ${t.side.toUpperCase()} @ ${t.yes_price}¢`}],details:{}}}catch(e){return{content:[{type:"text",text:`✗ Order failed: ${e.message}`}],details:{}}}}},{name:"cancel_order",label:"Cancel Order",description:"Cancel a resting order on Kalshi.",parameters:o.Object({orderId:o.String({description:"Order ID to cancel"})}),execute:async(e,t)=>{try{return await d.cancelOrder(t.orderId),{content:[{type:"text",text:`✓ Order ${t.orderId} cancelled.`}],details:{}}}catch(e){return{content:[{type:"text",text:`✗ Cancel failed: ${e.message}`}],details:{}}}}}),g.push({name:"fs_read",label:"Read File",description:"Read a file from workspace (~/.sf/workspace/).",parameters:o.Object({path:o.String({description:"Relative file path"})}),execute:async(e,t)=>{const n=(0,a.wsRead)(t.path);return{content:[{type:"text",text:n.ok?n.content:`Error: ${n.content}`}],details:{}}}},{name:"fs_write",label:"Write File",description:"Write or append to a file in workspace.",parameters:o.Object({path:o.String({description:"Relative file path"}),content:o.String({description:"Content"}),append:o.Optional(o.Boolean({description:"Append mode"}))}),execute:async(e,t)=>({content:[{type:"text",text:(0,a.wsWrite)(t.path,t.content,t.append).message}],details:{}})},{name:"fs_list",label:"List Files",description:"List files in workspace.",parameters:o.Object({path:o.Optional(o.String({description:"Directory"})),glob:o.Optional(o.String({description:"Filter pattern"}))}),execute:async(e,t)=>{const n=(0,a.wsList)(t.path,t.glob);return n.ok?{content:[{type:"text",text:n.entries.length>0?n.entries.join("\n"):"(empty)"}],details:{}}:{content:[{type:"text",text:`Error: ${n.message}`}],details:{}}}},{name:"fs_search",label:"Search Files",description:"Search file contents in workspace using regex.",parameters:o.Object({pattern:o.String({description:"Regex pattern"}),path:o.Optional(o.String({description:"Directory scope"}))}),execute:async(e,t)=>{const n=(0,a.wsSearch)(t.pattern,t.path);return n.ok?0===n.matches.length?{content:[{type:"text",text:"No matches."}],details:{}}:{content:[{type:"text",text:n.matches.map(e=>`${e.file}:${e.line}: ${e.text}`).join("\n")}],details:{}}:{content:[{type:"text",text:`Error: ${n.message}`}],details:{}}}},{name:"fs_delete",label:"Delete File",description:"Delete a file from workspace.",parameters:o.Object({path:o.String({description:"File to delete"})}),execute:async(e,t)=>({content:[{type:"text",text:(0,a.wsDelete)(t.path).message}],details:{}})}),g.push({name:"calculate",label:"Calculate",description:"Evaluate a math expression precisely.",parameters:o.Object({expression:o.String({description:"Math expression"})}),execute:async(e,t)=>{try{const e=t.expression.trim();return/^[\d\s+\-*/.%(),eE]+$/.test(e.replace(/Math\.\w+/g,"").replace(/\*\*/g,""))?{content:[{type:"text",text:`${e} = ${new Function(`"use strict"; return (${e})`)()}`}],details:{}}:{content:[{type:"text",text:"Unsafe expression."}],details:{}}}catch(e){return{content:[{type:"text",text:`Calc error: ${e.message}`}],details:{}}}}},{name:"cancel_all_intents",label:"Cancel All",description:"Cancel all active intents. Emergency use.",parameters:o.Object({confirm:o.Boolean({description:"Must be true"})}),execute:async(t,n)=>{if(!n.confirm)return{content:[{type:"text",text:"Set confirm=true."}],details:{}};try{const t=((await e.listIntents({active:!0})).intents||[]).filter(e=>["pending","armed"].includes(e.status));if(0===t.length)return{content:[{type:"text",text:"No active intents."}],details:{}};let n=0;for(const i of t)try{await e.cancelIntentAPI(i.id),n++}catch{}return{content:[{type:"text",text:`Cancelled ${n}/${t.length} intents.`}],details:{}}}catch(e){return{content:[{type:"text",text:`Error: ${e.message}`}],details:{}}}}});const y=c.apiUrl||process.env.SF_API_URL||"https://simplefunctions.dev";return c.apiKey||process.env.SF_API_KEY,g.push({name:"create_intent",label:"Create Intent",description:"Declare an execution intent with trigger conditions. Runtime daemon evaluates triggers and executes via local keys.",parameters:o.Object({action:o.String({description:"buy or sell"}),venue:o.String({description:"kalshi or polymarket"}),marketId:o.String({description:"Market ticker"}),marketTitle:o.String({description:"Human-readable name"}),direction:o.String({description:"yes or no"}),targetQuantity:o.Number({description:"Number of contracts"}),maxPrice:o.Optional(o.Number({description:"Max price in cents (1-99)"})),triggerType:o.Optional(o.String({description:"immediate, price_below, price_above, time"})),triggerPrice:o.Optional(o.Number({description:"Price trigger threshold in cents"})),triggerAt:o.Optional(o.String({description:"ISO timestamp for time trigger"})),softCondition:o.Optional(o.String({description:"Natural language condition evaluated by LLM before execution"})),rationale:o.Optional(o.String({description:"Why this trade"})),autoExecute:o.Optional(o.Boolean({description:"Auto-execute without confirmation"}))}),execute:async(t,n)=>{const i=await e.createIntent({...n,source:"telegram",expireAt:new Date(Date.now()+864e5).toISOString()});return{content:[{type:"text",text:JSON.stringify(i,null,2)}],details:{}}}},{name:"list_intents",label:"List Intents",description:"List execution intents — pending, armed, triggered, filled.",parameters:o.Object({activeOnly:o.Optional(o.Boolean({description:"Only active (default true)"}))}),execute:async(t,n)=>{const i=await e.listIntents({active:!1!==n.activeOnly});return{content:[{type:"text",text:JSON.stringify(i,null,2)}],details:{}}}},{name:"cancel_intent",label:"Cancel Intent",description:"Cancel an active intent.",parameters:o.Object({intentId:o.String({description:"Intent ID"})}),execute:async(t,n)=>{const i=await e.cancelIntentAPI(n.intentId);return{content:[{type:"text",text:JSON.stringify(i)}],details:{}}}},{name:"runtime_status",label:"Runtime Status",description:"Check if the local execution runtime is running.",parameters:l,execute:async()=>{const{existsSync:t,readFileSync:i}=await Promise.resolve().then(n.t.bind(n,79896,23)),{join:a}=await Promise.resolve().then(n.t.bind(n,16928,23)),{homedir:s}=await Promise.resolve().then(n.t.bind(n,70857,23)),r=a(s(),".sf","runtime.pid");let o=!1,c="";if(t(r)){c=i(r,"utf-8").trim();try{process.kill(parseInt(c),0),o=!0}catch{}}const l=await e.listIntents({active:!0});return{content:[{type:"text",text:JSON.stringify({running:o,pid:o?c:null,...l},null,2)}],details:{}}}},{name:"runtime_start",label:"Start Runtime",description:"Start the local execution runtime daemon.",parameters:l,execute:async()=>{const{existsSync:e,readFileSync:t,mkdirSync:i,openSync:a}=await Promise.resolve().then(n.t.bind(n,79896,23)),{join:s}=await Promise.resolve().then(n.t.bind(n,16928,23)),{homedir:r}=await Promise.resolve().then(n.t.bind(n,70857,23)),{spawn:o}=await Promise.resolve().then(n.t.bind(n,35317,23)),c=s(r(),".sf","runtime.pid"),l=s(r(),".sf","runtime.log");if(e(c)){const e=t(c,"utf-8").trim();try{return process.kill(parseInt(e),0),{content:[{type:"text",text:`Runtime already running (PID ${e}).`}],details:{}}}catch{}}i(s(r(),".sf"),{recursive:!0});const d=a(l,"a");return o(process.execPath,[process.argv[1],"runtime","start"],{detached:!0,stdio:["ignore",d,d],env:{...process.env}}).unref(),await new Promise(e=>setTimeout(e,1e3)),{content:[{type:"text",text:`Runtime started. Log: ${l}`}],details:{}}}},{name:"runtime_stop",label:"Stop Runtime",description:"Stop the local execution runtime daemon.",parameters:l,execute:async()=>{const{existsSync:e,readFileSync:t,unlinkSync:i}=await Promise.resolve().then(n.t.bind(n,79896,23)),{join:a}=await Promise.resolve().then(n.t.bind(n,16928,23)),{homedir:s}=await Promise.resolve().then(n.t.bind(n,70857,23)),r=a(s(),".sf","runtime.pid");if(!e(r))return{content:[{type:"text",text:"No runtime running."}],details:{}};const o=t(r,"utf-8").trim();try{return process.kill(parseInt(o),"SIGTERM"),i(r),{content:[{type:"text",text:`Runtime stopped (PID ${o}).`}],details:{}}}catch{try{i(r)}catch{}return{content:[{type:"text",text:"Runtime was not running (stale PID removed)."}],details:{}}}}},{name:"daemon_command",label:"Daemon Command",description:"Send command to a running daemon. Actions: pause, resume, scan_now.",parameters:o.Object({target:o.String({description:"Target: runtime, telegram, watch"}),action:o.String({description:"Command: pause, resume, scan_now"})}),execute:async(e,t)=>{const{writeMessage:i}=await n.e(563).then(n.bind(n,9563)),a=i({from:"agent",to:t.target,type:"command",priority:"normal",payload:{action:t.action},ttl:3600});return{content:[{type:"text",text:`Command sent to ${t.target}: ${t.action} (msg ${a})`}],details:{}}}},{name:"set_wake_condition",label:"Set Wake Condition",description:"Set a condition for daemons to alert you. Types: price, time, llm.",parameters:o.Object({description:o.String({description:"Human-readable description"}),type:o.String({description:"price, time, or llm"}),condition:o.Any({description:"Condition config"}),priority:o.Optional(o.String())}),execute:async(e,t)=>{const{saveWakeCondition:i}=await n.e(563).then(n.bind(n,9563)),{randomBytes:a}=await Promise.resolve().then(n.t.bind(n,76982,23)),s={id:a(8).toString("hex"),createdAt:(new Date).toISOString(),description:t.description,type:t.type,[`${t.type}Condition`]:t.condition,alertChannels:["bus","telegram"],priority:t.priority||"normal",maxFires:-1,firedCount:0,lastFiredAt:null,expiresAt:null,active:!0};return i(s),{content:[{type:"text",text:`Wake condition set: "${t.description}" (${s.id})`}],details:{}}}},{name:"check_daemon_alerts",label:"Check Alerts",description:"Read alerts from running daemons.",parameters:l,execute:async()=>{const{readMessages:e,deleteMessage:t}=await n.e(563).then(n.bind(n,9563)),i=e("agent","outbox");return 0===i.length?{content:[{type:"text",text:"No new daemon alerts."}],details:{}}:{content:[{type:"text",text:i.map(e=>(t(e.id,"outbox"),`[${e.priority}] ${e.from}: ${e.payload.summary||JSON.stringify(e.payload)}`)).join("\n")}],details:{}}}},{name:"schedule_wake",label:"Schedule Wake",description:"Schedule a self-wake: after N minutes, perform an action. Can repeat.",parameters:o.Object({delayMinutes:o.Number({description:"Minutes from now"}),action:o.String({description:"prompt, tool, or check"}),prompt:o.Optional(o.String({description:"Prompt text (for action=prompt)"})),repeatMinutes:o.Optional(o.Number({description:"Repeat interval in minutes"})),context:o.Optional(o.String({description:"Why this wake"}))}),execute:async(e,i)=>{const{scheduleWake:a}=await n.e(563).then(n.bind(n,9563)),s=a({...i,thesisId:t});return{content:[{type:"text",text:`Wake scheduled: ${s.id} fires at ${s.fireAt}${i.repeatMinutes?` (repeats every ${i.repeatMinutes}m)`:""}`}],details:{}}}},{name:"list_wakes",label:"List Wakes",description:"List all scheduled self-wakes.",parameters:l,execute:async()=>{const{listWakes:e}=await n.e(563).then(n.bind(n,9563)),t=e();return 0===t.length?{content:[{type:"text",text:"No scheduled wakes."}],details:{}}:{content:[{type:"text",text:t.map(e=>`${e.id.slice(0,8)} ${e.firedAt?"FIRED":"PENDING"} at ${e.fireAt} — ${e.context||e.action}`).join("\n")}],details:{}}}},{name:"cancel_wake",label:"Cancel Wake",description:"Cancel a scheduled wake.",parameters:o.Object({wakeId:o.String({description:"Wake ID"})}),execute:async(e,t)=>{const{cancelWake:i}=await n.e(563).then(n.bind(n,9563));return{content:[{type:"text",text:i(t.wakeId)?"Cancelled.":"Not found."}],details:{}}}},{name:"send_alert",label:"Send Alert",description:"Push an alert to Telegram and/or daemon bus.",parameters:o.Object({message:o.String({description:"Alert message"}),priority:o.Optional(o.String({description:"low | normal | high | critical"}))}),execute:async(e,t)=>{try{const{writeMessage:e}=await n.e(563).then(n.bind(n,9563));return e({from:"agent",to:"all",type:"alert",priority:t.priority||"high",payload:{summary:t.message},ttl:7200}),{content:[{type:"text",text:`Alert sent: "${t.message}"`}],details:{}}}catch(e){return{content:[{type:"text",text:`Error: ${e.message}`}],details:{}}}}}),g.push({name:"get_world_delta",label:"World Delta",description:"Incremental world state update — only what changed. ~30-50 tokens. Much cheaper than full state for polling.",parameters:o.Object({since:o.Optional(o.String({description:'"30m", "1h", "6h", "24h" or ISO timestamp (default "1h")'}))}),execute:async(e,t)=>{const n=t.since||"1h",i=await fetch(`${y}/api/agent/world/delta?since=${encodeURIComponent(n)}`);return i.ok?{content:[{type:"text",text:await i.text()}],details:{}}:{content:[{type:"text",text:`Delta API error: ${i.status}`}],details:{}}}},{name:"get_trade_ideas",label:"Trade Ideas",description:"S&T-style trade ideas with conviction levels and catalysts.",parameters:o.Object({freshness:o.Optional(o.String({description:"today, week, or all"})),category:o.Optional(o.String({description:"macro, geopolitics, crypto, policy, event"}))}),execute:async(e,t)=>{const n=new URLSearchParams;t.freshness&&n.set("freshness",t.freshness),t.category&&n.set("category",t.category);const i=await fetch(`${y}/api/public/ideas?${n.toString()}`);return i.ok?{content:[{type:"text",text:JSON.stringify(await i.json(),null,2)}],details:{}}:{content:[{type:"text",text:`Ideas API error: ${i.status}`}],details:{}}}},{name:"get_milestones",label:"Milestones",description:"Upcoming events from Kalshi calendar: economic releases, political events, catalysts.",parameters:o.Object({hours:o.Optional(o.Number({description:"Hours ahead (default 168 = 1 week)"})),category:o.Optional(o.String({description:"Economics, Politics, Sports"}))}),execute:async(e,t)=>{const i=await Promise.resolve().then(n.t.bind(n,96139,23)),a=await i.getExchangeAnnouncements();if(!a||0===a.length)return{content:[{type:"text",text:"No upcoming milestones."}],details:{}};const s=t.category?a.filter(e=>e.category?.toLowerCase().includes(t.category.toLowerCase())):a;return{content:[{type:"text",text:JSON.stringify(s.slice(0,20),null,2)}],details:{}}}},{name:"get_liquidity",label:"Liquidity",description:"Orderbook liquidity analysis for markets matching a query. Returns bid/ask depth, spread, liquidity score.",parameters:o.Object({query:o.String({description:"Search query"})}),execute:async(e,t)=>{const i=await fetch(`${y}/api/public/scan?q=${encodeURIComponent(t.query)}&limit=10`);if(!i.ok)return{content:[{type:"text",text:`Scan error: ${i.status}`}],details:{}};const a=await i.json(),s=(a.results||a.markets||[]).slice(0,5),r=[];for(const e of s)if("kalshi"===e.venue&&e.ticker){const t=await(await Promise.resolve().then(n.t.bind(n,96139,23))).getPublicOrderbook(e.ticker,5);if(t){const n=t.yes_dollars||[],i=t.no_dollars||[],a=n.length>0?Math.round(100*parseFloat(n[0][0])):0,s=i.length>0?100-Math.round(100*parseFloat(i[0][0])):100;r.push({ticker:e.ticker,title:(e.title||"").slice(0,50),bestBid:a,bestAsk:s,spread:s-a,venue:"kalshi"})}}return{content:[{type:"text",text:r.length>0?JSON.stringify(r,null,2):"No orderbook data found."}],details:{}}}},{name:"explore_public",label:"Explore Public",description:"Browse public theses with edges. Discover what other users are tracking.",parameters:o.Object({limit:o.Optional(o.Number({description:"Max results (default 10)"}))}),execute:async(e,t)=>{const n=await fetch(`${y}/api/public/theses?limit=${t.limit||10}`);return n.ok?{content:[{type:"text",text:JSON.stringify(await n.json(),null,2)}],details:{}}:{content:[{type:"text",text:`Public theses error: ${n.status}`}],details:{}}}},{name:"create_strategy",label:"Create Strategy",description:"Create a trading strategy for a thesis with entry/exit conditions.",parameters:o.Object({marketId:o.String({description:"Market ticker"}),market:o.String({description:"Human-readable name"}),direction:o.String({description:"yes or no"}),entryBelow:o.Optional(o.Number({description:"Entry: ask <= cents"})),stopLoss:o.Optional(o.Number({description:"Stop loss: bid <= cents"})),takeProfit:o.Optional(o.Number({description:"Take profit: bid >= cents"})),maxQuantity:o.Optional(o.Number({description:"Max contracts (default 500)"})),softConditions:o.Optional(o.String({description:"LLM-evaluated conditions"})),rationale:o.Optional(o.String({description:"Reasoning"}))}),execute:async(n,i)=>{const a=await e.createStrategyAPI(t,{...i,createdBy:"telegram"});return{content:[{type:"text",text:JSON.stringify(a)}],details:{}}}},{name:"list_strategies",label:"List Strategies",description:"List strategies for the current thesis.",parameters:o.Object({status:o.Optional(o.String({description:"Filter: active, watching, executed, cancelled"}))}),execute:async(n,i)=>{const a=await e.getStrategies(t,i.status);return{content:[{type:"text",text:JSON.stringify(a,null,2)}],details:{}}}}),g}(e,t.thesisId,y),b=d.model||"anthropic/claude-sonnet-4.6";let w;try{w=l("openrouter",b)}catch{w={modelId:b,provider:"openrouter",api:"openai-completions",baseUrl:"https://openrouter.ai/api/v1",id:b,name:b,inputPrice:0,outputPrice:0,contextWindow:2e5,supportsImages:!0,supportsTools:!0,headers:{"HTTP-Referer":"https://simplefunctions.dev","X-Title":"SimpleFunctions"}}}g&&(w.baseUrl=`${m}/api/proxy`);const S=(y.edges||[]).sort((e,t)=>Math.abs(t.edge)-Math.abs(e.edge)).slice(0,5).map(e=>` ${(e.market||"").slice(0,35)} | ${e.venue||"kalshi"} | mkt ${e.marketPrice}¢ → thesis ${e.thesisPrice}¢ | edge ${e.edge>0?"+":""}${e.edge}`).join("\n")||" (no edges)",k=(y.causalTree?.nodes||[]).filter(e=>0===e.depth||!e.depth).slice(0,5).map(e=>` ${e.id} ${(e.label||"").slice(0,35)} — ${Math.round(100*(e.probability||.5))}%`).join("\n")||" (no causal tree)",O=new s({initialState:{systemPrompt:`You are a prediction market trading assistant on Telegram. Your job is to help the user see reality clearly and make correct trading decisions.\n\n## Framework\nEdge = thesis price - market price. Positive = market underprices.\nEdge types: [consensus] depth>=500 real opponents, [attention] depth<100 illusory, [timing] market lags, [risk_premium] platform risk. Tag when reporting.\nPrice: depth >= 500 = consensus, < 100 = unreliable, spread > 5 = noisy.\n\n## Rules\n- When reporting an edge, tag it: [consensus] [attention] [timing] [risk_premium].\n- If any kill condition is triggered or approaching, lead with that.\n- If nothing material to do, say "quiet — no action needed." Don't pad.\n- Keep Telegram messages SHORT — bullet points, no walls of text.\n- Prices in cents (¢). P&L in dollars ($). Don't re-convert tool output units.\n- Call tools for fresh data. Never guess prices or P&L from this prompt.\n- Use search_x for X/Twitter sentiment. Use x_volume for discussion spikes. Use x_account to track key people.\n- Use heartbeat_config to view/adjust scan intervals, model tier, budget cap, or check cost breakdown.\n- Use monitor_the_situation to scrape URLs and cross-reference with markets. Use enrich_content for text-only analysis.\n- Use get_world_state for broad situational awareness (~800 tokens). Use get_world_delta for cheap incremental updates.\n- Use get_trade_ideas for S&T-style pitches. Use get_milestones for upcoming catalysts.\n- Use get_liquidity / explore_public for discovery. Use create_strategy / list_strategies for trade planning.\n- Use create_skill / list_skills / browse_public_skills / fork_skill to manage agent skills.\n- Use fork_thesis to fork a public thesis (copies thesis + causal tree).\n- fs_read/fs_write/fs_list/fs_search/fs_delete: workspace. Write notes proactively. Shared with TUI.\n- calculate: precise math. send_alert: push to Telegram/bus. schedule_wake / list_wakes / cancel_wake: self-scheduling.\n- create_intent / list_intents / cancel_intent: execution intents with triggers.\n- runtime_start / runtime_stop / runtime_status: local execution daemon.\n- daemon_command / set_wake_condition / check_daemon_alerts: smart daemon control.\n- Live State shows positions/edges each turn — use it directly, don't re-fetch.\n- If user mentions news, inject_signal immediately. Don't ask "should I?"\n- If user says "evaluate" or "run it", trigger immediately.\n- Don't end with "anything else?" — user will ask.\n- Use Chinese if user writes Chinese, English if English.\n${d.tradingEnabled?"- Trading ENABLED. You have place_order and cancel_order. ALWAYS confirm before placing.":"- Trading DISABLED. Tell user: sf setup --enable-trading"}\n\n## Current State\nThesis: ${(y.thesis||y.rawThesis||"N/A").slice(0,200)}\nID: ${t.thesisId.slice(0,8)} | Confidence: ${x}%\n\nCausal nodes:\n${k}\n\nTop edges:\n${S}\n\n${y.lastEvaluation?.summary?`Latest eval: ${y.lastEvaluation.summary.slice(0,200)}`:""}`,model:w,tools:f,thinkingLevel:"off"},streamFn:o,getApiKey:e=>"openrouter"===e?h:void 0});if(t.agentMessages.length>0)try{O.replaceMessages(t.agentMessages)}catch{}else if(t.thesisId)try{const e=(0,a.readRecentContext)(t.thesisId,30);if(e.length>0){const t=[];for(const n of e)"user"===n.role?t.push({role:"user",content:n.content}):"assistant"===n.role&&t.push({role:"assistant",content:n.content});const n=[];for(const e of t)0!==n.length&&n[n.length-1].role===e.role||n.push(e);if(n.length>0)try{O.replaceMessages(n)}catch{}}}catch{}return t.agent=O,O}}};
|
|
1
|
+
"use strict";exports.id=160,exports.ids=[160],exports.modules={28160:(e,t,n)=>{t.runAgentMessage=async function(e,t,n,i){const s=await o(e,t);return new Promise((e,r)=>{let o="",c="";const l=setTimeout(()=>{e(o||c||"Response timeout (45s). Try a simpler question.")},45e3),d=s.subscribe(r=>{if("message_update"===r.type){const e=r.assistantMessageEvent;"text_delta"===e.type&&(o+=e.delta)}if("tool_execution_start"===r.type&&(c+=`⚡ ${r.toolName}\n`,i&&i(r.toolName)),"agent_end"===r.type){clearTimeout(l),d?.(),s.state?.error&&console.error("[bridge] agent error:",s.state.error),t.agentMessages=s.state.messages||[];try{t.thesisId&&((0,a.appendContext)(t.thesisId,{ts:(new Date).toISOString(),role:"user",content:n,source:"telegram"}),o&&(0,a.appendContext)(t.thesisId,{ts:(new Date).toISOString(),role:"assistant",content:o.slice(0,5e3),source:"telegram"}))}catch{}e(o||c||"(no response)")}});s.prompt(n).catch(e=>{clearTimeout(l),d?.(),r(e)})})};const i=n(11627),a=n(73600);let s=null;async function r(){if(s)return s;const[e,t]=await Promise.all([Promise.all([n.e(788),n.e(641),n.e(582)]).then(n.bind(n,65653)),Promise.all([n.e(788),n.e(641),n.e(174)]).then(n.bind(n,99641))]),i=await Promise.all([n.e(788),n.e(722)]).then(n.bind(n,85722));return s={Agent:e.Agent,streamSimple:t.streamSimple,Type:i.Type},s}async function o(e,t){if(t.agent)return t.agent;const{Agent:s,streamSimple:o}=await r(),c=await Promise.all([n.e(788),n.e(641),n.e(174)]).then(n.bind(n,99641)),{getModel:l}=c,d=(0,i.loadConfig)(),p=d.openrouterKey||process.env.OPENROUTER_API_KEY,u=d.apiKey||process.env.SF_API_KEY,m=d.apiUrl||process.env.SF_API_URL||"https://simplefunctions.dev",g=!p&&!!u,y=p||u;if(!y)throw new Error("Need API key. Run sf login or sf setup.");const h=await e.getContext(t.thesisId),x=await async function(e,t,s){const{Type:o}=await r(),c=(0,i.loadConfig)(),l=o.Object({}),d=await Promise.resolve().then(n.t.bind(n,96139,23)),{kalshiFetchAllSeries:p,kalshiFetchMarketsBySeries:u,kalshiFetchMarket:m}=await Promise.resolve().then(n.bind(n,19218)),g=[{name:"get_context",label:"Context",description:"Get thesis snapshot with causal tree, edges, evaluation",parameters:l,execute:async()=>{const n=await e.getContext(t);return{content:[{type:"text",text:JSON.stringify(n,null,2)}],details:{}}}},{name:"global_context",label:"Snapshot",description:"Global market snapshot — movers, expiring, milestones, liquidity, signals. No thesis needed.",parameters:l,execute:async()=>{const{fetchGlobalContext:e}=await Promise.resolve().then(n.bind(n,19218)),t=await e();return{content:[{type:"text",text:JSON.stringify(t,null,2)}],details:{}}}},{name:"query",label:"Query",description:"LLM-enhanced prediction market search. Returns answer, live prices, key factors.",parameters:o.Object({q:o.String({description:"Question"})}),execute:async(e,t)=>{const{fetchQuery:i}=await Promise.resolve().then(n.bind(n,19218)),a=await i(t.q);return{content:[{type:"text",text:JSON.stringify(a,null,2)}],details:{}}}},{name:"get_markets",label:"Markets",description:"Traditional market prices: SPY, VIX, Treasury, Gold, Oil.",parameters:l,execute:async()=>{const{fetchTraditionalMarkets:e}=await Promise.resolve().then(n.bind(n,19218)),t=await e();return{content:[{type:"text",text:JSON.stringify(t,null,2)}],details:{}}}},{name:"inject_signal",label:"Signal",description:"Inject a signal (news, note, observation) into the thesis",parameters:o.Object({content:o.String({description:"Signal content"}),type:o.Optional(o.String({description:"news | user_note | external"}))}),execute:async(n,i)=>(await e.injectSignal(t,i.type||"user_note",i.content,"telegram"),{content:[{type:"text",text:"Signal injected."}],details:{}})},{name:"trigger_evaluation",label:"Evaluate",description:"Trigger a deep evaluation cycle",parameters:l,execute:async()=>(await e.evaluate(t),{content:[{type:"text",text:"Evaluation triggered. Results in ~2 minutes."}],details:{}})},{name:"scan_markets",label:"Scan",description:"Search Kalshi markets by keyword, series, or ticker",parameters:o.Object({query:o.Optional(o.String({description:"Keyword search"})),series:o.Optional(o.String({description:"Series ticker"})),market:o.Optional(o.String({description:"Market ticker"}))}),execute:async(e,t)=>{let n;if(t.market)n=await m(t.market);else if(t.series)n=await u(t.series);else if(t.query){const e=await p(),i=t.query.toLowerCase().split(/\s+/);n=e.filter(e=>i.every(t=>((e.title||"")+(e.ticker||"")).toLowerCase().includes(t))).filter(e=>parseFloat(e.volume_fp||"0")>1e3).sort((e,t)=>parseFloat(t.volume_fp||"0")-parseFloat(e.volume_fp||"0")).slice(0,10)}else n={error:"Provide query, series, or market"};return{content:[{type:"text",text:JSON.stringify(n,null,2)}],details:{}}}},{name:"list_theses",label:"List",description:"List all theses",parameters:l,execute:async()=>{const t=await e.listTheses();return{content:[{type:"text",text:JSON.stringify(t,null,2)}],details:{}}}},{name:"get_positions",label:"Positions",description:"Get Kalshi positions with live prices and P&L",parameters:l,execute:async()=>{const e=await d.getPositions();if(!e)return{content:[{type:"text",text:"Kalshi not configured."}],details:{}};for(const t of e){const e=await d.getMarketPrice(t.ticker);null!=e&&(t.current_value=e,t.unrealized_pnl=Math.round((e-t.average_price_paid)*t.quantity))}const t=e.map(e=>({ticker:e.ticker,qty:e.quantity,avg_price:`${e.average_price_paid}¢`,current:`${e.current_value}¢`,pnl:`$${((e.unrealized_pnl||0)/100).toFixed(2)}`}));return{content:[{type:"text",text:JSON.stringify(t,null,2)}],details:{}}}},{name:"get_balance",label:"Balance",description:"Get Kalshi account balance",parameters:l,execute:async()=>{const e=await d.getBalance();return e?{content:[{type:"text",text:JSON.stringify(e,null,2)}],details:{}}:{content:[{type:"text",text:"Kalshi not configured."}],details:{}}}},{name:"get_orders",label:"Orders",description:"Get resting orders on Kalshi",parameters:l,execute:async()=>{const e=await d.getOrders({status:"resting",limit:50});return e?{content:[{type:"text",text:JSON.stringify(e.orders,null,2)}],details:{}}:{content:[{type:"text",text:"Kalshi not configured."}],details:{}}}},{name:"get_fills",label:"Fills",description:"Get recent trade fills",parameters:o.Object({ticker:o.Optional(o.String())}),execute:async(e,t)=>{const n=await d.getFills({ticker:t.ticker,limit:20});return n?{content:[{type:"text",text:JSON.stringify(n.fills,null,2)}],details:{}}:{content:[{type:"text",text:"Kalshi not configured."}],details:{}}}},{name:"get_settlements",label:"Settlements",description:"Get settled contracts with P&L",parameters:l,execute:async()=>{const e=await d.getSettlements({limit:50});return e?{content:[{type:"text",text:JSON.stringify(e.settlements,null,2)}],details:{}}:{content:[{type:"text",text:"Kalshi not configured."}],details:{}}}},{name:"get_edges",label:"Edges",description:"Top 10 edges across all active theses",parameters:l,execute:async()=>{const{theses:t}=await e.listTheses(),n=(t||[]).filter(e=>"active"===e.status),i=await Promise.allSettled(n.map(async t=>((await e.getContext(t.id)).edges||[]).map(e=>({...e,thesisId:t.id})))),a=[];for(const e of i)"fulfilled"===e.status&&a.push(...e.value);return a.sort((e,t)=>Math.abs(t.edge||0)-Math.abs(e.edge||0)),{content:[{type:"text",text:JSON.stringify(a.slice(0,10),null,2)}],details:{}}}},{name:"get_schedule",label:"Schedule",description:"Exchange status (open/closed) and trading hours",parameters:l,execute:async()=>{const e=await fetch("https://api.elections.kalshi.com/trade-api/v2/exchange/status",{headers:{Accept:"application/json"}});if(!e.ok)return{content:[{type:"text",text:`API error: ${e.status}`}],details:{}};const t=await e.json();return{content:[{type:"text",text:JSON.stringify(t,null,2)}],details:{}}}},{name:"get_feed",label:"Feed",description:"Recent evaluation history",parameters:o.Object({hours:o.Optional(o.Number({description:"Hours of history (default 24)"}))}),execute:async(t,n)=>{const i=await e.getFeed(n.hours||24);return{content:[{type:"text",text:JSON.stringify(i,null,2)}],details:{}}}},{name:"web_search",label:"Search",description:"Search the web for latest news",parameters:o.Object({query:o.String({description:"Search query"})}),execute:async(e,t)=>{const n=process.env.TAVILY_API_KEY||c.tavilyKey,i=c.apiKey||process.env.SF_API_KEY,a=c.apiUrl||process.env.SF_API_URL||"https://simplefunctions.dev";if(!n&&(n||!i))return{content:[{type:"text",text:"Web search not available. Run sf login or set TAVILY_API_KEY."}],details:{}};let s;if(s=n?await fetch("https://api.tavily.com/search",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({api_key:n,query:t.query,max_results:3,search_depth:"basic",include_answer:!0})}):await fetch(`${a}/api/proxy/search`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${i}`},body:JSON.stringify({query:t.query,max_results:3,search_depth:"basic",include_answer:!0})}),!s.ok)return{content:[{type:"text",text:`Search failed: ${s.status}`}],details:{}};const r=await s.json();return{content:[{type:"text",text:`${r.answer?`Summary: ${r.answer}\n\n`:""}${(r.results||[]).map(e=>`${e.title}: ${(e.content||"").slice(0,150)}`).join("\n\n")}`}],details:{}}}},{name:"create_thesis",label:"Create",description:"Create a new thesis",parameters:o.Object({rawThesis:o.String({description:"Thesis statement"})}),execute:async(t,n)=>{const i=await e.createThesis(n.rawThesis,!0);return{content:[{type:"text",text:`Created: ${i.id}\nConfidence: ${Math.round(100*(i.confidence||.5))}%`}],details:{}}}},{name:"what_if",label:"What-If",description:"Override causal tree node probabilities and see how edges change. Zero LLM cost.",parameters:o.Object({overrides:o.Array(o.Object({nodeId:o.String({description:"Node ID (e.g. n1, n3.1)"}),newProbability:o.Number({description:"New probability 0-1"})}))}),execute:async(e,t)=>{const n=s,i=[];!function e(t){for(const n of t)i.push(n),n.children?.length&&e(n.children)}(n?.causalTree?.nodes||[]);const a=new Map(t.overrides.map(e=>[e.nodeId,e.newProbability])),r=(n?.causalTree?.nodes||[]).filter(e=>!e.parentId||0===e.depth),o=r.reduce((e,t)=>e+(t.probability||.5),0)/Math.max(r.length,1);for(const e of i)a.has(e.id)&&(e.probability=a.get(e.id));const c=r.reduce((e,t)=>e+(t.probability||.5),0)/Math.max(r.length,1),l=(n?.edges||[]).slice(0,10).map(e=>{const t=i.find(t=>t.id===e.relatedNodeId);if(!t||!a.has(t.id))return{market:e.market,oldEdge:e.edge,newEdge:e.edge,signal:"unchanged"};const n=t.probability/(e.confidence||.5),s=Math.round(e.thesisPrice*n)-e.marketPrice;return{market:e.market,oldEdge:e.edge,newEdge:s,signal:Math.abs(s-e.edge)<1?"unchanged":"changed"}}).filter(e=>"unchanged"!==e.signal);return{content:[{type:"text",text:JSON.stringify({confidence:{old:Math.round(100*o),new:Math.round(100*c)},edges:l},null,2)}],details:{}}}}];g.push({name:"search_x",label:"X Search",description:"Search X (Twitter) for recent discussions. Returns posts, sentiment, themes.",parameters:o.Object({query:o.String({description:"Search query"}),mode:o.Optional(o.String({description:'"summary" or "raw"'})),hours:o.Optional(o.Number({description:"Hours (default 24)"}))}),execute:async(t,n)=>{const i=await e.searchX(n.query,{mode:n.mode,hours:n.hours});return{content:[{type:"text",text:JSON.stringify(i,null,2)}],details:{}}}},{name:"x_volume",label:"X Volume",description:"X discussion volume trend — total posts, velocity, peak time.",parameters:o.Object({query:o.String({description:"Search query"}),hours:o.Optional(o.Number({description:"Hours (default 72)"}))}),execute:async(t,n)=>{const i=await e.getXVolume(n.query,{hours:n.hours});return{content:[{type:"text",text:JSON.stringify(i,null,2)}],details:{}}}},{name:"x_news",label:"X News",description:"News stories trending on X — titles, summaries, tickers.",parameters:o.Object({query:o.String({description:"Search query"}),limit:o.Optional(o.Number({description:"Max stories (default 10)"}))}),execute:async(t,n)=>{const i=await e.searchXNews(n.query,{limit:n.limit});return{content:[{type:"text",text:JSON.stringify(i,null,2)}],details:{}}}},{name:"x_account",label:"X Account",description:"Recent posts from a specific X account.",parameters:o.Object({username:o.String({description:"X username (with or without @)"}),hours:o.Optional(o.Number({description:"Hours (default 24)"}))}),execute:async(t,n)=>{const i=await e.getXAccount(n.username,{hours:n.hours});return{content:[{type:"text",text:JSON.stringify(i,null,2)}],details:{}}}},{name:"heartbeat_config",label:"Heartbeat Config",description:"View or update heartbeat settings: scan intervals, model tier, budget cap, pause/resume. Shows cost breakdown.",parameters:o.Object({thesisId:o.String({description:"Thesis ID"}),newsIntervalMin:o.Optional(o.Number({description:"News scan interval (15-1440 min)"})),xIntervalMin:o.Optional(o.Number({description:"X scan interval (60-1440 min)"})),evalModelTier:o.Optional(o.String({description:"cheap, medium, or heavy"})),monthlyBudgetUsd:o.Optional(o.Number({description:"Monthly budget (0 = unlimited)"})),paused:o.Optional(o.Boolean({description:"Pause or resume heartbeat"}))}),execute:async(t,n)=>{if(n.newsIntervalMin||n.xIntervalMin||n.evalModelTier||void 0!==n.monthlyBudgetUsd||void 0!==n.paused){const t={};n.newsIntervalMin&&(t.newsIntervalMin=n.newsIntervalMin),n.xIntervalMin&&(t.xIntervalMin=n.xIntervalMin),n.evalModelTier&&(t.evalModelTier=n.evalModelTier),void 0!==n.monthlyBudgetUsd&&(t.monthlyBudgetUsd=n.monthlyBudgetUsd),void 0!==n.paused&&(t.paused=n.paused),await e.updateHeartbeatConfig(n.thesisId,t)}const i=await e.getHeartbeatConfig(n.thesisId);return{content:[{type:"text",text:JSON.stringify(i,null,2)}],details:{}}}});const y=process.env.SF_API_URL||c.apiUrl||"https://simplefunctions.dev";g.push({name:"get_world_state",label:"World",description:"Real-time world model (~800 tokens). Geopolitics, economy, energy, elections, crypto, tech.",parameters:o.Object({focus:o.Optional(o.String({description:"Comma-separated topics"}))}),execute:async(e,t)=>{const n=new URLSearchParams;t.focus&&n.set("focus",t.focus);const i=await fetch(`${y}/api/agent/world?${n}`);return{content:[{type:"text",text:await i.text()}],details:{}}}},{name:"monitor_the_situation",label:"Monitor",description:"Scrape any URL (Firecrawl), analyze with any LLM, cross-reference with 9,706 markets, push to webhook.",parameters:o.Object({sourceAction:o.String({description:"scrape|crawl|search|map|extract"}),url:o.Optional(o.String()),query:o.Optional(o.String()),topics:o.Optional(o.String({description:"Comma-separated topics for market enrichment"}))}),execute:async(e,t)=>{const n={source:{action:t.sourceAction}};t.url&&(n.source.url=t.url),t.query&&(n.source.query=t.query),t.topics&&(n.enrich={enabled:!0,topics:t.topics.split(",").map(e=>e.trim()),includeIndex:!0});const i=await fetch(`${y}/api/monitor-the-situation`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(n)}),a=await i.json();return{content:[{type:"text",text:JSON.stringify(a,null,2)}],details:{}}}},{name:"enrich_content",label:"Enrich",description:"Cross-reference any text with 9,706 prediction markets. Returns divergences.",parameters:o.Object({content:o.String({description:"Text to cross-reference"}),topics:o.Optional(o.String({description:"Comma-separated topics"}))}),execute:async(e,t)=>{const n={content:t.content};t.topics?n.topics=t.topics.split(",").map(e=>e.trim()):n.topics=["general"];const i=await fetch(`${y}/api/monitor-the-situation/enrich`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(n)}),a=await i.json();return{content:[{type:"text",text:JSON.stringify(a,null,2)}],details:{}}}},{name:"create_skill",label:"Create Skill",description:"Create a custom agent skill.",parameters:o.Object({name:o.String(),trigger:o.String(),description:o.String(),prompt:o.String(),category:o.Optional(o.String())}),execute:async(e,t)=>{const n=await fetch(`${y}/api/skill`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${c.apiKey}`},body:JSON.stringify(t)}),i=await n.json();return{content:[{type:"text",text:JSON.stringify(i,null,2)}],details:{}}}},{name:"list_skills",label:"Skills",description:"List built-in + custom skills.",parameters:l,execute:async()=>{const e=await fetch(`${y}/api/skill`,{headers:{Authorization:`Bearer ${c.apiKey}`}}),t=await e.json();return{content:[{type:"text",text:JSON.stringify(t,null,2)}],details:{}}}},{name:"browse_public_skills",label:"Public Skills",description:"Browse community skills.",parameters:o.Object({q:o.Optional(o.String()),sort:o.Optional(o.String())}),execute:async(e,t)=>{const n=new URLSearchParams;t.q&&n.set("q",t.q),t.sort&&n.set("sort",t.sort);const i=await fetch(`${y}/api/public/skills?${n}`),a=await i.json();return{content:[{type:"text",text:JSON.stringify(a,null,2)}],details:{}}}},{name:"fork_skill",label:"Fork Skill",description:"Fork a public skill into your collection.",parameters:o.Object({skillId:o.String()}),execute:async(e,t)=>{const n=await fetch(`${y}/api/skill/${t.skillId}/fork`,{method:"POST",headers:{Authorization:`Bearer ${c.apiKey}`}}),i=await n.json();return{content:[{type:"text",text:JSON.stringify(i,null,2)}],details:{}}}},{name:"fork_thesis",label:"Fork Thesis",description:"Fork a public thesis. Copies thesis + causal tree.",parameters:o.Object({slug:o.String()}),execute:async(e,t)=>{const n=await fetch(`${y}/api/thesis/${t.slug}/fork`,{method:"POST",headers:{Authorization:`Bearer ${c.apiKey}`}}),i=await n.json();return{content:[{type:"text",text:JSON.stringify(i,null,2)}],details:{}}}}),c.tradingEnabled&&g.push({name:"place_order",label:"Place Order",description:"Place a buy or sell order on Kalshi. Requires trading to be enabled. Always confirm with user before placing.",parameters:o.Object({ticker:o.String({description:"Market ticker (e.g. KXWTIMAX-26DEC31-T135)"}),side:o.String({description:"yes or no"}),action:o.String({description:"buy or sell"}),count:o.Number({description:"Number of contracts"}),yes_price:o.Number({description:"Price in cents (1-99)"})}),execute:async(e,t)=>{try{const e=await d.createOrder({ticker:t.ticker,side:t.side,action:t.action,type:"limit",count:t.count,yes_price:t.yes_price});return{content:[{type:"text",text:`✓ Order placed: ${(e.order||e).order_id||"OK"}\n${t.action.toUpperCase()} ${t.count}x ${t.ticker} ${t.side.toUpperCase()} @ ${t.yes_price}¢`}],details:{}}}catch(e){return{content:[{type:"text",text:`✗ Order failed: ${e.message}`}],details:{}}}}},{name:"cancel_order",label:"Cancel Order",description:"Cancel a resting order on Kalshi.",parameters:o.Object({orderId:o.String({description:"Order ID to cancel"})}),execute:async(e,t)=>{try{return await d.cancelOrder(t.orderId),{content:[{type:"text",text:`✓ Order ${t.orderId} cancelled.`}],details:{}}}catch(e){return{content:[{type:"text",text:`✗ Cancel failed: ${e.message}`}],details:{}}}}}),g.push({name:"fs_read",label:"Read File",description:"Read a file from workspace (~/.sf/workspace/).",parameters:o.Object({path:o.String({description:"Relative file path"})}),execute:async(e,t)=>{const n=(0,a.wsRead)(t.path);return{content:[{type:"text",text:n.ok?n.content:`Error: ${n.content}`}],details:{}}}},{name:"fs_write",label:"Write File",description:"Write or append to a file in workspace.",parameters:o.Object({path:o.String({description:"Relative file path"}),content:o.String({description:"Content"}),append:o.Optional(o.Boolean({description:"Append mode"}))}),execute:async(e,t)=>({content:[{type:"text",text:(0,a.wsWrite)(t.path,t.content,t.append).message}],details:{}})},{name:"fs_list",label:"List Files",description:"List files in workspace.",parameters:o.Object({path:o.Optional(o.String({description:"Directory"})),glob:o.Optional(o.String({description:"Filter pattern"}))}),execute:async(e,t)=>{const n=(0,a.wsList)(t.path,t.glob);return n.ok?{content:[{type:"text",text:n.entries.length>0?n.entries.join("\n"):"(empty)"}],details:{}}:{content:[{type:"text",text:`Error: ${n.message}`}],details:{}}}},{name:"fs_search",label:"Search Files",description:"Search file contents in workspace using regex.",parameters:o.Object({pattern:o.String({description:"Regex pattern"}),path:o.Optional(o.String({description:"Directory scope"}))}),execute:async(e,t)=>{const n=(0,a.wsSearch)(t.pattern,t.path);return n.ok?0===n.matches.length?{content:[{type:"text",text:"No matches."}],details:{}}:{content:[{type:"text",text:n.matches.map(e=>`${e.file}:${e.line}: ${e.text}`).join("\n")}],details:{}}:{content:[{type:"text",text:`Error: ${n.message}`}],details:{}}}},{name:"fs_delete",label:"Delete File",description:"Delete a file from workspace.",parameters:o.Object({path:o.String({description:"File to delete"})}),execute:async(e,t)=>({content:[{type:"text",text:(0,a.wsDelete)(t.path).message}],details:{}})}),g.push({name:"calculate",label:"Calculate",description:"Evaluate a math expression precisely.",parameters:o.Object({expression:o.String({description:"Math expression"})}),execute:async(e,t)=>{try{const e=t.expression.trim();return/^[\d\s+\-*/.%(),eE]+$/.test(e.replace(/Math\.\w+/g,"").replace(/\*\*/g,""))?{content:[{type:"text",text:`${e} = ${new Function(`"use strict"; return (${e})`)()}`}],details:{}}:{content:[{type:"text",text:"Unsafe expression."}],details:{}}}catch(e){return{content:[{type:"text",text:`Calc error: ${e.message}`}],details:{}}}}},{name:"cancel_all_intents",label:"Cancel All",description:"Cancel all active intents. Emergency use.",parameters:o.Object({confirm:o.Boolean({description:"Must be true"})}),execute:async(t,n)=>{if(!n.confirm)return{content:[{type:"text",text:"Set confirm=true."}],details:{}};try{const t=((await e.listIntents({active:!0})).intents||[]).filter(e=>["pending","armed"].includes(e.status));if(0===t.length)return{content:[{type:"text",text:"No active intents."}],details:{}};let n=0;for(const i of t)try{await e.cancelIntentAPI(i.id),n++}catch{}return{content:[{type:"text",text:`Cancelled ${n}/${t.length} intents.`}],details:{}}}catch(e){return{content:[{type:"text",text:`Error: ${e.message}`}],details:{}}}}});const h=c.apiUrl||process.env.SF_API_URL||"https://simplefunctions.dev";return c.apiKey||process.env.SF_API_KEY,g.push({name:"create_intent",label:"Create Intent",description:"Declare an execution intent with trigger conditions. Runtime daemon evaluates triggers and executes via local keys.",parameters:o.Object({action:o.String({description:"buy or sell"}),venue:o.String({description:"kalshi or polymarket"}),marketId:o.String({description:"Market ticker"}),marketTitle:o.String({description:"Human-readable name"}),direction:o.String({description:"yes or no"}),targetQuantity:o.Number({description:"Number of contracts"}),maxPrice:o.Optional(o.Number({description:"Max price in cents (1-99)"})),triggerType:o.Optional(o.String({description:"immediate, price_below, price_above, time"})),triggerPrice:o.Optional(o.Number({description:"Price trigger threshold in cents"})),triggerAt:o.Optional(o.String({description:"ISO timestamp for time trigger"})),softCondition:o.Optional(o.String({description:"Natural language condition evaluated by LLM before execution"})),rationale:o.Optional(o.String({description:"Why this trade"})),autoExecute:o.Optional(o.Boolean({description:"Auto-execute without confirmation"}))}),execute:async(t,n)=>{const i=await e.createIntent({...n,source:"telegram",expireAt:new Date(Date.now()+864e5).toISOString()});return{content:[{type:"text",text:JSON.stringify(i,null,2)}],details:{}}}},{name:"list_intents",label:"List Intents",description:"List execution intents — pending, armed, triggered, filled.",parameters:o.Object({activeOnly:o.Optional(o.Boolean({description:"Only active (default true)"}))}),execute:async(t,n)=>{const i=await e.listIntents({active:!1!==n.activeOnly});return{content:[{type:"text",text:JSON.stringify(i,null,2)}],details:{}}}},{name:"cancel_intent",label:"Cancel Intent",description:"Cancel an active intent.",parameters:o.Object({intentId:o.String({description:"Intent ID"})}),execute:async(t,n)=>{const i=await e.cancelIntentAPI(n.intentId);return{content:[{type:"text",text:JSON.stringify(i)}],details:{}}}},{name:"runtime_status",label:"Runtime Status",description:"Check if the local execution runtime is running.",parameters:l,execute:async()=>{const{existsSync:t,readFileSync:i}=await Promise.resolve().then(n.t.bind(n,79896,23)),{join:a}=await Promise.resolve().then(n.t.bind(n,16928,23)),{homedir:s}=await Promise.resolve().then(n.t.bind(n,70857,23)),r=a(s(),".sf","runtime.pid");let o=!1,c="";if(t(r)){c=i(r,"utf-8").trim();try{process.kill(parseInt(c),0),o=!0}catch{}}const l=await e.listIntents({active:!0});return{content:[{type:"text",text:JSON.stringify({running:o,pid:o?c:null,...l},null,2)}],details:{}}}},{name:"runtime_start",label:"Start Runtime",description:"Start the local execution runtime daemon.",parameters:l,execute:async()=>{const{existsSync:e,readFileSync:t,mkdirSync:i,openSync:a}=await Promise.resolve().then(n.t.bind(n,79896,23)),{join:s}=await Promise.resolve().then(n.t.bind(n,16928,23)),{homedir:r}=await Promise.resolve().then(n.t.bind(n,70857,23)),{spawn:o}=await Promise.resolve().then(n.t.bind(n,35317,23)),c=s(r(),".sf","runtime.pid"),l=s(r(),".sf","runtime.log");if(e(c)){const e=t(c,"utf-8").trim();try{return process.kill(parseInt(e),0),{content:[{type:"text",text:`Runtime already running (PID ${e}).`}],details:{}}}catch{}}i(s(r(),".sf"),{recursive:!0});const d=a(l,"a");return o(process.execPath,[process.argv[1],"runtime","start"],{detached:!0,stdio:["ignore",d,d],env:{...process.env}}).unref(),await new Promise(e=>setTimeout(e,1e3)),{content:[{type:"text",text:`Runtime started. Log: ${l}`}],details:{}}}},{name:"runtime_stop",label:"Stop Runtime",description:"Stop the local execution runtime daemon.",parameters:l,execute:async()=>{const{existsSync:e,readFileSync:t,unlinkSync:i}=await Promise.resolve().then(n.t.bind(n,79896,23)),{join:a}=await Promise.resolve().then(n.t.bind(n,16928,23)),{homedir:s}=await Promise.resolve().then(n.t.bind(n,70857,23)),r=a(s(),".sf","runtime.pid");if(!e(r))return{content:[{type:"text",text:"No runtime running."}],details:{}};const o=t(r,"utf-8").trim();try{return process.kill(parseInt(o),"SIGTERM"),i(r),{content:[{type:"text",text:`Runtime stopped (PID ${o}).`}],details:{}}}catch{try{i(r)}catch{}return{content:[{type:"text",text:"Runtime was not running (stale PID removed)."}],details:{}}}}},{name:"daemon_command",label:"Daemon Command",description:"Send command to a running daemon. Actions: pause, resume, scan_now.",parameters:o.Object({target:o.String({description:"Target: runtime, telegram, watch"}),action:o.String({description:"Command: pause, resume, scan_now"})}),execute:async(e,t)=>{const{writeMessage:i}=await n.e(563).then(n.bind(n,9563)),a=i({from:"agent",to:t.target,type:"command",priority:"normal",payload:{action:t.action},ttl:3600});return{content:[{type:"text",text:`Command sent to ${t.target}: ${t.action} (msg ${a})`}],details:{}}}},{name:"set_wake_condition",label:"Set Wake Condition",description:"Set a condition for daemons to alert you. Types: price, time, llm.",parameters:o.Object({description:o.String({description:"Human-readable description"}),type:o.String({description:"price, time, or llm"}),condition:o.Any({description:"Condition config"}),priority:o.Optional(o.String())}),execute:async(e,t)=>{const{saveWakeCondition:i}=await n.e(563).then(n.bind(n,9563)),{randomBytes:a}=await Promise.resolve().then(n.t.bind(n,76982,23)),s={id:a(8).toString("hex"),createdAt:(new Date).toISOString(),description:t.description,type:t.type,[`${t.type}Condition`]:t.condition,alertChannels:["bus","telegram"],priority:t.priority||"normal",maxFires:-1,firedCount:0,lastFiredAt:null,expiresAt:null,active:!0};return i(s),{content:[{type:"text",text:`Wake condition set: "${t.description}" (${s.id})`}],details:{}}}},{name:"check_daemon_alerts",label:"Check Alerts",description:"Read alerts from running daemons.",parameters:l,execute:async()=>{const{readMessages:e,deleteMessage:t}=await n.e(563).then(n.bind(n,9563)),i=e("agent","outbox");return 0===i.length?{content:[{type:"text",text:"No new daemon alerts."}],details:{}}:{content:[{type:"text",text:i.map(e=>(t(e.id,"outbox"),`[${e.priority}] ${e.from}: ${e.payload.summary||JSON.stringify(e.payload)}`)).join("\n")}],details:{}}}},{name:"schedule_wake",label:"Schedule Wake",description:"Schedule a self-wake: after N minutes, perform an action. Can repeat.",parameters:o.Object({delayMinutes:o.Number({description:"Minutes from now"}),action:o.String({description:"prompt, tool, or check"}),prompt:o.Optional(o.String({description:"Prompt text (for action=prompt)"})),repeatMinutes:o.Optional(o.Number({description:"Repeat interval in minutes"})),context:o.Optional(o.String({description:"Why this wake"}))}),execute:async(e,i)=>{const{scheduleWake:a}=await n.e(563).then(n.bind(n,9563)),s=a({...i,thesisId:t});return{content:[{type:"text",text:`Wake scheduled: ${s.id} fires at ${s.fireAt}${i.repeatMinutes?` (repeats every ${i.repeatMinutes}m)`:""}`}],details:{}}}},{name:"list_wakes",label:"List Wakes",description:"List all scheduled self-wakes.",parameters:l,execute:async()=>{const{listWakes:e}=await n.e(563).then(n.bind(n,9563)),t=e();return 0===t.length?{content:[{type:"text",text:"No scheduled wakes."}],details:{}}:{content:[{type:"text",text:t.map(e=>`${e.id.slice(0,8)} ${e.firedAt?"FIRED":"PENDING"} at ${e.fireAt} — ${e.context||e.action}`).join("\n")}],details:{}}}},{name:"cancel_wake",label:"Cancel Wake",description:"Cancel a scheduled wake.",parameters:o.Object({wakeId:o.String({description:"Wake ID"})}),execute:async(e,t)=>{const{cancelWake:i}=await n.e(563).then(n.bind(n,9563));return{content:[{type:"text",text:i(t.wakeId)?"Cancelled.":"Not found."}],details:{}}}},{name:"send_alert",label:"Send Alert",description:"Push an alert to Telegram and/or daemon bus.",parameters:o.Object({message:o.String({description:"Alert message"}),priority:o.Optional(o.String({description:"low | normal | high | critical"}))}),execute:async(e,t)=>{try{const{writeMessage:e}=await n.e(563).then(n.bind(n,9563));return e({from:"agent",to:"all",type:"alert",priority:t.priority||"high",payload:{summary:t.message},ttl:7200}),{content:[{type:"text",text:`Alert sent: "${t.message}"`}],details:{}}}catch(e){return{content:[{type:"text",text:`Error: ${e.message}`}],details:{}}}}}),g.push({name:"get_world_delta",label:"World Delta",description:"Incremental world state update — only what changed. ~30-50 tokens. Much cheaper than full state for polling.",parameters:o.Object({since:o.Optional(o.String({description:'"30m", "1h", "6h", "24h" or ISO timestamp (default "1h")'}))}),execute:async(e,t)=>{const n=t.since||"1h",i=await fetch(`${h}/api/agent/world/delta?since=${encodeURIComponent(n)}`);return i.ok?{content:[{type:"text",text:await i.text()}],details:{}}:{content:[{type:"text",text:`Delta API error: ${i.status}`}],details:{}}}},{name:"get_trade_ideas",label:"Trade Ideas",description:"S&T-style trade ideas with conviction levels and catalysts.",parameters:o.Object({freshness:o.Optional(o.String({description:"today, week, or all"})),category:o.Optional(o.String({description:"macro, geopolitics, crypto, policy, event"}))}),execute:async(e,t)=>{const n=new URLSearchParams;t.freshness&&n.set("freshness",t.freshness),t.category&&n.set("category",t.category);const i=await fetch(`${h}/api/public/ideas?${n.toString()}`);return i.ok?{content:[{type:"text",text:JSON.stringify(await i.json(),null,2)}],details:{}}:{content:[{type:"text",text:`Ideas API error: ${i.status}`}],details:{}}}},{name:"get_milestones",label:"Milestones",description:"Upcoming events from Kalshi calendar: economic releases, political events, catalysts.",parameters:o.Object({hours:o.Optional(o.Number({description:"Hours ahead (default 168 = 1 week)"})),category:o.Optional(o.String({description:"Economics, Politics, Sports"}))}),execute:async(e,t)=>{const i=await Promise.resolve().then(n.t.bind(n,96139,23)),a=await i.getExchangeAnnouncements();if(!a||0===a.length)return{content:[{type:"text",text:"No upcoming milestones."}],details:{}};const s=t.category?a.filter(e=>e.category?.toLowerCase().includes(t.category.toLowerCase())):a;return{content:[{type:"text",text:JSON.stringify(s.slice(0,20),null,2)}],details:{}}}},{name:"get_liquidity",label:"Liquidity",description:"Orderbook liquidity analysis for markets matching a query. Returns bid/ask depth, spread, liquidity score.",parameters:o.Object({query:o.String({description:"Search query"})}),execute:async(e,t)=>{const i=await fetch(`${h}/api/public/scan?q=${encodeURIComponent(t.query)}&limit=10`);if(!i.ok)return{content:[{type:"text",text:`Scan error: ${i.status}`}],details:{}};const a=await i.json(),s=(a.results||a.markets||[]).slice(0,5),r=[];for(const e of s)if("kalshi"===e.venue&&e.ticker){const t=await(await Promise.resolve().then(n.t.bind(n,96139,23))).getPublicOrderbook(e.ticker,5);if(t){const n=t.yes_dollars||[],i=t.no_dollars||[],a=n.length>0?Math.round(100*parseFloat(n[0][0])):0,s=i.length>0?100-Math.round(100*parseFloat(i[0][0])):100;r.push({ticker:e.ticker,title:(e.title||"").slice(0,50),bestBid:a,bestAsk:s,spread:s-a,venue:"kalshi"})}}return{content:[{type:"text",text:r.length>0?JSON.stringify(r,null,2):"No orderbook data found."}],details:{}}}},{name:"explore_public",label:"Explore Public",description:"Browse public theses with edges. Discover what other users are tracking.",parameters:o.Object({limit:o.Optional(o.Number({description:"Max results (default 10)"}))}),execute:async(e,t)=>{const n=await fetch(`${h}/api/public/theses?limit=${t.limit||10}`);return n.ok?{content:[{type:"text",text:JSON.stringify(await n.json(),null,2)}],details:{}}:{content:[{type:"text",text:`Public theses error: ${n.status}`}],details:{}}}},{name:"create_strategy",label:"Create Strategy",description:"Create a trading strategy for a thesis with entry/exit conditions.",parameters:o.Object({marketId:o.String({description:"Market ticker"}),market:o.String({description:"Human-readable name"}),direction:o.String({description:"yes or no"}),entryBelow:o.Optional(o.Number({description:"Entry: ask <= cents"})),stopLoss:o.Optional(o.Number({description:"Stop loss: bid <= cents"})),takeProfit:o.Optional(o.Number({description:"Take profit: bid >= cents"})),maxQuantity:o.Optional(o.Number({description:"Max contracts (default 500)"})),softConditions:o.Optional(o.String({description:"LLM-evaluated conditions"})),rationale:o.Optional(o.String({description:"Reasoning"}))}),execute:async(n,i)=>{const a=await e.createStrategyAPI(t,{...i,createdBy:"telegram"});return{content:[{type:"text",text:JSON.stringify(a)}],details:{}}}},{name:"list_strategies",label:"List Strategies",description:"List strategies for the current thesis.",parameters:o.Object({status:o.Optional(o.String({description:"Filter: active, watching, executed, cancelled"}))}),execute:async(n,i)=>{const a=await e.getStrategies(t,i.status);return{content:[{type:"text",text:JSON.stringify(a,null,2)}],details:{}}}}),g}(e,t.thesisId,h),f="number"==typeof h.confidence?Math.round(100*h.confidence):50,b=d.model||"anthropic/claude-sonnet-4.6";let w;try{w=l("openrouter",b)}catch{w={modelId:b,provider:"openrouter",api:"openai-completions",baseUrl:"https://openrouter.ai/api/v1",id:b,name:b,inputPrice:0,outputPrice:0,contextWindow:2e5,supportsImages:!0,supportsTools:!0,headers:{"HTTP-Referer":"https://simplefunctions.dev","X-Title":"SimpleFunctions"}}}g&&(w.baseUrl=`${m}/api/proxy`);const S=(h.edges||[]).sort((e,t)=>Math.abs(t.edge)-Math.abs(e.edge)).slice(0,5).map(e=>` ${(e.market||"").slice(0,35)} | ${e.venue||"kalshi"} | mkt ${e.marketPrice}¢ → thesis ${e.thesisPrice}¢ | edge ${e.edge>0?"+":""}${e.edge}`).join("\n")||" (no edges)",k=(h.causalTree?.nodes||[]).filter(e=>0===e.depth||!e.depth).slice(0,5).map(e=>` ${e.id} ${(e.label||"").slice(0,35)} — ${Math.round(100*(e.probability||.5))}%`).join("\n")||" (no causal tree)",O=new s({initialState:{systemPrompt:`You are a prediction market trading assistant on Telegram. Your job is to help the user see reality clearly and make correct trading decisions.\n\n## Framework\nEdge = thesis price - market price. Positive = market underprices.\nEdge types: [consensus] depth>=500 real opponents, [attention] depth<100 illusory, [timing] market lags, [risk_premium] platform risk. Tag when reporting.\nPrice: depth >= 500 = consensus, < 100 = unreliable, spread > 5 = noisy.\n\n## Rules\n- When reporting an edge, tag it: [consensus] [attention] [timing] [risk_premium].\n- If any kill condition is triggered or approaching, lead with that.\n- If nothing material to do, say "quiet — no action needed." Don't pad.\n- Keep Telegram messages SHORT — bullet points, no walls of text.\n- Prices in cents (¢). P&L in dollars ($). Don't re-convert tool output units.\n- Call tools for fresh data. Never guess prices or P&L from this prompt.\n- Use search_x for X/Twitter sentiment. Use x_volume for discussion spikes. Use x_account to track key people.\n- Use heartbeat_config to view/adjust scan intervals, model tier, budget cap, or check cost breakdown.\n- Use monitor_the_situation to scrape URLs and cross-reference with markets. Use enrich_content for text-only analysis.\n- Use get_world_state for broad situational awareness (~800 tokens). Use get_world_delta for cheap incremental updates.\n- Use get_trade_ideas for S&T-style pitches. Use get_milestones for upcoming catalysts.\n- Use get_liquidity / explore_public for discovery. Use create_strategy / list_strategies for trade planning.\n- Use create_skill / list_skills / browse_public_skills / fork_skill to manage agent skills.\n- Use fork_thesis to fork a public thesis (copies thesis + causal tree).\n- fs_read/fs_write/fs_list/fs_search/fs_delete: workspace. Write notes proactively. Shared with TUI.\n- calculate: precise math. send_alert: push to Telegram/bus. schedule_wake / list_wakes / cancel_wake: self-scheduling.\n- create_intent / list_intents / cancel_intent: execution intents with triggers.\n- runtime_start / runtime_stop / runtime_status: local execution daemon.\n- daemon_command / set_wake_condition / check_daemon_alerts: smart daemon control.\n- Live State shows positions/edges each turn — use it directly, don't re-fetch.\n- If user mentions news, inject_signal immediately. Don't ask "should I?"\n- If user says "evaluate" or "run it", trigger immediately.\n- Don't end with "anything else?" — user will ask.\n- Use Chinese if user writes Chinese, English if English.\n${d.tradingEnabled?"- Trading ENABLED. You have place_order and cancel_order. ALWAYS confirm before placing.":"- Trading DISABLED. Tell user: sf setup --enable-trading"}\n\n## Current State\nThesis: ${(h.thesis||h.rawThesis||"N/A").slice(0,200)}\nID: ${t.thesisId.slice(0,8)} | Confidence: ${f}%\n\nCausal nodes:\n${k}\n\nTop edges:\n${S}\n\n${h.lastEvaluation?.summary?`Latest eval: ${h.lastEvaluation.summary.slice(0,200)}`:""}`,model:w,tools:x,thinkingLevel:"off"},streamFn:o,getApiKey:e=>"openrouter"===e?y:void 0});if(t.agentMessages.length>0)try{O.replaceMessages(t.agentMessages)}catch{}else if(t.thesisId)try{const e=(0,a.readRecentContext)(t.thesisId,30);if(e.length>0){const t=[];for(const n of e){const e="string"==typeof n.content?[{type:"text",text:n.content}]:n.content;"user"===n.role?t.push({role:"user",content:e}):"assistant"===n.role&&t.push({role:"assistant",content:e})}const n=[];for(const e of t)0!==n.length&&n[n.length-1].role===e.role||n.push(e);if(n.length>0)try{O.replaceMessages(n)}catch{}}}catch{}return t.agent=O,O}}};
|
package/dist/174.index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
exports.id=174,exports.ids=[174],exports.modules={84005:
|
|
1
|
+
exports.id=174,exports.ids=[174],exports.modules={84005:r=>{function e(r){return import(r).catch(()=>{try{return require(r)}catch(t){var e=new Error("Cannot find module '"+r+"'");throw e.code="MODULE_NOT_FOUND",e}})}e.keys=()=>[],e.resolve=e,e.id=84005,r.exports=e},70162:r=>{function e(r){return import(r).catch(()=>{try{return require(r)}catch(t){var e=new Error("Cannot find module '"+r+"'");throw e.code="MODULE_NOT_FOUND",e}})}e.keys=()=>[],e.resolve=e,e.id=70162,r.exports=e}};
|
package/dist/582.index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
exports.id=582,exports.ids=[582,174],exports.modules={84005:e=>{function t(e){try{return Promise.resolve(require(e))}catch(t){return Promise.resolve().then(()=>{var t=new Error("Cannot find module '"+e+"'");throw t.code="MODULE_NOT_FOUND",t})}}t.keys=()=>[],t.resolve=t,t.id=84005,e.exports=t},70162:e=>{function t(e){try{return Promise.resolve(require(e))}catch(t){return Promise.resolve().then(()=>{var t=new Error("Cannot find module '"+e+"'");throw t.code="MODULE_NOT_FOUND",t})}}t.keys=()=>[],t.resolve=t,t.id=70162,e.exports=t},65653:(e,t,s)=>{"use strict";s.r(t),s.d(t,{Agent:()=>p,agentLoop:()=>o,agentLoopContinue:()=>r,streamProxy:()=>d});var n=s(99641);function o(e,t,s,n,o){const r=a();return(async()=>{const a=[...e],l={...t,messages:[...t.messages,...e]};r.push({type:"agent_start"}),r.push({type:"turn_start"});for(const t of e)r.push({type:"message_start",message:t}),r.push({type:"message_end",message:t});await i(l,a,s,n,r,o)})(),r}function r(e,t,s,n){if(0===e.messages.length)throw new Error("Cannot continue: no messages in context");if("assistant"===e.messages[e.messages.length-1].role)throw new Error("Cannot continue from message role: assistant");const o=a();return(async()=>{const r={...e};o.push({type:"agent_start"}),o.push({type:"turn_start"}),await i(r,[],t,s,o,n)})(),o}function a(){return new n.EventStream(e=>"agent_end"===e.type,e=>"agent_end"===e.type?e.messages:[])}async function i(e,t,s,n,o,r){let a=!0,i=await(s.getSteeringMessages?.())||[];for(;;){let u=!0,c=null;for(;u||i.length>0;){if(a?a=!1:o.push({type:"turn_start"}),i.length>0){for(const s of i)o.push({type:"message_start",message:s}),o.push({type:"message_end",message:s}),e.messages.push(s),t.push(s);i=[]}const p=await l(e,s,n,o,r);if(t.push(p),"error"===p.stopReason||"aborted"===p.stopReason)return o.push({type:"turn_end",message:p,toolResults:[]}),o.push({type:"agent_end",messages:t}),void o.end(t);u=p.content.filter(e=>"toolCall"===e.type).length>0;const h=[];if(u){const r=await g(e.tools,p,n,o,s.getSteeringMessages);h.push(...r.toolResults),c=r.steeringMessages??null;for(const s of h)e.messages.push(s),t.push(s)}o.push({type:"turn_end",message:p,toolResults:h}),c&&c.length>0?(i=c,c=null):i=await(s.getSteeringMessages?.())||[]}const p=await(s.getFollowUpMessages?.())||[];if(!(p.length>0))break;i=p}o.push({type:"agent_end",messages:t}),o.end(t)}async function l(e,t,s,o,r){let a=e.messages;t.transformContext&&(a=await t.transformContext(a,s));const i=await t.convertToLlm(a),l={systemPrompt:e.systemPrompt,messages:i,tools:e.tools},g=r||n.streamSimple,u=(t.getApiKey?await t.getApiKey(t.model.provider):void 0)||t.apiKey,c=await g(t.model,l,{...t,apiKey:u,signal:s});let p=null,h=!1;for await(const t of c)switch(t.type){case"start":p=t.partial,e.messages.push(p),h=!0,o.push({type:"message_start",message:{...p}});break;case"text_start":case"text_delta":case"text_end":case"thinking_start":case"thinking_delta":case"thinking_end":case"toolcall_start":case"toolcall_delta":case"toolcall_end":p&&(p=t.partial,e.messages[e.messages.length-1]=p,o.push({type:"message_update",assistantMessageEvent:t,message:{...p}}));break;case"done":case"error":{const t=await c.result();return h?e.messages[e.messages.length-1]=t:e.messages.push(t),h||o.push({type:"message_start",message:{...t}}),o.push({type:"message_end",message:t}),t}}return await c.result()}async function g(e,t,s,o,r){const a=t.content.filter(e=>"toolCall"===e.type),i=[];let l;for(let t=0;t<a.length;t++){const g=a[t],c=e?.find(e=>e.name===g.name);let p;o.push({type:"tool_execution_start",toolCallId:g.id,toolName:g.name,args:g.arguments});let h=!1;try{if(!c)throw new Error(`Tool ${g.name} not found`);const e=(0,n.validateToolArguments)(c,g);p=await c.execute(g.id,e,s,e=>{o.push({type:"tool_execution_update",toolCallId:g.id,toolName:g.name,args:g.arguments,partialResult:e})})}catch(e){p={content:[{type:"text",text:e instanceof Error?e.message:String(e)}],details:{}},h=!0}o.push({type:"tool_execution_end",toolCallId:g.id,toolName:g.name,result:p,isError:h});const d={role:"toolResult",toolCallId:g.id,toolName:g.name,content:p.content,details:p.details,isError:h,timestamp:Date.now()};if(i.push(d),o.push({type:"message_start",message:d}),o.push({type:"message_end",message:d}),r){const e=await r();if(e.length>0){l=e;const s=a.slice(t+1);for(const e of s)i.push(u(e,o));break}}}return{toolResults:i,steeringMessages:l}}function u(e,t){const s={content:[{type:"text",text:"Skipped due to queued user message."}],details:{}};t.push({type:"tool_execution_start",toolCallId:e.id,toolName:e.name,args:e.arguments}),t.push({type:"tool_execution_end",toolCallId:e.id,toolName:e.name,result:s,isError:!0});const n={role:"toolResult",toolCallId:e.id,toolName:e.name,content:s.content,details:{},isError:!0,timestamp:Date.now()};return t.push({type:"message_start",message:n}),t.push({type:"message_end",message:n}),n}function c(e){return e.filter(e=>"user"===e.role||"assistant"===e.role||"toolResult"===e.role)}class p{_state={systemPrompt:"",model:(0,n.getModel)("google","gemini-2.5-flash-lite-preview-06-17"),thinkingLevel:"off",tools:[],messages:[],isStreaming:!1,streamMessage:null,pendingToolCalls:new Set,error:void 0};listeners=new Set;abortController;convertToLlm;transformContext;steeringQueue=[];followUpQueue=[];steeringMode;followUpMode;streamFn;_sessionId;getApiKey;_onPayload;runningPrompt;resolveRunningPrompt;_thinkingBudgets;_transport;_maxRetryDelayMs;constructor(e={}){this._state={...this._state,...e.initialState},this.convertToLlm=e.convertToLlm||c,this.transformContext=e.transformContext,this.steeringMode=e.steeringMode||"one-at-a-time",this.followUpMode=e.followUpMode||"one-at-a-time",this.streamFn=e.streamFn||n.streamSimple,this._sessionId=e.sessionId,this.getApiKey=e.getApiKey,this._onPayload=e.onPayload,this._thinkingBudgets=e.thinkingBudgets,this._transport=e.transport??"sse",this._maxRetryDelayMs=e.maxRetryDelayMs}get sessionId(){return this._sessionId}set sessionId(e){this._sessionId=e}get thinkingBudgets(){return this._thinkingBudgets}set thinkingBudgets(e){this._thinkingBudgets=e}get transport(){return this._transport}setTransport(e){this._transport=e}get maxRetryDelayMs(){return this._maxRetryDelayMs}set maxRetryDelayMs(e){this._maxRetryDelayMs=e}get state(){return this._state}subscribe(e){return this.listeners.add(e),()=>this.listeners.delete(e)}setSystemPrompt(e){this._state.systemPrompt=e}setModel(e){this._state.model=e}setThinkingLevel(e){this._state.thinkingLevel=e}setSteeringMode(e){this.steeringMode=e}getSteeringMode(){return this.steeringMode}setFollowUpMode(e){this.followUpMode=e}getFollowUpMode(){return this.followUpMode}setTools(e){this._state.tools=e}replaceMessages(e){this._state.messages=e.slice()}appendMessage(e){this._state.messages=[...this._state.messages,e]}steer(e){this.steeringQueue.push(e)}followUp(e){this.followUpQueue.push(e)}clearSteeringQueue(){this.steeringQueue=[]}clearFollowUpQueue(){this.followUpQueue=[]}clearAllQueues(){this.steeringQueue=[],this.followUpQueue=[]}hasQueuedMessages(){return this.steeringQueue.length>0||this.followUpQueue.length>0}dequeueSteeringMessages(){if("one-at-a-time"===this.steeringMode){if(this.steeringQueue.length>0){const e=this.steeringQueue[0];return this.steeringQueue=this.steeringQueue.slice(1),[e]}return[]}const e=this.steeringQueue.slice();return this.steeringQueue=[],e}dequeueFollowUpMessages(){if("one-at-a-time"===this.followUpMode){if(this.followUpQueue.length>0){const e=this.followUpQueue[0];return this.followUpQueue=this.followUpQueue.slice(1),[e]}return[]}const e=this.followUpQueue.slice();return this.followUpQueue=[],e}clearMessages(){this._state.messages=[]}abort(){this.abortController?.abort()}waitForIdle(){return this.runningPrompt??Promise.resolve()}reset(){this._state.messages=[],this._state.isStreaming=!1,this._state.streamMessage=null,this._state.pendingToolCalls=new Set,this._state.error=void 0,this.steeringQueue=[],this.followUpQueue=[]}async prompt(e,t){if(this._state.isStreaming)throw new Error("Agent is already processing a prompt. Use steer() or followUp() to queue messages, or wait for completion.");if(!this._state.model)throw new Error("No model configured");let s;if(Array.isArray(e))s=e;else if("string"==typeof e){const n=[{type:"text",text:e}];t&&t.length>0&&n.push(...t),s=[{role:"user",content:n,timestamp:Date.now()}]}else s=[e];await this._runLoop(s)}async continue(){if(this._state.isStreaming)throw new Error("Agent is already processing. Wait for completion before continuing.");const e=this._state.messages;if(0===e.length)throw new Error("No messages to continue from");if("assistant"===e[e.length-1].role){const e=this.dequeueSteeringMessages();if(e.length>0)return void await this._runLoop(e,{skipInitialSteeringPoll:!0});const t=this.dequeueFollowUpMessages();if(t.length>0)return void await this._runLoop(t);throw new Error("Cannot continue from message role: assistant")}await this._runLoop(void 0)}async _runLoop(e,t){const s=this._state.model;if(!s)throw new Error("No model configured");this.runningPrompt=new Promise(e=>{this.resolveRunningPrompt=e}),this.abortController=new AbortController,this._state.isStreaming=!0,this._state.streamMessage=null,this._state.error=void 0;const n="off"===this._state.thinkingLevel?void 0:this._state.thinkingLevel,a={systemPrompt:this._state.systemPrompt,messages:this._state.messages.slice(),tools:this._state.tools};let i=!0===t?.skipInitialSteeringPoll;const l={model:s,reasoning:n,sessionId:this._sessionId,onPayload:this._onPayload,transport:this._transport,thinkingBudgets:this._thinkingBudgets,maxRetryDelayMs:this._maxRetryDelayMs,convertToLlm:this.convertToLlm,transformContext:this.transformContext,getApiKey:this.getApiKey,getSteeringMessages:async()=>i?(i=!1,[]):this.dequeueSteeringMessages(),getFollowUpMessages:async()=>this.dequeueFollowUpMessages()};let g=null;try{const t=e?o(e,a,l,this.abortController.signal,this.streamFn):r(a,l,this.abortController.signal,this.streamFn);for await(const e of t){switch(e.type){case"message_start":case"message_update":g=e.message,this._state.streamMessage=e.message;break;case"message_end":g=null,this._state.streamMessage=null,this.appendMessage(e.message);break;case"tool_execution_start":{const t=new Set(this._state.pendingToolCalls);t.add(e.toolCallId),this._state.pendingToolCalls=t;break}case"tool_execution_end":{const t=new Set(this._state.pendingToolCalls);t.delete(e.toolCallId),this._state.pendingToolCalls=t;break}case"turn_end":"assistant"===e.message.role&&e.message.errorMessage&&(this._state.error=e.message.errorMessage);break;case"agent_end":this._state.isStreaming=!1,this._state.streamMessage=null}this.emit(e)}if(g&&"assistant"===g.role&&g.content.length>0){if(!g.content.some(e=>"thinking"===e.type&&e.thinking.trim().length>0||"text"===e.type&&e.text.trim().length>0||"toolCall"===e.type&&e.name.trim().length>0)){if(this.abortController?.signal.aborted)throw new Error("Request was aborted")}else this.appendMessage(g)}}catch(e){const t={role:"assistant",content:[{type:"text",text:""}],api:s.api,provider:s.provider,model:s.id,usage:{input:0,output:0,cacheRead:0,cacheWrite:0,totalTokens:0,cost:{input:0,output:0,cacheRead:0,cacheWrite:0,total:0}},stopReason:this.abortController?.signal.aborted?"aborted":"error",errorMessage:e?.message||String(e),timestamp:Date.now()};this.appendMessage(t),this._state.error=e?.message||String(e),this.emit({type:"agent_end",messages:[t]})}finally{this._state.isStreaming=!1,this._state.streamMessage=null,this._state.pendingToolCalls=new Set,this.abortController=void 0,this.resolveRunningPrompt?.(),this.runningPrompt=void 0,this.resolveRunningPrompt=void 0}}emit(e){for(const t of this.listeners)t(e)}}class h extends n.EventStream{constructor(){super(e=>"done"===e.type||"error"===e.type,e=>{if("done"===e.type)return e.message;if("error"===e.type)return e.error;throw new Error("Unexpected event type")})}}function d(e,t,s){const n=new h;return(async()=>{const o={role:"assistant",stopReason:"stop",content:[],api:e.api,provider:e.provider,model:e.id,usage:{input:0,output:0,cacheRead:0,cacheWrite:0,totalTokens:0,cost:{input:0,output:0,cacheRead:0,cacheWrite:0,total:0}},timestamp:Date.now()};let r;const a=()=>{r&&r.cancel("Request aborted by user").catch(()=>{})};s.signal&&s.signal.addEventListener("abort",a);try{const a=await fetch(`${s.proxyUrl}/api/stream`,{method:"POST",headers:{Authorization:`Bearer ${s.authToken}`,"Content-Type":"application/json"},body:JSON.stringify({model:e,context:t,options:{temperature:s.temperature,maxTokens:s.maxTokens,reasoning:s.reasoning}}),signal:s.signal});if(!a.ok){let e=`Proxy error: ${a.status} ${a.statusText}`;try{const t=await a.json();t.error&&(e=`Proxy error: ${t.error}`)}catch{}throw new Error(e)}r=a.body.getReader();const i=new TextDecoder;let l="";for(;;){const{done:e,value:t}=await r.read();if(e)break;if(s.signal?.aborted)throw new Error("Request aborted by user");l+=i.decode(t,{stream:!0});const a=l.split("\n");l=a.pop()||"";for(const e of a)if(e.startsWith("data: ")){const t=e.slice(6).trim();if(t){const e=m(JSON.parse(t),o);e&&n.push(e)}}}if(s.signal?.aborted)throw new Error("Request aborted by user");n.end()}catch(e){const t=e instanceof Error?e.message:String(e),r=s.signal?.aborted?"aborted":"error";o.stopReason=r,o.errorMessage=t,n.push({type:"error",reason:r,error:o}),n.end()}finally{s.signal&&s.signal.removeEventListener("abort",a)}})(),n}function m(e,t){switch(e.type){case"start":return{type:"start",partial:t};case"text_start":return t.content[e.contentIndex]={type:"text",text:""},{type:"text_start",contentIndex:e.contentIndex,partial:t};case"text_delta":{const s=t.content[e.contentIndex];if("text"===s?.type)return s.text+=e.delta,{type:"text_delta",contentIndex:e.contentIndex,delta:e.delta,partial:t};throw new Error("Received text_delta for non-text content")}case"text_end":{const s=t.content[e.contentIndex];if("text"===s?.type)return s.textSignature=e.contentSignature,{type:"text_end",contentIndex:e.contentIndex,content:s.text,partial:t};throw new Error("Received text_end for non-text content")}case"thinking_start":return t.content[e.contentIndex]={type:"thinking",thinking:""},{type:"thinking_start",contentIndex:e.contentIndex,partial:t};case"thinking_delta":{const s=t.content[e.contentIndex];if("thinking"===s?.type)return s.thinking+=e.delta,{type:"thinking_delta",contentIndex:e.contentIndex,delta:e.delta,partial:t};throw new Error("Received thinking_delta for non-thinking content")}case"thinking_end":{const s=t.content[e.contentIndex];if("thinking"===s?.type)return s.thinkingSignature=e.contentSignature,{type:"thinking_end",contentIndex:e.contentIndex,content:s.thinking,partial:t};throw new Error("Received thinking_end for non-thinking content")}case"toolcall_start":return t.content[e.contentIndex]={type:"toolCall",id:e.id,name:e.toolName,arguments:{},partialJson:""},{type:"toolcall_start",contentIndex:e.contentIndex,partial:t};case"toolcall_delta":{const s=t.content[e.contentIndex];if("toolCall"===s?.type)return s.partialJson+=e.delta,s.arguments=(0,n.parseStreamingJson)(s.partialJson)||{},t.content[e.contentIndex]={...s},{type:"toolcall_delta",contentIndex:e.contentIndex,delta:e.delta,partial:t};throw new Error("Received toolcall_delta for non-toolCall content")}case"toolcall_end":{const s=t.content[e.contentIndex];return"toolCall"===s?.type?(delete s.partialJson,{type:"toolcall_end",contentIndex:e.contentIndex,toolCall:s,partial:t}):void 0}case"done":return t.stopReason=e.reason,t.usage=e.usage,{type:"done",reason:e.reason,message:t};case"error":return t.stopReason=e.reason,t.errorMessage=e.errorMessage,t.usage=e.usage,{type:"error",reason:e.reason,error:t};default:return void console.warn(`Unhandled proxy event type: ${e.type}`)}}}};
|
|
1
|
+
exports.id=582,exports.ids=[582,174],exports.modules={84005:e=>{function t(e){return import(e).catch(()=>{try{return require(e)}catch(s){var t=new Error("Cannot find module '"+e+"'");throw t.code="MODULE_NOT_FOUND",t}})}t.keys=()=>[],t.resolve=t,t.id=84005,e.exports=t},70162:e=>{function t(e){return import(e).catch(()=>{try{return require(e)}catch(s){var t=new Error("Cannot find module '"+e+"'");throw t.code="MODULE_NOT_FOUND",t}})}t.keys=()=>[],t.resolve=t,t.id=70162,e.exports=t},65653:(e,t,s)=>{"use strict";s.r(t),s.d(t,{Agent:()=>p,agentLoop:()=>o,agentLoopContinue:()=>r,streamProxy:()=>d});var n=s(99641);function o(e,t,s,n,o){const r=a();return(async()=>{const a=[...e],l={...t,messages:[...t.messages,...e]};r.push({type:"agent_start"}),r.push({type:"turn_start"});for(const t of e)r.push({type:"message_start",message:t}),r.push({type:"message_end",message:t});await i(l,a,s,n,r,o)})(),r}function r(e,t,s,n){if(0===e.messages.length)throw new Error("Cannot continue: no messages in context");if("assistant"===e.messages[e.messages.length-1].role)throw new Error("Cannot continue from message role: assistant");const o=a();return(async()=>{const r={...e};o.push({type:"agent_start"}),o.push({type:"turn_start"}),await i(r,[],t,s,o,n)})(),o}function a(){return new n.EventStream(e=>"agent_end"===e.type,e=>"agent_end"===e.type?e.messages:[])}async function i(e,t,s,n,o,r){let a=!0,i=await(s.getSteeringMessages?.())||[];for(;;){let u=!0,c=null;for(;u||i.length>0;){if(a?a=!1:o.push({type:"turn_start"}),i.length>0){for(const s of i)o.push({type:"message_start",message:s}),o.push({type:"message_end",message:s}),e.messages.push(s),t.push(s);i=[]}const p=await l(e,s,n,o,r);if(t.push(p),"error"===p.stopReason||"aborted"===p.stopReason)return o.push({type:"turn_end",message:p,toolResults:[]}),o.push({type:"agent_end",messages:t}),void o.end(t);u=p.content.filter(e=>"toolCall"===e.type).length>0;const h=[];if(u){const r=await g(e.tools,p,n,o,s.getSteeringMessages);h.push(...r.toolResults),c=r.steeringMessages??null;for(const s of h)e.messages.push(s),t.push(s)}o.push({type:"turn_end",message:p,toolResults:h}),c&&c.length>0?(i=c,c=null):i=await(s.getSteeringMessages?.())||[]}const p=await(s.getFollowUpMessages?.())||[];if(!(p.length>0))break;i=p}o.push({type:"agent_end",messages:t}),o.end(t)}async function l(e,t,s,o,r){let a=e.messages;t.transformContext&&(a=await t.transformContext(a,s));const i=await t.convertToLlm(a),l={systemPrompt:e.systemPrompt,messages:i,tools:e.tools},g=r||n.streamSimple,u=(t.getApiKey?await t.getApiKey(t.model.provider):void 0)||t.apiKey,c=await g(t.model,l,{...t,apiKey:u,signal:s});let p=null,h=!1;for await(const t of c)switch(t.type){case"start":p=t.partial,e.messages.push(p),h=!0,o.push({type:"message_start",message:{...p}});break;case"text_start":case"text_delta":case"text_end":case"thinking_start":case"thinking_delta":case"thinking_end":case"toolcall_start":case"toolcall_delta":case"toolcall_end":p&&(p=t.partial,e.messages[e.messages.length-1]=p,o.push({type:"message_update",assistantMessageEvent:t,message:{...p}}));break;case"done":case"error":{const t=await c.result();return h?e.messages[e.messages.length-1]=t:e.messages.push(t),h||o.push({type:"message_start",message:{...t}}),o.push({type:"message_end",message:t}),t}}return await c.result()}async function g(e,t,s,o,r){const a=t.content.filter(e=>"toolCall"===e.type),i=[];let l;for(let t=0;t<a.length;t++){const g=a[t],c=e?.find(e=>e.name===g.name);let p;o.push({type:"tool_execution_start",toolCallId:g.id,toolName:g.name,args:g.arguments});let h=!1;try{if(!c)throw new Error(`Tool ${g.name} not found`);const e=(0,n.validateToolArguments)(c,g);p=await c.execute(g.id,e,s,e=>{o.push({type:"tool_execution_update",toolCallId:g.id,toolName:g.name,args:g.arguments,partialResult:e})})}catch(e){p={content:[{type:"text",text:e instanceof Error?e.message:String(e)}],details:{}},h=!0}o.push({type:"tool_execution_end",toolCallId:g.id,toolName:g.name,result:p,isError:h});const d={role:"toolResult",toolCallId:g.id,toolName:g.name,content:p.content,details:p.details,isError:h,timestamp:Date.now()};if(i.push(d),o.push({type:"message_start",message:d}),o.push({type:"message_end",message:d}),r){const e=await r();if(e.length>0){l=e;const s=a.slice(t+1);for(const e of s)i.push(u(e,o));break}}}return{toolResults:i,steeringMessages:l}}function u(e,t){const s={content:[{type:"text",text:"Skipped due to queued user message."}],details:{}};t.push({type:"tool_execution_start",toolCallId:e.id,toolName:e.name,args:e.arguments}),t.push({type:"tool_execution_end",toolCallId:e.id,toolName:e.name,result:s,isError:!0});const n={role:"toolResult",toolCallId:e.id,toolName:e.name,content:s.content,details:{},isError:!0,timestamp:Date.now()};return t.push({type:"message_start",message:n}),t.push({type:"message_end",message:n}),n}function c(e){return e.filter(e=>"user"===e.role||"assistant"===e.role||"toolResult"===e.role)}class p{_state={systemPrompt:"",model:(0,n.getModel)("google","gemini-2.5-flash-lite-preview-06-17"),thinkingLevel:"off",tools:[],messages:[],isStreaming:!1,streamMessage:null,pendingToolCalls:new Set,error:void 0};listeners=new Set;abortController;convertToLlm;transformContext;steeringQueue=[];followUpQueue=[];steeringMode;followUpMode;streamFn;_sessionId;getApiKey;_onPayload;runningPrompt;resolveRunningPrompt;_thinkingBudgets;_transport;_maxRetryDelayMs;constructor(e={}){this._state={...this._state,...e.initialState},this.convertToLlm=e.convertToLlm||c,this.transformContext=e.transformContext,this.steeringMode=e.steeringMode||"one-at-a-time",this.followUpMode=e.followUpMode||"one-at-a-time",this.streamFn=e.streamFn||n.streamSimple,this._sessionId=e.sessionId,this.getApiKey=e.getApiKey,this._onPayload=e.onPayload,this._thinkingBudgets=e.thinkingBudgets,this._transport=e.transport??"sse",this._maxRetryDelayMs=e.maxRetryDelayMs}get sessionId(){return this._sessionId}set sessionId(e){this._sessionId=e}get thinkingBudgets(){return this._thinkingBudgets}set thinkingBudgets(e){this._thinkingBudgets=e}get transport(){return this._transport}setTransport(e){this._transport=e}get maxRetryDelayMs(){return this._maxRetryDelayMs}set maxRetryDelayMs(e){this._maxRetryDelayMs=e}get state(){return this._state}subscribe(e){return this.listeners.add(e),()=>this.listeners.delete(e)}setSystemPrompt(e){this._state.systemPrompt=e}setModel(e){this._state.model=e}setThinkingLevel(e){this._state.thinkingLevel=e}setSteeringMode(e){this.steeringMode=e}getSteeringMode(){return this.steeringMode}setFollowUpMode(e){this.followUpMode=e}getFollowUpMode(){return this.followUpMode}setTools(e){this._state.tools=e}replaceMessages(e){this._state.messages=e.slice()}appendMessage(e){this._state.messages=[...this._state.messages,e]}steer(e){this.steeringQueue.push(e)}followUp(e){this.followUpQueue.push(e)}clearSteeringQueue(){this.steeringQueue=[]}clearFollowUpQueue(){this.followUpQueue=[]}clearAllQueues(){this.steeringQueue=[],this.followUpQueue=[]}hasQueuedMessages(){return this.steeringQueue.length>0||this.followUpQueue.length>0}dequeueSteeringMessages(){if("one-at-a-time"===this.steeringMode){if(this.steeringQueue.length>0){const e=this.steeringQueue[0];return this.steeringQueue=this.steeringQueue.slice(1),[e]}return[]}const e=this.steeringQueue.slice();return this.steeringQueue=[],e}dequeueFollowUpMessages(){if("one-at-a-time"===this.followUpMode){if(this.followUpQueue.length>0){const e=this.followUpQueue[0];return this.followUpQueue=this.followUpQueue.slice(1),[e]}return[]}const e=this.followUpQueue.slice();return this.followUpQueue=[],e}clearMessages(){this._state.messages=[]}abort(){this.abortController?.abort()}waitForIdle(){return this.runningPrompt??Promise.resolve()}reset(){this._state.messages=[],this._state.isStreaming=!1,this._state.streamMessage=null,this._state.pendingToolCalls=new Set,this._state.error=void 0,this.steeringQueue=[],this.followUpQueue=[]}async prompt(e,t){if(this._state.isStreaming)throw new Error("Agent is already processing a prompt. Use steer() or followUp() to queue messages, or wait for completion.");if(!this._state.model)throw new Error("No model configured");let s;if(Array.isArray(e))s=e;else if("string"==typeof e){const n=[{type:"text",text:e}];t&&t.length>0&&n.push(...t),s=[{role:"user",content:n,timestamp:Date.now()}]}else s=[e];await this._runLoop(s)}async continue(){if(this._state.isStreaming)throw new Error("Agent is already processing. Wait for completion before continuing.");const e=this._state.messages;if(0===e.length)throw new Error("No messages to continue from");if("assistant"===e[e.length-1].role){const e=this.dequeueSteeringMessages();if(e.length>0)return void await this._runLoop(e,{skipInitialSteeringPoll:!0});const t=this.dequeueFollowUpMessages();if(t.length>0)return void await this._runLoop(t);throw new Error("Cannot continue from message role: assistant")}await this._runLoop(void 0)}async _runLoop(e,t){const s=this._state.model;if(!s)throw new Error("No model configured");this.runningPrompt=new Promise(e=>{this.resolveRunningPrompt=e}),this.abortController=new AbortController,this._state.isStreaming=!0,this._state.streamMessage=null,this._state.error=void 0;const n="off"===this._state.thinkingLevel?void 0:this._state.thinkingLevel,a={systemPrompt:this._state.systemPrompt,messages:this._state.messages.slice(),tools:this._state.tools};let i=!0===t?.skipInitialSteeringPoll;const l={model:s,reasoning:n,sessionId:this._sessionId,onPayload:this._onPayload,transport:this._transport,thinkingBudgets:this._thinkingBudgets,maxRetryDelayMs:this._maxRetryDelayMs,convertToLlm:this.convertToLlm,transformContext:this.transformContext,getApiKey:this.getApiKey,getSteeringMessages:async()=>i?(i=!1,[]):this.dequeueSteeringMessages(),getFollowUpMessages:async()=>this.dequeueFollowUpMessages()};let g=null;try{const t=e?o(e,a,l,this.abortController.signal,this.streamFn):r(a,l,this.abortController.signal,this.streamFn);for await(const e of t){switch(e.type){case"message_start":case"message_update":g=e.message,this._state.streamMessage=e.message;break;case"message_end":g=null,this._state.streamMessage=null,this.appendMessage(e.message);break;case"tool_execution_start":{const t=new Set(this._state.pendingToolCalls);t.add(e.toolCallId),this._state.pendingToolCalls=t;break}case"tool_execution_end":{const t=new Set(this._state.pendingToolCalls);t.delete(e.toolCallId),this._state.pendingToolCalls=t;break}case"turn_end":"assistant"===e.message.role&&e.message.errorMessage&&(this._state.error=e.message.errorMessage);break;case"agent_end":this._state.isStreaming=!1,this._state.streamMessage=null}this.emit(e)}if(g&&"assistant"===g.role&&g.content.length>0){if(!g.content.some(e=>"thinking"===e.type&&e.thinking.trim().length>0||"text"===e.type&&e.text.trim().length>0||"toolCall"===e.type&&e.name.trim().length>0)){if(this.abortController?.signal.aborted)throw new Error("Request was aborted")}else this.appendMessage(g)}}catch(e){const t={role:"assistant",content:[{type:"text",text:""}],api:s.api,provider:s.provider,model:s.id,usage:{input:0,output:0,cacheRead:0,cacheWrite:0,totalTokens:0,cost:{input:0,output:0,cacheRead:0,cacheWrite:0,total:0}},stopReason:this.abortController?.signal.aborted?"aborted":"error",errorMessage:e?.message||String(e),timestamp:Date.now()};this.appendMessage(t),this._state.error=e?.message||String(e),this.emit({type:"agent_end",messages:[t]})}finally{this._state.isStreaming=!1,this._state.streamMessage=null,this._state.pendingToolCalls=new Set,this.abortController=void 0,this.resolveRunningPrompt?.(),this.runningPrompt=void 0,this.resolveRunningPrompt=void 0}}emit(e){for(const t of this.listeners)t(e)}}class h extends n.EventStream{constructor(){super(e=>"done"===e.type||"error"===e.type,e=>{if("done"===e.type)return e.message;if("error"===e.type)return e.error;throw new Error("Unexpected event type")})}}function d(e,t,s){const n=new h;return(async()=>{const o={role:"assistant",stopReason:"stop",content:[],api:e.api,provider:e.provider,model:e.id,usage:{input:0,output:0,cacheRead:0,cacheWrite:0,totalTokens:0,cost:{input:0,output:0,cacheRead:0,cacheWrite:0,total:0}},timestamp:Date.now()};let r;const a=()=>{r&&r.cancel("Request aborted by user").catch(()=>{})};s.signal&&s.signal.addEventListener("abort",a);try{const a=await fetch(`${s.proxyUrl}/api/stream`,{method:"POST",headers:{Authorization:`Bearer ${s.authToken}`,"Content-Type":"application/json"},body:JSON.stringify({model:e,context:t,options:{temperature:s.temperature,maxTokens:s.maxTokens,reasoning:s.reasoning}}),signal:s.signal});if(!a.ok){let e=`Proxy error: ${a.status} ${a.statusText}`;try{const t=await a.json();t.error&&(e=`Proxy error: ${t.error}`)}catch{}throw new Error(e)}r=a.body.getReader();const i=new TextDecoder;let l="";for(;;){const{done:e,value:t}=await r.read();if(e)break;if(s.signal?.aborted)throw new Error("Request aborted by user");l+=i.decode(t,{stream:!0});const a=l.split("\n");l=a.pop()||"";for(const e of a)if(e.startsWith("data: ")){const t=e.slice(6).trim();if(t){const e=m(JSON.parse(t),o);e&&n.push(e)}}}if(s.signal?.aborted)throw new Error("Request aborted by user");n.end()}catch(e){const t=e instanceof Error?e.message:String(e),r=s.signal?.aborted?"aborted":"error";o.stopReason=r,o.errorMessage=t,n.push({type:"error",reason:r,error:o}),n.end()}finally{s.signal&&s.signal.removeEventListener("abort",a)}})(),n}function m(e,t){switch(e.type){case"start":return{type:"start",partial:t};case"text_start":return t.content[e.contentIndex]={type:"text",text:""},{type:"text_start",contentIndex:e.contentIndex,partial:t};case"text_delta":{const s=t.content[e.contentIndex];if("text"===s?.type)return s.text+=e.delta,{type:"text_delta",contentIndex:e.contentIndex,delta:e.delta,partial:t};throw new Error("Received text_delta for non-text content")}case"text_end":{const s=t.content[e.contentIndex];if("text"===s?.type)return s.textSignature=e.contentSignature,{type:"text_end",contentIndex:e.contentIndex,content:s.text,partial:t};throw new Error("Received text_end for non-text content")}case"thinking_start":return t.content[e.contentIndex]={type:"thinking",thinking:""},{type:"thinking_start",contentIndex:e.contentIndex,partial:t};case"thinking_delta":{const s=t.content[e.contentIndex];if("thinking"===s?.type)return s.thinking+=e.delta,{type:"thinking_delta",contentIndex:e.contentIndex,delta:e.delta,partial:t};throw new Error("Received thinking_delta for non-thinking content")}case"thinking_end":{const s=t.content[e.contentIndex];if("thinking"===s?.type)return s.thinkingSignature=e.contentSignature,{type:"thinking_end",contentIndex:e.contentIndex,content:s.thinking,partial:t};throw new Error("Received thinking_end for non-thinking content")}case"toolcall_start":return t.content[e.contentIndex]={type:"toolCall",id:e.id,name:e.toolName,arguments:{},partialJson:""},{type:"toolcall_start",contentIndex:e.contentIndex,partial:t};case"toolcall_delta":{const s=t.content[e.contentIndex];if("toolCall"===s?.type)return s.partialJson+=e.delta,s.arguments=(0,n.parseStreamingJson)(s.partialJson)||{},t.content[e.contentIndex]={...s},{type:"toolcall_delta",contentIndex:e.contentIndex,delta:e.delta,partial:t};throw new Error("Received toolcall_delta for non-toolCall content")}case"toolcall_end":{const s=t.content[e.contentIndex];return"toolCall"===s?.type?(delete s.partialJson,{type:"toolcall_end",contentIndex:e.contentIndex,toolCall:s,partial:t}):void 0}case"done":return t.stopReason=e.reason,t.usage=e.usage,{type:"done",reason:e.reason,message:t};case"error":return t.stopReason=e.reason,t.errorMessage=e.errorMessage,t.usage=e.usage,{type:"error",reason:e.reason,error:t};default:return void console.warn(`Unhandled proxy event type: ${e.type}`)}}}};
|