@treeport/treeport 0.1.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.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Noice Tech
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,12 @@
1
+ # Treeport
2
+
3
+ Treeport is a worktree-first terminal driver for persistent development workspaces.
4
+
5
+ ```sh
6
+ npm install --global @treeport/treeport
7
+ treeport up
8
+ ```
9
+
10
+ Treeport supports macOS and Linux and requires Node.js 24 or newer, Git, and tmux 3.2 or newer.
11
+
12
+ Documentation: <https://treeport.app>
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ import '../dist/node/cli/index.js'
@@ -0,0 +1,254 @@
1
+ import { z } from "zod";
2
+ //#region ../../packages/shared/dist/terminal-protocol.js
3
+ const SOCKET_IO_PATH = "/api/socket.io/";
4
+ const TERMINAL_CONTROLLER_GRACE_MS = 1e4;
5
+ const TERMINAL_OUTPUT_HIGH_WATERMARK = 256 * 1024;
6
+ const TERMINAL_OUTPUT_LOW_WATERMARK = 64 * 1024;
7
+ const TERMINAL_OUTPUT_STALL_TIMEOUT_MS = 3e4;
8
+ const TERMINAL_MAX_CLIENT_MESSAGE_BYTES = 128 * 1024;
9
+ const TERMINAL_MAX_INPUT_BYTES = 64 * 1024;
10
+ const terminalId = z.string().min(1).max(128);
11
+ const clientId = z.string().min(1).max(128);
12
+ const streamId = z.string().min(1).max(128);
13
+ const generation = z.number().int().nonnegative();
14
+ const dimensions = {
15
+ cols: z.number().int().min(2).max(1e3),
16
+ rows: z.number().int().min(2).max(500)
17
+ };
18
+ const terminalSizeSchema = z.strictObject(dimensions);
19
+ const terminalProgressSchema = z.strictObject({
20
+ state: z.enum([
21
+ "normal",
22
+ "error",
23
+ "indeterminate",
24
+ "paused"
25
+ ]),
26
+ value: z.number().int().min(0).max(100).nullable()
27
+ });
28
+ const terminalRuntimeMetadataSchema = z.strictObject({
29
+ terminalId: z.string().min(1),
30
+ title: z.string().max(256).nullable(),
31
+ hasForegroundProcess: z.boolean().nullable().optional(),
32
+ progress: terminalProgressSchema.nullable(),
33
+ progressStartedAt: z.string().datetime().nullable().default(null),
34
+ progressClearedAt: z.string().datetime().nullable().default(null),
35
+ bell: z.strictObject({
36
+ sequence: z.number().int().positive(),
37
+ at: z.string().datetime(),
38
+ unread: z.boolean()
39
+ }).nullable().default(null)
40
+ });
41
+ const terminalBellAcknowledgementSchema = z.strictObject({ sequence: z.number().int().positive() });
42
+ function parseTerminalRuntimeMetadata(value) {
43
+ const parsed = terminalRuntimeMetadataSchema.safeParse(value);
44
+ return parsed.success ? parsed.data : null;
45
+ }
46
+ function parseTerminalProgress(data) {
47
+ const [command, rawState, rawValue, ...extra] = data.split(";");
48
+ if (command !== "4" || extra.length > 0 || !/^[0-4]$/.test(rawState ?? "")) return;
49
+ const state = Number(rawState);
50
+ if (state === 0) return null;
51
+ if (rawValue !== void 0 && rawValue !== "" && !/^\d{1,3}$/.test(rawValue)) return;
52
+ const value = rawValue === void 0 || rawValue === "" ? null : Number(rawValue);
53
+ if (value !== null && value > 100) return;
54
+ return {
55
+ state: [
56
+ void 0,
57
+ "normal",
58
+ "error",
59
+ "indeterminate",
60
+ "paused"
61
+ ][state],
62
+ value
63
+ };
64
+ }
65
+ const terminalAuthSchema = z.strictObject({
66
+ terminalId,
67
+ clientId,
68
+ ...dimensions
69
+ });
70
+ const terminalInputSchema = z.strictObject({
71
+ generation,
72
+ data: z.string().max(TERMINAL_MAX_INPUT_BYTES)
73
+ });
74
+ const terminalBinarySchema = z.strictObject({
75
+ generation,
76
+ data: z.string().max(TERMINAL_MAX_INPUT_BYTES)
77
+ });
78
+ const terminalResizeSchema = z.strictObject({
79
+ generation,
80
+ ...dimensions
81
+ });
82
+ const terminalTakeControlSchema = z.strictObject({
83
+ generation,
84
+ ...dimensions
85
+ });
86
+ const terminalLegacyTakeControlSchema = z.strictObject({ generation });
87
+ const terminalOutputAckSchema = z.strictObject({
88
+ streamId,
89
+ sequence: z.number().int().nonnegative()
90
+ });
91
+ const terminalReadyBase = {
92
+ connectionId: z.string().min(1).max(128),
93
+ streamId,
94
+ generation,
95
+ controller: z.boolean(),
96
+ reset: z.literal("full")
97
+ };
98
+ const terminalLegacyReadySchema = z.strictObject(terminalReadyBase);
99
+ const terminalReadyV2Schema = z.strictObject({
100
+ ...terminalReadyBase,
101
+ ...dimensions,
102
+ revision: z.number().int().positive()
103
+ });
104
+ z.union([terminalLegacyReadySchema, terminalReadyV2Schema]);
105
+ z.strictObject({
106
+ ...dimensions,
107
+ revision: z.number().int().positive()
108
+ });
109
+ z.strictObject({
110
+ streamId,
111
+ sequence: z.number().int().positive(),
112
+ data: z.string()
113
+ });
114
+ z.strictObject({ title: z.string().max(256) });
115
+ z.strictObject({ progress: terminalProgressSchema.nullable() });
116
+ z.strictObject({
117
+ generation,
118
+ controller: z.boolean()
119
+ });
120
+ z.strictObject({ exitCode: z.number().int().nullable() });
121
+ z.strictObject({
122
+ code: z.string().min(1).max(80),
123
+ message: z.string().min(1).max(1e3),
124
+ retryable: z.boolean()
125
+ });
126
+ function parseTerminalAuth(value) {
127
+ const parsed = terminalAuthSchema.safeParse(value);
128
+ return parsed.success ? parsed.data : null;
129
+ }
130
+ //#endregion
131
+ //#region ../../packages/shared/dist/socket-protocol.js
132
+ const productEventTypeSchema = z.enum([
133
+ "project.created",
134
+ "project.updated",
135
+ "project.removed",
136
+ "worktree.created",
137
+ "worktree.updated",
138
+ "worktree.removed",
139
+ "terminal.created",
140
+ "terminal.updated",
141
+ "terminal.removed",
142
+ "terminal.metadata",
143
+ "terminal.controller_changed",
144
+ "remove.started",
145
+ "remove.completed",
146
+ "remove.failed"
147
+ ]);
148
+ const productEventSchema = z.strictObject({
149
+ id: z.string().min(1).max(128),
150
+ type: productEventTypeSchema,
151
+ at: z.string().datetime(),
152
+ data: z.record(z.string(), z.unknown())
153
+ });
154
+ const eventsSnapshotSchema = z.strictObject({
155
+ at: z.string().datetime(),
156
+ terminalMetadata: z.array(terminalRuntimeMetadataSchema)
157
+ });
158
+ function parseEventsSnapshot(value) {
159
+ const parsed = eventsSnapshotSchema.safeParse(value);
160
+ return parsed.success ? parsed.data : null;
161
+ }
162
+ function parseProductEvent(value) {
163
+ const parsed = productEventSchema.safeParse(value);
164
+ return parsed.success ? parsed.data : null;
165
+ }
166
+ //#endregion
167
+ //#region ../../packages/shared/dist/index.js
168
+ const TERMINAL_MAX_UPLOAD_BYTES = 50 * 1024 * 1024;
169
+ const TERMINAL_EXECUTABLE_MAX_LENGTH = 4096;
170
+ const TERMINAL_ARGUMENT_MAX_LENGTH = 4096;
171
+ const TERMINAL_CAPTURE_MAX_LINES = 5e3;
172
+ const PROJECT_COLORS = [
173
+ "rose",
174
+ "orange",
175
+ "amber",
176
+ "emerald",
177
+ "cyan",
178
+ "blue",
179
+ "violet",
180
+ "pink"
181
+ ];
182
+ const browseDirectoryQuerySchema = z.object({
183
+ input: z.string().trim().min(1).max(4096),
184
+ hidden: z.enum(["true", "false"]).optional().default("false").transform((value) => value === "true")
185
+ });
186
+ const terminalCaptureQuerySchema = z.object({ lines: z.coerce.number().int().min(1).max(TERMINAL_CAPTURE_MAX_LINES).optional().default(200) });
187
+ const registerProjectSchema = z.object({
188
+ path: z.string().trim().min(1),
189
+ name: z.string().trim().min(1).max(120).optional()
190
+ });
191
+ const updateProjectSchema = z.object({ color: z.enum(PROJECT_COLORS).nullable() });
192
+ const terminalNameSchema = z.string().trim().min(1).max(120);
193
+ const terminalArgvSchema = z.array(z.string()).min(1).max(128);
194
+ const terminalPresetArgumentSchema = z.string().max(TERMINAL_ARGUMENT_MAX_LENGTH);
195
+ const terminalPresetFields = {
196
+ name: terminalNameSchema,
197
+ executable: z.string().min(1).max(TERMINAL_EXECUTABLE_MAX_LENGTH).refine((value) => value.trim().length > 0, { message: "Executable cannot be blank" }),
198
+ args: z.array(terminalPresetArgumentSchema).max(127),
199
+ closeOnSuccess: z.boolean().default(false)
200
+ };
201
+ const terminalPresetRevisionSchema = z.string().min(1).max(64);
202
+ const initialTerminalSchema = z.object({
203
+ name: terminalNameSchema,
204
+ argv: terminalArgvSchema.optional(),
205
+ returnToShell: z.boolean().optional(),
206
+ initialSize: terminalSizeSchema.optional()
207
+ });
208
+ const createWorktreeSchema = z.object({
209
+ name: z.string().trim().min(1).max(120),
210
+ base: z.enum(["default", "current"]).default("default"),
211
+ sourceWorktreeId: z.string().min(1).optional(),
212
+ initialTerminal: initialTerminalSchema.optional()
213
+ }).superRefine((value, context) => {
214
+ if (value.base === "current" && !value.sourceWorktreeId) context.addIssue({
215
+ code: "custom",
216
+ path: ["sourceWorktreeId"],
217
+ message: "A source worktree is required when starting from current"
218
+ });
219
+ });
220
+ const createTerminalSchema = z.object({
221
+ name: terminalNameSchema,
222
+ argv: terminalArgvSchema.optional(),
223
+ returnToShell: z.boolean().optional(),
224
+ closeOnSuccess: z.boolean().optional(),
225
+ initialSize: terminalSizeSchema.optional()
226
+ }).refine((value) => !(value.returnToShell && value.closeOnSuccess), { message: "A terminal cannot return to a shell and close on success" });
227
+ const updateTerminalSchema = z.object({ name: terminalNameSchema });
228
+ const createTerminalPresetSchema = z.object(terminalPresetFields);
229
+ const updateTerminalPresetSchema = z.object({
230
+ ...terminalPresetFields,
231
+ closeOnSuccess: z.boolean().optional(),
232
+ expectedUpdatedAt: terminalPresetRevisionSchema
233
+ });
234
+ const deleteTerminalPresetSchema = z.object({ expectedUpdatedAt: terminalPresetRevisionSchema });
235
+ const removeWorktreeSchema = z.object({
236
+ confirmationToken: z.string().length(64),
237
+ confirmDestructive: z.boolean()
238
+ });
239
+ const spawnSchema = z.object({
240
+ project: z.string().min(1),
241
+ worktreeName: z.string().trim().min(1).max(120),
242
+ name: terminalNameSchema,
243
+ argv: terminalArgvSchema.optional(),
244
+ base: z.enum(["default", "current"]).default("default"),
245
+ sourceWorktreeId: z.string().min(1).optional()
246
+ }).superRefine((value, context) => {
247
+ if (value.base === "current" && !value.sourceWorktreeId) context.addIssue({
248
+ code: "custom",
249
+ path: ["sourceWorktreeId"],
250
+ message: "A source worktree is required when starting from current"
251
+ });
252
+ });
253
+ //#endregion
254
+ export { terminalLegacyTakeControlSchema as A, TERMINAL_OUTPUT_STALL_TIMEOUT_MS as C, terminalBellAcknowledgementSchema as D, parseTerminalRuntimeMetadata as E, terminalResizeSchema as M, terminalSizeSchema as N, terminalBinarySchema as O, terminalTakeControlSchema as P, TERMINAL_OUTPUT_LOW_WATERMARK as S, parseTerminalProgress as T, SOCKET_IO_PATH as _, createTerminalSchema as a, TERMINAL_MAX_INPUT_BYTES as b, registerProjectSchema as c, terminalCaptureQuerySchema as d, updateProjectSchema as f, parseProductEvent as g, parseEventsSnapshot as h, createTerminalPresetSchema as i, terminalOutputAckSchema as j, terminalInputSchema as k, removeWorktreeSchema as l, updateTerminalSchema as m, TERMINAL_MAX_UPLOAD_BYTES as n, createWorktreeSchema as o, updateTerminalPresetSchema as p, browseDirectoryQuerySchema as r, deleteTerminalPresetSchema as s, TERMINAL_CAPTURE_MAX_LINES as t, spawnSchema as u, TERMINAL_CONTROLLER_GRACE_MS as v, parseTerminalAuth as w, TERMINAL_OUTPUT_HIGH_WATERMARK as x, TERMINAL_MAX_CLIENT_MESSAGE_BYTES as y };