pi-codex-marketplace 1.0.2 → 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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pi-codex-marketplace",
3
- "version": "1.0.2",
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": [
@@ -46,7 +46,7 @@ import { SourceCache } from '../cache/source-cache.js';
46
46
 
47
47
  export interface CommandOptions {
48
48
  /** Optional presentation-only update progress; final result remains authoritative. */
49
- onProgress?: (message: string) => void;
49
+ onProgress?: (message: string, kind?: 'activity' | 'result') => void;
50
50
  statePath?: string;
51
51
  agentDir?: string;
52
52
  cwd?: string;
@@ -492,9 +492,9 @@ export async function runCommand(
492
492
  }
493
493
  const subcmd = rawArgs[0]?.toLowerCase();
494
494
 
495
- const progress = (message: string): void => {
495
+ const progress = (message: string, kind: 'activity' | 'result' = 'activity'): void => {
496
496
  // An observer must never affect acquisition or durable state.
497
- try { opts.onProgress?.(message); } catch {}
497
+ try { opts.onProgress?.(message, kind); } catch {}
498
498
  };
499
499
  if (subcmd === 'update') progress('開始更新 Marketplace…');
500
500
 
@@ -971,7 +971,7 @@ export async function runCommand(
971
971
  const updateLines: string[] = [];
972
972
  const report = (line: string): void => {
973
973
  updateLines.push(line);
974
- progress(line);
974
+ progress(line, 'result');
975
975
  };
976
976
  let anyChanged = false; // 有 plugin 實際升到最新 → reload+結尾「已重新載入生效」
977
977
  let gitAdvanced = false; // git registration 已推進到新 fingerprint → 需持久化(即使無已安裝 plugin)
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
  };
@@ -77,25 +83,44 @@ export async function runCli(
77
83
  try {
78
84
  result = await runCommand(argv, {
79
85
  ...opts,
80
- onProgress(message) {
81
- clearActivity();
82
- writeStream(io.stderr, message);
83
- if (terminal) {
84
- timer = setInterval(() => {
85
- try { terminal.write(`\r${['|', '/', '-', '\\'][frame++ % 4]} 處理中…`); } catch {
86
- clearInterval(timer);
87
- timer = undefined;
86
+ onProgress(message, kind) {
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;
88
101
  }
89
- }, 100);
90
- 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
+ }
91
112
  }
92
- opts.onProgress?.(message);
113
+ opts.onProgress?.(message, kind);
93
114
  },
94
115
  });
95
116
  } finally {
96
117
  clearActivity();
97
118
  }
98
- 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;
99
124
 
100
125
  if (result.ok) {
101
126
  if (output) {