@nggaigc/cli 0.1.55 → 0.1.57

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
@@ -12,10 +12,12 @@ CLI 保留 macOS npm symlink 入口与 packed-TGZ launcher 检查,并验证随
12
12
 
13
13
  从 CLI `0.1.52` 起,Intel Mac 仅放开安装限制,安装的签名包与 macOS 辅助程序字节保持不变;未做 Intel 兼容性适配或真机验收,不保证登录及工作流可用,运行失败按原有机制报告。实际公开版本和 `@latest` 状态以 npm registry 为准,Apple Silicon 真机验收需单独进行。
14
14
 
15
- CLI `0.1.55` 是兼容修复候选,实际公开版本与 `latest` 以 registry 为准。它通过官方签名 ZIP 的完整文件闭包识别现有根 Skill `1.1.49`/`1.1.50`;本地安装标记仅作提示。兼容时直接复用现有启动器,当前目录确实要求新版根时才安全升级;不会降级已验证的新版安装。旧目录仍使用根149时,保留已装150,并在不可发现为 active Skill 的私有缓存内验证、使用官方149兼容运行文件;目录切到新版后使用150,启动回执指向实际受信运行文件。保留豆包工作识别和 Intel Mac 安装放行的原边界。
15
+ CLI `0.1.56` 延续 `0.1.55` 的版本兼容修复,实际公开版本与 `latest` 以 registry 为准。它通过官方签名 ZIP 的完整文件闭包识别现有根 Skill `1.1.49`/`1.1.50`;本地安装标记仅作提示。兼容时直接复用现有启动器,当前目录确实要求新版根时才安全升级;不会降级已验证的新版安装。旧目录仍使用根149时,保留已装150,并在不可发现为 active Skill 的私有缓存内验证、使用官方149兼容运行文件;目录切到新版后使用150,启动回执指向实际受信运行文件。保留豆包工作识别和 Intel Mac 安装放行的原边界。
16
16
 
17
17
  升级在原安装锁内先验证私有临时目录的文件类型、哈希和系统可表达的执行位,再原子替换并复验。失败时恢复已验证旧安装;进程中断后先按原事务读回恢复,不盲目开始新升级。Windows 不把 POSIX 执行位当作其系统权限证明,真机验收另记。
18
18
 
19
+ CLI `0.1.56` 修复 Windows 写盘句柄:校验缓存和升级暂存文件使用不截断文件的读写句柄执行 `fsync`,保留验签和失败停止。更新已发布安装器时,使用 `npx --yes @nggaigc/cli@0.1.56 install`;项目级或指定宿主安装保留原命令中的 `--skills-dir` 或 `--agent`,不要另换目录、删除配置或重提已有付费任务。发布状态以 npm 为准。本次原生 Windows 实测尚未完成,不能把模拟回归或 Mac 验收视为 Windows 已通过。维护者在原生 Windows 的 Node 22、24 上构建后,必须分别运行 `node --test packages/cli/scripts/windows-root-flush.integration.test.mjs`,覆盖新装、149→150 升级、重复安装及失败恢复;非 Windows 环境会明确拒绝该验收。模拟约束的回归测试不能代替此项。
20
+
19
21
  旧的显式 `start-skill skill.<id> <version>` 只有在官方受签、精确绑定当前目录的有限迁移许可内,才可转到同一 Skill 的当前版本;结果分别返回 `requestedVersion` 与 `resolvedVersion`,在线准入使用真实新版本及哈希。未列版本、目录变化、停用或验签失败均停止。确需固定版本可加 `--exact-version`,此时绝不迁移到其他版本。无版本调用仍要求唯一 active 入口,不激活旧版本。
20
22
 
21
23
  此许可仅用于新启动。已经受理或结果未知的任务保留原请求和任务身份;`client` 将原参数交给已验证启动器,不为恢复任务重新准入、提交或付费。
@@ -69,3 +71,5 @@ v2须声明以下有限元数据:
69
71
  运行清单是已签名的 `references/runtime-lock.json`,至少有 `schemaVersion: 1`及`files`路径到SHA256的映射。每个打包Python文件必须与其中同路径摘要一致;清单中不能出现未打包的scripts文件,也不能自引用运行清单。文档及同级依赖的摘要可继续由独立工具按自身范围复核;安装器不执行或解释其业务规则。
70
72
 
71
73
  安装、复用、API合同加载和回滚只验证/交付字节,**不会执行Python、安装解释器/FFmpeg或调用付费服务**。工作流按实际阶段检查宿主依赖并明确调用已声明入口。全部既有签名、逐文件摘要、安全ZIP、32文件/4MiB、路径检查、原子替换及回滚规则继续生效。旧v1 loader明确拒绝v2;不能给旧包加脚本但保留v1声明,或把源码改成文档后缀绕过规则。
74
+
75
+ 本地候选目录兼容协议:CLI 0.1.57 从已验签的 1.1.52 私有运行时启动,保留原位已安装总 Skill 1.1.49/1.1.50,不能把私有缓存准备称为原位总 Skill 升级。该运行时通过公开 `X-NGG-Catalog-View: private-runtime-v1` 协商当前目录;此值不授予权限,现有账户、设备、签名、hash 和在线准入检查仍逐次执行。未协商的旧客户端保留真实 C168。新私有运行时未正式签名/完整安装验收前,本候选不可发布。
@@ -0,0 +1,11 @@
1
+ /** Finite protocol negotiation; not an authentication credential. */
2
+ export const PRIVATE_RUNTIME_VERSION = "1.1.52";
3
+ export const CATALOG_VIEW_HEADER = "X-NGG-Catalog-View";
4
+ export const CATALOG_VIEW = "private-runtime-v1";
5
+ export function currentCatalogFetcher(fetcher = globalThis.fetch) {
6
+ return (input, init = {}) => {
7
+ const headers = new Headers(init.headers);
8
+ headers.set(CATALOG_VIEW_HEADER, CATALOG_VIEW);
9
+ return fetcher(input, { ...init, headers });
10
+ };
11
+ }
@@ -1,3 +1,4 @@
1
+ import { PRIVATE_RUNTIME_VERSION } from "./catalog-view.js";
1
2
  /** Official root material is authenticity evidence; a local marker is only a hint. */
2
3
  import { createHash, randomBytes } from "node:crypto";
3
4
  import { lstat, mkdir, readFile, rename, copyFile, open, realpath, rm, } from "node:fs/promises";
@@ -89,7 +90,9 @@ export async function saveProof(skills, bundle, vendor = rootVendor) {
89
90
  path.join(temp, `nggaigc-plugin-${bundle.version}.zip`),
90
91
  path.join(temp, "manifest.json"),
91
92
  ]) {
92
- const fd = await open(file, "r");
93
+ // Windows FlushFileBuffers requires a writable handle. r+ preserves bytes
94
+ // and fails if the already-verified staging file is missing (unlike w).
95
+ const fd = await open(file, "r+");
93
96
  try {
94
97
  await fd.sync();
95
98
  }
@@ -120,7 +123,7 @@ export async function trustedRoot(skills, vendor = rootVendor) {
120
123
  }
121
124
  /** Creation holds the install lock; verified immutable reuse is read-only. */
122
125
  export async function trustedRuntime(skills, version, vendor = rootVendor, create = true) {
123
- if (!["1.1.49", "1.1.50"].includes(version))
126
+ if (!["1.1.49", "1.1.50", PRIVATE_RUNTIME_VERSION].includes(version))
124
127
  throw new CliError("ROOT_UNAVAILABLE");
125
128
  await trustedRoot(skills, vendor);
126
129
  // Delegates always use an immutable runtime, including the currently installed version.
@@ -315,7 +315,8 @@ export async function installVerifiedRootLocked(skills, bundle, options = {}) {
315
315
  await verifyInstalledSkill(p.stage, bundle.files, bundle.executableFiles);
316
316
  // Flush all payloads before recording intent; directory renames then survive process interruption.
317
317
  for (const name of Object.keys(bundle.files).filter((x) => x.startsWith("skills/nggaigc/"))) {
318
- const fd = await open(path.join(p.stage, name.slice(15)), "r");
318
+ // Flush existing staged payloads without truncating or creating files.
319
+ const fd = await open(path.join(p.stage, name.slice(15)), "r+");
319
320
  try {
320
321
  await fd.sync();
321
322
  }
@@ -1,3 +1,4 @@
1
+ import { PRIVATE_RUNTIME_VERSION, currentCatalogFetcher, } from "./catalog-view.js";
1
2
  import { createHash, createPublicKey } from "node:crypto";
2
3
  import { readFile, realpath } from "node:fs/promises";
3
4
  import { createRequire } from "node:module";
@@ -7,18 +8,9 @@ import { resolveSkillLocation, } from "./skill-location.js";
7
8
  import { CliError } from "./errors.js";
8
9
  import { trustedKeyId, trustedKeySpkiSha256 } from "./bundle.js";
9
10
  import { trustedRoot, trustedRuntime, exists } from "./root-store.js";
10
- import { withRootLock, recoverRootForUse, ensureCurrentRootLocked, } from "./root-upgrade.js";
11
+ import { withRootLock, recoverRootForUse } from "./root-upgrade.js";
11
12
  import { canonical, resolveStartAlias } from "./start-compatibility.js";
12
13
  import { IndependentSkillError, projectActiveSkillCatalog, startIndependentSkill, } from "./independent-skill.js";
13
- function compare(a, b) {
14
- const x = a.split(".").map(Number), y = b.split(".").map(Number);
15
- for (let i = 0; i < 3; i++) {
16
- const d = x[i] - y[i];
17
- if (d)
18
- return d;
19
- }
20
- return 0;
21
- }
22
14
  function fail(code) {
23
15
  throw new IndependentSkillError(code);
24
16
  }
@@ -27,8 +19,8 @@ function record(value) {
27
19
  }
28
20
  async function productionDependenciesLocked(skillsDirectory, verifiedLauncher, runtimeVersion, createRuntime = true) {
29
21
  const vendor = fileURLToPath(new URL("../vendor/", import.meta.url));
30
- const current = await trustedRoot(skillsDirectory);
31
- const installed = await trustedRuntime(skillsDirectory, runtimeVersion ?? current.version, undefined, createRuntime);
22
+ await trustedRoot(skillsDirectory);
23
+ const installed = await trustedRuntime(skillsDirectory, runtimeVersion ?? PRIVATE_RUNTIME_VERSION, undefined, createRuntime);
32
24
  const root = installed.directory;
33
25
  const keys = JSON.parse(await readFile(path.join(vendor, "trusted-keys.json"), "utf8"));
34
26
  if (!record(keys) ||
@@ -82,9 +74,6 @@ export async function productionDependencies(skillsDirectory, verifiedLauncher,
82
74
  return productionDependenciesLocked(skillsDirectory, verifiedLauncher, runtimeVersion, true);
83
75
  });
84
76
  }
85
- async function upgradeRoot(skillsDirectory) {
86
- await withRootLock(skillsDirectory, () => ensureCurrentRootLocked(skillsDirectory));
87
- }
88
77
  function catalogRootVersion(snapshot) {
89
78
  if (!record(snapshot) || !Array.isArray(snapshot.entries))
90
79
  fail("CATALOG_INVALID");
@@ -95,7 +84,7 @@ function catalogRootVersion(snapshot) {
95
84
  record(e.manifest.lifecycle) &&
96
85
  e.manifest.lifecycle.status === "published");
97
86
  if (roots.length !== 1 ||
98
- !["1.1.49", "1.1.50"].includes(String(roots[0].version)))
87
+ String(roots[0].version) !== PRIVATE_RUNTIME_VERSION)
99
88
  fail("ROOT_UNAVAILABLE");
100
89
  return String(roots[0].version);
101
90
  }
@@ -131,8 +120,7 @@ export async function runClientCommand(args, options = {}, launcherOptions = {})
131
120
  fail("CATALOG_INVALID");
132
121
  const target = catalogRootVersion(snapshot);
133
122
  if (target !== rootSkillVersion) {
134
- if (compare(target, rootSkillVersion) > 0)
135
- await upgradeRoot(skillsDirectory);
123
+ // Switching a private runtime must never replace the installed legacy root.
136
124
  const updated = await productionDependencies(skillsDirectory, options.verifiedLauncher, target);
137
125
  launcher = updated.launcher;
138
126
  const fresh = await launcher.main(["catalog-snapshot"], launcherOptions);
@@ -188,8 +176,7 @@ export async function runSkillStartCommand(skillId, skillVersion, options = {})
188
176
  if (production) {
189
177
  const target = catalogRootVersion(snapshot);
190
178
  if (target !== rootSkillVersion) {
191
- if (compare(target, rootSkillVersion) > 0)
192
- await upgradeRoot(skillsDirectory);
179
+ // Switching a private runtime must never replace the installed legacy root.
193
180
  const updated = await productionDependencies(skillsDirectory, options.verifiedLauncher, target);
194
181
  launcher = updated.launcher;
195
182
  rootSkillVersion = updated.rootSkillVersion;
@@ -208,7 +195,7 @@ export async function runSkillStartCommand(skillId, skillVersion, options = {})
208
195
  platformVersion,
209
196
  skillsDirectory,
210
197
  trust,
211
- fetcher: options.fetcher,
198
+ fetcher: currentCatalogFetcher(options.fetcher),
212
199
  admit: async (identity) => {
213
200
  const answer = await launcher.main([
214
201
  "skill-admit",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nggaigc/cli",
3
- "version": "0.1.55",
3
+ "version": "0.1.57",
4
4
  "description": "Secure NGGAIGC Skill installer for Codex, WorkBuddy and compatible agents.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -0,0 +1,47 @@
1
+ {
2
+ "schemaVersion": "nggaigc-plugin-package/v1",
3
+ "artifactId": "plugin.nggaigc",
4
+ "version": "1.1.52",
5
+ "sourceCommit": "e2aa56e384db076f5dd69713d26c2c096c82159e",
6
+ "artifactPath": "packages/plugins/nggaigc-plugin-1.1.52.zip",
7
+ "sha256": "85e6a51dc48946a02f385ebb366605107468fb86fe5d7c1a03cb6669e5e03b8d",
8
+ "sizeBytes": 510622,
9
+ "fileCount": 24,
10
+ "platforms": [
11
+ "win32-x64",
12
+ "win32-arm64",
13
+ "darwin-arm64"
14
+ ],
15
+ "files": {
16
+ ".codex-plugin/plugin.json": "d1aa9601a6f1cb10fda9804efdcd9100b46fa499e6c8799fa42a17b712389f21",
17
+ "installer/install.cjs": "76f4ed73233fd39900fb0bedbc434dea39e52e6b6b4622f3fd388a5ca09c6f62",
18
+ "installer/legacy-root-digests.json": "922552646a5aa6cff8616c372912a37b1d5f263351206b85785ed9b2eae31641",
19
+ "installer/signed-pair-1.1.16.json": "ccb22a90302cc5c9c585067ebc211a27b0c9d8a177c2740a5678a58a3d70bfe9",
20
+ "installer/signed-pair-1.1.17.json": "a3697506c929aaa085a6d994fc3a1b9a87e522ec6e1e32f3f760e6a534effa2b",
21
+ "migration/seedream-1.1.3/agents/openai.yaml": "3cbf034ddccd64a7972acd37e7433683a3944f3d8c7b5bdccbbd70e517bf5a8c",
22
+ "migration/seedream-1.1.3/references/image-generation.md": "15a6dd1f96c53240ef9e961049a7b323ca3c42d2dcf01c9982f1849f01e96afe",
23
+ "migration/seedream-1.1.3/references/source.json": "75998d079a229435d1097b00bd008703bd38026fc6485c312254925bf55398a8",
24
+ "migration/seedream-1.1.3/scripts/seedream.mjs": "dcc6af4d945790d9dfd7fac21c60934759d7ac2576a14507d0299f4833942a96",
25
+ "migration/seedream-1.1.3/SKILL.md": "65e39b129f40f86b76b24a19be6494f9b091bc3d1ccffd20b8a6cd56130a0cb7",
26
+ "skills/nggaigc/agents/openai.yaml": "8936d97b9821e687e224e9349cc42be2ee5fc20988562efffbcb70080aedf87c",
27
+ "skills/nggaigc/references/catalog-and-updates.md": "534979fe28e85463c4558700e14401268b1c0e443fc49092199eef1911449f0c",
28
+ "skills/nggaigc/references/source.json": "3063b696eeb56d71d47516dfa849ed4542771b708412e8442fe94b228da48105",
29
+ "skills/nggaigc/scripts/api_client.mjs": "e16bf750a297ef7e88e4843d2fba9c33b412a66516bfe76822d7deec6c153069",
30
+ "skills/nggaigc/scripts/api_package.mjs": "824ea8f935e2c3aec7ad5ea5c6ad043f1b77ccd9918c86687a9bd61558954fe4",
31
+ "skills/nggaigc/scripts/bootstrap-public.json": "4c3dd5e548480e8e60842bae85ce76fb2bd0107defd4b3532129b29842dda33b",
32
+ "skills/nggaigc/scripts/launch-ngg-client.cjs": "69bc926f0816196436b3fbbcec70efc7b17a7f44ec6c06c5082c211574a76bad",
33
+ "skills/nggaigc/scripts/macos-keychain": "b0bdf29d14219d38ca18c7e5c599deb0daa8c8ac70b0babbc7d4fb23673079ec",
34
+ "skills/nggaigc/scripts/macos-keychain.swift": "1b57e74fde66c824fe970547dd8ca0883a3334c34c065e85a8a2a90d4556a7f5",
35
+ "skills/nggaigc/scripts/ngg-session.mjs": "632f5368bc861a9bdd52d7cfeb8fb8376c34ef8f802e01ca1d41fc2716dbc31a",
36
+ "skills/nggaigc/scripts/ngg_client.mjs": "89458ab4acb5fd0b4b9ae77cea15f8f259a13cd7588038f52511bf809d5b44e2",
37
+ "skills/nggaigc/scripts/supported-platforms.json": "ec8b0754c489e04534a1d9880dd6664ba9c5bcd07789e06d138e0923f23575ff",
38
+ "skills/nggaigc/scripts/windows-credential.ps1": "641888d8c6016bb84f18df19315322ed802c5709fbe5209250eaf1b0ce498aec",
39
+ "skills/nggaigc/SKILL.md": "bca7a53138b6f820c0a735dcdcb20b688e9a702699bc84babc4ef6a630988a07"
40
+ },
41
+ "signature": {
42
+ "algorithm": "ed25519",
43
+ "keyId": "ngg-signing-skill-release-1",
44
+ "scope": "artifact-bytes",
45
+ "value": "/SCLOXoya4UqiisUZLvnJm9BjXQ0iaF5FvU+2tTEAd24QCNqkXNQDDtIGp5J/pj1CL+ioEFiml42xcahfLUXAg=="
46
+ }
47
+ }
@@ -2,9 +2,9 @@
2
2
  "payload": {
3
3
  "schemaVersion": "nggaigc-start-compatibility/v1",
4
4
  "catalog": {
5
- "releaseId": "catalog-2026.11.02.3",
6
- "catalogVersion": "1.10.168",
7
- "releaseSha256": "11fa89a45efc9b859d26ae6398b97b3a7559c1d614eefae3ff59a9403f481950"
5
+ "releaseId": "catalog-2026.11.03.3",
6
+ "catalogVersion": "1.10.172",
7
+ "releaseSha256": "e6de2635868a34ad501355ae132ce8c420bc5b1a38df31530fb6c38a356c4410"
8
8
  },
9
9
  "contract": "same-skill-inputs-pricing-permissions",
10
10
  "aliases": [
@@ -19,8 +19,15 @@
19
19
  "id": "skill.h3-broll-video-assets",
20
20
  "fromVersion": "0.1.9",
21
21
  "fromManifestSha256": "d4f3a01ce66879e668935af9ccba225ca08ca9b123296e8f7e6144a2beb71674",
22
- "toVersion": "0.1.10",
23
- "toManifestSha256": "14b2d3996d927f2b3c995c3e827a33e990bcca923aa64f84c905b24b3badcfe4"
22
+ "toVersion": "0.1.12",
23
+ "toManifestSha256": "f42ea141a6c0e67844dbe981c52047c7c8871737decd6cde2534bf273d8d5987"
24
+ },
25
+ {
26
+ "id": "skill.h3-broll-video-assets",
27
+ "fromVersion": "0.1.10",
28
+ "fromManifestSha256": "14b2d3996d927f2b3c995c3e827a33e990bcca923aa64f84c905b24b3badcfe4",
29
+ "toVersion": "0.1.12",
30
+ "toManifestSha256": "f42ea141a6c0e67844dbe981c52047c7c8871737decd6cde2534bf273d8d5987"
24
31
  },
25
32
  {
26
33
  "id": "skill.image-singing-digital-human",
@@ -47,8 +54,15 @@
47
54
  "id": "skill.ngg-depth-dance-copy",
48
55
  "fromVersion": "0.2.1",
49
56
  "fromManifestSha256": "efb34854dd2d5ab5e8d33363ca1ce93c69c7743cac143c16c34c360a8bab89fd",
50
- "toVersion": "0.2.2",
51
- "toManifestSha256": "6eca6fc0897875ba56c0cb460052f7f490f6833c61164daf3dfc22b4e9530fd9"
57
+ "toVersion": "0.2.3",
58
+ "toManifestSha256": "e2448e360bc9bdfd57d14ff20cf81cc90693eda00a7edcf1a27abd9f09b62a20"
59
+ },
60
+ {
61
+ "id": "skill.ngg-depth-dance-copy",
62
+ "fromVersion": "0.2.2",
63
+ "fromManifestSha256": "6eca6fc0897875ba56c0cb460052f7f490f6833c61164daf3dfc22b4e9530fd9",
64
+ "toVersion": "0.2.3",
65
+ "toManifestSha256": "e2448e360bc9bdfd57d14ff20cf81cc90693eda00a7edcf1a27abd9f09b62a20"
52
66
  },
53
67
  {
54
68
  "id": "skill.ngg-drama-workflow",
@@ -119,6 +133,6 @@
119
133
  "algorithm": "ed25519",
120
134
  "keyId": "ngg-signing-skill-release-1",
121
135
  "scope": "nggaigc-start-compatibility/v1",
122
- "value": "TieQh/DsCu0K6ViZsYATqXFnBIFtnJxk97Nd3j9Jp8F4VfeacC7IE2vOlG5VLz/gWvxXqALy6J9OOiBJi45PDQ=="
136
+ "value": "tHSv9okTaDs4zJISa0tj9nAc99Hq9VogRKNDZgceJXz5KWhXUIcOKY5Ipk6nZTuEiTWvGV5PLAokYGCRWT7XAg=="
123
137
  }
124
138
  }