@seqyuan/annodex 0.1.53 → 0.1.55

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 (71) hide show
  1. package/.next/BUILD_ID +1 -1
  2. package/.next/app-path-routes-manifest.json +11 -11
  3. package/.next/build-manifest.json +2 -2
  4. package/.next/prerender-manifest.json +3 -3
  5. package/.next/required-server-files.js +3 -1
  6. package/.next/required-server-files.json +3 -1
  7. package/.next/server/app/_global-error.html +1 -1
  8. package/.next/server/app/_global-error.rsc +1 -1
  9. package/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  10. package/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  11. package/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  12. package/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  13. package/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  14. package/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  15. package/.next/server/app/_not-found.html +1 -1
  16. package/.next/server/app/_not-found.rsc +1 -1
  17. package/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
  18. package/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  19. package/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
  20. package/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  21. package/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  22. package/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  23. package/.next/server/app/api/internal/runtime/route.js +1 -1
  24. package/.next/server/app/api/version/route.js +1 -1
  25. package/.next/server/app/docs/changelog.html +2 -2
  26. package/.next/server/app/docs/changelog.rsc +1 -1
  27. package/.next/server/app/docs/changelog.segments/_full.segment.rsc +1 -1
  28. package/.next/server/app/docs/changelog.segments/_head.segment.rsc +1 -1
  29. package/.next/server/app/docs/changelog.segments/_index.segment.rsc +1 -1
  30. package/.next/server/app/docs/changelog.segments/_tree.segment.rsc +1 -1
  31. package/.next/server/app/docs/changelog.segments/docs/changelog/__PAGE__.segment.rsc +1 -1
  32. package/.next/server/app/docs/changelog.segments/docs/changelog.segment.rsc +1 -1
  33. package/.next/server/app/docs/changelog.segments/docs.segment.rsc +1 -1
  34. package/.next/server/app/index.html +1 -1
  35. package/.next/server/app/index.rsc +1 -1
  36. package/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
  37. package/.next/server/app/index.segments/_full.segment.rsc +1 -1
  38. package/.next/server/app/index.segments/_head.segment.rsc +1 -1
  39. package/.next/server/app/index.segments/_index.segment.rsc +1 -1
  40. package/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  41. package/.next/server/app/login.html +1 -1
  42. package/.next/server/app/login.rsc +1 -1
  43. package/.next/server/app/login.segments/_full.segment.rsc +1 -1
  44. package/.next/server/app/login.segments/_head.segment.rsc +1 -1
  45. package/.next/server/app/login.segments/_index.segment.rsc +1 -1
  46. package/.next/server/app/login.segments/_tree.segment.rsc +1 -1
  47. package/.next/server/app/login.segments/login/__PAGE__.segment.rsc +1 -1
  48. package/.next/server/app/login.segments/login.segment.rsc +1 -1
  49. package/.next/server/app/workspace/page.js +3 -3
  50. package/.next/server/app/workspace/page_client-reference-manifest.js +1 -1
  51. package/.next/server/app/workspace.html +1 -1
  52. package/.next/server/app/workspace.rsc +2 -2
  53. package/.next/server/app/workspace.segments/_full.segment.rsc +2 -2
  54. package/.next/server/app/workspace.segments/_head.segment.rsc +1 -1
  55. package/.next/server/app/workspace.segments/_index.segment.rsc +1 -1
  56. package/.next/server/app/workspace.segments/_tree.segment.rsc +1 -1
  57. package/.next/server/app/workspace.segments/workspace/__PAGE__.segment.rsc +2 -2
  58. package/.next/server/app/workspace.segments/workspace.segment.rsc +1 -1
  59. package/.next/server/app-paths-manifest.json +11 -11
  60. package/.next/server/chunks/6983.js +12 -5
  61. package/.next/server/middleware-build-manifest.js +1 -1
  62. package/.next/server/pages/404.html +1 -1
  63. package/.next/server/pages/500.html +1 -1
  64. package/.next/server/server-reference-manifest.json +1 -1
  65. package/.next/static/chunks/app/workspace/{page-d1366e4f9b7a7a15.js → page-249489e08420f59d.js} +3 -3
  66. package/bin/annodex.js +299 -0
  67. package/lib/macos-codex-security.js +376 -0
  68. package/next.config.ts +1 -1
  69. package/package.json +2 -1
  70. /package/.next/static/{ZR0UxSLWFSPEwsYD3WfeI → vW2g3YlVaZErFy9-fsfCO}/_buildManifest.js +0 -0
  71. /package/.next/static/{ZR0UxSLWFSPEwsYD3WfeI → vW2g3YlVaZErFy9-fsfCO}/_ssgManifest.js +0 -0
package/bin/annodex.js CHANGED
@@ -27,6 +27,7 @@ const https = require("https");
27
27
  const { randomBytes } = require("crypto");
28
28
  // eslint-disable-next-line @typescript-eslint/no-require-imports
29
29
  const { readAppSettings, ensureAppSettings } = require("../lib/app-settings.js");
30
+ const macosCodexSecurity = require("../lib/macos-codex-security.js");
30
31
 
31
32
  const pkgDir = path.join(__dirname, "..");
32
33
  const nextDir = path.join(pkgDir, ".next");
@@ -82,6 +83,7 @@ const { values: cliArgs, positionals } = parseArgs({
82
83
  hostname: { type: "string", short: "H" },
83
84
  json: { type: "boolean" },
84
85
  follow: { type: "boolean", short: "f" },
86
+ repair: { type: "boolean" },
85
87
  version: { type: "boolean", short: "v" },
86
88
  help: { type: "boolean", short: "h" },
87
89
  },
@@ -719,6 +721,298 @@ function spawnDetachedServer(extraEnv = {}, overridePort, overrideHost) {
719
721
  return child;
720
722
  }
721
723
 
724
+
725
+ function commandOutput(command, args, options = {}) {
726
+ try {
727
+ const result = spawnSync(command, args, {
728
+ encoding: "utf8",
729
+ timeout: options.timeout ?? 5000,
730
+ windowsHide: true,
731
+ ...options,
732
+ });
733
+ return {
734
+ ok: result.status === 0,
735
+ status: result.status,
736
+ signal: result.signal,
737
+ stdout: (result.stdout || "").trim(),
738
+ stderr: (result.stderr || "").trim(),
739
+ error: result.error ? result.error.message : null,
740
+ };
741
+ } catch (error) {
742
+ return { ok: false, status: null, signal: null, stdout: "", stderr: "", error: error instanceof Error ? error.message : String(error) };
743
+ }
744
+ }
745
+
746
+ function getNpmPrefix() {
747
+ const npm = process.platform === "win32" ? "npm.cmd" : "npm";
748
+ const result = commandOutput(npm, ["prefix", "-g"], { timeout: 3000 });
749
+ return result.ok && result.stdout ? result.stdout.split(/\r?\n/)[0].trim() : null;
750
+ }
751
+
752
+ function codexPackageInfo() {
753
+ const platform = process.platform;
754
+ const arch = process.arch;
755
+ let pkgName = null;
756
+ let triple = null;
757
+ if (platform === "darwin") {
758
+ if (arch === "arm64") { pkgName = "codex-darwin-arm64"; triple = "aarch64-apple-darwin"; }
759
+ else if (arch === "x64") { pkgName = "codex-darwin-x64"; triple = "x86_64-apple-darwin"; }
760
+ } else if (platform === "linux") {
761
+ if (arch === "arm64") { pkgName = "codex-linux-arm64"; triple = "aarch64-unknown-linux-musl"; }
762
+ else if (arch === "x64") { pkgName = "codex-linux-x64"; triple = "x86_64-unknown-linux-musl"; }
763
+ } else if (platform === "win32") {
764
+ if (arch === "arm64") { pkgName = "codex-win32-arm64"; triple = "aarch64-pc-windows-msvc"; }
765
+ else if (arch === "x64") { pkgName = "codex-win32-x64"; triple = "x86_64-pc-windows-msvc"; }
766
+ }
767
+ return { pkgName, triple, binaryName: platform === "win32" ? "codex.exe" : "codex" };
768
+ }
769
+
770
+ function resolveCodexNativeCandidates() {
771
+ const { pkgName, triple, binaryName } = codexPackageInfo();
772
+ if (!pkgName || !triple) return [];
773
+ const roots = [
774
+ path.join(process.cwd(), "node_modules"),
775
+ path.join(pkgDir, "node_modules"),
776
+ ];
777
+ const npmPrefix = getNpmPrefix();
778
+ if (npmPrefix) roots.push(path.join(npmPrefix, "lib", "node_modules"));
779
+ const installedDir = getInstalledPackageDir();
780
+ roots.push(path.join(installedDir, "node_modules"));
781
+ roots.push(path.join(installedDir, "..", "..", "node_modules"));
782
+ const seen = new Set();
783
+ const out = [];
784
+ const subPaths = [
785
+ path.join("vendor", triple, "bin", binaryName),
786
+ path.join("vendor", triple, "codex", binaryName),
787
+ ];
788
+ for (const root of roots) {
789
+ for (const layout of ["flat", "nested"]) {
790
+ const pkgRoot = layout === "flat"
791
+ ? path.join(root, "@openai", pkgName)
792
+ : path.join(root, "@openai", "codex", "node_modules", "@openai", pkgName);
793
+ for (const sub of subPaths) {
794
+ const candidate = path.join(pkgRoot, sub);
795
+ if (seen.has(candidate)) continue;
796
+ seen.add(candidate);
797
+ if (fs.existsSync(candidate)) out.push(candidate);
798
+ }
799
+ }
800
+ }
801
+ return out;
802
+ }
803
+
804
+ function resolveCodexShimCandidates() {
805
+ const names = process.platform === "win32" ? ["codex.cmd", "codex.exe", "codex"] : ["codex"];
806
+ const dirs = [path.join(process.cwd(), "node_modules", ".bin"), path.join(pkgDir, "node_modules", ".bin")];
807
+ const npmPrefix = getNpmPrefix();
808
+ if (npmPrefix) dirs.push(process.platform === "win32" ? npmPrefix : path.join(npmPrefix, "bin"));
809
+ const installedDir = getInstalledPackageDir();
810
+ dirs.push(path.join(installedDir, "node_modules", ".bin"));
811
+ dirs.push(path.join(installedDir, "..", "..", ".bin"));
812
+ const seen = new Set();
813
+ const out = [];
814
+ for (const dir of dirs) {
815
+ for (const name of names) {
816
+ const candidate = path.join(dir, name);
817
+ if (!seen.has(candidate) && fs.existsSync(candidate)) {
818
+ seen.add(candidate);
819
+ out.push(candidate);
820
+ }
821
+ }
822
+ }
823
+ const which = commandOutput(process.platform === "win32" ? "where" : "which", ["codex"], { timeout: 3000 });
824
+ if (which.ok && which.stdout) {
825
+ for (const line of which.stdout.split(/\r?\n/).map((v) => v.trim()).filter(Boolean)) {
826
+ if (!seen.has(line) && fs.existsSync(line)) {
827
+ seen.add(line);
828
+ out.push(line);
829
+ }
830
+ }
831
+ }
832
+ return out;
833
+ }
834
+
835
+ function xattrInfo(target) {
836
+ if (process.platform !== "darwin" || !target) return null;
837
+ const result = commandOutput("xattr", [target], { timeout: 3000 });
838
+ return {
839
+ ok: result.ok,
840
+ hasQuarantine: /com\.apple\.quarantine/.test(result.stdout),
841
+ attributes: result.stdout ? result.stdout.split(/\r?\n/).filter(Boolean) : [],
842
+ error: result.ok ? null : (result.stderr || result.error),
843
+ };
844
+ }
845
+
846
+ function spctlAssess(target) {
847
+ if (process.platform !== "darwin" || !target) return null;
848
+ const result = commandOutput("spctl", ["--assess", "--verbose", target], { timeout: 5000 });
849
+ return {
850
+ accepted: result.ok || /accepted/i.test(`${result.stdout}\n${result.stderr}`),
851
+ status: result.status,
852
+ output: `${result.stdout}${result.stderr ? `\n${result.stderr}` : ""}`.trim(),
853
+ error: result.error,
854
+ };
855
+ }
856
+
857
+ function selectedCodexPath(nativeCandidates, shimCandidates) {
858
+ const envPath = process.env.ANNODEX_CODEX_PATH?.trim();
859
+ if (envPath) return { path: envPath, source: "ANNODEX_CODEX_PATH", exists: fs.existsSync(envPath) };
860
+ if (nativeCandidates[0]) return { path: nativeCandidates[0], source: "native-candidate", exists: true };
861
+ if (shimCandidates[0]) return { path: shimCandidates[0], source: "shim-candidate", exists: true };
862
+ return { path: process.platform === "win32" ? "codex.cmd" : "codex", source: "PATH fallback", exists: null };
863
+ }
864
+
865
+ function detectMacOSVersion() {
866
+ if (process.platform !== "darwin") return null;
867
+ const result = commandOutput("sw_vers", ["-productVersion"], { timeout: 3000 });
868
+ return result.ok ? result.stdout : null;
869
+ }
870
+
871
+ function macOSProtectedLocationInfo(targetPath) {
872
+ if (process.platform !== "darwin" || !targetPath) return null;
873
+ const real = safeRealpath(targetPath);
874
+ const home = os.homedir();
875
+ const protectedRoots = [
876
+ { label: "Desktop", path: path.join(home, "Desktop") },
877
+ { label: "Documents", path: path.join(home, "Documents") },
878
+ { label: "Downloads", path: path.join(home, "Downloads") },
879
+ { label: "iCloud Drive", path: path.join(home, "Library", "Mobile Documents") },
880
+ ];
881
+ const match = protectedRoots.find((root) => isPathInside(real, root.path));
882
+ return {
883
+ path: real,
884
+ inProtectedLocation: Boolean(match),
885
+ root: match?.label ?? null,
886
+ };
887
+ }
888
+
889
+ function runDoctor(json = false, repair = false) {
890
+ const nativeCandidates = resolveCodexNativeCandidates();
891
+ const shimCandidates = resolveCodexShimCandidates();
892
+ const selected = selectedCodexPath(nativeCandidates, shimCandidates);
893
+ const selectedReal = selected.exists ? safeRealpath(selected.path) : selected.path;
894
+
895
+ let repairResults = null;
896
+ if (repair && process.platform === "darwin") {
897
+ macosCodexSecurity.clearMacOSQuarantine(process.cwd());
898
+ const repairPaths = [...new Set([
899
+ ...nativeCandidates,
900
+ selected.exists ? selected.path : null,
901
+ ].filter(Boolean))];
902
+ repairResults = macosCodexSecurity.repairMacOSCodexPaths(repairPaths);
903
+ if (!json) {
904
+ console.log("repair:");
905
+ for (const item of repairResults) {
906
+ if (item.skipped) {
907
+ console.log(`- ${item.path}: skipped (no revoked cert)`);
908
+ } else {
909
+ console.log(`- ${item.path}: ${item.repair?.ok ? "repaired" : "failed"}`);
910
+ }
911
+ }
912
+ console.log("");
913
+ }
914
+ }
915
+
916
+ const transport = (process.env.ANNODEX_CODEX_TRANSPORT || "auto").toLowerCase();
917
+ const resolvedTransport = transport === "ws" || transport === "stdio" ? transport : (process.platform === "linux" ? "ws" : "stdio");
918
+ const versionProbe = selected.path
919
+ ? commandOutput(selected.path, ["--version"], { timeout: 15000 })
920
+ : null;
921
+ const report = {
922
+ annodex: { version: VERSION, packageName: PKG_NAME, packageDir: pkgDir, installedPackageDir: getInstalledPackageDir() },
923
+ platform: { platform: process.platform, arch: process.arch, macOSVersion: detectMacOSVersion() },
924
+ node: { version: process.version, execPath: process.execPath, cwd: process.cwd() },
925
+ appBundle: { enabled: process.env.ANNODEX_APP_BUNDLE === "1", env: process.env.ANNODEX_APP_BUNDLE || null },
926
+ workspace: {
927
+ packageDir: safeRealpath(pkgDir),
928
+ cwd: safeRealpath(process.cwd()),
929
+ packageDirMacOSProtection: macOSProtectedLocationInfo(pkgDir),
930
+ cwdMacOSProtection: macOSProtectedLocationInfo(process.cwd()),
931
+ },
932
+ config: { configDir: agentDir, logFile, npmPrefix: getNpmPrefix() },
933
+ transport: { requested: process.env.ANNODEX_CODEX_TRANSPORT || "auto", resolved: resolvedTransport },
934
+ codex: {
935
+ envPath: process.env.ANNODEX_CODEX_PATH || null,
936
+ selected: { ...selected, realpath: selectedReal },
937
+ nativeCandidates,
938
+ shimCandidates,
939
+ selectedXattr: xattrInfo(selected.exists ? selected.path : null),
940
+ selectedCodesign: selected.exists
941
+ ? macosCodexSecurity.codesignVerify(selected.path)
942
+ : null,
943
+ selectedSpctl: spctlAssess(selected.exists ? selected.path : null),
944
+ versionProbe: versionProbe ? {
945
+ ok: versionProbe.ok,
946
+ status: versionProbe.status,
947
+ signal: versionProbe.signal,
948
+ stdout: versionProbe.stdout,
949
+ stderr: versionProbe.stderr,
950
+ error: versionProbe.error,
951
+ } : null,
952
+ },
953
+ recommendations: [],
954
+ repair: repairResults,
955
+ };
956
+ if (process.platform === "darwin") {
957
+ if (!report.appBundle.enabled) report.recommendations.push("macOS: not launched from Annodex.app; CLI mode is diagnostic/advanced until the launcher PoC is validated.");
958
+ if (report.appBundle.enabled && report.workspace.packageDirMacOSProtection?.inProtectedLocation) {
959
+ report.recommendations.push(`macOS: Annodex.app is reading source/runtime files from ${report.workspace.packageDirMacOSProtection.root}. Finder-launched apps may hit TCC EPERM there. Move the repo/runtime outside protected folders or bundle the runtime into Annodex.app before evaluating launcher viability.`);
960
+ }
961
+ if (report.codex.selectedXattr?.hasQuarantine) report.recommendations.push("macOS: selected codex path has com.apple.quarantine. Run `annodex doctor --repair` or restart annodex (xattr is cleared automatically on codex spawn).");
962
+ if (report.codex.selectedCodesign?.revoked || (report.codex.selectedSpctl?.output && macosCodexSecurity.needsRevokedCertRepair(report.codex.selectedSpctl.output))) {
963
+ report.recommendations.push("macOS: codex binary has a revoked Developer ID signature (CSSMERR_TP_CERT_REVOKED). Run `annodex doctor --repair` to strip and apply ad-hoc signing, then retry codex --version.");
964
+ } else if (report.codex.selectedSpctl && !report.codex.selectedSpctl.accepted && versionProbe && !versionProbe.ok) {
965
+ report.recommendations.push("macOS: spctl assessment did not accept the selected codex binary and codex --version failed. Try `annodex doctor --repair` for ad-hoc signing.");
966
+ }
967
+ }
968
+ if (report.codex.selected.exists === false) report.recommendations.push("ANNODEX_CODEX_PATH is set but does not exist. Fix or unset it.");
969
+ if (versionProbe && !versionProbe.ok) report.recommendations.push("codex --version probe failed. Check the selected codex path and macOS security dialogs/logs.");
970
+
971
+ if (json) {
972
+ console.log(JSON.stringify(report, null, 2));
973
+ return versionProbe && !versionProbe.ok ? 1 : 0;
974
+ }
975
+ console.log(`annodex doctor v${VERSION}`);
976
+ console.log(`platform: ${process.platform}/${process.arch}${report.platform.macOSVersion ? ` macOS ${report.platform.macOSVersion}` : ""}`);
977
+ console.log(`node: ${process.version} ${process.execPath}`);
978
+ console.log(`app bundle: ${report.appBundle.enabled ? "yes" : "no"}`);
979
+ if (report.workspace.packageDirMacOSProtection?.inProtectedLocation) {
980
+ console.log(`package dir protection: ${report.workspace.packageDirMacOSProtection.root}`);
981
+ }
982
+ if (report.workspace.cwdMacOSProtection?.inProtectedLocation) {
983
+ console.log(`cwd protection: ${report.workspace.cwdMacOSProtection.root}`);
984
+ }
985
+ console.log(`config dir: ${agentDir}`);
986
+ console.log(`transport: requested=${report.transport.requested} resolved=${report.transport.resolved}`);
987
+ console.log(`codex selected: ${selected.path} (${selected.source}, exists=${selected.exists})`);
988
+ if (selectedReal && selectedReal !== selected.path) console.log(`codex realpath: ${selectedReal}`);
989
+ console.log(`native candidates: ${nativeCandidates.length ? nativeCandidates.join("; ") : "none"}`);
990
+ console.log(`shim candidates: ${shimCandidates.length ? shimCandidates.join("; ") : "none"}`);
991
+ if (report.codex.selectedXattr) {
992
+ console.log(`xattr quarantine: ${report.codex.selectedXattr.hasQuarantine ? "yes" : "no"}`);
993
+ if (report.codex.selectedXattr.attributes.length) console.log(`xattr attributes: ${report.codex.selectedXattr.attributes.join(", ")}`);
994
+ }
995
+ if (report.codex.selectedCodesign) {
996
+ console.log(`codesign verify: ${report.codex.selectedCodesign.ok ? "ok" : "failed"}${report.codex.selectedCodesign.revoked ? " (revoked cert)" : ""}`);
997
+ if (report.codex.selectedCodesign.output) console.log(`codesign output: ${report.codex.selectedCodesign.output}`);
998
+ }
999
+ if (report.codex.selectedSpctl) {
1000
+ console.log(`spctl accepted: ${report.codex.selectedSpctl.accepted ? "yes" : "no"}`);
1001
+ if (report.codex.selectedSpctl.output) console.log(`spctl output: ${report.codex.selectedSpctl.output}`);
1002
+ }
1003
+ if (versionProbe) {
1004
+ console.log(`codex --version: ${versionProbe.ok ? "ok" : "failed"}${versionProbe.signal ? ` signal=${versionProbe.signal}` : ""}`);
1005
+ if (versionProbe.stdout) console.log(` stdout: ${versionProbe.stdout}`);
1006
+ if (versionProbe.stderr) console.log(` stderr: ${versionProbe.stderr}`);
1007
+ if (versionProbe.error) console.log(` error: ${versionProbe.error}`);
1008
+ }
1009
+ if (report.recommendations.length) {
1010
+ console.log("recommendations:");
1011
+ for (const item of report.recommendations) console.log(`- ${item}`);
1012
+ }
1013
+ return versionProbe && !versionProbe.ok ? 1 : 0;
1014
+ }
1015
+
722
1016
  if (cliArgs.version) {
723
1017
  console.log(VERSION);
724
1018
  process.exit(0);
@@ -734,6 +1028,7 @@ Usage:
734
1028
  annodex stop Stop background annodex
735
1029
  annodex status [--json] Show background server status
736
1030
  annodex logs [-f] Show background server logs
1031
+ annodex doctor [--json] [--repair] Diagnose local codex/runtime setup
737
1032
  annodex passwd Set or change password (empty = disable auth)
738
1033
  annodex update Update to the latest version
739
1034
 
@@ -749,6 +1044,10 @@ Options:
749
1044
  }
750
1045
 
751
1046
  const firstPos = positionals[0];
1047
+ if (firstPos === "doctor") {
1048
+ process.exit(runDoctor(cliArgs.json, cliArgs.repair));
1049
+ }
1050
+
752
1051
  if (firstPos === "status") {
753
1052
  const json = cliArgs.json;
754
1053
  staleStateRemoved();