@ory/argus 1.0.0 → 1.0.1

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.
@@ -1,9 +1,9 @@
1
1
  {
2
2
  "repo": "ory-agent-plugins",
3
- "commit": "6f11a1695f60ec11e7905c6a73f8683235c5e4df",
4
- "commitShort": "6f11a16",
3
+ "commit": "f803b3fe7be2cd6918652a082a7a4a3eb4ddab53",
4
+ "commitShort": "f803b3f",
5
5
  "branch": "main",
6
- "commitDate": "2026-08-29T19:17:15-07:00",
6
+ "commitDate": "2026-08-30T11:50:10-07:00",
7
7
  "dirty": false,
8
- "builtAt": "2026-08-30T02:20:53.108Z"
8
+ "builtAt": "2026-08-30T18:53:36.809Z"
9
9
  }
package/dist/runtime.d.ts CHANGED
@@ -345,6 +345,11 @@ export interface PreparedRuntime {
345
345
  /** Store directories GC'd after rewiring — reported by `install`. */
346
346
  prunedStores: string[];
347
347
  }
348
+ /** Serialize installs because npm mutates and prunes the shared prefix in place. */
349
+ export declare function withRuntimeInstallLock<T>(action: () => T, options?: {
350
+ timeoutMs?: number;
351
+ pollMs?: number;
352
+ }): T;
348
353
  /**
349
354
  * One call per plugin install: resolve the runtime, write the shims, record
350
355
  * the wiring, and GC stores nothing references any more.
package/dist/runtime.js CHANGED
@@ -104,12 +104,14 @@ exports.removeRuntimeWiring = removeRuntimeWiring;
104
104
  exports.pruneRuntimeStores = pruneRuntimeStores;
105
105
  exports.resolveRuntimeForInstall = resolveRuntimeForInstall;
106
106
  exports.requireHookCommand = requireHookCommand;
107
+ exports.withRuntimeInstallLock = withRuntimeInstallLock;
107
108
  exports.wireRuntime = wireRuntime;
108
109
  exports.checkRuntimeHealth = checkRuntimeHealth;
109
110
  exports.describeRuntimeHealth = describeRuntimeHealth;
110
111
  const fs = __importStar(require("node:fs"));
111
112
  const path = __importStar(require("node:path"));
112
113
  const node_child_process_1 = require("node:child_process");
114
+ const node_crypto_1 = require("node:crypto");
113
115
  const config_js_1 = require("./config.js");
114
116
  // ─── Paths ─────────────────────────────────────────────────────────
115
117
  /** Root of the runtime store: `<dataDir>/runtime`. */
@@ -120,6 +122,9 @@ function getRuntimeRoot() {
120
122
  function getRuntimeStoreDir(version) {
121
123
  return path.join(getRuntimeRoot(), version);
122
124
  }
125
+ function getRuntimeInstallLockPath() {
126
+ return path.join(getRuntimeRoot(), ".install.lock");
127
+ }
123
128
  /** Directory holding the generated entry shims: `<dataDir>/bin`. */
124
129
  function getShimDir() {
125
130
  return path.join((0, config_js_1.getDataDir)(), "bin");
@@ -222,7 +227,16 @@ function materializeRuntime(opts) {
222
227
  const storeDir = getRuntimeStoreDir(version);
223
228
  fs.mkdirSync(storeDir, { recursive: true });
224
229
  const extras = opts.extraPackages ?? [`${exports.MCP_SERVER_PACKAGE}@${version}`];
225
- const specs = [`${packageName}@${version}`, ...extras];
230
+ // npm --no-save prunes packages omitted from a later install into the same
231
+ // prefix. Reinstall every runtime already wired to this shared store so
232
+ // adding one harness cannot remove another harness's package.
233
+ const retained = Object.values(readRuntimeManifest().harnesses)
234
+ .filter((wiring) => wiring.storeDir &&
235
+ path.resolve(wiring.storeDir) === path.resolve(storeDir))
236
+ .map((wiring) => `${wiring.packageName}@${wiring.version}`);
237
+ const specs = [
238
+ ...new Set([`${packageName}@${version}`, ...retained, ...extras]),
239
+ ];
226
240
  const installer = opts.installer ?? exports.defaultNpmInstaller;
227
241
  const result = installer({ prefix: storeDir, specs });
228
242
  if (!result.ok) {
@@ -648,6 +662,66 @@ function requireHookCommand(runtime) {
648
662
  }
649
663
  return runtime.hookCommand;
650
664
  }
665
+ const RUNTIME_LOCK_TIMEOUT_MS = 5 * 60_000;
666
+ const RUNTIME_LOCK_POLL_MS = 50;
667
+ /** Serialize installs because npm mutates and prunes the shared prefix in place. */
668
+ function withRuntimeInstallLock(action, options = {}) {
669
+ const root = getRuntimeRoot();
670
+ const lockPath = getRuntimeInstallLockPath();
671
+ const deadline = Date.now() + (options.timeoutMs ?? RUNTIME_LOCK_TIMEOUT_MS);
672
+ fs.mkdirSync(root, { recursive: true });
673
+ let fd;
674
+ const token = `${process.pid}:${(0, node_crypto_1.randomUUID)()}`;
675
+ for (;;) {
676
+ try {
677
+ fd = fs.openSync(lockPath, "wx", 0o600);
678
+ fs.writeSync(fd, token);
679
+ break;
680
+ }
681
+ catch (err) {
682
+ if (err.code !== "EEXIST")
683
+ throw err;
684
+ if (Date.now() > deadline) {
685
+ throw new Error(`Timed out waiting for the Ory runtime install lock at ${lockPath}. ` +
686
+ "Remove it only if no other plugin install is running.");
687
+ }
688
+ sleepRuntimeLock(options.pollMs ?? RUNTIME_LOCK_POLL_MS);
689
+ }
690
+ }
691
+ try {
692
+ return action();
693
+ }
694
+ finally {
695
+ try {
696
+ fs.closeSync(fd);
697
+ }
698
+ catch {
699
+ /* best-effort */
700
+ }
701
+ try {
702
+ if (fs.readFileSync(lockPath, "utf8") === token)
703
+ fs.unlinkSync(lockPath);
704
+ }
705
+ catch {
706
+ /* best-effort */
707
+ }
708
+ }
709
+ }
710
+ let runtimeLockSleepBuffer;
711
+ function sleepRuntimeLock(ms) {
712
+ if (runtimeLockSleepBuffer === undefined) {
713
+ try {
714
+ runtimeLockSleepBuffer = new Int32Array(new SharedArrayBuffer(4));
715
+ }
716
+ catch {
717
+ runtimeLockSleepBuffer = null;
718
+ }
719
+ }
720
+ if (!runtimeLockSleepBuffer) {
721
+ throw new Error("This runtime cannot wait for another Ory plugin install to finish.");
722
+ }
723
+ Atomics.wait(runtimeLockSleepBuffer, 0, 0, ms);
724
+ }
651
725
  /**
652
726
  * One call per plugin install: resolve the runtime, write the shims, record
653
727
  * the wiring, and GC stores nothing references any more.
@@ -656,6 +730,9 @@ function requireHookCommand(runtime) {
656
730
  * harness is about to use is never a GC candidate.
657
731
  */
658
732
  function wireRuntime(opts) {
733
+ return withRuntimeInstallLock(() => wireRuntimeUnlocked(opts));
734
+ }
735
+ function wireRuntimeUnlocked(opts) {
659
736
  const target = resolveRuntimeForInstall({
660
737
  packageName: opts.packageName,
661
738
  packageRoot: opts.packageRoot,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ory/argus",
3
- "version": "1.0.0",
3
+ "version": "1.0.1",
4
4
  "description": "Ory Argus: the core API for building authentication, authorization, and audit into AI agent harness plugins, extensions, and custom integrations",
5
5
  "license": "Apache-2.0",
6
6
  "homepage": "https://ory.com",