@langgexyz/anycode 0.4.6 → 0.4.10
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 +1 -1
- package/npm/README.md +6 -0
- package/npm/dist/cli.mjs +512 -74
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -75,7 +75,7 @@ anycode doctor
|
|
|
75
75
|
`https://anycode.me/releases/latest.json`;不指定版本默认安装 stable。发布包支持 macOS 和 Linux 的 `arm64`、`x64` 以及 Windows `x64`;安装器支持
|
|
76
76
|
macOS 和 Linux,Windows 用户从 `https://anycode.me/releases/v<版本>/` 手动下载。安装目录为
|
|
77
77
|
`~/.local/share/anycode`,启动器为 `~/.local/bin/anycode`。本地工程操作不要求登录;需要访问
|
|
78
|
-
AnyCode 账户的操作使用 `anycode login
|
|
78
|
+
AnyCode 账户的操作使用 `anycode login`。升级使用 `anycode update`(`anycode upgrade` 是同义别名);默认更新 stable,`--rc` 更新预览版。`anycode version` 和 `anycode --version` 显示当前版本号;Windows 暂不支持自动更新,需手动下载指定版本。
|
|
79
79
|
|
|
80
80
|
仓库内没有 workflow 推送 tag;维护者从具备仓库写权限的 Git 环境推送 tag,测试机只用于构建与测试。
|
|
81
81
|
|
package/npm/README.md
CHANGED
|
@@ -29,8 +29,14 @@ npx @langgexyz/anycode <command>
|
|
|
29
29
|
curl -fsSL https://anycode.me/install.sh | sh
|
|
30
30
|
curl -fsSL https://anycode.me/install.sh | ANYCODE_VERSION=<version> sh
|
|
31
31
|
anycode update
|
|
32
|
+
anycode upgrade
|
|
33
|
+
anycode version
|
|
34
|
+
anycode --version
|
|
32
35
|
```
|
|
33
36
|
|
|
37
|
+
`upgrade` is an alias for `update`; plain version commands print the installed
|
|
38
|
+
version number.
|
|
39
|
+
|
|
34
40
|
The release packages support macOS and Linux on `arm64` and `x64`, plus Windows
|
|
35
41
|
`x64`. The installer supports macOS and Linux; Windows users can manually
|
|
36
42
|
download the `windows-x64` package from
|
package/npm/dist/cli.mjs
CHANGED
|
@@ -1,17 +1,36 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
import { createRequire } from "node:module";
|
|
3
|
+
var __require = /* @__PURE__ */ createRequire(import.meta.url);
|
|
2
4
|
|
|
3
|
-
//
|
|
4
|
-
import { createHash as
|
|
5
|
+
// src/cli.ts
|
|
6
|
+
import { createHash as createHash5 } from "node:crypto";
|
|
5
7
|
import { mkdir, mkdtemp, readFile, rm, writeFile } from "node:fs/promises";
|
|
6
8
|
import { homedir } from "node:os";
|
|
7
|
-
import { dirname as
|
|
8
|
-
import { fileURLToPath } from "node:url";
|
|
9
|
+
import { dirname as dirname4, join as join4 } from "node:path";
|
|
9
10
|
import { spawnSync } from "node:child_process";
|
|
10
11
|
|
|
11
|
-
// runtime/
|
|
12
|
+
// ../runtime/harness-context/src/entry-module.ts
|
|
13
|
+
import { realpathSync } from "node:fs";
|
|
14
|
+
import { resolve } from "node:path";
|
|
15
|
+
import { fileURLToPath } from "node:url";
|
|
16
|
+
function isEntryModule(moduleUrl, invokedFile, isRuntimeMain = false, runtimeExecutable) {
|
|
17
|
+
if (isRuntimeMain)
|
|
18
|
+
return true;
|
|
19
|
+
if (invokedFile === undefined)
|
|
20
|
+
return false;
|
|
21
|
+
if (runtimeExecutable !== undefined && resolve(invokedFile) === resolve(runtimeExecutable))
|
|
22
|
+
return true;
|
|
23
|
+
try {
|
|
24
|
+
return realpathSync(resolve(invokedFile)) === realpathSync(resolve(fileURLToPath(moduleUrl)));
|
|
25
|
+
} catch {
|
|
26
|
+
return false;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// ../runtime/archive/src/index.ts
|
|
12
31
|
import { gunzipSync, gzipSync } from "node:zlib";
|
|
13
32
|
import { chmodSync, existsSync, lstatSync, mkdirSync, readFileSync, readdirSync, statSync, writeFileSync } from "node:fs";
|
|
14
|
-
import { dirname, join, posix, relative, resolve } from "node:path";
|
|
33
|
+
import { dirname, join, posix, relative, resolve as resolve2 } from "node:path";
|
|
15
34
|
function readTarGzip(archive) {
|
|
16
35
|
const bytes = gunzipSync(readFileSync(archive));
|
|
17
36
|
const entries = [];
|
|
@@ -92,8 +111,8 @@ function parsePax(body) {
|
|
|
92
111
|
}
|
|
93
112
|
function safeArchivePath(root, value) {
|
|
94
113
|
const normalized = normalizeArchivePath(value);
|
|
95
|
-
const path =
|
|
96
|
-
const relativePath = relative(
|
|
114
|
+
const path = resolve2(root, normalized);
|
|
115
|
+
const relativePath = relative(resolve2(root), path);
|
|
97
116
|
if (!relativePath || relativePath === ".." || relativePath.startsWith(`..${"/"}`) || relativePath.startsWith("/"))
|
|
98
117
|
throw new Error(`package contains unsafe path: ${value}`);
|
|
99
118
|
return path;
|
|
@@ -126,7 +145,7 @@ function pendingNumber(buffer, offset, length, field) {
|
|
|
126
145
|
return value;
|
|
127
146
|
}
|
|
128
147
|
|
|
129
|
-
// runtime/core/src/connector.ts
|
|
148
|
+
// ../runtime/core/src/connector.ts
|
|
130
149
|
class ConnectorRegistry {
|
|
131
150
|
connectors = new Map;
|
|
132
151
|
capabilityOwners = new Map;
|
|
@@ -270,10 +289,10 @@ function failed(request, reason, errorCode) {
|
|
|
270
289
|
}
|
|
271
290
|
};
|
|
272
291
|
}
|
|
273
|
-
// runtime/core/src/protection.ts
|
|
292
|
+
// ../runtime/core/src/protection.ts
|
|
274
293
|
var LOCAL_CAPABILITY_DOMAINS = new Set(["change", "project", "verification", "git"]);
|
|
275
294
|
var TARGETS = new Set(["workstation", "test", "beta", "prod", "external"]);
|
|
276
|
-
// runtime/core/src/index.ts
|
|
295
|
+
// ../runtime/core/src/index.ts
|
|
277
296
|
class CapabilityRegistry {
|
|
278
297
|
specs = new Map;
|
|
279
298
|
constructor(specs = []) {
|
|
@@ -318,7 +337,7 @@ function validateCapabilityRequest(request) {
|
|
|
318
337
|
}
|
|
319
338
|
}
|
|
320
339
|
|
|
321
|
-
// runtime/providers/src/installation/package-build.ts
|
|
340
|
+
// ../runtime/providers/src/installation/package-build.ts
|
|
322
341
|
var LAUNCHER = `#!/bin/sh
|
|
323
342
|
` + `script="$0"
|
|
324
343
|
` + `while [ -L "$script" ]; do
|
|
@@ -342,7 +361,7 @@ var WINDOWS_LAUNCHER = `@echo off\r
|
|
|
342
361
|
` + `)\r
|
|
343
362
|
` + `"%ANYCODE_NODE%" "%root%\\runtime\\providers\\dist\\cli.mjs" %*\r
|
|
344
363
|
`;
|
|
345
|
-
// runtime/providers/src/installation/package-installed.ts
|
|
364
|
+
// ../runtime/providers/src/installation/package-installed.ts
|
|
346
365
|
import { createHash } from "node:crypto";
|
|
347
366
|
import { existsSync as existsSync2, lstatSync as lstatSync2, readFileSync as readFileSync2, readdirSync as readdirSync2, readlinkSync } from "node:fs";
|
|
348
367
|
import { join as join2, posix as posix2, relative as relative2, sep } from "node:path";
|
|
@@ -370,7 +389,7 @@ function validateExistingInstall(root) {
|
|
|
370
389
|
try {
|
|
371
390
|
JSON.parse(readFileSync2(manifestPath, "utf8"));
|
|
372
391
|
} catch {
|
|
373
|
-
throw new Error(
|
|
392
|
+
throw new Error(`\u65e7\u7248\u6241\u5e73\u5b89\u88c5\u6e05\u5355\u89e3\u6790\u5931\u8d25\uff1a${manifestPath}`);
|
|
374
393
|
}
|
|
375
394
|
verifyInstalledPackage(root);
|
|
376
395
|
}
|
|
@@ -476,66 +495,459 @@ function isRecord(value) {
|
|
|
476
495
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
477
496
|
}
|
|
478
497
|
|
|
479
|
-
// runtime/providers/src/installation/activation.ts
|
|
480
|
-
import { copyFileSync, existsSync as existsSync3, lstatSync as lstatSync3, mkdirSync as
|
|
481
|
-
import { dirname as
|
|
498
|
+
// ../runtime/providers/src/installation/activation.ts
|
|
499
|
+
import { copyFileSync, existsSync as existsSync3, lstatSync as lstatSync3, mkdirSync as mkdirSync3, readFileSync as readFileSync4, readlinkSync as readlinkSync2, renameSync as renameSync2, rmSync, statSync as statSync2, symlinkSync, writeFileSync as writeFileSync3 } from "node:fs";
|
|
500
|
+
import { dirname as dirname3, join as join3, relative as relative3, resolve as resolve3 } from "node:path";
|
|
501
|
+
// ../runtime/providers/src/infrastructure/command-runner.ts
|
|
502
|
+
var SAFE_ENVIRONMENT_KEYS = new Set([
|
|
503
|
+
"PATH",
|
|
504
|
+
"HOME",
|
|
505
|
+
"LANG",
|
|
506
|
+
"LC_ALL",
|
|
507
|
+
"LC_CTYPE",
|
|
508
|
+
"TZ",
|
|
509
|
+
"TMPDIR",
|
|
510
|
+
"HTTP_PROXY",
|
|
511
|
+
"HTTPS_PROXY",
|
|
512
|
+
"ALL_PROXY",
|
|
513
|
+
"NO_PROXY",
|
|
514
|
+
"http_proxy",
|
|
515
|
+
"https_proxy",
|
|
516
|
+
"all_proxy",
|
|
517
|
+
"no_proxy"
|
|
518
|
+
]);
|
|
519
|
+
var PROXY_KEYS = new Set(["HTTP_PROXY", "HTTPS_PROXY", "ALL_PROXY", "http_proxy", "https_proxy", "all_proxy"]);
|
|
520
|
+
// ../runtime/credentials/src/memory.ts
|
|
521
|
+
import { createHash as createHash2 } from "node:crypto";
|
|
522
|
+
|
|
523
|
+
// ../runtime/credentials/src/validation.ts
|
|
524
|
+
function validateCredentialRef(ref) {
|
|
525
|
+
for (const [name, value] of Object.entries(ref)) {
|
|
526
|
+
if (!value.trim())
|
|
527
|
+
throw new Error(`credential ${name} must not be empty`);
|
|
528
|
+
if (!/^[A-Za-z0-9._:/-]+$/u.test(value))
|
|
529
|
+
throw new Error(`credential ${name} contains unsupported characters`);
|
|
530
|
+
}
|
|
531
|
+
}
|
|
532
|
+
function credentialKey(ref) {
|
|
533
|
+
validateCredentialRef(ref);
|
|
534
|
+
return JSON.stringify([ref.scope, ref.field]);
|
|
535
|
+
}
|
|
536
|
+
|
|
537
|
+
// ../runtime/credentials/src/secret-lease.ts
|
|
538
|
+
var leaseStates = new WeakMap;
|
|
539
|
+
function createSecretLease(ref, secret) {
|
|
540
|
+
const secretForms = [
|
|
541
|
+
secret,
|
|
542
|
+
encodeURIComponent(secret),
|
|
543
|
+
Buffer.from(secret, "utf8").toString("base64"),
|
|
544
|
+
Buffer.from(secret, "utf8").toString("base64url"),
|
|
545
|
+
Buffer.from(secret, "utf8").toString("hex")
|
|
546
|
+
].filter((form) => form.length > 0);
|
|
547
|
+
const state = { active: true, secret };
|
|
548
|
+
const lease = Object.freeze({
|
|
549
|
+
ref: Object.freeze({ ...ref }),
|
|
550
|
+
use(consumer) {
|
|
551
|
+
if (!state.active)
|
|
552
|
+
throw new Error("credential lease is no longer active");
|
|
553
|
+
let result;
|
|
554
|
+
try {
|
|
555
|
+
result = consumer(state.secret);
|
|
556
|
+
} catch (error) {
|
|
557
|
+
throw sanitizedError(error, secretForms);
|
|
558
|
+
}
|
|
559
|
+
return guardResult(result, secretForms);
|
|
560
|
+
}
|
|
561
|
+
});
|
|
562
|
+
leaseStates.set(lease, state);
|
|
563
|
+
return lease;
|
|
564
|
+
}
|
|
565
|
+
function guardResult(result, secretForms) {
|
|
566
|
+
let promiseLike;
|
|
567
|
+
try {
|
|
568
|
+
promiseLike = isPromiseLike(result);
|
|
569
|
+
} catch (error) {
|
|
570
|
+
throw sanitizedError(error, secretForms);
|
|
571
|
+
}
|
|
572
|
+
if (promiseLike) {
|
|
573
|
+
return Promise.resolve(result).then((value) => guardValue(value, secretForms), (error) => {
|
|
574
|
+
throw sanitizedError(error, secretForms);
|
|
575
|
+
});
|
|
576
|
+
}
|
|
577
|
+
return guardValue(result, secretForms);
|
|
578
|
+
}
|
|
579
|
+
function guardValue(value, secretForms) {
|
|
580
|
+
if (containsSecret(value, secretForms, new WeakSet)) {
|
|
581
|
+
throw new Error("Connector result must not contain a credential value");
|
|
582
|
+
}
|
|
583
|
+
return value;
|
|
584
|
+
}
|
|
585
|
+
function containsSecret(value, secretForms, visited) {
|
|
586
|
+
if (typeof value === "string")
|
|
587
|
+
return secretForms.some((form) => value.includes(form));
|
|
588
|
+
if (typeof value === "function")
|
|
589
|
+
return true;
|
|
590
|
+
if (value === null || typeof value !== "object")
|
|
591
|
+
return false;
|
|
592
|
+
if (visited.has(value))
|
|
593
|
+
return false;
|
|
594
|
+
visited.add(value);
|
|
595
|
+
if (value instanceof Uint8Array)
|
|
596
|
+
return secretForms.some((form) => includesBytes(value, new TextEncoder().encode(form)));
|
|
597
|
+
if (value instanceof Map)
|
|
598
|
+
return [...value].some(([key, entry]) => containsSecret(key, secretForms, visited) || containsSecret(entry, secretForms, visited));
|
|
599
|
+
if (value instanceof Set)
|
|
600
|
+
return [...value].some((entry) => containsSecret(entry, secretForms, visited));
|
|
601
|
+
try {
|
|
602
|
+
const prototype = Object.getPrototypeOf(value);
|
|
603
|
+
if (!Array.isArray(value) && prototype !== Object.prototype && prototype !== null)
|
|
604
|
+
return true;
|
|
605
|
+
if (Reflect.ownKeys(value).some((key) => typeof key === "string" ? secretForms.some((form) => key.includes(form)) : secretForms.some((form) => String(key).includes(form))))
|
|
606
|
+
return true;
|
|
607
|
+
for (const descriptor of Object.values(Object.getOwnPropertyDescriptors(value))) {
|
|
608
|
+
if (!("value" in descriptor))
|
|
609
|
+
return true;
|
|
610
|
+
if (containsSecret(descriptor.value, secretForms, visited))
|
|
611
|
+
return true;
|
|
612
|
+
}
|
|
613
|
+
} catch {
|
|
614
|
+
return true;
|
|
615
|
+
}
|
|
616
|
+
return false;
|
|
617
|
+
}
|
|
618
|
+
function includesBytes(bytes, needle) {
|
|
619
|
+
if (needle.length === 0)
|
|
620
|
+
return false;
|
|
621
|
+
outer:
|
|
622
|
+
for (let start = 0;start <= bytes.length - needle.length; start += 1) {
|
|
623
|
+
for (let offset = 0;offset < needle.length; offset += 1) {
|
|
624
|
+
if (bytes[start + offset] !== needle[offset])
|
|
625
|
+
continue outer;
|
|
626
|
+
}
|
|
627
|
+
return true;
|
|
628
|
+
}
|
|
629
|
+
return false;
|
|
630
|
+
}
|
|
631
|
+
function sanitizedError(error, secretForms) {
|
|
632
|
+
let message;
|
|
633
|
+
try {
|
|
634
|
+
message = error instanceof Error ? error.message : String(error);
|
|
635
|
+
} catch {
|
|
636
|
+
message = "Connector operation failed";
|
|
637
|
+
}
|
|
638
|
+
const sanitized = secretForms.some((form) => message.includes(form)) ? "Connector operation failed; error details contained a credential value" : message;
|
|
639
|
+
const result = new Error(sanitized);
|
|
640
|
+
if (error instanceof Error)
|
|
641
|
+
result.name = error.name;
|
|
642
|
+
return result;
|
|
643
|
+
}
|
|
644
|
+
function isPromiseLike(value) {
|
|
645
|
+
return (typeof value === "object" || typeof value === "function") && value !== null && "then" in value && typeof value.then === "function";
|
|
646
|
+
}
|
|
647
|
+
|
|
648
|
+
// ../runtime/credentials/src/memory.ts
|
|
649
|
+
class MemoryCredentialStorage {
|
|
650
|
+
id = "memory";
|
|
651
|
+
strategyId = this.id;
|
|
652
|
+
entries = new Map;
|
|
653
|
+
inspect(ref) {
|
|
654
|
+
validateCredentialRef(ref);
|
|
655
|
+
const entry = this.entries.get(credentialKey(ref));
|
|
656
|
+
return entry ? metadata(entry) : { ref, present: false };
|
|
657
|
+
}
|
|
658
|
+
list() {
|
|
659
|
+
return [...this.entries.values()].map(metadata);
|
|
660
|
+
}
|
|
661
|
+
write(ref, input) {
|
|
662
|
+
validateCredentialRef(ref);
|
|
663
|
+
if (!input.value)
|
|
664
|
+
throw new Error("credential value must not be empty");
|
|
665
|
+
const entry = { ref, value: input.value, updatedAt: new Date().toISOString() };
|
|
666
|
+
this.entries.set(credentialKey(ref), entry);
|
|
667
|
+
return metadata(entry);
|
|
668
|
+
}
|
|
669
|
+
fingerprint(ref) {
|
|
670
|
+
const entry = this.require(ref);
|
|
671
|
+
return { ...metadata(entry), fingerprint: fingerprint(entry.value) };
|
|
672
|
+
}
|
|
673
|
+
remove(ref) {
|
|
674
|
+
validateCredentialRef(ref);
|
|
675
|
+
return this.entries.delete(credentialKey(ref));
|
|
676
|
+
}
|
|
677
|
+
useSecret(ref, consumer) {
|
|
678
|
+
const entry = this.require(ref);
|
|
679
|
+
return createSecretLease(entry.ref, entry.value).use(consumer);
|
|
680
|
+
}
|
|
681
|
+
require(ref) {
|
|
682
|
+
validateCredentialRef(ref);
|
|
683
|
+
const entry = this.entries.get(credentialKey(ref));
|
|
684
|
+
if (!entry)
|
|
685
|
+
throw new Error(`credential is unavailable: ${credentialKey(ref)}`);
|
|
686
|
+
return entry;
|
|
687
|
+
}
|
|
688
|
+
}
|
|
689
|
+
function metadata(entry) {
|
|
690
|
+
return { ref: entry.ref, present: true, updatedAt: entry.updatedAt };
|
|
691
|
+
}
|
|
692
|
+
function fingerprint(value) {
|
|
693
|
+
return `sha256:${createHash2("sha256").update(value).digest("hex")}`;
|
|
694
|
+
}
|
|
695
|
+
// ../runtime/credentials/src/encrypted-file.ts
|
|
696
|
+
import { createCipheriv, createDecipheriv, createHash as createHash3, randomBytes } from "node:crypto";
|
|
697
|
+
import { chmodSync as chmodSync2, mkdirSync as mkdirSync2, readFileSync as readFileSync3, renameSync, writeFileSync as writeFileSync2 } from "node:fs";
|
|
698
|
+
import { dirname as dirname2 } from "node:path";
|
|
699
|
+
class EncryptedFileCredentialStorage {
|
|
700
|
+
filePath;
|
|
701
|
+
keyProvider;
|
|
702
|
+
id = "encrypted-file";
|
|
703
|
+
strategyId = this.id;
|
|
704
|
+
constructor(filePath, keyProvider) {
|
|
705
|
+
this.filePath = filePath;
|
|
706
|
+
this.keyProvider = keyProvider;
|
|
707
|
+
}
|
|
708
|
+
inspect(ref) {
|
|
709
|
+
const entry = this.entries().get(credentialKey(ref));
|
|
710
|
+
return entry ? metadata2(entry) : { ref, present: false };
|
|
711
|
+
}
|
|
712
|
+
list() {
|
|
713
|
+
return [...this.entries().values()].map(metadata2);
|
|
714
|
+
}
|
|
715
|
+
write(ref, input) {
|
|
716
|
+
validateCredentialRef(ref);
|
|
717
|
+
if (!input.value)
|
|
718
|
+
throw new Error("credential value must not be empty");
|
|
719
|
+
const entries = this.entries();
|
|
720
|
+
const entry = { ref, value: input.value, updatedAt: new Date().toISOString() };
|
|
721
|
+
entries.set(credentialKey(ref), entry);
|
|
722
|
+
this.save(entries);
|
|
723
|
+
return metadata2(entry);
|
|
724
|
+
}
|
|
725
|
+
fingerprint(ref) {
|
|
726
|
+
const entry = this.require(ref);
|
|
727
|
+
return { ...metadata2(entry), fingerprint: fingerprint2(entry.value) };
|
|
728
|
+
}
|
|
729
|
+
remove(ref) {
|
|
730
|
+
const entries = this.entries();
|
|
731
|
+
const removed = entries.delete(credentialKey(ref));
|
|
732
|
+
if (removed)
|
|
733
|
+
this.save(entries);
|
|
734
|
+
return removed;
|
|
735
|
+
}
|
|
736
|
+
useSecret(ref, consumer) {
|
|
737
|
+
const entry = this.require(ref);
|
|
738
|
+
return createSecretLease(entry.ref, entry.value).use(consumer);
|
|
739
|
+
}
|
|
740
|
+
require(ref) {
|
|
741
|
+
const entry = this.entries().get(credentialKey(ref));
|
|
742
|
+
if (!entry)
|
|
743
|
+
throw new Error(`credential is unavailable: ${credentialKey(ref)}`);
|
|
744
|
+
return entry;
|
|
745
|
+
}
|
|
746
|
+
entries() {
|
|
747
|
+
try {
|
|
748
|
+
const envelope = JSON.parse(readFileSync3(this.filePath, "utf8"));
|
|
749
|
+
return decode(envelope, this.keyProvider.key());
|
|
750
|
+
} catch (error) {
|
|
751
|
+
if (isMissingFile(error))
|
|
752
|
+
return new Map;
|
|
753
|
+
throw new Error(`credential store cannot be opened: ${error instanceof Error ? error.message : String(error)}`);
|
|
754
|
+
}
|
|
755
|
+
}
|
|
756
|
+
save(entries) {
|
|
757
|
+
const directory = dirname2(this.filePath);
|
|
758
|
+
mkdirSync2(directory, { recursive: true, mode: 448 });
|
|
759
|
+
const temporary = `${this.filePath}.${process.pid}.${randomBytes(6).toString("hex")}.tmp`;
|
|
760
|
+
writeFileSync2(temporary, JSON.stringify(encode(entries, this.keyProvider.key())) + `
|
|
761
|
+
`, { mode: 384 });
|
|
762
|
+
chmodSync2(temporary, 384);
|
|
763
|
+
renameSync(temporary, this.filePath);
|
|
764
|
+
chmodSync2(this.filePath, 384);
|
|
765
|
+
}
|
|
766
|
+
}
|
|
767
|
+
function encode(entries, key) {
|
|
768
|
+
const iv = randomBytes(12);
|
|
769
|
+
const cipher = createCipheriv("aes-256-gcm", key, iv);
|
|
770
|
+
const plaintext = JSON.stringify([...entries.values()]);
|
|
771
|
+
const ciphertext = Buffer.concat([cipher.update(plaintext, "utf8"), cipher.final()]);
|
|
772
|
+
return { version: 1, iv: iv.toString("base64url"), tag: cipher.getAuthTag().toString("base64url"), ciphertext: ciphertext.toString("base64url") };
|
|
773
|
+
}
|
|
774
|
+
function decode(envelope, key) {
|
|
775
|
+
if (envelope.version !== 1)
|
|
776
|
+
throw new Error("unsupported credential store version");
|
|
777
|
+
const decipher = createDecipheriv("aes-256-gcm", key, Buffer.from(envelope.iv, "base64url"));
|
|
778
|
+
decipher.setAuthTag(Buffer.from(envelope.tag, "base64url"));
|
|
779
|
+
const plaintext = Buffer.concat([decipher.update(Buffer.from(envelope.ciphertext, "base64url")), decipher.final()]).toString("utf8");
|
|
780
|
+
const values = JSON.parse(plaintext);
|
|
781
|
+
const entries = new Map;
|
|
782
|
+
for (const entry of values) {
|
|
783
|
+
validateCredentialRef(entry.ref);
|
|
784
|
+
entries.set(credentialKey(entry.ref), entry);
|
|
785
|
+
}
|
|
786
|
+
return entries;
|
|
787
|
+
}
|
|
788
|
+
function metadata2(entry) {
|
|
789
|
+
return { ref: entry.ref, present: true, updatedAt: entry.updatedAt };
|
|
790
|
+
}
|
|
791
|
+
function fingerprint2(value) {
|
|
792
|
+
return `sha256:${createHash3("sha256").update(value).digest("hex")}`;
|
|
793
|
+
}
|
|
794
|
+
function isMissingFile(error) {
|
|
795
|
+
return typeof error === "object" && error !== null && "code" in error && error.code === "ENOENT";
|
|
796
|
+
}
|
|
797
|
+
// ../runtime/credentials/src/registry.ts
|
|
798
|
+
class CredentialStorageRegistry {
|
|
799
|
+
strategies = new Map;
|
|
800
|
+
constructor(strategies = []) {
|
|
801
|
+
for (const strategy of strategies)
|
|
802
|
+
this.register(strategy);
|
|
803
|
+
}
|
|
804
|
+
register(strategy) {
|
|
805
|
+
if (this.strategies.has(strategy.id))
|
|
806
|
+
throw new Error(`duplicate credential storage strategy: ${strategy.id}`);
|
|
807
|
+
this.strategies.set(strategy.id, strategy);
|
|
808
|
+
}
|
|
809
|
+
resolve(policy) {
|
|
810
|
+
const id = policy.kind === "external" ? policy.provider : policy.kind;
|
|
811
|
+
if (!id)
|
|
812
|
+
throw new Error("external credential storage requires a provider");
|
|
813
|
+
const strategy = this.strategies.get(id);
|
|
814
|
+
if (!strategy)
|
|
815
|
+
throw new Error(`credential storage strategy is unavailable: ${id}`);
|
|
816
|
+
return strategy;
|
|
817
|
+
}
|
|
818
|
+
}
|
|
819
|
+
// ../runtime/providers/src/infrastructure/authenticated-transport.ts
|
|
820
|
+
var MAX_REQUEST_BYTES = 1024 * 1024;
|
|
821
|
+
var MAX_RESPONSE_BYTES = 4 * 1024 * 1024;
|
|
822
|
+
var REQUEST_HEADERS = new Set(["accept", "content-type", "user-agent"]);
|
|
823
|
+
// ../runtime/providers/src/infrastructure/sensitive-key.ts
|
|
824
|
+
var SECRET_NOUNS = ["authorization", "credentials", "credential", "password", "passwd", "secret", "token"];
|
|
825
|
+
var KEY_QUALIFIERS = ["access", "api", "private", "secret"];
|
|
826
|
+
var nounPattern = SECRET_NOUNS.join("|");
|
|
827
|
+
var qualifierPattern = `(?:${KEY_QUALIFIERS.join("|")})[_-]?key`;
|
|
828
|
+
var SENSITIVE_KEY_PATTERN = `[\\p{L}\\p{N}_-]*(?:${nounPattern}|${qualifierPattern})(?![\\p{L}\\p{N}_])`;
|
|
829
|
+
|
|
830
|
+
// ../runtime/providers/src/infrastructure/redaction-rules.ts
|
|
831
|
+
var REDACTION_RULES = [
|
|
832
|
+
{
|
|
833
|
+
id: "private-key",
|
|
834
|
+
pattern: /-----BEGIN [^-]*PRIVATE KEY-----[\s\S]*?-----END [^-]*PRIVATE KEY-----/gu,
|
|
835
|
+
replacement: "[REDACTED:private-key]"
|
|
836
|
+
},
|
|
837
|
+
{
|
|
838
|
+
id: "bearer",
|
|
839
|
+
pattern: /\bBearer\s+(?!\[REDACTED:)[^\s,;}\]]+/giu,
|
|
840
|
+
replacement: "Bearer [REDACTED:bearer]"
|
|
841
|
+
},
|
|
842
|
+
{
|
|
843
|
+
id: "authorization",
|
|
844
|
+
pattern: /(?<authorizationQuote>["']?)(?<authorizationKey>authorization)\k<authorizationQuote>(?<authorizationSeparator>\s*[:=]\s*)(?!\s*\[REDACTED:)(?:(?<authorizationValueQuote>["'])(?:[\s\S]*?)\k<authorizationValueQuote>|[^\r\n"']+)/giu,
|
|
845
|
+
replacement: "$<authorizationQuote>$<authorizationKey>$<authorizationQuote>$<authorizationSeparator>$<authorizationValueQuote>[REDACTED:authorization]$<authorizationValueQuote>"
|
|
846
|
+
},
|
|
847
|
+
{
|
|
848
|
+
id: "assignment",
|
|
849
|
+
pattern: new RegExp(`(?<assignmentQuote>["']?)(?<assignmentKey>${SENSITIVE_KEY_PATTERN})\\k<assignmentQuote>(?<assignmentSeparator>\\s*[:=]\\s*)(?!\\s*\\[REDACTED:)(?:(?<assignmentValueQuote>["'])(?:[\\s\\S]*?)\\k<assignmentValueQuote>|[^\\s,;}\\]"']+)`, "giu"),
|
|
850
|
+
replacement: "$<assignmentQuote>$<assignmentKey>$<assignmentQuote>$<assignmentSeparator>$<assignmentValueQuote>[REDACTED:assignment]$<assignmentValueQuote>"
|
|
851
|
+
},
|
|
852
|
+
{
|
|
853
|
+
id: "url-userinfo",
|
|
854
|
+
pattern: /(?<urlScheme>\b[a-z][a-z0-9+.-]*:\/\/[^\s:@\/?#]*:)(?!\[REDACTED:)[^\s@\/?#]+(?=@)/giu,
|
|
855
|
+
replacement: "$<urlScheme>[REDACTED:url-password]"
|
|
856
|
+
}
|
|
857
|
+
];
|
|
858
|
+
|
|
859
|
+
// ../runtime/providers/src/infrastructure/redaction.ts
|
|
860
|
+
var COMBINED_RULES = new RegExp(REDACTION_RULES.map((rule, index) => `(?<r${index}>${rule.pattern.source})`).join("|"), "giu");
|
|
861
|
+
// ../runtime/providers/src/infrastructure/transaction.ts
|
|
862
|
+
function rethrowAfterUndo(original, steps) {
|
|
863
|
+
const failures = [];
|
|
864
|
+
for (const undo of steps)
|
|
865
|
+
try {
|
|
866
|
+
undo();
|
|
867
|
+
} catch (error) {
|
|
868
|
+
failures.push(error);
|
|
869
|
+
}
|
|
870
|
+
if (failures.length === 0)
|
|
871
|
+
throw original;
|
|
872
|
+
throw new AggregateError([original, ...failures], `${original instanceof Error ? original.message : String(original)}; rollback had ${failures.length} failure(s)`, { cause: original });
|
|
873
|
+
}
|
|
874
|
+
// ../runtime/providers/src/installation/activation.ts
|
|
482
875
|
function activatePackage(stagedPackage, installRoot, launcherPath, options = {}) {
|
|
483
876
|
const platform = options.platform ?? process.platform;
|
|
484
877
|
const executable = options.executable ?? (platform === "win32" ? "anycode.exe" : "anycode");
|
|
485
|
-
|
|
486
|
-
const releaseLock = acquireActivationLock(installRoot);
|
|
878
|
+
mkdirSync3(dirname3(installRoot), { recursive: true });
|
|
879
|
+
const releaseLock = acquireActivationLock(installRoot, platform);
|
|
487
880
|
const previous = `${installRoot}.previous`;
|
|
488
881
|
let movedCurrent = false;
|
|
489
882
|
let installedNew = false;
|
|
490
883
|
try {
|
|
491
|
-
|
|
884
|
+
reconcileActivation(installRoot, previous, launcherPath, executable, platform);
|
|
492
885
|
const manifest = verifyInstalledPackage(stagedPackage);
|
|
493
886
|
validateExistingInstall(installRoot);
|
|
494
887
|
validateLauncherOwnership(launcherPath, installRoot, stagedPackage, executable, platform);
|
|
495
888
|
if (existsSync3(installRoot)) {
|
|
496
889
|
rmSync(previous, { recursive: true, force: true });
|
|
497
|
-
|
|
890
|
+
renameSync2(installRoot, previous);
|
|
498
891
|
movedCurrent = true;
|
|
499
892
|
}
|
|
500
|
-
|
|
893
|
+
renameSync2(stagedPackage, installRoot);
|
|
501
894
|
installedNew = true;
|
|
502
895
|
const installed = verifyInstalledPackage(installRoot);
|
|
503
896
|
if (installed.version !== manifest.version || installed.payload_digest !== manifest.payload_digest)
|
|
504
|
-
throw new Error("
|
|
897
|
+
throw new Error("\u5b89\u88c5\u540e\u7684 AnyCode \u5305\u6821\u9a8c\u5931\u8d25");
|
|
505
898
|
linkLauncher(join3(installRoot, "bin", executable), launcherPath, platform);
|
|
899
|
+
try {
|
|
900
|
+
removeActivationPath(previous);
|
|
901
|
+
} catch {}
|
|
506
902
|
return installRoot;
|
|
507
903
|
} catch (error) {
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
904
|
+
rethrowAfterUndo(error, [
|
|
905
|
+
() => {
|
|
906
|
+
if (installedNew && existsSync3(installRoot))
|
|
907
|
+
rmSync(installRoot, { recursive: true, force: true });
|
|
908
|
+
},
|
|
909
|
+
() => {
|
|
910
|
+
if (movedCurrent && existsSync3(previous) && !existsSync3(installRoot))
|
|
911
|
+
renameSync2(previous, installRoot);
|
|
912
|
+
}
|
|
913
|
+
]);
|
|
514
914
|
} finally {
|
|
515
915
|
releaseLock();
|
|
516
916
|
}
|
|
517
917
|
}
|
|
518
|
-
function acquireActivationLock(installRoot) {
|
|
918
|
+
function acquireActivationLock(installRoot, platform) {
|
|
519
919
|
const lock = `${installRoot}.activation-lock`;
|
|
520
920
|
const deadline = Date.now() + 30000;
|
|
521
921
|
const token = `${process.pid}:${Date.now()}:${Math.random().toString(16).slice(2)}`;
|
|
522
922
|
while (true) {
|
|
523
923
|
try {
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
return () => {
|
|
924
|
+
if (platform === "win32") {
|
|
925
|
+
mkdirSync3(lock);
|
|
527
926
|
try {
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
927
|
+
writeFileSync3(join3(lock, "owner"), token, { flag: "wx", mode: 384 });
|
|
928
|
+
} catch (error) {
|
|
929
|
+
rethrowAfterUndo(error, [() => rmSync(lock, { recursive: true, force: true })]);
|
|
930
|
+
}
|
|
931
|
+
} else {
|
|
932
|
+
symlinkSync(token, lock);
|
|
933
|
+
}
|
|
934
|
+
return () => {
|
|
935
|
+
for (let attempt = 0;attempt < 2; attempt += 1) {
|
|
936
|
+
try {
|
|
937
|
+
const owner = platform === "win32" ? readFileSync4(join3(lock, "owner"), "utf8") : readlinkSync2(lock);
|
|
938
|
+
if (owner === token)
|
|
939
|
+
rmSync(lock, { recursive: true, force: true });
|
|
940
|
+
return;
|
|
941
|
+
} catch {}
|
|
942
|
+
}
|
|
531
943
|
};
|
|
532
944
|
} catch (error) {
|
|
533
945
|
if (error.code !== "EEXIST")
|
|
534
946
|
throw error;
|
|
535
|
-
const ownerPath = join3(lock, "owner");
|
|
536
947
|
let stale = false;
|
|
537
948
|
try {
|
|
538
|
-
const
|
|
949
|
+
const metadata3 = lstatSync3(lock);
|
|
950
|
+
const owner = metadata3.isSymbolicLink() ? readlinkSync2(lock) : readFileSync4(join3(lock, "owner"), "utf8");
|
|
539
951
|
const pid = Number(owner.split(":", 1)[0]);
|
|
540
952
|
if (Number.isSafeInteger(pid) && pid > 0) {
|
|
541
953
|
try {
|
|
@@ -561,13 +973,37 @@ function acquireActivationLock(installRoot) {
|
|
|
561
973
|
}
|
|
562
974
|
}
|
|
563
975
|
}
|
|
564
|
-
function
|
|
565
|
-
|
|
976
|
+
function removeActivationPath(path) {
|
|
977
|
+
try {
|
|
978
|
+
rmSync(path, { recursive: true, force: true });
|
|
979
|
+
} catch (first) {
|
|
980
|
+
try {
|
|
981
|
+
rmSync(path, { recursive: true, force: true });
|
|
982
|
+
} catch (second) {
|
|
983
|
+
throw new AggregateError([first, second], `could not remove activation recovery path: ${path}`, { cause: first });
|
|
984
|
+
}
|
|
985
|
+
}
|
|
986
|
+
}
|
|
987
|
+
function reconcileActivation(installRoot, previous, launcherPath, executable, platform) {
|
|
988
|
+
if (!existsSync3(installRoot)) {
|
|
989
|
+
if (!existsSync3(previous))
|
|
990
|
+
return;
|
|
991
|
+
validateExistingInstall(previous);
|
|
992
|
+
renameSync2(previous, installRoot);
|
|
566
993
|
return;
|
|
994
|
+
}
|
|
567
995
|
if (!existsSync3(previous))
|
|
568
996
|
return;
|
|
569
|
-
|
|
570
|
-
|
|
997
|
+
try {
|
|
998
|
+
verifyInstalledPackage(installRoot);
|
|
999
|
+
} catch {
|
|
1000
|
+
return;
|
|
1001
|
+
}
|
|
1002
|
+
validateLauncherOwnership(launcherPath, installRoot, installRoot, executable, platform);
|
|
1003
|
+
linkLauncher(join3(installRoot, "bin", executable), launcherPath, platform);
|
|
1004
|
+
try {
|
|
1005
|
+
rmSync(previous, { recursive: true, force: true });
|
|
1006
|
+
} catch {}
|
|
571
1007
|
}
|
|
572
1008
|
function validateLauncherOwnership(launcher, root, staged, executable, platform) {
|
|
573
1009
|
let existing;
|
|
@@ -579,52 +1015,54 @@ function validateLauncherOwnership(launcher, root, staged, executable, platform)
|
|
|
579
1015
|
throw error;
|
|
580
1016
|
}
|
|
581
1017
|
if (existing.isSymbolicLink()) {
|
|
582
|
-
const target =
|
|
583
|
-
const path = relative3(
|
|
584
|
-
if (path === `bin/${executable}`)
|
|
1018
|
+
const target = resolve3(dirname3(launcher), readlinkSync2(launcher));
|
|
1019
|
+
const path = relative3(resolve3(root), target).replaceAll("\\", "/");
|
|
1020
|
+
if (path === `bin/${executable}` || !path.startsWith("../") && path !== ".." && path.endsWith(`/bin/${executable}`))
|
|
585
1021
|
return;
|
|
586
|
-
try {
|
|
587
|
-
validateExistingInstall(root);
|
|
588
|
-
if (path === `current/bin/${executable}` && realpathSync(target) === realpathSync(join3(root, "current", "bin", executable)))
|
|
589
|
-
return;
|
|
590
|
-
} catch {}
|
|
591
1022
|
} else if (platform === "win32" && existing.isFile()) {
|
|
592
|
-
const bytes =
|
|
1023
|
+
const bytes = readFileSync4(launcher);
|
|
593
1024
|
for (const candidate of [join3(staged, "bin", executable), join3(root, "bin", executable)]) {
|
|
594
|
-
if (existsSync3(candidate) && bytes.equals(
|
|
1025
|
+
if (existsSync3(candidate) && bytes.equals(readFileSync4(candidate)))
|
|
595
1026
|
return;
|
|
596
1027
|
}
|
|
597
1028
|
}
|
|
598
1029
|
throw new Error(`refusing to replace an unmanaged anycode launcher: ${launcher}`);
|
|
599
1030
|
}
|
|
600
1031
|
function linkLauncher(source, launcherPath, platform) {
|
|
601
|
-
|
|
602
|
-
const next = `${launcherPath}
|
|
1032
|
+
mkdirSync3(dirname3(launcherPath), { recursive: true });
|
|
1033
|
+
const next = `${launcherPath}.next`;
|
|
603
1034
|
rmSync(next, { force: true });
|
|
604
1035
|
if (platform === "win32")
|
|
605
1036
|
copyFileSync(source, next);
|
|
606
1037
|
else
|
|
607
1038
|
symlinkSync(source, next);
|
|
608
|
-
|
|
1039
|
+
try {
|
|
1040
|
+
renameSync2(next, launcherPath);
|
|
1041
|
+
} catch (error) {
|
|
1042
|
+
try {
|
|
1043
|
+
rmSync(next, { force: true });
|
|
1044
|
+
} catch {}
|
|
1045
|
+
throw error;
|
|
1046
|
+
}
|
|
609
1047
|
}
|
|
610
|
-
// runtime/providers/src/installation/release-trust.ts
|
|
1048
|
+
// ../runtime/providers/src/installation/release-trust.ts
|
|
611
1049
|
import { verify } from "node:crypto";
|
|
612
1050
|
import { basename } from "node:path";
|
|
613
1051
|
|
|
614
|
-
// runtime/providers/src/installation/release-key.generated.ts
|
|
1052
|
+
// ../runtime/providers/src/installation/release-key.generated.ts
|
|
615
1053
|
var RELEASE_PUBLIC_KEY_PEM = `-----BEGIN PUBLIC KEY-----
|
|
616
1054
|
MCowBQYDK2VwAyEA/hfqP5bUwAMqzY3QS+j9GIGjbYpyrtcheixQGJt93zo=
|
|
617
1055
|
-----END PUBLIC KEY-----
|
|
618
1056
|
`;
|
|
619
1057
|
|
|
620
|
-
// runtime/providers/src/installation/release-trust.ts
|
|
1058
|
+
// ../runtime/providers/src/installation/release-trust.ts
|
|
621
1059
|
function verifyReleaseChecksums(sums, encodedSignature, publicKey = RELEASE_PUBLIC_KEY_PEM) {
|
|
622
1060
|
const encoded = encodedSignature.trim();
|
|
623
1061
|
const signature = Buffer.from(encoded, "base64");
|
|
624
1062
|
if (signature.toString("base64") !== encoded || signature.byteLength !== 64)
|
|
625
|
-
throw new Error("AnyCode SHA256SUMS
|
|
1063
|
+
throw new Error("AnyCode SHA256SUMS \u7b7e\u540d\u683c\u5f0f\u65e0\u6548");
|
|
626
1064
|
if (!verify(null, sums, publicKey, signature))
|
|
627
|
-
throw new Error("AnyCode SHA256SUMS Ed25519
|
|
1065
|
+
throw new Error("AnyCode SHA256SUMS Ed25519 \u7b7e\u540d\u9a8c\u8bc1\u5931\u8d25");
|
|
628
1066
|
return parseReleaseChecksums(Buffer.from(sums).toString("utf8"));
|
|
629
1067
|
}
|
|
630
1068
|
function parseReleaseChecksums(value) {
|
|
@@ -634,16 +1072,16 @@ function parseReleaseChecksums(value) {
|
|
|
634
1072
|
continue;
|
|
635
1073
|
const match = /^([a-f0-9]{64})\s+[* ]?([^\s]+)$/u.exec(line.trim());
|
|
636
1074
|
if (!match || basename(match[2]) !== match[2] || result.has(match[2]))
|
|
637
|
-
throw new Error("
|
|
1075
|
+
throw new Error("\u5df2\u7b7e\u540d SHA256SUMS \u683c\u5f0f\u65e0\u6548");
|
|
638
1076
|
result.set(match[2], match[1]);
|
|
639
1077
|
}
|
|
640
1078
|
if (!result.size)
|
|
641
|
-
throw new Error("
|
|
1079
|
+
throw new Error("\u5df2\u7b7e\u540d SHA256SUMS \u4e0d\u80fd\u4e3a\u7a7a");
|
|
642
1080
|
return result;
|
|
643
1081
|
}
|
|
644
1082
|
|
|
645
|
-
// runtime/providers/src/installation/update.ts
|
|
646
|
-
import { createHash as
|
|
1083
|
+
// ../runtime/providers/src/installation/update.ts
|
|
1084
|
+
import { createHash as createHash4, createPublicKey } from "node:crypto";
|
|
647
1085
|
var PLATFORM = new Map([
|
|
648
1086
|
["darwin-arm64", "darwin-arm64"],
|
|
649
1087
|
["darwin-x64", "darwin-x64"],
|
|
@@ -652,8 +1090,8 @@ var PLATFORM = new Map([
|
|
|
652
1090
|
["win32-arm64", "windows-arm64"],
|
|
653
1091
|
["win32-x64", "windows-x64"]
|
|
654
1092
|
]);
|
|
655
|
-
var RELEASE_PUBLIC_KEY_DER_SHA256 =
|
|
656
|
-
//
|
|
1093
|
+
var RELEASE_PUBLIC_KEY_DER_SHA256 = createHash4("sha256").update(createPublicKey(RELEASE_PUBLIC_KEY_PEM).export({ type: "spki", format: "der" })).digest("hex");
|
|
1094
|
+
// src/cli.ts
|
|
657
1095
|
var HARNESS_IDS = ["opencode-v1", "opencode-v2", "claude", "pi"];
|
|
658
1096
|
var HARNESS_ENTRYPOINTS = {
|
|
659
1097
|
"opencode-v1": "bin/harness/opencode-1.x.js",
|
|
@@ -670,8 +1108,8 @@ function parsePackageMetadata(value) {
|
|
|
670
1108
|
}
|
|
671
1109
|
return { version: value["version"] };
|
|
672
1110
|
}
|
|
673
|
-
var
|
|
674
|
-
var PACKAGE_VERSION =
|
|
1111
|
+
var metadata3 = parsePackageMetadata(JSON.parse(await readFile(new URL("../../package.json", import.meta.url), "utf8")));
|
|
1112
|
+
var PACKAGE_VERSION = metadata3.version;
|
|
675
1113
|
var RELEASE_BASE_URL = (process.env["ANYCODE_RELEASE_BASE_URL"] ?? "https://anycode.me").replace(/\/$/u, "");
|
|
676
1114
|
var homeDirectory = homedir();
|
|
677
1115
|
var INSTALL_ROOT = join4(process.env["ANYCODE_INSTALL_ROOT"] ?? join4(homeDirectory, ".local", "share", "anycode"));
|
|
@@ -721,7 +1159,7 @@ function ensureNodeVersion() {
|
|
|
721
1159
|
}
|
|
722
1160
|
async function verifyArtifact(artifact, checksumFile) {
|
|
723
1161
|
const expected = (await readFile(checksumFile, "utf8")).trim().split(/\s+/).at(-1);
|
|
724
|
-
const actual =
|
|
1162
|
+
const actual = createHash5("sha256").update(await readFile(artifact)).digest("hex");
|
|
725
1163
|
const normalized = expected?.replace(/^sha256:/, "");
|
|
726
1164
|
if (!normalized || normalized !== actual) {
|
|
727
1165
|
throw new Error("release artifact sha256 does not match its checksum");
|
|
@@ -751,7 +1189,7 @@ async function verifySignedRelease(version, target, artifact, options = {}) {
|
|
|
751
1189
|
const signedHash = verifyReleaseChecksums(Buffer.from(sums), await signatureResponse.text(), options.publicKeyPem ?? RELEASE_PUBLIC_KEY_PEM).get(name);
|
|
752
1190
|
if (signedHash !== file.sha256)
|
|
753
1191
|
throw new Error("AnyCode manifest does not match signed SHA256SUMS");
|
|
754
|
-
const actual =
|
|
1192
|
+
const actual = createHash5("sha256").update(await readFile(artifact)).digest("hex");
|
|
755
1193
|
if (actual !== signedHash)
|
|
756
1194
|
throw new Error("AnyCode release artifact does not match signed SHA256SUMS");
|
|
757
1195
|
}
|
|
@@ -786,8 +1224,8 @@ async function install(version, harness, options = {}) {
|
|
|
786
1224
|
throw new Error("AnyCode release base URL must use HTTPS");
|
|
787
1225
|
const fetcher = options.fetcher ?? fetch;
|
|
788
1226
|
const requestOptions = { redirect: "follow", signal: AbortSignal.timeout(DOWNLOAD_TIMEOUT_MS) };
|
|
789
|
-
await mkdir(
|
|
790
|
-
const temporary = await mkdtemp(join4(
|
|
1227
|
+
await mkdir(dirname4(installRoot), { recursive: true });
|
|
1228
|
+
const temporary = await mkdtemp(join4(dirname4(installRoot), ".anycode-npm-"));
|
|
791
1229
|
const artifact = join4(temporary, `anycode-${version}-${target.os}-${target.arch}.tar.gz`);
|
|
792
1230
|
const checksum = `${artifact}.sha256`;
|
|
793
1231
|
const source = join4(temporary, "source");
|
|
@@ -885,7 +1323,7 @@ async function main(args) {
|
|
|
885
1323
|
}
|
|
886
1324
|
if (args.includes("--version") && args.length === 1) {
|
|
887
1325
|
const native = newerNativeExecutable();
|
|
888
|
-
console.log(native ?
|
|
1326
|
+
console.log(native ? native.version : PACKAGE_VERSION);
|
|
889
1327
|
return 0;
|
|
890
1328
|
}
|
|
891
1329
|
if (args[0] === "install") {
|
|
@@ -900,7 +1338,7 @@ async function main(args) {
|
|
|
900
1338
|
}
|
|
901
1339
|
return result.status ?? 1;
|
|
902
1340
|
}
|
|
903
|
-
if (process.argv[1] &&
|
|
1341
|
+
if (isEntryModule(import.meta.url, process.argv[1], process.versions["bun"] !== undefined && __require.main == __require.module === true)) {
|
|
904
1342
|
main(process.argv.slice(2)).then((code) => {
|
|
905
1343
|
process.exitCode = code;
|
|
906
1344
|
}).catch((error) => {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@langgexyz/anycode",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.10",
|
|
4
4
|
"description": "AnyCode distribution bootstrap for the native runtime",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
"typescript": "7.0.2"
|
|
24
24
|
},
|
|
25
25
|
"scripts": {
|
|
26
|
-
"build": "bun scripts/generate-release-key.ts --check && bun
|
|
26
|
+
"build": "bun scripts/generate-release-key.ts --check && bun scripts/provider-bundle.ts --bundle npm --outfile npm/dist/cli.mjs",
|
|
27
27
|
"build:binary": "bun scripts/build-binary.ts",
|
|
28
28
|
"build:binary-package": "bun scripts/build-binary-package.ts",
|
|
29
29
|
"build:git-gate": "bun build scripts/git-gate.ts --outfile scripts/git-gate.mjs --target node",
|