{"_id":"@absolutejs/rules","_rev":"3-ddbb79bd3850798785236574951925d4","name":"@absolutejs/rules","dist-tags":{"latest":"0.1.0"},"versions":{"0.0.1":{"name":"@absolutejs/rules","version":"0.0.1","author":"Alex Kahn","license":"BUSL-1.1","_id":"@absolutejs/rules@0.0.1","maintainers":[{"name":"alexkahndev","email":"alexkahn2019@gmail.com"}],"homepage":"https://github.com/absolutejs/rules","bugs":{"url":"https://github.com/absolutejs/rules/issues"},"dist":{"shasum":"b07feb3da515627a96b1737f524f1e873e85b99c","tarball":"https://registry.npmjs.org/@absolutejs/rules/-/rules-0.0.1.tgz","fileCount":10,"integrity":"sha512-z6ViirDxlxhLKIzQh2RzQfJ5zkmLXo2ai/aW6g7WYYnHqfhku9+KKylt2m0YiX1qS5+ePquZ8tgCpKgKS3oUhQ==","signatures":[{"sig":"MEUCIQCN0MVQ4Kuk2vLFIMuAEKBfc9yV8DuGCx0kIixipR4uAAIgGihc4Bc4aKL8AyDEryIwsM3dwNA+yanP9YoAHTTgtlw=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":27474},"main":"./dist/index.js","types":"./dist/src/index.d.ts","shasum":"b07feb3da515627a96b1737f524f1e873e85b99c","scripts":{"test":"bun test","build":"rm -rf dist && bun build src/index.ts --outdir dist --target=bun && tsc --emitDeclarationOnly --project tsconfig.json","format":"prettier --write \"./**/*.{ts,json,md}\"","release":"bun run format && bun run test && bun run build && bun publish","typecheck":"tsc --noEmit --project tsconfig.json"},"_npmUser":{"name":"alexkahndev","email":"alexkahn2019@gmail.com"},"_integrity":"sha512-z6ViirDxlxhLKIzQh2RzQfJ5zkmLXo2ai/aW6g7WYYnHqfhku9+KKylt2m0YiX1qS5+ePquZ8tgCpKgKS3oUhQ==","repository":{"url":"https://github.com/absolutejs/rules.git","type":"git"},"_npmVersion":"10.8.3","description":"Typed standing automations (\"if X do Y\") for AI-agent products — a closed trigger/action vocabulary drives the validator, LLM tool schemas, and a capped, cooldown-guarded firing engine, so the agent itself can author rules without hallucinating behavior.","directories":{},"_nodeVersion":"24.3.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"prettier":"3.5.3","@types/bun":"latest","typescript":"5.8.3"},"_npmOperationalInternal":{"tmp":"tmp/rules_0.0.1_1783542538278_0.92470391281393","host":"s3://npm-registry-packages-npm-production"}},"0.0.2":{"name":"@absolutejs/rules","version":"0.0.2","author":"Alex Kahn","license":"BUSL-1.1","_id":"@absolutejs/rules@0.0.2","maintainers":[{"name":"alexkahndev","email":"alexkahn2019@gmail.com"}],"homepage":"https://github.com/absolutejs/rules","bugs":{"url":"https://github.com/absolutejs/rules/issues"},"dist":{"shasum":"20b80002bb252dc9c6164975c46620b0964cfb20","tarball":"https://registry.npmjs.org/@absolutejs/rules/-/rules-0.0.2.tgz","fileCount":13,"integrity":"sha512-mVs9K8YsGxFCFk7BwtAoGAtDsOheswBROotp78qDzKJ3P7+qhrZ09HlmSpowKRjBrOtbGWt02U0/C0WE9Gp/5A==","signatures":[{"sig":"MEQCIEWJgRg64X8leSc9BSyuHwbvi9kMUg3pC/4kBxUMS4LAAiBfC+2ZzpOVpDlqxImcT1i4nHuP2bM6dBCZUzKwfnJn6A==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":390710},"main":"./dist/index.js","types":"./dist/src/index.d.ts","shasum":"20b80002bb252dc9c6164975c46620b0964cfb20","exports":{".":{"types":"./dist/src/index.d.ts","import":"./dist/index.js","default":"./dist/index.js"},"./manifest":{"types":"./dist/src/manifest.d.ts","import":"./dist/manifest.js","default":"./dist/manifest.js"},"./manifest.json":"./dist/manifest.json"},"scripts":{"test":"bun test","build":"rm -rf dist && bun build src/index.ts src/manifest.ts --outdir dist --root ./src --target=bun && tsc --emitDeclarationOnly --project tsconfig.json && absolute-manifest emit","format":"prettier --write \"./**/*.{ts,json,md}\"","release":"bun run format && bun run test && bun run build && bun publish","typecheck":"tsc --noEmit --project tsconfig.json"},"_npmUser":{"name":"alexkahndev","email":"alexkahn2019@gmail.com"},"_integrity":"sha512-mVs9K8YsGxFCFk7BwtAoGAtDsOheswBROotp78qDzKJ3P7+qhrZ09HlmSpowKRjBrOtbGWt02U0/C0WE9Gp/5A==","absolutejs":{"manifestContract":1},"repository":{"url":"https://github.com/absolutejs/rules.git","type":"git"},"_npmVersion":"10.8.3","description":"Typed standing automations (\"if X do Y\") for AI-agent products — a closed trigger/action vocabulary drives the validator, LLM tool schemas, and a capped, cooldown-guarded firing engine, so the agent itself can author rules without hallucinating behavior.","directories":{},"_nodeVersion":"24.3.0","dependencies":{"@sinclair/typebox":"^0.34.0","@absolutejs/manifest":"^0.1.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"prettier":"3.5.3","@types/bun":"latest","typescript":"5.8.3"},"_npmOperationalInternal":{"tmp":"tmp/rules_0.0.2_1783964471660_0.9863903412749886","host":"s3://npm-registry-packages-npm-production"}},"0.1.0":{"author":{"name":"Alex Kahn"},"description":"Typed standing automations (\"if X do Y\") for AI-agent products — a closed trigger/action vocabulary drives the validator, LLM tool schemas, and a capped, cooldown-guarded firing engine, so the agent itself can author rules without hallucinating behavior.","devDependencies":{"@types/bun":"latest","prettier":"3.5.3","typescript":"5.8.3"},"license":"BUSL-1.1","publishConfig":{"access":"public"},"main":"./dist/index.js","name":"@absolutejs/rules","repository":{"type":"git","url":"git+https://github.com/absolutejs/rules.git"},"homepage":"https://github.com/absolutejs/rules","bugs":{"url":"https://github.com/absolutejs/rules/issues"},"scripts":{"build":"rm -rf dist && bun build src/index.ts src/manifest.ts --outdir dist --root ./src --target=bun && tsc --emitDeclarationOnly --project tsconfig.json && absolute-manifest emit","format":"prettier --write \"./**/*.{ts,json,md}\"","release":"bun run format && bun run test && bun run build && bun publish","test":"bun test","typecheck":"tsc --noEmit --project tsconfig.json"},"types":"./dist/src/index.d.ts","version":"0.1.0","absolutejs":{"manifestContract":2},"exports":{".":{"types":"./dist/src/index.d.ts","import":"./dist/index.js","default":"./dist/index.js"},"./manifest":{"types":"./dist/src/manifest.d.ts","import":"./dist/manifest.js","default":"./dist/manifest.js"},"./manifest.json":"./dist/manifest.json"},"dependencies":{"@absolutejs/manifest":"^0.4.0","@sinclair/typebox":"^0.34.0"},"_id":"@absolutejs/rules@0.1.0","gitHead":"de193e86398715519d1f34fe25cf8b25219a428e","_nodeVersion":"22.14.0","_npmVersion":"10.9.2","dist":{"integrity":"sha512-0NFtapJA0AdWC0VXjCpVjDeT25aj5vcTiwB4+mEHM474nvdJ78/0TsIth6ab37RGqB1SHtVlU1f3V2Mz+/LPmA==","shasum":"45aee3ceedbdd8cc3d6b798ce5564e904f5e567c","tarball":"https://registry.npmjs.org/@absolutejs/rules/-/rules-0.1.0.tgz","fileCount":13,"unpackedSize":394236,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEQCIE7KJt4S9+B6CAoSo/2cses9cJ5XetXkbxfe/x/msRU9AiA65zXzWcI5CjkvoujkIsDUH21YmAePjusJcr7svc3zuw=="}]},"_npmUser":{"name":"alexkahndev","email":"alexkahn2019@gmail.com"},"directories":{},"maintainers":[{"name":"alexkahndev","email":"alexkahn2019@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/rules_0.1.0_1784807597975_0.5934079685038469"},"_hasShrinkwrap":false}},"time":{"created":"2026-07-08T20:28:58.109Z","modified":"2026-07-23T11:53:18.284Z","0.0.1":"2026-07-08T20:28:58.411Z","0.0.2":"2026-07-13T17:41:11.794Z","0.1.0":"2026-07-23T11:53:18.128Z"},"bugs":{"url":"https://github.com/absolutejs/rules/issues"},"author":{"name":"Alex Kahn"},"license":"BUSL-1.1","homepage":"https://github.com/absolutejs/rules","repository":{"type":"git","url":"git+https://github.com/absolutejs/rules.git"},"description":"Typed standing automations (\"if X do Y\") for AI-agent products — a closed trigger/action vocabulary drives the validator, LLM tool schemas, and a capped, cooldown-guarded firing engine, so the agent itself can author rules without hallucinating behavior.","maintainers":[{"name":"alexkahndev","email":"alexkahn2019@gmail.com"}],"readme":"# @absolutejs/rules\n\nTyped standing automations (\"if X do Y\") for AI-agent products — safe for the\n**agent itself** to author.\n\nBuilt for the AbsoluteJS AI Studio.\n\n## The idea\n\nLetting an LLM create automations on a member's behalf is only safe if the\nrule language is closed. This package makes the vocabulary the contract: you\ndefine your triggers and actions **once**, with typed, bounded parameters, and\neverything derives from that single definition —\n\n- **The validator** (`validateRuleInput`): unknown triggers/actions reject with\n  the available options spelled out (an error the LLM can relay verbatim),\n  unknown params strip, numbers clamp to their bounds, closed-set strings\n  narrow. A stored rule can never carry behavior your engine doesn't implement.\n- **The AI tool schemas** (`ruleToolSchemas`): create/update tool inputs whose\n  trigger/action fields are enums of your vocabulary — the hallucination-proofing.\n- **The firing engine** (`createRuleEngine`): per-entity cooldown via a firing\n  ledger, daily firing + auto-execution caps, a kill switch, and your authoring\n  policy re-checked at fire time (a rule authored under a looser policy can't\n  outrun a tightened one).\n\nThe only free text a rule carries is `guidance` — a bounded style note your\ndrafting pipeline applies to generated copy. It never selects behavior.\n\n## Quick start\n\n```ts\nimport {\n  createMemoryRuleStore,\n  createRuleEngine,\n  defineRuleVocabulary,\n  ruleToolSchemas,\n  validateRuleInput,\n} from \"@absolutejs/rules\";\n\nconst vocabulary = defineRuleVocabulary({\n  triggers: {\n    no_reply: {\n      label: \"My outreach gets no reply\",\n      paramsHelp: \"days (default 4)\",\n      params: { days: { type: \"number\", min: 1, max: 30, defaultValue: 4 } },\n    },\n  },\n  actions: {\n    draft_followup: {\n      label: \"Draft a follow-up for my approval\",\n      paramsHelp: \"none (guidance styles the copy)\",\n      capability: \"outbound\",\n    },\n  },\n});\n\n// 1. Validate anything that wants to become a rule (AI tool, REST, forms):\nconst result = validateRuleInput(\n  vocabulary,\n  {\n    trigger: \"no_reply\",\n    action: \"draft_followup\",\n    triggerParams: { days: 45 },\n  },\n  {\n    canUseAction: (action) =>\n      memberTier !== \"restricted\" || \"Outbound rules need a higher score.\",\n    canAutoSend: () =>\n      memberTier === \"trusted\" || \"Auto-send needs the trusted tier.\",\n  },\n);\n// result.ok.triggerParams.days === 30 (clamped)\n\n// 2. Give your agent the tools (schemas only — you own the handlers):\nconst { createInput, updateInput, help } = ruleToolSchemas(vocabulary);\n\n// 3. Fire occurrences from your signal hooks / sweeps:\nconst engine = createRuleEngine({\n  vocabulary,\n  store, // your RuleStore (drizzle, memory, …)\n  executeAction: async (rule, event, { autoSend }) => {\n    // queue a draft for approval, create a task, auto-execute…\n    return autoSend ? \"executed\" : \"drafted\";\n  },\n});\n\nawait engine.fire(\n  ownerId,\n  {\n    trigger: \"no_reply\",\n    entityId: `noreply:${matchId}`,\n    context: \"no reply from Brendan in 5 days\",\n    signal: { days: 5 },\n  },\n  {\n    killSwitch: false,\n    cooldownDays: 3,\n    maxFiringsPerDay: 10,\n    maxAutoPerDay: 3,\n    canUseAction: () => true,\n    canAutoSend: () => true,\n  },\n);\n```\n\nStorage is pluggable via the small `RuleStore` interface (list enabled rules,\nledger reads/writes). `createMemoryRuleStore` ships for tests; a drizzle/\nPostgres store is a few lines against your own tables (see the onSpark\nreference integration).\n\n## License\n\nBusiness Source License 1.1 — free for your own products and internal use;\nyou may not offer it as a competing hosted automation/rules service. Converts\nto Apache 2.0 on July 8, 2030. See [LICENSE](./LICENSE).\n","readmeFilename":"README.md"}