@pome-sh/cli 0.44.0 → 0.45.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -142,6 +142,7 @@ Global hosted configuration:
142
142
  | `POME_API_KEY` | Authenticate hosted commands. This value takes precedence over stored credentials. |
143
143
  | `POME_API_URL` | Set the control-plane URL. `--api-url` takes precedence. |
144
144
  | `POME_DASHBOARD_URL` | Set the dashboard URL for login and result links. |
145
+ | `POME_TELEMETRY=0` | Turn off the anonymous daily usage event (one per day at most: CLI version, OS, Node major, command name; never arguments, paths or repo names). `DO_NOT_TRACK=1` is honoured too, and nothing is sent when `CI` is set. |
145
146
 
146
147
  Agent process configuration:
147
148
 
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "package": "pome-sh",
3
- "version": "0.44.0",
4
- "git_sha": "a80259dcddd5ec6f1a16dba3a6f252539996ebb7",
5
- "build_time": "2026-09-16T12:52:26.327Z"
3
+ "version": "0.45.1",
4
+ "git_sha": "f9ed48177ccfffac7020d1987e6ec9b810d7a4de",
5
+ "build_time": "2026-09-16T19:49:02.473Z"
6
6
  }
@@ -183,7 +183,7 @@ async function checkTwinReachable(_configDir) {
183
183
  });
184
184
  let harness;
185
185
  try {
186
- const { bootTwin } = await import('./twinHarness-YDGIGB4P.js');
186
+ const { bootTwin } = await import('./twinHarness-I2JGKQYD.js');
187
187
  harness = await bootTwin({
188
188
  twin: "github",
189
189
  seedState: void 0,
@@ -1,5 +1,5 @@
1
1
  import { mkdir, writeFile, rename, chmod, readFile, unlink, open, stat } from 'node:fs/promises';
2
- import { dirname, join } from 'node:path';
2
+ import { dirname, join, basename } from 'node:path';
3
3
 
4
4
  // src/twin/twinStatusFile.ts
5
5
  var STANDALONE_STATUS_PATH = ".pome/twin-status.json";
@@ -10,6 +10,15 @@ async function writeStandaloneStatusFile(status, path = STANDALONE_STATUS_PATH)
10
10
  await rename(tmp, path);
11
11
  await chmod(path, 384);
12
12
  }
13
+ async function ensureSelfIgnoring(dir) {
14
+ if (basename(dir) !== ".pome") return;
15
+ const path = join(dir, ".gitignore");
16
+ try {
17
+ await writeFile(path, "*\n", { flag: "wx", mode: 384 });
18
+ } catch (err) {
19
+ if (err.code !== "EEXIST") throw err;
20
+ }
21
+ }
13
22
  var STALE_LOCK_MS = 1e4;
14
23
  async function withStatusLock(path, fn) {
15
24
  const lockPath = `${path}.lock`;
@@ -46,6 +55,7 @@ async function withStatusLock(path, fn) {
46
55
  }
47
56
  async function updateStandaloneStatusFile(entries, path = STANDALONE_STATUS_PATH) {
48
57
  await mkdir(dirname(path), { recursive: true, mode: 448 });
58
+ await ensureSelfIgnoring(dirname(path));
49
59
  return await withStatusLock(path, async () => {
50
60
  const merged = mergeStandaloneStatus(await readStandaloneStatusFile(path), entries);
51
61
  await writeStandaloneStatusFile(merged, path);
@@ -39,7 +39,7 @@ var TWIN_REGISTRY = {
39
39
  defaultSeedState,
40
40
  GitHubDomain,
41
41
  openGitHubCloneDatabase
42
- } = await import('./src-252X4AEZ.js');
42
+ } = await import('./src-46YGR2WY.js');
43
43
  const db = openGitHubCloneDatabase();
44
44
  const domain = new GitHubDomain(db);
45
45
  domain.seed(seedState === void 0 ? defaultSeedState() : seedState);
@@ -90,7 +90,7 @@ var TWIN_REGISTRY = {
90
90
  parseSeed: async (input) => (await import('./seed-E6SA4NKZ.js')).parseSeed(input),
91
91
  seedFields: async () => Object.keys((await import('./seed-E6SA4NKZ.js')).seedSchema.shape),
92
92
  async boot({ seedState, runId, recorder, twinBaseUrl }) {
93
- const stripeTwin = await import('./src-P5MEPJY4.js');
93
+ const stripeTwin = await import('./src-STAXYPD3.js');
94
94
  const { createApp } = await import('./server-GECKG2H6.js');
95
95
  const {
96
96
  applySeed: applyStripeSeed,
@@ -181,7 +181,7 @@ var TWIN_REGISTRY = {
181
181
  }
182
182
  };
183
183
  async function createGitHubSmokeApp() {
184
- const { createGitHubCloneApp } = await import('./src-252X4AEZ.js');
184
+ const { createGitHubCloneApp } = await import('./src-46YGR2WY.js');
185
185
  return createGitHubCloneApp();
186
186
  }
187
187
  function defaultPortFor(twin, env = process.env) {
@@ -1,4 +1,4 @@
1
- import { isTwinName, TWIN_REGISTRY, TWIN_NAMES } from './chunk-RYAQ2ZYA.js';
1
+ import { isTwinName, TWIN_REGISTRY, TWIN_NAMES } from './chunk-BXYPNEJY.js';
2
2
  import { readFileSync } from 'node:fs';
3
3
  import { parse } from 'yaml';
4
4
 
@@ -1,4 +1,4 @@
1
- import { TWIN_NAMES, isTwinName, TWIN_REGISTRY } from './chunk-RYAQ2ZYA.js';
1
+ import { TWIN_NAMES, isTwinName, TWIN_REGISTRY } from './chunk-BXYPNEJY.js';
2
2
  import { createFileBackedRecorderStore, createRecorderStore } from './chunk-TWURH7YM.js';
3
3
 
4
4
  // src/recorder/recorder.ts
@@ -1,9 +1,9 @@
1
- import { readSeedFileText, parseSeedFileText, soleTwinOf, twinsNamedBy, seedsForTwins } from './chunk-ZVKPZHFQ.js';
2
- import { gmailSeedSchema, defaultSeedState } from './chunk-PASFBRK4.js';
3
- import { linearSeedSchema, defaultSeedState as defaultSeedState$1 } from './chunk-3FZY376K.js';
4
- import { isTwinName, TWIN_REGISTRY } from './chunk-RYAQ2ZYA.js';
5
1
  import { HostedDiscardRefusedError, HostedOrchError, HostedAuthError, readManifest, normalizeManifestTwins, HostedQuotaError, HostedTrialError } from './chunk-26UAPLHK.js';
6
2
  import { criterionSchema, normalizeTaskConfigKeys, finalizeResponseSchema, MOUNTED_TWINS, submitResultResponseSchema, createEvalSessionResponseSchema, createSessionResponseSchema, agentResponseSchema, isMultiTwinSeedEnvelope, sessionPublicSchema } from './chunk-M7ATJ423.js';
3
+ import { gmailSeedSchema, defaultSeedState } from './chunk-PASFBRK4.js';
4
+ import { linearSeedSchema, defaultSeedState as defaultSeedState$1 } from './chunk-3FZY376K.js';
5
+ import { readSeedFileText, parseSeedFileText, soleTwinOf, twinsNamedBy, seedsForTwins } from './chunk-DX2KCFJM.js';
6
+ import { isTwinName, TWIN_REGISTRY } from './chunk-BXYPNEJY.js';
7
7
  import { seedSchema as seedSchema$1, parseSeed, defaultSeedState as defaultSeedState$2 } from './chunk-NBOQN5VX.js';
8
8
  import { seedSchema } from './chunk-YBWG5JK2.js';
9
9
  import { toTwinHttpEventRow } from './chunk-TWURH7YM.js';
@@ -1,12 +1,12 @@
1
- import { runTaskHosted, createHostedClient, parseTaskFile, resolveRunAgentIdentity, outcomeOf, isNarrated, criterionPhrase, narratorReadingLines } from './chunk-G3YRDMBE.js';
2
- import './chunk-ZVKPZHFQ.js';
1
+ import { runTaskHosted, createHostedClient, parseTaskFile, resolveRunAgentIdentity, outcomeOf, isNarrated, criterionPhrase, narratorReadingLines } from './chunk-HEEFOMSZ.js';
3
2
  import './chunk-4LQ4IJOC.js';
3
+ import { HostedQuotaError, HostedTrialError } from './chunk-26UAPLHK.js';
4
+ import './chunk-M7ATJ423.js';
4
5
  import './chunk-NW7HGA2K.js';
5
6
  import './chunk-PASFBRK4.js';
6
7
  import './chunk-3FZY376K.js';
7
- import './chunk-RYAQ2ZYA.js';
8
- import { HostedQuotaError, HostedTrialError } from './chunk-26UAPLHK.js';
9
- import './chunk-M7ATJ423.js';
8
+ import './chunk-DX2KCFJM.js';
9
+ import './chunk-BXYPNEJY.js';
10
10
  import './chunk-NBOQN5VX.js';
11
11
  import './chunk-YBWG5JK2.js';
12
12
  import './chunk-TWURH7YM.js';
@@ -1,18 +1,18 @@
1
1
  #!/usr/bin/env node
2
- import { DEFAULT_CONTROL_PLANE_URL, DEFAULT_DASHBOARD_URL, clearLocalCredentials, friendlyHostedError, SESSION_TWIN_NAMES, runSessionCreate, runSessionList, runSessionStop, resolveCredentials, parseTaskFile, runTaskHosted, scoreStatus, runScoreLine, narratorReadingLines, readLatestRun, readMetaSummary, discoverRunSet, outcomeOf, persistCredentialsAfterLogin, DEFAULT_DOCS_SITE_ORIGIN, resolveSeams, readConfigTwins, resolveCachedAgentId, readLinkCache, seedStateForTwin, runAgentCommand, scoreCountsSummary, criterionRowLine, readCodeCriteria, postAgentResolver, writeLinkCache, ensurePomeGitignored, writeRunArtifactsCore, createHostedClient, redactJsonl, scoreFromFinalizeResponse, parseGitHubSeedState, uploadRunBlobs, isPreSatisfied } from '../../chunk-G3YRDMBE.js';
3
- import '../../chunk-ZVKPZHFQ.js';
2
+ import { getAvailablePort } from '../../chunk-XDU6TD4O.js';
3
+ import { DEFAULT_CONTROL_PLANE_URL, DEFAULT_DASHBOARD_URL, clearLocalCredentials, friendlyHostedError, SESSION_TWIN_NAMES, runSessionCreate, runSessionList, runSessionStop, resolveCredentials, parseTaskFile, runTaskHosted, scoreStatus, runScoreLine, narratorReadingLines, readLatestRun, readMetaSummary, discoverRunSet, outcomeOf, persistCredentialsAfterLogin, DEFAULT_DOCS_SITE_ORIGIN, resolveSeams, readConfigTwins, resolveCachedAgentId, readLinkCache, seedStateForTwin, runAgentCommand, scoreCountsSummary, criterionRowLine, readCodeCriteria, postAgentResolver, writeLinkCache, ensurePomeGitignored, writeRunArtifactsCore, createHostedClient, redactJsonl, scoreFromFinalizeResponse, parseGitHubSeedState, uploadRunBlobs, isPreSatisfied } from '../../chunk-HEEFOMSZ.js';
4
4
  import '../../chunk-4LQ4IJOC.js';
5
+ import { readManifest, writeManifest, MANIFEST_JSON, exitCodeFor, readRequiredManifest, HostedUsageError, HostedOrchError, normalizeManifestTwins } from '../../chunk-26UAPLHK.js';
6
+ import { MOUNTED_TWINS, deriveAgentSlug } from '../../chunk-M7ATJ423.js';
5
7
  import '../../chunk-NW7HGA2K.js';
6
8
  import { GMAIL_CHECKS } from '../../chunk-JM6VS62R.js';
7
9
  import '../../chunk-PASFBRK4.js';
8
10
  import { LINEAR_CHECKS } from '../../chunk-TSOSDKXP.js';
9
11
  import '../../chunk-3FZY376K.js';
10
- import { createRecorder, bootTwin } from '../../chunk-3T4FUF43.js';
11
- import { TWIN_NAME_LIST, TWIN_REGISTRY, createGitHubSmokeApp } from '../../chunk-RYAQ2ZYA.js';
12
- import { getAvailablePort } from '../../chunk-XDU6TD4O.js';
13
- import { readManifest, writeManifest, MANIFEST_JSON, exitCodeFor, readRequiredManifest, HostedUsageError, HostedOrchError, normalizeManifestTwins } from '../../chunk-26UAPLHK.js';
14
- import { MOUNTED_TWINS, deriveAgentSlug } from '../../chunk-M7ATJ423.js';
15
12
  import { buildEgressAllowlist, readBlockedEgress } from '../../chunk-CBFKZZBR.js';
13
+ import '../../chunk-DX2KCFJM.js';
14
+ import { createRecorder, bootTwin } from '../../chunk-EZYVICDB.js';
15
+ import { TWIN_NAME_LIST, TWIN_REGISTRY, createGitHubSmokeApp } from '../../chunk-BXYPNEJY.js';
16
16
  import { TAPE_ASSERTABLE_TOOLS } from '../../chunk-C4BVTUA3.js';
17
17
  import { seedSchema } from '../../chunk-NBOQN5VX.js';
18
18
  import { SLACK_CHECKS } from '../../chunk-2ZGVDTJC.js';
@@ -25,7 +25,7 @@ import '../../chunk-2K6BJ3PI.js';
25
25
  import '../../chunk-FBSA5L36.js';
26
26
  import { Command } from 'commander';
27
27
  import { existsSync, readFileSync, realpathSync, statSync, constants } from 'node:fs';
28
- import { mkdir, readFile, writeFile, readdir, copyFile, stat, cp } from 'node:fs/promises';
28
+ import { readFile, mkdir, writeFile, readdir, copyFile, stat, open, unlink, chmod, cp } from 'node:fs/promises';
29
29
  import { dirname, resolve, join, basename, relative, extname } from 'node:path';
30
30
  import { fileURLToPath } from 'node:url';
31
31
  import { serve } from '@hono/node-server';
@@ -37,6 +37,7 @@ import { createInterface } from 'node:readline';
37
37
  import { z } from 'zod';
38
38
  import Anthropic from '@anthropic-ai/sdk';
39
39
  import { createRequire } from 'node:module';
40
+ import { homedir } from 'node:os';
40
41
 
41
42
  async function readEventsJsonl(runDir) {
42
43
  const file = resolve(runDir, "events.jsonl");
@@ -1111,7 +1112,7 @@ function extractJsonPayload(text) {
1111
1112
 
1112
1113
  // src/task/seed-verifier.ts
1113
1114
  async function verifySeedWithTwin(seed) {
1114
- const { GitHubDomain, openGitHubCloneDatabase } = await import('../../src-252X4AEZ.js');
1115
+ const { GitHubDomain, openGitHubCloneDatabase } = await import('../../src-46YGR2WY.js');
1115
1116
  const db = openGitHubCloneDatabase(":memory:");
1116
1117
  try {
1117
1118
  new GitHubDomain(db).seed(seed);
@@ -3319,7 +3320,7 @@ function localDigest(twin) {
3319
3320
  }
3320
3321
  function bakedVersions() {
3321
3322
  try {
3322
- return JSON.parse('{"@pome-sh/sdk":"0.11.6","@pome-sh/wire":"0.4.2","@pome-sh/twin-github":"0.12.0","@pome-sh/twin-gmail":"0.4.0","@pome-sh/twin-linear":"0.4.1","@pome-sh/twin-slack":"0.4.1","@pome-sh/twin-stripe":"0.4.7"}');
3323
+ return JSON.parse('{"@pome-sh/sdk":"0.11.6","@pome-sh/wire":"0.4.3","@pome-sh/twin-github":"0.12.0","@pome-sh/twin-gmail":"0.4.0","@pome-sh/twin-linear":"0.4.1","@pome-sh/twin-slack":"0.4.1","@pome-sh/twin-stripe":"0.4.7"}');
3323
3324
  } catch {
3324
3325
  return {};
3325
3326
  }
@@ -4871,7 +4872,7 @@ function firstSentence(description) {
4871
4872
  function resolveExampleRef(env = process.env) {
4872
4873
  const override = env.POME_EXAMPLE_REF?.trim();
4873
4874
  if (override) return override;
4874
- const baked = "a80259dcddd5ec6f1a16dba3a6f252539996ebb7".trim() ;
4875
+ const baked = "f9ed48177ccfffac7020d1987e6ec9b810d7a4de".trim() ;
4875
4876
  return FULL_SHA.test(baked) ? baked : "main";
4876
4877
  }
4877
4878
  function rawUrlFor(example, file, ref) {
@@ -5226,6 +5227,143 @@ async function loadTrialEvents(runDir) {
5226
5227
  }
5227
5228
  return events;
5228
5229
  }
5230
+ var USAGE_EVENT = "cli_usage";
5231
+ var USAGE_DOCS_URL = "https://github.com/pome-sh/digital-twins#telemetry";
5232
+ var DEFAULT_HOST = "https://us.i.posthog.com";
5233
+ var REQUEST_TIMEOUT_MS = 1500;
5234
+ function bakedIn(name) {
5235
+ const value = name === "key" ? "phc_AzLfRtYcvZimDUSYfLjBjmCiT9AunyAY9RLkxeVHaBDZ" : "https://eu.i.posthog.com" ;
5236
+ return value !== void 0 && value.length > 0 ? value : void 0;
5237
+ }
5238
+ function telemetryDestination(env = process.env) {
5239
+ const key = env.POME_TELEMETRY_KEY || bakedIn("key");
5240
+ if (!key) return void 0;
5241
+ const host = (env.POME_TELEMETRY_HOST || bakedIn("host") || DEFAULT_HOST).replace(/\/+$/, "");
5242
+ return { key, host };
5243
+ }
5244
+ function telemetryOptOut(env = process.env) {
5245
+ const off = (value) => value !== void 0 && /^(0|false|off|no)$/i.test(value.trim());
5246
+ const set = (value) => value !== void 0 && value.trim() !== "" && value.trim() !== "0";
5247
+ if (off(env.POME_TELEMETRY)) return "POME_TELEMETRY";
5248
+ if (set(env.DO_NOT_TRACK)) return "DO_NOT_TRACK";
5249
+ if (set(env.CI)) return "CI";
5250
+ return void 0;
5251
+ }
5252
+ function usageStatePath() {
5253
+ return join(homedir(), ".pome", "telemetry.json");
5254
+ }
5255
+ function usageProperties(input) {
5256
+ const nodeVersion = input.nodeVersion ?? process.version;
5257
+ return {
5258
+ command: input.command,
5259
+ cli_version: input.version,
5260
+ os: input.platform ?? process.platform,
5261
+ node_major: Number(nodeVersion.replace(/^v/, "").split(".")[0]),
5262
+ // Anonymous events: no person profile is created or updated in PostHog.
5263
+ $process_person_profile: false
5264
+ };
5265
+ }
5266
+ function commandName(command) {
5267
+ const names = [];
5268
+ let current = command;
5269
+ while (current && current.parent) {
5270
+ names.unshift(current.name());
5271
+ current = current.parent;
5272
+ }
5273
+ return names.join(" ");
5274
+ }
5275
+ var FIRST_RUN_NOTICE = `pome sends one anonymous usage event per day (CLI version, OS, Node major, command name; no arguments, paths or repo names). Turn it off with POME_TELEMETRY=0. ${USAGE_DOCS_URL}`;
5276
+ async function readState(path) {
5277
+ try {
5278
+ const parsed = JSON.parse(await readFile(path, "utf8"));
5279
+ if (typeof parsed.id === "string" && parsed.id.length > 0) {
5280
+ return {
5281
+ id: parsed.id,
5282
+ ...typeof parsed.last_sent === "string" ? { last_sent: parsed.last_sent } : {},
5283
+ ...parsed.notice_shown === true ? { notice_shown: true } : {}
5284
+ };
5285
+ }
5286
+ } catch {
5287
+ }
5288
+ return { id: randomUUID() };
5289
+ }
5290
+ async function writeState(path, state) {
5291
+ await mkdir(dirname(path), { recursive: true, mode: 448 });
5292
+ await writeFile(path, `${JSON.stringify(state, null, 2)}
5293
+ `, { mode: 384 });
5294
+ await chmod(path, 384);
5295
+ }
5296
+ var STALE_LOCK_MS = 3e4;
5297
+ async function withStateLock(path, fn) {
5298
+ const lockPath = `${path}.lock`;
5299
+ await mkdir(dirname(path), { recursive: true, mode: 448 });
5300
+ try {
5301
+ const handle = await open(lockPath, "wx", 384);
5302
+ await handle.close();
5303
+ } catch (err) {
5304
+ if (err.code !== "EEXIST") throw err;
5305
+ const age = await stat(lockPath).then((s) => Date.now() - s.mtimeMs, () => 0);
5306
+ if (age <= STALE_LOCK_MS) return "locked";
5307
+ await unlink(lockPath).catch(() => void 0);
5308
+ try {
5309
+ const handle = await open(lockPath, "wx", 384);
5310
+ await handle.close();
5311
+ } catch {
5312
+ return "locked";
5313
+ }
5314
+ }
5315
+ try {
5316
+ return await fn();
5317
+ } finally {
5318
+ await unlink(lockPath).catch(() => void 0);
5319
+ }
5320
+ }
5321
+ async function maybeSendUsageTick(input) {
5322
+ const env = input.env ?? process.env;
5323
+ const optOut = telemetryOptOut(env);
5324
+ if (optOut) return { sent: false, reason: "opt-out", detail: optOut };
5325
+ const destination = telemetryDestination(env);
5326
+ if (!destination) return { sent: false, reason: "no-key" };
5327
+ const statePath2 = input.statePath ?? usageStatePath();
5328
+ const today = (input.now ?? /* @__PURE__ */ new Date()).toISOString().slice(0, 10);
5329
+ let state;
5330
+ try {
5331
+ const claimed = await withStateLock(statePath2, async () => {
5332
+ const current = await readState(statePath2);
5333
+ if (current.last_sent === today) return void 0;
5334
+ if (!current.notice_shown) {
5335
+ (input.notify ?? ((line) => console.error(line)))(FIRST_RUN_NOTICE);
5336
+ current.notice_shown = true;
5337
+ }
5338
+ current.last_sent = today;
5339
+ await writeState(statePath2, current);
5340
+ return current;
5341
+ });
5342
+ if (claimed === "locked" || claimed === void 0) return { sent: false, reason: "already-today" };
5343
+ state = claimed;
5344
+ } catch (err) {
5345
+ return { sent: false, reason: "request-failed", detail: `state: ${err.message}` };
5346
+ }
5347
+ const body = {
5348
+ api_key: destination.key,
5349
+ event: USAGE_EVENT,
5350
+ distinct_id: state.id,
5351
+ properties: usageProperties({ command: input.command, version: input.version }),
5352
+ timestamp: (input.now ?? /* @__PURE__ */ new Date()).toISOString()
5353
+ };
5354
+ try {
5355
+ const res = await (input.fetchImpl ?? fetch)(`${destination.host}/capture/`, {
5356
+ method: "POST",
5357
+ headers: { "content-type": "application/json" },
5358
+ body: JSON.stringify(body),
5359
+ signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS)
5360
+ });
5361
+ if (!res.ok) return { sent: false, reason: "request-failed", detail: `HTTP ${res.status}` };
5362
+ return { sent: true };
5363
+ } catch (err) {
5364
+ return { sent: false, reason: "request-failed", detail: err.message };
5365
+ }
5366
+ }
5229
5367
 
5230
5368
  // src/cli/main.ts
5231
5369
  var PACKAGE_VERSION = readPackageVersion();
@@ -5234,7 +5372,7 @@ var DEFAULT_AGENT_COMMAND = `node ${DEFAULT_AGENT_FILE}`;
5234
5372
  var MANIFEST_SCHEMA_URL = "https://pome.sh/schemas/v1/pome.json";
5235
5373
  var MAX_UNREADABLE_PATHS_SHOWN = 5;
5236
5374
  function readPackageVersion() {
5237
- if ("0.44.0".length > 0) return "0.44.0";
5375
+ if ("0.45.1".length > 0) return "0.45.1";
5238
5376
  try {
5239
5377
  const here = dirname(fileURLToPath(import.meta.url));
5240
5378
  const candidates = [
@@ -5263,8 +5401,91 @@ function createProgram() {
5263
5401
  process.env.POME_API_URL ?? DEFAULT_CONTROL_PLANE_URL
5264
5402
  ).option("--artifacts-dir <dir>", "Directory for run artifacts", "runs");
5265
5403
  program.name("pome").description(
5266
- "Test AI agents against digital twins of real SaaS APIs. Runs are recorded to app.pome.sh. Start with `pome init`."
5267
- ).version(PACKAGE_VERSION).showHelpAfterError("(add --help for usage)");
5404
+ "Stateful local twins of GitHub, Slack, Stripe, Gmail and Linear that your agent calls as if they were the real API. Start with `pome twin start <twin>`."
5405
+ ).version(PACKAGE_VERSION).showHelpAfterError("(add --help for usage)").hook("preAction", (_root, actionCommand) => {
5406
+ void maybeSendUsageTick({ command: commandName(actionCommand), version: PACKAGE_VERSION });
5407
+ });
5408
+ const twin = program.command("twin").summary("Run a twin on this machine").description(
5409
+ "Start a twin on this machine, print its status, show its tape, or write a starter seed file"
5410
+ );
5411
+ twin.command("start").argument(
5412
+ "[names...]",
5413
+ `Twin names (${TWIN_NAME_LIST.join(" | ")}). One, or several to boot together (each on its own port). Optional when --seed names exactly one twin.`
5414
+ ).option(
5415
+ "--port <port>",
5416
+ // Built from the registry rather than restated: the per-twin overrides
5417
+ // are the registry's to add, and this text went stale when linear's did.
5418
+ `Port to bind (default: $PORT, else ${TWIN_NAME_LIST.filter(
5419
+ (twin2) => TWIN_REGISTRY[twin2].portEnvName
5420
+ ).map((twin2) => `${TWIN_REGISTRY[twin2].portEnvName}/${TWIN_REGISTRY[twin2].defaultPort} for ${twin2}`).join(", ")}, otherwise 3333). With several twins: the first twin's port; the rest take the next free ports above it. Without it, each twin takes its default port, else the next free one.`
5421
+ ).option(
5422
+ "--seed <path>",
5423
+ "Boot from a JSON or YAML seed file instead of the default. A seed REPLACES the default; it does not merge. Takes the per-twin envelope { <twin>: { \u2026 } } or one twin's flat seed (several twins need the envelope, one entry per named twin). Overrides POME_SEED_JSON."
5424
+ ).description(
5425
+ "Start one or more standalone twins as a long-lived foreground server (Ctrl-C to stop)"
5426
+ ).action(async (names, options) => {
5427
+ const { runTwinStartCommand } = await import('../../twinStart-XN3BYOUF.js');
5428
+ await runTwinStartCommand(names, options);
5429
+ });
5430
+ twin.command("new-seed").argument("<name...>", `Twin name (${TWIN_NAME_LIST.join(" | ")}). Repeat for one file covering several.`).option("--out <path>", "Write to this file instead of stdout. Refuses to overwrite.").summary("Print a new starter seed file for a twin").description(
5431
+ "Print a new starter seed file for a twin, generated from the twin's own starting state. One twin is flat, several are the per-twin envelope. Boot it with `twin start <twin> --seed`, seed a sandbox with `sandbox create --twin <twin> --seed`, or drop it beside a task as <task>.seed.json"
5432
+ ).action(async (names, options) => {
5433
+ const { runTwinSeedCommand } = await import('../../twinSeed-ZFZO7BL7.js');
5434
+ await runTwinSeedCommand(names, options);
5435
+ });
5436
+ twin.command("status").summary("Say whether the local twins are running").description(
5437
+ "Say whether each twin `pome twin start` booted here is still running, and print its paste-able env lines"
5438
+ ).action(async () => {
5439
+ const statusPath = ".pome/twin-status.json";
5440
+ if (!existsSync(statusPath)) {
5441
+ console.log("No standalone twin status found.");
5442
+ return;
5443
+ }
5444
+ const { standaloneStatusEntries } = await import('../../twinStart-XN3BYOUF.js');
5445
+ let entries;
5446
+ try {
5447
+ entries = standaloneStatusEntries(JSON.parse(await readFile(statusPath, "utf8"))).map(
5448
+ (status) => ({ ...status, origin: new URL(status.rest_url).origin })
5449
+ );
5450
+ if (entries.length === 0 || entries.some((status) => status.name === "")) {
5451
+ throw new Error("no twins");
5452
+ }
5453
+ } catch {
5454
+ throw new Error(
5455
+ `pome twin status: ${statusPath} is unreadable \u2014 start a twin with \`pome twin start <${TWIN_NAME_LIST.join("|")}>\`.`
5456
+ );
5457
+ }
5458
+ for (const [index, status] of entries.entries()) {
5459
+ const running = await fetch(`${status.origin}/healthz`, {
5460
+ signal: AbortSignal.timeout(1e3)
5461
+ }).then(
5462
+ async (res) => res.ok && (await res.json().catch(() => ({}))).twin === status.name,
5463
+ () => false
5464
+ );
5465
+ if (index > 0) console.log("");
5466
+ console.log(
5467
+ running ? `${status.name} twin \u2014 running` : `${status.name} twin \u2014 not running (stale ${statusPath})`
5468
+ );
5469
+ const envName = TWIN_REGISTRY[status.name]?.envName ?? status.name.toUpperCase();
5470
+ console.log(`POME_${envName}_REST_URL=${status.rest_url}`);
5471
+ console.log(`POME_${envName}_MCP_URL=${status.mcp_url}`);
5472
+ console.log(`POME_AUTH_TOKEN=${status.auth_token}`);
5473
+ }
5474
+ });
5475
+ twin.command("tape").argument(
5476
+ "[name]",
5477
+ `Twin name (${TWIN_NAME_LIST.join(" | ")}). Optional when one twin is recorded in .pome/twin-status.json.`
5478
+ ).option(
5479
+ "--diff",
5480
+ "Also print the state diff since the twin booted \u2014 its seed, default or --seed \u2014 per collection: added, changed, removed.",
5481
+ false
5482
+ ).option("--json", "Print the tape (and the diff, with --diff) as one JSON envelope.", false).summary("Show what the agent did on a local twin").description(
5483
+ "Print the running twin's tape: one line per request with status, fidelity and whether state changed, so a call that claimed success but landed nothing stands out. Reads the twin's address and token from .pome/twin-status.json; no account, no hosted call."
5484
+ ).action(async (name, options) => {
5485
+ const { runTwinTapeCommand } = await import('../../twinTape-5P3HQ27N.js');
5486
+ await runTwinTapeCommand(name, options);
5487
+ });
5488
+ program.commandsGroup("Going further:");
5268
5489
  program.command("init").summary("Set up Pome in this project").description(
5269
5490
  "Create pome.json, plus starter files in a new project \u2014 or, with --example <id>, fetch a complete runnable example into ./<id>"
5270
5491
  ).option(
@@ -5638,7 +5859,7 @@ function createProgram() {
5638
5859
  return;
5639
5860
  }
5640
5861
  {
5641
- const { runDoctorChecks } = await import('../../checks-BOOQNOGJ.js');
5862
+ const { runDoctorChecks } = await import('../../checks-RDU56OGI.js');
5642
5863
  const { renderDoctorReport } = await import('../../render-ZQQ4UMNO.js');
5643
5864
  const doctorReport = await runDoctorChecks({ mode: useLocal ? "full" : "hosted" });
5644
5865
  if (!doctorReport.ok) {
@@ -5676,7 +5897,7 @@ function createProgram() {
5676
5897
  taskForRuns.config.runs
5677
5898
  );
5678
5899
  if (k > 1) {
5679
- const { runTrialGroup } = await import('../../runTrialGroup-I3PC2AST.js');
5900
+ const { runTrialGroup } = await import('../../runTrialGroup-MMTTTDWY.js');
5680
5901
  const fileForRerun = relative(process.cwd(), file);
5681
5902
  const rerunCommand = defaultTask ? options.trials !== void 0 ? `pome run -n ${k}` : "pome run" : `pome run ${fileForRerun && !fileForRerun.startsWith("..") ? fileForRerun : file} -n ${k}`;
5682
5903
  const groupResult = await runTrialGroup({
@@ -5758,7 +5979,7 @@ function createProgram() {
5758
5979
  program.command("doctor").summary("Check the agent and twin wiring").description(
5759
5980
  "Check the agent\u2194twin wiring: pome.json (or pome.yaml) present + valid, the local twin boots + serves, requests routed to the twin (not a hardcoded production host), egress floor active. On failure prints one named cause (file:line where knowable) + one concrete fix and exits non-zero."
5760
5981
  ).action(async () => {
5761
- const { runDoctorChecks } = await import('../../checks-BOOQNOGJ.js');
5982
+ const { runDoctorChecks } = await import('../../checks-RDU56OGI.js');
5762
5983
  const { renderDoctorReport } = await import('../../render-ZQQ4UMNO.js');
5763
5984
  const report = await runDoctorChecks();
5764
5985
  for (const line of renderDoctorReport(report, { passNote: true })) console.error(line);
@@ -5909,86 +6130,6 @@ function createProgram() {
5909
6130
  })
5910
6131
  );
5911
6132
  });
5912
- const twin = program.command("twin").summary("Run a twin on this machine").description(
5913
- "Start a twin on this machine, print its status, show its tape, or write a starter seed file"
5914
- );
5915
- twin.command("start").argument(
5916
- "[names...]",
5917
- `Twin names (${TWIN_NAME_LIST.join(" | ")}). One, or several to boot together (each on its own port). Optional when --seed names exactly one twin.`
5918
- ).option(
5919
- "--port <port>",
5920
- // Built from the registry rather than restated: the per-twin overrides
5921
- // are the registry's to add, and this text went stale when linear's did.
5922
- `Port to bind (default: $PORT, else ${TWIN_NAME_LIST.filter(
5923
- (twin2) => TWIN_REGISTRY[twin2].portEnvName
5924
- ).map((twin2) => `${TWIN_REGISTRY[twin2].portEnvName}/${TWIN_REGISTRY[twin2].defaultPort} for ${twin2}`).join(", ")}, otherwise 3333). With several twins: the first twin's port; the rest take the next free ports above it. Without it, each twin takes its default port, else the next free one.`
5925
- ).option(
5926
- "--seed <path>",
5927
- "Boot from a JSON or YAML seed file instead of the default. A seed REPLACES the default; it does not merge. Takes the per-twin envelope { <twin>: { \u2026 } } or one twin's flat seed (several twins need the envelope, one entry per named twin). Overrides POME_SEED_JSON."
5928
- ).description(
5929
- "Start one or more standalone twins as a long-lived foreground server (Ctrl-C to stop)"
5930
- ).action(async (names, options) => {
5931
- const { runTwinStartCommand } = await import('../../twinStart-E5R26SF4.js');
5932
- await runTwinStartCommand(names, options);
5933
- });
5934
- twin.command("new-seed").argument("<name...>", `Twin name (${TWIN_NAME_LIST.join(" | ")}). Repeat for one file covering several.`).option("--out <path>", "Write to this file instead of stdout. Refuses to overwrite.").summary("Print a new starter seed file for a twin").description(
5935
- "Print a new starter seed file for a twin, generated from the twin's own starting state. One twin is flat, several are the per-twin envelope. Boot it with `twin start <twin> --seed`, seed a sandbox with `sandbox create --twin <twin> --seed`, or drop it beside a task as <task>.seed.json"
5936
- ).action(async (names, options) => {
5937
- const { runTwinSeedCommand } = await import('../../twinSeed-ADWQ62CA.js');
5938
- await runTwinSeedCommand(names, options);
5939
- });
5940
- twin.command("status").summary("Say whether the local twins are running").description(
5941
- "Say whether each twin `pome twin start` booted here is still running, and print its paste-able env lines"
5942
- ).action(async () => {
5943
- const statusPath = ".pome/twin-status.json";
5944
- if (!existsSync(statusPath)) {
5945
- console.log("No standalone twin status found.");
5946
- return;
5947
- }
5948
- const { standaloneStatusEntries } = await import('../../twinStart-E5R26SF4.js');
5949
- let entries;
5950
- try {
5951
- entries = standaloneStatusEntries(JSON.parse(await readFile(statusPath, "utf8"))).map(
5952
- (status) => ({ ...status, origin: new URL(status.rest_url).origin })
5953
- );
5954
- if (entries.length === 0 || entries.some((status) => status.name === "")) {
5955
- throw new Error("no twins");
5956
- }
5957
- } catch {
5958
- throw new Error(
5959
- `pome twin status: ${statusPath} is unreadable \u2014 start a twin with \`pome twin start <${TWIN_NAME_LIST.join("|")}>\`.`
5960
- );
5961
- }
5962
- for (const [index, status] of entries.entries()) {
5963
- const running = await fetch(`${status.origin}/healthz`, {
5964
- signal: AbortSignal.timeout(1e3)
5965
- }).then(
5966
- async (res) => res.ok && (await res.json().catch(() => ({}))).twin === status.name,
5967
- () => false
5968
- );
5969
- if (index > 0) console.log("");
5970
- console.log(
5971
- running ? `${status.name} twin \u2014 running` : `${status.name} twin \u2014 not running (stale ${statusPath})`
5972
- );
5973
- const envName = TWIN_REGISTRY[status.name]?.envName ?? status.name.toUpperCase();
5974
- console.log(`POME_${envName}_REST_URL=${status.rest_url}`);
5975
- console.log(`POME_${envName}_MCP_URL=${status.mcp_url}`);
5976
- console.log(`POME_AUTH_TOKEN=${status.auth_token}`);
5977
- }
5978
- });
5979
- twin.command("tape").argument(
5980
- "[name]",
5981
- `Twin name (${TWIN_NAME_LIST.join(" | ")}). Optional when one twin is recorded in .pome/twin-status.json.`
5982
- ).option(
5983
- "--diff",
5984
- "Also print the state diff since the twin booted \u2014 its seed, default or --seed \u2014 per collection: added, changed, removed.",
5985
- false
5986
- ).option("--json", "Print the tape (and the diff, with --diff) as one JSON envelope.", false).summary("Show what the agent did on a local twin").description(
5987
- "Print the running twin's tape: one line per request with status, fidelity and whether state changed, so a call that claimed success but landed nothing stands out. Reads the twin's address and token from .pome/twin-status.json; no account, no hosted call."
5988
- ).action(async (name, options) => {
5989
- const { runTwinTapeCommand } = await import('../../twinTape-3XNU3GRW.js');
5990
- await runTwinTapeCommand(name, options);
5991
- });
5992
6133
  program.command("capture-server").summary("Record the agent's model calls").description(
5993
6134
  "Boot an HTTP CONNECT-tunnel proxy that appends one LlmCallEvent per tunnel to events.jsonl. Spawned by `pome run`; agent traffic flows via HTTPS_PROXY."
5994
6135
  ).option("--port <port>", "TCP port to listen on (0 = ephemeral).", "8910").option(
@@ -6033,8 +6174,8 @@ async function taskFiles(target) {
6033
6174
  if (!existsSync(resolved)) {
6034
6175
  throw new HostedUsageError(`Task path not found: ${target}`);
6035
6176
  }
6036
- const stat3 = await import('node:fs/promises').then((fs) => fs.stat(resolved));
6037
- if (stat3.isFile()) return [resolved];
6177
+ const stat4 = await import('node:fs/promises').then((fs) => fs.stat(resolved));
6178
+ if (stat4.isFile()) return [resolved];
6038
6179
  const entries = await readdir(resolved);
6039
6180
  return entries.filter((entry) => entry.endsWith(".md")).sort().map((entry) => join(resolved, entry));
6040
6181
  }
@@ -3081,12 +3081,6 @@ function checkRunJson(run, repo) {
3081
3081
  html_url: `https://github.com/${repo.full_name}/runs/${run.id}`,
3082
3082
  details_url: run.details_url,
3083
3083
  status: run.status,
3084
- // The twin's `conclusion` column carries the full GitHub check-run
3085
- // conclusion vocabulary including `"stale"`, but the pinned
3086
- // @octokit/openapi-types version's `check-run.conclusion` enum predates
3087
- // `"stale"`. The twin faithfully emits a real upstream value; narrow it to
3088
- // the schema's declared union for the type anchor only (twin
3089
- // tracks live GitHub, not a lagging spec snapshot), runtime value unchanged.
3090
3084
  conclusion: run.conclusion,
3091
3085
  started_at: run.started_at,
3092
3086
  completed_at: run.completed_at,
@@ -4205,13 +4205,29 @@ function stripeToolInputSchema(schema) {
4205
4205
  const candidate = z.toJSONSchema;
4206
4206
  if (typeof candidate === "function") {
4207
4207
  try {
4208
- return candidate(schema);
4208
+ return rewriteNullableTypeArray(candidate(schema));
4209
4209
  } catch {
4210
4210
  return {};
4211
4211
  }
4212
4212
  }
4213
4213
  return {};
4214
4214
  }
4215
+ function rewriteNullableTypeArray(value) {
4216
+ if (Array.isArray(value))
4217
+ return value.map(rewriteNullableTypeArray);
4218
+ if (!value || typeof value !== "object")
4219
+ return value;
4220
+ const rec = value;
4221
+ const next = {};
4222
+ for (const [key, child] of Object.entries(rec)) {
4223
+ if (key === "type" && Array.isArray(child) && child.length === 2 && child.includes("string") && child.includes("null")) {
4224
+ next.anyOf = [{ type: "string" }, { type: "null" }];
4225
+ continue;
4226
+ }
4227
+ next[key] = rewriteNullableTypeArray(child);
4228
+ }
4229
+ return next;
4230
+ }
4215
4231
 
4216
4232
  // ../packages/twin-stripe/dist/src/twin.js
4217
4233
  var NO_API_KEY_MESSAGE = "You did not provide an API key. You need to provide your API key in the Authorization header, using Bearer auth (e.g. 'Authorization: Bearer YOUR_SECRET_KEY'). See https://stripe.com/docs/api#authentication for details, or we can help at https://support.stripe.com/.";
@@ -0,0 +1,6 @@
1
+ export { UnsupportedTwinError, bootTwin } from './chunk-EZYVICDB.js';
2
+ export { STRIPE_LOCAL_ACCOUNT_ID } from './chunk-BXYPNEJY.js';
3
+ import './chunk-TWURH7YM.js';
4
+ import './chunk-7VZBAHQ2.js';
5
+ import './chunk-SG6ZTIMT.js';
6
+ import './chunk-FBSA5L36.js';
@@ -1,4 +1,4 @@
1
- import { TWIN_NAMES, isTwinName, TWIN_REGISTRY } from './chunk-RYAQ2ZYA.js';
1
+ import { TWIN_NAMES, isTwinName, TWIN_REGISTRY } from './chunk-BXYPNEJY.js';
2
2
  import { writeFile } from 'node:fs/promises';
3
3
 
4
4
  async function generateSeedFile(twins) {
@@ -1,8 +1,8 @@
1
- import { snapshotStandaloneInitialState, updateStandaloneStatusFile } from './chunk-7ULGZG7X.js';
2
- export { STANDALONE_STATUS_PATH, mergeStandaloneStatus, readStandaloneStatusFile, standaloneStatusEntries, updateStandaloneStatusFile, writeStandaloneStatusFile } from './chunk-7ULGZG7X.js';
3
- import { readSeedFileText, seedForTwin, parseSeedFileText, soleTwinOf, twinsNamedBy } from './chunk-ZVKPZHFQ.js';
4
- import { bootTwin } from './chunk-3T4FUF43.js';
5
- import { defaultPortFor, TWIN_REGISTRY, isTwinName, TWIN_NAMES } from './chunk-RYAQ2ZYA.js';
1
+ import { snapshotStandaloneInitialState, updateStandaloneStatusFile } from './chunk-AGZOWSLG.js';
2
+ export { STANDALONE_STATUS_PATH, mergeStandaloneStatus, readStandaloneStatusFile, standaloneStatusEntries, updateStandaloneStatusFile, writeStandaloneStatusFile } from './chunk-AGZOWSLG.js';
3
+ import { readSeedFileText, seedForTwin, parseSeedFileText, soleTwinOf, twinsNamedBy } from './chunk-DX2KCFJM.js';
4
+ import { bootTwin } from './chunk-EZYVICDB.js';
5
+ import { defaultPortFor, TWIN_REGISTRY, isTwinName, TWIN_NAMES } from './chunk-BXYPNEJY.js';
6
6
  import './chunk-TWURH7YM.js';
7
7
  import './chunk-7VZBAHQ2.js';
8
8
  import './chunk-SG6ZTIMT.js';
@@ -1,7 +1,7 @@
1
- import { STANDALONE_STATUS_PATH, standaloneStatusEntries, readStandaloneStatusFile, readStandaloneInitialState, standaloneInitialStatePath } from './chunk-7ULGZG7X.js';
1
+ import { STANDALONE_STATUS_PATH, standaloneStatusEntries, readStandaloneStatusFile, readStandaloneInitialState, standaloneInitialStatePath } from './chunk-AGZOWSLG.js';
2
2
  import './chunk-4LQ4IJOC.js';
3
- import { TWIN_NAMES } from './chunk-RYAQ2ZYA.js';
4
3
  import './chunk-M7ATJ423.js';
4
+ import { TWIN_NAMES } from './chunk-BXYPNEJY.js';
5
5
  import './chunk-NBOQN5VX.js';
6
6
  import './chunk-YBWG5JK2.js';
7
7
  import { recorderEventSchema } from './chunk-7VZBAHQ2.js';
package/package.json CHANGED
@@ -1,18 +1,24 @@
1
1
  {
2
2
  "name": "@pome-sh/cli",
3
- "version": "0.44.0",
4
- "description": "Test AI agents against digital twins of real SaaS APIs. Records tool-call traces and scores them on pome.sh.",
3
+ "version": "0.45.1",
4
+ "description": "Test mode for your integrations, built for the way agents build. Local, stateful twins of GitHub, Slack, Stripe, Gmail and Linear, over REST and MCP.",
5
5
  "keywords": [
6
- "ai",
7
- "agents",
8
- "agent-testing",
6
+ "mcp",
7
+ "mcp-server",
8
+ "model-context-protocol",
9
+ "claude-code",
10
+ "codex",
11
+ "testing",
12
+ "test-mode",
13
+ "sandbox",
14
+ "api-mocking",
9
15
  "digital-twin",
10
- "llm",
11
- "evals",
12
- "claude",
13
- "anthropic",
16
+ "ai-agents",
14
17
  "github",
18
+ "slack",
15
19
  "stripe",
20
+ "gmail",
21
+ "linear",
16
22
  "cli"
17
23
  ],
18
24
  "homepage": "https://pome.sh",
@@ -54,19 +60,19 @@
54
60
  "check:manifest-schema": "node scripts/emit-manifest-schema.mjs --check"
55
61
  },
56
62
  "dependencies": {
57
- "@ai-sdk/anthropic": "^4.0.29",
58
- "@ai-sdk/gateway": "^4.0.40",
59
- "@ai-sdk/google": "^4.0.33",
60
- "@ai-sdk/openai": "^4.0.29",
61
- "@anthropic-ai/sdk": "^0.115.0",
62
- "@hono/node-server": "^2.1.0",
63
+ "@ai-sdk/anthropic": "^4.0.54",
64
+ "@ai-sdk/gateway": "^4.0.82",
65
+ "@ai-sdk/google": "^4.0.72",
66
+ "@ai-sdk/openai": "^4.0.67",
67
+ "@anthropic-ai/sdk": "^0.126.0",
68
+ "@hono/node-server": "^2.1.1",
63
69
  "@openrouter/ai-sdk-provider": "^3.0.0",
64
- "ai": "^7.0.51",
70
+ "ai": "^7.0.102",
65
71
  "commander": "^15.0.0",
66
- "graphql": "^16.11.0",
67
- "hono": "^4.13.0",
68
- "yaml": "^2.9.0",
69
- "zod": "^4.4.3"
72
+ "graphql": "^16.14.2",
73
+ "hono": "^4.13.8",
74
+ "yaml": "^2.9.1",
75
+ "zod": "^4.6.5"
70
76
  },
71
77
  "devDependencies": {
72
78
  "@pome-sh/sdk": "*",
@@ -76,11 +82,11 @@
76
82
  "@pome-sh/twin-linear": "*",
77
83
  "@pome-sh/twin-slack": "*",
78
84
  "@pome-sh/twin-stripe": "*",
79
- "@types/node": "^26.1.2",
80
- "tsx": "^4.23.5",
85
+ "@types/node": "^26.6.1",
86
+ "tsx": "^4.23.13",
81
87
  "typescript": "^5.9.3",
82
- "vitest": "^4.1.10",
83
- "tsup": "^8.5.0"
88
+ "vitest": "^5.0.1",
89
+ "tsup": "^8.5.1"
84
90
  },
85
91
  "engines": {
86
92
  "node": ">=24"
@@ -1,6 +0,0 @@
1
- export { UnsupportedTwinError, bootTwin } from './chunk-3T4FUF43.js';
2
- export { STRIPE_LOCAL_ACCOUNT_ID } from './chunk-RYAQ2ZYA.js';
3
- import './chunk-TWURH7YM.js';
4
- import './chunk-7VZBAHQ2.js';
5
- import './chunk-SG6ZTIMT.js';
6
- import './chunk-FBSA5L36.js';