@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 +6 -0
- package/dist/deployment/adapter.d.ts +7 -7
- package/dist/deployment/descriptor.d.ts +1 -1
- package/dist/deployment/descriptor.js +1 -1
- package/dist/src/cli.js +55 -31
- package/dist/src/deployment-order.d.ts +1 -1
- package/dist/src/deployment-order.js +0 -1
- package/dist/src/lifecycle/dispatch.d.ts +1 -0
- package/dist/src/lifecycle/dispatch.js +8 -1
- package/dist/src/lifecycle/thin.js +20 -53
- package/dist/src/registry/index.d.ts +1 -1
- package/dist/src/registry/index.js +1 -1
- package/dist/src/registry/npm-registry.d.ts +2 -0
- package/dist/src/registry/npm-registry.js +11 -6
- package/package.json +3 -3
- package/proflow.module.json +1 -1
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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" &&
|
|
563
|
-
|
|
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] ?? "未知")} · ${
|
|
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
|
-
|
|
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 =
|
|
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}
|
|
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: "
|
|
673
|
+
ai: "platform setup --module dev-tunnel",
|
|
661
674
|
inputs: "无",
|
|
662
675
|
},
|
|
663
676
|
"model-provider-api": {
|
|
664
|
-
ai: "
|
|
677
|
+
ai: "platform setup --module model-provider-api",
|
|
665
678
|
inputs: "无(等待 Deployment resolver 提供 endpoint)",
|
|
666
679
|
},
|
|
667
680
|
"model-runtime": {
|
|
668
|
-
ai: "
|
|
681
|
+
ai: "platform setup --module model-runtime",
|
|
669
682
|
inputs: "无(仅等价合格候选歧义时选择)",
|
|
670
683
|
},
|
|
671
684
|
"execution-browser-extension": {
|
|
672
|
-
ai: "
|
|
685
|
+
ai: "platform setup --module execution-browser-extension",
|
|
673
686
|
inputs: "无",
|
|
674
687
|
},
|
|
675
688
|
"agent-controller-dev": {
|
|
676
|
-
ai: "
|
|
689
|
+
ai: "platform setup --module agent-controller-dev",
|
|
677
690
|
inputs: "无",
|
|
678
691
|
},
|
|
679
692
|
"agent-product": {
|
|
680
|
-
ai: "
|
|
693
|
+
ai: "platform setup --module agent-product",
|
|
681
694
|
inputs: "无",
|
|
682
695
|
},
|
|
683
696
|
"agent-test-ops": {
|
|
684
|
-
ai: "
|
|
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: `
|
|
757
|
+
ai: `platform setup --module ${moduleRef}`,
|
|
745
758
|
inputs: "按命令提示提供",
|
|
746
759
|
};
|
|
747
|
-
lines.push(`
|
|
760
|
+
lines.push(` 人工执行:${commands.ai}`);
|
|
748
761
|
lines.push(` AI 执行:${commands.ai}`);
|
|
749
762
|
lines.push(` 需要输入:${commands.inputs}`);
|
|
750
|
-
lines.push(
|
|
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
|
-
`
|
|
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: "
|
|
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
|
|
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 : "模块尚未就绪"}
|
|
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)}
|
|
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"
|
|
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
|
|
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) =>
|
|
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
|
-
|
|
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
|
-
|
|
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 <
|
|
56
|
+
while (nextIndex < activeNames.length) {
|
|
52
57
|
const index = nextIndex++;
|
|
53
|
-
const packageName =
|
|
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:
|
|
70
|
+
total: activeNames.length,
|
|
66
71
|
packageName,
|
|
67
72
|
});
|
|
68
73
|
}
|
|
69
74
|
};
|
|
70
|
-
await Promise.all(Array.from({ length: Math.min(4,
|
|
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.
|
|
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-
|
|
31
|
-
"@tomflow/proflow-
|
|
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": [
|
package/proflow.module.json
CHANGED