@itphx/synth-core 0.2.0 → 0.4.4

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 (670) hide show
  1. package/definitions/protected-paths.json +36 -0
  2. package/definitions/shell-policy.json +36 -0
  3. package/dist/auth/local.d.ts +14 -0
  4. package/dist/auth/local.d.ts.map +1 -1
  5. package/dist/auth/local.js +63 -11
  6. package/dist/auth/local.js.map +1 -1
  7. package/dist/auth/local.test.js +59 -0
  8. package/dist/auth/local.test.js.map +1 -1
  9. package/dist/definitions/protected-paths.json +36 -0
  10. package/dist/definitions/shell-policy.json +36 -0
  11. package/dist/engine/agents/definitions/admin.json +3 -1
  12. package/dist/engine/agents/definitions/analyst.json +3 -1
  13. package/dist/engine/agents/definitions/assistant.json +2 -2
  14. package/dist/engine/agents/definitions/auditor.json +4 -1
  15. package/dist/engine/agents/definitions/developer.json +4 -1
  16. package/dist/engine/agents/definitions/devops.json +4 -1
  17. package/dist/engine/agents/definitions/explore.json +3 -3
  18. package/dist/engine/agents/definitions/general.json +2 -2
  19. package/dist/engine/agents/definitions/pm.json +5 -1
  20. package/dist/engine/agents/definitions/qa.json +4 -1
  21. package/dist/engine/agents/definitions/title.json +2 -2
  22. package/dist/engine/agents/index.d.ts +4 -0
  23. package/dist/engine/agents/index.d.ts.map +1 -1
  24. package/dist/engine/agents/index.js +9 -3
  25. package/dist/engine/agents/index.js.map +1 -1
  26. package/dist/engine/agents/mode.d.ts +5 -3
  27. package/dist/engine/agents/mode.d.ts.map +1 -1
  28. package/dist/engine/agents/mode.js +6 -6
  29. package/dist/engine/agents/mode.js.map +1 -1
  30. package/dist/engine/agents/mode.test.js +9 -3
  31. package/dist/engine/agents/mode.test.js.map +1 -1
  32. package/dist/engine/agents/normalize.d.ts +9 -0
  33. package/dist/engine/agents/normalize.d.ts.map +1 -0
  34. package/dist/engine/agents/normalize.js +22 -0
  35. package/dist/engine/agents/normalize.js.map +1 -0
  36. package/dist/engine/agents/normalize.test.d.ts +2 -0
  37. package/dist/engine/agents/normalize.test.d.ts.map +1 -0
  38. package/dist/engine/agents/normalize.test.js +37 -0
  39. package/dist/engine/agents/normalize.test.js.map +1 -0
  40. package/dist/engine/agents/registry.d.ts +2 -1
  41. package/dist/engine/agents/registry.d.ts.map +1 -1
  42. package/dist/engine/agents/registry.js +7 -6
  43. package/dist/engine/agents/registry.js.map +1 -1
  44. package/dist/engine/agents/registry.test.js +24 -0
  45. package/dist/engine/agents/registry.test.js.map +1 -1
  46. package/dist/engine/context/config.d.ts +43 -6
  47. package/dist/engine/context/config.d.ts.map +1 -1
  48. package/dist/engine/context/config.js +123 -26
  49. package/dist/engine/context/config.js.map +1 -1
  50. package/dist/engine/context/config.security.test.d.ts +2 -0
  51. package/dist/engine/context/config.security.test.d.ts.map +1 -0
  52. package/dist/engine/context/config.security.test.js +82 -0
  53. package/dist/engine/context/config.security.test.js.map +1 -0
  54. package/dist/engine/context/config.test.js +199 -10
  55. package/dist/engine/context/config.test.js.map +1 -1
  56. package/dist/engine/context/optimizer.d.ts +20 -1
  57. package/dist/engine/context/optimizer.d.ts.map +1 -1
  58. package/dist/engine/context/optimizer.js +63 -29
  59. package/dist/engine/context/optimizer.js.map +1 -1
  60. package/dist/engine/context/optimizer.test.js +156 -0
  61. package/dist/engine/context/optimizer.test.js.map +1 -1
  62. package/dist/engine/gateway/gateway-provider.d.ts +4 -0
  63. package/dist/engine/gateway/gateway-provider.d.ts.map +1 -1
  64. package/dist/engine/gateway/gateway-provider.js +7 -2
  65. package/dist/engine/gateway/gateway-provider.js.map +1 -1
  66. package/dist/engine/gateway/gateway-provider.test.js +3 -3
  67. package/dist/engine/gateway/gateway-provider.test.js.map +1 -1
  68. package/dist/engine/gateway/input-guard.d.ts.map +1 -1
  69. package/dist/engine/gateway/input-guard.js +2 -1
  70. package/dist/engine/gateway/input-guard.js.map +1 -1
  71. package/dist/engine/gateway/secret-detector.d.ts.map +1 -1
  72. package/dist/engine/gateway/secret-detector.js +2 -3
  73. package/dist/engine/gateway/secret-detector.js.map +1 -1
  74. package/dist/engine/gateway/secret-detector.test.js +4 -4
  75. package/dist/engine/gateway/secret-detector.test.js.map +1 -1
  76. package/dist/engine/llm-error.d.ts +23 -0
  77. package/dist/engine/llm-error.d.ts.map +1 -0
  78. package/dist/engine/llm-error.js +86 -0
  79. package/dist/engine/llm-error.js.map +1 -0
  80. package/dist/engine/llm-error.test.d.ts +2 -0
  81. package/dist/engine/llm-error.test.d.ts.map +1 -0
  82. package/dist/engine/llm-error.test.js +101 -0
  83. package/dist/engine/llm-error.test.js.map +1 -0
  84. package/dist/engine/orchestrator-deny-abort.test.d.ts +2 -0
  85. package/dist/engine/orchestrator-deny-abort.test.d.ts.map +1 -0
  86. package/dist/engine/orchestrator-deny-abort.test.js +414 -0
  87. package/dist/engine/orchestrator-deny-abort.test.js.map +1 -0
  88. package/dist/engine/orchestrator-error.test.d.ts +2 -0
  89. package/dist/engine/orchestrator-error.test.d.ts.map +1 -0
  90. package/dist/engine/orchestrator-error.test.js +136 -0
  91. package/dist/engine/orchestrator-error.test.js.map +1 -0
  92. package/dist/engine/orchestrator.d.ts +123 -10
  93. package/dist/engine/orchestrator.d.ts.map +1 -1
  94. package/dist/engine/orchestrator.js +791 -181
  95. package/dist/engine/orchestrator.js.map +1 -1
  96. package/dist/engine/orchestrator.test.js +723 -0
  97. package/dist/engine/orchestrator.test.js.map +1 -1
  98. package/dist/engine/permission/approval.d.ts.map +1 -1
  99. package/dist/engine/permission/approval.js +29 -10
  100. package/dist/engine/permission/approval.js.map +1 -1
  101. package/dist/engine/permission/approval.test.js +57 -0
  102. package/dist/engine/permission/approval.test.js.map +1 -1
  103. package/dist/engine/permission/evaluator.d.ts +13 -0
  104. package/dist/engine/permission/evaluator.d.ts.map +1 -1
  105. package/dist/engine/permission/evaluator.js +121 -22
  106. package/dist/engine/permission/evaluator.js.map +1 -1
  107. package/dist/engine/permission/evaluator.test.js +188 -4
  108. package/dist/engine/permission/evaluator.test.js.map +1 -1
  109. package/dist/engine/permission/groups.d.ts.map +1 -1
  110. package/dist/engine/permission/groups.js +19 -1
  111. package/dist/engine/permission/groups.js.map +1 -1
  112. package/dist/engine/permission/integration.test.js +165 -4
  113. package/dist/engine/permission/integration.test.js.map +1 -1
  114. package/dist/engine/plan.integration.test.js +142 -33
  115. package/dist/engine/plan.integration.test.js.map +1 -1
  116. package/dist/engine/router/micro/tasks/classify-intent.d.ts.map +1 -1
  117. package/dist/engine/router/micro/tasks/classify-intent.js +24 -18
  118. package/dist/engine/router/micro/tasks/classify-intent.js.map +1 -1
  119. package/dist/engine/router/micro/tasks/classify-intent.test.js +4 -4
  120. package/dist/engine/router/micro/tasks/classify-intent.test.js.map +1 -1
  121. package/dist/engine/router/micro/tasks/enum-decision.d.ts.map +1 -1
  122. package/dist/engine/router/micro/tasks/enum-decision.js +14 -8
  123. package/dist/engine/router/micro/tasks/enum-decision.js.map +1 -1
  124. package/dist/engine/router/micro/tasks/enum-decision.test.js +2 -2
  125. package/dist/engine/router/micro/tasks/enum-decision.test.js.map +1 -1
  126. package/dist/engine/router/micro/tasks/small-talk.d.ts.map +1 -1
  127. package/dist/engine/router/micro/tasks/small-talk.js +20 -17
  128. package/dist/engine/router/micro/tasks/small-talk.js.map +1 -1
  129. package/dist/engine/router/micro/types.d.ts +2 -0
  130. package/dist/engine/router/micro/types.d.ts.map +1 -1
  131. package/dist/engine/router/provider-pool.d.ts +2 -2
  132. package/dist/engine/router/provider-pool.d.ts.map +1 -1
  133. package/dist/engine/router/provider-pool.js +5 -3
  134. package/dist/engine/router/provider-pool.js.map +1 -1
  135. package/dist/engine/router/quality-checker.d.ts.map +1 -1
  136. package/dist/engine/router/quality-checker.js +15 -14
  137. package/dist/engine/router/quality-checker.js.map +1 -1
  138. package/dist/engine/router/router.d.ts +2 -2
  139. package/dist/engine/router/router.d.ts.map +1 -1
  140. package/dist/engine/router/router.js +8 -5
  141. package/dist/engine/router/router.js.map +1 -1
  142. package/dist/engine/router/utils.d.ts +2 -2
  143. package/dist/engine/router/utils.d.ts.map +1 -1
  144. package/dist/engine/router/utils.js +2 -1
  145. package/dist/engine/router/utils.js.map +1 -1
  146. package/dist/engine/security/index.d.ts +6 -0
  147. package/dist/engine/security/index.d.ts.map +1 -1
  148. package/dist/engine/security/index.js +3 -0
  149. package/dist/engine/security/index.js.map +1 -1
  150. package/dist/engine/security/integration.test.js +11 -11
  151. package/dist/engine/security/integration.test.js.map +1 -1
  152. package/dist/engine/security/prompt-injection.d.ts +1 -1
  153. package/dist/engine/security/prompt-injection.d.ts.map +1 -1
  154. package/dist/engine/security/prompt-injection.js +2 -1
  155. package/dist/engine/security/prompt-injection.js.map +1 -1
  156. package/dist/engine/security/prompt-injection.test.js +1 -1
  157. package/dist/engine/security/prompt-injection.test.js.map +1 -1
  158. package/dist/engine/security/protected-paths-store.d.ts +56 -0
  159. package/dist/engine/security/protected-paths-store.d.ts.map +1 -0
  160. package/dist/engine/security/protected-paths-store.js +239 -0
  161. package/dist/engine/security/protected-paths-store.js.map +1 -0
  162. package/dist/engine/security/protected-paths.d.ts +54 -0
  163. package/dist/engine/security/protected-paths.d.ts.map +1 -0
  164. package/dist/engine/security/protected-paths.js +193 -0
  165. package/dist/engine/security/protected-paths.js.map +1 -0
  166. package/dist/engine/security/protected-paths.test.d.ts +2 -0
  167. package/dist/engine/security/protected-paths.test.d.ts.map +1 -0
  168. package/dist/engine/security/protected-paths.test.js +166 -0
  169. package/dist/engine/security/protected-paths.test.js.map +1 -0
  170. package/dist/engine/security/shell-guard.d.ts +117 -0
  171. package/dist/engine/security/shell-guard.d.ts.map +1 -0
  172. package/dist/engine/security/shell-guard.js +578 -0
  173. package/dist/engine/security/shell-guard.js.map +1 -0
  174. package/dist/engine/security/shell-guard.test.d.ts +2 -0
  175. package/dist/engine/security/shell-guard.test.d.ts.map +1 -0
  176. package/dist/engine/security/shell-guard.test.js +378 -0
  177. package/dist/engine/security/shell-guard.test.js.map +1 -0
  178. package/dist/engine/system-messages.d.ts +237 -0
  179. package/dist/engine/system-messages.d.ts.map +1 -0
  180. package/dist/engine/system-messages.js +276 -0
  181. package/dist/engine/system-messages.js.map +1 -0
  182. package/dist/engine/system-messages.test.d.ts +2 -0
  183. package/dist/engine/system-messages.test.d.ts.map +1 -0
  184. package/dist/engine/system-messages.test.js +81 -0
  185. package/dist/engine/system-messages.test.js.map +1 -0
  186. package/dist/engine/tools/abort.d.ts +21 -0
  187. package/dist/engine/tools/abort.d.ts.map +1 -0
  188. package/dist/engine/tools/abort.js +44 -0
  189. package/dist/engine/tools/abort.js.map +1 -0
  190. package/dist/engine/tools/classify-conversation.d.ts.map +1 -1
  191. package/dist/engine/tools/classify-conversation.js +7 -2
  192. package/dist/engine/tools/classify-conversation.js.map +1 -1
  193. package/dist/engine/tools/fs-read.d.ts.map +1 -1
  194. package/dist/engine/tools/fs-read.js +17 -6
  195. package/dist/engine/tools/fs-read.js.map +1 -1
  196. package/dist/engine/tools/fs-read.test.js +43 -0
  197. package/dist/engine/tools/fs-read.test.js.map +1 -1
  198. package/dist/engine/tools/fs-write.d.ts.map +1 -1
  199. package/dist/engine/tools/fs-write.js +47 -17
  200. package/dist/engine/tools/fs-write.js.map +1 -1
  201. package/dist/engine/tools/git.d.ts +2 -1
  202. package/dist/engine/tools/git.d.ts.map +1 -1
  203. package/dist/engine/tools/git.js +85 -17
  204. package/dist/engine/tools/git.js.map +1 -1
  205. package/dist/engine/tools/git.test.js +39 -0
  206. package/dist/engine/tools/git.test.js.map +1 -1
  207. package/dist/engine/tools/index.d.ts.map +1 -1
  208. package/dist/engine/tools/index.js +16 -2
  209. package/dist/engine/tools/index.js.map +1 -1
  210. package/dist/engine/tools/json-schema.js +38 -0
  211. package/dist/engine/tools/json-schema.js.map +1 -1
  212. package/dist/engine/tools/json-schema.test.d.ts +2 -0
  213. package/dist/engine/tools/json-schema.test.d.ts.map +1 -0
  214. package/dist/engine/tools/json-schema.test.js +40 -0
  215. package/dist/engine/tools/json-schema.test.js.map +1 -0
  216. package/dist/engine/tools/path-utils.d.ts.map +1 -1
  217. package/dist/engine/tools/path-utils.js +24 -0
  218. package/dist/engine/tools/path-utils.js.map +1 -1
  219. package/dist/engine/tools/path-utils.test.js +15 -0
  220. package/dist/engine/tools/path-utils.test.js.map +1 -1
  221. package/dist/engine/tools/plan.d.ts +11 -3
  222. package/dist/engine/tools/plan.d.ts.map +1 -1
  223. package/dist/engine/tools/plan.js +326 -95
  224. package/dist/engine/tools/plan.js.map +1 -1
  225. package/dist/engine/tools/plan.test.js +161 -47
  226. package/dist/engine/tools/plan.test.js.map +1 -1
  227. package/dist/engine/tools/project-context.d.ts.map +1 -1
  228. package/dist/engine/tools/project-context.js +54 -42
  229. package/dist/engine/tools/project-context.js.map +1 -1
  230. package/dist/engine/tools/project-context.test.js +37 -22
  231. package/dist/engine/tools/project-context.test.js.map +1 -1
  232. package/dist/engine/tools/project-manage.d.ts +24 -0
  233. package/dist/engine/tools/project-manage.d.ts.map +1 -0
  234. package/dist/engine/tools/project-manage.js +311 -0
  235. package/dist/engine/tools/project-manage.js.map +1 -0
  236. package/dist/engine/tools/project-manage.test.d.ts +2 -0
  237. package/dist/engine/tools/project-manage.test.d.ts.map +1 -0
  238. package/dist/engine/tools/project-manage.test.js +196 -0
  239. package/dist/engine/tools/project-manage.test.js.map +1 -0
  240. package/dist/engine/tools/read-reference.d.ts.map +1 -1
  241. package/dist/engine/tools/read-reference.js +10 -5
  242. package/dist/engine/tools/read-reference.js.map +1 -1
  243. package/dist/engine/tools/read-reference.test.js +5 -2
  244. package/dist/engine/tools/read-reference.test.js.map +1 -1
  245. package/dist/engine/tools/search.d.ts.map +1 -1
  246. package/dist/engine/tools/search.js +16 -6
  247. package/dist/engine/tools/search.js.map +1 -1
  248. package/dist/engine/tools/shell.d.ts.map +1 -1
  249. package/dist/engine/tools/shell.js +17 -4
  250. package/dist/engine/tools/shell.js.map +1 -1
  251. package/dist/engine/tools/shell.test.js +63 -1
  252. package/dist/engine/tools/shell.test.js.map +1 -1
  253. package/dist/engine/tools/task-resume.d.ts +93 -0
  254. package/dist/engine/tools/task-resume.d.ts.map +1 -0
  255. package/dist/engine/tools/task-resume.js +269 -0
  256. package/dist/engine/tools/task-resume.js.map +1 -0
  257. package/dist/engine/tools/task-resume.test.d.ts +2 -0
  258. package/dist/engine/tools/task-resume.test.d.ts.map +1 -0
  259. package/dist/engine/tools/task-resume.test.js +423 -0
  260. package/dist/engine/tools/task-resume.test.js.map +1 -0
  261. package/dist/engine/tools/task.d.ts +81 -2
  262. package/dist/engine/tools/task.d.ts.map +1 -1
  263. package/dist/engine/tools/task.js +898 -471
  264. package/dist/engine/tools/task.js.map +1 -1
  265. package/dist/engine/tools/task.test.js +371 -3
  266. package/dist/engine/tools/task.test.js.map +1 -1
  267. package/dist/engine/tools/todo.d.ts +27 -1
  268. package/dist/engine/tools/todo.d.ts.map +1 -1
  269. package/dist/engine/tools/todo.js +320 -14
  270. package/dist/engine/tools/todo.js.map +1 -1
  271. package/dist/engine/tools/todo.test.js +150 -48
  272. package/dist/engine/tools/todo.test.js.map +1 -1
  273. package/dist/engine/tools/web.d.ts.map +1 -1
  274. package/dist/engine/tools/web.js +65 -18
  275. package/dist/engine/tools/web.js.map +1 -1
  276. package/dist/engine/tools/web.test.js +94 -2
  277. package/dist/engine/tools/web.test.js.map +1 -1
  278. package/dist/events/bus.d.ts +7 -0
  279. package/dist/events/bus.d.ts.map +1 -1
  280. package/dist/events/bus.js +26 -3
  281. package/dist/events/bus.js.map +1 -1
  282. package/dist/events/bus.test.js +46 -0
  283. package/dist/events/bus.test.js.map +1 -1
  284. package/dist/index.d.ts +11 -3
  285. package/dist/index.d.ts.map +1 -1
  286. package/dist/index.js +7 -3
  287. package/dist/index.js.map +1 -1
  288. package/dist/logger.d.ts.map +1 -1
  289. package/dist/logger.js +0 -1
  290. package/dist/logger.js.map +1 -1
  291. package/dist/main.js +250 -10
  292. package/dist/main.js.map +1 -1
  293. package/dist/prompts/roles/ADMIN.en.md +12 -11
  294. package/dist/prompts/roles/ADMIN.ru.md +12 -11
  295. package/dist/prompts/roles/ANALYST.en.md +12 -11
  296. package/dist/prompts/roles/ANALYST.ru.md +12 -11
  297. package/dist/prompts/roles/ASSISTANT.en.md +12 -11
  298. package/dist/prompts/roles/ASSISTANT.ru.md +12 -11
  299. package/dist/prompts/roles/AUDITOR.en.md +12 -11
  300. package/dist/prompts/roles/AUDITOR.ru.md +12 -11
  301. package/dist/prompts/roles/DEVELOPER.en.md +12 -11
  302. package/dist/prompts/roles/DEVELOPER.ru.md +12 -11
  303. package/dist/prompts/roles/DEVOPS.en.md +12 -11
  304. package/dist/prompts/roles/DEVOPS.ru.md +12 -11
  305. package/dist/prompts/roles/PM.en.md +12 -11
  306. package/dist/prompts/roles/PM.ru.md +12 -11
  307. package/dist/prompts/roles/QA.en.md +12 -11
  308. package/dist/prompts/roles/QA.ru.md +12 -11
  309. package/dist/prompts/roles/TITLE.en.md +30 -0
  310. package/dist/prompts/roles/TITLE.ru.md +3 -11
  311. package/dist/prompts/security/ask-protected-path.en.md +1 -0
  312. package/dist/prompts/security/ask-protected-path.ru.md +1 -0
  313. package/dist/prompts/security/deny-command.en.md +1 -0
  314. package/dist/prompts/security/deny-command.ru.md +1 -0
  315. package/dist/prompts/security/deny-protected-dir.en.md +1 -0
  316. package/dist/prompts/security/deny-protected-dir.ru.md +1 -0
  317. package/dist/prompts/security/deny-protected-path.en.md +1 -0
  318. package/dist/prompts/security/deny-protected-path.ru.md +1 -0
  319. package/dist/prompts/subagents/explore.en.md +23 -0
  320. package/dist/prompts/subagents/general.en.md +19 -0
  321. package/dist/prompts/system/MODE_ACT.en.md +20 -0
  322. package/{prompts/modes/act.md → dist/prompts/system/MODE_ACT.ru.md} +2 -0
  323. package/dist/prompts/system/MODE_PLAN.en.md +22 -0
  324. package/dist/prompts/{modes/plan.md → system/MODE_PLAN.ru.md} +4 -3
  325. package/dist/prompts/system/MODE_YOLO.en.md +22 -0
  326. package/{prompts/modes/yolo.md → dist/prompts/system/MODE_YOLO.ru.md} +2 -0
  327. package/dist/prompts/system/PLAN_GUIDE.en.md +36 -0
  328. package/dist/prompts/system/PLAN_GUIDE.ru.md +33 -0
  329. package/dist/prompts/system/PLAN_MODE_AUTO.en.md +11 -0
  330. package/dist/prompts/system/PLAN_MODE_AUTO.ru.md +12 -0
  331. package/dist/prompts/system/PLAN_MODE_STRICT_APPROVED.en.md +8 -0
  332. package/dist/prompts/system/PLAN_MODE_STRICT_APPROVED.ru.md +8 -0
  333. package/dist/prompts/system/PLAN_MODE_STRICT_NOT_APPROVED.en.md +7 -0
  334. package/dist/prompts/system/PLAN_MODE_STRICT_NOT_APPROVED.ru.md +7 -0
  335. package/dist/providers/anthropic.d.ts.map +1 -1
  336. package/dist/providers/anthropic.js +28 -2
  337. package/dist/providers/anthropic.js.map +1 -1
  338. package/dist/providers/base.d.ts +20 -1
  339. package/dist/providers/base.d.ts.map +1 -1
  340. package/dist/providers/base.js +17 -0
  341. package/dist/providers/base.js.map +1 -1
  342. package/dist/providers/exceptions.d.ts.map +1 -1
  343. package/dist/providers/exceptions.js +3 -2
  344. package/dist/providers/exceptions.js.map +1 -1
  345. package/dist/providers/index.d.ts +1 -0
  346. package/dist/providers/index.d.ts.map +1 -1
  347. package/dist/providers/index.js +4 -0
  348. package/dist/providers/index.js.map +1 -1
  349. package/dist/providers/ollama.d.ts +23 -0
  350. package/dist/providers/ollama.d.ts.map +1 -1
  351. package/dist/providers/ollama.js +128 -12
  352. package/dist/providers/ollama.js.map +1 -1
  353. package/dist/providers/ollama.test.d.ts +2 -0
  354. package/dist/providers/ollama.test.d.ts.map +1 -0
  355. package/dist/providers/ollama.test.js +129 -0
  356. package/dist/providers/ollama.test.js.map +1 -0
  357. package/dist/providers/openai.d.ts.map +1 -1
  358. package/dist/providers/openai.js +82 -9
  359. package/dist/providers/openai.js.map +1 -1
  360. package/dist/providers/openai.test.d.ts +2 -0
  361. package/dist/providers/openai.test.d.ts.map +1 -0
  362. package/dist/providers/openai.test.js +84 -0
  363. package/dist/providers/openai.test.js.map +1 -0
  364. package/dist/providers/remote.d.ts +60 -0
  365. package/dist/providers/remote.d.ts.map +1 -0
  366. package/dist/providers/remote.js +394 -0
  367. package/dist/providers/remote.js.map +1 -0
  368. package/dist/providers/remote.test.d.ts +2 -0
  369. package/dist/providers/remote.test.d.ts.map +1 -0
  370. package/dist/providers/remote.test.js +258 -0
  371. package/dist/providers/remote.test.js.map +1 -0
  372. package/dist/providers/stream-error.test.d.ts +2 -0
  373. package/dist/providers/stream-error.test.d.ts.map +1 -0
  374. package/dist/providers/stream-error.test.js +63 -0
  375. package/dist/providers/stream-error.test.js.map +1 -0
  376. package/dist/providers/timeout.test.d.ts +2 -0
  377. package/dist/providers/timeout.test.d.ts.map +1 -0
  378. package/dist/providers/timeout.test.js +129 -0
  379. package/dist/providers/timeout.test.js.map +1 -0
  380. package/dist/queue/processor.d.ts +22 -0
  381. package/dist/queue/processor.d.ts.map +1 -1
  382. package/dist/queue/processor.js +150 -25
  383. package/dist/queue/processor.js.map +1 -1
  384. package/dist/queue/processor.test.d.ts +2 -0
  385. package/dist/queue/processor.test.d.ts.map +1 -0
  386. package/dist/queue/processor.test.js +211 -0
  387. package/dist/queue/processor.test.js.map +1 -0
  388. package/dist/remote/aggregate.d.ts +43 -0
  389. package/dist/remote/aggregate.d.ts.map +1 -0
  390. package/dist/remote/aggregate.js +84 -0
  391. package/dist/remote/aggregate.js.map +1 -0
  392. package/dist/remote/aggregate.test.d.ts +2 -0
  393. package/dist/remote/aggregate.test.d.ts.map +1 -0
  394. package/dist/remote/aggregate.test.js +120 -0
  395. package/dist/remote/aggregate.test.js.map +1 -0
  396. package/dist/remote/client.d.ts +142 -0
  397. package/dist/remote/client.d.ts.map +1 -0
  398. package/dist/remote/client.js +290 -0
  399. package/dist/remote/client.js.map +1 -0
  400. package/dist/remote/client.test.d.ts +2 -0
  401. package/dist/remote/client.test.d.ts.map +1 -0
  402. package/dist/remote/client.test.js +176 -0
  403. package/dist/remote/client.test.js.map +1 -0
  404. package/dist/remote/connection.d.ts +66 -0
  405. package/dist/remote/connection.d.ts.map +1 -0
  406. package/dist/remote/connection.js +298 -0
  407. package/dist/remote/connection.js.map +1 -0
  408. package/dist/remote/connection.test.d.ts +2 -0
  409. package/dist/remote/connection.test.d.ts.map +1 -0
  410. package/dist/remote/connection.test.js +323 -0
  411. package/dist/remote/connection.test.js.map +1 -0
  412. package/dist/remote/credentials.d.ts +13 -0
  413. package/dist/remote/credentials.d.ts.map +1 -0
  414. package/dist/remote/credentials.js +81 -0
  415. package/dist/remote/credentials.js.map +1 -0
  416. package/dist/remote/credentials.test.d.ts +2 -0
  417. package/dist/remote/credentials.test.d.ts.map +1 -0
  418. package/dist/remote/credentials.test.js +69 -0
  419. package/dist/remote/credentials.test.js.map +1 -0
  420. package/dist/remote/device-flow.d.ts +72 -0
  421. package/dist/remote/device-flow.d.ts.map +1 -0
  422. package/dist/remote/device-flow.js +229 -0
  423. package/dist/remote/device-flow.js.map +1 -0
  424. package/dist/remote/device-flow.test.d.ts +2 -0
  425. package/dist/remote/device-flow.test.d.ts.map +1 -0
  426. package/dist/remote/device-flow.test.js +103 -0
  427. package/dist/remote/device-flow.test.js.map +1 -0
  428. package/dist/remote/event-bridge.d.ts +46 -0
  429. package/dist/remote/event-bridge.d.ts.map +1 -0
  430. package/dist/remote/event-bridge.js +218 -0
  431. package/dist/remote/event-bridge.js.map +1 -0
  432. package/dist/remote/event-bridge.test.d.ts +2 -0
  433. package/dist/remote/event-bridge.test.d.ts.map +1 -0
  434. package/dist/remote/event-bridge.test.js +240 -0
  435. package/dist/remote/event-bridge.test.js.map +1 -0
  436. package/dist/remote/index.d.ts +19 -0
  437. package/dist/remote/index.d.ts.map +1 -0
  438. package/dist/remote/index.js +11 -0
  439. package/dist/remote/index.js.map +1 -0
  440. package/dist/remote/session.d.ts +72 -0
  441. package/dist/remote/session.d.ts.map +1 -0
  442. package/dist/remote/session.js +248 -0
  443. package/dist/remote/session.js.map +1 -0
  444. package/dist/remote/session.test.d.ts +2 -0
  445. package/dist/remote/session.test.d.ts.map +1 -0
  446. package/dist/remote/session.test.js +482 -0
  447. package/dist/remote/session.test.js.map +1 -0
  448. package/dist/remote/transfer.d.ts +75 -0
  449. package/dist/remote/transfer.d.ts.map +1 -0
  450. package/dist/remote/transfer.js +491 -0
  451. package/dist/remote/transfer.js.map +1 -0
  452. package/dist/remote/transfer.test.d.ts +2 -0
  453. package/dist/remote/transfer.test.d.ts.map +1 -0
  454. package/dist/remote/transfer.test.js +416 -0
  455. package/dist/remote/transfer.test.js.map +1 -0
  456. package/dist/remote/types.d.ts +28 -0
  457. package/dist/remote/types.d.ts.map +1 -0
  458. package/dist/remote/types.js +10 -0
  459. package/dist/remote/types.js.map +1 -0
  460. package/dist/server/app.d.ts +62 -1
  461. package/dist/server/app.d.ts.map +1 -1
  462. package/dist/server/app.js +393 -27
  463. package/dist/server/app.js.map +1 -1
  464. package/dist/server/app.proxy.test.d.ts +2 -0
  465. package/dist/server/app.proxy.test.d.ts.map +1 -0
  466. package/dist/server/app.proxy.test.js +193 -0
  467. package/dist/server/app.proxy.test.js.map +1 -0
  468. package/dist/server/app.remote.test.d.ts +2 -0
  469. package/dist/server/app.remote.test.d.ts.map +1 -0
  470. package/dist/server/app.remote.test.js +674 -0
  471. package/dist/server/app.remote.test.js.map +1 -0
  472. package/dist/server/chat.d.ts.map +1 -1
  473. package/dist/server/chat.js +18 -2
  474. package/dist/server/chat.js.map +1 -1
  475. package/dist/server/proxy.d.ts +14 -0
  476. package/dist/server/proxy.d.ts.map +1 -0
  477. package/dist/server/proxy.js +93 -0
  478. package/dist/server/proxy.js.map +1 -0
  479. package/dist/server/routes/agents.d.ts.map +1 -1
  480. package/dist/server/routes/agents.js +39 -23
  481. package/dist/server/routes/agents.js.map +1 -1
  482. package/dist/server/routes/auth.d.ts +26 -2
  483. package/dist/server/routes/auth.d.ts.map +1 -1
  484. package/dist/server/routes/auth.js +269 -36
  485. package/dist/server/routes/auth.js.map +1 -1
  486. package/dist/server/routes/auth.test.d.ts +2 -0
  487. package/dist/server/routes/auth.test.d.ts.map +1 -0
  488. package/dist/server/routes/auth.test.js +466 -0
  489. package/dist/server/routes/auth.test.js.map +1 -0
  490. package/dist/server/routes/fs.d.ts +2 -1
  491. package/dist/server/routes/fs.d.ts.map +1 -1
  492. package/dist/server/routes/fs.js +340 -7
  493. package/dist/server/routes/fs.js.map +1 -1
  494. package/dist/server/routes/hybrid.d.ts +32 -0
  495. package/dist/server/routes/hybrid.d.ts.map +1 -0
  496. package/dist/server/routes/hybrid.js +21 -0
  497. package/dist/server/routes/hybrid.js.map +1 -0
  498. package/dist/server/routes/hybrid.test.d.ts +2 -0
  499. package/dist/server/routes/hybrid.test.d.ts.map +1 -0
  500. package/dist/server/routes/hybrid.test.js +454 -0
  501. package/dist/server/routes/hybrid.test.js.map +1 -0
  502. package/dist/server/routes/messages.d.ts +2 -1
  503. package/dist/server/routes/messages.d.ts.map +1 -1
  504. package/dist/server/routes/messages.js +104 -1
  505. package/dist/server/routes/messages.js.map +1 -1
  506. package/dist/server/routes/models.cache.test.d.ts +2 -0
  507. package/dist/server/routes/models.cache.test.d.ts.map +1 -0
  508. package/dist/server/routes/models.cache.test.js +59 -0
  509. package/dist/server/routes/models.cache.test.js.map +1 -0
  510. package/dist/server/routes/models.d.ts +9 -1
  511. package/dist/server/routes/models.d.ts.map +1 -1
  512. package/dist/server/routes/models.js +38 -3
  513. package/dist/server/routes/models.js.map +1 -1
  514. package/dist/server/routes/models.remote.test.d.ts +2 -0
  515. package/dist/server/routes/models.remote.test.d.ts.map +1 -0
  516. package/dist/server/routes/models.remote.test.js +101 -0
  517. package/dist/server/routes/models.remote.test.js.map +1 -0
  518. package/dist/server/routes/project-transfer.d.ts +16 -0
  519. package/dist/server/routes/project-transfer.d.ts.map +1 -0
  520. package/dist/server/routes/project-transfer.js +141 -0
  521. package/dist/server/routes/project-transfer.js.map +1 -0
  522. package/dist/server/routes/project-transfer.test.d.ts +2 -0
  523. package/dist/server/routes/project-transfer.test.d.ts.map +1 -0
  524. package/dist/server/routes/project-transfer.test.js +199 -0
  525. package/dist/server/routes/project-transfer.test.js.map +1 -0
  526. package/dist/server/routes/projects.d.ts +2 -1
  527. package/dist/server/routes/projects.d.ts.map +1 -1
  528. package/dist/server/routes/projects.js +101 -5
  529. package/dist/server/routes/projects.js.map +1 -1
  530. package/dist/server/routes/providers.d.ts +1 -1
  531. package/dist/server/routes/providers.d.ts.map +1 -1
  532. package/dist/server/routes/providers.js +3 -1
  533. package/dist/server/routes/providers.js.map +1 -1
  534. package/dist/server/routes/providers.test.d.ts +2 -0
  535. package/dist/server/routes/providers.test.d.ts.map +1 -0
  536. package/dist/server/routes/providers.test.js +58 -0
  537. package/dist/server/routes/providers.test.js.map +1 -0
  538. package/dist/server/routes/queue.d.ts +2 -1
  539. package/dist/server/routes/queue.d.ts.map +1 -1
  540. package/dist/server/routes/queue.js +180 -18
  541. package/dist/server/routes/queue.js.map +1 -1
  542. package/dist/server/routes/sessions.d.ts +9 -1
  543. package/dist/server/routes/sessions.d.ts.map +1 -1
  544. package/dist/server/routes/sessions.js +269 -18
  545. package/dist/server/routes/sessions.js.map +1 -1
  546. package/dist/server/routes/sessions.test.js +102 -2
  547. package/dist/server/routes/sessions.test.js.map +1 -1
  548. package/dist/server/routes/settings.d.ts +6 -1
  549. package/dist/server/routes/settings.d.ts.map +1 -1
  550. package/dist/server/routes/settings.js +138 -0
  551. package/dist/server/routes/settings.js.map +1 -1
  552. package/dist/server/routes/settings.test.js +65 -1
  553. package/dist/server/routes/settings.test.js.map +1 -1
  554. package/dist/server/serialize.d.ts +11 -3
  555. package/dist/server/serialize.d.ts.map +1 -1
  556. package/dist/server/serialize.js +11 -3
  557. package/dist/server/serialize.js.map +1 -1
  558. package/dist/sessions/auto-title.d.ts +1 -1
  559. package/dist/sessions/auto-title.d.ts.map +1 -1
  560. package/dist/sessions/auto-title.js +24 -13
  561. package/dist/sessions/auto-title.js.map +1 -1
  562. package/dist/sessions/manager.d.ts +1 -2
  563. package/dist/sessions/manager.d.ts.map +1 -1
  564. package/dist/sessions/manager.js +11 -36
  565. package/dist/sessions/manager.js.map +1 -1
  566. package/dist/sessions/manager.test.js +2 -10
  567. package/dist/sessions/manager.test.js.map +1 -1
  568. package/dist/storage/file-store.d.ts.map +1 -1
  569. package/dist/storage/file-store.js +2 -6
  570. package/dist/storage/file-store.js.map +1 -1
  571. package/dist/storage/file-store.test.js +1 -6
  572. package/dist/storage/file-store.test.js.map +1 -1
  573. package/dist/storage/project-store.d.ts.map +1 -1
  574. package/dist/storage/project-store.js +12 -0
  575. package/dist/storage/project-store.js.map +1 -1
  576. package/dist/storage/runtime-settings.d.ts +25 -1
  577. package/dist/storage/runtime-settings.d.ts.map +1 -1
  578. package/dist/storage/runtime-settings.js +31 -0
  579. package/dist/storage/runtime-settings.js.map +1 -1
  580. package/package.json +10 -5
  581. package/prompts/roles/TITLE.en.md +30 -0
  582. package/prompts/security/ask-protected-path.en.md +1 -0
  583. package/prompts/security/ask-protected-path.ru.md +1 -0
  584. package/prompts/security/deny-command.en.md +1 -0
  585. package/prompts/security/deny-command.ru.md +1 -0
  586. package/prompts/security/deny-protected-dir.en.md +1 -0
  587. package/prompts/security/deny-protected-dir.ru.md +1 -0
  588. package/prompts/security/deny-protected-path.en.md +1 -0
  589. package/prompts/security/deny-protected-path.ru.md +1 -0
  590. package/prompts/subagents/explore.en.md +23 -0
  591. package/prompts/subagents/general.en.md +19 -0
  592. package/prompts/system/MODE_ACT.en.md +20 -0
  593. package/{dist/prompts/modes/act.md → prompts/system/MODE_ACT.ru.md} +2 -0
  594. package/prompts/system/MODE_PLAN.en.md +22 -0
  595. package/{dist/prompts/prompts/modes/plan.md → prompts/system/MODE_PLAN.ru.md} +4 -3
  596. package/prompts/system/MODE_YOLO.en.md +22 -0
  597. package/{dist/prompts/prompts/modes/yolo.md → prompts/system/MODE_YOLO.ru.md} +2 -0
  598. package/prompts/system/PLAN_GUIDE.en.md +36 -0
  599. package/prompts/system/PLAN_GUIDE.ru.md +33 -0
  600. package/prompts/system/PLAN_MODE_AUTO.en.md +11 -0
  601. package/prompts/system/PLAN_MODE_AUTO.ru.md +12 -0
  602. package/prompts/system/PLAN_MODE_STRICT_APPROVED.en.md +8 -0
  603. package/prompts/system/PLAN_MODE_STRICT_APPROVED.ru.md +8 -0
  604. package/prompts/system/PLAN_MODE_STRICT_NOT_APPROVED.en.md +7 -0
  605. package/prompts/system/PLAN_MODE_STRICT_NOT_APPROVED.ru.md +7 -0
  606. package/dist/dictionaries/dictionaries/coding.en.yaml +0 -20
  607. package/dist/dictionaries/dictionaries/coding.ru.yaml +0 -22
  608. package/dist/dictionaries/dictionaries/coding.tools.yaml +0 -12
  609. package/dist/dictionaries/dictionaries/enum.en.yaml +0 -54
  610. package/dist/dictionaries/dictionaries/enum.ru.yaml +0 -67
  611. package/dist/dictionaries/dictionaries/injection.en.yaml +0 -51
  612. package/dist/dictionaries/dictionaries/injection.ru.yaml +0 -51
  613. package/dist/dictionaries/dictionaries/intents.en.yaml +0 -68
  614. package/dist/dictionaries/dictionaries/intents.ru.yaml +0 -78
  615. package/dist/dictionaries/dictionaries/research.en.yaml +0 -17
  616. package/dist/dictionaries/dictionaries/research.ru.yaml +0 -17
  617. package/dist/dictionaries/dictionaries/small-talk.en.yaml +0 -67
  618. package/dist/dictionaries/dictionaries/small-talk.ru.yaml +0 -81
  619. package/dist/prompts/modes/yolo.md +0 -20
  620. package/dist/prompts/prompts/modes/act.md +0 -18
  621. package/dist/prompts/prompts/roles/ADMIN.en.md +0 -33
  622. package/dist/prompts/prompts/roles/ADMIN.ru.md +0 -33
  623. package/dist/prompts/prompts/roles/ANALYST.en.md +0 -33
  624. package/dist/prompts/prompts/roles/ANALYST.ru.md +0 -33
  625. package/dist/prompts/prompts/roles/ASSISTANT.en.md +0 -38
  626. package/dist/prompts/prompts/roles/ASSISTANT.ru.md +0 -38
  627. package/dist/prompts/prompts/roles/AUDITOR.en.md +0 -33
  628. package/dist/prompts/prompts/roles/AUDITOR.ru.md +0 -33
  629. package/dist/prompts/prompts/roles/DEVELOPER.en.md +0 -42
  630. package/dist/prompts/prompts/roles/DEVELOPER.ru.md +0 -42
  631. package/dist/prompts/prompts/roles/DEVOPS.en.md +0 -35
  632. package/dist/prompts/prompts/roles/DEVOPS.ru.md +0 -35
  633. package/dist/prompts/prompts/roles/PM.en.md +0 -33
  634. package/dist/prompts/prompts/roles/PM.ru.md +0 -33
  635. package/dist/prompts/prompts/roles/QA.en.md +0 -33
  636. package/dist/prompts/prompts/roles/QA.ru.md +0 -33
  637. package/dist/prompts/prompts/roles/TITLE.ru.md +0 -30
  638. package/dist/prompts/prompts/subagents/explore.ru.md +0 -23
  639. package/dist/prompts/prompts/subagents/general.ru.md +0 -19
  640. package/dist/prompts/prompts/system/COMPRESSED_DIALOG.en.md +0 -5
  641. package/dist/prompts/prompts/system/COMPRESSED_DIALOG.ru.md +0 -5
  642. package/dist/prompts/prompts/system/INTERVIEW.en.md +0 -18
  643. package/dist/prompts/prompts/system/INTERVIEW.ru.md +0 -18
  644. package/dist/prompts/prompts/system/PARTICIPANTS_NOTICE.en.md +0 -7
  645. package/dist/prompts/prompts/system/PARTICIPANTS_NOTICE.ru.md +0 -7
  646. package/dist/prompts/prompts/system/ROLES_DESCRIPTION.en.md +0 -16
  647. package/dist/prompts/prompts/system/ROLES_DESCRIPTION.ru.md +0 -16
  648. package/dist/prompts/prompts/system/ROUTING.en.md +0 -13
  649. package/dist/prompts/prompts/system/ROUTING.md +0 -6
  650. package/dist/prompts/prompts/system/ROUTING.ru.md +0 -13
  651. package/dist/prompts/prompts/system/RULES.en.md +0 -10
  652. package/dist/prompts/prompts/system/RULES.md +0 -10
  653. package/dist/prompts/prompts/system/RULES.ru.md +0 -10
  654. package/dist/prompts/prompts/system/STICKY_NOTES.en.md +0 -6
  655. package/dist/prompts/prompts/system/STICKY_NOTES.ru.md +0 -6
  656. package/dist/prompts/prompts/system/SUMMARIZER.en.md +0 -54
  657. package/dist/prompts/prompts/system/SUMMARIZER.ru.md +0 -54
  658. package/dist/prompts/prompts/system/USER_CONTEXT.en.md +0 -5
  659. package/dist/prompts/prompts/system/USER_CONTEXT.ru.md +0 -5
  660. package/dist/prompts/system/ROUTING.md +0 -6
  661. package/dist/prompts/system/RULES.md +0 -10
  662. package/dist/server/routes/i18n.d.ts +0 -3
  663. package/dist/server/routes/i18n.d.ts.map +0 -1
  664. package/dist/server/routes/i18n.js +0 -83
  665. package/dist/server/routes/i18n.js.map +0 -1
  666. package/prompts/modes/plan.md +0 -20
  667. package/prompts/system/ROUTING.md +0 -6
  668. package/prompts/system/RULES.md +0 -10
  669. /package/dist/prompts/{prompts/system → system}/GATEWAY.en.md +0 -0
  670. /package/dist/prompts/{prompts/system → system}/GATEWAY.ru.md +0 -0
@@ -0,0 +1,298 @@
1
+ // RemoteConnection — менеджер runtime-подключения к удалённому backend для гибридного режима.
2
+ //
3
+ // Отличие от RemoteSession (который при отсутствии credentials уходит в интерактивный
4
+ // device flow): сервер стартует «холодным», без подключения, а пользователь логинится
5
+ // в UI (connectByPassword, ROPC). OIDC-параметры локальный core узнаёт с самого сервера
6
+ // (GET {server}/auth/oidc-meta); для старых серверов без эндпоинта есть fallback на
7
+ // deps.defaultIssuer/defaultClientId.
8
+ //
9
+ // Никакого device flow в этом модуле нет: только логин/пароль и сохранённые credentials.
10
+ import { RemoteError } from './types.js';
11
+ import { loadCredentials, saveCredentials, listCredentials } from './credentials.js';
12
+ import { refreshAccessToken } from './device-flow.js';
13
+ import { RemoteSession } from './session.js';
14
+ /** Таймаут GET {server}/auth/oidc-meta по умолчанию. */
15
+ const DEFAULT_OIDC_META_TIMEOUT_MS = 15_000;
16
+ /** Обрезать завершающие слэши у адреса сервера. */
17
+ function normalizeBaseUrl(url) {
18
+ return url.trim().replace(/\/+$/, '');
19
+ }
20
+ /** Токен протух, если expiresAt задан и не позже текущего момента. */
21
+ function isTokenExpired(expiresAt) {
22
+ if (!expiresAt)
23
+ return false;
24
+ const ts = Date.parse(expiresAt);
25
+ if (Number.isNaN(ts))
26
+ return false;
27
+ return ts <= Date.now();
28
+ }
29
+ export class RemoteConnection {
30
+ deps;
31
+ _backendUrl = null;
32
+ _session = null;
33
+ _user = null;
34
+ /** Последний использованный issuer (для UI/логов). */
35
+ _issuer = null;
36
+ constructor(deps) {
37
+ this.deps = deps;
38
+ }
39
+ // ── Состояние ──
40
+ /** true когда есть валидная сессия (токен получен). */
41
+ get connected() {
42
+ return this._session !== null;
43
+ }
44
+ get backendUrl() {
45
+ return this._backendUrl;
46
+ }
47
+ get client() {
48
+ return this._session?.getClient() ?? null;
49
+ }
50
+ get getToken() {
51
+ return this._session ? () => this._session.getToken() : null;
52
+ }
53
+ get user() {
54
+ return this._user;
55
+ }
56
+ get issuer() {
57
+ return this._issuer;
58
+ }
59
+ // ── Дискавери ──
60
+ /**
61
+ * Спросить у сервера его OIDC issuer + public client_id (GET {server}/auth/oidc-meta).
62
+ * - enabled:false → RemoteError('AUTH') — сервер не принимает вход по логину/паролю;
63
+ * - эндпоинт отсутствует (404/5xx) → fallback на deps.defaultIssuer/defaultClientId,
64
+ * при их отсутствии — RemoteError('AUTH');
65
+ * - сеть недоступна → fallback на deps.defaultIssuer/defaultClientId,
66
+ * при их отсутствии — RemoteError('OFFLINE').
67
+ */
68
+ async discoverOidc(serverUrl) {
69
+ const base = normalizeBaseUrl(serverUrl);
70
+ const fallback = this.deps.defaultIssuer && this.deps.defaultClientId
71
+ ? { issuer: this.deps.defaultIssuer, clientId: this.deps.defaultClientId }
72
+ : null;
73
+ let res;
74
+ try {
75
+ res = await fetch(`${base}/auth/oidc-meta`, {
76
+ signal: AbortSignal.timeout(this.deps.timeoutMs ?? DEFAULT_OIDC_META_TIMEOUT_MS),
77
+ });
78
+ }
79
+ catch {
80
+ if (fallback)
81
+ return { ...fallback };
82
+ throw new RemoteError(`Сервер недоступен: не удалось получить OIDC-параметры (${base})`, 'OFFLINE');
83
+ }
84
+ let body = {};
85
+ try {
86
+ body = (await res.json());
87
+ }
88
+ catch {
89
+ // не-JSON тело — ошибку сформируем по статусу ниже
90
+ }
91
+ if (body.enabled === false) {
92
+ throw new RemoteError('Сервер не поддерживает вход по логину/паролю', 'AUTH');
93
+ }
94
+ if (!res.ok) {
95
+ // Старый сервер без эндпоинта (404) или ошибка сервера — fallback на дефолты.
96
+ if (fallback)
97
+ return { ...fallback };
98
+ throw new RemoteError(`Сервер не отдал OIDC-параметры (HTTP ${res.status})`, 'AUTH');
99
+ }
100
+ const issuer = typeof body.issuer === 'string' ? body.issuer : undefined;
101
+ const clientId = typeof body.clientId === 'string' ? body.clientId : undefined;
102
+ if (!issuer || !clientId) {
103
+ throw new RemoteError('Сервер вернул некорректные OIDC-параметры', 'AUTH');
104
+ }
105
+ return { issuer, clientId };
106
+ }
107
+ // ── Подключение ──
108
+ /**
109
+ * Полное подключение: serverUrl → discoverOidc → RemoteSession.loginWithPassword.
110
+ * Обновляет _backendUrl/_session/_user/_issuer только после успешного входа,
111
+ * так что наружу не уходят частичные состояния. Ошибки пароля приходят из
112
+ * loginWithPassword как RemoteError('AUTH') и пробрасываются с русским сообщением.
113
+ */
114
+ async connectByPassword(serverUrl, username, password) {
115
+ const backendUrl = normalizeBaseUrl(serverUrl);
116
+ const { issuer, clientId } = await this.discoverOidc(backendUrl);
117
+ const session = await RemoteSession.loginWithPassword({
118
+ backendUrl,
119
+ issuer,
120
+ clientId,
121
+ credentialsPath: this.deps.credentialsPath,
122
+ timeoutMs: this.deps.timeoutMs,
123
+ }, username, password);
124
+ // loginWithPassword уже пробовал получить user из /auth/status; если сервер не
125
+ // ответил — делаем ещё одну попытку. Без профиля (id/roles) RemoteUser не собрать,
126
+ // поэтому соединение не фиксируем.
127
+ const user = session.user ?? (await this._fetchUserBestEffort(session));
128
+ if (!user) {
129
+ throw new RemoteError('Удалённый сервер не ответил профилем пользователя после входа', 'AUTH');
130
+ }
131
+ this._backendUrl = backendUrl;
132
+ this._session = session;
133
+ this._user = user;
134
+ this._issuer = issuer;
135
+ return user;
136
+ }
137
+ /**
138
+ * Подключение по API-ключу (authType='api_key', без дискавери OIDC).
139
+ * Используется для машинного входа (`serve --token` / CLI-автоматизация):
140
+ * никакого device flow, issuer не нужен. Сессия строится сразу, после чего
141
+ * best-effort запрашивается серверный пользователь (GET /auth/status).
142
+ * Если профиль не получить — подключение не фиксируется.
143
+ */
144
+ async connectWithApiKey(serverUrl, apiKey) {
145
+ const backendUrl = normalizeBaseUrl(serverUrl);
146
+ if (!apiKey) {
147
+ throw new RemoteError('Для подключения по API-ключу укажите ключ (--token)', 'AUTH');
148
+ }
149
+ const session = await RemoteSession.ensureAuthenticated({
150
+ backendUrl,
151
+ authType: 'api_key',
152
+ apiKey,
153
+ credentialsPath: this.deps.credentialsPath,
154
+ timeoutMs: this.deps.timeoutMs,
155
+ });
156
+ const user = session.user ?? (await this._fetchUserBestEffort(session));
157
+ if (!user) {
158
+ throw new RemoteError('Удалённый сервер не ответил профилем пользователя после подключения', 'AUTH');
159
+ }
160
+ this._backendUrl = backendUrl;
161
+ this._session = session;
162
+ this._user = user;
163
+ this._issuer = null;
164
+ return user;
165
+ }
166
+ /**
167
+ * Неинтерактивное подключение по сохранённым credentials (старт/авто-логин).
168
+ * Не запускает device flow! Если credentials нет или протухли без refresh —
169
+ * возвращает null (не бросает). Если backendUrl не передан — ищет по всем
170
+ * сохранённым credentials (порядок файла).
171
+ */
172
+ async connectFromSaved(backendUrl) {
173
+ const candidates = [];
174
+ if (backendUrl) {
175
+ candidates.push(normalizeBaseUrl(backendUrl));
176
+ }
177
+ else if (this._backendUrl) {
178
+ candidates.push(this._backendUrl);
179
+ }
180
+ else {
181
+ candidates.push(...(await listCredentials(this.deps.credentialsPath)));
182
+ }
183
+ for (const url of candidates) {
184
+ const user = await this._tryConnectFromSaved(url);
185
+ if (user)
186
+ return user;
187
+ }
188
+ return null;
189
+ }
190
+ /** Полный сброс runtime-состояния (провайдер/event bridge чистит вызывающий). */
191
+ disconnect() {
192
+ this._session = null;
193
+ this._user = null;
194
+ this._backendUrl = null;
195
+ this._issuer = null;
196
+ }
197
+ // ── Приватные помощники ──
198
+ /** Попытка подключиться к одному backendUrl по сохранённым credentials. */
199
+ async _tryConnectFromSaved(backendUrl) {
200
+ let creds = null;
201
+ try {
202
+ creds = await loadCredentials(backendUrl, this.deps.credentialsPath);
203
+ }
204
+ catch {
205
+ return null;
206
+ }
207
+ if (!creds?.accessToken)
208
+ return null;
209
+ const expired = isTokenExpired(creds.expiresAt);
210
+ let issuer;
211
+ let clientId;
212
+ if (expired) {
213
+ // Протух + есть refreshToken → дискавери (или deps.default*) и refresh.
214
+ if (!creds.refreshToken)
215
+ return null;
216
+ try {
217
+ const meta = await this.discoverOidc(backendUrl);
218
+ issuer = meta.issuer;
219
+ clientId = meta.clientId;
220
+ const refreshed = await refreshAccessToken(issuer, clientId, creds.refreshToken);
221
+ const updated = {
222
+ backendUrl,
223
+ accessToken: refreshed.accessToken,
224
+ refreshToken: refreshed.refreshToken ?? creds.refreshToken,
225
+ expiresAt: refreshed.expiresIn
226
+ ? new Date(Date.now() + refreshed.expiresIn * 1000).toISOString()
227
+ : undefined,
228
+ user: creds.user,
229
+ };
230
+ await saveCredentials(updated, this.deps.credentialsPath);
231
+ }
232
+ catch {
233
+ // дискавери/refresh не удались (сеть, OIDC выключен, invalid_grant) — не авто-логинимся
234
+ return null;
235
+ }
236
+ }
237
+ else {
238
+ // Валидный accessToken: issuer/clientId нужны для runtime-refresh (getToken).
239
+ // Дискавери best-effort (внутри — fallback на deps.default*); при неудаче сессия
240
+ // всё равно строится, но авто-refresh в рантайме будет недоступен.
241
+ try {
242
+ const meta = await this.discoverOidc(backendUrl);
243
+ issuer = meta.issuer;
244
+ clientId = meta.clientId;
245
+ }
246
+ catch {
247
+ issuer = this.deps.defaultIssuer;
248
+ clientId = this.deps.defaultClientId;
249
+ }
250
+ }
251
+ // На диске теперь валидные credentials → ensureAuthenticated выйдет на ветке
252
+ // «сохранённый accessToken действителен» и НЕ запустит device flow.
253
+ let session;
254
+ try {
255
+ session = await RemoteSession.ensureAuthenticated({
256
+ backendUrl,
257
+ issuer,
258
+ clientId,
259
+ credentialsPath: this.deps.credentialsPath,
260
+ timeoutMs: this.deps.timeoutMs,
261
+ });
262
+ }
263
+ catch {
264
+ return null;
265
+ }
266
+ // Обновить _user из /auth/status (best-effort; при недоступности сервера
267
+ // getAuthStatus сам возвращает connected:false).
268
+ let user = session.user ?? null;
269
+ try {
270
+ const status = await session.getAuthStatus();
271
+ if (status.connected && status.user) {
272
+ user = { id: status.user.id, username: status.user.username, roles: status.user.roles };
273
+ }
274
+ }
275
+ catch {
276
+ // оставляем user из credentials
277
+ }
278
+ this._backendUrl = backendUrl;
279
+ this._session = session;
280
+ this._user = user;
281
+ this._issuer = issuer ?? null;
282
+ return user;
283
+ }
284
+ /** Единичная best-effort попытка получить серверного пользователя. */
285
+ async _fetchUserBestEffort(session) {
286
+ try {
287
+ const status = await session.getClient().getAuthStatus();
288
+ if (status.user) {
289
+ return { id: status.user.id, username: status.user.username, roles: status.user.roles };
290
+ }
291
+ }
292
+ catch {
293
+ // best-effort
294
+ }
295
+ return null;
296
+ }
297
+ }
298
+ //# sourceMappingURL=connection.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"connection.js","sourceRoot":"","sources":["../../src/remote/connection.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=connection.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"connection.test.d.ts","sourceRoot":"","sources":["../../src/remote/connection.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,323 @@
1
+ import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest';
2
+ import { mkdtemp, rm } from 'node:fs/promises';
3
+ import { join } from 'node:path';
4
+ import { tmpdir } from 'node:os';
5
+ import { RemoteConnection } from './connection.js';
6
+ import { saveCredentials, loadCredentials } from './credentials.js';
7
+ import { RemoteError } from './types.js';
8
+ function jsonResponse(data, status = 200) {
9
+ return new Response(JSON.stringify(data), {
10
+ status,
11
+ headers: { 'Content-Type': 'application/json' },
12
+ });
13
+ }
14
+ const BACKEND = 'https://backend.test';
15
+ const ISSUER = 'https://kc.test/realms/synth';
16
+ const CLIENT_ID = 'synth-cli';
17
+ const OIDC_DISCOVERY = {
18
+ issuer: ISSUER,
19
+ token_endpoint: `${ISSUER}/protocol/openid-connect/token`,
20
+ device_authorization_endpoint: `${ISSUER}/protocol/openid-connect/auth/device`,
21
+ };
22
+ const SERVER_USER = { id: 'u-1', username: 'lucky', roles: ['ADMIN', 'USER'] };
23
+ /**
24
+ * fetch-мок успешного ROPC-входа: дискавери OIDC-меты на backend, token-грант
25
+ * (grant_type=password) на Keycloak, /auth/status с серверным пользователем.
26
+ */
27
+ function passwordFlowFetchMock(overrides = {}) {
28
+ const { tokenStatus = 200, tokenBody } = overrides;
29
+ return vi.fn((url) => {
30
+ const u = String(url);
31
+ if (u.includes('/auth/oidc-meta')) {
32
+ return Promise.resolve(jsonResponse({ enabled: true, issuer: ISSUER, clientId: CLIENT_ID }));
33
+ }
34
+ if (u.includes('/protocol/openid-connect/token')) {
35
+ if (tokenStatus !== 200) {
36
+ return Promise.resolve(jsonResponse(tokenBody ?? { error: 'invalid_grant' }, tokenStatus));
37
+ }
38
+ return Promise.resolve(jsonResponse(tokenBody ?? {
39
+ access_token: 'at-ropc',
40
+ refresh_token: 'rt-ropc',
41
+ expires_in: 300,
42
+ }));
43
+ }
44
+ if (u.includes('/auth/status')) {
45
+ return Promise.resolve(jsonResponse({ authenticated: true, oidc_enabled: true, user: SERVER_USER }));
46
+ }
47
+ return Promise.resolve(jsonResponse({ error: 'not_found' }, 404));
48
+ });
49
+ }
50
+ /** fetch-мок для connectFromSaved по протухшим credentials: oidc-meta + refresh-грант + status. */
51
+ function refreshFlowFetchMock() {
52
+ return vi.fn((url, init) => {
53
+ const u = String(url);
54
+ if (u.includes('/auth/oidc-meta')) {
55
+ return Promise.resolve(jsonResponse({ enabled: true, issuer: ISSUER, clientId: CLIENT_ID }));
56
+ }
57
+ if (u.includes('.well-known/openid-configuration')) {
58
+ return Promise.resolve(jsonResponse(OIDC_DISCOVERY));
59
+ }
60
+ if (u.includes('/protocol/openid-connect/token')) {
61
+ const body = init?.body instanceof URLSearchParams ? init.body : null;
62
+ if (body?.get('grant_type') === 'refresh_token') {
63
+ return Promise.resolve(jsonResponse({
64
+ access_token: 'at-refreshed',
65
+ refresh_token: 'rt-refreshed',
66
+ expires_in: 3600,
67
+ }));
68
+ }
69
+ }
70
+ if (u.includes('/auth/status')) {
71
+ return Promise.resolve(jsonResponse({ authenticated: true, oidc_enabled: true, user: SERVER_USER }));
72
+ }
73
+ return Promise.resolve(jsonResponse({ error: 'not_found' }, 404));
74
+ });
75
+ }
76
+ afterEach(() => {
77
+ vi.unstubAllGlobals();
78
+ });
79
+ describe('RemoteConnection.discoverOidc', () => {
80
+ it('сервер вернул {enabled:true, issuer, clientId} → возвращает их; адрес без завершающего /', async () => {
81
+ const fetchMock = vi.fn().mockResolvedValue(jsonResponse({ enabled: true, issuer: ISSUER, clientId: CLIENT_ID }));
82
+ vi.stubGlobal('fetch', fetchMock);
83
+ const conn = new RemoteConnection({});
84
+ const meta = await conn.discoverOidc('https://backend.test/');
85
+ expect(meta).toEqual({ issuer: ISSUER, clientId: CLIENT_ID });
86
+ expect(fetchMock).toHaveBeenCalledWith('https://backend.test/auth/oidc-meta', expect.objectContaining({ signal: expect.anything() }));
87
+ });
88
+ it('enabled:false → RemoteError(AUTH) с русским сообщением', async () => {
89
+ vi.stubGlobal('fetch', vi.fn().mockResolvedValue(jsonResponse({ enabled: false })));
90
+ const conn = new RemoteConnection({ defaultIssuer: ISSUER, defaultClientId: CLIENT_ID });
91
+ const err = await conn.discoverOidc(BACKEND).catch((e) => e);
92
+ expect(err).toBeInstanceOf(RemoteError);
93
+ expect(err.code).toBe('AUTH');
94
+ expect(err.message).toContain('не поддерживает вход по логину/паролю');
95
+ });
96
+ it('404 + deps.defaultIssuer/defaultClientId → fallback на дефолты', async () => {
97
+ vi.stubGlobal('fetch', vi.fn().mockResolvedValue(jsonResponse({ error: 'not_found' }, 404)));
98
+ const conn = new RemoteConnection({ defaultIssuer: ISSUER, defaultClientId: CLIENT_ID });
99
+ const meta = await conn.discoverOidc(BACKEND);
100
+ expect(meta).toEqual({ issuer: ISSUER, clientId: CLIENT_ID });
101
+ });
102
+ it('404 без fallback → RemoteError(AUTH)', async () => {
103
+ vi.stubGlobal('fetch', vi.fn().mockResolvedValue(jsonResponse({ error: 'not_found' }, 404)));
104
+ const conn = new RemoteConnection({});
105
+ const err = await conn.discoverOidc(BACKEND).catch((e) => e);
106
+ expect(err).toBeInstanceOf(RemoteError);
107
+ expect(err.code).toBe('AUTH');
108
+ });
109
+ it('сеть недоступна + fallback есть → возвращает дефолты', async () => {
110
+ vi.stubGlobal('fetch', vi.fn().mockRejectedValue(new TypeError('Failed to fetch')));
111
+ const conn = new RemoteConnection({ defaultIssuer: ISSUER, defaultClientId: CLIENT_ID });
112
+ const meta = await conn.discoverOidc(BACKEND);
113
+ expect(meta).toEqual({ issuer: ISSUER, clientId: CLIENT_ID });
114
+ });
115
+ it('сеть недоступна без fallback → RemoteError(OFFLINE)', async () => {
116
+ vi.stubGlobal('fetch', vi.fn().mockRejectedValue(new TypeError('Failed to fetch')));
117
+ const conn = new RemoteConnection({});
118
+ const err = await conn.discoverOidc(BACKEND).catch((e) => e);
119
+ expect(err).toBeInstanceOf(RemoteError);
120
+ expect(err.code).toBe('OFFLINE');
121
+ });
122
+ });
123
+ describe('RemoteConnection.connectByPassword', () => {
124
+ let dir;
125
+ beforeEach(async () => {
126
+ dir = await mkdtemp(join(tmpdir(), 'synth-conn-'));
127
+ });
128
+ afterEach(async () => {
129
+ await rm(dir, { recursive: true, force: true });
130
+ });
131
+ function credsPath() {
132
+ return join(dir, 'credentials.json');
133
+ }
134
+ it('успех: connected, user из /auth/status, client не null, backendUrl без завершающего /', async () => {
135
+ vi.stubGlobal('fetch', passwordFlowFetchMock());
136
+ const conn = new RemoteConnection({ credentialsPath: credsPath() });
137
+ const user = await conn.connectByPassword('https://backend.test/', 'lucky', 'secret');
138
+ expect(user).toEqual(SERVER_USER);
139
+ expect(conn.connected).toBe(true);
140
+ expect(conn.backendUrl).toBe(BACKEND);
141
+ expect(conn.client).not.toBeNull();
142
+ expect(conn.user?.username).toBe('lucky');
143
+ expect(conn.issuer).toBe(ISSUER);
144
+ expect(conn.getToken).not.toBeNull();
145
+ expect(await conn.getToken?.()).toBe('at-ropc');
146
+ const saved = await loadCredentials(BACKEND, credsPath());
147
+ expect(saved?.accessToken).toBe('at-ropc');
148
+ expect(saved?.user?.username).toBe('lucky');
149
+ });
150
+ it('неверный пароль → RemoteError(AUTH), connected:false, состояние не фиксируется', async () => {
151
+ vi.stubGlobal('fetch', passwordFlowFetchMock({
152
+ tokenStatus: 401,
153
+ tokenBody: { error: 'invalid_grant', error_description: 'Invalid user credentials' },
154
+ }));
155
+ const conn = new RemoteConnection({ credentialsPath: credsPath() });
156
+ const err = await conn.connectByPassword(BACKEND, 'lucky', 'wrong').catch((e) => e);
157
+ expect(err).toBeInstanceOf(RemoteError);
158
+ expect(err.code).toBe('AUTH');
159
+ expect(err.message).toContain('Неверный логин или пароль');
160
+ expect(conn.connected).toBe(false);
161
+ expect(conn.user).toBeNull();
162
+ expect(conn.backendUrl).toBeNull();
163
+ expect(conn.client).toBeNull();
164
+ // credentials не сохраняются при ошибке
165
+ expect(await loadCredentials(BACKEND, credsPath())).toBeNull();
166
+ });
167
+ });
168
+ describe('RemoteConnection.connectWithApiKey', () => {
169
+ let dir;
170
+ beforeEach(async () => {
171
+ dir = await mkdtemp(join(tmpdir(), 'synth-conn-apikey-'));
172
+ });
173
+ afterEach(async () => {
174
+ await rm(dir, { recursive: true, force: true });
175
+ });
176
+ it('успех: connected, user из /auth/status, issuer null (без дискавери)', async () => {
177
+ vi.stubGlobal('fetch', passwordFlowFetchMock());
178
+ const conn = new RemoteConnection({ credentialsPath: join(dir, 'credentials.json') });
179
+ const user = await conn.connectWithApiKey('https://backend.test/', 'api-key-1');
180
+ expect(user).toEqual(SERVER_USER);
181
+ expect(conn.connected).toBe(true);
182
+ expect(conn.backendUrl).toBe(BACKEND);
183
+ expect(conn.client).not.toBeNull();
184
+ expect(conn.user?.username).toBe('lucky');
185
+ expect(conn.issuer).toBeNull();
186
+ expect(await conn.getToken?.()).toBe('api-key-1');
187
+ // api_key-сессия ничего не пишет в credentials (это не OAuth-токен)
188
+ expect(await loadCredentials(BACKEND, join(dir, 'credentials.json'))).toBeNull();
189
+ });
190
+ it('пустой ключ → RemoteError(AUTH)', async () => {
191
+ const conn = new RemoteConnection({});
192
+ const err = await conn.connectWithApiKey(BACKEND, '').catch((e) => e);
193
+ expect(err).toBeInstanceOf(RemoteError);
194
+ expect(err.code).toBe('AUTH');
195
+ expect(conn.connected).toBe(false);
196
+ });
197
+ it('backend не отдаёт профиль (/auth/status без user) → RemoteError(AUTH), состояние не фиксируется', async () => {
198
+ vi.stubGlobal('fetch', vi.fn().mockResolvedValue(jsonResponse({ authenticated: true, oidc_enabled: true, user: null })));
199
+ const conn = new RemoteConnection({});
200
+ const err = await conn.connectWithApiKey(BACKEND, 'api-key-1').catch((e) => e);
201
+ expect(err).toBeInstanceOf(RemoteError);
202
+ expect(err.code).toBe('AUTH');
203
+ expect(conn.connected).toBe(false);
204
+ expect(conn.backendUrl).toBeNull();
205
+ });
206
+ it('backend недоступен (сеть) → RemoteError(AUTH), состояние не фиксируется', async () => {
207
+ vi.stubGlobal('fetch', vi.fn().mockRejectedValue(new TypeError('Failed to fetch')));
208
+ const conn = new RemoteConnection({});
209
+ const err = await conn.connectWithApiKey(BACKEND, 'api-key-1').catch((e) => e);
210
+ expect(err).toBeInstanceOf(RemoteError);
211
+ expect(conn.connected).toBe(false);
212
+ expect(conn.client).toBeNull();
213
+ });
214
+ });
215
+ describe('RemoteConnection.connectFromSaved', () => {
216
+ let dir;
217
+ beforeEach(async () => {
218
+ dir = await mkdtemp(join(tmpdir(), 'synth-conn-saved-'));
219
+ });
220
+ afterEach(async () => {
221
+ await rm(dir, { recursive: true, force: true });
222
+ });
223
+ function credsPath() {
224
+ return join(dir, 'credentials.json');
225
+ }
226
+ function validCreds(overrides = {}) {
227
+ return {
228
+ backendUrl: BACKEND,
229
+ accessToken: 'at-valid',
230
+ refreshToken: 'rt-1',
231
+ expiresAt: new Date(Date.now() + 3_600_000).toISOString(),
232
+ user: { id: 'u-saved', username: 'admin', roles: ['ADMIN'] },
233
+ ...overrides,
234
+ };
235
+ }
236
+ it('без credentials → null, connected:false, fetch не вызывался (нет device flow)', async () => {
237
+ const fetchMock = vi.fn();
238
+ vi.stubGlobal('fetch', fetchMock);
239
+ const conn = new RemoteConnection({ credentialsPath: credsPath() });
240
+ const user = await conn.connectFromSaved(BACKEND);
241
+ expect(user).toBeNull();
242
+ expect(conn.connected).toBe(false);
243
+ expect(conn.user).toBeNull();
244
+ expect(fetchMock).not.toHaveBeenCalled();
245
+ });
246
+ it('валидный accessToken в credentials → connected, user обновлён с /auth/status', async () => {
247
+ await saveCredentials(validCreds(), credsPath());
248
+ vi.stubGlobal('fetch', passwordFlowFetchMock());
249
+ const conn = new RemoteConnection({ credentialsPath: credsPath() });
250
+ const user = await conn.connectFromSaved(BACKEND);
251
+ expect(user?.username).toBe('lucky');
252
+ expect(conn.connected).toBe(true);
253
+ expect(conn.backendUrl).toBe(BACKEND);
254
+ expect(conn.client).not.toBeNull();
255
+ expect(conn.issuer).toBe(ISSUER);
256
+ // токен не обновлялся — в файле остался исходный
257
+ const saved = await loadCredentials(BACKEND, credsPath());
258
+ expect(saved?.accessToken).toBe('at-valid');
259
+ });
260
+ it('протухший accessToken + refreshToken → дискавери + refresh, connected, credentials обновлены', async () => {
261
+ await saveCredentials(validCreds({
262
+ accessToken: 'at-old',
263
+ refreshToken: 'rt-old',
264
+ expiresAt: '2020-01-01T00:00:00.000Z',
265
+ user: { id: 'u-saved', username: 'admin', roles: ['ADMIN'] },
266
+ }), credsPath());
267
+ vi.stubGlobal('fetch', refreshFlowFetchMock());
268
+ const conn = new RemoteConnection({ credentialsPath: credsPath() });
269
+ const user = await conn.connectFromSaved(BACKEND);
270
+ expect(user?.username).toBe('lucky');
271
+ expect(conn.connected).toBe(true);
272
+ expect(conn.issuer).toBe(ISSUER);
273
+ const saved = await loadCredentials(BACKEND, credsPath());
274
+ expect(saved?.accessToken).toBe('at-refreshed');
275
+ expect(saved?.refreshToken).toBe('rt-refreshed');
276
+ });
277
+ it('backendUrl не передан → берёт сохранённые credentials из файла', async () => {
278
+ await saveCredentials(validCreds(), credsPath());
279
+ vi.stubGlobal('fetch', passwordFlowFetchMock());
280
+ const conn = new RemoteConnection({ credentialsPath: credsPath() });
281
+ const user = await conn.connectFromSaved();
282
+ expect(user?.username).toBe('lucky');
283
+ expect(conn.connected).toBe(true);
284
+ expect(conn.backendUrl).toBe(BACKEND);
285
+ });
286
+ it('протух без refreshToken → null, connected:false', async () => {
287
+ await saveCredentials(validCreds({
288
+ accessToken: 'at-old',
289
+ expiresAt: '2020-01-01T00:00:00.000Z',
290
+ refreshToken: undefined,
291
+ }), credsPath());
292
+ const fetchMock = vi.fn();
293
+ vi.stubGlobal('fetch', fetchMock);
294
+ const conn = new RemoteConnection({ credentialsPath: credsPath() });
295
+ const user = await conn.connectFromSaved(BACKEND);
296
+ expect(user).toBeNull();
297
+ expect(conn.connected).toBe(false);
298
+ expect(fetchMock).not.toHaveBeenCalled();
299
+ });
300
+ });
301
+ describe('RemoteConnection.disconnect', () => {
302
+ let dir;
303
+ beforeEach(async () => {
304
+ dir = await mkdtemp(join(tmpdir(), 'synth-conn-disc-'));
305
+ });
306
+ afterEach(async () => {
307
+ await rm(dir, { recursive: true, force: true });
308
+ });
309
+ it('сбрасывает состояние: connected:false, client null, user null, backendUrl null', async () => {
310
+ vi.stubGlobal('fetch', passwordFlowFetchMock());
311
+ const conn = new RemoteConnection({ credentialsPath: join(dir, 'credentials.json') });
312
+ await conn.connectByPassword(BACKEND, 'lucky', 'secret');
313
+ expect(conn.connected).toBe(true);
314
+ conn.disconnect();
315
+ expect(conn.connected).toBe(false);
316
+ expect(conn.client).toBeNull();
317
+ expect(conn.getToken).toBeNull();
318
+ expect(conn.user).toBeNull();
319
+ expect(conn.backendUrl).toBeNull();
320
+ expect(conn.issuer).toBeNull();
321
+ });
322
+ });
323
+ //# sourceMappingURL=connection.test.js.map