@pome-sh/cli 0.21.16 → 0.21.17

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.21.16",
4
- "git_sha": "19f47532359d604ec1ad36a4920a293dbbc6bad9",
5
- "build_time": "2026-08-09T12:30:48.699Z"
3
+ "version": "0.21.17",
4
+ "git_sha": "8b7c792f2aae4f9c2db1773c84b083bd2fa768d9",
5
+ "build_time": "2026-08-09T14:09:36.017Z"
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-W2PMGB4D.js');
186
+ const { bootTwin } = await import('./twinHarness-SBJDUUMK.js');
187
187
  harness = await bootTwin({
188
188
  twin: "github",
189
189
  seedState: void 0,
@@ -16,7 +16,7 @@ var package_default4 = {
16
16
 
17
17
  // ../packages/twin-linear/package.json
18
18
  var package_default5 = {
19
- version: "0.3.5"};
19
+ version: "0.4.0"};
20
20
 
21
21
  // src/twin/registry.ts
22
22
  var TWIN_NAME_LIST = ["github", "slack", "stripe", "gmail", "linear"];
@@ -149,7 +149,7 @@ var TWIN_REGISTRY = {
149
149
  portEnvName: "LINEAR_TWIN_PORT",
150
150
  tokenEnvName: "POME_LINEAR_TOKEN",
151
151
  version: package_default5.version,
152
- defaultSeed: async () => (await import('./src-F4J75FHJ.js')).defaultSeedState(),
152
+ defaultSeed: async () => (await import('./src-WZSM2RYX.js')).defaultSeedState(),
153
153
  async boot({ seedState, runId, recorder }) {
154
154
  const {
155
155
  createLinearTwinApp,
@@ -157,7 +157,7 @@ var TWIN_REGISTRY = {
157
157
  LinearDomain,
158
158
  openLinearTwinDatabase,
159
159
  parseSeed
160
- } = await import('./src-F4J75FHJ.js');
160
+ } = await import('./src-WZSM2RYX.js');
161
161
  const db = openLinearTwinDatabase(":memory:");
162
162
  const seed = parseSeed(seedState);
163
163
  const domain = new LinearDomain(db);
@@ -1,5 +1,5 @@
1
1
  import { readManifest, normalizeManifestTwins } from './chunk-KUVTL4NZ.js';
2
- import { createHostedClient, perTwinReturnedByCloud, parseTaskFile, runAgentCommand, writeRunArtifactsCore, toTwinHttpEvent, redactJsonl, uploadRunBlobs, scoreFromFinalizeResponse, scoreStatus } from './chunk-TFH6A3MX.js';
2
+ import { createHostedClient, perTwinReturnedByCloud, parseTaskFile, runAgentCommand, writeRunArtifactsCore, toTwinHttpEvent, redactJsonl, uploadRunBlobs, scoreFromFinalizeResponse, scoreStatus } from './chunk-SRG5CJM7.js';
3
3
  import { MOUNTED_TWINS, HostedAuthError, HostedDiscardRefusedError, HostedQuotaError, HostedOrchError, HostedTrialError, agentResponseSchema } from './chunk-PQYIAA6K.js';
4
4
  import { redactSecrets, redactEvent } from './chunk-SG6ZTIMT.js';
5
5
  import { existsSync } from 'node:fs';
@@ -1,7 +1,7 @@
1
1
  import { getAvailablePort } from './chunk-XDU6TD4O.js';
2
2
  import { buildEgressAllowlist, readBlockedEgress } from './chunk-CBFKZZBR.js';
3
- import { parseTaskFile, seedStateForTwin, runAgentCommand, writeRunArtifactsCore } from './chunk-TFH6A3MX.js';
4
- import { createRecorder, bootTwin } from './chunk-MN23RUGG.js';
3
+ import { parseTaskFile, seedStateForTwin, runAgentCommand, writeRunArtifactsCore } from './chunk-SRG5CJM7.js';
4
+ import { createRecorder, bootTwin } from './chunk-IWTB3NN5.js';
5
5
  import { eventSchema } from './chunk-VBATFCWR.js';
6
6
  import { redactSecrets, redactEvent } from './chunk-SG6ZTIMT.js';
7
7
  import { serve } from '@hono/node-server';
@@ -1,4 +1,4 @@
1
- import { TWIN_NAMES, isTwinName, TWIN_REGISTRY } from './chunk-GPLI6UFI.js';
1
+ import { TWIN_NAMES, isTwinName, TWIN_REGISTRY } from './chunk-3JUWDIJ2.js';
2
2
  import { createFileBackedRecorderStore, createRecorderStore } from './chunk-TV5S6WQV.js';
3
3
 
4
4
  // src/recorder/recorder.ts
@@ -2,7 +2,7 @@ import { criterionSchema, finalizeResponseSchema, HostedDiscardRefusedError, Hos
2
2
  import { seedSchema, parseSeed, defaultSeedState as defaultSeedState$2 } from './chunk-SGDUD7KK.js';
3
3
  import { gmailSeedSchema, defaultSeedState } from './chunk-NJ246QPJ.js';
4
4
  import { linearSeedSchema, defaultSeedState as defaultSeedState$1 } from './chunk-ZKID2HS3.js';
5
- import { isTwinName, TWIN_REGISTRY } from './chunk-GPLI6UFI.js';
5
+ import { isTwinName, TWIN_REGISTRY } from './chunk-3JUWDIJ2.js';
6
6
  import { toTwinHttpEventRow } from './chunk-TV5S6WQV.js';
7
7
  import { redactEvent, redactSecrets } from './chunk-SG6ZTIMT.js';
8
8
  import { mkdir, appendFile, writeFile, readFile } from 'node:fs/promises';
@@ -1,16 +1,16 @@
1
1
  import { newGroupId, reassuranceBox, twinReadyLine, trialsHeaderLine, trialLine, summaryLines, evaluatingLine, criterionPhrase } from './chunk-RGZBC7NF.js';
2
2
  import { DemoCapacityError, capacityLabel, parseCapacityMarker, capacityKindFrom } from './chunk-ZX4WNSZ5.js';
3
- import { runTask, demoTaskPath, DEMO_TASK_NAME, DEMO_REPO } from './chunk-GW2SMCUT.js';
3
+ import { runTask, demoTaskPath, DEMO_TASK_NAME, DEMO_REPO } from './chunk-IUXQAUYY.js';
4
4
  import { getAvailablePort } from './chunk-XDU6TD4O.js';
5
5
  import './chunk-CBFKZZBR.js';
6
- import { createHostedClient, parseTaskFile, uploadRunBlobs, scoreFromFinalizeResponse, scoreStatus, outcomeOf } from './chunk-TFH6A3MX.js';
6
+ import { createHostedClient, parseTaskFile, uploadRunBlobs, scoreFromFinalizeResponse, scoreStatus, outcomeOf } from './chunk-SRG5CJM7.js';
7
7
  import './chunk-NW7HGA2K.js';
8
8
  import { HostedQuotaError, HostedOrchError } from './chunk-PQYIAA6K.js';
9
9
  import './chunk-SGDUD7KK.js';
10
10
  import './chunk-NJ246QPJ.js';
11
11
  import './chunk-ZKID2HS3.js';
12
- import { bootTwin } from './chunk-MN23RUGG.js';
13
- import './chunk-GPLI6UFI.js';
12
+ import { bootTwin } from './chunk-IWTB3NN5.js';
13
+ import './chunk-3JUWDIJ2.js';
14
14
  import './chunk-TV5S6WQV.js';
15
15
  import './chunk-VBATFCWR.js';
16
16
  import './chunk-SG6ZTIMT.js';
@@ -1,13 +1,13 @@
1
1
  import { newGroupId, criterionPhrase } from './chunk-RGZBC7NF.js';
2
- import { runTaskHosted, resolveRunAgentIdentity } from './chunk-FKMSYT5H.js';
2
+ import { runTaskHosted, resolveRunAgentIdentity } from './chunk-HZEOZGFN.js';
3
3
  import './chunk-KUVTL4NZ.js';
4
- import { createHostedClient, parseTaskFile, outcomeOf } from './chunk-TFH6A3MX.js';
4
+ import { createHostedClient, parseTaskFile, outcomeOf } from './chunk-SRG5CJM7.js';
5
5
  import './chunk-NW7HGA2K.js';
6
6
  import { HostedQuotaError, HostedTrialError } from './chunk-PQYIAA6K.js';
7
7
  import './chunk-SGDUD7KK.js';
8
8
  import './chunk-NJ246QPJ.js';
9
9
  import './chunk-ZKID2HS3.js';
10
- import './chunk-GPLI6UFI.js';
10
+ import './chunk-3JUWDIJ2.js';
11
11
  import './chunk-TV5S6WQV.js';
12
12
  import './chunk-VBATFCWR.js';
13
13
  import './chunk-SG6ZTIMT.js';
@@ -1,10 +1,10 @@
1
1
  #!/usr/bin/env node
2
- import { DEFAULT_CONTROL_PLANE_URL, DEFAULT_DASHBOARD_URL, clearLocalCredentials, friendlyHostedError, runSessionCreate, runSessionList, runSessionStop, resolveCredentials, runTaskHosted, discoverRunSet, loadTrialEvents, persistCredentialsAfterLogin, DEFAULT_DOCS_SITE_ORIGIN, resolveSeams, resolveCachedAgentId, readLinkCache, postAgentResolver, writeLinkCache, ensurePomeGitignored } from '../../chunk-FKMSYT5H.js';
2
+ import { DEFAULT_CONTROL_PLANE_URL, DEFAULT_DASHBOARD_URL, clearLocalCredentials, friendlyHostedError, runSessionCreate, runSessionList, runSessionStop, resolveCredentials, runTaskHosted, discoverRunSet, loadTrialEvents, persistCredentialsAfterLogin, DEFAULT_DOCS_SITE_ORIGIN, resolveSeams, resolveCachedAgentId, readLinkCache, postAgentResolver, writeLinkCache, ensurePomeGitignored } from '../../chunk-HZEOZGFN.js';
3
3
  import { readManifest, writeManifest, MANIFEST_JSON, readRequiredManifest, normalizeManifestTwins } from '../../chunk-KUVTL4NZ.js';
4
- import { assetPath, runTask, resolvePackageRoot, DEMO_TASK_NAME, demoTaskPath } from '../../chunk-GW2SMCUT.js';
4
+ import { assetPath, runTask, resolvePackageRoot, DEMO_TASK_NAME, demoTaskPath } from '../../chunk-IUXQAUYY.js';
5
5
  import '../../chunk-XDU6TD4O.js';
6
6
  import '../../chunk-CBFKZZBR.js';
7
- import { parseTaskFile, scoreStatus, runScoreLine, readLatestRun, readMetaSummary, readConfigTwins, scoreCountsSummary, markerFor, outcomeOf, criterionMarkerLabel, twinSkipSuffix, readCodeCriteria, createHostedClient, toTwinHttpEvent, redactJsonl, scoreFromFinalizeResponse, parseGitHubSeedState, uploadRunBlobs } from '../../chunk-TFH6A3MX.js';
7
+ import { parseTaskFile, scoreStatus, runScoreLine, readLatestRun, readMetaSummary, readConfigTwins, scoreCountsSummary, markerFor, outcomeOf, criterionMarkerLabel, twinSkipSuffix, readCodeCriteria, createHostedClient, toTwinHttpEvent, redactJsonl, scoreFromFinalizeResponse, parseGitHubSeedState, uploadRunBlobs } from '../../chunk-SRG5CJM7.js';
8
8
  import '../../chunk-NW7HGA2K.js';
9
9
  import { MOUNTED_TWINS, deriveAgentSlug, exitCodeFor, HostedUsageError, HostedOrchError, HostedAuthError, HostedQuotaError } from '../../chunk-PQYIAA6K.js';
10
10
  import { TAPE_ASSERTABLE_TOOLS } from '../../chunk-FKZZWWYC.js';
@@ -15,8 +15,8 @@ import '../../chunk-NJ246QPJ.js';
15
15
  import { LINEAR_CHECKS } from '../../chunk-XBT6ZLBG.js';
16
16
  import '../../chunk-ZKID2HS3.js';
17
17
  import { oneOf, defineCheck, repoRef, VACUITY_SENTINEL_NUMBER, childStatePath, VACUITY_SENTINEL, statePath, templateSlots, renderCheck, checksDigest, checkPattern, checkNearMissPattern } from '../../chunk-JWJYNAWI.js';
18
- import '../../chunk-MN23RUGG.js';
19
- import { TWIN_NAME_LIST, isTwinName, createGitHubSmokeApp } from '../../chunk-GPLI6UFI.js';
18
+ import '../../chunk-IWTB3NN5.js';
19
+ import { TWIN_NAME_LIST, isTwinName, createGitHubSmokeApp } from '../../chunk-3JUWDIJ2.js';
20
20
  import '../../chunk-TV5S6WQV.js';
21
21
  import { isLegacyEventRow, eventSchema } from '../../chunk-VBATFCWR.js';
22
22
  import { redactEvent, redactSecrets } from '../../chunk-SG6ZTIMT.js';
@@ -4490,7 +4490,7 @@ var DEFAULT_AGENT_FILE = "examples/agents/scripted-triage-agent.ts";
4490
4490
  var DEFAULT_AGENT_COMMAND = `node ${DEFAULT_AGENT_FILE}`;
4491
4491
  var MANIFEST_SCHEMA_URL = "https://pome.sh/schemas/v1/pome.json";
4492
4492
  function readPackageVersion() {
4493
- if ("0.21.16".length > 0) return "0.21.16";
4493
+ if ("0.21.17".length > 0) return "0.21.17";
4494
4494
  try {
4495
4495
  const here = dirname(fileURLToPath(import.meta.url));
4496
4496
  const candidates = [
@@ -4945,7 +4945,7 @@ function createProgram() {
4945
4945
  return;
4946
4946
  }
4947
4947
  {
4948
- const { runDoctorChecks } = await import('../../checks-TZ4BVN5S.js');
4948
+ const { runDoctorChecks } = await import('../../checks-DH7XLBI3.js');
4949
4949
  const { renderDoctorReport } = await import('../../render-ZQQ4UMNO.js');
4950
4950
  const doctorReport = await runDoctorChecks({ mode: useLocal ? "full" : "hosted" });
4951
4951
  if (!doctorReport.ok) {
@@ -4983,7 +4983,7 @@ function createProgram() {
4983
4983
  taskForRuns.config.runs
4984
4984
  );
4985
4985
  if (k > 1) {
4986
- const { runTrialGroup } = await import('../../runTrialGroup-SFGCMNXD.js');
4986
+ const { runTrialGroup } = await import('../../runTrialGroup-DGAWGKIA.js');
4987
4987
  const fileForRerun = relative(process.cwd(), file);
4988
4988
  const rerunCommand = defaultTask ? options.trials !== void 0 ? `pome run -n ${k}` : "pome run" : `pome run ${fileForRerun && !fileForRerun.startsWith("..") ? fileForRerun : file} -n ${k}`;
4989
4989
  const groupResult = await runTrialGroup({
@@ -5077,7 +5077,7 @@ function createProgram() {
5077
5077
  process.exitCode = 5;
5078
5078
  return;
5079
5079
  }
5080
- const { runDemo } = await import('../../runDemo-77JUEOSA.js');
5080
+ const { runDemo } = await import('../../runDemo-CNAK5VH3.js');
5081
5081
  const result = await runDemo({
5082
5082
  apiBase: opts.apiUrl.replace(/\/$/, ""),
5083
5083
  dashboardBase: process.env.POME_DASHBOARD_URL ?? DEFAULT_DASHBOARD_URL,
@@ -5095,7 +5095,7 @@ function createProgram() {
5095
5095
  program.command("doctor").description(
5096
5096
  "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."
5097
5097
  ).action(async () => {
5098
- const { runDoctorChecks } = await import('../../checks-TZ4BVN5S.js');
5098
+ const { runDoctorChecks } = await import('../../checks-DH7XLBI3.js');
5099
5099
  const { renderDoctorReport } = await import('../../render-ZQQ4UMNO.js');
5100
5100
  const report = await runDoctorChecks();
5101
5101
  for (const line of renderDoctorReport(report, { passNote: true })) console.error(line);
@@ -5227,7 +5227,7 @@ function createProgram() {
5227
5227
  ).description(
5228
5228
  "Start a standalone twin as a long-lived foreground server (Ctrl-C to stop)"
5229
5229
  ).action(async (name, options) => {
5230
- const { runTwinStartCommand } = await import('../../twinStart-53YUOJVD.js');
5230
+ const { runTwinStartCommand } = await import('../../twinStart-R4RLPJ3F.js');
5231
5231
  await runTwinStartCommand(name, options);
5232
5232
  });
5233
5233
  twin.command("reset").argument("[name]", "Twin name (default: github)", "github").description("Reset standalone twin state").action(async (name) => {
@@ -7,9 +7,9 @@ import { loadMcpToolFixture, deriveMcpToolTable, openTwinDatabase, defineTwin, c
7
7
  import './chunk-VBATFCWR.js';
8
8
  import './chunk-SG6ZTIMT.js';
9
9
  import { createHmac, timingSafeEqual, createHash, randomBytes } from 'node:crypto';
10
+ import { z } from 'zod';
10
11
  import { isIP } from 'node:net';
11
12
  import { lookup } from 'node:dns/promises';
12
- import { z } from 'zod';
13
13
  import { Hono } from 'hono';
14
14
  import { buildSchema, graphql, parse, getOperationAST } from 'graphql';
15
15
 
@@ -271,8 +271,8 @@ CREATE TABLE IF NOT EXISTS agent_activities (
271
271
  id TEXT PRIMARY KEY,
272
272
  session_id TEXT NOT NULL,
273
273
  user_id TEXT,
274
- type TEXT NOT NULL,
275
- body TEXT NOT NULL,
274
+ content_json TEXT NOT NULL DEFAULT '{}',
275
+ signal TEXT,
276
276
  ephemeral INTEGER NOT NULL DEFAULT 0,
277
277
  created_at TEXT NOT NULL,
278
278
  updated_at TEXT NOT NULL,
@@ -340,6 +340,27 @@ function migrate(db) {
340
340
  ensureColumn(db, "issues", "parent_id", "TEXT");
341
341
  ensureColumn(db, "comments", "parent_id", "TEXT");
342
342
  migrateAgentSessions(db);
343
+ migrateAgentActivities(db);
344
+ }
345
+ function migrateAgentActivities(db) {
346
+ const columns = db.prepare("PRAGMA table_info(agent_activities)").all().map((column) => column.name);
347
+ if (!columns.includes("content_json")) {
348
+ db.exec("ALTER TABLE agent_activities ADD COLUMN content_json TEXT NOT NULL DEFAULT '{}'");
349
+ }
350
+ if (!columns.includes("signal"))
351
+ db.exec("ALTER TABLE agent_activities ADD COLUMN signal TEXT");
352
+ if (columns.includes("type") && columns.includes("body")) {
353
+ db.exec(`UPDATE agent_activities
354
+ SET content_json = json_object('type', type, 'body', body)
355
+ WHERE content_json = '{}'`);
356
+ }
357
+ if (columns.includes("type"))
358
+ db.exec("ALTER TABLE agent_activities DROP COLUMN type");
359
+ if (columns.includes("body"))
360
+ db.exec("ALTER TABLE agent_activities DROP COLUMN body");
361
+ db.exec(`UPDATE agent_activities
362
+ SET user_id = (SELECT app_user_id FROM agent_sessions WHERE agent_sessions.id = session_id)
363
+ WHERE user_id IS NULL`);
343
364
  }
344
365
  function migrateAgentSessions(db) {
345
366
  const columnNames = () => db.prepare("PRAGMA table_info(agent_sessions)").all().map((column) => column.name);
@@ -444,8 +465,6 @@ function assertNoParentCycle(domain, issueId, parentId) {
444
465
  cursor = row?.parentId ?? null;
445
466
  }
446
467
  }
447
-
448
- // ../packages/twin-linear/dist/src/domain/normalize.js
449
468
  function assertTitle(title) {
450
469
  if (byteLength(title) > TITLE_MAX_BYTES)
451
470
  badUserInput(`Issue title exceeds ${TITLE_MAX_BYTES} bytes`);
@@ -494,23 +513,51 @@ function readSessionStatus(value) {
494
513
  }
495
514
  return value;
496
515
  }
497
- function normalizeSessionStatus(value) {
498
- if (!AGENT_SESSION_STATUSES.includes(value)) {
499
- badUserInput(`Invalid agent session status: ${value}`);
516
+ function readActivityUserId(activityId, value) {
517
+ if (!value) {
518
+ throw new LinearTwinError(500, "INTERNAL_SERVER_ERROR", `Agent activity "${activityId}" has no user. Linear declares AgentActivity.user as non-null; this row's author was cleared, which no code path in this twin does.`);
500
519
  }
501
520
  return value;
502
521
  }
503
- function normalizeActivityType(value) {
504
- const allowed = [
505
- "thought",
506
- "elicitation",
507
- "action",
508
- "response",
509
- "error",
510
- "prompt"
511
- ];
512
- if (!allowed.includes(value))
513
- badUserInput(`Invalid agent activity type: ${value}`);
522
+ var AGENT_ACTIVITY_SIGNALS = ["stop", "continue", "auth", "select"];
523
+ var AGENT_ACTIVITY_SESSION_STATUS = {
524
+ thought: "active",
525
+ action: "active",
526
+ elicitation: "awaitingInput",
527
+ response: "complete",
528
+ error: "error",
529
+ prompt: "pending"
530
+ };
531
+ var bodyContent = { body: z.string().min(1), bodyData: z.unknown().optional() };
532
+ var agentActivityContentSchema = z.discriminatedUnion("type", [
533
+ z.object({ type: z.literal("thought"), ...bodyContent }).strict(),
534
+ z.object({ type: z.literal("response"), ...bodyContent }).strict(),
535
+ z.object({ type: z.literal("elicitation"), ...bodyContent }).strict(),
536
+ z.object({ type: z.literal("prompt"), ...bodyContent, title: z.string().nullish() }).strict(),
537
+ z.object({ type: z.literal("error"), ...bodyContent, reasonCode: z.string().nullish() }).strict(),
538
+ z.object({
539
+ type: z.literal("action"),
540
+ action: z.string().min(1),
541
+ parameter: z.string().min(1),
542
+ result: z.string().nullish(),
543
+ resultData: z.unknown().optional()
544
+ }).strict()
545
+ ]);
546
+ function normalizeActivityContent(value) {
547
+ const parsed = agentActivityContentSchema.safeParse(value);
548
+ if (!parsed.success) {
549
+ const issue = parsed.error.issues[0];
550
+ badUserInput(`Invalid agent activity content${issue ? `: ${issue.path.join(".") || "type"} \u2014 ${issue.message}` : ""}`);
551
+ }
552
+ const content = parsed.data;
553
+ if ("body" in content)
554
+ assertBody(content.body);
555
+ return content;
556
+ }
557
+ function normalizeActivitySignal(value) {
558
+ if (!AGENT_ACTIVITY_SIGNALS.includes(value)) {
559
+ badUserInput(`Invalid agent activity signal: ${value}`);
560
+ }
514
561
  return value;
515
562
  }
516
563
 
@@ -690,10 +737,10 @@ function mapAgentSession(row) {
690
737
  function mapAgentActivity(row) {
691
738
  return {
692
739
  id: row.id,
693
- sessionId: row.session_id,
694
- userId: row.user_id,
695
- type: row.type,
696
- body: row.body,
740
+ agentSessionId: row.session_id,
741
+ userId: readActivityUserId(row.id, row.user_id),
742
+ content: JSON.parse(row.content_json),
743
+ signal: row.signal,
697
744
  ephemeral: !!row.ephemeral,
698
745
  createdAt: row.created_at,
699
746
  updatedAt: row.updated_at
@@ -1598,8 +1645,9 @@ function exportLinearState(db) {
1598
1645
  payload: parseJson(row.payload),
1599
1646
  headers: redactHeaders(parseJson(row.headers))
1600
1647
  })), "webhookDeliveries", truncatedCollections, true);
1601
- const agentActivities = capped(db.prepare(`SELECT id, session_id AS sessionId, user_id AS userId, type, body, ephemeral,
1602
- created_at AS createdAt FROM agent_activities ORDER BY created_at DESC, id DESC`).all(), "agentActivities", truncatedCollections, true);
1648
+ const agentActivities = capped(db.prepare(`SELECT id, session_id AS agentSessionId, user_id AS userId, content_json AS content,
1649
+ signal, ephemeral, created_at AS createdAt
1650
+ FROM agent_activities ORDER BY created_at DESC, id DESC`).all().map((row) => ({ ...row, content: parseJson(row.content) })), "agentActivities", truncatedCollections, true);
1603
1651
  return {
1604
1652
  schemaVersion: 1,
1605
1653
  clock,
@@ -1755,7 +1803,7 @@ async function createAgentSessionOnIssue(domain, input, actor = {}) {
1755
1803
  const now = domain.tick();
1756
1804
  const id = domain.nextId("agent_session");
1757
1805
  domain.db.prepare(`INSERT INTO agent_sessions(id, issue_id, comment_id, app_user_id, status, plan, external_urls_json, created_at, updated_at)
1758
- VALUES (?,?,?,?,?,?,?,?,?)`).run(id, issue.id, null, agent.id, "pending", input.plan ?? null, JSON.stringify(input.externalUrls ?? []), now, now);
1806
+ VALUES (?,?,?,?,?,?,?,?,?)`).run(id, issue.id, null, agent.id, "pending", null, JSON.stringify(input.externalUrls ?? []), now, now);
1759
1807
  const session = domain.requireAgentSession(id);
1760
1808
  await emitWebhook(domain, {
1761
1809
  type: "AgentSessionEvent",
@@ -1775,7 +1823,7 @@ async function createAgentSessionOnComment(domain, input, actor = {}) {
1775
1823
  const now = domain.tick();
1776
1824
  const id = domain.nextId("agent_session");
1777
1825
  domain.db.prepare(`INSERT INTO agent_sessions(id, issue_id, comment_id, app_user_id, status, plan, external_urls_json, created_at, updated_at)
1778
- VALUES (?,?,?,?,?,?,?,?,?)`).run(id, issue.id, comment.id, agent.id, "pending", input.plan ?? null, JSON.stringify(input.externalUrls ?? []), now, now);
1826
+ VALUES (?,?,?,?,?,?,?,?,?)`).run(id, issue.id, comment.id, agent.id, "pending", null, JSON.stringify(input.externalUrls ?? []), now, now);
1779
1827
  return domain.requireAgentSession(id);
1780
1828
  }
1781
1829
  function updateAgentSession(domain, id, input, actor = {}) {
@@ -1783,29 +1831,31 @@ function updateAgentSession(domain, id, input, actor = {}) {
1783
1831
  const session = domain.requireAgentSession(id);
1784
1832
  const now = domain.tick();
1785
1833
  domain.db.prepare(`UPDATE agent_sessions SET
1786
- status = COALESCE(?, status),
1787
1834
  plan = CASE WHEN ? THEN ? ELSE plan END,
1788
1835
  external_urls_json = CASE WHEN ? THEN ? ELSE external_urls_json END,
1789
1836
  updated_at = ?
1790
- WHERE id = ?`).run(input.status ? normalizeSessionStatus(input.status) : null, input.plan !== void 0 ? 1 : 0, input.plan ?? null, input.externalUrls !== void 0 ? 1 : 0, JSON.stringify(input.externalUrls ?? []), now, session.id);
1837
+ WHERE id = ?`).run(input.plan !== void 0 ? 1 : 0, input.plan ?? null, input.externalUrls !== void 0 ? 1 : 0, JSON.stringify(input.externalUrls ?? []), now, session.id);
1791
1838
  return domain.requireAgentSession(session.id);
1792
1839
  }
1793
1840
  async function createAgentActivity(domain, input, actor = {}) {
1794
1841
  domain.requireScopes(actor, ["write"]);
1795
- assertBody(input.body);
1796
- const session = domain.requireAgentSession(input.sessionId);
1842
+ const session = domain.requireAgentSession(input.agentSessionId);
1797
1843
  const viewer = domain.resolveViewer(actor);
1798
- const type = normalizeActivityType(input.type);
1844
+ const content = normalizeActivityContent(input.content);
1845
+ const signal = input.signal ? normalizeActivitySignal(input.signal) : null;
1799
1846
  const now = domain.tick();
1800
1847
  const id = domain.nextId("agent_activity");
1801
- const ephemeral = typeof input.ephemeral === "boolean" ? input.ephemeral : type === "thought" || type === "action";
1802
- domain.db.prepare(`INSERT INTO agent_activities(id, session_id, user_id, type, body, ephemeral, created_at, updated_at)
1803
- VALUES (?,?,?,?,?,?,?,?)`).run(id, session.id, viewer.id, type, input.body, ephemeral ? 1 : 0, now, now);
1804
- if (type === "prompt") {
1848
+ const ephemeral = typeof input.ephemeral === "boolean" ? input.ephemeral : content.type === "thought" || content.type === "action";
1849
+ domain.db.prepare(`INSERT INTO agent_activities(id, session_id, user_id, content_json, signal, ephemeral, created_at, updated_at)
1850
+ VALUES (?,?,?,?,?,?,?,?)`).run(id, session.id, viewer.id, JSON.stringify(content), signal, ephemeral ? 1 : 0, now, now);
1851
+ const status = AGENT_ACTIVITY_SESSION_STATUS[content.type];
1852
+ domain.db.prepare("UPDATE agent_sessions SET status = ?, updated_at = ? WHERE id = ?").run(status, now, session.id);
1853
+ if (content.type === "prompt") {
1805
1854
  await emitWebhook(domain, {
1806
1855
  type: "AgentSessionEvent",
1807
1856
  action: "prompted",
1808
- data: { id: session.id, status: session.status },
1857
+ // The status the activity just produced, not the one it replaced.
1858
+ data: { id: session.id, status },
1809
1859
  actor: viewer,
1810
1860
  teamId: session.issueId ? domain.requireIssue(session.issueId).teamId : null
1811
1861
  });
@@ -1819,8 +1869,8 @@ function getAgentActivity(domain, ref) {
1819
1869
  const row = domain.db.prepare("SELECT * FROM agent_activities WHERE id = ?").get(ref);
1820
1870
  return row ? mapAgentActivity(row) : null;
1821
1871
  }
1822
- function listAgentActivities(domain, sessionId) {
1823
- return domain.db.prepare("SELECT * FROM agent_activities WHERE session_id = ? ORDER BY created_at, id").all(sessionId).map(mapAgentActivity);
1872
+ function listAgentActivities(domain, agentSessionId) {
1873
+ return domain.db.prepare("SELECT * FROM agent_activities WHERE session_id = ? ORDER BY created_at, id").all(agentSessionId).map(mapAgentActivity);
1824
1874
  }
1825
1875
 
1826
1876
  // ../packages/twin-linear/dist/src/domain/catalog.js
@@ -2533,8 +2583,8 @@ var LinearDomain = class {
2533
2583
  getAgentActivity(ref) {
2534
2584
  return getAgentActivity(this, ref);
2535
2585
  }
2536
- listAgentActivities(sessionId) {
2537
- return listAgentActivities(this, sessionId);
2586
+ listAgentActivities(agentSessionId) {
2587
+ return listAgentActivities(this, agentSessionId);
2538
2588
  }
2539
2589
  listOAuthApps() {
2540
2590
  return listOAuthApps(this);
@@ -3982,13 +4032,13 @@ function createFormatters(commands, actor) {
3982
4032
  });
3983
4033
  const formatAgentActivity = (activity) => ({
3984
4034
  id: activity.id,
3985
- type: activity.type,
3986
- body: activity.body,
4035
+ content: activity.content,
4036
+ signal: activity.signal,
3987
4037
  ephemeral: activity.ephemeral,
3988
4038
  createdAt: activity.createdAt,
3989
4039
  updatedAt: activity.updatedAt,
3990
- session: () => formatAgentSession(commands.requireAgentSession(activity.sessionId)),
3991
- user: () => activity.userId ? formatUser(commands.requireUser(activity.userId)) : null
4040
+ agentSession: () => formatAgentSession(commands.requireAgentSession(activity.agentSessionId)),
4041
+ user: () => formatUser(commands.requireUser(activity.userId))
3992
4042
  });
3993
4043
  function formatIssue(issue) {
3994
4044
  return {
@@ -4207,26 +4257,25 @@ var agentSessionExternalUrlSchema = z.object({ url: z.string().min(1), label: z.
4207
4257
  var optionalExternalUrls = z.array(agentSessionExternalUrlSchema).nullish();
4208
4258
  var agentSessionOnIssueInputSchema = z.object({
4209
4259
  issueId: z.string().min(1),
4210
- appUserId: z.string().optional(),
4211
- plan: optionalString,
4212
4260
  externalUrls: optionalExternalUrls
4213
4261
  }).strict();
4214
4262
  var agentSessionOnCommentInputSchema = z.object({
4215
4263
  commentId: z.string().min(1),
4216
- appUserId: z.string().optional(),
4217
- plan: optionalString,
4218
4264
  externalUrls: optionalExternalUrls
4219
4265
  }).strict();
4220
4266
  var agentSessionUpdateInputSchema = z.object({
4221
- id: z.string().min(1).optional(),
4222
- status: z.string().optional(),
4223
4267
  plan: optionalString,
4224
4268
  externalUrls: optionalExternalUrls
4225
4269
  }).strict();
4226
4270
  var agentActivityCreateInputSchema = z.object({
4227
- sessionId: z.string().min(1),
4228
- type: z.string().min(1),
4229
- body: z.string().min(1),
4271
+ agentSessionId: z.string().min(1),
4272
+ // `JSONObject!` upstream. The envelope is checked here; which of Linear's
4273
+ // six `AgentActivityContent` members it is, and whether it is well formed,
4274
+ // is the domain's `normalizeActivityContent` — the same split as
4275
+ // `priority` and `normalizePriority`, and the reason a bad content names
4276
+ // itself rather than surfacing as a stray "expected string".
4277
+ content: z.record(z.string(), z.unknown()),
4278
+ signal: z.enum(AGENT_ACTIVITY_SIGNALS).nullish(),
4230
4279
  ephemeral: z.boolean().optional()
4231
4280
  }).strict();
4232
4281
  function parseOrBadUserInput(schema, input, label) {
@@ -4333,37 +4382,22 @@ function parseWebhookCreateInput(input) {
4333
4382
  }
4334
4383
  function parseAgentSessionOnIssueInput(input) {
4335
4384
  const raw = parseOrBadUserInput(agentSessionOnIssueInputSchema, input, "agentSessionCreateOnIssue input");
4336
- return {
4337
- issueId: raw.issueId,
4338
- appUserId: raw.appUserId,
4339
- plan: raw.plan ?? null,
4340
- externalUrls: raw.externalUrls ?? null
4341
- };
4385
+ return { issueId: raw.issueId, externalUrls: raw.externalUrls ?? null };
4342
4386
  }
4343
4387
  function parseAgentSessionOnCommentInput(input) {
4344
4388
  const raw = parseOrBadUserInput(agentSessionOnCommentInputSchema, input, "agentSessionCreateOnComment input");
4345
- return {
4346
- commentId: raw.commentId,
4347
- appUserId: raw.appUserId,
4348
- plan: raw.plan ?? null,
4349
- externalUrls: raw.externalUrls ?? null
4350
- };
4389
+ return { commentId: raw.commentId, externalUrls: raw.externalUrls ?? null };
4351
4390
  }
4352
4391
  function parseAgentSessionUpdateInput(input) {
4353
4392
  const raw = parseOrBadUserInput(agentSessionUpdateInputSchema, input, "agentSessionUpdate input");
4354
- return {
4355
- id: raw.id,
4356
- status: raw.status,
4357
- plan: raw.plan,
4358
- externalUrls: raw.externalUrls
4359
- };
4393
+ return { plan: raw.plan, externalUrls: raw.externalUrls };
4360
4394
  }
4361
4395
  function parseAgentActivityCreateInput(input) {
4362
4396
  const raw = parseOrBadUserInput(agentActivityCreateInputSchema, input, "agentActivityCreate input");
4363
4397
  return {
4364
- sessionId: raw.sessionId,
4365
- type: raw.type,
4366
- body: raw.body,
4398
+ agentSessionId: raw.agentSessionId,
4399
+ content: raw.content,
4400
+ signal: raw.signal ?? null,
4367
4401
  ephemeral: raw.ephemeral
4368
4402
  };
4369
4403
  }
@@ -4519,13 +4553,10 @@ function createRootValue(ctx) {
4519
4553
  const session = await commands.createAgentSessionOnComment(parseAgentSessionOnCommentInput(input), actor);
4520
4554
  return payload({ agentSession: formatAgentSession(session) });
4521
4555
  },
4556
+ // `id` is non-null on the schema, as it is upstream — there is no longer an
4557
+ // `input.id` to fall back to (F-1176).
4522
4558
  agentSessionUpdate: ({ id, input }) => {
4523
- const parsed = parseAgentSessionUpdateInput(input);
4524
- const session = commands.updateAgentSession(String(id ?? parsed.id), {
4525
- status: parsed.status,
4526
- plan: parsed.plan,
4527
- externalUrls: parsed.externalUrls
4528
- }, actor);
4559
+ const session = commands.updateAgentSession(id, parseAgentSessionUpdateInput(input), actor);
4529
4560
  return payload({ agentSession: formatAgentSession(session) });
4530
4561
  },
4531
4562
  agentActivityCreate: async ({ input }) => {
@@ -4539,6 +4570,7 @@ var linearGraphQLSchema = buildSchema(`
4539
4570
  scalar PaginationOrderBy
4540
4571
  scalar DateTime
4541
4572
  scalar JSON
4573
+ scalar JSONObject
4542
4574
 
4543
4575
  type Query {
4544
4576
  viewer: User!
@@ -4591,7 +4623,7 @@ var linearGraphQLSchema = buildSchema(`
4591
4623
  webhookDelete(id: String!): DeletePayload!
4592
4624
  agentSessionCreateOnIssue(input: AgentSessionCreateOnIssue!): AgentSessionPayload!
4593
4625
  agentSessionCreateOnComment(input: AgentSessionCreateOnComment!): AgentSessionPayload!
4594
- agentSessionUpdate(id: String, input: AgentSessionUpdateInput!): AgentSessionPayload!
4626
+ agentSessionUpdate(id: String!, input: AgentSessionUpdateInput!): AgentSessionPayload!
4595
4627
  agentActivityCreate(input: AgentActivityCreateInput!): AgentActivityPayload!
4596
4628
  }
4597
4629
 
@@ -4854,15 +4886,29 @@ var linearGraphQLSchema = buildSchema(`
4854
4886
  activities(first: Int, after: String, last: Int, before: String): AgentActivityConnection!
4855
4887
  }
4856
4888
 
4889
+ """Linear's AgentActivitySignal, member-for-member (F-1176)."""
4890
+ enum AgentActivitySignal {
4891
+ stop
4892
+ continue
4893
+ auth
4894
+ select
4895
+ }
4896
+
4857
4897
  type AgentActivity {
4858
- id: String!
4859
- type: String!
4860
- body: String!
4898
+ id: ID!
4899
+ """
4900
+ Linear's AgentActivityContent union, carried as an opaque payload: a
4901
+ {type, body} object for five of the six members, {type, action, parameter}
4902
+ for the action member. The union itself is a scalar-level divergence,
4903
+ written up in REFERENCE-DIVERGENCES.md (F-1176).
4904
+ """
4905
+ content: JSON!
4906
+ signal: AgentActivitySignal
4861
4907
  ephemeral: Boolean!
4862
- createdAt: String!
4863
- updatedAt: String!
4864
- session: AgentSession!
4865
- user: User
4908
+ createdAt: DateTime!
4909
+ updatedAt: DateTime!
4910
+ agentSession: AgentSession!
4911
+ user: User!
4866
4912
  }
4867
4913
 
4868
4914
  type NodeRef {
@@ -5022,31 +5068,30 @@ var linearGraphQLSchema = buildSchema(`
5022
5068
  label: String!
5023
5069
  }
5024
5070
 
5071
+ """Linear's AgentSessionCreateOnIssue, minus the fields the twin does not model (F-1176)."""
5025
5072
  input AgentSessionCreateOnIssue {
5026
5073
  issueId: String!
5027
- appUserId: String
5028
- plan: String
5029
5074
  externalUrls: [AgentSessionExternalUrlInput!]
5030
5075
  }
5031
5076
 
5032
5077
  input AgentSessionCreateOnComment {
5033
5078
  commentId: String!
5034
- appUserId: String
5035
- plan: String
5036
5079
  externalUrls: [AgentSessionExternalUrlInput!]
5037
5080
  }
5038
5081
 
5082
+ """
5083
+ Linear declares no status and no id field here (F-1176). Status follows the
5084
+ agent's activities; id is the mutation's own non-null argument.
5085
+ """
5039
5086
  input AgentSessionUpdateInput {
5040
- id: String
5041
- status: AgentSessionStatus
5042
5087
  plan: String
5043
5088
  externalUrls: [AgentSessionExternalUrlInput!]
5044
5089
  }
5045
5090
 
5046
5091
  input AgentActivityCreateInput {
5047
- sessionId: String!
5048
- type: String!
5049
- body: String!
5092
+ agentSessionId: String!
5093
+ content: JSONObject!
5094
+ signal: AgentActivitySignal
5050
5095
  ephemeral: Boolean
5051
5096
  }
5052
5097
  `);
@@ -0,0 +1,5 @@
1
+ export { UnsupportedTwinError, bootTwin } from './chunk-IWTB3NN5.js';
2
+ export { STRIPE_LOCAL_ACCOUNT_ID } from './chunk-3JUWDIJ2.js';
3
+ import './chunk-TV5S6WQV.js';
4
+ import './chunk-VBATFCWR.js';
5
+ import './chunk-SG6ZTIMT.js';
@@ -1,5 +1,5 @@
1
- import { bootTwin } from './chunk-MN23RUGG.js';
2
- import { isTwinName, TWIN_NAMES, defaultPortFor, TWIN_REGISTRY } from './chunk-GPLI6UFI.js';
1
+ import { bootTwin } from './chunk-IWTB3NN5.js';
2
+ import { isTwinName, TWIN_NAMES, defaultPortFor, TWIN_REGISTRY } from './chunk-3JUWDIJ2.js';
3
3
  import './chunk-TV5S6WQV.js';
4
4
  import './chunk-VBATFCWR.js';
5
5
  import './chunk-SG6ZTIMT.js';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pome-sh/cli",
3
- "version": "0.21.16",
3
+ "version": "0.21.17",
4
4
  "description": "Digital-twin testing for AI agents — run tasks against resettable local or hosted twins and record tool-call traces for evaluation on pome.sh.",
5
5
  "keywords": [
6
6
  "ai",
@@ -1,5 +0,0 @@
1
- export { UnsupportedTwinError, bootTwin } from './chunk-MN23RUGG.js';
2
- export { STRIPE_LOCAL_ACCOUNT_ID } from './chunk-GPLI6UFI.js';
3
- import './chunk-TV5S6WQV.js';
4
- import './chunk-VBATFCWR.js';
5
- import './chunk-SG6ZTIMT.js';