helloloop 0.7.2 → 0.7.3

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.
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "helloloop",
3
- "version": "0.7.2",
3
+ "version": "0.7.3",
4
4
  "description": "HelloLoop 的 Claude Code 原生插件元数据,用于多 CLI 宿主分发。",
5
5
  "author": {
6
6
  "name": "HelloLoop"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "helloloop",
3
- "version": "0.7.2",
3
+ "version": "0.7.3",
4
4
  "description": "面向 Codex CLI、Claude Code、Gemini CLI 的多宿主开发工作流插件,Codex 路径为首发与参考实现。",
5
5
  "author": {
6
6
  "name": "HelloLoop"
package/README.md CHANGED
@@ -294,7 +294,8 @@ npx helloloop install --host all --force
294
294
  - `Claude` 会刷新 marketplace、缓存插件目录,以及 `settings.json` / `known_marketplaces.json` / `installed_plugins.json` 中的 `helloloop` 条目
295
295
  - `Gemini` 会刷新 `extensions/helloloop/`,不会动同目录下其他扩展
296
296
  - 安装 / 升级 / 重装时,会同步校准 `~/.helloloop/settings.json` 的当前版本结构:补齐缺失项、清理未知项、保留已知项现有值
297
- - 如果 `~/.helloloop/settings.json` 不是合法 JSON,会先备份原文件,再按当前版本结构重建
297
+ - 如果 `~/.helloloop/settings.json` 被确认不是合法 JSON,会先备份原文件,再按当前版本结构重建
298
+ - 如果只是首次读取时出现瞬时异常,但重读后内容合法,则不会误生成备份文件
298
299
  - 如果宿主自己的配置 JSON(如 `Codex marketplace.json`、`Claude settings.json`、`known_marketplaces.json`、`installed_plugins.json`)本身已损坏,`HelloLoop` 会先明确报错并停止,不会先清理现有安装再失败
299
300
 
300
301
  ### 卸载
@@ -442,7 +443,8 @@ npx helloloop doctor --host all --codex-home <CODEX_HOME> --claude-home <CLAUDE_
442
443
 
443
444
  - 这里不保存项目 backlog、状态、运行记录
444
445
  - 安装 / 升级 / 重装时,会对 `settings.json` 做结构校准,但不会校验或篡改你已存在的已知项内容
445
- - 如果 `settings.json` 非法,会先备份,再重建为当前版本结构
446
+ - 只有在 `settings.json` 被确认非法时,才会先备份,再重建为当前版本结构
447
+ - 如果只是读取瞬时异常、重读后合法,不会误生成 `.bak`
446
448
 
447
449
  ## `.helloloop/` 状态目录
448
450
 
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "helloloop",
3
- "version": "0.7.2",
3
+ "version": "0.7.3",
4
4
  "description": "HelloLoop 的 Gemini CLI 原生扩展,用于按开发文档接续推进项目开发。",
5
5
  "contextFileName": "GEMINI.md",
6
6
  "excludeTools": [
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "helloloop",
3
- "version": "0.7.2",
3
+ "version": "0.7.3",
4
4
  "description": "面向 Codex CLI、Claude Code、Gemini CLI 的多宿主开发工作流插件",
5
5
  "author": "HelloLoop",
6
6
  "license": "Apache-2.0",
@@ -148,6 +148,10 @@ export function saveUserSettings(settings, options = {}) {
148
148
  });
149
149
  }
150
150
 
151
+ function tryParseUserSettingsText(text) {
152
+ return JSON.parse(String(text || ""));
153
+ }
154
+
151
155
  export function syncUserSettingsFile(options = {}) {
152
156
  const settingsFile = resolveUserSettingsFile(options.userSettingsFile);
153
157
  const defaults = defaultUserSettings();
@@ -161,12 +165,33 @@ export function syncUserSettingsFile(options = {}) {
161
165
  };
162
166
  }
163
167
 
164
- let parsed;
168
+ const firstText = readText(settingsFile);
165
169
  try {
166
- parsed = readJson(settingsFile);
170
+ const parsed = tryParseUserSettingsText(firstText);
171
+ writeJson(settingsFile, syncUserSettingsShape(parsed));
172
+ return {
173
+ settingsFile,
174
+ action: "synced",
175
+ backupFile: "",
176
+ };
167
177
  } catch (error) {
178
+ const retryText = readText(settingsFile);
179
+ if (retryText !== firstText) {
180
+ try {
181
+ const parsed = tryParseUserSettingsText(retryText);
182
+ writeJson(settingsFile, syncUserSettingsShape(parsed));
183
+ return {
184
+ settingsFile,
185
+ action: "synced",
186
+ backupFile: "",
187
+ recoveredAfterRetry: true,
188
+ };
189
+ } catch {
190
+ }
191
+ }
192
+
168
193
  const backupFile = `${settingsFile}.invalid-${timestampForFile()}.bak`;
169
- writeText(backupFile, readText(settingsFile));
194
+ writeText(backupFile, retryText);
170
195
  writeJson(settingsFile, defaults);
171
196
  return {
172
197
  settingsFile,
@@ -175,11 +200,4 @@ export function syncUserSettingsFile(options = {}) {
175
200
  error: String(error?.message || error || ""),
176
201
  };
177
202
  }
178
-
179
- writeJson(settingsFile, syncUserSettingsShape(parsed));
180
- return {
181
- settingsFile,
182
- action: "synced",
183
- backupFile: "",
184
- };
185
203
  }