@treeport/treeport 0.3.0 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -57,6 +57,20 @@
57
57
  "when": 1786533775050,
58
58
  "tag": "0007_dashing_pestilence",
59
59
  "breakpoints": true
60
+ },
61
+ {
62
+ "idx": 8,
63
+ "version": "6",
64
+ "when": 1786600000000,
65
+ "tag": "0008_recent_project_visibility",
66
+ "breakpoints": true
67
+ },
68
+ {
69
+ "idx": 9,
70
+ "version": "6",
71
+ "when": 1786800000000,
72
+ "tag": "0009_open_folders",
73
+ "breakpoints": true
60
74
  }
61
75
  ]
62
76
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@treeport/treeport",
3
- "version": "0.3.0",
4
- "description": "A worktree-first terminal driver for persistent development workspaces.",
3
+ "version": "0.5.0",
4
+ "description": "A tree-first terminal driver for persistent development workspaces.",
5
5
  "type": "module",
6
6
  "bin": {
7
7
  "treeport": "bin/treeport.mjs"
@@ -51,7 +51,7 @@
51
51
  "socket.io-client": "4.8.3",
52
52
  "vite": "8.1.5",
53
53
  "zod": "^4.3.6",
54
- "@treeport/panel-sdk": "0.3.0"
54
+ "@treeport/panel-sdk": "0.5.0"
55
55
  },
56
56
  "devDependencies": {
57
57
  "@fontsource-variable/inter": "^5.2.8",
@@ -91,7 +91,7 @@
91
91
  "check:package": "node scripts/check-package.mjs",
92
92
  "test:package": "node scripts/smoke-package.mjs",
93
93
  "dev": "node scripts/development.mjs",
94
- "dev:server": "TREEPORT_DATA_DIR=.treeport-dev/data TREEPORT_RUNTIME_DIR=.treeport-dev/runtime TREEPORT_DAEMON_LIFECYCLE=external tsdown --watch --on-success \"node --enable-source-maps dist/node/server/index.js\"",
94
+ "dev:server": "rm -rf .treeport-dev-dist && TREEPORT_DATA_DIR=.treeport-dev/data TREEPORT_RUNTIME_DIR=.treeport-dev/runtime TREEPORT_DAEMON_LIFECYCLE=external tsdown --watch --out-dir .treeport-dev-dist",
95
95
  "start": "TREEPORT_WEB_DIST=dist/web node dist/node/server/index.js",
96
96
  "db:generate": "drizzle-kit generate",
97
97
  "typecheck": "pnpm typecheck:node && pnpm typecheck:web",
@@ -1,12 +1,12 @@
1
1
  ---
2
2
  name: treeport
3
- description: Understand Treeport-managed terminal context and safely create persistent, observable terminals and child worktrees with the Treeport CLI. Use when an agent or extension needs to inspect its Treeport environment, open another session, or spawn work in a separate worktree.
3
+ description: Understand Treeport-managed terminal context and safely create persistent, observable terminals and child trees with the Treeport CLI. Use when an agent or extension needs to inspect its Treeport environment, open another session, or spawn work in a separate tree.
4
4
  compatibility: Requires the treeport CLI on PATH and a reachable Treeport daemon. Creation commands also require the requested child executable to be installed.
5
5
  ---
6
6
 
7
7
  # Treeport
8
8
 
9
- Treeport is a generic terminal and worktree layer. Its terminals are persistent tmux sessions that appear in the Treeport UI. A user can open a created terminal, take control of the normal application TUI, and continue working in the same session.
9
+ Treeport is a generic terminal and tree layer. Its terminals are persistent tmux sessions that appear in the Treeport UI. A user can open a created terminal, take control of the normal application TUI, and continue working in the same session.
10
10
 
11
11
  Treeport does not define task sources, planning or approval states, agent tool policies, or provider-specific workflows. The caller owns names, commands, prompts, and higher-level orchestration.
12
12
 
@@ -16,8 +16,17 @@ Treeport does not define task sources, planning or approval states, agent tool p
16
16
  - Treat command arguments after `--` as an argv array. Do not turn them into a shell command string.
17
17
  - Do not use `eval` or an implicit `sh -lc`. Launch a shell explicitly only when the caller intentionally requests shell semantics.
18
18
  - Do not place untrusted titles, prompts, or other external text into interpolated shell fragments. Pass each value as one argument or use a caller-managed file when the child supports file arguments.
19
- - Never delete a terminal or remove a worktree unless the user explicitly asks.
20
- - Obey the daemon lifecycle reported by `treeport context`. When it is `external`, never run `treeport start`, `treeport stop`, or `treeport remote enable`; the parent process owns startup, shutdown, and remote exposure. When it is `service`, normal `start` and `stop` delegate to the OS manager and can require the printed administrator action.
19
+ - Never delete a terminal or remove a tree unless the user explicitly asks.
20
+ - Obey the daemon lifecycle reported by `treeport context`.
21
+ - When the lifecycle is `external`, never run `treeport start`, `treeport stop`, or `treeport remote enable`.
22
+ - In the external lifecycle, the parent process owns startup, shutdown, and remote exposure.
23
+ - When the lifecycle is `service`, normal `start` and `stop` delegate to the OS manager.
24
+ - Use bare `treeport update` to update a supported local npm installation. It preserves tmux terminals and an enabled service, and restarts only a daemon that was running.
25
+ - Never run bare `treeport update` for an external or selected remote daemon.
26
+ - Never invoke `sudo` for a normal service or update operation.
27
+ - Normal macOS service mode is a user/login LaunchAgent and does not need an administrator.
28
+ - Advanced headless mode is explicit.
29
+ - If an existing headless service prints an administrator command, report the command and wait for the user.
21
30
  - Do not restrict a launched agent's normal tools or make it ephemeral unless the caller explicitly asks. The persistent interactive session is intended to remain useful when the user takes over.
22
31
 
23
32
  ## Understand the current context
@@ -28,45 +37,46 @@ Run:
28
37
  treeport context
29
38
  ```
30
39
 
31
- Inside a managed terminal, this reports the current project, worktree, terminal, paths, statuses, IDs, daemon URL, and whether the daemon lifecycle is managed by Treeport, by the OS service, or by an external process. It resolves the injected IDs strictly; it does not guess identity from the current path.
40
+ Inside a managed terminal, this reports the current project, tree, terminal, paths, statuses, IDs, and daemon URL. It reports whether Treeport, the OS service, or an external process manages the daemon lifecycle. It resolves the injected IDs strictly. It does not guess identity from the current path.
32
41
 
33
42
  Outside Treeport it reports that the terminal is not managed and exits successfully. `TREEPORT_API_URL` may be configured outside a managed terminal; if any context ID is present, however, all injected values are required. Partial IDs or IDs that no longer belong together fail instead of falling back to path inference.
34
43
 
35
- Use the exact IDs from this command for subsequent operations. `.` is a convenient shorthand for the current project or worktree, but exact IDs are clearer once context has been resolved.
44
+ Use the exact IDs from this command when an operation targets a different project or tree. `.` is a convenient shorthand for the current project or tree.
36
45
 
37
- ## Create a terminal in the current worktree
46
+ When the current folder is in the target project, omit `--project` from `worktree create` and `spawn`. Treeport detects the registered project from the current folder.
47
+
48
+ ## Create a terminal in the current tree
38
49
 
39
50
  Create a persistent login shell:
40
51
 
41
52
  ```sh
42
- treeport terminal create --worktree <worktree-id> --name <terminal-name>
53
+ treeport terminal create --worktree <tree-id> --name <terminal-name>
43
54
  ```
44
55
 
45
56
  Launch a program directly:
46
57
 
47
58
  ```sh
48
- treeport terminal create --worktree <worktree-id> --name <terminal-name> -- <program> <arg> ...
59
+ treeport terminal create --worktree <tree-id> --name <terminal-name> -- <program> <arg> ...
49
60
  ```
50
61
 
51
62
  The command returns after Treeport creates the tmux session. The program continues independently of the browser and of the caller that created it.
52
63
 
53
- ## Create a child worktree and terminal
64
+ ## Create a child tree and terminal
54
65
 
55
- Create a linked worktree and its first persistent terminal together:
66
+ Create a linked tree and its first persistent terminal together:
56
67
 
57
68
  ```sh
58
69
  treeport spawn \
59
- --project <project-id> \
60
- --worktree-name <worktree-name> \
70
+ --worktree-name <tree-name> \
61
71
  --name <terminal-name> \
62
72
  -- <program> <arg> ...
63
73
  ```
64
74
 
65
75
  The child program and its arguments are entirely caller-owned. Treeport preserves them but does not add prompts, modes, capability restrictions, or lifecycle policy.
66
76
 
67
- By default, Treeport bases the worktree on the fetched remote default branch. Add `--from-current` only when the caller wants the current worktree's committed `HEAD` as the base. Uncommitted changes are not copied.
77
+ By default, Treeport bases the tree on the fetched remote default branch. Add `--from-current` only for the current tree's committed `HEAD`. Uncommitted changes are not copied.
68
78
 
69
- Treeport serializes worktree mutations per project. If a caller needs several child worktrees, create them one at a time; their terminal programs can run concurrently after creation.
79
+ Treeport serializes tree mutations per project. If a caller needs several child trees, create them one at a time. Their terminal programs can run concurrently after creation.
70
80
 
71
81
  ## Interpret creation results
72
82
 
@@ -75,16 +85,16 @@ A successful `terminal create` means the tmux session was created. The requested
75
85
  `spawn` is intentionally non-atomic after Git creates the worktree:
76
86
 
77
87
  - A terminal ID means the persistent session was created.
78
- - `terminalError` means the worktree remains but its initial terminal could not be created.
79
- - `setupError` means worktree setup could not be prepared. A retained terminal may display that error and exit without launching the requested program.
88
+ - `terminalError` means the tree remains but its initial terminal could not be created.
89
+ - `setupError` means tree setup could not be prepared. A retained terminal may display that error and exit without launching the requested program.
80
90
  - Setup tasks can also fail after the create response. Their output and failure remain visible in the retained terminal.
81
91
 
82
- Report partial creation with the returned worktree and terminal IDs. Do not blindly rerun `spawn`: the worktree may already exist. Do not remove retained resources automatically.
92
+ Report partial creation with the returned tree and terminal IDs. Do not blindly rerun `spawn`: the tree may already exist. Do not remove retained resources automatically.
83
93
 
84
94
  Inspect terminal inventory later with:
85
95
 
86
96
  ```sh
87
- treeport terminal list --worktree <worktree-id>
97
+ treeport terminal list --worktree <tree-id>
88
98
  ```
89
99
 
90
100
  Inspect one terminal's refreshed process status and volatile runtime metadata with:
@@ -131,13 +141,12 @@ Extensions and scripts should add `--json` before the `--` command separator:
131
141
  treeport context --json
132
142
 
133
143
  treeport terminal create \
134
- --worktree <worktree-id> \
144
+ --worktree <tree-id> \
135
145
  --name <terminal-name> \
136
146
  --json -- <program> <arg> ...
137
147
 
138
148
  treeport spawn \
139
- --project <project-id> \
140
- --worktree-name <worktree-name> \
149
+ --worktree-name <tree-name> \
141
150
  --name <terminal-name> \
142
151
  --json -- <program> <arg> ...
143
152
  ```
@@ -1,407 +0,0 @@
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 TERMINAL_SCROLL_EXIT_SEQUENCE = "\x1B[9000~";
11
- const TERMINAL_SELECTION_START_SEQUENCE = "\x1B[9001~";
12
- const TERMINAL_SELECTION_STOP_SEQUENCE = "\x1B[9002~";
13
- const TERMINAL_SELECTION_CLEAR_SEQUENCE = "\x1B[9003~";
14
- const TERMINAL_SELECTION_RESTORE_SEQUENCE = "\x1B[9004~";
15
- const terminalId = z.string().min(1).max(128);
16
- const clientId = z.string().min(1).max(128);
17
- const streamId = z.string().min(1).max(128);
18
- const generation = z.number().int().nonnegative();
19
- const dimensions = {
20
- cols: z.number().int().min(2).max(1e3),
21
- rows: z.number().int().min(2).max(500)
22
- };
23
- const terminalSizeSchema = z.strictObject(dimensions);
24
- const terminalProgressSchema = z.strictObject({
25
- state: z.enum([
26
- "normal",
27
- "error",
28
- "indeterminate",
29
- "paused"
30
- ]),
31
- value: z.number().int().min(0).max(100).nullable()
32
- });
33
- const terminalProgramSchema = z.enum([
34
- "pi",
35
- "claude",
36
- "codex"
37
- ]);
38
- const terminalRuntimeMetadataSchema = z.strictObject({
39
- terminalId: z.string().min(1),
40
- title: z.string().max(256).nullable(),
41
- program: terminalProgramSchema.nullable().default(null),
42
- hasForegroundProcess: z.boolean().nullable().optional(),
43
- progress: terminalProgressSchema.nullable(),
44
- progressStartedAt: z.string().datetime().nullable().default(null),
45
- progressClearedAt: z.string().datetime().nullable().default(null),
46
- bell: z.strictObject({
47
- sequence: z.number().int().positive(),
48
- at: z.string().datetime(),
49
- unread: z.boolean()
50
- }).nullable().default(null)
51
- });
52
- const terminalBellAcknowledgementSchema = z.strictObject({ sequence: z.number().int().positive() });
53
- function parseTerminalProgress(data) {
54
- const [command, rawState, rawValue, ...extra] = data.split(";");
55
- if (command !== "4" || extra.length > 0 || !/^[0-4]$/.test(rawState ?? "")) return;
56
- const state = Number(rawState);
57
- if (state === 0) return null;
58
- if (rawValue !== void 0 && rawValue !== "" && !/^\d{1,3}$/.test(rawValue)) return;
59
- const value = rawValue === void 0 || rawValue === "" ? null : Number(rawValue);
60
- if (value !== null && value > 100) return;
61
- return {
62
- state: [
63
- void 0,
64
- "normal",
65
- "error",
66
- "indeterminate",
67
- "paused"
68
- ][state],
69
- value
70
- };
71
- }
72
- const terminalAuthSchema = z.strictObject({
73
- terminalId,
74
- clientId,
75
- ...dimensions
76
- });
77
- const terminalInputSchema = z.strictObject({
78
- generation,
79
- data: z.string().max(TERMINAL_MAX_INPUT_BYTES)
80
- });
81
- const terminalBinarySchema = z.strictObject({
82
- generation,
83
- data: z.string().max(TERMINAL_MAX_INPUT_BYTES)
84
- });
85
- const terminalResizeSchema = z.strictObject({
86
- generation,
87
- ...dimensions
88
- });
89
- const terminalTakeControlSchema = z.strictObject({
90
- generation,
91
- ...dimensions
92
- });
93
- const terminalLegacyTakeControlSchema = z.strictObject({ generation });
94
- const terminalOutputAckSchema = z.strictObject({
95
- streamId,
96
- sequence: z.number().int().nonnegative()
97
- });
98
- const terminalReadyBase = {
99
- connectionId: z.string().min(1).max(128),
100
- streamId,
101
- generation,
102
- controller: z.boolean(),
103
- reset: z.literal("full")
104
- };
105
- const terminalLegacyReadySchema = z.strictObject(terminalReadyBase);
106
- const terminalReadyV2Schema = z.strictObject({
107
- ...terminalReadyBase,
108
- ...dimensions,
109
- revision: z.number().int().positive()
110
- });
111
- z.union([terminalLegacyReadySchema, terminalReadyV2Schema]);
112
- z.strictObject({
113
- ...dimensions,
114
- revision: z.number().int().positive()
115
- });
116
- z.strictObject({
117
- streamId,
118
- sequence: z.number().int().positive(),
119
- data: z.string()
120
- });
121
- z.strictObject({ title: z.string().max(256) });
122
- z.strictObject({ progress: terminalProgressSchema.nullable() });
123
- z.strictObject({ viewing: z.boolean() });
124
- z.strictObject({
125
- generation,
126
- controller: z.boolean()
127
- });
128
- z.strictObject({ exitCode: z.number().int().nullable() });
129
- z.strictObject({
130
- code: z.string().min(1).max(80),
131
- message: z.string().min(1).max(1e3),
132
- retryable: z.boolean()
133
- });
134
- function parseTerminalAuth(value) {
135
- const parsed = terminalAuthSchema.safeParse(value);
136
- return parsed.success ? parsed.data : null;
137
- }
138
- //#endregion
139
- //#region ../../packages/shared/dist/socket-protocol.js
140
- const identifierSchema = z.string().min(1).max(128);
141
- const eventEnvelope = (type, data) => z.strictObject({
142
- id: identifierSchema,
143
- type: z.literal(type),
144
- at: z.string().datetime(),
145
- data
146
- });
147
- const projectEventDataSchema = z.strictObject({
148
- projectId: identifierSchema,
149
- worktreeId: z.null()
150
- });
151
- const worktreeEventDataSchema = z.strictObject({ worktreeId: identifierSchema });
152
- const projectWorktreeEventDataSchema = z.strictObject({
153
- projectId: identifierSchema,
154
- worktreeId: identifierSchema
155
- });
156
- const operationEventDataSchema = z.strictObject({
157
- operationId: identifierSchema,
158
- worktreeId: identifierSchema
159
- });
160
- const productEventSchema = z.discriminatedUnion("type", [
161
- eventEnvelope("project.created", projectEventDataSchema),
162
- eventEnvelope("project.updated", projectEventDataSchema),
163
- eventEnvelope("project.removed", projectEventDataSchema),
164
- eventEnvelope("worktree.created", projectWorktreeEventDataSchema),
165
- eventEnvelope("worktree.updated", worktreeEventDataSchema),
166
- eventEnvelope("worktree.removed", projectWorktreeEventDataSchema),
167
- eventEnvelope("create.started", z.strictObject({
168
- projectId: identifierSchema,
169
- operationId: identifierSchema,
170
- worktreeId: z.null()
171
- })),
172
- eventEnvelope("create.completed", z.strictObject({
173
- projectId: identifierSchema,
174
- operationId: identifierSchema,
175
- worktreeId: identifierSchema
176
- })),
177
- eventEnvelope("create.failed", z.strictObject({
178
- projectId: identifierSchema,
179
- operationId: identifierSchema,
180
- worktreeId: z.null()
181
- })),
182
- eventEnvelope("terminal.created", z.strictObject({
183
- projectId: identifierSchema.optional(),
184
- worktreeId: identifierSchema,
185
- terminalId: identifierSchema
186
- })),
187
- eventEnvelope("terminal.updated", z.strictObject({
188
- worktreeId: identifierSchema,
189
- terminalId: identifierSchema
190
- })),
191
- eventEnvelope("terminal.removed", z.strictObject({
192
- worktreeId: identifierSchema,
193
- terminalId: identifierSchema
194
- })),
195
- eventEnvelope("terminal.metadata", terminalRuntimeMetadataSchema.extend({ worktreeId: z.null() })),
196
- eventEnvelope("terminal.controller_changed", z.strictObject({
197
- terminalId: identifierSchema,
198
- controlled: z.boolean(),
199
- worktreeId: z.null()
200
- })),
201
- eventEnvelope("panel.created", z.strictObject({
202
- worktreeId: identifierSchema,
203
- panelId: identifierSchema
204
- })),
205
- eventEnvelope("panel.updated", z.strictObject({
206
- worktreeId: identifierSchema,
207
- panelId: identifierSchema
208
- })),
209
- eventEnvelope("panel.open_requested", z.strictObject({
210
- worktreeId: identifierSchema,
211
- panelId: identifierSchema,
212
- sourceTerminalId: identifierSchema.nullable()
213
- })),
214
- eventEnvelope("panel.removed", z.strictObject({
215
- worktreeId: identifierSchema,
216
- panelId: identifierSchema
217
- })),
218
- eventEnvelope("remove.started", operationEventDataSchema.extend({ kind: z.literal("remove") })),
219
- eventEnvelope("remove.completed", operationEventDataSchema),
220
- eventEnvelope("remove.failed", operationEventDataSchema.extend({ error: z.string() }))
221
- ]);
222
- const webPanelSnapshotSchema = z.strictObject({
223
- id: z.string().min(1),
224
- kind: z.literal("web"),
225
- worktreeId: z.string().min(1),
226
- definitionId: z.string().min(1),
227
- title: z.string().min(1),
228
- launch: z.strictObject({
229
- input: z.record(z.string(), z.json()).nullable(),
230
- cwd: z.string().nullable()
231
- }),
232
- sandbox: z.strictObject({ allowSameOrigin: z.boolean() }),
233
- createdAt: z.string(),
234
- updatedAt: z.string()
235
- });
236
- const eventsSnapshotSchema = z.strictObject({
237
- at: z.string().datetime(),
238
- terminalMetadata: z.array(terminalRuntimeMetadataSchema),
239
- webPanels: z.array(webPanelSnapshotSchema)
240
- });
241
- function parseEventsSnapshot(value) {
242
- const parsed = eventsSnapshotSchema.safeParse(value);
243
- return parsed.success ? parsed.data : null;
244
- }
245
- function parseProductEvent(value) {
246
- const parsed = productEventSchema.safeParse(value);
247
- return parsed.success ? parsed.data : null;
248
- }
249
- //#endregion
250
- //#region ../../packages/shared/dist/index.js
251
- const TERMINAL_MAX_UPLOAD_BYTES = 50 * 1024 * 1024;
252
- const TERMINAL_EXECUTABLE_MAX_LENGTH = 4096;
253
- const TERMINAL_ARGUMENT_MAX_LENGTH = 4096;
254
- const TERMINAL_CAPTURE_MAX_LINES = 5e3;
255
- const WEB_PANEL_INPUT_MAX_BYTES = 64 * 1024;
256
- const PROJECT_COLORS = [
257
- "rose",
258
- "orange",
259
- "amber",
260
- "emerald",
261
- "cyan",
262
- "blue",
263
- "violet",
264
- "pink"
265
- ];
266
- const browseDirectoryQuerySchema = z.object({
267
- input: z.string().trim().min(1).max(4096),
268
- hidden: z.enum(["true", "false"]).optional().default("false").transform((value) => value === "true")
269
- });
270
- const terminalCaptureQuerySchema = z.object({ lines: z.coerce.number().int().min(1).max(TERMINAL_CAPTURE_MAX_LINES).optional().default(200) });
271
- const registerProjectSchema = z.object({
272
- path: z.string().trim().min(1),
273
- name: z.string().trim().min(1).max(120).optional()
274
- });
275
- const updateProjectSchema = z.object({ color: z.enum(PROJECT_COLORS).nullable() });
276
- const terminalNameSchema = z.string().trim().min(1).max(120);
277
- const terminalArgvSchema = z.array(z.string()).min(1).max(128);
278
- const terminalPresetArgumentSchema = z.string().max(TERMINAL_ARGUMENT_MAX_LENGTH);
279
- const terminalPresetFields = {
280
- name: terminalNameSchema,
281
- executable: z.string().min(1).max(TERMINAL_EXECUTABLE_MAX_LENGTH).refine((value) => value.trim().length > 0, { message: "Executable cannot be blank" }),
282
- args: z.array(terminalPresetArgumentSchema).max(127),
283
- closeOnSuccess: z.boolean().default(false)
284
- };
285
- const repositoryTerminalPresetSchema = z.strictObject(terminalPresetFields);
286
- const repositoryTerminalPresetIdSchema = z.string().regex(/^[a-z0-9][a-z0-9._-]{0,119}$/, { message: "Preset IDs must contain only lowercase letters, numbers, dots, underscores, and hyphens" });
287
- const repositoryTerminalPresetsFileSchema = z.strictObject({
288
- version: z.literal(1),
289
- presets: z.record(repositoryTerminalPresetIdSchema, z.unknown())
290
- });
291
- const terminalPresetRevisionSchema = z.string().min(1).max(64);
292
- const initialTerminalSchema = z.object({
293
- name: terminalNameSchema,
294
- argv: terminalArgvSchema.optional(),
295
- returnToShell: z.boolean().optional(),
296
- initialSize: terminalSizeSchema.optional()
297
- });
298
- const createWorktreeSchema = z.object({
299
- name: z.string().trim().min(1).max(120),
300
- base: z.enum(["default", "current"]).default("default"),
301
- sourceWorktreeId: z.string().min(1).optional(),
302
- initialTerminal: initialTerminalSchema.optional()
303
- }).superRefine((value, context) => {
304
- if (value.base === "current" && !value.sourceWorktreeId) context.addIssue({
305
- code: "custom",
306
- path: ["sourceWorktreeId"],
307
- message: "A source worktree is required when starting from current"
308
- });
309
- });
310
- const terminalCwdSchema = z.string().min(1).max(4096).refine((value) => value.trim().length > 0 && !value.includes("\0"), { message: "Working directory cannot be blank or contain NUL" });
311
- const terminalEnvironmentKeySchema = z.string().min(1).max(256).refine((value) => !value.includes("=") && !value.includes("\0"), { message: "Environment keys cannot contain equals or NUL" });
312
- const terminalEnvironmentSchema = z.record(terminalEnvironmentKeySchema, z.string().max(TERMINAL_ARGUMENT_MAX_LENGTH).refine((value) => !value.includes("\0"), { message: "Environment values cannot contain NUL" })).refine((value) => Object.keys(value).length <= 128, { message: "Environment cannot contain more than 128 variables" });
313
- const createTerminalSchema = z.object({
314
- name: terminalNameSchema,
315
- argv: terminalArgvSchema.optional(),
316
- cwd: terminalCwdSchema.optional(),
317
- env: terminalEnvironmentSchema.optional(),
318
- returnToShell: z.boolean().optional(),
319
- closeOnSuccess: z.boolean().optional(),
320
- initialSize: terminalSizeSchema.optional()
321
- }).refine((value) => !(value.returnToShell && value.closeOnSuccess), { message: "A terminal cannot return to a shell and close on success" });
322
- const updateTerminalSchema = z.object({ name: terminalNameSchema });
323
- const webPanelInputSchema = z.record(z.string(), z.json());
324
- const createWebPanelSchema = z.object({
325
- definitionId: z.string().min(1).max(256),
326
- input: webPanelInputSchema.nullable().optional(),
327
- launchCwd: z.string().max(4096).nullable().optional()
328
- });
329
- const openWebPanelSchema = createWebPanelSchema.extend({
330
- newInstance: z.boolean().optional(),
331
- sourceTerminalId: z.string().min(1).max(128).nullable().optional()
332
- });
333
- const webPanelStorageKeySchema = z.string().min(1).max(128);
334
- const getWebPanelStorageSchema = z.object({ key: webPanelStorageKeySchema });
335
- const setWebPanelStorageSchema = z.object({
336
- key: webPanelStorageKeySchema,
337
- value: z.json()
338
- });
339
- const deleteWebPanelStorageSchema = z.object({ key: webPanelStorageKeySchema });
340
- const createTerminalPresetSchema = z.object(terminalPresetFields);
341
- const updateTerminalPresetSchema = z.object({
342
- ...terminalPresetFields,
343
- closeOnSuccess: z.boolean().optional(),
344
- expectedUpdatedAt: terminalPresetRevisionSchema
345
- });
346
- const deleteTerminalPresetSchema = z.object({ expectedUpdatedAt: terminalPresetRevisionSchema });
347
- const packageProjectQuerySchema = z.object({ path: z.string().trim().min(1).max(4096) });
348
- const packageInstallSchema = z.object({
349
- source: z.string().trim().min(1).max(4096),
350
- projectId: z.string().min(1).optional()
351
- });
352
- const packageRemoveSchema = z.object({
353
- source: z.string().trim().min(1).max(4096),
354
- projectId: z.string().min(1).optional()
355
- });
356
- const packageUpdateSchema = z.object({ source: z.string().trim().min(1).max(4096).optional() });
357
- const packageReloadSchema = z.object({ projectId: z.string().min(1).optional() });
358
- const removeWorktreeSchema = z.object({
359
- confirmationToken: z.string().length(64),
360
- confirmDestructive: z.boolean()
361
- });
362
- z.object({
363
- project: z.string().min(1),
364
- worktreeName: z.string().trim().min(1).max(120),
365
- name: terminalNameSchema,
366
- argv: terminalArgvSchema.optional(),
367
- base: z.enum(["default", "current"]).default("default"),
368
- sourceWorktreeId: z.string().min(1).optional()
369
- }).superRefine((value, context) => {
370
- if (value.base === "current" && !value.sourceWorktreeId) context.addIssue({
371
- code: "custom",
372
- path: ["sourceWorktreeId"],
373
- message: "A source worktree is required when starting from current"
374
- });
375
- });
376
- //#endregion
377
- //#region src/duration.ts
378
- const DURATION_UNITS = {
379
- ms: 1,
380
- s: 1e3,
381
- m: 6e4,
382
- h: 36e5
383
- };
384
- const MAX_DURATION_MS = 2147483647;
385
- function parseDurationMs(value) {
386
- const match = /^(\d+)(ms|s|m|h)$/.exec(value);
387
- if (!match) throw new Error("Timeout must be a positive duration such as 500ms, 30s, 5m, or 1h");
388
- const timeoutMs = Number(match[1]) * DURATION_UNITS[match[2]];
389
- if (!Number.isSafeInteger(timeoutMs) || timeoutMs <= 0 || timeoutMs > MAX_DURATION_MS) throw new Error("Timeout must be between 1ms and 2147483647ms");
390
- return timeoutMs;
391
- }
392
- //#endregion
393
- //#region src/server/core/loopback.ts
394
- const LOOPBACK_HOSTS = /* @__PURE__ */ new Set([
395
- "127.0.0.1",
396
- "::1",
397
- "localhost"
398
- ]);
399
- function isLoopbackHost(host) {
400
- return LOOPBACK_HOSTS.has(host.trim().toLowerCase());
401
- }
402
- function assertLoopbackHost(host) {
403
- if (isLoopbackHost(host)) return;
404
- throw new Error("Treeport supports only loopback listeners. Run `treeport start --host 127.0.0.1`, then use `treeport remote enable` for private remote access.");
405
- }
406
- //#endregion
407
- export { parseProductEvent as A, TERMINAL_SELECTION_RESTORE_SEQUENCE as B, repositoryTerminalPresetsFileSchema as C, updateTerminalPresetSchema as D, updateProjectSchema as E, TERMINAL_OUTPUT_HIGH_WATERMARK as F, terminalBellAcknowledgementSchema as G, TERMINAL_SELECTION_STOP_SEQUENCE as H, TERMINAL_OUTPUT_LOW_WATERMARK as I, terminalLegacyTakeControlSchema as J, terminalBinarySchema as K, TERMINAL_OUTPUT_STALL_TIMEOUT_MS as L, TERMINAL_CONTROLLER_GRACE_MS as M, TERMINAL_MAX_CLIENT_MESSAGE_BYTES as N, updateTerminalSchema as O, TERMINAL_MAX_INPUT_BYTES as P, terminalTakeControlSchema as Q, TERMINAL_SCROLL_EXIT_SEQUENCE as R, repositoryTerminalPresetSchema as S, terminalCaptureQuerySchema as T, parseTerminalAuth as U, TERMINAL_SELECTION_START_SEQUENCE as V, parseTerminalProgress as W, terminalResizeSchema as X, terminalOutputAckSchema as Y, terminalSizeSchema as Z, packageReloadSchema as _, WEB_PANEL_INPUT_MAX_BYTES as a, registerProjectSchema as b, createTerminalSchema as c, deleteTerminalPresetSchema as d, deleteWebPanelStorageSchema as f, packageProjectQuerySchema as g, packageInstallSchema as h, TERMINAL_MAX_UPLOAD_BYTES as i, SOCKET_IO_PATH as j, parseEventsSnapshot as k, createWebPanelSchema as l, openWebPanelSchema as m, parseDurationMs as n, browseDirectoryQuerySchema as o, getWebPanelStorageSchema as p, terminalInputSchema as q, TERMINAL_CAPTURE_MAX_LINES as r, createTerminalPresetSchema as s, assertLoopbackHost as t, createWorktreeSchema as u, packageRemoveSchema as v, setWebPanelStorageSchema as w, removeWorktreeSchema as x, packageUpdateSchema as y, TERMINAL_SELECTION_CLEAR_SEQUENCE as z };