@treeport/treeport 0.4.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.
- package/README.md +1 -1
- package/dist/node/cli/index.js +47 -1589
- package/dist/node/server/core/launcher.js +16 -0
- package/dist/node/server/index.js +740 -210
- package/dist/update-BW-a6Bd-.js +3107 -0
- package/dist/web/assets/index-Cr4UkmRD.js +146 -0
- package/dist/web/assets/index-he-SubzL.css +2 -0
- package/dist/web/index.html +2 -2
- package/drizzle/0008_recent_project_visibility.sql +4 -0
- package/drizzle/0009_open_folders.sql +148 -0
- package/drizzle/meta/0008_snapshot.json +792 -0
- package/drizzle/meta/0009_snapshot.json +804 -0
- package/drizzle/meta/_journal.json +14 -0
- package/package.json +3 -3
- package/skills/treeport/SKILL.md +13 -4
- package/dist/loopback-D7k_J_Wl.js +0 -412
- package/dist/web/assets/index-DCtptjcH.js +0 -146
- package/dist/web/assets/index-Wj0w0nWP.css +0 -2
|
@@ -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,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@treeport/treeport",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.0",
|
|
4
4
|
"description": "A tree-first terminal driver for persistent development workspaces.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -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.
|
|
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",
|
|
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",
|
package/skills/treeport/SKILL.md
CHANGED
|
@@ -17,7 +17,16 @@ Treeport does not define task sources, planning or approval states, agent tool p
|
|
|
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
19
|
- Never delete a terminal or remove a tree unless the user explicitly asks.
|
|
20
|
-
- Obey the daemon lifecycle reported by `treeport context`.
|
|
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
|
|
@@ -32,7 +41,9 @@ Inside a managed terminal, this reports the current project, tree, terminal, pat
|
|
|
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
|
|
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.
|
|
45
|
+
|
|
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.
|
|
36
47
|
|
|
37
48
|
## Create a terminal in the current tree
|
|
38
49
|
|
|
@@ -56,7 +67,6 @@ Create a linked tree and its first persistent terminal together:
|
|
|
56
67
|
|
|
57
68
|
```sh
|
|
58
69
|
treeport spawn \
|
|
59
|
-
--project <project-id> \
|
|
60
70
|
--worktree-name <tree-name> \
|
|
61
71
|
--name <terminal-name> \
|
|
62
72
|
-- <program> <arg> ...
|
|
@@ -136,7 +146,6 @@ treeport terminal create \
|
|
|
136
146
|
--json -- <program> <arg> ...
|
|
137
147
|
|
|
138
148
|
treeport spawn \
|
|
139
|
-
--project <project-id> \
|
|
140
149
|
--worktree-name <tree-name> \
|
|
141
150
|
--name <terminal-name> \
|
|
142
151
|
--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 };
|