@pome-sh/cli 0.38.0 → 0.39.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.
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "package": "pome-sh",
3
- "version": "0.38.0",
4
- "git_sha": "cf682a4d73f8a19d38a0d6a934fdef5eae82bb50",
5
- "build_time": "2026-08-30T04:48:25.959Z"
3
+ "version": "0.39.1",
4
+ "git_sha": "ad57e84671dd2e6a2fb0dc3b66a78d97b95ed1c7",
5
+ "build_time": "2026-08-30T05:08:05.900Z"
6
6
  }
@@ -9,7 +9,7 @@ import '../../chunk-PASFBRK4.js';
9
9
  import { LINEAR_CHECKS } from '../../chunk-TSOSDKXP.js';
10
10
  import '../../chunk-3FZY376K.js';
11
11
  import '../../chunk-5NPGY73F.js';
12
- import { TWIN_NAME_LIST, isTwinName, createGitHubSmokeApp } from '../../chunk-RPPF2KDQ.js';
12
+ import { TWIN_NAME_LIST, TWIN_REGISTRY, createGitHubSmokeApp } from '../../chunk-RPPF2KDQ.js';
13
13
  import { readManifest, writeManifest, MANIFEST_JSON, readRequiredManifest, normalizeManifestTwins } from '../../chunk-DFOQGAKS.js';
14
14
  import '../../chunk-XDU6TD4O.js';
15
15
  import { MOUNTED_TWINS, deriveAgentSlug, exitCodeFor, HostedUsageError, HostedOrchError } from '../../chunk-NNXVR46L.js';
@@ -26,7 +26,7 @@ import '../../chunk-2K6BJ3PI.js';
26
26
  import '../../chunk-FBSA5L36.js';
27
27
  import { Command } from 'commander';
28
28
  import { existsSync, readFileSync, realpathSync, statSync, constants } from 'node:fs';
29
- import { mkdir, readFile, rm, writeFile, readdir, copyFile, stat, cp } from 'node:fs/promises';
29
+ import { mkdir, readFile, writeFile, readdir, copyFile, stat, cp } from 'node:fs/promises';
30
30
  import { dirname, resolve, join, basename, relative, extname } from 'node:path';
31
31
  import { fileURLToPath } from 'node:url';
32
32
  import { execFile } from 'node:child_process';
@@ -4575,7 +4575,7 @@ function firstSentence(description) {
4575
4575
  function resolveExampleRef(env = process.env) {
4576
4576
  const override = env.POME_EXAMPLE_REF?.trim();
4577
4577
  if (override) return override;
4578
- const baked = "cf682a4d73f8a19d38a0d6a934fdef5eae82bb50".trim() ;
4578
+ const baked = "ad57e84671dd2e6a2fb0dc3b66a78d97b95ed1c7".trim() ;
4579
4579
  return FULL_SHA.test(baked) ? baked : "main";
4580
4580
  }
4581
4581
  function rawUrlFor(example, file, ref) {
@@ -4929,7 +4929,7 @@ var DEFAULT_AGENT_COMMAND = `node ${DEFAULT_AGENT_FILE}`;
4929
4929
  var MANIFEST_SCHEMA_URL = "https://pome.sh/schemas/v1/pome.json";
4930
4930
  var MAX_UNREADABLE_PATHS_SHOWN = 5;
4931
4931
  function readPackageVersion() {
4932
- if ("0.38.0".length > 0) return "0.38.0";
4932
+ if ("0.39.1".length > 0) return "0.39.1";
4933
4933
  try {
4934
4934
  const here = dirname(fileURLToPath(import.meta.url));
4935
4935
  const candidates = [
@@ -5703,20 +5703,24 @@ function createProgram() {
5703
5703
  })
5704
5704
  );
5705
5705
  });
5706
- const twin = program.command("twin").summary("Run a twin on this machine").description("Start and reset a twin on this machine, print its status or a starter seed file");
5706
+ const twin = program.command("twin").summary("Run a twin on this machine").description("Start a twin on this machine, print its status or a starter seed file");
5707
5707
  twin.command("start").argument(
5708
5708
  "[name]",
5709
5709
  `Twin name (${TWIN_NAME_LIST.join(" | ")}). Optional when --seed names exactly one twin.`
5710
5710
  ).option(
5711
5711
  "--port <port>",
5712
- "Port to bind (default: $PORT, else GMAIL_TWIN_PORT/3336 for gmail, else 3333)"
5712
+ // Built from the registry rather than restated: the per-twin overrides
5713
+ // are the registry's to add, and this text went stale when linear's did.
5714
+ `Port to bind (default: $PORT, else ${TWIN_NAME_LIST.filter(
5715
+ (twin2) => TWIN_REGISTRY[twin2].portEnvName
5716
+ ).map((twin2) => `${TWIN_REGISTRY[twin2].portEnvName}/${TWIN_REGISTRY[twin2].defaultPort} for ${twin2}`).join(", ")}, otherwise 3333)`
5713
5717
  ).option(
5714
5718
  "--seed <path>",
5715
5719
  "Boot this twin from a JSON or YAML seed file instead of its default. A seed REPLACES the default; it does not merge. Takes the per-twin envelope { <twin>: { \u2026 } } or one twin's flat seed. Overrides POME_SEED_JSON."
5716
5720
  ).description(
5717
5721
  "Start a standalone twin as a long-lived foreground server (Ctrl-C to stop)"
5718
5722
  ).action(async (name, options) => {
5719
- const { runTwinStartCommand } = await import('../../twinStart-2LICNC4D.js');
5723
+ const { runTwinStartCommand } = await import('../../twinStart-N6HTOARC.js');
5720
5724
  await runTwinStartCommand(name, options);
5721
5725
  });
5722
5726
  twin.command("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.").option(
@@ -5728,36 +5732,38 @@ function createProgram() {
5728
5732
  const { runTwinSeedCommand } = await import('../../twinSeed-7M4GOIBS.js');
5729
5733
  await runTwinSeedCommand(names, options);
5730
5734
  });
5731
- twin.command("reset").argument("[name]", "Twin name", "github").summary("Reset a twin's saved state").description(
5732
- "Delete the twin's database under `.pome/` or `.pome-data/`, and `.pome/twin-status.json`, the one file `pome twin status` reads for every twin. A twin holding its state in memory has nothing to delete."
5733
- ).action(async (name) => {
5734
- if (!isTwinName(name)) {
5735
- throw new Error(`Unknown twin '${name}'. Supported: ${TWIN_NAME_LIST.join(", ")}.`);
5736
- }
5737
- const dbPaths = name === "gmail" ? [".pome/gmail.db", ".pome-data/gmail/gmail.db"] : [`.pome/${name}.db`, `.pome-data/${name}/${name}.db`];
5738
- for (const dbPath of dbPaths) {
5739
- await rm(dbPath, { force: true });
5740
- await rm(`${dbPath}-wal`, { force: true });
5741
- await rm(`${dbPath}-shm`, { force: true });
5742
- }
5743
- await rm(".pome/twin-status.json", { force: true });
5744
- console.log(`Standalone ${name} twin state reset.`);
5745
- });
5746
- twin.command("status").description("Print standalone twin status").action(async () => {
5747
- if (!existsSync(".pome/twin-status.json")) {
5735
+ twin.command("status").summary("Print the local twin's status").description(
5736
+ "Say whether the twin `pome twin start` last booted here is still running, and print its paste-able env lines"
5737
+ ).action(async () => {
5738
+ const statusPath = ".pome/twin-status.json";
5739
+ if (!existsSync(statusPath)) {
5748
5740
  console.log("No standalone twin status found.");
5749
5741
  return;
5750
5742
  }
5751
- console.log(await import('node:fs/promises').then((fs) => fs.readFile(".pome/twin-status.json", "utf8")));
5752
- });
5753
- program.command("endpoints").summary("List a twin's endpoints").argument("<name>", "Twin name").description("List the endpoints the github or gmail twin serves").action((name) => {
5754
- const endpoints = name === "github" ? SUPPORTED_GITHUB_ENDPOINTS : name === "gmail" ? SUPPORTED_GMAIL_ENDPOINTS : null;
5755
- if (!endpoints) {
5756
- throw new Error("Endpoint listing is available for: github, gmail.");
5757
- }
5758
- for (const endpoint of endpoints) {
5759
- console.log(`${endpoint} semantic`);
5743
+ let status;
5744
+ let origin;
5745
+ try {
5746
+ status = JSON.parse(await readFile(statusPath, "utf8"));
5747
+ if (typeof status.name !== "string" || status.name === "") throw new Error("no name");
5748
+ origin = new URL(status.rest_url).origin;
5749
+ } catch {
5750
+ throw new Error(
5751
+ `pome twin status: ${statusPath} is unreadable \u2014 start a twin with \`pome twin start <${TWIN_NAME_LIST.join("|")}>\`.`
5752
+ );
5760
5753
  }
5754
+ const running = await fetch(`${origin}/healthz`, {
5755
+ signal: AbortSignal.timeout(1e3)
5756
+ }).then(
5757
+ async (res) => res.ok && (await res.json().catch(() => ({}))).twin === status.name,
5758
+ () => false
5759
+ );
5760
+ console.log(
5761
+ running ? `${status.name} twin \u2014 running` : `${status.name} twin \u2014 not running (stale ${statusPath})`
5762
+ );
5763
+ const envName = TWIN_REGISTRY[status.name]?.envName ?? status.name.toUpperCase();
5764
+ console.log(`POME_${envName}_REST_URL=${status.rest_url}`);
5765
+ console.log(`POME_${envName}_MCP_URL=${status.mcp_url}`);
5766
+ console.log(`POME_AUTH_TOKEN=${status.auth_token}`);
5761
5767
  });
5762
5768
  program.command("capture-server").summary("Record the agent's model calls").description(
5763
5769
  "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."
@@ -5798,43 +5804,6 @@ function createProgram() {
5798
5804
  });
5799
5805
  return program;
5800
5806
  }
5801
- var SUPPORTED_GITHUB_ENDPOINTS = [
5802
- "GET /repos/:owner/:repo",
5803
- "GET /repos/:owner/:repo/issues",
5804
- "GET /repos/:owner/:repo/issues/:number",
5805
- "PATCH /repos/:owner/:repo/issues/:number",
5806
- "POST /repos/:owner/:repo/issues/:number/comments",
5807
- "GET /repos/:owner/:repo/labels",
5808
- "POST /repos/:owner/:repo/labels",
5809
- "GET /repos/:owner/:repo/issues/:number/labels",
5810
- "POST /repos/:owner/:repo/issues/:number/labels",
5811
- "DELETE /repos/:owner/:repo/issues/:number/labels/:name",
5812
- "GET /repos/:owner/:repo/collaborators",
5813
- "POST /repos/:owner/:repo/issues/:number/assignees"
5814
- ];
5815
- var SUPPORTED_GMAIL_ENDPOINTS = [
5816
- "GET /gmail/v1/users/:userId/profile",
5817
- "GET|POST /gmail/v1/users/:userId/messages",
5818
- "GET|DELETE /gmail/v1/users/:userId/messages/:id",
5819
- "POST /gmail/v1/users/:userId/messages/{send,import,batchModify,batchDelete}",
5820
- "POST /gmail/v1/users/:userId/messages/:id/{modify,trash,untrash}",
5821
- "GET /gmail/v1/users/:userId/messages/:messageId/attachments/:id",
5822
- "GET|POST /gmail/v1/users/:userId/drafts",
5823
- "GET|PUT|DELETE /gmail/v1/users/:userId/drafts/:id",
5824
- "POST /gmail/v1/users/:userId/drafts/send",
5825
- "GET /gmail/v1/users/:userId/threads",
5826
- "GET|DELETE /gmail/v1/users/:userId/threads/:id",
5827
- "POST /gmail/v1/users/:userId/threads/:id/{modify,trash,untrash}",
5828
- "GET|POST /gmail/v1/users/:userId/labels",
5829
- "GET|PUT|PATCH|DELETE /gmail/v1/users/:userId/labels/:id",
5830
- "GET /gmail/v1/users/:userId/history",
5831
- "GET|POST /gmail/v1/users/:userId/settings/filters",
5832
- "GET|DELETE /gmail/v1/users/:userId/settings/filters/:id",
5833
- "GET /gmail/v1/users/:userId/settings/{forwardingAddresses,sendAs}",
5834
- "GET /gmail/v1/users/:userId/settings/forwardingAddresses/:email",
5835
- "GET /gmail/v1/users/:userId/settings/sendAs/:email",
5836
- "POST /upload/gmail/v1/users/:userId/{messages,drafts} (media|multipart)"
5837
- ];
5838
5807
  async function taskFiles(target) {
5839
5808
  const resolved = resolve(target);
5840
5809
  if (!existsSync(resolved)) {
@@ -114,6 +114,21 @@ async function runTwinStartCommand(nameArg, options) {
114
114
  const mcpUrl = `${restUrl}/mcp`;
115
115
  const server = serve({ fetch: harness.app.fetch, port, hostname: "127.0.0.1" });
116
116
  try {
117
+ await new Promise((resolve, reject) => {
118
+ const onError = (err) => {
119
+ reject(
120
+ err.code === "EADDRINUSE" ? new Error(
121
+ `pome twin start: port ${port} is already in use \u2014 pass --port <port>, or stop the twin using it.`
122
+ ) : err
123
+ );
124
+ };
125
+ server.once("error", onError);
126
+ server.once("listening", () => {
127
+ server.off("error", onError);
128
+ server.on("error", (err) => console.error(`pome twin start: server error: ${err}`));
129
+ resolve();
130
+ });
131
+ });
117
132
  await mkdir(".pome", { recursive: true });
118
133
  await writeFile(
119
134
  ".pome/twin-status.json",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pome-sh/cli",
3
- "version": "0.38.0",
3
+ "version": "0.39.1",
4
4
  "description": "Test AI agents against digital twins of real SaaS APIs. Records tool-call traces and scores them on pome.sh.",
5
5
  "keywords": [
6
6
  "ai",