@simonyea/holysheep-cli 2.1.74 → 2.1.76

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 \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",
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.74",
4407
+ version: "2.1.76",
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",
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",
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.74",
15
+ version: "2.1.76",
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",
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",
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 \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",
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
  }
@@ -9263,6 +9518,8 @@ var require_aionui_wrapper = __commonJS({
9263
9518
  var codexTool = require_codex();
9264
9519
  var droidTool = require_droid();
9265
9520
  var hermesTool = require_hermes();
9521
+ var qwenCodeTool = require_qwen_code();
9522
+ var codebuddyTool = require_codebuddy();
9266
9523
  var openclawTool = require_openclaw();
9267
9524
  var BRIDGE_DIR = path.join(os.homedir(), ".holysheep");
9268
9525
  var BRIDGE_CRED_FILE = path.join(BRIDGE_DIR, "aionui-bridge.json");
@@ -10345,6 +10602,18 @@ var require_aionui_wrapper = __commonJS({
10345
10602
  tool: geminiTool,
10346
10603
  settingsHint: "~/.gemini/settings.json (selectedAuthType only \u2014 HolySheep key does not proxy Gemini)",
10347
10604
  configureArgs: [apiKey, BASE_URL_ANTHROPIC, BASE_URL_OPENAI]
10605
+ },
10606
+ {
10607
+ id: "qwen-code",
10608
+ tool: qwenCodeTool,
10609
+ settingsHint: "~/.qwen/.env (OPENAI_* + ANTHROPIC_* envs)",
10610
+ configureArgs: [apiKey, BASE_URL_ANTHROPIC, BASE_URL_OPENAI]
10611
+ },
10612
+ {
10613
+ id: "codebuddy",
10614
+ tool: codebuddyTool,
10615
+ settingsHint: "~/.codebuddy/.env (CODEBUDDY_* + OPENAI_* + ANTHROPIC_* envs)",
10616
+ configureArgs: [apiKey, BASE_URL_ANTHROPIC, BASE_URL_OPENAI]
10348
10617
  }
10349
10618
  ];
10350
10619
  for (const s of siblings) {
package/package.json CHANGED
@@ -1,10 +1,10 @@
1
1
  {
2
2
  "name": "@simonyea/holysheep-cli",
3
- "version": "2.1.74",
3
+ "version": "2.1.76",
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",
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",
8
8
  "prepublishOnly": "npm run build && npm test && node scripts/check-tarball-size.js"
9
9
  },
10
10
  "keywords": [