authorgravatar for julius0216@outlook.comJulius Marminge <julius0216@outlook.com> 2026-05-13 21:35:01+02:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2026-05-13 21:35:01+02:00
logf92e1e1b06ec5ba78ce66849cf288a3a45e54bb0
treed360353895b6da02c850b9a58b30c522c9b5ba9c
parent556c42452c5ac94ae8d8698d64fcd372c1680955
signature Signed by PGP key B5690EEEBB952194

Simplify workspace package builds and deps (#2676)


16 files changed, 106 insertions(+), 130 deletions(-)

apps/desktop/package.json+4-6
......@@ -16,6 +16,10 @@
1616 },
1717 "dependencies": {
1818 "@effect/platform-node": "catalog:",
19 "@t3tools/contracts": "workspace:*",
20 "@t3tools/shared": "workspace:*",
21 "@t3tools/ssh": "workspace:*",
22 "@t3tools/tailscale": "workspace:*",
1923 "effect": "catalog:",
2024 "electron": "41.5.0",
2125 "electron-updater": "^6.6.2"
......@@ -23,13 +27,7 @@
2327 "devDependencies": {
2428 "@effect/language-service": "catalog:",
2529 "@effect/vitest": "catalog:",
26 "@t3tools/client-runtime": "workspace:*",
27 "@t3tools/contracts": "workspace:*",
28 "@t3tools/shared": "workspace:*",
29 "@t3tools/ssh": "workspace:*",
30 "@t3tools/tailscale": "workspace:*",
3130 "@types/node": "catalog:",
32 "effect-acp": "workspace:*",
3331 "tsdown": "catalog:",
3432 "typescript": "catalog:",
3533 "vitest": "catalog:"
apps/desktop/src/backend/DesktopServerExposure.ts+1-1
......@@ -3,7 +3,7 @@ import * as NodeOS from "node:os";
33import {
44 createAdvertisedEndpoint,
55 type CreateAdvertisedEndpointInput,
6} from "@t3tools/client-runtime";
6} from "@t3tools/shared/advertisedEndpoint";
77import type {
88 AdvertisedEndpoint,
99 AdvertisedEndpointProvider,
apps/desktop/src/backend/tailscaleEndpointProvider.ts+1-1
......@@ -1,4 +1,4 @@
1import { createAdvertisedEndpoint } from "@t3tools/client-runtime";
1import { createAdvertisedEndpoint } from "@t3tools/shared/advertisedEndpoint";
22import type { AdvertisedEndpoint, AdvertisedEndpointProvider } from "@t3tools/contracts";
33import {
44 buildTailscaleHttpsBaseUrl,
apps/desktop/tsdown.config.ts+1-1
......@@ -12,7 +12,7 @@ export default defineConfig([
1212 ...shared,
1313 entry: ["src/main.ts"],
1414 clean: true,
15 noExternal: (id) => id.startsWith("@t3tools/") || id.startsWith("effect-acp"),
15 noExternal: (id) => id.startsWith("@t3tools/"),
1616 },
1717 {
1818 ...shared,
apps/server/package.json+2-2
......@@ -20,13 +20,13 @@
2020 "build:bundle": "tsdown",
2121 "start": "node dist/bin.mjs",
2222 "typecheck": "tsc --noEmit",
23 "test": "vitest run",
24 "test:process-reaper": "vitest run src/server.test.ts src/provider/Layers/ClaudeAdapter.test.ts src/provider/Layers/ProviderSessionDirectory.test.ts src/provider/Layers/ProviderSessionReaper.test.ts src/provider/Layers/CodexAdapter.test.ts"
23 "test": "vitest run"
2524 },
2625 "dependencies": {
2726 "@anthropic-ai/claude-agent-sdk": "^0.2.111",
2827 "@effect/platform-bun": "catalog:",
2928 "@effect/platform-node": "catalog:",
29 "@effect/platform-node-shared": "catalog:",
3030 "@effect/sql-sqlite-bun": "catalog:",
3131 "@opencode-ai/sdk": "^1.3.15",
3232 "@pierre/diffs": "catalog:",
apps/server/tsdown.config.ts+3-5
......@@ -1,15 +1,13 @@
11import { defineConfig } from "tsdown";
22
3const internalPackagePrefixes = ["@t3tools/", "effect-acp", "effect-codex-app-server"];
4
35export default defineConfig({
46 entry: ["src/bin.ts"],
5 format: ["esm", "cjs"],
6 checks: {
7 legacyCjs: false,
8 },
97 outDir: "dist",
108 sourcemap: true,
119 clean: true,
12 noExternal: (id) => id.startsWith("@t3tools/") || id.startsWith("effect-acp"),
10 noExternal: (id) => internalPackagePrefixes.some((prefix) => id.startsWith(prefix)),
1311 inlineOnly: false,
1412 banner: {
1513 js: "#!/usr/bin/env node\n",
bun.lock+5-13
......@@ -20,6 +20,10 @@
2020 "version": "0.0.23",
2121 "dependencies": {
2222 "@effect/platform-node": "catalog:",
23 "@t3tools/contracts": "workspace:*",
24 "@t3tools/shared": "workspace:*",
25 "@t3tools/ssh": "workspace:*",
26 "@t3tools/tailscale": "workspace:*",
2327 "effect": "catalog:",
2428 "electron": "41.5.0",
2529 "electron-updater": "^6.6.2",
......@@ -27,13 +31,7 @@
2731 "devDependencies": {
2832 "@effect/language-service": "catalog:",
2933 "@effect/vitest": "catalog:",
30 "@t3tools/client-runtime": "workspace:*",
31 "@t3tools/contracts": "workspace:*",
32 "@t3tools/shared": "workspace:*",
33 "@t3tools/ssh": "workspace:*",
34 "@t3tools/tailscale": "workspace:*",
3534 "@types/node": "catalog:",
36 "effect-acp": "workspace:*",
3735 "tsdown": "catalog:",
3836 "typescript": "catalog:",
3937 "vitest": "catalog:",
......@@ -60,6 +58,7 @@
6058 "@anthropic-ai/claude-agent-sdk": "^0.2.111",
6159 "@effect/platform-bun": "catalog:",
6260 "@effect/platform-node": "catalog:",
61 "@effect/platform-node-shared": "catalog:",
6362 "@effect/sql-sqlite-bun": "catalog:",
6463 "@opencode-ai/sdk": "^1.3.15",
6564 "@pierre/diffs": "catalog:",
......@@ -153,7 +152,6 @@
153152 },
154153 "packages/client-runtime": {
155154 "name": "@t3tools/client-runtime",
156 "version": "0.0.0-alpha.1",
157155 "dependencies": {
158156 "@t3tools/contracts": "workspace:*",
159157 "effect": "catalog:",
......@@ -173,7 +171,6 @@
173171 "devDependencies": {
174172 "@effect/language-service": "catalog:",
175173 "@effect/vitest": "catalog:",
176 "tsdown": "catalog:",
177174 "typescript": "catalog:",
178175 "vitest": "catalog:",
179176 },
......@@ -188,7 +185,6 @@
188185 "@effect/openapi-generator": "catalog:",
189186 "@effect/platform-node": "catalog:",
190187 "@effect/vitest": "catalog:",
191 "tsdown": "catalog:",
192188 "typescript": "catalog:",
193189 "vitest": "catalog:",
194190 },
......@@ -203,14 +199,12 @@
203199 "@effect/openapi-generator": "catalog:",
204200 "@effect/platform-node": "catalog:",
205201 "@effect/vitest": "catalog:",
206 "tsdown": "catalog:",
207202 "typescript": "catalog:",
208203 "vitest": "catalog:",
209204 },
210205 },
211206 "packages/shared": {
212207 "name": "@t3tools/shared",
213 "version": "0.0.0-alpha.1",
214208 "dependencies": {
215209 "@t3tools/contracts": "workspace:*",
216210 "effect": "catalog:",
......@@ -226,7 +220,6 @@
226220 },
227221 "packages/ssh": {
228222 "name": "@t3tools/ssh",
229 "version": "0.0.0-alpha.1",
230223 "dependencies": {
231224 "@t3tools/contracts": "workspace:*",
232225 "@t3tools/shared": "workspace:*",
......@@ -243,7 +236,6 @@
243236 },
244237 "packages/tailscale": {
245238 "name": "@t3tools/tailscale",
246 "version": "0.0.0-alpha.1",
247239 "dependencies": {
248240 "@effect/platform-node": "catalog:",
249241 "effect": "catalog:",
packages/client-runtime/package.json+1-1
......@@ -1,6 +1,5 @@
11{
22 "name": "@t3tools/client-runtime",
3 "version": "0.0.0-alpha.1",
43 "private": true,
54 "type": "module",
65 "exports": {
......@@ -15,6 +14,7 @@
1514 },
1615 "dependencies": {
1716 "@t3tools/contracts": "workspace:*",
17 "@t3tools/shared": "workspace:*",
1818 "effect": "catalog:"
1919 },
2020 "devDependencies": {
packages/client-runtime/src/advertisedEndpoint.ts+1-78
......@@ -1,78 +1 @@
1import type {
2 AdvertisedEndpoint,
3 AdvertisedEndpointHostedHttpsCompatibility,
4 AdvertisedEndpointProvider,
5 AdvertisedEndpointReachability,
6 AdvertisedEndpointSource,
7 AdvertisedEndpointStatus,
8} from "@t3tools/contracts";
9
10export interface CreateAdvertisedEndpointInput {
11 readonly id: string;
12 readonly label: string;
13 readonly provider: AdvertisedEndpointProvider;
14 readonly httpBaseUrl: string;
15 readonly reachability: AdvertisedEndpointReachability;
16 readonly hostedHttpsCompatibility?: AdvertisedEndpointHostedHttpsCompatibility;
17 readonly desktopCompatibility?: "compatible" | "unknown";
18 readonly source: AdvertisedEndpointSource;
19 readonly status?: AdvertisedEndpointStatus;
20 readonly isDefault?: boolean;
21 readonly description?: string;
22}
23
24export function normalizeHttpBaseUrl(rawValue: string): string {
25 const url = new URL(rawValue);
26 if (url.protocol === "ws:") {
27 url.protocol = "http:";
28 } else if (url.protocol === "wss:") {
29 url.protocol = "https:";
30 }
31
32 if (url.protocol !== "http:" && url.protocol !== "https:") {
33 throw new Error(`Endpoint must use HTTP or HTTPS. Received ${url.protocol}`);
34 }
35
36 url.pathname = "/";
37 url.search = "";
38 url.hash = "";
39 return url.toString();
40}
41
42export function deriveWsBaseUrl(httpBaseUrl: string): string {
43 const url = new URL(normalizeHttpBaseUrl(httpBaseUrl));
44 url.protocol = url.protocol === "https:" ? "wss:" : "ws:";
45 return url.toString();
46}
47
48export function classifyHostedHttpsCompatibility(
49 httpBaseUrl: string,
50 fallback: AdvertisedEndpointHostedHttpsCompatibility = "unknown",
51): AdvertisedEndpointHostedHttpsCompatibility {
52 const url = new URL(normalizeHttpBaseUrl(httpBaseUrl));
53 if (url.protocol === "http:") {
54 return "mixed-content-blocked";
55 }
56 return fallback === "mixed-content-blocked" ? "unknown" : fallback;
57}
58
59export function createAdvertisedEndpoint(input: CreateAdvertisedEndpointInput): AdvertisedEndpoint {
60 const httpBaseUrl = normalizeHttpBaseUrl(input.httpBaseUrl);
61 return {
62 id: input.id,
63 label: input.label,
64 provider: input.provider,
65 httpBaseUrl,
66 wsBaseUrl: deriveWsBaseUrl(httpBaseUrl),
67 reachability: input.reachability,
68 compatibility: {
69 hostedHttpsApp:
70 input.hostedHttpsCompatibility ?? classifyHostedHttpsCompatibility(httpBaseUrl),
71 desktopApp: input.desktopCompatibility ?? "compatible",
72 },
73 source: input.source,
74 status: input.status ?? "available",
75 ...(input.isDefault === undefined ? {} : { isDefault: input.isDefault }),
76 ...(input.description === undefined ? {} : { description: input.description }),
77 };
78}
1export * from "@t3tools/shared/advertisedEndpoint";
packages/contracts/package.json+5-13
......@@ -6,24 +6,17 @@
66 "dist"
77 ],
88 "type": "module",
9 "main": "./dist/index.cjs",
10 "module": "./dist/index.mjs",
11 "types": "./src/index.ts",
129 "exports": {
13 "./settings": {
14 "types": "./src/settings.ts",
15 "import": "./src/settings.ts",
16 "require": "./src/settings.ts"
17 },
1810 ".": {
1911 "types": "./src/index.ts",
20 "import": "./src/index.ts",
21 "require": "./dist/index.cjs"
12 "import": "./src/index.ts"
13 },
14 "./settings": {
15 "types": "./src/settings.ts",
16 "import": "./src/settings.ts"
2217 }
2318 },
2419 "scripts": {
25 "dev": "tsdown src/index.ts --format esm,cjs --dts --watch --clean",
26 "build": "tsdown src/index.ts --format esm,cjs --dts --clean",
2720 "typecheck": "tsc --noEmit",
2821 "test": "vitest run"
2922 },
......@@ -33,7 +26,6 @@
3326 "devDependencies": {
3427 "@effect/language-service": "catalog:",
3528 "@effect/vitest": "catalog:",
36 "tsdown": "catalog:",
3729 "typescript": "catalog:",
3830 "vitest": "catalog:"
3931 }
packages/effect-acp/package.json-3
......@@ -33,8 +33,6 @@
3333 }
3434 },
3535 "scripts": {
36 "dev": "tsdown src/client.ts src/agent.ts src/_generated/schema.gen.ts src/rpc.ts src/protocol.ts src/terminal.ts --format esm,cjs --dts --watch --clean",
37 "build": "tsdown src/client.ts src/agent.ts src/_generated/schema.gen.ts src/rpc.ts src/protocol.ts src/terminal.ts --format esm,cjs --dts --clean",
3836 "typecheck": "tsc --noEmit",
3937 "test": "vitest run",
4038 "generate": "bun run scripts/generate.ts"
......@@ -47,7 +45,6 @@
4745 "@effect/openapi-generator": "catalog:",
4846 "@effect/platform-node": "catalog:",
4947 "@effect/vitest": "catalog:",
50 "tsdown": "catalog:",
5148 "typescript": "catalog:",
5249 "vitest": "catalog:"
5350 }
packages/effect-codex-app-server/package.json-3
......@@ -25,8 +25,6 @@
2525 }
2626 },
2727 "scripts": {
28 "dev": "tsdown src/client.ts src/rpc.ts src/protocol.ts src/schema.ts --format esm,cjs --dts --watch --clean",
29 "build": "tsdown src/client.ts src/rpc.ts src/protocol.ts src/schema.ts --format esm,cjs --dts --clean",
3028 "typecheck": "tsc --noEmit",
3129 "test": "vitest run",
3230 "generate": "bun run scripts/generate.ts",
......@@ -40,7 +38,6 @@
4038 "@effect/openapi-generator": "catalog:",
4139 "@effect/platform-node": "catalog:",
4240 "@effect/vitest": "catalog:",
43 "tsdown": "catalog:",
4441 "typescript": "catalog:",
4542 "vitest": "catalog:"
4643 }
packages/shared/package.json+4-1
......@@ -1,6 +1,5 @@
11{
22 "name": "@t3tools/shared",
3 "version": "0.0.0-alpha.1",
43 "private": true,
54 "type": "module",
65 "exports": {
......@@ -8,6 +7,10 @@
87 "types": "./src/model.ts",
98 "import": "./src/model.ts"
109 },
10 "./advertisedEndpoint": {
11 "types": "./src/advertisedEndpoint.ts",
12 "import": "./src/advertisedEndpoint.ts"
13 },
1114 "./git": {
1215 "types": "./src/git.ts",
1316 "import": "./src/git.ts"
packages/shared/src/advertisedEndpoint.ts created+78
......@@ -0,0 +1,78 @@
1import type {
2 AdvertisedEndpoint,
3 AdvertisedEndpointHostedHttpsCompatibility,
4 AdvertisedEndpointProvider,
5 AdvertisedEndpointReachability,
6 AdvertisedEndpointSource,
7 AdvertisedEndpointStatus,
8} from "@t3tools/contracts";
9
10export interface CreateAdvertisedEndpointInput {
11 readonly id: string;
12 readonly label: string;
13 readonly provider: AdvertisedEndpointProvider;
14 readonly httpBaseUrl: string;
15 readonly reachability: AdvertisedEndpointReachability;
16 readonly hostedHttpsCompatibility?: AdvertisedEndpointHostedHttpsCompatibility;
17 readonly desktopCompatibility?: "compatible" | "unknown";
18 readonly source: AdvertisedEndpointSource;
19 readonly status?: AdvertisedEndpointStatus;
20 readonly isDefault?: boolean;
21 readonly description?: string;
22}
23
24export function normalizeHttpBaseUrl(rawValue: string): string {
25 const url = new URL(rawValue);
26 if (url.protocol === "ws:") {
27 url.protocol = "http:";
28 } else if (url.protocol === "wss:") {
29 url.protocol = "https:";
30 }
31
32 if (url.protocol !== "http:" && url.protocol !== "https:") {
33 throw new Error(`Endpoint must use HTTP or HTTPS. Received ${url.protocol}`);
34 }
35
36 url.pathname = "/";
37 url.search = "";
38 url.hash = "";
39 return url.toString();
40}
41
42export function deriveWsBaseUrl(httpBaseUrl: string): string {
43 const url = new URL(normalizeHttpBaseUrl(httpBaseUrl));
44 url.protocol = url.protocol === "https:" ? "wss:" : "ws:";
45 return url.toString();
46}
47
48export function classifyHostedHttpsCompatibility(
49 httpBaseUrl: string,
50 fallback: AdvertisedEndpointHostedHttpsCompatibility = "unknown",
51): AdvertisedEndpointHostedHttpsCompatibility {
52 const url = new URL(normalizeHttpBaseUrl(httpBaseUrl));
53 if (url.protocol === "http:") {
54 return "mixed-content-blocked";
55 }
56 return fallback === "mixed-content-blocked" ? "unknown" : fallback;
57}
58
59export function createAdvertisedEndpoint(input: CreateAdvertisedEndpointInput): AdvertisedEndpoint {
60 const httpBaseUrl = normalizeHttpBaseUrl(input.httpBaseUrl);
61 return {
62 id: input.id,
63 label: input.label,
64 provider: input.provider,
65 httpBaseUrl,
66 wsBaseUrl: deriveWsBaseUrl(httpBaseUrl),
67 reachability: input.reachability,
68 compatibility: {
69 hostedHttpsApp:
70 input.hostedHttpsCompatibility ?? classifyHostedHttpsCompatibility(httpBaseUrl),
71 desktopApp: input.desktopCompatibility ?? "compatible",
72 },
73 source: input.source,
74 status: input.status ?? "available",
75 ...(input.isDefault === undefined ? {} : { isDefault: input.isDefault }),
76 ...(input.description === undefined ? {} : { description: input.description }),
77 };
78}
packages/ssh/package.json-1
......@@ -1,6 +1,5 @@
11{
22 "name": "@t3tools/ssh",
3 "version": "0.0.0-alpha.1",
43 "private": true,
54 "type": "module",
65 "exports": {
packages/tailscale/package.json-1
......@@ -1,6 +1,5 @@
11{
22 "name": "@t3tools/tailscale",
3 "version": "0.0.0-alpha.1",
43 "private": true,
54 "type": "module",
65 "exports": {