@brierb/brier-cli 0.0.11 → 0.0.13

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.
@@ -1,6 +1,30 @@
1
1
  import { spawn } from 'node:child_process';
2
+ import { chmodSync } from 'node:fs';
3
+ import { dirname, join } from 'node:path';
4
+ import { createRequire } from 'node:module';
2
5
  import pty from 'node-pty';
3
6
  import { logger, resolveRuntimeExecutable, RUNTIME_PROMPT_FLAGS } from '../core/index.js';
7
+ const require = createRequire(import.meta.url);
8
+ /**
9
+ * 修复 node-pty 的 darwin spawn-helper 可执行权限。
10
+ *
11
+ * 现象:node-pty 在 macOS 上先 spawn 自带的 spawn-helper 再执行目标命令;
12
+ * 若该 helper 因下载/安装而缺失可执行位(0644),posix_spawnp 返回 EACCES,
13
+ * 且 node-pty 只抛出笼统的 "posix_spawnp failed."(无 errno),难以定位。
14
+ * 每次 pty 启动前兜底 chmod +x,兼容重装后权限再丢失的情况。
15
+ */
16
+ const ensurePtyHelperExecutable = () => {
17
+ if (process.platform !== 'darwin')
18
+ return;
19
+ try {
20
+ const pkgDir = dirname(require.resolve('node-pty/package.json'));
21
+ const helper = join(pkgDir, 'prebuilds', `darwin-${process.arch}`, 'spawn-helper');
22
+ chmodSync(helper, 0o755);
23
+ }
24
+ catch {
25
+ // helper 权限修正失败不致命:若 node-pty 自身可执行则正常走;否则抛错由上层捕获
26
+ }
27
+ };
4
28
  const MAX_CONCURRENT = 3;
5
29
  /** 取消后等待 SIGTERM 生效的时间,超时升级 SIGKILL(仅 pipe 模式需要;pty.kill 为同步终止) */
6
30
  const KILL_GRACE_MS = 2_000;
@@ -118,10 +142,14 @@ export const createTaskExecutor = (callbacks) => {
118
142
  * pty 模式:伪终端交互子进程。
119
143
  * CLI 检测到 tty 后进入交互模式(会提问、渲染进度、等待输入);
120
144
  * 屏幕字节经 onData 上行(含 ANSI),用户输入经 writeInput 写入(模拟击键)。
145
+ *
146
+ * 与 pipe 模式的关键差异:prompt 任务不再把 prompt 拼成命令行参数,
147
+ * 而是启动后作为“用户输入”敲进终端(交互式 CLI 从会话里读取首条消息)。
121
148
  */
122
- const executePty = (task, cmd, args, childEnv) => {
149
+ const executePty = (task, cmd, args, childEnv, initialInput) => {
123
150
  let handle;
124
151
  try {
152
+ ensurePtyHelperExecutable();
125
153
  handle = pty.spawn(cmd, args, {
126
154
  name: 'xterm-256color',
127
155
  cols: 120,
@@ -136,6 +164,10 @@ export const createTaskExecutor = (callbacks) => {
136
164
  }
137
165
  ptyProcs.set(task.taskId, handle);
138
166
  logger.info(`Task ${task.taskId} started in pty mode: ${cmd} ${args.join(' ')}`, task.runtime);
167
+ // prompt 作为首条会话消息敲入(补回车触发提交);无 prompt(command 模式)不注入
168
+ if (initialInput) {
169
+ handle.write(initialInput);
170
+ }
139
171
  handle.onData((data) => {
140
172
  // pty 只有一路输出(合并 stdout/stderr 的终端字节流),统一按 stdout 上行;
141
173
  // 前端如需区分文本/控制序列,属于展示层解析,不在执行层拆流。
@@ -168,13 +200,17 @@ export const createTaskExecutor = (callbacks) => {
168
200
  callbacks.onError(task.taskId, `Cannot resolve command for runtime: ${task.runtime} (no command provided)`);
169
201
  return;
170
202
  }
171
- const args = buildArgs(task);
172
203
  const childEnv = buildEnv(task);
173
204
  if (task.execMode === 'pty') {
174
- executePty(task, cmd, args, childEnv);
205
+ // 交互模式:prompt 不拼参数,作为首条输入敲入;command 模式透传 args
206
+ const args = task.prompt ? [] : (task.args ?? []);
207
+ const initialInput = task.prompt !== undefined && task.prompt.trim() !== ''
208
+ ? `${task.prompt.replace(/\r?\n/g, '\r')}\r`
209
+ : undefined;
210
+ executePty(task, cmd, args, childEnv, initialInput);
175
211
  return;
176
212
  }
177
- executePipe(task, cmd, args, childEnv);
213
+ executePipe(task, cmd, buildArgs(task), childEnv);
178
214
  };
179
215
  const writeInput = (taskId, data) => {
180
216
  if (!data)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@brierb/brier-cli",
3
- "version": "0.0.11",
3
+ "version": "0.0.13",
4
4
  "description": "Brier 平台接入命令行工具:通过加密隧道将本机接入 Brier 远程编码池,接收并执行远程任务",
5
5
  "keywords": [
6
6
  "brier",