pi-codex-marketplace 1.0.3 → 1.0.4

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.
Files changed (2) hide show
  1. package/package.json +1 -1
  2. package/src/cli/index.ts +38 -18
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pi-codex-marketplace",
3
- "version": "1.0.3",
3
+ "version": "1.0.4",
4
4
  "description": "Bridge Package for Codex and Claude Marketplace compatibility in Pi — 極簡 /codex-marketplace 純文字指令與 Headless CLI(add/list/install/update/disable/enable/remove/forget)、單一 Global Bridge State、當下最新安裝與即時投影",
5
5
  "type": "module",
6
6
  "keywords": [
package/src/cli/index.ts CHANGED
@@ -12,8 +12,8 @@ import { runCommand, getPackageVersion, type CommandOptions, type CommandResult
12
12
  export { getPackageVersion };
13
13
 
14
14
  export interface CliIO {
15
- stdout?: { write: (chunk: string) => unknown } | ((chunk: string) => unknown);
16
- stderr?: { write: (chunk: string) => unknown; isTTY?: boolean } | ((chunk: string) => unknown);
15
+ stdout?: { write: (chunk: string) => unknown; isTTY?: boolean } | ((chunk: string) => unknown);
16
+ stderr?: { write: (chunk: string) => unknown; isTTY?: boolean; columns?: number } | ((chunk: string) => unknown);
17
17
  exit?: (code: number) => unknown;
18
18
  }
19
19
 
@@ -63,13 +63,19 @@ export async function runCli(
63
63
  return exitWith(0);
64
64
  }
65
65
 
66
- const terminal = typeof io.stderr === 'object' && io.stderr.isTTY ? io.stderr : undefined;
66
+ const interactive = typeof io.stdout === 'object' && io.stdout.isTTY;
67
+ const terminal = interactive && typeof io.stderr === 'object' && io.stderr.isTTY ? io.stderr : undefined;
67
68
  let timer: ReturnType<typeof setInterval> | undefined;
68
69
  let frame = 0;
70
+ let activityVisible = false;
71
+ let updating = false;
69
72
  const clearActivity = (): void => {
70
73
  if (timer !== undefined) {
71
74
  clearInterval(timer);
72
75
  timer = undefined;
76
+ }
77
+ if (activityVisible) {
78
+ activityVisible = false;
73
79
  try { terminal?.write('\r\x1b[2K'); } catch { /* Progress is best-effort. */ }
74
80
  }
75
81
  };
@@ -78,21 +84,31 @@ export async function runCli(
78
84
  result = await runCommand(argv, {
79
85
  ...opts,
80
86
  onProgress(message, kind) {
81
- // Result lines belong to the authoritative final summary, not both streams.
82
- if (kind === 'result') {
83
- opts.onProgress?.(message, kind);
84
- return;
85
- }
86
- clearActivity();
87
- writeStream(io.stderr, message);
88
- if (terminal) {
89
- timer = setInterval(() => {
90
- try { terminal.write(`\r${['|', '/', '-', '\\'][frame++ % 4]} 處理中…`); } catch {
91
- clearInterval(timer);
92
- timer = undefined;
87
+ updating = true; // Only update emits progress; other command formatting stays unchanged.
88
+ if (kind !== 'result' && terminal) {
89
+ clearActivity();
90
+ const render = (): void => {
91
+ // Reserve the last column to prevent wrapping into permanent history.
92
+ const width = Math.max(0, (terminal.columns ?? 80) - 1);
93
+ const text = `${['|', '/', '-', '\\'][frame++ % 4]} ${message}`;
94
+ let line = '';
95
+ let used = 0;
96
+ for (const char of text.replace(/[\x00-\x1f\x7f-\x9f]/g, ' ')) {
97
+ const cells = char.codePointAt(0)! < 128 ? 1 : 2;
98
+ if (used + cells > width) break;
99
+ line += char;
100
+ used += cells;
93
101
  }
94
- }, 100);
95
- timer.unref();
102
+ try {
103
+ activityVisible = true;
104
+ terminal.write(`\r\x1b[2K${line}`);
105
+ } catch { clearActivity(); }
106
+ };
107
+ render();
108
+ if (activityVisible) {
109
+ timer = setInterval(render, 100);
110
+ timer.unref();
111
+ }
96
112
  }
97
113
  opts.onProgress?.(message, kind);
98
114
  },
@@ -100,7 +116,11 @@ export async function runCli(
100
116
  } finally {
101
117
  clearActivity();
102
118
  }
103
- const output = formatCliOutput(result);
119
+ const formatted = formatCliOutput(result);
120
+ const output = updating
121
+ ? formatted.split('\n').filter((line) => line.length > 0)
122
+ .map((line) => line.replace(/^(.+? )重新抓取… /, '$1')).join('\n')
123
+ : formatted;
104
124
 
105
125
  if (result.ok) {
106
126
  if (output) {