@pome-sh/cli 0.27.0 → 0.29.0
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/dist/build-info.json +3 -3
- package/dist/{checks-QM7QOJ6U.js → checks-JR4OEKZM.js} +3 -3
- package/dist/chunk-B7PA7UDX.js +105 -0
- package/dist/{chunk-BZO3YCJS.js → chunk-E7WJ3SRP.js} +37 -2
- package/dist/{chunk-N74LP4QH.js → chunk-IYMDPMMZ.js} +2 -2
- package/dist/{chunk-MQE6DKIK.js → chunk-MRCYOSBM.js} +24 -5
- package/dist/{chunk-IK2F7ZA3.js → chunk-S6JLWI4S.js} +1 -1
- package/dist/{chunk-JE4H5ODK.js → chunk-SRG22BIH.js} +12 -9
- package/dist/{chunk-CXGMLUZ4.js → chunk-VO2XUPZC.js} +1 -1
- package/dist/{chunk-CTA54N4K.js → chunk-XAQGX7K2.js} +23 -6
- package/dist/{runDemo-O67ASC54.js → runDemo-GBPVF5AA.js} +6 -6
- package/dist/{runTrialGroup-V3HB57YI.js → runTrialGroup-XEBG225L.js} +7 -6
- package/dist/{seed-3ZTWKLBE.js → seed-F7RNI55S.js} +1 -1
- package/dist/src/cli/main.js +40 -20
- package/dist/{src-JRBHNT4Y.js → src-5YCI6VIR.js} +2 -2
- package/dist/twinHarness-CUVRO5IV.js +6 -0
- package/dist/twinSeed-MOQXJDEG.js +48 -0
- package/dist/{twinStart-PDL53BY5.js → twinStart-ZDWFU6M4.js} +46 -42
- package/package.json +1 -1
- package/dist/twinHarness-YOVJR72F.js +0 -6
- /package/dist/{chunk-G6GOCYIT.js → chunk-Q5NBPR57.js} +0 -0
package/dist/build-info.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"package": "pome-sh",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"git_sha": "
|
|
5
|
-
"build_time": "2026-08-
|
|
3
|
+
"version": "0.29.0",
|
|
4
|
+
"git_sha": "b065b0336a80c35d63c53bed262be6b037bfec76",
|
|
5
|
+
"build_time": "2026-08-26T21:23:55.631Z"
|
|
6
6
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { findManifestPath, readManifest } from './chunk-
|
|
1
|
+
import { findManifestPath, readManifest } from './chunk-VO2XUPZC.js';
|
|
2
2
|
import { getAvailablePort } from './chunk-XDU6TD4O.js';
|
|
3
|
-
import './chunk-
|
|
3
|
+
import './chunk-E7WJ3SRP.js';
|
|
4
4
|
import { buildEgressAllowlist } from './chunk-CBFKZZBR.js';
|
|
5
5
|
import './chunk-6KJC4BTO.js';
|
|
6
6
|
import './chunk-SG6ZTIMT.js';
|
|
@@ -183,7 +183,7 @@ async function checkTwinReachable(_configDir) {
|
|
|
183
183
|
});
|
|
184
184
|
let harness;
|
|
185
185
|
try {
|
|
186
|
-
const { bootTwin } = await import('./twinHarness-
|
|
186
|
+
const { bootTwin } = await import('./twinHarness-CUVRO5IV.js');
|
|
187
187
|
harness = await bootTwin({
|
|
188
188
|
twin: "github",
|
|
189
189
|
seedState: void 0,
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import { isTwinName, TWIN_REGISTRY, TWIN_NAMES } from './chunk-SRG22BIH.js';
|
|
2
|
+
import { readFileSync } from 'node:fs';
|
|
3
|
+
import { parse } from 'yaml';
|
|
4
|
+
|
|
5
|
+
function readSeedFileText(path, flag = "--seed") {
|
|
6
|
+
try {
|
|
7
|
+
return readFileSync(path, "utf8");
|
|
8
|
+
} catch (err) {
|
|
9
|
+
throw new Error(`${flag}: cannot read ${path}: ${err.message}`);
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
function parseSeedFileText(raw, origin) {
|
|
13
|
+
let parsed;
|
|
14
|
+
try {
|
|
15
|
+
parsed = parse(raw);
|
|
16
|
+
} catch (err) {
|
|
17
|
+
throw new Error(`${origin} is not valid JSON or YAML: ${err.message}`);
|
|
18
|
+
}
|
|
19
|
+
if (Array.isArray(parsed)) {
|
|
20
|
+
throw new Error(`${origin} is not a seed file: its top level is an array, not an object.`);
|
|
21
|
+
}
|
|
22
|
+
if (parsed === null || typeof parsed !== "object") {
|
|
23
|
+
throw new Error(
|
|
24
|
+
`${origin} is not a seed file: its top level is ${parsed === null ? "null" : typeof parsed}, not an object.`
|
|
25
|
+
);
|
|
26
|
+
}
|
|
27
|
+
const { _meta, ...rest } = parsed;
|
|
28
|
+
const keys = Object.keys(rest);
|
|
29
|
+
const twinKeys = keys.filter((key) => isTwinName(key));
|
|
30
|
+
if (twinKeys.length === 0) return { shape: "flat", seed: rest };
|
|
31
|
+
if (twinKeys.length !== keys.length) {
|
|
32
|
+
const others = keys.filter((key) => !isTwinName(key));
|
|
33
|
+
throw new Error(
|
|
34
|
+
`${origin} mixes twin ids (${twinKeys.join(", ")}) with other keys (${others.join(", ")}). A seed file is either one twin's flat seed or a per-twin envelope { <twin>: <seed> }, not both.`
|
|
35
|
+
);
|
|
36
|
+
}
|
|
37
|
+
return { shape: "envelope", byTwin: rest };
|
|
38
|
+
}
|
|
39
|
+
function twinsNamedBy(file) {
|
|
40
|
+
if (file.shape === "flat") return [];
|
|
41
|
+
return Object.keys(file.byTwin).filter((key) => isTwinName(key));
|
|
42
|
+
}
|
|
43
|
+
function soleTwinOf(file) {
|
|
44
|
+
const named = twinsNamedBy(file);
|
|
45
|
+
return named.length === 1 ? named[0] : void 0;
|
|
46
|
+
}
|
|
47
|
+
async function seedFieldsFor(twin) {
|
|
48
|
+
return TWIN_REGISTRY[twin].seedFields();
|
|
49
|
+
}
|
|
50
|
+
async function seedForTwin(file, twin, origin, opts = {}) {
|
|
51
|
+
if (file.shape === "flat") return parseWith(twin, file.seed, origin, file);
|
|
52
|
+
assertOnlyAsked(file, opts.asked, origin);
|
|
53
|
+
const named = twinsNamedBy(file);
|
|
54
|
+
if (!(twin in file.byTwin)) {
|
|
55
|
+
throw new Error(
|
|
56
|
+
`${origin} declares no ${twin} seed (it names ${named.join(", ")}). Add a "${twin}" key, or start the twin it names.`
|
|
57
|
+
);
|
|
58
|
+
}
|
|
59
|
+
return parseWith(twin, file.byTwin[twin], `${origin} ("${twin}")`, file);
|
|
60
|
+
}
|
|
61
|
+
async function seedsForTwins(file, twins, origin) {
|
|
62
|
+
if (file.shape === "flat") {
|
|
63
|
+
if (twins.length !== 1) {
|
|
64
|
+
throw new Error(
|
|
65
|
+
`${origin} is a flat seed and this sandbox has ${twins.length} twins (${twins.join(", ")}), so nothing says which one it is for. Wrap it in a per-twin envelope: { "${twins[0] ?? "<twin>"}": { \u2026 } }.`
|
|
66
|
+
);
|
|
67
|
+
}
|
|
68
|
+
return { [twins[0]]: await parseWith(twins[0], file.seed, origin, file) };
|
|
69
|
+
}
|
|
70
|
+
assertOnlyAsked(file, twins, origin);
|
|
71
|
+
const out = {};
|
|
72
|
+
for (const twin of twins) {
|
|
73
|
+
if (twin in file.byTwin) {
|
|
74
|
+
out[twin] = await parseWith(twin, file.byTwin[twin], `${origin} ("${twin}")`, file);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
return out;
|
|
78
|
+
}
|
|
79
|
+
function assertOnlyAsked(file, asked, origin) {
|
|
80
|
+
if (asked === void 0 || file.shape !== "envelope") return;
|
|
81
|
+
const extras = twinsNamedBy(file).filter((twin) => !asked.includes(twin));
|
|
82
|
+
if (extras.length === 0) return;
|
|
83
|
+
throw new Error(
|
|
84
|
+
`${origin} names ${extras.join(", ")}, which this command was not asked for (asked: ${asked.length ? asked.join(", ") : "none"}). Add --twin for each, or remove them from the file.`
|
|
85
|
+
);
|
|
86
|
+
}
|
|
87
|
+
async function parseWith(twin, seed, where, file) {
|
|
88
|
+
try {
|
|
89
|
+
return await TWIN_REGISTRY[twin].parseSeed(seed);
|
|
90
|
+
} catch (err) {
|
|
91
|
+
const hint = file.shape === "flat" ? await notSeedFieldsHint(twin, file.seed) : "";
|
|
92
|
+
throw new Error(`${where} is not a seed this twin can boot: ${err.message}${hint}`);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
async function notSeedFieldsHint(twin, seed) {
|
|
96
|
+
if (seed === null || typeof seed !== "object" || Array.isArray(seed)) return "";
|
|
97
|
+
const keys = Object.keys(seed);
|
|
98
|
+
if (keys.length === 0) return "";
|
|
99
|
+
const fields = new Set(await seedFieldsFor(twin));
|
|
100
|
+
if (keys.some((key) => fields.has(key))) return "";
|
|
101
|
+
return `
|
|
102
|
+
None of its top-level keys (${keys.join(", ")}) is a field of the ${twin} seed. If this file is a per-twin envelope, its keys must be twin ids: ${TWIN_NAMES.join(", ")}.`;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
export { parseSeedFileText, readSeedFileText, seedForTwin, seedsForTwins, soleTwinOf, twinsNamedBy };
|
|
@@ -91,8 +91,40 @@ var baseCriterionResultSchema = z.object({
|
|
|
91
91
|
passed: z.boolean(),
|
|
92
92
|
skipped: z.boolean(),
|
|
93
93
|
// true if [code] fell back to [model] but the judge was unreachable, etc.
|
|
94
|
-
reason: z.string()
|
|
94
|
+
reason: z.string(),
|
|
95
95
|
// human-readable evidence
|
|
96
|
+
// Why this row is out of the denominator, when `skipped` alone is too coarse.
|
|
97
|
+
// The two values that carry meaning here are `ADVISORY_SCORE_STATE` and
|
|
98
|
+
// `ABSTAINED_SCORE_STATE` (`@pome-sh/wire/run-completeness`), which the
|
|
99
|
+
// narrator stamps on a `[model]` row it read but had no authority to score.
|
|
100
|
+
//
|
|
101
|
+
// NOT NAMED `outcome`: `hosted/evalResultView.ts`'s display model has
|
|
102
|
+
// reserved that key on this same object for a disjoint vocabulary
|
|
103
|
+
// (`passed | failed | skipped | errored`) since long before the narrator, and
|
|
104
|
+
// reserved it for the CLOUD to fill. A cloud writing `advisory` into it would
|
|
105
|
+
// hand `outcomeOf` a value outside its own union and render an advisory row
|
|
106
|
+
// with the skipped glyph.
|
|
107
|
+
//
|
|
108
|
+
// ON THE BASE AND NOT ON ONE ARM, for the mirror image of the reason the arm
|
|
109
|
+
// order below is what it is: an advisory row carries no `confidence` /
|
|
110
|
+
// `judge_model`, so it fails the probabilistic arm and lands on the
|
|
111
|
+
// DETERMINISTIC one — whose `.extend({})` is a plain `z.object` and would
|
|
112
|
+
// strip an unknown key. Declared on one arm, the state would be discarded
|
|
113
|
+
// before any consumer could read it, and the run would keep reading
|
|
114
|
+
// INCOMPLETE with the exemption sitting there correct and dead.
|
|
115
|
+
//
|
|
116
|
+
// `z.string()` AND NOT THE CLOSED ENUM pome-cloud declares for the same
|
|
117
|
+
// field, because the two sides of it have opposite jobs. pome-cloud PRODUCES
|
|
118
|
+
// it and validates what it serves; the CLI CONSUMES it, and
|
|
119
|
+
// `finalizeResponseSchema` is deliberately a tolerant reader (its own comment
|
|
120
|
+
// says so: cloud may emit additive keys "that older/newer CLIs strip rather
|
|
121
|
+
// than reject"). A closed enum here would turn a cloud that adds a third
|
|
122
|
+
// score state into a hard parse failure of the ENTIRE /finalize response —
|
|
123
|
+
// an unreadable run instead of an unrecognised field. The closed vocabulary
|
|
124
|
+
// is applied by the PREDICATE that reads it (`isNarrated`), exactly as
|
|
125
|
+
// `reason` is a plain string and `PRE_SATISFIED_REASON` is a comparison, so
|
|
126
|
+
// an unrecognised spelling is not exempted from anything.
|
|
127
|
+
score_state: z.string().optional()
|
|
96
128
|
});
|
|
97
129
|
var deterministicCriterionResultSchema = baseCriterionResultSchema.extend({
|
|
98
130
|
// [code] adds nothing further; criterion.type === "code" identifies it.
|
|
@@ -704,6 +736,9 @@ z.record(
|
|
|
704
736
|
z.string(),
|
|
705
737
|
z.record(z.string(), z.unknown())
|
|
706
738
|
);
|
|
739
|
+
function isMultiTwinSeedEnvelope(twins) {
|
|
740
|
+
return twins.length > 1;
|
|
741
|
+
}
|
|
707
742
|
var taskClassSchema = z.enum(["conformance", "restraint", "adversarial"]);
|
|
708
743
|
var taskConfigSchema = z.object({
|
|
709
744
|
twins: z.array(z.string()).default(["github"]),
|
|
@@ -1232,4 +1267,4 @@ function exitCodeFor(err) {
|
|
|
1232
1267
|
return 2;
|
|
1233
1268
|
}
|
|
1234
1269
|
|
|
1235
|
-
export { HostedAuthError, HostedDiscardRefusedError, HostedOrchError, HostedQuotaError, HostedTrialError, HostedUsageError, MOUNTED_TWINS, SLUG_RE, agentResponseSchema, createEvalSessionResponseSchema, createSessionResponseSchema, criterionSchema, deriveAgentSlug, exitCodeFor, finalizeResponseSchema, manifestSchema, sessionPublicSchema, submitResultResponseSchema };
|
|
1270
|
+
export { HostedAuthError, HostedDiscardRefusedError, HostedOrchError, HostedQuotaError, HostedTrialError, HostedUsageError, MOUNTED_TWINS, SLUG_RE, agentResponseSchema, createEvalSessionResponseSchema, createSessionResponseSchema, criterionSchema, deriveAgentSlug, exitCodeFor, finalizeResponseSchema, isMultiTwinSeedEnvelope, manifestSchema, sessionPublicSchema, submitResultResponseSchema };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { parseTaskFile, seedStateForTwin, runAgentCommand, writeRunArtifactsCore } from './chunk-
|
|
2
|
-
import { createRecorder, bootTwin } from './chunk-
|
|
1
|
+
import { parseTaskFile, seedStateForTwin, runAgentCommand, writeRunArtifactsCore } from './chunk-XAQGX7K2.js';
|
|
2
|
+
import { createRecorder, bootTwin } from './chunk-S6JLWI4S.js';
|
|
3
3
|
import { getAvailablePort } from './chunk-XDU6TD4O.js';
|
|
4
4
|
import { buildEgressAllowlist, readBlockedEgress } from './chunk-CBFKZZBR.js';
|
|
5
5
|
import { eventSchema } from './chunk-6KJC4BTO.js';
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import { createHostedClient, perTwinReturnedByCloud, parseTaskFile, runAgentCommand, writeRunArtifactsCore, toTwinHttpEvent, redactJsonl, uploadRunBlobs, scoreFromFinalizeResponse, scoreStatus, evaluationCounts } from './chunk-
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
1
|
+
import { createHostedClient, perTwinReturnedByCloud, parseTaskFile, runAgentCommand, writeRunArtifactsCore, toTwinHttpEvent, redactJsonl, uploadRunBlobs, scoreFromFinalizeResponse, scoreStatus, evaluationCounts } from './chunk-XAQGX7K2.js';
|
|
2
|
+
import { readSeedFileText, parseSeedFileText, soleTwinOf, seedsForTwins } from './chunk-B7PA7UDX.js';
|
|
3
|
+
import { readManifest, normalizeManifestTwins } from './chunk-VO2XUPZC.js';
|
|
4
|
+
import { MOUNTED_TWINS, HostedAuthError, HostedDiscardRefusedError, HostedQuotaError, HostedOrchError, HostedTrialError, agentResponseSchema, isMultiTwinSeedEnvelope } from './chunk-E7WJ3SRP.js';
|
|
4
5
|
import { redactSecrets, redactEvent } from './chunk-SG6ZTIMT.js';
|
|
5
6
|
import { randomUUID, createHash } from 'node:crypto';
|
|
6
7
|
import { rm, readFile, stat, mkdir, writeFile, chmod, mkdtemp, readdir, rename } from 'node:fs/promises';
|
|
@@ -697,8 +698,22 @@ function normalizeSessionTwins(raw) {
|
|
|
697
698
|
}
|
|
698
699
|
return deduped;
|
|
699
700
|
}
|
|
701
|
+
async function resolveSessionSeed(seedPath, requestedTwins) {
|
|
702
|
+
const raw = readSeedFileText(seedPath, "pome sandbox create --seed");
|
|
703
|
+
const origin = `--seed ${seedPath}`;
|
|
704
|
+
const file = parseSeedFileText(raw, origin);
|
|
705
|
+
const twins = normalizeSessionTwins(
|
|
706
|
+
requestedTwins.length > 0 ? requestedTwins : [soleTwinOf(file) ?? ""].filter(Boolean)
|
|
707
|
+
);
|
|
708
|
+
const byTwin = await seedsForTwins(file, twins, origin);
|
|
709
|
+
return {
|
|
710
|
+
twins,
|
|
711
|
+
seed: isMultiTwinSeedEnvelope(twins) ? byTwin : byTwin[twins[0]]
|
|
712
|
+
};
|
|
713
|
+
}
|
|
700
714
|
async function runSessionCreate(opts) {
|
|
701
|
-
const
|
|
715
|
+
const resolvedSeed = opts.seedPath === void 0 ? void 0 : await resolveSessionSeed(opts.seedPath, opts.twins);
|
|
716
|
+
const twins = resolvedSeed?.twins ?? normalizeSessionTwins(opts.twins);
|
|
702
717
|
const creds = await resolveCredentials({ apiBaseUrl: opts.apiBaseUrl });
|
|
703
718
|
const client = createHostedClient({
|
|
704
719
|
baseUrl: creds.apiBaseUrl,
|
|
@@ -713,7 +728,8 @@ async function runSessionCreate(opts) {
|
|
|
713
728
|
taskSource: "# ..\n",
|
|
714
729
|
idempotencyKey: randomUUID(),
|
|
715
730
|
agentId: identity.agentId,
|
|
716
|
-
agentVersion: identity.agentVersion
|
|
731
|
+
agentVersion: identity.agentVersion,
|
|
732
|
+
...resolvedSeed ? { seed: resolvedSeed.seed } : {}
|
|
717
733
|
});
|
|
718
734
|
if (opts.secretsFile) {
|
|
719
735
|
await writeSecretsFile(opts.secretsFile, formatEnvExport(session, twins));
|
|
@@ -736,6 +752,9 @@ async function runSessionCreate(opts) {
|
|
|
736
752
|
}
|
|
737
753
|
console.error(`Session: ${session.session_id}`);
|
|
738
754
|
console.error(`Expires: ${session.expires_at}`);
|
|
755
|
+
if (opts.seedPath !== void 0) {
|
|
756
|
+
console.error(`Seed: ${opts.seedPath} (replaces the default for ${twins.join(", ")}).`);
|
|
757
|
+
}
|
|
739
758
|
let printedAny = false;
|
|
740
759
|
const mcpFromCloud = perTwinReturnedByCloud(session);
|
|
741
760
|
for (const twin of twins) {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { TWIN_NAMES, isTwinName, TWIN_REGISTRY } from './chunk-
|
|
1
|
+
import { TWIN_NAMES, isTwinName, TWIN_REGISTRY } from './chunk-SRG22BIH.js';
|
|
2
2
|
import { createFileBackedRecorderStore, createRecorderStore } from './chunk-E665XWYU.js';
|
|
3
3
|
|
|
4
4
|
// src/recorder/recorder.ts
|
|
@@ -30,10 +30,9 @@ var TWIN_REGISTRY = {
|
|
|
30
30
|
envName: "GITHUB",
|
|
31
31
|
defaultPort: 3333,
|
|
32
32
|
version: package_default.version,
|
|
33
|
-
|
|
34
|
-
// when no seed is supplied — the pre-existing standalone behavior.
|
|
35
|
-
defaultSeed: async () => void 0,
|
|
33
|
+
defaultSeed: async () => (await import('./seed-BG5HMSBM.js')).defaultSeedState(),
|
|
36
34
|
parseSeed: async (input) => (await import('./seed-BG5HMSBM.js')).parseSeed(input),
|
|
35
|
+
seedFields: async () => Object.keys((await import('./seed-BG5HMSBM.js')).seedSchema.shape),
|
|
37
36
|
async boot({ seedState, runId, recorder }) {
|
|
38
37
|
const {
|
|
39
38
|
createGitHubCloneApp,
|
|
@@ -60,8 +59,9 @@ var TWIN_REGISTRY = {
|
|
|
60
59
|
envName: "SLACK",
|
|
61
60
|
defaultPort: 3333,
|
|
62
61
|
version: package_default2.version,
|
|
63
|
-
defaultSeed: async () => (await import('./
|
|
62
|
+
defaultSeed: async () => (await import('./seed-IIMBJHAJ.js')).defaultSeedState(),
|
|
64
63
|
parseSeed: async (input) => (await import('./seed-IIMBJHAJ.js')).parseSeed(input),
|
|
64
|
+
seedFields: async () => Object.keys((await import('./seed-IIMBJHAJ.js')).seedSchema.shape),
|
|
65
65
|
async boot({ seedState, runId, recorder }) {
|
|
66
66
|
const { createSlackTwinApp, openSlackTwinDatabase, SlackDomain } = await import('./src-SKCWAMVQ.js');
|
|
67
67
|
const db = openSlackTwinDatabase(":memory:");
|
|
@@ -86,8 +86,9 @@ var TWIN_REGISTRY = {
|
|
|
86
86
|
envName: "STRIPE",
|
|
87
87
|
defaultPort: 3333,
|
|
88
88
|
version: package_default3.version,
|
|
89
|
-
defaultSeed: async () => (await import('./
|
|
89
|
+
defaultSeed: async () => (await import('./seed-YWDTT2WL.js')).defaultSeed(),
|
|
90
90
|
parseSeed: async (input) => (await import('./seed-YWDTT2WL.js')).parseSeed(input),
|
|
91
|
+
seedFields: async () => Object.keys((await import('./seed-YWDTT2WL.js')).seedSchema.shape),
|
|
91
92
|
async boot({ seedState, runId, recorder, twinBaseUrl }) {
|
|
92
93
|
const stripeTwin = await import('./src-PW7U25ZX.js');
|
|
93
94
|
const { createApp } = await import('./server-DMLORMOV.js');
|
|
@@ -131,8 +132,9 @@ var TWIN_REGISTRY = {
|
|
|
131
132
|
portEnvName: "GMAIL_TWIN_PORT",
|
|
132
133
|
tokenEnvName: "POME_GMAIL_TOKEN",
|
|
133
134
|
version: package_default4.version,
|
|
134
|
-
defaultSeed: async () => (await import('./
|
|
135
|
+
defaultSeed: async () => (await import('./seed-NR6RUKXV.js')).defaultSeedState(),
|
|
135
136
|
parseSeed: async (input) => (await import('./seed-NR6RUKXV.js')).parseSeed(input),
|
|
137
|
+
seedFields: async () => Object.keys((await import('./seed-NR6RUKXV.js')).gmailSeedSchema.shape),
|
|
136
138
|
async boot({ seedState, runId, recorder }) {
|
|
137
139
|
const { createGmailTwinApp, GmailDomain, openGmailTwinDatabase, parseSeed } = await import('./src-KSLAF3I4.js');
|
|
138
140
|
const db = openGmailTwinDatabase(":memory:");
|
|
@@ -153,8 +155,9 @@ var TWIN_REGISTRY = {
|
|
|
153
155
|
portEnvName: "LINEAR_TWIN_PORT",
|
|
154
156
|
tokenEnvName: "POME_LINEAR_TOKEN",
|
|
155
157
|
version: package_default5.version,
|
|
156
|
-
defaultSeed: async () => (await import('./
|
|
157
|
-
parseSeed: async (input) => (await import('./seed-
|
|
158
|
+
defaultSeed: async () => (await import('./seed-F7RNI55S.js')).defaultSeedState(),
|
|
159
|
+
parseSeed: async (input) => (await import('./seed-F7RNI55S.js')).parseSeed(input),
|
|
160
|
+
seedFields: async () => Object.keys((await import('./seed-F7RNI55S.js')).linearSeedSchema.shape),
|
|
158
161
|
async boot({ seedState, runId, recorder }) {
|
|
159
162
|
const {
|
|
160
163
|
createLinearTwinApp,
|
|
@@ -162,7 +165,7 @@ var TWIN_REGISTRY = {
|
|
|
162
165
|
LinearDomain,
|
|
163
166
|
openLinearTwinDatabase,
|
|
164
167
|
parseSeed
|
|
165
|
-
} = await import('./src-
|
|
168
|
+
} = await import('./src-5YCI6VIR.js');
|
|
166
169
|
const db = openLinearTwinDatabase(":memory:");
|
|
167
170
|
const seed = parseSeed(seedState);
|
|
168
171
|
const domain = new LinearDomain(db);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { HostedOrchError, manifestSchema, deriveAgentSlug, SLUG_RE } from './chunk-
|
|
1
|
+
import { HostedOrchError, manifestSchema, deriveAgentSlug, SLUG_RE } from './chunk-E7WJ3SRP.js';
|
|
2
2
|
import { readFile, writeFile } from 'node:fs/promises';
|
|
3
3
|
import { resolve, join, dirname } from 'node:path';
|
|
4
4
|
import { stringify, parse } from 'yaml';
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { gmailSeedSchema, defaultSeedState } from './chunk-3T5XN64P.js';
|
|
2
|
-
import { linearSeedSchema, defaultSeedState as defaultSeedState$1 } from './chunk-
|
|
3
|
-
import { isTwinName, TWIN_REGISTRY } from './chunk-
|
|
4
|
-
import { criterionSchema, finalizeResponseSchema, HostedDiscardRefusedError, HostedOrchError, HostedAuthError, HostedQuotaError, submitResultResponseSchema, createEvalSessionResponseSchema, createSessionResponseSchema, sessionPublicSchema } from './chunk-
|
|
2
|
+
import { linearSeedSchema, defaultSeedState as defaultSeedState$1 } from './chunk-Q5NBPR57.js';
|
|
3
|
+
import { isTwinName, TWIN_REGISTRY } from './chunk-SRG22BIH.js';
|
|
4
|
+
import { criterionSchema, finalizeResponseSchema, HostedDiscardRefusedError, HostedOrchError, HostedAuthError, HostedQuotaError, submitResultResponseSchema, createEvalSessionResponseSchema, createSessionResponseSchema, sessionPublicSchema } from './chunk-E7WJ3SRP.js';
|
|
5
5
|
import { seedSchema, parseSeed, defaultSeedState as defaultSeedState$2 } from './chunk-HJX25USP.js';
|
|
6
6
|
import { toTwinHttpEventRow } from './chunk-E665XWYU.js';
|
|
7
7
|
import { redactEvent, redactSecrets } from './chunk-SG6ZTIMT.js';
|
|
@@ -1255,6 +1255,8 @@ function normalizeAgentSdk(value) {
|
|
|
1255
1255
|
|
|
1256
1256
|
// ../packages/wire/dist/run-completeness.js
|
|
1257
1257
|
var PRE_SATISFIED_REASON = "already_true_in_seed";
|
|
1258
|
+
var ADVISORY_SCORE_STATE = "advisory";
|
|
1259
|
+
var ABSTAINED_SCORE_STATE = "abstained";
|
|
1258
1260
|
|
|
1259
1261
|
// src/hosted/evalResultView.ts
|
|
1260
1262
|
function outcomeOf(result) {
|
|
@@ -1265,6 +1267,9 @@ function outcomeOf(result) {
|
|
|
1265
1267
|
function isPreSatisfied(result) {
|
|
1266
1268
|
return result.skipped && result.reason === PRE_SATISFIED_REASON;
|
|
1267
1269
|
}
|
|
1270
|
+
function isNarrated(result) {
|
|
1271
|
+
return result.skipped && (result.score_state === ADVISORY_SCORE_STATE || result.score_state === ABSTAINED_SCORE_STATE);
|
|
1272
|
+
}
|
|
1268
1273
|
function scoreStatus(score, passThreshold) {
|
|
1269
1274
|
if (!score.evaluated || !score.can_pass) return "incomplete";
|
|
1270
1275
|
return score.satisfaction >= passThreshold ? "pass" : "fail";
|
|
@@ -1296,12 +1301,16 @@ function criteriaWord(n) {
|
|
|
1296
1301
|
}
|
|
1297
1302
|
function evaluationCounts(score) {
|
|
1298
1303
|
const evaluated = score.total_required;
|
|
1299
|
-
const
|
|
1304
|
+
const exempt = score.preSatisfied + score.advisory + score.abstained;
|
|
1305
|
+
const notEvaluated = score.skipped + score.errored - exempt;
|
|
1300
1306
|
return {
|
|
1301
1307
|
evaluated,
|
|
1302
1308
|
notEvaluated,
|
|
1303
1309
|
preSatisfied: score.preSatisfied,
|
|
1304
|
-
total
|
|
1310
|
+
// `total` counts every exemption, not just `preSatisfied`, so it still
|
|
1311
|
+
// names every criterion the run recorded — the reason `outcomeOf` keeps
|
|
1312
|
+
// narrator rows inside `skipped` rather than returning their state raw.
|
|
1313
|
+
total: evaluated + notEvaluated + exempt
|
|
1305
1314
|
};
|
|
1306
1315
|
}
|
|
1307
1316
|
function scoreCountsSummary(score) {
|
|
@@ -1486,8 +1495,14 @@ function scoreFromFinalizeResponse(finalized) {
|
|
|
1486
1495
|
const preSatisfied = results.filter(
|
|
1487
1496
|
(r) => outcomeOf(r) === "skipped" && isPreSatisfied(r)
|
|
1488
1497
|
).length;
|
|
1498
|
+
const advisory = results.filter(
|
|
1499
|
+
(r) => isNarrated(r) && !isPreSatisfied(r) && r.score_state === ADVISORY_SCORE_STATE
|
|
1500
|
+
).length;
|
|
1501
|
+
const abstained = results.filter(
|
|
1502
|
+
(r) => isNarrated(r) && !isPreSatisfied(r) && r.score_state === ABSTAINED_SCORE_STATE
|
|
1503
|
+
).length;
|
|
1489
1504
|
const totalRequired = passed + failed;
|
|
1490
|
-
const unresolvedAbstentions = skipped - preSatisfied + errored;
|
|
1505
|
+
const unresolvedAbstentions = skipped - preSatisfied - advisory - abstained + errored;
|
|
1491
1506
|
return {
|
|
1492
1507
|
satisfaction: finalized.score,
|
|
1493
1508
|
passed,
|
|
@@ -1495,6 +1510,8 @@ function scoreFromFinalizeResponse(finalized) {
|
|
|
1495
1510
|
skipped,
|
|
1496
1511
|
errored,
|
|
1497
1512
|
preSatisfied,
|
|
1513
|
+
advisory,
|
|
1514
|
+
abstained,
|
|
1498
1515
|
total_required: totalRequired,
|
|
1499
1516
|
evaluated: hasCriteriaResults ? totalRequired > 0 : true,
|
|
1500
1517
|
can_pass: hasCriteriaResults ? totalRequired > 0 && unresolvedAbstentions === 0 : true,
|
|
@@ -1,14 +1,14 @@
|
|
|
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-
|
|
4
|
-
import { createHostedClient, parseTaskFile, uploadRunBlobs, scoreFromFinalizeResponse, scoreStatus, outcomeOf } from './chunk-
|
|
3
|
+
import { runTask, demoTaskPath, DEMO_TASK_NAME, DEMO_REPO } from './chunk-IYMDPMMZ.js';
|
|
4
|
+
import { createHostedClient, parseTaskFile, uploadRunBlobs, scoreFromFinalizeResponse, scoreStatus, outcomeOf } from './chunk-XAQGX7K2.js';
|
|
5
5
|
import './chunk-NW7HGA2K.js';
|
|
6
6
|
import './chunk-3T5XN64P.js';
|
|
7
|
-
import './chunk-
|
|
8
|
-
import { bootTwin } from './chunk-
|
|
9
|
-
import './chunk-
|
|
7
|
+
import './chunk-Q5NBPR57.js';
|
|
8
|
+
import { bootTwin } from './chunk-S6JLWI4S.js';
|
|
9
|
+
import './chunk-SRG22BIH.js';
|
|
10
10
|
import { getAvailablePort } from './chunk-XDU6TD4O.js';
|
|
11
|
-
import { HostedQuotaError, HostedOrchError } from './chunk-
|
|
11
|
+
import { HostedQuotaError, HostedOrchError } from './chunk-E7WJ3SRP.js';
|
|
12
12
|
import './chunk-CBFKZZBR.js';
|
|
13
13
|
import './chunk-HJX25USP.js';
|
|
14
14
|
import './chunk-E665XWYU.js';
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import { newGroupId, criterionPhrase } from './chunk-RGZBC7NF.js';
|
|
2
|
-
import { runTaskHosted, resolveRunAgentIdentity } from './chunk-
|
|
3
|
-
import { createHostedClient, parseTaskFile, outcomeOf } from './chunk-
|
|
2
|
+
import { runTaskHosted, resolveRunAgentIdentity } from './chunk-MRCYOSBM.js';
|
|
3
|
+
import { createHostedClient, parseTaskFile, outcomeOf } from './chunk-XAQGX7K2.js';
|
|
4
|
+
import './chunk-B7PA7UDX.js';
|
|
4
5
|
import './chunk-NW7HGA2K.js';
|
|
5
6
|
import './chunk-3T5XN64P.js';
|
|
6
|
-
import './chunk-
|
|
7
|
-
import './chunk-
|
|
8
|
-
import './chunk-
|
|
9
|
-
import { HostedQuotaError, HostedTrialError } from './chunk-
|
|
7
|
+
import './chunk-Q5NBPR57.js';
|
|
8
|
+
import './chunk-SRG22BIH.js';
|
|
9
|
+
import './chunk-VO2XUPZC.js';
|
|
10
|
+
import { HostedQuotaError, HostedTrialError } from './chunk-E7WJ3SRP.js';
|
|
10
11
|
import './chunk-HJX25USP.js';
|
|
11
12
|
import './chunk-E665XWYU.js';
|
|
12
13
|
import './chunk-6KJC4BTO.js';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export { defaultSeedState, linearSeedSchema, loadSeedFromEnv, parseSeed } from './chunk-
|
|
1
|
+
export { defaultSeedState, linearSeedSchema, loadSeedFromEnv, parseSeed } from './chunk-Q5NBPR57.js';
|
package/dist/src/cli/main.js
CHANGED
|
@@ -1,17 +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, runTaskHosted, discoverRunSet, VERDICT_ARTIFACT_VERSION, persistCredentialsAfterLogin, DEFAULT_DOCS_SITE_ORIGIN, resolveSeams, resolveCachedAgentId, readLinkCache, postAgentResolver, writeLinkCache, ensurePomeGitignored } from '../../chunk-
|
|
3
|
-
import { assetPath, runTask, resolvePackageRoot, DEMO_TASK_NAME, demoTaskPath } from '../../chunk-
|
|
4
|
-
import { parseTaskFile, scoreStatus, runScoreLine, readLatestRun, readMetaSummary, outcomeOf, readConfigTwins, scoreCountsSummary, markerFor, criterionMarkerLabel, twinSkipSuffix, readCodeCriteria, createHostedClient, toTwinHttpEvent, redactJsonl, scoreFromFinalizeResponse, parseGitHubSeedState, uploadRunBlobs, isPreSatisfied } from '../../chunk-
|
|
2
|
+
import { DEFAULT_CONTROL_PLANE_URL, DEFAULT_DASHBOARD_URL, clearLocalCredentials, friendlyHostedError, SESSION_TWIN_NAMES, runSessionCreate, runSessionList, runSessionStop, resolveCredentials, runTaskHosted, discoverRunSet, VERDICT_ARTIFACT_VERSION, persistCredentialsAfterLogin, DEFAULT_DOCS_SITE_ORIGIN, resolveSeams, resolveCachedAgentId, readLinkCache, postAgentResolver, writeLinkCache, ensurePomeGitignored } from '../../chunk-MRCYOSBM.js';
|
|
3
|
+
import { assetPath, runTask, resolvePackageRoot, DEMO_TASK_NAME, demoTaskPath } from '../../chunk-IYMDPMMZ.js';
|
|
4
|
+
import { parseTaskFile, scoreStatus, runScoreLine, readLatestRun, readMetaSummary, outcomeOf, readConfigTwins, scoreCountsSummary, markerFor, criterionMarkerLabel, twinSkipSuffix, readCodeCriteria, createHostedClient, toTwinHttpEvent, redactJsonl, scoreFromFinalizeResponse, parseGitHubSeedState, uploadRunBlobs, isPreSatisfied } from '../../chunk-XAQGX7K2.js';
|
|
5
|
+
import '../../chunk-B7PA7UDX.js';
|
|
5
6
|
import '../../chunk-NW7HGA2K.js';
|
|
6
7
|
import { GMAIL_CHECKS } from '../../chunk-JM6VS62R.js';
|
|
7
8
|
import '../../chunk-3T5XN64P.js';
|
|
8
9
|
import { LINEAR_CHECKS } from '../../chunk-XBT6ZLBG.js';
|
|
9
|
-
import '../../chunk-
|
|
10
|
-
import '../../chunk-
|
|
11
|
-
import { TWIN_NAME_LIST, isTwinName, createGitHubSmokeApp } from '../../chunk-
|
|
12
|
-
import { readManifest, writeManifest, MANIFEST_JSON, readRequiredManifest, normalizeManifestTwins } from '../../chunk-
|
|
10
|
+
import '../../chunk-Q5NBPR57.js';
|
|
11
|
+
import '../../chunk-S6JLWI4S.js';
|
|
12
|
+
import { TWIN_NAME_LIST, isTwinName, createGitHubSmokeApp } from '../../chunk-SRG22BIH.js';
|
|
13
|
+
import { readManifest, writeManifest, MANIFEST_JSON, readRequiredManifest, normalizeManifestTwins } from '../../chunk-VO2XUPZC.js';
|
|
13
14
|
import '../../chunk-XDU6TD4O.js';
|
|
14
|
-
import { MOUNTED_TWINS, deriveAgentSlug, exitCodeFor, HostedUsageError, HostedOrchError, HostedAuthError, HostedQuotaError } from '../../chunk-
|
|
15
|
+
import { MOUNTED_TWINS, deriveAgentSlug, exitCodeFor, HostedUsageError, HostedOrchError, HostedAuthError, HostedQuotaError } from '../../chunk-E7WJ3SRP.js';
|
|
15
16
|
import '../../chunk-CBFKZZBR.js';
|
|
16
17
|
import { TAPE_ASSERTABLE_TOOLS } from '../../chunk-C4BVTUA3.js';
|
|
17
18
|
import { seedSchema } from '../../chunk-HJX25USP.js';
|
|
@@ -4652,7 +4653,7 @@ var DEFAULT_AGENT_COMMAND = `node ${DEFAULT_AGENT_FILE}`;
|
|
|
4652
4653
|
var MANIFEST_SCHEMA_URL = "https://pome.sh/schemas/v1/pome.json";
|
|
4653
4654
|
var MAX_UNREADABLE_PATHS_SHOWN = 5;
|
|
4654
4655
|
function readPackageVersion() {
|
|
4655
|
-
if ("0.
|
|
4656
|
+
if ("0.29.0".length > 0) return "0.29.0";
|
|
4656
4657
|
try {
|
|
4657
4658
|
const here = dirname(fileURLToPath(import.meta.url));
|
|
4658
4659
|
const candidates = [
|
|
@@ -4896,7 +4897,7 @@ function createProgram() {
|
|
|
4896
4897
|
const session = program.command("session").alias("sandbox").description(
|
|
4897
4898
|
"Hosted sandbox sessions (same API as the dashboard Twins page \u2014 requires login)"
|
|
4898
4899
|
);
|
|
4899
|
-
session.command("create").description("Create a hosted sandbox session for one or more twins and print its connection info").
|
|
4900
|
+
session.command("create").description("Create a hosted sandbox session for one or more twins and print its connection info").option(
|
|
4900
4901
|
"--twin <name>",
|
|
4901
4902
|
// The enumeration is derived, never typed: this line is the public
|
|
4902
4903
|
// discovery surface for which twins exist, and a hand-written copy of the
|
|
@@ -4904,8 +4905,17 @@ function createProgram() {
|
|
|
4904
4905
|
// stays editorial — github+gmail is the pairing bundled task 27 exercises —
|
|
4905
4906
|
// and `session-twin-help.test.ts` runs the twins it names through the same
|
|
4906
4907
|
// validator, so it cannot rot either.
|
|
4907
|
-
|
|
4908
|
+
//
|
|
4909
|
+
// No longer `requiredOption`: a `--seed` file whose envelope names exactly
|
|
4910
|
+
// one twin already says which twin the sandbox is for. Commander would
|
|
4911
|
+
// reject the invocation before the action runs, so the check moved into
|
|
4912
|
+
// `runSessionCreate`, which fails with the same "No twin specified"
|
|
4913
|
+
// sentence when neither source supplies one.
|
|
4914
|
+
`${SESSION_TWIN_NAMES.join(" | ")}. Repeat the flag for a multi-twin session (e.g. --twin github --twin gmail). Optional when --seed names exactly one twin.`,
|
|
4908
4915
|
(value, previous = []) => [...previous, value]
|
|
4916
|
+
).option(
|
|
4917
|
+
"--seed <path>",
|
|
4918
|
+
"Start the sandbox from a JSON or YAML seed file instead of each twin's default. A seed REPLACES the default; it does not merge. Same file `pome twin start --seed` takes; write one with `pome twin seed <name>`."
|
|
4909
4919
|
).option(
|
|
4910
4920
|
"--api-url <url>",
|
|
4911
4921
|
"Control-plane URL",
|
|
@@ -4928,10 +4938,11 @@ function createProgram() {
|
|
|
4928
4938
|
}
|
|
4929
4939
|
await runSessionCreate({
|
|
4930
4940
|
apiBaseUrl: opts.apiUrl,
|
|
4931
|
-
twins: opts.twin,
|
|
4941
|
+
twins: opts.twin ?? [],
|
|
4932
4942
|
showSecrets: opts.showSecrets,
|
|
4933
4943
|
format,
|
|
4934
|
-
secretsFile: opts.secretsFile
|
|
4944
|
+
secretsFile: opts.secretsFile,
|
|
4945
|
+
seedPath: opts.seed
|
|
4935
4946
|
});
|
|
4936
4947
|
} catch (err) {
|
|
4937
4948
|
console.error(friendlyHostedError(err));
|
|
@@ -5103,7 +5114,7 @@ function createProgram() {
|
|
|
5103
5114
|
return;
|
|
5104
5115
|
}
|
|
5105
5116
|
{
|
|
5106
|
-
const { runDoctorChecks } = await import('../../checks-
|
|
5117
|
+
const { runDoctorChecks } = await import('../../checks-JR4OEKZM.js');
|
|
5107
5118
|
const { renderDoctorReport } = await import('../../render-ZQQ4UMNO.js');
|
|
5108
5119
|
const doctorReport = await runDoctorChecks({ mode: useLocal ? "full" : "hosted" });
|
|
5109
5120
|
if (!doctorReport.ok) {
|
|
@@ -5141,7 +5152,7 @@ function createProgram() {
|
|
|
5141
5152
|
taskForRuns.config.runs
|
|
5142
5153
|
);
|
|
5143
5154
|
if (k > 1) {
|
|
5144
|
-
const { runTrialGroup } = await import('../../runTrialGroup-
|
|
5155
|
+
const { runTrialGroup } = await import('../../runTrialGroup-XEBG225L.js');
|
|
5145
5156
|
const fileForRerun = relative(process.cwd(), file);
|
|
5146
5157
|
const rerunCommand = defaultTask ? options.trials !== void 0 ? `pome run -n ${k}` : "pome run" : `pome run ${fileForRerun && !fileForRerun.startsWith("..") ? fileForRerun : file} -n ${k}`;
|
|
5147
5158
|
const groupResult = await runTrialGroup({
|
|
@@ -5235,7 +5246,7 @@ function createProgram() {
|
|
|
5235
5246
|
process.exitCode = 5;
|
|
5236
5247
|
return;
|
|
5237
5248
|
}
|
|
5238
|
-
const { runDemo } = await import('../../runDemo-
|
|
5249
|
+
const { runDemo } = await import('../../runDemo-GBPVF5AA.js');
|
|
5239
5250
|
const result = await runDemo({
|
|
5240
5251
|
apiBase: opts.apiUrl.replace(/\/$/, ""),
|
|
5241
5252
|
dashboardBase: process.env.POME_DASHBOARD_URL ?? DEFAULT_DASHBOARD_URL,
|
|
@@ -5253,7 +5264,7 @@ function createProgram() {
|
|
|
5253
5264
|
program.command("doctor").description(
|
|
5254
5265
|
"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."
|
|
5255
5266
|
).action(async () => {
|
|
5256
|
-
const { runDoctorChecks } = await import('../../checks-
|
|
5267
|
+
const { runDoctorChecks } = await import('../../checks-JR4OEKZM.js');
|
|
5257
5268
|
const { renderDoctorReport } = await import('../../render-ZQQ4UMNO.js');
|
|
5258
5269
|
const report = await runDoctorChecks();
|
|
5259
5270
|
for (const line of renderDoctorReport(report, { passNote: true })) console.error(line);
|
|
@@ -5423,18 +5434,27 @@ function createProgram() {
|
|
|
5423
5434
|
);
|
|
5424
5435
|
});
|
|
5425
5436
|
const twin = program.command("twin").description("Manage local twins");
|
|
5426
|
-
twin.command("start").argument(
|
|
5437
|
+
twin.command("start").argument(
|
|
5438
|
+
"[name]",
|
|
5439
|
+
`Twin name (${TWIN_NAME_LIST.join(" | ")}). Optional when --seed names exactly one twin.`
|
|
5440
|
+
).option(
|
|
5427
5441
|
"--port <port>",
|
|
5428
5442
|
"Port to bind (default: $PORT, else GMAIL_TWIN_PORT/3336 for gmail, else 3333)"
|
|
5429
5443
|
).option(
|
|
5430
5444
|
"--seed <path>",
|
|
5431
|
-
"Boot this twin
|
|
5445
|
+
"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."
|
|
5432
5446
|
).description(
|
|
5433
5447
|
"Start a standalone twin as a long-lived foreground server (Ctrl-C to stop)"
|
|
5434
5448
|
).action(async (name, options) => {
|
|
5435
|
-
const { runTwinStartCommand } = await import('../../twinStart-
|
|
5449
|
+
const { runTwinStartCommand } = await import('../../twinStart-ZDWFU6M4.js');
|
|
5436
5450
|
await runTwinStartCommand(name, options);
|
|
5437
5451
|
});
|
|
5452
|
+
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.").description(
|
|
5453
|
+
"Print a starter seed file for a twin, generated from the twin's own starting state"
|
|
5454
|
+
).action(async (names, options) => {
|
|
5455
|
+
const { runTwinSeedCommand } = await import('../../twinSeed-MOQXJDEG.js');
|
|
5456
|
+
await runTwinSeedCommand(names, options);
|
|
5457
|
+
});
|
|
5438
5458
|
twin.command("reset").argument("[name]", "Twin name (default: github)", "github").description("Reset standalone twin state").action(async (name) => {
|
|
5439
5459
|
if (!isTwinName(name)) {
|
|
5440
5460
|
throw new Error(`Unknown twin '${name}'. Supported: ${TWIN_NAME_LIST.join(", ")}.`);
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export { LINEAR_CHECKS } from './chunk-XBT6ZLBG.js';
|
|
2
|
-
import { MCP_PAGE_MAX, defaultSeedState, linearSeedSchema, notFound, badUserInput, MCP_PAGE_DEFAULT, DEFAULT_LINEAR_EMAIL, RELAY_PAGE_MAX, RELAY_PAGE_DEFAULT, STATE_EXPORT_CAP, parseSeed, DEFAULT_LINEAR_CLOCK, LINEAR_PROVIDER_TOKEN_PREFIX, DEFAULT_LINEAR_SID, DEFAULT_SCOPES, linearErrorEnvelope, unauthorizedEnvelope, unsupportedEnvelope, forbiddenEnvelope, assertWebhookUrl, ACCESS_TOKEN_TTL_SECONDS, OAUTH_CODE_TTL_SECONDS, TITLE_MAX_BYTES, BODY_MAX_BYTES, LinearTwinError, GRAPHQL_QUERY_MAX_BYTES, GRAPHQL_SELECTION_DEPTH_MAX } from './chunk-
|
|
3
|
-
export { DEFAULT_LINEAR_CLOCK, DEFAULT_LINEAR_EMAIL, DEFAULT_LINEAR_PORT, DEFAULT_LINEAR_SID, DEFAULT_LINEAR_TOKEN, LINEAR_PROVIDER_TOKEN_PREFIX, LinearTwinError, STATE_EXPORT_CAP, assertWebhookUrl, defaultSeedState, linearErrorEnvelope, linearSeedSchema, loadSeedFromEnv, parseSeed, unauthorizedEnvelope, unsupportedEnvelope, webhookUrlError } from './chunk-
|
|
2
|
+
import { MCP_PAGE_MAX, defaultSeedState, linearSeedSchema, notFound, badUserInput, MCP_PAGE_DEFAULT, DEFAULT_LINEAR_EMAIL, RELAY_PAGE_MAX, RELAY_PAGE_DEFAULT, STATE_EXPORT_CAP, parseSeed, DEFAULT_LINEAR_CLOCK, LINEAR_PROVIDER_TOKEN_PREFIX, DEFAULT_LINEAR_SID, DEFAULT_SCOPES, linearErrorEnvelope, unauthorizedEnvelope, unsupportedEnvelope, forbiddenEnvelope, assertWebhookUrl, ACCESS_TOKEN_TTL_SECONDS, OAUTH_CODE_TTL_SECONDS, TITLE_MAX_BYTES, BODY_MAX_BYTES, LinearTwinError, GRAPHQL_QUERY_MAX_BYTES, GRAPHQL_SELECTION_DEPTH_MAX } from './chunk-Q5NBPR57.js';
|
|
3
|
+
export { DEFAULT_LINEAR_CLOCK, DEFAULT_LINEAR_EMAIL, DEFAULT_LINEAR_PORT, DEFAULT_LINEAR_SID, DEFAULT_LINEAR_TOKEN, LINEAR_PROVIDER_TOKEN_PREFIX, LinearTwinError, STATE_EXPORT_CAP, assertWebhookUrl, defaultSeedState, linearErrorEnvelope, linearSeedSchema, loadSeedFromEnv, parseSeed, unauthorizedEnvelope, unsupportedEnvelope, webhookUrlError } from './chunk-Q5NBPR57.js';
|
|
4
4
|
import './chunk-JWJYNAWI.js';
|
|
5
5
|
import { routeInputDeclarer, mountDeclaredRoute, UndeclaredInputError } from './chunk-IZFM7W2V.js';
|
|
6
6
|
import { loadMcpToolFixture, deriveMcpToolTable, openTwinDatabase, defineTwin, createApp } from './chunk-E665XWYU.js';
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { TWIN_NAMES, isTwinName, TWIN_REGISTRY } from './chunk-SRG22BIH.js';
|
|
2
|
+
import { writeFile } from 'node:fs/promises';
|
|
3
|
+
|
|
4
|
+
async function generateSeedFile(twins) {
|
|
5
|
+
if (twins.length === 0) {
|
|
6
|
+
throw new Error(`No twin specified. Pass at least one of: ${TWIN_NAMES.join(", ")}.`);
|
|
7
|
+
}
|
|
8
|
+
for (const twin of twins) {
|
|
9
|
+
if (!isTwinName(twin)) {
|
|
10
|
+
throw new Error(`Unknown twin '${twin}'. Supported: ${TWIN_NAMES.join(", ")}.`);
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
const duplicates = twins.filter((twin, i) => twins.indexOf(twin) !== i);
|
|
14
|
+
if (duplicates.length > 0) {
|
|
15
|
+
throw new Error(`A seed file has one entry per twin, and this one is named twice: ${[...new Set(duplicates)].join(", ")}.`);
|
|
16
|
+
}
|
|
17
|
+
const envelope = {};
|
|
18
|
+
for (const twin of twins) {
|
|
19
|
+
const entry = TWIN_REGISTRY[twin];
|
|
20
|
+
envelope[twin] = await entry.parseSeed(await entry.defaultSeed());
|
|
21
|
+
}
|
|
22
|
+
return `${JSON.stringify(envelope, null, 2)}
|
|
23
|
+
`;
|
|
24
|
+
}
|
|
25
|
+
async function writeSeedFile(path, text) {
|
|
26
|
+
try {
|
|
27
|
+
await writeFile(path, text, { flag: "wx" });
|
|
28
|
+
} catch (err) {
|
|
29
|
+
if (err.code === "EEXIST") {
|
|
30
|
+
throw new Error(
|
|
31
|
+
`${path} already exists \u2014 delete it or pass a different --out. A seed file is authored content once it is on disk.`
|
|
32
|
+
);
|
|
33
|
+
}
|
|
34
|
+
throw err;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
async function runTwinSeedCommand(names, options = {}) {
|
|
38
|
+
const text = await generateSeedFile(names);
|
|
39
|
+
if (options.out === void 0) {
|
|
40
|
+
process.stdout.write(text);
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
await writeSeedFile(options.out, text);
|
|
44
|
+
console.error(`Wrote ${options.out} \u2014 the ${names.join(" + ")} starting seed.`);
|
|
45
|
+
console.error(`Boot it: pome twin start ${names[0]} --seed ${options.out}`);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export { generateSeedFile, runTwinSeedCommand, writeSeedFile };
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { readSeedFileText, seedForTwin, parseSeedFileText, soleTwinOf, twinsNamedBy } from './chunk-B7PA7UDX.js';
|
|
2
|
+
import { bootTwin } from './chunk-S6JLWI4S.js';
|
|
3
|
+
import { TWIN_REGISTRY, isTwinName, TWIN_NAMES, defaultPortFor } from './chunk-SRG22BIH.js';
|
|
3
4
|
import './chunk-E665XWYU.js';
|
|
4
5
|
import './chunk-6KJC4BTO.js';
|
|
5
6
|
import './chunk-SG6ZTIMT.js';
|
|
@@ -10,7 +11,6 @@ import { mkdir, writeFile } from 'node:fs/promises';
|
|
|
10
11
|
import { join } from 'node:path';
|
|
11
12
|
import { serve } from '@hono/node-server';
|
|
12
13
|
import { sign } from 'hono/jwt';
|
|
13
|
-
import { parse } from 'yaml';
|
|
14
14
|
|
|
15
15
|
var STANDALONE_SID = "standalone";
|
|
16
16
|
function resolveStandaloneAuthSecret(twin, env = process.env) {
|
|
@@ -35,59 +35,59 @@ function resolveStandaloneAuthSecret(twin, env = process.env) {
|
|
|
35
35
|
}
|
|
36
36
|
return { secret: randomBytes(32).toString("hex"), source: "ephemeral" };
|
|
37
37
|
}
|
|
38
|
-
async function resolveStandaloneSeed(twin, seedPath, env = process.env) {
|
|
39
|
-
const entry = TWIN_REGISTRY[twin];
|
|
38
|
+
async function resolveStandaloneSeed(twin, seedPath, env = process.env, seedText) {
|
|
40
39
|
if (seedPath !== void 0) {
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
raw = readFileSync(seedPath, "utf8");
|
|
44
|
-
} catch (err) {
|
|
45
|
-
throw new Error(
|
|
46
|
-
`pome twin start --seed: cannot read ${seedPath}: ${err.message}`
|
|
47
|
-
);
|
|
48
|
-
}
|
|
40
|
+
const raw = seedText ?? readSeedFileText(seedPath, "pome twin start --seed");
|
|
41
|
+
const origin = `--seed ${seedPath}`;
|
|
49
42
|
return {
|
|
50
|
-
seedState: await
|
|
43
|
+
seedState: await seedForTwin(parseSeedFileText(raw, origin), twin, origin),
|
|
51
44
|
source: "file",
|
|
52
45
|
path: seedPath
|
|
53
46
|
};
|
|
54
47
|
}
|
|
55
48
|
const fromEnv = env.POME_SEED_JSON;
|
|
56
49
|
if (fromEnv !== void 0 && fromEnv !== "") {
|
|
57
|
-
return {
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
50
|
+
return {
|
|
51
|
+
seedState: await seedForTwin(
|
|
52
|
+
parseSeedFileText(fromEnv, "POME_SEED_JSON"),
|
|
53
|
+
twin,
|
|
54
|
+
"POME_SEED_JSON"
|
|
55
|
+
),
|
|
56
|
+
source: "env"
|
|
57
|
+
};
|
|
65
58
|
}
|
|
66
|
-
return
|
|
59
|
+
return { seedState: await TWIN_REGISTRY[twin].defaultSeed(), source: "default" };
|
|
67
60
|
}
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
61
|
+
function resolveStandaloneTwin(name, seedPath, seedText) {
|
|
62
|
+
if (name !== void 0) {
|
|
63
|
+
if (!isTwinName(name)) {
|
|
64
|
+
throw new Error(`Unknown twin '${name}'. Supported: ${TWIN_NAMES.join(", ")}.`);
|
|
65
|
+
}
|
|
66
|
+
return name;
|
|
74
67
|
}
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
68
|
+
if (seedPath === void 0 || seedText === void 0) {
|
|
69
|
+
throw new Error(
|
|
70
|
+
`pome twin start: name a twin (${TWIN_NAMES.join(", ")}), or pass a --seed file whose envelope names exactly one.`
|
|
71
|
+
);
|
|
79
72
|
}
|
|
73
|
+
const origin = `--seed ${seedPath}`;
|
|
74
|
+
const file = parseSeedFileText(seedText, origin);
|
|
75
|
+
const sole = soleTwinOf(file);
|
|
76
|
+
if (sole !== void 0) return sole;
|
|
77
|
+
const named = twinsNamedBy(file);
|
|
78
|
+
throw new Error(
|
|
79
|
+
named.length === 0 ? `${origin} is a flat seed, so it does not name a twin. Pass the name: pome twin start <${TWIN_NAMES.join("|")}> --seed ${seedPath}` : `${origin} names ${named.length} twins (${named.join(", ")}), so it does not say which one to start. Pass the name: pome twin start ${named[0]} --seed ${seedPath}`
|
|
80
|
+
);
|
|
80
81
|
}
|
|
81
|
-
async function runTwinStartCommand(
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
}
|
|
82
|
+
async function runTwinStartCommand(nameArg, options) {
|
|
83
|
+
const seedText = options.seed === void 0 ? void 0 : readSeedFileText(options.seed, "pome twin start --seed");
|
|
84
|
+
const name = resolveStandaloneTwin(nameArg, options.seed, seedText);
|
|
85
85
|
const portRaw = options.port ?? defaultPortFor(name, process.env);
|
|
86
86
|
const port = Number(portRaw);
|
|
87
87
|
if (!Number.isInteger(port) || port < 1 || port > 65535) {
|
|
88
88
|
throw new Error(`pome twin start: invalid --port "${portRaw}"`);
|
|
89
89
|
}
|
|
90
|
-
const world = await resolveStandaloneSeed(name, options.seed);
|
|
90
|
+
const world = await resolveStandaloneSeed(name, options.seed, process.env, seedText);
|
|
91
91
|
const resolved = resolveStandaloneAuthSecret(name);
|
|
92
92
|
process.env.TWIN_AUTH_SECRET = resolved.secret;
|
|
93
93
|
const baseUrl = `http://127.0.0.1:${port}`;
|
|
@@ -130,11 +130,15 @@ async function runTwinStartCommand(name, options) {
|
|
|
130
130
|
}
|
|
131
131
|
console.log(`Pome ${name} twin listening at ${restUrl}`);
|
|
132
132
|
if (world.source === "file") {
|
|
133
|
-
console.log(`
|
|
133
|
+
console.log(`Seed: ${world.path} (replaces the ${name} twin's default).`);
|
|
134
134
|
} else if (world.source === "env") {
|
|
135
|
-
console.log(
|
|
135
|
+
console.log(
|
|
136
|
+
`Seed: POME_SEED_JSON (replaces the ${name} twin's default; --seed <path> overrides it).`
|
|
137
|
+
);
|
|
136
138
|
} else {
|
|
137
|
-
console.log(
|
|
139
|
+
console.log(
|
|
140
|
+
`Seed: the ${name} twin's default (pass --seed <path>, or write one with \`pome twin seed ${name}\`).`
|
|
141
|
+
);
|
|
138
142
|
}
|
|
139
143
|
if (resolved.source === "persisted") {
|
|
140
144
|
console.log(
|
|
@@ -161,4 +165,4 @@ async function runTwinStartCommand(name, options) {
|
|
|
161
165
|
process.once("SIGTERM", shutdown);
|
|
162
166
|
}
|
|
163
167
|
|
|
164
|
-
export { resolveStandaloneAuthSecret, resolveStandaloneSeed, runTwinStartCommand };
|
|
168
|
+
export { resolveStandaloneAuthSecret, resolveStandaloneSeed, resolveStandaloneTwin, runTwinStartCommand };
|
package/package.json
CHANGED
|
File without changes
|