@langgexyz/anycode 0.4.6 → 0.4.9

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