orizu 0.5.22 → 0.5.23
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +42 -14
- package/dist/cleanup.d.ts +6 -0
- package/dist/cleanup.d.ts.map +1 -0
- package/dist/cleanup.js +27 -0
- package/dist/help.js +3 -3
- package/dist/hosted-commands.d.ts +13 -0
- package/dist/hosted-commands.d.ts.map +1 -0
- package/dist/hosted-commands.js +10 -0
- package/dist/hosted-gepa-cli.d.ts +11 -0
- package/dist/hosted-gepa-cli.d.ts.map +1 -0
- package/dist/hosted-gepa-cli.js +110 -0
- package/dist/hosted-gepa-numeric-values.d.ts +3 -0
- package/dist/hosted-gepa-numeric-values.d.ts.map +1 -0
- package/dist/hosted-gepa-numeric-values.js +49 -0
- package/dist/hosted-provider-settings.d.ts +3 -0
- package/dist/hosted-provider-settings.d.ts.map +1 -0
- package/dist/hosted-provider-settings.js +69 -0
- package/dist/hosted-session-cli.d.ts.map +1 -1
- package/dist/hosted-session-cli.js +6 -1
- package/dist/http.d.ts +1 -0
- package/dist/http.d.ts.map +1 -1
- package/dist/http.js +7 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +69 -36
- package/dist/optimizations-promote-cli.d.ts +3 -0
- package/dist/optimizations-promote-cli.d.ts.map +1 -1
- package/dist/optimizations-promote-cli.js +75 -7
- package/dist/runner-dir-verify.d.ts.map +1 -1
- package/dist/runner-dir-verify.js +4 -7
- package/dist/skilled-proposer-bake-report.d.ts +2 -0
- package/dist/skilled-proposer-bake-report.d.ts.map +1 -0
- package/dist/skilled-proposer-bake-report.js +1 -0
- package/dist/skilled-proposer-launch.d.ts +22 -0
- package/dist/skilled-proposer-launch.d.ts.map +1 -1
- package/dist/skilled-proposer-launch.js +39 -6
- package/package.json +1 -1
- package/scripts/vendor-gepa-python.mjs +81 -12
- package/src/cleanup.ts +37 -0
- package/src/help.ts +3 -3
- package/src/hosted-commands.ts +4 -0
- package/src/hosted-gepa-cli.ts +107 -0
- package/src/hosted-gepa-numeric-values.ts +60 -0
- package/src/hosted-provider-settings.ts +69 -0
- package/src/hosted-session-cli.ts +4 -1
- package/src/http.ts +8 -0
- package/src/index.ts +107 -37
- package/src/optimizations-promote-cli.ts +85 -7
- package/src/runner-dir-verify.ts +11 -6
- package/src/skilled-proposer-bake-report.ts +1 -0
- package/src/skilled-proposer-launch.ts +38 -7
- package/src/skilled-proposer-venv-manager.mjs +44 -27
- package/vendor/orizu-gepa/src/orizu_gepa_connector/runtime.py +7 -2
- package/vendor/orizu-gepa-python/src/orizu_gepa/cli.py +1 -0
- package/vendor/orizu-gepa-python/src/orizu_gepa/client.py +15 -0
- package/vendor/skills/orizu-cli/SKILL.md +94 -202
- package/vendor/skills/orizu-cli/references/assess-and-plan.md +107 -0
- package/vendor/skills/orizu-cli/references/building-judges.md +442 -180
- package/vendor/skills/orizu-cli/references/cli-reference.md +20 -19
- package/vendor/skills/orizu-cli/references/dataset-design.md +100 -0
- package/vendor/skills/orizu-cli/references/eval-strategy.md +64 -0
- package/vendor/skills/orizu-cli/references/instructions-after-prompts.md +12 -17
- package/vendor/skills/orizu-cli/references/migrate-existing-gepa-setup.md +78 -70
- package/vendor/skills/orizu-cli/references/optimization-reports.md +195 -108
- package/vendor/skills/orizu-cli/references/optimization-with-gepa.md +42 -23
- package/vendor/skills/orizu-cli/references/primer.md +25 -16
- package/vendor/skills/orizu-cli/references/prompt-control-plane.md +94 -73
package/dist/index.js
CHANGED
|
@@ -21,7 +21,7 @@ import { parseGlobalFlags } from './global-flags.js';
|
|
|
21
21
|
import { getCapabilities, renderHelpForArgs, renderRootHelp } from './help.js';
|
|
22
22
|
import { runLocalAppPreview } from './preview-runtime.js';
|
|
23
23
|
import { readAssignmentManifestJsonlFile } from './task-assignment-manifest.js';
|
|
24
|
-
import { assertSecureTokenTransport, authedFetch, getBaseUrl, resolveLoginBaseUrl, setGlobalFlags } from './http.js';
|
|
24
|
+
import { assertSecureTokenTransport, authedFetch, credentialRequestRedirectPolicy, getBaseUrl, resolveLoginBaseUrl, setGlobalFlags, } from './http.js';
|
|
25
25
|
import { computeSkillContentHash, getSkillInstallPath, getSkillTargetStatus, getTargetForAgent, installSkillTarget, isSkillInstallAgent, isSkillInstallTarget, resolveSkillSource, SKILL_INSTALL_AGENTS, SKILL_INSTALL_TARGETS, targetNeedsOverwrite, } from './skill-installer.js';
|
|
26
26
|
import { renderBanner } from './banner.js';
|
|
27
27
|
import { formatTaskCreateError } from './task-create-error.js';
|
|
@@ -33,6 +33,7 @@ import { ARTIFACT_MAX_BYTES, runnerOptimizerCommand } from './artifact-pull.js';
|
|
|
33
33
|
import { killSwitchCommand } from './kill-switch-cli.js';
|
|
34
34
|
import { egressAllowlistCommand } from './egress-allowlist-cli.js';
|
|
35
35
|
import { acceptScoreRunCommand } from './scores-accept-cli.js';
|
|
36
|
+
import { cleanupAll, throwWithCleanup } from './cleanup.js';
|
|
36
37
|
import { listOptimizationRunsCommand } from './optimizations-list-cli.js';
|
|
37
38
|
import { promoteOptimizationCommand } from './optimizations-promote-cli.js';
|
|
38
39
|
import { scorersCommand } from './scorers-cli.js';
|
|
@@ -41,7 +42,7 @@ import { archiveArtifactCommand, listAssignmentsCommand, printAppSummaries, prin
|
|
|
41
42
|
import { teamConnectorsCommand } from './team-connectors-cli.js';
|
|
42
43
|
import { manifestsCommand } from './manifests-cli.js';
|
|
43
44
|
import { workbenchCommand } from './workbench-cli.js';
|
|
44
|
-
import {
|
|
45
|
+
import { dispatchHostedCommands } from './hosted-commands.js';
|
|
45
46
|
import { workspaceSyncCommand } from './workspace-sync.js';
|
|
46
47
|
import { runGitCredentialInvocation } from './git-credential.js';
|
|
47
48
|
import { instructionSetsCommand, syncToDisk } from './instruction-sets-cli.js';
|
|
@@ -52,7 +53,7 @@ import { readMarkdownReportInput } from './markdown-report-input.js';
|
|
|
52
53
|
import { promptPushErrorMessage, promptReportCommand } from './prompt-report-cli.js';
|
|
53
54
|
import { setPromptLabel } from './prompt-label-cli.js';
|
|
54
55
|
import { printPromptSummaryTable } from './prompt-summary-table.js';
|
|
55
|
-
import { assertSnapshotManifestConfined, verifyGepaRunnerDirsFromArgs, verifyRunnerDirRegistered } from './runner-dir-verify.js';
|
|
56
|
+
import { assertSnapshotManifestConfined, extractFlagValue, verifyGepaRunnerDirsFromArgs, verifyRunnerDirRegistered, } from './runner-dir-verify.js';
|
|
56
57
|
import { runScorersRegister } from './scorer-draft-push.js';
|
|
57
58
|
import { runZipArtifactPush } from './zip-draft-push.js';
|
|
58
59
|
import { runGithubLink, runInteractiveHostedSetup } from './github-setup.js';
|
|
@@ -811,6 +812,7 @@ async function logout() {
|
|
|
811
812
|
body: 'refreshToken' in credentials
|
|
812
813
|
? JSON.stringify({ refreshToken: credentials.refreshToken })
|
|
813
814
|
: undefined,
|
|
815
|
+
...credentialRequestRedirectPolicy(),
|
|
814
816
|
});
|
|
815
817
|
if (!response.ok) {
|
|
816
818
|
remoteLogoutError = sanitizeTerminalText(await response.text()).slice(0, 180);
|
|
@@ -1751,6 +1753,30 @@ async function updateOptimizationRunLifecycle(action) {
|
|
|
1751
1753
|
}
|
|
1752
1754
|
// ALI-1073 list moved to optimizations-list-cli.ts (line ratchet, ALI-976);
|
|
1753
1755
|
// ALI-1175 labels its best scores as agent-reported evidence there.
|
|
1756
|
+
const GEPA_RUNNER_MATERIALIZATION_PAIRS = [
|
|
1757
|
+
{ versionFlag: '--runner-version-id', dirFlag: '--candidate-runner-dir' },
|
|
1758
|
+
{ versionFlag: '--scorer-runner-version-id', dirFlag: '--scorer-runner-dir' },
|
|
1759
|
+
];
|
|
1760
|
+
async function materializeMissingGepaRunnerDirs(args) {
|
|
1761
|
+
const rewritten = [...args];
|
|
1762
|
+
const cleanups = [];
|
|
1763
|
+
const cleanup = () => cleanupAll(cleanups, 'Failed to clean materialized runner directories');
|
|
1764
|
+
try {
|
|
1765
|
+
for (const pair of GEPA_RUNNER_MATERIALIZATION_PAIRS) {
|
|
1766
|
+
const runnerVersionId = extractFlagValue(rewritten, pair.versionFlag);
|
|
1767
|
+
const runnerDir = extractFlagValue(rewritten, pair.dirFlag);
|
|
1768
|
+
if (!runnerVersionId || runnerDir)
|
|
1769
|
+
continue;
|
|
1770
|
+
const materialized = await materializeRunnerVersion(runnerVersionId);
|
|
1771
|
+
cleanups.push(materialized.cleanup);
|
|
1772
|
+
rewritten.push(pair.dirFlag, materialized.runnerDir);
|
|
1773
|
+
}
|
|
1774
|
+
}
|
|
1775
|
+
catch (error) {
|
|
1776
|
+
throwWithCleanup(error, cleanups, 'Runner materialization failed and cleanup also failed');
|
|
1777
|
+
}
|
|
1778
|
+
return { args: rewritten, cleanup };
|
|
1779
|
+
}
|
|
1754
1780
|
async function runGepaOptimization() {
|
|
1755
1781
|
const project = getArg('--project') || await resolveProjectSlug(null);
|
|
1756
1782
|
const baseUrl = getBaseUrl();
|
|
@@ -1763,11 +1789,12 @@ async function runGepaOptimization() {
|
|
|
1763
1789
|
// itself (both argparse flag forms), fail-closed on half-populated pairs,
|
|
1764
1790
|
// and REWRITES the dir flags to verified snapshots (the exact hashed bytes)
|
|
1765
1791
|
// so a post-hash mutation of the original dirs cannot change what runs.
|
|
1766
|
-
const
|
|
1767
|
-
|
|
1768
|
-
let result;
|
|
1792
|
+
const materialized = await materializeMissingGepaRunnerDirs(forwardedArgs);
|
|
1793
|
+
let verified;
|
|
1769
1794
|
let selectedEngine = 'official';
|
|
1770
1795
|
try {
|
|
1796
|
+
verified = await verifyGepaRunnerDirsFromArgs(materialized.args);
|
|
1797
|
+
forwardedArgs = verified.args;
|
|
1771
1798
|
// Uniform resolution (ALI-1090): honors ORIZU_TOKEN / ORIZU_TOKEN_FILE before
|
|
1772
1799
|
// credentials.json so hosted sandboxes can run optimizations. Read at spawn
|
|
1773
1800
|
// time — AFTER the verification awaits above, so a hosted token-file
|
|
@@ -1794,17 +1821,21 @@ async function runGepaOptimization() {
|
|
|
1794
1821
|
dispatch.environment.ORIZU_INSTRUCTION_SET_PROFILE_VERSION_ID = instructionSetProfileVersionId;
|
|
1795
1822
|
selectedEngine = dispatch.engine;
|
|
1796
1823
|
const launch = prepareSkilledProposerLaunch(python, dispatch.engine, dispatch.environment);
|
|
1797
|
-
result = await spawnSkilledProposerChild(launch.python, ['-m', dispatch.module, ...dispatch.args], dispatch.engine, launch.environment);
|
|
1798
|
-
|
|
1799
|
-
|
|
1800
|
-
|
|
1801
|
-
|
|
1802
|
-
|
|
1803
|
-
|
|
1824
|
+
const result = await spawnSkilledProposerChild(launch.python, ['-m', dispatch.module, ...dispatch.args], dispatch.engine, launch.environment);
|
|
1825
|
+
if (result.error) {
|
|
1826
|
+
throw new Error(`${selectedEngine} GEPA engine failed: ${result.error.message}`, { cause: result.error });
|
|
1827
|
+
}
|
|
1828
|
+
if (result.status !== 0) {
|
|
1829
|
+
throw new Error(`${selectedEngine} GEPA engine failed with exit code ${result.status}`);
|
|
1830
|
+
}
|
|
1804
1831
|
}
|
|
1805
|
-
|
|
1806
|
-
|
|
1832
|
+
catch (error) {
|
|
1833
|
+
throwWithCleanup(error, [
|
|
1834
|
+
...(verified ? [verified.cleanup] : []),
|
|
1835
|
+
materialized.cleanup,
|
|
1836
|
+
], 'GEPA launch failed and runner cleanup also failed');
|
|
1807
1837
|
}
|
|
1838
|
+
cleanupAll([verified.cleanup, materialized.cleanup], 'Failed to clean GEPA runner directories');
|
|
1808
1839
|
if (hasJsonFlag()) {
|
|
1809
1840
|
printJson({ status: 'completed', exitCode: 0 });
|
|
1810
1841
|
}
|
|
@@ -4467,24 +4498,27 @@ export async function materializeRunnerVersion(runnerVersionId) {
|
|
|
4467
4498
|
const tempDir = mkdtempSync(join(tmpdir(), 'orizu-runner-version-'));
|
|
4468
4499
|
const zipPath = join(tempDir, 'runner.zip');
|
|
4469
4500
|
const runnerDir = join(tempDir, 'runner');
|
|
4470
|
-
const
|
|
4471
|
-
|
|
4472
|
-
|
|
4473
|
-
|
|
4474
|
-
|
|
4475
|
-
|
|
4476
|
-
|
|
4477
|
-
|
|
4478
|
-
|
|
4479
|
-
|
|
4480
|
-
|
|
4481
|
-
|
|
4501
|
+
const cleanup = () => rmSync(tempDir, { recursive: true, force: true });
|
|
4502
|
+
try {
|
|
4503
|
+
const zipBytes = new Uint8Array(await response.arrayBuffer());
|
|
4504
|
+
if (zipBytes.byteLength > ARTIFACT_MAX_BYTES) {
|
|
4505
|
+
throw new Error(`Runner artifact exceeds ${ARTIFACT_MAX_BYTES} bytes`);
|
|
4506
|
+
}
|
|
4507
|
+
writeFileSync(zipPath, zipBytes);
|
|
4508
|
+
const result = spawnSync('unzip', ['-q', zipPath, '-d', runnerDir], {
|
|
4509
|
+
encoding: 'utf8',
|
|
4510
|
+
});
|
|
4511
|
+
if (result.error) {
|
|
4512
|
+
throw result.error;
|
|
4513
|
+
}
|
|
4514
|
+
if (result.status !== 0) {
|
|
4515
|
+
throw new Error(`unzip failed: ${sanitizeTerminalText(result.stderr || result.stdout || '')}`);
|
|
4516
|
+
}
|
|
4517
|
+
return { runnerDir, cleanup };
|
|
4482
4518
|
}
|
|
4483
|
-
|
|
4484
|
-
|
|
4485
|
-
throw new Error(`unzip failed: ${sanitizeTerminalText(result.stderr || result.stdout || '')}`);
|
|
4519
|
+
catch (error) {
|
|
4520
|
+
throwWithCleanup(error, [cleanup], `Runner ${runnerVersionId} materialization failed and cleanup also failed`);
|
|
4486
4521
|
}
|
|
4487
|
-
return { runnerDir, cleanup: () => rmSync(tempDir, { recursive: true, force: true }) };
|
|
4488
4522
|
}
|
|
4489
4523
|
async function runnersExec() {
|
|
4490
4524
|
const prompt = getArg('--prompt');
|
|
@@ -4895,6 +4929,8 @@ export async function main(rawArgs = process.argv.slice(2)) {
|
|
|
4895
4929
|
await acceptScoreRunCommand(cliArgs.slice(2), { json: hasJsonFlag(), print: printLine, resolveProjectSlug });
|
|
4896
4930
|
return;
|
|
4897
4931
|
}
|
|
4932
|
+
if (await dispatchHostedCommands(cliArgs, { environment: process.env, getArg, json: hasJsonFlag(), printJson, printLine, printErr: printError, resolveProjectSlug, setExitCode: code => { process.exitCode = code; } }))
|
|
4933
|
+
return;
|
|
4898
4934
|
if (command === 'optimizations' && subcommand === 'start') {
|
|
4899
4935
|
await startOptimizationRun();
|
|
4900
4936
|
return;
|
|
@@ -4923,7 +4959,8 @@ export async function main(rawArgs = process.argv.slice(2)) {
|
|
|
4923
4959
|
}
|
|
4924
4960
|
if (command === 'optimizations' && subcommand === 'promote') {
|
|
4925
4961
|
await promoteOptimizationCommand(cliArgs.slice(2), {
|
|
4926
|
-
json: hasJsonFlag(), print: printLine,
|
|
4962
|
+
json: hasJsonFlag(), origin: parsed.flags, print: printLine, printErr: printError,
|
|
4963
|
+
resolveProjectSlug, fetcher: authedFetch,
|
|
4927
4964
|
});
|
|
4928
4965
|
return;
|
|
4929
4966
|
}
|
|
@@ -5071,10 +5108,6 @@ export async function main(rawArgs = process.argv.slice(2)) {
|
|
|
5071
5108
|
await downloadAnnotations();
|
|
5072
5109
|
return;
|
|
5073
5110
|
}
|
|
5074
|
-
if (command === 'internal' || (command === 'session' && subcommand === 'start' && hasArg('--hosted'))) {
|
|
5075
|
-
process.exitCode = await hostedCommand(cliArgs, { json: hasJsonFlag(), print: printLine, printErr: printError });
|
|
5076
|
-
return;
|
|
5077
|
-
}
|
|
5078
5111
|
if (command === 'session' || command === 'run') {
|
|
5079
5112
|
process.exitCode = await workbenchCommand(cliArgs, { json: hasJsonFlag(), print: printLine });
|
|
5080
5113
|
return;
|
|
@@ -1,6 +1,9 @@
|
|
|
1
|
+
import type { GlobalFlags } from './global-flags.js';
|
|
1
2
|
export interface OptimizationsPromoteIo {
|
|
2
3
|
json: boolean;
|
|
4
|
+
origin: GlobalFlags;
|
|
3
5
|
print: (line: string) => void;
|
|
6
|
+
printErr: (line: string) => void;
|
|
4
7
|
resolveProjectSlug: (projectArg: string | null) => Promise<string>;
|
|
5
8
|
fetcher: (path: string, init?: RequestInit) => Promise<Response>;
|
|
6
9
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"optimizations-promote-cli.d.ts","sourceRoot":"","sources":["../src/optimizations-promote-cli.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"optimizations-promote-cli.d.ts","sourceRoot":"","sources":["../src/optimizations-promote-cli.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAA;AAEpD,MAAM,WAAW,sBAAsB;IACrC,IAAI,EAAE,OAAO,CAAA;IACb,MAAM,EAAE,WAAW,CAAA;IACnB,KAAK,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAA;IAC7B,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAA;IAChC,kBAAkB,EAAE,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI,KAAK,OAAO,CAAC,MAAM,CAAC,CAAA;IAClE,OAAO,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,WAAW,KAAK,OAAO,CAAC,QAAQ,CAAC,CAAA;CACjE;AA0DD,wBAAsB,0BAA0B,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,sBAAsB,GAAG,OAAO,CAAC,IAAI,CAAC,CAiD1G"}
|
|
@@ -1,9 +1,59 @@
|
|
|
1
1
|
import { extractErrorMessage } from './error-response.js';
|
|
2
|
-
import { sanitizeTerminalText } from './json-response.js';
|
|
2
|
+
import { sanitizeHumanInlineText, sanitizeTerminalText } from './json-response.js';
|
|
3
3
|
function option(args, name) {
|
|
4
4
|
const index = args.indexOf(name);
|
|
5
5
|
return index === -1 || !args[index + 1] || args[index + 1].startsWith('--') ? null : args[index + 1];
|
|
6
6
|
}
|
|
7
|
+
function shellArgument(value) {
|
|
8
|
+
if (/^[A-Za-z0-9._/:@-]+$/.test(value))
|
|
9
|
+
return value;
|
|
10
|
+
if (/[\u0000-\u001F\u007F-\u009F\u2028\u2029]/.test(value)) {
|
|
11
|
+
let escaped = '';
|
|
12
|
+
for (const character of value) {
|
|
13
|
+
if (character === '\\')
|
|
14
|
+
escaped += '\\\\';
|
|
15
|
+
else if (character === "'")
|
|
16
|
+
escaped += "\\'";
|
|
17
|
+
else if (character === '\n')
|
|
18
|
+
escaped += '\\n';
|
|
19
|
+
else if (character === '\r')
|
|
20
|
+
escaped += '\\r';
|
|
21
|
+
else if (character === '\t')
|
|
22
|
+
escaped += '\\t';
|
|
23
|
+
else {
|
|
24
|
+
const codePoint = character.codePointAt(0);
|
|
25
|
+
if (codePoint <= 0x1f || codePoint === 0x7f) {
|
|
26
|
+
escaped += `\\x${codePoint.toString(16).padStart(2, '0')}`;
|
|
27
|
+
}
|
|
28
|
+
else if ((codePoint >= 0x80 && codePoint <= 0x9f) || codePoint === 0x2028 || codePoint === 0x2029) {
|
|
29
|
+
for (const byte of new TextEncoder().encode(character)) {
|
|
30
|
+
escaped += `\\x${byte.toString(16).padStart(2, '0')}`;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
else {
|
|
34
|
+
escaped += character;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
return `$'${escaped}'`;
|
|
39
|
+
}
|
|
40
|
+
const safeValue = sanitizeTerminalText(value);
|
|
41
|
+
return `'${safeValue.replace(/'/g, `'\\''`)}'`;
|
|
42
|
+
}
|
|
43
|
+
function inlineTerminalText(value) {
|
|
44
|
+
return sanitizeHumanInlineText(sanitizeTerminalText, value)
|
|
45
|
+
.replaceAll('\u2028', '\\u2028')
|
|
46
|
+
.replaceAll('\u2029', '\\u2029');
|
|
47
|
+
}
|
|
48
|
+
const APPLIED_LABEL_VERSION_SKEW_NOTE = 'Server response predates the appliedLabel discriminator; printing the production-promotion follow-up as a fail-safe.';
|
|
49
|
+
function productionPromotionReplay(runId, candidateId, project, origin) {
|
|
50
|
+
const originArguments = origin.local
|
|
51
|
+
? ' --local'
|
|
52
|
+
: origin.server
|
|
53
|
+
? ` --server ${shellArgument(origin.server)}`
|
|
54
|
+
: '';
|
|
55
|
+
return `Promote this profile with: orizu${originArguments} optimizations promote ${shellArgument(runId)} --candidate ${shellArgument(candidateId)} --label production --project ${shellArgument(project)}`;
|
|
56
|
+
}
|
|
7
57
|
export async function promoteOptimizationCommand(args, io) {
|
|
8
58
|
const runId = args.find(arg => !arg.startsWith('--') && arg !== option(args, '--candidate') && arg !== option(args, '--label') && arg !== option(args, '--project'));
|
|
9
59
|
const candidateId = option(args, '--candidate');
|
|
@@ -18,17 +68,35 @@ export async function promoteOptimizationCommand(args, io) {
|
|
|
18
68
|
if (!response.ok)
|
|
19
69
|
throw new Error(`Failed to promote optimization candidate: ${await extractErrorMessage(response)}`);
|
|
20
70
|
const data = await response.json();
|
|
71
|
+
const isProfilePromotion = 'profileVersionId' in data;
|
|
72
|
+
const replay = isProfilePromotion && data.appliedLabel !== 'production'
|
|
73
|
+
? productionPromotionReplay(runId, candidateId, project, io.origin)
|
|
74
|
+
: null;
|
|
21
75
|
if (io.json) {
|
|
22
|
-
io.print(JSON.stringify(
|
|
23
|
-
? {
|
|
76
|
+
io.print(JSON.stringify(isProfilePromotion
|
|
77
|
+
? {
|
|
78
|
+
profileVersionId: data.profileVersionId,
|
|
79
|
+
versionNumber: data.versionNumber,
|
|
80
|
+
appliedLabel: data.appliedLabel,
|
|
81
|
+
components: data.components,
|
|
82
|
+
}
|
|
24
83
|
: { promptVersionId: data.promptVersionId }));
|
|
84
|
+
if (isProfilePromotion && data.appliedLabel === undefined) {
|
|
85
|
+
io.printErr(APPLIED_LABEL_VERSION_SKEW_NOTE);
|
|
86
|
+
io.printErr(replay);
|
|
87
|
+
}
|
|
25
88
|
return;
|
|
26
89
|
}
|
|
27
|
-
if (
|
|
90
|
+
if (isProfilePromotion) {
|
|
28
91
|
io.print(`Promoted profile version ${sanitizeTerminalText(data.profileVersionId)}`);
|
|
29
|
-
|
|
30
|
-
io.
|
|
92
|
+
if (data.appliedLabel === undefined) {
|
|
93
|
+
io.printErr(APPLIED_LABEL_VERSION_SKEW_NOTE);
|
|
94
|
+
}
|
|
95
|
+
if (replay)
|
|
96
|
+
io.print(replay);
|
|
97
|
+
for (const component of data.components)
|
|
98
|
+
io.print(`${inlineTerminalText(component.key)}: ${inlineTerminalText(component.status)}`);
|
|
31
99
|
return;
|
|
32
100
|
}
|
|
33
|
-
io.print(`Promoted prompt version ${sanitizeTerminalText(data.promptVersionId
|
|
101
|
+
io.print(`Promoted prompt version ${sanitizeTerminalText(data.promptVersionId)}`);
|
|
34
102
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"runner-dir-verify.d.ts","sourceRoot":"","sources":["../src/runner-dir-verify.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"runner-dir-verify.d.ts","sourceRoot":"","sources":["../src/runner-dir-verify.ts"],"names":[],"mappings":"AAaA;;;;;;;;;;;GAWG;AAEH,4DAA4D;AAC5D,MAAM,WAAW,oBAAoB;IACnC,eAAe,EAAE,MAAM,CAAA;IACvB,GAAG,EAAE,MAAM,CAAA;IACX,+DAA+D;IAC/D,IAAI,EAAE,MAAM,CAAA;IACZ,OAAO,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,WAAW,KAAK,OAAO,CAAC,QAAQ,CAAC,CAAA;CAClE;AA6DD,MAAM,WAAW,sBAAsB;IACrC;;;;;;OAMG;IACH,WAAW,EAAE,MAAM,CAAA;IACnB,OAAO,EAAE,MAAM,IAAI,CAAA;CACpB;AAED,wBAAsB,yBAAyB,CAAC,KAAK,EAAE,oBAAoB,GAAG,OAAO,CAAC,sBAAsB,CAAC,CA4F5G;AAonBD;;;;;;;GAOG;AACH,wBAAgB,8BAA8B,CAAC,WAAW,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CA0EtF;AAYD;6EAC6E;AAC7E,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAY5E;AAoBD,MAAM,WAAW,gBAAgB;IAC/B;gFAC4E;IAC5E,IAAI,EAAE,MAAM,EAAE,CAAA;IACd,uEAAuE;IACvE,YAAY,EAAE,MAAM,EAAE,CAAA;IACtB,OAAO,EAAE,MAAM,IAAI,CAAA;CACpB;AAED;;;;;;;;;;;GAWG;AACH,wBAAsB,4BAA4B,CAChD,IAAI,EAAE,MAAM,EAAE,EACd,OAAO,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,WAAW,KAAK,OAAO,CAAC,QAAQ,CAAC,GAChE,OAAO,CAAC,gBAAgB,CAAC,CAuD3B"}
|
|
@@ -3,6 +3,7 @@ import { tmpdir } from 'os';
|
|
|
3
3
|
import { basename, dirname, isAbsolute, join, normalize } from 'path';
|
|
4
4
|
import { archiveArtifactEntries, expandHomePath, readArtifactEntries, shouldExcludeArtifactPath, } from './artifact-archive.js';
|
|
5
5
|
import { authedFetch } from './http.js';
|
|
6
|
+
import { cleanupAll, throwWithCleanup } from './cleanup.js';
|
|
6
7
|
function scanRunnerDir(dir, relativeDir = '') {
|
|
7
8
|
const absoluteDir = relativeDir ? join(dir, relativeDir) : dir;
|
|
8
9
|
const result = { envFiles: [], symlinks: [] };
|
|
@@ -82,7 +83,7 @@ export async function verifyRunnerDirRegistered(input) {
|
|
|
82
83
|
'cannot be verified against it. Drop the flag to execute the registered bytes.');
|
|
83
84
|
}
|
|
84
85
|
if (registeredSha.toLowerCase() !== localSha.toLowerCase()) {
|
|
85
|
-
throw new Error(`Local runner bytes at ${dir} are not registered runner version ${input.runnerVersionId} ` +
|
|
86
|
+
throw new Error(`runner_version_bytes_mismatch: Local runner bytes at ${dir} are not registered runner version ${input.runnerVersionId} ` +
|
|
86
87
|
`(content sha ${localSha} != ${registeredSha}). Runs may only execute registered runner bytes ` +
|
|
87
88
|
'(ADR-007): register the directory first with `orizu runners push` ' +
|
|
88
89
|
'(use --session <session-id> inside a workspace session) and re-run against the new version, ' +
|
|
@@ -802,10 +803,7 @@ export async function verifyGepaRunnerDirsFromArgs(args, fetcher) {
|
|
|
802
803
|
let rewritten = [...args];
|
|
803
804
|
const verifiedDirs = [];
|
|
804
805
|
const cleanups = [];
|
|
805
|
-
const cleanup = () =>
|
|
806
|
-
for (const dispose of cleanups)
|
|
807
|
-
dispose();
|
|
808
|
-
};
|
|
806
|
+
const cleanup = () => cleanupAll(cleanups, 'Failed to clean verified runner snapshots');
|
|
809
807
|
try {
|
|
810
808
|
for (const pair of GEPA_RUNNER_FLAG_PAIRS) {
|
|
811
809
|
// Duplicate flags are refused outright (codex round 3, P1): argparse
|
|
@@ -841,8 +839,7 @@ export async function verifyGepaRunnerDirsFromArgs(args, fetcher) {
|
|
|
841
839
|
}
|
|
842
840
|
}
|
|
843
841
|
catch (error) {
|
|
844
|
-
cleanup
|
|
845
|
-
throw error;
|
|
842
|
+
throwWithCleanup(error, cleanups, 'Runner verification failed and snapshot cleanup also failed');
|
|
846
843
|
}
|
|
847
844
|
return { args: rewritten, verifiedDirs, cleanup };
|
|
848
845
|
}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
export declare const SKILLED_PROPOSER_BAKE_REPORT_FIELDS: readonly ["venv", "publishKey", "publishedVenv", "waitedForPublishLock", "pythonPathEntries", "executedPipArgv", "sslCertFile", "warnings", "marker", "python", "packageRoot", "manager", "lock", "vendoredGepaPath", "launcherVenv", "launcherSslCertFile"];
|
|
2
|
+
//# sourceMappingURL=skilled-proposer-bake-report.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"skilled-proposer-bake-report.d.ts","sourceRoot":"","sources":["../src/skilled-proposer-bake-report.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,mCAAmC,8PAA+P,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export const SKILLED_PROPOSER_BAKE_REPORT_FIELDS = ['venv', 'publishKey', 'publishedVenv', 'waitedForPublishLock', 'pythonPathEntries', 'executedPipArgv', 'sslCertFile', 'warnings', 'marker', 'python', 'packageRoot', 'manager', 'lock', 'vendoredGepaPath', 'launcherVenv', 'launcherSslCertFile'];
|
|
@@ -1,11 +1,33 @@
|
|
|
1
1
|
import type { GepaEngine } from './gepa-engine-dispatch.js';
|
|
2
|
+
interface SkilledProposerVenvReport {
|
|
3
|
+
venv: string;
|
|
4
|
+
publishKey: string;
|
|
5
|
+
sslCertFile: string | null;
|
|
6
|
+
pythonPathEntries: string[];
|
|
7
|
+
warnings: Array<{
|
|
8
|
+
code: string;
|
|
9
|
+
message: string;
|
|
10
|
+
}>;
|
|
11
|
+
waitedForPublishLock: boolean;
|
|
12
|
+
error?: string;
|
|
13
|
+
message?: string;
|
|
14
|
+
publishedVenv?: boolean | null;
|
|
15
|
+
executedPipArgv?: string[] | null;
|
|
16
|
+
}
|
|
2
17
|
export interface SkilledProposerLaunch {
|
|
3
18
|
python: string;
|
|
4
19
|
environment: NodeJS.ProcessEnv;
|
|
20
|
+
report?: SkilledProposerVenvReport;
|
|
5
21
|
}
|
|
6
22
|
export declare function spawnSkilledProposerChild(command: string, args: string[], engine: GepaEngine, environment: NodeJS.ProcessEnv): Promise<{
|
|
7
23
|
status: number | null;
|
|
8
24
|
error?: Error;
|
|
9
25
|
}>;
|
|
26
|
+
interface BakeCommandIo {
|
|
27
|
+
print: (value: string) => void;
|
|
28
|
+
printErr?: (value: string) => void;
|
|
29
|
+
}
|
|
30
|
+
export declare function skilledProposerBakeCommand(io: BakeCommandIo, verify?: boolean): number;
|
|
10
31
|
export declare function prepareSkilledProposerLaunch(python: string, engine: GepaEngine, environment: NodeJS.ProcessEnv): SkilledProposerLaunch;
|
|
32
|
+
export {};
|
|
11
33
|
//# sourceMappingURL=skilled-proposer-launch.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"skilled-proposer-launch.d.ts","sourceRoot":"","sources":["../src/skilled-proposer-launch.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,2BAA2B,CAAA;
|
|
1
|
+
{"version":3,"file":"skilled-proposer-launch.d.ts","sourceRoot":"","sources":["../src/skilled-proposer-launch.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,2BAA2B,CAAA;AAK3D,UAAU,yBAAyB;IACjC,IAAI,EAAE,MAAM,CAAA;IACZ,UAAU,EAAE,MAAM,CAAA;IAClB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAA;IAC1B,iBAAiB,EAAE,MAAM,EAAE,CAAA;IAC3B,QAAQ,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;IAClD,oBAAoB,EAAE,OAAO,CAAA;IAC7B,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,aAAa,CAAC,EAAE,OAAO,GAAG,IAAI,CAAA;IAC9B,eAAe,CAAC,EAAE,MAAM,EAAE,GAAG,IAAI,CAAA;CAClC;AACD,MAAM,WAAW,qBAAqB;IACpC,MAAM,EAAE,MAAM,CAAA;IACd,WAAW,EAAE,MAAM,CAAC,UAAU,CAAA;IAC9B,MAAM,CAAC,EAAE,yBAAyB,CAAA;CACnC;AAiBD,wBAAsB,yBAAyB,CAC7C,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,MAAM,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,CAAC,UAAU;YA4B9C,MAAM,GAAG,IAAI;YAAU,KAAK;GAUlE;AAwCD,UAAU,aAAa;IAAG,KAAK,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAAC,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAA;CAAE;AAQ9F,wBAAgB,0BAA0B,CAAC,EAAE,EAAE,aAAa,EAAE,MAAM,UAAQ,GAAG,MAAM,CAepF;AAED,wBAAgB,4BAA4B,CAC1C,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,UAAU,EAClB,WAAW,EAAE,MAAM,CAAC,UAAU,GAC7B,qBAAqB,CAyBvB"}
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import { spawn, spawnSync } from 'child_process';
|
|
2
|
-
import { mkdtempSync, rmSync, writeFileSync } from 'fs';
|
|
2
|
+
import { existsSync, mkdtempSync, readdirSync, rmSync, writeFileSync } from 'fs';
|
|
3
3
|
import { tmpdir } from 'os';
|
|
4
4
|
import { join } from 'path';
|
|
5
5
|
import { fileURLToPath } from 'url';
|
|
6
|
-
import { bundledOfficialGepaPythonPath } from './gepa-python-paths.js';
|
|
6
|
+
import { bundledOfficialGepaPythonPath, getGepaPythonPathEntries } from './gepa-python-paths.js';
|
|
7
7
|
import { sanitizeTerminalText } from './json-response.js';
|
|
8
|
+
import { SKILLED_PROPOSER_BAKE_REPORT_FIELDS } from './skilled-proposer-bake-report.js';
|
|
8
9
|
function materializeConfigPayload(engine, environment) {
|
|
9
10
|
const payload = environment.ORIZU_SKILLED_PROPOSER_CONFIG;
|
|
10
11
|
if (engine !== 'official' || environment.ORIZU_CANDIDATE_PROPOSER !== 'skilled-proposer' || payload === undefined)
|
|
@@ -67,12 +68,11 @@ export async function spawnSkilledProposerChild(command, args, engine, environme
|
|
|
67
68
|
cleanup();
|
|
68
69
|
}
|
|
69
70
|
}
|
|
70
|
-
function ensureSelectedSkilledProposerVenv(python, vendoredGepaPath)
|
|
71
|
+
function ensureSelectedSkilledProposerVenv(python, vendoredGepaPath, cacheRoot = existsSync('/opt/orizu/prebaked.json')
|
|
72
|
+
? '/opt/orizu/cache/skilled-proposer'
|
|
73
|
+
: join(process.cwd(), '.orizu', 'cache', 'skilled-proposer')) {
|
|
71
74
|
const manager = fileURLToPath(new URL('../scripts/ensure-skilled-proposer-venv.mjs', import.meta.url));
|
|
72
75
|
const lock = fileURLToPath(new URL('../requirements/skilled-proposer.lock', import.meta.url));
|
|
73
|
-
// This is a regenerable workspace cache. The manager's publish key further
|
|
74
|
-
// separates interpreters, platforms, and lock revisions inside it.
|
|
75
|
-
const cacheRoot = join(process.cwd(), '.orizu', 'cache', 'skilled-proposer');
|
|
76
76
|
const result = spawnSync(process.execPath, [manager, '--python', python, '--cache-root', cacheRoot, '--lock', lock,
|
|
77
77
|
'--vendored-gepa-path', vendoredGepaPath, '--json'], {
|
|
78
78
|
env: process.env,
|
|
@@ -98,6 +98,38 @@ function ensureSelectedSkilledProposerVenv(python, vendoredGepaPath) {
|
|
|
98
98
|
}
|
|
99
99
|
return report;
|
|
100
100
|
}
|
|
101
|
+
const packageRoot = join(fileURLToPath(new URL('.', import.meta.url)), '..');
|
|
102
|
+
const managerPath = join(packageRoot, 'scripts/ensure-skilled-proposer-venv.mjs');
|
|
103
|
+
const lockPath = join(packageRoot, 'requirements/skilled-proposer.lock');
|
|
104
|
+
const vendoredGepaPath = join(packageRoot, 'vendor/gepa-python/src');
|
|
105
|
+
const packagedPythonPathEntries = ['vendor/orizu-gepa/src', 'vendor/orizu-gepa-python/src', 'vendor/gepa-python/src'].map(path => join(packageRoot, path));
|
|
106
|
+
const bakedCacheRoot = '/opt/orizu/cache/skilled-proposer';
|
|
107
|
+
export function skilledProposerBakeCommand(io, verify = false) {
|
|
108
|
+
try {
|
|
109
|
+
const python = process.env.PYTHON || 'python3';
|
|
110
|
+
if (!verify) {
|
|
111
|
+
io.print(JSON.stringify(ensureSelectedSkilledProposerVenv(python, vendoredGepaPath, bakedCacheRoot)));
|
|
112
|
+
return 0;
|
|
113
|
+
}
|
|
114
|
+
if (!readdirSync(join(bakedCacheRoot, 'venvs'), { withFileTypes: true }).some(entry => entry.isDirectory() && existsSync(join(bakedCacheRoot, 'venvs', entry.name, '.orizu-skilled-proposer-venv.json'))))
|
|
115
|
+
throw new Error('ALI_1588_VENV_MARKER_MISSING');
|
|
116
|
+
const environment = { ...process.env, ORIZU_CANDIDATE_PROPOSER: 'skilled-proposer' };
|
|
117
|
+
const launch = prepareSkilledProposerLaunch(python, 'official', environment);
|
|
118
|
+
const report = launch.report;
|
|
119
|
+
if (report.publishedVenv !== false || report.executedPipArgv !== null)
|
|
120
|
+
throw new Error('ALI_1588_DEPENDENCY_SETUP_NOT_REUSED');
|
|
121
|
+
const pythonPathEntries = getGepaPythonPathEntries(undefined);
|
|
122
|
+
if (JSON.stringify(pythonPathEntries) !== JSON.stringify(packagedPythonPathEntries))
|
|
123
|
+
throw new Error('ALI_1588_PYTHON_ROOT_MISSING');
|
|
124
|
+
const completeReport = { ...report, pythonPathEntries, marker: 'ALI_1588_DEPENDENCY_SETUP_REUSED', python: launch.python, packageRoot, manager: managerPath, lock: lockPath, vendoredGepaPath, launcherVenv: launch.environment.ORIZU_SKILLED_PROPOSER_VENV ?? null, launcherSslCertFile: launch.environment.SSL_CERT_FILE ?? null };
|
|
125
|
+
io.print(JSON.stringify(Object.fromEntries(SKILLED_PROPOSER_BAKE_REPORT_FIELDS.map(key => [key, completeReport[key]]))));
|
|
126
|
+
return 0;
|
|
127
|
+
}
|
|
128
|
+
catch (error) {
|
|
129
|
+
io.printErr?.(`${error instanceof Error ? error.message : String(error)}\n`);
|
|
130
|
+
return 1;
|
|
131
|
+
}
|
|
132
|
+
}
|
|
101
133
|
export function prepareSkilledProposerLaunch(python, engine, environment) {
|
|
102
134
|
if (engine !== 'official' || environment.ORIZU_CANDIDATE_PROPOSER !== 'skilled-proposer') {
|
|
103
135
|
return { python, environment };
|
|
@@ -120,5 +152,6 @@ export function prepareSkilledProposerLaunch(python, engine, environment) {
|
|
|
120
152
|
? join(report.venv, 'Scripts', 'python.exe')
|
|
121
153
|
: join(report.venv, 'bin', 'python'),
|
|
122
154
|
environment,
|
|
155
|
+
report,
|
|
123
156
|
};
|
|
124
157
|
}
|