@nggaigc/cli 0.1.9 → 0.1.12
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 +5 -3
- package/dist/archive.js +213 -0
- package/dist/bin.js +32 -11
- package/dist/bundle.js +60 -72
- package/dist/independent-skill.js +690 -0
- package/dist/install.js +18 -7
- package/dist/skill-command.js +115 -0
- package/package.json +7 -7
- package/vendor/manifest.json +28 -22
- package/vendor/nggaigc-plugin-1.1.14.zip +0 -0
- package/vendor/nggaigc-plugin-1.1.10.zip +0 -0
package/dist/install.js
CHANGED
|
@@ -8,7 +8,7 @@ import { CliError, fixedErrorCode } from "./errors.js";
|
|
|
8
8
|
function defaultBundle() {
|
|
9
9
|
const vendor = fileURLToPath(new URL("../vendor/", import.meta.url));
|
|
10
10
|
return {
|
|
11
|
-
archive: path.join(vendor, "nggaigc-plugin-1.1.
|
|
11
|
+
archive: path.join(vendor, "nggaigc-plugin-1.1.14.zip"),
|
|
12
12
|
manifest: path.join(vendor, "manifest.json"),
|
|
13
13
|
trust: path.join(vendor, "trusted-keys.json"),
|
|
14
14
|
};
|
|
@@ -17,9 +17,10 @@ function validateRuntime(platform, architecture) {
|
|
|
17
17
|
const [major, minor] = process.versions.node.split(".").map(Number);
|
|
18
18
|
if (!((major === 22 && (minor ?? 0) >= 13) || major === 24))
|
|
19
19
|
throw new CliError("RUNTIME_UNSUPPORTED");
|
|
20
|
-
if (platform !== "win32")
|
|
20
|
+
if (platform !== "win32" && platform !== "darwin")
|
|
21
21
|
throw new CliError("UNSUPPORTED_PLATFORM");
|
|
22
|
-
if (
|
|
22
|
+
if ((platform === "darwin" && architecture !== "arm64") ||
|
|
23
|
+
(platform === "win32" && architecture !== "x64" && architecture !== "arm64"))
|
|
23
24
|
throw new CliError("UNSUPPORTED_PLATFORM");
|
|
24
25
|
}
|
|
25
26
|
function safeProfile(value) {
|
|
@@ -27,6 +28,14 @@ function safeProfile(value) {
|
|
|
27
28
|
throw new CliError("INVALID_INPUT");
|
|
28
29
|
return path.resolve(value);
|
|
29
30
|
}
|
|
31
|
+
function installationError(error) {
|
|
32
|
+
const code = fixedErrorCode(error);
|
|
33
|
+
if (["SKILL_PAIR_UPGRADE_REQUIRED", "SKILL_PAIR_UNSAFE"].includes(code ?? ""))
|
|
34
|
+
return new CliError("SKILL_PAIR_UPGRADE_REQUIRED");
|
|
35
|
+
if (["SKILL_PAIR_RECOVERY_REQUIRED", "SKILL_PAIR_SOURCE_INVALID"].includes(code ?? ""))
|
|
36
|
+
return new CliError("SKILL_PAIR_RECOVERY_REQUIRED");
|
|
37
|
+
return new CliError("INSTALLATION_FAILED");
|
|
38
|
+
}
|
|
30
39
|
async function installedVersion(target) {
|
|
31
40
|
try {
|
|
32
41
|
const marker = JSON.parse(await readFile(path.join(target, ".nggaigc-install.json"), "utf8"));
|
|
@@ -64,7 +73,7 @@ async function installSkill(installer, source, profile, codexHome, expectedVersi
|
|
|
64
73
|
}
|
|
65
74
|
catch (error) {
|
|
66
75
|
if (fixedErrorCode(error) !== "ALREADY_INSTALLED")
|
|
67
|
-
throw
|
|
76
|
+
throw installationError(error);
|
|
68
77
|
}
|
|
69
78
|
const currentVersion = await installedVersion(target);
|
|
70
79
|
if (!currentVersion)
|
|
@@ -83,8 +92,8 @@ async function installSkill(installer, source, profile, codexHome, expectedVersi
|
|
|
83
92
|
await verifyInstalledSkill(target, bundleFiles);
|
|
84
93
|
return "updated";
|
|
85
94
|
}
|
|
86
|
-
catch {
|
|
87
|
-
throw
|
|
95
|
+
catch (error) {
|
|
96
|
+
throw installationError(error);
|
|
88
97
|
}
|
|
89
98
|
}
|
|
90
99
|
async function connect(launcher, options, report, probe) {
|
|
@@ -162,12 +171,14 @@ export async function runInstall(options = {}) {
|
|
|
162
171
|
const report = options.reporter ?? (() => undefined);
|
|
163
172
|
report("verifying");
|
|
164
173
|
const bundle = await verifyBundle(options.bundle ?? defaultBundle());
|
|
174
|
+
if (!bundle.platforms.includes(`${options.platform ?? process.platform}-${options.architecture ?? process.arch}`))
|
|
175
|
+
throw new CliError("UNSUPPORTED_PLATFORM");
|
|
165
176
|
const temporaryParent = path.resolve(options.temporaryRoot ?? os.tmpdir());
|
|
166
177
|
const temporary = await mkdtemp(path.join(temporaryParent, "nggaigc-cli-"));
|
|
167
178
|
assertDisposableRoot(temporary, temporaryParent);
|
|
168
179
|
try {
|
|
169
180
|
const extracted = path.join(temporary, "plugin");
|
|
170
|
-
await extractBundle(bundle.archive, extracted);
|
|
181
|
+
await extractBundle(bundle.archive, extracted, bundle.sha256);
|
|
171
182
|
await verifyExtractedBundle(extracted, bundle.files);
|
|
172
183
|
report("installing");
|
|
173
184
|
const require = createRequire(import.meta.url);
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import { createHash, createPublicKey } from "node:crypto";
|
|
2
|
+
import { readFile } from "node:fs/promises";
|
|
3
|
+
import { createRequire } from "node:module";
|
|
4
|
+
import os from "node:os";
|
|
5
|
+
import path from "node:path";
|
|
6
|
+
import { fileURLToPath } from "node:url";
|
|
7
|
+
import { trustedKeyId, trustedKeySpkiSha256, verifyBundle, verifyInstalledSkill, } from "./bundle.js";
|
|
8
|
+
import { IndependentSkillError, projectActiveSkillCatalog, startIndependentSkill, } from "./independent-skill.js";
|
|
9
|
+
function fail(code) {
|
|
10
|
+
throw new IndependentSkillError(code);
|
|
11
|
+
}
|
|
12
|
+
function record(value) {
|
|
13
|
+
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
14
|
+
}
|
|
15
|
+
async function productionDependencies(codexHome) {
|
|
16
|
+
const vendor = fileURLToPath(new URL("../vendor/", import.meta.url));
|
|
17
|
+
const bundle = await verifyBundle({
|
|
18
|
+
archive: path.join(vendor, "nggaigc-plugin-1.1.14.zip"),
|
|
19
|
+
manifest: path.join(vendor, "manifest.json"),
|
|
20
|
+
trust: path.join(vendor, "trusted-keys.json"),
|
|
21
|
+
});
|
|
22
|
+
const root = path.join(codexHome, "skills", "nggaigc");
|
|
23
|
+
await verifyInstalledSkill(root, bundle.files);
|
|
24
|
+
const source = JSON.parse(await readFile(path.join(root, "references", "source.json"), "utf8"));
|
|
25
|
+
if (!record(source) ||
|
|
26
|
+
source.id !== "skill.nggaigc" ||
|
|
27
|
+
typeof source.version !== "string" ||
|
|
28
|
+
!/^\d+\.\d+\.\d+$/.test(source.version) ||
|
|
29
|
+
source.clientProtocol !== 1)
|
|
30
|
+
fail("ROOT_UNAVAILABLE");
|
|
31
|
+
const keys = JSON.parse(await readFile(path.join(vendor, "trusted-keys.json"), "utf8"));
|
|
32
|
+
if (!record(keys) ||
|
|
33
|
+
keys.schemaVersion !== "ngg-trusted-package-keys/v1" ||
|
|
34
|
+
!Array.isArray(keys.keys))
|
|
35
|
+
fail("TRUST_UNAVAILABLE");
|
|
36
|
+
const match = keys.keys.find((key) => record(key) &&
|
|
37
|
+
key.keyId === trustedKeyId &&
|
|
38
|
+
typeof key.publicKeyPem === "string");
|
|
39
|
+
if (!record(match) || typeof match.publicKeyPem !== "string")
|
|
40
|
+
fail("TRUST_UNAVAILABLE");
|
|
41
|
+
const key = createPublicKey(match.publicKeyPem);
|
|
42
|
+
const fingerprint = createHash("sha256")
|
|
43
|
+
.update(key.export({ type: "spki", format: "der" }))
|
|
44
|
+
.digest("hex");
|
|
45
|
+
if (fingerprint !== trustedKeySpkiSha256)
|
|
46
|
+
fail("TRUST_UNAVAILABLE");
|
|
47
|
+
const require = createRequire(import.meta.url);
|
|
48
|
+
const launcher = require(path.join(root, "scripts", "launch-ngg-client.cjs"));
|
|
49
|
+
if (!record(launcher) || typeof launcher.main !== "function")
|
|
50
|
+
fail("ROOT_UNAVAILABLE");
|
|
51
|
+
return {
|
|
52
|
+
launcher: launcher,
|
|
53
|
+
trust: {
|
|
54
|
+
keyId: trustedKeyId,
|
|
55
|
+
publicKeyPem: match.publicKeyPem,
|
|
56
|
+
spkiSha256: fingerprint,
|
|
57
|
+
},
|
|
58
|
+
rootSkillVersion: source.version,
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
/** Candidate npm entry: active catalog → server admission → verified local Skill path. */
|
|
62
|
+
export async function runSkillStartCommand(skillId, skillVersion, options = {}) {
|
|
63
|
+
if (!/^skill\.[a-z0-9][a-z0-9.-]{0,79}$/.test(skillId) ||
|
|
64
|
+
(skillVersion !== undefined && !/^\d+\.\d+\.\d+$/.test(skillVersion)))
|
|
65
|
+
fail("INVALID_INPUT");
|
|
66
|
+
const codexHome = path.resolve(options.codexHome ??
|
|
67
|
+
process.env.CODEX_HOME ??
|
|
68
|
+
path.join(os.homedir(), ".codex"));
|
|
69
|
+
if (!path.isAbsolute(codexHome))
|
|
70
|
+
fail("INSTALL_PATH_UNSAFE");
|
|
71
|
+
const production = options.launcher && options.trust && options.rootSkillVersion
|
|
72
|
+
? null
|
|
73
|
+
: await productionDependencies(codexHome);
|
|
74
|
+
const launcher = options.launcher ?? production.launcher;
|
|
75
|
+
const trust = options.trust ?? production.trust;
|
|
76
|
+
const rootSkillVersion = options.rootSkillVersion ?? production.rootSkillVersion;
|
|
77
|
+
const platformVersion = options.platformVersion ??
|
|
78
|
+
JSON.parse(await readFile(new URL("../package.json", import.meta.url), "utf8")).version;
|
|
79
|
+
let snapshot;
|
|
80
|
+
try {
|
|
81
|
+
snapshot = await launcher.main(["catalog-snapshot"]);
|
|
82
|
+
}
|
|
83
|
+
catch {
|
|
84
|
+
fail("CATALOG_UNAVAILABLE");
|
|
85
|
+
}
|
|
86
|
+
const index = projectActiveSkillCatalog(snapshot);
|
|
87
|
+
const matches = index.entries.filter((entry) => entry.id === skillId &&
|
|
88
|
+
entry.state === "active" &&
|
|
89
|
+
entry.sourceManifest?.role === "independent_skill" &&
|
|
90
|
+
(skillVersion === undefined || entry.version === skillVersion));
|
|
91
|
+
if (matches.length !== 1)
|
|
92
|
+
fail("SKILL_UNAVAILABLE");
|
|
93
|
+
const selected = matches[0];
|
|
94
|
+
return startIndependentSkill({
|
|
95
|
+
index,
|
|
96
|
+
skillId: selected.id,
|
|
97
|
+
skillVersion: selected.version,
|
|
98
|
+
rootSkillVersion,
|
|
99
|
+
platformVersion,
|
|
100
|
+
codexHome,
|
|
101
|
+
trust,
|
|
102
|
+
fetcher: options.fetcher,
|
|
103
|
+
admit: async (identity) => {
|
|
104
|
+
const answer = await launcher.main([
|
|
105
|
+
"skill-admit",
|
|
106
|
+
identity.kind,
|
|
107
|
+
identity.id,
|
|
108
|
+
identity.version,
|
|
109
|
+
identity.manifestSha256,
|
|
110
|
+
identity.releaseId,
|
|
111
|
+
]);
|
|
112
|
+
return answer;
|
|
113
|
+
},
|
|
114
|
+
});
|
|
115
|
+
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nggaigc/cli",
|
|
3
|
-
"version": "0.1.
|
|
4
|
-
"description": "Secure one-command NGGAIGC Skill installer for Codex
|
|
3
|
+
"version": "0.1.12",
|
|
4
|
+
"description": "Secure one-command NGGAIGC Skill installer for Codex.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
7
7
|
"nggaigc": "dist/bin.js"
|
|
@@ -15,18 +15,18 @@
|
|
|
15
15
|
"node": ">=22.13.0 <23 || >=24.0.0 <25"
|
|
16
16
|
},
|
|
17
17
|
"os": [
|
|
18
|
-
"win32"
|
|
18
|
+
"win32",
|
|
19
|
+
"darwin"
|
|
19
20
|
],
|
|
20
21
|
"cpu": [
|
|
21
22
|
"x64",
|
|
22
23
|
"arm64"
|
|
23
24
|
],
|
|
25
|
+
"license": "UNLICENSED",
|
|
24
26
|
"scripts": {
|
|
25
27
|
"build": "tsc -p tsconfig.build.json",
|
|
26
|
-
"prepack": "tsc -p tsconfig.build.json && node scripts/stage-assets.mjs",
|
|
27
28
|
"test": "vitest run src --exclude 'src/windows-secure-store.integration.test.ts'",
|
|
28
29
|
"test:credential:os": "tsc -p tsconfig.build.json && vitest run src/windows-secure-store.integration.test.ts",
|
|
29
30
|
"typecheck": "tsc -p tsconfig.json --noEmit"
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
}
|
|
31
|
+
}
|
|
32
|
+
}
|
package/vendor/manifest.json
CHANGED
|
@@ -1,33 +1,39 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schemaVersion": "nggaigc-plugin-package/v1",
|
|
3
3
|
"artifactId": "plugin.nggaigc",
|
|
4
|
-
"version": "1.1.
|
|
5
|
-
"sourceCommit": "
|
|
6
|
-
"artifactPath": "packages/plugins/nggaigc-plugin-1.1.
|
|
7
|
-
"sha256": "
|
|
8
|
-
"sizeBytes":
|
|
9
|
-
"fileCount":
|
|
10
|
-
"platforms": [
|
|
11
|
-
"win32-x64",
|
|
12
|
-
"win32-arm64"
|
|
13
|
-
],
|
|
4
|
+
"version": "1.1.14",
|
|
5
|
+
"sourceCommit": "d7e68a4311bfc9c34cff1419197906417b50c6ec",
|
|
6
|
+
"artifactPath": "packages/plugins/nggaigc-plugin-1.1.14.zip",
|
|
7
|
+
"sha256": "3610b002a56703534a4975c506f2e90a9d589a671ce42a4557d4282d1d6852aa",
|
|
8
|
+
"sizeBytes": 337385,
|
|
9
|
+
"fileCount": 20,
|
|
10
|
+
"platforms": ["win32-x64", "win32-arm64", "darwin-arm64"],
|
|
14
11
|
"files": {
|
|
15
|
-
".codex-plugin/plugin.json": "
|
|
16
|
-
"installer/install.cjs": "
|
|
17
|
-
"
|
|
18
|
-
"
|
|
19
|
-
"
|
|
20
|
-
"
|
|
21
|
-
"
|
|
22
|
-
"
|
|
23
|
-
"skills/nggaigc/
|
|
24
|
-
"skills/nggaigc/
|
|
25
|
-
"skills/nggaigc/
|
|
12
|
+
".codex-plugin/plugin.json": "35d8cde373c830a9dd8ebf4616d8c8b32f62034c8ae9a4c0df710c5e094041bc",
|
|
13
|
+
"installer/install.cjs": "69e4c8a6b54c0393c4b3186a14ca29ccc2915997ac05b379549128ffa9e3fc93",
|
|
14
|
+
"installer/legacy-root-digests.json": "922552646a5aa6cff8616c372912a37b1d5f263351206b85785ed9b2eae31641",
|
|
15
|
+
"migration/seedream-1.1.1/SKILL.md": "c45ee501af0b28ca9e66c81a75827ca83dfa6c7420cfd142952512a1fccc2c37",
|
|
16
|
+
"migration/seedream-1.1.1/agents/openai.yaml": "3cbf034ddccd64a7972acd37e7433683a3944f3d8c7b5bdccbbd70e517bf5a8c",
|
|
17
|
+
"migration/seedream-1.1.1/references/image-generation.md": "b27a8ac38099d3aea4ad00351887437e3d79c537e318a463108fb017d05b838e",
|
|
18
|
+
"migration/seedream-1.1.1/references/source.json": "fb89c461b7ef587ebd8e9ceaa7b3128d0766f2004ee437c261c0d5ec25a31ce8",
|
|
19
|
+
"migration/seedream-1.1.1/scripts/seedream.mjs": "195e0e8eaca0b62c7e89262a05bfc27fa8caa9d59d5ea6418ec3a72239ee2ad5",
|
|
20
|
+
"skills/nggaigc/SKILL.md": "935970e818e5a60839c5f68738889f22eaae4fc85a0c4bf9a0a89f0571d17403",
|
|
21
|
+
"skills/nggaigc/agents/openai.yaml": "8936d97b9821e687e224e9349cc42be2ee5fc20988562efffbcb70080aedf87c",
|
|
22
|
+
"skills/nggaigc/references/catalog-and-updates.md": "638357c1d7a5170dc4a0ce635a08e148ef440f69ce51251bc2a053b0871589a9",
|
|
23
|
+
"skills/nggaigc/references/source.json": "7c69604cd85211e2d4ba15a79b81ab81e08caf5808f94b20af972e3e475377fc",
|
|
24
|
+
"skills/nggaigc/scripts/bootstrap-public.json": "78670a0a52ee878cc66107c282fcdda35e6d3ad372a8aacaf5986fd773bf3d43",
|
|
25
|
+
"skills/nggaigc/scripts/launch-ngg-client.cjs": "c2f76f3fc10796904158a4b56d6d0a43581b3e4b7583837a8aed44f0c727eb84",
|
|
26
|
+
"skills/nggaigc/scripts/macos-keychain": "b0bdf29d14219d38ca18c7e5c599deb0daa8c8ac70b0babbc7d4fb23673079ec",
|
|
27
|
+
"skills/nggaigc/scripts/macos-keychain.swift": "1b57e74fde66c824fe970547dd8ca0883a3334c34c065e85a8a2a90d4556a7f5",
|
|
28
|
+
"skills/nggaigc/scripts/ngg-session.mjs": "8904c71d66cef8140bb758bbfa0d3cea429ffa3a20fef1c871bcaa530243b698",
|
|
29
|
+
"skills/nggaigc/scripts/ngg_client.mjs": "588722bcc25a127a53d8f84e37f59c97f03963f67e55fa64773e6fd8eec4aa57",
|
|
30
|
+
"skills/nggaigc/scripts/supported-platforms.json": "ec8b0754c489e04534a1d9880dd6664ba9c5bcd07789e06d138e0923f23575ff",
|
|
31
|
+
"skills/nggaigc/scripts/windows-credential.ps1": "ce097f2a8601664522fcfa8c9505243439ff786a45f15a1dba702b8f9b13dab1"
|
|
26
32
|
},
|
|
27
33
|
"signature": {
|
|
28
34
|
"algorithm": "ed25519",
|
|
29
35
|
"keyId": "ngg-signing-skill-release-1",
|
|
30
36
|
"scope": "artifact-bytes",
|
|
31
|
-
"value": "
|
|
37
|
+
"value": "RUaaTuzklZJdr2Mj7OAkWZ703UVkj77q7+GPjVBugivClX/86fMLf2ugqEEEjpxLxTPItqS7J1piN53VFyf0DA=="
|
|
32
38
|
}
|
|
33
39
|
}
|
|
Binary file
|
|
Binary file
|