shennian 0.3.10 → 0.3.12

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 (49) hide show
  1. package/dist/publish-build-manifest.json +47 -42
  2. package/dist/src/agents/model-registry/parsers.js +4 -4
  3. package/dist/src/commands/daemon-windows.d.ts +7 -0
  4. package/dist/src/commands/daemon-windows.js +12 -8
  5. package/dist/src/commands/daemon.d.ts +4 -1
  6. package/dist/src/commands/daemon.js +9 -9
  7. package/dist/src/commands/room.d.ts +9 -0
  8. package/dist/src/commands/room.js +8 -4
  9. package/dist/src/index.js +2 -2
  10. package/dist/src/integrations/room-plugin-shared.js +2 -2
  11. package/dist/src/integrations/workbuddy-plugin-lifecycle.d.ts +10 -0
  12. package/dist/src/integrations/workbuddy-plugin-lifecycle.js +2 -2
  13. package/dist/src/room/activation-service.d.ts +3 -0
  14. package/dist/src/room/activation-service.js +9 -5
  15. package/dist/src/room/agent-tool.d.ts +1 -0
  16. package/dist/src/room/agent-tool.js +1 -1
  17. package/dist/src/room/managed-room-binding.d.ts +23 -1
  18. package/dist/src/room/managed-room-binding.js +1 -1
  19. package/dist/src/room/managed-room-session-runtime.d.ts +18 -0
  20. package/dist/src/room/managed-room-session-runtime.js +1 -0
  21. package/dist/src/room/mirror-sync-service.d.ts +3 -1
  22. package/dist/src/room/mirror-sync-service.js +1 -1
  23. package/dist/src/room/operator-ipc.d.ts +2 -0
  24. package/dist/src/room/operator-ipc.js +1 -1
  25. package/dist/src/room/room-action-client.d.ts +2 -0
  26. package/dist/src/room/room-action-ipc.d.ts +1 -0
  27. package/dist/src/room/room-action-ipc.js +1 -1
  28. package/dist/src/room/room-binding-client.d.ts +9 -0
  29. package/dist/src/room/room-binding-client.js +1 -1
  30. package/dist/src/room/room-binding-ipc.d.ts +3 -1
  31. package/dist/src/room/session-registry.d.ts +7 -1
  32. package/dist/src/room/session-registry.js +2 -2
  33. package/dist/src/room/tool-schema.d.ts +1 -1
  34. package/dist/src/room/tool-schema.js +1 -1
  35. package/dist/src/session/handlers/chat.d.ts +8 -1
  36. package/dist/src/session/handlers/chat.js +1 -1
  37. package/dist/src/session/handlers/room-managed.d.ts +1 -0
  38. package/dist/src/session/handlers/room-managed.js +1 -1
  39. package/dist/src/session/manager.d.ts +20 -0
  40. package/dist/src/session/manager.js +1 -1
  41. package/dist/src/upgrade/engine.d.ts +5 -0
  42. package/dist/src/upgrade/engine.js +2 -2
  43. package/node_modules/@shennian/wire/dist/agent-workspace.d.ts +1 -0
  44. package/node_modules/@shennian/wire/dist/agent-workspace.d.ts.map +1 -1
  45. package/node_modules/@shennian/wire/dist/methods.d.ts +1 -1
  46. package/node_modules/@shennian/wire/dist/methods.d.ts.map +1 -1
  47. package/node_modules/@shennian/wire/dist/room.d.ts +2 -0
  48. package/node_modules/@shennian/wire/dist/room.d.ts.map +1 -1
  49. package/package.json +1 -1
@@ -2,7 +2,7 @@
2
2
  "schemaVersion": 1,
3
3
  "jsMinified": true,
4
4
  "minifier": "esbuild",
5
- "fileCount": 128,
5
+ "fileCount": 129,
6
6
  "files": [
7
7
  {
8
8
  "file": "bin/shennian.js",
@@ -86,8 +86,8 @@
86
86
  },
87
87
  {
88
88
  "file": "src/agents/model-registry/parsers.js",
89
- "beforeBytes": 18471,
90
- "afterBytes": 9024
89
+ "beforeBytes": 19646,
90
+ "afterBytes": 10067
91
91
  },
92
92
  {
93
93
  "file": "src/agents/model-registry/runner.js",
@@ -156,13 +156,13 @@
156
156
  },
157
157
  {
158
158
  "file": "src/commands/daemon-windows.js",
159
- "beforeBytes": 3570,
160
- "afterBytes": 2877
159
+ "beforeBytes": 3905,
160
+ "afterBytes": 3130
161
161
  },
162
162
  {
163
163
  "file": "src/commands/daemon.js",
164
- "beforeBytes": 37848,
165
- "afterBytes": 18285
164
+ "beforeBytes": 38493,
165
+ "afterBytes": 18618
166
166
  },
167
167
  {
168
168
  "file": "src/commands/integration.js",
@@ -191,8 +191,8 @@
191
191
  },
192
192
  {
193
193
  "file": "src/commands/room.js",
194
- "beforeBytes": 2630,
195
- "afterBytes": 1520
194
+ "beforeBytes": 11089,
195
+ "afterBytes": 5750
196
196
  },
197
197
  {
198
198
  "file": "src/commands/tools.js",
@@ -266,8 +266,8 @@
266
266
  },
267
267
  {
268
268
  "file": "src/index.js",
269
- "beforeBytes": 25211,
270
- "afterBytes": 13075
269
+ "beforeBytes": 26361,
270
+ "afterBytes": 13566
271
271
  },
272
272
  {
273
273
  "file": "src/integrations/claude-room-plugin-lifecycle.js",
@@ -291,8 +291,8 @@
291
291
  },
292
292
  {
293
293
  "file": "src/integrations/room-plugin-shared.js",
294
- "beforeBytes": 8353,
295
- "afterBytes": 5533
294
+ "beforeBytes": 8919,
295
+ "afterBytes": 6095
296
296
  },
297
297
  {
298
298
  "file": "src/integrations/room-session-hook.js",
@@ -306,8 +306,8 @@
306
306
  },
307
307
  {
308
308
  "file": "src/integrations/workbuddy-plugin-lifecycle.js",
309
- "beforeBytes": 14838,
310
- "afterBytes": 7721
309
+ "beforeBytes": 15998,
310
+ "afterBytes": 8237
311
311
  },
312
312
  {
313
313
  "file": "src/integrations/workbuddy-session-hook.js",
@@ -401,13 +401,13 @@
401
401
  },
402
402
  {
403
403
  "file": "src/room/activation-service.js",
404
- "beforeBytes": 9879,
405
- "afterBytes": 5818
404
+ "beforeBytes": 13148,
405
+ "afterBytes": 8188
406
406
  },
407
407
  {
408
408
  "file": "src/room/agent-tool.js",
409
- "beforeBytes": 4977,
410
- "afterBytes": 2981
409
+ "beforeBytes": 5020,
410
+ "afterBytes": 3009
411
411
  },
412
412
  {
413
413
  "file": "src/room/attachment-cache.js",
@@ -466,8 +466,13 @@
466
466
  },
467
467
  {
468
468
  "file": "src/room/managed-room-binding.js",
469
- "beforeBytes": 3203,
470
- "afterBytes": 1658
469
+ "beforeBytes": 6069,
470
+ "afterBytes": 3316
471
+ },
472
+ {
473
+ "file": "src/room/managed-room-session-runtime.js",
474
+ "beforeBytes": 6336,
475
+ "afterBytes": 3257
471
476
  },
472
477
  {
473
478
  "file": "src/room/managed-room-session.js",
@@ -476,13 +481,13 @@
476
481
  },
477
482
  {
478
483
  "file": "src/room/mirror-sync-service.js",
479
- "beforeBytes": 7591,
480
- "afterBytes": 3460
484
+ "beforeBytes": 7686,
485
+ "afterBytes": 3515
481
486
  },
482
487
  {
483
488
  "file": "src/room/operator-ipc.js",
484
- "beforeBytes": 4612,
485
- "afterBytes": 2271
489
+ "beforeBytes": 8566,
490
+ "afterBytes": 4401
486
491
  },
487
492
  {
488
493
  "file": "src/room/pending-authorized-actions.js",
@@ -491,13 +496,13 @@
491
496
  },
492
497
  {
493
498
  "file": "src/room/room-action-client.js",
494
- "beforeBytes": 22450,
499
+ "beforeBytes": 22556,
495
500
  "afterBytes": 11355
496
501
  },
497
502
  {
498
503
  "file": "src/room/room-action-ipc.js",
499
- "beforeBytes": 15434,
500
- "afterBytes": 6907
504
+ "beforeBytes": 15565,
505
+ "afterBytes": 6951
501
506
  },
502
507
  {
503
508
  "file": "src/room/room-action-schema.js",
@@ -511,8 +516,8 @@
511
516
  },
512
517
  {
513
518
  "file": "src/room/room-binding-client.js",
514
- "beforeBytes": 4396,
515
- "afterBytes": 2546
519
+ "beforeBytes": 6716,
520
+ "afterBytes": 3894
516
521
  },
517
522
  {
518
523
  "file": "src/room/room-binding-ipc.js",
@@ -526,13 +531,13 @@
526
531
  },
527
532
  {
528
533
  "file": "src/room/session-registry.js",
529
- "beforeBytes": 21855,
530
- "afterBytes": 12317
534
+ "beforeBytes": 23644,
535
+ "afterBytes": 13190
531
536
  },
532
537
  {
533
538
  "file": "src/room/tool-schema.js",
534
- "beforeBytes": 4903,
535
- "afterBytes": 2973
539
+ "beforeBytes": 4993,
540
+ "afterBytes": 3063
536
541
  },
537
542
  {
538
543
  "file": "src/room/tool-server.js",
@@ -561,8 +566,8 @@
561
566
  },
562
567
  {
563
568
  "file": "src/session/handlers/chat.js",
564
- "beforeBytes": 31062,
565
- "afterBytes": 13525
569
+ "beforeBytes": 31069,
570
+ "afterBytes": 13554
566
571
  },
567
572
  {
568
573
  "file": "src/session/handlers/control.js",
@@ -576,8 +581,8 @@
576
581
  },
577
582
  {
578
583
  "file": "src/session/handlers/room-managed.js",
579
- "beforeBytes": 1595,
580
- "afterBytes": 965
584
+ "beforeBytes": 3173,
585
+ "afterBytes": 1972
581
586
  },
582
587
  {
583
588
  "file": "src/session/handlers/session-refresh.js",
@@ -596,8 +601,8 @@
596
601
  },
597
602
  {
598
603
  "file": "src/session/manager.js",
599
- "beforeBytes": 16188,
600
- "afterBytes": 8308
604
+ "beforeBytes": 20500,
605
+ "afterBytes": 10670
601
606
  },
602
607
  {
603
608
  "file": "src/session/projection.js",
@@ -631,8 +636,8 @@
631
636
  },
632
637
  {
633
638
  "file": "src/upgrade/engine.js",
634
- "beforeBytes": 15457,
635
- "afterBytes": 6563
639
+ "beforeBytes": 15579,
640
+ "afterBytes": 6624
636
641
  },
637
642
  {
638
643
  "file": "src/upgrade/scheduler.js",
@@ -1,4 +1,4 @@
1
- function m(e){return e.replace(/\u001b\[[0-9;?]*[a-zA-Z]/g,"").replace(/\u001b\][^\u0007]*\u0007/g,"").replace(/[\u0000-\u0008\u000b-\u001f\u007f]/g,"")}function d(e){const n=new Set,t=[];for(const o of e)!o.id||n.has(o.id)||(n.add(o.id),t.push(o));return t}function h(e){return e&&e[0].toUpperCase()+e.slice(1)}function b(e){return e.split("-").map(n=>n==="gpt"?"GPT":n==="codex"?"Codex":/^\d/.test(n)?n:h(n)).join("-")}function A(e){switch(e){case"low":return"Low";case"medium":return"Medium";case"high":return"High";case"xhigh":return"Extra High";default:return h(e)}}const D=[{id:"gpt-5.6-sol",name:"GPT-5.6 Sol",description:"Latest GPT-5.6 Codex model.",provider:"openai"},{id:"gpt-5.6-terra",name:"GPT-5.6 Terra",description:"Latest GPT-5.6 Codex model.",provider:"openai"},{id:"gpt-5.6-luna",name:"GPT-5.6 Luna",description:"Latest GPT-5.6 Codex model.",provider:"openai"}];function x(e){const n={...e};return e.supportedReasoningEfforts&&(n.supportedReasoningEfforts=e.supportedReasoningEfforts.map(t=>({...t}))),e.additionalSpeedTiers&&(n.additionalSpeedTiers=[...e.additionalSpeedTiers]),n}function R(e,n){const t=n??e.find(i=>i.isDefault)?.id,o=d([...e.map(x),...D.map(i=>x(i))]);return t?o.map(i=>({...i,isDefault:i.id===t})):o}function H(){return D.map((e,n)=>({...x(e),...n===0?{isDefault:!0}:{}}))}function F(){return[{id:"auto",name:"Auto",provider:"workbuddy",isDefault:!0,supportedReasoningEfforts:["minimal","low","medium","high","xhigh","max"].map(e=>({id:e,name:A(e)})),defaultReasoningEffort:"medium"}]}function k(e){return e.split("-").map(n=>/^\d/.test(n)?n:h(n)).join(" ")}function _(e,n,t=!1){const o=n.toLowerCase().replace(/\s+/g,"-");return`gemini-${e}-${o}${t?"-preview":""}`}function I(e){const n=[],t=m(e);for(const o of t.split(`
2
- `)){const i=o.trim().match(/^(\S+)\s+-\s+(.+?)(?:\s+\(([^)]+)\))?$/);if(!i)continue;const[,s,r,a]=i,u=a?.split(",").map(c=>c.trim().toLowerCase())??[];n.push({id:s,name:r.trim()||k(s),description:a?.trim(),isDefault:u.includes("default")||u.includes("current")})}return d(n)}function U(e){try{const t=(JSON.parse(e).models??[]).filter(o=>o.available).map(o=>({id:o.key,name:o.name?.trim()||o.key,provider:o.key.split("/")[0],description:o.tags?.join(", "),isDefault:o.tags?.includes("default")??!1}));return d(t)}catch{return[]}}function j(e){const n=m(e).split(`
3
- `).map(t=>t.trim()).filter(Boolean).filter(t=>!t.includes(" ")).map(t=>({id:t,name:t,provider:t.includes("/")?t.split("/")[0]:void 0}));return d(n)}function B(e){const n=m(e).replace(/\s+/g," "),t=[[/\d+\.Default\(recommended\).*?(?:Sonnet|currently\s*Sonnet)\s*([\d.]+)/i,"default","Default (recommended)"],[/\d+\.Sonnet.*?Sonnet\s*([\d.]+)/i,"sonnet","Sonnet"],[/\d+\.Opus.*?Opus\s*([\d.]+)/i,"opus","Opus"],[/\d+\.Haiku.*?Haiku\s*([\d.]+)/i,"haiku","Haiku"]],o=[];for(const[a,u,c]of t){const l=n.match(a);l&&o.push(g({id:u,name:c,description:`v${l[1]}`,provider:"anthropic",isDefault:u==="default"}))}if(o.length>0)return d(o);const i=[],s=n.match(/currently\s*(Sonnet|Opus|Haiku)\s*([34](?:\.\d)?)/i),r={sonnet:"sonnet",opus:"opus",haiku:"haiku"};for(const a of n.matchAll(/\b(Sonnet|Opus|Haiku)\s*([34](?:\.\d)?)\b/gi)){const u=(a[1]??"").toLowerCase(),c=r[u];if(!c)continue;const l=a[2]??"",C=s&&s[1]?.toLowerCase()===u&&s[2]===l;i.push(g({id:c,name:`${h(u)} ${l}`,provider:"anthropic",isDefault:!!C}))}return d(i)}function T(e,n){const t=Math.max(e.length,n.length);for(let o=0;o<t;o++){const i=e[o]??-1,s=n[o]??-1;if(i!==s)return i-s}return 0}function w(e,n){const t=e.match(new RegExp(`^claude-${n}-([0-9]+(?:-[0-9]+)*)$`,"i"));if(!t?.[1])return null;const o=t[1].split("-").map(i=>Number.parseInt(i,10)).filter(i=>Number.isFinite(i));return o.length===0||o.length>2?null:o}function $(e){if(e?.length)return`v${e.join(".")}`}const y={default:"Default (recommended)",sonnet:"Sonnet",opus:"Opus",haiku:"Haiku"},L={default:"ANTHROPIC_MODEL",sonnet:"ANTHROPIC_DEFAULT_SONNET_MODEL",opus:"ANTHROPIC_DEFAULT_OPUS_MODEL",haiku:"ANTHROPIC_DEFAULT_HAIKU_MODEL"},G=[{id:"max",name:"Max"}],N=[{id:"low",name:"Low"},{id:"medium",name:"Medium"},{id:"high",name:"High"},{id:"xhigh",name:"Extra High"},{id:"max",name:"Max"}];function g(e){return{...e,supportedReasoningEfforts:N,defaultReasoningEffort:"medium"}}function E(e,n){return e[n]?.trim()||null}function M(e,n){const t=E(n,"ANTHROPIC_BASE_URL")?.toLowerCase()??"";return t.includes("deepseek.com")||e.toLowerCase().startsWith("deepseek-")?"deepseek":t?"custom":"anthropic"}function S(e){const n=new Set;for(const o of Object.values(L)){const i=E(e,o);i&&n.add(i)}const t=Array.from(n).map((o,i)=>{const s=M(o,e),r={id:o,name:o,provider:s,isDefault:i===0};return s==="deepseek"?{...r,supportedReasoningEfforts:G,defaultReasoningEffort:E(e,"CLAUDE_CODE_EFFORT_LEVEL")??"max"}:g(r)});return d(t)}function V(e=process.env){return S(e)}function P(e,n=process.env){return e.map(t=>{if(!["default","sonnet","opus","haiku"].includes(t.id))return t;const o=t.id,i=E(n,L[o]);if(!i)return t;const r=`Claude Code alias: ${y[o]}`;return{...t,name:i,description:t.description?`${r} \xB7 ${t.description}`:r,provider:M(i,n)}})}function z(e){const n=m(e),t=new Map;for(const i of["sonnet","opus","haiku"])for(const s of n.matchAll(new RegExp(`\\bclaude-${i}-[0-9.-]+\\b`,"gi"))){const r=s[0].trim().toLowerCase().replace(/\./g,"-").replace(/-+$/g,""),a=w(r,i);if(!a)continue;const u=t.get(i);(!u||T(u,a)<0)&&t.set(i,a)}const o=[];for(const i of["default","sonnet","opus","haiku"]){if(!new RegExp(`\\b${i}\\b`,"i").test(n))continue;const s=(i==="default"?t.get("sonnet"):t.get(i))??null;o.push(g({id:i,name:y[i],description:$(s),provider:"anthropic",isDefault:i==="default"}))}return d(o)}function q(e=process.env){const n=S(e);return n.length>0?n:P([{id:"default",name:"Default (recommended)",provider:"anthropic",isDefault:!0},{id:"sonnet",name:"Sonnet",provider:"anthropic"},{id:"opus",name:"Opus",provider:"anthropic"},{id:"haiku",name:"Haiku",provider:"anthropic"}],e).map(g)}function K(e){const n=m(e),t=[];for(const o of n.split(`
4
- `)){const i=o.match(/\b(gpt-[a-z0-9][a-z0-9.-]*)\b/i);if(!i)continue;const s=i[1].trim(),r=o.replace(s,"").replace(/^[^\w]+/,"").trim()||void 0;t.push({id:s,name:b(s),description:r,provider:"openai",isDefault:/\bcurrent\b/i.test(o)||/\bselected\b/i.test(o)})}return d(t)}function W(e){const n=typeof e=="object"&&e!==null?e:{},t=typeof n.config?.model=="string"?n.config.model:void 0,o=typeof n.config?.model_reasoning_effort=="string"?n.config.model_reasoning_effort:void 0,i=[];for(const s of n.data??[]){if(typeof s!="object"||s===null)continue;const r=s,a=typeof r.id=="string"?r.id:typeof r.model=="string"?r.model:"";if(!a)continue;const u=typeof r.displayName=="string"?r.displayName:typeof r.name=="string"?r.name:void 0,c=typeof r.description=="string"?r.description:void 0,l=typeof r.defaultReasoningEffort=="string"?r.defaultReasoningEffort:void 0,C=Array.isArray(r.supportedReasoningEfforts)?r.supportedReasoningEfforts.map(f=>{if(typeof f!="object"||f===null)return null;const p=f,v=typeof p.reasoningEffort=="string"?p.reasoningEffort:typeof p.id=="string"?p.id:"";return v?{id:v,name:A(v),description:typeof p.description=="string"?p.description:void 0}:null}).filter(f=>f!=null):void 0,O=Array.isArray(r.additionalSpeedTiers)?r.additionalSpeedTiers.filter(f=>typeof f=="string"):void 0;i.push({id:a,name:u||b(a),description:c,provider:"openai",isDefault:t?t===a:r.isDefault===!0,supportedReasoningEfforts:C,defaultReasoningEffort:l,additionalSpeedTiers:O})}return t&&!i.some(s=>s.id===t)&&i.unshift({id:t,name:b(t),provider:"openai",isDefault:!0,defaultReasoningEffort:o}),R(d(i),t)}function J(e){const n=m(e),t=[];for(const o of n.matchAll(/\b(?:auto-)?gemini-[a-z0-9.-]+\b/gi)){const i=o[0].trim();t.push({id:i,name:i,provider:"google",isDefault:/\bcurrent\b/i.test(n)&&n.includes(i)})}for(const o of n.matchAll(/\bGemini\s*(\d(?:\.\d)?)\s*(Pro|Flash(?:[- ]Lite)?)\s*(Preview)?\b/gi)){const i=o[1]??"",s=(o[2]??"").replace(/\s+/g,"-"),r=!!o[3],a=_(i,s,r);t.push({id:a,name:`Gemini ${i} ${s.replace(/-/g," ")}`.trim(),provider:"google",isDefault:/\bcurrent\b/i.test(n)&&n.includes(o[0]??"")})}for(const o of n.matchAll(/\bAuto\s*Gemini\s*(\d(?:\.\d)?)\b/gi)){const i=o[1]??"",s=`auto-gemini-${i}`;t.push({id:s,name:`Auto Gemini ${i}`,provider:"google",isDefault:/\bcurrent\b/i.test(n)&&n.includes(o[0]??"")})}return d(t)}function X(){return[{id:"gemini-2.5-pro",name:"Gemini 2.5 Pro",provider:"google",isDefault:!0},{id:"gemini-2.5-flash",name:"Gemini 2.5 Flash",provider:"google"},{id:"auto-gemini-2.5",name:"Auto Gemini 2.5",provider:"google"}]}export{P as applyClaudeModelEnvOverrides,V as discoverClaudeAliasModelsFromEnv,q as fallbackClaudeAliasModels,H as fallbackCodexModels,X as fallbackGeminiModels,F as fallbackWorkBuddyModels,M as inferClaudeOverrideProvider,z as parseClaudeBinaryModels,B as parseClaudeModels,W as parseCodexAppServerModels,K as parseCodexModels,I as parseCursorModels,J as parseGeminiModels,U as parseOpenClawModels,j as parseOpenCodeModels,E as readEnvValue,m as stripAnsi};
1
+ function g(e){return e.replace(/\u001b\[[0-9;?]*[a-zA-Z]/g,"").replace(/\u001b\][^\u0007]*\u0007/g,"").replace(/[\u0000-\u0008\u000b-\u001f\u007f]/g,"")}function d(e){const n=new Set,t=[];for(const o of e)!o.id||n.has(o.id)||(n.add(o.id),t.push(o));return t}function E(e){return e&&e[0].toUpperCase()+e.slice(1)}function b(e){return e.split("-").map(n=>n==="gpt"?"GPT":n==="codex"?"Codex":/^\d/.test(n)?n:E(n)).join("-")}function M(e){switch(e){case"low":return"Low";case"medium":return"Medium";case"high":return"High";case"xhigh":return"Extra High";default:return E(e)}}const O=[{id:"gpt-5.6-sol",name:"GPT-5.6 Sol",description:"Latest GPT-5.6 Codex model.",provider:"openai"},{id:"gpt-5.6-terra",name:"GPT-5.6 Terra",description:"Latest GPT-5.6 Codex model.",provider:"openai"},{id:"gpt-5.6-luna",name:"GPT-5.6 Luna",description:"Latest GPT-5.6 Codex model.",provider:"openai"}];function C(e){const n={...e};return e.supportedReasoningEfforts&&(n.supportedReasoningEfforts=e.supportedReasoningEfforts.map(t=>({...t}))),e.additionalSpeedTiers&&(n.additionalSpeedTiers=[...e.additionalSpeedTiers]),n}function R(e,n){const t=n??e.find(i=>i.isDefault)?.id,o=d([...e.map(C),...O.map(i=>C(i))]);return t?o.map(i=>({...i,isDefault:i.id===t})):o}function H(){return O.map((e,n)=>({...C(e),...n===0?{isDefault:!0}:{}}))}function F(){return[{id:"auto",name:"Auto",provider:"workbuddy",isDefault:!0,supportedReasoningEfforts:["minimal","low","medium","high","xhigh","max"].map(e=>({id:e,name:M(e)})),defaultReasoningEffort:"medium"}]}function k(e){return e.split("-").map(n=>/^\d/.test(n)?n:E(n)).join(" ")}function _(e,n,t=!1){const o=n.toLowerCase().replace(/\s+/g,"-");return`gemini-${e}-${o}${t?"-preview":""}`}function I(e){const n=[],t=g(e);for(const o of t.split(`
2
+ `)){const i=o.trim().match(/^(\S+)\s+-\s+(.+?)(?:\s+\(([^)]+)\))?$/);if(!i)continue;const[,s,r,a]=i,u=a?.split(",").map(c=>c.trim().toLowerCase())??[];n.push({id:s,name:r.trim()||k(s),description:a?.trim(),isDefault:u.includes("default")||u.includes("current")})}return d(n)}function U(e){try{const t=(JSON.parse(e).models??[]).filter(o=>o.available).map(o=>({id:o.key,name:o.name?.trim()||o.key,provider:o.key.split("/")[0],description:o.tags?.join(", "),isDefault:o.tags?.includes("default")??!1}));return d(t)}catch{return[]}}function B(e){const n=g(e).split(`
3
+ `).map(t=>t.trim()).filter(Boolean).filter(t=>!t.includes(" ")).map(t=>({id:t,name:t,provider:t.includes("/")?t.split("/")[0]:void 0}));return d(n)}function j(e){const n=g(e).replace(/\s+/g," "),t=[[/\d+\.Default\(recommended\).*?(?:Sonnet|currently\s*Sonnet)\s*([\d.]+)/i,"default","Default (recommended)"],[/\d+\.Best.*?Opus\s*([\d.]+)/i,"best","Best","Most capable available model"],[/\d+\.Opus\(1Mcontext\).*?Opus\s*([\d.]+)/i,"opus[1m]","Opus (1M context)"],[/\d+\.OpusPlan.*?Opus\s*([\d.]+)/i,"opusplan","Opus Plan","Opus for planning \xB7 Sonnet for execution"],[/\d+\.Opus(?!\(1Mcontext\)).*?Opus\s*([\d.]+)/i,"opus","Opus"],[/\d+\.Sonnet\(1Mcontext\).*?Sonnet\s*([\d.]+)/i,"sonnet[1m]","Sonnet (1M context)"],[/\d+\.Sonnet(?!\(1Mcontext\)).*?Sonnet\s*([\d.]+)/i,"sonnet","Sonnet"],[/\d+\.Haiku.*?Haiku\s*([\d.]+)/i,"haiku","Haiku"]],o=[];for(const[a,u,c,l]of t){const p=n.match(a);p&&o.push(h({id:u,name:c,description:l?`${l} \xB7 v${p[1]}`:`v${p[1]}`,provider:"anthropic",isDefault:u==="default"}))}if(o.length>0)return d(o);const i=[],s=n.match(/currently\s*(Sonnet|Opus|Haiku)\s*([34](?:\.\d)?)/i),r={sonnet:"sonnet",opus:"opus",haiku:"haiku"};for(const a of n.matchAll(/\b(Sonnet|Opus|Haiku)\s*([34](?:\.\d)?)\b/gi)){const u=(a[1]??"").toLowerCase(),c=r[u];if(!c)continue;const l=a[2]??"",p=s&&s[1]?.toLowerCase()===u&&s[2]===l;i.push(h({id:c,name:`${E(u)} ${l}`,provider:"anthropic",isDefault:!!p}))}return d(i)}function T(e,n){const t=Math.max(e.length,n.length);for(let o=0;o<t;o++){const i=e[o]??-1,s=n[o]??-1;if(i!==s)return i-s}return 0}function w(e,n){const t=e.match(new RegExp(`^claude-${n}-([0-9]+(?:-[0-9]+)*)$`,"i"));if(!t?.[1])return null;const o=t[1].split("-").map(i=>Number.parseInt(i,10)).filter(i=>Number.isFinite(i));return o.length===0||o.length>2?null:o}function $(e){if(e?.length)return`v${e.join(".")}`}const y={default:"Default (recommended)",sonnet:"Sonnet",opus:"Opus",haiku:"Haiku"},L={default:"ANTHROPIC_MODEL",sonnet:"ANTHROPIC_DEFAULT_SONNET_MODEL",opus:"ANTHROPIC_DEFAULT_OPUS_MODEL",haiku:"ANTHROPIC_DEFAULT_HAIKU_MODEL"},P=[{id:"max",name:"Max"}],G=[{id:"low",name:"Low"},{id:"medium",name:"Medium"},{id:"high",name:"High"},{id:"xhigh",name:"Extra High"},{id:"max",name:"Max"}];function h(e){return{...e,supportedReasoningEfforts:G,defaultReasoningEffort:"medium"}}function x(e,n){return e[n]?.trim()||null}function A(e,n){const t=x(n,"ANTHROPIC_BASE_URL")?.toLowerCase()??"";return t.includes("deepseek.com")||e.toLowerCase().startsWith("deepseek-")?"deepseek":t?"custom":"anthropic"}function D(e){const n=new Set;for(const o of Object.values(L)){const i=x(e,o);i&&n.add(i)}const t=Array.from(n).map((o,i)=>{const s=A(o,e),r={id:o,name:o,provider:s,isDefault:i===0};return s==="deepseek"?{...r,supportedReasoningEfforts:P,defaultReasoningEffort:x(e,"CLAUDE_CODE_EFFORT_LEVEL")??"max"}:h(r)});return d(t)}function V(e=process.env){return D(e)}function N(e,n=process.env){return e.map(t=>{if(!["default","sonnet","opus","haiku"].includes(t.id))return t;const o=t.id,i=x(n,L[o]);if(!i)return t;const r=`Claude Code alias: ${y[o]}`;return{...t,name:i,description:t.description?`${r} \xB7 ${t.description}`:r,provider:A(i,n)}})}function z(e){const n=g(e),t=new Map;for(const i of["sonnet","opus","haiku"])for(const s of n.matchAll(new RegExp(`\\bclaude-${i}-[0-9.-]+\\b`,"gi"))){const r=s[0].trim().toLowerCase().replace(/\./g,"-").replace(/-+$/g,""),a=w(r,i);if(!a)continue;const u=t.get(i);(!u||T(u,a)<0)&&t.set(i,a)}const o=[];for(const i of["default","sonnet","opus","haiku"]){if(!new RegExp(`\\b${i}\\b`,"i").test(n))continue;const s=(i==="default"?t.get("sonnet"):t.get(i))??null;o.push(h({id:i,name:y[i],description:$(s),provider:"anthropic",isDefault:i==="default"}))}return d(o)}function q(e=process.env){const n=D(e);return n.length>0?n:N([{id:"default",name:"Default (recommended)",description:"Recommended model for your account",provider:"anthropic",isDefault:!0},{id:"best",name:"Best",description:"Most capable available model \xB7 currently Opus",provider:"anthropic"},{id:"opus",name:"Opus",description:"Latest Opus \xB7 complex reasoning",provider:"anthropic"},{id:"opus[1m]",name:"Opus (1M context)",description:"Latest Opus \xB7 long sessions",provider:"anthropic"},{id:"sonnet",name:"Sonnet",description:"Latest Sonnet \xB7 everyday coding",provider:"anthropic"},{id:"sonnet[1m]",name:"Sonnet (1M context)",description:"Latest Sonnet \xB7 long sessions",provider:"anthropic"},{id:"haiku",name:"Haiku",description:"Fast and efficient \xB7 simple tasks",provider:"anthropic"},{id:"opusplan",name:"Opus Plan",description:"Opus for planning \xB7 Sonnet for execution",provider:"anthropic"}],e).map(h)}function K(e){const n=g(e),t=[];for(const o of n.split(`
4
+ `)){const i=o.match(/\b(gpt-[a-z0-9][a-z0-9.-]*)\b/i);if(!i)continue;const s=i[1].trim(),r=o.replace(s,"").replace(/^[^\w]+/,"").trim()||void 0;t.push({id:s,name:b(s),description:r,provider:"openai",isDefault:/\bcurrent\b/i.test(o)||/\bselected\b/i.test(o)})}return d(t)}function W(e){const n=typeof e=="object"&&e!==null?e:{},t=typeof n.config?.model=="string"?n.config.model:void 0,o=typeof n.config?.model_reasoning_effort=="string"?n.config.model_reasoning_effort:void 0,i=[];for(const s of n.data??[]){if(typeof s!="object"||s===null)continue;const r=s,a=typeof r.id=="string"?r.id:typeof r.model=="string"?r.model:"";if(!a)continue;const u=typeof r.displayName=="string"?r.displayName:typeof r.name=="string"?r.name:void 0,c=typeof r.description=="string"?r.description:void 0,l=typeof r.defaultReasoningEffort=="string"?r.defaultReasoningEffort:void 0,p=Array.isArray(r.supportedReasoningEfforts)?r.supportedReasoningEfforts.map(f=>{if(typeof f!="object"||f===null)return null;const m=f,v=typeof m.reasoningEffort=="string"?m.reasoningEffort:typeof m.id=="string"?m.id:"";return v?{id:v,name:M(v),description:typeof m.description=="string"?m.description:void 0}:null}).filter(f=>f!=null):void 0,S=Array.isArray(r.additionalSpeedTiers)?r.additionalSpeedTiers.filter(f=>typeof f=="string"):void 0;i.push({id:a,name:u||b(a),description:c,provider:"openai",isDefault:t?t===a:r.isDefault===!0,supportedReasoningEfforts:p,defaultReasoningEffort:l,additionalSpeedTiers:S})}return t&&!i.some(s=>s.id===t)&&i.unshift({id:t,name:b(t),provider:"openai",isDefault:!0,defaultReasoningEffort:o}),R(d(i),t)}function J(e){const n=g(e),t=[];for(const o of n.matchAll(/\b(?:auto-)?gemini-[a-z0-9.-]+\b/gi)){const i=o[0].trim();t.push({id:i,name:i,provider:"google",isDefault:/\bcurrent\b/i.test(n)&&n.includes(i)})}for(const o of n.matchAll(/\bGemini\s*(\d(?:\.\d)?)\s*(Pro|Flash(?:[- ]Lite)?)\s*(Preview)?\b/gi)){const i=o[1]??"",s=(o[2]??"").replace(/\s+/g,"-"),r=!!o[3],a=_(i,s,r);t.push({id:a,name:`Gemini ${i} ${s.replace(/-/g," ")}`.trim(),provider:"google",isDefault:/\bcurrent\b/i.test(n)&&n.includes(o[0]??"")})}for(const o of n.matchAll(/\bAuto\s*Gemini\s*(\d(?:\.\d)?)\b/gi)){const i=o[1]??"",s=`auto-gemini-${i}`;t.push({id:s,name:`Auto Gemini ${i}`,provider:"google",isDefault:/\bcurrent\b/i.test(n)&&n.includes(o[0]??"")})}return d(t)}function X(){return[{id:"gemini-2.5-pro",name:"Gemini 2.5 Pro",provider:"google",isDefault:!0},{id:"gemini-2.5-flash",name:"Gemini 2.5 Flash",provider:"google"},{id:"auto-gemini-2.5",name:"Auto Gemini 2.5",provider:"google"}]}export{N as applyClaudeModelEnvOverrides,V as discoverClaudeAliasModelsFromEnv,q as fallbackClaudeAliasModels,H as fallbackCodexModels,X as fallbackGeminiModels,F as fallbackWorkBuddyModels,A as inferClaudeOverrideProvider,z as parseClaudeBinaryModels,j as parseClaudeModels,W as parseCodexAppServerModels,K as parseCodexModels,I as parseCursorModels,J as parseGeminiModels,U as parseOpenClawModels,B as parseOpenCodeModels,x as readEnvValue,g as stripAnsi};
@@ -13,4 +13,11 @@ export declare function buildWindowsScheduledTaskXml(input: {
13
13
  command: string;
14
14
  arguments: string[];
15
15
  }): string;
16
+ export declare function buildWindowsScheduledTaskCommands(input: {
17
+ taskName: string;
18
+ xmlPath: string;
19
+ }): {
20
+ create: string;
21
+ run: string;
22
+ };
16
23
  export {};
@@ -1,4 +1,4 @@
1
- import i from"node:path";function a(e){return e.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;").replace(/'/g,"&apos;")}function d(e){return`"${e.replace(/\\/g,"\\\\").replace(/"/g,'\\"')}"`}function o(e){return`"${e.replace(/"/g,'""')}"`}function l(e){return e.replace(/"/g,'""')}function n(e){return a(e)}function s(e){const t=i.extname(e).toLowerCase();return t===".cmd"||t===".bat"}function m(e,t){const r=[e.command,...e.args].map(o).join(" ");return["@echo off","setlocal",'if not defined SHENNIAN_HOME set "SHENNIAN_HOME=%~dp0."',`${s(e.command)?`call ${r}`:r} >> ${o(t)} 2>&1`,""].join(`\r
1
+ import a from"node:path";function i(e){return e.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;").replace(/'/g,"&apos;")}function d(e){return`"${e.replace(/\\/g,"\\\\").replace(/"/g,'\\"')}"`}function n(e){return`"${e.replace(/"/g,'""')}"`}function l(e){return e.replace(/"/g,'""')}function r(e){return i(e)}function s(e){const t=a.extname(e).toLowerCase();return t===".cmd"||t===".bat"}function m(e,t){const o=[e.command,...e.args].map(n).join(" ");return["@echo off","setlocal",'if not defined SHENNIAN_HOME set "SHENNIAN_HOME=%~dp0."',`${s(e.command)?`call ${o}`:o} >> ${n(t)} 2>&1`,""].join(`\r
2
2
  `)}function g(e){return['Set shell = CreateObject("WScript.Shell")',`shell.Run Chr(34) & "${l(e)}" & Chr(34), 0, False`,""].join(`\r
3
3
  `)}function p(e){const t=e.arguments.join(" ");return`<?xml version="1.0" encoding="UTF-16"?>
4
4
  <Task version="1.4" xmlns="http://schemas.microsoft.com/windows/2004/02/mit/task">
@@ -6,9 +6,13 @@ import i from"node:path";function a(e){return e.replace(/&/g,"&amp;").replace(/<
6
6
  <Description>Shennian Agent Daemon</Description>
7
7
  </RegistrationInfo>
8
8
  <Triggers>
9
+ <BootTrigger>
10
+ <Enabled>true</Enabled>
11
+ <Delay>PT15S</Delay>
12
+ </BootTrigger>
9
13
  <LogonTrigger>
10
14
  <Enabled>true</Enabled>
11
- <UserId>${n(e.userId)}</UserId>
15
+ <UserId>${r(e.userId)}</UserId>
12
16
  </LogonTrigger>
13
17
  <EventTrigger>
14
18
  <Enabled>true</Enabled>
@@ -22,8 +26,8 @@ import i from"node:path";function a(e){return e.replace(/&/g,"&amp;").replace(/<
22
26
  </Triggers>
23
27
  <Principals>
24
28
  <Principal id="Author">
25
- <UserId>${n(e.userId)}</UserId>
26
- <LogonType>InteractiveToken</LogonType>
29
+ <UserId>${r(e.userId)}</UserId>
30
+ <LogonType>S4U</LogonType>
27
31
  <RunLevel>LeastPrivilege</RunLevel>
28
32
  </Principal>
29
33
  </Principals>
@@ -42,7 +46,7 @@ import i from"node:path";function a(e){return e.replace(/&/g,"&amp;").replace(/<
42
46
  <Enabled>true</Enabled>
43
47
  <Hidden>true</Hidden>
44
48
  <RunOnlyIfIdle>false</RunOnlyIfIdle>
45
- <WakeToRun>false</WakeToRun>
49
+ <WakeToRun>true</WakeToRun>
46
50
  <ExecutionTimeLimit>PT0S</ExecutionTimeLimit>
47
51
  <Priority>7</Priority>
48
52
  <RestartOnFailure>
@@ -52,8 +56,8 @@ import i from"node:path";function a(e){return e.replace(/&/g,"&amp;").replace(/<
52
56
  </Settings>
53
57
  <Actions Context="Author">
54
58
  <Exec>
55
- <Command>${n(e.command)}</Command>
56
- <Arguments>${n(t)}</Arguments>
59
+ <Command>${r(e.command)}</Command>
60
+ <Arguments>${r(t)}</Arguments>
57
61
  </Exec>
58
62
  </Actions>
59
- </Task>`}export{m as buildWindowsLauncherCommand,p as buildWindowsScheduledTaskXml,g as buildWindowsStartupVbs,a as escapeXml,s as isWindowsCmdScript,o as quoteCmdArg,d as quoteSystemdArg};
63
+ </Task>`}function S(e){return{create:`schtasks /create /tn ${n(e.taskName)} /xml ${n(e.xmlPath)} /f`,run:`schtasks /run /tn ${n(e.taskName)}`}}export{m as buildWindowsLauncherCommand,S as buildWindowsScheduledTaskCommands,p as buildWindowsScheduledTaskXml,g as buildWindowsStartupVbs,i as escapeXml,s as isWindowsCmdScript,n as quoteCmdArg,d as quoteSystemdArg};
@@ -1,6 +1,6 @@
1
1
  import { spawn } from 'node:child_process';
2
2
  import type { Command } from 'commander';
3
- export { buildWindowsLauncherCommand, buildWindowsScheduledTaskXml, buildWindowsStartupVbs, } from './daemon-windows.js';
3
+ export { buildWindowsLauncherCommand, buildWindowsScheduledTaskCommands, buildWindowsScheduledTaskXml, buildWindowsStartupVbs, } from './daemon-windows.js';
4
4
  export { isShennianRunServiceCommand } from './daemon-process.js';
5
5
  export declare function isSafeSnapshotEnvKey(key: string): boolean;
6
6
  type Platform = 'darwin' | 'linux' | 'win32';
@@ -70,6 +70,9 @@ export declare function saveEnvSnapshot(): void;
70
70
  export declare function startDaemonProcess(opts?: {
71
71
  quiet?: boolean;
72
72
  }): void;
73
+ export declare function shouldReplaceRunningDaemon(status: Pick<DaemonStatus, 'pid' | 'running' | 'adopted'>, record?: {
74
+ version?: string;
75
+ } | null, currentVersion?: string): boolean;
73
76
  /**
74
77
  * Install the platform-native auto-start service.
75
78
  * Returns true if the service was immediately started (so caller can skip startDaemonProcess).
@@ -1,13 +1,13 @@
1
- import s from"chalk";import o from"node:fs";import c from"node:path";import u from"node:os";import{execSync as a,spawn as ae}from"node:child_process";import{randomUUID as ce}from"node:crypto";import{fileURLToPath as ue}from"node:url";import{getShennianDir as de,loadConfig as j,resolveShennianPath as h,saveConfig as le}from"../config/index.js";import{buildAugmentedPath as pe}from"../env-path.js";import{buildWindowsLauncherCommand as me,buildWindowsScheduledTaskXml as fe,buildWindowsStartupVbs as Se,escapeXml as N,isWindowsCmdScript as he,quoteCmdArg as W,quoteSystemdArg as ge}from"./daemon-windows.js";import{waitForDaemonReadyStatus as b}from"./daemon-start-wait.js";import{findRunningWindowsDaemonProcessIds as ye,isShennianRunServiceCommand as we}from"./daemon-process.js";import{buildWindowsLauncherCommand as Sn,buildWindowsScheduledTaskXml as hn,buildWindowsStartupVbs as gn}from"./daemon-windows.js";import{isShennianRunServiceCommand as wn}from"./daemon-process.js";const Ee=c.dirname(ue(import.meta.url)),g=de(),p=h("daemon.pid"),d=h("daemon.log"),L=h("remote-access.disabled"),P=h("daemon-launcher.json"),F=c.resolve(Ee,"../../bin/shennian.js"),B=process.execPath,V=new Set(["PATH","HOME","USERPROFILE","HOMEDRIVE","HOMEPATH","USERNAME","USERDOMAIN","COMPUTERNAME","USER","LOGNAME","SHELL","TMPDIR","LANG","LC_ALL","LC_CTYPE","SSH_AUTH_SOCK","XDG_CONFIG_HOME","XDG_DATA_HOME","TEMP","TMP","APPDATA","LOCALAPPDATA","SHENNIAN_DESKTOP_SERVER_URL","SHENNIAN_WECHAT_CHANNEL_HELPER_DIR","SHENNIAN_HOME","SHENNIAN_NATIVE_FUSION_DISABLED","SHENNIAN_WECHAT_DELIVERABILITY_TRACE"]);function ve(e){return V.has(e)}function l(){const e=u.platform();return e==="darwin"||e==="linux"||e==="win32"?e:"linux"}function R(e){const n=e.replace(/\\/g,"/").toLowerCase(),t=u.tmpdir().replace(/\\/g,"/").toLowerCase();return n.includes("/_npx/")||n.includes("/npm-cache/_npx/")||n.includes("/pnpm/dlx/")||n.startsWith(t.endsWith("/")?t:`${t}/`)}function Ae(e){return o.existsSync(e.scriptPath)&&!R(e.scriptPath)?{command:e.nodeExec,args:[e.scriptPath,"run-service"],mode:"direct"}:e.shennianCommandPath&&!R(e.shennianCommandPath)?{command:e.shennianCommandPath,args:["run-service"],mode:"global-shim"}:e.npxPath?{command:e.npxPath,args:["--yes","shennian","run-service"],mode:"npx"}:{command:e.nodeExec,args:[e.scriptPath,"run-service"],mode:"direct"}}function Ie(e){const n=e.trim();if(!n)return null;if(n.startsWith("{"))try{const r=JSON.parse(n),i=Number(r.pid);return!Number.isInteger(i)||i<=0?null:{pid:i,...typeof r.instanceId=="string"?{instanceId:r.instanceId}:{},...typeof r.version=="string"?{version:r.version}:{},...r.launcher==="desktop-managed"||r.launcher==="global-cli"||r.launcher==="unknown"?{launcher:r.launcher}:{},...typeof r.startedAt=="string"?{startedAt:r.startedAt}:{},...r.adopted===!0?{adopted:!0}:{}}}catch{return null}const t=parseInt(n,10);return isNaN(t)?null:{pid:t}}function O(){try{return Ie(o.readFileSync(p,"utf-8"))}catch{return null}}function ke(){return O()?.pid??null}function w(e){try{return process.kill(e,0),!0}catch{return!1}}function Pe(e,n=3e3){const t=Date.now();for(;Date.now()-t<n;){if(!w(e))return!0;Atomics.wait(new Int32Array(new SharedArrayBuffer(4)),0,0,100)}return!w(e)}function De(){return o.existsSync(L)}function Ne(){try{o.unlinkSync(L)}catch{}}function J(){return"global-cli"}function be(){return`${process.pid}-${Date.now()}-${ce()}`}function Le(e,n,t={}){o.mkdirSync(g,{recursive:!0}),o.writeFileSync(p,JSON.stringify({pid:e,instanceId:n,...t.version?{version:t.version}:{},launcher:t.launcher??J(),...t.adopted?{adopted:!0}:{},startedAt:new Date().toISOString()},null,2))}function dn(e,n){const t=O();if(!(t?.pid!==e||t.instanceId!==n))try{o.unlinkSync(p)}catch{}}function G(e,n=J(),t){o.mkdirSync(g,{recursive:!0}),o.writeFileSync(P,JSON.stringify({pid:e,launcher:n,...t?{instanceId:t}:{},updatedAt:new Date().toISOString()},null,2))}function T(e){if(e)try{if(JSON.parse(o.readFileSync(P,"utf-8")).instanceId!==e)return}catch{return}try{o.unlinkSync(P)}catch{}}function Re(e){e&&G(e)}function Oe(e,n){if(!e||!n)return"unknown";try{const t=JSON.parse(o.readFileSync(P,"utf-8"));if(t.pid!==e)return"unknown";if(t.launcher==="desktop-managed"||t.launcher==="global-cli")return t.launcher}catch{}return x(e)}function x(e){if(l()==="win32")return"unknown";try{const n=a(`ps -p ${e} -o command=`,{encoding:"utf-8",stdio:["ignore","pipe","ignore"],timeout:1e3,windowsHide:!0}).replace(/\\/g,"/");if(n.includes("/node_modules/shennian/")||n.includes("/bin/shennian")||n.includes(" shennian run-service")||n.includes(" shennian.js run-service"))return"global-cli"}catch{}return"unknown"}function K(e=process.pid){if(l()==="win32")return ye(e);try{return a("ps -axo pid=,command=",{encoding:"utf-8",stdio:["ignore","pipe","ignore"],timeout:1e3,windowsHide:!0}).split(/\r?\n/).map(t=>{const r=t.trim().match(/^(\d+)\s+(.+)$/);if(!r)return null;const i=Number(r[1]),S=r[2];return!Number.isInteger(i)||i===e?null:we(S)?i:null}).filter(t=>typeof t=="number")}catch{return[]}}function ln(e=process.env,n=g,t=u.tmpdir()){if(e.SHENNIAN_E2E_ISOLATED_DAEMON!=="1"||!e.SHENNIAN_HOME?.trim())return!1;const r=c.relative(c.resolve(t),c.resolve(n));return r!==""&&r!==".."&&!r.startsWith(`..${c.sep}`)&&!c.isAbsolute(r)}function f(e={}){let n=O(),t=n?.pid??null,r=t!==null&&w(t),i=t!==null&&!r,S=n?.adopted===!0;const E=j();if(i&&e.cleanupStale){try{o.unlinkSync(p)}catch{}n=null,t=null,r=!1,i=!1}if(!r){const y=K()[0];if(y&&(t=y,r=!0,i=!1,S=!0,e.cleanupStale)){const C=be();Le(y,C,{launcher:x(y),adopted:!0}),G(y,x(y)),n={pid:y,instanceId:C,adopted:!0}}}return{running:r,pid:t,stale:i,remoteAccessDisabled:De(),launcher:Oe(t,r),platform:l(),shennianDir:g,pidFile:p,logFile:d,...n?.instanceId?{instanceId:n.instanceId}:{},...S?{adopted:!0}:{},...E.machineId?{machineId:E.machineId}:{},paired:!!(E.machineToken&&E.machineId),...E.serverUrl?{serverUrl:E.serverUrl}:{}}}function v(e){process.stdout.write(`${JSON.stringify(e,null,2)}
2
- `)}function X(e){const n=e?.trim();if(!n)return;const t=j();t.serverUrl=n,le(t)}function q(e){return e?.trim()||process.env.SHENNIAN_DESKTOP_SERVER_URL?.trim()||void 0}const $="com.shennian.agent",m=c.join(u.homedir(),"Library/LaunchAgents",`${$}.plist`),Te=c.join(u.homedir(),"AppData","Roaming","Microsoft","Windows","Start Menu","Programs","Startup"),H=h("autostart.cmd"),_=h("autostart.vbs"),M=h("autostart.xml"),xe=c.join(Te,"ShennianAgent.vbs");function Y(e){const n=l()==="win32"?`where ${e}`:`command -v ${e}`;try{return a(n,{stdio:["ignore","pipe","pipe"],encoding:"utf-8",windowsHide:!0}).split(/\r?\n/).map(i=>i.trim()).find(Boolean)??null}catch{return null}}function $e(){const e=l()==="win32"?"npx.cmd":"npx",n=c.join(c.dirname(B),e);return o.existsSync(n)?n:Y("npx")}function A(){return Ae({nodeExec:B,scriptPath:F,shennianCommandPath:Y("shennian"),npxPath:$e()})}function z(){try{a(`schtasks /delete /tn "${I}" /f`,{stdio:"pipe",windowsHide:!0})}catch{}}function Q(){try{o.unlinkSync(xe)}catch{}}function He(){const e=process.env.USERDOMAIN?.trim(),n=process.env.COMPUTERNAME?.trim(),t=process.env.USERNAME?.trim()||u.userInfo().username;return e&&e.toUpperCase()!=="WORKGROUP"?`${e}\\${t}`:n?`${n}\\${t}`:t}function _e(e){if(l()==="win32"&&he(e.command)){const n=[e.command,...e.args].map(W).join(" ");return{command:process.env.ComSpec||"cmd.exe",args:["/d","/s","/c",`"${n}"`],windowsVerbatimArguments:!0}}return{command:e.command,args:e.args}}function Me(e,n,t=process.env){return{detached:!0,stdio:["ignore",n,n],env:t,windowsHide:!0,...e.windowsVerbatimArguments?{windowsVerbatimArguments:!0}:{}}}function Ue(){const e=A();o.writeFileSync(H,me(e,d)),o.writeFileSync(_,Se(H)),Q(),z();const n=fe({userId:He(),command:c.join(process.env.SystemRoot||"C:\\Windows","System32","wscript.exe"),arguments:[W(_)]});o.writeFileSync(M,n,"utf8");try{return a(`schtasks /create /tn "${I}" /xml "${M}" /f`,{stdio:"pipe",windowsHide:!0}),a(`schtasks /run /tn "${I}"`,{stdio:"pipe",windowsHide:!0}),!0}catch{return!1}}function Z(){const e={};for(const n of V)process.env[n]&&(e[n]=process.env[n]);if(e.HOME??=u.homedir(),e.PATH=pe({pathValue:e.PATH,env:e}),e.USER??=u.userInfo().username,l()==="win32"){const n=process.env.TEMP||process.env.TMP||u.tmpdir(),t=u.homedir();e.USERPROFILE??=t;const r=c.win32.parse(t);e.HOMEDRIVE??=r.root.replace(/[\\/]$/,"")||process.env.HOMEDRIVE||"",e.HOMEPATH??=t.slice((e.HOMEDRIVE||"").length)||process.env.HOMEPATH||"",e.USERNAME??=process.env.USERNAME||u.userInfo().username,e.COMPUTERNAME??=process.env.COMPUTERNAME||"",e.TMPDIR??=n,e.TEMP??=n,e.TMP??=n}else e.TMPDIR??="/tmp";return e}function Ce(){const e=Z(),n=A(),t=Object.entries(e).map(([i,S])=>` <key>${N(i)}</key>
3
- <string>${N(S)}</string>`).join(`
4
- `),r=[n.command,...n.args].map(i=>` <string>${N(i)}</string>`).join(`
1
+ import s from"chalk";import i from"node:fs";import c from"node:path";import u from"node:os";import{execSync as a,spawn as ue}from"node:child_process";import{randomUUID as de}from"node:crypto";import{fileURLToPath as le}from"node:url";import{getShennianDir as pe,loadConfig as j,resolveShennianPath as h,saveConfig as me}from"../config/index.js";import{buildAugmentedPath as fe}from"../env-path.js";import{buildWindowsLauncherCommand as Se,buildWindowsScheduledTaskCommands as he,buildWindowsScheduledTaskXml as ge,buildWindowsStartupVbs as ye,escapeXml as b,isWindowsCmdScript as we,quoteCmdArg as W,quoteSystemdArg as Ee}from"./daemon-windows.js";import{waitForDaemonReadyStatus as L}from"./daemon-start-wait.js";import{findRunningWindowsDaemonProcessIds as ve,isShennianRunServiceCommand as Ie}from"./daemon-process.js";import{getCurrentVersion as ke}from"../upgrade/engine.js";import{buildWindowsLauncherCommand as wn,buildWindowsScheduledTaskCommands as En,buildWindowsScheduledTaskXml as vn,buildWindowsStartupVbs as In}from"./daemon-windows.js";import{isShennianRunServiceCommand as An}from"./daemon-process.js";const Ae=c.dirname(le(import.meta.url)),g=pe(),p=h("daemon.pid"),d=h("daemon.log"),R=h("remote-access.disabled"),P=h("daemon-launcher.json"),F=c.resolve(Ae,"../../bin/shennian.js"),B=process.execPath,V=new Set(["PATH","HOME","USERPROFILE","HOMEDRIVE","HOMEPATH","USERNAME","USERDOMAIN","COMPUTERNAME","USER","LOGNAME","SHELL","TMPDIR","LANG","LC_ALL","LC_CTYPE","SSH_AUTH_SOCK","XDG_CONFIG_HOME","XDG_DATA_HOME","TEMP","TMP","APPDATA","LOCALAPPDATA","SHENNIAN_DESKTOP_SERVER_URL","SHENNIAN_WECHAT_CHANNEL_HELPER_DIR","SHENNIAN_HOME","SHENNIAN_NATIVE_FUSION_DISABLED","SHENNIAN_WECHAT_DELIVERABILITY_TRACE"]);function Pe(e){return V.has(e)}function l(){const e=u.platform();return e==="darwin"||e==="linux"||e==="win32"?e:"linux"}function O(e){const n=e.replace(/\\/g,"/").toLowerCase(),t=u.tmpdir().replace(/\\/g,"/").toLowerCase();return n.includes("/_npx/")||n.includes("/npm-cache/_npx/")||n.includes("/pnpm/dlx/")||n.startsWith(t.endsWith("/")?t:`${t}/`)}function De(e){return i.existsSync(e.scriptPath)&&!O(e.scriptPath)?{command:e.nodeExec,args:[e.scriptPath,"run-service"],mode:"direct"}:e.shennianCommandPath&&!O(e.shennianCommandPath)?{command:e.shennianCommandPath,args:["run-service"],mode:"global-shim"}:e.npxPath?{command:e.npxPath,args:["--yes","shennian","run-service"],mode:"npx"}:{command:e.nodeExec,args:[e.scriptPath,"run-service"],mode:"direct"}}function Ne(e){const n=e.trim();if(!n)return null;if(n.startsWith("{"))try{const r=JSON.parse(n),o=Number(r.pid);return!Number.isInteger(o)||o<=0?null:{pid:o,...typeof r.instanceId=="string"?{instanceId:r.instanceId}:{},...typeof r.version=="string"?{version:r.version}:{},...r.launcher==="desktop-managed"||r.launcher==="global-cli"||r.launcher==="unknown"?{launcher:r.launcher}:{},...typeof r.startedAt=="string"?{startedAt:r.startedAt}:{},...r.adopted===!0?{adopted:!0}:{}}}catch{return null}const t=parseInt(n,10);return isNaN(t)?null:{pid:t}}function I(){try{return Ne(i.readFileSync(p,"utf-8"))}catch{return null}}function be(){return I()?.pid??null}function w(e){try{return process.kill(e,0),!0}catch{return!1}}function G(e,n=3e3){const t=Date.now();for(;Date.now()-t<n;){if(!w(e))return!0;Atomics.wait(new Int32Array(new SharedArrayBuffer(4)),0,0,100)}return!w(e)}function Le(){return i.existsSync(R)}function Re(){try{i.unlinkSync(R)}catch{}}function J(){return"global-cli"}function Oe(){return`${process.pid}-${Date.now()}-${de()}`}function Te(e,n,t={}){i.mkdirSync(g,{recursive:!0}),i.writeFileSync(p,JSON.stringify({pid:e,instanceId:n,...t.version?{version:t.version}:{},launcher:t.launcher??J(),...t.adopted?{adopted:!0}:{},startedAt:new Date().toISOString()},null,2))}function fn(e,n){const t=I();if(!(t?.pid!==e||t.instanceId!==n))try{i.unlinkSync(p)}catch{}}function K(e,n=J(),t){i.mkdirSync(g,{recursive:!0}),i.writeFileSync(P,JSON.stringify({pid:e,launcher:n,...t?{instanceId:t}:{},updatedAt:new Date().toISOString()},null,2))}function T(e){if(e)try{if(JSON.parse(i.readFileSync(P,"utf-8")).instanceId!==e)return}catch{return}try{i.unlinkSync(P)}catch{}}function xe(e){e&&K(e)}function He(e,n){if(!e||!n)return"unknown";try{const t=JSON.parse(i.readFileSync(P,"utf-8"));if(t.pid!==e)return"unknown";if(t.launcher==="desktop-managed"||t.launcher==="global-cli")return t.launcher}catch{}return x(e)}function x(e){if(l()==="win32")return"unknown";try{const n=a(`ps -p ${e} -o command=`,{encoding:"utf-8",stdio:["ignore","pipe","ignore"],timeout:1e3,windowsHide:!0}).replace(/\\/g,"/");if(n.includes("/node_modules/shennian/")||n.includes("/bin/shennian")||n.includes(" shennian run-service")||n.includes(" shennian.js run-service"))return"global-cli"}catch{}return"unknown"}function X(e=process.pid){if(l()==="win32")return ve(e);try{return a("ps -axo pid=,command=",{encoding:"utf-8",stdio:["ignore","pipe","ignore"],timeout:1e3,windowsHide:!0}).split(/\r?\n/).map(t=>{const r=t.trim().match(/^(\d+)\s+(.+)$/);if(!r)return null;const o=Number(r[1]),S=r[2];return!Number.isInteger(o)||o===e?null:Ie(S)?o:null}).filter(t=>typeof t=="number")}catch{return[]}}function Sn(e=process.env,n=g,t=u.tmpdir()){if(e.SHENNIAN_E2E_ISOLATED_DAEMON!=="1"||!e.SHENNIAN_HOME?.trim())return!1;const r=c.relative(c.resolve(t),c.resolve(n));return r!==""&&r!==".."&&!r.startsWith(`..${c.sep}`)&&!c.isAbsolute(r)}function f(e={}){let n=I(),t=n?.pid??null,r=t!==null&&w(t),o=t!==null&&!r,S=n?.adopted===!0;const E=j();if(o&&e.cleanupStale){try{i.unlinkSync(p)}catch{}n=null,t=null,r=!1,o=!1}if(!r){const y=X()[0];if(y&&(t=y,r=!0,o=!1,S=!0,e.cleanupStale)){const U=Oe();Te(y,U,{launcher:x(y),adopted:!0}),K(y,x(y)),n={pid:y,instanceId:U,adopted:!0}}}return{running:r,pid:t,stale:o,remoteAccessDisabled:Le(),launcher:He(t,r),platform:l(),shennianDir:g,pidFile:p,logFile:d,...n?.instanceId?{instanceId:n.instanceId}:{},...S?{adopted:!0}:{},...E.machineId?{machineId:E.machineId}:{},paired:!!(E.machineToken&&E.machineId),...E.serverUrl?{serverUrl:E.serverUrl}:{}}}function v(e){process.stdout.write(`${JSON.stringify(e,null,2)}
2
+ `)}function q(e){const n=e?.trim();if(!n)return;const t=j();t.serverUrl=n,me(t)}function Y(e){return e?.trim()||process.env.SHENNIAN_DESKTOP_SERVER_URL?.trim()||void 0}const H="com.shennian.agent",m=c.join(u.homedir(),"Library/LaunchAgents",`${H}.plist`),_e=c.join(u.homedir(),"AppData","Roaming","Microsoft","Windows","Start Menu","Programs","Startup"),_=h("autostart.cmd"),$=h("autostart.vbs"),C=h("autostart.xml"),$e=c.join(_e,"ShennianAgent.vbs");function z(e){const n=l()==="win32"?`where ${e}`:`command -v ${e}`;try{return a(n,{stdio:["ignore","pipe","pipe"],encoding:"utf-8",windowsHide:!0}).split(/\r?\n/).map(o=>o.trim()).find(Boolean)??null}catch{return null}}function Ce(){const e=l()==="win32"?"npx.cmd":"npx",n=c.join(c.dirname(B),e);return i.existsSync(n)?n:z("npx")}function k(){return De({nodeExec:B,scriptPath:F,shennianCommandPath:z("shennian"),npxPath:Ce()})}function Q(){try{a(`schtasks /delete /tn "${N}" /f`,{stdio:"pipe",windowsHide:!0})}catch{}}function Z(){try{i.unlinkSync($e)}catch{}}function Me(){const e=process.env.USERDOMAIN?.trim(),n=process.env.COMPUTERNAME?.trim(),t=process.env.USERNAME?.trim()||u.userInfo().username;return e&&e.toUpperCase()!=="WORKGROUP"?`${e}\\${t}`:n?`${n}\\${t}`:t}function Ue(e){if(l()==="win32"&&we(e.command)){const n=[e.command,...e.args].map(W).join(" ");return{command:process.env.ComSpec||"cmd.exe",args:["/d","/s","/c",`"${n}"`],windowsVerbatimArguments:!0}}return{command:e.command,args:e.args}}function je(e,n,t=process.env){return{detached:!0,stdio:["ignore",n,n],env:t,windowsHide:!0,...e.windowsVerbatimArguments?{windowsVerbatimArguments:!0}:{}}}function We(){const e=k();i.writeFileSync(_,Se(e,d)),i.writeFileSync($,ye(_)),Z(),Q();const n=ge({userId:Me(),command:c.join(process.env.SystemRoot||"C:\\Windows","System32","wscript.exe"),arguments:[W($)]});i.writeFileSync(C,n,"utf8");const t=he({taskName:N,xmlPath:C});try{return a(t.create,{stdio:"pipe",windowsHide:!0}),a(t.run,{stdio:"pipe",windowsHide:!0}),!0}catch{return!1}}function ee(){const e={};for(const n of V)process.env[n]&&(e[n]=process.env[n]);if(e.HOME??=u.homedir(),e.PATH=fe({pathValue:e.PATH,env:e}),e.USER??=u.userInfo().username,l()==="win32"){const n=process.env.TEMP||process.env.TMP||u.tmpdir(),t=u.homedir();e.USERPROFILE??=t;const r=c.win32.parse(t);e.HOMEDRIVE??=r.root.replace(/[\\/]$/,"")||process.env.HOMEDRIVE||"",e.HOMEPATH??=t.slice((e.HOMEDRIVE||"").length)||process.env.HOMEPATH||"",e.USERNAME??=process.env.USERNAME||u.userInfo().username,e.COMPUTERNAME??=process.env.COMPUTERNAME||"",e.TMPDIR??=n,e.TEMP??=n,e.TMP??=n}else e.TMPDIR??="/tmp";return e}function Fe(){const e=ee(),n=k(),t=Object.entries(e).map(([o,S])=>` <key>${b(o)}</key>
3
+ <string>${b(S)}</string>`).join(`
4
+ `),r=[n.command,...n.args].map(o=>` <string>${b(o)}</string>`).join(`
5
5
  `);return`<?xml version="1.0" encoding="UTF-8"?>
6
6
  <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
7
7
  <plist version="1.0">
8
8
  <dict>
9
9
  <key>Label</key>
10
- <string>${$}</string>
10
+ <string>${H}</string>
11
11
  <key>ProgramArguments</key>
12
12
  <array>
13
13
  ${r}
@@ -27,8 +27,8 @@ ${t}
27
27
  <key>StandardErrorPath</key>
28
28
  <string>${d}</string>
29
29
  </dict>
30
- </plist>`}const D=c.join(u.homedir(),".config/systemd/user/shennian.service");function je(){const e=Z(),n=A(),t=Object.entries(e).map(([i,S])=>`Environment=${i}=${S}`).join(`
31
- `),r=[n.command,...n.args].map(ge).join(" ");return`[Unit]
30
+ </plist>`}const D=c.join(u.homedir(),".config/systemd/user/shennian.service");function Be(){const e=ee(),n=k(),t=Object.entries(e).map(([o,S])=>`Environment=${o}=${S}`).join(`
31
+ `),r=[n.command,...n.args].map(Ee).join(" ");return`[Unit]
32
32
  Description=Shennian Agent Daemon
33
33
  After=network.target
34
34
 
@@ -41,6 +41,6 @@ StandardOutput=append:${d}
41
41
  StandardError=append:${d}
42
42
 
43
43
  [Install]
44
- WantedBy=default.target`}const I="ShennianAgent";function We(e){a(e,{stdio:"pipe",windowsHide:!0})}function Fe(){const e=process.getuid?.();if(typeof e=="number")return e;const n=u.userInfo();return typeof n.uid=="number"?n.uid:n.username}function ee(e=Fe()){return`gui/${e}/${$}`}function Be(e=We){try{return e(`launchctl unload "${m}" 2>/dev/null; launchctl load -w "${m}"`),e(`launchctl kickstart -k "${ee()}"`),!0}catch{try{return e(`launchctl load -w "${m}"`),e(`launchctl kickstart -k "${ee()}"`),!0}catch{return!1}}}function Ve(){o.mkdirSync(g,{recursive:!0});const e={};for(const[n,t]of Object.entries(process.env))t!==void 0&&ve(n)&&(e[n]=t);o.writeFileSync(h("env.json"),JSON.stringify(e,null,2))}function ne(e={}){o.mkdirSync(g,{recursive:!0});const n=f({cleanupStale:!0});if(n.pid!==null&&n.running&&!n.adopted){e.quiet||console.log(s.green(`\u2713 Background service already running (PID ${n.pid})`));return}te(n);const t=o.openSync(d,"a"),r=_e(A()),i=ae(r.command,r.args,Me(r,t));i.unref(),o.closeSync(t),Re(i.pid),e.quiet||(console.log(s.green(`\u2713 Background service started (PID ${i.pid})`)),console.log(s.gray(` Logs: ${d}`)))}function te(e=f({cleanupStale:!0})){if(!(e.pid===null||!e.running||!e.adopted))try{process.kill(e.pid,"SIGTERM"),Pe(e.pid);try{o.unlinkSync(p)}catch{}}catch{}}function re(){o.mkdirSync(g,{recursive:!0});const e=l();switch(A().mode==="direct"&&R(F)&&console.warn(s.yellow("\u26A0 Warning: Current CLI path is temporary (npx). Auto-start may not work after reboot.\n Run `npm install -g shennian@latest` for reliable auto-start.")),e){case"darwin":{const t=c.dirname(m);return o.mkdirSync(t,{recursive:!0}),o.writeFileSync(m,Ce()),Be()}case"linux":{const t=c.dirname(D);o.mkdirSync(t,{recursive:!0}),o.writeFileSync(D,je());try{a("systemctl --user daemon-reload && systemctl --user enable shennian",{stdio:"pipe",windowsHide:!0})}catch{return!1}try{a(`loginctl enable-linger ${u.userInfo().username}`,{stdio:"pipe",windowsHide:!0})}catch{}try{return a("systemctl --user restart shennian",{stdio:"pipe",windowsHide:!0}),!0}catch{return!1}}case"win32":return Ue()}}function Je(){const n=f({cleanupStale:!0}).pid;if(n===null)return{};if(!w(n)){try{o.unlinkSync(p)}catch{}return{stalePid:n}}try{return process.kill(n,"SIGTERM"),{stoppedPid:n}}catch(t){return{error:t instanceof Error?t.message:String(t)}}}async function Ge(e=5e3){const n=Je();if(!n.stoppedPid)return n;if(!await k(n.stoppedPid,e))try{process.kill(n.stoppedPid,"SIGKILL"),await k(n.stoppedPid,2e3)}catch(r){return{...n,error:r instanceof Error?r.message:String(r)}}try{o.unlinkSync(p)}catch{}T();for(const r of K())if(r!==n.stoppedPid)try{process.kill(r,"SIGTERM"),await k(r,2e3)}catch{}return n}function Ke(e={}){X(q(e.api)),Ne(),te(),re()||ne({quiet:e.json}),e.json?v(b(()=>f({cleanupStale:!0}))):console.log(s.green("\u2713 Background service started"))}async function Xe(e={}){switch(o.mkdirSync(g,{recursive:!0}),o.writeFileSync(L,new Date().toISOString()),l()){case"darwin":{if(o.existsSync(m))try{a(`launchctl unload -w "${m}"`,{stdio:"pipe",windowsHide:!0})}catch{}break}case"linux":{try{a("systemctl --user disable --now shennian",{stdio:"pipe",windowsHide:!0})}catch{}break}case"win32":{try{a(`schtasks /change /tn "${I}" /disable`,{stdio:"pipe",windowsHide:!0})}catch{}try{a(`schtasks /end /tn "${I}"`,{stdio:"pipe",windowsHide:!0})}catch{}break}}const t=await Ge(),r=f({cleanupStale:!0});if(e.json){v(t.error?{...r,error:t.error}:r);return}t.error?console.error(s.red(`\u2717 Failed to stop: ${t.error}`)):console.log(s.green("\u2713 Background service stopped"))}function oe(e){Ve(),Ke(e)}async function U(e={}){await Xe(e)}async function k(e,n=5e3){const t=Date.now();for(;Date.now()-t<n;){if(!w(e))return!0;await new Promise(r=>setTimeout(r,100))}return!w(e)}async function qe(e={}){X(q(e.api));const n=ke();if(n!==null&&w(n))try{process.kill(n,"SIGTERM"),await k(n)||(process.kill(n,"SIGKILL"),await k(n,2e3));try{o.unlinkSync(p)}catch{}T(),e.json||console.log(s.green(`\u2713 Background service stopped (PID ${n})`))}catch(t){const r=t instanceof Error?t.message:String(t);e.json?v({...f(),error:r}):console.error(s.red(`\u2717 Failed to stop: ${r}`));return}else if(n!==null){try{o.unlinkSync(p)}catch{}T(),e.json||console.log(s.yellow(`\u26A0 Service process no longer exists, cleaned up stale PID ${n}`))}else e.json||console.log(s.gray("\u25CF Background service not running, starting it now"));if(l()==="linux"&&re()){e.json&&v(b(()=>f({cleanupStale:!0})));return}ne({quiet:e.json}),e.json&&v(b(()=>f({cleanupStale:!0})))}function ie(e={}){const n=f({cleanupStale:!0});if(e.json){v(n);return}if(n.pid===null){console.log(s.gray("\u25CF Background service not running"));return}n.running?(console.log(s.green(`\u25CF Background service running (PID ${n.pid})`)),console.log(s.gray(` Logs: ${d}`))):console.log(s.yellow(`\u25CF Background service stopped (PID ${n.pid} is stale)`))}function se(e){if(!o.existsSync(d)){console.log(s.gray("No logs yet"));return}try{const n=a(u.platform()==="win32"?`powershell Get-Content -Tail ${e.lines} "${d}"`:`tail -n ${e.lines} "${d}"`,{encoding:"utf-8",windowsHide:!0});process.stdout.write(n)}catch{const n=o.readFileSync(d,"utf-8").split(`
44
+ WantedBy=default.target`}const N="ShennianAgent";function Ve(e){a(e,{stdio:"pipe",windowsHide:!0})}function Ge(){const e=process.getuid?.();if(typeof e=="number")return e;const n=u.userInfo();return typeof n.uid=="number"?n.uid:n.username}function ne(e=Ge()){return`gui/${e}/${H}`}function Je(e=Ve){try{return e(`launchctl unload "${m}" 2>/dev/null; launchctl load -w "${m}"`),e(`launchctl kickstart -k "${ne()}"`),!0}catch{try{return e(`launchctl load -w "${m}"`),e(`launchctl kickstart -k "${ne()}"`),!0}catch{return!1}}}function Ke(){i.mkdirSync(g,{recursive:!0});const e={};for(const[n,t]of Object.entries(process.env))t!==void 0&&Pe(n)&&(e[n]=t);i.writeFileSync(h("env.json"),JSON.stringify(e,null,2))}function te(e={}){i.mkdirSync(g,{recursive:!0});const n=f({cleanupStale:!0});if(n.pid!==null&&n.running&&!re(n)){e.quiet||console.log(s.green(`\u2713 Background service already running (PID ${n.pid})`));return}ie(n);const t=i.openSync(d,"a"),r=Ue(k()),o=ue(r.command,r.args,je(r,t));o.unref(),i.closeSync(t),xe(o.pid),e.quiet||(console.log(s.green(`\u2713 Background service started (PID ${o.pid})`)),console.log(s.gray(` Logs: ${d}`)))}function re(e,n=I(),t=ke()){return e.pid===null||!e.running?!1:e.adopted===!0||n?.version!==t}function ie(e=f({cleanupStale:!0})){if(!(!re(e)||e.pid===null))try{process.kill(e.pid,"SIGTERM"),G(e.pid,5e3)||(process.kill(e.pid,"SIGKILL"),G(e.pid,2e3));try{I()?.pid===e.pid&&i.unlinkSync(p)}catch{}}catch{}}function oe(){i.mkdirSync(g,{recursive:!0});const e=l();switch(k().mode==="direct"&&O(F)&&console.warn(s.yellow("\u26A0 Warning: Current CLI path is temporary (npx). Auto-start may not work after reboot.\n Run `npm install -g shennian@latest` for reliable auto-start.")),e){case"darwin":{const t=c.dirname(m);return i.mkdirSync(t,{recursive:!0}),i.writeFileSync(m,Fe()),Je()}case"linux":{const t=c.dirname(D);i.mkdirSync(t,{recursive:!0}),i.writeFileSync(D,Be());try{a("systemctl --user daemon-reload && systemctl --user enable shennian",{stdio:"pipe",windowsHide:!0})}catch{return!1}try{a(`loginctl enable-linger ${u.userInfo().username}`,{stdio:"pipe",windowsHide:!0})}catch{}try{return a("systemctl --user restart shennian",{stdio:"pipe",windowsHide:!0}),!0}catch{return!1}}case"win32":return We()}}function Xe(){const n=f({cleanupStale:!0}).pid;if(n===null)return{};if(!w(n)){try{i.unlinkSync(p)}catch{}return{stalePid:n}}try{return process.kill(n,"SIGTERM"),{stoppedPid:n}}catch(t){return{error:t instanceof Error?t.message:String(t)}}}async function qe(e=5e3){const n=Xe();if(!n.stoppedPid)return n;if(!await A(n.stoppedPid,e))try{process.kill(n.stoppedPid,"SIGKILL"),await A(n.stoppedPid,2e3)}catch(r){return{...n,error:r instanceof Error?r.message:String(r)}}try{i.unlinkSync(p)}catch{}T();for(const r of X())if(r!==n.stoppedPid)try{process.kill(r,"SIGTERM"),await A(r,2e3)}catch{}return n}function Ye(e={}){q(Y(e.api)),Re(),ie(),oe()||te({quiet:e.json}),e.json?v(L(()=>f({cleanupStale:!0}))):console.log(s.green("\u2713 Background service started"))}async function ze(e={}){switch(i.mkdirSync(g,{recursive:!0}),i.writeFileSync(R,new Date().toISOString()),l()){case"darwin":{if(i.existsSync(m))try{a(`launchctl unload -w "${m}"`,{stdio:"pipe",windowsHide:!0})}catch{}break}case"linux":{try{a("systemctl --user disable --now shennian",{stdio:"pipe",windowsHide:!0})}catch{}break}case"win32":{try{a(`schtasks /change /tn "${N}" /disable`,{stdio:"pipe",windowsHide:!0})}catch{}try{a(`schtasks /end /tn "${N}"`,{stdio:"pipe",windowsHide:!0})}catch{}break}}const t=await qe(),r=f({cleanupStale:!0});if(e.json){v(t.error?{...r,error:t.error}:r);return}t.error?console.error(s.red(`\u2717 Failed to stop: ${t.error}`)):console.log(s.green("\u2713 Background service stopped"))}function se(e){Ke(),Ye(e)}async function M(e={}){await ze(e)}async function A(e,n=5e3){const t=Date.now();for(;Date.now()-t<n;){if(!w(e))return!0;await new Promise(r=>setTimeout(r,100))}return!w(e)}async function Qe(e={}){q(Y(e.api));const n=be();if(n!==null&&w(n))try{process.kill(n,"SIGTERM"),await A(n)||(process.kill(n,"SIGKILL"),await A(n,2e3));try{i.unlinkSync(p)}catch{}T(),e.json||console.log(s.green(`\u2713 Background service stopped (PID ${n})`))}catch(t){const r=t instanceof Error?t.message:String(t);e.json?v({...f(),error:r}):console.error(s.red(`\u2717 Failed to stop: ${r}`));return}else if(n!==null){try{i.unlinkSync(p)}catch{}T(),e.json||console.log(s.yellow(`\u26A0 Service process no longer exists, cleaned up stale PID ${n}`))}else e.json||console.log(s.gray("\u25CF Background service not running, starting it now"));if(l()==="linux"&&oe()){e.json&&v(L(()=>f({cleanupStale:!0})));return}te({quiet:e.json}),e.json&&v(L(()=>f({cleanupStale:!0})))}function ae(e={}){const n=f({cleanupStale:!0});if(e.json){v(n);return}if(n.pid===null){console.log(s.gray("\u25CF Background service not running"));return}n.running?(console.log(s.green(`\u25CF Background service running (PID ${n.pid})`)),console.log(s.gray(` Logs: ${d}`))):console.log(s.yellow(`\u25CF Background service stopped (PID ${n.pid} is stale)`))}function ce(e){if(!i.existsSync(d)){console.log(s.gray("No logs yet"));return}try{const n=a(u.platform()==="win32"?`powershell Get-Content -Tail ${e.lines} "${d}"`:`tail -n ${e.lines} "${d}"`,{encoding:"utf-8",windowsHide:!0});process.stdout.write(n)}catch{const n=i.readFileSync(d,"utf-8").split(`
45
45
  `).slice(-e.lines);console.log(n.join(`
46
- `))}}async function Ye(){switch(await U(),l()){case"darwin":{if(o.existsSync(m)){try{a(`launchctl unload -w "${m}"`,{stdio:"pipe",windowsHide:!0})}catch{}o.unlinkSync(m),console.log(s.green("\u2713 Auto-start uninstalled (launchd)"))}break}case"linux":{try{a("systemctl --user disable --now shennian",{stdio:"pipe",windowsHide:!0})}catch{}if(o.existsSync(D)){o.unlinkSync(D);try{a("systemctl --user daemon-reload",{stdio:"pipe",windowsHide:!0})}catch{}}console.log(s.green("\u2713 Auto-start uninstalled (systemd)"));break}case"win32":{z();try{o.unlinkSync(H)}catch{}try{o.unlinkSync(_)}catch{}try{o.unlinkSync(M)}catch{}Q(),console.log(s.green("\u2713 Auto-start uninstalled (Task Scheduler)"));break}}}function pn(e){e.command("start").description("Start the background service").option("--json","Print machine-readable status JSON").option("--api <url>","Server URL override").action(r=>oe(r)),e.command("stop").description("Stop the background service").option("--json","Print machine-readable status JSON").action(r=>U(r)),e.command("status").description("Show background service status").option("--json","Print machine-readable status JSON").action(r=>ie(r)),e.command("logs").description("Show recent logs").option("-n, --lines <n>","Number of lines","50").action(r=>se({lines:parseInt(r.lines,10)}));const n=e.command("daemon",{hidden:!0}).description("Deprecated: use top-level start/stop/status/logs"),t=(r,i)=>{i||console.error(s.yellow(`\u26A0 Deprecated command. Use \`shennian ${r}\` instead.`))};n.command("start").description("Start the background service").option("--json","Print machine-readable status JSON").option("--api <url>","Server URL override").action(r=>{t("start",r.json),oe(r)}),n.command("stop").description("Stop the background service").option("--json","Print machine-readable status JSON").action(async r=>{t("stop",r.json),await U(r)}),n.command("restart").description("Restart the background service").option("--json","Print machine-readable status JSON").option("--api <url>","Server URL override").action(r=>{t("stop && shennian start",r.json),qe(r)}),n.command("status").description("Show background service status").option("--json","Print machine-readable status JSON").action(r=>{t("status",r.json),ie(r)}),n.command("logs").description("Show recent logs").option("-n, --lines <n>","Number of lines","50").action(r=>{t("logs"),se({lines:parseInt(r.lines,10)})}),n.command("uninstall").description("Uninstall auto-start service").action(Ye)}export{Me as buildDaemonSpawnOptions,Sn as buildWindowsLauncherCommand,hn as buildWindowsScheduledTaskXml,gn as buildWindowsStartupVbs,Z as captureEnvForService,T as clearDaemonLauncher,dn as clearDaemonPidIfOwner,Ne as clearRemoteAccessDisabled,be as createDaemonInstanceId,K as findRunningDaemonProcessIds,J as getCurrentProcessDaemonLauncher,f as getDaemonStatus,ee as getLaunchdServiceTarget,re as installService,R as isEphemeralCliPath,ln as isIsolatedDaemonE2eInstance,De as isRemoteAccessDisabled,ve as isSafeSnapshotEnvKey,wn as isShennianRunServiceCommand,Re as recordStartedDaemon,pn as registerDaemonCommand,Be as reloadLaunchdAgent,Ae as resolveServiceLaunchSpec,Ve as saveEnvSnapshot,ne as startDaemonProcess,G as writeDaemonLauncher,Le as writeDaemonPid};
46
+ `))}}async function Ze(){switch(await M(),l()){case"darwin":{if(i.existsSync(m)){try{a(`launchctl unload -w "${m}"`,{stdio:"pipe",windowsHide:!0})}catch{}i.unlinkSync(m),console.log(s.green("\u2713 Auto-start uninstalled (launchd)"))}break}case"linux":{try{a("systemctl --user disable --now shennian",{stdio:"pipe",windowsHide:!0})}catch{}if(i.existsSync(D)){i.unlinkSync(D);try{a("systemctl --user daemon-reload",{stdio:"pipe",windowsHide:!0})}catch{}}console.log(s.green("\u2713 Auto-start uninstalled (systemd)"));break}case"win32":{Q();try{i.unlinkSync(_)}catch{}try{i.unlinkSync($)}catch{}try{i.unlinkSync(C)}catch{}Z(),console.log(s.green("\u2713 Auto-start uninstalled (Task Scheduler)"));break}}}function hn(e){e.command("start").description("Start the background service").option("--json","Print machine-readable status JSON").option("--api <url>","Server URL override").action(r=>se(r)),e.command("stop").description("Stop the background service").option("--json","Print machine-readable status JSON").action(r=>M(r)),e.command("status").description("Show background service status").option("--json","Print machine-readable status JSON").action(r=>ae(r)),e.command("logs").description("Show recent logs").option("-n, --lines <n>","Number of lines","50").action(r=>ce({lines:parseInt(r.lines,10)}));const n=e.command("daemon",{hidden:!0}).description("Deprecated: use top-level start/stop/status/logs"),t=(r,o)=>{o||console.error(s.yellow(`\u26A0 Deprecated command. Use \`shennian ${r}\` instead.`))};n.command("start").description("Start the background service").option("--json","Print machine-readable status JSON").option("--api <url>","Server URL override").action(r=>{t("start",r.json),se(r)}),n.command("stop").description("Stop the background service").option("--json","Print machine-readable status JSON").action(async r=>{t("stop",r.json),await M(r)}),n.command("restart").description("Restart the background service").option("--json","Print machine-readable status JSON").option("--api <url>","Server URL override").action(r=>{t("stop && shennian start",r.json),Qe(r)}),n.command("status").description("Show background service status").option("--json","Print machine-readable status JSON").action(r=>{t("status",r.json),ae(r)}),n.command("logs").description("Show recent logs").option("-n, --lines <n>","Number of lines","50").action(r=>{t("logs"),ce({lines:parseInt(r.lines,10)})}),n.command("uninstall").description("Uninstall auto-start service").action(Ze)}export{je as buildDaemonSpawnOptions,wn as buildWindowsLauncherCommand,En as buildWindowsScheduledTaskCommands,vn as buildWindowsScheduledTaskXml,In as buildWindowsStartupVbs,ee as captureEnvForService,T as clearDaemonLauncher,fn as clearDaemonPidIfOwner,Re as clearRemoteAccessDisabled,Oe as createDaemonInstanceId,X as findRunningDaemonProcessIds,J as getCurrentProcessDaemonLauncher,f as getDaemonStatus,ne as getLaunchdServiceTarget,oe as installService,O as isEphemeralCliPath,Sn as isIsolatedDaemonE2eInstance,Le as isRemoteAccessDisabled,Pe as isSafeSnapshotEnvKey,An as isShennianRunServiceCommand,xe as recordStartedDaemon,hn as registerDaemonCommand,Je as reloadLaunchdAgent,De as resolveServiceLaunchSpec,Ke as saveEnvSnapshot,re as shouldReplaceRunningDaemon,te as startDaemonProcess,K as writeDaemonLauncher,Te as writeDaemonPid};
@@ -6,8 +6,17 @@ type RoomCommandIo = {
6
6
  stderr: (text: string) => void;
7
7
  fail: () => void;
8
8
  };
9
+ type ConfirmManagedAgent = (summary: string) => Promise<boolean>;
10
+ type ManagedAgentIntentStore = {
11
+ acquire: (intentKey: string) => string;
12
+ complete: (intentKey: string, operationId: string) => void;
13
+ };
9
14
  export declare function registerRoomCommand(program: Command, options?: {
10
15
  invoke?: InvokeDaemon;
11
16
  io?: RoomCommandIo;
17
+ confirmManagedAgent?: ConfirmManagedAgent;
18
+ managedAgentIntents?: ManagedAgentIntentStore;
19
+ interactive?: boolean;
12
20
  }): void;
21
+ export declare function createFileManagedAgentIntentStore(directory?: string): ManagedAgentIntentStore;
13
22
  export {};
@@ -1,4 +1,8 @@
1
- import{callDaemonIpc as c}from"../daemon-ipc/client.js";import{DaemonIpcError as s}from"../daemon-ipc/protocol.js";const d={stdout:o=>process.stdout.write(o),stderr:o=>process.stderr.write(o),fail:()=>{process.exitCode=1}};function l(o,a={}){const t=a.invoke??c,e=a.io??d,n=o.command("room").description("Inspect locally observed Shennian Rooms and manage safe Room operations");n.command("status").description("Show local Room integration status").action(async()=>{await m("status",t,e)}),n.command("list").description("List Rooms observed by this daemon on this machine").action(async()=>{await m("list",t,e)}),n.command("create").description("Create a private Room owned by the signed-in Shennian account").requiredOption("--name <name>","Room name").action(async i=>{await p(i.name,t,e)})}async function m(o,a,t){try{const e=await a({method:"room-operator.inspect",params:{action:o}});t.stdout(`${JSON.stringify({ok:!0,command:`room.${o}`,result:e})}
2
- `)}catch(e){r(e,t)}}async function p(o,a,t){const e=o.trim();if(!e||e.length>80){r(new s("invalid_params","Room name must contain 1 to 80 characters."),t);return}try{const n=await a({method:"room-operator.create",params:{name:e},timeoutMs:15e3});t.stdout(`${JSON.stringify({ok:!0,command:"room.create",result:n})}
3
- `)}catch(n){r(n,t)}}function r(o,a){const t=o instanceof s?{code:o.code,message:o.message}:{code:"room_command_failed",message:"Shennian Room command failed."};a.stdout(`${JSON.stringify({ok:!1,error:t})}
4
- `),a.fail()}export{l as registerRoomCommand};
1
+ import g from"node:crypto";import i from"node:fs";import v from"node:path";import{createInterface as I}from"node:readline/promises";import{loadConfig as _,resolveShennianPath as k}from"../config/index.js";import{callDaemonIpc as R}from"../daemon-ipc/client.js";import{DaemonIpcError as u}from"../daemon-ipc/protocol.js";const $={stdout:e=>process.stdout.write(e),stderr:e=>process.stderr.write(e),fail:()=>{process.exitCode=1}};function G(e,n={}){const t=n.invoke??R,o=n.io??$,r=e.command("room").description("Inspect locally observed Shennian Rooms and manage safe Room operations");r.command("status").description("Show local Room integration status").action(async()=>{await w("status",t,o)}),r.command("list").description("List Rooms observed by this daemon on this machine").action(async()=>{await w("list",t,o)}),r.command("create").description("Create a private Room owned by the signed-in Shennian account").requiredOption("--name <name>","Room name").action(async a=>{await N(a.name,t,o)}),r.command("agent").description("Manage Agent conversations for a Room").command("create").description("Create a managed Agent conversation and join it to an explicit Room invite").requiredOption("--room <invite-url>","Exact Room invite URL; recent Rooms are never guessed").requiredOption("--agent <runtime>","codex, claude-code, or workbuddy").requiredOption("--workdir <absolute-path>","Absolute working directory for the new Agent").option("--model <model>","Agent model").option("--name <alias>","Agent display name").option("--mode <mode>","auto, mention, or paused","auto").option("--yes","Confirm creation in a non-interactive environment",!1).action(async a=>{await M(a,t,o,{confirm:n.confirmManagedAgent??D,interactive:n.interactive??!!(process.stdin.isTTY&&process.stdout.isTTY),intents:n.managedAgentIntents??b})})}async function w(e,n,t){try{const o=await n({method:"room-operator.inspect",params:{action:e}});t.stdout(`${JSON.stringify({ok:!0,command:`room.${e}`,result:o})}
2
+ `)}catch(o){s(o,t)}}async function N(e,n,t){const o=e.trim();if(!o||o.length>80){s(new u("invalid_params","Room name must contain 1 to 80 characters."),t);return}try{const r=await n({method:"room-operator.create",params:{name:o},timeoutMs:15e3});t.stdout(`${JSON.stringify({ok:!0,command:"room.create",result:r})}
3
+ `)}catch(r){s(r,t)}}async function M(e,n,t,o){const r=e.agent.trim().toLowerCase(),c=r==="claude-code"?"claude":r,a=e.mode.trim().toLowerCase(),y=a==="auto"?"auto_follow":a==="mention"?"mention_only":a,p=e.name?.trim()||T(c),m={room:e.room.trim(),agent:c,workDir:e.workdir.trim(),...e.model?.trim()?{modelId:e.model.trim()}:{},alias:p,activationMode:y};if(!["codex","claude","workbuddy"].includes(c)||!["auto_follow","mention_only","paused"].includes(y)||!m.room||!m.workDir||!p||p.length>80){s(new u("invalid_params","Managed Agent parameters are invalid."),t);return}if(!e.yes){if(!o.interactive){s(new u("confirmation_required","Creating an Agent starts a model process. Re-run with --yes after reviewing the target."),t);return}if(!await o.confirm(["Create and start this managed Agent?",`Room: ${x(m.room)}`,`Agent: ${r}`,`Workdir: ${m.workDir}`,`Model: ${e.model?.trim()||"(default)"}`,`Name: ${p}`,`Mode: ${a}`].join(`
4
+ `))){s(new u("cancelled","Managed Agent creation was cancelled."),t);return}}const h=g.createHash("sha256").update(JSON.stringify({machineId:_().machineId??null,...m}),"utf8").digest("hex");let f;try{f=o.intents.acquire(h)}catch(d){s(d,t);return}try{const d=await n({method:"room-operator.agent-create",params:{...m,operationId:f},timeoutMs:9e4});try{o.intents.complete(h,f)}catch{}t.stdout(`${JSON.stringify({ok:!0,command:"room.agent.create",result:d})}
5
+ `)}catch(d){s(d,t)}}const O=/^room_agent_[a-f0-9]{48}$/,E=k("runtime","room-agent-create-intents");function C(e=E){return{acquire:n=>{const t=A(e,n);try{return S(t)}catch(a){if(a.code!=="ENOENT")throw a}i.mkdirSync(e,{recursive:!0,mode:448});const o=i.lstatSync(e);if(!o.isDirectory()||o.isSymbolicLink())throw l();process.platform!=="win32"&&i.chmodSync(e,448);const r=`room_agent_${g.randomBytes(24).toString("hex")}`,c=`${t}.tmp-${process.pid}-${g.randomBytes(6).toString("hex")}`;try{return i.writeFileSync(c,`${JSON.stringify({operationId:r})}
6
+ `,{encoding:"utf8",mode:384,flag:"wx"}),process.platform!=="win32"&&i.chmodSync(c,384),i.linkSync(c,t),r}catch(a){if(a.code!=="EEXIST")throw a;return S(t)}finally{try{i.unlinkSync(c)}catch{}}},complete:(n,t)=>{const o=A(e,n);try{const r=i.lstatSync(o);if(!r.isFile()||r.isSymbolicLink())throw l();JSON.parse(i.readFileSync(o,"utf8")).operationId===t&&i.unlinkSync(o)}catch(r){if(r.code!=="ENOENT")throw r}}}}function S(e){const n=i.lstatSync(e);if(!n.isFile()||n.isSymbolicLink())throw l();const t=JSON.parse(i.readFileSync(e,"utf8"));if(typeof t.operationId!="string"||!O.test(t.operationId))throw l();return t.operationId}const b=C();function A(e,n){if(!/^[a-f0-9]{64}$/.test(n))throw l();return v.join(e,`${n}.json`)}function l(){return Object.assign(new Error("Managed Agent create intent storage is unsafe or corrupt."),{code:"unsafe_managed_agent_intent_store"})}function T(e){return e==="claude"?"Claude Code":e==="workbuddy"?"WorkBuddy":"Codex"}function x(e){try{return`${new URL(e).origin}/spaces/join/[capability]`}catch{return"[invalid Room reference]"}}async function D(e){const n=I({input:process.stdin,output:process.stdout});try{const t=await n.question(`${e}
7
+ Continue? (y/N) `);return/^(?:y|yes)$/i.test(t.trim())}finally{n.close()}}function s(e,n){const t=e instanceof u?{code:e.code,message:e.message}:{code:"room_command_failed",message:"Shennian Room command failed."};n.stdout(`${JSON.stringify({ok:!1,error:t})}
8
+ `),n.fail()}export{C as createFileManagedAgentIntentStore,G as registerRoomCommand};