paracosm 0.9.1021 → 0.9.1022
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.
- package/README.md +11 -10
- package/assets/landing.css +1 -477
- package/dist/dashboard/dist/assets/{index-YkbFYo4m.js → index-Da6eIzNW.js} +2 -2
- package/dist/dashboard/dist/assets/{pdf-D0rlhCn8.js → pdf-CdfMQ2jQ.js} +1 -1
- package/dist/dashboard/dist/index.html +1 -1
- package/dist/dashboard/dist/llms-full.txt +4 -6
- package/dist/dashboard/dist/llms.txt +2 -0
- package/dist/dashboard/landing.html +31 -262
- package/dist/server/rate-limiter.d.ts +0 -9
- package/dist/server/rate-limiter.d.ts.map +1 -1
- package/dist/server/rate-limiter.js +0 -36
- package/dist/server/rate-limiter.js.map +1 -1
- package/dist/server/routes/waitlist.d.ts +15 -19
- package/dist/server/routes/waitlist.d.ts.map +1 -1
- package/dist/server/routes/waitlist.js +5 -107
- package/dist/server/routes/waitlist.js.map +1 -1
- package/dist/server/server-app.d.ts.map +1 -1
- package/dist/server/server-app.js +28 -27
- package/dist/server/server-app.js.map +1 -1
- package/dist/server/services/email-templates.d.ts +4 -11
- package/dist/server/services/email-templates.d.ts.map +1 -1
- package/dist/server/services/email-templates.js +4 -70
- package/dist/server/services/email-templates.js.map +1 -1
- package/package.json +1 -1
|
@@ -67,7 +67,7 @@
|
|
|
67
67
|
}
|
|
68
68
|
}
|
|
69
69
|
</script>
|
|
70
|
-
<script type="module" crossorigin src="/assets/index-
|
|
70
|
+
<script type="module" crossorigin src="/assets/index-Da6eIzNW.js"></script>
|
|
71
71
|
<link rel="stylesheet" crossorigin href="/assets/index-BN6k2mB_.css">
|
|
72
72
|
</head>
|
|
73
73
|
<body>
|
|
@@ -211,18 +211,16 @@ Compile-from-seed adds ~$0.10 (cached to disk by seed signature).
|
|
|
211
211
|
|
|
212
212
|
Largest cost lever: tool reuse after turn 3. Anthropic prompt cache hits the shared system prefix from turn 2 onward (10× input-cost reduction); OpenAI auto-caches any prompt over 1024 tokens. The artifact's `cost` field reports tokens read, tokens created, and USD saved per run.
|
|
213
213
|
|
|
214
|
-
## Network
|
|
214
|
+
## Network behavior
|
|
215
215
|
|
|
216
|
-
-
|
|
217
|
-
-
|
|
218
|
-
- Artifact records `offline: true` flag for auditability
|
|
219
|
-
- Air-gapped deployments via custom inference gateway + pre-ingested research bundles (hosted enterprise tier)
|
|
216
|
+
- Compiling a scenario and running it both call the OpenAI or Anthropic API
|
|
217
|
+
- Web search is optional: live search is off by default for a run, and department research then comes from the scenario's knowledge bundle
|
|
220
218
|
|
|
221
219
|
## Pricing model
|
|
222
220
|
|
|
223
221
|
- Engine itself: Apache-2.0, commercial use unrestricted
|
|
224
222
|
- LLM costs: you provide your own API keys
|
|
225
|
-
- Hosted
|
|
223
|
+
- Hosted demo: https://paracosm.agentos.sh/sim is free to try on the host's API keys, with capped run size and a daily limit per IP address; your own OpenAI or Anthropic key lifts both
|
|
226
224
|
- Contact: team@frame.dev
|
|
227
225
|
|
|
228
226
|
## Glossary
|
|
@@ -8,6 +8,8 @@ Paracosm is built by [Framers Lab, Inc.](https://frame.dev) on top of [AgentOS](
|
|
|
8
8
|
|
|
9
9
|
- Homepage: https://paracosm.agentos.sh
|
|
10
10
|
- API Reference: https://paracosm.agentos.sh/docs
|
|
11
|
+
- HTTP API reference: https://github.com/framerslab/paracosm/blob/master/docs/HTTP_API.md
|
|
12
|
+
- Cookbook: https://github.com/framerslab/paracosm/blob/master/docs/COOKBOOK.md
|
|
11
13
|
- npm: https://www.npmjs.com/package/paracosm
|
|
12
14
|
- GitHub: https://github.com/framerslab/paracosm
|
|
13
15
|
- AgentOS (parent runtime): https://agentos.sh
|
|
@@ -70,8 +70,8 @@
|
|
|
70
70
|
{"@type":"Question","name":"What does a typical run cost?","acceptedAnswer":{"@type":"Answer","text":"A six-turn run on a small scenario runs roughly tens of cents under economy and a few dollars under quality. Compile-from-seed adds ~$0.10 (cached to disk by seed signature). Tool reuse after turn three is the largest cost lever. Anthropic prompt cache hits the shared system prefix from turn 2 onward (10x input-cost reduction); OpenAI auto-caches any prompt over 1024 tokens. The cost field reports tokens read, tokens created, and USD saved per run."}},
|
|
71
71
|
{"@type":"Question","name":"What verticals does this apply to?","acceptedAnswer":{"@type":"Answer","text":"Digital-twin medicine, corporate strategy (M&A, market entry, leadership replays), policy simulation (tax, regulation, congestion pricing, healthcare reform), defense / wargaming (commander HEXACO under shared starting conditions; replay any past run after a code change), game design playtesting (procedural NPC civilizations, runtime tool forge), AI alignment red-teaming (pressure-test agent behavior under specific HEXACO weights). The engine is domain-agnostic; the scenario contract names the world."}},
|
|
72
72
|
{"@type":"Question","name":"Can I build my own scenario?","acceptedAnswer":{"@type":"Answer","text":"Three paths. (1) Write a ScenarioPackage in TypeScript with custom hooks for progression, crisis generation, milestones, and politics — full control. (2) Write a scenario JSON draft and run it through compileScenario() — zero-code authoring, $0.10 per compile, caches to disk. (3) Pass a brief or URL to WorldModel.fromPrompt() and let an LLM draft the JSON contract first. All three produce the same canonical ScenarioPackage."}},
|
|
73
|
-
{"@type":"Question","name":"Does Paracosm need an internet connection?","acceptedAnswer":{"@type":"Answer","text":"Yes
|
|
74
|
-
{"@type":"Question","name":"Is Paracosm free?","acceptedAnswer":{"@type":"Answer","text":"The engine is open source under Apache-2.0. Use in commercial products without restriction. You provide LLM API keys; running a 6-turn quality-preset run costs roughly $1-3 on OpenAI, $3-7 on Anthropic.
|
|
73
|
+
{"@type":"Question","name":"Does Paracosm need an internet connection?","acceptedAnswer":{"@type":"Answer","text":"Yes. Compiling a scenario and running it both call the OpenAI or Anthropic API. Web search is optional. Live search is off by default for a run, and department research then comes from the scenario's knowledge bundle."}},
|
|
74
|
+
{"@type":"Question","name":"Is Paracosm free?","acceptedAnswer":{"@type":"Answer","text":"The engine is open source under Apache-2.0. Use in commercial products without restriction. You provide LLM API keys; running a 6-turn quality-preset run costs roughly $1-3 on OpenAI, $3-7 on Anthropic. The hosted demo at paracosm.agentos.sh/sim is free to try. It runs on the host's API keys with capped run size and a daily limit per IP address, and your own OpenAI or Anthropic key lifts both."}}
|
|
75
75
|
]}
|
|
76
76
|
</script>
|
|
77
77
|
<script type="application/ld+json">
|
|
@@ -82,7 +82,7 @@
|
|
|
82
82
|
]}
|
|
83
83
|
</script>
|
|
84
84
|
<script type="application/ld+json">
|
|
85
|
-
{"@context":"https://schema.org","@type":"TechArticle","@id":"https://paracosm.agentos.sh/#article","headline":"Paracosm: Agent Swarm Simulation for Structured World Modeling with LLMs","description":"Agent swarm simulation for structured world modeling with LLMs. Compile prompts, briefs, URLs into typed ScenarioPackages. Deterministic seeded kernel, HEXACO-personality leaders, runtime tool forging in sandboxed node:vm, replay-verified forkable simulations.","url":"https://paracosm.agentos.sh","mainEntityOfPage":"https://paracosm.agentos.sh","author":{"@id":"https://paracosm.agentos.sh/#author"},"publisher":{"@id":"https://paracosm.agentos.sh/#publisher"},"datePublished":"2026-04-13","dateModified":"2026-
|
|
85
|
+
{"@context":"https://schema.org","@type":"TechArticle","@id":"https://paracosm.agentos.sh/#article","headline":"Paracosm: Agent Swarm Simulation for Structured World Modeling with LLMs","description":"Agent swarm simulation for structured world modeling with LLMs. Compile prompts, briefs, URLs into typed ScenarioPackages. Deterministic seeded kernel, HEXACO-personality leaders, runtime tool forging in sandboxed node:vm, replay-verified forkable simulations.","url":"https://paracosm.agentos.sh","mainEntityOfPage":"https://paracosm.agentos.sh","author":{"@id":"https://paracosm.agentos.sh/#author"},"publisher":{"@id":"https://paracosm.agentos.sh/#publisher"},"datePublished":"2026-04-13","dateModified":"2026-10-10","articleSection":"AI Engineering","keywords":"agent swarm, agent swarm simulation, multi-agent simulation, world model, structured world model, LLM world model, world modeling, digital twin, HEXACO, agent-based modeling, AgentOS, paracosm","proficiencyLevel":"Expert","about":[{"@type":"Thing","name":"Agent-based modeling"},{"@type":"Thing","name":"Multi-agent simulation"},{"@type":"Thing","name":"Large language models"},{"@type":"Thing","name":"World model"},{"@type":"Thing","name":"HEXACO personality model"},{"@type":"Thing","name":"Digital twin"}],"image":"https://paracosm.agentos.sh/brand/social/paracosm-social-1200x630.png"}
|
|
86
86
|
</script>
|
|
87
87
|
<script type="application/ld+json">
|
|
88
88
|
{"@context":"https://schema.org","@type":"Person","@id":"https://paracosm.agentos.sh/#author","name":"Johnny Dunn","alternateName":"jddunn","url":"https://github.com/jddunn","jobTitle":"Founder & Engineer","worksFor":{"@id":"https://paracosm.agentos.sh/#publisher"},"affiliation":{"@id":"https://paracosm.agentos.sh/#publisher"},"sameAs":["https://github.com/jddunn","https://www.linkedin.com/in/johnnyddunn","https://twitter.com/jddunn","https://x.com/jddunn","https://frame.dev"],"knowsAbout":["Agent swarm simulation","Multi-agent systems","Large language models","Structured world modeling","HEXACO personality model","AI agent runtimes","Digital twins","TypeScript","Node.js","Deterministic simulation","Counterfactual modeling","Runtime tool forging","Sandboxed code execution","AgentOS"],"description":"Founder of Frame. Builds open-source AI agent runtimes and structured world-model engines. Author of AgentOS and Paracosm."}
|
|
@@ -165,7 +165,7 @@
|
|
|
165
165
|
<a href="#features" role="menuitem">Features</a>
|
|
166
166
|
<a href="#how-it-works" role="menuitem">How It Works</a>
|
|
167
167
|
<a href="#scenarios" role="menuitem">Scenarios</a>
|
|
168
|
-
<a href="#
|
|
168
|
+
<a href="#get-started" role="menuitem">Get Started</a>
|
|
169
169
|
<a href="#faq" role="menuitem">FAQ</a>
|
|
170
170
|
<a href="#about" role="menuitem">About</a>
|
|
171
171
|
</div>
|
|
@@ -177,6 +177,7 @@
|
|
|
177
177
|
<button class="nav-dropdown-trigger" aria-haspopup="true" aria-expanded="false" type="button">Docs <svg width="10" height="10" viewBox="0 0 10 10" aria-hidden="true"><path d="M1 3l4 4 4-4" stroke="currentColor" stroke-width="1.5" fill="none" stroke-linecap="round" stroke-linejoin="round"/></svg></button>
|
|
178
178
|
<div class="nav-dropdown-menu" role="menu">
|
|
179
179
|
<a href="/docs" role="menuitem">API Reference</a>
|
|
180
|
+
<a href="https://github.com/framerslab/paracosm/blob/master/docs/HTTP_API.md" target="_blank" rel="noopener" role="menuitem">HTTP API Reference</a>
|
|
180
181
|
<a href="https://github.com/framerslab/paracosm/blob/master/docs/COOKBOOK.md" target="_blank" rel="noopener" role="menuitem">Cookbook (markdown)</a>
|
|
181
182
|
<a href="https://github.com/framerslab/paracosm/blob/master/docs/positioning/world-model-mapping.md" target="_blank" rel="noopener" role="menuitem">Positioning Map</a>
|
|
182
183
|
</div>
|
|
@@ -198,7 +199,7 @@
|
|
|
198
199
|
<a href="#features">Features</a>
|
|
199
200
|
<a href="#how-it-works">How It Works</a>
|
|
200
201
|
<a href="#scenarios">Scenarios</a>
|
|
201
|
-
<a href="#
|
|
202
|
+
<a href="#get-started">Get Started</a>
|
|
202
203
|
<a href="#faq">FAQ</a>
|
|
203
204
|
<a href="#about">About</a>
|
|
204
205
|
</div>
|
|
@@ -210,6 +211,7 @@
|
|
|
210
211
|
<summary><span>Docs</span></summary>
|
|
211
212
|
<div class="nav-mobile-group-body">
|
|
212
213
|
<a href="/docs">API Reference</a>
|
|
214
|
+
<a href="https://github.com/framerslab/paracosm/blob/master/docs/HTTP_API.md" target="_blank" rel="noopener">HTTP API Reference</a>
|
|
213
215
|
<a href="https://github.com/framerslab/paracosm/blob/master/docs/COOKBOOK.md" target="_blank" rel="noopener">Cookbook (markdown)</a>
|
|
214
216
|
<a href="https://github.com/framerslab/paracosm/blob/master/docs/positioning/world-model-mapping.md" target="_blank" rel="noopener">Positioning Map</a>
|
|
215
217
|
</div>
|
|
@@ -253,7 +255,7 @@
|
|
|
253
255
|
|
|
254
256
|
<div class="hero-ctas">
|
|
255
257
|
<a href="/sim" class="cta cta-pulse">Try Live Demo <svg><use href="#i-arrow"/></svg></a>
|
|
256
|
-
<a href="#
|
|
258
|
+
<a href="#get-started" class="cta cta-secondary">Install from npm</a>
|
|
257
259
|
<a href="https://github.com/framerslab/paracosm" target="_blank" rel="noopener" class="btn-ghost">★ Star Paracosm</a>
|
|
258
260
|
</div>
|
|
259
261
|
|
|
@@ -699,7 +701,7 @@ npm run dashboard <span class="cm"># opens http://localhost:3456</span>
|
|
|
699
701
|
|
|
700
702
|
<!-- System flow diagram. Click-to-expand opens a zoomable modal with
|
|
701
703
|
pan/zoom/keyboard controls; see the script near </body>. -->
|
|
702
|
-
<figure class="flow-diagram rv" style="margin:36px auto 0;max-width:1080px;padding:16px 12px 8px;background:var(--bg2);border:1px solid var(--border);border-radius:12px;box-shadow:0 4px 24px rgba(0,0,0,0.25),0 0 30px rgba(232,180,74,0.05);position:relative;">
|
|
704
|
+
<figure class="flow-diagram rv" id="how-it-works" style="scroll-margin-top:80px;margin:36px auto 0;max-width:1080px;padding:16px 12px 8px;background:var(--bg2);border:1px solid var(--border);border-radius:12px;box-shadow:0 4px 24px rgba(0,0,0,0.25),0 0 30px rgba(232,180,74,0.05);position:relative;">
|
|
703
705
|
<button type="button" class="flow-diagram-trigger" data-diagram-src="/diagrams/paracosm-flow.svg" data-diagram-title="Paracosm system flow" aria-label="Open the Paracosm system flow diagram in a zoomable full-screen viewer" style="display:block;width:100%;padding:0;background:transparent;border:0;cursor:zoom-in;position:relative;color:inherit;font:inherit;">
|
|
704
706
|
<img src="/diagrams/paracosm-flow.svg" alt="Paracosm system flow: world source through Scenario Compiler, ScenarioPackage, Deterministic Kernel, Runtime Orchestrator turn loop (Director then Departments in parallel then Commander then Reactions, with Tool Forge in a V8 sandbox, an LLM Judge, HEXACO drift, and AgentMemory side modules), Agent Swarm of about a hundred personality-typed cells, and a Zod-validated RunArtifact that can be replayed byte-for-byte or forked at any past turn into divergent branches." width="1200" height="1180" loading="lazy" decoding="async" style="display:block;width:100%;height:auto;border-radius:8px;">
|
|
705
707
|
<span class="flow-diagram-badge" aria-hidden="true" style="position:absolute;top:18px;right:18px;display:inline-flex;align-items:center;gap:0.35rem;padding:0.35rem 0.6rem;font-family:var(--mono);font-size:11px;font-weight:600;color:#fff;background:rgba(15,12,8,0.82);backdrop-filter:blur(4px);-webkit-backdrop-filter:blur(4px);border-radius:6px;box-shadow:0 2px 8px rgba(0,0,0,0.25);pointer-events:none;letter-spacing:0.04em;opacity:0.88;transition:opacity 0.15s ease,transform 0.15s ease;">
|
|
@@ -716,7 +718,7 @@ npm run dashboard <span class="cm"># opens http://localhost:3456</span>
|
|
|
716
718
|
.flow-diagram-trigger:hover img { opacity: 0.96; }
|
|
717
719
|
</style>
|
|
718
720
|
|
|
719
|
-
<div class="arch rv" style="margin-top:32px">
|
|
721
|
+
<div class="arch rv" id="features" style="margin-top:32px;scroll-margin-top:80px">
|
|
720
722
|
<div class="arch-row" style="border-left:3px solid var(--amber)">
|
|
721
723
|
<svg style="color:var(--amber);width:24px;height:24px" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="4" y="5" width="16" height="14" rx="2"/><line x1="4" y1="10" x2="20" y2="10"/><line x1="9" y1="14" x2="9" y2="14.01"/><line x1="13" y1="14" x2="17" y2="14"/></svg>
|
|
722
724
|
<div class="arch-label" style="color:var(--amber)">Structured state, deterministic spine</div>
|
|
@@ -852,47 +854,33 @@ npm run dashboard <span class="cm"># opens http://localhost:3456</span>
|
|
|
852
854
|
</div>
|
|
853
855
|
</section>
|
|
854
856
|
|
|
855
|
-
<section class="sec sec-alt" id="
|
|
857
|
+
<section class="sec sec-alt" id="get-started">
|
|
856
858
|
<div class="sec-inner">
|
|
857
|
-
<h2 class="sec-title rv">
|
|
858
|
-
<p class="sec-desc rv">
|
|
859
|
+
<h2 class="sec-title rv">Use Paracosm today</h2>
|
|
860
|
+
<p class="sec-desc rv">Paracosm is open source and its dashboard is live. Try a run in the browser, install the package from npm, or read the API references.</p>
|
|
859
861
|
|
|
860
862
|
<div class="feat-grid" style="margin-top:24px">
|
|
861
863
|
<div class="feat rv rv-d1">
|
|
862
|
-
<h3>
|
|
863
|
-
<p>
|
|
864
|
-
<div class="feat-ref">analytics warehouse: per-run, per-leader, per-decision, per-forge</div>
|
|
864
|
+
<h3>Run a simulation in your browser</h3>
|
|
865
|
+
<p>Open the hosted demo at <a href="https://paracosm.agentos.sh/sim">paracosm.agentos.sh/sim</a>, give it a brief, a URL or a PDF, and watch each actor's run play out turn by turn. It asks for no account. On the host's API keys a run is capped in size and each IP address has a daily limit; your own OpenAI or Anthropic key, added in <a href="https://paracosm.agentos.sh/sim?tab=settings">Settings</a>, lifts both.</p>
|
|
865
866
|
</div>
|
|
866
867
|
<div class="feat rv rv-d2">
|
|
867
|
-
<h3>
|
|
868
|
-
<
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
<
|
|
873
|
-
<p>Multi-session agent memory with consolidation, eviction, and stance drift across runs. Reload any past run. Replay any artifact for byte-equal kernel verification. Compare runs across paracosm versions to localize behavior changes between releases.</p>
|
|
874
|
-
<div class="feat-ref">durable agent memory, kernel replay, version-diff regression</div>
|
|
875
|
-
</div>
|
|
876
|
-
<div class="feat rv rv-d1">
|
|
877
|
-
<h3>Team workspaces</h3>
|
|
878
|
-
<p>Shared scenario libraries, leader rosters, and run history with role-based access. Approval gates on production simulations. Audit trails on every run. Scenario authoring studio with a visual form-based editor on top of the canonical JSON contract.</p>
|
|
879
|
-
<div class="feat-ref">SSO, RBAC, audit log, scenario marketplace, version control</div>
|
|
880
|
-
</div>
|
|
881
|
-
<div class="feat rv rv-d2">
|
|
882
|
-
<h3>Business intelligence</h3>
|
|
883
|
-
<p>Leadership-decision modeling for organizations: model M&A scenarios, market-entry plays, workforce planning, governance experiments, alignment red-team sweeps, defense wargames. Integrate with internal data warehouses and identity providers for real-context scenario seeding.</p>
|
|
884
|
-
<div class="feat-ref">SQL connector, S3/Snowflake/BigQuery seed ingestion, SSO</div>
|
|
868
|
+
<h3>Install the package</h3>
|
|
869
|
+
<div class="code-block" style="margin:12px 0">
|
|
870
|
+
<div class="code-header"><span>npm</span><button class="code-copy" onclick="copyCode(this,'npm install paracosm')">Copy</button></div>
|
|
871
|
+
<div tabindex="0" class="code-body">npm install paracosm</div>
|
|
872
|
+
</div>
|
|
873
|
+
<p>ESM for Node 22 or newer, under Apache-2.0. Import <code>run</code>, <code>runMany</code> or <code>WorldModel</code> and call them with your own OpenAI or Anthropic key. Its CLI is included, and <code>npx paracosm dashboard</code> serves this dashboard from your machine at <code>http://localhost:3456</code>.</p>
|
|
885
874
|
</div>
|
|
886
875
|
<div class="feat rv rv-d3">
|
|
887
|
-
<h3>
|
|
888
|
-
<p>
|
|
889
|
-
<div class="feat-ref">VPC / on-prem / air-gapped, custom inference gateway, SLA</div>
|
|
876
|
+
<h3>Read the API references</h3>
|
|
877
|
+
<p>The <a href="/docs">API reference</a> covers the package's six entry points: <code>paracosm</code> and its <code>compiler</code>, <code>schema</code>, <code>swarm</code>, <code>digital-twin</code> and <code>core</code> subpaths. The <a href="https://github.com/framerslab/paracosm/blob/master/docs/HTTP_API.md" target="_blank" rel="noopener">HTTP API reference</a> documents the dashboard server's <code>/api/v1</code> routes with their request and response shapes and status codes. The <a href="https://github.com/framerslab/paracosm/blob/master/docs/COOKBOOK.md" target="_blank" rel="noopener">Cookbook</a> walks through the SDK with input and output JSON captured from real runs.</p>
|
|
890
878
|
</div>
|
|
891
879
|
</div>
|
|
892
880
|
|
|
893
881
|
<div style="margin-top:32px;text-align:center">
|
|
894
|
-
<a href="
|
|
895
|
-
<a href="https://
|
|
882
|
+
<a href="/sim" class="cta">Open the live demo <svg><use href="#i-arrow"/></svg></a>
|
|
883
|
+
<a href="https://www.npmjs.com/package/paracosm" target="_blank" rel="noopener" class="btn-ghost" style="margin-left:12px">View on npm</a>
|
|
896
884
|
</div>
|
|
897
885
|
</div>
|
|
898
886
|
</section>
|
|
@@ -1031,227 +1019,6 @@ npm run dashboard <span class="cm"># opens http://localhost:3456</span>
|
|
|
1031
1019
|
</div>
|
|
1032
1020
|
</section>
|
|
1033
1021
|
|
|
1034
|
-
<!-- WHITEPAPER COMING SOON -->
|
|
1035
|
-
<section class="sec sec-alt whitepaper-sec" id="whitepaper" aria-label="Paracosm whitepaper coming soon">
|
|
1036
|
-
<div class="sec-inner whitepaper-inner">
|
|
1037
|
-
<div class="whitepaper-card rv">
|
|
1038
|
-
<span class="whitepaper-pill" aria-label="Whitepaper status">
|
|
1039
|
-
<svg class="whitepaper-pill-icon" width="14" height="14" viewBox="0 0 24 24" aria-hidden="true">
|
|
1040
|
-
<path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"/>
|
|
1041
|
-
<path d="M14 2v6h6" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"/>
|
|
1042
|
-
</svg>
|
|
1043
|
-
WHITEPAPER · COMING SOON
|
|
1044
|
-
</span>
|
|
1045
|
-
<h2 class="whitepaper-title">The Paracosm Technical Whitepaper</h2>
|
|
1046
|
-
<p class="whitepaper-dek">
|
|
1047
|
-
The full architecture and methodology, written for engineers and researchers
|
|
1048
|
-
who want a citable PDF instead of scrolling docs. Deterministic kernel design,
|
|
1049
|
-
HEXACO leader differentiation, LLM-as-a-judge event grounding, runtime tool
|
|
1050
|
-
forging with sandboxed safety, reproducible counterfactual surfaces (fork /
|
|
1051
|
-
replay / intervene), and the `RunArtifact` schema with Zod
|
|
1052
|
-
validation for byte-equal reproducibility at fixed seeds.
|
|
1053
|
-
</p>
|
|
1054
|
-
<div class="whitepaper-grid">
|
|
1055
|
-
<div class="whitepaper-grid-item">
|
|
1056
|
-
<div class="whitepaper-grid-label">Architecture</div>
|
|
1057
|
-
<div class="whitepaper-grid-body">
|
|
1058
|
-
ScenarioPackage compilation, deterministic kernel, HEXACO leader engine, LLM event director, judge layer, snapshot capture for fork & replay.
|
|
1059
|
-
</div>
|
|
1060
|
-
</div>
|
|
1061
|
-
<div class="whitepaper-grid-item">
|
|
1062
|
-
<div class="whitepaper-grid-label">Methodology</div>
|
|
1063
|
-
<div class="whitepaper-grid-body">
|
|
1064
|
-
Counterfactual surfaces (fork at turn N, replay byte-equal, intervene as digital twin), divergence metrics, KPI rollups, judge verdict semantics.
|
|
1065
|
-
</div>
|
|
1066
|
-
</div>
|
|
1067
|
-
<div class="whitepaper-grid-item">
|
|
1068
|
-
<div class="whitepaper-grid-label">Reproducibility</div>
|
|
1069
|
-
<div class="whitepaper-grid-body">
|
|
1070
|
-
Single-CLI run, seed-pinned kernel, Zod-validated artifacts, sandboxed tool forging with explicit safety bounds, end-to-end COOKBOOK with real input + output JSON.
|
|
1071
|
-
</div>
|
|
1072
|
-
</div>
|
|
1073
|
-
</div>
|
|
1074
|
-
<div class="whitepaper-cta-row">
|
|
1075
|
-
<button type="button" class="whitepaper-cta-disabled" disabled aria-disabled="true" title="Whitepaper PDF coming later this year">
|
|
1076
|
-
PDF · Coming soon
|
|
1077
|
-
</button>
|
|
1078
|
-
<a href="https://wilds.ai/discord" target="_blank" rel="noopener" class="whitepaper-cta-notify">
|
|
1079
|
-
Notify me when it drops
|
|
1080
|
-
</a>
|
|
1081
|
-
<a href="https://github.com/framerslab/paracosm/blob/master/docs/COOKBOOK.md" target="_blank" rel="noopener" class="whitepaper-cta-secondary">
|
|
1082
|
-
Read the cookbook while you wait
|
|
1083
|
-
</a>
|
|
1084
|
-
</div>
|
|
1085
|
-
</div>
|
|
1086
|
-
</div>
|
|
1087
|
-
</section>
|
|
1088
|
-
|
|
1089
|
-
<!-- WAITLIST -->
|
|
1090
|
-
<section id="waitlist" class="sec waitlist-section">
|
|
1091
|
-
<div class="waitlist-inner">
|
|
1092
|
-
<div class="waitlist-eyebrow">Early access · shipping Q3 2026</div>
|
|
1093
|
-
<h2 class="waitlist-heading">Request <span class="waitlist-heading-accent">early access</span></h2>
|
|
1094
|
-
<p class="waitlist-sub">Join the waitlist for the hosted dashboard, fleet orchestration, and team workspaces. We'll reach out as features ship.</p>
|
|
1095
|
-
<form id="waitlist-form" class="waitlist-form" novalidate>
|
|
1096
|
-
<label class="waitlist-field">
|
|
1097
|
-
<span>Email <span class="waitlist-required">*</span></span>
|
|
1098
|
-
<input type="email" name="email" required maxlength="254" autocomplete="email" placeholder="you@example.com">
|
|
1099
|
-
<span class="waitlist-field-hint" aria-live="polite"></span>
|
|
1100
|
-
</label>
|
|
1101
|
-
<label class="waitlist-field">
|
|
1102
|
-
<span>Name (optional)</span>
|
|
1103
|
-
<input type="text" name="name" maxlength="120" autocomplete="name" placeholder="Your name">
|
|
1104
|
-
<span class="waitlist-field-hint" aria-live="polite"></span>
|
|
1105
|
-
</label>
|
|
1106
|
-
<label class="waitlist-field">
|
|
1107
|
-
<span>I'm a (optional)</span>
|
|
1108
|
-
<select name="userType" class="waitlist-select">
|
|
1109
|
-
<option value="hobbyist" selected>Hobbyist</option>
|
|
1110
|
-
<option value="developer">Developer</option>
|
|
1111
|
-
<option value="researcher">Researcher</option>
|
|
1112
|
-
<option value="professional">Professional user</option>
|
|
1113
|
-
<option value="enterprise">Enterprise</option>
|
|
1114
|
-
<option value="vc">VC</option>
|
|
1115
|
-
<option value="investor">Investor</option>
|
|
1116
|
-
<option value="other">Other</option>
|
|
1117
|
-
</select>
|
|
1118
|
-
</label>
|
|
1119
|
-
<label class="waitlist-field">
|
|
1120
|
-
<span>Use case (optional)</span>
|
|
1121
|
-
<textarea name="useCase" maxlength="2000" rows="3" placeholder="What problem are you trying to solve with agent simulation?"></textarea>
|
|
1122
|
-
<span class="waitlist-field-hint" aria-live="polite"></span>
|
|
1123
|
-
</label>
|
|
1124
|
-
<button type="submit" class="waitlist-submit">Join waitlist <svg><use href="#i-arrow"/></svg></button>
|
|
1125
|
-
<p class="waitlist-fineprint">No spam. One confirmation email from <code>team@frame.dev</code>. Unsubscribe anytime.</p>
|
|
1126
|
-
</form>
|
|
1127
|
-
<div id="waitlist-success" class="waitlist-success" hidden>
|
|
1128
|
-
<div class="waitlist-success-icon">✓</div>
|
|
1129
|
-
<h3>You're on the list</h3>
|
|
1130
|
-
<p id="waitlist-success-msg"></p>
|
|
1131
|
-
</div>
|
|
1132
|
-
<div id="waitlist-error" class="waitlist-error" hidden role="alert">
|
|
1133
|
-
<strong>Something went wrong.</strong>
|
|
1134
|
-
<span id="waitlist-error-msg"></span>
|
|
1135
|
-
</div>
|
|
1136
|
-
</div>
|
|
1137
|
-
</section>
|
|
1138
|
-
|
|
1139
|
-
<script>
|
|
1140
|
-
(function () {
|
|
1141
|
-
var form = document.getElementById('waitlist-form');
|
|
1142
|
-
if (!form) return;
|
|
1143
|
-
var successEl = document.getElementById('waitlist-success');
|
|
1144
|
-
var successMsg = document.getElementById('waitlist-success-msg');
|
|
1145
|
-
var errorEl = document.getElementById('waitlist-error');
|
|
1146
|
-
var errorMsg = document.getElementById('waitlist-error-msg');
|
|
1147
|
-
|
|
1148
|
-
// Real-time validation: mark each field as ok/err/empty as the user
|
|
1149
|
-
// types. Avoids the :invalid-fires-on-paint problem where empty
|
|
1150
|
-
// required inputs look broken before the user has touched them.
|
|
1151
|
-
var EMAIL_RE = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
1152
|
-
function setFieldState(field, state, hintText) {
|
|
1153
|
-
field.setAttribute('data-validity', state);
|
|
1154
|
-
var hint = field.querySelector('.waitlist-field-hint');
|
|
1155
|
-
if (hint) hint.textContent = hintText || '';
|
|
1156
|
-
}
|
|
1157
|
-
var emailField = form.email && form.email.closest('.waitlist-field');
|
|
1158
|
-
var nameField = form.name && form.name.closest('.waitlist-field');
|
|
1159
|
-
var useCaseField = form.useCase && form.useCase.closest('.waitlist-field');
|
|
1160
|
-
function validateEmail() {
|
|
1161
|
-
if (!emailField) return;
|
|
1162
|
-
var v = (form.email.value || '').trim();
|
|
1163
|
-
if (!v) { setFieldState(emailField, 'empty', ''); return; }
|
|
1164
|
-
if (EMAIL_RE.test(v) && v.length <= 254) {
|
|
1165
|
-
setFieldState(emailField, 'ok', 'Looks good.');
|
|
1166
|
-
} else {
|
|
1167
|
-
setFieldState(emailField, 'err', 'That doesn’t look like an email.');
|
|
1168
|
-
}
|
|
1169
|
-
}
|
|
1170
|
-
function validateName() {
|
|
1171
|
-
if (!nameField) return;
|
|
1172
|
-
var v = (form.name.value || '').trim();
|
|
1173
|
-
if (!v) { setFieldState(nameField, 'empty', ''); return; }
|
|
1174
|
-
if (v.length > 120) {
|
|
1175
|
-
setFieldState(nameField, 'err', 'Keep names under 120 characters.');
|
|
1176
|
-
} else {
|
|
1177
|
-
setFieldState(nameField, 'ok', '');
|
|
1178
|
-
}
|
|
1179
|
-
}
|
|
1180
|
-
function validateUseCase() {
|
|
1181
|
-
if (!useCaseField) return;
|
|
1182
|
-
var v = (form.useCase.value || '').trim();
|
|
1183
|
-
if (!v) { setFieldState(useCaseField, 'empty', ''); return; }
|
|
1184
|
-
if (v.length > 2000) {
|
|
1185
|
-
setFieldState(useCaseField, 'err', 'Keep use case under 2000 characters.');
|
|
1186
|
-
} else {
|
|
1187
|
-
setFieldState(useCaseField, 'ok', '');
|
|
1188
|
-
}
|
|
1189
|
-
}
|
|
1190
|
-
if (form.email) {
|
|
1191
|
-
form.email.addEventListener('input', validateEmail);
|
|
1192
|
-
form.email.addEventListener('blur', validateEmail);
|
|
1193
|
-
}
|
|
1194
|
-
if (form.name) {
|
|
1195
|
-
form.name.addEventListener('input', validateName);
|
|
1196
|
-
}
|
|
1197
|
-
if (form.useCase) {
|
|
1198
|
-
form.useCase.addEventListener('input', validateUseCase);
|
|
1199
|
-
}
|
|
1200
|
-
|
|
1201
|
-
function getSource() {
|
|
1202
|
-
try {
|
|
1203
|
-
var p = new URLSearchParams(window.location.search);
|
|
1204
|
-
var s = p.get('utm_source') || '';
|
|
1205
|
-
return s.replace(/[^a-zA-Z0-9_-]/g, '').slice(0, 40) || null;
|
|
1206
|
-
} catch (_) { return null; }
|
|
1207
|
-
}
|
|
1208
|
-
|
|
1209
|
-
form.addEventListener('submit', async function (e) {
|
|
1210
|
-
e.preventDefault();
|
|
1211
|
-
errorEl.hidden = true;
|
|
1212
|
-
var btn = form.querySelector('button[type=submit]');
|
|
1213
|
-
var originalHtml = btn.innerHTML;
|
|
1214
|
-
btn.disabled = true;
|
|
1215
|
-
btn.textContent = 'Submitting…';
|
|
1216
|
-
try {
|
|
1217
|
-
var fd = new FormData(form);
|
|
1218
|
-
var payload = {
|
|
1219
|
-
email: String(fd.get('email') || '').trim(),
|
|
1220
|
-
name: String(fd.get('name') || '').trim() || undefined,
|
|
1221
|
-
useCase: String(fd.get('useCase') || '').trim() || undefined,
|
|
1222
|
-
userType: String(fd.get('userType') || '').trim() || undefined,
|
|
1223
|
-
source: getSource() || undefined,
|
|
1224
|
-
};
|
|
1225
|
-
var res = await fetch('/api/waitlist', {
|
|
1226
|
-
method: 'POST',
|
|
1227
|
-
headers: { 'Content-Type': 'application/json' },
|
|
1228
|
-
body: JSON.stringify(payload),
|
|
1229
|
-
});
|
|
1230
|
-
var data = {};
|
|
1231
|
-
try { data = await res.json(); } catch (_) {}
|
|
1232
|
-
if (!res.ok) {
|
|
1233
|
-
var msg = (data && data.error) ? data.error : ('HTTP ' + res.status);
|
|
1234
|
-
if (res.status === 429) msg = 'You already signed up recently. Check your inbox or try again in a few minutes.';
|
|
1235
|
-
throw new Error(msg);
|
|
1236
|
-
}
|
|
1237
|
-
var pos = data.position || '?';
|
|
1238
|
-
var sentLine = data.emailSent
|
|
1239
|
-
? 'You’re #' + pos + '. Check your inbox for confirmation from team@frame.dev.'
|
|
1240
|
-
: 'You’re #' + pos + '. Email confirmation is delayed; we’ll be in touch.';
|
|
1241
|
-
if (data.alreadyOnList) sentLine = 'You’re already on the list at #' + pos + '. We’ll be in touch.';
|
|
1242
|
-
successMsg.textContent = sentLine;
|
|
1243
|
-
form.hidden = true;
|
|
1244
|
-
successEl.hidden = false;
|
|
1245
|
-
} catch (err) {
|
|
1246
|
-
errorMsg.textContent = (err && err.message) ? err.message : 'Network error. Please try again.';
|
|
1247
|
-
errorEl.hidden = false;
|
|
1248
|
-
btn.disabled = false;
|
|
1249
|
-
btn.innerHTML = originalHtml;
|
|
1250
|
-
}
|
|
1251
|
-
});
|
|
1252
|
-
})();
|
|
1253
|
-
</script>
|
|
1254
|
-
|
|
1255
1022
|
<!-- FAQ -->
|
|
1256
1023
|
<section class="sec" id="faq">
|
|
1257
1024
|
<div class="sec-inner">
|
|
@@ -1289,7 +1056,7 @@ npm run dashboard <span class="cm"># opens http://localhost:3456</span>
|
|
|
1289
1056
|
|
|
1290
1057
|
<details class="faq-item"><summary>How does runtime tool forging work, and is it safe?</summary><div class="faq-body">
|
|
1291
1058
|
When a department agent needs a calculation the codebase doesn't provide, it writes one. A medical officer facing a radiation crisis writes a dose calculator. An engineer writes a structural load analyzer. The pipeline: specialist proposes a tool → Zod-validated input/output schema → JavaScript body authored by the LLM → run in an in-process <a href="https://nodejs.org/api/vm.html" target="_blank" rel="noopener"><code>node:vm</code> context</a> with a 10-second wall-clock limit, its heap use reported against a nominal 128 MB budget. The forge always rejects code that uses <code>eval</code>, <code>Function</code>, <code>require</code>, dynamic <code>import</code>, <code>process</code>, <code>child_process</code> or destructive <code>fs.*</code> calls, and paracosm grants forged code no network, file or crypto access. An LLM judge reviews the output against the specialist's stated intent — match approves, mismatch rejects. Approved tools land in a discoverable registry that subsequent turns and other actors pull from. Reuse via <code>call_forged_tool</code> costs tens of tokens; fresh forges cost full LLM tokens for proposal + body + scaffolding + judge. After turn three, most decisions invoke a previously-forged tool and total run cost flattens.
|
|
1292
|
-
<div class="faq-cite">Implementation: AgentOS <code>EmergentCapabilityEngine</code> + <code>EmergentJudge</code> + <code>ForgeToolMetaTool</code> + <code>CodeSandbox</code
|
|
1059
|
+
<div class="faq-cite">Implementation: AgentOS <code>EmergentCapabilityEngine</code> + <code>EmergentJudge</code> + <code>ForgeToolMetaTool</code> + <code>CodeSandbox</code>.</div>
|
|
1293
1060
|
</div></details>
|
|
1294
1061
|
|
|
1295
1062
|
<details class="faq-item"><summary>What is the HEXACO personality model and why use it?</summary><div class="faq-body">
|
|
@@ -1340,15 +1107,15 @@ npm run dashboard <span class="cm"># opens http://localhost:3456</span>
|
|
|
1340
1107
|
</div></details>
|
|
1341
1108
|
|
|
1342
1109
|
<details class="faq-item"><summary>Does Paracosm need an internet connection?</summary><div class="faq-body">
|
|
1343
|
-
Yes
|
|
1110
|
+
Yes. Compiling a scenario and running it both call the OpenAI or Anthropic API. Web search is optional. Live search is off by default for a run, and department research then comes from the scenario's knowledge bundle.
|
|
1344
1111
|
</div></details>
|
|
1345
1112
|
|
|
1346
1113
|
<details class="faq-item"><summary>Is Paracosm free?</summary><div class="faq-body">
|
|
1347
|
-
The engine is open source under <a href="https://opensource.org/licenses/Apache-2.0" target="_blank" rel="noopener">Apache-2.0</a>. Use it in commercial products without restriction: install from npm, fork the repo, build on it. You provide LLM API keys; running a 6-turn quality-preset run costs roughly $1-3 on OpenAI, $3-7 on Anthropic.
|
|
1114
|
+
The engine is open source under <a href="https://opensource.org/licenses/Apache-2.0" target="_blank" rel="noopener">Apache-2.0</a>. Use it in commercial products without restriction: install from npm, fork the repo, build on it. You provide LLM API keys; running a 6-turn quality-preset run costs roughly $1-3 on OpenAI, $3-7 on Anthropic. The hosted demo at <a href="https://paracosm.agentos.sh/sim">paracosm.agentos.sh/sim</a> is free to try. It runs on the host's API keys with capped run size and a daily limit per IP address, and your own OpenAI or Anthropic key lifts both.
|
|
1348
1115
|
</div></details>
|
|
1349
1116
|
|
|
1350
1117
|
<details class="faq-item"><summary>Where can I read more or contribute?</summary><div class="faq-body">
|
|
1351
|
-
Source: <a href="https://github.com/framerslab/paracosm" target="_blank" rel="noopener">github.com/framerslab/paracosm</a>. Cookbook: <a href="https://github.com/framerslab/paracosm/blob/master/docs/COOKBOOK.md" target="_blank" rel="noopener">docs/COOKBOOK.md</a>. Architecture write-up: <a href="https://github.com/framerslab/paracosm/blob/master/docs/ARCHITECTURE.md" target="_blank" rel="noopener">docs/ARCHITECTURE.md</a>. Long-form launch post (the wilds.ai vault story + engine reference, Johnny Dunn): <a href="https://agentos.sh/blog/paracosm-launch" target="_blank" rel="noopener">agentos.sh/blog/paracosm-launch</a>. AgentOS runtime: <a href="https://github.com/framerslab/agentos" target="_blank" rel="noopener">github.com/framerslab/agentos</a>. Benchmarks: <a href="https://github.com/framerslab/agentos-bench" target="_blank" rel="noopener">github.com/framerslab/agentos-bench</a>. Reading lists: <a href="https://github.com/AGI-Edgerunners/LLM-Agents-Papers" target="_blank" rel="noopener">LLM-Agents-Papers</a>, <a href="https://github.com/leofan90/Awesome-World-Models" target="_blank" rel="noopener">Awesome World Models</a>. Issues
|
|
1118
|
+
Source: <a href="https://github.com/framerslab/paracosm" target="_blank" rel="noopener">github.com/framerslab/paracosm</a>. Cookbook: <a href="https://github.com/framerslab/paracosm/blob/master/docs/COOKBOOK.md" target="_blank" rel="noopener">docs/COOKBOOK.md</a>. Architecture write-up: <a href="https://github.com/framerslab/paracosm/blob/master/docs/ARCHITECTURE.md" target="_blank" rel="noopener">docs/ARCHITECTURE.md</a>. Long-form launch post (the wilds.ai vault story + engine reference, Johnny Dunn): <a href="https://agentos.sh/blog/paracosm-launch" target="_blank" rel="noopener">agentos.sh/blog/paracosm-launch</a>. AgentOS runtime: <a href="https://github.com/framerslab/agentos" target="_blank" rel="noopener">github.com/framerslab/agentos</a>. Benchmarks: <a href="https://github.com/framerslab/agentos-bench" target="_blank" rel="noopener">github.com/framerslab/agentos-bench</a>. Reading lists: <a href="https://github.com/AGI-Edgerunners/LLM-Agents-Papers" target="_blank" rel="noopener">LLM-Agents-Papers</a>, <a href="https://github.com/leofan90/Awesome-World-Models" target="_blank" rel="noopener">Awesome World Models</a>. Issues and pull requests are welcome.
|
|
1352
1119
|
</div></details>
|
|
1353
1120
|
|
|
1354
1121
|
</div>
|
|
@@ -1374,6 +1141,8 @@ npm run dashboard <span class="cm"># opens http://localhost:3456</span>
|
|
|
1374
1141
|
<nav class="ft-links" aria-label="Footer">
|
|
1375
1142
|
<a href="https://agentos.sh">agentos.sh</a>
|
|
1376
1143
|
<a href="/docs">API Docs</a>
|
|
1144
|
+
<a href="https://github.com/framerslab/paracosm/blob/master/docs/HTTP_API.md" target="_blank" rel="noopener">HTTP API</a>
|
|
1145
|
+
<a href="https://github.com/framerslab/paracosm/blob/master/docs/COOKBOOK.md" target="_blank" rel="noopener">Cookbook</a>
|
|
1377
1146
|
<a href="https://agentos.sh/blog" target="_blank" rel="noopener">Blog</a>
|
|
1378
1147
|
<a href="https://github.com/framerslab/paracosm">GitHub</a>
|
|
1379
1148
|
<a href="https://www.npmjs.com/package/paracosm">npm</a>
|
|
@@ -30,10 +30,6 @@ export declare class IpRateLimiter {
|
|
|
30
30
|
private simStore;
|
|
31
31
|
private compileStore;
|
|
32
32
|
private chatStore;
|
|
33
|
-
/** Last waitlist-submission timestamp per IP (Unix ms). 5-minute
|
|
34
|
-
* sliding window — abuse mitigation only; genuine users only
|
|
35
|
-
* submit once. */
|
|
36
|
-
private waitlistLastSeen;
|
|
37
33
|
/** Single-bucket global counter for /chat. Per-IP caps are
|
|
38
34
|
* trivially evaded by IP rotation (VPNs, proxy pools, residential
|
|
39
35
|
* proxies), so we additionally cap the hosted-key chat budget
|
|
@@ -84,11 +80,6 @@ export declare class IpRateLimiter {
|
|
|
84
80
|
* decrements when the per-IP slot was actually granted, so a
|
|
85
81
|
* blocked-by-IP attempt doesn't burn the shared budget. */
|
|
86
82
|
consumeChat(ip: string): RateLimitDecision;
|
|
87
|
-
/** Per-IP 5-minute sliding cooldown for waitlist submissions.
|
|
88
|
-
* Decision shape matches the bucket-based methods so callers can
|
|
89
|
-
* treat them uniformly. Genuine users only ever submit once;
|
|
90
|
-
* the cap exists as abuse mitigation, not a budget. */
|
|
91
|
-
consumeWaitlist(ip: string): RateLimitDecision;
|
|
92
83
|
/** Get stats for monitoring endpoints. */
|
|
93
84
|
stats(): {
|
|
94
85
|
totalIps: number;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rate-limiter.d.ts","sourceRoot":"","sources":["../../src/server/rate-limiter.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AAcjD,MAAM,WAAW,iBAAiB;IAChC,OAAO,EAAE,OAAO,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;CACf;AAED,qBAAa,aAAa;IACxB,OAAO,CAAC,QAAQ,CAAqC;IACrD,OAAO,CAAC,YAAY,CAAqC;IACzD,OAAO,CAAC,SAAS,CAAqC;IACtD
|
|
1
|
+
{"version":3,"file":"rate-limiter.d.ts","sourceRoot":"","sources":["../../src/server/rate-limiter.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AAcjD,MAAM,WAAW,iBAAiB;IAChC,OAAO,EAAE,OAAO,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;CACf;AAED,qBAAa,aAAa;IACxB,OAAO,CAAC,QAAQ,CAAqC;IACrD,OAAO,CAAC,YAAY,CAAqC;IACzD,OAAO,CAAC,SAAS,CAAqC;IACtD;;;;wDAIoD;IACpD,OAAO,CAAC,UAAU,CAA4C;IAC9D,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,gBAAgB,CAAS;IACjC,OAAO,CAAC,cAAc,CAAS;IAC/B,OAAO,CAAC,oBAAoB,CAAS;IACrC,OAAO,CAAC,YAAY,CAAiC;IACrD,OAAO,CAAC,eAAe,CAAuB;IAC9C,OAAO,CAAC,YAAY,CAA8C;gBAGhE,SAAS,GAAE,MAAU,EACrB,gBAAgB,GAAE,MAAU,EAC5B,cAAc,GAAE,MAAW,EAC3B,eAAe,GAAE,MAAM,GAAG,IAAW,EACrC,oBAAoB,GAAE,MAAY;IAWpC,gFAAgF;IAChF,OAAO,CAAC,IAAI;IAyBZ,iEAAiE;IACjE,OAAO,CAAC,OAAO;IA0Bf;;;;;;;;;;;;;;;uEAemE;IACnE,MAAM,CAAC,KAAK,CAAC,GAAG,EAAE,eAAe,GAAG,MAAM;IAgB1C,OAAO,CAAC,SAAS;IAWjB,OAAO,CAAC,IAAI;IAyBZ,+DAA+D;IAC/D,KAAK,CAAC,EAAE,EAAE,MAAM,GAAG,iBAAiB;IAIpC,+EAA+E;IAC/E,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI;IAQxB,yEAAyE;IACzE,cAAc,CAAC,EAAE,EAAE,MAAM,GAAG,iBAAiB;IAI7C;;;;;gEAK4D;IAC5D,WAAW,CAAC,EAAE,EAAE,MAAM,GAAG,iBAAiB;IAyB1C,0CAA0C;IAC1C,KAAK,IAAI;QACP,QAAQ,EAAE,MAAM,CAAC;QACjB,GAAG,EAAE,KAAK,CAAC;YAAE,EAAE,EAAE,MAAM,CAAC;YAAC,KAAK,EAAE,MAAM,CAAC;YAAC,OAAO,EAAE,MAAM,CAAA;SAAE,CAAC,CAAC;QAC3D,OAAO,EAAE,KAAK,CAAC;YAAE,EAAE,EAAE,MAAM,CAAC;YAAC,KAAK,EAAE,MAAM,CAAC;YAAC,OAAO,EAAE,MAAM,CAAA;SAAE,CAAC,CAAC;QAC/D,IAAI,EAAE,KAAK,CAAC;YAAE,EAAE,EAAE,MAAM,CAAC;YAAC,KAAK,EAAE,MAAM,CAAC;YAAC,OAAO,EAAE,MAAM,CAAA;SAAE,CAAC,CAAC;KAC7D;IAWD,OAAO,CAAC,OAAO;IAcf,OAAO,IAAI,IAAI;CAIhB"}
|
|
@@ -24,10 +24,6 @@ export class IpRateLimiter {
|
|
|
24
24
|
simStore = new Map();
|
|
25
25
|
compileStore = new Map();
|
|
26
26
|
chatStore = new Map();
|
|
27
|
-
/** Last waitlist-submission timestamp per IP (Unix ms). 5-minute
|
|
28
|
-
* sliding window — abuse mitigation only; genuine users only
|
|
29
|
-
* submit once. */
|
|
30
|
-
waitlistLastSeen = new Map();
|
|
31
27
|
/** Single-bucket global counter for /chat. Per-IP caps are
|
|
32
28
|
* trivially evaded by IP rotation (VPNs, proxy pools, residential
|
|
33
29
|
* proxies), so we additionally cap the hosted-key chat budget
|
|
@@ -218,30 +214,6 @@ export class IpRateLimiter {
|
|
|
218
214
|
this.chatGlobal.count++;
|
|
219
215
|
return ipResult;
|
|
220
216
|
}
|
|
221
|
-
/** Per-IP 5-minute sliding cooldown for waitlist submissions.
|
|
222
|
-
* Decision shape matches the bucket-based methods so callers can
|
|
223
|
-
* treat them uniformly. Genuine users only ever submit once;
|
|
224
|
-
* the cap exists as abuse mitigation, not a budget. */
|
|
225
|
-
consumeWaitlist(ip) {
|
|
226
|
-
const COOLDOWN_MS = 5 * 60 * 1000;
|
|
227
|
-
const now = Date.now();
|
|
228
|
-
const last = this.waitlistLastSeen.get(ip);
|
|
229
|
-
if (last !== undefined && now - last < COOLDOWN_MS) {
|
|
230
|
-
return {
|
|
231
|
-
allowed: false,
|
|
232
|
-
remaining: 0,
|
|
233
|
-
resetAt: last + COOLDOWN_MS,
|
|
234
|
-
limit: 1,
|
|
235
|
-
};
|
|
236
|
-
}
|
|
237
|
-
this.waitlistLastSeen.set(ip, now);
|
|
238
|
-
return {
|
|
239
|
-
allowed: true,
|
|
240
|
-
remaining: 0,
|
|
241
|
-
resetAt: now + COOLDOWN_MS,
|
|
242
|
-
limit: 1,
|
|
243
|
-
};
|
|
244
|
-
}
|
|
245
217
|
/** Get stats for monitoring endpoints. */
|
|
246
218
|
stats() {
|
|
247
219
|
const dump = (s) => [...s.entries()].map(([ip, e]) => ({ ip, count: e.count, resetAt: new Date(e.resetAt).toISOString() }));
|
|
@@ -263,14 +235,6 @@ export class IpRateLimiter {
|
|
|
263
235
|
}
|
|
264
236
|
}
|
|
265
237
|
}
|
|
266
|
-
const WAITLIST_COOLDOWN_MS = 5 * 60 * 1000;
|
|
267
|
-
for (const [ip, last] of this.waitlistLastSeen) {
|
|
268
|
-
if (now - last >= WAITLIST_COOLDOWN_MS) {
|
|
269
|
-
this.waitlistLastSeen.delete(ip);
|
|
270
|
-
// No persist() — waitlistLastSeen is in-memory only; the
|
|
271
|
-
// persistence path only writes the count-based buckets.
|
|
272
|
-
}
|
|
273
|
-
}
|
|
274
238
|
if (mutated)
|
|
275
239
|
this.persist();
|
|
276
240
|
}
|