{"_id":"@dereekb/openrouter","_rev":"24-862588f6708553b2375f41ab0007fbf0","name":"@dereekb/openrouter","dist-tags":{"latest":"14.14.0"},"versions":{"13.37.0":{"name":"@dereekb/openrouter","version":"13.37.0","_id":"@dereekb/openrouter@13.37.0","maintainers":[{"name":"dereekb","email":"npm@dereekb.com"}],"dist":{"shasum":"30c952f987b26712b7b40936a41c2a165cb6e9e7","tarball":"https://registry.npmjs.org/@dereekb/openrouter/-/openrouter-13.37.0.tgz","fileCount":51,"integrity":"sha512-7nuouOH9zw4KG/q/9vxBgKsOV7vKCoqObz3E6ijgrK/9o0t8pChD0uFkQ/K64YVYp8WBt8CC7YhnhjueK4REyQ==","signatures":[{"sig":"MEQCIH0MSHBYSQWG+cc1hDWAfu73K3KuJbvRxNYbUJ05uNwcAiBF/DSHXrTOAtGH/8rCjdLFbFE6WRqVgHFZlQXDYMlCMA==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":811738},"main":"./index.cjs.js","types":"./index.d.ts","module":"./index.esm.js","exports":{".":{"types":"./index.d.ts","import":"./index.cjs.mjs","module":"./index.esm.js","default":"./index.cjs.js"},"./firebase":{"types":"./firebase/index.d.ts","import":"./firebase/index.cjs.mjs","module":"./firebase/index.esm.js","default":"./firebase/index.cjs.js"},"./package.json":"./package.json","./firebase-server":{"types":"./firebase-server/index.d.ts","import":"./firebase-server/index.cjs.mjs","module":"./firebase-server/index.esm.js","default":"./firebase-server/index.cjs.js"}},"gitHead":"da167c76eef3f7df1cdd883ce31f2a47284488a9","_npmUser":{"name":"dereekb","email":"npm@dereekb.com"},"_npmVersion":"11.8.0","description":"Replacement for OpenAI's deprecated reusable Prompt Objects (`v1/prompts`, removed 2026-11-30), built on OpenRouter.","directories":{},"_nodeVersion":"24.13.1","_hasShrinkwrap":false,"peerDependencies":{"@dereekb/util":"13.37.0","@openrouter/sdk":"^1.2.26"},"_npmOperationalInternal":{"tmp":"tmp/openrouter_13.37.0_1787056154448_0.6491482015924581","host":"s3://npm-registry-packages-npm-production"}},"13.38.0":{"name":"@dereekb/openrouter","version":"13.38.0","_id":"@dereekb/openrouter@13.38.0","maintainers":[{"name":"dereekb","email":"npm@dereekb.com"}],"dist":{"shasum":"1d3142b5f75f10e1baf2437377e1166a5e6c08cc","tarball":"https://registry.npmjs.org/@dereekb/openrouter/-/openrouter-13.38.0.tgz","fileCount":51,"integrity":"sha512-duRIUVMDzuI5vJy9cYcKaJ/tW6CsQmxWLu13/GZDUtr8noTRGfKsCzslJzQ/uOuyCyNmjWDgePTFTfhjh1ANzA==","signatures":[{"sig":"MEUCIGW+Ohi7lCn/pWseROGEOe+KBRVq/CJQhD7MyKgfC63TAiEArHG68+79fGSNSfx3jtXbQKtvEEII9HyYmNHW45XLfP0=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":811784},"main":"./index.cjs.js","types":"./index.d.ts","module":"./index.esm.js","exports":{".":{"types":"./index.d.ts","import":"./index.cjs.mjs","module":"./index.esm.js","default":"./index.cjs.js"},"./firebase":{"types":"./firebase/index.d.ts","import":"./firebase/index.cjs.mjs","module":"./firebase/index.esm.js","default":"./firebase/index.cjs.js"},"./package.json":"./package.json","./firebase-server":{"types":"./firebase-server/index.d.ts","import":"./firebase-server/index.cjs.mjs","module":"./firebase-server/index.esm.js","default":"./firebase-server/index.cjs.js"}},"gitHead":"cb4fc5b9f36d3c09a88c9c51c80a65b0a8bd3a3c","_npmUser":{"name":"dereekb","email":"npm@dereekb.com"},"_npmVersion":"11.8.0","description":"Replacement for OpenAI's deprecated reusable Prompt Objects (`v1/prompts`, removed 2026-11-30), built on OpenRouter.","directories":{},"_nodeVersion":"24.13.1","_hasShrinkwrap":false,"peerDependencies":{"@dereekb/util":"13.38.0","@openrouter/sdk":"^1.2.26"},"_npmOperationalInternal":{"tmp":"tmp/openrouter_13.38.0_1787244893251_0.10541291053609658","host":"s3://npm-registry-packages-npm-production"}},"13.39.0":{"name":"@dereekb/openrouter","version":"13.39.0","_id":"@dereekb/openrouter@13.39.0","maintainers":[{"name":"dereekb","email":"npm@dereekb.com"}],"dist":{"shasum":"07368260c577787675fba2417c2f15010685feee","tarball":"https://registry.npmjs.org/@dereekb/openrouter/-/openrouter-13.39.0.tgz","fileCount":42,"integrity":"sha512-FpXc+31l5wce/2FW67z2PqYSS6ObcJIO3bSGO2+YlHeZCTW+tOzC5j6Dtn1xG7JQskl3s2KSFWeVw4U5flWC1A==","signatures":[{"sig":"MEYCIQDTU2EXEyT3+E+hlqgDs5a421c+fiqjvs8C8e7BBqVfnQIhALznVPGh02RwUeT6Ba4+ERxZuB07XN0IhF5ZMuTmbPdR","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":493796},"main":"./index.esm.js","type":"module","types":"./index.d.ts","module":"./index.esm.js","exports":{".":{"types":"./index.d.ts","import":"./index.esm.js","default":"./index.esm.js"},"./firebase":{"types":"./firebase/index.d.ts","import":"./firebase/index.esm.js","default":"./firebase/index.esm.js"},"./package.json":"./package.json","./firebase-server":{"types":"./firebase-server/index.d.ts","import":"./firebase-server/index.esm.js","default":"./firebase-server/index.esm.js"}},"gitHead":"8f899864b082dce2312197aec56278a22e83d7ce","_npmUser":{"name":"dereekb","email":"npm@dereekb.com"},"_npmVersion":"11.8.0","description":"Replacement for OpenAI's deprecated reusable Prompt Objects (`v1/prompts`, removed 2026-11-30), built on OpenRouter.","directories":{},"_nodeVersion":"24.13.1","_hasShrinkwrap":false,"peerDependencies":{"@dereekb/util":"13.39.0","@openrouter/sdk":"^1.2.26"},"_npmOperationalInternal":{"tmp":"tmp/openrouter_13.39.0_1787333128218_0.9791596231236774","host":"s3://npm-registry-packages-npm-production"}},"13.40.0":{"name":"@dereekb/openrouter","version":"13.40.0","_id":"@dereekb/openrouter@13.40.0","maintainers":[{"name":"dereekb","email":"npm@dereekb.com"}],"dist":{"shasum":"e782c356b6dd402b37203a6abb3c2f6ca92dcb5b","tarball":"https://registry.npmjs.org/@dereekb/openrouter/-/openrouter-13.40.0.tgz","fileCount":42,"integrity":"sha512-4x+VDwmhsMH8fIoQYyYkXTKG5mSINwZRN8N0g9pJ5SqIUb3cLLrzp1wvtNUNzQwXEir0BlNcL0VmBv5joqFHKg==","signatures":[{"sig":"MEYCIQDVRyg8J/A6dF6dM6gPsNXQPMSOO6ezveu5yrePGRMnxwIhAI3CkF69qiql3NUvZU235Zu97Ey12uCzCDUM15y1g3z9","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":493796},"main":"./index.esm.js","type":"module","types":"./index.d.ts","module":"./index.esm.js","exports":{".":{"types":"./index.d.ts","import":"./index.esm.js","default":"./index.esm.js"},"./firebase":{"types":"./firebase/index.d.ts","import":"./firebase/index.esm.js","default":"./firebase/index.esm.js"},"./package.json":"./package.json","./firebase-server":{"types":"./firebase-server/index.d.ts","import":"./firebase-server/index.esm.js","default":"./firebase-server/index.esm.js"}},"gitHead":"dd72c54046c2c0309ea512910950ff41d1d05267","_npmUser":{"name":"dereekb","email":"npm@dereekb.com"},"_npmVersion":"11.8.0","description":"Replacement for OpenAI's deprecated reusable Prompt Objects (`v1/prompts`, removed 2026-11-30), built on OpenRouter.","directories":{},"_nodeVersion":"24.13.1","_hasShrinkwrap":false,"peerDependencies":{"@dereekb/util":"13.40.0","@openrouter/sdk":"^1.2.26"},"_npmOperationalInternal":{"tmp":"tmp/openrouter_13.40.0_1787410883304_0.5753110611299723","host":"s3://npm-registry-packages-npm-production"}},"13.41.0":{"name":"@dereekb/openrouter","version":"13.41.0","_id":"@dereekb/openrouter@13.41.0","maintainers":[{"name":"dereekb","email":"npm@dereekb.com"}],"dist":{"shasum":"07a5cc558de5dd3e51ca52fd44db346fbfd487d9","tarball":"https://registry.npmjs.org/@dereekb/openrouter/-/openrouter-13.41.0.tgz","fileCount":42,"integrity":"sha512-te7AUBitLtT06YHzu1Z0mEM4DYKztUdkCCqls5UwenYihi2zgMgV3f0sRr7JlO9ONESYM8Fz35Sw+Xi6MfVPrg==","signatures":[{"sig":"MEUCIQDvHbonJsLw93LBUsbUO3YYbTw7Y3YIiPJEVY/uvDkATgIgE/wOjNOhRytnQ8RCEXqxbECT/D13bG91f3lMmaij2YU=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":493796},"main":"./index.esm.js","type":"module","types":"./index.d.ts","module":"./index.esm.js","exports":{".":{"types":"./index.d.ts","import":"./index.esm.js","default":"./index.esm.js"},"./firebase":{"types":"./firebase/index.d.ts","import":"./firebase/index.esm.js","default":"./firebase/index.esm.js"},"./package.json":"./package.json","./firebase-server":{"types":"./firebase-server/index.d.ts","import":"./firebase-server/index.esm.js","default":"./firebase-server/index.esm.js"}},"gitHead":"f5bcfa75fc4d648a6de2cb9d21cb4fea0b856ff1","_npmUser":{"name":"dereekb","email":"npm@dereekb.com"},"_npmVersion":"11.8.0","description":"Replacement for OpenAI's deprecated reusable Prompt Objects (`v1/prompts`, removed 2026-11-30), built on OpenRouter.","directories":{},"_nodeVersion":"24.13.1","_hasShrinkwrap":false,"peerDependencies":{"@dereekb/util":"13.41.0","@openrouter/sdk":"^1.2.26"},"_npmOperationalInternal":{"tmp":"tmp/openrouter_13.41.0_1787426832348_0.3336271494987997","host":"s3://npm-registry-packages-npm-production"}},"13.42.0":{"name":"@dereekb/openrouter","version":"13.42.0","_id":"@dereekb/openrouter@13.42.0","maintainers":[{"name":"dereekb","email":"npm@dereekb.com"}],"dist":{"shasum":"7be287d59665683073c1055f3bf5b8265ff63ab8","tarball":"https://registry.npmjs.org/@dereekb/openrouter/-/openrouter-13.42.0.tgz","fileCount":42,"integrity":"sha512-PJ2RZzFZQt7qSr3OuP912ZcfRW9+L9Txbpeqf3wOcdLqsvG3dFtCO033k3MbUULmTcUaUqQX1cqjoLqzWc7bYQ==","signatures":[{"sig":"MEQCIGbGw8jmfndWusD7KsNmqAfKcGxn3ios7nOCSvKlwLjnAiAk8mDyw4y+Hjnp3Xc5l8sHOYiNSEdj3yfOjm/pXMrSJQ==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEYCIQCRrl546SUsAdeoB0UKEmc7zlozXSaLUm0Ex0cSVmtXfwIhAJXEysKJzJPj8uEbSJ1YMAaTVpczqaqrvS8ejxnTFzww","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":493796},"main":"./index.esm.js","type":"module","types":"./index.d.ts","module":"./index.esm.js","exports":{".":{"types":"./index.d.ts","import":"./index.esm.js","default":"./index.esm.js"},"./firebase":{"types":"./firebase/index.d.ts","import":"./firebase/index.esm.js","default":"./firebase/index.esm.js"},"./package.json":"./package.json","./firebase-server":{"types":"./firebase-server/index.d.ts","import":"./firebase-server/index.esm.js","default":"./firebase-server/index.esm.js"}},"gitHead":"3495ecc1db6bede0d942041cade7e3f33130ef58","_npmUser":{"name":"dereekb","email":"npm@dereekb.com"},"_npmVersion":"11.8.0","description":"Replacement for OpenAI's deprecated reusable Prompt Objects (`v1/prompts`, removed 2026-11-30), built on OpenRouter.","directories":{},"_nodeVersion":"24.13.1","_hasShrinkwrap":false,"peerDependencies":{"@dereekb/util":"13.42.0","@openrouter/sdk":"^1.2.26"},"_npmOperationalInternal":{"tmp":"tmp/openrouter_13.42.0_1787928768572_0.10108637003939203","host":"s3://npm-registry-packages-npm-production"}},"13.43.0":{"name":"@dereekb/openrouter","version":"13.43.0","_id":"@dereekb/openrouter@13.43.0","maintainers":[{"name":"dereekb","email":"npm@dereekb.com"}],"dist":{"shasum":"c1e2f412c37a09ddf61a72c826318903293233ed","tarball":"https://registry.npmjs.org/@dereekb/openrouter/-/openrouter-13.43.0.tgz","fileCount":42,"integrity":"sha512-5fnByANw8FOSzJqnC3UpPS+zrzbJVf8R6ab6g61gwInXtHAN7RBrXUEtekUh9NKTHJPyNPEKKxQvAaz8w6ligQ==","signatures":[{"sig":"MEQCIHA+cA7+DthlZ3EIhwED9KHMousMNHOvzkWLEbV9vSp3AiB2lUqm08NNSQrUrO6kAh2g7g4RdttsVjf/xnXFM1dopw==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEYCIQDn4aMVMOhq4wDx+fQ7vYMGqlXFzrDSG/u75j9RtPlR+AIhAOJGPtj+Fj1BsnEj5u2JID+5dhKeTk/6+8933x+8RtRM","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":493796},"main":"./index.esm.js","type":"module","types":"./index.d.ts","module":"./index.esm.js","exports":{".":{"types":"./index.d.ts","import":"./index.esm.js","default":"./index.esm.js"},"./firebase":{"types":"./firebase/index.d.ts","import":"./firebase/index.esm.js","default":"./firebase/index.esm.js"},"./package.json":"./package.json","./firebase-server":{"types":"./firebase-server/index.d.ts","import":"./firebase-server/index.esm.js","default":"./firebase-server/index.esm.js"}},"gitHead":"569f209e2507cd25e228d7e1199a9a8dbd2d1b28","_npmUser":{"name":"dereekb","email":"npm@dereekb.com"},"_npmVersion":"11.8.0","description":"Replacement for OpenAI's deprecated reusable Prompt Objects (`v1/prompts`, removed 2026-11-30), built on OpenRouter.","directories":{},"_nodeVersion":"24.13.1","_hasShrinkwrap":false,"peerDependencies":{"@dereekb/util":"13.43.0","@openrouter/sdk":"^1.2.26"},"_npmOperationalInternal":{"tmp":"tmp/openrouter_13.43.0_1788273728302_0.7220122234930675","host":"s3://npm-registry-packages-npm-production"}},"14.0.0":{"name":"@dereekb/openrouter","version":"14.0.0","_id":"@dereekb/openrouter@14.0.0","maintainers":[{"name":"dereekb","email":"npm@dereekb.com"}],"dist":{"shasum":"3368d6c8e73e361268e997fd902c2960b0d22143","tarball":"https://registry.npmjs.org/@dereekb/openrouter/-/openrouter-14.0.0.tgz","fileCount":42,"integrity":"sha512-EclYLaV5VOpHDjM13oWVewgn20M7FJukvI5Tw0YrgKz6d6o5u9r8zMjNR63b34EixmskLP634DcN7kN/MngdhA==","signatures":[{"sig":"MEUCIQCj1w10O2yxFQeWgUPZgKc18gMm6uWcwZaLK10W6XrNFQIgayAjWP8gIAr64LD8g+430g1pvwZ1OMgSZKZ1dqprlRw=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEUCIQCl73G87xz7bVIb+GWmRcE6AdsVN9LJjY3x+/0EFSXWvwIgBYbhM12jdQNCvvk+Ij/fCYtFnwzhcqfShY5epE7dJm0=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":493111},"main":"./index.esm.js","type":"module","types":"./index.d.ts","module":"./index.esm.js","exports":{".":{"types":"./index.d.ts","import":"./index.esm.js","default":"./index.esm.js"},"./firebase":{"types":"./firebase/index.d.ts","import":"./firebase/index.esm.js","default":"./firebase/index.esm.js"},"./package.json":"./package.json","./firebase-server":{"types":"./firebase-server/index.d.ts","import":"./firebase-server/index.esm.js","default":"./firebase-server/index.esm.js"}},"gitHead":"c0ad7d699c1fe56e0c021f767058ebbed5e00180","_npmUser":{"name":"dereekb","email":"npm@dereekb.com"},"_npmVersion":"11.8.0","description":"Replacement for OpenAI's deprecated reusable Prompt Objects (`v1/prompts`, removed 2026-11-30), built on OpenRouter.","directories":{},"_nodeVersion":"24.13.1","_hasShrinkwrap":false,"peerDependencies":{"@dereekb/util":"14.0.0","@openrouter/sdk":"^1.2.26"},"_npmOperationalInternal":{"tmp":"tmp/openrouter_14.0.0_1788444221851_0.9733708149743021","host":"s3://npm-registry-packages-npm-production"}},"14.0.1":{"name":"@dereekb/openrouter","version":"14.0.1","_id":"@dereekb/openrouter@14.0.1","maintainers":[{"name":"dereekb","email":"npm@dereekb.com"}],"dist":{"shasum":"7ff38197de388bf3fcfc74bd248d23b9a5e7d7aa","tarball":"https://registry.npmjs.org/@dereekb/openrouter/-/openrouter-14.0.1.tgz","fileCount":42,"integrity":"sha512-aS5LKQnKO5KWMhWXSP3E6Su6PQfTQx7l02aVEvaB4ud4RQqnLgN9N5QnozH+2tPP+I8Lt3OumTw1CUW7bDzPSA==","signatures":[{"sig":"MEYCIQDJiB9MxlCdE5bto+cchyIjTW0cLFVu/6oSQe6Mptnq0gIhAPZb+0k9GbND1SJMekPClTeX4+4CV+SaL2jTWugklbwa","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEUCIAq6csR29SJCtze3k9ZYZvviCHiFTC53Qn3B3ynSNA7bAiEArW7qXSKC/XsjcqITjw/I6OXTw8UotlJsqiIPlhWlNy0=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":493111},"main":"./index.esm.js","type":"module","types":"./index.d.ts","module":"./index.esm.js","exports":{".":{"types":"./index.d.ts","import":"./index.esm.js","default":"./index.esm.js"},"./firebase":{"types":"./firebase/index.d.ts","import":"./firebase/index.esm.js","default":"./firebase/index.esm.js"},"./package.json":"./package.json","./firebase-server":{"types":"./firebase-server/index.d.ts","import":"./firebase-server/index.esm.js","default":"./firebase-server/index.esm.js"}},"gitHead":"bf5d92f0538949a45a384b49fd4820712e6cd026","_npmUser":{"name":"dereekb","email":"npm@dereekb.com"},"_npmVersion":"11.8.0","description":"Replacement for OpenAI's deprecated reusable Prompt Objects (`v1/prompts`, removed 2026-11-30), built on OpenRouter.","directories":{},"_nodeVersion":"24.13.1","_hasShrinkwrap":false,"peerDependencies":{"@dereekb/util":"14.0.1","@openrouter/sdk":"^1.2.26"},"_npmOperationalInternal":{"tmp":"tmp/openrouter_14.0.1_1788489746263_0.04590764766452038","host":"s3://npm-registry-packages-npm-production"}},"14.1.0":{"name":"@dereekb/openrouter","version":"14.1.0","_id":"@dereekb/openrouter@14.1.0","maintainers":[{"name":"dereekb","email":"npm@dereekb.com"}],"dist":{"shasum":"99ef844f633212e0b1d398ce353b3325675a76f3","tarball":"https://registry.npmjs.org/@dereekb/openrouter/-/openrouter-14.1.0.tgz","fileCount":42,"integrity":"sha512-/1mKSAqAq0njPxMG7ZPfYSr8oWrDMq73Vqdd/z3qeXXv1875qV+EqymAD/9Z5mWkcjADPAf6t3qqWi63qZULpg==","signatures":[{"sig":"MEUCIBykTHWatssREy8HL/mtF5/1yJrn9bbA7Ph4nl3uSJi4AiEAkdFwutF/F0IhzrtleHk/hgzJ4LaBIsinNOSGJLgD7zE=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEUCIAC7cN8jRt0d9O8I+SIlPuw1shDEiWNTrx0ebr5GU064AiEAkTl+2+Bxpinedd22pJjv0yMvpRUO5n3lONpeT5sLsxw=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":493111},"main":"./index.esm.js","type":"module","types":"./index.d.ts","module":"./index.esm.js","exports":{".":{"types":"./index.d.ts","import":"./index.esm.js","default":"./index.esm.js"},"./firebase":{"types":"./firebase/index.d.ts","import":"./firebase/index.esm.js","default":"./firebase/index.esm.js"},"./package.json":"./package.json","./firebase-server":{"types":"./firebase-server/index.d.ts","import":"./firebase-server/index.esm.js","default":"./firebase-server/index.esm.js"}},"gitHead":"2f1bdc65c3127bb42d87c0034cd03ccd9113069b","_npmUser":{"name":"dereekb","email":"npm@dereekb.com"},"_npmVersion":"11.8.0","description":"Replacement for OpenAI's deprecated reusable Prompt Objects (`v1/prompts`, removed 2026-11-30), built on OpenRouter.","directories":{},"_nodeVersion":"24.13.1","_hasShrinkwrap":false,"peerDependencies":{"@dereekb/util":"14.1.0","@openrouter/sdk":"^1.2.26"},"_npmOperationalInternal":{"tmp":"tmp/openrouter_14.1.0_1788811934155_0.5322475137821268","host":"s3://npm-registry-packages-npm-production"}},"14.2.0":{"name":"@dereekb/openrouter","version":"14.2.0","_id":"@dereekb/openrouter@14.2.0","maintainers":[{"name":"dereekb","email":"npm@dereekb.com"}],"dist":{"shasum":"c79f3ae191fbc4845bfe4e7492415f586a5ab2b9","tarball":"https://registry.npmjs.org/@dereekb/openrouter/-/openrouter-14.2.0.tgz","fileCount":42,"integrity":"sha512-EFzP5JoZrf6AoXInmK0wkfviQOJHHsukDfuRTqvHEZ6/HKpxypZeik6z1voKZPwm94tXbQIHXQg8Q9BROi7DXw==","signatures":[{"sig":"MEUCIQDXxTeukNyHF65Kri8MUm4f0g0lb7KVrIUNJMrUCYd0vQIgf22P6cD7oweZIXckY4LhqnUP0fLek4cY2JF3PyGHKMk=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEUCIB/hln0ouQTk6Des+jErLtunDVWoVLBHeU275CxnN2cuAiEA2PZD3BSGCRjfuKXXcVv3w6jwfcMLOulMaQ66dwPWDQg=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":493584},"main":"./index.esm.js","type":"module","types":"./index.d.ts","module":"./index.esm.js","exports":{".":{"types":"./index.d.ts","import":"./index.esm.js","default":"./index.esm.js"},"./firebase":{"types":"./firebase/index.d.ts","import":"./firebase/index.esm.js","default":"./firebase/index.esm.js"},"./package.json":"./package.json","./firebase-server":{"types":"./firebase-server/index.d.ts","import":"./firebase-server/index.esm.js","default":"./firebase-server/index.esm.js"}},"gitHead":"79840fdafe026b20ad4be64a7f17ffaf3621b20e","_npmUser":{"name":"dereekb","email":"npm@dereekb.com"},"_npmVersion":"11.8.0","description":"Replacement for OpenAI's deprecated reusable Prompt Objects (`v1/prompts`, removed 2026-11-30), built on OpenRouter.","directories":{},"sideEffects":false,"_nodeVersion":"24.13.1","_hasShrinkwrap":false,"peerDependencies":{"@dereekb/util":"14.2.0","@openrouter/sdk":"^1.2.26"},"_npmOperationalInternal":{"tmp":"tmp/openrouter_14.2.0_1789147524969_0.31175608041835146","host":"s3://npm-registry-packages-npm-production"}},"14.3.0":{"name":"@dereekb/openrouter","version":"14.3.0","_id":"@dereekb/openrouter@14.3.0","maintainers":[{"name":"dereekb","email":"npm@dereekb.com"}],"dist":{"shasum":"20b5775aee6347d086a873188723f78b8d4f2144","tarball":"https://registry.npmjs.org/@dereekb/openrouter/-/openrouter-14.3.0.tgz","fileCount":42,"integrity":"sha512-k6mXUP/I4nQwxvZ+MY9sjgf7xhlhU40Fg9m0s67GvBXTpKU3vCQ9cPZTS35dZFKq+qEGcS3S6NK5lOnb/SCQjg==","signatures":[{"sig":"MEUCIFzjGQ0UnfTN4HlP31v5sYxqDD+IHyJzi1i81xQdWhXTAiEAp8nYTmAymiLRWRE3U3YXmWrX4SNe+FvgCWy8jXYRc3c=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEQCIENNpOeGb6qqaLgvdw5CYgcTDX1LvSW8iz5ejmlqD+itAiBcOLUCAf2fqnIw8d78Gi8F0h0qB7aXQSSJkDSqjIiiWQ==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":512034},"main":"./index.esm.js","type":"module","types":"./index.d.ts","module":"./index.esm.js","exports":{".":{"types":"./index.d.ts","import":"./index.esm.js","default":"./index.esm.js"},"./firebase":{"types":"./firebase/index.d.ts","import":"./firebase/index.esm.js","default":"./firebase/index.esm.js"},"./package.json":"./package.json","./firebase-server":{"types":"./firebase-server/index.d.ts","import":"./firebase-server/index.esm.js","default":"./firebase-server/index.esm.js"}},"gitHead":"e586ded685ff88486f20fb0db41da8888fa91ae9","_npmUser":{"name":"dereekb","email":"npm@dereekb.com"},"_npmVersion":"11.8.0","description":"Replacement for OpenAI's deprecated reusable Prompt Objects (`v1/prompts`, removed 2026-11-30), built on OpenRouter.","directories":{},"sideEffects":false,"_nodeVersion":"24.13.1","_hasShrinkwrap":false,"peerDependencies":{"@dereekb/util":"14.3.0","@openrouter/sdk":"^1.2.26"},"_npmOperationalInternal":{"tmp":"tmp/openrouter_14.3.0_1789245214953_0.4014133752921827","host":"s3://npm-registry-packages-npm-production"}},"14.4.0":{"name":"@dereekb/openrouter","version":"14.4.0","_id":"@dereekb/openrouter@14.4.0","maintainers":[{"name":"dereekb","email":"npm@dereekb.com"}],"dist":{"shasum":"1fd0404a6e3874c4efee2d27a236f85e855f9b96","tarball":"https://registry.npmjs.org/@dereekb/openrouter/-/openrouter-14.4.0.tgz","fileCount":42,"integrity":"sha512-5btQ1CSUmancMqaa/p0JeXG9ixKbgPf3dFVg/mo/zC6A6zX730NOKteEa3SFCsA5FcIMY+3BpCIiyL2TJ3j0jg==","signatures":[{"sig":"MEYCIQDygt8LM8fs2iNvae6yiUmq6Ac1michZbxFLkujbKP3UgIhAKIxRYD5oxx52F33wnxSairvi4aFHYA07SFbMrrKAWZf","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEUCIA1d1qJfAOYb4oGwlpaVSssednH8XE4w3HgWBRAKaDarAiEA3cgE7kZ/5rBcNhH20KrrymkxVEn6VDXCxXUXpzEeN/0=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":512034},"main":"./index.esm.js","type":"module","types":"./index.d.ts","module":"./index.esm.js","exports":{".":{"types":"./index.d.ts","import":"./index.esm.js","default":"./index.esm.js"},"./firebase":{"types":"./firebase/index.d.ts","import":"./firebase/index.esm.js","default":"./firebase/index.esm.js"},"./package.json":"./package.json","./firebase-server":{"types":"./firebase-server/index.d.ts","import":"./firebase-server/index.esm.js","default":"./firebase-server/index.esm.js"}},"gitHead":"6f87162ba4b2239fcd80d07dbcc530bf6394ab96","_npmUser":{"name":"dereekb","email":"npm@dereekb.com"},"_npmVersion":"11.8.0","description":"Replacement for OpenAI's deprecated reusable Prompt Objects (`v1/prompts`, removed 2026-11-30), built on OpenRouter.","directories":{},"sideEffects":false,"_nodeVersion":"24.13.1","_hasShrinkwrap":false,"peerDependencies":{"@dereekb/util":"14.4.0","@openrouter/sdk":"^1.2.26"},"_npmOperationalInternal":{"tmp":"tmp/openrouter_14.4.0_1789352178613_0.9242524302353101","host":"s3://npm-registry-packages-npm-production"}},"14.5.0":{"name":"@dereekb/openrouter","version":"14.5.0","_id":"@dereekb/openrouter@14.5.0","maintainers":[{"name":"dereekb","email":"npm@dereekb.com"}],"dist":{"shasum":"b1245e605b59814b03141a4c47f5267c2a730cc4","tarball":"https://registry.npmjs.org/@dereekb/openrouter/-/openrouter-14.5.0.tgz","fileCount":42,"integrity":"sha512-b8IIlo5RUhWeQT7C3tk2rL3C2EPru7Yj5j+MccIwwiuCzMrMJFmSWh1E0IdO19hTTY+31qDHLBYXidxcLlDFxg==","signatures":[{"sig":"MEQCICcsUMiOLNOGRX/1pep820bWMY109mRnj+CLYbu1GUNTAiAUT6U97+A5sjs8KjcSjz2+vbB89yoApVJRmrD4YbkToQ==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEQCICL4UsiOmnBFwZWer1wKuohAi2/t1cvxkixN5Grrn6cmAiBFqMz/GDNyWm2JQ3cWM7OuRXz3JsrMNhBaCjRVJbH84A==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":512294},"main":"./index.esm.js","type":"module","types":"./index.d.ts","module":"./index.esm.js","exports":{".":{"types":"./index.d.ts","import":"./index.esm.js","default":"./index.esm.js"},"./firebase":{"types":"./firebase/index.d.ts","import":"./firebase/index.esm.js","default":"./firebase/index.esm.js"},"./package.json":"./package.json","./firebase-server":{"types":"./firebase-server/index.d.ts","import":"./firebase-server/index.esm.js","default":"./firebase-server/index.esm.js"}},"gitHead":"b8b309d63cf41d497b7d89f57ee92dd28d751e8d","_npmUser":{"name":"dereekb","email":"npm@dereekb.com"},"_npmVersion":"11.8.0","description":"Replacement for OpenAI's deprecated reusable Prompt Objects (`v1/prompts`, removed 2026-11-30), built on OpenRouter.","directories":{},"sideEffects":false,"_nodeVersion":"24.13.1","_hasShrinkwrap":false,"devDependencies":{"@dereekb/nestjs":"14.5.0"},"peerDependencies":{"arktype":"^2.2.0","@dereekb/util":"14.5.0","@dereekb/model":"14.5.0","@nestjs/common":"^12.0.1","@openrouter/sdk":"^1.2.26","@dereekb/firebase":"14.5.0","@dereekb/firebase-server":"14.5.0"},"_npmOperationalInternal":{"tmp":"tmp/openrouter_14.5.0_1789522243276_0.2948992841675744","host":"s3://npm-registry-packages-npm-production"}},"14.5.1":{"name":"@dereekb/openrouter","version":"14.5.1","_id":"@dereekb/openrouter@14.5.1","maintainers":[{"name":"dereekb","email":"npm@dereekb.com"}],"dist":{"shasum":"b25a0addfcf40c5587ddda419706d59e86abecdb","tarball":"https://registry.npmjs.org/@dereekb/openrouter/-/openrouter-14.5.1.tgz","fileCount":42,"integrity":"sha512-eEGuP3vLr89PLqPdlsxz3d2VTcx0wdbMIE4N5RLI8MyxpGWLFEh87FNojzGPx4yz3G0iiZnENFoCf+aB9eY7ag==","signatures":[{"sig":"MEUCIFybaHAIRH6hJMMD+Y05hiv0g1ByyUB/LkafieqNT/8LAiEA8nf6aY68QpsrM/CkZpCIAFiGNFypT659bHMckfzZZHo=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEUCIQD8qd1ymTCHLNdgnAcWdZB98hjP5YWQFm2BpE/YHTSLzwIgFwx6GKaGCVPbMYpmdLV0k4Brqagm/gfL4DRA7ZoEyqY=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":512294},"main":"./index.esm.js","type":"module","types":"./index.d.ts","module":"./index.esm.js","exports":{".":{"types":"./index.d.ts","import":"./index.esm.js","default":"./index.esm.js"},"./firebase":{"types":"./firebase/index.d.ts","import":"./firebase/index.esm.js","default":"./firebase/index.esm.js"},"./package.json":"./package.json","./firebase-server":{"types":"./firebase-server/index.d.ts","import":"./firebase-server/index.esm.js","default":"./firebase-server/index.esm.js"}},"gitHead":"ddfffd300bd0b061f4a850b51ba43e77d7aa8d1c","_npmUser":{"name":"dereekb","email":"npm@dereekb.com"},"_npmVersion":"11.8.0","description":"Replacement for OpenAI's deprecated reusable Prompt Objects (`v1/prompts`, removed 2026-11-30), built on OpenRouter.","directories":{},"sideEffects":false,"_nodeVersion":"24.13.1","_hasShrinkwrap":false,"devDependencies":{"@dereekb/nestjs":"14.5.1"},"peerDependencies":{"arktype":"^2.2.0","@dereekb/util":"14.5.1","@dereekb/model":"14.5.1","@nestjs/common":"^12.0.1","@openrouter/sdk":"^1.2.26","@dereekb/firebase":"14.5.1","@dereekb/firebase-server":"14.5.1"},"_npmOperationalInternal":{"tmp":"tmp/openrouter_14.5.1_1789563913250_0.5751136497827707","host":"s3://npm-registry-packages-npm-production"}},"14.6.0":{"name":"@dereekb/openrouter","version":"14.6.0","_id":"@dereekb/openrouter@14.6.0","maintainers":[{"name":"dereekb","email":"npm@dereekb.com"}],"dist":{"shasum":"d82b850344db3a3252cd83b90af3df027e24b6e1","tarball":"https://registry.npmjs.org/@dereekb/openrouter/-/openrouter-14.6.0.tgz","fileCount":42,"integrity":"sha512-m2vFQO7MBzSVgkLA4g3JlD5T3kN95xBQIvBQ+uuS3TBGtyQUuV30C/aDf7OeB0oN7ypjPYdsPRSwjZG5P4ojHw==","signatures":[{"sig":"MEUCIHDNH6iyCZAiSnNgODbfFkqKPRolmh9HU2mVwNmlZKxRAiEAq17j4G8vfs3Vu6dxiC9Xjoztwgx0W1dNuWSgbIbY7dA=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEQCICbXsK8jvr818ob1q+vtmEnL7/3urQeJvlXRHybMDW5SAiBkk6kx0CLrI9rifmymiI9xVHOF/5tAGUEYUAvHg1Bayg==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":512294},"main":"./index.esm.js","type":"module","types":"./index.d.ts","module":"./index.esm.js","exports":{".":{"types":"./index.d.ts","import":"./index.esm.js","default":"./index.esm.js"},"./firebase":{"types":"./firebase/index.d.ts","import":"./firebase/index.esm.js","default":"./firebase/index.esm.js"},"./package.json":"./package.json","./firebase-server":{"types":"./firebase-server/index.d.ts","import":"./firebase-server/index.esm.js","default":"./firebase-server/index.esm.js"}},"gitHead":"3306e8121108f017cf7764cb0388bcd54779fc2e","_npmUser":{"name":"dereekb","email":"npm@dereekb.com"},"_npmVersion":"11.8.0","description":"Replacement for OpenAI's deprecated reusable Prompt Objects (`v1/prompts`, removed 2026-11-30), built on OpenRouter.","directories":{},"sideEffects":false,"_nodeVersion":"24.13.1","_hasShrinkwrap":false,"devDependencies":{"@dereekb/nestjs":"14.6.0"},"peerDependencies":{"arktype":"^2.2.0","@dereekb/util":"14.6.0","@dereekb/model":"14.6.0","@nestjs/common":"^12.0.1","@openrouter/sdk":"^1.2.26","@dereekb/firebase":"14.6.0","@dereekb/firebase-server":"14.6.0"},"_npmOperationalInternal":{"tmp":"tmp/openrouter_14.6.0_1789763771790_0.19350210330302997","host":"s3://npm-registry-packages-npm-production"}},"14.7.0":{"name":"@dereekb/openrouter","version":"14.7.0","_id":"@dereekb/openrouter@14.7.0","maintainers":[{"name":"dereekb","email":"npm@dereekb.com"}],"dist":{"shasum":"87b7ddd0d870202bf52cea168337772c4269d143","tarball":"https://registry.npmjs.org/@dereekb/openrouter/-/openrouter-14.7.0.tgz","fileCount":42,"integrity":"sha512-r78lw1FhMUyvHiVNntqNgZ2FXjeh1RyOAZgcMRmX6R9QVNIO4+tcUcEfPKBLyAjPdH8hk51aOfOAW5W4eBcb0A==","signatures":[{"sig":"MEUCIQC3s5G8mS+nyQObK8rRtwiI0EG2h5bsVLYuq4NpkzIIhAIgNxIhtg0mV2z2Gn79wqgiXC+fkZvC5M434RtDRFXwAok=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEYCIQCJiDzM6Yo+bKAPQHDLKDCAsTEoQGFA/PrcoD+Pki6jRwIhAOXMdTFd1DIpH3jpadp9OrtIp3BRTOn7k9vrRRkbsdMy","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":512292},"main":"./index.esm.js","type":"module","types":"./index.d.ts","module":"./index.esm.js","exports":{".":{"types":"./index.d.ts","import":"./index.esm.js","default":"./index.esm.js"},"./firebase":{"types":"./firebase/index.d.ts","import":"./firebase/index.esm.js","default":"./firebase/index.esm.js"},"./package.json":"./package.json","./firebase-server":{"types":"./firebase-server/index.d.ts","import":"./firebase-server/index.esm.js","default":"./firebase-server/index.esm.js"}},"gitHead":"d0d2c67ed0cd89c7f687a0bf0a3ba33cb4910c9e","_npmUser":{"name":"dereekb","email":"npm@dereekb.com"},"_npmVersion":"11.8.0","description":"Replacement for OpenAI's deprecated reusable Prompt Objects (`v1/prompts`, removed 2026-11-30), built on OpenRouter.","directories":{},"sideEffects":false,"_nodeVersion":"24.13.1","_hasShrinkwrap":false,"devDependencies":{"@dereekb/nestjs":"14.7.0"},"peerDependencies":{"arktype":"^2.2.0","@dereekb/util":"14.7.0","@dereekb/model":"14.7.0","@nestjs/common":"^12.0.1","@openrouter/sdk":"^1.3.0","@dereekb/firebase":"14.7.0","@dereekb/firebase-server":"14.7.0"},"_npmOperationalInternal":{"tmp":"tmp/openrouter_14.7.0_1790094684065_0.0648545782284573","host":"s3://npm-registry-packages-npm-production"}},"14.8.0":{"name":"@dereekb/openrouter","version":"14.8.0","_id":"@dereekb/openrouter@14.8.0","maintainers":[{"name":"dereekb","email":"npm@dereekb.com"}],"dist":{"shasum":"342cd1a80c03427cf6fa830c146dca478a5a3a10","tarball":"https://registry.npmjs.org/@dereekb/openrouter/-/openrouter-14.8.0.tgz","fileCount":44,"integrity":"sha512-/mRNKkIF1UBVBxAA2JHoHRwpTnqRpD8gFw8ArxPUbjzb3qowIwCZojMLpW/EH4fPZdPkY0DIhWmjWkpY/sDNJA==","signatures":[{"sig":"MEUCIQCd+gV/LCK8AWaM0PGIr4tBqrm31A+IsA7ikGipOez4uQIgGINYuBwhjDWbqqoviAk0h4o6qNB2UVOr7c5lTwIVqJM=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEUCIHkkjCVq/ENxg++WwBBoGFfnP0WMzAwzph5qf4uD7PjgAiEAviKdvzRFqobqcAUYzsocTyxTdnSZa0cGcSDGyAWmMsQ=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":655662},"main":"./index.esm.js","type":"module","types":"./index.d.ts","module":"./index.esm.js","exports":{".":{"types":"./index.d.ts","import":"./index.esm.js","default":"./index.esm.js"},"./firebase":{"types":"./firebase/index.d.ts","import":"./firebase/index.esm.js","default":"./firebase/index.esm.js"},"./package.json":"./package.json","./firebase-server":{"types":"./firebase-server/index.d.ts","import":"./firebase-server/index.esm.js","default":"./firebase-server/index.esm.js"}},"gitHead":"d14212333af79270e4efc649b96ba7832943662a","_npmUser":{"name":"dereekb","email":"npm@dereekb.com"},"_npmVersion":"11.8.0","description":"Replacement for OpenAI's deprecated reusable Prompt Objects (`v1/prompts`, removed 2026-11-30), built on OpenRouter.","directories":{},"sideEffects":false,"_nodeVersion":"24.13.1","_hasShrinkwrap":false,"devDependencies":{"@dereekb/nestjs":"14.8.0"},"peerDependencies":{"arktype":"^2.2.0","@dereekb/util":"14.8.0","@dereekb/model":"14.8.0","@nestjs/common":"^12.0.1","@openrouter/sdk":"^1.3.8","@dereekb/firebase":"14.8.0","@dereekb/firebase-server":"14.8.0"},"_npmOperationalInternal":{"tmp":"tmp/openrouter_14.8.0_1790108060705_0.7266724393630861","host":"s3://npm-registry-packages-npm-production"}},"14.9.0":{"name":"@dereekb/openrouter","version":"14.9.0","_id":"@dereekb/openrouter@14.9.0","maintainers":[{"name":"dereekb","email":"npm@dereekb.com"}],"dist":{"shasum":"838e167458b416c397d015d755ab04030c8c71bf","tarball":"https://registry.npmjs.org/@dereekb/openrouter/-/openrouter-14.9.0.tgz","fileCount":49,"integrity":"sha512-kbLmcKMH02huUW3b70WxKIZOVz+GV7yrg92VuI1xRlqjkFOFmMDblStyT7Lg5r8R6F5Vo0UWBATqA78q5/FVDA==","signatures":[{"sig":"MEUCIG6L9TlE5FMyzBFx8eplEComGcCNGCwzLiUzn7X3HHArAiEAmp3COKWPiceGmRGeO7M6WiF78bwtl9P7XCRb1KpNXKw=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEUCIAWzsTD5OkADB3ysoRqUVhnDW8WaggwezEZqAsmjyDogAiEAv5R1C8yAZC4FWVGZ+KKHplbYNujp2kpMOfGDW+CwngI=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":665048},"main":"./index.esm.js","type":"module","types":"./index.d.ts","module":"./index.esm.js","exports":{".":{"types":"./index.d.ts","import":"./index.esm.js","default":"./index.esm.js"},"./decision":{"types":"./decision.d.ts","import":"./decision.esm.js","default":"./decision.esm.js"},"./firebase":{"types":"./firebase/index.d.ts","import":"./firebase/index.esm.js","default":"./firebase/index.esm.js"},"./package.json":"./package.json","./firebase-server":{"types":"./firebase-server/index.d.ts","import":"./firebase-server/index.esm.js","default":"./firebase-server/index.esm.js"}},"gitHead":"125b29398be5736ba8f5f3a36d36c88f7fb790aa","_npmUser":{"name":"dereekb","email":"npm@dereekb.com"},"_npmVersion":"11.12.1","description":"Replacement for OpenAI's deprecated reusable Prompt Objects (`v1/prompts`, removed 2026-11-30), built on OpenRouter.","directories":{},"sideEffects":false,"_nodeVersion":"24.15.0","_hasShrinkwrap":false,"devDependencies":{"@dereekb/nestjs":"14.9.0"},"peerDependencies":{"arktype":"^2.2.0","@dereekb/util":"14.9.0","@dereekb/model":"14.9.0","@nestjs/common":"^12.0.1","@openrouter/sdk":"^1.3.8","@dereekb/firebase":"14.9.0","@dereekb/firebase-server":"14.9.0"},"_npmOperationalInternal":{"tmp":"tmp/openrouter_14.9.0_1790185589355_0.2040813018106713","host":"s3://npm-registry-packages-npm-production"}},"14.10.0":{"name":"@dereekb/openrouter","version":"14.10.0","_id":"@dereekb/openrouter@14.10.0","maintainers":[{"name":"dereekb","email":"npm@dereekb.com"}],"dist":{"shasum":"784858234be28e0b6e3ab983bd13e48bbfa7db24","tarball":"https://registry.npmjs.org/@dereekb/openrouter/-/openrouter-14.10.0.tgz","fileCount":49,"integrity":"sha512-NIsDE/aMmsJbXWdzgWtwqvTHsJS52bSz1Wkkx1abkQjL5AJP92K9iPM+V4MzqhhXaaPohGxJb5dxBQYXJqUEsw==","signatures":[{"sig":"MEQCIHzeSDUfJlTrBUw277cMB4Ug19ALQebptRDDBE6A2GS/AiBfwgsF7rHWYABnYoXdFHqmwNtDEx1xnCtP13b6ufCDbw==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEYCIQD1NX5QUi6AcYVg6+mRi7cX5My3QgQ4IvURAiMlv+uLvwIhALdSpw3LWVHAiXKPuOk93NZiZakARbPIVucG9injYKnr","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":665072},"main":"./index.esm.js","type":"module","types":"./index.d.ts","module":"./index.esm.js","exports":{".":{"types":"./index.d.ts","import":"./index.esm.js","default":"./index.esm.js"},"./decision":{"types":"./decision.d.ts","import":"./decision.esm.js","default":"./decision.esm.js"},"./firebase":{"types":"./firebase/index.d.ts","import":"./firebase/index.esm.js","default":"./firebase/index.esm.js"},"./package.json":"./package.json","./firebase-server":{"types":"./firebase-server/index.d.ts","import":"./firebase-server/index.esm.js","default":"./firebase-server/index.esm.js"}},"gitHead":"50862eb1b2cfbe1f98cda037b6c40809fc2d2420","_npmUser":{"name":"dereekb","email":"npm@dereekb.com"},"_npmVersion":"11.12.1","description":"Replacement for OpenAI's deprecated reusable Prompt Objects (`v1/prompts`, removed 2026-11-30), built on OpenRouter.","directories":{},"sideEffects":false,"_nodeVersion":"24.15.0","_hasShrinkwrap":false,"devDependencies":{"@dereekb/nestjs":"14.10.0"},"peerDependencies":{"arktype":"^2.2.0","@dereekb/util":"14.10.0","@dereekb/model":"14.10.0","@nestjs/common":"^12.0.1","@openrouter/sdk":"^1.3.8","@dereekb/firebase":"14.10.0","@dereekb/firebase-server":"14.10.0"},"_npmOperationalInternal":{"tmp":"tmp/openrouter_14.10.0_1790438643963_0.3730147492525311","host":"s3://npm-registry-packages-npm-production"}},"14.11.0":{"name":"@dereekb/openrouter","version":"14.11.0","_id":"@dereekb/openrouter@14.11.0","maintainers":[{"name":"dereekb","email":"npm@dereekb.com"}],"dist":{"shasum":"e792ba7c7dc95e593db7e69082e0ba5127a4f009","tarball":"https://registry.npmjs.org/@dereekb/openrouter/-/openrouter-14.11.0.tgz","fileCount":49,"integrity":"sha512-XmGt08aY3ZAdKM0iYQBOOofgVMku4GVRMnR7yQ5A45LTRL/9lcr39E++N8C7coZhk0HGIU9puINwqugHC9HkRQ==","signatures":[{"sig":"MEUCIQDWlHzqzQ5thZeeqaXQa7tPfbpFwazokWz6kpghrJ036QIgDwadTpvdDOjbLrjpy6rFdtIE9qaSJWM6tGv/axxqodo=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEUCIQDFLgVTPE4fmXWalI0pwIwHb4o8nDSf1hvuGQvSDXYxSAIgWAVek2erroIf4OPV7YNnjrT2pMDADgL0cBjEAY4WKpw=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":665072},"main":"./index.esm.js","type":"module","types":"./index.d.ts","module":"./index.esm.js","exports":{".":{"types":"./index.d.ts","import":"./index.esm.js","default":"./index.esm.js"},"./decision":{"types":"./decision.d.ts","import":"./decision.esm.js","default":"./decision.esm.js"},"./firebase":{"types":"./firebase/index.d.ts","import":"./firebase/index.esm.js","default":"./firebase/index.esm.js"},"./package.json":"./package.json","./firebase-server":{"types":"./firebase-server/index.d.ts","import":"./firebase-server/index.esm.js","default":"./firebase-server/index.esm.js"}},"gitHead":"ee8951a117d0d7ce22fc3ea088e633126fd387dd","_npmUser":{"name":"dereekb","email":"npm@dereekb.com"},"_npmVersion":"11.8.0","description":"Replacement for OpenAI's deprecated reusable Prompt Objects (`v1/prompts`, removed 2026-11-30), built on OpenRouter.","directories":{},"sideEffects":false,"_nodeVersion":"24.13.1","_hasShrinkwrap":false,"devDependencies":{"@dereekb/nestjs":"14.11.0"},"peerDependencies":{"arktype":"^2.2.0","@dereekb/util":"14.11.0","@dereekb/model":"14.11.0","@nestjs/common":"^12.0.1","@openrouter/sdk":"^1.3.8","@dereekb/firebase":"14.11.0","@dereekb/firebase-server":"14.11.0"},"_npmOperationalInternal":{"tmp":"tmp/openrouter_14.11.0_1790618574809_0.6447968662198569","host":"s3://npm-registry-packages-npm-production"}},"14.12.0":{"name":"@dereekb/openrouter","version":"14.12.0","_id":"@dereekb/openrouter@14.12.0","maintainers":[{"name":"dereekb","email":"npm@dereekb.com"}],"dist":{"shasum":"f343b66a7ae2599c5852f46eaf7e83ec0658330e","tarball":"https://registry.npmjs.org/@dereekb/openrouter/-/openrouter-14.12.0.tgz","fileCount":49,"integrity":"sha512-NBgxLjbBBDS6Lh4FwdSfiPqMiaWRobWTRj1BwVK2eJuXa7bbvXlXH9IdewzqMmRiQWX3fOyj/b94/sEjROsvhw==","signatures":[{"sig":"MEYCIQC2CQNyMfrlg9NAhwKvG46NReRXehjCs2z/ApqMOBloPwIhAMLaOOmKldWl0k30xJZsp1IoP9TXImDUpLrnQHtuXQdl","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEQCIGzDjoZUZsV1xM2y9Lm5w54eguYysOrdVkftFDuNkng+AiA4R5MKLlH4PeMx9vZmpiC1oCrHH1qmtZakps4jL+IpNQ==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":665072},"main":"./index.esm.js","type":"module","types":"./index.d.ts","module":"./index.esm.js","exports":{".":{"types":"./index.d.ts","import":"./index.esm.js","default":"./index.esm.js"},"./decision":{"types":"./decision.d.ts","import":"./decision.esm.js","default":"./decision.esm.js"},"./firebase":{"types":"./firebase/index.d.ts","import":"./firebase/index.esm.js","default":"./firebase/index.esm.js"},"./package.json":"./package.json","./firebase-server":{"types":"./firebase-server/index.d.ts","import":"./firebase-server/index.esm.js","default":"./firebase-server/index.esm.js"}},"gitHead":"a98b3276d913ad8cdab17e2da9012247c87a1016","_npmUser":{"name":"dereekb","email":"npm@dereekb.com"},"_npmVersion":"11.8.0","description":"Replacement for OpenAI's deprecated reusable Prompt Objects (`v1/prompts`, removed 2026-11-30), built on OpenRouter.","directories":{},"sideEffects":false,"_nodeVersion":"24.13.1","_hasShrinkwrap":false,"devDependencies":{"@dereekb/nestjs":"14.12.0"},"peerDependencies":{"arktype":"^2.2.0","@dereekb/util":"14.12.0","@dereekb/model":"14.12.0","@nestjs/common":"^12.0.1","@openrouter/sdk":"^1.3.8","@dereekb/firebase":"14.12.0","@dereekb/firebase-server":"14.12.0"},"_npmOperationalInternal":{"tmp":"tmp/openrouter_14.12.0_1790682942653_0.9998912539421834","host":"s3://npm-registry-packages-npm-production"}},"14.13.0":{"name":"@dereekb/openrouter","version":"14.13.0","_id":"@dereekb/openrouter@14.13.0","maintainers":[{"name":"dereekb","email":"npm@dereekb.com"}],"dist":{"shasum":"5f9a9e091a365b5333466001b8fdcbcb6f85ef50","tarball":"https://registry.npmjs.org/@dereekb/openrouter/-/openrouter-14.13.0.tgz","fileCount":49,"integrity":"sha512-jWAbXWZhKgCns2NF1oavmB86nGTSAdzReUFyp9OWEGEdqknZX7LpsTwm0ZzSVPBueb9uNIlK5nIwgEMAF+/xjg==","signatures":[{"sig":"MEQCIC/P/yfeauYvNoDx9HdwXzSznGhgLZDcTpTaZ2Ul7S+XAiBshqzSx9y1NfJ67G9Ig/GB+kw3a6vgiwgPRcZvk9S5rw==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEQCIBsdr/awFdBwX5Gpmw7ryLG07gyhv7B5bH+EwKRs2QOgAiBmrNjOeLI63yKemixjGbTOMY0q2ZvabejR7NlXIZs8wA==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":665072},"main":"./index.esm.js","type":"module","types":"./index.d.ts","module":"./index.esm.js","exports":{".":{"types":"./index.d.ts","import":"./index.esm.js","default":"./index.esm.js"},"./decision":{"types":"./decision.d.ts","import":"./decision.esm.js","default":"./decision.esm.js"},"./firebase":{"types":"./firebase/index.d.ts","import":"./firebase/index.esm.js","default":"./firebase/index.esm.js"},"./package.json":"./package.json","./firebase-server":{"types":"./firebase-server/index.d.ts","import":"./firebase-server/index.esm.js","default":"./firebase-server/index.esm.js"}},"gitHead":"9a16ba8a74afd3c31143fff115393704a3115810","_npmUser":{"name":"dereekb","email":"npm@dereekb.com"},"_npmVersion":"11.8.0","description":"Replacement for OpenAI's deprecated reusable Prompt Objects (`v1/prompts`, removed 2026-11-30), built on OpenRouter.","directories":{},"sideEffects":false,"_nodeVersion":"24.13.1","_hasShrinkwrap":false,"devDependencies":{"@dereekb/nestjs":"14.13.0"},"peerDependencies":{"arktype":"^2.2.0","@dereekb/util":"14.13.0","@dereekb/model":"14.13.0","@nestjs/common":"^12.0.1","@openrouter/sdk":"^1.3.8","@dereekb/firebase":"14.13.0","@dereekb/firebase-server":"14.13.0"},"_npmOperationalInternal":{"tmp":"tmp/openrouter_14.13.0_1790707774649_0.8833500191197488","host":"s3://npm-registry-packages-npm-production"}},"14.14.0":{"_id":"@dereekb/openrouter@14.14.0","dist":{"shasum":"4db9a314b7746aa83d2aff04d16797b05c04e973","tarball":"https://registry.npmjs.org/@dereekb/openrouter/-/openrouter-14.14.0.tgz","fileCount":49,"integrity":"sha512-SLb+hERhPwItWVJ5A1x41Mqe8JAcwbsLuBZ0+4AcvWppULa5AQ5kltdZQfC+VNq9e5yz0vo2aJT2Bdwx2f5quw==","signatures":[{"sig":"MEQCID7P8KoZQa0UKpqs9c9HIAHX5J+rAXpiuqQxqq9nigyoAiAQvxOwq8XsbOEItklvG2GQE++W5qlpcyWLihdYewZfkA==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEQCIB5h9dXmmz507FuEH8HA5kFZj95jVH4u3cguiRCJAkwlAiBgK2Y+zJeq2P+/+uC7dIGoh2GT4Cj68JATIzIEPYbINg=="}],"unpackedSize":665072},"main":"./index.esm.js","name":"@dereekb/openrouter","type":"module","types":"./index.d.ts","module":"./index.esm.js","exports":{".":{"types":"./index.d.ts","import":"./index.esm.js","default":"./index.esm.js"},"./decision":{"types":"./decision.d.ts","import":"./decision.esm.js","default":"./decision.esm.js"},"./firebase":{"types":"./firebase/index.d.ts","import":"./firebase/index.esm.js","default":"./firebase/index.esm.js"},"./package.json":"./package.json","./firebase-server":{"types":"./firebase-server/index.d.ts","import":"./firebase-server/index.esm.js","default":"./firebase-server/index.esm.js"}},"gitHead":"6680f24ca430cf12ac58bb20eb0cd759dac75ce8","version":"14.14.0","_npmUser":{"name":"dereekb","email":"npm@dereekb.com"},"_npmVersion":"11.8.0","description":"Replacement for OpenAI's deprecated reusable Prompt Objects (`v1/prompts`, removed 2026-11-30), built on OpenRouter.","directories":{},"maintainers":[{"name":"dereekb","email":"npm@dereekb.com"}],"sideEffects":false,"_nodeVersion":"24.13.1","_hasShrinkwrap":false,"devDependencies":{"@dereekb/nestjs":"14.14.0"},"peerDependencies":{"arktype":"^2.2.0","@dereekb/util":"14.14.0","@dereekb/model":"14.14.0","@nestjs/common":"^12.0.1","@openrouter/sdk":"^1.3.8","@dereekb/firebase":"14.14.0","@dereekb/firebase-server":"14.14.0"},"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/openrouter_14.14.0_1790821464547_0.038482458914243844"}}},"time":{"created":"2026-08-18T12:29:14.218Z","modified":"2026-10-01T02:24:24.837Z","13.37.0":"2026-08-18T12:29:14.602Z","13.38.0":"2026-08-20T16:54:53.392Z","13.39.0":"2026-08-21T17:25:28.360Z","13.40.0":"2026-08-22T15:01:23.462Z","13.41.0":"2026-08-22T19:27:12.495Z","13.42.0":"2026-08-28T14:52:48.668Z","13.43.0":"2026-09-01T14:42:08.452Z","14.0.0":"2026-09-03T14:03:41.953Z","14.0.1":"2026-09-04T02:42:26.390Z","14.1.0":"2026-09-07T20:12:14.263Z","14.2.0":"2026-09-11T17:25:25.136Z","14.3.0":"2026-09-12T20:33:35.052Z","14.4.0":"2026-09-14T02:16:18.692Z","14.5.0":"2026-09-16T01:30:43.397Z","14.5.1":"2026-09-16T13:05:13.382Z","14.6.0":"2026-09-18T20:36:11.929Z","14.7.0":"2026-09-22T16:31:24.206Z","14.8.0":"2026-09-22T20:14:20.806Z","14.9.0":"2026-09-23T17:46:29.847Z","14.10.0":"2026-09-26T16:04:04.082Z","14.11.0":"2026-09-28T18:02:54.929Z","14.12.0":"2026-09-29T11:55:42.747Z","14.13.0":"2026-09-29T18:49:34.723Z","14.14.0":"2026-10-01T02:24:24.680Z"},"description":"Replacement for OpenAI's deprecated reusable Prompt Objects (`v1/prompts`, removed 2026-11-30), built on OpenRouter.","maintainers":[{"name":"dereekb","email":"npm@dereekb.com"}],"readme":"# @dereekb/openrouter\n\nReplacement for OpenAI's deprecated reusable Prompt Objects (`v1/prompts`, removed 2026-11-30), built\non OpenRouter.\n\nOpenRouter is **stateless** — `store` is type-pinned to `false`, there is no `background: true`, no\nserver-side job store, and `previous_response_id` is rejected. Everything OpenAI used to do on their\nside is therefore done here: prompt content and model config live in Firestore (git-adjacent and\nMCP-editable rather than hidden in a dashboard), and asynchronous execution is an app-owned run-task\nqueue drained by a sweeper the app mounts on a schedule it already runs.\n\n## Entry points\n\n| Entry | Purpose |\n|---|---|\n| `@dereekb/openrouter` | Config types, request builder, `callModel` wrapper, deferred-tool helpers, embeddings, **decisions**. Pure — no I/O. |\n| `@dereekb/openrouter/decision` | The decision layer WITHOUT `@openrouter/sdk`: questions, validation, the request body, the answer reader, model ids. See [below](#loading-without-the-sdk). |\n| `@dereekb/openrouter/firebase` | The `OpenRouterPrompt`, `OpenRouterPromptVersion` and `OpenRouterRunTask` models. |\n| `@dereekb/openrouter/firebase-server` | Prompt service, run-task queue + sweep, Firestore `StateAccessor`, server actions. |\n\nThe raw OpenRouter client (`OpenRouterApi`) and the OTLP broadcast webhook live in\n`@dereekb/nestjs/openrouter`; this package builds on them rather than duplicating them.\n\n## Execution model\n\n1. **Enqueue** — `enqueueRunTask({ key, promptKey, input })` writes one Firestore doc with\n   `s: QUEUED` and returns. One write, nothing blocks.\n2. **Drain** — `openRouterRunTaskSweep(...)` claims a page of `QUEUED` tasks by lease in **`qat` order**,\n   runs them `maxParallelTasks` at a time, writes results, and stops claiming new pages once its\n   `maxRunTimeMs` budget is spent. Unclaimed work stays `QUEUED` for the next tick. Mount it on a\n   per-minute-ish schedule the app already runs.\n3. **Consume** — `readRunTask(key)` → `COMPLETE` uses the output, `QUEUED`/`RUNNING` retries later,\n   `FAILED` takes the failure path.\n4. **Expire** — `openRouterRunTaskExpirationSweep(...)` deletes every task queued more than\n   `OPENROUTER_RUN_TASK_MAX_AGE` (**7 days**) ago, **in any state, `RUNNING` included**. Its own, far\n   slower schedule — hourly is plenty. Nothing lives past the ceiling, and there is no per-task\n   expiration field to set or forget: a queued task runs essentially immediately, so `qat` *is* its age.\n\nRetries are classified rather than uniform: a transient failure (429, 5xx, `ECONNRESET`, a Firestore\n`UNAVAILABLE`) spends the `maxAttempts` budget, while a deterministic one (400, 401, 402, 403, 404, a\nprompt that does not resolve) reaches `FAILED` on its first attempt instead of burning three sweep ticks\nto reach the same answer. Anything unrecognized is treated as transient.\n\nThere is no replay. `enqueueRunTask({ key, …, restart: true })` re-runs a key, and `continueFrom` chains\none run onto another's history.\n\nShort calls skip all of it: `callModelForPrompt(...)` runs inline and returns the result with no\ndocument.\n\n## Decisions (System One / Jev)\n\nOpenRouter has **two** inference surfaces, and this package serves both. `/responses` asks a model for\nprose and validates the reply back into a shape. **System One** (`POST /systemone`, the `typesafe/jev-*`\nmodels) inverts that: the caller declares the answer space up front as typed questions, and the model\nreturns a position inside it plus a calibrated distribution. `(state, questions) → answers`. There is no\nreply to parse, so there is no off-shape reply to recover from.\n\nThree primitives, and no others:\n\n| Primitive | Asks | Answers |\n|---|---|---|\n| `openRouterChoiceQuestion(instructions, options)` | which of these options? | `choice`, guaranteed one of the declared options; `probabilities` over every option summing to 1 (a free full ranking); `confidence` |\n| `openRouterScoreQuestion(instructions, levels)` | which level on this rubric? | a `score` that may land BETWEEN two levels, the distribution, `confidence` |\n| `openRouterNoulQuestion(instructions, means?)` | is this true? | `noul` 0..1 — the probability IS the uncertainty, so there is no separate confidence |\n\n```ts\nconst questions = {\n  team: openRouterChoiceQuestion('Which team should own `ticket`?', {\n    billing: { what: 'Charges, invoices, refunds', not_for: 'Anything about signing in' },\n    access: { what: 'Sign-in, passwords, permissions', not_for: 'Anything about money' },\n    other: { what: 'Anything the other options do not cover' }\n  }),\n  spam: openRouterNoulQuestion('`ticket` is unsolicited marketing rather than a real request.')\n};\n\nconst result = await decideForPrompt({ client, promptService, promptKey: 'demo-support-triage', state: { ticket } });\nresult.answers.team.choice;   // typed to the declared option names\nresult.answers.spam.noul;     // 0..1\n```\n\n**Declare every question one state could need in ONE call.** Each is evaluated independently against the\nsame state, so the question map is both the batching unit and the cost unit: the state is sent and billed\nonce, and a speculative question the caller may discard costs only its own tokens.\n\n**Membership is the transport's guarantee.** `readOpenRouterDecisionAnswers` checks every answer against\nthe question that asked it, so no consumer re-checks: past that point a `choice` is one of the declared\noptions, a `score` is inside the declared range, a `noul` is a probability. An answer that left its space\nraises `OpenRouterDecisionAnswerFaultError` — a defect in the RESPONSE, never a judgement the model made.\n\"None of these fits\" is said through a Noul the caller declared for it, and lands as an *answer*.\n\nA Choice is only ever RELATIVE — its probabilities are normalised over the options supplied, so something\nalways wins even when nothing fits. When \"nothing fits\" is an outcome you act on, pair it with a Noul,\nwhich is absolute and may be low for every option.\n\n### Writing a question\n\n- **One snap judgement per question.** A judgement weighing several factors is several questions combined\n  in your own code.\n- **Write the COMPLETE question in `instructions`** — the question id is never sent, so a descriptive key\n  is no substitute. A blank one is refused at declaration.\n- **Point at named state with backticked dot-paths** — `` `phrase` ``, `` `ticket.sender.email` ``,\n  `` `messages[0].text` ``. Prefer an object state so each part has a name to point at.\n  `openRouterDecisionStatePaths` reads them back so a spec can pin that a declaration names keys its\n  state has (documented and inspectable, never enforced — backticks also quote literals).\n- **Score levels are SITUATIONS, not degrees.** \"Broken feature, but a workaround exists\" gives the model\n  something to match against; \"moderately severe\" does not. Every level is evaluated separately and the\n  model never sees a level's number or its neighbours, so numbers in the descriptions do not help.\n- **Choice options are CONTRASTIVE** — the same keys on every option (`{what, not_for, examples}`) so the\n  model compares like with like. Include an explicit `other` when the set may not cover the input.\n- **Filter in code first.** Accuracy falls as a state grows with material unrelated to the decision; a\n  wide state is not a free hedge.\n\nEvery declaration surface takes `string | object | array` and the wire carries it VERBATIM — start with\nstrings, and reach for structure only for guidance prose would blur or for data that is already JSON.\n\n### Limits, enforced at declaration\n\n| Limit | Value | Past it |\n|---|---|---|\n| Choice options | ≤ 255 | Narrow in two stages. Never truncate — an option removed is one the model can never pick, and nothing reports it was missing. |\n| Score levels | 2 .. 10 | MERGE the levels that cannot be told apart. The trap: a 0..8 band is nine levels and legal, a 0..10 scale is eleven and 400s at the wire. |\n| Context | 64k tokens per request | Filter in code first. |\n| Price | $0.042 / Mtok input; output reported but **not billed** | `usage.cost` is synchronous and final. |\n\n`validateOpenRouterDecisionQuestions` fails at the DECLARATION, naming the question — not as a 4xx about\na request body — and runs at version create / update / seed, so a malformed question map is refused when\nit is written rather than every time it is asked.\n\n### Routing: the model id is the discriminator\n\nSystem One models are **not listed by `GET /models`**, so nothing can be learned about one from the\ncatalog, and a wrong guess does not produce an error anyone can read. The slug is therefore checked on\n**both** arms and neither can be entered with the other's model:\n\n- `validateOpenRouterModelConfig(config)` errors on a `typesafe/…` slug, naming `openRouterDecision`.\n  It already runs at publish time, so a Jev slug typed into a stored version is refused when written.\n- `validateOpenRouterModelConfig(config, { decision: true })` errors on a chat slug.\n- `openRouterResponsesRequestBody` throws `OpenRouterSystemOneModelOnCompletionArmError`. It is the one\n  point every completion dispatch path builds its body, so no route can be added later that skips it.\n\n`OPENROUTER_JEV_1_13_MODEL_ID` is a **versioned** slug, deliberately not the moving `jev-latest` alias:\nan answer is only reproducible against the model that gave it, which is the same reason versions exist.\nThe reply reports the model that actually served it (`typesafe/jev-1.13-20260917`), so read `result.model`\nrather than assuming the slug you asked for.\n\n### Loading without the SDK\n\nThe root entry re-exports SDK values (`callModel`, `responsesSend`, `systemOneCreate`, …), so importing\nANY value from `@dereekb/openrouter` evaluates `@openrouter/sdk` — a real cold-start cost, and one a test\nrunner that isolates each spec file pays once per file. `@dereekb/openrouter/decision` carries everything a\ndecision is built from and read with, and loads nothing under `@openrouter/sdk`:\n\n- `openRouterChoiceQuestion` / `openRouterScoreQuestion` / `openRouterNoulQuestion`, the answer and\n  confidence helpers, and `validateOpenRouterDecisionQuestions`;\n- `openRouterDecisionRequest`, `openRouterDecisionRequestBody` (the `/systemone` body, wire mapping\n  included), `readOpenRouterDecisionAnswers` and its `OpenRouterDecisionAnswerFaultError`,\n  `openRouterRunUsageFromDecisionsUsage`, `validateOpenRouterDecisionRequest`;\n- the model config and the model ids, `isOpenRouterSystemOneModelId` among them.\n\nWhat it does NOT carry is `openRouterDecision` — the transport, and the one `systemOneCreate` caller. A\nconsumer that owns its transport (its own timeout, retry policy or error shape) builds the body here, sends\nit through its own lazily-loaded client, and reads the reply here. The two entries share one built chunk,\nso a class has one identity whichever entry it was imported through.\n\n### Where a decision lives\n\nA decision prompt is an ordinary `OpenRouterPrompt` whose version carries `q` (questions) instead of\n`m` (messages), and whose config names a System One model. The two are mutually exclusive — a decision\nhas no prose output for instructions and seed messages to shape.\n\nStored questions are the STATIC half of the answer space; a caller may declare further questions per call\nand they merge over the stored ones by id. That is what lets a fixed taxonomy be tuned by an operator\nwhile a per-call candidate set still comes from code.\n\n| Call | When |\n|---|---|\n| `decideForPrompt(...)` | The default. No document, no sweep — a Jev call answers in about a hundred milliseconds, has no tools and nothing to defer, so the queue buys nothing on the happy path. |\n| `enqueueRunTask({ state, questions, immediate: true })` | When a FAILURE has to survive this process. Same run-it-now latency, plus a document: a retryable failure (OpenRouter down, a 429) is left QUEUED for the sweep, and a deterministic one still reaches FAILED on the first attempt. |\n\n`immediate` writes the document either way, so `readRunTask(key)` behaves the same whether or not the\ninline attempt succeeded — which is the point of it being a queue flag rather than a second inline call.\nIt is not decisions-specific; a completion run can use it too.\n\n## Store-locking a prompt\n\n`storeLocked` (`sl`) on an `OpenRouterPrompt` says the STORE owns this prompt's content: a code\ndefinition can neither seed it nor overtake it. It is the counterpart of a version's `lk` — that locks a\nversion against edits, this locks a prompt against its own definition — and it applies to any prompt,\nnot just a decision.\n\nSet it on a prompt whose content is maintained at runtime. A decision is the motivating case, because its\nquestions are exactly the thing an operator tunes, and a later `version` bump in code would otherwise\npublish straight over that work.\n\n- **Seeding** skips a locked prompt and says so in the run's `warnings`, beside the existing rule that\n  never resurrects an `ARCHIVED` one.\n- **Resolution** stops preferring a definition whose version has moved ahead of the store.\n- It is deliberately **lenient**: a definition may still STAND IN when the store holds no version at all,\n  which is what keeps a fresh emulator or a never-seeded project able to serve the prompt with no manual\n  step. The lock prevents being *overwritten*, not being served.\n\nTurn it on through `openRouterPrompt.update`, or declare `storeLocked` on a definition to set it when the\nprompt is first created. A definition cannot lock a prompt it did not create — that would let code seize\none an operator is already maintaining.\n\n## Managing prompts\n\nThere is deliberately no Angular UI for prompt authoring. Declaring the CRUD is what makes every prompt\noperation reachable over a consuming app's existing callModel surface — its CLI and the callModel MCP —\ninstead of requiring a screen.\n\n| Operation | What it does |\n|---|---|\n| `openRouterPrompt.read` | The prompt plus **the version it actually serves**. |\n| `openRouterPrompt.query` | Page the collection, optionally filtered by lifecycle state. |\n| `openRouterPrompt.update` | Metadata, lifecycle state, and which version is active. |\n| `openRouterPromptVersion.create` | Publish a version. Allocates its number and locks the one it succeeds. |\n| `openRouterPromptVersion.update` | Edit the head version in place. Refuses a locked one. |\n\nA prompt has no `create`: it comes into existence server-side from a seed against an\n`OpenRouterPromptDefinition` the app already ships. Seeding is not CRUD either — exposing it would hand\nany admin a button that rewrites prompt pointers.\n\n**Prefer `read` over `model-get`.** Both models are registered model services, so either document is\nfetchable by key, but the prompt document holds only pointers (`av`, `lv`) and none of what the prompt\nsays. Following them by hand means addressing the version subcollection at a zero-padded id, and still\nmisses the definition fallback. `read` resolves, and reports `source: 'store' | 'definition'` so the\nprecedence rule is observable rather than rederived:\n\n| Store state | Served | `source` |\n|---|---|---|\n| No prompt document | Code definition | `definition` |\n| Stored `activeVersion` **≥** the definition's declared version | Store | `store` |\n| Stored `activeVersion` **<** the definition's declared version | Code definition | `definition` |\n\n### Access\n\nPrompts are operational configuration, not secrets — nothing here is encrypted, and reads are\n**admin-only** rather than server-only. An admin who can edit a prompt has to be able to read back what\nthey wrote, which is why neither model carries `@dbxModelServerOnly`: that tag is copied onto the\ngenerated CLI/MCP manifest, so a consuming app cannot override it, and the CLI would refuse the read\nlocally before choosing a transport.\n\nA consuming app that wants these closed does so in the two places that actually refuse a read, and must\ndo **both** — they mirror each other, and `dbx_model_server_only_validate_app` reports the drift when\nthey disagree:\n\n1. omit the `orp` / `orpv` match blocks from `firestore.rules`, and\n2. set `serverOnly: true` on the model's `firebaseModelServiceFactory`.\n\nAn app that leaves them open grants the read to system admins:\n\n```\nmatch /orp/{openRouterPrompt} {\n  allow read: if userClaimsIsSysAdmin();\n\n  match /orpv/{openRouterPromptVersion} {\n    allow read: if userClaimsIsSysAdmin();\n  }\n}\n\n// the model API addresses a version through the collection GROUP, which the nested match does not cover\nmatch /{path=**}/orpv/{openRouterPromptVersion} {\n  allow read: if userClaimsIsSysAdmin();\n}\n```\n\n`orrt` (`OpenRouterRunTask`) is readable by a system admin too — it is the execution record an operator\nreaches for when a run fails, and its `msg` field carrying the model's raw input and output is the\nreason to read it. It is granted `read` ALONE, on both transports: the sweep owns every write (claim,\nlease, state transition), so a client write would move a task out from under the sweep executing it.\n\n```\nmatch /orrt/{openRouterRunTask} {\n  allow read: if userClaimsIsSysAdmin();\n}\n```\n\n## Files and PDFs\n\nThere is no upload step. A run task stores the **GCS object path** (`fp`) and nothing else — never a\nURL, never the bytes. The attachment is resolved fresh on **every attempt**, in one of two modes:\n\n| Mode | What goes on the wire | When |\n|---|---|---|\n| `signedUrl` | `file_url`, a short-lived signed URL OpenRouter dereferences itself | Default. Cheap, keeps the request small. |\n| `inlineData` | `file_data: \"data:<mime>;base64,…\"` | The object is not reachable from the public internet. |\n\n**The mode comes from the environment**, not from a flag an app has to remember to set twice: give\n`openRouterRunTaskService` a `FirebaseServerEnvService` and `isTestingEnv` selects `inlineData`. That is\nwhat makes files work against the **Firebase storage emulator**, where nothing is really signed and the\nhost is `localhost`, so a `file_url` OpenRouter tries to fetch resolves to nothing. `fileAttachmentMode`\noverrides it explicitly, and `maxInlineFileSizeBytes` (default 256 KB) caps the read — inline bloats the\nrequest ~33% and is re-paid on every attempt, unlike a URL.\n\n`openRouterFileAttachmentResolver()` is the same factory, exposed for an inline (`callModelForPrompt`)\ncaller that needs attachments without going through the queue.\n\nNeither payload is ever persisted. Resolving per attempt is only half the fix — the other half is that\nthe conversation written back through the `StateAccessor` has its `input_file` payloads **stripped**\n(`openRouterMessagesWithoutFileAttachmentData`), keeping only `filename` as the rejoin key, and `load()`\nre-points them at the current attempt's attachment\n(`openRouterMessagesWithFreshFileAttachments`). Without that, a deferred resume hours later would replay\na URL that expired minutes after it was minted, or carry a second copy of the whole file in a Firestore\ndocument with a 1 MiB ceiling.\n\nPDF parsing pins `engine: 'native'` so the model provider parses on our BYOK key; the default silently\nfalls back to `mistral-ocr` (8-image cap, per-page billing) with no error.\n\nA file whose parse is already cached on the run task (`fa`) is **not re-attached** on a retry — the\ncached text is resubmitted instead. OpenRouter's documented `annotations` echo is emitted too, but it\ndoes not currently survive the SDK: `@openrouter/sdk@1.2.26` validates the `/responses` body against a\nclosed union whose message variants have no `annotations` field, so the property is stripped before the\nrequest leaves the process. Not sending the document is therefore the only thing that actually prevents\na re-parse today.\n\n## Hosted tools (`file_search`, `web_search`, `mcp`)\n\nHosted (server-executed) tools go on the model config's `tools` array and are dispatched for real:\n\n```ts\nconfig: {\n  model: 'openai/gpt-5.1',\n  tools: [openRouterFileSearchTool(['vs_…'], 5)],\n  include: ['file_search_call.results'],\n  provider: openRouterProviderPinnedTo('openai')   // BYOK pinning + requireParameters\n}\n```\n\n**They do not go through `callModel`.** `@openrouter/sdk`'s `callModel` destructures `tools` off the\nrequest and runs every entry through its client-function converter, which reads `tool.function.name` —\nso a hosted entry is dropped outright when no client tools are present, and throws inside the SDK at\ndispatch when they are. `callModelForOpenRouterRequest` therefore routes by the shape of the request:\n\n| Run | Transport |\n|---|---|\n| No hosted tools | `callModel`, unchanged. |\n| Hosted tools, no client tools and no `StateAccessor` | `sendOpenRouterResponsesRequest` — a direct, **non-streaming** `POST /responses`. |\n| Hosted tools **plus** client tools or a `StateAccessor` | `ModelResult` assembled here, with the hosted entries appended **after** client-tool conversion. |\n\nThe two are **not** mutually exclusive: a run can search a vector store and drive the client-side tool\nloop in the same call. Only the entry point differs — the merged path is a `callModel` request in\neverything else, including the `x-openrouter-callmodel` header and the `stopWhen` step ceiling.\n\nGoing direct for the hosted-only case is not just about getting the tool onto the wire. The request is\nnon-streaming, so the returned `OpenResponsesResult` is OpenRouter's body verbatim rather than one\nreassembled from stream events — which is what preserves a `file_search_call` output item and the chunks\n`include: ['file_search_call.results']` asked for.\n\n**OpenRouter's side is verified live.** A hosted `file_search` tool is forwarded upstream to OpenAI,\nwhich resolves the store id and (for a nonexistent one) answers with its own\n`Vector store with id [...] not found.` — an error only the upstream lookup can produce. The tool comes\nback echoed on the response intact. See `openrouter.filesearch.spike.spec.ts`.\n\nTwo details settled by the same probes:\n\n- The wire name is `vector_store_ids`; sending `vectorStoreIds` to the API is a flat `400`. The SDK\n  takes `vectorStoreIds` and remaps it, so `openRouterFileSearchTool()` is camelCase on purpose and\n  validation rejects the wire-cased spelling (which the SDK would silently drop, leaving a tool that\n  searches nothing and a model answering ungrounded).\n- `provider.requireParameters: true` made no difference on a single-provider model, which is the one\n  case where it cannot. Keep it for any model with more than one provider — validation warns when a\n  hosted tool is configured without it.\n\n**OpenRouter can never create or populate a vector store** — ingestion always goes direct to OpenAI.\n\n## Auditing a run\n\nA run task stores its own output; `gi (generationIds)` exists so a completed run can be looked up\nafterwards. `openRouterGeneration({ client, id })` returns finish reason, cancellation, BYOK, latency and\nthe server-finalised token/cost breakdown, and `openRouterGenerationContent(...)` returns the stored\nprompt / completion / reasoning / output.\n\nTreat both as **audit surfaces, never the system of record**: what they return is tied to account logging\nsettings (nothing is retained under ZDR / logging-disabled), retention is undocumented, and they are\nkeyed per generation rather than per conversation.\n\n## Live probes\n\nTwo blocks make real API calls, both skipped unless `OPENROUTER_API_KEY` is set:\n\n- `openrouter.filesearch.spike.spec.ts` — the `file_search` passthrough probes. Deliberately cheap: a\n  free model by default, and the file_search probe fails at the store lookup before anything is billed.\n- `openrouter.decision.spike.spec.ts` — the System One probes. Cheap for a different reason: input is\n  $0.042/Mtok and output is not billed at all. They pin what only a real call can settle — that all three\n  primitives answer in the declared shape, that `usage.cost` arrives synchronously (which is why a\n  decision needs no broadcast reconciliation), and that the wire is snake_case where the SDK decodes to\n  camelCase.\n- the `live end-to-end` block in `openrouter.runtask.emulator.spec.ts` — publishes a version, enqueues a\n  run, drains it with the real sweeper against the real API, then resolves the stored generation id\n  through `openRouterGeneration`. This is the plan's end-to-end bullet minus its MCP transport: no app in\n  this repo consumes the models yet, so the same server actions the callModel MCP surfaces are called\n  directly instead.\n\n| Variable | Purpose |\n|---|---|\n| `OPENROUTER_API_KEY` | Enables the live probes. |\n| `OPENROUTER_TEST_MODEL_ID` | Model for the general probe and the end-to-end run. Defaults to `nvidia/nemotron-nano-9b-v2:free`. |\n| `OPENROUTER_FILE_SEARCH_MODEL_ID` | Model for the file_search probe. Must be an OpenAI model. |\n| `OPENROUTER_FILE_SEARCH_VECTOR_STORE_ID` | A real `vs_…`; upgrades the probe to the full grounded assertion. |\n| `OPENROUTER_TEST_DECISION_MODEL_ID` | System One model for the decision probes. Defaults to `typesafe/jev-1.13`. Its own knob because the two arms cannot share one value. |\n\n## CJS / ESM\n\n`@openrouter/sdk` is ESM-only (`\"type\": \"module\"`) while this package also ships a CommonJS bundle, so\nthe CJS bundle `require()`s an ESM dependency. That works on Node 22.12+ and is verified on the\n`nodejs24` runtime `firebase.json` deploys to: `require('dist/packages/openrouter/index.cjs.js')` loads\nand resolves every export, `responsesSend` / `ModelResult` / `convertToolsToAPIFormat` included. Re-check\nit if the Functions runtime is ever pinned lower — below 22.12 this is an `ERR_REQUIRE_ESM`, not a\nwarning.\n\n## Firestore indexes\n\n`firebase/firestore.indexes.json` is generated from the `@dbxModelFirebaseIndex`-tagged query factories\nand is the set a consuming app must merge into its own indexes file:\n\n```\ndbx-cli-generate-firestore-indexes --component packages/openrouter/firebase --output packages/openrouter/firebase/firestore.indexes.json\n```\n\n**Two** composites on `orrt`: `(s, qat)` for the drain sweep and `(s, lat)` for lease reclamation. The\nretention query needs none at all — `qat <= cutoff` ordered by `qat` is a single-field range with a\nmatching order, which Firestore serves from its automatic single-field index.\n\nNothing on `orp`. The prompt query filters on `s` alone and adds no ordering, so pagination rides\nFirestore's implicit `__name__` order — which for this model is the prompt's own readable key. Adding a\nsecond filter axis (an `array-contains` on `t`, say) is what would buy the first composite here.\n\n**The emulator does not enforce composite indexes**, so a green integration run proves nothing here —\n`openrouter.query.spec.ts` asserts the generated file against the query factories instead, and pins the\ncount at exactly two so a re-added factory cannot quietly buy a third.\n","readmeFilename":"README.md"}