@tomflow/proflow-platform-cli 0.1.37 → 0.1.38

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/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # @tomflow/proflow-platform-cli
2
2
 
3
+ ## 0.1.38
4
+
5
+ ### Patch Changes
6
+
7
+ - Retire the obsolete Carrier package and Browser standalone management CLI, make Platform setup/status preserve owner and dependency semantics, and enforce read-only status observation across the final Real-3 deployment closeout.
8
+
3
9
  ## 0.1.37
4
10
 
5
11
  ### Patch Changes
@@ -6,7 +6,7 @@ export declare const behaviorAdapter: {
6
6
  readonly ok: true;
7
7
  readonly status: "SUCCEEDED";
8
8
  readonly moduleRef: "platform-cli";
9
- readonly moduleVersion: "0.1.37";
9
+ readonly moduleVersion: "0.1.38";
10
10
  };
11
11
  observedEffects: never[];
12
12
  }>;
@@ -16,7 +16,7 @@ export declare const behaviorAdapter: {
16
16
  readonly ok: true;
17
17
  readonly status: "SUCCEEDED";
18
18
  readonly moduleRef: "platform-cli";
19
- readonly moduleVersion: "0.1.37";
19
+ readonly moduleVersion: "0.1.38";
20
20
  };
21
21
  observedEffects: never[];
22
22
  }>;
@@ -26,7 +26,7 @@ export declare const behaviorAdapter: {
26
26
  ok: true;
27
27
  status: "SUCCEEDED";
28
28
  moduleRef: "platform-cli";
29
- moduleVersion: "0.1.37";
29
+ moduleVersion: "0.1.38";
30
30
  data: {
31
31
  readonly setupStatus: "READY";
32
32
  readonly runtimeStatus: "NOT_APPLICABLE";
@@ -40,7 +40,7 @@ export declare const behaviorAdapter: {
40
40
  readonly ok: true;
41
41
  readonly status: "SUCCEEDED";
42
42
  readonly moduleRef: "platform-cli";
43
- readonly moduleVersion: "0.1.37";
43
+ readonly moduleVersion: "0.1.38";
44
44
  };
45
45
  observedEffects: never[];
46
46
  }>;
@@ -50,7 +50,7 @@ export declare const behaviorAdapter: {
50
50
  ok: true;
51
51
  status: "SUCCEEDED";
52
52
  moduleRef: "platform-cli";
53
- moduleVersion: "0.1.37";
53
+ moduleVersion: "0.1.38";
54
54
  data: {
55
55
  docs: string;
56
56
  };
@@ -63,7 +63,7 @@ export declare const behaviorAdapter: {
63
63
  readonly ok: true;
64
64
  readonly status: "SUCCEEDED";
65
65
  readonly moduleRef: "platform-cli";
66
- readonly moduleVersion: "0.1.37";
66
+ readonly moduleVersion: "0.1.38";
67
67
  };
68
68
  observedEffects: never[];
69
69
  }>;
@@ -73,7 +73,7 @@ export declare const behaviorAdapter: {
73
73
  readonly ok: true;
74
74
  readonly status: "SUCCEEDED";
75
75
  readonly moduleRef: "platform-cli";
76
- readonly moduleVersion: "0.1.37";
76
+ readonly moduleVersion: "0.1.38";
77
77
  };
78
78
  observedEffects: never[];
79
79
  }>;
@@ -3,7 +3,7 @@ export declare const descriptor: {
3
3
  readonly contractVersion: "1.0.0";
4
4
  readonly moduleRef: "platform-cli";
5
5
  readonly packageName: "@tomflow/proflow-platform-cli";
6
- readonly moduleVersion: "0.1.37";
6
+ readonly moduleVersion: "0.1.38";
7
7
  readonly kind: "cli";
8
8
  readonly templateVersion: "1.0.0";
9
9
  readonly platformCompatibility: ">=1.0.0 <2.0.0";
@@ -3,7 +3,7 @@ export const descriptor = {
3
3
  contractVersion: "1.0.0",
4
4
  moduleRef: "platform-cli",
5
5
  packageName: "@tomflow/proflow-platform-cli",
6
- moduleVersion: "0.1.37",
6
+ moduleVersion: "0.1.38",
7
7
  kind: "cli",
8
8
  templateVersion: "1.0.0",
9
9
  platformCompatibility: ">=1.0.0 <2.0.0",
package/dist/src/cli.js CHANGED
@@ -158,6 +158,9 @@ async function handleStatus(root, runtime) {
158
158
  ...(parsed.data.issues === undefined
159
159
  ? {}
160
160
  : { issues: parsed.data.issues }),
161
+ ...(item.externalAvailabilityClaim === undefined
162
+ ? {}
163
+ : { externalAvailabilityClaim: item.externalAvailabilityClaim }),
161
164
  };
162
165
  });
163
166
  reportProgress(runtime.onProgress, {
@@ -558,9 +561,17 @@ function renderStatus(data, theme) {
558
561
  NOT_APPLICABLE: "无独立进程",
559
562
  };
560
563
  const modules = data.modules.filter(isRecord);
564
+ const productOrder = new Map([
565
+ ["execution-browser-extension", 0],
566
+ ["dev-tunnel", 1],
567
+ ["model-provider-api", 2],
568
+ ]);
569
+ const orderedProblems = (entries) => [...entries].sort((a, b) => (productOrder.get(String(a.moduleRef)) ?? 100) -
570
+ (productOrder.get(String(b.moduleRef)) ?? 100));
561
571
  const failedModules = modules.filter((item) => item.setupStatus === "FAILED" || item.runtimeStatus === "FAILED");
562
- const actionModules = modules.filter((item) => item.setupStatus === "ACTION_REQUIRED" && item.runtimeStatus !== "FAILED");
563
- const blockedModules = modules.filter((item) => item.setupStatus === "BLOCKED" && item.runtimeStatus !== "FAILED");
572
+ const actionModules = orderedProblems(modules.filter((item) => item.setupStatus === "ACTION_REQUIRED" &&
573
+ item.runtimeStatus !== "FAILED"));
574
+ const blockedModules = orderedProblems(modules.filter((item) => item.setupStatus === "BLOCKED" && item.runtimeStatus !== "FAILED"));
564
575
  const running = modules.filter((item) => item.setupStatus === "READY" && item.runtimeStatus === "RUNNING");
565
576
  const healthy = modules.filter((item) => item.setupStatus === "READY" &&
566
577
  item.runtimeStatus !== "RUNNING" &&
@@ -574,8 +585,11 @@ function renderStatus(data, theme) {
574
585
  const moduleRef = String(raw.moduleRef);
575
586
  const setupStatus = String(raw.setupStatus);
576
587
  const runtimeStatus = String(raw.runtimeStatus);
588
+ const runtimeLabel = raw.externalAvailabilityClaim === "AVAILABLE"
589
+ ? "外部资源可用"
590
+ : (runtimeLabels[runtimeStatus] ?? "未知");
577
591
  lines.push(`${tone(icon)} ${theme.section(moduleRef)} ${theme.muted(String(raw.version))}`);
578
- lines.push(` ${tone(setupLabels[setupStatus] ?? "未知")} · ${runtimeLabels[runtimeStatus] ?? "未知"}`);
592
+ lines.push(` ${tone(setupLabels[setupStatus] ?? "未知")} · ${runtimeLabel}`);
579
593
  const issues = Array.isArray(raw.issues)
580
594
  ? raw.issues.filter(isRecord)
581
595
  : [];
@@ -584,7 +598,8 @@ function renderStatus(data, theme) {
584
598
  if (Array.isArray(issue.relatedModuleRefs) &&
585
599
  issue.relatedModuleRefs.length > 0)
586
600
  lines.push(` 依赖:${issue.relatedModuleRefs.map(String).join("、")}`);
587
- lines.push(` 下一步:${theme.command(String(issue.nextCommand))}`);
601
+ if (setupStatus !== "BLOCKED")
602
+ lines.push(` 下一步:${theme.command(String(issue.nextCommand))}`);
588
603
  }
589
604
  lines.push("");
590
605
  }
@@ -597,7 +612,9 @@ function renderStatus(data, theme) {
597
612
  return;
598
613
  lines.push(theme.section(title), "");
599
614
  for (const item of entries) {
600
- const runtime = runtimeLabels[String(item.runtimeStatus)] ?? "未知";
615
+ const runtime = item.externalAvailabilityClaim === "AVAILABLE"
616
+ ? "外部资源可用"
617
+ : (runtimeLabels[String(item.runtimeStatus)] ?? "未知");
601
618
  lines.push(`${theme.success(symbol)} ${String(item.moduleRef).padEnd(32)} ${theme.muted(String(item.version).padEnd(9))} ${runtime}`);
602
619
  }
603
620
  lines.push("");
@@ -608,7 +625,7 @@ function renderStatus(data, theme) {
608
625
  const action = modules.filter((item) => item.setupStatus === "ACTION_REQUIRED" && item.runtimeStatus !== "FAILED").length;
609
626
  const failed = failedModules.length;
610
627
  const blocked = modules.filter((item) => item.setupStatus === "BLOCKED" && item.runtimeStatus !== "FAILED").length;
611
- lines.push(theme.section("汇总"), `${theme.success(`${ready} 已就绪`)} · ${theme.warning(`${action} 需要操作`)} · ${theme.info(`${blocked} 等待依赖`)} · ${failed > 0 ? theme.failure(`${failed} 失败`) : `${failed} 失败`}`);
628
+ lines.push(theme.section("汇总"), `${theme.success(`${ready} 配置已完成`)} · ${theme.warning(`${action} 根阻塞`)} · ${theme.info(`${blocked} 下游等待`)} · ${failed > 0 ? theme.failure(`${failed} 失败`) : `${failed} 失败`} · ${running.length} 个真实进程运行中`, `PLATFORM_READY=${action === 0 && blocked === 0 && failed === 0 ? "YES" : "NO"}`);
612
629
  return lines.join("\n");
613
630
  }
614
631
  function renderTerminalMarkdown(source, theme) {
@@ -652,36 +669,32 @@ function renderDocs(data, theme) {
652
669
  return lines.join("\n");
653
670
  }
654
671
  const setupCommands = {
655
- "chatgpt-carrier": {
656
- ai: "pnpm exec -- proflow-chatgpt-carrier setup",
657
- inputs: "无",
658
- },
659
672
  "dev-tunnel": {
660
- ai: "pnpm exec -- proflow-dev-tunnel setup",
673
+ ai: "platform setup --module dev-tunnel",
661
674
  inputs: "无",
662
675
  },
663
676
  "model-provider-api": {
664
- ai: "pnpm exec -- proflow-model-provider-api setup",
677
+ ai: "platform setup --module model-provider-api",
665
678
  inputs: "无(等待 Deployment resolver 提供 endpoint)",
666
679
  },
667
680
  "model-runtime": {
668
- ai: "pnpm exec -- proflow-model-runtime setup",
681
+ ai: "platform setup --module model-runtime",
669
682
  inputs: "无(仅等价合格候选歧义时选择)",
670
683
  },
671
684
  "execution-browser-extension": {
672
- ai: "pnpm exec -- proflow-execution-browser-extension setup",
685
+ ai: "platform setup --module execution-browser-extension",
673
686
  inputs: "无",
674
687
  },
675
688
  "agent-controller-dev": {
676
- ai: "pnpm exec -- proflow-agent-controller-dev setup",
689
+ ai: "platform setup --module agent-controller-dev",
677
690
  inputs: "无",
678
691
  },
679
692
  "agent-product": {
680
- ai: "pnpm exec -- proflow-agent-product setup",
693
+ ai: "platform setup --module agent-product",
681
694
  inputs: "无",
682
695
  },
683
696
  "agent-test-ops": {
684
- ai: "pnpm exec -- proflow-agent-test-ops setup",
697
+ ai: "platform setup --module agent-test-ops",
685
698
  inputs: "无",
686
699
  },
687
700
  };
@@ -741,13 +754,13 @@ function renderSetup(data, theme) {
741
754
  const error = raw.result.error;
742
755
  if (status !== "FAILED") {
743
756
  const commands = setupCommands[moduleRef] ?? {
744
- ai: `proflow-${moduleRef} setup`,
757
+ ai: `platform setup --module ${moduleRef}`,
745
758
  inputs: "按命令提示提供",
746
759
  };
747
- lines.push(` 人工执行:pnpm exec -- proflow-${moduleRef} setup`);
760
+ lines.push(` 人工执行:${commands.ai}`);
748
761
  lines.push(` AI 执行:${commands.ai}`);
749
762
  lines.push(` 需要输入:${commands.inputs}`);
750
- lines.push(` 验证:proflow-${moduleRef} verify`);
763
+ lines.push(" 验证:platform status");
751
764
  lines.push(" 完成条件:配置状态变为“已就绪”");
752
765
  }
753
766
  else if (isRecord(error)) {
@@ -839,17 +852,17 @@ function renderHelp(theme, command) {
839
852
  theme.section("推荐流程"),
840
853
  ` ${theme.command("install → status → docs → setup → start → status → stop")}`,
841
854
  "",
842
- theme.section("人工配置示例"),
843
- ` 人工:${theme.command("pnpm exec -- proflow-chatgpt-carrier setup")}`,
844
- ` AI: ${theme.command("pnpm exec -- proflow-chatgpt-carrier setup")}`,
855
+ theme.section("配置入口"),
856
+ ` ${theme.command("platform setup")}`,
845
857
  "",
846
858
  theme.section("状态图例"),
847
859
  ` ${theme.success("已就绪")} 配置与验证完成`,
848
860
  ` ${theme.warning("需要操作")} 需要执行 setup 步骤`,
849
861
  ` ${theme.info("等待依赖")} 等待上游 Module 或外部服务`,
850
862
  ` ${theme.failure("失败")} 已确认配置或运行故障`,
851
- " 运行中 服务进程正在运行",
852
- " 无独立进程 该模块无需启动",
863
+ " 运行中 服务进程正在运行",
864
+ " 外部资源可用 Chrome 等外部资源已通过真实探测",
865
+ " 无独立进程 该模块无需启动",
853
866
  "",
854
867
  theme.section("遇到问题"),
855
868
  ` 先运行 ${theme.command("platform status")};配置问题运行 ${theme.command("platform setup")}。`,
@@ -866,24 +879,35 @@ export function renderHumanResult(result, options = {}) {
866
879
  ? result.data.blockers.filter(isRecord)
867
880
  : [];
868
881
  if (blockers.length > 0) {
882
+ const productOrder = new Map([
883
+ ["execution-browser-extension", 0],
884
+ ["dev-tunnel", 1],
885
+ ["model-provider-api", 2],
886
+ ]);
869
887
  const groups = [
870
888
  { status: "FAILED", title: "失败", icon: "✕", tone: theme.failure },
871
889
  {
872
890
  status: "ACTION_REQUIRED",
873
- title: "需要操作",
891
+ title: "当前根阻塞",
874
892
  icon: "◆",
875
893
  tone: theme.warning,
876
894
  },
877
- { status: "BLOCKED", title: "等待依赖", icon: "◇", tone: theme.info },
895
+ { status: "BLOCKED", title: "下游等待", icon: "◇", tone: theme.info },
878
896
  ];
879
897
  const lines = [theme.failure("平台未启动:存在未就绪模块"), ""];
880
898
  for (const group of groups) {
881
- const entries = blockers.filter((item) => item.setupStatus === group.status);
899
+ const entries = blockers
900
+ .filter((item) => item.setupStatus === group.status)
901
+ .sort((a, b) => (productOrder.get(String(a.moduleRef)) ?? 100) -
902
+ (productOrder.get(String(b.moduleRef)) ?? 100));
882
903
  if (entries.length === 0)
883
904
  continue;
884
905
  lines.push(theme.section(group.title));
885
- for (const item of entries)
886
- lines.push(`${group.tone(group.icon)} ${theme.section(String(item.moduleRef))}`, ` 原因:${typeof item.reason === "string" ? item.reason : "模块尚未就绪"}`, ` 下一步:${theme.command(typeof item.nextCommand === "string" ? item.nextCommand : `platform setup --module ${String(item.moduleRef)}`)}`);
906
+ for (const item of entries) {
907
+ lines.push(`${group.tone(group.icon)} ${theme.section(String(item.moduleRef))}`, ` 原因:${typeof item.reason === "string" ? item.reason : "模块尚未就绪"}`);
908
+ if (group.status !== "BLOCKED")
909
+ lines.push(` 下一步:${theme.command(typeof item.nextCommand === "string" ? item.nextCommand : `platform setup --module ${String(item.moduleRef)}`)}`);
910
+ }
887
911
  lines.push("");
888
912
  }
889
913
  const readyCount = Array.isArray(result.data.results)
@@ -891,7 +915,7 @@ export function renderHumanResult(result, options = {}) {
891
915
  isRecord(item.result) &&
892
916
  item.result.status === "SUCCEEDED").length - blockers.length
893
917
  : 0;
894
- lines.push(theme.section("检查汇总"), `${Math.max(0, readyCount)} 已就绪 · ${blockers.length} 未就绪 · 0 个模块已启动`, `处理方式:${theme.command(`platform setup${result.workspaceRoot ? ` --workspace "${result.workspaceRoot}"` : ""}`)}`);
918
+ lines.push(theme.section("检查汇总"), `${Math.max(0, readyCount)} 配置已完成 · ${blockers.filter((item) => item.setupStatus === "ACTION_REQUIRED").length} 根阻塞 · ${blockers.filter((item) => item.setupStatus === "BLOCKED").length} 下游等待 · 0 个真实进程启动`, "PLATFORM_READY=NO", `处理方式:${theme.command(`platform setup${result.workspaceRoot ? ` --workspace "${result.workspaceRoot}"` : ""}`)}`);
895
919
  return lines.join("\n");
896
920
  }
897
921
  }
@@ -1,2 +1,2 @@
1
- export declare const FROZEN_DEPLOYMENT_INSTALL_ORDER: readonly ["chrome-runtime", "execution-browser-extension", "agent-controller-dev", "agent-product", "agent-test-ops", "agent-gateway", "dev-tunnel", "agent-runtime", "platform-host", "execution-runtime", "execution-local", "model-provider-api", "model-runtime", "task-orchestration", "task-store-sqlite", "task-migration-runner", "execution-contracts", "model-contracts", "module-contract", "module-skill", "module-template", "deployment-conformance", "platform-cli", "chatgpt-carrier"];
1
+ export declare const FROZEN_DEPLOYMENT_INSTALL_ORDER: readonly ["chrome-runtime", "execution-browser-extension", "agent-controller-dev", "agent-product", "agent-test-ops", "agent-gateway", "dev-tunnel", "agent-runtime", "platform-host", "execution-runtime", "execution-local", "model-provider-api", "model-runtime", "task-orchestration", "task-store-sqlite", "task-migration-runner", "execution-contracts", "model-contracts", "module-contract", "module-skill", "module-template", "deployment-conformance", "platform-cli"];
2
2
  export declare function orderModuleRefsForInstall(moduleRefs: readonly string[]): string[];
@@ -22,7 +22,6 @@ export const FROZEN_DEPLOYMENT_INSTALL_ORDER = [
22
22
  "module-template",
23
23
  "deployment-conformance",
24
24
  "platform-cli",
25
- "chatgpt-carrier",
26
25
  ];
27
26
  const installRank = new Map(FROZEN_DEPLOYMENT_INSTALL_ORDER.map((moduleRef, index) => [moduleRef, index]));
28
27
  export function orderModuleRefsForInstall(moduleRefs) {
@@ -6,5 +6,6 @@ export interface ModuleDispatchResult {
6
6
  command: ModuleManagementCommand;
7
7
  result: ModuleOperationResult;
8
8
  observedEffects: string[];
9
+ externalAvailabilityClaim?: "AVAILABLE" | "UNAVAILABLE";
9
10
  }
10
11
  export declare function dispatchModuleCommand(catalog: ModuleCatalog, module: ResolvedModule, command: ModuleManagementCommand, context: ModuleCommandContext): Promise<ModuleDispatchResult>;
@@ -24,6 +24,10 @@ function normalizeInvocation(raw) {
24
24
  observedEffects: Array.isArray(raw.observedEffects)
25
25
  ? raw.observedEffects.filter((item) => typeof item === "string")
26
26
  : [],
27
+ ...(raw.externalAvailabilityClaim === "AVAILABLE" ||
28
+ raw.externalAvailabilityClaim === "UNAVAILABLE"
29
+ ? { externalAvailabilityClaim: raw.externalAvailabilityClaim }
30
+ : {}),
27
31
  };
28
32
  }
29
33
  export async function dispatchModuleCommand(catalog, module, command, context) {
@@ -32,7 +36,7 @@ export async function dispatchModuleCommand(catalog, module, command, context) {
32
36
  const invoke = adapter[command];
33
37
  if (!isCommandFn(invoke))
34
38
  throw new PlatformError("COMMAND_FAILED", `module ${module.moduleRef} does not implement standard command "${command}"`);
35
- const { result, observedEffects } = normalizeInvocation(await invoke(context));
39
+ const { result, observedEffects, externalAvailabilityClaim } = normalizeInvocation(await invoke(context));
36
40
  const parsed = moduleOperationResultSchema.safeParse(result);
37
41
  if (!parsed.success)
38
42
  throw new PlatformError("COMMAND_FAILED", `module ${module.moduleRef} "${command}" returned an invalid result: ${parsed.error.message}`);
@@ -41,5 +45,8 @@ export async function dispatchModuleCommand(catalog, module, command, context) {
41
45
  command,
42
46
  result: parsed.data,
43
47
  observedEffects,
48
+ ...(externalAvailabilityClaim === undefined
49
+ ? {}
50
+ : { externalAvailabilityClaim }),
44
51
  };
45
52
  }
@@ -178,32 +178,13 @@ export async function setupModulesThin(catalog, modules, workspaceRoot, target,
178
178
  const blockers = [];
179
179
  const graph = buildDependencyGraph(modules);
180
180
  const byRef = new Map(modules.map((module) => [module.moduleRef, module]));
181
- const dependenciesByRef = new Map();
182
- for (const edge of graph.edges) {
183
- const dependencies = dependenciesByRef.get(edge.from) ?? [];
184
- dependencies.push(edge.to);
185
- dependenciesByRef.set(edge.from, dependencies);
186
- }
187
181
  if (target !== undefined && !byRef.has(target.moduleRef))
188
182
  throw new PlatformError("INVALID_REQUEST", `setup target module ${target.moduleRef} was not discovered`);
189
- const visitedRefs = new Set();
190
- const includeWithDependencies = (moduleRef) => {
191
- if (visitedRefs.has(moduleRef))
192
- return;
193
- visitedRefs.add(moduleRef);
194
- for (const dependency of dependenciesByRef.get(moduleRef) ?? [])
195
- includeWithDependencies(dependency);
196
- };
197
- if (target !== undefined)
198
- includeWithDependencies(target.moduleRef);
199
- else
200
- for (const moduleRef of graph.order)
201
- visitedRefs.add(moduleRef);
183
+ const selectedRefs = new Set(target === undefined ? graph.order : [target.moduleRef]);
202
184
  const modulesInOrder = graph.order
203
- .filter((moduleRef) => visitedRefs.has(moduleRef))
185
+ .filter((moduleRef) => selectedRefs.has(moduleRef))
204
186
  .map((moduleRef) => byRef.get(moduleRef))
205
187
  .filter((module) => module !== undefined);
206
- const setupStatusByRef = new Map();
207
188
  let completed = true;
208
189
  for (const [index, module] of modulesInOrder.entries()) {
209
190
  reportProgress(reporter, {
@@ -218,16 +199,12 @@ export async function setupModulesThin(catalog, modules, workspaceRoot, target,
218
199
  const status = await dispatchModuleCommand(catalog, module, "status", context(workspaceRoot));
219
200
  if (!succeeded(status.result)) {
220
201
  results.push(status);
221
- setupStatusByRef.set(module.moduleRef, "FAILED");
222
202
  completed = false;
223
203
  if (target?.moduleRef === module.moduleRef)
224
204
  break;
225
205
  continue;
226
206
  }
227
207
  const observed = moduleStatusObservationSchema.parse(status.result.data);
228
- setupStatusByRef.set(module.moduleRef, observed.setupStatus);
229
- if (target !== undefined && module.moduleRef !== target.moduleRef)
230
- continue;
231
208
  if (observed.setupStatus === "READY" && target === undefined) {
232
209
  skipped.push({ moduleRef: module.moduleRef, reason: "READY" });
233
210
  reportProgress(reporter, {
@@ -241,29 +218,6 @@ export async function setupModulesThin(catalog, modules, workspaceRoot, target,
241
218
  });
242
219
  continue;
243
220
  }
244
- const unavailableDependencies = (dependenciesByRef.get(module.moduleRef) ?? []).filter((moduleRef) => setupStatusByRef.get(moduleRef) !== "READY");
245
- if (unavailableDependencies.length > 0) {
246
- const first = unavailableDependencies[0];
247
- blockers.push({
248
- moduleRef: module.moduleRef,
249
- setupStatus: "BLOCKED",
250
- reason: `等待依赖模块就绪:${unavailableDependencies.join(", ")}`,
251
- nextCommand: `platform setup --module ${first}`,
252
- });
253
- completed = false;
254
- reportProgress(reporter, {
255
- command: "setup",
256
- phase: "setup",
257
- current: index + 1,
258
- total: modulesInOrder.length,
259
- moduleRef: module.moduleRef,
260
- status: "SKIPPED",
261
- message: `${module.moduleRef} 等待 ${unavailableDependencies.join(", ")}`,
262
- });
263
- if (target !== undefined)
264
- break;
265
- continue;
266
- }
267
221
  const setup = await dispatchModuleCommand(catalog, module, "setup", context(workspaceRoot, target?.input));
268
222
  results.push(setup);
269
223
  reportProgress(reporter, {
@@ -283,14 +237,27 @@ export async function setupModulesThin(catalog, modules, workspaceRoot, target,
283
237
  completed = false;
284
238
  }
285
239
  const reconciled = await dispatchModuleCommand(catalog, module, "status", context(workspaceRoot));
286
- if (succeeded(reconciled.result))
287
- setupStatusByRef.set(module.moduleRef, moduleStatusObservationSchema.parse(reconciled.result.data).setupStatus);
288
- else {
240
+ if (!succeeded(reconciled.result)) {
289
241
  results.push(reconciled);
290
- setupStatusByRef.set(module.moduleRef, "FAILED");
291
242
  completed = false;
292
243
  }
293
- if (target !== undefined && !succeeded(setup.result))
244
+ else {
245
+ const reconciledStatus = moduleStatusObservationSchema.parse(reconciled.result.data);
246
+ if (reconciledStatus.setupStatus === "BLOCKED" ||
247
+ reconciledStatus.setupStatus === "FAILED") {
248
+ const issue = reconciledStatus.issues?.find((item) => item.scope === "SETUP");
249
+ blockers.push({
250
+ moduleRef: module.moduleRef,
251
+ setupStatus: reconciledStatus.setupStatus,
252
+ ...(issue === undefined
253
+ ? {}
254
+ : { reason: issue.message, nextCommand: issue.nextCommand }),
255
+ });
256
+ completed = false;
257
+ }
258
+ }
259
+ if (target !== undefined &&
260
+ (!succeeded(setup.result) || blockers.length > 0))
294
261
  break;
295
262
  }
296
263
  return {
@@ -1,2 +1,2 @@
1
1
  export type { NpmCommandResult, NpmCommandRunner, RegistryDiscoveryResult, RegistryModuleCandidate, RegistryRejectedPackage, } from "./npm-registry.ts";
2
- export { discoverRegistryModules, PRO_FLOW_PACKAGE_PREFIX, PRO_FLOW_SCOPE, resolveScopeRegistry, systemNpmRunner, } from "./npm-registry.ts";
2
+ export { discoverRegistryModules, PRO_FLOW_PACKAGE_PREFIX, PRO_FLOW_SCOPE, RETIRED_PRO_FLOW_PACKAGES, resolveScopeRegistry, systemNpmRunner, } from "./npm-registry.ts";
@@ -1 +1 @@
1
- export { discoverRegistryModules, PRO_FLOW_PACKAGE_PREFIX, PRO_FLOW_SCOPE, resolveScopeRegistry, systemNpmRunner, } from "./npm-registry.js";
1
+ export { discoverRegistryModules, PRO_FLOW_PACKAGE_PREFIX, PRO_FLOW_SCOPE, RETIRED_PRO_FLOW_PACKAGES, resolveScopeRegistry, systemNpmRunner, } from "./npm-registry.js";
@@ -1,5 +1,6 @@
1
1
  export declare const PRO_FLOW_SCOPE = "@tomflow";
2
2
  export declare const PRO_FLOW_PACKAGE_PREFIX = "@tomflow/proflow-";
3
+ export declare const RETIRED_PRO_FLOW_PACKAGES: Set<string>;
3
4
  export interface NpmCommandResult {
4
5
  stdout: string;
5
6
  stderr: string;
@@ -26,6 +27,7 @@ export interface RegistryDiscoveryResult {
26
27
  registry: string;
27
28
  candidates: RegistryModuleCandidate[];
28
29
  rejected: RegistryRejectedPackage[];
30
+ retired: string[];
29
31
  }
30
32
  export declare function systemNpmRunner(): NpmCommandRunner;
31
33
  export declare function resolveScopeRegistry(workspaceRoot: string, runner?: NpmCommandRunner): Promise<string>;
@@ -6,6 +6,9 @@ import { versionSatisfies } from "../modules.js";
6
6
  const execFileAsync = promisify(execFile);
7
7
  export const PRO_FLOW_SCOPE = "@tomflow";
8
8
  export const PRO_FLOW_PACKAGE_PREFIX = "@tomflow/proflow-";
9
+ export const RETIRED_PRO_FLOW_PACKAGES = new Set([
10
+ "@tomflow/proflow-chatgpt-carrier",
11
+ ]);
9
12
  export function systemNpmRunner() {
10
13
  return {
11
14
  async run(args, cwd, timeoutMs) {
@@ -42,15 +45,17 @@ export async function discoverRegistryModules(options) {
42
45
  const names = options.packageName === undefined
43
46
  ? await searchPackageNames(options.workspaceRoot, registry, runner)
44
47
  : [validateRequestedPackageName(options.packageName)];
45
- options.onSearchComplete?.(names.length);
48
+ const retired = names.filter((name) => RETIRED_PRO_FLOW_PACKAGES.has(name));
49
+ const activeNames = names.filter((name) => !RETIRED_PRO_FLOW_PACKAGES.has(name));
50
+ options.onSearchComplete?.(activeNames.length);
46
51
  const candidates = [];
47
52
  const rejected = [];
48
53
  let nextIndex = 0;
49
54
  let completed = 0;
50
55
  const worker = async () => {
51
- while (nextIndex < names.length) {
56
+ while (nextIndex < activeNames.length) {
52
57
  const index = nextIndex++;
53
- const packageName = names[index];
58
+ const packageName = activeNames[index];
54
59
  if (packageName === undefined)
55
60
  return;
56
61
  const manifest = await viewManifest(options.workspaceRoot, registry, packageName, runner);
@@ -62,15 +67,15 @@ export async function discoverRegistryModules(options) {
62
67
  completed += 1;
63
68
  options.onPackageChecked?.({
64
69
  current: completed,
65
- total: names.length,
70
+ total: activeNames.length,
66
71
  packageName,
67
72
  });
68
73
  }
69
74
  };
70
- await Promise.all(Array.from({ length: Math.min(4, names.length) }, () => worker()));
75
+ await Promise.all(Array.from({ length: Math.min(4, activeNames.length) }, () => worker()));
71
76
  candidates.sort((left, right) => left.packageName.localeCompare(right.packageName));
72
77
  rejected.sort((left, right) => left.packageName.localeCompare(right.packageName));
73
- return { registry, candidates, rejected };
78
+ return { registry, candidates, rejected, retired };
74
79
  }
75
80
  async function searchPackageNames(workspaceRoot, registry, runner) {
76
81
  const result = await runner.run([
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tomflow/proflow-platform-cli",
3
- "version": "0.1.37",
3
+ "version": "0.1.38",
4
4
  "type": "module",
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -27,8 +27,8 @@
27
27
  "@tomflow/proflow-module-contract": "^0.1.13"
28
28
  },
29
29
  "devDependencies": {
30
- "@tomflow/proflow-module-template": "^0.1.10",
31
- "@tomflow/proflow-deployment-conformance": "^0.1.11"
30
+ "@tomflow/proflow-deployment-conformance": "^0.1.12",
31
+ "@tomflow/proflow-module-template": "^0.1.10"
32
32
  },
33
33
  "description": "Thin Platform CLI for Module discovery, documentation, package synchronization and lifecycle orchestration.",
34
34
  "keywords": [
@@ -3,7 +3,7 @@
3
3
  "contractVersion": "1.0.0",
4
4
  "moduleRef": "platform-cli",
5
5
  "packageName": "@tomflow/proflow-platform-cli",
6
- "moduleVersion": "0.1.37",
6
+ "moduleVersion": "0.1.38",
7
7
  "kind": "cli",
8
8
  "templateVersion": "1.0.0",
9
9
  "platformCompatibility": ">=1.0.0 <2.0.0",