@simonyea/holysheep-cli 2.1.75 → 2.1.77

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.
@@ -4150,16 +4150,265 @@ providers:
4150
4150
  }
4151
4151
  });
4152
4152
 
4153
+ // src/tools/qwen-code.js
4154
+ var require_qwen_code = __commonJS({
4155
+ "src/tools/qwen-code.js"(exports2, module2) {
4156
+ var fs = require("fs");
4157
+ var path = require("path");
4158
+ var os = require("os");
4159
+ var CONFIG_DIR = path.join(os.homedir(), ".qwen");
4160
+ var CONFIG_FILE = path.join(CONFIG_DIR, ".env");
4161
+ var MARKER_BEGIN = "# >>> HolySheep BEGIN >>>";
4162
+ var MARKER_END = "# <<< HolySheep END <<<";
4163
+ var DEFAULT_OPENAI_MODEL = "gpt-5.5";
4164
+ var DEFAULT_ANTHROPIC_MODEL = "claude-sonnet-4-6";
4165
+ function stripManagedBlock(content) {
4166
+ if (!content) return "";
4167
+ const text = String(content).replace(/\r\n/g, "\n");
4168
+ const re = new RegExp(
4169
+ `(?:^|\\n)\\s*${escapeRegex(MARKER_BEGIN)}[\\s\\S]*?${escapeRegex(MARKER_END)}\\s*(?:\\n|$)`,
4170
+ "g"
4171
+ );
4172
+ return text.replace(re, "\n");
4173
+ }
4174
+ __name(stripManagedBlock, "stripManagedBlock");
4175
+ function escapeRegex(s) {
4176
+ return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
4177
+ }
4178
+ __name(escapeRegex, "escapeRegex");
4179
+ function buildManagedBlock(apiKey, baseUrlAnthropicNoV1, baseUrlOpenAI) {
4180
+ const cleanOpenAi = String(baseUrlOpenAI || "https://api.holysheep.ai/v1").replace(/\/+$/, "");
4181
+ const cleanAnthropic = String(baseUrlAnthropicNoV1 || "https://api.holysheep.ai").replace(/\/+$/, "");
4182
+ return [
4183
+ MARKER_BEGIN,
4184
+ "# Managed by holysheep-cli \u2014 do not edit between markers.",
4185
+ "# Run `hs reset` to remove this block; user-added env lines outside",
4186
+ "# this block are preserved.",
4187
+ `OPENAI_API_KEY=${apiKey}`,
4188
+ `OPENAI_BASE_URL=${cleanOpenAi}`,
4189
+ `OPENAI_MODEL=${DEFAULT_OPENAI_MODEL}`,
4190
+ `ANTHROPIC_BASE_URL=${cleanAnthropic}`,
4191
+ `ANTHROPIC_AUTH_TOKEN=${apiKey}`,
4192
+ `ANTHROPIC_MODEL=${DEFAULT_ANTHROPIC_MODEL}`,
4193
+ MARKER_END
4194
+ ].join("\n");
4195
+ }
4196
+ __name(buildManagedBlock, "buildManagedBlock");
4197
+ function readSafe() {
4198
+ try {
4199
+ if (fs.existsSync(CONFIG_FILE)) {
4200
+ return fs.readFileSync(CONFIG_FILE, "utf8");
4201
+ }
4202
+ } catch {
4203
+ }
4204
+ return "";
4205
+ }
4206
+ __name(readSafe, "readSafe");
4207
+ function writeManaged(apiKey, baseUrlAnthropicNoV1, baseUrlOpenAI) {
4208
+ fs.mkdirSync(CONFIG_DIR, { recursive: true });
4209
+ const existing = readSafe();
4210
+ const stripped = stripManagedBlock(existing);
4211
+ const block = buildManagedBlock(apiKey, baseUrlAnthropicNoV1, baseUrlOpenAI);
4212
+ const userPart = stripped.replace(/\n{3,}/g, "\n\n").replace(/^\n+|\n+$/g, "");
4213
+ const out = userPart ? `${userPart}
4214
+
4215
+ ${block}
4216
+ ` : `${block}
4217
+ `;
4218
+ fs.writeFileSync(CONFIG_FILE, out, { encoding: "utf8", mode: 384 });
4219
+ try {
4220
+ fs.chmodSync(CONFIG_FILE, 384);
4221
+ } catch {
4222
+ }
4223
+ }
4224
+ __name(writeManaged, "writeManaged");
4225
+ module2.exports = {
4226
+ name: "Qwen Code",
4227
+ id: "qwen-code",
4228
+ // See header comment — npx fallback means the CLI is "always available"
4229
+ // from aionui's perspective, so we always want auto-config to run.
4230
+ checkInstalled() {
4231
+ return true;
4232
+ },
4233
+ isConfigured() {
4234
+ const content = readSafe();
4235
+ return content.includes(MARKER_BEGIN) && content.includes(MARKER_END);
4236
+ },
4237
+ configure(apiKey, baseUrlAnthropicNoV1, baseUrlOpenAI) {
4238
+ if (!apiKey) {
4239
+ throw new Error("qwen-code.configure: apiKey is required");
4240
+ }
4241
+ writeManaged(apiKey, baseUrlAnthropicNoV1, baseUrlOpenAI);
4242
+ return {
4243
+ file: CONFIG_FILE,
4244
+ hot: true
4245
+ };
4246
+ },
4247
+ reset() {
4248
+ if (!fs.existsSync(CONFIG_FILE)) return;
4249
+ const stripped = stripManagedBlock(readSafe());
4250
+ const cleaned = stripped.replace(/^\n+|\n+$/g, "");
4251
+ if (cleaned) {
4252
+ fs.writeFileSync(CONFIG_FILE, cleaned + "\n", "utf8");
4253
+ } else {
4254
+ fs.writeFileSync(CONFIG_FILE, "", "utf8");
4255
+ }
4256
+ },
4257
+ getConfigPath() {
4258
+ return CONFIG_FILE;
4259
+ },
4260
+ hint: "Qwen Code \u901A\u8FC7 ~/.qwen/.env \u8BFB\u53D6 OPENAI_API_KEY / OPENAI_BASE_URL / OPENAI_MODEL\uFF1B\u542F\u52A8\u540E\u7ACB\u5373\u751F\u6548",
4261
+ launchCmd: "qwen",
4262
+ installCmd: "npm install -g @qwen-code/qwen-code",
4263
+ docsUrl: "https://qwenlm.github.io/qwen-code-docs/en/users/configuration/auth/",
4264
+ envVarFormat: "openai",
4265
+ // Exposed for tests / future tooling.
4266
+ __internal: {
4267
+ MARKER_BEGIN,
4268
+ MARKER_END,
4269
+ DEFAULT_OPENAI_MODEL,
4270
+ DEFAULT_ANTHROPIC_MODEL,
4271
+ stripManagedBlock,
4272
+ buildManagedBlock
4273
+ }
4274
+ };
4275
+ }
4276
+ });
4277
+
4278
+ // src/tools/codebuddy.js
4279
+ var require_codebuddy = __commonJS({
4280
+ "src/tools/codebuddy.js"(exports2, module2) {
4281
+ var fs = require("fs");
4282
+ var path = require("path");
4283
+ var os = require("os");
4284
+ var CONFIG_DIR = path.join(os.homedir(), ".codebuddy");
4285
+ var CONFIG_FILE = path.join(CONFIG_DIR, ".env");
4286
+ var MARKER_BEGIN = "# >>> HolySheep BEGIN >>>";
4287
+ var MARKER_END = "# <<< HolySheep END <<<";
4288
+ var DEFAULT_OPENAI_MODEL = "gpt-5.5";
4289
+ var DEFAULT_ANTHROPIC_MODEL = "claude-sonnet-4-6";
4290
+ function escapeRegex(s) {
4291
+ return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
4292
+ }
4293
+ __name(escapeRegex, "escapeRegex");
4294
+ function stripManagedBlock(content) {
4295
+ if (!content) return "";
4296
+ const text = String(content).replace(/\r\n/g, "\n");
4297
+ const re = new RegExp(
4298
+ `(?:^|\\n)\\s*${escapeRegex(MARKER_BEGIN)}[\\s\\S]*?${escapeRegex(MARKER_END)}\\s*(?:\\n|$)`,
4299
+ "g"
4300
+ );
4301
+ return text.replace(re, "\n");
4302
+ }
4303
+ __name(stripManagedBlock, "stripManagedBlock");
4304
+ function buildManagedBlock(apiKey, baseUrlAnthropicNoV1, baseUrlOpenAI) {
4305
+ const cleanOpenAi = String(baseUrlOpenAI || "https://api.holysheep.ai/v1").replace(/\/+$/, "");
4306
+ const cleanAnthropic = String(baseUrlAnthropicNoV1 || "https://api.holysheep.ai").replace(/\/+$/, "");
4307
+ return [
4308
+ MARKER_BEGIN,
4309
+ "# Managed by holysheep-cli \u2014 do not edit between markers.",
4310
+ "# Run `hs reset` to remove this block; user-added env lines outside",
4311
+ "# this block (e.g. CODEBUDDY_INTERNET_ENVIRONMENT) are preserved.",
4312
+ `CODEBUDDY_API_KEY=${apiKey}`,
4313
+ `CODEBUDDY_BASE_URL=${cleanOpenAi}`,
4314
+ `OPENAI_API_KEY=${apiKey}`,
4315
+ `OPENAI_BASE_URL=${cleanOpenAi}`,
4316
+ `OPENAI_MODEL=${DEFAULT_OPENAI_MODEL}`,
4317
+ `ANTHROPIC_BASE_URL=${cleanAnthropic}`,
4318
+ `ANTHROPIC_AUTH_TOKEN=${apiKey}`,
4319
+ `ANTHROPIC_MODEL=${DEFAULT_ANTHROPIC_MODEL}`,
4320
+ MARKER_END
4321
+ ].join("\n");
4322
+ }
4323
+ __name(buildManagedBlock, "buildManagedBlock");
4324
+ function readSafe() {
4325
+ try {
4326
+ if (fs.existsSync(CONFIG_FILE)) {
4327
+ return fs.readFileSync(CONFIG_FILE, "utf8");
4328
+ }
4329
+ } catch {
4330
+ }
4331
+ return "";
4332
+ }
4333
+ __name(readSafe, "readSafe");
4334
+ function writeManaged(apiKey, baseUrlAnthropicNoV1, baseUrlOpenAI) {
4335
+ fs.mkdirSync(CONFIG_DIR, { recursive: true });
4336
+ const existing = readSafe();
4337
+ const stripped = stripManagedBlock(existing);
4338
+ const block = buildManagedBlock(apiKey, baseUrlAnthropicNoV1, baseUrlOpenAI);
4339
+ const userPart = stripped.replace(/\n{3,}/g, "\n\n").replace(/^\n+|\n+$/g, "");
4340
+ const out = userPart ? `${userPart}
4341
+
4342
+ ${block}
4343
+ ` : `${block}
4344
+ `;
4345
+ fs.writeFileSync(CONFIG_FILE, out, { encoding: "utf8", mode: 384 });
4346
+ try {
4347
+ fs.chmodSync(CONFIG_FILE, 384);
4348
+ } catch {
4349
+ }
4350
+ }
4351
+ __name(writeManaged, "writeManaged");
4352
+ module2.exports = {
4353
+ name: "CodeBuddy",
4354
+ id: "codebuddy",
4355
+ checkInstalled() {
4356
+ return true;
4357
+ },
4358
+ isConfigured() {
4359
+ const content = readSafe();
4360
+ return content.includes(MARKER_BEGIN) && content.includes(MARKER_END);
4361
+ },
4362
+ configure(apiKey, baseUrlAnthropicNoV1, baseUrlOpenAI) {
4363
+ if (!apiKey) {
4364
+ throw new Error("codebuddy.configure: apiKey is required");
4365
+ }
4366
+ writeManaged(apiKey, baseUrlAnthropicNoV1, baseUrlOpenAI);
4367
+ return {
4368
+ file: CONFIG_FILE,
4369
+ hot: true
4370
+ };
4371
+ },
4372
+ reset() {
4373
+ if (!fs.existsSync(CONFIG_FILE)) return;
4374
+ const stripped = stripManagedBlock(readSafe());
4375
+ const cleaned = stripped.replace(/^\n+|\n+$/g, "");
4376
+ if (cleaned) {
4377
+ fs.writeFileSync(CONFIG_FILE, cleaned + "\n", "utf8");
4378
+ } else {
4379
+ fs.writeFileSync(CONFIG_FILE, "", "utf8");
4380
+ }
4381
+ },
4382
+ getConfigPath() {
4383
+ return CONFIG_FILE;
4384
+ },
4385
+ hint: "CodeBuddy \u9ED8\u8BA4\u8D70 Tencent SSO\uFF08\u8981\u6C42\u4EA4\u4E92\u5F0F /login\uFF09\u3002HolySheep \u5DF2\u628A API Key/Base URL \u5199\u5230 ~/.codebuddy/.env \u4F5C\u4E3A\u7B2C\u4E09\u65B9\u6A21\u5F0F\u5907\u7528\uFF1B\u8981\u542F\u7528\u7B2C\u4E09\u65B9\u8DEF\u7531\uFF0C\u9700\u8981 export \u8FD9\u4E24\u4E2A\u53D8\u91CF\u8FDB\u5F53\u524D shell\uFF08CodeBuddy \u4E0D\u81EA\u52A8\u8BFB .env\uFF09\uFF1Aset -a; source ~/.codebuddy/.env; set +a; export CODEBUDDY_INTERNET_ENVIRONMENT=third_party\u3002CODEBUDDY_INTERNET_ENVIRONMENT \u6211\u4EEC\u6545\u610F\u4E0D\u5199\u5165 .env\uFF0C\u4EE5\u514D\u8986\u76D6\u4E2D\u56FD\u7248/iOA \u7248\u7528\u6237\u9009\u62E9\u3002",
4386
+ launchCmd: "codebuddy",
4387
+ installCmd: "npm install -g @tencent-ai/codebuddy-code",
4388
+ docsUrl: "https://www.codebuddy.ai/docs/cli/env-vars",
4389
+ envVarFormat: "openai",
4390
+ __internal: {
4391
+ MARKER_BEGIN,
4392
+ MARKER_END,
4393
+ DEFAULT_OPENAI_MODEL,
4394
+ DEFAULT_ANTHROPIC_MODEL,
4395
+ stripManagedBlock,
4396
+ buildManagedBlock
4397
+ }
4398
+ };
4399
+ }
4400
+ });
4401
+
4153
4402
  // package.json
4154
4403
  var require_package = __commonJS({
4155
4404
  "package.json"(exports2, module2) {
4156
4405
  module2.exports = {
4157
4406
  name: "@simonyea/holysheep-cli",
4158
- version: "2.1.75",
4407
+ version: "2.1.77",
4159
4408
  description: "Claude Code/Cursor/Cline API relay for China \u2014 \xA51=$1, WeChat/Alipay payment, no credit card, no VPN. One command setup for all AI coding tools.",
4160
4409
  scripts: {
4161
4410
  build: "node scripts/build.mjs",
4162
- test: "node tests/droid.test.js && node tests/workspace-store.test.js && node tests/runtime-stale-upgrade.test.js && node tests/hermes.test.js && node tests/preflight.test.js && node tests/opencode-auth-purge.test.js && node tests/shell-winpath.test.js && node tests/openclaw-atomic-write.test.js && node tests/openclaw-disable-auth-direct.test.js && node tests/opencode-default-model.test.js && node tests/paths-bundled.test.js && node tests/aionui-runtime-resources.test.js && node tests/aionui-wrapper-claude-proxy.test.js && node tests/aionui-wrapper-probe.test.js && node tests/aionui-wrapper-proxy-integration.test.js && node tests/aionui-wrapper-all-clis-autoconf.test.js && node tests/aionui-wrapper-env-signal.test.js && node tests/aionui-wrapper-csp-rewrite.test.js && node tests/aionui-wrapper-version-status.test.js && node tests/claude-proxy-daemon.test.js && node tests/claude-proxy-vscode-settings.test.js && node tests/claude-proxy-vscode-env.test.js && node tests/acptypes-patch.test.js && node tests/codex-approval-policy.test.js && node tests/version-check.test.js && node tests/runclaude-missing-binary.test.js && node tests/claude-code-configure-preserve.test.js && node tests/webui-claude-proxy-virtual-tool.test.js && node tests/webui-claude-proxy-ui.test.js && node tests/webui-response-consumer.test.js && node tests/webui-claude-proxy-install-gating.test.js && node tests/claude-code-windows-local-bin.test.js && node tests/qwen-code-config.test.js && node tests/codebuddy-config.test.js",
4411
+ test: "node tests/droid.test.js && node tests/workspace-store.test.js && node tests/runtime-stale-upgrade.test.js && node tests/hermes.test.js && node tests/preflight.test.js && node tests/opencode-auth-purge.test.js && node tests/shell-winpath.test.js && node tests/openclaw-atomic-write.test.js && node tests/openclaw-disable-auth-direct.test.js && node tests/opencode-default-model.test.js && node tests/paths-bundled.test.js && node tests/aionui-runtime-resources.test.js && node tests/aionui-wrapper-claude-proxy.test.js && node tests/aionui-wrapper-probe.test.js && node tests/aionui-wrapper-proxy-integration.test.js && node tests/aionui-wrapper-all-clis-autoconf.test.js && node tests/aionui-wrapper-env-signal.test.js && node tests/aionui-wrapper-csp-rewrite.test.js && node tests/aionui-wrapper-version-status.test.js && node tests/claude-proxy-daemon.test.js && node tests/claude-proxy-vscode-settings.test.js && node tests/claude-proxy-vscode-env.test.js && node tests/acptypes-patch.test.js && node tests/codex-approval-policy.test.js && node tests/version-check.test.js && node tests/runclaude-missing-binary.test.js && node tests/claude-code-configure-preserve.test.js && node tests/webui-claude-proxy-virtual-tool.test.js && node tests/webui-claude-proxy-ui.test.js && node tests/webui-response-consumer.test.js && node tests/webui-claude-proxy-install-gating.test.js && node tests/claude-code-windows-local-bin.test.js && node tests/qwen-code-config.test.js && node tests/codebuddy-config.test.js && node tests/hs-reset-routing.test.js && node tests/setup-auto-install-routing.test.js && node tests/upgrade-routing.test.js",
4163
4412
  prepublishOnly: "npm run build && npm test && node scripts/check-tarball-size.js"
4164
4413
  },
4165
4414
  keywords: [
@@ -4704,6 +4953,12 @@ var require_tools = __commonJS({
4704
4953
  require_openclaw(),
4705
4954
  // 2.1.14: Hermes Agent (Nous Research) — Python/uv based, macOS/Linux/WSL2 only.
4706
4955
  require_hermes(),
4956
+ // [v2.1.76] qwen-code + codebuddy: same npx-fallback model as openclaw, so
4957
+ // that `hs reset` actually wipes ~/.qwen/.env and ~/.codebuddy/.env managed
4958
+ // blocks (otherwise the marker comment in those .env files would point to
4959
+ // a no-op command).
4960
+ require_qwen_code(),
4961
+ require_codebuddy(),
4707
4962
  require_env_config()
4708
4963
  ];
4709
4964
  }
package/dist/index.js CHANGED
@@ -12,11 +12,11 @@ var require_package = __commonJS({
12
12
  "package.json"(exports2, module2) {
13
13
  module2.exports = {
14
14
  name: "@simonyea/holysheep-cli",
15
- version: "2.1.75",
15
+ version: "2.1.77",
16
16
  description: "Claude Code/Cursor/Cline API relay for China \u2014 \xA51=$1, WeChat/Alipay payment, no credit card, no VPN. One command setup for all AI coding tools.",
17
17
  scripts: {
18
18
  build: "node scripts/build.mjs",
19
- test: "node tests/droid.test.js && node tests/workspace-store.test.js && node tests/runtime-stale-upgrade.test.js && node tests/hermes.test.js && node tests/preflight.test.js && node tests/opencode-auth-purge.test.js && node tests/shell-winpath.test.js && node tests/openclaw-atomic-write.test.js && node tests/openclaw-disable-auth-direct.test.js && node tests/opencode-default-model.test.js && node tests/paths-bundled.test.js && node tests/aionui-runtime-resources.test.js && node tests/aionui-wrapper-claude-proxy.test.js && node tests/aionui-wrapper-probe.test.js && node tests/aionui-wrapper-proxy-integration.test.js && node tests/aionui-wrapper-all-clis-autoconf.test.js && node tests/aionui-wrapper-env-signal.test.js && node tests/aionui-wrapper-csp-rewrite.test.js && node tests/aionui-wrapper-version-status.test.js && node tests/claude-proxy-daemon.test.js && node tests/claude-proxy-vscode-settings.test.js && node tests/claude-proxy-vscode-env.test.js && node tests/acptypes-patch.test.js && node tests/codex-approval-policy.test.js && node tests/version-check.test.js && node tests/runclaude-missing-binary.test.js && node tests/claude-code-configure-preserve.test.js && node tests/webui-claude-proxy-virtual-tool.test.js && node tests/webui-claude-proxy-ui.test.js && node tests/webui-response-consumer.test.js && node tests/webui-claude-proxy-install-gating.test.js && node tests/claude-code-windows-local-bin.test.js && node tests/qwen-code-config.test.js && node tests/codebuddy-config.test.js",
19
+ test: "node tests/droid.test.js && node tests/workspace-store.test.js && node tests/runtime-stale-upgrade.test.js && node tests/hermes.test.js && node tests/preflight.test.js && node tests/opencode-auth-purge.test.js && node tests/shell-winpath.test.js && node tests/openclaw-atomic-write.test.js && node tests/openclaw-disable-auth-direct.test.js && node tests/opencode-default-model.test.js && node tests/paths-bundled.test.js && node tests/aionui-runtime-resources.test.js && node tests/aionui-wrapper-claude-proxy.test.js && node tests/aionui-wrapper-probe.test.js && node tests/aionui-wrapper-proxy-integration.test.js && node tests/aionui-wrapper-all-clis-autoconf.test.js && node tests/aionui-wrapper-env-signal.test.js && node tests/aionui-wrapper-csp-rewrite.test.js && node tests/aionui-wrapper-version-status.test.js && node tests/claude-proxy-daemon.test.js && node tests/claude-proxy-vscode-settings.test.js && node tests/claude-proxy-vscode-env.test.js && node tests/acptypes-patch.test.js && node tests/codex-approval-policy.test.js && node tests/version-check.test.js && node tests/runclaude-missing-binary.test.js && node tests/claude-code-configure-preserve.test.js && node tests/webui-claude-proxy-virtual-tool.test.js && node tests/webui-claude-proxy-ui.test.js && node tests/webui-response-consumer.test.js && node tests/webui-claude-proxy-install-gating.test.js && node tests/claude-code-windows-local-bin.test.js && node tests/qwen-code-config.test.js && node tests/codebuddy-config.test.js && node tests/hs-reset-routing.test.js && node tests/setup-auto-install-routing.test.js && node tests/upgrade-routing.test.js",
20
20
  prepublishOnly: "npm run build && npm test && node scripts/check-tarball-size.js"
21
21
  },
22
22
  keywords: [
@@ -4718,6 +4718,255 @@ providers:
4718
4718
  }
4719
4719
  });
4720
4720
 
4721
+ // src/tools/qwen-code.js
4722
+ var require_qwen_code = __commonJS({
4723
+ "src/tools/qwen-code.js"(exports2, module2) {
4724
+ var fs = require("fs");
4725
+ var path = require("path");
4726
+ var os = require("os");
4727
+ var CONFIG_DIR = path.join(os.homedir(), ".qwen");
4728
+ var CONFIG_FILE = path.join(CONFIG_DIR, ".env");
4729
+ var MARKER_BEGIN = "# >>> HolySheep BEGIN >>>";
4730
+ var MARKER_END = "# <<< HolySheep END <<<";
4731
+ var DEFAULT_OPENAI_MODEL = "gpt-5.5";
4732
+ var DEFAULT_ANTHROPIC_MODEL = "claude-sonnet-4-6";
4733
+ function stripManagedBlock(content) {
4734
+ if (!content) return "";
4735
+ const text = String(content).replace(/\r\n/g, "\n");
4736
+ const re = new RegExp(
4737
+ `(?:^|\\n)\\s*${escapeRegex(MARKER_BEGIN)}[\\s\\S]*?${escapeRegex(MARKER_END)}\\s*(?:\\n|$)`,
4738
+ "g"
4739
+ );
4740
+ return text.replace(re, "\n");
4741
+ }
4742
+ __name(stripManagedBlock, "stripManagedBlock");
4743
+ function escapeRegex(s) {
4744
+ return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
4745
+ }
4746
+ __name(escapeRegex, "escapeRegex");
4747
+ function buildManagedBlock(apiKey, baseUrlAnthropicNoV1, baseUrlOpenAI) {
4748
+ const cleanOpenAi = String(baseUrlOpenAI || "https://api.holysheep.ai/v1").replace(/\/+$/, "");
4749
+ const cleanAnthropic = String(baseUrlAnthropicNoV1 || "https://api.holysheep.ai").replace(/\/+$/, "");
4750
+ return [
4751
+ MARKER_BEGIN,
4752
+ "# Managed by holysheep-cli \u2014 do not edit between markers.",
4753
+ "# Run `hs reset` to remove this block; user-added env lines outside",
4754
+ "# this block are preserved.",
4755
+ `OPENAI_API_KEY=${apiKey}`,
4756
+ `OPENAI_BASE_URL=${cleanOpenAi}`,
4757
+ `OPENAI_MODEL=${DEFAULT_OPENAI_MODEL}`,
4758
+ `ANTHROPIC_BASE_URL=${cleanAnthropic}`,
4759
+ `ANTHROPIC_AUTH_TOKEN=${apiKey}`,
4760
+ `ANTHROPIC_MODEL=${DEFAULT_ANTHROPIC_MODEL}`,
4761
+ MARKER_END
4762
+ ].join("\n");
4763
+ }
4764
+ __name(buildManagedBlock, "buildManagedBlock");
4765
+ function readSafe() {
4766
+ try {
4767
+ if (fs.existsSync(CONFIG_FILE)) {
4768
+ return fs.readFileSync(CONFIG_FILE, "utf8");
4769
+ }
4770
+ } catch {
4771
+ }
4772
+ return "";
4773
+ }
4774
+ __name(readSafe, "readSafe");
4775
+ function writeManaged(apiKey, baseUrlAnthropicNoV1, baseUrlOpenAI) {
4776
+ fs.mkdirSync(CONFIG_DIR, { recursive: true });
4777
+ const existing = readSafe();
4778
+ const stripped = stripManagedBlock(existing);
4779
+ const block = buildManagedBlock(apiKey, baseUrlAnthropicNoV1, baseUrlOpenAI);
4780
+ const userPart = stripped.replace(/\n{3,}/g, "\n\n").replace(/^\n+|\n+$/g, "");
4781
+ const out = userPart ? `${userPart}
4782
+
4783
+ ${block}
4784
+ ` : `${block}
4785
+ `;
4786
+ fs.writeFileSync(CONFIG_FILE, out, { encoding: "utf8", mode: 384 });
4787
+ try {
4788
+ fs.chmodSync(CONFIG_FILE, 384);
4789
+ } catch {
4790
+ }
4791
+ }
4792
+ __name(writeManaged, "writeManaged");
4793
+ module2.exports = {
4794
+ name: "Qwen Code",
4795
+ id: "qwen-code",
4796
+ // See header comment — npx fallback means the CLI is "always available"
4797
+ // from aionui's perspective, so we always want auto-config to run.
4798
+ checkInstalled() {
4799
+ return true;
4800
+ },
4801
+ isConfigured() {
4802
+ const content = readSafe();
4803
+ return content.includes(MARKER_BEGIN) && content.includes(MARKER_END);
4804
+ },
4805
+ configure(apiKey, baseUrlAnthropicNoV1, baseUrlOpenAI) {
4806
+ if (!apiKey) {
4807
+ throw new Error("qwen-code.configure: apiKey is required");
4808
+ }
4809
+ writeManaged(apiKey, baseUrlAnthropicNoV1, baseUrlOpenAI);
4810
+ return {
4811
+ file: CONFIG_FILE,
4812
+ hot: true
4813
+ };
4814
+ },
4815
+ reset() {
4816
+ if (!fs.existsSync(CONFIG_FILE)) return;
4817
+ const stripped = stripManagedBlock(readSafe());
4818
+ const cleaned = stripped.replace(/^\n+|\n+$/g, "");
4819
+ if (cleaned) {
4820
+ fs.writeFileSync(CONFIG_FILE, cleaned + "\n", "utf8");
4821
+ } else {
4822
+ fs.writeFileSync(CONFIG_FILE, "", "utf8");
4823
+ }
4824
+ },
4825
+ getConfigPath() {
4826
+ return CONFIG_FILE;
4827
+ },
4828
+ hint: "Qwen Code \u901A\u8FC7 ~/.qwen/.env \u8BFB\u53D6 OPENAI_API_KEY / OPENAI_BASE_URL / OPENAI_MODEL\uFF1B\u542F\u52A8\u540E\u7ACB\u5373\u751F\u6548",
4829
+ launchCmd: "qwen",
4830
+ installCmd: "npm install -g @qwen-code/qwen-code",
4831
+ docsUrl: "https://qwenlm.github.io/qwen-code-docs/en/users/configuration/auth/",
4832
+ envVarFormat: "openai",
4833
+ // Exposed for tests / future tooling.
4834
+ __internal: {
4835
+ MARKER_BEGIN,
4836
+ MARKER_END,
4837
+ DEFAULT_OPENAI_MODEL,
4838
+ DEFAULT_ANTHROPIC_MODEL,
4839
+ stripManagedBlock,
4840
+ buildManagedBlock
4841
+ }
4842
+ };
4843
+ }
4844
+ });
4845
+
4846
+ // src/tools/codebuddy.js
4847
+ var require_codebuddy = __commonJS({
4848
+ "src/tools/codebuddy.js"(exports2, module2) {
4849
+ var fs = require("fs");
4850
+ var path = require("path");
4851
+ var os = require("os");
4852
+ var CONFIG_DIR = path.join(os.homedir(), ".codebuddy");
4853
+ var CONFIG_FILE = path.join(CONFIG_DIR, ".env");
4854
+ var MARKER_BEGIN = "# >>> HolySheep BEGIN >>>";
4855
+ var MARKER_END = "# <<< HolySheep END <<<";
4856
+ var DEFAULT_OPENAI_MODEL = "gpt-5.5";
4857
+ var DEFAULT_ANTHROPIC_MODEL = "claude-sonnet-4-6";
4858
+ function escapeRegex(s) {
4859
+ return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
4860
+ }
4861
+ __name(escapeRegex, "escapeRegex");
4862
+ function stripManagedBlock(content) {
4863
+ if (!content) return "";
4864
+ const text = String(content).replace(/\r\n/g, "\n");
4865
+ const re = new RegExp(
4866
+ `(?:^|\\n)\\s*${escapeRegex(MARKER_BEGIN)}[\\s\\S]*?${escapeRegex(MARKER_END)}\\s*(?:\\n|$)`,
4867
+ "g"
4868
+ );
4869
+ return text.replace(re, "\n");
4870
+ }
4871
+ __name(stripManagedBlock, "stripManagedBlock");
4872
+ function buildManagedBlock(apiKey, baseUrlAnthropicNoV1, baseUrlOpenAI) {
4873
+ const cleanOpenAi = String(baseUrlOpenAI || "https://api.holysheep.ai/v1").replace(/\/+$/, "");
4874
+ const cleanAnthropic = String(baseUrlAnthropicNoV1 || "https://api.holysheep.ai").replace(/\/+$/, "");
4875
+ return [
4876
+ MARKER_BEGIN,
4877
+ "# Managed by holysheep-cli \u2014 do not edit between markers.",
4878
+ "# Run `hs reset` to remove this block; user-added env lines outside",
4879
+ "# this block (e.g. CODEBUDDY_INTERNET_ENVIRONMENT) are preserved.",
4880
+ `CODEBUDDY_API_KEY=${apiKey}`,
4881
+ `CODEBUDDY_BASE_URL=${cleanOpenAi}`,
4882
+ `OPENAI_API_KEY=${apiKey}`,
4883
+ `OPENAI_BASE_URL=${cleanOpenAi}`,
4884
+ `OPENAI_MODEL=${DEFAULT_OPENAI_MODEL}`,
4885
+ `ANTHROPIC_BASE_URL=${cleanAnthropic}`,
4886
+ `ANTHROPIC_AUTH_TOKEN=${apiKey}`,
4887
+ `ANTHROPIC_MODEL=${DEFAULT_ANTHROPIC_MODEL}`,
4888
+ MARKER_END
4889
+ ].join("\n");
4890
+ }
4891
+ __name(buildManagedBlock, "buildManagedBlock");
4892
+ function readSafe() {
4893
+ try {
4894
+ if (fs.existsSync(CONFIG_FILE)) {
4895
+ return fs.readFileSync(CONFIG_FILE, "utf8");
4896
+ }
4897
+ } catch {
4898
+ }
4899
+ return "";
4900
+ }
4901
+ __name(readSafe, "readSafe");
4902
+ function writeManaged(apiKey, baseUrlAnthropicNoV1, baseUrlOpenAI) {
4903
+ fs.mkdirSync(CONFIG_DIR, { recursive: true });
4904
+ const existing = readSafe();
4905
+ const stripped = stripManagedBlock(existing);
4906
+ const block = buildManagedBlock(apiKey, baseUrlAnthropicNoV1, baseUrlOpenAI);
4907
+ const userPart = stripped.replace(/\n{3,}/g, "\n\n").replace(/^\n+|\n+$/g, "");
4908
+ const out = userPart ? `${userPart}
4909
+
4910
+ ${block}
4911
+ ` : `${block}
4912
+ `;
4913
+ fs.writeFileSync(CONFIG_FILE, out, { encoding: "utf8", mode: 384 });
4914
+ try {
4915
+ fs.chmodSync(CONFIG_FILE, 384);
4916
+ } catch {
4917
+ }
4918
+ }
4919
+ __name(writeManaged, "writeManaged");
4920
+ module2.exports = {
4921
+ name: "CodeBuddy",
4922
+ id: "codebuddy",
4923
+ checkInstalled() {
4924
+ return true;
4925
+ },
4926
+ isConfigured() {
4927
+ const content = readSafe();
4928
+ return content.includes(MARKER_BEGIN) && content.includes(MARKER_END);
4929
+ },
4930
+ configure(apiKey, baseUrlAnthropicNoV1, baseUrlOpenAI) {
4931
+ if (!apiKey) {
4932
+ throw new Error("codebuddy.configure: apiKey is required");
4933
+ }
4934
+ writeManaged(apiKey, baseUrlAnthropicNoV1, baseUrlOpenAI);
4935
+ return {
4936
+ file: CONFIG_FILE,
4937
+ hot: true
4938
+ };
4939
+ },
4940
+ reset() {
4941
+ if (!fs.existsSync(CONFIG_FILE)) return;
4942
+ const stripped = stripManagedBlock(readSafe());
4943
+ const cleaned = stripped.replace(/^\n+|\n+$/g, "");
4944
+ if (cleaned) {
4945
+ fs.writeFileSync(CONFIG_FILE, cleaned + "\n", "utf8");
4946
+ } else {
4947
+ fs.writeFileSync(CONFIG_FILE, "", "utf8");
4948
+ }
4949
+ },
4950
+ getConfigPath() {
4951
+ return CONFIG_FILE;
4952
+ },
4953
+ hint: "CodeBuddy \u9ED8\u8BA4\u8D70 Tencent SSO\uFF08\u8981\u6C42\u4EA4\u4E92\u5F0F /login\uFF09\u3002HolySheep \u5DF2\u628A API Key/Base URL \u5199\u5230 ~/.codebuddy/.env \u4F5C\u4E3A\u7B2C\u4E09\u65B9\u6A21\u5F0F\u5907\u7528\uFF1B\u8981\u542F\u7528\u7B2C\u4E09\u65B9\u8DEF\u7531\uFF0C\u9700\u8981 export \u8FD9\u4E24\u4E2A\u53D8\u91CF\u8FDB\u5F53\u524D shell\uFF08CodeBuddy \u4E0D\u81EA\u52A8\u8BFB .env\uFF09\uFF1Aset -a; source ~/.codebuddy/.env; set +a; export CODEBUDDY_INTERNET_ENVIRONMENT=third_party\u3002CODEBUDDY_INTERNET_ENVIRONMENT \u6211\u4EEC\u6545\u610F\u4E0D\u5199\u5165 .env\uFF0C\u4EE5\u514D\u8986\u76D6\u4E2D\u56FD\u7248/iOA \u7248\u7528\u6237\u9009\u62E9\u3002",
4954
+ launchCmd: "codebuddy",
4955
+ installCmd: "npm install -g @tencent-ai/codebuddy-code",
4956
+ docsUrl: "https://www.codebuddy.ai/docs/cli/env-vars",
4957
+ envVarFormat: "openai",
4958
+ __internal: {
4959
+ MARKER_BEGIN,
4960
+ MARKER_END,
4961
+ DEFAULT_OPENAI_MODEL,
4962
+ DEFAULT_ANTHROPIC_MODEL,
4963
+ stripManagedBlock,
4964
+ buildManagedBlock
4965
+ }
4966
+ };
4967
+ }
4968
+ });
4969
+
4721
4970
  // src/tools/env-config.js
4722
4971
  var require_env_config = __commonJS({
4723
4972
  "src/tools/env-config.js"(exports2, module2) {
@@ -4886,6 +5135,12 @@ var require_tools = __commonJS({
4886
5135
  require_openclaw(),
4887
5136
  // 2.1.14: Hermes Agent (Nous Research) — Python/uv based, macOS/Linux/WSL2 only.
4888
5137
  require_hermes(),
5138
+ // [v2.1.76] qwen-code + codebuddy: same npx-fallback model as openclaw, so
5139
+ // that `hs reset` actually wipes ~/.qwen/.env and ~/.codebuddy/.env managed
5140
+ // blocks (otherwise the marker comment in those .env files would point to
5141
+ // a no-op command).
5142
+ require_qwen_code(),
5143
+ require_codebuddy(),
4889
5144
  require_env_config()
4890
5145
  ];
4891
5146
  }
@@ -4976,7 +5231,13 @@ var require_setup = __commonJS({
4976
5231
  "gemini-cli": { cmd: "npm install -g @google/gemini-cli", mgr: "npm" },
4977
5232
  "opencode": { cmd: "npm install -g opencode-ai", mgr: "npm" },
4978
5233
  "openclaw": { cmd: "npm install -g openclaw@latest", mgr: "npm" },
4979
- "aider": { cmd: "pip install aider-chat", mgr: "pip" }
5234
+ "aider": { cmd: "pip install aider-chat", mgr: "pip" },
5235
+ // [v2.1.77] Qwen Code + CodeBuddy: hs setup install entry. Adapter
5236
+ // checkInstalled() is hardcoded true (npx fallback for AionUI), so the
5237
+ // setup flow needs to detect real PATH separately. canAutoInstall(t.id)
5238
+ // already keys off this dict — adding here is enough.
5239
+ "qwen-code": { cmd: "npm install -g @qwen-code/qwen-code", mgr: "npm" },
5240
+ "codebuddy": { cmd: "npm install -g @tencent-ai/codebuddy-code", mgr: "npm" }
4980
5241
  };
4981
5242
  function getWindowsImmediateLaunchCmd(tool) {
4982
5243
  if (process.platform !== "win32" || !(tool == null ? void 0 : tool.launchCmd)) return null;
@@ -5699,6 +5960,26 @@ var require_upgrade = __commonJS({
5699
5960
  versionCmd: "gemini --version",
5700
5961
  npmPkg: "@google/gemini-cli",
5701
5962
  installCmd: "npm install -g @google/gemini-cli@latest"
5963
+ },
5964
+ // [v2.1.77] Qwen Code: adapter checkInstalled() is hardcoded true (npx
5965
+ // fallback for AionUI), so we must NOT use that here — upgrade uses
5966
+ // commandExists(tool.command) below, which checks real PATH. Same for
5967
+ // CodeBuddy.
5968
+ {
5969
+ name: "Qwen Code",
5970
+ id: "qwen-code",
5971
+ command: "qwen",
5972
+ versionCmd: "qwen --version",
5973
+ npmPkg: "@qwen-code/qwen-code",
5974
+ installCmd: "npm install -g @qwen-code/qwen-code@latest"
5975
+ },
5976
+ {
5977
+ name: "CodeBuddy",
5978
+ id: "codebuddy",
5979
+ command: "codebuddy",
5980
+ versionCmd: "codebuddy --version",
5981
+ npmPkg: "@tencent-ai/codebuddy-code",
5982
+ installCmd: "npm install -g @tencent-ai/codebuddy-code@latest"
5702
5983
  }
5703
5984
  ];
5704
5985
  function getLocalVersion(tool) {
@@ -6550,255 +6831,6 @@ var require_gemini_cli = __commonJS({
6550
6831
  }
6551
6832
  });
6552
6833
 
6553
- // src/tools/qwen-code.js
6554
- var require_qwen_code = __commonJS({
6555
- "src/tools/qwen-code.js"(exports2, module2) {
6556
- var fs = require("fs");
6557
- var path = require("path");
6558
- var os = require("os");
6559
- var CONFIG_DIR = path.join(os.homedir(), ".qwen");
6560
- var CONFIG_FILE = path.join(CONFIG_DIR, ".env");
6561
- var MARKER_BEGIN = "# >>> HolySheep BEGIN >>>";
6562
- var MARKER_END = "# <<< HolySheep END <<<";
6563
- var DEFAULT_OPENAI_MODEL = "gpt-5.5";
6564
- var DEFAULT_ANTHROPIC_MODEL = "claude-sonnet-4-6";
6565
- function stripManagedBlock(content) {
6566
- if (!content) return "";
6567
- const text = String(content).replace(/\r\n/g, "\n");
6568
- const re = new RegExp(
6569
- `(?:^|\\n)\\s*${escapeRegex(MARKER_BEGIN)}[\\s\\S]*?${escapeRegex(MARKER_END)}\\s*(?:\\n|$)`,
6570
- "g"
6571
- );
6572
- return text.replace(re, "\n");
6573
- }
6574
- __name(stripManagedBlock, "stripManagedBlock");
6575
- function escapeRegex(s) {
6576
- return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
6577
- }
6578
- __name(escapeRegex, "escapeRegex");
6579
- function buildManagedBlock(apiKey, baseUrlAnthropicNoV1, baseUrlOpenAI) {
6580
- const cleanOpenAi = String(baseUrlOpenAI || "https://api.holysheep.ai/v1").replace(/\/+$/, "");
6581
- const cleanAnthropic = String(baseUrlAnthropicNoV1 || "https://api.holysheep.ai").replace(/\/+$/, "");
6582
- return [
6583
- MARKER_BEGIN,
6584
- "# Managed by holysheep-cli \u2014 do not edit between markers.",
6585
- "# Run `hs reset qwen-code` to remove this block; user-added env lines",
6586
- "# outside this block are preserved.",
6587
- `OPENAI_API_KEY=${apiKey}`,
6588
- `OPENAI_BASE_URL=${cleanOpenAi}`,
6589
- `OPENAI_MODEL=${DEFAULT_OPENAI_MODEL}`,
6590
- `ANTHROPIC_BASE_URL=${cleanAnthropic}`,
6591
- `ANTHROPIC_AUTH_TOKEN=${apiKey}`,
6592
- `ANTHROPIC_MODEL=${DEFAULT_ANTHROPIC_MODEL}`,
6593
- MARKER_END
6594
- ].join("\n");
6595
- }
6596
- __name(buildManagedBlock, "buildManagedBlock");
6597
- function readSafe() {
6598
- try {
6599
- if (fs.existsSync(CONFIG_FILE)) {
6600
- return fs.readFileSync(CONFIG_FILE, "utf8");
6601
- }
6602
- } catch {
6603
- }
6604
- return "";
6605
- }
6606
- __name(readSafe, "readSafe");
6607
- function writeManaged(apiKey, baseUrlAnthropicNoV1, baseUrlOpenAI) {
6608
- fs.mkdirSync(CONFIG_DIR, { recursive: true });
6609
- const existing = readSafe();
6610
- const stripped = stripManagedBlock(existing);
6611
- const block = buildManagedBlock(apiKey, baseUrlAnthropicNoV1, baseUrlOpenAI);
6612
- const userPart = stripped.replace(/\n{3,}/g, "\n\n").replace(/^\n+|\n+$/g, "");
6613
- const out = userPart ? `${userPart}
6614
-
6615
- ${block}
6616
- ` : `${block}
6617
- `;
6618
- fs.writeFileSync(CONFIG_FILE, out, { encoding: "utf8", mode: 384 });
6619
- try {
6620
- fs.chmodSync(CONFIG_FILE, 384);
6621
- } catch {
6622
- }
6623
- }
6624
- __name(writeManaged, "writeManaged");
6625
- module2.exports = {
6626
- name: "Qwen Code",
6627
- id: "qwen-code",
6628
- // See header comment — npx fallback means the CLI is "always available"
6629
- // from aionui's perspective, so we always want auto-config to run.
6630
- checkInstalled() {
6631
- return true;
6632
- },
6633
- isConfigured() {
6634
- const content = readSafe();
6635
- return content.includes(MARKER_BEGIN) && content.includes(MARKER_END);
6636
- },
6637
- configure(apiKey, baseUrlAnthropicNoV1, baseUrlOpenAI) {
6638
- if (!apiKey) {
6639
- throw new Error("qwen-code.configure: apiKey is required");
6640
- }
6641
- writeManaged(apiKey, baseUrlAnthropicNoV1, baseUrlOpenAI);
6642
- return {
6643
- file: CONFIG_FILE,
6644
- hot: true
6645
- };
6646
- },
6647
- reset() {
6648
- if (!fs.existsSync(CONFIG_FILE)) return;
6649
- const stripped = stripManagedBlock(readSafe());
6650
- const cleaned = stripped.replace(/^\n+|\n+$/g, "");
6651
- if (cleaned) {
6652
- fs.writeFileSync(CONFIG_FILE, cleaned + "\n", "utf8");
6653
- } else {
6654
- fs.writeFileSync(CONFIG_FILE, "", "utf8");
6655
- }
6656
- },
6657
- getConfigPath() {
6658
- return CONFIG_FILE;
6659
- },
6660
- hint: "Qwen Code \u901A\u8FC7 ~/.qwen/.env \u8BFB\u53D6 OPENAI_API_KEY / OPENAI_BASE_URL / OPENAI_MODEL\uFF1B\u542F\u52A8\u540E\u7ACB\u5373\u751F\u6548",
6661
- launchCmd: "qwen",
6662
- installCmd: "npm install -g @qwen-code/qwen-code",
6663
- docsUrl: "https://qwenlm.github.io/qwen-code-docs/en/users/configuration/auth/",
6664
- envVarFormat: "openai",
6665
- // Exposed for tests / future tooling.
6666
- __internal: {
6667
- MARKER_BEGIN,
6668
- MARKER_END,
6669
- DEFAULT_OPENAI_MODEL,
6670
- DEFAULT_ANTHROPIC_MODEL,
6671
- stripManagedBlock,
6672
- buildManagedBlock
6673
- }
6674
- };
6675
- }
6676
- });
6677
-
6678
- // src/tools/codebuddy.js
6679
- var require_codebuddy = __commonJS({
6680
- "src/tools/codebuddy.js"(exports2, module2) {
6681
- var fs = require("fs");
6682
- var path = require("path");
6683
- var os = require("os");
6684
- var CONFIG_DIR = path.join(os.homedir(), ".codebuddy");
6685
- var CONFIG_FILE = path.join(CONFIG_DIR, ".env");
6686
- var MARKER_BEGIN = "# >>> HolySheep BEGIN >>>";
6687
- var MARKER_END = "# <<< HolySheep END <<<";
6688
- var DEFAULT_OPENAI_MODEL = "gpt-5.5";
6689
- var DEFAULT_ANTHROPIC_MODEL = "claude-sonnet-4-6";
6690
- function escapeRegex(s) {
6691
- return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
6692
- }
6693
- __name(escapeRegex, "escapeRegex");
6694
- function stripManagedBlock(content) {
6695
- if (!content) return "";
6696
- const text = String(content).replace(/\r\n/g, "\n");
6697
- const re = new RegExp(
6698
- `(?:^|\\n)\\s*${escapeRegex(MARKER_BEGIN)}[\\s\\S]*?${escapeRegex(MARKER_END)}\\s*(?:\\n|$)`,
6699
- "g"
6700
- );
6701
- return text.replace(re, "\n");
6702
- }
6703
- __name(stripManagedBlock, "stripManagedBlock");
6704
- function buildManagedBlock(apiKey, baseUrlAnthropicNoV1, baseUrlOpenAI) {
6705
- const cleanOpenAi = String(baseUrlOpenAI || "https://api.holysheep.ai/v1").replace(/\/+$/, "");
6706
- const cleanAnthropic = String(baseUrlAnthropicNoV1 || "https://api.holysheep.ai").replace(/\/+$/, "");
6707
- return [
6708
- MARKER_BEGIN,
6709
- "# Managed by holysheep-cli \u2014 do not edit between markers.",
6710
- "# Run `hs reset codebuddy` to remove this block; user-added env lines",
6711
- "# outside this block (e.g. CODEBUDDY_INTERNET_ENVIRONMENT) are preserved.",
6712
- `CODEBUDDY_API_KEY=${apiKey}`,
6713
- `CODEBUDDY_BASE_URL=${cleanOpenAi}`,
6714
- `OPENAI_API_KEY=${apiKey}`,
6715
- `OPENAI_BASE_URL=${cleanOpenAi}`,
6716
- `OPENAI_MODEL=${DEFAULT_OPENAI_MODEL}`,
6717
- `ANTHROPIC_BASE_URL=${cleanAnthropic}`,
6718
- `ANTHROPIC_AUTH_TOKEN=${apiKey}`,
6719
- `ANTHROPIC_MODEL=${DEFAULT_ANTHROPIC_MODEL}`,
6720
- MARKER_END
6721
- ].join("\n");
6722
- }
6723
- __name(buildManagedBlock, "buildManagedBlock");
6724
- function readSafe() {
6725
- try {
6726
- if (fs.existsSync(CONFIG_FILE)) {
6727
- return fs.readFileSync(CONFIG_FILE, "utf8");
6728
- }
6729
- } catch {
6730
- }
6731
- return "";
6732
- }
6733
- __name(readSafe, "readSafe");
6734
- function writeManaged(apiKey, baseUrlAnthropicNoV1, baseUrlOpenAI) {
6735
- fs.mkdirSync(CONFIG_DIR, { recursive: true });
6736
- const existing = readSafe();
6737
- const stripped = stripManagedBlock(existing);
6738
- const block = buildManagedBlock(apiKey, baseUrlAnthropicNoV1, baseUrlOpenAI);
6739
- const userPart = stripped.replace(/\n{3,}/g, "\n\n").replace(/^\n+|\n+$/g, "");
6740
- const out = userPart ? `${userPart}
6741
-
6742
- ${block}
6743
- ` : `${block}
6744
- `;
6745
- fs.writeFileSync(CONFIG_FILE, out, { encoding: "utf8", mode: 384 });
6746
- try {
6747
- fs.chmodSync(CONFIG_FILE, 384);
6748
- } catch {
6749
- }
6750
- }
6751
- __name(writeManaged, "writeManaged");
6752
- module2.exports = {
6753
- name: "CodeBuddy",
6754
- id: "codebuddy",
6755
- checkInstalled() {
6756
- return true;
6757
- },
6758
- isConfigured() {
6759
- const content = readSafe();
6760
- return content.includes(MARKER_BEGIN) && content.includes(MARKER_END);
6761
- },
6762
- configure(apiKey, baseUrlAnthropicNoV1, baseUrlOpenAI) {
6763
- if (!apiKey) {
6764
- throw new Error("codebuddy.configure: apiKey is required");
6765
- }
6766
- writeManaged(apiKey, baseUrlAnthropicNoV1, baseUrlOpenAI);
6767
- return {
6768
- file: CONFIG_FILE,
6769
- hot: true
6770
- };
6771
- },
6772
- reset() {
6773
- if (!fs.existsSync(CONFIG_FILE)) return;
6774
- const stripped = stripManagedBlock(readSafe());
6775
- const cleaned = stripped.replace(/^\n+|\n+$/g, "");
6776
- if (cleaned) {
6777
- fs.writeFileSync(CONFIG_FILE, cleaned + "\n", "utf8");
6778
- } else {
6779
- fs.writeFileSync(CONFIG_FILE, "", "utf8");
6780
- }
6781
- },
6782
- getConfigPath() {
6783
- return CONFIG_FILE;
6784
- },
6785
- hint: "CodeBuddy \u901A\u8FC7 ~/.codebuddy/.env \u8BFB\u53D6 CODEBUDDY_API_KEY / CODEBUDDY_BASE_URL\uFF08\u7B2C\u4E09\u65B9\u6A21\u5F0F\uFF09\uFF1B\u4E2D\u56FD\u7248/iOA \u7248\u7528\u6237\u8BF7\u81EA\u884C\u8BBE\u7F6E CODEBUDDY_INTERNET_ENVIRONMENT",
6786
- launchCmd: "codebuddy",
6787
- installCmd: "npm install -g @tencent-ai/codebuddy-code",
6788
- docsUrl: "https://www.codebuddy.ai/docs/cli/env-vars",
6789
- envVarFormat: "openai",
6790
- __internal: {
6791
- MARKER_BEGIN,
6792
- MARKER_END,
6793
- DEFAULT_OPENAI_MODEL,
6794
- DEFAULT_ANTHROPIC_MODEL,
6795
- stripManagedBlock,
6796
- buildManagedBlock
6797
- }
6798
- };
6799
- }
6800
- });
6801
-
6802
6834
  // src/webui/workspace-store.js
6803
6835
  var require_workspace_store = __commonJS({
6804
6836
  "src/webui/workspace-store.js"(exports2, module2) {
package/package.json CHANGED
@@ -1,10 +1,10 @@
1
1
  {
2
2
  "name": "@simonyea/holysheep-cli",
3
- "version": "2.1.75",
3
+ "version": "2.1.77",
4
4
  "description": "Claude Code/Cursor/Cline API relay for China — ¥1=$1, WeChat/Alipay payment, no credit card, no VPN. One command setup for all AI coding tools.",
5
5
  "scripts": {
6
6
  "build": "node scripts/build.mjs",
7
- "test": "node tests/droid.test.js && node tests/workspace-store.test.js && node tests/runtime-stale-upgrade.test.js && node tests/hermes.test.js && node tests/preflight.test.js && node tests/opencode-auth-purge.test.js && node tests/shell-winpath.test.js && node tests/openclaw-atomic-write.test.js && node tests/openclaw-disable-auth-direct.test.js && node tests/opencode-default-model.test.js && node tests/paths-bundled.test.js && node tests/aionui-runtime-resources.test.js && node tests/aionui-wrapper-claude-proxy.test.js && node tests/aionui-wrapper-probe.test.js && node tests/aionui-wrapper-proxy-integration.test.js && node tests/aionui-wrapper-all-clis-autoconf.test.js && node tests/aionui-wrapper-env-signal.test.js && node tests/aionui-wrapper-csp-rewrite.test.js && node tests/aionui-wrapper-version-status.test.js && node tests/claude-proxy-daemon.test.js && node tests/claude-proxy-vscode-settings.test.js && node tests/claude-proxy-vscode-env.test.js && node tests/acptypes-patch.test.js && node tests/codex-approval-policy.test.js && node tests/version-check.test.js && node tests/runclaude-missing-binary.test.js && node tests/claude-code-configure-preserve.test.js && node tests/webui-claude-proxy-virtual-tool.test.js && node tests/webui-claude-proxy-ui.test.js && node tests/webui-response-consumer.test.js && node tests/webui-claude-proxy-install-gating.test.js && node tests/claude-code-windows-local-bin.test.js && node tests/qwen-code-config.test.js && node tests/codebuddy-config.test.js",
7
+ "test": "node tests/droid.test.js && node tests/workspace-store.test.js && node tests/runtime-stale-upgrade.test.js && node tests/hermes.test.js && node tests/preflight.test.js && node tests/opencode-auth-purge.test.js && node tests/shell-winpath.test.js && node tests/openclaw-atomic-write.test.js && node tests/openclaw-disable-auth-direct.test.js && node tests/opencode-default-model.test.js && node tests/paths-bundled.test.js && node tests/aionui-runtime-resources.test.js && node tests/aionui-wrapper-claude-proxy.test.js && node tests/aionui-wrapper-probe.test.js && node tests/aionui-wrapper-proxy-integration.test.js && node tests/aionui-wrapper-all-clis-autoconf.test.js && node tests/aionui-wrapper-env-signal.test.js && node tests/aionui-wrapper-csp-rewrite.test.js && node tests/aionui-wrapper-version-status.test.js && node tests/claude-proxy-daemon.test.js && node tests/claude-proxy-vscode-settings.test.js && node tests/claude-proxy-vscode-env.test.js && node tests/acptypes-patch.test.js && node tests/codex-approval-policy.test.js && node tests/version-check.test.js && node tests/runclaude-missing-binary.test.js && node tests/claude-code-configure-preserve.test.js && node tests/webui-claude-proxy-virtual-tool.test.js && node tests/webui-claude-proxy-ui.test.js && node tests/webui-response-consumer.test.js && node tests/webui-claude-proxy-install-gating.test.js && node tests/claude-code-windows-local-bin.test.js && node tests/qwen-code-config.test.js && node tests/codebuddy-config.test.js && node tests/hs-reset-routing.test.js && node tests/setup-auto-install-routing.test.js && node tests/upgrade-routing.test.js",
8
8
  "prepublishOnly": "npm run build && npm test && node scripts/check-tarball-size.js"
9
9
  },
10
10
  "keywords": [