@skylandnpm/octopus-proxy 0.1.3 → 0.1.5

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/README.md CHANGED
@@ -11,8 +11,21 @@ octopus-proxy version
11
11
  octopus-proxy onboard
12
12
  ```
13
13
 
14
+ 如果升级后 `octopus-proxy version` 仍显示旧版本,运行 `command -v npm`、`npm prefix -g` 和 `command -v octopus-proxy`,确认 npm 的全局安装目录与实际执行的命令属于同一套 Node.js 环境;使用 NVM 与 Homebrew 时尤其要检查这一点。
15
+
14
16
  向导默认使用 `https://octopus.wuyehao.com` 作为 Hub 地址;按需可输入其他地址,或用 `--hub-url` 指定。再次运行向导时会读取现有配置,直接回车即可保留各项设置;机器人 Secret 只提示已配置,不在终端显示原值。macOS 上选择编码工具时,向导优先显示已配置或探测到的命令路径,否则给出该工具的 macOS 路径示例;回车后会检查文件可执行性并运行版本命令,失败时要求重新输入。无交互环境可使用 `octopus-proxy onboard --non-interactive`,未提供 `--hub-url` 时也使用该默认地址;完整选项见 `octopus-proxy help`。安装服务后可运行 `octopus-proxy status` 和 `octopus-proxy doctor` 检查状态。
15
17
 
18
+ 添加授权项目时,填写项目 ID 后会询问是否继续添加;直接回车即可结束添加并继续保存配置。
19
+
20
+ 如果旧配置中的项目 ID 重复或有错误项,先列出项目,再按序号删除指定项。此命令直接读取原始配置,因此配置校验失败时也能使用;删除前会生成仅当前用户可读的备份。清理完成后检查配置并重启服务:
21
+
22
+ ```sh
23
+ octopus-proxy projects
24
+ octopus-proxy projects --remove 2
25
+ octopus-proxy doctor
26
+ octopus-proxy restart
27
+ ```
28
+
16
29
  Claw 打开机器人工作区时会通过 Hub 向 Proxy 发送只读 `runtime.snapshot` 命令。响应包含当前运行状态、Hub 和工具设置、授权项目路径,以及工具可提供的模型信息;机器人 Secret、工具密码和提供商凭据不会返回。工作区的“Proxy 信息”按钮可查看这些内容。
17
30
 
18
31
  ## Pi agent
@@ -11645,7 +11645,7 @@ async function loadConfig(path) {
11645
11645
  const local = new URL(config.tool.baseUrl);
11646
11646
  if (!["127.0.0.1", "localhost", "[::1]"].includes(local.hostname) || local.protocol !== "http:") throw new Error("OpenCode must be an HTTP loopback endpoint");
11647
11647
  }
11648
- if (new Set(config.projects.map((p) => p.id)).size !== config.projects.length) throw new Error("Project ids must be unique");
11648
+ if (new Set(config.projects.map((p) => p.id)).size !== config.projects.length) throw new Error("\u9879\u76EE ID \u91CD\u590D\uFF1B\u8FD0\u884C octopus-proxy projects \u67E5\u770B\u9879\u76EE\uFF0C\u518D\u7528 projects --remove <\u5E8F\u53F7> \u5220\u9664\u9519\u8BEF\u9879");
11649
11649
  return config;
11650
11650
  } catch (error) {
11651
11651
  if (error instanceof ConfigError) throw error;
package/dist/cli.js CHANGED
@@ -17,7 +17,7 @@ import {
17
17
  runDaemon,
18
18
  supportedPlatform,
19
19
  systemdUnitPath
20
- } from "./chunk-3TRTDBUO.js";
20
+ } from "./chunk-JWIM27KY.js";
21
21
 
22
22
  // src/cli.ts
23
23
  import { spawn } from "node:child_process";
@@ -454,7 +454,8 @@ var validUrl = (value) => {
454
454
  return "\u8BF7\u8F93\u5165\u5408\u6CD5 URL\uFF0C\u4F8B\u5982 https://hub.example.com";
455
455
  }
456
456
  };
457
- var validId = (value) => /^[a-zA-Z0-9_-]+$/.test(value) ? void 0 : "\u4EC5\u9650\u5B57\u6BCD\u3001\u6570\u5B57\u3001\u4E0B\u5212\u7EBF\u548C\u8FDE\u5B57\u7B26";
457
+ var validId = (value) => !value ? "\u9879\u76EE ID \u4E0D\u80FD\u4E3A\u7A7A" : /^[a-zA-Z0-9_-]+$/.test(value) ? void 0 : "\u4EC5\u9650\u5B57\u6BCD\u3001\u6570\u5B57\u3001\u4E0B\u5212\u7EBF\u548C\u8FDE\u5B57\u7B26";
458
+ var validateProjectId = (value, previousProjects) => validId(value) ?? (previousProjects.some((project) => project.id === value) ? `\u9879\u76EE ID\u300C${value}\u300D\u5DF2\u5B58\u5728\uFF0C\u8BF7\u8F93\u5165\u5176\u4ED6 ID` : void 0);
458
459
  var validBotId = (value) => /^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i.test(value) ? void 0 : "\u8BF7\u8F93\u5165\u673A\u5668\u4EBA UUID";
459
460
  var run5 = promisify5(execFile5);
460
461
  var MACOS_TOOL_EXAMPLES = {
@@ -509,7 +510,7 @@ async function runOnboard(opts) {
509
510
  console.log(` \u5DF2\u786E\u8BA4 ${descriptor.label} \u547D\u4EE4\u53EF\u6267\u884C\uFF1A${toolCommand}`);
510
511
  if (toolKind === "opencode") mode = await ask(rl, "OpenCode \u6A21\u5F0F\uFF08managed=\u7531\u4EE3\u7406\u6258\u7BA1\u542F\u52A8\uFF0Cexternal=\u4EC5\u8FDE\u63A5\u5DF2\u6709\u670D\u52A1\uFF09", { default: mode, validate: (value) => value === "managed" || value === "external" ? void 0 : "\u8F93\u5165 managed \u6216 external" });
511
512
  if (projects.length) console.log("\n\u5DF2\u6709\u6388\u6743\u9879\u76EE\uFF08\u76F4\u63A5\u56DE\u8F66\u4FDD\u7559\u5404\u9879\uFF09\uFF1A");
512
- for (const project of projects) {
513
+ for (const [index, project] of projects.entries()) {
513
514
  project.name = await ask(rl, " \u9879\u76EE\u540D\u79F0", { default: project.name });
514
515
  for (; ; ) {
515
516
  project.directory = expandHome(await ask(rl, ` \u300C${project.name}\u300D\u76EE\u5F55\uFF08\u7EDD\u5BF9\u8DEF\u5F84\uFF09`, { default: project.directory }));
@@ -523,7 +524,7 @@ async function runOnboard(opts) {
523
524
  }
524
525
  break;
525
526
  }
526
- project.id = await ask(rl, " \u9879\u76EE ID", { default: project.id ?? slug(project.name), validate: validId });
527
+ project.id = await ask(rl, " \u9879\u76EE ID", { default: project.id ?? slug(project.name), validate: (value) => validateProjectId(value, projects.slice(0, index)) });
527
528
  }
528
529
  console.log("\n\u6DFB\u52A0\u6388\u6743\u9879\u76EE\uFF08\u540D\u79F0\u7559\u7A7A\u7ED3\u675F\uFF09\uFF1A");
529
530
  for (; ; ) {
@@ -542,8 +543,14 @@ async function runOnboard(opts) {
542
543
  }
543
544
  break;
544
545
  }
545
- const id = await ask(rl, " \u9879\u76EE ID", { default: slug(name), validate: validId });
546
+ const id = await ask(rl, " \u9879\u76EE ID", { default: slug(name), validate: (value) => validateProjectId(value, projects) });
546
547
  projects.push({ id, name, directory });
548
+ const addMore = await ask(rl, " \u7EE7\u7EED\u6DFB\u52A0\u66F4\u591A\u6388\u6743\u9879\u76EE\uFF1F(y/N)", {
549
+ default: "n",
550
+ showDefault: false,
551
+ validate: (value) => /^(y|yes|n|no)$/i.test(value) ? void 0 : "\u8BF7\u8F93\u5165 y \u6216 n"
552
+ });
553
+ if (!/^(y|yes)$/i.test(addMore)) break;
547
554
  }
548
555
  rl.close();
549
556
  if (!projects.length) throw new Error("\u81F3\u5C11\u9700\u8981\u5F55\u5165\u4E00\u4E2A\u6388\u6743\u9879\u76EE");
@@ -560,6 +567,11 @@ async function runOnboard(opts) {
560
567
  projects = projects.map((project) => ({ ...project, id: project.id ?? slug(project.name) }));
561
568
  const invalid = projects.find((project) => validId(project.id ?? "") !== void 0);
562
569
  if (invalid) throw new Error(`\u9879\u76EE\u300C${invalid.name}\u300D\u65E0\u6CD5\u63A8\u5BFC\u51FA\u5408\u6CD5 ID\uFF08\u4EC5\u9650\u5B57\u6BCD\u3001\u6570\u5B57\u3001\u4E0B\u5212\u7EBF\u548C\u8FDE\u5B57\u7B26\uFF09\uFF0C\u8BF7\u8C03\u6574\u540D\u79F0\u6216\u624B\u5DE5\u6307\u5B9A ID`);
570
+ const seenIds = /* @__PURE__ */ new Set();
571
+ for (const project of projects) {
572
+ if (seenIds.has(project.id)) throw new Error(`\u9879\u76EE ID\u300C${project.id}\u300D\u91CD\u590D\uFF0C\u8BF7\u8C03\u6574\u9879\u76EE\u540D\u79F0\u6216\u624B\u5DE5\u6307\u5B9A\u4E0D\u540C ID`);
573
+ seenIds.add(project.id);
574
+ }
563
575
  if (projects.some((project) => !isAbsolute3(project.directory))) throw new Error("--project \u7684\u76EE\u5F55\u5FC5\u987B\u662F\u7EDD\u5BF9\u8DEF\u5F84");
564
576
  const descriptor = describeTool(toolKind);
565
577
  toolCommand = toolCommand ? expandHome(toolCommand) : await resolveCommandOnPath(toolKind, toolSearchDirs(toolKind)) ?? descriptor.defaultCommand;
@@ -613,6 +625,48 @@ async function runOnboard(opts) {
613
625
  } else console.log("\u5DF2\u8DF3\u8FC7\u670D\u52A1\u5B89\u88C5\uFF1B\u4E4B\u540E\u53EF\u8FD0\u884C octopus-proxy install");
614
626
  }
615
627
 
628
+ // src/projects-command.ts
629
+ import { randomUUID } from "node:crypto";
630
+ import { readFile as readFile2, writeFile as writeFile3 } from "node:fs/promises";
631
+ function asConfig(value) {
632
+ if (typeof value !== "object" || value === null || Array.isArray(value) || !Array.isArray(value.projects)) {
633
+ throw new Error("\u914D\u7F6E\u6587\u4EF6\u7F3A\u5C11 projects \u6570\u7EC4\uFF0C\u65E0\u6CD5\u7BA1\u7406\u6388\u6743\u9879\u76EE");
634
+ }
635
+ return value;
636
+ }
637
+ function display(value) {
638
+ return typeof value === "string" && value.length > 0 ? JSON.stringify(value) : "\uFF08\u7A7A\uFF09";
639
+ }
640
+ async function manageProjects(configPath2, remove) {
641
+ const original = await readFile2(configPath2);
642
+ const config = asConfig(JSON.parse(original.toString("utf8")));
643
+ if (remove === void 0) {
644
+ if (config.projects.length === 0) console.log("\u914D\u7F6E\u4E2D\u6CA1\u6709\u6388\u6743\u9879\u76EE");
645
+ else for (const [index2, entry] of config.projects.entries()) {
646
+ const project = typeof entry === "object" && entry !== null && !Array.isArray(entry) ? entry : {};
647
+ console.log(`${index2 + 1}. ID=${display(project.id)} \u540D\u79F0=${display(project.name)} \u76EE\u5F55=${display(project.directory)}`);
648
+ }
649
+ console.log("\u5220\u9664\u9519\u8BEF\u9879\uFF1Aoctopus-proxy projects --remove <\u5E8F\u53F7>");
650
+ return;
651
+ }
652
+ if (!/^[1-9][0-9]*$/.test(remove)) throw new Error("--remove \u9700\u8981\u4E0A\u65B9\u5217\u8868\u4E2D\u7684\u6B63\u6574\u6570\u5E8F\u53F7");
653
+ const index = Number(remove) - 1;
654
+ if (!Number.isSafeInteger(index) || index >= config.projects.length) throw new Error(`\u9879\u76EE\u5E8F\u53F7\u8D85\u51FA\u8303\u56F4\uFF1A${remove}`);
655
+ if (config.projects.length === 1) throw new Error("\u81F3\u5C11\u9700\u8981\u4FDD\u7559\u4E00\u4E2A\u6388\u6743\u9879\u76EE\uFF1B\u65E0\u6CD5\u5220\u9664\u6700\u540E\u4E00\u9879");
656
+ const backupPath = `${configPath2}.backup-${randomUUID()}`;
657
+ await writeFile3(backupPath, original, { mode: 384, flag: "wx" });
658
+ config.projects.splice(index, 1);
659
+ await atomicJson(configPath2, config);
660
+ console.log(`\u5DF2\u5220\u9664\u7B2C ${remove} \u4E2A\u6388\u6743\u9879\u76EE\uFF1B\u539F\u914D\u7F6E\u5907\u4EFD\uFF1A${backupPath}`);
661
+ try {
662
+ await loadConfig(configPath2);
663
+ console.log("\u914D\u7F6E\u6821\u9A8C\u901A\u8FC7\uFF1B\u8FD0\u884C octopus-proxy restart \u4F7F\u670D\u52A1\u4F7F\u7528\u65B0\u914D\u7F6E");
664
+ } catch (error) {
665
+ console.log(`\u914D\u7F6E\u4ECD\u6709\u9519\u8BEF\uFF1A${error instanceof Error ? error.message : String(error)}`);
666
+ console.log("\u7EE7\u7EED\u6E05\u7406\u540E\u8FD0\u884C octopus-proxy doctor \u68C0\u67E5\u914D\u7F6E");
667
+ }
668
+ }
669
+
616
670
  // src/cli.ts
617
671
  var USAGE = `octopus-proxy \u2014 Octopus \u4E3B\u673A\u4EE3\u7406
618
672
 
@@ -620,6 +674,7 @@ var USAGE = `octopus-proxy \u2014 Octopus \u4E3B\u673A\u4EE3\u7406
620
674
 
621
675
  \u547D\u4EE4:
622
676
  onboard \u4EA4\u4E92\u5F0F\u521D\u59CB\u5316\u914D\u7F6E\uFF0C\u5E76\u9ED8\u8BA4\u5B89\u88C5\u7CFB\u7EDF\u670D\u52A1
677
+ projects \u5217\u51FA\u6388\u6743\u9879\u76EE\uFF1B\u53EF\u6309\u5E8F\u53F7\u5220\u9664\u9519\u8BEF\u914D\u7F6E\u9879
623
678
  install \u6821\u9A8C\u914D\u7F6E\u540E\u5B89\u88C5/\u66F4\u65B0\u7CFB\u7EDF\u670D\u52A1\uFF08\u5E42\u7B49\uFF0C\u81EA\u52A8\u542F\u52A8\uFF09
624
679
  uninstall \u505C\u6B62\u5E76\u79FB\u9664\u7CFB\u7EDF\u670D\u52A1\uFF08\u4FDD\u7559\u914D\u7F6E\u4E0E\u72B6\u6001\u6570\u636E\uFF09
625
680
  start \u542F\u52A8\u670D\u52A1
@@ -650,12 +705,15 @@ install \u9009\u9879:
650
705
  --force \u91CD\u5199\u670D\u52A1\u5B9A\u4E49\u5E76\u91CD\u542F\uFF08\u914D\u7F6E\u6216\u8DEF\u5F84\u53D8\u5316\u540E\u4F7F\u7528\uFF09
651
706
  --node-path <p> \u56FA\u5B9A\u670D\u52A1\u4F7F\u7528\u7684 node \u7EDD\u5BF9\u8DEF\u5F84
652
707
 
708
+ projects \u9009\u9879:
709
+ --remove <\u5E8F\u53F7> \u5220\u9664\u6307\u5B9A\u9879\u76EE\uFF08\u5148\u8FD0\u884C projects \u67E5\u770B\u5E8F\u53F7\uFF1B\u81EA\u52A8\u5907\u4EFD\u539F\u914D\u7F6E\uFF09
710
+
653
711
  doctor / logs \u9009\u9879:
654
712
  --fix \u81EA\u52A8\u4FEE\u590D\uFF08\u914D\u7F6E\u6743\u9650\u3001\u670D\u52A1\u5B9A\u4E49\u3001\u542F\u52A8\u670D\u52A1\uFF09
655
713
  -f, --follow \u6301\u7EED\u8F93\u51FA\u65E5\u5FD7
656
714
 
657
715
  \u9000\u51FA\u7801: 0 \u6210\u529F\uFF1B1 \u4E00\u822C\u9519\u8BEF\uFF1B78 \u914D\u7F6E\u65E0\u6548\uFF08\u670D\u52A1\u5355\u5143\u5DF2\u914D\u7F6E\u4E0D\u56E0\u6B64\u91CD\u542F\uFF09`;
658
- var VALUE_FLAGS = /* @__PURE__ */ new Set(["--config", "--node-path", "--hub-url", "--bot-id", "--secret-key", "--state-dir", "--tool", "--tool-command", "--opencode-command", "--project"]);
716
+ var VALUE_FLAGS = /* @__PURE__ */ new Set(["--config", "--node-path", "--hub-url", "--bot-id", "--secret-key", "--state-dir", "--tool", "--tool-command", "--opencode-command", "--project", "--remove"]);
659
717
  function parse(argv) {
660
718
  const flags2 = {}, projectArgs2 = [];
661
719
  let command2;
@@ -742,6 +800,9 @@ try {
742
800
  });
743
801
  break;
744
802
  }
803
+ case "projects":
804
+ await manageProjects(configPath, flags["--remove"]);
805
+ break;
745
806
  case "install": {
746
807
  const outcome = await installService({ configPath, nodePath: flags["--node-path"], force: flags["--force"] === "true" });
747
808
  console.log(outcome.changed ? `\u5DF2\u5B89\u88C5\u5E76\u542F\u52A8\u670D\u52A1\uFF1A${outcome.serviceFile}` : `\u670D\u52A1\u5B9A\u4E49\u4E0E\u914D\u7F6E\u4E00\u81F4\uFF0C\u5DF2\u786E\u4FDD\u8FD0\u884C\uFF1A${outcome.serviceFile}`);
package/dist/main.js CHANGED
@@ -2,7 +2,7 @@
2
2
  import {
3
3
  ConfigError,
4
4
  runDaemon
5
- } from "./chunk-3TRTDBUO.js";
5
+ } from "./chunk-JWIM27KY.js";
6
6
 
7
7
  // src/main.ts
8
8
  runDaemon(process.env.OCTOPUS_PROXY_CONFIG ?? "proxy.json").catch((error) => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@skylandnpm/octopus-proxy",
3
- "version": "0.1.3",
3
+ "version": "0.1.5",
4
4
  "type": "module",
5
5
  "description": "Octopus host proxy: OpenCode, Codex, ZCode and Pi adapters with service installer CLI",
6
6
  "bin": {