jivamai 0.1.4-dev.63d462c

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (50) hide show
  1. package/CHANGELOG.md +170 -0
  2. package/README.md +94 -0
  3. package/assets/icon.icns +0 -0
  4. package/assets/icon.iconset/icon_128x128.png +0 -0
  5. package/assets/icon.iconset/icon_128x128@2x.png +0 -0
  6. package/assets/icon.iconset/icon_16x16.png +0 -0
  7. package/assets/icon.iconset/icon_16x16@2x.png +0 -0
  8. package/assets/icon.iconset/icon_256x256.png +0 -0
  9. package/assets/icon.iconset/icon_256x256@2x.png +0 -0
  10. package/assets/icon.iconset/icon_32x32.png +0 -0
  11. package/assets/icon.iconset/icon_32x32@2x.png +0 -0
  12. package/assets/icon.iconset/icon_512x512.png +0 -0
  13. package/assets/icon.iconset/icon_512x512@2x.png +0 -0
  14. package/assets/icon.png +0 -0
  15. package/assets/logo.png +0 -0
  16. package/bin/jivam.js +7 -0
  17. package/dist/assets/index-CisS1YJo.css +10 -0
  18. package/dist/assets/index-DftBqc_W.js +510 -0
  19. package/dist/assets/logo-CJttTQkq.png +0 -0
  20. package/dist/icon-192.png +0 -0
  21. package/dist/icon-512.png +0 -0
  22. package/dist/index.html +19 -0
  23. package/dist/logo.png +0 -0
  24. package/dist/manifest.json +24 -0
  25. package/dist-server/icon-192.png +0 -0
  26. package/dist-server/icon-512.png +0 -0
  27. package/dist-server/index.js +292 -0
  28. package/dist-server/index.js.map +1 -0
  29. package/dist-server/logo.png +0 -0
  30. package/dist-server/manifest.json +24 -0
  31. package/docs/README.md +55 -0
  32. package/docs/architecture/cloud-mode.md +204 -0
  33. package/docs/architecture/code-agent-integration.md +276 -0
  34. package/docs/architecture/ipc-contract.md +162 -0
  35. package/docs/architecture/jiva-core-integration.md +147 -0
  36. package/docs/architecture/overview.md +87 -0
  37. package/docs/architecture/startup-flow.md +108 -0
  38. package/docs/architecture/state-management.md +153 -0
  39. package/docs/guides/adding-features.md +196 -0
  40. package/docs/guides/design-guide.md +308 -0
  41. package/docs/release_notes/.gitkeep +0 -0
  42. package/electron-builder.yml +86 -0
  43. package/index.html +18 -0
  44. package/package.json +62 -0
  45. package/portal_home.png +0 -0
  46. package/proposal.md +61 -0
  47. package/public/icon-192.png +0 -0
  48. package/public/icon-512.png +0 -0
  49. package/public/logo.png +0 -0
  50. package/public/manifest.json +24 -0
Binary file
Binary file
Binary file
@@ -0,0 +1,19 @@
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
+ <meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline' https://fonts.googleapis.com; font-src 'self' https://fonts.gstatic.com; connect-src 'self' ws://localhost:* wss://localhost:* http://localhost:* https:; img-src 'self' data: blob:;" />
7
+ <meta name="theme-color" content="#8b5cf6" />
8
+ <link rel="manifest" href="/manifest.json" />
9
+ <title>Jivam</title>
10
+ <link rel="preconnect" href="https://fonts.googleapis.com">
11
+ <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
12
+ <link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap" rel="stylesheet">
13
+ <script type="module" crossorigin src="/assets/index-DftBqc_W.js"></script>
14
+ <link rel="stylesheet" crossorigin href="/assets/index-CisS1YJo.css">
15
+ </head>
16
+ <body>
17
+ <div id="root"></div>
18
+ </body>
19
+ </html>
package/dist/logo.png ADDED
Binary file
@@ -0,0 +1,24 @@
1
+ {
2
+ "id": "/",
3
+ "name": "Jivam",
4
+ "short_name": "Jivam",
5
+ "description": "Desktop UI for the Jiva autonomous AI agent",
6
+ "start_url": "/",
7
+ "display": "standalone",
8
+ "background_color": "#0d0d0d",
9
+ "theme_color": "#8b5cf6",
10
+ "icons": [
11
+ {
12
+ "src": "/icon-192.png",
13
+ "sizes": "192x192",
14
+ "type": "image/png",
15
+ "purpose": "any maskable"
16
+ },
17
+ {
18
+ "src": "/icon-512.png",
19
+ "sizes": "512x512",
20
+ "type": "image/png",
21
+ "purpose": "any maskable"
22
+ }
23
+ ]
24
+ }
Binary file
Binary file
@@ -0,0 +1,292 @@
1
+ "use strict";var He=Object.create;var ae=Object.defineProperty;var Ge=Object.getOwnPropertyDescriptor;var Ve=Object.getOwnPropertyNames;var Ye=Object.getPrototypeOf,Ke=Object.prototype.hasOwnProperty;var Xe=(r,n,e)=>n in r?ae(r,n,{enumerable:!0,configurable:!0,writable:!0,value:e}):r[n]=e;var Ze=(r,n,e,t)=>{if(n&&typeof n=="object"||typeof n=="function")for(let s of Ve(n))!Ke.call(r,s)&&s!==e&&ae(r,s,{get:()=>n[s],enumerable:!(t=Ge(n,s))||t.enumerable});return r};var C=(r,n,e)=>(e=r!=null?He(Ye(r)):{},Ze(n||!r||!r.__esModule?ae(e,"default",{value:r,enumerable:!0}):e,r));var x=(r,n,e)=>Xe(r,typeof n!="symbol"?n+"":n,e);const $=require("child_process"),u=require("fs"),S=require("os"),m=require("path"),E=require("express"),Qe=require("http"),$e=require("ws"),Me=require("events"),me=require("url"),pe=require("zlib");function et(){if(process.platform==="win32")return;try{const o=process.env.SHELL??"/bin/zsh",i=$.execSync(`${o} -l -c 'echo $PATH'`,{timeout:3e3}).toString().trim();if(i){process.env.PATH=i;return}}catch{}const r=S.homedir(),n=["/usr/local/bin","/opt/homebrew/bin","/opt/local/bin",`${r}/.npm-global/bin`,"/usr/local/opt/node/bin"];try{const o=m.join(r,".nvm","versions","node");if(u.existsSync(o)){const i=u.readdirSync(o).sort().reverse()[0];i&&n.push(m.join(o,i,"bin"))}}catch{}const e=process.env.PATH??"",t=new Set(e.split(":").filter(Boolean)),s=n.filter(o=>!t.has(o));s.length&&(process.env.PATH=[...s,e].join(":"))}let fe=null;const te=new Set;function tt(r){fe=new $e.WebSocketServer({server:r,path:"/ws"}),fe.on("connection",(n,e)=>{te.add(n),n.on("close",()=>te.delete(n)),n.on("error",()=>te.delete(n))})}function O(r,n){if(!fe)return;const e=JSON.stringify({type:r,...n!==null&&typeof n=="object"?n:{data:n}});for(const t of te)t.readyState===$e.WebSocket.OPEN&&t.send(e)}const ne=m.join(S.homedir(),".jiva"),ce=m.join(ne,"jiva-directive.md"),le=m.join(ne,"conversations");function nt(r=5){try{return u.existsSync(le)?u.readdirSync(le).filter(e=>e.endsWith(".json")).map(e=>{const t=m.join(le,e);try{const s=u.statSync(t),o=JSON.parse(u.readFileSync(t,"utf-8")),i=Array.isArray(o.messages)?o.messages.length:0;let a=o.summary??o.title??"";if(!a&&Array.isArray(o.messages)){const c=o.messages.find(l=>l.role==="user");c!=null&&c.content&&(a=String(c.content).slice(0,60).replace(/\n/g," "),String(c.content).length>60&&(a+="..."))}return a=a||"Untitled conversation",{stat:s,title:a,messageCount:i}}catch{return null}}).filter(Boolean).sort((e,t)=>t.stat.mtimeMs-e.stat.mtimeMs).slice(0,r).map(({stat:e,title:t,messageCount:s})=>{const o=new Date(e.mtimeMs);return{date:`${o.getFullYear()}-${String(o.getMonth()+1).padStart(2,"0")}-${String(o.getDate()).padStart(2,"0")} ${String(o.getHours()).padStart(2,"0")}:${String(o.getMinutes()).padStart(2,"0")}`,title:t,messageCount:s}}):[]}catch{return[]}}function st(r){var f;const n=new Date,e=["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],t=["January","February","March","April","May","June","July","August","September","October","November","December"],s=e[n.getDay()],o=t[n.getMonth()],i=n.getDate(),a=n.getFullYear(),c=String(n.getHours()).padStart(2,"0"),l=String(n.getMinutes()).padStart(2,"0"),d=`${c}:${l}`;let p="UTC";try{p=((f=Intl.DateTimeFormat("en",{timeZoneName:"short"}).formatToParts(n).find(g=>g.type==="timeZoneName"))==null?void 0:f.value)??"UTC"}catch{const g=-n.getTimezoneOffset(),j=g>=0?"+":"-",b=String(Math.floor(Math.abs(g)/60)).padStart(2,"0"),k=String(Math.abs(g)%60).padStart(2,"0");p=`UTC${j}${b}:${k}`}const h=n.toISOString(),y=nt(5);let v;y.length===0?v="_No previous sessions found._":v=`| Date | Title | Messages |
2
+ |------|-------|----------|
3
+ ${y.map(j=>`| ${j.date} | "${j.title}" | ${j.messageCount} |`).join(`
4
+ `)}`;const A=`# Jiva Operating Context
5
+
6
+ ## Current Date & Time
7
+ - Date: ${s}, ${o} ${i}, ${a}
8
+ - Time: ${d} ${p}
9
+ - ISO: ${h}
10
+
11
+ ## Important
12
+ - Always use the date above when referencing "today", "current year", or "recent" events
13
+ - Do NOT rely on training data for the current date — use only what is stated above
14
+ - When performing web searches, always use the year ${a} for current events
15
+
16
+ ## Recent Session Activity
17
+ ${v}
18
+ `;return r!=null&&r.trim()?r.trim()+`
19
+
20
+ ---
21
+
22
+ `+A:A}function he(r){const n=st(r);try{u.existsSync(ne)||u.mkdirSync(ne,{recursive:!0}),u.writeFileSync(ce,n,"utf-8"),console.log(`[DirectiveManager] Wrote directive to ${ce}`)}catch(e){console.warn("[DirectiveManager] Failed to write directive:",e)}return{path:ce,content:n}}function N(){return m.join(S.homedir(),".jivam","config.json")}function rt(){return N()}N();function P(){try{const r=N();if(u.existsSync(r)){const n=u.readFileSync(r,"utf-8");return JSON.parse(n)}return null}catch(r){return console.error("[ConfigManager] Failed to read config:",r),null}}function R(r){try{const n=N(),e=m.dirname(n);return u.existsSync(e)||u.mkdirSync(e,{recursive:!0}),u.writeFileSync(n,JSON.stringify(r,null,2),"utf-8"),!0}catch(n){return console.error("[ConfigManager] Failed to write config:",n),!1}}let ue=null;function ot(r){const n=/^---\s*\n([\s\S]*?)\n---/.exec(r);if(!n)return{};const e={};for(const t of n[1].split(`
23
+ `)){const s=t.indexOf(":");if(s===-1)continue;const o=t.slice(0,s).trim(),i=t.slice(s+1).trim().replace(/^["']|["']$/g,"");o&&(e[o]=i)}return e}async function it(){if(ue!==null)return ue;const r=[m.join(S.homedir(),".claude","skills"),m.join(S.homedir(),".jiva","skills")],n=[];for(const e of r){if(!u.existsSync(e))continue;let t;try{t=u.readdirSync(e,{withFileTypes:!0})}catch{continue}for(const s of t){if(!s.isDirectory())continue;const o=m.join(e,s.name),i=m.join(o,"SKILL.md");if(u.existsSync(i))try{const a=u.readFileSync(i,"utf-8"),c=ot(a),l=c.name??s.name,d=c.description??"";n.push({name:l,description:d,dir:o})}catch{}}}return ue=n,n}function M(r,n){n({timestamp:new Date().toISOString(),level:"info",tag:"brain",message:r})}const at=new Set(["thanks","thank","you","ty","ok","okay","alright","right","sure","yep","yup","yeah","nope","great","good","nice","cool","perfect","awesome","excellent","fantastic","wonderful","brilliant","well","done","job","work","bye","goodbye","later","cheers","ciao","welcome","problem","np","worries","no","we","are","were","finished","this","is","the","end","session","all","that","it","for","our","now","here","got","sounds","lol","haha","heh","wow","oh","ah","hmm","a","an","and","or","but","very","much","so","yes","s"]);function ct(r){const n=r.trim();if(n.length>80)return!1;const e=n.toLowerCase().replace(/[^a-z'\s]/g,"").trim().split(/\s+/);return e.length===0||e.length>12?!1:e.every(t=>at.has(t))}function ve(r,n=140){const e=r.split(`
24
+ `);for(const t of e){const s=t.replace(/^#+\s*/,"").replace(/\*\*/g,"").trim();if(s.length>=20)return s.length>n?s.slice(0,n-1)+"…":s}return r.slice(0,n)}async function lt(r,n,e,t,s,o){const i=n.length>0?n.map(h=>`- ${h.name} (${h.dir}): ${h.description}`).join(`
25
+ `):"(none available)",a=s?`
26
+ Conversation history so far:
27
+ ${s}
28
+ `:"",c=o&&o.length>0?`
29
+ Configured MCP servers (tools the agent already has access to): ${o.join(", ")}`:`
30
+ Configured MCP servers: none beyond built-in filesystem and shell.`,l=`You are a senior AI coordinator. Your first job is to decide whether to answer the user DIRECTLY or DELEGATE the task to a capable AI coding worker.${a}
31
+ ANSWER DIRECTLY (mode: "direct") when the message is:
32
+ - Conversational: greetings, thanks, sign-offs, "great work", "we're done", smalltalk
33
+ - Simple follow-up you can answer from the conversation context above ("what did you find?", "how many issues?")
34
+ - Meta-questions about the session: "are we done?", "can you summarise what we covered?"
35
+ - Anything that would be bizarre to run shell commands for
36
+
37
+ DELEGATE (mode: "delegate") when the message genuinely requires:
38
+ - Code execution, file operations, web research, data analysis
39
+ - Reading, writing, or modifying files in a workspace
40
+ - Iterative tool use, running tests, building, or searching
41
+
42
+ For DIRECT: write a warm, natural response in "directResponse". Be concise.
43
+ For DELEGATE: decompose into 1-5 focused subtasks. Prefer 1 subtask unless distinct phases are truly needed.
44
+
45
+ Rules for delegation:
46
+ - Each subtask prompt must be self-contained and include all relevant context.
47
+ - Write subtask prompts as clean, direct task instructions — no internal headers ("Goal:", "Requirements:", "Planned Subtask for the Worker"), no scaffolding phrases ("Please proceed with...", "Once the results are returned, I will review them", "provide the final response to the user"). Brief the worker as you would a colleague: just the task.
48
+ - "explanation" is 1-2 plain-English sentences for the user about your approach.
49
+ - Set "complexity" per subtask: "simple" for quick single-file edits, "complex" for multi-file refactors or build cycles, "medium" for everything else.
50
+ - Respond with valid JSON only. No markdown fences.
51
+ ${c}
52
+
53
+ MCP recommendations: If the user's request would be meaningfully better with an MCP server that is NOT currently configured (e.g. they want to browse the web but no browser MCP is present, interact with GitHub but no GitHub MCP is set up, send Slack messages, query databases, etc.), include an "mcpRecommendations" array. Each entry: {"name":"package-or-server-name","reason":"one sentence why"}. Only recommend when genuinely useful — skip for tasks that can be done with the current tools. The user can discover and install MCP servers at https://mcpservers.org and configure them in Jivam via Settings (gear icon) → MCPs.
54
+
55
+ Available skills:
56
+ ${i}`,d=`User message:
57
+ ${r}
58
+
59
+ Respond with JSON exactly (use the mode that fits):
60
+ {"mode":"direct","reasoning":"one sentence","explanation":"1-2 sentences for the user","directResponse":"full warm response to the user","subtasks":[]}
61
+ OR
62
+ {"mode":"delegate","reasoning":"one sentence","explanation":"1-2 sentences for the user","subtasks":[{"id":1,"label":"short 3-6 word label","prompt":"full focused self-contained prompt","complexity":"simple|medium|complex"}],"mcpRecommendations":[{"name":"server-name","reason":"why it helps"}]}`,p={mode:"delegate",reasoning:"Proceeding as a single task",explanation:"On it...",subtasks:[{id:1,label:"completing your request",prompt:r}]};try{const h=await e(l,d);if(!h)return p;const y=h.trim().replace(/^```json\s*|\s*```$/g,""),v=JSON.parse(y),A=v.mode==="direct"?"direct":"delegate",f=typeof v.reasoning=="string"?v.reasoning:"",g=typeof v.explanation=="string"&&v.explanation?v.explanation:A==="direct"?"Answering this directly.":"Handling this as a single focused task.",j=Array.isArray(v.mcpRecommendations)?v.mcpRecommendations.filter(w=>typeof w.name=="string"&&w.name.trim()).map(w=>({name:w.name,reason:typeof w.reason=="string"?w.reason:""})):void 0;if(A==="direct"){const w=typeof v.directResponse=="string"?v.directResponse:"";return{mode:"direct",reasoning:f,explanation:g,directResponse:w,subtasks:[],mcpRecommendations:j}}if(!Array.isArray(v.subtasks)||v.subtasks.length===0)return p;const b=v.subtasks.filter(w=>typeof w.label=="string"&&typeof w.prompt=="string").map((w,D)=>({id:typeof w.id=="number"?w.id:D+1,label:w.label,prompt:w.prompt,complexity:w.complexity==="simple"||w.complexity==="medium"||w.complexity==="complex"?w.complexity:"medium"}));return b.length===0?p:{mode:"delegate",reasoning:f,explanation:g,subtasks:b,mcpRecommendations:j}}catch{return p}}async function Se(r,n,e,t){M("Pulling everything together...",t);const s="You are a technical writer. Synthesize the outputs of multiple completed subtasks into one coherent final response to the user's original request. Be concise. Do not repeat implementation details — reference them. Markdown is fine.",o=n.map((a,c)=>`### Subtask ${c+1}: ${a.label}
63
+ ${a.content}`).join(`
64
+
65
+ `),i=`Original request:
66
+ ${r}
67
+
68
+ Subtask results:
69
+
70
+ ${o}
71
+
72
+ Write the final synthesized response.`;try{const a=await e(s,i);if(a)return a}catch{}return n[n.length-1].content}async function ut(r,n,e,t){M("Checking the result...",t);const s="You are verifying whether an AI agent fully completed a task. Be strict but fair — if the core request was addressed, mark it satisfied. Only mark unsatisfied if something specific and important was clearly missed or left incomplete. Respond with valid JSON only, no markdown fences.",o=`Original request:
73
+ ${r}
74
+
75
+ Agent output (truncated to 2000 chars):
76
+ ${n.slice(0,2e3)}
77
+
78
+ Respond with JSON:
79
+ {"satisfied":true,"follow_up":"empty if satisfied, otherwise a precise description of what is still missing"}`,i={satisfied:!0,followUp:""};try{const a=await e(s,o);if(!a)return i;const c=a.trim().replace(/^```json\s*|\s*```$/g,""),l=JSON.parse(c);return{satisfied:l.satisfied!==!1,followUp:typeof l.follow_up=="string"?l.follow_up:""}}catch{return i}}function dt(r,n){switch(r){case"simple":return Math.max(10,Math.floor(n*.4));case"complex":return Math.min(n*2,200);default:return n}}async function ke(r,n,e,t,s){M(`Adjusting my approach (attempt ${e})...`,s);const o="You are helping recover from a failed AI agent execution. The agent was given a task but encountered an error. Rewrite the task prompt to be more explicit, simpler, or to work around the failure. Do not include meta-commentary — output only the revised prompt text.",i=`Original task:
80
+ ${r}
81
+
82
+ Error encountered:
83
+ ${n}
84
+
85
+ Write an improved version of the task prompt that is more likely to succeed.`;try{const a=await t(o,i);if(a&&a.trim().length>20)return a.trim()}catch{}return r}async function je(r,n,e,t,s){M(`Ran into trouble with "${r}" — here's what happened:`,s);const o="You are a helpful AI assistant explaining a task failure to the user. Be concise, honest, and constructive. Do not expose raw error messages or stack traces. Explain what was attempted, what went wrong at a high level, and suggest what the user could try next. Use plain Markdown.",i=`Task attempted: ${r}
86
+ Task description: ${n}
87
+ Error: ${e}
88
+
89
+ Write a short, user-friendly explanation of what happened and what could be done next.`;try{const a=await t(o,i);if(a&&a.trim().length>20)return a.trim()}catch{}return`I wasn't able to complete the task **"${r}"** after multiple attempts.
90
+
91
+ The worker ran into an issue: ${e.slice(0,200)}${e.length>200?"…":""}
92
+
93
+ You may want to check your configuration or try rephrasing the request.`}const mt=[/\bplanned subtask for the worker\b/i,/\bplease proceed with this subtask\b/i,/\bonce the results are returned,?\s+i will\b/i,/\bi will review them and provide the final response\b/i,/\bprovide the final response to the user\b/i];function pt(r){const n=r.slice(0,600);return mt.some(e=>e.test(n))}const Q=2;async function Ae(r,n,e,t,s=50,o,i){const a=await it();if(M("Thinking...",t),ct(r)){const f=o?`
94
+ Conversation history:
95
+ ${o}`:"";let g;try{g=await n(`You are a warm, helpful AI assistant. Reply naturally and concisely. Markdown is fine.${f}`,r)??"You're welcome!"}catch{g="You're welcome!"}return{content:g,toolsUsed:[],iterations:0,plan:{subtasks:[],reasoning:"Conversational response"}}}const c=await lt(r,a,n,t,o,i);if(c.mode==="direct"){let f=c.directResponse??"";if(!f.trim())try{const g=o?`
96
+ Conversation history:
97
+ ${o}`:"";f=await n(`You are a warm, helpful AI assistant. Answer the user's message naturally and concisely. Markdown is fine.${g}`,r)??"Got it!"}catch{f="Got it!"}return{content:f,toolsUsed:[],iterations:0,plan:{subtasks:[],reasoning:c.reasoning}}}if(M(c.explanation,t),c.mcpRecommendations&&c.mcpRecommendations.length>0){M("💡 You could get better results by adding these MCP servers:",t);for(const f of c.mcpRecommendations)M(` • **${f.name}** — ${f.reason}`,t);M("Browse https://mcpservers.org to find them, then add via Settings (⚙️) → MCPs.",t)}const l=c.subtasks.length;if(l>1){const f=c.subtasks.map((g,j)=>`${j+1}. ${g.label}`).join(" · ");M(`My plan: ${f}`,t)}const d=[];for(const f of c.subtasks){M(`Working on step ${f.id}: ${f.label}...`,t);const g=dt(f.complexity,s);let j=null,b="";for(let k=1;k<=Q;k++)try{const w=k===1?f.prompt:await ke(f.prompt,b,k,n,t),D=Date.now(),L=setInterval(()=>{const T=Math.round((Date.now()-D)/1e3);M(`Still at it (${T}s)…`,t)},25e3);try{j=await e(w,{maxIterations:g})}finally{clearInterval(L)}break}catch(w){b=w instanceof Error?w.message:String(w),k<Q?M("Hit a snag — let me try a different approach...",t):j={content:await je(f.label,f.prompt,b,n,t),toolsUsed:[],iterations:0}}if(l>1){const k=ve(j.content);k&&M(`Step ${f.id} done: ${k}`,t)}d.push({...j,label:f.label})}let p;if(l===1?p=d[0].content:p=await Se(r,d.map(f=>({label:f.label,content:f.content})),n,t),pt(p)){M("The worker couldn't complete this one — let me answer directly...",t);const f=o?`
98
+ Conversation history:
99
+ ${o}`:"";try{p=await n(`You are a helpful AI assistant. The AI agent encountered a technical issue and could not complete the task using tools. Answer the user's question directly from your knowledge. Be honest if the answer would benefit from live data that you can't access right now. Markdown is fine.${f}`,r)??p}catch{}}const h=await ut(r,p,n,t);if(!h.satisfied&&h.followUp){M("Almost there — one more thing to tackle...",t);const f=`The following was not fully addressed in your previous response:
100
+
101
+ ${h.followUp}
102
+
103
+ Original request:
104
+ ${r}
105
+
106
+ Previous work summary:
107
+ ${p.slice(0,800)}
108
+
109
+ Please address the missing parts specifically.`;let g=null,j="";for(let k=1;k<=Q;k++)try{const w=k===1?f:await ke(f,j,k,n,t);g=await e(w,{maxIterations:s});break}catch(w){j=w instanceof Error?w.message:String(w),k<Q?M("The follow-up hit an issue — trying once more...",t):g={content:await je("follow-up",f,j,n,t),toolsUsed:[],iterations:0}}const b=ve(g.content);b&&M(`That covers it: ${b}`,t),p=await Se(r,[{label:"Initial work",content:p},{label:"Follow-up",content:g.content}],n,t),d.push({...g,label:"follow-up"})}else h.satisfied&&M("All done — here's the result:",t);const y=d.flatMap(f=>f.toolsUsed??[]),v=[...new Set(y)],A=d.reduce((f,g)=>f+(g.iterations??0),0);return{...d[d.length-1],content:p,toolsUsed:v,iterations:A,plan:{subtasks:c.subtasks.map(f=>f.label),reasoning:c.reasoning}}}function ft(){try{const n=$.execSync("npm root -g",{timeout:5e3}).toString().trim(),e=m.join(n,"jiva-core","package.json");if(u.existsSync(e)){const s=JSON.parse(u.readFileSync(e,"utf-8")).main??"dist/index.js";return m.join(n,"jiva-core",s)}}catch{}const r=m.join(S.homedir(),".npm-global","lib","node_modules","jiva-core","dist","index.js");if(u.existsSync(r))return r;throw new Error("Could not find jiva-core. Please run: npm install -g jiva-core")}const ht=/^(\d{4}-\d{2}-\d{2}T[\d:.Z]+)\s+\[(INFO|WARN|ERROR)\]\s+\[(\w+)\]\s+(.+)$/;function Ie(r){const n=ht.exec(r.trim());return n?{timestamp:n[1],level:n[2].toLowerCase(),tag:n[3],message:n[4]}:null}class gt extends Me.EventEmitter{constructor(){super(...arguments);x(this,"agent",null);x(this,"orchestrator",null);x(this,"workspace",null);x(this,"conversationManager",null);x(this,"mcpManager",null);x(this,"codeLogger",null);x(this,"ready",!1);x(this,"deepRun",!1);x(this,"maxIterations",50)}isReady(){return this.ready}getConversationId(){return this.conversationManager?this.conversationManager.currentConversationId??null:null}async initialize(e,t,s){var V,Y;this.deepRun=(s==null?void 0:s.deepRun)??!1,this.maxIterations=(s==null?void 0:s.maxIterations)??50;const o=ft();console.log(`[CodeRunner] Loading jiva-core from: ${o}`);const i=await import(me.pathToFileURL(o).href),{configManager:a,ModelOrchestrator:c,WorkspaceManager:l,ConversationManager:d,CodeAgent:p,MCPServerManager:h,createKrutrimModel:y,createLocalProvider:v,logger:A}=i;this.codeLogger=A??null,a.validateConfig();const f=a.getReasoningModel(),j=y({endpoint:f.endpoint,apiKey:f.apiKey,model:f.defaultModel,type:"reasoning",useHarmonyFormat:f.useHarmonyFormat}),b=c;this.orchestrator=new b({reasoningModel:j});const{path:k}=he((V=P())==null?void 0:V.userDirective),w=l;this.workspace=new w({workspaceDir:e,directivePath:k}),await this.workspace.initialize();const L=await v(),T=d;this.conversationManager=new T(L,this.orchestrator),this.mcpManager=null;const F=t&&t.length>0?t:null;if(F&&h){const oe=h,ie=new oe,K=((Y=P())==null?void 0:Y.mcpServers)??{},X={};for(const q of F)K[q]&&(X[q]=K[q]);await ie.initialize(X),this.mcpManager=ie,console.log(`[CodeRunner] MCP servers loaded: ${F.join(", ")}`)}const re=p;this.agent=new re({orchestrator:this.orchestrator,workspace:this.workspace,conversationManager:this.conversationManager,maxIterations:this.maxIterations,...this.mcpManager&&F?{mcpManager:this.mcpManager,mcpServerNames:F}:{}}),this.ready=!0,console.log(`[CodeRunner] Initialized (maxIterations=${this.maxIterations}, deepRun=${this.deepRun})`)}makeCompleter(){const e=this.orchestrator;return async(t,s)=>{if(typeof e.chat!="function")return null;try{const i=await e.chat.bind(e)({messages:[{role:"system",content:t},{role:"user",content:s}],reasoningEffort:"low"});return(i==null?void 0:i.content)??null}catch(o){return console.warn("[CodeRunner] makeCompleter: chat() failed:",o),null}}}async chat(e,t,s){if((s==null?void 0:s.maxIterations)!==void 0&&s.maxIterations!==this.maxIterations){this.maxIterations=s.maxIterations;try{this.agent.maxIterations=this.maxIterations}catch{}}return(s==null?void 0:s.deepRun)!==!1&&((s==null?void 0:s.deepRun)??this.deepRun)?await Ae(e,this.makeCompleter(),(a,c)=>this.runChatWithIterations(a,t,c==null?void 0:c.maxIterations),a=>t(a),this.maxIterations,(s==null?void 0:s.conversationHistory)||void 0):this.runChat(e,t)}async runChatWithIterations(e,t,s){if(s!==void 0&&s!==this.maxIterations){this.maxIterations=s;try{this.agent.maxIterations=this.maxIterations}catch{}}return this.runChat(e,t)}hookLogger(e){const t=this.codeLogger,s=(i,a,c)=>{const l=i.toLowerCase();e({timestamp:new Date().toISOString(),level:l==="warn"||l==="error"?l:"info",tag:a,message:c})};if(t&&typeof t.on=="function"){const i=(...a)=>{if(a.length>=3&&typeof a[0]=="string")s(a[0],a[1]??"CodeAgent",a[2]);else if(a.length>=2&&typeof a[0]=="string")s("info","CodeAgent",a[1]);else if(a.length>=1&&typeof a[0]=="object"){const c=a[0];s(String(c.level??"info"),String(c.tag??c.name??"CodeAgent"),String(c.message??c.msg??""))}};try{return t.on("log",i),()=>{typeof t.off=="function"?t.off("log",i):typeof t.removeListener=="function"&&t.removeListener("log",i)}}catch{}}if(t)for(const i of["addTransport","addHandler","addSink"]){if(typeof t[i]!="function")continue;const a=i.replace("add","remove"),c={write:l=>{s(String(l.level??"info"),String(l.tag??l.name??"CodeAgent"),String(l.message??l.msg??""))},log:l=>{s(String(l.level??"info"),String(l.tag??l.name??"CodeAgent"),String(l.message??l.msg??""))}};try{return t[i](c),()=>{if(typeof t[a]=="function")try{t[a](c)}catch{}}}catch{}}const o=process.stdout.write.bind(process.stdout);return process.stdout.write=(i,...a)=>{const c=typeof i=="string"?i:Buffer.from(i).toString();for(const l of c.split(`
110
+ `)){const d=Ie(l);if(d){e(d);continue}const p=/(?:tool(?:\s+call)?|calling|executing)[:\s]+([^\s(]+)/i.exec(l.trim());p&&e({timestamp:new Date().toISOString(),level:"info",tag:"CodeAgent",message:`Tool: ${p[1]}`})}return o(i,...a)},()=>{process.stdout.write=o}}async runChat(e,t){var i;if(!this.agent)throw new Error("CodeRunner not initialized");const s=this.agent,o=this.hookLogger(t);try{const a=await s.chat(e);if((i=a.toolsUsed)!=null&&i.length){const c=new Set;for(const l of a.toolsUsed)c.has(l)||(c.add(l),t({timestamp:new Date().toISOString(),level:"info",tag:"CodeAgent",message:`Tool: ${l}`}))}return{content:a.content,toolsUsed:a.toolsUsed??[],iterations:a.iterations??0}}finally{o()}}stop(){this.agent&&this.agent.stop()}async cleanup(){if(this.agent)try{await this.agent.cleanup()}catch(e){console.warn("[CodeRunner] Cleanup error:",e)}if(this.mcpManager)try{await this.mcpManager.cleanup()}catch{}this.agent=null,this.orchestrator=null,this.workspace=null,this.conversationManager=null,this.mcpManager=null,this.ready=!1}}function yt(){try{const n=$.execSync("npm root -g",{timeout:5e3}).toString().trim(),e=m.join(n,"jiva-core","package.json");if(u.existsSync(e)){const s=JSON.parse(u.readFileSync(e,"utf-8")).main??"dist/index.js";return m.join(n,"jiva-core",s)}}catch{}if(process.platform==="win32"){const n=[m.join(process.env.APPDATA??"","npm","node_modules","jiva-core","dist","index.js"),m.join(process.env.LOCALAPPDATA??"","npm","node_modules","jiva-core","dist","index.js"),"C:\\Program Files\\nodejs\\node_modules\\jiva-core\\dist\\index.js"];for(const e of n)if(u.existsSync(e))return e}const r="/Users/abidev/.npm-global/lib/node_modules/jiva-core/dist/index.js";if(u.existsSync(r))return r;throw new Error("Could not find jiva-core. Please ensure it is installed globally: npm install -g jiva-core")}class wt extends Me.EventEmitter{constructor(){super(...arguments);x(this,"status","stopped");x(this,"agent",null);x(this,"orchestrator",null);x(this,"mcpManager",null);x(this,"workspace",null);x(this,"conversationManager",null);x(this,"personaManager",null);x(this,"jivaLogger",null);x(this,"currentPersona",null);x(this,"currentConversationId",null);x(this,"maxIterations",50)}getStatus(){return this.status}getCurrentConversationId(){return this.currentConversationId}async initialize(e){var t,s;this.setStatus("initializing");try{const o=yt();console.log(`[JivaRunner] Loading jiva-core from: ${o}`);const i=await import(me.pathToFileURL(o).href),{MCPServerManager:a,WorkspaceManager:c,ConversationManager:l,ModelOrchestrator:d,DualAgent:p,createKrutrimModel:h,LogLevel:y,logger:v,createLocalProvider:A}=i,f=P();if(!((s=(t=f==null?void 0:f.models)==null?void 0:t.reasoning)!=null&&s.apiKey))throw new Error("Jivam is not configured. Add your API key in Settings → Models.");const g=f.models.reasoning,j=f.models.multimodal,b=h,k=g.defaultModel??g.model??"",w=b({endpoint:g.endpoint,apiKey:g.apiKey,model:k,type:"reasoning",useHarmonyFormat:g.useHarmonyFormat,...g.reasoningEffortStrategy?{reasoningEffortStrategy:g.reasoningEffortStrategy}:{},...g.defaultMaxTokens?{defaultMaxTokens:g.defaultMaxTokens}:{}});let D;if(j!=null&&j.apiKey)try{const Z=j.defaultModel??"";D=b({endpoint:j.endpoint,apiKey:j.apiKey,model:Z,type:"multimodal"})}catch{console.warn("[JivaRunner] Failed to create multimodal model, continuing without vision")}const L=d;this.orchestrator=new L({reasoningModel:w,multimodalModel:D});const T=f.mcpServers??{},F=S.platform()==="win32"?"C:\\Users":"/Users";T.filesystem||(T.filesystem={command:"npx",args:["-y","@modelcontextprotocol/server-filesystem",F],enabled:!0});const re=a;this.mcpManager=new re,await this.mcpManager.initialize(T);const{path:V}=he(f.userDirective),Y=process.cwd(),oe=c;this.workspace=new oe({workspaceDir:Y,directivePath:V}),await this.workspace.initialize();const K=await A(),X=l;this.conversationManager=new X(K,this.orchestrator);const q=m.dirname(o),Ne=m.dirname(q),Ue=m.join(Ne,"dist","personas","persona-manager.js"),{PersonaManager:Le}=await import(me.pathToFileURL(Ue).href);this.personaManager=new Le,await this.personaManager.initialize(e??void 0);const qe=this.personaManager.getPersonaMCPServers();for(const[Z,We]of Object.entries(qe))try{await this.mcpManager.addServer(Z,We)}catch(Be){console.warn(`[JivaRunner] Failed to add persona MCP server '${Z}':`,Be)}const ze=p;this.agent=new ze({orchestrator:this.orchestrator,mcpManager:this.mcpManager,workspace:this.workspace,conversationManager:this.conversationManager,personaManager:this.personaManager,maxSubtasks:20,maxIterations:this.maxIterations,autoSave:!0,condensingThreshold:30}),this.jivaLogger=v,this.currentPersona=e??null,this.setStatus("ready"),console.log("[JivaRunner] Initialized successfully")}catch(o){const i=o instanceof Error?o.message:String(o);throw console.error("[JivaRunner] Initialization failed:",i),this.setStatus("error",i),o}}makeCompleter(){const e=this.orchestrator;return async(t,s)=>{if(typeof e.chat!="function")return null;try{const i=await e.chat.bind(e)({messages:[{role:"system",content:t},{role:"user",content:s}],reasoningEffort:"low"});return(i==null?void 0:i.content)??null}catch(o){return console.warn("[JivaRunner] makeCompleter: chat() failed:",o),null}}}hookLogger(e){const t=this.jivaLogger;if(!t)return()=>{};const s=(i,a,c)=>{const l=i.toLowerCase();e({timestamp:new Date().toISOString(),level:l==="warn"||l==="error"?l:"info",tag:a,message:c})};if(typeof t.on=="function"){const i=(...a)=>{if(a.length>=3&&typeof a[0]=="string")s(a[0],a[1]??"jiva",a[2]);else if(a.length>=2&&typeof a[0]=="string")s("info","jiva",a[1]);else if(a.length>=1&&typeof a[0]=="object"){const c=a[0];s(String(c.level??"info"),String(c.tag??c.name??"jiva"),String(c.message??c.msg??""))}};try{return t.on("log",i),()=>{typeof t.off=="function"?t.off("log",i):typeof t.removeListener=="function"&&t.removeListener("log",i)}}catch{}}for(const i of["addTransport","addHandler","addSink"]){if(typeof t[i]!="function")continue;const a=i.replace("add","remove"),c={write:l=>{s(String(l.level??"info"),String(l.tag??l.name??"jiva"),String(l.message??l.msg??""))},log:l=>{s(String(l.level??"info"),String(l.tag??l.name??"jiva"),String(l.message??l.msg??""))}};try{return t[i](c),()=>{if(typeof t[a]=="function")try{t[a](c)}catch{}}}catch{}}const o=process.stdout.write.bind(process.stdout);return process.stdout.write=(i,...a)=>{const c=typeof i=="string"?i:Buffer.from(i).toString();for(const l of c.split(`
111
+ `)){const d=Ie(l);if(d){e(d);continue}const p=/(?:tool(?:\s+call)?|calling|executing)[:\s]+([^\s(]+)/i.exec(l.trim());p&&e({timestamp:new Date().toISOString(),level:"info",tag:"jiva",message:`Tool: ${p[1]}`})}return o(i,...a)},()=>{process.stdout.write=o}}async runChat(e,t,s){var l,d,p;const o=s?this.hookLogger(s):null,i=this.agent;let a;try{a=await i.chat(e)}finally{o==null||o()}if(s&&((l=a.toolsUsed)!=null&&l.length))for(const h of a.toolsUsed)s({timestamp:new Date().toISOString(),level:"info",tag:"jiva",message:`Tool: ${h}`});let c=null;try{c=((p=(d=this.conversationManager).getCurrentConversationId)==null?void 0:p.call(d))??null}catch{}if(!c)try{c=await this.agent.saveConversation()}catch{}return c&&(this.currentConversationId=c),{content:a.content,iterations:a.iterations,toolsUsed:a.toolsUsed??[],plan:a.plan?{subtasks:a.plan.subtasks??[],reasoning:a.plan.reasoning}:null,durationMs:Date.now()-t,conversationId:this.currentConversationId??void 0}}async chat(e,t,s,o){var l;if(!this.agent)throw new Error("JivaRunner not initialized. Call initialize() first.");if(this.status==="busy")throw new Error("Agent is already processing a request.");if((s==null?void 0:s.maxIterations)!==void 0&&s.maxIterations!==this.maxIterations){this.maxIterations=s.maxIterations;try{this.agent.maxIterations=this.maxIterations}catch{}}this.setStatus("busy");const i=Date.now();t("planning");const a=setTimeout(()=>t("executing"),2e3),c=setTimeout(()=>t("synthesizing"),3e4);try{let d;if((s==null?void 0:s.deepRun)!==!1){const p=Object.keys(((l=P())==null?void 0:l.mcpServers)??{});d=await Ae(e,this.makeCompleter(),(h,y)=>{if((y==null?void 0:y.maxIterations)!==void 0&&y.maxIterations!==this.maxIterations){this.maxIterations=y.maxIterations;try{this.agent.maxIterations=this.maxIterations}catch{}}return this.runChat(h,i,o)},h=>o==null?void 0:o(h),this.maxIterations,(s==null?void 0:s.conversationHistory)||void 0,p)}else d=await this.runChat(e,i,o);return clearTimeout(a),clearTimeout(c),t("done"),this.setStatus("ready"),d}catch(d){throw clearTimeout(a),clearTimeout(c),this.setStatus("ready"),d}}async loadConversation(e){if(!this.agent)throw new Error("JivaRunner not initialized. Call initialize() first.");await this.agent.loadConversation(e),this.currentConversationId=e,console.log(`[JivaRunner] Loaded conversation: ${e}`)}async switchPersona(e){this.agent&&await this.cleanup(),await this.initialize(e)}resetConversation(){this.agent&&this.agent.resetConversation(),this.currentConversationId=null}getMCPTools(){var e,t;if(!this.mcpManager)return{};try{const s=((t=(e=this.mcpManager).getAllTools)==null?void 0:t.call(e))??[],o={};for(const i of s){const a=i.name.split("__"),c=a.length>1?a[0]:"unknown",l=a.length>1?a.slice(1).join("__"):i.name;o[c]||(o[c]=[]),o[c].push({name:l,description:i.description??""})}return o}catch{return{}}}async addMCPServer(e,t){if(!this.mcpManager)throw new Error("MCP manager not initialized");await this.mcpManager.addServer(e,t)}async removeMCPServer(e){if(!this.mcpManager)throw new Error("MCP manager not initialized");const t=this.mcpManager;t.removeServer?await t.removeServer(e):t.disableServer&&await t.disableServer(e)}getMCPServerStatus(){var e,t;if(!this.mcpManager)return[];try{return(((t=(e=this.mcpManager).getServerStatus)==null?void 0:t.call(e))??[]).map(o=>({...o,error:o.error??o.lastError}))}catch{return[]}}async reconnectMCPServer(e){var c,l,d;if(!this.mcpManager)throw new Error("MCP manager not initialized");const t=this.mcpManager;if(typeof t.reconnectServer=="function"){await t.reconnectServer(e);return}if(!this.getMCPServerStatus().find(p=>p.name===e))throw new Error(`MCP server "${e}" not found`);const i=((d=(l=(c=this.mcpManager).getServerStatus)==null?void 0:l.call(c))==null?void 0:d.find(p=>p.name===e))??{};await this.removeMCPServer(e);const a=i.url!=null?{type:"http",url:i.url,env:i.env,enabled:!0}:{type:"stdio",command:i.command,args:i.args,env:i.env,enabled:!0};await this.addMCPServer(e,a)}async toggleMCPServer(e,t){if(!this.mcpManager)throw new Error("MCP manager not initialized");const s=this.mcpManager;t&&s.enableServer?await s.enableServer(e):!t&&s.disableServer&&await s.disableServer(e)}async describeImage(e){var i;if(!this.orchestrator)throw new Error("JivaRunner not initialized. Call initialize() first.");const t=P();if(!((i=t==null?void 0:t.models)!=null&&i.multimodal))throw new Error("No multimodal (vision) model is configured. Enable it in Settings → Models.");return(await this.orchestrator.chat({messages:[{role:"user",content:[{type:"image_url",image_url:{url:e}},{type:"text",text:"Describe this image in detail, including all visible content, text, charts, diagrams, and any notable elements."}]}]})).content}async cleanup(){try{this.agent&&(await this.agent.cleanup(),this.agent=null),this.mcpManager&&(await this.mcpManager.cleanup(),this.mcpManager=null)}catch(e){console.warn("[JivaRunner] Cleanup error:",e)}this.orchestrator=null,this.workspace=null,this.conversationManager=null,this.personaManager=null,this.currentConversationId=null,this.setStatus("stopped")}stop(){this.agent&&this.agent.stop()}setStatus(e,t){this.status=e,this.emit("status-changed",e,{error:t})}}const ee="https://jiva-hdjcuspt2a-uc.a.run.app";class vt{constructor(){x(this,"userId",null);x(this,"sessionId",null);x(this,"_active",!1);x(this,"_abortController",null);x(this,"_readyPromise",null);x(this,"_readyResolve",null);x(this,"_readyReject",null)}startInit(){this._active||this._readyPromise||(this._readyPromise=new Promise((n,e)=>{this._readyResolve=n,this._readyReject=e}))}configure(n,e){var t;this.userId=n,this.sessionId=e,this._active=!0,(t=this._readyResolve)==null||t.call(this),this._readyResolve=null,this._readyReject=null}waitUntilReady(n){return this._active?Promise.resolve():this._readyPromise?Promise.race([this._readyPromise,new Promise((e,t)=>setTimeout(()=>t(new Error(`Cloud runner not ready after ${n}ms`)),n))]):Promise.reject(new Error("Cloud runner init not started"))}isActive(){return this._active}isInitializing(){return!this._active&&this._readyPromise!==null}deactivate(){var n;this._active=!1,this.userId=null,this.sessionId=null,(n=this._readyReject)==null||n.call(this,new Error("Cloud session deactivated")),this._readyPromise=null,this._readyResolve=null,this._readyReject=null}stop(){var n;(n=this._abortController)==null||n.abort()}get headers(){return{"Content-Type":"application/json","x-tenant-id":this.userId??"dev-tenant","x-session-id":this.sessionId??"default-session"}}async chat(n,e,t,s){if(!this._active)throw new Error("CloudRunner not configured");const o=Date.now();e("planning"),this._abortController=new AbortController;const{signal:i}=this._abortController;try{return{...await this._streamChat(n,e,s,i),durationMs:Date.now()-o}}catch(a){return a.name==="AbortError"?{content:"",iterations:0,toolsUsed:[],plan:null,durationMs:Date.now()-o}:(console.warn("[CloudRunner] SSE failed, falling back to non-streaming:",a),{...await this._nonStreamChat(n,e,i),durationMs:Date.now()-o})}finally{this._abortController=null,e("done")}}async _streamChat(n,e,t,s){const o=await fetch(`${ee}/api/chat/stream`,{method:"POST",headers:{...this.headers,Accept:"text/event-stream"},body:JSON.stringify({message:n}),signal:s});if(!o.ok||!o.body)throw new Error(`SSE request failed: ${o.status}`);const i=o.body.getReader(),a=new TextDecoder;let c="",l="",d=0;const p=[];let h=null,y=null;e:for(;;){const{done:v,value:A}=await i.read();if(v)break;c+=a.decode(A,{stream:!0});const f=c.split(`
112
+ `);c=f.pop()??"";for(const g of f){if(g.startsWith("event: ")){y=g.slice(7).trim();continue}if(!g.startsWith("data: "))continue;const j=g.slice(6).trim();if(!j||j==="[DONE]")continue;let b;try{b=JSON.parse(j)}catch{continue}const k=y??b.type;if(y=null,k==="status"){const w=b.message;w&&(e("executing"),t==null||t({timestamp:new Date().toISOString(),level:"info",tag:"cloud",message:`Tool: ${w}`}))}else if(k==="response")l=b.content??b.response??"",d=b.iterations??0,Array.isArray(b.toolsUsed)&&p.push(...b.toolsUsed),b.plan&&(h=b.plan);else{if(k==="error")throw new Error(b.message??"Stream error");if(k==="done")break e}}}return{content:l,iterations:d,toolsUsed:p,plan:h}}async _nonStreamChat(n,e,t){e("executing");const s=await fetch(`${ee}/api/chat`,{method:"POST",headers:this.headers,body:JSON.stringify({message:n}),signal:t});if(!s.ok){const i=await s.text();throw new Error(`Cloud chat failed (${s.status}): ${i}`)}const o=await s.json();return{content:o.response??"",iterations:o.iterations??0,toolsUsed:Array.isArray(o.toolsUsed)?o.toolsUsed:[],plan:o.plan??null}}async resetConversation(){if(this._active)try{await fetch(`${ee}/api/chat/history`,{method:"DELETE",headers:this.headers})}catch(n){console.error("[CloudRunner] resetConversation failed:",n)}}async stopMessage(){try{await fetch(`${ee}/api/chat/stop`,{method:"POST",headers:this.headers})}catch{}this.stop()}}const Pe=E.Router();Pe.get("/check",(r,n)=>{var p;let e=!1,t;try{$.execSync("npm --version",{timeout:3e3}),e=!0;try{t=$.execSync("node --version",{timeout:3e3}).toString().trim().replace(/^v/,"")}catch{}}catch{}let s=!1,o;if(e){const h=[];try{const y=$.execSync("npm root -g",{timeout:5e3}).toString().trim();h.push(m.join(y,"jiva-core","package.json"))}catch{}h.push(m.join(S.homedir(),".npm-global","lib","node_modules","jiva-core","package.json")),process.platform==="win32"&&(h.push(m.join(process.env.APPDATA??"","npm","node_modules","jiva-core","package.json")),h.push(m.join(process.env.LOCALAPPDATA??"","npm","node_modules","jiva-core","package.json")));for(const y of h)if(u.existsSync(y))try{o=JSON.parse(u.readFileSync(y,"utf-8")).version,s=!0;break}catch{}}const i=[N(),m.join(S.homedir(),".jiva","config.json")];let a=!1,c="";for(const h of i)if(u.existsSync(h))try{const y=JSON.parse(u.readFileSync(h,"utf-8")),v=((p=y==null?void 0:y.models)==null?void 0:p.reasoning)??{};if(((v==null?void 0:v.apiKey)??(y==null?void 0:y.apiKey)??"").length>0){a=!0,c=h;break}}catch{}let l=!1,d;try{const h=m.join(__dirname,"..","..","package.json");if(d=JSON.parse(u.readFileSync(h,"utf-8")).jivaCompatibleVersion,d&&o){const[v,A]=d.split(".").map(Number),[f,g]=o.split(".").map(Number);(v!==f||A!==g)&&(l=!0)}}catch{}n.json({nodejs:{ok:e,version:t},jivaCore:{ok:s,version:o},config:{ok:a,path:c||i[0]},platform:process.platform,jivaVersionMismatch:l,requiredJivaVersion:d})});const H=E.Router(),St={sarvam:{endpoint:"https://api.sarvam.ai/v1/chat/completions",defaultModel:"sarvam-105b",useHarmonyFormat:!1,reasoningEffortStrategy:"api_param",defaultMaxTokens:8192,multimodal:null},krutrim:{endpoint:"https://cloud.olakrutrim.com/v1/chat/completions",defaultModel:"gpt-oss-120b",useHarmonyFormat:!0,reasoningEffortStrategy:"system_prompt",multimodal:{defaultModel:"Llama-4-Maverick-17B-128E-Instruct"}},groq:{endpoint:"https://api.groq.com/openai/v1/chat/completions",defaultModel:"openai/gpt-oss-120b",useHarmonyFormat:!1,reasoningEffortStrategy:"api_param",multimodal:{defaultModel:"meta-llama/llama-4-maverick-17b-128e-instruct"}},"openai-compatible":{endpoint:"",defaultModel:"",useHarmonyFormat:!1,reasoningEffortStrategy:"both",multimodal:null}};H.get("/",(r,n)=>{n.json(P())});H.post("/",(r,n)=>{const e=R(r.body);n.json(e)});H.get("/path",(r,n)=>{n.json(N())});H.post("/setup-provider",(r,n)=>{const{provider:e,apiKey:t,customEndpoint:s,customModel:o}=r.body;try{const i=St[e];if(!i)return n.json({success:!1,error:`Unknown provider: ${e}`});const a=e==="openai-compatible"?s??"":i.endpoint,c=e==="openai-compatible"?o??"":i.defaultModel,d=P()??{models:{reasoning:null}};if(d.models={...d.models,reasoning:{name:"reasoning",type:"reasoning",provider:e,endpoint:a,apiKey:t,defaultModel:c,useHarmonyFormat:i.useHarmonyFormat,reasoningEffortStrategy:i.reasoningEffortStrategy,...i.defaultMaxTokens?{defaultMaxTokens:i.defaultMaxTokens}:{}},multimodal:i.multimodal?{name:"multimodal",type:"multimodal",endpoint:a,apiKey:t,defaultModel:i.multimodal.defaultModel}:void 0},!d.mcpServers){const h=process.platform==="win32"?"C:\\Users":`${S.homedir()}`;d.mcpServers={filesystem:{command:"npx",args:["-y","@modelcontextprotocol/server-filesystem",h],enabled:!0},"mcp-shell-server":{command:"npx",args:["-y","@mkusaka/mcp-shell-server"],enabled:!0}}}const p=R(d);return n.json({success:p,error:p?void 0:"Failed to write config"})}catch(i){return n.json({success:!1,error:i instanceof Error?i.message:String(i)})}});const ge=E.Router();ge.get("/",(r,n)=>{const e=m.join(S.homedir(),".jiva","conversations");try{if(!u.existsSync(e))return n.json([]);const t=u.readdirSync(e).filter(s=>s.endsWith(".json")).map(s=>{var a,c,l;const o=m.join(e,s),i=u.statSync(o);try{const d=JSON.parse(u.readFileSync(o,"utf-8"));let p=((a=d.metadata)==null?void 0:a.title)??d.summary??d.title??"";if(!p&&Array.isArray(d.messages)){const h=d.messages.find(y=>y.role==="user");if(h!=null&&h.content){const y=typeof h.content=="string"?h.content:Array.isArray(h.content)?h.content.filter(v=>v.type==="text").map(v=>v.text??"").join(""):"";p=y.slice(0,60).replace(/\n/g," "),y.length>60&&(p+="...")}}return{id:s.replace(".json",""),summary:p||"Untitled",messageCount:((c=d.messages)==null?void 0:c.length)??0,lastModified:i.mtimeMs,type:((l=d.metadata)==null?void 0:l.type)??"chat"}}catch{return null}}).filter(Boolean).sort((s,o)=>o.lastModified-s.lastModified);return n.json(t)}catch{return n.json([])}});ge.get("/:id",(r,n)=>{const e=m.join(S.homedir(),".jiva","conversations",`${r.params.id}.json`);try{return u.existsSync(e)?n.json(JSON.parse(u.readFileSync(e,"utf-8"))):n.json(null)}catch{return n.json(null)}});const U=E.Router();U.get("/is-repo",(r,n)=>{const e=r.query.dir;try{$.execFileSync("git",["rev-parse","--is-inside-work-tree"],{cwd:e,timeout:3e3}),n.json(!0)}catch{n.json(!1)}});U.get("/status",(r,n)=>{const e=r.query.dir;try{const t=$.execFileSync("git",["status","--porcelain"],{cwd:e,timeout:5e3}).toString();n.json(t.split(`
113
+ `).filter(Boolean).map(s=>({status:s.slice(0,2).trim(),file:s.slice(3).trim()})))}catch{n.json([])}});U.get("/diff-file",(r,n)=>{const{dir:e,file:t,status:s}=r.query;try{if(s==="??"){const o=m.join(e,t);try{const a=u.readFileSync(o,"utf-8").split(`
114
+ `);return a[a.length-1]===""&&a.pop(),n.json(`--- /dev/null
115
+ +++ b/${t}
116
+ @@ -0,0 +1,${a.length} @@
117
+ ${a.map(c=>`+${c}`).join(`
118
+ `)}`)}catch{return n.json(null)}}if(s==="A")try{const o=$.execFileSync("git",["diff","--cached","--",t],{cwd:e,timeout:5e3}).toString();if(o.trim())return n.json(o)}catch{}try{const o=$.execFileSync("git",["diff","HEAD","--",t],{cwd:e,timeout:5e3}).toString();if(o.trim())return n.json(o)}catch{}try{const o=$.execFileSync("git",["diff","--cached","--",t],{cwd:e,timeout:5e3}).toString();if(o.trim())return n.json(o)}catch{}try{const o=$.execFileSync("git",["diff","--",t],{cwd:e,timeout:5e3}).toString();if(o.trim())return n.json(o)}catch{}return n.json(null)}catch{return n.json(null)}});U.post("/init-repo",(r,n)=>{const{dir:e}=r.body;try{$.execFileSync("git",["init"],{cwd:e,timeout:1e4}),n.json({success:!0})}catch(t){n.json({success:!1,error:t instanceof Error?t.message:String(t)})}});U.get("/branch-info",(r,n)=>{const e=r.query.dir;try{const t=$.execFileSync("git",["rev-parse","--abbrev-ref","HEAD"],{cwd:e,timeout:3e3}).toString().trim();let s=0,o=0;try{const i=$.execFileSync("git",["rev-parse","--abbrev-ref","--symbolic-full-name","@{u}"],{cwd:e,timeout:3e3}).toString().trim();if(i){const a=$.execFileSync("git",["rev-list","--left-right","--count",`${i}...HEAD`],{cwd:e,timeout:3e3}).toString().trim().split(" ");o=parseInt(a[0])||0,s=parseInt(a[1])||0}}catch{}n.json({branch:t,ahead:s,behind:o})}catch{n.json(null)}});const ye=E.Router();ye.get("/",(r,n)=>{const e=P();n.json((e==null?void 0:e.userDirective)??"")});ye.post("/",(r,n)=>{const{content:e}=r.body,t=P()??{models:{reasoning:null}};R({...t,userDirective:e}),he(e||void 0),n.json({success:!0})});const _=E.Router();_.get("/dir",(r,n)=>{const e=P();n.json((e==null?void 0:e.workspaceDir)??S.homedir())});_.post("/dir",(r,n)=>{const{dir:e}=r.body;try{const t=P()??{models:{reasoning:null}};R({...t,workspaceDir:e}),n.json({success:!0})}catch(t){n.json({success:!1,error:t instanceof Error?t.message:String(t)})}});_.post("/pick-dir",async(r,n)=>{try{let e=null;if(process.platform==="darwin"){const t=$.execSync(`osascript -e 'POSIX path of (choose folder with prompt "Select Workspace Directory")'`,{timeout:6e4}).toString().trim();t&&(e=t.replace(/\/$/,""))}else if(process.platform==="win32"){const t=['[System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms") | Out-Null',"$f = New-Object System.Windows.Forms.FolderBrowserDialog",'$f.Description = "Select Workspace Directory"','if ($f.ShowDialog() -eq "OK") { $f.SelectedPath }'].join("; "),s=$.execSync(`powershell -Command "${t}"`,{timeout:6e4}).toString().trim();s&&(e=s)}else try{const t=$.execSync('zenity --file-selection --directory --title="Select Workspace Directory"',{timeout:6e4}).toString().trim();t&&(e=t)}catch{try{const t=$.execSync('kdialog --getexistingdirectory "Select Workspace Directory"',{timeout:6e4}).toString().trim();t&&(e=t)}catch{}}n.json(e)}catch{n.json(null)}});_.get("/files",(r,n)=>{const e=r.query.path;try{const t=S.homedir(),s=m.resolve(e),o=m.resolve(t);if(!s.startsWith(o)&&s!==o)return n.json([]);if(!u.existsSync(s))return n.json([]);const i=u.readdirSync(s,{withFileTypes:!0});return n.json(i.filter(a=>!a.name.startsWith(".")).map(a=>{const c=m.join(s,a.name),l=u.statSync(c);return{name:a.name,path:c,isDirectory:a.isDirectory(),size:l.size,modified:l.mtimeMs}}))}catch{return n.json([])}});_.get("/file",(r,n)=>{const e=r.query.path;try{const t=S.homedir(),s=m.resolve(e);return!s.startsWith(m.resolve(t))||!u.existsSync(s)?n.json(null):u.statSync(s).size>512*1024?n.json("[File too large to preview — open in an external editor]"):n.json(u.readFileSync(s,"utf-8"))}catch{return n.json(null)}});_.post("/open-external",(r,n)=>{const{filePath:e}=r.body;try{const t=process.platform==="darwin"?"open":process.platform==="win32"?"explorer":"xdg-open";$.execSync(`${t} "${e}"`,{timeout:5e3})}catch{}n.json({})});function kt(r,n){const e=E.Router();return e.post("/start",async(t,s)=>{try{(r.getStatus()==="stopped"||r.getStatus()==="error")&&await r.initialize(),s.json({success:!0,status:r.getStatus()})}catch(o){s.json({success:!1,error:o instanceof Error?o.message:String(o)})}}),e.post("/stop",async(t,s)=>{try{await r.cleanup(),s.json({success:!0})}catch(o){s.json({success:!1,error:o instanceof Error?o.message:String(o)})}}),e.post("/restart",async(t,s)=>{try{await r.cleanup(),await r.initialize(),s.json({success:!0,status:r.getStatus()})}catch(o){s.json({success:!1,error:o instanceof Error?o.message:String(o)})}}),e.get("/status",(t,s)=>{const o=r.getStatus();s.json({status:o==="ready"||o==="busy"?"running":o,port:0})}),e.post("/send-message",async(t,s)=>{const{prompt:o,opts:i,isCloud:a}=t.body;try{if(a){n.isActive()||await n.waitUntilReady(3e4);const l=await n.chat(o,d=>{O("jiva:phase-update",{phase:d})},i,d=>{O("jiva:jiva-log",{event:d})});return s.json({success:!0,result:l,conversationId:l.conversationId})}(r.getStatus()==="stopped"||r.getStatus()==="error")&&await r.initialize();const c=await r.chat(o,l=>{O("jiva:phase-update",{phase:l})},i,l=>{O("jiva:jiva-log",{event:l})});return s.json({success:!0,result:c,conversationId:c.conversationId})}catch(c){return s.json({success:!1,error:c instanceof Error?c.message:String(c)})}}),e.post("/stop-message",(t,s)=>{r.stop(),s.json({success:!0})}),e.post("/reset-conversation",(t,s)=>{r.resetConversation(),s.json({success:!0})}),e.post("/load-conversation",async(t,s)=>{const{id:o}=t.body;try{(r.getStatus()==="stopped"||r.getStatus()==="error")&&await r.initialize(),await r.loadConversation(o),s.json({success:!0})}catch(i){s.json({success:!1,error:i instanceof Error?i.message:String(i)})}}),r.on("status-changed",(t,s)=>{O("jiva:server:status-changed",{status:t==="ready"||t==="busy"?"running":t,data:s})}),e}const de=m.join(S.homedir(),".jiva","personas");function jt(r,n){return r==="chat"||n.includes("chat")?"MessageSquare":r==="research"||n.includes("research")?"Search":r==="developer"||r==="code-reviewer"||n.includes("code")?"Code2":r==="engineering-manager"||n.includes("management")?"Layers":r==="tester"||n.includes("testing")?"FlaskConical":r==="data-analyst"||n.includes("data")?"BarChart3":"Bot"}function bt(){const r=[];if(!u.existsSync(de))return r;try{const n=u.readdirSync(de,{withFileTypes:!0});for(const e of n){if(!e.isDirectory()||e.name==="skills")continue;const t=m.join(de,e.name),s=m.join(t,".jiva-plugin","plugin.json");let o={};if(u.existsSync(s))try{const l=u.readFileSync(s,"utf-8");o=JSON.parse(l)}catch{}const i=e.name,a=o.tags??[],c=["chat","research"];r.push({name:i,displayName:(o.name??i).replace(/-/g," ").replace(/\b\w/g,l=>l.toUpperCase()),description:o.description??`${i} persona`,tags:a,icon:jt(i,a),isBuiltIn:c.includes(i),dirPath:t})}}catch(n){console.error("[PersonaManager] Failed to list personas:",n)}return r.sort((n,e)=>n.isBuiltIn&&!e.isBuiltIn?-1:!n.isBuiltIn&&e.isBuiltIn?1:n.name.localeCompare(e.name))}function xt(r){const{execSync:n}=require("child_process");try{return n(`jiva persona activate ${r}`,{timeout:1e4,stdio:"ignore"}),!0}catch{const e=m.join(S.homedir(),".jiva","active-persona.txt");try{return u.writeFileSync(e,r,"utf-8"),!0}catch{return!1}}}function Ct(){try{const r=rt();if(u.existsSync(r)){const e=JSON.parse(u.readFileSync(r,"utf-8"));if(e.activePersona)return e.activePersona}const n=m.join(S.homedir(),".jiva","active-persona.txt");if(u.existsSync(n))return u.readFileSync(n,"utf-8").trim()}catch{}return null}function $t(r){const n=E.Router();return n.get("/",(e,t)=>{t.json(bt())}),n.post("/activate",async(e,t)=>{const{name:s}=e.body,o=xt(s);if(o)try{await r.switchPersona(s)}catch(i){console.error("[Personas] Failed to switch persona:",i)}t.json({success:o})}),n.get("/active",(e,t)=>{t.json(Ct())}),n}function Mt(r){const n=E.Router();return n.get("/status",(e,t)=>{try{const s=r.getMCPServerStatus(),o=P(),i=(o==null?void 0:o.mcpServers)??{},a=new Map(s.map(l=>[l.name,l])),c=Object.entries(i).map(([l,d])=>{const p=a.get(l);return{name:l,enabled:d.enabled??!0,connected:(p==null?void 0:p.connected)??!1,toolCount:(p==null?void 0:p.toolCount)??0,command:d.command??"",args:d.args??[],env:d.env??{},url:d.url,type:d.command?"stdio":"http",error:p==null?void 0:p.error}});for(const l of s)i[l.name]||c.push({name:l.name,enabled:l.enabled,connected:l.connected,toolCount:l.toolCount,command:"",args:[],env:{},url:void 0,type:"stdio",error:void 0});t.json(c)}catch{t.json([])}}),n.get("/tools",(e,t)=>{try{t.json(r.getMCPTools())}catch{t.json({})}}),n.post("/add",async(e,t)=>{const{name:s,config:o}=e.body;try{const i=P();if(!i)return t.json({success:!1,error:"Config not found"});const a={enabled:o.enabled??!0};return o.type==="stdio"?(a.command=o.command??"",a.args=o.args??[],o.env&&Object.keys(o.env).length>0&&(a.env=o.env)):(a.url=o.url??"",o.env&&Object.keys(o.env).length>0&&(a.env=o.env)),i.mcpServers||(i.mcpServers={}),i.mcpServers[s]=a,R(i),(r.getStatus()==="ready"||r.getStatus()==="busy")&&await r.addMCPServer(s,a),t.json({success:!0})}catch(i){return t.json({success:!1,error:i instanceof Error?i.message:String(i)})}}),n.post("/remove",async(e,t)=>{const{name:s}=e.body;try{const o=P();o!=null&&o.mcpServers&&(delete o.mcpServers[s],R(o)),(r.getStatus()==="ready"||r.getStatus()==="busy")&&await r.removeMCPServer(s),t.json({success:!0})}catch(o){t.json({success:!1,error:o instanceof Error?o.message:String(o)})}}),n.post("/toggle",async(e,t)=>{var i;const{name:s,enabled:o}=e.body;try{const a=P();(i=a==null?void 0:a.mcpServers)!=null&&i[s]&&(a.mcpServers[s].enabled=o,R(a)),(r.getStatus()==="ready"||r.getStatus()==="busy")&&await r.toggleMCPServer(s,o),t.json({success:!0})}catch(a){t.json({success:!1,error:a instanceof Error?a.message:String(a)})}}),n.post("/reconnect",async(e,t)=>{const{name:s}=e.body;try{await r.reconnectMCPServer(s),t.json({success:!0})}catch(o){t.json({success:!1,error:o instanceof Error?o.message:String(o)})}}),n}const se=m.join(S.homedir(),".jiva","jivam-mcp-selections.json");function be(){try{if(u.existsSync(se))return JSON.parse(u.readFileSync(se,"utf-8"))}catch{}return{}}function At(r){const n=E.Router();return n.post("/send-message",async(e,t)=>{const{prompt:s,opts:o}=e.body;try{if(!r.isReady()){const a=P(),c=(a==null?void 0:a.workspaceDir)??S.homedir();await r.initialize(c)}const i=await r.chat(s,a=>{O("jiva:code-log",{event:a})},o);t.json({success:!0,...i})}catch(i){t.json({success:!1,error:i instanceof Error?i.message:String(i)})}}),n.post("/stop-message",(e,t)=>{r.stop(),t.json({success:!0})}),n.post("/reset-session",async(e,t)=>{try{await r.cleanup(),t.json({success:!0})}catch(s){t.json({success:!1,error:s instanceof Error?s.message:String(s)})}}),n.post("/init",async(e,t)=>{const{dir:s,mcpServers:o,opts:i}=e.body;try{await r.initialize(s,o,i),t.json({success:!0})}catch(a){t.json({success:!1,error:a instanceof Error?a.message:String(a)})}}),n.get("/mcp-for-code",(e,t)=>{try{const s=P(),o=(s==null?void 0:s.mcpServers)??{};t.json(Object.entries(o).map(([i,a])=>({name:i,enabled:a.enabled??!0,codeMode:a.codeMode===!0,command:a.command??"",url:a.url})))}catch{t.json([])}}),n.get("/conversation-id",(e,t)=>{t.json(r.getConversationId())}),n.get("/mcp-selection/:convId",(e,t)=>{t.json(be()[e.params.convId]??[])}),n.post("/mcp-selection",(e,t)=>{const{convId:s,servers:o}=e.body;try{const i=be();i[s]=o,u.mkdirSync(m.dirname(se),{recursive:!0}),u.writeFileSync(se,JSON.stringify(i,null,2)),t.json({success:!0})}catch(i){t.json({success:!1,error:i instanceof Error?i.message:String(i)})}}),n}const It=new Set(["txt","md","markdown","rst","log","js","jsx","ts","tsx","mjs","cjs","py","rb","go","rs","java","kt","swift","c","cpp","cc","h","hpp","cs","css","scss","sass","less","html","htm","xml","svg","xhtml","json","jsonc","yaml","yml","toml","ini","cfg","conf","sh","bash","zsh","fish","ps1","bat","cmd","sql","graphql","gql","proto","env","editorconfig","gitignore","gitattributes","dockerfile","makefile","cmake","gradle","r","jl","scala","clj","ex","exs","erl","hs","lua","pl","vue","svelte","astro","lock","mod","sum"]),Ee={png:"image/png",jpg:"image/jpeg",jpeg:"image/jpeg",gif:"image/gif",webp:"image/webp",bmp:"image/bmp"},Pt={js:"javascript",jsx:"jsx",ts:"typescript",tsx:"tsx",py:"python",rb:"ruby",go:"go",rs:"rust",java:"java",kt:"kotlin",swift:"swift",cs:"csharp",c:"c",cpp:"cpp",h:"c",hpp:"cpp",css:"css",scss:"scss",sass:"sass",less:"less",html:"html",htm:"html",xml:"xml",svg:"xml",json:"json",jsonc:"json",yaml:"yaml",yml:"yaml",toml:"toml",sh:"bash",bash:"bash",zsh:"bash",fish:"fish",ps1:"powershell",sql:"sql",graphql:"graphql",gql:"graphql",proto:"protobuf",md:"markdown",markdown:"markdown",rst:"rst",r:"r",jl:"julia",scala:"scala",lua:"lua",vue:"vue",svelte:"svelte"};function Et(r){const n=r.toLowerCase().replace(/^\./,"");return It.has(n)?"text":n in Ee?"image":n==="pdf"?"pdf":n==="docx"?"docx":"unsupported"}function xe(r){const n=m.basename(r),e=m.extname(r).toLowerCase().replace(/^\./,""),t=Et(e);try{switch(t){case"text":return Dt(r,n,e);case"pdf":return Tt(r,n);case"docx":return Rt(r,n);case"image":return Jt(r,n,e);default:return{name:n,category:"unsupported",markdown:"",error:`File type .${e} is not supported`}}}catch(s){return{name:n,category:t,markdown:"",error:s instanceof Error?s.message:"Failed to read file"}}}function Dt(r,n,e){if(u.statSync(r).size>2*1024*1024)return{name:n,category:"text",markdown:"",error:"File is too large (max 2 MB for text files)"};const s=u.readFileSync(r,"utf-8"),i=`\`\`\`${Pt[e]??e}
119
+ ${s}
120
+ \`\`\``;return{name:n,category:"text",markdown:i}}function Tt(r,n){if(u.statSync(r).size>10*1024*1024)return{name:n,category:"pdf",markdown:"",error:"PDF is too large (max 10 MB)"};const t=u.readFileSync(r),s=Ft(t);if(!s.trim())return{name:n,category:"pdf",markdown:"",error:"Could not extract text from PDF (may be a scanned/image-only PDF)"};const o=`**[PDF: ${n}]**
121
+
122
+ ${s}`;return{name:n,category:"pdf",markdown:o}}function Ft(r){const n=r.toString("latin1"),e=[],t=/<<[^>]*\/Filter\s*\/FlateDecode[^>]*>>\s*stream\r?\n([\s\S]*?)\r?\nendstream/g;let s;for(;(s=t.exec(n))!==null;)try{const i=Buffer.from(s[1],"latin1"),a=pe.inflateSync(i).toString("latin1");e.push(...Ce(a))}catch{}const o=/BT([\s\S]*?)ET/g;for(;(s=o.exec(n))!==null;)e.push(...Ce(s[1]));return[...new Set(e)].join(" ").replace(/\s+/g," ").trim()}function Ce(r){const n=[],e=/BT([\s\S]*?)ET/g;let t;for(;(t=e.exec(r))!==null;){const s=t[1],o=/\(([^)\\]*(?:\\.[^)\\]*)*)\)/g;let i;for(;(i=o.exec(s))!==null;){const l=i[1].replace(/\\n/g,`
123
+ `).replace(/\\r/g,"\r").replace(/\\t/g," ").replace(/\\\(/g,"(").replace(/\\\)/g,")").replace(/\\\\/g,"\\").replace(/[^\x20-\x7E\n\r\t]/g,"").trim();l.length>0&&n.push(l)}const a=/<([0-9A-Fa-f\s]+)>/g;for(;(i=a.exec(s))!==null;){const c=i[1].replace(/\s/g,"");if(c.length%2!==0)continue;let l="";for(let d=0;d<c.length;d+=2){const p=parseInt(c.slice(d,d+2),16);p>=32&&p<=126&&(l+=String.fromCharCode(p))}l.trim().length>0&&n.push(l.trim())}}return n}function Rt(r,n){if(u.statSync(r).size>10*1024*1024)return{name:n,category:"docx",markdown:"",error:"DOCX is too large (max 10 MB)"};const t=u.readFileSync(r),s=_t(t,"word/document.xml");if(!s)return{name:n,category:"docx",markdown:"",error:"Could not extract content from DOCX file"};const o=Ot(s.toString("utf-8"));if(!o.trim())return{name:n,category:"docx",markdown:"",error:"DOCX appears to be empty"};const i=`**[DOCX: ${n}]**
124
+
125
+ ${o}`;return{name:n,category:"docx",markdown:i}}function _t(r,n){let e=0;for(;e<r.length-30;){if(r.readUInt32LE(e)!==67324752){e++;continue}const t=r.readUInt16LE(e+8),s=r.readUInt32LE(e+18),o=r.readUInt32LE(e+22),i=r.readUInt16LE(e+26),a=r.readUInt16LE(e+28),c=r.slice(e+30,e+30+i).toString("utf-8"),l=e+30+i+a,d=l+s;if(c===n){const p=r.slice(l,d);if(t===0)return p;if(t===8)try{return pe.inflateRawSync(p)}catch{try{return pe.inflateSync(p)}catch{return null}}return null}s===0&&o===0?e=l:e=d}return null}function Ot(r){const n=[],e=/<w:p[ >]([\s\S]*?)<\/w:p>/g;let t;for(;(t=e.exec(r))!==null;){const s=[],o=/<w:t[^>]*>([^<]*)<\/w:t>/g;let i;for(;(i=o.exec(t[1]))!==null;)s.push(i[1]);const a=s.join("").trim();a&&n.push(a)}return n.join(`
126
+
127
+ `)}function Jt(r,n,e){if(u.statSync(r).size>20*1024*1024)return{name:n,category:"image",markdown:"",error:"Image is too large (max 20 MB)"};const s=Ee[e.toLowerCase()]??"image/png";return{name:n,category:"image",markdown:r,mimeType:s}}function Nt(r){const n=E.Router();return n.post("/convert",(e,t)=>{const{filePath:s}=e.body,o=S.homedir();if(!m.resolve(s).startsWith(m.resolve(o)))return t.json({name:m.basename(s),category:"unsupported",markdown:"",error:"Access denied"});const a=xe(s);if(a.category==="image"&&!a.error)try{const c=(()=>{try{return JSON.parse(u.readFileSync(m.join(S.homedir(),"Library","Preferences","jiva-nodejs","config.json"),"utf-8"))}catch{return null}})(),l=(c==null?void 0:c.workspaceDir)??o,d=m.join(l,".jiva","uploads");u.mkdirSync(d,{recursive:!0});const p=m.join(d,m.basename(s));u.copyFileSync(s,p),a.markdown=p}catch(c){a.error=`Failed to save image: ${c instanceof Error?c.message:String(c)}`}return t.json(a)}),n.post("/upload-and-convert",(e,t)=>{const{files:s}=e.body,o=S.homedir(),i=m.join(S.tmpdir(),"jivam-uploads");u.mkdirSync(i,{recursive:!0});const a=s.map(c=>{const l=m.join(i,c.name);try{u.writeFileSync(l,Buffer.from(c.data,"base64"));const d=xe(l);if(d.category==="image"&&!d.error)try{const p=(()=>{try{return JSON.parse(u.readFileSync(m.join(o,"Library","Preferences","jiva-nodejs","config.json"),"utf-8"))}catch{return null}})(),h=(p==null?void 0:p.workspaceDir)??o,y=m.join(h,".jiva","uploads");u.mkdirSync(y,{recursive:!0});const v=m.join(y,c.name);u.copyFileSync(l,v),d.markdown=v}catch{}return d}catch(d){return{name:c.name,category:"unsupported",markdown:"",error:String(d)}}finally{try{u.unlinkSync(l)}catch{}}});t.json(a)}),n.post("/describe-image",async(e,t)=>{const{dataUri:s}=e.body;try{const o=await r.describeImage(s);t.json({success:!0,description:o})}catch(o){t.json({success:!1,error:o instanceof Error?o.message:String(o)})}}),n}const Ut="https://hcomegrnonxmjupvvyus.supabase.co",Lt="eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6Imhjb21lZ3Jub254bWp1cHZ2eXVzIiwicm9sZSI6ImFub24iLCJpYXQiOjE3NzgxNTQwMjcsImV4cCI6MjA5MzczMDAyN30.sBBOTrPsdCZk75HDEzJaIv5Mz-bE3HTuJQ-1LcJ45nk",qt="https://jiva-hdjcuspt2a-uc.a.run.app";async function De(r,n){const e=await fetch(`${Ut}${r}`,{method:"POST",headers:{"Content-Type":"application/json",apikey:Lt},body:JSON.stringify(n)}),t=await e.json();if(!e.ok){const s=t.error_description??t.error??t.message??"Auth failed";throw new Error(s)}return t}async function zt(r,n){const e=await De("/auth/v1/token?grant_type=password",{email:r,password:n});return{userId:e.user.id,email:e.user.email,accessToken:e.access_token,refreshToken:e.refresh_token}}async function Wt(r,n){const e=await De("/auth/v1/signup",{email:r,password:n}),t=e.user??e;return{userId:t.id,email:t.email,accessToken:e.access_token??"",refreshToken:e.refresh_token??""}}async function Bt(r,n){const e=await fetch(`${qt}/api/session`,{method:"POST",headers:{"Content-Type":"application/json","x-tenant-id":r,"x-session-id":n},body:JSON.stringify({})});if(!e.ok){const t=await e.text();throw new Error(`Cloud session init failed: ${t}`)}}function Ht(r){const n=E.Router();return n.post("/sign-in",async(e,t)=>{const{email:s,password:o}=e.body;try{const i=await zt(s,o);t.json({userId:i.userId,email:i.email})}catch(i){t.json({error:i instanceof Error?i.message:String(i)})}}),n.post("/sign-up",async(e,t)=>{const{email:s,password:o}=e.body;try{const i=await Wt(s,o);t.json({userId:i.userId,email:i.email})}catch(i){t.json({error:i instanceof Error?i.message:String(i)})}}),n.post("/sign-out",(e,t)=>{r.deactivate(),t.json({})}),n.post("/init",async(e,t)=>{const{userId:s,sessionId:o}=e.body;r.startInit();try{await Bt(s,o),r.configure(s,o),t.json({success:!0})}catch(i){r.deactivate(),t.json({success:!1,error:i instanceof Error?i.message:String(i)})}}),n}et();const W=parseInt(process.env.JIVAM_PORT??"7842",10),Te=process.env.NODE_ENV==="development";function Gt(r){const n=[m.join(S.homedir(),"Applications","Safari Apps"),m.join(S.homedir(),"Applications")];for(const e of n){if(!u.existsSync(e))continue;const t=u.readdirSync(e).filter(s=>s.endsWith(".app"));for(const s of t){if(r.has(`${e}::${s}`))continue;const o=m.join(e,s,"Contents","Info.plist");if(u.existsSync(o))try{const i=u.readFileSync(o,"utf-8");if(i.includes("com.apple.Safari.WebApp")&&i.includes("<string>Jivam</string>"))return m.join(e,s)}catch{}}}return null}function Vt(){const r=[m.join(S.homedir(),"Applications","Safari Apps"),m.join(S.homedir(),"Applications")],n=new Set;for(const e of r)if(u.existsSync(e))for(const t of u.readdirSync(e).filter(s=>s.endsWith(".app")))n.add(`${e}::${t}`);return n}async function Yt(r){const{exec:n}=await import("child_process"),{promisify:e}=await import("util"),t=e(n);try{const{stdout:s}=await t("sw_vers -productVersion");if(parseInt(s.trim().split(".")[0]??"0",10)<14)return console.warn("Safari Add to Dock requires macOS Sonoma (14) or later — skipping."),null;const i=Vt(),a=m.join(S.tmpdir(),"jivam-add-to-dock.applescript"),c=`
128
+ on run
129
+ tell application "Safari"
130
+ activate
131
+ if (count of windows) = 0 then
132
+ make new document
133
+ end if
134
+ set URL of front document to "${r}"
135
+ end tell
136
+ delay 2
137
+ tell application "Safari" to activate
138
+ delay 1
139
+ tell application "System Events" to tell process "Safari" to set frontmost to true
140
+ delay 1
141
+ tell application "System Events"
142
+ tell process "Safari"
143
+ click menu item "Add to Dock…" of menu "File" of menu bar 1
144
+ end tell
145
+ end tell
146
+ delay 2
147
+ end run
148
+ `;u.writeFileSync(a,c);try{await t(`osascript "${a}"`,{timeout:2e4})}finally{u.rmSync(a,{force:!0})}console.log(`
149
+ A "Add to Dock" confirmation opened in Safari — click Add to finish setting up Jivam as an app.`),console.log("Waiting up to 60s for you to click it...");for(let l=0;l<60;l++){await new Promise(p=>setTimeout(p,1e3));const d=Gt(i);if(d)return d}return console.warn("No click detected within 60s — falling back to --app mode. Run `jivam --install` again anytime to retry."),null}catch(s){const o=s instanceof Error?s.message:String(s);if(o.includes("assistive access")||o.includes("-1719")){console.warn(`
150
+ Safari Add to Dock needs Accessibility permission (one-time setup) to control Safari's menus.
151
+ Opening System Settings — enable access for Terminal (or whichever app you ran this from),
152
+ then re-run: jivam --install
153
+ Falling back to --app mode for now — Jivam will still work, just without the native single-window Dock experience.`);try{await t('open "x-apple.systempreferences:com.apple.preference.security?Privacy_Accessibility"')}catch{}}else console.warn("Safari Add to Dock automation failed, falling back to --app mode:",s);return null}}const we="ai.karmaloop.jivam",J="JivamServer";function Fe(){return m.join(S.homedir(),"Library","LaunchAgents",`${we}.plist`)}async function Kt(){const{exec:r}=await import("child_process"),{promisify:n}=await import("util"),e=n(r);try{const{stdout:o}=await e("which jivam");if(o.trim())return o.trim()}catch{}const t=["/usr/local/bin/jivam",m.join(S.homedir(),".npm-global","bin","jivam"),"/opt/homebrew/bin/jivam","/usr/bin/jivam"];for(const o of t)if(u.existsSync(o))return o;const s=m.join(S.homedir(),".nvm","versions","node");if(u.existsSync(s))try{const o=u.readdirSync(s).sort().reverse();for(const i of o){const a=m.join(s,i,"bin","jivam");if(u.existsSync(a))return a}}catch{}return`"${process.execPath}" "${process.argv[1]}"`}async function Xt(r){const n=["/usr/local/bin","/opt/homebrew/bin","/opt/homebrew/sbin",m.join(S.homedir(),".npm-global","bin"),m.join(S.homedir(),".nvm","versions","node"),"/usr/bin","/bin"].join(":"),e=m.join(S.homedir(),".jivam");u.mkdirSync(e,{recursive:!0});const t=m.join(e,"jivam.log"),o=r.startsWith('"')?r.split('" "').map(c=>c.replace(/^"|"$/g,"")):[r],i=`<?xml version="1.0" encoding="UTF-8"?>
154
+ <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
155
+ <plist version="1.0">
156
+ <dict>
157
+ <key>Label</key>
158
+ <string>${we}</string>
159
+ <key>ProgramArguments</key>
160
+ <array>
161
+ ${o.map(c=>`<string>${c}</string>`).join(`
162
+ `)}
163
+ <string>--server-only</string>
164
+ </array>
165
+ <key>RunAtLoad</key>
166
+ <true/>
167
+ <key>KeepAlive</key>
168
+ <true/>
169
+ <key>ThrottleInterval</key>
170
+ <integer>5</integer>
171
+ <key>StandardOutPath</key>
172
+ <string>${t}</string>
173
+ <key>StandardErrorPath</key>
174
+ <string>${t}</string>
175
+ <key>EnvironmentVariables</key>
176
+ <dict>
177
+ <key>PATH</key>
178
+ <string>${n}:/usr/bin:/bin</string>
179
+ </dict>
180
+ </dict>
181
+ </plist>
182
+ `,a=Fe();return u.mkdirSync(m.dirname(a),{recursive:!0}),u.writeFileSync(a,i),a}async function Re(r){var c;const{exec:n}=await import("child_process"),{promisify:e}=await import("util"),t=e(n),s=Fe(),i=`gui/${((c=process.getuid)==null?void 0:c.call(process))??0}`,a=`${i}/${we}`;if(!u.existsSync(s)){console.log("Jivam background service is not installed. Run: jivam --install");return}if(r==="start")try{await t(`launchctl bootstrap ${i} "${s}"`),console.log("Jivam background service started.")}catch(l){const d=l instanceof Error?l.message:String(l);d.includes("already bootstrapped")||d.includes("Service already loaded")?console.log("Jivam background service is already running."):console.error("Failed to start service:",l)}else if(r==="stop")try{await t(`launchctl bootout ${a}`),console.log("Jivam background service stopped.")}catch{console.warn("Service was not running (or already stopped).")}else if(r==="restart")try{await t(`launchctl kickstart -k ${a}`),console.log("Jivam background service restarted.")}catch{try{await t(`launchctl bootstrap ${i} "${s}"`),console.log("Jivam background service started.")}catch(d){console.error("Failed to restart service:",d)}}else if(r==="status")try{const{stdout:l}=await t(`launchctl print ${a}`),d=/state = running/.test(l);console.log(d?"Jivam background service is running.":"Jivam background service is loaded but not running.");const p=l.match(/pid = (\d+)/);p&&console.log(` PID: ${p[1]}`)}catch{console.log("Jivam background service is not running.")}}async function Zt(){const{exec:r}=await import("child_process"),{promisify:n}=await import("util"),e=n(r),t=m.join(S.homedir(),"Applications","Jivam.app"),s=m.join(t,"Contents","MacOS"),o=m.join(t,"Contents","Resources");u.mkdirSync(s,{recursive:!0}),u.mkdirSync(o,{recursive:!0});const a=`#!/bin/bash
183
+ URL="${`http://localhost:${W}`}"
184
+ CHROME="/Applications/Google Chrome.app/Contents/MacOS/Google Chrome"
185
+ EDGE="/Applications/Microsoft Edge.app/Contents/MacOS/Microsoft Edge"
186
+ BRAVE="/Applications/Brave Browser.app/Contents/MacOS/Brave Browser"
187
+
188
+ if [ -f "$CHROME" ]; then
189
+ "$CHROME" --app="$URL" --disable-extensions &
190
+ elif [ -f "$EDGE" ]; then
191
+ "$EDGE" --app="$URL" --disable-extensions &
192
+ elif [ -f "$BRAVE" ]; then
193
+ "$BRAVE" --app="$URL" --disable-extensions &
194
+ else
195
+ osascript -e "tell application \\"Safari\\" to open location \\"$URL\\"" \\
196
+ -e "tell application \\"Safari\\" to activate"
197
+ fi
198
+ `;u.writeFileSync(m.join(s,"jivam-launcher"),a,{mode:493}),u.writeFileSync(m.join(t,"Contents","Info.plist"),`<?xml version="1.0" encoding="UTF-8"?>
199
+ <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
200
+ <plist version="1.0">
201
+ <dict>
202
+ <key>CFBundleExecutable</key>
203
+ <string>jivam-launcher</string>
204
+ <key>CFBundleIdentifier</key>
205
+ <string>ai.karmaloop.jivam</string>
206
+ <key>CFBundleName</key>
207
+ <string>Jivam</string>
208
+ <key>CFBundleDisplayName</key>
209
+ <string>Jivam</string>
210
+ <key>CFBundleIconFile</key>
211
+ <string>Jivam</string>
212
+ <key>CFBundleVersion</key>
213
+ <string>1</string>
214
+ <key>CFBundlePackageType</key>
215
+ <string>APPL</string>
216
+ <key>LSUIElement</key>
217
+ <false/>
218
+ </dict>
219
+ </plist>
220
+ `);const d=[m.join(__dirname,"..","dist","icon-512.png"),m.join(__dirname,"..","public","icon-512.png")].find(p=>u.existsSync(p));if(d)try{const p=m.join(S.tmpdir(),"Jivam.iconset");u.mkdirSync(p,{recursive:!0});const h=[[16,"icon_16x16.png"],[32,"icon_16x16@2x.png"],[32,"icon_32x32.png"],[64,"icon_32x32@2x.png"],[128,"icon_128x128.png"],[256,"icon_128x128@2x.png"],[256,"icon_256x256.png"],[512,"icon_256x256@2x.png"],[512,"icon_512x512.png"]];for(const[y,v]of h)await e(`sips -z ${y} ${y} "${d}" --out "${m.join(p,v)}"`);await e(`iconutil -c icns "${p}" --output "${m.join(o,"Jivam.icns")}"`),u.rmSync(p,{recursive:!0,force:!0})}catch(p){console.warn("Could not convert icon (sips/iconutil failed):",p)}return t}async function Qt(r){const{exec:n}=await import("child_process"),{promisify:e}=await import("util"),t=e(n),s="/System/Library/Frameworks/CoreServices.framework/Frameworks/LaunchServices.framework/Support/lsregister";try{await t(`touch "${r}"`),await t(`"${s}" -f "${r}"`)}catch{}const o=`<dict><key>tile-data</key><dict><key>file-data</key><dict><key>_CFURLString</key><string>${r}</string><key>_CFURLStringType</key><integer>0</integer></dict></dict></dict>`;try{await t(`defaults write com.apple.dock persistent-apps -array-add '${o}' && killall Dock`),console.log(`Added to Dock: ${r}`)}catch(i){console.warn("Could not add to Dock automatically — drag the app to your Dock manually."),console.warn(i)}}async function en(){process.platform!=="darwin"&&(console.error("--install is currently only supported on macOS."),process.exit(1));const r=`http://localhost:${W}`;console.log("Setting up the Jivam background service...");const n=await Kt();await Xt(n),await Re("restart");let e=!1;for(let o=0;o<30;o++){try{if((await fetch(`${r}/api/version`)).ok){e=!0;break}}catch{}await new Promise(i=>setTimeout(i,500))}e?console.log("Jivam server is running."):console.warn("Server did not come up within 15s — continuing anyway (check ~/.jivam/jivam.log)."),console.log("Installing Jivam as a Safari web app (this may take a few seconds)...");const s=await Yt(r)??await Zt();await Qt(s),console.log(`
221
+ Done! Click the Jivam icon in your Dock to launch.`),console.log("The server runs continuously in the background — manage it with:"),console.log(" jivam stop jivam start jivam restart jivam status"),process.exit(0)}async function tn(){const{exec:r}=await import("child_process"),{promisify:n}=await import("util"),e=n(r);try{const{stdout:o}=await e("where jivam"),i=o.split(`
222
+ `)[0].trim();if(i)return i}catch{}const t=process.env.LOCALAPPDATA??m.join(S.homedir(),"AppData","Local"),s=[m.join(t,"npm","jivam.cmd"),m.join(process.env.APPDATA??"","npm","jivam.cmd"),"C:\\Program Files\\nodejs\\jivam.cmd"];for(const o of s)if(u.existsSync(o))return o;return`"${process.execPath}" "${process.argv[1]}"`}async function nn(r){const{exec:n}=await import("child_process"),{promisify:e}=await import("util"),t=e(n),s=r.startsWith('"'),[o,...i]=s?r.split('" "').map(d=>d.replace(/^"|"$/g,"")):[r],a=[...i,"--server-only"].join(" "),c=`<?xml version="1.0" encoding="UTF-16"?>
223
+ <Task version="1.2" xmlns="http://schemas.microsoft.com/windows/2004/02/mit/task">
224
+ <Triggers>
225
+ <LogonTrigger>
226
+ <Enabled>true</Enabled>
227
+ </LogonTrigger>
228
+ </Triggers>
229
+ <Principals>
230
+ <Principal id="Author">
231
+ <LogonType>InteractiveToken</LogonType>
232
+ <RunLevel>LeastPrivilege</RunLevel>
233
+ </Principal>
234
+ </Principals>
235
+ <Settings>
236
+ <MultipleInstancesPolicy>IgnoreNew</MultipleInstancesPolicy>
237
+ <DisallowStartIfOnBatteries>false</DisallowStartIfOnBatteries>
238
+ <StopIfGoingOnBatteries>false</StopIfGoingOnBatteries>
239
+ <StartWhenAvailable>true</StartWhenAvailable>
240
+ <RunOnlyIfNetworkAvailable>false</RunOnlyIfNetworkAvailable>
241
+ <Hidden>true</Hidden>
242
+ <ExecutionTimeLimit>PT0S</ExecutionTimeLimit>
243
+ <RestartOnFailure>
244
+ <Interval>PT1M</Interval>
245
+ <Count>999</Count>
246
+ </RestartOnFailure>
247
+ </Settings>
248
+ <Actions Context="Author">
249
+ <Exec>
250
+ <Command>${o}</Command>
251
+ <Arguments>${a}</Arguments>
252
+ </Exec>
253
+ </Actions>
254
+ </Task>
255
+ `,l=m.join(S.tmpdir(),"jivam-task.xml");u.writeFileSync(l,Buffer.concat([Buffer.from([255,254]),Buffer.from(c,"utf16le")]));try{await t(`schtasks /Create /TN "${J}" /XML "${l}" /F`)}finally{u.rmSync(l,{force:!0})}}async function _e(r){const{exec:n}=await import("child_process"),{promisify:e}=await import("util"),t=e(n);try{await t(`schtasks /Query /TN "${J}"`)}catch{console.log("Jivam background service is not installed. Run: jivam --install");return}if(r==="start"||r==="restart"){if(r==="restart"){try{await t(`schtasks /End /TN "${J}"`)}catch{}await new Promise(s=>setTimeout(s,1e3))}try{await t(`schtasks /Run /TN "${J}"`),console.log(`Jivam background service ${r==="restart"?"restarted":"started"}.`)}catch(s){console.error(`Failed to ${r} service:`,s)}}else if(r==="stop")try{await t(`schtasks /End /TN "${J}"`),console.log("Jivam background service stopped.")}catch{console.warn("Service was not running (or already stopped).")}else if(r==="status")try{const{stdout:s}=await t(`schtasks /Query /TN "${J}" /FO LIST /V`),o=s.match(/Status:\s*(.+)/);console.log(o?`Jivam background service status: ${o[1].trim()}`:"Jivam background service is registered.")}catch{console.log("Jivam background service is not running.")}}async function sn(){const{exec:r}=await import("child_process"),{promisify:n}=await import("util"),e=n(r),t=process.env.LOCALAPPDATA??m.join(S.homedir(),"AppData","Local"),s=m.join(t,"Jivam"),o=m.join(s,"jivam-launcher.bat"),i=m.join(s,"jivam-launcher.vbs"),a=m.join(s,"Jivam.ico"),c=m.join(S.homedir(),"Desktop","Jivam.lnk"),l=m.join(t,"Microsoft","Windows","Start Menu","Programs"),d=m.join(l,"Jivam.lnk");u.mkdirSync(s,{recursive:!0});const p=`http://localhost:${W}`;console.log("Setting up the Jivam background service...");const h=await tn();await nn(h),await _e("restart");let y=!1;for(let k=0;k<30;k++){try{if((await fetch(`${p}/api/version`)).ok){y=!0;break}}catch{}await new Promise(w=>setTimeout(w,500))}y?console.log("Jivam server is running."):console.warn("Server did not come up within 15s — continuing anyway (check %LOCALAPPDATA%\\Jivam\\jivam.log).");const v=`@echo off
256
+ set URL=${p}
257
+ set CHROME=%ProgramFiles%\\Google\\Chrome\\Application\\chrome.exe
258
+ set EDGE=%ProgramFiles(x86)%\\Microsoft\\Edge\\Application\\msedge.exe
259
+
260
+ if exist "%CHROME%" (
261
+ start "" "%CHROME%" --app=%URL% --disable-extensions
262
+ ) else if exist "%EDGE%" (
263
+ start "" "%EDGE%" --app=%URL% --disable-extensions
264
+ ) else (
265
+ start "" %URL%
266
+ )
267
+ `,A=`Set oShell = CreateObject("WScript.Shell")
268
+ oShell.Run Chr(34) & "${o.replace(/\\/g,"\\\\")}" & Chr(34), 0, False
269
+ `;u.writeFileSync(o,v),u.writeFileSync(i,A),console.log(`Created launcher at ${s}`);const g=[m.join(B,"..","dist","icon-512.png"),m.join(B,"..","public","icon-512.png")].find(k=>u.existsSync(k));if(g){const k=`
270
+ Add-Type -AssemblyName System.Drawing
271
+ $src = [System.Drawing.Image]::FromFile('${g.replace(/\\/g,"\\\\")}')
272
+ $bmp = New-Object System.Drawing.Bitmap($src, 256, 256)
273
+ $ico = [System.Drawing.Icon]::FromHandle($bmp.GetHicon())
274
+ $fs = [System.IO.File]::Create('${a.replace(/\\/g,"\\\\")}')
275
+ $ico.Save($fs)
276
+ $fs.Close()
277
+ $ico.Dispose()
278
+ $bmp.Dispose()
279
+ $src.Dispose()
280
+ Write-Host "Icon written"
281
+ `.trim();try{await e(`powershell -NoProfile -NonInteractive -Command "${k.replace(/"/g,'\\"').replace(/\n/g,"; ")}"`),console.log("Icon created.")}catch(w){console.warn("Could not create icon (PowerShell/System.Drawing failed):",w)}}const j=u.existsSync(a)?`$s.IconLocation = '${a.replace(/\\/g,"\\\\")}'`:"",b=k=>`
282
+ $ws = New-Object -ComObject WScript.Shell
283
+ $s = $ws.CreateShortcut('${k.replace(/\\/g,"\\\\")}')
284
+ $s.TargetPath = 'wscript.exe'
285
+ $s.Arguments = '//B "${i.replace(/\\/g,"\\\\")}"'
286
+ $s.WorkingDirectory = '${s.replace(/\\/g,"\\\\")}'
287
+ $s.Description = 'Jivam - AI Agent UI'
288
+ ${j}
289
+ $s.Save()
290
+ `.trim();try{u.mkdirSync(l,{recursive:!0});for(const k of[c,d]){const w=b(k);await e(`powershell -NoProfile -NonInteractive -Command "${w.replace(/"/g,'\\"').replace(/\n/g,"; ")}"`)}console.log(`Created Desktop shortcut: ${c}`),console.log(`Created Start Menu entry: ${d}`)}catch(k){console.warn("Could not create shortcuts:",k)}console.log(`
291
+ Done! Double-click the Jivam icon on your Desktop to launch.`),console.log("The server runs continuously in the background — manage it with:"),console.log(" jivam stop jivam start jivam restart jivam status"),process.exit(0)}const B=__dirname,I=E();I.use(E.json({limit:"50mb"}));const G=new wt,Oe=new gt,Je=new vt;I.use("/api/setup",Pe);I.use("/api/config",H);I.use("/api/conversations",ge);I.use("/api/git",U);I.use("/api/directive",ye);I.use("/api/workspace",_);I.use("/api/jiva",kt(G,Je));I.use("/api/personas",$t(G));I.use("/api/mcp",Mt(G));I.use("/api/code",At(Oe));I.use("/api/files",Nt(G));I.use("/api/cloud",Ht(Je));I.get("/api/platform",(r,n)=>n.json(process.platform));I.get("/api/version",(r,n)=>{try{const e=JSON.parse(u.readFileSync(m.join(B,"..","package.json"),"utf-8"));n.json(e.version)}catch{n.json("0.0.0")}});if(!Te){const r=m.join(B,"..","dist");u.existsSync(r)&&(I.use(E.static(r)),I.get(/(.*)/,(n,e)=>{e.sendFile(m.join(r,"index.html"))}))}async function rn(r){const{execFile:n,exec:e}=await import("child_process"),{promisify:t}=await import("util"),s=t(e),o=(process.env.JIVAM_BROWSER??"").toLowerCase();if(process.platform==="darwin"){if(o!=="chrome"&&o!=="edge"&&o!=="brave"){const i=[m.join(S.homedir(),"Applications","Safari Apps","Jivam.app"),m.join(S.homedir(),"Applications","Jivam.app"),"/Applications/Jivam.app"];for(const a of i)if(u.existsSync(a))try{await s(`open "${a}"`),console.log(`Launched Safari PWA: ${a}`);return}catch{}}if(o==="safari")try{await s(`osascript -e 'tell application "Safari" to open location "${r}"' -e 'tell application "Safari" to activate'`),console.log("Opened in Safari (tip: File → Add to Dock for app experience)");return}catch(i){console.error("Failed to open Safari:",i)}if(o!=="safari"){const i=[["chrome","/Applications/Google Chrome.app/Contents/MacOS/Google Chrome"],["edge","/Applications/Microsoft Edge.app/Contents/MacOS/Microsoft Edge"],["brave","/Applications/Brave Browser.app/Contents/MacOS/Brave Browser"]];for(const[a,c]of i)if(!(o&&o!==a))try{n(c,[`--app=${r}`,"--disable-extensions"]),console.log(`Opened in app-mode window: ${c}`);return}catch{}}if(!o)try{await s(`osascript -e 'tell application "Safari" to open location "${r}"' -e 'tell application "Safari" to activate'`),console.log("Opened in Safari (tip: File → Add to Dock for app experience)");return}catch{}}else if(process.platform==="win32"){const i=[["msedge",[`--app=${r}`]],["chrome",[`--app=${r}`]],["brave",[`--app=${r}`]]];for(const[a,c]of i)try{n(`start ${a}`,c,{shell:!0});return}catch{}try{await s(`start "" "${r}"`);return}catch{}}else{const i=[["google-chrome",[`--app=${r}`]],["google-chrome-stable",[`--app=${r}`]],["chromium-browser",[`--app=${r}`]],["chromium",[`--app=${r}`]],["brave-browser",[`--app=${r}`]],["microsoft-edge",[`--app=${r}`]]];for(const[a,c]of i)try{n(a,c);return}catch{}}try{const{default:i}=await import("open");await i(r),console.log(`Opened in default browser: ${r}`)}catch(i){console.error("Could not open browser automatically:",i),console.log(`Open manually: ${r}`)}}function on(){const n=async()=>{try{const{exec:e}=await import("child_process"),{promisify:t}=await import("util"),s=t(e),o=JSON.parse(u.readFileSync(m.join(B,"..","package.json"),"utf-8")),{stdout:i}=await s("npm view jivamai version"),a=i.trim();if(a&&a!==o.version){console.log(`Update available: jivamai ${o.version} → ${a}. Updating...`),await s("npm install -g jivamai jiva-core"),console.log("Update installed — restarting to pick it up."),process.exit(1);return}}catch(e){console.warn("Update check failed (probably offline):",e)}setTimeout(n,864e5)};setTimeout(n,864e5)}const z=process.argv[2],an=z==="start"||z==="stop"||z==="restart"||z==="status";if(process.argv.includes("--install"))(process.platform==="win32"?sn:en)().catch(n=>{console.error(n),process.exit(1)});else if(an)(process.platform==="win32"?_e:Re)(z).then(()=>process.exit(0)).catch(n=>{console.error(n),process.exit(1)});else{const r=process.argv.includes("--server-only"),n=Qe.createServer(I);tt(n),n.listen(W,"127.0.0.1",async()=>{const t=`http://localhost:${W}`;console.log(`Jivam server running at ${t}`),!Te&&!r&&await rn(t),r&&on()});async function e(){await G.cleanup(),await Oe.cleanup(),n.close(),process.exit(0)}process.on("SIGINT",e),process.on("SIGTERM",e)}
292
+ //# sourceMappingURL=index.js.map