maoda-commander-tt 0.0.63 → 0.0.64

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 CHANGED
@@ -114,19 +114,19 @@ revision,不回显 value。
114
114
 
115
115
  ## 后台启动 Codex
116
116
 
117
- `tt codex`、`tt ai run` 和本地图片 worker 共用可执行文件查找顺序:
117
+ `tt codex`、`tt codex-exec` 和本地图片 worker 共用可执行文件查找顺序:
118
118
  `/Applications/ChatGPT.app/Contents/Resources/codex` →
119
119
  `/Applications/Codex.app/Contents/Resources/codex` → PATH 中的 `codex`。
120
120
  App 内路径不存在、不是文件或不可执行时跳到下一项;启动后的执行失败不重试下一项。
121
121
 
122
122
  ```bash
123
123
  tt codex "我的具体 prompt"
124
- tt codex -C /path/to/repo -m gpt-5.6-sol -r ultra "我的具体 prompt"
124
+ tt codex -C /path/to/repo -m gpt-6-astra -r high "我的具体 prompt"
125
125
  tt codex --help
126
126
  ```
127
127
 
128
- 默认工作目录 `/Users/bytedance/work/autogen`,默认模型 `gpt-6-astra`,默认推理强度
129
- `high`。模型可选 `gpt-6-astra`、`gpt-5.6-sol`;推理强度可选
128
+ 默认工作目录 `/Users/bytedance/work/autogen`,默认模型 `gpt-6-sol`,默认推理强度
129
+ `ultra`。模型可选 `gpt-6-sol`、`gpt-6-astra`、`gpt-5.6-sol`;推理强度可选
130
130
  `low`、`medium`、`high`、`xhigh`、`max`、`ultra`。
131
131
 
132
132
  macOS/Linux 下通过 `nohup` 启动后台 worker,由 worker 运行 `codex app-server`,
@@ -146,27 +146,27 @@ App 可发现 app-server 会话,但 App 侧边栏是否按项目分组还取
146
146
  项目归属同步。服务端绑定 projectId 不等同于旧版 App 侧边栏已同步;tt 不修改 App
147
147
  私有状态文件或数据库来强制分组。
148
148
 
149
- ## 后台启动 Traex
149
+ ## 同步执行 Codex
150
150
 
151
151
  ```bash
152
- tt traex "我的具体 prompt"
153
- tt traex -C /path/to/repo -m gpt-6-astra -r high "我的具体 prompt"
154
- tt traex --help
152
+ tt codex-exec "我的具体 prompt"
153
+ tt codex-exec -C /path/to/workdir -m gpt-6-astra -r high --json "我的具体 prompt"
154
+ tt codex-exec --help
155
155
  ```
156
156
 
157
- 默认目录 `/Users/bytedance/work/autogen`,默认模型 `gpt-5.6-sol`,默认推理强度
158
- `xhigh`。模型可选 `gpt-5.6-sol`、`gpt-6-astra`;推理强度按 Traex
159
- 支持范围提供 `low`、`medium`、`high`、`xhigh`。需要本机已安装并登录 `traex`。
157
+ `tt codex-exec` 直接运行 `codex exec`,等待本轮完成后返回。参数与 `tt codex` 对齐:
158
+ 完整非空提示词必填,`-m/--model` 默认 `gpt-6-sol`,`-r/--reasoning` 默认 `ultra`,
159
+ 模型与推理强度使用相同枚举。未传 `-C/--cd` 时,每次在系统临时目录下新建独立空目录作为工作目录,
160
+ 成功、失败或 Ctrl-C 结束后删除目录及其中全部文件产物。需要保留文件必须指定 `-C`,
161
+ 显式指定的目录及产物保留;路径必须非空且已存在,可指定空目录,无需 Git 仓库。
162
+ 相对路径基于调用目录解析,不存在的目录直接报错。
160
163
 
161
- 与 `tt codex` 一样,通过 `nohup` 后台 worker 运行 `traex app-server`,固定
162
- `danger-full-access` 和 `never`,收到 `turn/start` 确认后立即返回一行 JSON。
163
- 保留本机 Traex 配置、登录态及会话持久化,终端 IO 丢弃,不生成任务日志,
164
- 不提供任务跟踪。后台 worker 保持连接到本轮结束后退出。
165
-
166
- 返回 `status: "launched"`、worker `pid`、`threadId`、`turnId`、`cwd`、`model`、
167
- `reasoning` 和 `projectId: null`。Traex 暂不支持项目接口,因此仅传工作目录,
168
- 不调用 `project/list` 或传入 `thread/start.projectId`。App 显示及项目分组可能
169
- 延迟,`launched` 只代表服务端已接受任务,不代表执行完成或已在 App 中显示。
164
+ 无沙箱且不请求审批,继承本机 Codex 配置、登录态与会话持久化,不保证 App 项目归属。
165
+ 普通模式 stdout 透传原生最终回答文本,stderr 透传原生执行过程。
166
+ `--json` 将 stdout 切换为 Codex 原生 JSONL 事件流,stderr 为诊断。
167
+ 不添加 tt envelope、事件包装或心跳,等待原生执行结束并保留其退出码。
168
+ tt 参数校验、启动或清理失败写入 stderr,退出码为 1;清理失败不撤回已透传到 stdout 的内容。
169
+ Ctrl-C 终止本次执行,显式 `-C` 中已产生的改动不回滚;SIGKILL 或进程崩溃无法保证临时目录清理。
170
170
 
171
171
  ## 发布到 npm
172
172
 
@@ -377,15 +377,6 @@ loopback HTTP 除外),客户端不跟随重定向,以免将 token 发送
377
377
  若公开目标已删除,但目录清单刷新或私有暂存清理失败,命令返回错误和非零退出码,
378
378
  同时保留 `data.state: "deleted"`;AI 应据此排查后续步骤,不能把它理解为目标仍在。
379
379
 
380
- ## Shell 快捷方式
381
-
382
- ```bash
383
- # 在 ~/work/web-proxy 中先执行 w2 start,成功后执行 pnpm gateway
384
- tt sc w2
385
- ```
386
-
387
- 命令日志直接输出到当前终端,gateway 在前台运行。
388
-
389
380
  ## AI 图片生成
390
381
 
391
382
  图片、音频与视频统一采用异步提交:默认返回 `taskId`,`status` 单次查询,
@@ -211,16 +211,87 @@ function describeSignal(signal) {
211
211
  return signal ? `, signal: ${signal}` : "";
212
212
  }
213
213
 
214
- // src/bedrock/process/detached-process.ts
214
+ // src/bedrock/process/passthrough-process.ts
215
+ import { spawn as spawn4 } from "node:child_process";
216
+ import { constants } from "node:os";
215
217
  import { err as err4, ok as ok4 } from "rockbed/error";
218
+ var FORWARDED_SIGNALS = ["SIGINT", "SIGTERM", "SIGHUP"];
219
+ var TERMINATION_GRACE_MS = 2e3;
220
+ function runPassthroughProcess(command, args, options = {}) {
221
+ return new Promise((resolve) => {
222
+ let child;
223
+ try {
224
+ child = spawn4(command, [...args], {
225
+ cwd: options.cwd,
226
+ env: options.env ? { ...process.env, ...options.env } : process.env,
227
+ shell: false,
228
+ stdio: [options.input === void 0 ? "ignore" : "pipe", "inherit", "inherit"]
229
+ });
230
+ } catch (error) {
231
+ resolve(err4(1, `\u542F\u52A8\u5B50\u8FDB\u7A0B\u5931\u8D25${describeErrorCode(error)}`));
232
+ return;
233
+ }
234
+ let failure;
235
+ let brokenInput = false;
236
+ let closed = false;
237
+ let killTimer;
238
+ const isRunning = () => child.pid !== void 0 && child.exitCode === null && child.signalCode === null;
239
+ const stop = (signal = "SIGTERM") => {
240
+ if (closed || !isRunning()) return;
241
+ if (!killTimer) {
242
+ killTimer = setTimeout(() => {
243
+ if (isRunning()) child.kill("SIGKILL");
244
+ }, TERMINATION_GRACE_MS);
245
+ }
246
+ child.kill(signal);
247
+ };
248
+ const fail = (message) => {
249
+ failure ??= err4(1, message);
250
+ stop();
251
+ };
252
+ const signalHandlers = FORWARDED_SIGNALS.map((signal) => {
253
+ const handler = () => stop(signal);
254
+ process.on(signal, handler);
255
+ return { signal, handler };
256
+ });
257
+ child.on("error", (error) => fail(`\u5B50\u8FDB\u7A0B\u6267\u884C\u5931\u8D25${describeErrorCode(error)}`));
258
+ child.on("exit", () => clearTimeout(killTimer));
259
+ child.on("close", (code, signal) => {
260
+ closed = true;
261
+ clearTimeout(killTimer);
262
+ for (const { signal: parentSignal, handler } of signalHandlers) process.off(parentSignal, handler);
263
+ const exitCode = code ?? (signal ? 128 + constants.signals[signal] : 1);
264
+ if (!failure && brokenInput && exitCode === 0) failure = err4(1, "\u5199\u5165\u5B50\u8FDB\u7A0B stdin \u5931\u8D25 (EPIPE)");
265
+ resolve(failure ?? ok4({ exitCode }));
266
+ });
267
+ child.stdin?.on("error", (error) => {
268
+ if (error.code === "EPIPE") brokenInput = true;
269
+ else fail(`\u5199\u5165\u5B50\u8FDB\u7A0B stdin \u5931\u8D25${describeErrorCode(error)}`);
270
+ });
271
+ if (options.input !== void 0) {
272
+ try {
273
+ child.stdin?.end(options.input);
274
+ } catch (error) {
275
+ fail(`\u5199\u5165\u5B50\u8FDB\u7A0B stdin \u5931\u8D25${describeErrorCode(error)}`);
276
+ }
277
+ }
278
+ });
279
+ }
280
+ function describeErrorCode(error) {
281
+ if (!error || typeof error !== "object" || !("code" in error)) return "";
282
+ return typeof error.code === "string" && /^[A-Z][A-Z0-9_]*$/.test(error.code) ? ` (${error.code})` : "";
283
+ }
216
284
 
217
- // src/bedrock/process/detached-worker.ts
218
- import { spawn as spawn4 } from "node:child_process";
285
+ // src/bedrock/process/detached-process.ts
219
286
  import { err as err5, ok as ok5 } from "rockbed/error";
287
+
288
+ // src/bedrock/process/detached-worker.ts
289
+ import { spawn as spawn5 } from "node:child_process";
290
+ import { err as err6, ok as ok6 } from "rockbed/error";
220
291
  function startDetachedWorker(args, options) {
221
- if (process.platform === "win32") return Promise.resolve(err5(1, "\u540E\u53F0 nohup \u542F\u52A8\u4EC5\u652F\u6301 macOS/Linux"));
292
+ if (process.platform === "win32") return Promise.resolve(err6(1, "\u540E\u53F0 nohup \u542F\u52A8\u4EC5\u652F\u6301 macOS/Linux"));
222
293
  return new Promise((resolve) => {
223
- const child = spawn4("nohup", [process.execPath, ...args], {
294
+ const child = spawn5("nohup", [process.execPath, ...args], {
224
295
  cwd: options.cwd,
225
296
  detached: true,
226
297
  stdio: ["ignore", "ignore", "ignore", "ipc"],
@@ -235,14 +306,14 @@ function startDetachedWorker(args, options) {
235
306
  child.unref();
236
307
  resolve(result);
237
308
  };
238
- const timer = setTimeout(() => finish(err5(1, "\u7B49\u5F85\u540E\u53F0\u63D0\u4EA4\u786E\u8BA4\u8D85\u65F6\uFF1B\u4EFB\u52A1\u53EF\u80FD\u5DF2\u521B\u5EFA\uFF0C\u8BF7\u5148\u5728\u5BF9\u5E94 App \u4E2D\u68C0\u67E5\uFF0C\u52FF\u76F4\u63A5\u91CD\u8BD5")), options.readyTimeoutMs ?? 45e3);
239
- child.once("error", (error) => finish(err5(1, `\u540E\u53F0\u542F\u52A8\u5931\u8D25: ${error.message}`)));
240
- child.once("exit", (code, signal) => finish(err5(1, `\u540E\u53F0\u8FDB\u7A0B\u5728\u63D0\u4EA4\u786E\u8BA4\u524D\u9000\u51FA (${signal ?? code ?? "unknown"})`)));
309
+ const timer = setTimeout(() => finish(err6(1, "\u7B49\u5F85\u540E\u53F0\u63D0\u4EA4\u786E\u8BA4\u8D85\u65F6\uFF1B\u4EFB\u52A1\u53EF\u80FD\u5DF2\u521B\u5EFA\uFF0C\u8BF7\u5148\u5728\u5BF9\u5E94 App \u4E2D\u68C0\u67E5\uFF0C\u52FF\u76F4\u63A5\u91CD\u8BD5")), options.readyTimeoutMs ?? 45e3);
310
+ child.once("error", (error) => finish(err6(1, `\u540E\u53F0\u542F\u52A8\u5931\u8D25: ${error.message}`)));
311
+ child.once("exit", (code, signal) => finish(err6(1, `\u540E\u53F0\u8FDB\u7A0B\u5728\u63D0\u4EA4\u786E\u8BA4\u524D\u9000\u51FA (${signal ?? code ?? "unknown"})`)));
241
312
  child.on("message", (message) => {
242
313
  if (!message || typeof message !== "object") return;
243
314
  const reply = message;
244
- if (reply.ready === true && reply.data !== void 0) finish(ok5({ pid: child.pid, data: reply.data }));
245
- else if (typeof reply.error === "string") finish(err5(1, reply.error));
315
+ if (reply.ready === true && reply.data !== void 0) finish(ok6({ pid: child.pid, data: reply.data }));
316
+ else if (typeof reply.error === "string") finish(err6(1, reply.error));
246
317
  });
247
318
  });
248
319
  }
@@ -251,9 +322,10 @@ export {
251
322
  runProcess,
252
323
  captureProcess,
253
324
  openUrl,
325
+ runPassthroughProcess,
254
326
  startDetachedWorker,
255
327
  runJsonRpcProcess,
256
328
  startBackgroundProcess,
257
329
  runJsonLineProcess
258
330
  };
259
- //# sourceMappingURL=chunk-VCLWIPCG.js.map
331
+ //# sourceMappingURL=chunk-2VUM57PV.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/bedrock/process/json-rpc-process.ts","../src/bedrock/process/background-process.ts","../src/bedrock/process/run-process.ts","../src/bedrock/process/passthrough-process.ts","../src/bedrock/process/detached-process.ts","../src/bedrock/process/detached-worker.ts"],"sourcesContent":["import { spawn } from \"node:child_process\";\nimport { createInterface } from \"node:readline\";\nimport { err, ok, type Result } from \"rockbed/error\";\n\nexport interface IJsonRpcNotification {\n readonly method: string;\n readonly params?: unknown;\n}\n\nexport interface IJsonRpcConnection {\n request<T>(method: string, params: unknown): Promise<Result<T>>;\n notify(method: string, params?: unknown): void;\n waitForNotification(predicate: (notification: IJsonRpcNotification) => boolean): Promise<Result<IJsonRpcNotification>>;\n}\n\n/** Own a stdio JSON-RPC process, discard diagnostics, and release it when the callback finishes. */\nexport async function runJsonRpcProcess<T>(\n command: string,\n args: readonly string[],\n options: { readonly cwd: string; readonly execute: (connection: IJsonRpcConnection) => Promise<Result<T>>; readonly requestTimeoutMs?: number },\n): Promise<Result<T>> {\n const child = spawn(command, [...args], { cwd: options.cwd, stdio: [\"pipe\", \"pipe\", \"ignore\"], shell: false });\n const lines = createInterface({ input: child.stdout });\n let sequence = 0;\n let closed: string | undefined;\n const pending = new Map<number, (result: Result<unknown>) => void>();\n const subscribers = new Set<(result: Result<IJsonRpcNotification>) => void>();\n const fail = (message: string): void => {\n if (closed) return;\n closed = message;\n for (const resolve of pending.values()) resolve(err(1, message));\n pending.clear();\n for (const resolve of [...subscribers]) resolve(err(1, message));\n subscribers.clear();\n };\n const send = (message: unknown): void => {\n if (!closed) child.stdin.write(`${JSON.stringify(message)}\\n`, (error) => { if (error) fail(`写入子进程失败: ${error.message}`); });\n };\n child.on(\"error\", (error) => fail(`启动 ${command} 失败: ${error.message}`));\n child.stdin.on(\"error\", (error) => fail(`子进程输入流失败: ${error.message}`));\n child.on(\"close\", (code, signal) => fail(`子进程连接已关闭 (${signal ?? code ?? \"unknown\"})`));\n lines.on(\"line\", (line) => {\n let message: { id?: number | string; method?: string; params?: unknown; result?: unknown; error?: { message?: string } };\n try { message = JSON.parse(line); } catch { return; }\n if (!message || typeof message !== \"object\") return;\n if (message.id !== undefined && message.method) {\n // This unattended client cannot answer interactive server requests.\n send({ id: message.id, error: { code: -32601, message: \"Unattended client cannot handle interactive requests\" } });\n } else if (typeof message.id === \"number\") {\n const resolve = pending.get(message.id);\n pending.delete(message.id);\n resolve?.(message.error ? err(1, message.error.message ?? \"JSON-RPC request failed\") : ok(message.result));\n } else if (typeof message.method === \"string\") {\n for (const subscriber of [...subscribers]) subscriber(ok({ method: message.method, params: message.params }));\n }\n });\n const connection: IJsonRpcConnection = {\n request: <R>(method: string, params: unknown): Promise<Result<R>> => {\n if (closed) return Promise.resolve(err(1, closed));\n return new Promise((resolve) => {\n const id = ++sequence;\n const timer = setTimeout(() => {\n pending.delete(id);\n resolve(err(1, `${method} 请求超时;远端可能已接收,请勿自动重试`));\n }, options.requestTimeoutMs ?? 15_000);\n pending.set(id, (result) => { clearTimeout(timer); resolve(result as Result<R>); });\n send({ id, method, params });\n });\n },\n notify: (method, params) => send({ method, ...(params === undefined ? {} : { params }) }),\n waitForNotification: (predicate) => {\n if (closed) return Promise.resolve(err(1, closed));\n return new Promise((resolve) => {\n const subscriber = (result: Result<IJsonRpcNotification>): void => {\n if (!result.ok || predicate(result.value)) { subscribers.delete(subscriber); resolve(result); }\n };\n subscribers.add(subscriber);\n });\n },\n };\n try {\n return await options.execute(connection);\n } catch (error) {\n return err(1, error instanceof Error ? error.message : String(error));\n } finally {\n fail(\"子进程连接已结束\");\n lines.close();\n child.stdin.end();\n // Allow graceful shutdown first, but never leave a stuck server behind.\n if (child.exitCode === null && child.signalCode === null) {\n const timer = setTimeout(() => child.kill(\"SIGKILL\"), 2000);\n timer.unref();\n child.once(\"close\", () => clearTimeout(timer));\n }\n }\n}\n","import { spawn } from \"node:child_process\";\nimport { createInterface } from \"node:readline\";\nimport { err, ok, type Result } from \"rockbed/error\";\n\nexport interface IBackgroundProcessOptions {\n readonly cwd?: string;\n readonly env?: NodeJS.ProcessEnv;\n readonly readyTimeoutMs?: number;\n}\n\n/** Detach only after the child explicitly acknowledges ownership over IPC. */\nexport function startBackgroundProcess(\n command: string,\n args: readonly string[],\n options: IBackgroundProcessOptions = {},\n): Promise<Result<void>> {\n return new Promise((resolve) => {\n const child = spawn(command, [...args], {\n cwd: options.cwd,\n env: options.env ? { ...process.env, ...options.env } : process.env,\n detached: true,\n stdio: [\"ignore\", \"ignore\", \"ignore\", \"ipc\"],\n });\n let settled = false;\n const finish = (result: Result<void>): void => {\n if (settled) return;\n settled = true;\n clearTimeout(timer);\n if (child.connected) child.disconnect();\n child.unref();\n resolve(result);\n };\n const timer = setTimeout(() => finish(err(1, \"后台进程未在限定时间内确认接管;可能仍在启动,请查询原任务\")), options.readyTimeoutMs ?? 15_000);\n child.on(\"error\", (error) => finish(err(1, `启动后台进程失败: ${error.message}`)));\n child.on(\"exit\", (code) => finish(err(1, `后台进程在确认接管前退出 (${code ?? \"signal\"})`)));\n child.on(\"message\", (message: unknown) => {\n if (!message || typeof message !== \"object\") return;\n const reply = message as { ready?: boolean; error?: string };\n if (reply.ready === true) finish(ok());\n else if (typeof reply.error === \"string\") finish(err(1, reply.error));\n });\n });\n}\n\n/** Stream JSONL without retaining potentially large or sensitive model output. */\nexport function runJsonLineProcess(\n command: string,\n args: readonly string[],\n options: { readonly cwd?: string; readonly onEvent: (event: unknown) => void },\n): Promise<Result<void>> {\n return new Promise((resolve) => {\n const child = spawn(command, [...args], { cwd: options.cwd, stdio: [\"ignore\", \"pipe\", \"ignore\"] });\n const lines = createInterface({ input: child.stdout! });\n lines.on(\"line\", (line) => {\n try { options.onEvent(JSON.parse(line)); } catch { /* Non-JSON diagnostics are not task results. */ }\n });\n child.on(\"error\", (error) => resolve(err(1, `启动 JSONL 子进程失败: ${error.message}`)));\n child.on(\"close\", (code, signal) => {\n lines.close();\n resolve(code === 0 ? ok() : err(1, `JSONL 子进程退出 (${signal ?? code ?? \"unknown\"})`));\n });\n });\n}\n","import { spawn } from \"node:child_process\";\nimport { err, ok, type Result } from \"rockbed/error\";\n\nexport interface IRunProcessOptions {\n readonly cwd?: string;\n /** 在 `process.env` 之上叠加的环境变量。 */\n readonly env?: NodeJS.ProcessEnv;\n /** 通过 shell 执行,允许 `a && b` 这类命令行。 */\n readonly shell?: boolean;\n /** `inherit`(默认)把子进程 stdio 透传到当前终端;`ignore` 完全静默。 */\n readonly stdio?: \"inherit\" | \"ignore\";\n}\n\nexport interface ICaptureProcessOptions {\n readonly cwd?: string;\n readonly env?: NodeJS.ProcessEnv;\n readonly shell?: boolean;\n}\n\nexport interface IProcessOutput {\n readonly stdout: string;\n readonly stderr: string;\n}\n\n/**\n * 运行子进程并等待退出,stdio 透传或忽略。退出码非 0 视为可预期失败。\n */\nexport function runProcess(\n command: string,\n args: readonly string[] = [],\n options: IRunProcessOptions = {},\n): Promise<Result<void>> {\n const child = spawn(command, [...args], {\n cwd: options.cwd ?? process.cwd(),\n env: options.env ? { ...process.env, ...options.env } : process.env,\n shell: options.shell ?? false,\n stdio: options.stdio ?? \"inherit\",\n });\n const label = describeCommand(command, args);\n\n return new Promise((resolve) => {\n child.on(\"error\", (error) => {\n resolve(err(1, `执行 ${label} 失败: ${error.message}`));\n });\n child.on(\"close\", (code, signal) => {\n if (code === 0) {\n resolve(ok());\n return;\n }\n resolve(err(code ?? 1, `执行 ${label} 失败${describeSignal(signal)}`));\n });\n });\n}\n\n/**\n * 运行子进程并捕获 stdout/stderr。退出码非 0 时把 stderr 附在失败消息里。\n */\nexport function captureProcess(\n command: string,\n args: readonly string[] = [],\n options: ICaptureProcessOptions = {},\n): Promise<Result<IProcessOutput>> {\n const child = spawn(command, [...args], {\n cwd: options.cwd ?? process.cwd(),\n env: options.env ? { ...process.env, ...options.env } : process.env,\n shell: options.shell ?? false,\n stdio: [\"ignore\", \"pipe\", \"pipe\"],\n });\n const label = describeCommand(command, args);\n let stdout = \"\";\n let stderr = \"\";\n\n child.stdout?.on(\"data\", (chunk: Buffer) => {\n stdout += chunk.toString();\n });\n child.stderr?.on(\"data\", (chunk: Buffer) => {\n stderr += chunk.toString();\n });\n\n return new Promise((resolve) => {\n child.on(\"error\", (error) => {\n resolve(err(1, `执行 ${label} 失败: ${error.message}`));\n });\n child.on(\"close\", (code, signal) => {\n if (code === 0) {\n resolve(ok({ stdout, stderr }));\n return;\n }\n const stderrText = stderr.trim() ? `\\n${stderr.trim()}` : \"\";\n resolve(\n err(\n code ?? 1,\n `执行 ${label} 失败${describeSignal(signal)}${stderrText}`,\n ),\n );\n });\n });\n}\n\n/**\n * 用系统默认程序打开 URL(macOS `open`、Windows `start`、其他 `xdg-open`)。\n */\nexport function openUrl(url: string): Promise<Result<void>> {\n const [command, args] =\n process.platform === \"darwin\"\n ? [\"open\", [url]]\n : process.platform === \"win32\"\n ? [\"cmd\", [\"/c\", \"start\", \"\", url]]\n : [\"xdg-open\", [url]];\n return runProcess(command, args, { stdio: \"ignore\" });\n}\n\nfunction describeCommand(command: string, args: readonly string[]): string {\n return [command, ...args].join(\" \").trim();\n}\n\nfunction describeSignal(signal: NodeJS.Signals | null): string {\n return signal ? `, signal: ${signal}` : \"\";\n}\n","import { spawn, type ChildProcess } from \"node:child_process\";\nimport { constants } from \"node:os\";\nimport { err, ok, type Result } from \"rockbed/error\";\n\nexport interface IPassthroughProcessOptions {\n readonly cwd?: string;\n /** Overlay the current process environment. */\n readonly env?: NodeJS.ProcessEnv;\n /** When supplied, write this value to stdin and close it, including an empty string. */\n readonly input?: string;\n}\n\nexport interface IPassthroughProcessResult {\n readonly exitCode: number;\n}\n\nconst FORWARDED_SIGNALS = [\"SIGINT\", \"SIGTERM\", \"SIGHUP\"] as const;\nconst TERMINATION_GRACE_MS = 2_000;\n\n/** Inherit native output and return the native exit status after the foreground child closes. */\nexport function runPassthroughProcess(\n command: string,\n args: readonly string[],\n options: IPassthroughProcessOptions = {},\n): Promise<Result<IPassthroughProcessResult>> {\n return new Promise((resolve) => {\n let child: ChildProcess;\n try {\n child = spawn(command, [...args], {\n cwd: options.cwd,\n env: options.env ? { ...process.env, ...options.env } : process.env,\n shell: false,\n stdio: [options.input === undefined ? \"ignore\" : \"pipe\", \"inherit\", \"inherit\"],\n });\n } catch (error) {\n resolve(err(1, `启动子进程失败${describeErrorCode(error)}`));\n return;\n }\n\n let failure: Result<IPassthroughProcessResult> | undefined;\n let brokenInput = false;\n let closed = false;\n let killTimer: ReturnType<typeof setTimeout> | undefined;\n const isRunning = (): boolean => child.pid !== undefined && child.exitCode === null && child.signalCode === null;\n const stop = (signal: NodeJS.Signals = \"SIGTERM\"): void => {\n if (closed || !isRunning()) return;\n if (!killTimer) {\n // A foreground invocation owns its child until it closes; keep the timer referenced.\n killTimer = setTimeout(() => {\n if (isRunning()) child.kill(\"SIGKILL\");\n }, TERMINATION_GRACE_MS);\n }\n child.kill(signal);\n };\n const fail = (message: string): void => {\n failure ??= err(1, message);\n stop();\n };\n const signalHandlers = FORWARDED_SIGNALS.map((signal) => {\n const handler = (): void => stop(signal);\n process.on(signal, handler);\n return { signal, handler };\n });\n\n child.on(\"error\", (error) => fail(`子进程执行失败${describeErrorCode(error)}`));\n child.on(\"exit\", () => clearTimeout(killTimer));\n child.on(\"close\", (code, signal) => {\n closed = true;\n clearTimeout(killTimer);\n for (const { signal: parentSignal, handler } of signalHandlers) process.off(parentSignal, handler);\n const exitCode = code ?? (signal ? 128 + constants.signals[signal] : 1);\n // Native input rejection commonly closes stdin early. Preserve its own failure status.\n if (!failure && brokenInput && exitCode === 0) failure = err(1, \"写入子进程 stdin 失败 (EPIPE)\");\n resolve(failure ?? ok({ exitCode }));\n });\n child.stdin?.on(\"error\", (error: NodeJS.ErrnoException) => {\n if (error.code === \"EPIPE\") brokenInput = true;\n else fail(`写入子进程 stdin 失败${describeErrorCode(error)}`);\n });\n if (options.input !== undefined) {\n try { child.stdin?.end(options.input); }\n catch (error) { fail(`写入子进程 stdin 失败${describeErrorCode(error)}`); }\n }\n });\n}\n\n/** System codes help diagnosis without disclosing command arguments or prompt contents. */\nfunction describeErrorCode(error: unknown): string {\n if (!error || typeof error !== \"object\" || !(\"code\" in error)) return \"\";\n return typeof error.code === \"string\" && /^[A-Z][A-Z0-9_]*$/.test(error.code) ? ` (${error.code})` : \"\";\n}\n","import { spawn } from \"node:child_process\";\nimport { constants } from \"node:fs\";\nimport { access, stat } from \"node:fs/promises\";\nimport { delimiter, resolve } from \"node:path\";\nimport { err, ok, type Result } from \"rockbed/error\";\n\n/** Fire-and-forget Unix process: ignore SIGHUP and discard all terminal IO. */\nexport async function startDetachedProcess(\n command: string,\n args: readonly string[],\n options: { readonly cwd: string },\n): Promise<Result<{ readonly pid: number }>> {\n if (process.platform === \"win32\") return err(1, \"后台 nohup 启动仅支持 macOS/Linux\");\n // Check the target before launching nohup, whose spawn event alone cannot detect ENOENT.\n const candidates = command.includes(\"/\")\n ? [resolve(options.cwd, command)]\n : (process.env.PATH ?? \"\").split(delimiter).map((dir) => resolve(options.cwd, dir, command));\n let executable: string | undefined;\n for (const candidate of candidates) {\n try {\n await access(candidate, constants.X_OK);\n if ((await stat(candidate)).isFile()) {\n executable = candidate;\n break;\n }\n } catch { /* Try the next PATH entry. */ }\n }\n if (!executable) return err(1, `找不到可执行文件: ${command}`);\n\n return new Promise((resolveResult) => {\n const child = spawn(\"nohup\", [executable, ...args], {\n cwd: options.cwd,\n detached: true,\n stdio: \"ignore\",\n shell: false,\n });\n child.once(\"error\", (error) => resolveResult(err(1, `后台启动失败: ${error.message}`)));\n child.once(\"spawn\", () => {\n child.unref();\n resolveResult(ok({ pid: child.pid! }));\n });\n });\n}\n","import { spawn } from \"node:child_process\";\nimport { err, ok, type Result } from \"rockbed/error\";\n\n/** Launch a Node worker under nohup; wait only for its submission acknowledgement. */\nexport function startDetachedWorker<T>(\n args: readonly string[],\n options: { readonly cwd: string; readonly readyTimeoutMs?: number },\n): Promise<Result<{ readonly pid: number; readonly data: T }>> {\n if (process.platform === \"win32\") return Promise.resolve(err(1, \"后台 nohup 启动仅支持 macOS/Linux\"));\n return new Promise((resolve) => {\n const child = spawn(\"nohup\", [process.execPath, ...args], {\n cwd: options.cwd, detached: true, stdio: [\"ignore\", \"ignore\", \"ignore\", \"ipc\"], shell: false,\n });\n let settled = false;\n const finish = (result: Result<{ readonly pid: number; readonly data: T }>): void => {\n if (settled) return;\n settled = true;\n clearTimeout(timer);\n if (child.connected) child.disconnect();\n child.unref();\n resolve(result);\n };\n const timer = setTimeout(() => finish(err(1, \"等待后台提交确认超时;任务可能已创建,请先在对应 App 中检查,勿直接重试\")), options.readyTimeoutMs ?? 45_000);\n child.once(\"error\", (error) => finish(err(1, `后台启动失败: ${error.message}`)));\n child.once(\"exit\", (code, signal) => finish(err(1, `后台进程在提交确认前退出 (${signal ?? code ?? \"unknown\"})`)));\n child.on(\"message\", (message: unknown) => {\n if (!message || typeof message !== \"object\") return;\n const reply = message as { ready?: boolean; data?: T; error?: string };\n if (reply.ready === true && reply.data !== undefined) finish(ok({ pid: child.pid!, data: reply.data }));\n else if (typeof reply.error === \"string\") finish(err(1, reply.error));\n });\n });\n}\n"],"mappings":"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","names":["spawn","createInterface","err","ok","spawn","err","ok","spawn","err","ok","err","ok","spawn","err","ok"]}