@treeport/treeport 0.6.1 → 0.8.3

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.
@@ -11,19 +11,18 @@ const ZSH_DELEGATE = (file) => `if [[ -r "$TREEPORT_USER_ZDOTDIR/${file}" ]]; th
11
11
  fi
12
12
  `;
13
13
  const ZSH_INTEGRATION = `${ZSH_DELEGATE(".zshrc")}
14
- if [[ -n "$TMUX_PANE" && -n "$TREEPORT_TMUX_EXECUTABLE" ]]; then
15
- _treeport_tmux_executable=$TREEPORT_TMUX_EXECUTABLE
16
- unset TREEPORT_TMUX_EXECUTABLE
14
+ if [[ -n "$TREEPORT_SHELL_INTEGRATION" ]]; then
15
+ unset TREEPORT_SHELL_INTEGRATION
17
16
  autoload -Uz add-zsh-hook 2>/dev/null
18
17
  _treeport_command_title_preexec() {
19
18
  emulate -L zsh
20
19
  local title=\${1//[[:cntrl:]]/}
21
20
  title=\${title[1,256]}
22
- "$_treeport_tmux_executable" set-option -p -t "$TMUX_PANE" -- @treeport-command "$title" >/dev/null 2>&1
21
+ printf '\\033]777;command;%s\\033\\\\' "$title"
23
22
  }
24
23
  _treeport_command_title_precmd() {
25
24
  emulate -L zsh
26
- "$_treeport_tmux_executable" set-option -p -u -t "$TMUX_PANE" @treeport-command >/dev/null 2>&1
25
+ printf '\\033]777;command;\\033\\\\'
27
26
  }
28
27
  add-zsh-hook -d preexec _treeport_command_title_preexec 2>/dev/null
29
28
  add-zsh-hook -d precmd _treeport_command_title_precmd 2>/dev/null
@@ -36,21 +35,8 @@ unset TREEPORT_USER_ZDOTDIR
36
35
  `;
37
36
  const BASH_INTEGRATION = `[[ $- == *i* ]] || return
38
37
 
39
- _treeport_bash_injected_prompt='source "\${TREEPORT_BASH_INTEGRATION_FILE}"'
40
- _treeport_bash_remaining_prompt=\${PROMPT_COMMAND//"$_treeport_bash_injected_prompt"/}
41
- _treeport_bash_remaining_prompt=\${_treeport_bash_remaining_prompt#;}
42
- _treeport_bash_remaining_prompt=\${_treeport_bash_remaining_prompt%;}
43
- if [[ -n "\${TREEPORT_BASH_PROMPT_COMMAND_SET-}" ]]; then
44
- PROMPT_COMMAND=$TREEPORT_BASH_PROMPT_COMMAND
45
- [[ -n "$_treeport_bash_remaining_prompt" ]] && PROMPT_COMMAND="\${PROMPT_COMMAND:+$PROMPT_COMMAND;}$_treeport_bash_remaining_prompt"
46
- else
47
- PROMPT_COMMAND=$_treeport_bash_remaining_prompt
48
- fi
49
- unset TREEPORT_BASH_INTEGRATION_FILE TREEPORT_BASH_PROMPT_COMMAND TREEPORT_BASH_PROMPT_COMMAND_SET
50
- unset _treeport_bash_injected_prompt _treeport_bash_remaining_prompt
38
+ unset TREEPORT_SHELL_INTEGRATION
51
39
 
52
- _treeport_tmux_executable=$TREEPORT_TMUX_EXECUTABLE
53
- unset TREEPORT_TMUX_EXECUTABLE
54
40
  _treeport_command_title_preexec() {
55
41
  local fallback=\${1-} line title
56
42
  line=$(HISTTIMEFORMAT= builtin history 1)
@@ -60,13 +46,10 @@ _treeport_command_title_preexec() {
60
46
  [[ -n "$title" ]] || title=$fallback
61
47
  title=$(LC_ALL=C printf '%s' "$title" | tr -d '\\000-\\037\\177')
62
48
  title="\${title:0:256}"
63
- [[ -n "$TMUX_PANE" && -n "$_treeport_tmux_executable" ]] || return
64
- "$_treeport_tmux_executable" set-option -p -t "$TMUX_PANE" -- @treeport-command "$title" >/dev/null 2>&1
49
+ printf '\\033]777;command;%s\\033\\\\' "$title"
65
50
  }
66
51
  _treeport_command_title_prompt() {
67
- if [[ -n "$TMUX_PANE" && -n "$_treeport_tmux_executable" ]]; then
68
- "$_treeport_tmux_executable" set-option -p -u -t "$TMUX_PANE" @treeport-command >/dev/null 2>&1
69
- fi
52
+ printf '\\033]777;command;\\033\\\\'
70
53
  [[ -n "\${_treeport_uses_debug_trap-}" ]] && _treeport_command_ready=1
71
54
  }
72
55
 
@@ -94,6 +77,26 @@ if [[ -n "\${_treeport_uses_debug_trap-}" ]]; then
94
77
  _treeport_command_ready=1
95
78
  fi
96
79
  `;
80
+ const BASH_PROFILE_DELEGATE = `_treeport_integration_home=$HOME
81
+ HOME=$TREEPORT_USER_HOME
82
+ unset TREEPORT_USER_HOME
83
+ if [[ -r "$HOME/.bash_profile" ]]; then
84
+ source "$HOME/.bash_profile"
85
+ elif [[ -r "$HOME/.bash_login" ]]; then
86
+ source "$HOME/.bash_login"
87
+ elif [[ -r "$HOME/.profile" ]]; then
88
+ source "$HOME/.profile"
89
+ fi
90
+ source "$_treeport_integration_home/../treeport.bash"
91
+ unset _treeport_integration_home
92
+ `;
93
+ const BASH_RC_DELEGATE = `_treeport_integration_home=$HOME
94
+ HOME=$TREEPORT_USER_HOME
95
+ unset TREEPORT_USER_HOME
96
+ [[ -r "$HOME/.bashrc" ]] && source "$HOME/.bashrc"
97
+ source "$_treeport_integration_home/../treeport.bash"
98
+ unset _treeport_integration_home
99
+ `;
97
100
  const FISH_INTEGRATION = `if set -q TREEPORT_FISH_XDG_DATA_DIR
98
101
  if set -q TREEPORT_FISH_XDG_DATA_DIRS_SET
99
102
  set -l treeport_xdg_dirs
@@ -108,32 +111,28 @@ const FISH_INTEGRATION = `if set -q TREEPORT_FISH_XDG_DATA_DIR
108
111
  end
109
112
  set -e TREEPORT_FISH_XDG_DATA_DIR TREEPORT_FISH_XDG_DATA_DIRS_SET
110
113
  end
111
- set -g _treeport_tmux_executable "$TREEPORT_TMUX_EXECUTABLE"
112
- set -e TREEPORT_TMUX_EXECUTABLE
114
+ set -e TREEPORT_SHELL_INTEGRATION
113
115
 
114
116
  function _treeport_command_title_preexec --on-event fish_preexec
115
117
  set -l title (string replace -ar '[[:cntrl:]]' '' -- "$argv[1]" | string sub -l 256)
116
- if test -n "$TMUX_PANE"; and test -n "$_treeport_tmux_executable"
117
- command "$_treeport_tmux_executable" set-option -p -t "$TMUX_PANE" -- @treeport-command "$title" >/dev/null 2>&1
118
- end
118
+ printf '\\e]777;command;%s\\e\\\\' "$title"
119
119
  end
120
120
 
121
121
  function _treeport_command_title_prompt --on-event fish_prompt
122
- if test -n "$TMUX_PANE"; and test -n "$_treeport_tmux_executable"
123
- command "$_treeport_tmux_executable" set-option -p -u -t "$TMUX_PANE" @treeport-command >/dev/null 2>&1
124
- end
122
+ printf '\\e]777;command;\\e\\\\'
125
123
  end
126
124
  `;
127
125
  async function prepareShellIntegration(root) {
128
126
  const zshDir = path.join(root, "zsh");
129
127
  const bashDir = path.join(root, "bash");
128
+ const bashHome = path.join(bashDir, "home");
130
129
  const fishDir = path.join(root, "fish", "fish", "vendor_conf.d");
131
130
  await Promise.all([
132
131
  fs.mkdir(zshDir, {
133
132
  recursive: true,
134
133
  mode: 448
135
134
  }),
136
- fs.mkdir(bashDir, {
135
+ fs.mkdir(bashHome, {
137
136
  recursive: true,
138
137
  mode: 448
139
138
  }),
@@ -151,12 +150,14 @@ async function prepareShellIntegration(root) {
151
150
  ].map((file) => fs.writeFile(path.join(zshDir, file), ZSH_DELEGATE(file), { mode: 384 })),
152
151
  fs.writeFile(path.join(zshDir, ".zshrc"), ZSH_INTEGRATION, { mode: 384 }),
153
152
  fs.writeFile(path.join(bashDir, "treeport.bash"), BASH_INTEGRATION, { mode: 384 }),
153
+ fs.writeFile(path.join(bashHome, ".bash_profile"), BASH_PROFILE_DELEGATE, { mode: 384 }),
154
+ fs.writeFile(path.join(bashHome, ".bashrc"), BASH_RC_DELEGATE, { mode: 384 }),
154
155
  fs.writeFile(path.join(fishDir, "treeport.fish"), FISH_INTEGRATION, { mode: 384 })
155
156
  ]);
156
157
  }
157
- function integrateShellLaunch(argv, env, root, tmuxExecutable) {
158
+ function integrateShellLaunch(argv, env, root, enabled) {
158
159
  const shell = path.basename(argv[0] ?? "").replace(/^-/, "");
159
- if (!root || !tmuxExecutable || ![
160
+ if (!root || !enabled || ![
160
161
  "zsh",
161
162
  "bash",
162
163
  "fish"
@@ -188,7 +189,7 @@ function integrateShellLaunch(argv, env, root, tmuxExecutable) {
188
189
  }
189
190
  const integratedEnv = {
190
191
  ...env,
191
- TREEPORT_TMUX_EXECUTABLE: tmuxExecutable
192
+ TREEPORT_SHELL_INTEGRATION: "1"
192
193
  };
193
194
  if (shell === "zsh") {
194
195
  const integrationZdotDir = path.join(root, "zsh");
@@ -239,19 +240,18 @@ function integrateShellLaunch(argv, env, root, tmuxExecutable) {
239
240
  env
240
241
  };
241
242
  }
242
- const integrationFile = path.join(root, "bash", "treeport.bash");
243
- const bashEnvironment = {
244
- ...integratedEnv,
245
- TREEPORT_BASH_INTEGRATION_FILE: integrationFile,
246
- PROMPT_COMMAND: "source \"${TREEPORT_BASH_INTEGRATION_FILE}\""
243
+ const userHome = env.HOME?.trim();
244
+ if (!userHome) return {
245
+ argv,
246
+ env
247
247
  };
248
- if (env.PROMPT_COMMAND !== void 0) {
249
- bashEnvironment.TREEPORT_BASH_PROMPT_COMMAND_SET = "1";
250
- bashEnvironment.TREEPORT_BASH_PROMPT_COMMAND = env.PROMPT_COMMAND;
251
- }
252
248
  return {
253
249
  argv,
254
- env: bashEnvironment
250
+ env: {
251
+ ...integratedEnv,
252
+ HOME: path.join(root, "bash", "home"),
253
+ TREEPORT_USER_HOME: userHome
254
+ }
255
255
  };
256
256
  }
257
257
  //#endregion
@@ -0,0 +1,378 @@
1
+ import path from "node:path";
2
+ import * as Layer from "effect/Layer";
3
+ import * as Effect from "effect/Effect";
4
+ import fsSync from "node:fs";
5
+ import { z } from "zod";
6
+ import * as Exit from "effect/Exit";
7
+ import * as Cause from "effect/Cause";
8
+ import * as Option from "effect/Option";
9
+ import * as Tracer from "effect/Tracer";
10
+ import * as ManagedRuntime from "effect/ManagedRuntime";
11
+ import { NodeSdk } from "@effect/opentelemetry";
12
+ import { BatchSpanProcessor } from "@opentelemetry/sdk-trace-base";
13
+ //#region src/server/tracing.ts
14
+ const SAFE_ATTRIBUTE_NAMES = /* @__PURE__ */ new Set([
15
+ "http.request.method",
16
+ "http.response.status_code",
17
+ "network.protocol",
18
+ "url.path",
19
+ "treeport.channel",
20
+ "treeport.client.id",
21
+ "treeport.connection.id",
22
+ "treeport.mutation.coordinator",
23
+ "treeport.mutation.queue_wait_ms",
24
+ "treeport.mutation.queued_ahead",
25
+ "treeport.panel.id",
26
+ "treeport.request.id",
27
+ "treeport.terminal.id",
28
+ "treeport.terminal.launch_kind",
29
+ "treeport.terminal.pending_output_bytes",
30
+ "treeport.terminal.snapshot_bytes",
31
+ "treeport.terminal_host.method",
32
+ "treeport.terminal_host.queue_wait_ms",
33
+ "treeport.worktree.id"
34
+ ]);
35
+ function tracingDestination(environment = process.env) {
36
+ if (environment.TREEPORT_TRACE !== "jsonl") return null;
37
+ const configuredPath = environment.TREEPORT_TRACE_FILE?.trim();
38
+ if (configuredPath && !path.isAbsolute(configuredPath)) throw new Error("TREEPORT_TRACE_FILE must be an absolute path");
39
+ return { filePath: configuredPath || null };
40
+ }
41
+ function safeAttributes(attributes) {
42
+ const result = {};
43
+ for (const [name, value] of Object.entries(attributes)) {
44
+ if (!SAFE_ATTRIBUTE_NAMES.has(name)) continue;
45
+ if (typeof value === "string") result[name] = value.slice(0, 512);
46
+ else if (typeof value === "number" || typeof value === "boolean") result[name] = value;
47
+ }
48
+ return result;
49
+ }
50
+ function hrTimeMilliseconds(value) {
51
+ return value[0] * 1e3 + value[1] / 1e6;
52
+ }
53
+ var JsonLinesSpanExporter = class {
54
+ serviceName;
55
+ descriptor;
56
+ closed = false;
57
+ constructor(serviceName, destination) {
58
+ this.serviceName = serviceName;
59
+ if (destination.filePath) {
60
+ fsSync.mkdirSync(path.dirname(destination.filePath), {
61
+ recursive: true,
62
+ mode: 448
63
+ });
64
+ this.descriptor = fsSync.openSync(destination.filePath, "a", 384);
65
+ fsSync.chmodSync(destination.filePath, 384);
66
+ } else this.descriptor = null;
67
+ }
68
+ export(spans, resultCallback) {
69
+ if (this.closed) {
70
+ resultCallback({ code: 1 });
71
+ return;
72
+ }
73
+ try {
74
+ for (const span of spans) {
75
+ const context = span.spanContext();
76
+ const record = {
77
+ type: "treeport.trace.span",
78
+ timestamp: new Date(hrTimeMilliseconds(span.startTime)).toISOString(),
79
+ service: this.serviceName,
80
+ traceId: context.traceId,
81
+ spanId: context.spanId,
82
+ parentSpanId: span.parentSpanContext?.spanId ?? null,
83
+ name: span.name,
84
+ kind: span.kind,
85
+ durationMs: Number(hrTimeMilliseconds(span.duration).toFixed(3)),
86
+ status: span.status.code,
87
+ attributes: safeAttributes(span.attributes)
88
+ };
89
+ const line = `${JSON.stringify(record)}\n`;
90
+ if (this.descriptor === null) process.stderr.write(line);
91
+ else fsSync.writeSync(this.descriptor, line);
92
+ }
93
+ resultCallback({ code: 0 });
94
+ } catch (error) {
95
+ resultCallback({
96
+ code: 1,
97
+ error: error instanceof Error ? error : new Error(String(error))
98
+ });
99
+ }
100
+ }
101
+ async forceFlush() {
102
+ if (this.descriptor !== null && !this.closed) fsSync.fsyncSync(this.descriptor);
103
+ }
104
+ async shutdown() {
105
+ if (this.closed) return;
106
+ await this.forceFlush();
107
+ this.closed = true;
108
+ if (this.descriptor !== null) fsSync.closeSync(this.descriptor);
109
+ }
110
+ };
111
+ function makeTracingLayer(options) {
112
+ if (!options.destination) return Layer.empty;
113
+ const exporter = new JsonLinesSpanExporter(options.serviceName, options.destination);
114
+ return NodeSdk.layer(() => ({
115
+ resource: {
116
+ serviceName: options.serviceName,
117
+ serviceVersion: options.serviceVersion
118
+ },
119
+ spanProcessor: new BatchSpanProcessor(exporter, {
120
+ maxQueueSize: 2048,
121
+ maxExportBatchSize: 256,
122
+ scheduledDelayMillis: 250
123
+ }),
124
+ shutdownTimeout: "5 seconds"
125
+ }));
126
+ }
127
+ function tracingLayerFromEnvironment(serviceName, serviceVersion, environment = process.env) {
128
+ return makeTracingLayer({
129
+ serviceName,
130
+ serviceVersion,
131
+ destination: tracingDestination(environment)
132
+ });
133
+ }
134
+ function tracingEnabled(environment = process.env) {
135
+ return tracingDestination(environment) !== null;
136
+ }
137
+ const currentTraceContext = tracingEnabled() ? Effect.option(Effect.currentSpan).pipe(Effect.map(Option.match({
138
+ onNone: () => null,
139
+ onSome: (span) => ({
140
+ traceId: span.traceId,
141
+ spanId: span.spanId,
142
+ sampled: span.sampled
143
+ })
144
+ }))) : Effect.succeed(null);
145
+ function makeHostTraceRuntime(serviceVersion) {
146
+ if (!tracingEnabled()) return null;
147
+ const runtime = ManagedRuntime.make(tracingLayerFromEnvironment("treeport-terminal-host", serviceVersion));
148
+ return {
149
+ async run(name, parent, attributes, evaluate) {
150
+ const exit = await runtime.runPromiseExit(Effect.tryPromise({
151
+ try: evaluate,
152
+ catch: (cause) => cause
153
+ }).pipe(Effect.withSpan(name, {
154
+ parent: Tracer.externalSpan({
155
+ traceId: parent.traceId,
156
+ spanId: parent.spanId,
157
+ sampled: parent.sampled
158
+ }),
159
+ attributes
160
+ })));
161
+ if (Exit.isSuccess(exit)) return exit.value;
162
+ const failure = Cause.failureOption(exit.cause);
163
+ if (Option.isSome(failure)) throw failure.value;
164
+ throw Cause.squash(exit.cause);
165
+ },
166
+ dispose() {
167
+ return runtime.dispose();
168
+ }
169
+ };
170
+ }
171
+ //#endregion
172
+ //#region src/server/terminal-host-protocol.ts
173
+ const TERMINAL_HOST_MAX_FRAME_BYTES = 64 * 1024 * 1024;
174
+ const terminalHostRecordSchema = z.object({
175
+ protocolVersion: z.number().int().positive(),
176
+ hostId: z.string().min(1),
177
+ hostKey: z.string().min(1),
178
+ pid: z.number().int().positive(),
179
+ socketPath: z.string().min(1),
180
+ startedAt: z.string().min(1)
181
+ }).strict();
182
+ const terminalSizeSchema = z.object({
183
+ cols: z.number().int().positive(),
184
+ rows: z.number().int().positive()
185
+ }).strict();
186
+ const terminalIdSchema = z.object({ terminalId: z.string().min(1) }).strict();
187
+ const worktreeIdSchema = z.object({ worktreeId: z.string().min(1) }).strict();
188
+ const setupTaskSchema = z.object({
189
+ label: z.string(),
190
+ argv: z.array(z.string()),
191
+ cwd: z.string(),
192
+ env: z.record(z.string(), z.string()),
193
+ timeoutMs: z.number().positive()
194
+ }).strict();
195
+ const createSchema = z.object({
196
+ terminalId: z.string().min(1),
197
+ worktreeId: z.string().min(1),
198
+ name: z.string(),
199
+ createdAt: z.string(),
200
+ cwd: z.string(),
201
+ argv: z.array(z.string()),
202
+ initialTitle: z.string().optional(),
203
+ shellCommand: z.string().nullable(),
204
+ interactiveShell: z.boolean(),
205
+ fallbackArgv: z.array(z.string()).optional(),
206
+ closeOnSuccess: z.boolean().optional(),
207
+ initialSize: terminalSizeSchema.optional(),
208
+ env: z.record(z.string(), z.string()),
209
+ setupTasks: z.array(setupTaskSchema).optional(),
210
+ setupError: z.string().optional()
211
+ }).strict();
212
+ const terminalHostInputSchemas = {
213
+ handshake: z.object({
214
+ token: z.string(),
215
+ hostKey: z.string(),
216
+ protocolVersion: z.number().int()
217
+ }).strict(),
218
+ create: createSchema,
219
+ inventory: worktreeIdSchema,
220
+ state: terminalIdSchema,
221
+ attach: terminalIdSchema,
222
+ unsubscribeOutput: terminalIdSchema,
223
+ subscribeRuntime: terminalIdSchema,
224
+ unsubscribeRuntime: terminalIdSchema,
225
+ runtimeState: terminalIdSchema,
226
+ write: z.object({
227
+ terminalId: z.string(),
228
+ data: z.string(),
229
+ encoding: z.enum(["utf8", "base64"]),
230
+ authority: z.object({
231
+ attachmentId: z.string(),
232
+ generation: z.number().int().positive()
233
+ }).strict()
234
+ }).strict(),
235
+ prepareQueryAuthority: terminalIdSchema,
236
+ activateQueryAuthority: terminalIdSchema.extend({
237
+ transitionId: z.string(),
238
+ attachmentId: z.string(),
239
+ generation: z.number().int().positive()
240
+ }).strict(),
241
+ hostQueryAuthority: terminalIdSchema,
242
+ resize: terminalIdSchema.extend({
243
+ cols: z.number().int().positive(),
244
+ rows: z.number().int().positive()
245
+ }).strict(),
246
+ capture: terminalIdSchema.extend({ lines: z.number().int().positive() }).strict(),
247
+ rename: terminalIdSchema.extend({
248
+ name: z.string(),
249
+ updatedAt: z.string()
250
+ }).strict(),
251
+ processes: worktreeIdSchema,
252
+ titleState: terminalIdSchema,
253
+ signal: terminalIdSchema.extend({ signal: z.enum([
254
+ "SIGINT",
255
+ "SIGTERM",
256
+ "SIGKILL",
257
+ "SIGHUP"
258
+ ]) }).strict(),
259
+ kill: terminalIdSchema,
260
+ killWorktree: worktreeIdSchema,
261
+ shutdown: z.object({ ifEmpty: z.literal(true) }).strict()
262
+ };
263
+ const TERMINAL_HOST_REQUEST_METHODS = [
264
+ "handshake",
265
+ "create",
266
+ "inventory",
267
+ "state",
268
+ "attach",
269
+ "unsubscribeOutput",
270
+ "subscribeRuntime",
271
+ "unsubscribeRuntime",
272
+ "runtimeState",
273
+ "write",
274
+ "prepareQueryAuthority",
275
+ "activateQueryAuthority",
276
+ "hostQueryAuthority",
277
+ "resize",
278
+ "capture",
279
+ "rename",
280
+ "processes",
281
+ "titleState",
282
+ "signal",
283
+ "kill",
284
+ "killWorktree",
285
+ "shutdown"
286
+ ];
287
+ const runtimeEventSchema = z.object({
288
+ title: z.string().optional(),
289
+ progress: z.strictObject({
290
+ state: z.enum([
291
+ "normal",
292
+ "error",
293
+ "indeterminate",
294
+ "paused"
295
+ ]),
296
+ value: z.number().int().min(0).max(100).nullable()
297
+ }).nullable().optional(),
298
+ bell: z.object({
299
+ sequence: z.number().int().positive(),
300
+ at: z.string().datetime()
301
+ }).strict().optional(),
302
+ exitCode: z.number().int().nullable().optional(),
303
+ titleState: z.object({
304
+ terminalTitle: z.string().nullable(),
305
+ currentCommand: z.string().nullable(),
306
+ commandLine: z.string().nullable()
307
+ }).strict().optional()
308
+ }).strict();
309
+ const terminalHostFrameSchema = z.union([
310
+ z.object({
311
+ protocolVersion: z.number().int(),
312
+ type: z.literal("request"),
313
+ id: z.string(),
314
+ method: z.enum(TERMINAL_HOST_REQUEST_METHODS),
315
+ input: z.record(z.string(), z.unknown()),
316
+ trace: z.object({
317
+ traceId: z.string().regex(/^[0-9a-f]{32}$/),
318
+ spanId: z.string().regex(/^[0-9a-f]{16}$/),
319
+ sampled: z.boolean()
320
+ }).strict().optional()
321
+ }).strict(),
322
+ z.object({
323
+ protocolVersion: z.number().int(),
324
+ type: z.literal("response"),
325
+ id: z.string(),
326
+ result: z.any().optional(),
327
+ error: z.object({
328
+ code: z.string(),
329
+ message: z.string(),
330
+ hostProtocolVersion: z.number().int().optional(),
331
+ liveSessionCount: z.number().int().nonnegative().optional()
332
+ }).strict().nullable()
333
+ }).strict(),
334
+ z.object({
335
+ protocolVersion: z.number().int(),
336
+ type: z.literal("event"),
337
+ event: z.literal("output"),
338
+ data: z.object({
339
+ terminalId: z.string(),
340
+ output: z.string(),
341
+ sequence: z.number().int().positive()
342
+ }).strict()
343
+ }).strict(),
344
+ z.object({
345
+ protocolVersion: z.number().int(),
346
+ type: z.literal("event"),
347
+ event: z.literal("runtime"),
348
+ data: z.object({
349
+ terminalId: z.string(),
350
+ value: runtimeEventSchema
351
+ }).strict()
352
+ }).strict()
353
+ ]);
354
+ function encodeTerminalHostFrame(frame) {
355
+ const payload = Buffer.from(JSON.stringify(frame), "utf8");
356
+ if (payload.byteLength > TERMINAL_HOST_MAX_FRAME_BYTES) throw new Error("Terminal host frame exceeds the byte limit");
357
+ const header = Buffer.allocUnsafe(4);
358
+ header.writeUInt32BE(payload.byteLength);
359
+ return Buffer.concat([header, payload]);
360
+ }
361
+ var TerminalHostFrameDecoder = class {
362
+ buffer = Buffer.alloc(0);
363
+ push(chunk) {
364
+ this.buffer = this.buffer.byteLength ? Buffer.concat([this.buffer, chunk]) : chunk;
365
+ const frames = [];
366
+ while (this.buffer.byteLength >= 4) {
367
+ const length = this.buffer.readUInt32BE(0);
368
+ if (length <= 0 || length > TERMINAL_HOST_MAX_FRAME_BYTES) throw new Error("Invalid terminal host frame length");
369
+ if (this.buffer.byteLength < length + 4) break;
370
+ const payload = this.buffer.subarray(4, length + 4);
371
+ this.buffer = this.buffer.subarray(length + 4);
372
+ frames.push(terminalHostFrameSchema.parse(JSON.parse(payload.toString("utf8"))));
373
+ }
374
+ return frames;
375
+ }
376
+ };
377
+ //#endregion
378
+ export { currentTraceContext as a, terminalHostRecordSchema as i, encodeTerminalHostFrame as n, makeHostTraceRuntime as o, terminalHostInputSchemas as r, tracingLayerFromEnvironment as s, TerminalHostFrameDecoder as t };