@curdx/flow 3.3.0 → 3.3.1
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 +7 -0
- package/dist/index.mjs +59 -14
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,13 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to `@curdx/flow` are documented here. Format follows [Keep a Changelog](https://keepachangelog.com/) and the project follows [Semantic Versioning](https://semver.org/).
|
|
4
4
|
|
|
5
|
+
## 3.3.1 — 2026-04-27
|
|
6
|
+
|
|
7
|
+
### Fixed
|
|
8
|
+
|
|
9
|
+
- **Silent stalls between phases** — added spinners to the previously-silent windows where flow shells out to `claude plugin list --json` and `claude mcp list` (the latter performs an MCP server health check and can take 5-15 seconds). Affected sites: `install` (state-derivation between marketplace refresh and the multiselect), `update` and `uninstall` (state-derivation at flow entry), and the post-flow CLAUDE.md sync (after install/update/uninstall busts the cache, sync re-queries state). Each now shows `Checking installed state… (claude plugin list / mcp list)` with a result line so the run no longer feels frozen.
|
|
10
|
+
- **CLAUDE.md sync feedback** — replaced the post-hoc `p.log.info` line with a live spinner that converts to a final status line on completion, matching the marketplace-refresh and per-item install UX.
|
|
11
|
+
|
|
5
12
|
## 3.3.0 — 2026-04-27
|
|
6
13
|
|
|
7
14
|
### Added
|
package/dist/index.mjs
CHANGED
|
@@ -67,6 +67,9 @@ var messages = {
|
|
|
67
67
|
"chrome.prereqChrome": "\u9700\u8981\u672C\u673A\u5DF2\u5B89\u88C5 Chrome\uFF08chrome-devtools-mcp \u4F1A\u8C03\u7528\u672C\u5730\u6D4F\u89C8\u5668\uFF09",
|
|
68
68
|
"reinstall.uninstalling": "\u5148\u5378\u8F7D\u65E7\u7248\u672C\u2026",
|
|
69
69
|
"reinstall.installing": "\u5B89\u88C5\u65B0\u7248\u672C\u2026",
|
|
70
|
+
"state.checking": "\u68C0\u67E5\u5DF2\u5B89\u88C5\u72B6\u6001\u2026\uFF08claude plugin list / mcp list\uFF09",
|
|
71
|
+
"state.checked": "\u5DF2\u68C0\u67E5 {count} \u9879",
|
|
72
|
+
"claudeMd.syncing": "\u540C\u6B65 ~/.claude/CLAUDE.md \u2026",
|
|
70
73
|
"claudeMd.synced": "CLAUDE.md \u5DF2\u66F4\u65B0\uFF08{path}\uFF09",
|
|
71
74
|
"claudeMd.unchanged": "CLAUDE.md \u5DF2\u662F\u6700\u65B0",
|
|
72
75
|
"claudeMd.removed": "\u5DF2\u4ECE CLAUDE.md \u79FB\u9664 @curdx/flow \u533A\u5757",
|
|
@@ -135,6 +138,9 @@ var messages2 = {
|
|
|
135
138
|
"chrome.prereqChrome": "Requires Chrome installed locally (chrome-devtools-mcp drives the local browser)",
|
|
136
139
|
"reinstall.uninstalling": "Uninstalling old version\u2026",
|
|
137
140
|
"reinstall.installing": "Installing new version\u2026",
|
|
141
|
+
"state.checking": "Checking installed state\u2026 (claude plugin list / mcp list)",
|
|
142
|
+
"state.checked": "Checked {count} item(s)",
|
|
143
|
+
"claudeMd.syncing": "Syncing ~/.claude/CLAUDE.md\u2026",
|
|
138
144
|
"claudeMd.synced": "CLAUDE.md updated ({path})",
|
|
139
145
|
"claudeMd.unchanged": "CLAUDE.md already up to date",
|
|
140
146
|
"claudeMd.removed": "Removed @curdx/flow block from CLAUDE.md",
|
|
@@ -769,23 +775,29 @@ async function syncClaudeMd(opts) {
|
|
|
769
775
|
}
|
|
770
776
|
}
|
|
771
777
|
async function syncFromState(opts) {
|
|
772
|
-
|
|
778
|
+
if (opts?.skip) {
|
|
779
|
+
p3.log.info(t("claudeMd.skipped"));
|
|
780
|
+
return;
|
|
781
|
+
}
|
|
782
|
+
const sp = p3.spinner();
|
|
783
|
+
sp.start(t("claudeMd.syncing"));
|
|
784
|
+
const r = await syncClaudeMd();
|
|
773
785
|
switch (r.status) {
|
|
774
786
|
case "skipped":
|
|
775
|
-
|
|
787
|
+
sp.stop(t("claudeMd.skipped"));
|
|
776
788
|
return;
|
|
777
789
|
case "unchanged":
|
|
778
|
-
|
|
790
|
+
sp.stop(t("claudeMd.unchanged"));
|
|
779
791
|
return;
|
|
780
792
|
case "created":
|
|
781
793
|
case "updated":
|
|
782
|
-
|
|
794
|
+
sp.stop(t("claudeMd.synced", { path: r.path }));
|
|
783
795
|
return;
|
|
784
796
|
case "removed":
|
|
785
|
-
|
|
797
|
+
sp.stop(t("claudeMd.removed"));
|
|
786
798
|
return;
|
|
787
799
|
case "failed":
|
|
788
|
-
|
|
800
|
+
sp.stop(t("claudeMd.failed", { error: r.error ?? "unknown" }));
|
|
789
801
|
return;
|
|
790
802
|
}
|
|
791
803
|
}
|
|
@@ -948,11 +960,18 @@ async function installFlow(opts = {}) {
|
|
|
948
960
|
return;
|
|
949
961
|
}
|
|
950
962
|
const stateMap = /* @__PURE__ */ new Map();
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
963
|
+
const sp = p4.spinner();
|
|
964
|
+
sp.start(t("state.checking"));
|
|
965
|
+
try {
|
|
966
|
+
await Promise.all([listPlugins(), listMcp()]);
|
|
967
|
+
await Promise.all(
|
|
968
|
+
candidates.map(async (pkg) => {
|
|
969
|
+
stateMap.set(pkg.id, await deriveState(pkg));
|
|
970
|
+
})
|
|
971
|
+
);
|
|
972
|
+
} finally {
|
|
973
|
+
sp.stop(t("state.checked", { count: candidates.length }));
|
|
974
|
+
}
|
|
956
975
|
let targets;
|
|
957
976
|
if (explicit) {
|
|
958
977
|
targets = candidates;
|
|
@@ -984,8 +1003,21 @@ async function getInstalled() {
|
|
|
984
1003
|
const states = await Promise.all(PKGS.map(async (pkg) => ({ pkg, installed: await pkg.isInstalled() })));
|
|
985
1004
|
return states.filter((s) => s.installed).map((s) => s.pkg);
|
|
986
1005
|
}
|
|
1006
|
+
async function probeInstalled() {
|
|
1007
|
+
const sp = p5.spinner();
|
|
1008
|
+
sp.start(t("state.checking"));
|
|
1009
|
+
try {
|
|
1010
|
+
await Promise.all([listPlugins(), listMcp()]);
|
|
1011
|
+
const installed = await getInstalled();
|
|
1012
|
+
sp.stop(t("state.checked", { count: installed.length }));
|
|
1013
|
+
return installed;
|
|
1014
|
+
} catch (err) {
|
|
1015
|
+
sp.stop(t("state.checked", { count: 0 }));
|
|
1016
|
+
throw err;
|
|
1017
|
+
}
|
|
1018
|
+
}
|
|
987
1019
|
async function uninstallFlow(opts = {}) {
|
|
988
|
-
const installed = await
|
|
1020
|
+
const installed = await probeInstalled();
|
|
989
1021
|
let targets;
|
|
990
1022
|
if (opts.ids && opts.ids.length > 0) {
|
|
991
1023
|
targets = [];
|
|
@@ -1068,8 +1100,21 @@ async function getInstalled2() {
|
|
|
1068
1100
|
const states = await Promise.all(PKGS.map(async (pkg) => ({ pkg, installed: await pkg.isInstalled() })));
|
|
1069
1101
|
return states.filter((s) => s.installed).map((s) => s.pkg);
|
|
1070
1102
|
}
|
|
1103
|
+
async function probeInstalled2() {
|
|
1104
|
+
const sp = p6.spinner();
|
|
1105
|
+
sp.start(t("state.checking"));
|
|
1106
|
+
try {
|
|
1107
|
+
await Promise.all([listPlugins(), listMcp()]);
|
|
1108
|
+
const installed = await getInstalled2();
|
|
1109
|
+
sp.stop(t("state.checked", { count: installed.length }));
|
|
1110
|
+
return installed;
|
|
1111
|
+
} catch (err) {
|
|
1112
|
+
sp.stop(t("state.checked", { count: 0 }));
|
|
1113
|
+
throw err;
|
|
1114
|
+
}
|
|
1115
|
+
}
|
|
1071
1116
|
async function updateFlow(opts = {}) {
|
|
1072
|
-
const installed = await
|
|
1117
|
+
const installed = await probeInstalled2();
|
|
1073
1118
|
if (installed.length === 0) {
|
|
1074
1119
|
p6.log.info(t("update.noneInstalled"));
|
|
1075
1120
|
return;
|
|
@@ -1316,7 +1361,7 @@ var SUBCOMMANDS = /* @__PURE__ */ new Set(["install", "uninstall", "update", "st
|
|
|
1316
1361
|
var root = defineCommand({
|
|
1317
1362
|
meta: {
|
|
1318
1363
|
name: "@curdx/flow",
|
|
1319
|
-
version: "3.3.
|
|
1364
|
+
version: "3.3.1",
|
|
1320
1365
|
description: "Interactive installer for Claude Code plugins and MCP servers"
|
|
1321
1366
|
},
|
|
1322
1367
|
args: sharedArgs,
|