@jingyi0605/codingns 0.4.0 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (267) hide show
  1. package/bin/codingns.mjs +425 -1
  2. package/dist/public/assets/AdaptiveButlerPage-B153lk5H.css +1 -0
  3. package/dist/public/assets/AdaptiveButlerPage-R-XZw7pd.js +3 -0
  4. package/dist/public/assets/App-DUAg5urj.css +1 -0
  5. package/dist/public/assets/App-DkvE5EyM.js +30 -0
  6. package/dist/public/assets/BootstrapPage-Vu5oEJ8z.js +1 -0
  7. package/dist/public/assets/ConversationPage-Cjpg6g0J.js +2 -0
  8. package/dist/public/assets/DesktopDetachPreviewPage-BgeEqbc5.js +1 -0
  9. package/dist/public/assets/DesktopWindowPage-1WelvxdH.js +2 -0
  10. package/dist/public/assets/FileContextPanel-D_ghXJuW.js +1 -0
  11. package/dist/public/assets/GitSidebar-D9f9Jxwr.js +6 -0
  12. package/dist/public/assets/MobileCreateSessionSheet-DLq5qPkx.js +1 -0
  13. package/dist/public/assets/MobileSheet-DLg-gX1t.js +1 -0
  14. package/dist/public/assets/MobileTopHeaderFrame-DArgZI7L.js +1 -0
  15. package/dist/public/assets/MobileWorkspaceSwitcherHeader-0ywJKfBQ.js +1 -0
  16. package/dist/public/assets/ServerSettingsModal-izoYMx9U.js +1 -0
  17. package/dist/public/assets/SessionIndexPage-C5aG8FIv.js +1 -0
  18. package/dist/public/assets/SettingsPage-HJIC-P-4.js +1 -0
  19. package/dist/public/assets/TerminalManagerPanel-DpyUTo9k.js +1 -0
  20. package/dist/public/assets/{TerminalPage-6jHZV9Mh.js → TerminalPage-CtKXIU0h.js} +19 -19
  21. package/dist/public/assets/TerminalRuntimeFallbackModal-CRhOQOsT.js +1 -0
  22. package/dist/public/assets/ToolFilesPage-DcYPsS-e.js +1 -0
  23. package/dist/public/assets/ToolGitPage-CsPl89ty.js +1 -0
  24. package/dist/public/assets/ToolProcessesPage-D0dvR8xK.js +1 -0
  25. package/dist/public/assets/ToolsHomePage-4fP-KRiv.js +1 -0
  26. package/dist/public/assets/WorkbenchLandingPage-kvlfyxRo.js +1 -0
  27. package/dist/public/assets/WorkbenchLayout-ByFw4eeu.js +3 -0
  28. package/dist/public/assets/WorkbenchModal-Ctob14VR.js +1 -0
  29. package/dist/public/assets/WorkbenchShellRoute-BUITtdAg.css +1 -0
  30. package/dist/public/assets/WorkbenchShellRoute-Kw7JEZI3.js +1 -0
  31. package/dist/public/assets/WorkspaceDebugDetailPage-Com5kEXJ.js +1 -0
  32. package/dist/public/assets/WorkspaceDetailPage-D0Lrx4Uz.js +1 -0
  33. package/dist/public/assets/WorkspaceHomePage-wR8d3aP9.js +1 -0
  34. package/dist/public/assets/butler-records-events-DgWCG364.js +1 -0
  35. package/dist/public/assets/default-session-permission-mode-CcGwR4Kk.js +1 -0
  36. package/dist/public/assets/event-DvH9tcej.js +1 -0
  37. package/dist/public/assets/file-tree-icon-UFVoVzhM.js +31 -0
  38. package/dist/public/assets/index-Byp9hJ0c.js +42 -0
  39. package/dist/public/assets/index-_52jxu4a.css +1 -0
  40. package/dist/public/assets/preferences-service-KIYeE2gk.js +1 -0
  41. package/dist/public/assets/session-runtime-machine-0KNSSPp5.js +17 -0
  42. package/dist/public/assets/styles-BWPBZvze.css +1 -0
  43. package/dist/public/assets/styles-CSUx5LGe.js +1 -0
  44. package/dist/public/assets/terminal-runtime-meta-AWXJpN4r.js +1 -0
  45. package/dist/public/assets/useRegisteredDebugTemplates-DBDRdptr.js +1 -0
  46. package/dist/public/assets/window-BWqRixxq.js +1 -0
  47. package/dist/public/index.html +2 -2
  48. package/dist/server/middlewares/auth-guard.d.ts +4 -0
  49. package/dist/server/middlewares/auth-guard.js +42 -4
  50. package/dist/server/middlewares/auth-guard.js.map +1 -1
  51. package/dist/server/modules/assistant-capability/assistant-capability-controller.d.ts +62 -1
  52. package/dist/server/modules/assistant-capability/assistant-capability-controller.js +58 -0
  53. package/dist/server/modules/assistant-capability/assistant-capability-controller.js.map +1 -1
  54. package/dist/server/modules/assistant-capability/assistant-capability-service.d.ts +66 -3
  55. package/dist/server/modules/assistant-capability/assistant-capability-service.js +173 -1
  56. package/dist/server/modules/assistant-capability/assistant-capability-service.js.map +1 -1
  57. package/dist/server/modules/auth/auth-controller.d.ts +11 -1
  58. package/dist/server/modules/auth/auth-controller.js +61 -2
  59. package/dist/server/modules/auth/auth-controller.js.map +1 -1
  60. package/dist/server/modules/auth/auth-device-display-name.d.ts +10 -0
  61. package/dist/server/modules/auth/auth-device-display-name.js +190 -0
  62. package/dist/server/modules/auth/auth-device-display-name.js.map +1 -0
  63. package/dist/server/modules/auth/auth-service.d.ts +80 -5
  64. package/dist/server/modules/auth/auth-service.js +333 -23
  65. package/dist/server/modules/auth/auth-service.js.map +1 -1
  66. package/dist/server/modules/butler/assistant-automation-service.d.ts +2 -0
  67. package/dist/server/modules/butler/assistant-automation-service.js +46 -0
  68. package/dist/server/modules/butler/assistant-automation-service.js.map +1 -1
  69. package/dist/server/modules/butler/assistant-sandbox-cleanup-scheduler.d.ts +32 -0
  70. package/dist/server/modules/butler/assistant-sandbox-cleanup-scheduler.js +93 -0
  71. package/dist/server/modules/butler/assistant-sandbox-cleanup-scheduler.js.map +1 -0
  72. package/dist/server/modules/butler/assistant-sandbox-service.d.ts +16 -2
  73. package/dist/server/modules/butler/assistant-sandbox-service.js +137 -4
  74. package/dist/server/modules/butler/assistant-sandbox-service.js.map +1 -1
  75. package/dist/server/modules/butler/butler-auth-service.js +7 -2
  76. package/dist/server/modules/butler/butler-auth-service.js.map +1 -1
  77. package/dist/server/modules/butler/butler-control-session-service.d.ts +4 -1
  78. package/dist/server/modules/butler/butler-control-session-service.js +20 -1
  79. package/dist/server/modules/butler/butler-control-session-service.js.map +1 -1
  80. package/dist/server/modules/butler/butler-follow-up-evaluation-instruction-adapter.d.ts +2 -1
  81. package/dist/server/modules/butler/butler-follow-up-evaluation-instruction-adapter.js +27 -25
  82. package/dist/server/modules/butler/butler-follow-up-evaluation-instruction-adapter.js.map +1 -1
  83. package/dist/server/modules/butler/butler-follow-up-service.d.ts +32 -4
  84. package/dist/server/modules/butler/butler-follow-up-service.js +436 -331
  85. package/dist/server/modules/butler/butler-follow-up-service.js.map +1 -1
  86. package/dist/server/modules/butler/butler-inbox-analysis-service.d.ts +1 -1
  87. package/dist/server/modules/butler/butler-inbox-analysis-service.js.map +1 -1
  88. package/dist/server/modules/butler/butler-inbox-service.js +1 -0
  89. package/dist/server/modules/butler/butler-inbox-service.js.map +1 -1
  90. package/dist/server/modules/butler/butler-session-service.d.ts +3 -1
  91. package/dist/server/modules/butler/butler-session-service.js +15 -1
  92. package/dist/server/modules/butler/butler-session-service.js.map +1 -1
  93. package/dist/server/modules/butler/butler-workspace-context.d.ts +1 -1
  94. package/dist/server/modules/butler/butler-workspace-context.js +54 -28
  95. package/dist/server/modules/butler/butler-workspace-context.js.map +1 -1
  96. package/dist/server/modules/provider/provider-controller.d.ts +1 -1
  97. package/dist/server/modules/provider/provider-controller.js.map +1 -1
  98. package/dist/server/modules/relay-tunnel/crypto/relay-tunnel-identity-service.d.ts +10 -0
  99. package/dist/server/modules/relay-tunnel/crypto/relay-tunnel-identity-service.js +48 -0
  100. package/dist/server/modules/relay-tunnel/crypto/relay-tunnel-identity-service.js.map +1 -0
  101. package/dist/server/modules/relay-tunnel/crypto/relay-tunnel-packets.d.ts +48 -0
  102. package/dist/server/modules/relay-tunnel/crypto/relay-tunnel-packets.js +11 -0
  103. package/dist/server/modules/relay-tunnel/crypto/relay-tunnel-packets.js.map +1 -0
  104. package/dist/server/modules/relay-tunnel/crypto/relay-tunnel-protocol.d.ts +74 -0
  105. package/dist/server/modules/relay-tunnel/crypto/relay-tunnel-protocol.js +302 -0
  106. package/dist/server/modules/relay-tunnel/crypto/relay-tunnel-protocol.js.map +1 -0
  107. package/dist/server/modules/relay-tunnel/relay-tunnel-controller.d.ts +33 -0
  108. package/dist/server/modules/relay-tunnel/relay-tunnel-controller.js +57 -0
  109. package/dist/server/modules/relay-tunnel/relay-tunnel-controller.js.map +1 -0
  110. package/dist/server/modules/relay-tunnel/relay-tunnel-edge-proof.d.ts +9 -0
  111. package/dist/server/modules/relay-tunnel/relay-tunnel-edge-proof.js +25 -0
  112. package/dist/server/modules/relay-tunnel/relay-tunnel-edge-proof.js.map +1 -0
  113. package/dist/server/modules/relay-tunnel/relay-tunnel-gateway-service.d.ts +18 -0
  114. package/dist/server/modules/relay-tunnel/relay-tunnel-gateway-service.js +230 -0
  115. package/dist/server/modules/relay-tunnel/relay-tunnel-gateway-service.js.map +1 -0
  116. package/dist/server/modules/relay-tunnel/relay-tunnel-runtime-adapter.d.ts +41 -0
  117. package/dist/server/modules/relay-tunnel/relay-tunnel-runtime-adapter.js +443 -0
  118. package/dist/server/modules/relay-tunnel/relay-tunnel-runtime-adapter.js.map +1 -0
  119. package/dist/server/modules/relay-tunnel/relay-tunnel-service.d.ts +111 -0
  120. package/dist/server/modules/relay-tunnel/relay-tunnel-service.js +771 -0
  121. package/dist/server/modules/relay-tunnel/relay-tunnel-service.js.map +1 -0
  122. package/dist/server/modules/sessions/codex-app-server-helper-client.d.ts +2 -1
  123. package/dist/server/modules/sessions/codex-app-server-helper-client.js +78 -0
  124. package/dist/server/modules/sessions/codex-app-server-helper-client.js.map +1 -1
  125. package/dist/server/modules/sessions/codex-app-server-helper-process.js +84 -2
  126. package/dist/server/modules/sessions/codex-app-server-helper-process.js.map +1 -1
  127. package/dist/server/modules/sessions/provider-session-delete-cli.d.ts +15 -0
  128. package/dist/server/modules/sessions/provider-session-delete-cli.js +148 -0
  129. package/dist/server/modules/sessions/provider-session-delete-cli.js.map +1 -0
  130. package/dist/server/modules/sessions/session-controller.d.ts +4 -1
  131. package/dist/server/modules/sessions/session-controller.js +4 -0
  132. package/dist/server/modules/sessions/session-controller.js.map +1 -1
  133. package/dist/server/modules/sessions/session-history-service.d.ts +17 -0
  134. package/dist/server/modules/sessions/session-history-service.js +150 -1
  135. package/dist/server/modules/sessions/session-history-service.js.map +1 -1
  136. package/dist/server/modules/sessions/session-live-runtime-router-service.d.ts +25 -0
  137. package/dist/server/modules/sessions/session-live-runtime-router-service.js +42 -0
  138. package/dist/server/modules/sessions/session-live-runtime-router-service.js.map +1 -0
  139. package/dist/server/modules/sessions/session-live-runtime-service.js +34 -18
  140. package/dist/server/modules/sessions/session-live-runtime-service.js.map +1 -1
  141. package/dist/server/modules/sessions/session-message-attachment-service.d.ts +1 -0
  142. package/dist/server/modules/sessions/session-message-attachment-service.js +22 -0
  143. package/dist/server/modules/sessions/session-message-attachment-service.js.map +1 -1
  144. package/dist/server/modules/sessions/session-permission-request-service.d.ts +1 -0
  145. package/dist/server/modules/sessions/session-permission-request-service.js +200 -5
  146. package/dist/server/modules/sessions/session-permission-request-service.js.map +1 -1
  147. package/dist/server/modules/sessions/session-provider-error-mapper.js +32 -0
  148. package/dist/server/modules/sessions/session-provider-error-mapper.js.map +1 -1
  149. package/dist/server/modules/sessions/session-provider-usage-guard-service.d.ts +37 -0
  150. package/dist/server/modules/sessions/session-provider-usage-guard-service.js +179 -0
  151. package/dist/server/modules/sessions/session-provider-usage-guard-service.js.map +1 -0
  152. package/dist/server/modules/sessions/session-provider-usage-limit.d.ts +17 -0
  153. package/dist/server/modules/sessions/session-provider-usage-limit.js +465 -0
  154. package/dist/server/modules/sessions/session-provider-usage-limit.js.map +1 -0
  155. package/dist/server/modules/skills/assistant-runtime-skill-catalog.d.ts +8 -0
  156. package/dist/server/modules/skills/assistant-runtime-skill-catalog.js +26 -0
  157. package/dist/server/modules/skills/assistant-runtime-skill-catalog.js.map +1 -0
  158. package/dist/server/modules/skills/assistant-runtime-skill-cleanup.d.ts +9 -0
  159. package/dist/server/modules/skills/assistant-runtime-skill-cleanup.js +55 -0
  160. package/dist/server/modules/skills/assistant-runtime-skill-cleanup.js.map +1 -0
  161. package/dist/server/modules/skills/builtin-skill-service.js +1 -6
  162. package/dist/server/modules/skills/builtin-skill-service.js.map +1 -1
  163. package/dist/server/modules/skills/skill-controller.d.ts +2 -2
  164. package/dist/server/modules/skills/skill-controller.js +9 -1
  165. package/dist/server/modules/skills/skill-controller.js.map +1 -1
  166. package/dist/server/modules/skills/skill-manager-service.d.ts +26 -1
  167. package/dist/server/modules/skills/skill-manager-service.js +346 -90
  168. package/dist/server/modules/skills/skill-manager-service.js.map +1 -1
  169. package/dist/server/modules/skills/skill-name-policy.d.ts +2 -0
  170. package/dist/server/modules/skills/skill-name-policy.js +10 -0
  171. package/dist/server/modules/skills/skill-name-policy.js.map +1 -0
  172. package/dist/server/modules/tailscale/tailscale-service.d.ts +2 -0
  173. package/dist/server/modules/tailscale/tailscale-service.js +21 -8
  174. package/dist/server/modules/tailscale/tailscale-service.js.map +1 -1
  175. package/dist/server/modules/tasks/task-types.d.ts +3 -0
  176. package/dist/server/modules/tasks/task-types.js +3 -0
  177. package/dist/server/modules/tasks/task-types.js.map +1 -1
  178. package/dist/server/modules/terminal/template-reverse-proxy-service.js +71 -3
  179. package/dist/server/modules/terminal/template-reverse-proxy-service.js.map +1 -1
  180. package/dist/server/routes/assistant.js +30 -0
  181. package/dist/server/routes/assistant.js.map +1 -1
  182. package/dist/server/routes/auth.js +4 -0
  183. package/dist/server/routes/auth.js.map +1 -1
  184. package/dist/server/routes/sessions.js +1 -0
  185. package/dist/server/routes/sessions.js.map +1 -1
  186. package/dist/server/routes/system.d.ts +2 -1
  187. package/dist/server/routes/system.js +13 -1
  188. package/dist/server/routes/system.js.map +1 -1
  189. package/dist/server/server/create-server.d.ts +10 -0
  190. package/dist/server/server/create-server.js +82 -12
  191. package/dist/server/server/create-server.js.map +1 -1
  192. package/dist/server/shared/utils/tokens.d.ts +3 -1
  193. package/dist/server/shared/utils/tokens.js +9 -2
  194. package/dist/server/shared/utils/tokens.js.map +1 -1
  195. package/dist/server/storage/repositories/assistant-automation-task-repository.d.ts +2 -0
  196. package/dist/server/storage/repositories/assistant-automation-task-repository.js +8 -2
  197. package/dist/server/storage/repositories/assistant-automation-task-repository.js.map +1 -1
  198. package/dist/server/storage/repositories/assistant-sandbox-workspace-repository.d.ts +1 -0
  199. package/dist/server/storage/repositories/assistant-sandbox-workspace-repository.js +27 -0
  200. package/dist/server/storage/repositories/assistant-sandbox-workspace-repository.js.map +1 -1
  201. package/dist/server/storage/repositories/auth-device-repository.d.ts +22 -0
  202. package/dist/server/storage/repositories/auth-device-repository.js +97 -0
  203. package/dist/server/storage/repositories/auth-device-repository.js.map +1 -0
  204. package/dist/server/storage/repositories/auth-device-session-repository.d.ts +17 -0
  205. package/dist/server/storage/repositories/auth-device-session-repository.js +82 -0
  206. package/dist/server/storage/repositories/auth-device-session-repository.js.map +1 -0
  207. package/dist/server/storage/repositories/auth-login-event-repository.d.ts +9 -0
  208. package/dist/server/storage/repositories/auth-login-event-repository.js +53 -0
  209. package/dist/server/storage/repositories/auth-login-event-repository.js.map +1 -0
  210. package/dist/server/storage/repositories/auth-token-repository.d.ts +4 -0
  211. package/dist/server/storage/repositories/auth-token-repository.js +58 -5
  212. package/dist/server/storage/repositories/auth-token-repository.js.map +1 -1
  213. package/dist/server/storage/repositories/butler-follow-up-task-repository.js +21 -3
  214. package/dist/server/storage/repositories/butler-follow-up-task-repository.js.map +1 -1
  215. package/dist/server/storage/repositories/instance-relay-tunnel-identity-repository.d.ts +8 -0
  216. package/dist/server/storage/repositories/instance-relay-tunnel-identity-repository.js +52 -0
  217. package/dist/server/storage/repositories/instance-relay-tunnel-identity-repository.js.map +1 -0
  218. package/dist/server/storage/repositories/instance-relay-tunnel-repository.d.ts +10 -0
  219. package/dist/server/storage/repositories/instance-relay-tunnel-repository.js +153 -0
  220. package/dist/server/storage/repositories/instance-relay-tunnel-repository.js.map +1 -0
  221. package/dist/server/storage/repositories/instance-tailscale-repository.js +6 -3
  222. package/dist/server/storage/repositories/instance-tailscale-repository.js.map +1 -1
  223. package/dist/server/storage/repositories/managed-skill-repository.d.ts +2 -1
  224. package/dist/server/storage/repositories/managed-skill-repository.js +14 -4
  225. package/dist/server/storage/repositories/managed-skill-repository.js.map +1 -1
  226. package/dist/server/storage/repositories/session-message-attachment-repository.d.ts +2 -0
  227. package/dist/server/storage/repositories/session-message-attachment-repository.js +24 -0
  228. package/dist/server/storage/repositories/session-message-attachment-repository.js.map +1 -1
  229. package/dist/server/storage/sqlite/client.js +297 -2
  230. package/dist/server/storage/sqlite/client.js.map +1 -1
  231. package/dist/server/storage/sqlite/schema.sql +122 -4
  232. package/dist/server/types/domain.d.ts +82 -1
  233. package/dist/server/ws/workbench-ws-hub.js +99 -75
  234. package/dist/server/ws/workbench-ws-hub.js.map +1 -1
  235. package/dist/server/ws/ws-auth-guard.js +1 -4
  236. package/dist/server/ws/ws-auth-guard.js.map +1 -1
  237. package/dist/server/ws/ws-server.d.ts +1 -1
  238. package/dist/server/ws/ws-server.js.map +1 -1
  239. package/node_modules/@codingns/session-sync-core/dist/codex-resume-history.d.ts +1 -0
  240. package/node_modules/@codingns/session-sync-core/dist/codex-resume-history.js +80 -0
  241. package/node_modules/@codingns/session-sync-core/dist/codex-resume-history.js.map +1 -0
  242. package/node_modules/@codingns/session-sync-core/dist/providers/claude-code.d.ts +1 -0
  243. package/node_modules/@codingns/session-sync-core/dist/providers/claude-code.js +11 -1
  244. package/node_modules/@codingns/session-sync-core/dist/providers/claude-code.js.map +1 -1
  245. package/node_modules/@codingns/session-sync-core/dist/providers/codex.d.ts +11 -0
  246. package/node_modules/@codingns/session-sync-core/dist/providers/codex.js +132 -21
  247. package/node_modules/@codingns/session-sync-core/dist/providers/codex.js.map +1 -1
  248. package/node_modules/@codingns/session-sync-core/dist/providers/gemini.d.ts +2 -0
  249. package/node_modules/@codingns/session-sync-core/dist/providers/gemini.js +53 -1
  250. package/node_modules/@codingns/session-sync-core/dist/providers/gemini.js.map +1 -1
  251. package/node_modules/@codingns/session-sync-core/dist/providers/kimi.d.ts +1 -0
  252. package/node_modules/@codingns/session-sync-core/dist/providers/kimi.js +10 -1
  253. package/node_modules/@codingns/session-sync-core/dist/providers/kimi.js.map +1 -1
  254. package/node_modules/@codingns/session-sync-core/dist/providers/opencode.d.ts +1 -0
  255. package/node_modules/@codingns/session-sync-core/dist/providers/opencode.js +30 -0
  256. package/node_modules/@codingns/session-sync-core/dist/providers/opencode.js.map +1 -1
  257. package/node_modules/@codingns/session-sync-core/dist/runtime/codex-runtime.d.ts +5 -1
  258. package/node_modules/@codingns/session-sync-core/dist/runtime/codex-runtime.js +145 -58
  259. package/node_modules/@codingns/session-sync-core/dist/runtime/codex-runtime.js.map +1 -1
  260. package/node_modules/@codingns/session-sync-core/dist/services.d.ts +1 -0
  261. package/node_modules/@codingns/session-sync-core/dist/services.js +7 -0
  262. package/node_modules/@codingns/session-sync-core/dist/services.js.map +1 -1
  263. package/node_modules/@codingns/session-sync-core/dist/types.d.ts +2 -0
  264. package/package.json +1 -1
  265. package/scripts/postinstall.mjs +0 -33
  266. package/dist/public/assets/index-CSVhg7I8.js +0 -123
  267. package/dist/public/assets/index-Ce1VX19m.css +0 -1
package/bin/codingns.mjs CHANGED
@@ -7,6 +7,15 @@ import { fileURLToPath } from "node:url";
7
7
 
8
8
  const packageRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..");
9
9
  const distRoot = path.join(packageRoot, "dist");
10
+ const ASSISTANT_REQUEST_SOURCE_HEADER = "X-CodingNS-Assistant-Source";
11
+ const ASSISTANT_CLI_REQUEST_SOURCE = "assistant-cli";
12
+ const PROVIDER_SESSION_DELETE_PROVIDERS = new Set([
13
+ "claude-code",
14
+ "codex",
15
+ "opencode",
16
+ "gemini",
17
+ "kimi"
18
+ ]);
10
19
 
11
20
  const [command, ...argv] = process.argv.slice(2);
12
21
 
@@ -21,6 +30,9 @@ switch (command) {
21
30
  case "assistant":
22
31
  await runAssistantCommand(argv);
23
32
  break;
33
+ case "provider-sessions":
34
+ await runProviderSessionsCommand(argv);
35
+ break;
24
36
  case "skills":
25
37
  await runSkillsCommand(argv);
26
38
  break;
@@ -200,6 +212,16 @@ async function runAssistantCommand(argv) {
200
212
  }));
201
213
  return;
202
214
  }
215
+ case "sessions:delete": {
216
+ const [sessionId, ...tail] = rest;
217
+ await printAssistantResponse(await requestAssistant({
218
+ method: "DELETE",
219
+ path: `/api/assistant/sessions/${requirePositional(sessionId, "sessionId")}`,
220
+ argv: tail,
221
+ helpTopic: "sessions.delete"
222
+ }));
223
+ return;
224
+ }
203
225
  case "sessions:send": {
204
226
  const [sessionId, ...tail] = rest;
205
227
  await printAssistantResponse(await requestAssistant({
@@ -464,6 +486,110 @@ async function runAssistantCommand(argv) {
464
486
  }));
465
487
  return;
466
488
  }
489
+ case "follow-ups:list":
490
+ await printAssistantResponse(await requestAssistant({
491
+ method: "GET",
492
+ path: "/api/assistant/follow-ups",
493
+ argv: rest,
494
+ supportedOptions: ["status", "project-id", "session-id", "limit"],
495
+ helpTopic: "follow-ups.list"
496
+ }, (options) => ({
497
+ status: readOptionalTrimmedValue(options.values.status),
498
+ projectId: readOptionalTrimmedValue(options.values["project-id"]),
499
+ sessionId: readOptionalTrimmedValue(options.values["session-id"]),
500
+ limit: readOptionalTrimmedValue(options.values.limit)
501
+ })));
502
+ return;
503
+ case "follow-ups:get": {
504
+ const [taskId, ...tail] = rest;
505
+ await printAssistantResponse(await requestAssistant({
506
+ method: "GET",
507
+ path: `/api/assistant/follow-ups/${requirePositional(taskId, "taskId")}`,
508
+ argv: tail,
509
+ helpTopic: "follow-ups.get"
510
+ }));
511
+ return;
512
+ }
513
+ case "follow-ups:create":
514
+ await printAssistantResponse(await requestAssistant({
515
+ method: "POST",
516
+ path: "/api/assistant/follow-ups",
517
+ argv: rest,
518
+ supportedOptions: [
519
+ "project-id",
520
+ "butler-session-id",
521
+ "provider",
522
+ "objective",
523
+ "completion-criteria",
524
+ "max-auto-continue-count",
525
+ "check-interval-seconds"
526
+ ],
527
+ helpTopic: "follow-ups.create"
528
+ }, (options) => ({
529
+ projectId: requireOptionValue(options.values["project-id"], "project-id"),
530
+ butlerSessionId: requireOptionValue(options.values["butler-session-id"], "butler-session-id"),
531
+ providerId: readOptionalTrimmedValue(options.values.provider),
532
+ objective: requireOptionValue(options.values.objective, "objective"),
533
+ completionCriteria: readOptionalTrimmedValue(options.values["completion-criteria"]),
534
+ maxAutoContinueCount: readOptionalTrimmedValue(options.values["max-auto-continue-count"]),
535
+ checkIntervalSeconds: readOptionalTrimmedValue(options.values["check-interval-seconds"])
536
+ })));
537
+ return;
538
+ case "follow-ups:continue": {
539
+ const [taskId, ...tail] = rest;
540
+ await printAssistantResponse(await requestAssistant({
541
+ method: "POST",
542
+ path: `/api/assistant/follow-ups/${requirePositional(taskId, "taskId")}/continue`,
543
+ argv: tail,
544
+ supportedOptions: ["summary", "continue-prompt"],
545
+ helpTopic: "follow-ups.continue"
546
+ }, (options) => ({
547
+ summary: requireOptionValue(options.values.summary, "summary"),
548
+ continuePrompt: requireOptionValue(options.values["continue-prompt"], "continue-prompt")
549
+ })));
550
+ return;
551
+ }
552
+ case "follow-ups:waiting-user": {
553
+ const [taskId, ...tail] = rest;
554
+ await printAssistantResponse(await requestAssistant({
555
+ method: "POST",
556
+ path: `/api/assistant/follow-ups/${requirePositional(taskId, "taskId")}/waiting-user`,
557
+ argv: tail,
558
+ supportedOptions: ["summary", "waiting-reason"],
559
+ helpTopic: "follow-ups.waiting-user"
560
+ }, (options) => ({
561
+ summary: requireOptionValue(options.values.summary, "summary"),
562
+ waitingReason: requireOptionValue(options.values["waiting-reason"], "waiting-reason")
563
+ })));
564
+ return;
565
+ }
566
+ case "follow-ups:complete": {
567
+ const [taskId, ...tail] = rest;
568
+ await printAssistantResponse(await requestAssistant({
569
+ method: "POST",
570
+ path: `/api/assistant/follow-ups/${requirePositional(taskId, "taskId")}/complete`,
571
+ argv: tail,
572
+ supportedOptions: ["summary"],
573
+ helpTopic: "follow-ups.complete"
574
+ }, (options) => ({
575
+ summary: requireOptionValue(options.values.summary, "summary")
576
+ })));
577
+ return;
578
+ }
579
+ case "follow-ups:fail": {
580
+ const [taskId, ...tail] = rest;
581
+ await printAssistantResponse(await requestAssistant({
582
+ method: "POST",
583
+ path: `/api/assistant/follow-ups/${requirePositional(taskId, "taskId")}/fail`,
584
+ argv: tail,
585
+ supportedOptions: ["summary", "reason"],
586
+ helpTopic: "follow-ups.fail"
587
+ }, (options) => ({
588
+ summary: requireOptionValue(options.values.summary, "summary"),
589
+ reason: readOptionalTrimmedValue(options.values.reason)
590
+ })));
591
+ return;
592
+ }
467
593
  case "terminals:list":
468
594
  await printAssistantResponse(await requestAssistant({
469
595
  method: "GET",
@@ -884,6 +1010,116 @@ async function runSkillsCommand(argv) {
884
1010
  }
885
1011
  }
886
1012
 
1013
+ async function runProviderSessionsCommand(argv) {
1014
+ const [action, ...rest] = argv;
1015
+
1016
+ if (!action || isHelpToken(action)) {
1017
+ printProviderSessionsHelpTopic(buildProviderSessionsHelpTopic(rest[0]), 0);
1018
+ }
1019
+
1020
+ if (rest.length > 0 && isHelpToken(rest[0])) {
1021
+ printProviderSessionsHelpTopic(buildProviderSessionsHelpTopic(action), 0);
1022
+ }
1023
+
1024
+ switch (action) {
1025
+ case "delete": {
1026
+ const options = parseArgs(rest, {
1027
+ supportedOptions: ["provider", "provider-session-id", "raw-store-ref"]
1028
+ });
1029
+
1030
+ if (options.help) {
1031
+ printProviderSessionsHelpTopic("provider-sessions.delete", 0);
1032
+ }
1033
+
1034
+ if (options.errors.length > 0) {
1035
+ for (const error of options.errors) {
1036
+ console.error(`[codingns] ${error}`);
1037
+ }
1038
+ printProviderSessionsHelpTopic("provider-sessions.delete", 1);
1039
+ }
1040
+
1041
+ const provider = requireOptionValue(options.values.provider, "provider");
1042
+ const providerSessionId = requireOptionValue(
1043
+ options.values["provider-session-id"],
1044
+ "provider-session-id"
1045
+ );
1046
+ const rawStoreRef = requireOptionValue(options.values["raw-store-ref"], "raw-store-ref");
1047
+
1048
+ if (!PROVIDER_SESSION_DELETE_PROVIDERS.has(provider)) {
1049
+ fail(
1050
+ `provider-sessions delete 仅支持 ${[...PROVIDER_SESSION_DELETE_PROVIDERS].join(", ")}`
1051
+ );
1052
+ }
1053
+
1054
+ const { SessionSyncService, ProviderRegistry } = await import("@codingns/session-sync-core");
1055
+ const {
1056
+ ClaudeCodeAdapter,
1057
+ CodexAdapter,
1058
+ GeminiAdapter,
1059
+ KimiAdapter,
1060
+ OpenCodeAdapter
1061
+ } = await import("@codingns/session-sync-core");
1062
+ const homeDir = os.homedir();
1063
+ const registry = new ProviderRegistry([
1064
+ new ClaudeCodeAdapter({
1065
+ homeDir: readStringOption(
1066
+ process.env.CODINGNS_CLAUDE_CODE_HOME,
1067
+ path.join(homeDir, ".claude")
1068
+ )
1069
+ }),
1070
+ new CodexAdapter({
1071
+ homeDir: readStringOption(
1072
+ process.env.CODINGNS_CODEX_HOME,
1073
+ path.join(homeDir, ".codex")
1074
+ )
1075
+ }),
1076
+ new GeminiAdapter({
1077
+ homeDir: readStringOption(
1078
+ process.env.CODINGNS_GEMINI_HOME,
1079
+ path.join(homeDir, ".gemini")
1080
+ ),
1081
+ commandPath: readStringOption(process.env.CODINGNS_GEMINI_COMMAND, "gemini")
1082
+ }),
1083
+ new KimiAdapter({
1084
+ homeDir: readStringOption(
1085
+ process.env.CODINGNS_KIMI_HOME,
1086
+ path.join(homeDir, ".kimi")
1087
+ ),
1088
+ defaultModel: readOptionalTrimmedValue(process.env.CODINGNS_KIMI_DEFAULT_MODEL)
1089
+ }),
1090
+ new OpenCodeAdapter({
1091
+ baseUrl: readOptionalTrimmedValue(process.env.CODINGNS_OPENCODE_BASE_URL) ?? undefined,
1092
+ dataDir:
1093
+ readOptionalTrimmedValue(process.env.CODINGNS_OPENCODE_DATA_DIR) ?? undefined,
1094
+ dbPath:
1095
+ readOptionalTrimmedValue(process.env.CODINGNS_OPENCODE_DB_PATH) ?? undefined
1096
+ })
1097
+ ]);
1098
+ const sessionSyncService = new SessionSyncService(registry);
1099
+
1100
+ try {
1101
+ await sessionSyncService.deleteSession(provider, providerSessionId, rawStoreRef);
1102
+ } catch (error) {
1103
+ console.error(
1104
+ JSON.stringify(normalizeProviderSessionDeleteFailure(error), null, 2)
1105
+ );
1106
+ process.exit(1);
1107
+ }
1108
+
1109
+ await printAssistantResponse({
1110
+ ok: true,
1111
+ provider,
1112
+ providerSessionId,
1113
+ rawStoreRef
1114
+ });
1115
+ return;
1116
+ }
1117
+ default:
1118
+ console.error(`[codingns] 不支持的 provider-sessions 子命令:${action}`);
1119
+ printProviderSessionsHelpTopic("provider-sessions", 1);
1120
+ }
1121
+ }
1122
+
887
1123
  async function requestAssistant(command, buildPayload) {
888
1124
  const options = parseArgs(command.argv, {
889
1125
  supportedOptions: [
@@ -927,6 +1163,7 @@ async function requestAssistant(command, buildPayload) {
927
1163
  method: command.method,
928
1164
  headers: {
929
1165
  Authorization: `Bearer ${accessToken}`,
1166
+ [ASSISTANT_REQUEST_SOURCE_HEADER]: ASSISTANT_CLI_REQUEST_SOURCE,
930
1167
  ...(usesJsonBody ? { "Content-Type": "application/json" } : {})
931
1168
  },
932
1169
  body: usesJsonBody ? JSON.stringify(payload ?? {}) : undefined
@@ -1411,6 +1648,7 @@ codingns 用法:
1411
1648
 
1412
1649
  codingns start [--host 0.0.0.0] [--port 3002] [--data-dir ~/.codingns] [--demo]
1413
1650
  codingns assistant <group> <action> [options]
1651
+ codingns provider-sessions <action> [options]
1414
1652
  codingns skills <action> [options]
1415
1653
 
1416
1654
  说明:
@@ -1430,6 +1668,7 @@ assistant 例子:
1430
1668
  codingns assistant debug-targets launch-plan <targetId> --port-request role=backend,cwd=apps/api,port=44001 --token <token>
1431
1669
  codingns assistant worktrees tree --root-workspace-id <id> --token <token>
1432
1670
  codingns assistant sessions send <sessionId> --message "继续修复类型错误" --token <token>
1671
+ codingns assistant follow-ups continue <taskId> --summary "目标还没完成" --continue-prompt "继续补齐剩余实现" --token <token>
1433
1672
  codingns assistant terminals send <terminalId> --input "npm test\\n" --token <token>
1434
1673
  codingns assistant terminals close <terminalId> --token <token>
1435
1674
 
@@ -1438,6 +1677,10 @@ skills 例子:
1438
1677
  codingns skills overview --token <token>
1439
1678
  codingns skills add --source ./my-skill --target codex --token <token>
1440
1679
  codingns skills sync <skillId> --target gemini --token <token>
1680
+
1681
+ provider-sessions 例子:
1682
+
1683
+ codingns provider-sessions delete --provider codex --provider-session-id <id> --raw-store-ref <ref>
1441
1684
  `.trim();
1442
1685
 
1443
1686
  if (exitCode === 0) {
@@ -1473,6 +1716,18 @@ function printSkillsHelpTopic(topic, exitCode) {
1473
1716
  process.exit(exitCode);
1474
1717
  }
1475
1718
 
1719
+ function printProviderSessionsHelpTopic(topic, exitCode) {
1720
+ const output = getProviderSessionsHelpText(topic);
1721
+
1722
+ if (exitCode === 0) {
1723
+ console.log(output);
1724
+ } else {
1725
+ console.error(output);
1726
+ }
1727
+
1728
+ process.exit(exitCode);
1729
+ }
1730
+
1476
1731
  function getAssistantHelpText(topic) {
1477
1732
  switch (topic) {
1478
1733
  case "capabilities":
@@ -1637,6 +1892,7 @@ codingns assistant sessions
1637
1892
  get 读取会话详情
1638
1893
  messages 读取消息窗口
1639
1894
  runtime 读取运行态
1895
+ delete 删除真实会话
1640
1896
  send 向真实项目会话发送消息
1641
1897
  fork 从会话或消息点 fork 新会话
1642
1898
 
@@ -1704,6 +1960,16 @@ codingns assistant sessions send
1704
1960
 
1705
1961
  用法:
1706
1962
  codingns assistant sessions send <sessionId> --message "..." [--client-request-id <id>] [--model <model>] [--reasoning-level <level>] [--permission-mode <mode>] --token <token>
1963
+ `.trim();
1964
+ case "sessions.delete":
1965
+ return `
1966
+ codingns assistant sessions delete
1967
+
1968
+ 用途:
1969
+ 删除指定真实会话;这会同时清理助手侧关联记录和工作区索引。
1970
+
1971
+ 用法:
1972
+ codingns assistant sessions delete <sessionId> --token <token>
1707
1973
  `.trim();
1708
1974
  case "sessions.fork":
1709
1975
  return `
@@ -1901,6 +2167,93 @@ codingns assistant timers cancel
1901
2167
 
1902
2168
  用法:
1903
2169
  codingns assistant timers cancel <timerId> --token <token>
2170
+ `.trim();
2171
+ case "follow-ups":
2172
+ return `
2173
+ codingns assistant follow-ups
2174
+
2175
+ 可用动作:
2176
+ list 列出跟进任务
2177
+ get 读取单个跟进任务
2178
+ create 创建新的跟进任务
2179
+ continue 回写继续推进结论
2180
+ waiting-user 回写等待用户结论
2181
+ complete 回写已完成结论
2182
+ fail 回写失败结论
2183
+
2184
+ 示例:
2185
+ codingns assistant follow-ups list --status active --token <token>
2186
+ codingns assistant follow-ups continue <taskId> --summary "目标还没做完" --continue-prompt "继续补齐剩余实现" --token <token>
2187
+ `.trim();
2188
+ case "follow-ups.list":
2189
+ return `
2190
+ codingns assistant follow-ups list
2191
+
2192
+ 用途:
2193
+ 查看当前用户可见的会话跟进任务。
2194
+
2195
+ 用法:
2196
+ codingns assistant follow-ups list [--status active|waiting_user|completed|failed|cancelled] [--project-id <projectId>] [--session-id <sessionId>] [--limit <n>] --token <token>
2197
+ `.trim();
2198
+ case "follow-ups.get":
2199
+ return `
2200
+ codingns assistant follow-ups get
2201
+
2202
+ 用途:
2203
+ 读取单个跟进任务详情和历史轮次。
2204
+
2205
+ 用法:
2206
+ codingns assistant follow-ups get <taskId> --token <token>
2207
+ `.trim();
2208
+ case "follow-ups.create":
2209
+ return `
2210
+ codingns assistant follow-ups create
2211
+
2212
+ 用途:
2213
+ 为指定 Butler 会话创建新的跟进任务。
2214
+
2215
+ 用法:
2216
+ codingns assistant follow-ups create --project-id <projectId> --butler-session-id <butlerSessionId> --objective "..." [--provider codex|claude-code] [--completion-criteria "..."] [--max-auto-continue-count <n>] [--check-interval-seconds <n>] --token <token>
2217
+ `.trim();
2218
+ case "follow-ups.continue":
2219
+ return `
2220
+ codingns assistant follow-ups continue
2221
+
2222
+ 用途:
2223
+ 回写“继续推进”结论,并安排下一轮自动跟进。
2224
+
2225
+ 用法:
2226
+ codingns assistant follow-ups continue <taskId> --summary "..." --continue-prompt "..." --token <token>
2227
+ `.trim();
2228
+ case "follow-ups.waiting-user":
2229
+ return `
2230
+ codingns assistant follow-ups waiting-user
2231
+
2232
+ 用途:
2233
+ 回写“需要等待用户”结论,并写明必须等待的原因。
2234
+
2235
+ 用法:
2236
+ codingns assistant follow-ups waiting-user <taskId> --summary "..." --waiting-reason "..." --token <token>
2237
+ `.trim();
2238
+ case "follow-ups.complete":
2239
+ return `
2240
+ codingns assistant follow-ups complete
2241
+
2242
+ 用途:
2243
+ 回写“任务已完成”结论,并结束当前跟进。
2244
+
2245
+ 用法:
2246
+ codingns assistant follow-ups complete <taskId> --summary "..." --token <token>
2247
+ `.trim();
2248
+ case "follow-ups.fail":
2249
+ return `
2250
+ codingns assistant follow-ups fail
2251
+
2252
+ 用途:
2253
+ 回写“任务失败”结论,并记录失败原因。
2254
+
2255
+ 用法:
2256
+ codingns assistant follow-ups fail <taskId> --summary "..." [--reason "..."] --token <token>
1904
2257
  `.trim();
1905
2258
  case "terminals":
1906
2259
  return `
@@ -2143,10 +2496,11 @@ codingns assistant worktrees cleanup
2143
2496
  return `
2144
2497
  codingns assistant 用法:
2145
2498
 
2146
- codingns assistant help [capabilities|projects|sessions|sandboxes|automations|timers|terminals|debug-targets|debug-runtimes|workspaces|worktrees] [action]
2499
+ codingns assistant help [capabilities|projects|sessions|sandboxes|automations|timers|follow-ups|terminals|debug-targets|debug-runtimes|workspaces|worktrees] [action]
2147
2500
  codingns assistant capabilities list [--base-url http://127.0.0.1:3002] --token <token>
2148
2501
  codingns assistant projects list [--workspace-id <id>] [--status active|paused|archived] [--risk-level low|medium|high] --token <token>
2149
2502
  codingns assistant projects get <projectId> [--base-url ...] --token <token>
2503
+ codingns assistant follow-ups continue <taskId> --summary "..." --continue-prompt "..." --token <token>
2150
2504
  codingns assistant debug-targets compatibility-matrix [--base-url ...] --token <token>
2151
2505
  codingns assistant debug-targets analyze --workspace-id <id> --root-path <path> [--command-hint <command>] [--command-hint <command>] [--base-url ...] --token <token>
2152
2506
  codingns assistant debug-targets framework-analysis <targetId> [--base-url ...] --token <token>
@@ -2170,6 +2524,7 @@ codingns assistant 用法:
2170
2524
  codingns assistant sessions get <sessionId> [--base-url ...] --token <token>
2171
2525
  codingns assistant sessions messages <sessionId> [--cursor <cursor>] [--limit 40] [--direction forward|backward] --token <token>
2172
2526
  codingns assistant sessions runtime <sessionId> [--base-url ...] --token <token>
2527
+ codingns assistant sessions delete <sessionId> [--base-url ...] --token <token>
2173
2528
  codingns assistant sessions send <sessionId> --message "..." [--client-request-id <id>] [--model <model>] [--reasoning-level <level>] [--permission-mode <mode>] --token <token>
2174
2529
  codingns assistant sessions fork <sessionId> [--source-type session|message] [--message-id <id>] [--strategy auto|native-only|reconstruct-only] [--target-provider <provider>] --token <token>
2175
2530
  codingns assistant sandboxes list [--status active|archived|expired|deleted] [--base-url ...] --token <token>
@@ -2205,6 +2560,39 @@ codingns assistant 用法:
2205
2560
  }
2206
2561
  }
2207
2562
 
2563
+ function getProviderSessionsHelpText(topic) {
2564
+ switch (topic) {
2565
+ case "provider-sessions.delete":
2566
+ return `
2567
+ codingns provider-sessions delete
2568
+
2569
+ 用途:
2570
+ 直接删除底层 provider 会话,不经过项目会话索引。适合给 Host 或脚本层做真实删除调用。
2571
+
2572
+ 用法:
2573
+ codingns provider-sessions delete --provider <claude-code|codex|opencode|gemini|kimi> --provider-session-id <id> --raw-store-ref <ref>
2574
+ `.trim();
2575
+ default:
2576
+ return `
2577
+ codingns provider-sessions 用法:
2578
+
2579
+ codingns provider-sessions delete --provider <claude-code|codex|opencode|gemini|kimi> --provider-session-id <id> --raw-store-ref <ref>
2580
+
2581
+ 环境变量:
2582
+
2583
+ CODINGNS_CLAUDE_CODE_HOME Claude Code 数据目录,默认 ~/.claude
2584
+ CODINGNS_CODEX_HOME Codex 数据目录,默认 ~/.codex
2585
+ CODINGNS_GEMINI_HOME Gemini 数据目录,默认 ~/.gemini
2586
+ CODINGNS_GEMINI_COMMAND Gemini CLI 路径,默认 gemini
2587
+ CODINGNS_KIMI_HOME Kimi 数据目录,默认 ~/.kimi
2588
+ CODINGNS_KIMI_DEFAULT_MODEL Kimi 默认模型,可选
2589
+ CODINGNS_OPENCODE_BASE_URL OpenCode server 地址,可选
2590
+ CODINGNS_OPENCODE_DATA_DIR OpenCode 数据目录,可选
2591
+ CODINGNS_OPENCODE_DB_PATH OpenCode sqlite 路径,可选
2592
+ `.trim();
2593
+ }
2594
+ }
2595
+
2208
2596
  function getSkillsHelpText(topic) {
2209
2597
  switch (topic) {
2210
2598
  case "skills.overview":
@@ -2424,10 +2812,46 @@ function buildSkillsHelpTopic(action) {
2424
2812
  return `skills.${action}`;
2425
2813
  }
2426
2814
 
2815
+ function buildProviderSessionsHelpTopic(action) {
2816
+ if (!action || action === "--help" || action === "-h") {
2817
+ return "provider-sessions";
2818
+ }
2819
+
2820
+ return `provider-sessions.${action}`;
2821
+ }
2822
+
2427
2823
  function isHelpToken(value) {
2428
2824
  return value === "help" || value === "--help" || value === "-h";
2429
2825
  }
2430
2826
 
2827
+ function normalizeProviderSessionDeleteFailure(error) {
2828
+ const errorCode =
2829
+ error instanceof Error && typeof error.message === "string" && error.message.trim().length > 0
2830
+ ? error.message.trim()
2831
+ : "PROVIDER_DELETE_FAILED";
2832
+
2833
+ return {
2834
+ ok: false,
2835
+ errorCode,
2836
+ detail: describeProviderSessionDeleteFailure(errorCode)
2837
+ };
2838
+ }
2839
+
2840
+ function describeProviderSessionDeleteFailure(errorCode) {
2841
+ switch (errorCode) {
2842
+ case "PROVIDER_DELETE_NOT_SUPPORTED":
2843
+ return "当前 provider 还没有接入 CLI 删除能力";
2844
+ case "PROVIDER_SESSION_NOT_FOUND":
2845
+ return "provider 会话不存在或已经被删除";
2846
+ case "PROVIDER_SESSION_ID_REQUIRED":
2847
+ return "providerSessionId 不能为空";
2848
+ case "PROVIDER_NOT_SUPPORTED":
2849
+ return "当前 provider 不受支持";
2850
+ default:
2851
+ return errorCode;
2852
+ }
2853
+ }
2854
+
2431
2855
  function fail(message) {
2432
2856
  console.error(`[codingns] ${message}`);
2433
2857
  process.exit(1);
@@ -0,0 +1 @@
1
+ .butler-page-shell{display:flex;flex-direction:column;height:100%;min-height:0;padding:0;box-sizing:border-box;overflow:hidden}.butler-chat-workspace{align-items:stretch;background:var(--bg-surface)}.butler-loading-shell{align-items:stretch;justify-content:center;padding:24px;background:radial-gradient(circle at top left,rgba(14,165,233,.12),transparent 36%),radial-gradient(circle at bottom right,rgba(16,185,129,.12),transparent 32%),var(--bg-surface)}.butler-main-column{min-height:0;flex:1 1 auto;display:flex;flex-direction:column;gap:0;padding:0;overflow:hidden;border:none;background:transparent}.butler-main-header{min-height:var(--workbench-header-min-height);height:var(--workbench-header-min-height);box-sizing:border-box;align-items:center;gap:8px;padding-left:calc(var(--workbench-header-padding-inline) + var(--workbench-collapsed-left-content-inset, 0px));padding-right:calc(var(--workbench-header-padding-inline) + var(--workbench-collapsed-right-content-inset, 0px));border-bottom:1px solid color-mix(in srgb,var(--border-primary) 78%,transparent);background:var(--bg-surface);transition:padding-left .22s cubic-bezier(.2,.9,.2,1),padding-right .22s cubic-bezier(.2,.9,.2,1)}.butler-header-main{display:flex;flex:1 1 auto;flex-direction:row;align-items:center;justify-content:flex-start;gap:10px;min-width:0;text-align:left}.butler-header-analysis-anchor{position:relative;display:inline-flex;align-items:center;gap:10px;min-width:0}.butler-header-analysis-popover{position:absolute;top:calc(100% + 8px);left:0;z-index:20;width:min(340px,72vw);padding:12px;border:1px solid var(--border-primary);border-radius:12px;background:color-mix(in srgb,var(--bg-surface) 97%,white 3%);box-shadow:0 14px 28px #0f172a29}.butler-header-analysis-popover strong{display:block;margin-bottom:8px;font-size:13px}.butler-header-analysis-item+.butler-header-analysis-item{margin-top:10px;padding-top:10px;border-top:1px solid color-mix(in srgb,var(--border-primary) 78%,transparent)}.butler-header-analysis-popover p{margin:0;font-size:12px;line-height:1.6;color:var(--text-secondary)}.butler-header-analysis-popover p+p{margin-top:6px}.butler-chat-avatar,.butler-message-avatar{display:inline-flex;align-items:center;justify-content:center;border-radius:18px;background:linear-gradient(135deg,#0ea5e924,#10b9812e);color:#0f172a;box-shadow:inset 0 0 0 1px #0ea5e914}.butler-chat-avatar{width:24px;height:24px;flex:0 0 auto;border-radius:8px}.butler-chat-avatar span{font-size:14px}.butler-message-avatar{width:24px;height:24px;font-size:18px}.butler-main-heading{min-width:0;display:flex;align-items:center;flex:0 1 auto}.butler-main-heading h1{margin:0;font-size:13px;line-height:1.35;font-weight:500;color:var(--text-secondary, #6b7280);white-space:nowrap}.butler-secondary-text{color:var(--text-secondary, #6b7280);font-size:11px;line-height:1.45}.butler-toolbar-cluster{display:flex;flex-wrap:nowrap;justify-content:flex-end;gap:8px;align-items:center;min-width:0;flex:0 0 auto}.butler-toolbar-button,.butler-provider-switcher button{border:1px solid rgba(15,23,42,.12);border-radius:10px;padding:8px 12px;background:#ffffffeb;color:var(--text-primary, #0f172a);cursor:pointer;transition:border-color .12s ease,transform .12s ease,background .12s ease,box-shadow .12s ease}.butler-toolbar-button:hover,.butler-provider-switcher button:hover{border-color:#0ea5e95c;background:#fff;transform:translateY(-1px);box-shadow:0 10px 18px #0f172a0f}.butler-toolbar-button:disabled,.butler-provider-switcher button:disabled{cursor:not-allowed;opacity:.62;transform:none;box-shadow:none}.butler-provider-switcher{display:flex;gap:8px;align-items:center;min-width:0;flex:0 1 auto}.butler-provider-switcher select,.butler-init-form input,.butler-init-form select,.butler-init-form textarea{border:1px solid rgba(15,23,42,.12);border-radius:10px;padding:9px 12px;font-size:14px;background:transparent;color:var(--text-secondary, #6b7280)}.butler-provider-switcher select{min-width:120px;height:26px;padding:0 28px 0 10px;border-radius:8px;font-size:12px}.butler-header-icon-button{flex:0 0 auto}.terminal-toolbar-icon.butler-history-toolbar-icon svg,.terminal-toolbar-icon.butler-history-toolbar-icon svg *{fill:none}.butler-session-history-anchor{position:relative;flex:0 0 auto}.butler-session-history-popover{display:flex;flex-direction:column;gap:0;padding:18px 18px 16px;border:1px solid var(--modal-panel-border);border-radius:18px;background:var(--modal-panel-surface);box-shadow:var(--modal-panel-shadow);backdrop-filter:var(--modal-panel-filter);-webkit-backdrop-filter:var(--modal-panel-filter)}.butler-session-history-panel{display:flex;flex-direction:column;gap:14px}.butler-session-history-header strong{display:block;color:var(--text-primary);font-size:14px;line-height:1.35}.butler-session-history-header p{margin:4px 0 0;color:var(--text-secondary);font-size:12px;line-height:1.5}.butler-session-history-search{display:flex;align-items:center;gap:8px;min-height:40px;padding:0 12px;border:1px solid var(--modal-control-border);border-radius:12px;background:var(--modal-control-surface);box-shadow:var(--modal-control-shadow)}.butler-session-history-search:focus-within{border-color:var(--modal-control-border-focus);box-shadow:var(--modal-control-focus-ring)}.butler-session-history-search-icon{width:14px;height:14px;display:inline-flex;align-items:center;justify-content:center;color:var(--text-tertiary, #9ca3af);flex:0 0 auto}.butler-session-history-search-icon svg{width:100%;height:100%}.butler-session-history-search input{width:100%;border:none;background:transparent;color:var(--text-primary);font-size:13px;line-height:1.4;outline:none}.butler-session-history-search input::placeholder{color:var(--modal-control-placeholder)}.butler-session-history-list{display:flex;flex-direction:column;gap:16px;max-height:min(60vh,440px);overflow:auto}.butler-session-history-section{display:flex;flex-direction:column;gap:4px}.butler-session-history-section-list.modal-list{border-top:0}.butler-session-history-divider{display:flex;align-items:center;gap:10px;color:color-mix(in srgb,var(--text-secondary) 74%,var(--bg-surface) 26%);font-size:11px;font-weight:600;line-height:1.4;letter-spacing:.02em}.butler-session-history-divider:after{content:"";flex:1 1 auto;min-width:24px;height:1px;background:var(--modal-list-item-border)}.butler-session-history-item.modal-list-item{position:relative}.butler-session-history-item .modal-list-item-main{align-items:flex-start;gap:0}.butler-session-history-item .modal-list-item-copy{gap:3px}.butler-session-history-item .modal-list-item-trailing{align-items:flex-start;padding-top:1px}.butler-session-history-item-trailing{display:flex;flex-direction:column;align-items:flex-end;gap:8px}.butler-session-history-item.modal-list-item[data-interactive=true]:hover:not(:disabled){background:color-mix(in srgb,var(--modal-list-item-hover) 52%,transparent)}.butler-session-history-item[data-selected=true]:before{content:"";position:absolute;left:6px;top:11px;bottom:11px;width:2px;border-radius:999px;background:color-mix(in srgb,var(--accent) 52%,transparent)}.butler-session-history-item-title{display:block;min-width:0;color:var(--text-primary);font-size:13px;line-height:1.45;font-weight:600;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.butler-session-history-item-preview{display:-webkit-box;min-width:0;color:color-mix(in srgb,var(--text-secondary) 82%,var(--bg-surface) 18%);font-size:11px;font-weight:400;line-height:1.55;overflow:hidden;-webkit-line-clamp:2;-webkit-box-orient:vertical;word-break:break-word}.butler-session-history-item-time{color:var(--text-tertiary, #9ca3af);font-size:11px;font-weight:500;line-height:1.4;white-space:nowrap}.butler-session-history-delete-button.secondary-button{min-height:28px;padding:0 10px;font-size:11px}.butler-provider-badge{display:inline-flex;align-items:center;justify-content:center;padding:6px 10px;border-radius:999px;background:#0f172a0f;color:#0f172a;font-size:12px;font-weight:600;white-space:nowrap}.butler-conversation-shell{min-height:0;display:grid;flex:1 1 auto;grid-template-rows:minmax(0,1fr) auto;gap:0;overflow:hidden}.butler-conversation-shell .message-timeline{min-height:0;height:100%;border-radius:0;border:none;background:transparent}.butler-composer-shell{position:relative;z-index:1;flex:0 0 auto;border-radius:0;border:none;border-top:1px solid var(--panel-separator, rgba(15, 23, 42, .08));background:color-mix(in srgb,var(--panel-bg-strong, #fff) 88%,transparent);box-shadow:none;overflow:hidden}.butler-composer-shell .composer-panel{background:transparent}.butler-control-timer-banner{position:relative;z-index:12;display:block;padding:12px var(--conversation-content-gutter, 12px) 10px;background:transparent;overflow:visible}.butler-control-timer-banner-shell{position:relative;z-index:12;width:100%;max-width:none;margin:0;display:grid;grid-template-columns:minmax(0,1fr) auto;align-items:stretch;gap:16px 18px;min-height:128px;padding:16px 18px;border:1px solid var(--surface-overlay-border);border-radius:18px;background:var(--bg-elevated);box-shadow:var(--desktop-panel-shadow)}.butler-control-timer-banner-copy{min-width:0;display:grid;grid-template-columns:auto minmax(0,1fr);align-items:start;gap:10px 14px}.butler-control-timer-banner-status{display:inline-flex;align-items:center;gap:6px;min-width:0;grid-row:1 / span 2;align-self:start;padding-top:6px;margin:0}.butler-control-timer-pulse{width:7px;height:7px;border-radius:999px;background:color-mix(in srgb,var(--accent) 72%,var(--text-secondary));box-shadow:0 0 color-mix(in srgb,var(--accent) 36%,transparent);animation:butler-control-timer-pulse 1.8s ease-in-out infinite}.butler-control-timer-banner-caption,.butler-control-timer-banner-lead,.butler-control-timer-banner-tail,.butler-control-timer-display-clock,.butler-control-timer-banner-meta{margin:0}.butler-control-timer-banner-caption{color:var(--text-secondary);font-size:10px;font-weight:600;letter-spacing:.05em;text-transform:uppercase}.butler-control-timer-display-panel{display:flex;flex-direction:row;align-items:baseline;gap:10px;min-width:0;min-height:44px;padding:0;border:none;border-radius:0;background:transparent;box-shadow:none}.butler-control-timer-banner-lead,.butler-control-timer-banner-tail{min-width:0;color:var(--text-secondary);font-size:11px;line-height:1.25;letter-spacing:.02em;white-space:nowrap}.butler-control-timer-display-clock{color:var(--text-primary);font-family:SFMono-Regular,SF Mono,"ui-monospace",Menlo,Monaco,monospace;font-size:clamp(24px,2.1vw,28px);line-height:1;font-weight:600;letter-spacing:.06em;font-variant-numeric:tabular-nums}.butler-control-timer-banner-meta{display:grid;grid-template-columns:max-content minmax(0,1fr);grid-column:1 / -1;justify-self:stretch;align-items:start;gap:8px 14px}.butler-control-timer-banner-meta-card{min-width:0;display:flex;align-items:baseline;justify-content:flex-start;gap:6px;padding:0;border:none;background:transparent;box-shadow:none;text-align:left}.butler-control-timer-banner-meta-card span{flex:0 0 auto;color:var(--text-secondary);font-size:10px;line-height:1.2;letter-spacing:.04em;text-transform:uppercase}.butler-control-timer-banner-meta-card strong{min-width:0;max-width:100%;color:var(--text-primary);font-size:12px;line-height:1.25;font-weight:600;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.butler-control-timer-banner-meta-card[data-kind=session]{justify-self:start;min-width:0}.butler-control-timer-session-link{min-width:0;width:100%;padding:0;border:none;background:transparent;color:var(--text-primary);font:inherit;font-size:12px;line-height:1.25;font-weight:600;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;cursor:pointer;text-align:left;text-decoration:none}.butler-control-timer-session-link:hover{color:var(--accent);text-decoration:underline}.butler-control-timer-session-link:focus-visible{outline:2px solid color-mix(in srgb,var(--accent) 20%,transparent);outline-offset:2px;border-radius:6px}.butler-control-timer-banner-actions{flex:0 0 auto;display:grid;grid-template-columns:auto auto auto;align-items:start;gap:10px;align-self:start;margin-top:4px}.butler-control-timer-banner-detail{position:relative;flex:0 0 auto}.butler-control-timer-banner-detail-button{width:34px;height:34px;display:inline-flex;align-items:center;justify-content:center;border:1px solid var(--border-primary);border-radius:999px;background:var(--bg-surface-secondary);color:var(--text-secondary);box-shadow:none;transition:transform .14s ease,background-color .14s ease,border-color .14s ease}.butler-control-timer-banner-detail-button:hover{transform:translateY(-1px);background:color-mix(in srgb,var(--accent) 8%,var(--bg-surface-secondary));border-color:color-mix(in srgb,var(--accent) 28%,var(--border-primary))}.butler-control-timer-banner-detail-button:focus-visible{outline:2px solid color-mix(in srgb,var(--accent) 20%,transparent);outline-offset:2px}.butler-control-timer-banner-detail-icon{width:14px;height:14px;display:inline-flex}.butler-control-timer-banner-detail-icon svg{width:100%;height:100%}.butler-control-timer-banner-detail-popover{padding:10px 12px;border:1px solid var(--surface-overlay-border);border-radius:14px;background:var(--bg-elevated);box-shadow:var(--desktop-panel-shadow-strong);max-height:min(48vh,320px);overflow:auto}.butler-control-timer-banner-detail-popover strong{display:block;margin-bottom:8px;color:var(--text-primary);font-size:13px}.butler-control-timer-banner-detail-popover p{margin:0;color:var(--text-secondary);font-size:12px;line-height:1.6;white-space:pre-wrap;word-break:break-word}.butler-control-timer-banner-action{min-width:108px;min-height:34px;padding-inline:12px;white-space:nowrap;border-radius:999px;border-color:var(--border-primary);background:var(--bg-surface-secondary);color:var(--text-primary);box-shadow:none}.butler-control-timer-banner-action:hover:not(:disabled){background:color-mix(in srgb,var(--accent) 8%,var(--bg-surface-secondary));border-color:color-mix(in srgb,var(--accent) 28%,var(--border-primary))}.butler-control-timer-banner-note{grid-column:1 / -1;margin:2px 0 0;color:var(--text-secondary);font-size:10px;line-height:1.3;text-align:right;justify-self:end}@media(max-width:960px){.butler-control-timer-banner{padding-inline:var(--conversation-content-gutter, 18px)}.butler-control-timer-banner-shell,.butler-control-timer-banner-copy{grid-template-columns:1fr}.butler-control-timer-banner-actions{display:flex;justify-content:flex-start;align-items:center;flex-wrap:wrap}.butler-control-timer-banner-detail-popover{max-height:min(46vh,280px)}.butler-control-timer-banner-shell{width:100%}.butler-control-timer-banner-status{grid-row:auto;align-self:start}.butler-control-timer-display-panel{flex-wrap:wrap}.butler-control-timer-banner-meta{grid-template-columns:1fr}.butler-control-timer-banner-note{justify-self:stretch}}@keyframes butler-control-timer-pulse{0%,to{transform:scale(1);box-shadow:0 0 color-mix(in srgb,var(--accent) 36%,transparent)}60%{transform:scale(1.12);box-shadow:0 0 0 8px transparent}}.butler-side-column{height:100%;min-height:0;display:flex;flex-direction:column;gap:0;overflow:hidden;padding:0}.workbench-auxiliary[data-custom-panel=true]{padding:0;overflow:hidden}.workbench-auxiliary-custom-panel{height:100%;min-height:0;overflow:hidden}.butler-side-header{flex:0 0 auto;min-height:var(--workbench-header-min-height);height:var(--workbench-header-min-height);box-sizing:border-box;padding:var(--workbench-header-padding-top) var(--workbench-header-padding-inline) var(--workbench-header-padding-bottom);border-bottom:1px solid var(--panel-separator, rgba(15, 23, 42, .08));background:var(--bg-surface, rgba(248, 250, 252, .98));display:flex;align-items:center}.butler-side-content{flex:1 1 auto;min-height:0;overflow:auto;overscroll-behavior:contain;padding:0 10px 10px}.butler-side-tabs{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:8px;width:100%;flex-wrap:nowrap}.butler-side-tabs .workbench-info-tab{width:100%;min-width:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.workbench-auxiliary[data-custom-panel=true] .butler-side-card.surface-card,.workbench-auxiliary-custom-panel .butler-side-card.surface-card,.butler-side-card{padding:8px 2px 0;display:flex;flex-direction:column;gap:8px;border:none!important;border-radius:0!important;background:transparent!important;box-shadow:none!important;backdrop-filter:none!important;-webkit-backdrop-filter:none!important}.workbench-auxiliary[data-custom-panel=true] .butler-side-card.surface-card+.butler-side-card.surface-card,.workbench-auxiliary-custom-panel .butler-side-card.surface-card+.butler-side-card.surface-card,.butler-side-card+.butler-side-card{margin-top:2px;padding-top:12px;border-top:1px solid color-mix(in srgb,var(--border-primary) 68%,transparent)}.butler-side-card h2{margin:0;font-size:13px;line-height:1.35;font-weight:500;color:var(--text-primary, #111827);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.butler-side-card header{display:flex;align-items:center;justify-content:space-between;gap:12px}.butler-side-card header p{margin:4px 0 0;font-size:10px;color:var(--text-tertiary, #9ca3af)}.butler-card-header-copy{min-width:0;flex:1 1 auto}.butler-inline-actions{display:flex;justify-content:flex-end}.butler-side-column .secondary-button,.butler-side-column .primary-button,.butler-side-column .ghost-button{min-height:28px;padding:0 10px;border-radius:10px;font-size:11px;font-weight:400;box-shadow:none}.butler-side-column .secondary-button,.butler-side-column .primary-button{background:transparent;border:1px solid color-mix(in srgb,var(--border-primary) 64%,transparent);color:var(--text-secondary, #6b7280)}.butler-side-column .ghost-button{color:var(--text-secondary, #6b7280)}.butler-side-column .secondary-button:hover:not(:disabled),.butler-side-column .primary-button:hover:not(:disabled),.butler-side-column .ghost-button:hover:not(:disabled){background:var(--bg-hover);color:var(--text-primary, #111827);border-color:color-mix(in srgb,var(--border-primary) 82%,transparent)}.butler-side-header-action{flex:0 0 auto;align-self:flex-start}.butler-sandbox-entry-card header{align-items:center}.butler-sandbox-panel{display:flex;flex-direction:column;gap:0}.butler-sandbox-panel-card{border:none}.butler-sandbox-current-header{align-items:flex-start}.butler-sandbox-header-actions{display:flex;align-items:center;justify-content:flex-end;flex-wrap:wrap;gap:8px}.butler-sandbox-select-button{width:100%;display:flex;align-items:flex-start;justify-content:space-between;gap:12px;padding:0;border:0;background:transparent;color:inherit;text-align:left;cursor:pointer}.butler-automation-card[data-selected=true]{border-color:color-mix(in srgb,var(--accent-primary) 46%,var(--border-primary));box-shadow:inset 0 0 0 1px color-mix(in srgb,var(--accent-primary) 28%,transparent)}.butler-sandbox-form-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:16px}.butler-sandbox-form-actions{margin-top:16px;display:flex;flex-wrap:wrap;gap:10px}.butler-sandbox-card-footer{display:flex;align-items:flex-start;justify-content:space-between;gap:12px}.butler-sandbox-card-actions{display:flex;flex-wrap:wrap;justify-content:flex-end;gap:8px}.butler-sandbox-files-card{min-height:480px}.butler-sandbox-files-shell{display:flex;flex-direction:column;gap:10px}.butler-sandbox-files-meta{display:grid;grid-template-columns:repeat(auto-fit,minmax(260px,1fr));gap:8px 16px;padding-bottom:10px;border-bottom:1px solid color-mix(in srgb,var(--border-primary) 62%,transparent)}.butler-sandbox-files-meta-item{min-width:0}.butler-sandbox-files-meta-item strong{word-break:break-word}.butler-sandbox-file-context-panel{min-height:380px;border:none!important;border-radius:0!important;background:transparent!important;box-shadow:none!important;overflow:visible}.butler-sandbox-file-context-panel.file-panel,.butler-sandbox-file-context-panel .file-panel-section{gap:10px}.butler-sandbox-file-context-panel .file-panel-tabs{gap:12px;padding-bottom:8px;border-bottom:1px solid color-mix(in srgb,var(--border-primary) 62%,transparent)}.butler-sandbox-file-context-panel .file-panel-tab{min-height:30px;padding:0 0 7px;border:none;border-bottom:1px solid transparent;border-radius:0;background:transparent}.butler-sandbox-file-context-panel .file-panel-tab:hover,.butler-sandbox-file-context-panel .file-panel-tab.active{background:transparent;border-color:transparent}.butler-sandbox-file-context-panel .file-panel-tab.active{border-bottom-color:color-mix(in srgb,var(--accent) 54%,transparent)}.butler-sandbox-file-context-panel .file-panel-tab-badge{background:transparent;border-color:color-mix(in srgb,var(--border-primary) 72%,transparent);color:var(--text-secondary)}.butler-sandbox-file-context-panel .file-panel-tab.active .file-panel-tab-badge{border-color:color-mix(in srgb,var(--accent) 26%,transparent);color:var(--accent)}.butler-sandbox-file-context-panel .file-tree{min-height:340px;padding:0;border:none;border-radius:0;background:transparent}.butler-sandbox-file-context-panel .file-tree-node+.file-tree-node{border-top:1px solid color-mix(in srgb,var(--border-primary) 54%,transparent)}.butler-sandbox-file-context-panel .file-tree-item{min-height:32px;border-radius:0;background:transparent}.butler-sandbox-file-context-panel .file-tree-item:hover{background:color-mix(in srgb,var(--bg-hover) 56%,transparent)}.butler-sandbox-file-context-panel .file-tree-item[data-selected=true],.butler-sandbox-file-context-panel .file-tree-item[data-active=true]{background:color-mix(in srgb,var(--bg-active) 18%,transparent);box-shadow:inset 2px 0 color-mix(in srgb,var(--accent) 58%,transparent)}.butler-sandbox-file-context-panel .file-tree-status{padding:12px 0}.butler-record-list{display:flex;flex-direction:column;gap:2px}.butler-record-list>*+*{margin-top:2px;padding-top:10px;border-top:1px solid color-mix(in srgb,var(--border-primary) 58%,transparent)}.butler-sandbox-record{gap:6px;padding:10px 0}.butler-sandbox-record-top{display:grid;grid-template-columns:minmax(0,1fr) auto;align-items:start;gap:10px 16px}.butler-sandbox-record-header{gap:10px}.butler-sandbox-record-title{gap:3px}.butler-sandbox-record-title strong{font-size:13px}.butler-sandbox-record-title span{line-height:1.45;word-break:break-word}.butler-sandbox-record-body{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:8px 14px}.butler-sandbox-record-meta{gap:2px;min-width:0}.butler-sandbox-record-meta strong,.butler-sandbox-record-purpose strong{word-break:break-word}.butler-sandbox-record-footer{display:grid;grid-template-columns:minmax(220px,1.2fr) auto;align-items:start;gap:12px 16px}.butler-sandbox-record-purpose{min-width:0;gap:2px}.butler-sandbox-record-actions{justify-content:flex-end;align-items:flex-start}.butler-sandbox-browser-list{gap:0}.butler-sandbox-browser-item{align-items:stretch}.butler-sandbox-browser-meta{display:flex;flex-wrap:wrap;gap:8px 12px;margin-top:6px;color:var(--text-secondary, #6b7280);font-size:11px;line-height:1.4}.butler-sandbox-browser-actions{display:inline-flex;align-items:center;justify-content:flex-end;flex-wrap:wrap;gap:8px}@media(max-width:900px){.butler-sandbox-header-actions{justify-content:flex-start}.butler-sandbox-record-top,.butler-sandbox-record-body,.butler-sandbox-record-footer{grid-template-columns:1fr}.butler-sandbox-record-actions,.butler-sandbox-browser-actions{justify-content:flex-start}}.workbench-auxiliary[data-custom-panel=true] .butler-simple-info-block,.workbench-auxiliary-custom-panel .butler-simple-info-block,.butler-simple-info-block{display:flex;flex-direction:column;gap:6px;padding:8px 10px;border:none!important;border-radius:0!important;background:transparent!important;box-shadow:none!important;transition:background var(--transition-fast)}.butler-simple-info-block:hover{background:var(--bg-hover)}.butler-simple-info-block span{font-size:10px;color:var(--text-tertiary, #9ca3af)}.butler-simple-info-block strong{font-size:12px;line-height:1.35;font-weight:400;color:var(--text-secondary, #6b7280)}.butler-record-toggle{display:inline-flex;align-items:center;gap:8px;color:var(--text-secondary, #6b7280);font-size:11px}.butler-record-toggle input{margin:0}.butler-todo-card{display:flex;flex-direction:column;gap:8px;padding:10px;border-radius:12px;border:1px solid color-mix(in srgb,var(--border-primary) 64%,transparent);background:color-mix(in srgb,var(--bg-primary) 94%,transparent)}.butler-todo-card-header{display:flex;align-items:flex-start;justify-content:space-between;gap:8px}.butler-todo-card-header strong{display:block;color:var(--text-primary, #111827);font-size:12px;line-height:1.45}.butler-todo-card-header span{display:block;margin-top:2px;color:var(--text-secondary, #6b7280);font-size:11px}.butler-todo-card-badges{display:flex;flex-wrap:wrap;justify-content:flex-end;gap:6px}.butler-inline-badge{display:inline-flex;align-items:center;min-height:22px;padding:0 8px;border-radius:999px;border:1px solid color-mix(in srgb,var(--border-primary) 64%,transparent);color:var(--text-secondary, #6b7280);font-size:10px}.butler-todo-card p{margin:0;color:var(--text-primary, #111827);font-size:12px;line-height:1.5;white-space:pre-wrap;word-break:break-word}.butler-todo-prompt-preview{display:flex;flex-wrap:wrap;align-items:flex-start;gap:8px}.butler-todo-prompt-preview-details{min-width:0;flex:1 1 220px}.butler-todo-prompt-preview summary{cursor:pointer;color:var(--text-secondary, #6b7280);font-size:11px}.butler-todo-prompt-preview pre{margin:8px 0 0;max-height:180px;overflow:auto;padding:10px;border-radius:10px;background:color-mix(in srgb,var(--bg-hover) 74%,transparent);color:var(--text-primary, #111827);font-size:11px;line-height:1.55;white-space:pre-wrap}.butler-todo-card-actions{display:flex;flex-wrap:wrap;gap:8px}.workbench-auxiliary[data-custom-panel=true] .butler-automation-card,.workbench-auxiliary-custom-panel .butler-automation-card,.butler-automation-card{display:flex;flex-direction:column;gap:8px;padding:8px 10px;border:none!important;border-radius:0!important;background:transparent!important;box-shadow:none!important;transition:background var(--transition-fast)}.butler-automation-card:hover{background:var(--bg-hover)}.butler-automation-card-header{display:flex;align-items:flex-start;justify-content:space-between;gap:8px}.butler-automation-card-title-group{min-width:0;display:flex;flex-direction:column;gap:2px}.butler-automation-card-title-group strong{font-size:12px;line-height:1.35;font-weight:600;color:var(--text-primary, #111827);word-break:break-word}.butler-automation-card-title-group span,.butler-automation-row span,.butler-automation-card-footer span{font-size:10px;color:var(--text-tertiary, #9ca3af)}.butler-automation-card-body{display:flex;flex-direction:column;gap:8px}.butler-automation-row,.butler-automation-card-footer-copy{display:flex;flex-direction:column;gap:4px}.butler-automation-row strong,.butler-automation-card-footer strong{font-size:11px;line-height:1.4;font-weight:400;color:var(--text-secondary, #6b7280)}.butler-automation-card-footer{display:flex;flex-wrap:wrap;align-items:center;justify-content:flex-start;gap:8px}.butler-automation-card-action{flex:0 0 auto}.butler-automation-overview-list{display:grid;grid-template-columns:repeat(auto-fit,minmax(228px,1fr));gap:10px}.butler-automation-overview-card{min-width:0;gap:10px;padding:12px;border:1px solid color-mix(in srgb,var(--border-primary) 74%,transparent)!important;border-radius:14px!important;background:radial-gradient(circle at top right,color-mix(in srgb,var(--accent) 8%,transparent),transparent 32%),linear-gradient(180deg,color-mix(in srgb,var(--bg-surface) 98%,transparent),color-mix(in srgb,var(--bg-primary) 95%,var(--bg-surface) 5%))!important;box-shadow:inset 0 1px #ffffffc7,0 8px 18px #0f172a0d!important}.butler-automation-overview-card:hover{background:radial-gradient(circle at top right,color-mix(in srgb,var(--accent) 12%,transparent),transparent 34%),linear-gradient(180deg,color-mix(in srgb,var(--bg-surface) 100%,transparent),color-mix(in srgb,var(--bg-hover) 94%,var(--bg-surface) 6%))!important;border-color:color-mix(in srgb,var(--accent) 22%,var(--border-primary))!important}.butler-automation-overview-card .butler-automation-card-title-group strong{font-size:13px;line-height:1.3;font-weight:600;color:var(--text-primary, #111827)}.butler-automation-overview-card .butler-automation-card-title-group span,.butler-automation-overview-card .butler-automation-card-footer span{font-size:11px}.butler-automation-overview-chip{display:inline-flex;align-items:center;align-self:flex-start;min-height:24px;padding:0 10px;border-radius:999px;background:color-mix(in srgb,var(--bg-hover) 92%,transparent);color:var(--text-secondary, #6b7280);font-size:11px;line-height:1;font-weight:500;white-space:nowrap}.butler-automation-overview-inline{display:grid;grid-template-columns:minmax(0,1fr);gap:8px}.butler-automation-overview-inline-meta{display:flex;align-items:center;min-height:30px;padding:0 10px;border-radius:10px;background:color-mix(in srgb,var(--bg-surface-secondary) 88%,transparent);border:1px solid color-mix(in srgb,var(--border-primary) 58%,transparent);color:var(--text-secondary, #6b7280);font-size:11px;line-height:1.35;word-break:break-word}.butler-automation-card-footer-hint{color:var(--text-secondary, #6b7280);font-size:11px}.butler-automation-overview-card .butler-automation-card-footer{padding-top:2px}.butler-follow-up-history-panel{display:flex;flex-direction:column;gap:12px}.workbench-auxiliary[data-custom-panel=true] .butler-follow-up-status-card,.workbench-auxiliary-custom-panel .butler-follow-up-status-card,.butler-follow-up-status-card{display:flex;flex-direction:column;gap:10px;padding:8px 10px;border:none!important;border-radius:0!important;background:transparent!important;box-shadow:none!important;transition:background var(--transition-fast)}.butler-follow-up-status-card:hover{background:var(--bg-hover)}.butler-follow-up-status-header,.butler-follow-up-status-footer{display:flex;align-items:flex-start;justify-content:space-between;gap:12px}.butler-follow-up-status-title-group{min-width:0;display:flex;flex-direction:column;gap:4px}.butler-follow-up-status-title-group strong{font-size:12px;line-height:1.35;font-weight:400;color:var(--text-secondary, #6b7280)}.butler-follow-up-status-title-group span,.butler-follow-up-status-footer span,.butler-follow-up-status-body p{font-size:10px;line-height:1.45;color:var(--text-tertiary, #9ca3af)}.butler-follow-up-status-body p{margin:0}.butler-follow-up-status-action{flex:0 0 auto}.butler-follow-up-rounds{display:flex;flex-direction:column;gap:12px}.butler-follow-up-round-summary{display:flex;flex-direction:column;gap:4px}.butler-follow-up-round-summary strong{font-size:12px;line-height:1.35;font-weight:400;color:var(--text-secondary, #6b7280)}.butler-follow-up-round-summary span{font-size:10px;color:var(--text-tertiary, #9ca3af)}.butler-follow-up-round-list{display:flex;flex-direction:column;gap:2px}.butler-follow-up-round-list>*+*{margin-top:2px;padding-top:10px;border-top:1px solid color-mix(in srgb,var(--border-primary) 58%,transparent)}.workbench-auxiliary[data-custom-panel=true] .butler-follow-up-round-card,.workbench-auxiliary-custom-panel .butler-follow-up-round-card,.butler-follow-up-round-card{display:flex;flex-direction:column;gap:8px;padding:8px 10px;border:none!important;border-radius:0!important;background:transparent!important;box-shadow:none!important}.butler-follow-up-round-header{display:flex;align-items:flex-start;justify-content:space-between;gap:12px}.butler-follow-up-round-header div{display:flex;flex-direction:column;gap:4px}.butler-follow-up-round-header strong{font-size:12px;line-height:1.35;font-weight:400;color:var(--text-secondary, #6b7280)}.butler-follow-up-round-header span,.butler-follow-up-round-body p{font-size:10px;line-height:1.45;color:var(--text-tertiary, #9ca3af)}.butler-follow-up-round-body{display:flex;flex-direction:column;gap:6px}.butler-follow-up-round-body p{margin:0}.butler-automation-status-badge{flex:0 0 auto;display:inline-flex;align-items:center;justify-content:center;min-height:24px;padding:0 10px;border-radius:999px;background:color-mix(in srgb,var(--bg-active) 72%,transparent);color:var(--text-secondary, #6b7280);font-size:10px;font-weight:500;white-space:nowrap}.butler-automation-status-badge[data-status=waiting_user]{background:#f59e0b29;color:#92400e}.butler-automation-status-badge[data-status=active]{background:#0ea5e924;color:#075985}.butler-automation-status-badge[data-status=completed]{background:#10b98129;color:#065f46}.butler-automation-status-badge[data-status=failed],.butler-automation-status-badge[data-status=cancelled]{background:#ef444424;color:#991b1b}.workbench-modal-card.butler-automation-detail-modal{width:min(980px,calc(100vw - 56px))}.workbench-modal-card.butler-automation-detail-modal .workbench-modal-body{max-height:calc(100vh - 180px);overflow:auto}.butler-automation-detail-shell{display:flex;flex-direction:column;gap:16px}.butler-automation-detail-summary-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(150px,1fr));gap:10px}.butler-automation-detail-summary-card{display:flex;flex-direction:column;gap:6px;min-width:0;padding:12px 13px;border:1px solid color-mix(in srgb,var(--border-primary) 70%,transparent);border-radius:14px;background:linear-gradient(180deg,color-mix(in srgb,var(--bg-surface) 98%,transparent),color-mix(in srgb,var(--bg-surface-secondary) 92%,transparent))}.butler-automation-detail-summary-card span{font-size:10px;color:var(--text-tertiary, #9ca3af)}.butler-automation-detail-summary-card strong{font-size:13px;line-height:1.45;font-weight:600;color:var(--text-primary, #111827);word-break:break-word}.butler-automation-detail-section.butler-side-card{gap:14px;padding:16px!important;border:1px solid color-mix(in srgb,var(--border-primary) 70%,transparent)!important;border-radius:18px!important;background:linear-gradient(180deg,color-mix(in srgb,var(--bg-surface) 99%,transparent),color-mix(in srgb,var(--bg-surface-secondary) 94%,transparent))!important;box-shadow:inset 0 1px #ffffffb8,0 8px 22px #0f172a0a!important}.butler-automation-detail-section.butler-side-card+.butler-automation-detail-section.butler-side-card{margin-top:0;padding-top:16px!important;border-top:1px solid color-mix(in srgb,var(--border-primary) 70%,transparent)!important}.butler-automation-detail-form-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:14px}.butler-automation-detail-textarea{min-height:140px;padding:10px 12px;resize:vertical;line-height:1.6}.butler-automation-detail-toggle{display:flex;align-items:center;gap:10px;min-height:40px;padding:0 12px;border:1px solid color-mix(in srgb,var(--border-primary) 62%,transparent);border-radius:12px;background:color-mix(in srgb,var(--bg-surface-secondary) 84%,transparent);color:var(--text-secondary, #6b7280);font-size:12px}.butler-automation-detail-toggle input{margin:0}.butler-automation-detail-actions{display:flex;justify-content:flex-end}.butler-automation-detail-run-list{display:grid;grid-template-columns:repeat(auto-fit,minmax(220px,1fr));gap:12px}.butler-automation-detail-run-card{display:flex;flex-direction:column;gap:8px;min-width:0;padding:12px;border:1px solid color-mix(in srgb,var(--border-primary) 68%,transparent);border-radius:14px;background:color-mix(in srgb,var(--bg-surface-secondary) 88%,transparent)}.butler-automation-detail-run-card header{display:flex;align-items:flex-start;justify-content:space-between;gap:8px}.butler-automation-detail-run-card header strong{font-size:12px;line-height:1.4;color:var(--text-primary, #111827)}.butler-automation-detail-run-meta{display:flex;flex-wrap:wrap;gap:8px;color:var(--text-tertiary, #9ca3af);font-size:11px}.butler-automation-detail-run-card p{margin:0;color:var(--text-secondary, #6b7280);font-size:12px;line-height:1.6;word-break:break-word}@media(max-width:860px){.workbench-modal-card.butler-automation-detail-modal{width:min(100vw - 24px,720px)}.butler-automation-detail-form-grid{grid-template-columns:minmax(0,1fr)}}.butler-loading-panel{width:min(520px,100%);min-height:280px;margin:auto;padding:32px 28px;border-radius:24px;border:1px solid var(--surface-overlay-border);background:var(--surface-overlay-bg);box-shadow:0 24px 56px color-mix(in srgb,var(--text-primary) 8%,transparent),inset 0 1px color-mix(in srgb,var(--surface-overlay-highlight) 84%,transparent);display:flex;flex-direction:column;align-items:center;justify-content:center;gap:20px;text-align:center}.butler-loading-orb{position:relative;width:88px;height:88px;display:grid;place-items:center}.butler-loading-ring,.butler-loading-core{position:absolute;border-radius:999px}.butler-loading-ring{top:0;right:0;bottom:0;left:0;border:3px solid transparent}.butler-loading-ring-primary{border-top-color:#0ea5e9eb;border-right-color:#0ea5e957;animation:butler-loading-spin 1s linear infinite}.butler-loading-ring-secondary{top:10px;right:10px;bottom:10px;left:10px;border-bottom-color:#10b981e6;border-left-color:#10b98152;animation:butler-loading-spin-reverse 1.4s linear infinite}.butler-loading-core{top:24px;right:24px;bottom:24px;left:24px;background:radial-gradient(circle at 30% 30%,color-mix(in srgb,var(--surface-overlay-highlight) 88%,transparent),color-mix(in srgb,var(--surface-overlay-highlight) 16%,transparent)),linear-gradient(135deg,color-mix(in srgb,rgba(14,165,233,.72) 28%,var(--bg-elevated)),color-mix(in srgb,rgba(16,185,129,.64) 22%,var(--bg-surface)));box-shadow:0 0 0 1px color-mix(in srgb,rgba(14,165,233,.2) 70%,var(--surface-overlay-border)),0 10px 24px color-mix(in srgb,rgba(14,165,233,.3) 44%,transparent)}.butler-loading-copy{display:flex;flex-direction:column;gap:8px}.butler-loading-copy h1{margin:0;font-size:24px;line-height:1.2}.butler-loading-copy p{margin:0;max-width:360px;color:var(--text-secondary, #6b7280);font-size:14px;line-height:1.6}.butler-init-shell{position:relative;justify-content:center;padding:clamp(20px,4vw,44px);overflow:auto;background:var(--butler-init-shell-bg)}.butler-init-backdrop{display:none}.butler-init-glow{position:absolute;border-radius:999px;filter:blur(12px);opacity:.9}.butler-init-glow-primary{top:7%;left:-8%;width:320px;height:320px;background:var(--butler-init-glow-primary)}.butler-init-glow-secondary{right:-6%;bottom:4%;width:360px;height:360px;background:var(--butler-init-glow-secondary)}.butler-init-layout{position:relative;z-index:1;display:grid;grid-template-columns:minmax(300px,360px) minmax(0,1fr);align-items:start;gap:28px;width:min(1180px,100%);margin:auto}.butler-init-sidebar,.butler-init-form{min-height:0}.butler-init-sidebar{display:flex;flex-direction:column;gap:18px;padding:0}.butler-init-hero-card,.butler-init-preview-card,.butler-init-form-section,.butler-init-actions{border:1px solid var(--butler-init-card-border);border-radius:24px;background:var(--butler-init-card-bg);box-shadow:var(--butler-init-card-shadow)}.butler-init-hero-card{display:flex;flex-direction:column;align-items:center;gap:16px;padding:22px;text-align:center}.butler-init-hero-copy{display:flex;flex-direction:column;align-items:center;gap:10px}.butler-init-hero-copy h1{margin:0;font-size:clamp(28px,3vw,34px);line-height:1.08;letter-spacing:-.04em}.butler-init-hero-copy p{margin:0;color:var(--text-secondary, #6b7280);font-size:14px;line-height:1.75}.butler-init-preview-card{display:flex;flex-direction:column;gap:14px;padding:20px}.butler-init-section-header{display:flex;align-items:flex-start;justify-content:space-between;gap:12px}.butler-init-section-header h2{margin:0;font-size:16px;line-height:1.25;letter-spacing:-.02em}.butler-init-section-header p{margin:6px 0 0;color:var(--text-secondary, #6b7280);font-size:13px;line-height:1.65}.butler-init-preview-identity{display:flex;flex-direction:column;align-items:center;gap:8px;text-align:center}.butler-init-preview-nameplate{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:12px;width:fit-content;max-width:100%;margin:0 auto}.butler-init-preview-nameplate strong{display:block;font-size:24px;line-height:1.12;letter-spacing:-.04em;text-align:center}.butler-init-preview-avatar{width:56px;height:56px;border-radius:16px;flex:0 0 auto;background:var(--butler-init-avatar-bg);color:var(--butler-init-avatar-fg);box-shadow:var(--butler-init-avatar-shadow)}.butler-init-preview-avatar span{font-size:26px}.butler-init-preview-provider{display:inline-flex;align-items:center;padding:6px 12px;border-radius:999px;border:1px solid var(--butler-init-provider-border);background:var(--butler-init-provider-bg);color:var(--accent);font-size:12px;font-weight:700;letter-spacing:.02em}.butler-init-chip-list{display:flex;flex-wrap:wrap;justify-content:center;gap:8px}.butler-init-chip{display:inline-flex;align-items:center;padding:7px 10px;border-radius:999px;border:1px solid var(--butler-init-chip-border);background:var(--butler-init-chip-bg);color:var(--butler-init-chip-text);font-size:12px;font-weight:600}.butler-init-preview-rows{display:flex;flex-direction:column}.butler-init-preview-row{display:flex;align-items:center;justify-content:space-between;gap:16px;padding:12px 0;border-top:1px solid color-mix(in srgb,var(--border-primary) 76%,transparent)}.butler-init-preview-row:first-child{padding-top:0;border-top:none}.butler-init-preview-row span{color:var(--text-secondary, #6b7280);font-size:12px}.butler-init-preview-row strong{font-size:13px;font-weight:700;text-align:right}.butler-init-form{display:flex;flex-direction:column;gap:18px;padding:0;overflow:auto}.butler-init-form-section{display:flex;flex-direction:column;gap:16px;padding:20px}.butler-init-basic-grid,.butler-init-preferences-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:16px}.butler-init-persona-grid{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:16px}.butler-form-field{display:flex;flex-direction:column;gap:8px;min-width:0}.butler-form-field span{font-size:11px;font-weight:400;color:var(--text-tertiary, #9ca3af)}.butler-form-field-wide{grid-column:1 / -1}.butler-form-field small{color:var(--text-tertiary, #9ca3af);font-size:10px;line-height:1.5}.butler-form-control{width:100%;min-height:38px;padding:0 12px;border:1px solid color-mix(in srgb,var(--border-primary) 64%,transparent);border-radius:12px;background:transparent;color:var(--text-secondary, #6b7280);box-shadow:none;transition:border-color .12s ease,box-shadow .12s ease,background .12s ease}select.butler-form-control{padding-right:36px}.butler-form-control:hover{border-color:color-mix(in srgb,var(--border-primary) 82%,transparent);background:var(--bg-hover)}.butler-form-control:focus{outline:none;border-color:color-mix(in srgb,var(--accent) 24%,var(--border-primary));background:var(--bg-hover);box-shadow:none}.butler-side-card.butler-settings-panel .butler-form-field span,.butler-side-card.butler-settings-panel .butler-form-field small,.butler-side-card.butler-settings-panel .butler-form-control,.butler-side-card.butler-settings-panel .butler-form-control::placeholder,.butler-side-card.butler-settings-panel .primary-button,.butler-side-card.butler-settings-panel .secondary-button,.butler-side-card.butler-settings-panel .ghost-button{color:var(--text-primary, #111827)!important}.butler-side-card.butler-settings-panel .butler-form-field small{opacity:.9}.butler-side-card.butler-settings-panel .butler-form-control option,.butler-side-card.butler-settings-panel .butler-settings-file-path{color:var(--text-primary, #111827)!important}.butler-settings-file-path{min-height:38px;font-family:SFMono-Regular,Consolas,Liberation Mono,Menlo,monospace;font-size:11px;line-height:1.5;color:var(--text-secondary, #6b7280)}.butler-settings-agents-editor{min-height:220px;padding:12px 14px;resize:vertical;font-family:SFMono-Regular,Consolas,Liberation Mono,Menlo,monospace;font-size:12px;line-height:1.6}.butler-init-actions{display:flex;align-items:center;justify-content:flex-end;gap:16px;padding:20px 22px}.butler-init-submit{display:inline-flex;align-items:center;justify-content:center;min-width:168px;min-height:46px;padding:0 20px;border:1px solid var(--butler-init-submit-border);border-radius:12px;background:var(--butler-init-submit-bg);color:var(--butler-init-submit-text);box-shadow:var(--butler-init-submit-shadow);cursor:pointer;transition:border-color .12s ease,background .12s ease,box-shadow .12s ease,transform .12s ease}.butler-init-submit:hover{border-color:color-mix(in srgb,var(--accent) 64%,var(--surface-overlay-border));background:var(--butler-init-submit-bg-hover);box-shadow:var(--butler-init-submit-shadow-hover);transform:translateY(-1px)}.butler-init-submit:disabled{border-color:color-mix(in srgb,var(--border-primary) 88%,transparent);background:var(--butler-init-submit-bg-disabled);color:var(--butler-init-submit-text-disabled);box-shadow:none;cursor:not-allowed;transform:none;opacity:1}@keyframes butler-loading-spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}@keyframes butler-loading-spin-reverse{0%{transform:rotate(360deg)}to{transform:rotate(0)}}@media(max-width:900px){.butler-main-header{flex-direction:column;align-items:stretch}.butler-toolbar-cluster,.butler-provider-switcher{justify-content:stretch;flex-wrap:wrap}.butler-provider-switcher{align-items:center}.butler-init-layout{grid-template-columns:minmax(0,1fr)}.butler-loading-panel{min-height:240px;padding:28px 22px}.butler-loading-copy h1{font-size:22px}}@media(max-width:960px){.butler-init-basic-grid,.butler-init-persona-grid,.butler-init-preferences-grid{grid-template-columns:minmax(0,1fr)}.butler-init-actions{flex-direction:column;align-items:stretch}.butler-init-submit{width:100%}}