shennian 0.2.0 → 0.2.5

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 (282) hide show
  1. package/dist/bin/shennian.d.ts +0 -1
  2. package/dist/bin/shennian.js +0 -1
  3. package/dist/src/agents/adapter.d.ts +0 -1
  4. package/dist/src/agents/adapter.js +0 -1
  5. package/dist/src/agents/claude.d.ts +1 -1
  6. package/dist/src/agents/claude.js +12 -6
  7. package/dist/src/agents/codex.d.ts +18 -1
  8. package/dist/src/agents/codex.js +372 -13
  9. package/dist/src/agents/command-spec.d.ts +28 -3
  10. package/dist/src/agents/command-spec.js +251 -10
  11. package/dist/src/agents/cursor.d.ts +0 -1
  12. package/dist/src/agents/cursor.js +2 -4
  13. package/dist/src/agents/custom.d.ts +0 -6
  14. package/dist/src/agents/custom.js +4 -40
  15. package/dist/src/agents/detect.d.ts +0 -1
  16. package/dist/src/agents/detect.js +0 -1
  17. package/dist/src/agents/gemini.d.ts +0 -1
  18. package/dist/src/agents/gemini.js +7 -3
  19. package/dist/src/agents/model-registry/cache.d.ts +0 -1
  20. package/dist/src/agents/model-registry/cache.js +0 -1
  21. package/dist/src/agents/model-registry/discovery.d.ts +0 -1
  22. package/dist/src/agents/model-registry/discovery.js +90 -48
  23. package/dist/src/agents/model-registry/parsers.d.ts +4 -1
  24. package/dist/src/agents/model-registry/parsers.js +168 -1
  25. package/dist/src/agents/model-registry/runner.d.ts +2 -7
  26. package/dist/src/agents/model-registry/runner.js +3 -134
  27. package/dist/src/agents/model-registry/service.d.ts +0 -1
  28. package/dist/src/agents/model-registry/service.js +12 -10
  29. package/dist/src/agents/model-registry/types.d.ts +0 -1
  30. package/dist/src/agents/model-registry/types.js +0 -1
  31. package/dist/src/agents/model-registry.d.ts +3 -2
  32. package/dist/src/agents/model-registry.js +3 -2
  33. package/dist/src/agents/openclaw.d.ts +0 -1
  34. package/dist/src/agents/openclaw.js +13 -4
  35. package/dist/src/agents/pi.d.ts +0 -1
  36. package/dist/src/agents/pi.js +0 -1
  37. package/dist/src/commands/agent.d.ts +0 -1
  38. package/dist/src/commands/agent.js +2 -33
  39. package/dist/src/commands/daemon.d.ts +6 -1
  40. package/dist/src/commands/daemon.js +153 -18
  41. package/dist/src/commands/pair-qr.d.ts +0 -1
  42. package/dist/src/commands/pair-qr.js +0 -1
  43. package/dist/src/commands/pair.d.ts +0 -1
  44. package/dist/src/commands/pair.js +0 -1
  45. package/dist/src/commands/upgrade.d.ts +0 -1
  46. package/dist/src/commands/upgrade.js +0 -1
  47. package/dist/src/config/index.d.ts +0 -1
  48. package/dist/src/config/index.js +0 -1
  49. package/dist/src/fs/handler.d.ts +0 -1
  50. package/dist/src/fs/handler.js +18 -1
  51. package/dist/src/fs/security.d.ts +0 -1
  52. package/dist/src/fs/security.js +5 -1
  53. package/dist/src/index.d.ts +0 -1
  54. package/dist/src/index.js +36 -8
  55. package/dist/src/log-reporter.d.ts +0 -1
  56. package/dist/src/log-reporter.js +2 -20
  57. package/dist/src/native-fusion/parsers.d.ts +0 -1
  58. package/dist/src/native-fusion/parsers.js +407 -44
  59. package/dist/src/native-fusion/service.d.ts +0 -1
  60. package/dist/src/native-fusion/service.js +16 -10
  61. package/dist/src/native-fusion/state.d.ts +0 -1
  62. package/dist/src/native-fusion/state.js +0 -1
  63. package/dist/src/native-fusion/types.d.ts +0 -1
  64. package/dist/src/native-fusion/types.js +0 -1
  65. package/dist/src/region.d.ts +0 -1
  66. package/dist/src/region.js +0 -1
  67. package/dist/src/relay/client.d.ts +11 -2
  68. package/dist/src/relay/client.js +22 -4
  69. package/dist/src/session/handlers/agents.d.ts +0 -1
  70. package/dist/src/session/handlers/agents.js +0 -1
  71. package/dist/src/session/handlers/chat.d.ts +0 -1
  72. package/dist/src/session/handlers/chat.js +49 -8
  73. package/dist/src/session/handlers/control.d.ts +0 -1
  74. package/dist/src/session/handlers/control.js +0 -1
  75. package/dist/src/session/handlers/fs.d.ts +0 -1
  76. package/dist/src/session/handlers/fs.js +37 -3
  77. package/dist/src/session/manager.d.ts +1 -1
  78. package/dist/src/session/manager.js +23 -4
  79. package/dist/src/session/store.d.ts +0 -1
  80. package/dist/src/session/store.js +0 -1
  81. package/dist/src/session/types.d.ts +6 -1
  82. package/dist/src/session/types.js +0 -1
  83. package/dist/src/upgrade/engine.d.ts +0 -1
  84. package/dist/src/upgrade/engine.js +0 -1
  85. package/package.json +3 -2
  86. package/dist/bin/shennian.d.ts.map +0 -1
  87. package/dist/bin/shennian.js.map +0 -1
  88. package/dist/src/__experiments__/probe-debug.d.ts +0 -2
  89. package/dist/src/__experiments__/probe-debug.d.ts.map +0 -1
  90. package/dist/src/__experiments__/probe-debug.js +0 -66
  91. package/dist/src/__experiments__/probe-debug.js.map +0 -1
  92. package/dist/src/__experiments__/probe-final-benchmark.d.ts +0 -3
  93. package/dist/src/__experiments__/probe-final-benchmark.d.ts.map +0 -1
  94. package/dist/src/__experiments__/probe-final-benchmark.js +0 -234
  95. package/dist/src/__experiments__/probe-final-benchmark.js.map +0 -1
  96. package/dist/src/__experiments__/probe-models-final.d.ts +0 -19
  97. package/dist/src/__experiments__/probe-models-final.d.ts.map +0 -1
  98. package/dist/src/__experiments__/probe-models-final.js +0 -250
  99. package/dist/src/__experiments__/probe-models-final.js.map +0 -1
  100. package/dist/src/__experiments__/probe-models.d.ts +0 -7
  101. package/dist/src/__experiments__/probe-models.d.ts.map +0 -1
  102. package/dist/src/__experiments__/probe-models.js +0 -251
  103. package/dist/src/__experiments__/probe-models.js.map +0 -1
  104. package/dist/src/__tests__/agents-e2e.d.ts +0 -21
  105. package/dist/src/__tests__/agents-e2e.d.ts.map +0 -1
  106. package/dist/src/__tests__/agents-e2e.js +0 -146
  107. package/dist/src/__tests__/agents-e2e.js.map +0 -1
  108. package/dist/src/__tests__/claude-adapter.test.d.ts +0 -2
  109. package/dist/src/__tests__/claude-adapter.test.d.ts.map +0 -1
  110. package/dist/src/__tests__/claude-adapter.test.js +0 -75
  111. package/dist/src/__tests__/claude-adapter.test.js.map +0 -1
  112. package/dist/src/__tests__/codex-adapter.test.d.ts +0 -2
  113. package/dist/src/__tests__/codex-adapter.test.d.ts.map +0 -1
  114. package/dist/src/__tests__/codex-adapter.test.js +0 -224
  115. package/dist/src/__tests__/codex-adapter.test.js.map +0 -1
  116. package/dist/src/__tests__/config.test.d.ts +0 -2
  117. package/dist/src/__tests__/config.test.d.ts.map +0 -1
  118. package/dist/src/__tests__/config.test.js +0 -60
  119. package/dist/src/__tests__/config.test.js.map +0 -1
  120. package/dist/src/__tests__/cursor-adapter.test.d.ts +0 -2
  121. package/dist/src/__tests__/cursor-adapter.test.d.ts.map +0 -1
  122. package/dist/src/__tests__/cursor-adapter.test.js +0 -69
  123. package/dist/src/__tests__/cursor-adapter.test.js.map +0 -1
  124. package/dist/src/__tests__/custom-agent-flow.test.d.ts +0 -2
  125. package/dist/src/__tests__/custom-agent-flow.test.d.ts.map +0 -1
  126. package/dist/src/__tests__/custom-agent-flow.test.js +0 -244
  127. package/dist/src/__tests__/custom-agent-flow.test.js.map +0 -1
  128. package/dist/src/__tests__/daemon-autostart.test.d.ts +0 -2
  129. package/dist/src/__tests__/daemon-autostart.test.d.ts.map +0 -1
  130. package/dist/src/__tests__/daemon-autostart.test.js +0 -60
  131. package/dist/src/__tests__/daemon-autostart.test.js.map +0 -1
  132. package/dist/src/__tests__/e2e-relay.d.ts +0 -19
  133. package/dist/src/__tests__/e2e-relay.d.ts.map +0 -1
  134. package/dist/src/__tests__/e2e-relay.js +0 -256
  135. package/dist/src/__tests__/e2e-relay.js.map +0 -1
  136. package/dist/src/__tests__/model-discovery.test.d.ts +0 -2
  137. package/dist/src/__tests__/model-discovery.test.d.ts.map +0 -1
  138. package/dist/src/__tests__/model-discovery.test.js +0 -47
  139. package/dist/src/__tests__/model-discovery.test.js.map +0 -1
  140. package/dist/src/__tests__/model-switching.test.d.ts +0 -2
  141. package/dist/src/__tests__/model-switching.test.d.ts.map +0 -1
  142. package/dist/src/__tests__/model-switching.test.js +0 -253
  143. package/dist/src/__tests__/model-switching.test.js.map +0 -1
  144. package/dist/src/__tests__/native-fusion-parsers.test.d.ts +0 -2
  145. package/dist/src/__tests__/native-fusion-parsers.test.d.ts.map +0 -1
  146. package/dist/src/__tests__/native-fusion-parsers.test.js +0 -216
  147. package/dist/src/__tests__/native-fusion-parsers.test.js.map +0 -1
  148. package/dist/src/__tests__/native-fusion-service.test.d.ts +0 -2
  149. package/dist/src/__tests__/native-fusion-service.test.d.ts.map +0 -1
  150. package/dist/src/__tests__/native-fusion-service.test.js +0 -157
  151. package/dist/src/__tests__/native-fusion-service.test.js.map +0 -1
  152. package/dist/src/__tests__/native-session-sync.test.d.ts +0 -2
  153. package/dist/src/__tests__/native-session-sync.test.d.ts.map +0 -1
  154. package/dist/src/__tests__/native-session-sync.test.js +0 -198
  155. package/dist/src/__tests__/native-session-sync.test.js.map +0 -1
  156. package/dist/src/__tests__/pair-qr.test.d.ts +0 -2
  157. package/dist/src/__tests__/pair-qr.test.d.ts.map +0 -1
  158. package/dist/src/__tests__/pair-qr.test.js +0 -13
  159. package/dist/src/__tests__/pair-qr.test.js.map +0 -1
  160. package/dist/src/__tests__/pi-context.test.d.ts +0 -2
  161. package/dist/src/__tests__/pi-context.test.d.ts.map +0 -1
  162. package/dist/src/__tests__/pi-context.test.js +0 -261
  163. package/dist/src/__tests__/pi-context.test.js.map +0 -1
  164. package/dist/src/__tests__/session-manager.test.d.ts +0 -2
  165. package/dist/src/__tests__/session-manager.test.d.ts.map +0 -1
  166. package/dist/src/__tests__/session-manager.test.js +0 -592
  167. package/dist/src/__tests__/session-manager.test.js.map +0 -1
  168. package/dist/src/__tests__/session-store.test.d.ts +0 -2
  169. package/dist/src/__tests__/session-store.test.d.ts.map +0 -1
  170. package/dist/src/__tests__/session-store.test.js +0 -106
  171. package/dist/src/__tests__/session-store.test.js.map +0 -1
  172. package/dist/src/agents/adapter.d.ts.map +0 -1
  173. package/dist/src/agents/adapter.js.map +0 -1
  174. package/dist/src/agents/claude.d.ts.map +0 -1
  175. package/dist/src/agents/claude.js.map +0 -1
  176. package/dist/src/agents/codex.d.ts.map +0 -1
  177. package/dist/src/agents/codex.js.map +0 -1
  178. package/dist/src/agents/command-spec.d.ts.map +0 -1
  179. package/dist/src/agents/command-spec.js.map +0 -1
  180. package/dist/src/agents/cursor.d.ts.map +0 -1
  181. package/dist/src/agents/cursor.js.map +0 -1
  182. package/dist/src/agents/custom.d.ts.map +0 -1
  183. package/dist/src/agents/custom.js.map +0 -1
  184. package/dist/src/agents/detect.d.ts.map +0 -1
  185. package/dist/src/agents/detect.js.map +0 -1
  186. package/dist/src/agents/gemini.d.ts.map +0 -1
  187. package/dist/src/agents/gemini.js.map +0 -1
  188. package/dist/src/agents/model-registry/cache.d.ts.map +0 -1
  189. package/dist/src/agents/model-registry/cache.js.map +0 -1
  190. package/dist/src/agents/model-registry/discovery.d.ts.map +0 -1
  191. package/dist/src/agents/model-registry/discovery.js.map +0 -1
  192. package/dist/src/agents/model-registry/parsers.d.ts.map +0 -1
  193. package/dist/src/agents/model-registry/parsers.js.map +0 -1
  194. package/dist/src/agents/model-registry/runner.d.ts.map +0 -1
  195. package/dist/src/agents/model-registry/runner.js.map +0 -1
  196. package/dist/src/agents/model-registry/service.d.ts.map +0 -1
  197. package/dist/src/agents/model-registry/service.js.map +0 -1
  198. package/dist/src/agents/model-registry/types.d.ts.map +0 -1
  199. package/dist/src/agents/model-registry/types.js.map +0 -1
  200. package/dist/src/agents/model-registry.d.ts.map +0 -1
  201. package/dist/src/agents/model-registry.js.map +0 -1
  202. package/dist/src/agents/openclaw.d.ts.map +0 -1
  203. package/dist/src/agents/openclaw.js.map +0 -1
  204. package/dist/src/agents/pi.d.ts.map +0 -1
  205. package/dist/src/agents/pi.js.map +0 -1
  206. package/dist/src/commands/agent.d.ts.map +0 -1
  207. package/dist/src/commands/agent.js.map +0 -1
  208. package/dist/src/commands/daemon.d.ts.map +0 -1
  209. package/dist/src/commands/daemon.js.map +0 -1
  210. package/dist/src/commands/pair-qr.d.ts.map +0 -1
  211. package/dist/src/commands/pair-qr.js.map +0 -1
  212. package/dist/src/commands/pair.d.ts.map +0 -1
  213. package/dist/src/commands/pair.js.map +0 -1
  214. package/dist/src/commands/upgrade.d.ts.map +0 -1
  215. package/dist/src/commands/upgrade.js.map +0 -1
  216. package/dist/src/config/index.d.ts.map +0 -1
  217. package/dist/src/config/index.js.map +0 -1
  218. package/dist/src/fs/handler.d.ts.map +0 -1
  219. package/dist/src/fs/handler.js.map +0 -1
  220. package/dist/src/fs/multimodal.d.ts +0 -5
  221. package/dist/src/fs/multimodal.d.ts.map +0 -1
  222. package/dist/src/fs/multimodal.js +0 -39
  223. package/dist/src/fs/multimodal.js.map +0 -1
  224. package/dist/src/fs/security.d.ts.map +0 -1
  225. package/dist/src/fs/security.js.map +0 -1
  226. package/dist/src/index.d.ts.map +0 -1
  227. package/dist/src/index.js.map +0 -1
  228. package/dist/src/log-reporter.d.ts.map +0 -1
  229. package/dist/src/log-reporter.js.map +0 -1
  230. package/dist/src/native-fusion/parsers.d.ts.map +0 -1
  231. package/dist/src/native-fusion/parsers.js.map +0 -1
  232. package/dist/src/native-fusion/service.d.ts.map +0 -1
  233. package/dist/src/native-fusion/service.js.map +0 -1
  234. package/dist/src/native-fusion/state.d.ts.map +0 -1
  235. package/dist/src/native-fusion/state.js.map +0 -1
  236. package/dist/src/native-fusion/types.d.ts.map +0 -1
  237. package/dist/src/native-fusion/types.js.map +0 -1
  238. package/dist/src/native-sync/discover.d.ts +0 -6
  239. package/dist/src/native-sync/discover.d.ts.map +0 -1
  240. package/dist/src/native-sync/discover.js +0 -69
  241. package/dist/src/native-sync/discover.js.map +0 -1
  242. package/dist/src/native-sync/parsers.d.ts +0 -3
  243. package/dist/src/native-sync/parsers.d.ts.map +0 -1
  244. package/dist/src/native-sync/parsers.js +0 -373
  245. package/dist/src/native-sync/parsers.js.map +0 -1
  246. package/dist/src/native-sync/service.d.ts +0 -16
  247. package/dist/src/native-sync/service.d.ts.map +0 -1
  248. package/dist/src/native-sync/service.js +0 -95
  249. package/dist/src/native-sync/service.js.map +0 -1
  250. package/dist/src/native-sync/state.d.ts +0 -6
  251. package/dist/src/native-sync/state.d.ts.map +0 -1
  252. package/dist/src/native-sync/state.js +0 -34
  253. package/dist/src/native-sync/state.js.map +0 -1
  254. package/dist/src/native-sync/types.d.ts +0 -23
  255. package/dist/src/native-sync/types.d.ts.map +0 -1
  256. package/dist/src/native-sync/types.js +0 -4
  257. package/dist/src/native-sync/types.js.map +0 -1
  258. package/dist/src/region.d.ts.map +0 -1
  259. package/dist/src/region.js.map +0 -1
  260. package/dist/src/relay/client.d.ts.map +0 -1
  261. package/dist/src/relay/client.js.map +0 -1
  262. package/dist/src/session/handlers/agents.d.ts.map +0 -1
  263. package/dist/src/session/handlers/agents.js.map +0 -1
  264. package/dist/src/session/handlers/chat.d.ts.map +0 -1
  265. package/dist/src/session/handlers/chat.js.map +0 -1
  266. package/dist/src/session/handlers/control.d.ts.map +0 -1
  267. package/dist/src/session/handlers/control.js.map +0 -1
  268. package/dist/src/session/handlers/fs.d.ts.map +0 -1
  269. package/dist/src/session/handlers/fs.js.map +0 -1
  270. package/dist/src/session/handlers/queue.d.ts +0 -4
  271. package/dist/src/session/handlers/queue.d.ts.map +0 -1
  272. package/dist/src/session/handlers/queue.js +0 -66
  273. package/dist/src/session/handlers/queue.js.map +0 -1
  274. package/dist/src/session/manager.d.ts.map +0 -1
  275. package/dist/src/session/manager.js.map +0 -1
  276. package/dist/src/session/store.d.ts.map +0 -1
  277. package/dist/src/session/store.js.map +0 -1
  278. package/dist/src/session/types.d.ts.map +0 -1
  279. package/dist/src/session/types.js.map +0 -1
  280. package/dist/src/upgrade/engine.d.ts.map +0 -1
  281. package/dist/src/upgrade/engine.js.map +0 -1
  282. package/dist/tsconfig.tsbuildinfo +0 -1
@@ -28,7 +28,7 @@ export function isEphemeralCliPath(candidate) {
28
28
  normalized.startsWith(tmp.endsWith('/') ? tmp : `${tmp}/`));
29
29
  }
30
30
  export function resolveServiceLaunchSpec(input) {
31
- if (!isEphemeralCliPath(input.scriptPath)) {
31
+ if (fs.existsSync(input.scriptPath) && !isEphemeralCliPath(input.scriptPath)) {
32
32
  return {
33
33
  command: input.nodeExec,
34
34
  args: [input.scriptPath, 'start'],
@@ -79,8 +79,10 @@ function isRunning(pid) {
79
79
  const LAUNCHD_LABEL = 'com.shennian.agent';
80
80
  const LAUNCHD_PLIST = path.join(os.homedir(), 'Library/LaunchAgents', `${LAUNCHD_LABEL}.plist`);
81
81
  const WINDOWS_STARTUP_DIR = path.join(os.homedir(), 'AppData', 'Roaming', 'Microsoft', 'Windows', 'Start Menu', 'Programs', 'Startup');
82
- const WINDOWS_STARTUP_VBS = path.join(WINDOWS_STARTUP_DIR, 'ShennianAgent.vbs');
83
82
  const WINDOWS_STARTUP_CMD = resolveShennianPath('autostart.cmd');
83
+ const WINDOWS_LAUNCHER_VBS = resolveShennianPath('autostart.vbs');
84
+ const WINDOWS_TASK_XML = resolveShennianPath('autostart.xml');
85
+ const WINDOWS_STARTUP_VBS = path.join(WINDOWS_STARTUP_DIR, 'ShennianAgent.vbs');
84
86
  function findCommandPath(binary) {
85
87
  const command = getPlatform() === 'win32' ? `where ${binary}` : `command -v ${binary}`;
86
88
  try {
@@ -130,12 +132,20 @@ function quoteCmdArg(text) {
130
132
  function escapeVbsString(text) {
131
133
  return text.replace(/"/g, '""');
132
134
  }
135
+ function escapeXmlValue(text) {
136
+ return escapeXml(text);
137
+ }
138
+ function isWindowsCmdScript(filePath) {
139
+ const ext = path.extname(filePath).toLowerCase();
140
+ return ext === '.cmd' || ext === '.bat';
141
+ }
133
142
  export function buildWindowsLauncherCommand(spec, logFile) {
134
143
  const commandLine = [spec.command, ...spec.args].map(quoteCmdArg).join(' ');
144
+ const invocation = isWindowsCmdScript(spec.command) ? `call ${commandLine}` : commandLine;
135
145
  return [
136
146
  '@echo off',
137
147
  'setlocal',
138
- `${commandLine} >> ${quoteCmdArg(logFile)} 2>&1`,
148
+ `${invocation} >> ${quoteCmdArg(logFile)} 2>&1`,
139
149
  '',
140
150
  ].join('\r\n');
141
151
  }
@@ -146,6 +156,66 @@ export function buildWindowsStartupVbs(cmdPath) {
146
156
  '',
147
157
  ].join('\r\n');
148
158
  }
159
+ export function buildWindowsScheduledTaskXml(input) {
160
+ const joinedArgs = input.arguments.join(' ');
161
+ return `<?xml version="1.0" encoding="UTF-16"?>
162
+ <Task version="1.4" xmlns="http://schemas.microsoft.com/windows/2004/02/mit/task">
163
+ <RegistrationInfo>
164
+ <Description>Shennian Agent Daemon</Description>
165
+ </RegistrationInfo>
166
+ <Triggers>
167
+ <LogonTrigger>
168
+ <Enabled>true</Enabled>
169
+ <UserId>${escapeXmlValue(input.userId)}</UserId>
170
+ </LogonTrigger>
171
+ <EventTrigger>
172
+ <Enabled>true</Enabled>
173
+ <Subscription><![CDATA[
174
+ <QueryList>
175
+ <Query Id="0" Path="System">
176
+ <Select Path="System">*[System[Provider[@Name='Microsoft-Windows-Power-Troubleshooter'] and EventID=1]]</Select>
177
+ </Query>
178
+ </QueryList>]]></Subscription>
179
+ </EventTrigger>
180
+ </Triggers>
181
+ <Principals>
182
+ <Principal id="Author">
183
+ <UserId>${escapeXmlValue(input.userId)}</UserId>
184
+ <LogonType>InteractiveToken</LogonType>
185
+ <RunLevel>LeastPrivilege</RunLevel>
186
+ </Principal>
187
+ </Principals>
188
+ <Settings>
189
+ <MultipleInstancesPolicy>IgnoreNew</MultipleInstancesPolicy>
190
+ <DisallowStartIfOnBatteries>false</DisallowStartIfOnBatteries>
191
+ <StopIfGoingOnBatteries>false</StopIfGoingOnBatteries>
192
+ <AllowHardTerminate>true</AllowHardTerminate>
193
+ <StartWhenAvailable>true</StartWhenAvailable>
194
+ <RunOnlyIfNetworkAvailable>false</RunOnlyIfNetworkAvailable>
195
+ <IdleSettings>
196
+ <StopOnIdleEnd>false</StopOnIdleEnd>
197
+ <RestartOnIdle>false</RestartOnIdle>
198
+ </IdleSettings>
199
+ <AllowStartOnDemand>true</AllowStartOnDemand>
200
+ <Enabled>true</Enabled>
201
+ <Hidden>true</Hidden>
202
+ <RunOnlyIfIdle>false</RunOnlyIfIdle>
203
+ <WakeToRun>false</WakeToRun>
204
+ <ExecutionTimeLimit>PT0S</ExecutionTimeLimit>
205
+ <Priority>7</Priority>
206
+ <RestartOnFailure>
207
+ <Interval>PT1M</Interval>
208
+ <Count>3</Count>
209
+ </RestartOnFailure>
210
+ </Settings>
211
+ <Actions Context="Author">
212
+ <Exec>
213
+ <Command>${escapeXmlValue(input.command)}</Command>
214
+ <Arguments>${escapeXmlValue(joinedArgs)}</Arguments>
215
+ </Exec>
216
+ </Actions>
217
+ </Task>`;
218
+ }
149
219
  function removeLegacyWindowsTask() {
150
220
  try {
151
221
  execSync(`schtasks /delete /tn "${WINDOWS_TASK_NAME}" /f`, { stdio: 'pipe' });
@@ -154,10 +224,64 @@ function removeLegacyWindowsTask() {
154
224
  // Ignore missing legacy Task Scheduler entries during migration.
155
225
  }
156
226
  }
157
- function captureEnvForService() {
227
+ function removeLegacyWindowsStartupFiles() {
228
+ try {
229
+ fs.unlinkSync(WINDOWS_STARTUP_VBS);
230
+ }
231
+ catch {
232
+ // Legacy Startup entry may already be absent.
233
+ }
234
+ }
235
+ function getWindowsTaskUserId() {
236
+ const domain = process.env.USERDOMAIN?.trim();
237
+ const computer = process.env.COMPUTERNAME?.trim();
238
+ const username = process.env.USERNAME?.trim() || os.userInfo().username;
239
+ if (domain && domain.toUpperCase() !== 'WORKGROUP')
240
+ return `${domain}\\${username}`;
241
+ if (computer)
242
+ return `${computer}\\${username}`;
243
+ return username;
244
+ }
245
+ function buildDetachedLaunchSpec(spec) {
246
+ if (getPlatform() === 'win32' && isWindowsCmdScript(spec.command)) {
247
+ const commandLine = [spec.command, ...spec.args].map(quoteCmdArg).join(' ');
248
+ return {
249
+ command: process.env.ComSpec || 'cmd.exe',
250
+ args: ['/d', '/s', '/c', `"${commandLine}"`],
251
+ windowsVerbatimArguments: true,
252
+ };
253
+ }
254
+ return {
255
+ command: spec.command,
256
+ args: spec.args,
257
+ };
258
+ }
259
+ function installWindowsScheduledTask() {
260
+ const launch = resolveCurrentServiceLaunchSpec();
261
+ fs.writeFileSync(WINDOWS_STARTUP_CMD, buildWindowsLauncherCommand(launch, LOG_FILE));
262
+ fs.writeFileSync(WINDOWS_LAUNCHER_VBS, buildWindowsStartupVbs(WINDOWS_STARTUP_CMD));
263
+ removeLegacyWindowsStartupFiles();
264
+ removeLegacyWindowsTask();
265
+ const taskXml = buildWindowsScheduledTaskXml({
266
+ userId: getWindowsTaskUserId(),
267
+ command: path.join(process.env.SystemRoot || 'C:\\Windows', 'System32', 'wscript.exe'),
268
+ arguments: [quoteCmdArg(WINDOWS_LAUNCHER_VBS)],
269
+ });
270
+ fs.writeFileSync(WINDOWS_TASK_XML, taskXml, 'utf8');
271
+ try {
272
+ execSync(`schtasks /create /tn "${WINDOWS_TASK_NAME}" /xml "${WINDOWS_TASK_XML}" /f`, { stdio: 'pipe' });
273
+ execSync(`schtasks /run /tn "${WINDOWS_TASK_NAME}"`, { stdio: 'pipe' });
274
+ return true;
275
+ }
276
+ catch {
277
+ return false;
278
+ }
279
+ }
280
+ export function captureEnvForService() {
158
281
  const keep = [
159
282
  'PATH', 'HOME', 'USER', 'LOGNAME', 'SHELL', 'TMPDIR', 'LANG',
160
283
  'LC_ALL', 'LC_CTYPE', 'SSH_AUTH_SOCK', 'XDG_CONFIG_HOME', 'XDG_DATA_HOME',
284
+ 'TEMP', 'TMP',
161
285
  'ANTHROPIC_API_KEY', 'ANTHROPIC_AUTH_TOKEN', 'ANTHROPIC_BASE_URL',
162
286
  'OPENAI_API_KEY', 'OPENAI_BASE_URL',
163
287
  'GEMINI_API_KEY', 'GOOGLE_API_KEY',
@@ -170,7 +294,15 @@ function captureEnvForService() {
170
294
  env.HOME ??= os.homedir();
171
295
  env.PATH ??= '/usr/local/bin:/usr/bin:/bin';
172
296
  env.USER ??= os.userInfo().username;
173
- env.TMPDIR ??= '/tmp';
297
+ if (getPlatform() === 'win32') {
298
+ const tempDir = process.env.TEMP || process.env.TMP || os.tmpdir();
299
+ env.TMPDIR ??= tempDir;
300
+ env.TEMP ??= tempDir;
301
+ env.TMP ??= tempDir;
302
+ }
303
+ else {
304
+ env.TMPDIR ??= '/tmp';
305
+ }
174
306
  return env;
175
307
  }
176
308
  function buildPlist() {
@@ -255,10 +387,12 @@ export function startDaemonProcess() {
255
387
  return;
256
388
  }
257
389
  const logFd = fs.openSync(LOG_FILE, 'a');
258
- const child = spawn(NODE_EXEC, [SHENNIAN_SCRIPT, 'start'], {
390
+ const launch = buildDetachedLaunchSpec(resolveCurrentServiceLaunchSpec());
391
+ const child = spawn(launch.command, launch.args, {
259
392
  detached: true,
260
393
  stdio: ['ignore', logFd, logFd],
261
394
  env: process.env,
395
+ ...(launch.windowsVerbatimArguments ? { windowsVerbatimArguments: true } : {}),
262
396
  });
263
397
  child.unref();
264
398
  fs.closeSync(logFd);
@@ -320,12 +454,7 @@ export function installService() {
320
454
  return false; // systemd enable doesn't start immediately; caller should startDaemonProcess
321
455
  }
322
456
  case 'win32': {
323
- const launch = resolveCurrentServiceLaunchSpec();
324
- fs.mkdirSync(WINDOWS_STARTUP_DIR, { recursive: true });
325
- fs.writeFileSync(WINDOWS_STARTUP_CMD, buildWindowsLauncherCommand(launch, LOG_FILE));
326
- fs.writeFileSync(WINDOWS_STARTUP_VBS, buildWindowsStartupVbs(WINDOWS_STARTUP_CMD));
327
- removeLegacyWindowsTask();
328
- return false; // Startup folder launches on logon; caller should startDaemonProcess now
457
+ return installWindowsScheduledTask();
329
458
  }
330
459
  }
331
460
  }
@@ -435,18 +564,25 @@ function daemonUninstall() {
435
564
  case 'win32': {
436
565
  removeLegacyWindowsTask();
437
566
  try {
438
- fs.unlinkSync(WINDOWS_STARTUP_VBS);
567
+ fs.unlinkSync(WINDOWS_STARTUP_CMD);
439
568
  }
440
569
  catch {
441
- // Startup entry may already be removed.
570
+ // Launcher script may already be removed.
442
571
  }
443
572
  try {
444
- fs.unlinkSync(WINDOWS_STARTUP_CMD);
573
+ fs.unlinkSync(WINDOWS_LAUNCHER_VBS);
445
574
  }
446
575
  catch {
447
- // Launcher script may already be removed.
576
+ // Launcher vbs may already be removed.
577
+ }
578
+ try {
579
+ fs.unlinkSync(WINDOWS_TASK_XML);
580
+ }
581
+ catch {
582
+ // Task xml may already be removed.
448
583
  }
449
- console.log(chalk.green('✓ Auto-start uninstalled (Startup folder)'));
584
+ removeLegacyWindowsStartupFiles();
585
+ console.log(chalk.green('✓ Auto-start uninstalled (Task Scheduler)'));
450
586
  break;
451
587
  }
452
588
  }
@@ -474,4 +610,3 @@ export function registerDaemonCommand(program) {
474
610
  .description('Uninstall auto-start service')
475
611
  .action(daemonUninstall);
476
612
  }
477
- //# sourceMappingURL=daemon.js.map
@@ -2,4 +2,3 @@ export declare const PAIR_QR_RENDER_OPTIONS: {
2
2
  readonly small: false;
3
3
  };
4
4
  export declare function buildPairQrPayload(pairToken: string): string;
5
- //# sourceMappingURL=pair-qr.d.ts.map
@@ -4,4 +4,3 @@ export const PAIR_QR_RENDER_OPTIONS = { small: false };
4
4
  export function buildPairQrPayload(pairToken) {
5
5
  return `pair:${pairToken}`;
6
6
  }
7
- //# sourceMappingURL=pair-qr.js.map
@@ -6,4 +6,3 @@ export declare function runPairFlow(opts: {
6
6
  }): Promise<void>;
7
7
  export declare function runSmartStart(serverUrl: string | undefined, machineName: string): Promise<void>;
8
8
  export declare function registerPairCommand(program: Command): void;
9
- //# sourceMappingURL=pair.d.ts.map
@@ -160,4 +160,3 @@ export function registerPairCommand(program) {
160
160
  }
161
161
  });
162
162
  }
163
- //# sourceMappingURL=pair.js.map
@@ -3,4 +3,3 @@ import type { CliRelayClient } from '../relay/client.js';
3
3
  export declare function registerUpgradeCommand(program: Command): void;
4
4
  export declare function handleUpgradeStart(client: CliRelayClient, reqId: string, targetVersion?: string): Promise<void>;
5
5
  export declare function handleUpgradeStatus(client: CliRelayClient, reqId: string): Promise<void>;
6
- //# sourceMappingURL=upgrade.d.ts.map
@@ -143,4 +143,3 @@ export async function handleUpgradeStatus(client, reqId) {
143
143
  : { hasUpdate: false, current: getCurrentVersion() },
144
144
  });
145
145
  }
146
- //# sourceMappingURL=upgrade.js.map
@@ -30,4 +30,3 @@ export type ShennianConfig = {
30
30
  export declare function loadConfig(): ShennianConfig;
31
31
  export declare function saveConfig(config: ShennianConfig): void;
32
32
  export declare function ensureDir(): void;
33
- //# sourceMappingURL=index.d.ts.map
@@ -29,4 +29,3 @@ export function ensureDir() {
29
29
  fs.mkdirSync(getShennianDir(), { recursive: true });
30
30
  fs.mkdirSync(resolveShennianPath('sessions'), { recursive: true });
31
31
  }
32
- //# sourceMappingURL=index.js.map
@@ -24,4 +24,3 @@ export declare function handleFsUploadInit(req: FsTransferRequest): {
24
24
  error: string;
25
25
  };
26
26
  export declare function handleFsUploadChunk(targetPath: string, chunk: FsChunk): void;
27
- //# sourceMappingURL=handler.d.ts.map
@@ -1,6 +1,8 @@
1
1
  import fs from 'node:fs';
2
+ import os from 'node:os';
2
3
  import path from 'node:path';
3
4
  import { normalizePath, isPathSafe } from './security.js';
5
+ const FILE_SYSTEM_ROOTS_PATH = '__roots__';
4
6
  const MAX_READ_SIZE = 100 * 1024;
5
7
  const MAX_TRANSFER_SIZE = 20 * 1024 * 1024;
6
8
  const CHUNK_SIZE = 64 * 1024;
@@ -8,7 +10,23 @@ const RATE_LIMIT_BYTES_PER_SEC = 5 * 1024 * 1024;
8
10
  function sleep(ms) {
9
11
  return new Promise((r) => setTimeout(r, ms));
10
12
  }
13
+ function listFileSystemRoots() {
14
+ if (os.platform() === 'win32') {
15
+ const entries = [];
16
+ for (let code = 65; code <= 90; code += 1) {
17
+ const drive = `${String.fromCharCode(code)}:\\`;
18
+ if (!fs.existsSync(drive))
19
+ continue;
20
+ entries.push({ name: drive, path: drive, isDir: true });
21
+ }
22
+ return { entries };
23
+ }
24
+ return { entries: [{ name: '/', path: '/', isDir: true }] };
25
+ }
11
26
  export function handleFsLs(reqPath) {
27
+ if (reqPath === FILE_SYSTEM_ROOTS_PATH) {
28
+ return listFileSystemRoots();
29
+ }
12
30
  const normalized = normalizePath(reqPath);
13
31
  if (!isPathSafe(normalized)) {
14
32
  return { error: `Access denied: ${reqPath}` };
@@ -110,4 +128,3 @@ export function handleFsUploadChunk(targetPath, chunk) {
110
128
  const flag = chunk.seq === 0 ? 'w' : 'a';
111
129
  fs.writeFileSync(targetPath, buf, { flag });
112
130
  }
113
- //# sourceMappingURL=handler.js.map
@@ -1,3 +1,2 @@
1
1
  export declare function normalizePath(inputPath: string): string;
2
2
  export declare function isPathSafe(normalizedPath: string): boolean;
3
- //# sourceMappingURL=security.d.ts.map
@@ -1,5 +1,6 @@
1
1
  import path from 'node:path';
2
2
  import os from 'node:os';
3
+ const FILE_SYSTEM_ROOTS_PATH = '__roots__';
3
4
  const ALLOWED_ROOTS = [os.homedir()];
4
5
  const BLOCKED_PATTERNS = [
5
6
  /\.\./, // directory traversal
@@ -10,12 +11,16 @@ const BLOCKED_PATTERNS = [
10
11
  /\/\.env\./,
11
12
  ];
12
13
  export function normalizePath(inputPath) {
14
+ if (inputPath === FILE_SYSTEM_ROOTS_PATH)
15
+ return inputPath;
13
16
  const expanded = inputPath.startsWith('~')
14
17
  ? path.join(os.homedir(), inputPath.slice(1))
15
18
  : inputPath;
16
19
  return path.resolve(expanded);
17
20
  }
18
21
  export function isPathSafe(normalizedPath) {
22
+ if (normalizedPath === FILE_SYSTEM_ROOTS_PATH)
23
+ return true;
19
24
  const withinAllowed = ALLOWED_ROOTS.some((root) => normalizedPath === root || normalizedPath.startsWith(root + path.sep));
20
25
  if (!withinAllowed)
21
26
  return false;
@@ -25,4 +30,3 @@ export function isPathSafe(normalizedPath) {
25
30
  }
26
31
  return true;
27
32
  }
28
- //# sourceMappingURL=security.js.map
@@ -1,2 +1 @@
1
1
  export {};
2
- //# sourceMappingURL=index.d.ts.map
package/dist/src/index.js CHANGED
@@ -23,6 +23,19 @@ const PID_FILE = resolveShennianPath('daemon.pid');
23
23
  function httpToWs(url) {
24
24
  return url.replace(/^https:\/\//, 'wss://').replace(/^http:\/\//, 'ws://');
25
25
  }
26
+ function formatDisconnectInfo(info) {
27
+ const parts = [
28
+ `trigger=${info.trigger ?? 'unknown'}`,
29
+ `phase=${info.phase}`,
30
+ `code=${info.code ?? 'unknown'}`,
31
+ `attempt=${info.reconnectAttempt}`,
32
+ ];
33
+ if (info.reason)
34
+ parts.push(`reason=${info.reason}`);
35
+ if (info.error)
36
+ parts.push(`error=${info.error}`);
37
+ return parts.join(' ');
38
+ }
26
39
  const program = new Command();
27
40
  program
28
41
  .name('shennian')
@@ -59,10 +72,13 @@ program
59
72
  const oldPid = parseInt(fs.readFileSync(pidFile, 'utf-8').trim(), 10);
60
73
  if (oldPid && oldPid !== process.pid) {
61
74
  try {
62
- process.kill(oldPid, 'SIGTERM');
75
+ process.kill(oldPid, 0);
76
+ console.log(`[${new Date().toISOString()}] daemon already running (PID ${oldPid}), skipping duplicate start`);
77
+ process.exit(0);
78
+ }
79
+ catch {
80
+ // Stale pid; continue booting and overwrite it below.
63
81
  }
64
- catch { /* noop */ }
65
- await new Promise((r) => setTimeout(r, 500));
66
82
  }
67
83
  }
68
84
  catch { /* noop */ }
@@ -143,9 +159,20 @@ program
143
159
  void scheduleAutoUpgrade(client, config.autoUpgrade ?? 'patch');
144
160
  nativeFusion?.handleConnected();
145
161
  },
146
- onDisconnected: () => {
147
- console.log(`[${new Date().toISOString()}] ⚠ Disconnected, reconnecting...`);
148
- reportLog({ level: 'warn', wsEvent: 'daemon.disconnected' });
162
+ onDisconnected: (info) => {
163
+ console.log(`[${new Date().toISOString()}] ⚠ Disconnected, reconnecting... ${formatDisconnectInfo(info)}`);
164
+ reportLog({
165
+ level: 'warn',
166
+ wsEvent: 'daemon.disconnected',
167
+ metadata: {
168
+ code: info.code,
169
+ reason: info.reason,
170
+ error: info.error,
171
+ phase: info.phase,
172
+ trigger: info.trigger,
173
+ reconnectAttempt: info.reconnectAttempt,
174
+ },
175
+ });
149
176
  },
150
177
  onReq: (req) => {
151
178
  console.log(`[${new Date().toISOString()}] [req] ${req.method}`);
@@ -153,7 +180,9 @@ program
153
180
  void sessionManager.handleReq(req);
154
181
  },
155
182
  });
156
- nativeFusion = new NativeSessionFusionService(client);
183
+ nativeFusion = process.env.SHENNIAN_NATIVE_FUSION_DISABLED === '1'
184
+ ? null
185
+ : new NativeSessionFusionService(client);
157
186
  const sessionManager = new SessionManager(client, nativeFusion);
158
187
  fs.mkdirSync(SHENNIAN_DIR, { recursive: true });
159
188
  fs.writeFileSync(PID_FILE, String(process.pid));
@@ -246,4 +275,3 @@ async function scheduleAutoUpgrade(client, policy) {
246
275
  // Use a dummy reqId since this is self-triggered
247
276
  await handleUpgradeStart(client, 'auto-upgrade', latest);
248
277
  }
249
- //# sourceMappingURL=index.js.map
@@ -16,4 +16,3 @@ export declare function initCliLogReporter(serverUrl: string, machineId: string)
16
16
  export declare function generateTraceId(): string;
17
17
  export declare function reportLog(entry: LogEntry): void;
18
18
  export {};
19
- //# sourceMappingURL=log-reporter.d.ts.map
@@ -11,24 +11,6 @@ export function generateTraceId() {
11
11
  export function reportLog(entry) {
12
12
  if (!_serverUrl || !_machineId)
13
13
  return;
14
- const body = {
15
- traceId: entry.traceId || generateTraceId(),
16
- machineId: _machineId,
17
- source: 'cli',
18
- type: entry.type ?? 'internal',
19
- level: entry.level,
20
- wsEvent: entry.wsEvent,
21
- wsDirection: entry.wsDirection,
22
- sessionId: entry.sessionId,
23
- errorMessage: entry.errorMessage,
24
- errorStack: entry.errorStack,
25
- durationMs: entry.durationMs,
26
- metadata: entry.metadata,
27
- };
28
- fetch(`${_serverUrl}/log`, {
29
- method: 'POST',
30
- headers: { 'Content-Type': 'application/json' },
31
- body: JSON.stringify(body),
32
- }).catch(() => { });
14
+ // Remote DB log reporting is intentionally disabled; keep the API for callers.
15
+ void entry;
33
16
  }
34
- //# sourceMappingURL=log-reporter.js.map
@@ -10,4 +10,3 @@ export declare function parseClaudeTranscriptChunk(filePath: string, startOffset
10
10
  nextOffset: number;
11
11
  events: ParsedNativeEvent[];
12
12
  };
13
- //# sourceMappingURL=parsers.d.ts.map