@nggaigc/cli 0.1.49 → 0.1.51

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
@@ -1,6 +1,6 @@
1
1
  # @nggaigc/cli
2
2
 
3
- NGGAIGC Skill 的受信安装器。Codex 与 WorkBuddy 使用同一条安装命令,自动识别当前宿主。
3
+ NGGAIGC Skill 的受信安装器。Codex、WorkBuddy 与豆包工作使用同一条安装命令,自动识别当前宿主。
4
4
 
5
5
  ```powershell
6
6
  npx --yes @nggaigc/cli@latest install
@@ -14,11 +14,11 @@ macOS arm64 辅助程序沿用已签名 Plugin 中通过完整性校验的字节
14
14
 
15
15
  ## 统一安装入口(0.1.46 起)
16
16
 
17
- 不带目录参数时,`install`、`start-skill`、`client` 使用同一套宿主识别:Codex 的当前会话标记,或 WorkBuddy 的会话标记/实际工作会话与专属应用标记组合。配置目录、已安装应用和通用终端变量本身不代表当前宿主;环境标记只是便利提示,不用于认证或授权。
17
+ 不带目录参数时,`install`、`start-skill`、`client` 使用同一套宿主识别:Codex 的当前会话标记,或 WorkBuddy 的会话标记/实际工作会话与专属应用标记组合。豆包工作使用本地命令环境同时提供的 `DOUBAO_OFFICE_APP_ID` 与 `DOUBAO_OFFICE_ANSWER_MESSAGE_ID` 标记,不读取 token。配置目录、已安装应用和通用终端变量本身不代表当前宿主;环境标记只是便利提示,不用于认证或授权。
18
18
 
19
- 无法识别或同时命中两个宿主时,有交互终端可选择 Codex 或 WorkBuddy;非交互调用立即返回 `status: selection-required`、两项 `choices` 和退出码 3,不安装、不打开授权网页。当前 Agent 应让用户选择一次,再把 `--agent codex` 或 `--agent workbuddy` 加到原命令继续;`client` 的目标选项放在 `--` 分隔符之前,业务参数保持原样。安装结果始终返回真实 `skillsDirectory` 和 `skillPath`,连接失败也保留该位置,后续继续使用同一位置。
19
+ 无法识别或同时命中多个宿主时,有交互终端可选择 Codex、WorkBuddy 或豆包工作;非交互调用立即返回 `status: selection-required`、三项 `choices` 和退出码 3,不安装、不打开授权网页。当前 Agent 应让用户选择一次,再由 Agent 将返回的目标值作为 `--agent <所选目标>` 加到原命令继续;`client` 的目标选项放在 `--` 分隔符之前,业务参数保持原样。安装结果始终返回真实 `skillsDirectory` 和 `skillPath`,连接失败也保留该位置,后续继续使用同一位置。
20
20
 
21
- 本次仅 Codex 与 WorkBuddy 为自动识别支持范围;旧 `universal` 与自定义目录参数仍兼容,但不代表其他 Agent 已获验收。
21
+ 豆包工作的本地目录为 `~/DoubaoWork/skills`,根包和后续独立 Skill 统一使用该位置;不会改动另一宿主的安装。豆包工作自动识别从 CLI `0.1.51` 起提供。此次适配依据 macOS 豆包工作 2.32.14 的真实命令环境和已声明技能根目录,其他平台及具体工作流效果须分别验收。旧 `universal` 与自定义目录参数仍兼容。
22
22
 
23
23
  ## 显式目标(0.1.45 起)
24
24
 
@@ -32,10 +32,32 @@ npx --yes @nggaigc/cli@latest start-skill skill.<id> [version] --skills-dir "/ab
32
32
  npx --yes @nggaigc/cli@latest client --skills-dir "/absolute/project/.codebuddy/skills" -- <原command> <原args>
33
33
  ```
34
34
 
35
- `install`、`start-skill` 和 `client` 支持互斥的 `--agent codex|workbuddy|universal` 或 `--skills-dir <绝对目录>`。识别或选择 Codex 后使用 `CODEX_HOME/skills`,未设置时为 `~/.codex/skills`。WorkBuddy 优先使用实际进程提供的 `WORKBUDDY_CONFIG_DIR/skills`(其次 `CODEBUDDY_CONFIG_DIR/skills`),否则使用 `~/.workbuddy/skills`;在宿主外升级时,若现代目录没有根 Skill 而旧 `~/.codebuddy/skills` 已安装,则继续使用旧位置。不会删除或迁移旧安装。`--skills-dir` 始终精确指定项目级或其他现有安装。universal 使用 `~/.agents/skills`,不保证所有 Agent 自动识别。`--no-login` 仅跳过安装后的登录,不绕过签名、哈希、路径检查或后续鉴权。
35
+ `install`、`start-skill` 和 `client` 支持互斥的 `--agent codex|workbuddy|doubao-work|universal` 或 `--skills-dir <绝对目录>`。识别或选择 Codex 后使用 `CODEX_HOME/skills`,未设置时为 `~/.codex/skills`。WorkBuddy 优先使用实际进程提供的 `WORKBUDDY_CONFIG_DIR/skills`(其次 `CODEBUDDY_CONFIG_DIR/skills`),否则使用 `~/.workbuddy/skills`;在宿主外升级时,若现代目录没有根 Skill 而旧 `~/.codebuddy/skills` 已安装,则继续使用旧位置。不会删除或迁移旧安装。`--skills-dir` 始终精确指定项目级或其他现有安装。universal 使用 `~/.agents/skills`,不保证所有 Agent 自动识别。`--no-login` 仅跳过安装后的登录,不绕过签名、哈希、路径检查或后续鉴权。
36
36
 
37
37
  根 Skill 按实际读取的 `SKILL.md` 定位父目录及其上一级 `skillsDirectory`;后续升级与 `start-skill` 显式使用同一目录。准备回执增加 `skillsDirectory`、`rootLauncherPath`,保留 `preparedSkills`;宿主应显式读取返回的真实路径。独立包的原客户端调用使用回执的受信根启动器;`client` 是同目录根包验签桥,保留原命令/参数,不增加 API 专用业务分支。安装新包不证明当前宿主热加载,必要时开启新会话。
38
38
 
39
39
  本地技能包导入可能复制文件,需核导入后的实际路径和独立包同级关系。交互使用宿主可用的提问工具或当前聊天,交付使用宿主可用的媒体/附件能力;不依赖 Codex 专用工具。切换宿主继续复用当前系统用户的系统凭证库和任务历史,不迁移凭据、不要求重新粘贴密钥。资金、权限与未知结果同幂等键恢复规则不变。
40
40
 
41
41
  此功能不增加 Linux、Intel Mac 支持,也不代表已接入或认证 WorkBuddy 官方连接器市场;现有系统、Node.js 与正式发布门禁保持适用。
42
+
43
+ ## 受信本地 Python 工具文件合同(开发候选)
44
+
45
+ 纯文档包继续使用 `ngg-skill-package/v1`,原结构及字节生成规则不变。本地工具包使用内部元数据 `schemaVersion: "ngg-skill-package/v2"`;ZIP中的元数据文件名仍为 `skill-package.v1.json`。正式发布时须把该包的root/platform最低兼容版本绑定到实际支持v2的新版根包及CLI;本节不指定尚未冻结的发布版本。
46
+
47
+ v2须声明以下有限元数据:
48
+
49
+ ```json
50
+ {
51
+ "localTools": {
52
+ "kind": "python",
53
+ "entrypoints": ["scripts/run.py"],
54
+ "runtimeLock": "references/runtime-lock.json"
55
+ }
56
+ }
57
+ ```
58
+
59
+ 仅此声明允许额外交付直接位于 `scripts/` 的Python源文件(文件名为ASCII字母/数字开头,后接字母、数字、下划线或连字符及`.py`)。入口必须存在且不重复;内部模块无需列作入口。全部源文件仍须列入已签名的逐文件清单,`executable=false`。不接受shell、pyc、任意YAML、嵌套脚本目录或根级runtime-lock。
60
+
61
+ 运行清单是已签名的 `references/runtime-lock.json`,至少有 `schemaVersion: 1`及`files`路径到SHA256的映射。每个打包Python文件必须与其中同路径摘要一致;清单中不能出现未打包的scripts文件,也不能自引用运行清单。文档及同级依赖的摘要可继续由独立工具按自身范围复核;安装器不执行或解释其业务规则。
62
+
63
+ 安装、复用、API合同加载和回滚只验证/交付字节,**不会执行Python、安装解释器/FFmpeg或调用付费服务**。工作流按实际阶段检查宿主依赖并明确调用已声明入口。全部既有签名、逐文件摘要、安全ZIP、32文件/4MiB、路径检查、原子替换及回滚规则继续生效。旧v1 loader明确拒绝v2;不能给旧包加脚本但保留v1声明,或把源码改成文档后缀绕过规则。
@@ -3,6 +3,7 @@ import { resolveSkillLocation, } from "./skill-location.js";
3
3
  export const agentChoices = [
4
4
  { agent: "codex", label: "Codex" },
5
5
  { agent: "workbuddy", label: "WorkBuddy" },
6
+ { agent: "doubao-work", label: "豆包工作" },
6
7
  ];
7
8
  export class AgentSelectionRequired extends Error {
8
9
  reason;
@@ -23,12 +24,18 @@ export function detectCallingAgent(environment) {
23
24
  (present(environment.CODEBUDDY_SESSION_ID) &&
24
25
  present(environment.WORKBUDDY_APP_VERSION) &&
25
26
  present(environment.WORKBUDDY_APP_PATH));
26
- if (codex && workbuddy)
27
+ // Observed in Doubao Work's local AgentInfraService shell. Neither marker
28
+ // contains a credential; installed directories and token variables are ignored.
29
+ const doubao = present(environment.DOUBAO_OFFICE_APP_ID) &&
30
+ present(environment.DOUBAO_OFFICE_ANSWER_MESSAGE_ID);
31
+ if ([codex, workbuddy, doubao].filter(Boolean).length > 1)
27
32
  return { reason: "conflicting" };
28
33
  if (codex)
29
34
  return { agent: "codex" };
30
35
  if (workbuddy)
31
36
  return { agent: "workbuddy" };
37
+ if (doubao)
38
+ return { agent: "doubao-work" };
32
39
  return { reason: "unknown" };
33
40
  }
34
41
  async function chooseInTerminal() {
@@ -41,13 +48,15 @@ async function chooseInTerminal() {
41
48
  terminal.once("SIGINT", cancel);
42
49
  terminal.once("close", cancel);
43
50
  try {
44
- const answer = (await terminal.question("请选择使用 NGGAIGC 的 AI 助手:1. Codex 2. WorkBuddy\n输入 1 或 2:", { signal: controller.signal }))
51
+ const answer = (await terminal.question("请选择使用 NGGAIGC 的 AI 助手:1. Codex 2. WorkBuddy 3. 豆包工作\n输入 1、2 或 3:", { signal: controller.signal }))
45
52
  .trim()
46
53
  .toLowerCase();
47
54
  if (answer === "1" || answer === "codex")
48
55
  return "codex";
49
56
  if (answer === "2" || answer === "workbuddy")
50
57
  return "workbuddy";
58
+ if (answer === "3" || answer === "doubao-work")
59
+ return "doubao-work";
51
60
  return undefined;
52
61
  }
53
62
  catch {
@@ -76,7 +85,7 @@ export async function selectCommandLocation(options, runtime = {}) {
76
85
  ? chooseInTerminal
77
86
  : undefined);
78
87
  const agent = await choose?.();
79
- if (agent === "codex" || agent === "workbuddy")
88
+ if (agent === "codex" || agent === "workbuddy" || agent === "doubao-work")
80
89
  return { ...options, agent };
81
90
  throw new AgentSelectionRequired(detected.reason);
82
91
  }
@@ -84,7 +93,7 @@ export function selectionRequiredResult(error) {
84
93
  return {
85
94
  status: "selection-required",
86
95
  error: { code: error.code, reason: error.reason },
87
- message: "请选择当前使用的 AI 助手,然后在原命令中添加 --agent codex 或 --agent workbuddy 继续;client 命令的选项须放在 -- 分隔符之前。",
96
+ message: "请选择当前使用的 AI 助手,再按所选目标继续;已识别的 Codex、WorkBuddy 和豆包工作均使用统一安装命令,无需增加目标参数。client 命令的选项须放在 -- 分隔符之前。",
88
97
  choices: agentChoices,
89
98
  nextAction: "select-agent-and-retry",
90
99
  };
package/dist/bundle.js CHANGED
@@ -47,7 +47,7 @@ export async function verifyBundle(input) {
47
47
  !exactKeys(manifestValue, manifestKeys) ||
48
48
  manifestValue.schemaVersion !== "nggaigc-plugin-package/v1" ||
49
49
  manifestValue.artifactId !== "plugin.nggaigc" ||
50
- manifestValue.version !== "1.1.47" ||
50
+ manifestValue.version !== "1.1.48" ||
51
51
  manifestValue.artifactPath !==
52
52
  `packages/plugins/nggaigc-plugin-${manifestValue.version}.zip` ||
53
53
  typeof manifestValue.sourceCommit !== "string" ||
@@ -345,7 +345,8 @@ function storedZipEntries(input) {
345
345
  localOffset + 30 > centralOffset)
346
346
  fail("PACKAGE_VERIFICATION_FAILED");
347
347
  const unixMode = externalAttributes >>> 16;
348
- if (unixMode !== 0 && (unixMode & 0xf000) !== 0x8000)
348
+ if (unixMode !== 0 &&
349
+ ((unixMode & 0xf000) !== 0x8000 || (unixMode & 0o111) !== 0))
349
350
  fail("PACKAGE_VERIFICATION_FAILED");
350
351
  const nameBytes = bytes.subarray(cursor + 46, cursor + 46 + nameLength);
351
352
  let name;
@@ -382,12 +383,60 @@ function storedZipEntries(input) {
382
383
  fail("PACKAGE_VERIFICATION_FAILED");
383
384
  return result;
384
385
  }
385
- function packageFileType(value) {
386
+ const PYTHON_SCRIPT = /^scripts\/[A-Za-z0-9][A-Za-z0-9_-]*\.py$/;
387
+ const PYTHON_RUNTIME_LOCK = "references/runtime-lock.json";
388
+ function validLocalPythonTools(value, paths) {
389
+ if (!record(value) ||
390
+ !exactKeys(value, ["kind", "entrypoints", "runtimeLock"]) ||
391
+ value.kind !== "python" ||
392
+ value.runtimeLock !== PYTHON_RUNTIME_LOCK ||
393
+ !paths.includes(PYTHON_RUNTIME_LOCK) ||
394
+ !Array.isArray(value.entrypoints) ||
395
+ value.entrypoints.length < 1 ||
396
+ value.entrypoints.length > MAX_FILES)
397
+ return false;
398
+ const seen = new Set();
399
+ for (const entry of value.entrypoints) {
400
+ if (typeof entry !== "string" ||
401
+ !PYTHON_SCRIPT.test(entry) ||
402
+ !paths.includes(entry) ||
403
+ seen.has(entry.toLowerCase()))
404
+ return false;
405
+ seen.add(entry.toLowerCase());
406
+ }
407
+ return true;
408
+ }
409
+ function validLocalPythonRuntimeLock(bytes, files) {
410
+ try {
411
+ const lock = JSON.parse(new TextDecoder("utf-8", { fatal: true }).decode(bytes));
412
+ if (!record(lock) ||
413
+ lock.schemaVersion !== 1 ||
414
+ !record(lock.files) ||
415
+ Object.hasOwn(lock.files, PYTHON_RUNTIME_LOCK) ||
416
+ Object.values(lock.files).some((value) => typeof value !== "string" || !DIGEST.test(value)))
417
+ return false;
418
+ const locked = lock.files;
419
+ return (files
420
+ .filter((file) => PYTHON_SCRIPT.test(file.path))
421
+ .every((file) => locked[file.path] === file.sha256) &&
422
+ Object.keys(locked)
423
+ .filter((name) => name.startsWith("scripts/"))
424
+ .every((name) => files.some((file) => PYTHON_SCRIPT.test(file.path) &&
425
+ file.path === name &&
426
+ file.sha256 === locked[name])));
427
+ }
428
+ catch {
429
+ return false;
430
+ }
431
+ }
432
+ function packageFileType(value, localPython = false) {
386
433
  if (value === "SKILL.md" ||
387
434
  /^references\/[A-Za-z0-9._/-]+\.(md|json)$/.test(value))
388
435
  return "document";
389
436
  if (/^assets\/[A-Za-z0-9._/-]+\.png$/.test(value))
390
437
  return "png";
438
+ if (localPython && PYTHON_SCRIPT.test(value))
439
+ return "python";
391
440
  return undefined;
392
441
  }
393
442
  function validStaticPng(input) {
@@ -459,8 +508,9 @@ function decodePackage(bytes, entry, trust) {
459
508
  catch {
460
509
  fail("PACKAGE_VERIFICATION_FAILED");
461
510
  }
511
+ const localPython = payload?.schemaVersion === "ngg-skill-package/v2";
462
512
  if (!record(payload) ||
463
- payload.schemaVersion !== "ngg-skill-package/v1" ||
513
+ (!localPython && payload.schemaVersion !== "ngg-skill-package/v1") ||
464
514
  payload.artifactId !== entry.id ||
465
515
  payload.packageVersion !== entry.version ||
466
516
  canonical(payload.compatibility) !== canonical(metadata.compatibility) ||
@@ -473,8 +523,12 @@ function decodePackage(bytes, entry, trust) {
473
523
  "packageVersion",
474
524
  "compatibility",
475
525
  "files",
526
+ ...(localPython ? ["localTools"] : []),
476
527
  ]))
477
528
  fail("PACKAGE_VERIFICATION_FAILED");
529
+ if (localPython &&
530
+ !validLocalPythonTools(payload.localTools, payload.files.map((file) => file?.path)))
531
+ fail("PACKAGE_VERIFICATION_FAILED");
478
532
  const seen = new Set();
479
533
  let total = 0;
480
534
  for (const file of payload.files) {
@@ -490,7 +544,7 @@ function decodePackage(bytes, entry, trust) {
490
544
  file.path
491
545
  .split("/")
492
546
  .some((part) => !part || part === "." || part === ".." || /[. ]$/.test(part)) ||
493
- !packageFileType(file.path))
547
+ !packageFileType(file.path, localPython))
494
548
  fail("PACKAGE_VERIFICATION_FAILED");
495
549
  const folded = file.path.toLowerCase();
496
550
  if (seen.has(folded) ||
@@ -511,6 +565,9 @@ function decodePackage(bytes, entry, trust) {
511
565
  }
512
566
  if (!seen.has("skill.md") || archive.size !== payload.files.length + 1)
513
567
  fail("PACKAGE_VERIFICATION_FAILED");
568
+ if (localPython &&
569
+ !validLocalPythonRuntimeLock(archive.get(PYTHON_RUNTIME_LOCK), payload.files))
570
+ fail("PACKAGE_VERIFICATION_FAILED");
514
571
  return payload.files.map((file) => ({
515
572
  path: file.path,
516
573
  sha256: file.sha256,
@@ -565,6 +622,9 @@ async function existingReceipt(target, entry, trust) {
565
622
  try {
566
623
  const packageBytes = await readFile(path.join(target, ".nggaigc-package.bin"));
567
624
  const signedFiles = decodePackage(packageBytes, entry, trust);
625
+ // The signed archive's versioned verifier already checked each file type
626
+ // and local-tools declaration. Never infer Python permission from receipt data.
627
+ const signedPaths = new Set(signedFiles.map((file) => file.path));
568
628
  if (JSON.stringify(Object.fromEntries(signedFiles.map((file) => [file.path, file.sha256]))) !== JSON.stringify(receipt.files))
569
629
  return false;
570
630
  const names = [];
@@ -590,7 +650,7 @@ async function existingReceipt(target, entry, trust) {
590
650
  ].sort()))
591
651
  return false;
592
652
  for (const [name, digest] of Object.entries(receipt.files)) {
593
- if (!packageFileType(name) ||
653
+ if (!signedPaths.has(name) ||
594
654
  name.split("/").some((part) => part === "." || part === ".."))
595
655
  return false;
596
656
  const file = path.join(target, ...name.split("/"));
package/dist/install.js CHANGED
@@ -9,7 +9,7 @@ import { resolveSkillLocation, } from "./skill-location.js";
9
9
  function defaultBundle() {
10
10
  const vendor = fileURLToPath(new URL("../vendor/", import.meta.url));
11
11
  return {
12
- archive: path.join(vendor, "nggaigc-plugin-1.1.47.zip"),
12
+ archive: path.join(vendor, "nggaigc-plugin-1.1.48.zip"),
13
13
  manifest: path.join(vendor, "manifest.json"),
14
14
  trust: path.join(vendor, "trusted-keys.json"),
15
15
  };
package/dist/main.js CHANGED
@@ -41,11 +41,11 @@ export async function main(args, runtime = {}) {
41
41
  if (args.length === 1 && ["--help", "-h", "help"].includes(args[0])) {
42
42
  output([
43
43
  "NGGAIGC CLI",
44
- "install [--agent codex|workbuddy|universal | --skills-dir <absolute-directory>] [--no-login]",
45
- "start-skill skill.<id> [version] [--agent codex|workbuddy|universal | --skills-dir <absolute-directory>]",
46
- "client [--agent codex|workbuddy|universal | --skills-dir <absolute-directory>] -- <command> [arguments]",
47
- "Default: automatically detect Codex or WorkBuddy. If unknown or conflicting, select one; non-interactive calls return selection-required (exit 3).",
48
- "Codex: existing CODEX_HOME is preserved, otherwise ~/.codex/skills. WorkBuddy: its runtime config directory/skills, otherwise ~/.workbuddy/skills; existing legacy ~/.codebuddy installs are reused. Explicit legacy universal/custom targets remain supported.",
44
+ "install [--agent codex|workbuddy|doubao-work|universal | --skills-dir <absolute-directory>] [--no-login]",
45
+ "start-skill skill.<id> [version] [--agent codex|workbuddy|doubao-work|universal | --skills-dir <absolute-directory>]",
46
+ "client [--agent codex|workbuddy|doubao-work|universal | --skills-dir <absolute-directory>] -- <command> [arguments]",
47
+ "Default: automatically detect Codex, WorkBuddy or Doubao Work. If unknown or conflicting, select one; non-interactive calls return selection-required (exit 3).",
48
+ "Codex: existing CODEX_HOME is preserved, otherwise ~/.codex/skills. WorkBuddy: its runtime config directory/skills, otherwise ~/.workbuddy/skills; existing legacy ~/.codebuddy installs are reused. Doubao Work: ~/DoubaoWork/skills. Explicit legacy universal/custom targets remain supported.",
49
49
  "Use the same target for install and subsequent commands. --no-login installs verified files without opening a browser.",
50
50
  "client examples: -- status, -- login, -- account-status, -- workflows, -- history, -- disconnect",
51
51
  "",
@@ -15,7 +15,7 @@ function record(value) {
15
15
  export async function productionDependencies(skillsDirectory) {
16
16
  const vendor = fileURLToPath(new URL("../vendor/", import.meta.url));
17
17
  const bundle = await verifyBundle({
18
- archive: path.join(vendor, "nggaigc-plugin-1.1.47.zip"),
18
+ archive: path.join(vendor, "nggaigc-plugin-1.1.48.zip"),
19
19
  manifest: path.join(vendor, "manifest.json"),
20
20
  trust: path.join(vendor, "trusted-keys.json"),
21
21
  });
@@ -54,7 +54,7 @@ export function resolveSkillLocation(options = {}, environment = process.env) {
54
54
  }
55
55
  const profile = absoluteDirectory(options.profile ?? os.homedir());
56
56
  const agent = options.agent ?? "codex";
57
- if (!["codex", "workbuddy", "universal"].includes(agent))
57
+ if (!["codex", "workbuddy", "doubao-work", "universal"].includes(agent))
58
58
  throw new CliError("INVALID_INPUT");
59
59
  const home = absoluteDirectory(options.codexHome ??
60
60
  (agent === "codex"
@@ -63,7 +63,9 @@ export function resolveSkillLocation(options = {}, environment = process.env) {
63
63
  : undefined) ?? path.join(profile, ".codex"))
64
64
  : agent === "workbuddy"
65
65
  ? workbuddyHome(profile, options.profile === undefined ? environment : {})
66
- : path.join(profile, ".agents")));
66
+ : agent === "doubao-work"
67
+ ? path.join(profile, "DoubaoWork")
68
+ : path.join(profile, ".agents")));
67
69
  return {
68
70
  skillsDirectory: path.join(home, "skills"),
69
71
  // Explicit and named-host calls for the same directory share one journal.
@@ -85,7 +87,7 @@ export function parseSkillLocation(args) {
85
87
  if (!argument || argument.startsWith("--"))
86
88
  throw new CliError("INVALID_INPUT");
87
89
  if (value === "--agent") {
88
- if (!["codex", "workbuddy", "universal"].includes(argument))
90
+ if (!["codex", "workbuddy", "doubao-work", "universal"].includes(argument))
89
91
  throw new CliError("INVALID_INPUT");
90
92
  location.agent = argument;
91
93
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nggaigc/cli",
3
- "version": "0.1.49",
3
+ "version": "0.1.51",
4
4
  "description": "Secure NGGAIGC Skill installer for Codex, WorkBuddy and compatible agents.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -1,11 +1,11 @@
1
1
  {
2
2
  "schemaVersion": "nggaigc-plugin-package/v1",
3
3
  "artifactId": "plugin.nggaigc",
4
- "version": "1.1.47",
5
- "sourceCommit": "b8f8c3b9551cabe8f496243747683e46c4ff8a6f",
6
- "artifactPath": "packages/plugins/nggaigc-plugin-1.1.47.zip",
7
- "sha256": "4c1eae813ddb688a19a6ad947d1cc78f72eb0c23405da732967f1d1dfbe3f3c9",
8
- "sizeBytes": 506301,
4
+ "version": "1.1.48",
5
+ "sourceCommit": "17038f7181c59b72b968866e68547f248069a3c5",
6
+ "artifactPath": "packages/plugins/nggaigc-plugin-1.1.48.zip",
7
+ "sha256": "92831457de7bd2f3e60ccd3805c4b7846ec32df7fd255b6b552dee225a83acc3",
8
+ "sizeBytes": 508669,
9
9
  "fileCount": 24,
10
10
  "platforms": [
11
11
  "win32-x64",
@@ -13,7 +13,7 @@
13
13
  "darwin-arm64"
14
14
  ],
15
15
  "files": {
16
- ".codex-plugin/plugin.json": "11563feb4ff9048a77055bfe76761265ebedc012d57be3f3b42b446aca63d8e8",
16
+ ".codex-plugin/plugin.json": "54daccc21f12195f2c44a1cd049e10bff5a73fa6daba245e201b3affe2e1ad7d",
17
17
  "installer/install.cjs": "76f4ed73233fd39900fb0bedbc434dea39e52e6b6b4622f3fd388a5ca09c6f62",
18
18
  "installer/legacy-root-digests.json": "922552646a5aa6cff8616c372912a37b1d5f263351206b85785ed9b2eae31641",
19
19
  "installer/signed-pair-1.1.16.json": "ccb22a90302cc5c9c585067ebc211a27b0c9d8a177c2740a5678a58a3d70bfe9",
@@ -25,15 +25,15 @@
25
25
  "migration/seedream-1.1.3/SKILL.md": "5c5cf3c2d99376f246425e873c5566436ed528256372ac3208abb60364c4517c",
26
26
  "skills/nggaigc/agents/openai.yaml": "8936d97b9821e687e224e9349cc42be2ee5fc20988562efffbcb70080aedf87c",
27
27
  "skills/nggaigc/references/catalog-and-updates.md": "a43bee94a480aa2bf0b1e7038cee6f27fb86d2bd8fa88a28a63678963d7c1530",
28
- "skills/nggaigc/references/source.json": "8e01f0fd3deb7255e3ceb8d5b9cc0c887f443f7e2117944e20451c9fdb2f463d",
28
+ "skills/nggaigc/references/source.json": "5fb7443d94c522a22cd03e508bb8b1bb2c6f67983b719ce85f5bf88bef2f01d0",
29
29
  "skills/nggaigc/scripts/api_client.mjs": "e16bf750a297ef7e88e4843d2fba9c33b412a66516bfe76822d7deec6c153069",
30
- "skills/nggaigc/scripts/api_package.mjs": "6beee22aed770cbf501abe6d1d9d252f7a53893eeb9b6399bd26c4ef68470d5a",
31
- "skills/nggaigc/scripts/bootstrap-public.json": "2ef38465223e8449c534e50f34cc3f2fa0bd9c03feacddf9360f50bb37dde68a",
32
- "skills/nggaigc/scripts/launch-ngg-client.cjs": "1942e3c9e6a435515b6e720b7c87d2150653ad15cef41a57df7b0e9a969ca228",
30
+ "skills/nggaigc/scripts/api_package.mjs": "824ea8f935e2c3aec7ad5ea5c6ad043f1b77ccd9918c86687a9bd61558954fe4",
31
+ "skills/nggaigc/scripts/bootstrap-public.json": "6d0a7d79ae4364fb5fba5786d87417732af6f559e32592373031daf24db078d2",
32
+ "skills/nggaigc/scripts/launch-ngg-client.cjs": "4f4786c2e70fbac8e24fa2de1ba02aa713d68d3f36773f4c7c242f91364a005e",
33
33
  "skills/nggaigc/scripts/macos-keychain": "b0bdf29d14219d38ca18c7e5c599deb0daa8c8ac70b0babbc7d4fb23673079ec",
34
34
  "skills/nggaigc/scripts/macos-keychain.swift": "1b57e74fde66c824fe970547dd8ca0883a3334c34c065e85a8a2a90d4556a7f5",
35
- "skills/nggaigc/scripts/ngg_client.mjs": "4cfc2b9fbb5ed3febe47cf6cd1453482a8161cce45c47272a5ac599a6c408f8c",
36
- "skills/nggaigc/scripts/ngg-session.mjs": "f244d3fe1fe44752ab964f64ae3f7c9f2c3a3951943434c83633c103564e1c70",
35
+ "skills/nggaigc/scripts/ngg_client.mjs": "254f36fad2e0fb600c91b9ae22e8f35cfd602fbb36c25ef56ab494436a2e4a77",
36
+ "skills/nggaigc/scripts/ngg-session.mjs": "026a1d9d480712ee3e2f4d505e1448e78001800c88025cd048658b38d3c040ce",
37
37
  "skills/nggaigc/scripts/supported-platforms.json": "ec8b0754c489e04534a1d9880dd6664ba9c5bcd07789e06d138e0923f23575ff",
38
38
  "skills/nggaigc/scripts/windows-credential.ps1": "641888d8c6016bb84f18df19315322ed802c5709fbe5209250eaf1b0ce498aec",
39
39
  "skills/nggaigc/SKILL.md": "8cb3eb8a03cf144ce15fa01d7d342495c2b11ba0f6a0cf61a493e1e43c83a11f"
@@ -42,6 +42,6 @@
42
42
  "algorithm": "ed25519",
43
43
  "keyId": "ngg-signing-skill-release-1",
44
44
  "scope": "artifact-bytes",
45
- "value": "wvDvfll37jzz498/ubLiUKCjXGv1DLnyI814WzuAWwqt4CpN9Ftv30yjWqG5dOK+cYhlohrcGHv7CZIwnKvcDw=="
45
+ "value": "FQ+2ziXnms95GTjoiJcdjVxekqOjSBcsfpZrGh+0IKCChqXt18AZi59WSPRDfhdM1BQO8AEiqZtM1ge5gI+JDA=="
46
46
  }
47
47
  }
index 3c8c67a..9711cc3 100644
Binary file