paracosm 0.7.409 → 0.7.431

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (146) hide show
  1. package/README.md +79 -14
  2. package/dist/cli/compile.d.ts +1 -1
  3. package/dist/cli/compile.js +4 -4
  4. package/dist/cli/fetch-seed-url.d.ts +48 -0
  5. package/dist/cli/fetch-seed-url.d.ts.map +1 -0
  6. package/dist/cli/fetch-seed-url.js +109 -0
  7. package/dist/cli/fetch-seed-url.js.map +1 -0
  8. package/dist/cli/fork-preconditions.d.ts +17 -0
  9. package/dist/cli/fork-preconditions.d.ts.map +1 -0
  10. package/dist/cli/fork-preconditions.js +51 -0
  11. package/dist/cli/fork-preconditions.js.map +1 -0
  12. package/dist/cli/init-templates.d.ts +43 -0
  13. package/dist/cli/init-templates.d.ts.map +1 -0
  14. package/dist/cli/init-templates.js +141 -0
  15. package/dist/cli/init-templates.js.map +1 -0
  16. package/dist/cli/init.d.ts +46 -0
  17. package/dist/cli/init.d.ts.map +1 -0
  18. package/dist/cli/init.js +207 -0
  19. package/dist/cli/init.js.map +1 -0
  20. package/dist/cli/pair-runner.d.ts +25 -2
  21. package/dist/cli/pair-runner.d.ts.map +1 -1
  22. package/dist/cli/pair-runner.js +141 -5
  23. package/dist/cli/pair-runner.js.map +1 -1
  24. package/dist/cli/quickstart-routes.d.ts +35 -0
  25. package/dist/cli/quickstart-routes.d.ts.map +1 -0
  26. package/dist/cli/quickstart-routes.js +100 -0
  27. package/dist/cli/quickstart-routes.js.map +1 -0
  28. package/dist/cli/run.js +8 -0
  29. package/dist/cli/run.js.map +1 -1
  30. package/dist/cli/server/enrich-run-record.d.ts +22 -0
  31. package/dist/cli/server/enrich-run-record.d.ts.map +1 -0
  32. package/dist/cli/server/enrich-run-record.js +27 -0
  33. package/dist/cli/server/enrich-run-record.js.map +1 -0
  34. package/dist/cli/server/routes/platform-api.d.ts +19 -3
  35. package/dist/cli/server/routes/platform-api.d.ts.map +1 -1
  36. package/dist/cli/server/routes/platform-api.js +174 -5
  37. package/dist/cli/server/routes/platform-api.js.map +1 -1
  38. package/dist/cli/server/run-history-store.d.ts +27 -1
  39. package/dist/cli/server/run-history-store.d.ts.map +1 -1
  40. package/dist/cli/server/run-history-store.js +5 -0
  41. package/dist/cli/server/run-history-store.js.map +1 -1
  42. package/dist/cli/server/run-record.d.ts +13 -0
  43. package/dist/cli/server/run-record.d.ts.map +1 -1
  44. package/dist/cli/server/run-record.js.map +1 -1
  45. package/dist/cli/server/sqlite-run-history-store.d.ts +6 -0
  46. package/dist/cli/server/sqlite-run-history-store.d.ts.map +1 -0
  47. package/dist/cli/server/sqlite-run-history-store.js +226 -0
  48. package/dist/cli/server/sqlite-run-history-store.js.map +1 -0
  49. package/dist/cli/server-app.d.ts +73 -2
  50. package/dist/cli/server-app.d.ts.map +1 -1
  51. package/dist/cli/server-app.js +409 -159
  52. package/dist/cli/server-app.js.map +1 -1
  53. package/dist/cli/session-title.js +1 -1
  54. package/dist/cli/sim-config.d.ts +13 -0
  55. package/dist/cli/sim-config.d.ts.map +1 -1
  56. package/dist/cli/sim-config.js +8 -1
  57. package/dist/cli/sim-config.js.map +1 -1
  58. package/dist/cli/simulate-route.d.ts +103 -0
  59. package/dist/cli/simulate-route.d.ts.map +1 -0
  60. package/dist/cli/simulate-route.js +95 -0
  61. package/dist/cli/simulate-route.js.map +1 -0
  62. package/dist/engine/compiler/cache.d.ts +2 -2
  63. package/dist/engine/compiler/cache.js +2 -2
  64. package/dist/engine/compiler/compile-from-seed.d.ts +78 -0
  65. package/dist/engine/compiler/compile-from-seed.d.ts.map +1 -0
  66. package/dist/engine/compiler/compile-from-seed.js +93 -0
  67. package/dist/engine/compiler/compile-from-seed.js.map +1 -0
  68. package/dist/engine/compiler/generate-fingerprint.d.ts.map +1 -1
  69. package/dist/engine/compiler/generate-fingerprint.js +3 -6
  70. package/dist/engine/compiler/generate-fingerprint.js.map +1 -1
  71. package/dist/engine/compiler/generate-politics.d.ts.map +1 -1
  72. package/dist/engine/compiler/generate-politics.js +3 -6
  73. package/dist/engine/compiler/generate-politics.js.map +1 -1
  74. package/dist/engine/compiler/generate-progression.d.ts +10 -1
  75. package/dist/engine/compiler/generate-progression.d.ts.map +1 -1
  76. package/dist/engine/compiler/generate-progression.js +15 -15
  77. package/dist/engine/compiler/generate-progression.js.map +1 -1
  78. package/dist/engine/compiler/generate-prompts.d.ts.map +1 -1
  79. package/dist/engine/compiler/generate-prompts.js +4 -7
  80. package/dist/engine/compiler/generate-prompts.js.map +1 -1
  81. package/dist/engine/compiler/generate-reactions.d.ts.map +1 -1
  82. package/dist/engine/compiler/generate-reactions.js +3 -6
  83. package/dist/engine/compiler/generate-reactions.js.map +1 -1
  84. package/dist/engine/compiler/index.d.ts +9 -6
  85. package/dist/engine/compiler/index.d.ts.map +1 -1
  86. package/dist/engine/compiler/index.js +9 -6
  87. package/dist/engine/compiler/index.js.map +1 -1
  88. package/dist/engine/compiler/sandbox-runner.d.ts +40 -0
  89. package/dist/engine/compiler/sandbox-runner.d.ts.map +1 -0
  90. package/dist/engine/compiler/sandbox-runner.js +278 -0
  91. package/dist/engine/compiler/sandbox-runner.js.map +1 -0
  92. package/dist/engine/compiler/scenario-fixture.d.ts +4 -4
  93. package/dist/engine/compiler/scenario-fixture.js +4 -4
  94. package/dist/engine/compiler/seed-ingestion.d.ts +2 -2
  95. package/dist/engine/compiler/seed-ingestion.js +2 -2
  96. package/dist/engine/compiler/state-shape-block.d.ts +1 -1
  97. package/dist/engine/compiler/state-shape-block.js +5 -5
  98. package/dist/engine/compiler/types.d.ts +2 -2
  99. package/dist/engine/compiler/types.d.ts.map +1 -1
  100. package/dist/engine/compiler/validate.js +1 -1
  101. package/dist/engine/core/kernel.d.ts +4 -4
  102. package/dist/engine/core/kernel.js +6 -6
  103. package/dist/engine/core/progression.d.ts +3 -3
  104. package/dist/engine/core/progression.js +21 -21
  105. package/dist/engine/core/state.d.ts +7 -5
  106. package/dist/engine/core/state.d.ts.map +1 -1
  107. package/dist/engine/digital-twin/index.d.ts +41 -0
  108. package/dist/engine/digital-twin/index.d.ts.map +1 -0
  109. package/dist/engine/digital-twin/index.js +40 -0
  110. package/dist/engine/digital-twin/index.js.map +1 -0
  111. package/dist/engine/index.d.ts +1 -1
  112. package/dist/engine/leader-presets.d.ts +39 -0
  113. package/dist/engine/leader-presets.d.ts.map +1 -0
  114. package/dist/engine/leader-presets.js +118 -0
  115. package/dist/engine/leader-presets.js.map +1 -0
  116. package/dist/engine/lunar/fingerprint.js +2 -2
  117. package/dist/engine/lunar/prompts.js +2 -2
  118. package/dist/engine/mars/fingerprint.js +1 -1
  119. package/dist/engine/mars/metrics.d.ts +2 -2
  120. package/dist/engine/mars/metrics.js +2 -2
  121. package/dist/engine/mars/prompts.js +3 -3
  122. package/dist/runtime/build-artifact.d.ts +2 -1
  123. package/dist/runtime/build-artifact.d.ts.map +1 -1
  124. package/dist/runtime/build-artifact.js +2 -1
  125. package/dist/runtime/build-artifact.js.map +1 -1
  126. package/dist/runtime/canonical-json.d.ts +25 -0
  127. package/dist/runtime/canonical-json.d.ts.map +1 -0
  128. package/dist/runtime/canonical-json.js +46 -0
  129. package/dist/runtime/canonical-json.js.map +1 -0
  130. package/dist/runtime/contracts.d.ts +1 -1
  131. package/dist/runtime/departments.js +1 -1
  132. package/dist/runtime/orchestrator.d.ts +44 -4
  133. package/dist/runtime/orchestrator.d.ts.map +1 -1
  134. package/dist/runtime/orchestrator.js +125 -33
  135. package/dist/runtime/orchestrator.js.map +1 -1
  136. package/dist/runtime/parsers.js +5 -5
  137. package/dist/runtime/reaction-step.js +2 -2
  138. package/dist/runtime/world-model/index.d.ts +172 -18
  139. package/dist/runtime/world-model/index.d.ts.map +1 -1
  140. package/dist/runtime/world-model/index.js +242 -4
  141. package/dist/runtime/world-model/index.js.map +1 -1
  142. package/dist/runtime/world-snapshot.d.ts +13 -0
  143. package/dist/runtime/world-snapshot.d.ts.map +1 -0
  144. package/dist/runtime/world-snapshot.js +19 -0
  145. package/dist/runtime/world-snapshot.js.map +1 -0
  146. package/package.json +19 -4
@@ -0,0 +1,141 @@
1
+ /**
2
+ * Pure renderer functions for the files emitted by `paracosm init`.
3
+ * Each function takes a small input record and returns the file contents
4
+ * as a string. No I/O, no dependencies on the caller's environment.
5
+ *
6
+ * Kept separate from init.ts so the renderers snapshot-test trivially.
7
+ *
8
+ * @module paracosm/cli/init-templates
9
+ */
10
+ export function renderPackageJson(input) {
11
+ const pkg = {
12
+ name: input.name,
13
+ version: '0.1.0',
14
+ private: true,
15
+ type: 'module',
16
+ scripts: {
17
+ start: 'node run.mjs',
18
+ },
19
+ dependencies: {
20
+ paracosm: `^${input.paracosmVersion}`,
21
+ },
22
+ };
23
+ return JSON.stringify(pkg, null, 2) + '\n';
24
+ }
25
+ /**
26
+ * Render the entry script for a paracosm-init scaffolded project.
27
+ *
28
+ * The script imports `runSimulation` from `paracosm/runtime` and runs the
29
+ * leader at index 0 against a turn-loop simulation. Mode is intentionally
30
+ * NOT a runtime input: it is a property of the produced
31
+ * `RunArtifact.metadata`, surfaced after the run completes. Batch-trajectory
32
+ * and batch-point modes are produced by `runBatch` (different entry point,
33
+ * different config shape); a future spec adds a separate `renderRunMjsBatch`
34
+ * for those modes.
35
+ */
36
+ export function renderRunMjs() {
37
+ return `#!/usr/bin/env node
38
+ /**
39
+ * Entry script for a paracosm-init scaffolded project.
40
+ *
41
+ * Reads scenario.json + leaders.json from this directory, runs the
42
+ * configured leader at index 0, and prints the resulting RunArtifact JSON.
43
+ * Edit the leader index, maxTurns, or seed below to explore.
44
+ *
45
+ * The "mode" of the resulting run lives on artifact.metadata.mode and is
46
+ * always "turn-loop" for runs produced by runSimulation. For
47
+ * batch-trajectory or batch-point modes, use runBatch directly.
48
+ */
49
+ import { readFileSync } from 'node:fs';
50
+ import { resolve, dirname } from 'node:path';
51
+ import { fileURLToPath } from 'node:url';
52
+ import { runSimulation } from 'paracosm/runtime';
53
+
54
+ const here = dirname(fileURLToPath(import.meta.url));
55
+ const scenario = JSON.parse(readFileSync(resolve(here, 'scenario.json'), 'utf-8'));
56
+ const leaders = JSON.parse(readFileSync(resolve(here, 'leaders.json'), 'utf-8'));
57
+
58
+ if (!Array.isArray(leaders) || leaders.length === 0) {
59
+ console.error('leaders.json is empty. Re-run \\\`paracosm init\\\` to regenerate.');
60
+ process.exit(1);
61
+ }
62
+
63
+ const leader = leaders[0];
64
+
65
+ const result = await runSimulation(leader, [], {
66
+ scenario,
67
+ maxTurns: 6,
68
+ seed: 42,
69
+ });
70
+
71
+ console.log(JSON.stringify(result, null, 2));
72
+ `;
73
+ }
74
+ export function renderReadme(input) {
75
+ return `# ${input.name}
76
+
77
+ Scaffolded by \`paracosm init\` from the seed:
78
+
79
+ > ${input.domain.slice(0, 200)}${input.domain.length > 200 ? '...' : ''}
80
+
81
+ This project contains:
82
+
83
+ - \`scenario.json\`: compiled \`ScenarioPackage\` (LLM-generated at init time)
84
+ - \`leaders.json\`: ${input.leaders} HEXACO leader configs (LLM-generated)
85
+ - \`run.mjs\`: minimal entry script that runs leader 0 in \`${input.mode}\` mode
86
+
87
+ ## Quickstart
88
+
89
+ \`\`\`bash
90
+ npm install
91
+ cp .env.example .env
92
+ # Set OPENAI_API_KEY (and any other provider keys you need) in .env
93
+ node run.mjs
94
+ \`\`\`
95
+
96
+ ## Customizing
97
+
98
+ - Edit \`scenario.json\` to tweak departments, world state, events.
99
+ - Edit \`leaders.json\` to swap HEXACO traits or instructions.
100
+ - Edit \`run.mjs\` to change the leader index, mode, turn count, or seed.
101
+
102
+ See https://github.com/framersai/paracosm for the full API reference.
103
+ `;
104
+ }
105
+ export function renderEnvExample() {
106
+ return `# Required for compileScenario / generateText / generateObject calls.
107
+ OPENAI_API_KEY=
108
+
109
+ # Optional alternate providers paracosm can route to.
110
+ ANTHROPIC_API_KEY=
111
+ GOOGLE_API_KEY=
112
+
113
+ # Optional Cohere rerank for higher-accuracy retrieval.
114
+ COHERE_API_KEY=
115
+ `;
116
+ }
117
+ export function renderGitignore() {
118
+ return `node_modules/
119
+ .env
120
+ .paracosm/
121
+ dist/
122
+ *.log
123
+ .DS_Store
124
+ `;
125
+ }
126
+ /**
127
+ * Slug-normalize a project name. Lowercase ASCII, dashes between words,
128
+ * strips everything else, max 50 chars. If empty after stripping,
129
+ * returns 'paracosm-app'.
130
+ */
131
+ export function slugifyName(raw) {
132
+ const slug = raw
133
+ .toLowerCase()
134
+ .normalize('NFKD')
135
+ .replace(/[̀-ͯ]/g, '')
136
+ .replace(/[^a-z0-9]+/g, '-')
137
+ .replace(/^-+|-+$/g, '')
138
+ .slice(0, 50);
139
+ return slug || 'paracosm-app';
140
+ }
141
+ //# sourceMappingURL=init-templates.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init-templates.js","sourceRoot":"","sources":["../../src/cli/init-templates.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAOH,MAAM,UAAU,iBAAiB,CAAC,KAAuB;IACvD,MAAM,GAAG,GAAG;QACV,IAAI,EAAE,KAAK,CAAC,IAAI;QAChB,OAAO,EAAE,OAAO;QAChB,OAAO,EAAE,IAAI;QACb,IAAI,EAAE,QAAQ;QACd,OAAO,EAAE;YACP,KAAK,EAAE,cAAc;SACtB;QACD,YAAY,EAAE;YACZ,QAAQ,EAAE,IAAI,KAAK,CAAC,eAAe,EAAE;SACtC;KACF,CAAC;IACF,OAAO,IAAI,CAAC,SAAS,CAAC,GAAG,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,IAAI,CAAC;AAC7C,CAAC;AAID;;;;;;;;;;GAUG;AACH,MAAM,UAAU,YAAY;IAC1B,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAmCR,CAAC;AACF,CAAC;AASD,MAAM,UAAU,YAAY,CAAC,KAAkB;IAC7C,OAAO,KAAK,KAAK,CAAC,IAAI;;;;IAIpB,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,GAAG,KAAK,CAAC,MAAM,CAAC,MAAM,GAAG,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE;;;;;sBAKjD,KAAK,CAAC,OAAO;8DAC2B,KAAK,CAAC,IAAI;;;;;;;;;;;;;;;;;;CAkBvE,CAAC;AACF,CAAC;AAED,MAAM,UAAU,gBAAgB;IAC9B,OAAO;;;;;;;;;CASR,CAAC;AACF,CAAC;AAED,MAAM,UAAU,eAAe;IAC7B,OAAO;;;;;;CAMR,CAAC;AACF,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,WAAW,CAAC,GAAW;IACrC,MAAM,IAAI,GAAG,GAAG;SACb,WAAW,EAAE;SACb,SAAS,CAAC,MAAM,CAAC;SACjB,OAAO,CAAC,QAAQ,EAAE,EAAE,CAAC;SACrB,OAAO,CAAC,aAAa,EAAE,GAAG,CAAC;SAC3B,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC;SACvB,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IAChB,OAAO,IAAI,IAAI,cAAc,CAAC;AAChC,CAAC"}
@@ -0,0 +1,46 @@
1
+ import { compileFromSeed } from '../engine/compiler/compile-from-seed.js';
2
+ import { generateQuickstartLeaders } from '../runtime/world-model/index.js';
3
+ import { type SimulationMode } from './init-templates.js';
4
+ export interface InitOptions {
5
+ outputDir: string;
6
+ domain: string;
7
+ mode: SimulationMode;
8
+ leaders: number;
9
+ name: string;
10
+ force: boolean;
11
+ }
12
+ export interface InitArgError {
13
+ ok: false;
14
+ message: string;
15
+ }
16
+ export type InitArgResult = {
17
+ ok: true;
18
+ options: InitOptions;
19
+ } | InitArgError;
20
+ /**
21
+ * Parse the argv slice that follows `paracosm init`. Returns either a
22
+ * fully-resolved InitOptions or an InitArgError with a user-facing
23
+ * message that includes USAGE.
24
+ */
25
+ export declare function parseInitArgs(argv: readonly string[]): InitArgResult;
26
+ /**
27
+ * Hook seam for tests. Real implementation calls compileFromSeed +
28
+ * generateQuickstartLeaders + URL fetch directly. Tests pass mocks.
29
+ */
30
+ export interface RunInitDeps {
31
+ fetchSeedFromUrl?: (url: string) => Promise<{
32
+ text: string;
33
+ title: string;
34
+ }>;
35
+ compileFromSeed?: typeof compileFromSeed;
36
+ generateQuickstartLeaders?: typeof generateQuickstartLeaders;
37
+ readEnv?: () => NodeJS.ProcessEnv;
38
+ paracosmVersion?: string;
39
+ log?: (msg: string) => void;
40
+ }
41
+ /**
42
+ * Main flow. Returns 0 on success, non-zero on user-facing error
43
+ * (also prints a message to stderr in the error case).
44
+ */
45
+ export declare function runInit(argv: readonly string[], deps?: RunInitDeps): Promise<number>;
46
+ //# sourceMappingURL=init.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/cli/init.ts"],"names":[],"mappings":"AAcA,OAAO,EAAE,eAAe,EAAE,MAAM,yCAAyC,CAAC;AAC1E,OAAO,EAAE,yBAAyB,EAAE,MAAM,iCAAiC,CAAC;AAE5E,OAAO,EAOL,KAAK,cAAc,EACpB,MAAM,qBAAqB,CAAC;AAE7B,MAAM,WAAW,WAAW;IAC1B,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,cAAc,CAAC;IACrB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,OAAO,CAAC;CAChB;AAED,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,KAAK,CAAC;IACV,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,MAAM,aAAa,GAAG;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,OAAO,EAAE,WAAW,CAAA;CAAE,GAAG,YAAY,CAAC;AAqB9E;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,GAAG,aAAa,CA0DpE;AA6BD;;;GAGG;AACH,MAAM,WAAW,WAAW;IAC1B,gBAAgB,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC7E,eAAe,CAAC,EAAE,OAAO,eAAe,CAAC;IACzC,yBAAyB,CAAC,EAAE,OAAO,yBAAyB,CAAC;IAC7D,OAAO,CAAC,EAAE,MAAM,MAAM,CAAC,UAAU,CAAC;IAClC,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,GAAG,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;CAC7B;AAED;;;GAGG;AACH,wBAAsB,OAAO,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,EAAE,IAAI,GAAE,WAAgB,GAAG,OAAO,CAAC,MAAM,CAAC,CAgF9F"}
@@ -0,0 +1,207 @@
1
+ /**
2
+ * `paracosm init` subcommand. Scaffolds a runnable paracosm project
3
+ * from a seed text or URL via the existing compileFromSeed +
4
+ * generateQuickstartLeaders infrastructure.
5
+ *
6
+ * Flag-driven only (no interactive prompts) so it composes with shell
7
+ * scripts and CI. URL handling mirrors the server-app.ts pattern that
8
+ * dynamically imports AgentOS WebSearchService from the web-search subpath.
9
+ *
10
+ * @module paracosm/cli/init
11
+ */
12
+ import { mkdirSync, readdirSync, writeFileSync, existsSync, readFileSync } from 'node:fs';
13
+ import { resolve, basename, dirname } from 'node:path';
14
+ import { fileURLToPath } from 'node:url';
15
+ import { compileFromSeed } from '../engine/compiler/compile-from-seed.js';
16
+ import { generateQuickstartLeaders } from '../runtime/world-model/index.js';
17
+ import { fetchSeedFromUrl as fetchSeedFromUrlViaAgentOS } from './fetch-seed-url.js';
18
+ import { renderPackageJson, renderRunMjs, renderReadme, renderEnvExample, renderGitignore, slugifyName, } from './init-templates.js';
19
+ const VALID_MODES = new Set([
20
+ 'turn-loop',
21
+ 'batch-trajectory',
22
+ 'batch-point',
23
+ ]);
24
+ const USAGE = `paracosm init [dir] --domain <text|url> [--mode <m>] [--leaders <n>] [--name <name>] [--force]
25
+
26
+ dir output directory (default: ./paracosm-app)
27
+ --domain required: seed text describing the scenario, OR a URL
28
+ --mode turn-loop | batch-trajectory | batch-point (default: turn-loop)
29
+ --leaders number of HEXACO leaders, 2-6 (default: 3)
30
+ --name project name, default: derived from --domain
31
+ --force overwrite non-empty target dir
32
+
33
+ example:
34
+ paracosm init my-app --domain "Submarine crew of 8 in deep ocean for 30 days" --leaders 3
35
+ `;
36
+ /**
37
+ * Parse the argv slice that follows `paracosm init`. Returns either a
38
+ * fully-resolved InitOptions or an InitArgError with a user-facing
39
+ * message that includes USAGE.
40
+ */
41
+ export function parseInitArgs(argv) {
42
+ let outputDir;
43
+ let domain;
44
+ let mode = 'turn-loop';
45
+ let leaders = 3;
46
+ let name;
47
+ let force = false;
48
+ for (let i = 0; i < argv.length; i++) {
49
+ const arg = argv[i];
50
+ if (arg === '--domain') {
51
+ domain = argv[++i];
52
+ }
53
+ else if (arg === '--mode') {
54
+ const candidate = argv[++i];
55
+ if (!VALID_MODES.has(candidate)) {
56
+ return { ok: false, message: `Invalid --mode "${candidate}". Must be one of: turn-loop, batch-trajectory, batch-point.\n\n${USAGE}` };
57
+ }
58
+ mode = candidate;
59
+ }
60
+ else if (arg === '--leaders') {
61
+ const n = Number(argv[++i]);
62
+ if (!Number.isFinite(n) || n < 2 || n > 6 || !Number.isInteger(n)) {
63
+ return { ok: false, message: `Invalid --leaders "${argv[i]}". Must be an integer in [2, 6].\n\n${USAGE}` };
64
+ }
65
+ leaders = n;
66
+ }
67
+ else if (arg === '--name') {
68
+ name = argv[++i];
69
+ }
70
+ else if (arg === '--force') {
71
+ force = true;
72
+ }
73
+ else if (arg.startsWith('--')) {
74
+ return { ok: false, message: `Unknown flag: ${arg}\n\n${USAGE}` };
75
+ }
76
+ else if (outputDir === undefined) {
77
+ outputDir = arg;
78
+ }
79
+ else {
80
+ return { ok: false, message: `Unexpected positional argument: ${arg}\n\n${USAGE}` };
81
+ }
82
+ }
83
+ if (!domain) {
84
+ return { ok: false, message: `--domain is required.\n\n${USAGE}` };
85
+ }
86
+ if (domain.length > 50_000) {
87
+ return { ok: false, message: `--domain too long (${domain.length} chars; max 50000).\n\n${USAGE}` };
88
+ }
89
+ const resolvedDir = resolve(outputDir ?? './paracosm-app');
90
+ const resolvedName = name ?? slugifyName(basename(resolvedDir));
91
+ return {
92
+ ok: true,
93
+ options: {
94
+ outputDir: resolvedDir,
95
+ domain,
96
+ mode,
97
+ leaders,
98
+ name: resolvedName,
99
+ force,
100
+ },
101
+ };
102
+ }
103
+ function isUrl(s) {
104
+ return /^https?:\/\//.test(s);
105
+ }
106
+ function isDirEmpty(dir) {
107
+ if (!existsSync(dir))
108
+ return true;
109
+ return readdirSync(dir).length === 0;
110
+ }
111
+ /**
112
+ * Read the paracosm package.json sitting two directories up from this
113
+ * module file. Works from both the tsx (src/cli/init.ts) and built
114
+ * (dist/cli/init.js) layouts because both mirror src/.
115
+ *
116
+ * @returns The semver version string from paracosm's package.json.
117
+ * @throws Error when the package.json is unreadable or missing a version.
118
+ */
119
+ function readOwnVersion() {
120
+ const here = dirname(fileURLToPath(import.meta.url));
121
+ const pkgPath = resolve(here, '../../package.json');
122
+ const raw = JSON.parse(readFileSync(pkgPath, 'utf-8'));
123
+ if (typeof raw.version !== 'string' || raw.version.length === 0) {
124
+ throw new Error('paracosm package.json is missing a version field');
125
+ }
126
+ return raw.version;
127
+ }
128
+ /**
129
+ * Main flow. Returns 0 on success, non-zero on user-facing error
130
+ * (also prints a message to stderr in the error case).
131
+ */
132
+ export async function runInit(argv, deps = {}) {
133
+ const log = deps.log ?? ((m) => console.log(m));
134
+ const env = (deps.readEnv ?? (() => process.env))();
135
+ const parsed = parseInitArgs(argv);
136
+ if (!parsed.ok) {
137
+ process.stderr.write(parsed.message + '\n');
138
+ return 2;
139
+ }
140
+ const opts = parsed.options;
141
+ if (!env.OPENAI_API_KEY) {
142
+ process.stderr.write('Set OPENAI_API_KEY in your environment before running paracosm init.\n');
143
+ return 2;
144
+ }
145
+ if (!isDirEmpty(opts.outputDir) && !opts.force) {
146
+ process.stderr.write(`Target directory ${opts.outputDir} is not empty. Pass --force to overwrite.\n`);
147
+ return 2;
148
+ }
149
+ // Resolve seed text: URL fetch or pass-through.
150
+ let seedText = opts.domain;
151
+ if (isUrl(opts.domain)) {
152
+ log(`[paracosm init] Resolving URL: ${opts.domain}`);
153
+ try {
154
+ const fetcher = deps.fetchSeedFromUrl ?? fetchSeedFromUrlViaAgentOS;
155
+ const fetched = await fetcher(opts.domain);
156
+ seedText = fetched.text;
157
+ }
158
+ catch (err) {
159
+ process.stderr.write(`Failed to fetch URL ${opts.domain}: ${String(err)}\n`);
160
+ return 2;
161
+ }
162
+ }
163
+ if (seedText.length < 200) {
164
+ process.stderr.write(`Seed text too short (${seedText.length} chars; minimum 200). For URLs, the fetched body must contain enough content.\n`);
165
+ return 2;
166
+ }
167
+ if (seedText.length > 50_000) {
168
+ seedText = seedText.slice(0, 50_000);
169
+ }
170
+ log(`[paracosm init] Compiling scenario...`);
171
+ let scenario;
172
+ try {
173
+ const compile = deps.compileFromSeed ?? compileFromSeed;
174
+ scenario = await compile({ seedText });
175
+ }
176
+ catch (err) {
177
+ process.stderr.write(`Scenario compile failed: ${String(err)}\n`);
178
+ return 2;
179
+ }
180
+ log(`[paracosm init] Generating ${opts.leaders} HEXACO leaders...`);
181
+ let leaders;
182
+ try {
183
+ const gen = deps.generateQuickstartLeaders ?? generateQuickstartLeaders;
184
+ leaders = await gen(scenario, opts.leaders, {});
185
+ }
186
+ catch (err) {
187
+ process.stderr.write(`Leader generation failed: ${String(err)}\n`);
188
+ return 2;
189
+ }
190
+ log(`[paracosm init] Writing files to ${opts.outputDir}/...`);
191
+ mkdirSync(opts.outputDir, { recursive: true });
192
+ const paracosmVersion = deps.paracosmVersion ?? readOwnVersion();
193
+ writeFileSync(`${opts.outputDir}/package.json`, renderPackageJson({ name: opts.name, paracosmVersion }));
194
+ writeFileSync(`${opts.outputDir}/scenario.json`, JSON.stringify(scenario, null, 2) + '\n');
195
+ writeFileSync(`${opts.outputDir}/leaders.json`, JSON.stringify(leaders, null, 2) + '\n');
196
+ writeFileSync(`${opts.outputDir}/run.mjs`, renderRunMjs());
197
+ writeFileSync(`${opts.outputDir}/README.md`, renderReadme({ name: opts.name, domain: opts.domain, mode: opts.mode, leaders: opts.leaders }));
198
+ writeFileSync(`${opts.outputDir}/.env.example`, renderEnvExample());
199
+ writeFileSync(`${opts.outputDir}/.gitignore`, renderGitignore());
200
+ log(`[paracosm init] Done. Run:`);
201
+ log(` cd ${basename(opts.outputDir)}`);
202
+ log(` npm install`);
203
+ log(` cp .env.example .env # edit to add your API key`);
204
+ log(` node run.mjs`);
205
+ return 0;
206
+ }
207
+ //# sourceMappingURL=init.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init.js","sourceRoot":"","sources":["../../src/cli/init.ts"],"names":[],"mappings":"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"}
@@ -19,7 +19,14 @@ signal?: AbortSignal,
19
19
  * actually get their own hooks + labels run instead of silently
20
20
  * falling back to Mars while the page title shows the custom name.
21
21
  */
22
- scenario?: ScenarioPackage): Promise<void>;
22
+ scenario?: ScenarioPackage,
23
+ /**
24
+ * Optional callback fired after each leader's artifact completes.
25
+ * server-app uses this to insert a RunRecord per artifact into
26
+ * the SQLite run-history store. Failures inside the callback are
27
+ * caught and logged so a failing handler does not break the run.
28
+ */
29
+ onArtifact?: (artifact: import('../engine/schema/index.js').RunArtifact, leader: import('../runtime/orchestrator.js').LeaderConfig) => void | Promise<void>): Promise<void>;
23
30
  /**
24
31
  * Single-leader fork dispatch (Spec 2B). When `/setup` receives a
25
32
  * config with `forkFrom` set, the server branches here instead of
@@ -36,5 +43,21 @@ scenario?: ScenarioPackage): Promise<void>;
36
43
  * snapshots, single-leader guard) happened in the `/setup` handler
37
44
  * before this function is reached.
38
45
  */
39
- export declare function runForkSimulation(simConfig: NormalizedSimulationConfig, broadcast: BroadcastFn, signal?: AbortSignal, scenario?: ScenarioPackage): Promise<void>;
46
+ export declare function runForkSimulation(simConfig: NormalizedSimulationConfig, broadcast: BroadcastFn, signal?: AbortSignal, scenario?: ScenarioPackage,
47
+ /** Optional callback fired after the forked artifact completes. */
48
+ onArtifact?: (artifact: import('../engine/schema/index.js').RunArtifact, leader: import('../runtime/orchestrator.js').LeaderConfig) => void | Promise<void>): Promise<void>;
49
+ /**
50
+ * Generalized N-leader batch runner (Tier 5 Quickstart). Three or more
51
+ * leaders run against the same scenario + seed in parallel, each
52
+ * emitting per-leader SSE events identical to the pair path. No
53
+ * verdict generation: verdicts compare exactly two leaders and would
54
+ * be ambiguous across N >= 3. The dashboard's Quickstart tab surfaces
55
+ * group-median deltas instead.
56
+ *
57
+ * Per-leader tags are derived from archetype (lowercased, kebab-cased).
58
+ * Duplicate archetype strings get trailing indices for disambiguation.
59
+ */
60
+ export declare function runBatchSimulations(simConfig: NormalizedSimulationConfig, broadcast: BroadcastFn, signal?: AbortSignal, scenario?: ScenarioPackage,
61
+ /** Optional callback fired after each leader's artifact completes. */
62
+ onArtifact?: (artifact: import('../engine/schema/index.js').RunArtifact, leader: import('../runtime/orchestrator.js').LeaderConfig) => void | Promise<void>): Promise<void>;
40
63
  //# sourceMappingURL=pair-runner.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"pair-runner.d.ts","sourceRoot":"","sources":["../../src/cli/pair-runner.ts"],"names":[],"mappings":"AAAA,OAAO,EAAyB,KAAK,0BAA0B,EAAE,MAAM,iBAAiB,CAAC;AAIzF,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAG1D,MAAM,MAAM,WAAW,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;AAyBjE,wBAAsB,kBAAkB,CACtC,SAAS,EAAE,0BAA0B,EACrC,SAAS,EAAE,WAAW;AACtB;;;;;;;GAOG;AACH,MAAM,CAAC,EAAE,WAAW;AACpB;;;;;;;GAOG;AACH,QAAQ,GAAE,eAA8B,GACvC,OAAO,CAAC,IAAI,CAAC,CA2Lf;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAsB,iBAAiB,CACrC,SAAS,EAAE,0BAA0B,EACrC,SAAS,EAAE,WAAW,EACtB,MAAM,CAAC,EAAE,WAAW,EACpB,QAAQ,GAAE,eAA8B,GACvC,OAAO,CAAC,IAAI,CAAC,CA8Ef"}
1
+ {"version":3,"file":"pair-runner.d.ts","sourceRoot":"","sources":["../../src/cli/pair-runner.ts"],"names":[],"mappings":"AAAA,OAAO,EAAyB,KAAK,0BAA0B,EAAE,MAAM,iBAAiB,CAAC;AAIzF,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAG1D,MAAM,MAAM,WAAW,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;AAyBjE,wBAAsB,kBAAkB,CACtC,SAAS,EAAE,0BAA0B,EACrC,SAAS,EAAE,WAAW;AACtB;;;;;;;GAOG;AACH,MAAM,CAAC,EAAE,WAAW;AACpB;;;;;;;GAOG;AACH,QAAQ,GAAE,eAA8B;AACxC;;;;;GAKG;AACH,UAAU,CAAC,EAAE,CAAC,QAAQ,EAAE,OAAO,2BAA2B,EAAE,WAAW,EAAE,MAAM,EAAE,OAAO,4BAA4B,EAAE,YAAY,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,GAC1J,OAAO,CAAC,IAAI,CAAC,CAuMf;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAsB,iBAAiB,CACrC,SAAS,EAAE,0BAA0B,EACrC,SAAS,EAAE,WAAW,EACtB,MAAM,CAAC,EAAE,WAAW,EACpB,QAAQ,GAAE,eAA8B;AACxC,mEAAmE;AACnE,UAAU,CAAC,EAAE,CAAC,QAAQ,EAAE,OAAO,2BAA2B,EAAE,WAAW,EAAE,MAAM,EAAE,OAAO,4BAA4B,EAAE,YAAY,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,GAC1J,OAAO,CAAC,IAAI,CAAC,CAwFf;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,mBAAmB,CACvC,SAAS,EAAE,0BAA0B,EACrC,SAAS,EAAE,WAAW,EACtB,MAAM,CAAC,EAAE,WAAW,EACpB,QAAQ,GAAE,eAA8B;AACxC,sEAAsE;AACtE,UAAU,CAAC,EAAE,CAAC,QAAQ,EAAE,OAAO,2BAA2B,EAAE,WAAW,EAAE,MAAM,EAAE,OAAO,4BAA4B,EAAE,YAAY,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,GAC1J,OAAO,CAAC,IAAI,CAAC,CAuFf"}
@@ -39,7 +39,14 @@ signal,
39
39
  * actually get their own hooks + labels run instead of silently
40
40
  * falling back to Mars while the page title shows the custom name.
41
41
  */
42
- scenario = marsScenario) {
42
+ scenario = marsScenario,
43
+ /**
44
+ * Optional callback fired after each leader's artifact completes.
45
+ * server-app uses this to insert a RunRecord per artifact into
46
+ * the SQLite run-history store. Failures inside the callback are
47
+ * caught and logged so a failing handler does not break the run.
48
+ */
49
+ onArtifact) {
43
50
  const { leaders, turns, seed, startTime, liveSearch, customEvents } = simConfig;
44
51
  broadcast('status', { phase: 'starting', maxTurns: turns, customEvents });
45
52
  const { runSimulation } = await import('../runtime/orchestrator.js');
@@ -74,7 +81,8 @@ scenario = marsScenario) {
74
81
  execution: simConfig.execution,
75
82
  scenario,
76
83
  signal,
77
- }).then(result => {
84
+ captureSnapshots: simConfig.captureSnapshots ?? false,
85
+ }).then(async (result) => {
78
86
  broadcast('result', {
79
87
  leader: tag,
80
88
  summary: {
@@ -84,7 +92,21 @@ scenario = marsScenario) {
84
92
  citations: result.citations?.length ?? 0,
85
93
  },
86
94
  fingerprint: result.fingerprint ?? null,
95
+ // Spec 2B bridge: emit the full artifact on result when
96
+ // snapshot capture was on so the dashboard can fork from it
97
+ // without reconstructing from the event stream. Skipped when
98
+ // captureSnapshots is off to keep the SSE payload lean on
99
+ // hosted-demo runs that don't need fork capability.
100
+ artifact: simConfig.captureSnapshots ? result : undefined,
87
101
  });
102
+ if (onArtifact) {
103
+ try {
104
+ await onArtifact(result, leader);
105
+ }
106
+ catch (err) {
107
+ console.warn('[pair-runner] onArtifact handler failed:', err);
108
+ }
109
+ }
88
110
  return { tag, leader, result };
89
111
  }, error => {
90
112
  broadcast('sim_error', { leader: tag, error: String(error) });
@@ -107,8 +129,8 @@ scenario = marsScenario) {
107
129
  if (settled.length === 2) {
108
130
  try {
109
131
  const [a, b] = settled;
110
- const colA = a.result.finalState?.systems;
111
- const colB = b.result.finalState?.systems;
132
+ const colA = a.result.finalState?.metrics;
133
+ const colB = b.result.finalState?.metrics;
112
134
  const verdictModel = resolveVerdictModel(simConfig.provider || 'openai', simConfig.economics);
113
135
  if (!verdictModel) {
114
136
  broadcast('complete', {
@@ -238,7 +260,9 @@ Then fill out:
238
260
  * snapshots, single-leader guard) happened in the `/setup` handler
239
261
  * before this function is reached.
240
262
  */
241
- export async function runForkSimulation(simConfig, broadcast, signal, scenario = marsScenario) {
263
+ export async function runForkSimulation(simConfig, broadcast, signal, scenario = marsScenario,
264
+ /** Optional callback fired after the forked artifact completes. */
265
+ onArtifact) {
242
266
  if (!simConfig.forkFrom) {
243
267
  throw new Error('runForkSimulation called without simConfig.forkFrom set');
244
268
  }
@@ -295,7 +319,20 @@ export async function runForkSimulation(simConfig, broadcast, signal, scenario =
295
319
  },
296
320
  fingerprint: result.fingerprint ?? null,
297
321
  forkedFrom: result.metadata.forkedFrom,
322
+ // Fork runs always have captureSnapshots forced on (see
323
+ // simulate call above); emit the full artifact so the dashboard
324
+ // can keep forking recursively without the event-stream
325
+ // reconstruction the spec originally assumed.
326
+ artifact: result,
298
327
  });
328
+ if (onArtifact) {
329
+ try {
330
+ await onArtifact(result, leader);
331
+ }
332
+ catch (err) {
333
+ console.warn('[fork-runner] onArtifact handler failed:', err);
334
+ }
335
+ }
299
336
  }
300
337
  catch (err) {
301
338
  broadcast('sim_error', { leader: leader.archetype, error: String(err) });
@@ -303,4 +340,103 @@ export async function runForkSimulation(simConfig, broadcast, signal, scenario =
303
340
  }
304
341
  broadcast('complete', { timestamp: new Date().toISOString(), fork: true });
305
342
  }
343
+ /**
344
+ * Generalized N-leader batch runner (Tier 5 Quickstart). Three or more
345
+ * leaders run against the same scenario + seed in parallel, each
346
+ * emitting per-leader SSE events identical to the pair path. No
347
+ * verdict generation: verdicts compare exactly two leaders and would
348
+ * be ambiguous across N >= 3. The dashboard's Quickstart tab surfaces
349
+ * group-median deltas instead.
350
+ *
351
+ * Per-leader tags are derived from archetype (lowercased, kebab-cased).
352
+ * Duplicate archetype strings get trailing indices for disambiguation.
353
+ */
354
+ export async function runBatchSimulations(simConfig, broadcast, signal, scenario = marsScenario,
355
+ /** Optional callback fired after each leader's artifact completes. */
356
+ onArtifact) {
357
+ const { leaders, turns, seed, startTime, liveSearch, customEvents } = simConfig;
358
+ broadcast('status', { phase: 'starting', maxTurns: turns, customEvents, batch: true, leaderCount: leaders.length });
359
+ const { runSimulation } = await import('../runtime/orchestrator.js');
360
+ const onEvent = (event) => broadcast('sim', event);
361
+ broadcast('status', {
362
+ phase: 'parallel',
363
+ batch: true,
364
+ leaders: leaders.map(leader => ({
365
+ name: leader.name,
366
+ archetype: leader.archetype,
367
+ unit: leader.unit,
368
+ hexaco: leader.hexaco,
369
+ })),
370
+ });
371
+ console.log(` Running batch: ${leaders.map(l => l.name).join(' vs ')} | ${turns} turns | seed ${seed}
372
+ `);
373
+ const usedTags = new Map();
374
+ const leadersWithTags = leaders.map((leader, index) => {
375
+ const base = leader.archetype.toLowerCase().replace(/^the\s+/, '').replace(/\s+/g, '-') || `leader-${index}`;
376
+ const count = usedTags.get(base) ?? 0;
377
+ usedTags.set(base, count + 1);
378
+ const tag = count === 0 ? base : `${base}-${count + 1}`;
379
+ return { leader, index, tag };
380
+ });
381
+ const settled = await Promise.allSettled(leadersWithTags.map(({ leader, index, tag }) => {
382
+ return runSimulation(leader, simConfig.keyPersonnel ?? DEFAULT_KEY_PERSONNEL, {
383
+ maxTurns: turns,
384
+ seed,
385
+ startTime,
386
+ timePerTurn: simConfig.timePerTurn,
387
+ liveSearch,
388
+ activeDepartments: simConfig.activeDepartments,
389
+ onEvent,
390
+ customEvents,
391
+ provider: simConfig.provider,
392
+ models: simConfig.models,
393
+ economics: simConfig.economics,
394
+ initialPopulation: simConfig.initialPopulation,
395
+ startingResources: simConfig.startingResources,
396
+ startingPolitics: simConfig.startingPolitics,
397
+ execution: simConfig.execution,
398
+ scenario,
399
+ signal,
400
+ captureSnapshots: simConfig.captureSnapshots ?? false,
401
+ }).then(async (result) => {
402
+ broadcast('result', {
403
+ leader: tag,
404
+ leaderIndex: index,
405
+ summary: {
406
+ population: result.finalState?.metrics?.population,
407
+ morale: result.finalState?.metrics?.morale,
408
+ toolsForged: result.forgedTools?.length ?? 0,
409
+ citations: result.citations?.length ?? 0,
410
+ },
411
+ fingerprint: result.fingerprint ?? null,
412
+ artifact: simConfig.captureSnapshots ? result : undefined,
413
+ });
414
+ if (onArtifact) {
415
+ try {
416
+ await onArtifact(result, leader);
417
+ }
418
+ catch (err) {
419
+ console.warn('[batch-runner] onArtifact handler failed:', err);
420
+ }
421
+ }
422
+ return result;
423
+ }, error => {
424
+ broadcast('sim_error', { leader: tag, leaderIndex: index, error: String(error) });
425
+ throw error;
426
+ });
427
+ }));
428
+ // Mirror runPairSimulations: surface aborted/provider-error at the
429
+ // terminal event so the dashboard can badge the session as
430
+ // interrupted. We consider the batch aborted when every leader
431
+ // failed or reported abortion; a single success still counts as
432
+ // a successful batch run.
433
+ const fulfilled = settled.filter(s => s.status === 'fulfilled')
434
+ .map(s => s.value);
435
+ const allAborted = fulfilled.length === 0 || fulfilled.every(v => v?.aborted === true || !!v?.providerError);
436
+ broadcast('complete', {
437
+ timestamp: new Date().toISOString(),
438
+ batch: true,
439
+ ...(allAborted ? { aborted: true } : {}),
440
+ });
441
+ }
306
442
  //# sourceMappingURL=pair-runner.js.map