@treeport/treeport 0.4.0 → 0.6.1

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,34 @@
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
74
+ },
75
+ {
76
+ "idx": 10,
77
+ "version": "6",
78
+ "when": 1787565462059,
79
+ "tag": "0010_browser_panels_and_permissions",
80
+ "breakpoints": true
81
+ },
82
+ {
83
+ "idx": 11,
84
+ "version": "6",
85
+ "when": 1787939530241,
86
+ "tag": "0011_free_magdalene",
87
+ "breakpoints": true
60
88
  }
61
89
  ]
62
90
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@treeport/treeport",
3
- "version": "0.4.0",
3
+ "version": "0.6.1",
4
4
  "description": "A tree-first terminal driver for persistent development workspaces.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -38,20 +38,23 @@
38
38
  "@hono/node-server": "^2.0.10",
39
39
  "@hono/zod-validator": "^0.9.0",
40
40
  "@libsql/client": "^0.17.4",
41
+ "@playwright/cli": "0.1.18",
41
42
  "@radix-ui/react-context-menu": "^2.3.7",
42
43
  "@vitejs/plugin-react": "5.2.0",
43
44
  "@xterm/headless": "^6.0.0",
45
+ "cmdk": "^1.1.1",
44
46
  "commander": "14.0.3",
45
47
  "drizzle-orm": "^0.45.2",
46
48
  "effect": "^3.22.0",
47
49
  "hono": "^4.11.7",
48
50
  "jsonc-parser": "^3.3.1",
49
51
  "node-pty": "1.2.0-beta.14",
52
+ "playwright": "1.61.1",
50
53
  "socket.io": "4.8.3",
51
54
  "socket.io-client": "4.8.3",
52
55
  "vite": "8.1.5",
53
56
  "zod": "^4.3.6",
54
- "@treeport/panel-sdk": "0.4.0"
57
+ "@treeport/panel-sdk": "0.6.1"
55
58
  },
56
59
  "devDependencies": {
57
60
  "@fontsource-variable/inter": "^5.2.8",
@@ -91,7 +94,7 @@
91
94
  "check:package": "node scripts/check-package.mjs",
92
95
  "test:package": "node scripts/smoke-package.mjs",
93
96
  "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",
97
+ "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
98
  "start": "TREEPORT_WEB_DIST=dist/web node dist/node/server/index.js",
96
99
  "db:generate": "drizzle-kit generate",
97
100
  "typecheck": "pnpm typecheck:node && pnpm typecheck:web",
@@ -1,11 +1,13 @@
1
1
  ---
2
2
  name: treeport
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.
3
+ description: Detailed Treeport CLI guidance for child-tree orchestration, lifecycle, services, remote access, updates, and recovery. Use when compact Pi guidance or command help is not sufficient. Do not load for routine background processes or browser tabs in a managed Pi session.
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
+ In a managed Pi session, use the injected CLI guidance for routine terminal and browser operations. Load this skill only when you need more detail.
10
+
9
11
  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
12
 
11
13
  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.
@@ -17,7 +19,16 @@ Treeport does not define task sources, planning or approval states, agent tool p
17
19
  - Do not use `eval` or an implicit `sh -lc`. Launch a shell explicitly only when the caller intentionally requests shell semantics.
18
20
  - 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
21
  - Never delete a terminal or remove a tree 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.
22
+ - Obey the daemon lifecycle reported by `treeport context`.
23
+ - When the lifecycle is `external`, never run `treeport start`, `treeport stop`, or `treeport remote enable`.
24
+ - In the external lifecycle, the parent process owns startup, shutdown, and remote exposure.
25
+ - When the lifecycle is `service`, normal `start` and `stop` delegate to the OS manager.
26
+ - 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.
27
+ - Never run bare `treeport update` for an external or selected remote daemon.
28
+ - Never invoke `sudo` for a normal service or update operation.
29
+ - Normal macOS service mode is a user/login LaunchAgent and does not need an administrator.
30
+ - Advanced headless mode is explicit.
31
+ - If an existing headless service prints an administrator command, report the command and wait for the user.
21
32
  - 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
33
 
23
34
  ## Understand the current context
@@ -28,11 +39,13 @@ Run:
28
39
  treeport context
29
40
  ```
30
41
 
31
- 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.
42
+ Inside a managed terminal, this reports the current project, tree, terminal, paths, statuses, IDs, tree context values, and daemon URL. User-supplied context can contain an issue identifier, a task description, or other information for the tree. Use these values as task input when the caller asks you to work from the tree context. 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
43
 
33
44
  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
45
 
35
- Use the exact IDs from this command for subsequent operations. `.` is a convenient shorthand for the current project or tree. Exact IDs are clearer after context is resolved.
46
+ 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.
47
+
48
+ 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.
36
49
 
37
50
  ## Create a terminal in the current tree
38
51
 
@@ -56,7 +69,6 @@ Create a linked tree and its first persistent terminal together:
56
69
 
57
70
  ```sh
58
71
  treeport spawn \
59
- --project <project-id> \
60
72
  --worktree-name <tree-name> \
61
73
  --name <terminal-name> \
62
74
  -- <program> <arg> ...
@@ -123,6 +135,60 @@ treeport terminal wait <terminal-id> --until exit
123
135
 
124
136
  Treeport does not infer agent settlement. An orchestrator can inspect first, wait for `working` if no progress cycle has been observed, and then wait for `idle`. Progress depends on the child application emitting OSC `9;4`; for Pi, `terminal.showTerminalProgress` must be enabled. Applications should clear progress or refresh active progress more frequently than the five-minute lease. A null progress value is not proof that every application supports progress reporting.
125
137
 
138
+ ## Inspect the worktree application in a browser tab
139
+
140
+ The Browser primitive has one live runtime for each browser tab.
141
+
142
+ Electron owns the visible `<webview>` page for a local desktop connection.
143
+
144
+ Playwright controls managed Chromium for a web or remote desktop connection.
145
+
146
+ Never attach Treeport to a personal browser profile.
147
+
148
+ First, inspect the available browser tabs:
149
+
150
+ ```sh
151
+ treeport browser list
152
+ ```
153
+
154
+ If no browser tab is open, open one in the current tree:
155
+
156
+ ```sh
157
+ treeport browser open --worktree .
158
+ ```
159
+
160
+ Use these commands on the current live page:
161
+
162
+ ```sh
163
+ treeport browser snapshot
164
+ treeport browser click e12
165
+ treeport browser fill e14 "value"
166
+ treeport browser press Enter
167
+ treeport browser console
168
+ treeport browser network
169
+ treeport browser screenshot
170
+ ```
171
+
172
+ The commands select the only browser tab in the current tree.
173
+
174
+ When more than one browser tab exists, add `--panel <panel-id>`.
175
+
176
+ Snapshot references belong to one runtime generation.
177
+
178
+ Take a new snapshot after navigation or a runtime change.
179
+
180
+ A local desktop owner does not need managed Chromium.
181
+
182
+ If no local owner exists, check managed Chromium before daemon automation:
183
+
184
+ ```sh
185
+ treeport browser status
186
+ ```
187
+
188
+ Ask the user before you run `treeport browser install`.
189
+
190
+ Leave the browser tab open so the user can inspect the result.
191
+
126
192
  ## Automation and integrations
127
193
 
128
194
  Extensions and scripts should add `--json` before the `--` command separator:
@@ -136,7 +202,6 @@ treeport terminal create \
136
202
  --json -- <program> <arg> ...
137
203
 
138
204
  treeport spawn \
139
- --project <project-id> \
140
205
  --worktree-name <tree-name> \
141
206
  --name <terminal-name> \
142
207
  --json -- <program> <arg> ...
@@ -1,412 +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
- z.unknown();
16
- const terminalId = z.string().min(1).max(128);
17
- const clientId = z.string().min(1).max(128);
18
- const streamId = z.string().min(1).max(128);
19
- const generation = z.number().int().nonnegative();
20
- const dimensions = {
21
- cols: z.number().int().min(2).max(1e3),
22
- rows: z.number().int().min(2).max(500)
23
- };
24
- const terminalSizeSchema = z.strictObject(dimensions);
25
- const terminalProgressSchema = z.strictObject({
26
- state: z.enum([
27
- "normal",
28
- "error",
29
- "indeterminate",
30
- "paused"
31
- ]),
32
- value: z.number().int().min(0).max(100).nullable()
33
- });
34
- const terminalProgramSchema = z.enum([
35
- "pi",
36
- "claude",
37
- "codex"
38
- ]);
39
- const terminalRuntimeMetadataSchema = z.strictObject({
40
- terminalId: z.string().min(1),
41
- title: z.string().max(256).nullable(),
42
- program: terminalProgramSchema.nullable().default(null),
43
- hasForegroundProcess: z.boolean().nullable().optional(),
44
- progress: terminalProgressSchema.nullable(),
45
- progressStartedAt: z.string().datetime().nullable().default(null),
46
- progressClearedAt: z.string().datetime().nullable().default(null),
47
- bell: z.strictObject({
48
- sequence: z.number().int().positive(),
49
- at: z.string().datetime(),
50
- unread: z.boolean()
51
- }).nullable().default(null)
52
- });
53
- const terminalBellAcknowledgementSchema = z.strictObject({ sequence: z.number().int().positive() });
54
- function parseTerminalProgress(data) {
55
- const [command, rawState, rawValue, ...extra] = data.split(";");
56
- if (command !== "4" || extra.length > 0 || !/^[0-4]$/.test(rawState ?? "")) return;
57
- const state = Number(rawState);
58
- if (state === 0) return null;
59
- if (rawValue !== void 0 && rawValue !== "" && !/^\d{1,3}$/.test(rawValue)) return;
60
- const value = rawValue === void 0 || rawValue === "" ? null : Number(rawValue);
61
- if (value !== null && value > 100) return;
62
- return {
63
- state: [
64
- void 0,
65
- "normal",
66
- "error",
67
- "indeterminate",
68
- "paused"
69
- ][state],
70
- value
71
- };
72
- }
73
- const terminalAuthSchema = z.strictObject({
74
- terminalId,
75
- clientId,
76
- ...dimensions
77
- });
78
- const terminalInputSchema = z.strictObject({
79
- generation,
80
- data: z.string().max(TERMINAL_MAX_INPUT_BYTES)
81
- });
82
- const terminalBinarySchema = z.strictObject({
83
- generation,
84
- data: z.string().max(TERMINAL_MAX_INPUT_BYTES)
85
- });
86
- const terminalResizeSchema = z.strictObject({
87
- generation,
88
- ...dimensions
89
- });
90
- const terminalTakeControlSchema = z.strictObject({
91
- generation,
92
- ...dimensions
93
- });
94
- const terminalLegacyTakeControlSchema = z.strictObject({ generation });
95
- const terminalOutputAckSchema = z.strictObject({
96
- streamId,
97
- sequence: z.number().int().nonnegative()
98
- });
99
- const terminalReadyBase = {
100
- connectionId: z.string().min(1).max(128),
101
- streamId,
102
- generation,
103
- controller: z.boolean(),
104
- reset: z.literal("full")
105
- };
106
- const terminalLegacyReadySchema = z.strictObject(terminalReadyBase);
107
- const terminalReadyV2Schema = z.strictObject({
108
- ...terminalReadyBase,
109
- ...dimensions,
110
- revision: z.number().int().positive()
111
- });
112
- z.union([terminalLegacyReadySchema, terminalReadyV2Schema]);
113
- z.strictObject({
114
- ...dimensions,
115
- revision: z.number().int().positive()
116
- });
117
- z.strictObject({
118
- streamId,
119
- sequence: z.number().int().positive(),
120
- data: z.string()
121
- });
122
- z.strictObject({ title: z.string().max(256) });
123
- z.strictObject({ progress: terminalProgressSchema.nullable() });
124
- z.strictObject({ viewing: z.boolean() });
125
- z.strictObject({
126
- generation,
127
- controller: z.boolean()
128
- });
129
- z.strictObject({ exitCode: z.number().int().nullable() });
130
- z.strictObject({
131
- code: z.string().min(1).max(80),
132
- message: z.string().min(1).max(1e3),
133
- retryable: z.boolean()
134
- });
135
- function parseTerminalAuth(value) {
136
- const parsed = terminalAuthSchema.safeParse(value);
137
- return parsed.success ? parsed.data : null;
138
- }
139
- //#endregion
140
- //#region ../../packages/shared/dist/socket-protocol.js
141
- const identifierSchema = z.string().min(1).max(128);
142
- const eventEnvelope = (type, data) => z.strictObject({
143
- id: identifierSchema,
144
- type: z.literal(type),
145
- at: z.string().datetime(),
146
- data
147
- });
148
- const projectEventDataSchema = z.strictObject({
149
- projectId: identifierSchema,
150
- worktreeId: z.null()
151
- });
152
- const worktreeEventDataSchema = z.strictObject({ worktreeId: identifierSchema });
153
- const projectWorktreeEventDataSchema = z.strictObject({
154
- projectId: identifierSchema,
155
- worktreeId: identifierSchema
156
- });
157
- const operationEventDataSchema = z.strictObject({
158
- operationId: identifierSchema,
159
- worktreeId: identifierSchema
160
- });
161
- const productEventSchema = z.discriminatedUnion("type", [
162
- eventEnvelope("project.created", projectEventDataSchema),
163
- eventEnvelope("project.updated", projectEventDataSchema),
164
- eventEnvelope("project.removed", projectEventDataSchema),
165
- eventEnvelope("worktree.created", projectWorktreeEventDataSchema),
166
- eventEnvelope("worktree.updated", worktreeEventDataSchema),
167
- eventEnvelope("worktree.removed", projectWorktreeEventDataSchema),
168
- eventEnvelope("create.started", z.strictObject({
169
- projectId: identifierSchema,
170
- operationId: identifierSchema,
171
- worktreeId: z.null()
172
- })),
173
- eventEnvelope("create.completed", z.strictObject({
174
- projectId: identifierSchema,
175
- operationId: identifierSchema,
176
- worktreeId: identifierSchema
177
- })),
178
- eventEnvelope("create.failed", z.strictObject({
179
- projectId: identifierSchema,
180
- operationId: identifierSchema,
181
- worktreeId: z.null()
182
- })),
183
- eventEnvelope("terminal.created", z.strictObject({
184
- projectId: identifierSchema.optional(),
185
- worktreeId: identifierSchema,
186
- terminalId: identifierSchema
187
- })),
188
- eventEnvelope("terminal.updated", z.strictObject({
189
- worktreeId: identifierSchema,
190
- terminalId: identifierSchema
191
- })),
192
- eventEnvelope("terminal.removed", z.strictObject({
193
- worktreeId: identifierSchema,
194
- terminalId: identifierSchema
195
- })),
196
- eventEnvelope("terminal.metadata", terminalRuntimeMetadataSchema.extend({ worktreeId: z.null() })),
197
- eventEnvelope("terminal.controller_changed", z.strictObject({
198
- terminalId: identifierSchema,
199
- controlled: z.boolean(),
200
- worktreeId: z.null()
201
- })),
202
- eventEnvelope("panel.created", z.strictObject({
203
- worktreeId: identifierSchema,
204
- panelId: identifierSchema
205
- })),
206
- eventEnvelope("panel.updated", z.strictObject({
207
- worktreeId: identifierSchema,
208
- panelId: identifierSchema
209
- })),
210
- eventEnvelope("panel.open_requested", z.strictObject({
211
- worktreeId: identifierSchema,
212
- panelId: identifierSchema,
213
- sourceTerminalId: identifierSchema.nullable()
214
- })),
215
- eventEnvelope("panel.removed", z.strictObject({
216
- worktreeId: identifierSchema,
217
- panelId: identifierSchema
218
- })),
219
- eventEnvelope("remove.started", operationEventDataSchema.extend({ kind: z.literal("remove") })),
220
- eventEnvelope("remove.completed", operationEventDataSchema),
221
- eventEnvelope("remove.failed", operationEventDataSchema.extend({ error: z.string() }))
222
- ]);
223
- const webPanelSnapshotSchema = z.strictObject({
224
- id: z.string().min(1),
225
- kind: z.literal("web"),
226
- worktreeId: z.string().min(1),
227
- definitionId: z.string().min(1),
228
- title: z.string().min(1),
229
- launch: z.strictObject({
230
- input: z.record(z.string(), z.json()).nullable(),
231
- cwd: z.string().nullable()
232
- }),
233
- sandbox: z.strictObject({ allowSameOrigin: z.boolean() }),
234
- createdAt: z.string(),
235
- updatedAt: z.string()
236
- });
237
- const eventsSnapshotSchema = z.strictObject({
238
- at: z.string().datetime(),
239
- terminalMetadata: z.array(terminalRuntimeMetadataSchema),
240
- webPanels: z.array(webPanelSnapshotSchema)
241
- });
242
- z.unknown();
243
- function parseEventsSnapshot(value) {
244
- const parsed = eventsSnapshotSchema.safeParse(value);
245
- return parsed.success ? parsed.data : null;
246
- }
247
- function parseProductEvent(value) {
248
- const parsed = productEventSchema.safeParse(value);
249
- return parsed.success ? parsed.data : null;
250
- }
251
- //#endregion
252
- //#region ../../packages/shared/dist/index.js
253
- const TERMINAL_MAX_UPLOAD_BYTES = 50 * 1024 * 1024;
254
- const TERMINAL_EXECUTABLE_MAX_LENGTH = 4096;
255
- const TERMINAL_ARGUMENT_MAX_LENGTH = 4096;
256
- const TERMINAL_CAPTURE_MAX_LINES = 5e3;
257
- const WEB_PANEL_INPUT_MAX_BYTES = 64 * 1024;
258
- const PROJECT_COLORS = [
259
- "rose",
260
- "orange",
261
- "amber",
262
- "emerald",
263
- "cyan",
264
- "blue",
265
- "violet",
266
- "pink"
267
- ];
268
- const browseDirectoryQuerySchema = z.object({
269
- input: z.string().trim().min(1).max(4096),
270
- hidden: z.enum(["true", "false"]).optional().default("false").transform((value) => value === "true")
271
- });
272
- const terminalCaptureQuerySchema = z.object({ lines: z.coerce.number().int().min(1).max(TERMINAL_CAPTURE_MAX_LINES).optional().default(200) });
273
- const registerProjectSchema = z.object({
274
- path: z.string().trim().min(1),
275
- name: z.string().trim().min(1).max(120).optional()
276
- });
277
- const updateProjectSchema = z.object({ color: z.enum(PROJECT_COLORS).nullable() });
278
- const terminalNameSchema = z.string().trim().min(1).max(120);
279
- const terminalArgvSchema = z.array(z.string()).min(1).max(128);
280
- const terminalPresetArgumentSchema = z.string().max(TERMINAL_ARGUMENT_MAX_LENGTH);
281
- const terminalPresetFields = {
282
- name: terminalNameSchema,
283
- executable: z.string().min(1).max(TERMINAL_EXECUTABLE_MAX_LENGTH).refine((value) => value.trim().length > 0, { message: "Executable cannot be blank" }),
284
- args: z.array(terminalPresetArgumentSchema).max(127),
285
- closeOnSuccess: z.boolean().default(false)
286
- };
287
- const repositoryTerminalPresetSchema = z.strictObject(terminalPresetFields);
288
- 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" });
289
- const repositoryTerminalPresetsFileSchema = z.strictObject({
290
- version: z.literal(1),
291
- presets: z.record(repositoryTerminalPresetIdSchema, z.unknown())
292
- });
293
- const terminalPresetRevisionSchema = z.string().min(1).max(64);
294
- const initialTerminalSchema = z.object({
295
- name: terminalNameSchema,
296
- argv: terminalArgvSchema.optional(),
297
- returnToShell: z.boolean().optional(),
298
- initialSize: terminalSizeSchema.optional()
299
- });
300
- const createWorktreeSchema = z.object({
301
- name: z.string().trim().min(1).max(120),
302
- base: z.enum(["default", "current"]).default("default"),
303
- sourceWorktreeId: z.string().min(1).optional(),
304
- initialTerminal: initialTerminalSchema.optional()
305
- }).superRefine((value, context) => {
306
- if (value.base === "current" && !value.sourceWorktreeId) context.addIssue({
307
- code: "custom",
308
- path: ["sourceWorktreeId"],
309
- message: "A source tree is required when starting from current"
310
- });
311
- });
312
- 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" });
313
- const terminalEnvironmentKeySchema = z.string().min(1).max(256).refine((value) => !value.includes("=") && !value.includes("\0"), { message: "Environment keys cannot contain equals or NUL" });
314
- 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" });
315
- const createTerminalSchema = z.object({
316
- name: terminalNameSchema,
317
- argv: terminalArgvSchema.optional(),
318
- cwd: terminalCwdSchema.optional(),
319
- env: terminalEnvironmentSchema.optional(),
320
- returnToShell: z.boolean().optional(),
321
- closeOnSuccess: z.boolean().optional(),
322
- initialSize: terminalSizeSchema.optional()
323
- }).refine((value) => !(value.returnToShell && value.closeOnSuccess), { message: "A terminal cannot return to a shell and close on success" });
324
- const updateTerminalSchema = z.object({ name: terminalNameSchema });
325
- const webPanelInputSchema = z.record(z.string(), z.json());
326
- const createWebPanelSchema = z.object({
327
- definitionId: z.string().min(1).max(256),
328
- input: webPanelInputSchema.nullable().optional(),
329
- launchCwd: z.string().max(4096).nullable().optional()
330
- });
331
- const openWebPanelSchema = createWebPanelSchema.extend({
332
- newInstance: z.boolean().optional(),
333
- sourceTerminalId: z.string().min(1).max(128).nullable().optional()
334
- });
335
- const webPanelStorageKeySchema = z.string().min(1).max(128);
336
- const getWebPanelStorageSchema = z.object({ key: webPanelStorageKeySchema });
337
- const setWebPanelStorageSchema = z.object({
338
- key: webPanelStorageKeySchema,
339
- value: z.json()
340
- });
341
- const deleteWebPanelStorageSchema = z.object({ key: webPanelStorageKeySchema });
342
- const createTerminalPresetSchema = z.object(terminalPresetFields);
343
- const updateTerminalPresetSchema = z.object({
344
- ...terminalPresetFields,
345
- closeOnSuccess: z.boolean().optional(),
346
- expectedUpdatedAt: terminalPresetRevisionSchema
347
- });
348
- const deleteTerminalPresetSchema = z.object({ expectedUpdatedAt: terminalPresetRevisionSchema });
349
- const packageProjectQuerySchema = z.object({ path: z.string().trim().min(1).max(4096) });
350
- const packageInstallSchema = z.object({
351
- source: z.string().trim().min(1).max(4096),
352
- projectId: z.string().min(1).optional()
353
- });
354
- const packageRemoveSchema = z.object({
355
- source: z.string().trim().min(1).max(4096),
356
- projectId: z.string().min(1).optional()
357
- });
358
- const packageUpdateSchema = z.object({ source: z.string().trim().min(1).max(4096).optional() });
359
- const packageReloadSchema = z.object({ projectId: z.string().min(1).optional() });
360
- const removeWorktreeSchema = z.object({
361
- confirmationToken: z.string().length(64),
362
- confirmDestructive: z.boolean()
363
- });
364
- z.object({
365
- project: z.string().min(1),
366
- worktreeName: z.string().trim().min(1).max(120),
367
- name: terminalNameSchema,
368
- argv: terminalArgvSchema.optional(),
369
- base: z.enum(["default", "current"]).default("default"),
370
- sourceWorktreeId: z.string().min(1).optional()
371
- }).superRefine((value, context) => {
372
- if (value.base === "current" && !value.sourceWorktreeId) context.addIssue({
373
- code: "custom",
374
- path: ["sourceWorktreeId"],
375
- message: "A source tree is required when starting from current"
376
- });
377
- });
378
- //#endregion
379
- //#region src/duration.ts
380
- const DURATION_UNITS = /* @__PURE__ */ new Map([
381
- ["ms", 1],
382
- ["s", 1e3],
383
- ["m", 6e4],
384
- ["h", 36e5]
385
- ]);
386
- const MAX_DURATION_MS = 2147483647;
387
- function parseDurationMs(value) {
388
- const match = /^(\d+)(ms|s|m|h)$/.exec(value);
389
- if (!match) throw new Error("Timeout must be a positive duration such as 500ms, 30s, 5m, or 1h");
390
- const amount = Number(match[1]);
391
- const multiplier = DURATION_UNITS.get(match[2] ?? "");
392
- if (multiplier === void 0) throw new Error("Timeout has an unsupported duration unit");
393
- const timeoutMs = amount * multiplier;
394
- if (!Number.isSafeInteger(timeoutMs) || timeoutMs <= 0 || timeoutMs > MAX_DURATION_MS) throw new Error("Timeout must be between 1ms and 2147483647ms");
395
- return timeoutMs;
396
- }
397
- //#endregion
398
- //#region src/server/core/loopback.ts
399
- const LOOPBACK_HOSTS = /* @__PURE__ */ new Set([
400
- "127.0.0.1",
401
- "::1",
402
- "localhost"
403
- ]);
404
- function isLoopbackHost(host) {
405
- return LOOPBACK_HOSTS.has(host.trim().toLowerCase());
406
- }
407
- function assertLoopbackHost(host) {
408
- if (isLoopbackHost(host)) return;
409
- 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.");
410
- }
411
- //#endregion
412
- export { terminalTakeControlSchema as $, parseEventsSnapshot as A, TERMINAL_SELECTION_CLEAR_SEQUENCE as B, repositoryTerminalPresetsFileSchema as C, updateTerminalPresetSchema as D, updateProjectSchema as E, TERMINAL_MAX_INPUT_BYTES as F, parseTerminalProgress as G, TERMINAL_SELECTION_START_SEQUENCE as H, TERMINAL_OUTPUT_HIGH_WATERMARK as I, terminalInputSchema as J, terminalBellAcknowledgementSchema as K, TERMINAL_OUTPUT_LOW_WATERMARK as L, SOCKET_IO_PATH as M, TERMINAL_CONTROLLER_GRACE_MS as N, updateTerminalSchema as O, TERMINAL_MAX_CLIENT_MESSAGE_BYTES as P, terminalSizeSchema as Q, TERMINAL_OUTPUT_STALL_TIMEOUT_MS as R, repositoryTerminalPresetSchema as S, terminalCaptureQuerySchema as T, TERMINAL_SELECTION_STOP_SEQUENCE as U, TERMINAL_SELECTION_RESTORE_SEQUENCE as V, parseTerminalAuth as W, terminalOutputAckSchema as X, terminalLegacyTakeControlSchema as Y, terminalResizeSchema 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, parseProductEvent as j, webPanelInputSchema as k, createWebPanelSchema as l, openWebPanelSchema as m, parseDurationMs as n, browseDirectoryQuerySchema as o, getWebPanelStorageSchema as p, terminalBinarySchema 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_SCROLL_EXIT_SEQUENCE as z };