t3code-cli 0.11.0 → 0.13.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 (330) hide show
  1. package/README.md +42 -10
  2. package/dist/application.js +2 -2
  3. package/dist/auth.js +1 -1
  4. package/dist/bin.js +85549 -2668
  5. package/dist/cli.js +15 -2
  6. package/dist/config.js +120 -2
  7. package/dist/connection.js +2 -2
  8. package/dist/index.js +1 -1
  9. package/dist/node.js +6 -2
  10. package/dist/orchestration.js +2 -2
  11. package/dist/rolldown-runtime.js +1 -1
  12. package/dist/rpc.js +1 -1
  13. package/dist/runtime.js +2 -2
  14. package/dist/shared.js +23313 -8022
  15. package/dist/src/application/actions.d.ts +25 -0
  16. package/dist/src/application/index.d.ts +3 -3
  17. package/dist/src/application/layer.d.ts +66 -50
  18. package/dist/src/application/model-selection.d.ts +2 -2
  19. package/dist/src/application/models.d.ts +1 -1
  20. package/dist/src/application/project-commands.d.ts +23 -3
  21. package/dist/src/application/projects.d.ts +7 -7
  22. package/dist/src/application/service.d.ts +65 -2
  23. package/dist/src/application/shell-sequence.d.ts +25 -19
  24. package/dist/src/application/terminals.d.ts +8 -8
  25. package/dist/src/application/thread-commands.d.ts +19 -19
  26. package/dist/src/application/thread-update.d.ts +1 -1
  27. package/dist/src/application/thread-wait.d.ts +19 -15
  28. package/dist/src/application/threads.d.ts +134 -108
  29. package/dist/src/auth/error.d.ts +3 -3
  30. package/dist/src/auth/index.d.ts +1 -1
  31. package/dist/src/auth/layer.d.ts +36 -8
  32. package/dist/src/auth/local-base-dir.d.ts +5 -2
  33. package/dist/src/auth/local-origin.d.ts +3 -3
  34. package/dist/src/auth/local-token.d.ts +3 -3
  35. package/dist/src/auth/remote-error.d.ts +3 -0
  36. package/dist/src/auth/service.d.ts +15 -3
  37. package/dist/src/auth/type.d.ts +40 -1
  38. package/dist/src/cli/env/flag.d.ts +2 -0
  39. package/dist/src/cli/env/index.d.ts +2 -0
  40. package/dist/src/cli/env/selection-layer.d.ts +3 -0
  41. package/dist/src/cli/flags.d.ts +2 -0
  42. package/dist/src/cli/format/index.d.ts +1 -0
  43. package/dist/src/cli/format/output.d.ts +12 -0
  44. package/dist/src/cli/index.d.ts +4 -0
  45. package/dist/src/cli/runtime/index.d.ts +1 -0
  46. package/dist/src/cli/runtime/service.d.ts +16 -0
  47. package/dist/src/{scope → cli/scope}/resolve.d.ts +5 -4
  48. package/dist/src/config/config.d.ts +49 -0
  49. package/dist/src/config/credential/cipher-node.d.ts +3 -0
  50. package/dist/src/config/credential/cipher-web.d.ts +3 -0
  51. package/dist/src/config/credential/cipher.d.ts +29 -0
  52. package/dist/src/config/credential/env.d.ts +3 -0
  53. package/dist/src/config/credential/error.d.ts +8 -0
  54. package/dist/src/config/credential/index.d.ts +6 -0
  55. package/dist/src/config/credential/service.d.ts +34 -0
  56. package/dist/src/config/env/env.d.ts +55 -0
  57. package/dist/src/config/env/index.d.ts +2 -0
  58. package/dist/src/{layout/base-dir.d.ts → config/env/layout.d.ts} +0 -1
  59. package/dist/src/config/environment-name/index.d.ts +1 -0
  60. package/dist/src/config/environment-name/name.d.ts +10 -0
  61. package/dist/src/config/error.d.ts +4 -11
  62. package/dist/src/config/index.d.ts +10 -5
  63. package/dist/src/config/keystore/error.d.ts +8 -0
  64. package/dist/src/config/keystore/file.d.ts +9 -0
  65. package/dist/src/config/keystore/index.d.ts +4 -0
  66. package/dist/src/config/keystore/keyring-node.d.ts +4 -0
  67. package/dist/src/config/keystore/service.d.ts +33 -0
  68. package/dist/src/config/paths/index.d.ts +1 -0
  69. package/dist/src/config/paths/paths.d.ts +6 -0
  70. package/dist/src/config/persist/file-mode.d.ts +4 -0
  71. package/dist/src/config/persist/migration.d.ts +68 -0
  72. package/dist/src/config/persist/persist.d.ts +40 -0
  73. package/dist/src/config/persist/schema.d.ts +68 -0
  74. package/dist/src/config/resolve/resolve.d.ts +40 -0
  75. package/dist/src/config/selection/index.d.ts +1 -0
  76. package/dist/src/config/selection/resolve.d.ts +4 -0
  77. package/dist/src/config/selection/service.d.ts +10 -0
  78. package/dist/src/config/types.d.ts +36 -0
  79. package/dist/src/config/url/error.d.ts +10 -0
  80. package/dist/src/config/url/index.d.ts +2 -0
  81. package/dist/src/connection/error.d.ts +3 -1
  82. package/dist/src/connection/index.d.ts +0 -1
  83. package/dist/src/connection/prepared.d.ts +14 -0
  84. package/dist/src/contracts/index.d.ts +1 -1
  85. package/dist/src/domain/error.d.ts +14 -1
  86. package/dist/src/domain/helpers.d.ts +53 -43
  87. package/dist/src/domain/model-config.d.ts +92 -84
  88. package/dist/src/domain/thread-activities.d.ts +1 -1
  89. package/dist/src/domain/thread-lifecycle.d.ts +24 -20
  90. package/dist/src/index.d.ts +1 -2
  91. package/dist/src/{connection/node.d.ts → node/connection.d.ts} +1 -1
  92. package/dist/src/node/index.d.ts +1 -2
  93. package/dist/src/orchestration/index.d.ts +0 -1
  94. package/dist/src/orchestration/layer.d.ts +321 -390
  95. package/dist/src/orchestration/service.d.ts +1 -1
  96. package/dist/src/rpc/error.d.ts +4 -6
  97. package/dist/src/rpc/layer.d.ts +2036 -1917
  98. package/dist/src/rpc/operation.d.ts +4 -5732
  99. package/dist/src/rpc/service.d.ts +1 -1
  100. package/dist/src/rpc/session.d.ts +22 -0
  101. package/dist/src/rpc/ws-group.d.ts +456 -1032
  102. package/dist/src/runtime/index.d.ts +1 -2
  103. package/dist/src/runtime/layer.d.ts +12 -8
  104. package/dist/src/sql/node-sqlite-client.d.ts +1 -1
  105. package/dist/src/t3tools/index.d.ts +1 -1
  106. package/dist/t3tools.js +2 -2
  107. package/package.json +30 -25
  108. package/src/application/actions.test.ts +328 -0
  109. package/src/application/actions.ts +475 -0
  110. package/src/application/index.ts +9 -5
  111. package/src/application/layer.ts +9 -0
  112. package/src/application/model-selection.ts +2 -2
  113. package/src/application/project-commands.ts +23 -5
  114. package/src/application/projects.ts +6 -7
  115. package/src/application/service.ts +79 -1
  116. package/src/application/shell-sequence.ts +1 -1
  117. package/src/application/terminals.ts +2 -1
  118. package/src/application/thread-commands.ts +1 -1
  119. package/src/application/thread-update.ts +1 -1
  120. package/src/application/thread-wait.ts +5 -1
  121. package/src/application/threads.test.ts +9 -3
  122. package/src/application/threads.ts +6 -6
  123. package/src/auth/error.ts +4 -9
  124. package/src/auth/index.ts +7 -0
  125. package/src/auth/layer.test-utils.ts +34 -0
  126. package/src/auth/layer.ts +116 -34
  127. package/src/auth/local-base-dir.ts +13 -6
  128. package/src/auth/local-origin.ts +10 -7
  129. package/src/auth/local-token.ts +28 -23
  130. package/src/auth/remote-error.ts +17 -0
  131. package/src/auth/service.test.ts +200 -0
  132. package/src/auth/service.ts +27 -3
  133. package/src/auth/transport.ts +45 -114
  134. package/src/auth/type.ts +47 -1
  135. package/src/bin.ts +24 -6
  136. package/src/cli/action-format.ts +110 -0
  137. package/src/cli/action.ts +398 -0
  138. package/src/cli/app.ts +6 -0
  139. package/src/cli/auth.ts +76 -23
  140. package/src/cli/env/flag.ts +8 -0
  141. package/src/cli/env/index.ts +2 -0
  142. package/src/cli/env/selection-layer.test.ts +49 -0
  143. package/src/cli/env/selection-layer.ts +27 -0
  144. package/src/cli/env.ts +107 -0
  145. package/src/cli/extra-args.test.ts +32 -0
  146. package/src/cli/extra-args.ts +22 -0
  147. package/src/cli/flags.ts +11 -1
  148. package/src/cli/format/auth.ts +92 -0
  149. package/src/cli/format/human.ts +131 -0
  150. package/src/cli/format/index.ts +12 -0
  151. package/src/cli/format/model.ts +29 -0
  152. package/src/cli/format/output.ts +51 -0
  153. package/src/cli/format/project.ts +32 -0
  154. package/src/cli/format/terminal.ts +87 -0
  155. package/src/cli/{thread-format.test.ts → format/thread.test.ts} +6 -4
  156. package/src/cli/format/thread.ts +185 -0
  157. package/src/cli/index.ts +20 -0
  158. package/src/cli/interaction/confirm.ts +64 -0
  159. package/src/cli/{self-action.ts → interaction/self-action.ts} +8 -6
  160. package/src/cli/message-input.ts +1 -1
  161. package/src/cli/model.ts +9 -5
  162. package/src/cli/project.ts +13 -7
  163. package/src/cli/projects/delete.ts +13 -12
  164. package/src/cli/require.ts +9 -7
  165. package/src/cli/runtime/index.ts +1 -0
  166. package/src/cli/runtime/service.ts +28 -0
  167. package/src/{scope → cli/scope}/resolve.ts +11 -9
  168. package/src/cli/terminal/attach.ts +3 -6
  169. package/src/cli/terminal/create.ts +10 -9
  170. package/src/cli/terminal/destroy.ts +13 -11
  171. package/src/cli/terminal/list.ts +10 -9
  172. package/src/cli/terminal/read.test-utils.ts +48 -0
  173. package/src/cli/terminal/read.test.ts +35 -0
  174. package/src/cli/terminal/read.ts +3 -6
  175. package/src/cli/terminal/scope.ts +10 -5
  176. package/src/cli/terminal/shared.ts +1 -1
  177. package/src/cli/terminal/stream.ts +3 -6
  178. package/src/cli/terminal/wait.test.ts +5 -3
  179. package/src/cli/terminal/wait.ts +10 -9
  180. package/src/cli/terminal/write.test.ts +34 -0
  181. package/src/cli/terminal/write.ts +10 -9
  182. package/src/cli/threads/approve.ts +11 -7
  183. package/src/cli/threads/archive.ts +14 -9
  184. package/src/cli/threads/callback.ts +6 -4
  185. package/src/cli/threads/delete.ts +17 -11
  186. package/src/cli/threads/interrupt.ts +14 -9
  187. package/src/cli/threads/list.test.ts +5 -3
  188. package/src/cli/threads/list.ts +10 -10
  189. package/src/cli/threads/messages.ts +11 -7
  190. package/src/cli/threads/respond.ts +11 -7
  191. package/src/cli/threads/send.ts +19 -9
  192. package/src/cli/threads/show.ts +11 -7
  193. package/src/cli/threads/start.ts +18 -13
  194. package/src/cli/threads/unarchive.ts +11 -7
  195. package/src/cli/threads/update.ts +14 -9
  196. package/src/cli/threads/wait.ts +11 -7
  197. package/src/cli/wait-events.ts +1 -1
  198. package/src/config/config.ts +260 -0
  199. package/src/config/credential/cipher-node.ts +40 -0
  200. package/src/config/credential/cipher-web.ts +82 -0
  201. package/src/config/credential/cipher.ts +39 -0
  202. package/src/config/credential/env.ts +13 -0
  203. package/src/config/credential/error.ts +9 -0
  204. package/src/config/credential/index.ts +6 -0
  205. package/src/config/credential/service.test-utils.ts +25 -0
  206. package/src/config/credential/service.test.ts +116 -0
  207. package/src/config/credential/service.ts +205 -0
  208. package/src/config/env/env.test-utils.ts +14 -0
  209. package/src/config/env/env.ts +81 -0
  210. package/src/config/env/index.ts +2 -0
  211. package/src/{layout/base-dir.ts → config/env/layout.ts} +0 -9
  212. package/src/config/environment-name/index.ts +7 -0
  213. package/src/config/environment-name/name.test.ts +66 -0
  214. package/src/config/environment-name/name.ts +49 -0
  215. package/src/config/error.ts +6 -8
  216. package/src/config/index.ts +16 -5
  217. package/src/config/keystore/error.ts +9 -0
  218. package/src/config/keystore/file.ts +96 -0
  219. package/src/config/keystore/index.ts +4 -0
  220. package/src/config/keystore/keyring-node.test.ts +12 -0
  221. package/src/config/keystore/keyring-node.ts +100 -0
  222. package/src/config/keystore/service.test-utils.ts +15 -0
  223. package/src/config/keystore/service.test.ts +18 -0
  224. package/src/config/keystore/service.ts +29 -0
  225. package/src/config/layer.test-utils.ts +45 -0
  226. package/src/config/layer.test.ts +209 -0
  227. package/src/config/paths/index.ts +1 -0
  228. package/src/config/paths/paths.ts +36 -0
  229. package/src/config/persist/file-mode.ts +21 -0
  230. package/src/config/persist/migration.test.ts +71 -0
  231. package/src/config/persist/migration.ts +82 -0
  232. package/src/config/persist/persist.test.ts +113 -0
  233. package/src/config/persist/persist.ts +65 -0
  234. package/src/config/persist/schema.ts +37 -0
  235. package/src/config/platform.test-utils.ts +20 -0
  236. package/src/config/resolve/resolve.test-utils.ts +20 -0
  237. package/src/config/resolve/resolve.test.ts +137 -0
  238. package/src/config/resolve/resolve.ts +104 -0
  239. package/src/config/selection/index.ts +1 -0
  240. package/src/config/selection/resolve.ts +14 -0
  241. package/src/config/selection/service.ts +29 -0
  242. package/src/config/temp-home.test-utils.ts +7 -0
  243. package/src/config/types.ts +49 -0
  244. package/src/config/url/error.ts +8 -0
  245. package/src/config/url/index.ts +7 -0
  246. package/src/config/url/url.test.ts +31 -0
  247. package/src/connection/error.ts +4 -1
  248. package/src/connection/index.ts +0 -1
  249. package/src/connection/layer.ts +5 -2
  250. package/src/connection/prepared.ts +83 -0
  251. package/src/contracts/index.ts +1 -1
  252. package/src/domain/error.ts +20 -1
  253. package/src/domain/helpers.test.ts +1 -1
  254. package/src/domain/helpers.ts +1 -1
  255. package/src/domain/model-config.ts +1 -1
  256. package/src/domain/thread-activities.test.ts +1 -1
  257. package/src/domain/thread-activities.ts +1 -1
  258. package/src/domain/thread-lifecycle.test.ts +1 -1
  259. package/src/domain/thread-lifecycle.ts +1 -1
  260. package/src/effect.test-utils.ts +25 -0
  261. package/src/index.ts +1 -1
  262. package/src/{connection/node.ts → node/connection.ts} +1 -1
  263. package/src/node/index.ts +1 -2
  264. package/src/orchestration/index.ts +0 -1
  265. package/src/orchestration/layer.ts +3 -2
  266. package/src/orchestration/service.ts +1 -1
  267. package/src/rpc/error.ts +10 -17
  268. package/src/rpc/layer.ts +17 -51
  269. package/src/rpc/operation.ts +16 -2
  270. package/src/rpc/service.ts +2 -1
  271. package/src/rpc/session.ts +168 -0
  272. package/src/rpc/ws-group.ts +13 -27
  273. package/src/runtime/index.ts +2 -1
  274. package/src/runtime/layer.test-utils.ts +32 -0
  275. package/src/runtime/layer.test.ts +66 -0
  276. package/src/runtime/layer.ts +21 -12
  277. package/src/t3tools/index.ts +1 -1
  278. package/src/types/marked-terminal.d.ts +11 -0
  279. package/dist/layout.js +0 -2
  280. package/dist/scope.js +0 -2
  281. package/dist/src/cli/output-format.d.ts +0 -11
  282. package/dist/src/config/layer.d.ts +0 -22
  283. package/dist/src/config/service.d.ts +0 -22
  284. package/dist/src/environment/layer.d.ts +0 -3
  285. package/dist/src/environment/service.d.ts +0 -12
  286. package/dist/src/layout/index.d.ts +0 -1
  287. package/dist/upstream-t3code/packages/contracts/src/auth.d.ts +0 -441
  288. package/dist/upstream-t3code/packages/contracts/src/baseSchemas.d.ts +0 -38
  289. package/dist/upstream-t3code/packages/contracts/src/desktopBootstrap.d.ts +0 -14
  290. package/dist/upstream-t3code/packages/contracts/src/editor.d.ts +0 -124
  291. package/dist/upstream-t3code/packages/contracts/src/environment.d.ts +0 -64
  292. package/dist/upstream-t3code/packages/contracts/src/environmentHttp.d.ts +0 -762
  293. package/dist/upstream-t3code/packages/contracts/src/filesystem.d.ts +0 -26
  294. package/dist/upstream-t3code/packages/contracts/src/git.d.ts +0 -500
  295. package/dist/upstream-t3code/packages/contracts/src/index.d.ts +0 -25
  296. package/dist/upstream-t3code/packages/contracts/src/ipc.d.ts +0 -490
  297. package/dist/upstream-t3code/packages/contracts/src/keybindings.d.ts +0 -133
  298. package/dist/upstream-t3code/packages/contracts/src/model.d.ts +0 -112
  299. package/dist/upstream-t3code/packages/contracts/src/orchestration.d.ts +0 -6682
  300. package/dist/upstream-t3code/packages/contracts/src/project.d.ts +0 -45
  301. package/dist/upstream-t3code/packages/contracts/src/provider.d.ts +0 -116
  302. package/dist/upstream-t3code/packages/contracts/src/providerInstance.d.ts +0 -99
  303. package/dist/upstream-t3code/packages/contracts/src/providerRuntime.d.ts +0 -4276
  304. package/dist/upstream-t3code/packages/contracts/src/relay.d.ts +0 -1262
  305. package/dist/upstream-t3code/packages/contracts/src/relayClient.d.ts +0 -48
  306. package/dist/upstream-t3code/packages/contracts/src/remoteAccess.d.ts +0 -45
  307. package/dist/upstream-t3code/packages/contracts/src/review.d.ts +0 -37
  308. package/dist/upstream-t3code/packages/contracts/src/rpc.d.ts +0 -8218
  309. package/dist/upstream-t3code/packages/contracts/src/server.d.ts +0 -2291
  310. package/dist/upstream-t3code/packages/contracts/src/settings.d.ts +0 -271
  311. package/dist/upstream-t3code/packages/contracts/src/sourceControl.d.ts +0 -177
  312. package/dist/upstream-t3code/packages/contracts/src/terminal.d.ts +0 -330
  313. package/dist/upstream-t3code/packages/contracts/src/vcs.d.ts +0 -148
  314. package/src/cli/auth-format.ts +0 -45
  315. package/src/cli/confirm.ts +0 -31
  316. package/src/cli/model-format.ts +0 -18
  317. package/src/cli/output-format.ts +0 -45
  318. package/src/cli/project-format.ts +0 -18
  319. package/src/cli/terminal/commands.test.ts +0 -101
  320. package/src/cli/terminal-format.ts +0 -167
  321. package/src/cli/thread-format.ts +0 -128
  322. package/src/config/layer.ts +0 -105
  323. package/src/config/service.ts +0 -26
  324. package/src/environment/layer.ts +0 -12
  325. package/src/environment/service.ts +0 -13
  326. package/src/layout/index.ts +0 -1
  327. /package/dist/src/{scope → cli/scope}/index.d.ts +0 -0
  328. /package/dist/src/config/{url.d.ts → url/url.d.ts} +0 -0
  329. /package/src/{scope → cli/scope}/index.ts +0 -0
  330. /package/src/config/{url.ts → url/url.ts} +0 -0
@@ -0,0 +1,29 @@
1
+ import * as Context from "effect/Context";
2
+ import * as Effect from "effect/Effect";
3
+ import * as Layer from "effect/Layer";
4
+ import * as Option from "effect/Option";
5
+
6
+ import { loadT3CliEnv } from "../env/env.ts";
7
+ import { resolveConfiguredEnvironment } from "./resolve.ts";
8
+
9
+ export class T3ConfigSelection extends Context.Service<
10
+ T3ConfigSelection,
11
+ {
12
+ readonly getSelectedEnvironment: () => Effect.Effect<string | undefined>;
13
+ }
14
+ >()("t3cli/T3ConfigSelection") {}
15
+
16
+ export const layer = Layer.effect(
17
+ T3ConfigSelection,
18
+ Effect.gen(function* () {
19
+ const t3CliEnv = yield* loadT3CliEnv;
20
+ return {
21
+ getSelectedEnvironment: () =>
22
+ Effect.sync(() =>
23
+ resolveConfiguredEnvironment({
24
+ t3cliEnv: Option.getOrUndefined(t3CliEnv.t3cliEnv),
25
+ }),
26
+ ),
27
+ };
28
+ }),
29
+ );
@@ -0,0 +1,7 @@
1
+ import * as Effect from "effect/Effect";
2
+ import * as FileSystem from "effect/FileSystem";
3
+
4
+ export const makeTempHomeScoped = Effect.fn("makeTempHomeScoped")(function* (prefix: string) {
5
+ const fs = yield* FileSystem.FileSystem;
6
+ return yield* fs.makeTempDirectoryScoped({ prefix });
7
+ });
@@ -0,0 +1,49 @@
1
+ import type {
2
+ EncryptedToken,
3
+ StoredConfigV2File,
4
+ StoredEnvironmentFile,
5
+ } from "./persist/schema.ts";
6
+
7
+ export type EncryptedEnvironment = StoredEnvironmentFile;
8
+
9
+ export type EncryptedConfig = StoredConfigV2File;
10
+
11
+ export type DecryptedEnvironment = {
12
+ readonly url: string;
13
+ readonly local: boolean;
14
+ readonly token: string;
15
+ };
16
+
17
+ export type DecryptedConfig = {
18
+ readonly version: 2;
19
+ readonly default?: string;
20
+ readonly environments: Readonly<Record<string, DecryptedEnvironment>>;
21
+ };
22
+
23
+ export type EnvironmentSummary = {
24
+ readonly name: string;
25
+ readonly url: string;
26
+ readonly local: boolean;
27
+ readonly default: boolean;
28
+ };
29
+
30
+ export type ResolvedConfig = {
31
+ readonly url: string;
32
+ readonly token: string;
33
+ readonly source: "env" | "config";
34
+ readonly local: boolean;
35
+ readonly environment?: string;
36
+ };
37
+
38
+ export type UpsertEnvironmentInput = {
39
+ readonly name: string;
40
+ readonly url: string;
41
+ readonly token: string;
42
+ readonly local: boolean;
43
+ readonly makeDefault?: boolean;
44
+ };
45
+
46
+ export type StoredConfig = DecryptedConfig;
47
+ export type StoredEnvironment = DecryptedEnvironment;
48
+
49
+ export type { EncryptedToken };
@@ -0,0 +1,8 @@
1
+ import * as Cause from "effect/Cause";
2
+ import * as Schema from "effect/Schema";
3
+
4
+ export class UrlError extends Schema.TaggedErrorClass<UrlError>()("UrlError", {
5
+ message: Schema.String,
6
+ protocol: Schema.optionalKey(Schema.String),
7
+ cause: Schema.optionalKey(Schema.instanceOf(Cause.IllegalArgumentError)),
8
+ }) {}
@@ -0,0 +1,7 @@
1
+ export {
2
+ normalizeHttpBaseUrl,
3
+ toWebSocketBaseUrl,
4
+ toHttpEndpointUrl,
5
+ toWebSocketEndpointUrl,
6
+ } from "./url.ts";
7
+ export { UrlError } from "./error.ts";
@@ -0,0 +1,31 @@
1
+ import "vite-plus/test/config";
2
+
3
+ import * as Effect from "effect/Effect";
4
+ import { assert, describe, it } from "@effect/vitest";
5
+
6
+ import { expectFailWithMessage } from "../../effect.test-utils.ts";
7
+ import { UrlError } from "./error.ts";
8
+ import { normalizeHttpBaseUrl, toWebSocketEndpointUrl } from "./url.ts";
9
+
10
+ describe("normalizeHttpBaseUrl", () => {
11
+ it.effect("strips query and trailing slash from urls with paths", () =>
12
+ Effect.gen(function* () {
13
+ const normalized = yield* normalizeHttpBaseUrl("https://app.example.com/api/?q=1");
14
+ assert.equal(normalized, "https://app.example.com/api");
15
+ }),
16
+ );
17
+
18
+ it.effect("maps invalid urls to UrlError", () =>
19
+ expectFailWithMessage(normalizeHttpBaseUrl("not-a-url"), UrlError, "invalid url"),
20
+ );
21
+ });
22
+
23
+ describe("toWebSocketEndpointUrl", () => {
24
+ it.effect("rejects unsupported protocols with UrlError", () =>
25
+ expectFailWithMessage(
26
+ toWebSocketEndpointUrl("ftp://example.com", "/ws"),
27
+ UrlError,
28
+ "unsupported server url protocol: ftp:",
29
+ ),
30
+ );
31
+ });
@@ -1,9 +1,12 @@
1
1
  import * as Schema from "effect/Schema";
2
2
 
3
+ import { ConfigError } from "../config/error.ts";
4
+ import { UrlError } from "../config/url/error.ts";
5
+
3
6
  export class T3CodeConnectionError extends Schema.TaggedErrorClass<T3CodeConnectionError>()(
4
7
  "T3CodeConnectionError",
5
8
  {
6
9
  message: Schema.String,
7
- cause: Schema.optionalKey(Schema.Unknown),
10
+ cause: Schema.Union([ConfigError, UrlError]),
8
11
  },
9
12
  ) {}
@@ -1,6 +1,5 @@
1
1
  export { T3CodeConnectionError } from "./error.ts";
2
2
  export { T3CodeRpcLayer, makeT3CodeRpcLayer } from "./layer.ts";
3
- export { T3CodeNodeRpcLayer } from "./node.ts";
4
3
  export {
5
4
  T3CodeConnectionProvider,
6
5
  T3CodeConnectionProviderLive,
@@ -1,10 +1,13 @@
1
1
  import * as Layer from "effect/Layer";
2
2
 
3
- import { T3AuthTransportLive } from "../auth/transport.ts";
3
+ import { T3PreparedConnectionProviderLive } from "./prepared.ts";
4
4
  import { T3RpcLive } from "../rpc/layer.ts";
5
+ import { T3RpcSessionFactoryLive } from "../rpc/session.ts";
5
6
 
6
7
  export function makeT3CodeRpcLayer() {
7
- return T3RpcLive.pipe(Layer.provide(T3AuthTransportLive));
8
+ return T3RpcLive.pipe(
9
+ Layer.provide(Layer.mergeAll(T3PreparedConnectionProviderLive, T3RpcSessionFactoryLive)),
10
+ );
8
11
  }
9
12
 
10
13
  export const T3CodeRpcLayer = makeT3CodeRpcLayer();
@@ -0,0 +1,83 @@
1
+ import { resolveRemoteWebSocketConnectionUrl } from "@t3tools/client-runtime/authorization";
2
+ import {
3
+ BearerConnectionTarget,
4
+ type ConnectionAttemptError,
5
+ mapRemoteEnvironmentError,
6
+ type PreparedConnection,
7
+ } from "@t3tools/client-runtime/connection";
8
+ import { fetchRemoteEnvironmentDescriptor } from "@t3tools/client-runtime/environment";
9
+ import * as Context from "effect/Context";
10
+ import * as Effect from "effect/Effect";
11
+ import * as Layer from "effect/Layer";
12
+ import { HttpClient } from "effect/unstable/http";
13
+
14
+ import { toWebSocketEndpointUrl } from "../config/url/url.ts";
15
+ import { T3CodeConnectionError } from "./error.ts";
16
+ import { T3CodeConnectionProvider } from "./service.ts";
17
+ import type { T3CodeConnection } from "./type.ts";
18
+
19
+ export class T3PreparedConnectionProvider extends Context.Service<
20
+ T3PreparedConnectionProvider,
21
+ {
22
+ readonly get: Effect.Effect<PreparedConnection, ConnectionAttemptError | T3CodeConnectionError>;
23
+ }
24
+ >()("t3cli/T3PreparedConnectionProvider") {}
25
+
26
+ const makePreparedConnection = Effect.fn("makePreparedConnection")(function* (
27
+ connection: T3CodeConnection,
28
+ ) {
29
+ const httpBaseUrl = connection.origin.url;
30
+ const wsBaseUrl = yield* toWebSocketEndpointUrl(httpBaseUrl, "/ws").pipe(
31
+ Effect.mapError(
32
+ (error) =>
33
+ new T3CodeConnectionError({
34
+ message: "failed to resolve websocket endpoint",
35
+ cause: error,
36
+ }),
37
+ ),
38
+ );
39
+ const descriptor = yield* fetchRemoteEnvironmentDescriptor({ httpBaseUrl }).pipe(
40
+ Effect.mapError(mapRemoteEnvironmentError),
41
+ );
42
+ const socketUrl = yield* resolveRemoteWebSocketConnectionUrl({
43
+ httpBaseUrl,
44
+ wsBaseUrl,
45
+ bearerToken: connection.auth.token,
46
+ }).pipe(Effect.mapError(mapRemoteEnvironmentError));
47
+
48
+ return {
49
+ environmentId: descriptor.environmentId,
50
+ label: descriptor.label,
51
+ httpBaseUrl,
52
+ socketUrl,
53
+ httpAuthorization: {
54
+ _tag: "Bearer",
55
+ token: connection.auth.token,
56
+ },
57
+ target: new BearerConnectionTarget({
58
+ environmentId: descriptor.environmentId,
59
+ label: descriptor.label,
60
+ connectionId: descriptor.environmentId,
61
+ }),
62
+ } satisfies PreparedConnection;
63
+ });
64
+
65
+ const makeT3PreparedConnectionProvider = Effect.fn("makeT3PreparedConnectionProvider")(
66
+ function* () {
67
+ const connectionProvider = yield* T3CodeConnectionProvider;
68
+ const httpClient = yield* HttpClient.HttpClient;
69
+ const get = connectionProvider.get.pipe(
70
+ Effect.flatMap((connection) =>
71
+ makePreparedConnection(connection).pipe(
72
+ Effect.provideService(HttpClient.HttpClient, httpClient),
73
+ ),
74
+ ),
75
+ );
76
+ return T3PreparedConnectionProvider.of({ get });
77
+ },
78
+ );
79
+
80
+ export const T3PreparedConnectionProviderLive = Layer.effect(
81
+ T3PreparedConnectionProvider,
82
+ makeT3PreparedConnectionProvider(),
83
+ );
@@ -5,4 +5,4 @@ export type {
5
5
  OrchestrationThread,
6
6
  OrchestrationThreadShell,
7
7
  ServerProvider,
8
- } from "#t3tools/contracts";
8
+ } from "@t3tools/contracts";
@@ -55,6 +55,23 @@ export class TerminalLookupError extends Schema.TaggedErrorClass<TerminalLookupE
55
55
  },
56
56
  ) {}
57
57
 
58
+ export class ProjectActionLookupError extends Schema.TaggedErrorClass<ProjectActionLookupError>()(
59
+ "ProjectActionLookupError",
60
+ {
61
+ message: Schema.String,
62
+ projectId: Schema.String,
63
+ selector: Schema.String,
64
+ },
65
+ ) {}
66
+
67
+ export class ProjectActionValidationError extends Schema.TaggedErrorClass<ProjectActionValidationError>()(
68
+ "ProjectActionValidationError",
69
+ {
70
+ message: Schema.String,
71
+ projectId: Schema.String,
72
+ },
73
+ ) {}
74
+
58
75
  export type DomainError =
59
76
  | ProjectLookupError
60
77
  | ModelSelectionError
@@ -62,4 +79,6 @@ export type DomainError =
62
79
  | ThreadSessionError
63
80
  | ThreadLookupError
64
81
  | ProjectCreateVisibilityError
65
- | TerminalLookupError;
82
+ | TerminalLookupError
83
+ | ProjectActionLookupError
84
+ | ProjectActionValidationError;
@@ -5,7 +5,7 @@ import * as NodeServices from "@effect/platform-node/NodeServices";
5
5
  import { assert, describe, it } from "@effect/vitest";
6
6
  import { fromPartial } from "@total-typescript/shoehorn";
7
7
 
8
- import type { OrchestrationShellSnapshot } from "#t3tools/contracts";
8
+ import type { OrchestrationShellSnapshot } from "@t3tools/contracts";
9
9
 
10
10
  import { resolveProjectScope } from "./helpers.ts";
11
11
 
@@ -1,6 +1,6 @@
1
1
  import * as Effect from "effect/Effect";
2
2
  import * as Path from "effect/Path";
3
- import type { OrchestrationProjectShell, OrchestrationShellSnapshot } from "#t3tools/contracts";
3
+ import type { OrchestrationProjectShell, OrchestrationShellSnapshot } from "@t3tools/contracts";
4
4
 
5
5
  export type ResolvedProjectScope = {
6
6
  readonly project: OrchestrationProjectShell;
@@ -1,4 +1,4 @@
1
- import type { ServerProvider } from "#t3tools/contracts";
1
+ import type { ServerProvider } from "@t3tools/contracts";
2
2
 
3
3
  export function isSelectableProvider(provider: ServerProvider) {
4
4
  return provider.status === "ready" && provider.models.length > 0;
@@ -1,6 +1,6 @@
1
1
  import "vite-plus/test/config";
2
2
 
3
- import { EventId, TurnId, type OrchestrationThreadActivity } from "#t3tools/contracts";
3
+ import { EventId, TurnId, type OrchestrationThreadActivity } from "@t3tools/contracts";
4
4
  import { describe, expect, it } from "vite-plus/test";
5
5
 
6
6
  import { derivePendingApprovals, derivePendingUserInputs } from "./thread-activities.ts";
@@ -2,7 +2,7 @@ import {
2
2
  ApprovalRequestId,
3
3
  type OrchestrationThreadActivity,
4
4
  type UserInputQuestion,
5
- } from "#t3tools/contracts";
5
+ } from "@t3tools/contracts";
6
6
 
7
7
  export type PendingApproval = {
8
8
  readonly requestId: ApprovalRequestId;
@@ -3,7 +3,7 @@ import "vite-plus/test/config";
3
3
  import { describe, expect, it } from "vite-plus/test";
4
4
  import { fromPartial } from "@total-typescript/shoehorn";
5
5
 
6
- import type { OrchestrationThread } from "#t3tools/contracts";
6
+ import type { OrchestrationThread } from "@t3tools/contracts";
7
7
 
8
8
  import { isThreadActive, isThreadCompleteEnough } from "./thread-lifecycle.ts";
9
9
 
@@ -5,7 +5,7 @@ import {
5
5
  type OrchestrationSession,
6
6
  type OrchestrationThread,
7
7
  type OrchestrationThreadShell,
8
- } from "#t3tools/contracts";
8
+ } from "@t3tools/contracts";
9
9
  import * as Schema from "effect/Schema";
10
10
 
11
11
  type SessionStatusForDelete = OrchestrationSession["status"] | "closed";
@@ -0,0 +1,25 @@
1
+ import { assert } from "@effect/vitest";
2
+ import { assertInstanceOf } from "@effect/vitest/utils";
3
+ import * as Cause from "effect/Cause";
4
+ import * as Effect from "effect/Effect";
5
+ import * as Exit from "effect/Exit";
6
+ import * as Option from "effect/Option";
7
+
8
+ export const expectFailWithMessage = <E extends { readonly message: string }, R>(
9
+ effect: Effect.Effect<unknown, E, R>,
10
+ ErrorClass: new (...args: never) => E,
11
+ message: string,
12
+ ): Effect.Effect<void, never, R> =>
13
+ Effect.gen(function* () {
14
+ const exit = yield* effect.pipe(Effect.exit);
15
+ if (!Exit.isFailure(exit)) {
16
+ return yield* Effect.die("expected failure");
17
+ }
18
+ const error = Cause.findErrorOption(exit.cause);
19
+ if (Option.isNone(error)) {
20
+ return yield* Effect.die("expected failure cause");
21
+ }
22
+ assertInstanceOf(error.value, ErrorClass);
23
+ assert.equal(error.value.message, message);
24
+ return yield* Effect.void;
25
+ });
package/src/index.ts CHANGED
@@ -4,6 +4,6 @@ export type {
4
4
  StartThreadInput,
5
5
  StartThreadPolicy,
6
6
  WaitEvent,
7
+ ApplicationError,
7
8
  } from "./application/index.ts";
8
- export type { ApplicationError } from "./application/index.ts";
9
9
  export { AppLayer, AuthAppLayer } from "./runtime/index.ts";
@@ -2,7 +2,7 @@ import * as Layer from "effect/Layer";
2
2
  import * as NodeHttpClient from "@effect/platform-node/NodeHttpClient";
3
3
  import * as NodeSocket from "@effect/platform-node/NodeSocket";
4
4
 
5
- import { T3CodeRpcLayer } from "./layer.ts";
5
+ import { T3CodeRpcLayer } from "../connection/index.ts";
6
6
 
7
7
  const NodeConnectionPlatformLayer = Layer.mergeAll(
8
8
  NodeHttpClient.layerUndici,
package/src/node/index.ts CHANGED
@@ -1,2 +1 @@
1
- export { T3CodeNodeRpcLayer } from "../connection/node.ts";
2
- export { NodeEnvironmentLive } from "../environment/layer.ts";
1
+ export { T3CodeNodeRpcLayer } from "./connection.ts";
@@ -5,4 +5,3 @@ export {
5
5
  type OrchestrationError,
6
6
  } from "./service.ts";
7
7
  export { makeT3Orchestration, T3OrchestrationLive } from "./layer.ts";
8
- export { T3OrchestrationLayer } from "../runtime/layer.ts";
@@ -10,7 +10,7 @@ import {
10
10
  type ClientOrchestrationCommand,
11
11
  type OrchestrationShellStreamItem,
12
12
  type OrchestrationThreadStreamItem,
13
- } from "#t3tools/contracts";
13
+ } from "@t3tools/contracts";
14
14
 
15
15
  import { RpcError } from "../rpc/error.ts";
16
16
  import { T3RpcOperations } from "../rpc/operation.ts";
@@ -25,7 +25,8 @@ export const makeT3Orchestration = Effect.fn("makeT3Orchestration")(function* ()
25
25
  client[ORCHESTRATION_WS_METHODS.subscribeShell]({}),
26
26
  )
27
27
  .pipe(
28
- Stream.map((item: OrchestrationShellStreamItem) =>
28
+ Stream.filter((item: OrchestrationShellStreamItem) => item.kind !== "synchronized"),
29
+ Stream.map((item) =>
29
30
  item.kind === "snapshot" ? item.snapshot.snapshotSequence : item.sequence,
30
31
  ),
31
32
  );
@@ -10,7 +10,7 @@ import type {
10
10
  OrchestrationThread,
11
11
  OrchestrationThreadStreamItem,
12
12
  ServerProviders,
13
- } from "#t3tools/contracts";
13
+ } from "@t3tools/contracts";
14
14
 
15
15
  import type { RpcError } from "../rpc/error.ts";
16
16
 
package/src/rpc/error.ts CHANGED
@@ -1,21 +1,19 @@
1
- import * as Schema from "effect/Schema";
1
+ import {
2
+ ConnectionBlockedError,
3
+ ConnectionTransientError,
4
+ } from "@t3tools/client-runtime/connection";
2
5
  import {
3
6
  EnvironmentAuthorizationError,
4
7
  KeybindingsConfigError,
5
8
  OrchestrationDispatchCommandError,
6
9
  OrchestrationGetSnapshotError,
7
10
  ServerSettingsError,
8
- TerminalCwdError,
9
- TerminalHistoryError,
10
- TerminalNotRunningError,
11
- TerminalSessionLookupError,
12
- } from "#t3tools/contracts";
13
- import { HttpClientError } from "effect/unstable/http";
11
+ TerminalError,
12
+ } from "@t3tools/contracts";
13
+ import * as Schema from "effect/Schema";
14
14
  import { RpcClientError } from "effect/unstable/rpc";
15
15
 
16
- import { AuthTransportError } from "../auth/error.ts";
17
16
  import { T3CodeConnectionError } from "../connection/error.ts";
18
- import { UrlError } from "../config/error.ts";
19
17
 
20
18
  const RpcErrorCauseSchema = Schema.Union([
21
19
  RpcClientError.RpcClientError,
@@ -24,15 +22,10 @@ const RpcErrorCauseSchema = Schema.Union([
24
22
  OrchestrationDispatchCommandError,
25
23
  OrchestrationGetSnapshotError,
26
24
  ServerSettingsError,
27
- TerminalCwdError,
28
- TerminalHistoryError,
29
- TerminalNotRunningError,
30
- TerminalSessionLookupError,
31
- AuthTransportError,
25
+ TerminalError,
26
+ ConnectionBlockedError,
27
+ ConnectionTransientError,
32
28
  T3CodeConnectionError,
33
- HttpClientError.HttpClientErrorSchema,
34
- UrlError,
35
- Schema.instanceOf(Schema.SchemaError),
36
29
  ]);
37
30
 
38
31
  export type RpcKnownCause = Schema.Schema.Type<typeof RpcErrorCauseSchema>;
package/src/rpc/layer.ts CHANGED
@@ -3,22 +3,22 @@ import * as Effect from "effect/Effect";
3
3
  import * as Exit from "effect/Exit";
4
4
  import * as Layer from "effect/Layer";
5
5
  import * as Option from "effect/Option";
6
+ import * as Predicate from "effect/Predicate";
6
7
  import * as Schedule from "effect/Schedule";
7
8
  import * as Scope from "effect/Scope";
8
9
  import * as SynchronizedRef from "effect/SynchronizedRef";
9
- import { HttpClientRequest } from "effect/unstable/http";
10
- import { RpcClient, RpcSerialization } from "effect/unstable/rpc";
11
- import * as Socket from "effect/unstable/socket/Socket";
12
10
 
13
- import { T3AuthTransport } from "../auth/transport.ts";
14
- import { T3CodeConnectionProvider } from "../connection/service.ts";
15
- import { normalizeHttpBaseUrl, toWebSocketEndpointUrl } from "../config/url.ts";
16
- import { CliWsRpcGroup } from "./ws-group.ts";
11
+ import { T3PreparedConnectionProvider } from "../connection/prepared.ts";
17
12
  import { RpcError } from "./error.ts";
13
+ import { T3RpcSessionFactory } from "./session.ts";
18
14
  import { T3Rpc, type WsClient } from "./service.ts";
19
15
 
20
- const makeClient = RpcClient.make(CliWsRpcGroup);
21
- const connectionRetrySchedule = Schedule.exponential("100 millis").pipe(Schedule.take(4));
16
+ const connectionRetrySchedule = Schedule.exponential("100 millis").pipe(
17
+ Schedule.take(4),
18
+ Schedule.collectWhile((metadata: Schedule.Metadata) =>
19
+ Predicate.isTagged(metadata.input, "ConnectionTransientError"),
20
+ ),
21
+ );
22
22
 
23
23
  type Connection = {
24
24
  readonly scope: Scope.Closeable;
@@ -26,23 +26,19 @@ type Connection = {
26
26
  };
27
27
 
28
28
  export const makeT3RpcLayer = Effect.fn("makeT3RpcLayer")(function* () {
29
- const connectionProvider = yield* T3CodeConnectionProvider;
30
- const authTransport = yield* T3AuthTransport;
31
- const webSocketConstructor = yield* Socket.WebSocketConstructor;
29
+ const preparedConnectionProvider = yield* T3PreparedConnectionProvider;
30
+ const sessions = yield* T3RpcSessionFactory;
32
31
  const parentScope = yield* Scope.Scope;
33
32
  const connection = yield* SynchronizedRef.make(Option.none<Connection>());
34
33
  const openConnection = Effect.fn("T3RpcLive.openConnection")(function* () {
35
34
  const scope = yield* Scope.fork(parentScope);
36
35
  return yield* Effect.gen(function* () {
37
- const url = yield* makeWsUrl({ authTransport, connectionProvider });
38
- const protocol = yield* Layer.buildWithScope(
39
- makeProtocolLayer(url, webSocketConstructor),
40
- scope,
41
- );
42
- const client = yield* makeClient.pipe(
43
- Effect.provide(protocol),
44
- Effect.provideService(Scope.Scope, scope),
45
- );
36
+ const prepared = yield* preparedConnectionProvider.get;
37
+ const session = yield* sessions
38
+ .connect(prepared)
39
+ .pipe(Effect.provideService(Scope.Scope, scope));
40
+ yield* session.ready;
41
+ const client: WsClient = session.client;
46
42
  return { scope, client } satisfies Connection;
47
43
  }).pipe(
48
44
  Effect.retry(connectionRetrySchedule),
@@ -74,36 +70,6 @@ export const makeT3RpcLayer = Effect.fn("makeT3RpcLayer")(function* () {
74
70
  };
75
71
  });
76
72
 
77
- const makeWsUrl = Effect.fn("makeWsUrl")(function* (input: {
78
- readonly authTransport: T3AuthTransport["Service"];
79
- readonly connectionProvider: T3CodeConnectionProvider["Service"];
80
- }) {
81
- const connection = yield* input.connectionProvider.get;
82
- const origin = yield* normalizeHttpBaseUrl(connection.origin.url);
83
- const wsTicket = yield* input.authTransport.issueWebSocketTicket({
84
- url: origin,
85
- token: connection.auth.token,
86
- });
87
- const wsUrl = yield* toWebSocketEndpointUrl(origin, "/ws");
88
- const request = HttpClientRequest.get(wsUrl).pipe(
89
- HttpClientRequest.setUrlParam("wsTicket", wsTicket.ticket),
90
- );
91
- return Option.getOrThrow(HttpClientRequest.toUrl(request)).toString();
92
- });
93
-
94
- function makeProtocolLayer(
95
- url: string,
96
- webSocketConstructor: Socket.WebSocketConstructor["Service"],
97
- ) {
98
- const socketLayer = Socket.layerWebSocket(url).pipe(
99
- Layer.provide(Layer.succeed(Socket.WebSocketConstructor, webSocketConstructor)),
100
- );
101
- return RpcClient.layerProtocolSocket({ retryTransientErrors: true }).pipe(
102
- Layer.provide(socketLayer),
103
- Layer.provide(RpcSerialization.layerJson),
104
- );
105
- }
106
-
107
73
  export const T3RpcLive = Layer.effectContext(
108
74
  makeT3RpcLayer().pipe(Effect.map((rpc) => Context.make(T3Rpc, rpc))),
109
75
  );
@@ -1,3 +1,11 @@
1
+ import type {
2
+ EnvironmentAuthorizationError,
3
+ KeybindingsConfigError,
4
+ OrchestrationDispatchCommandError,
5
+ OrchestrationGetSnapshotError,
6
+ ServerSettingsError,
7
+ TerminalError,
8
+ } from "@t3tools/contracts";
1
9
  import * as Context from "effect/Context";
2
10
  import * as Effect from "effect/Effect";
3
11
  import * as Layer from "effect/Layer";
@@ -8,9 +16,15 @@ import { RpcClientError } from "effect/unstable/rpc";
8
16
 
9
17
  import { RpcError } from "./error.ts";
10
18
  import { T3Rpc, type WsClient } from "./service.ts";
11
- import type { CliRpcRequestError } from "./ws-group.ts";
12
19
 
13
- export type CliRpcOperationError = CliRpcRequestError | RpcClientError.RpcClientError;
20
+ export type CliRpcOperationError =
21
+ | EnvironmentAuthorizationError
22
+ | KeybindingsConfigError
23
+ | OrchestrationDispatchCommandError
24
+ | OrchestrationGetSnapshotError
25
+ | RpcClientError.RpcClientError
26
+ | ServerSettingsError
27
+ | TerminalError;
14
28
 
15
29
  export const rpcRetrySchedule = Schedule.exponential("100 millis").pipe(
16
30
  Schedule.take(4),
@@ -1,8 +1,9 @@
1
1
  import * as Context from "effect/Context";
2
2
  import type * as Effect from "effect/Effect";
3
3
  import type { RpcClient, RpcClientError } from "effect/unstable/rpc";
4
- import type { CliWsRpcGroup } from "./ws-group.ts";
4
+
5
5
  import type { RpcError } from "./error.ts";
6
+ import type { CliWsRpcGroup } from "./ws-group.ts";
6
7
 
7
8
  export type WsClient = RpcClient.FromGroup<typeof CliWsRpcGroup, RpcClientError.RpcClientError>;
8
9