orizu 0.5.19 → 0.5.20
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 +23 -0
- package/dist/diff-comments-cli.js +18 -2
- package/dist/gepa-engine-dispatch.js +261 -0
- package/dist/gepa-python-command.js +26 -0
- package/dist/gepa-python-paths.js +39 -0
- package/dist/help.js +4 -4
- package/dist/index.js +34 -40
- package/dist/markdown-report-input.js +15 -1
- package/dist/prompt-length-wire.js +2 -2
- package/dist/prompt-report-cli.js +2 -2
- package/dist/report-markdown-blankness.js +6 -0
- package/dist/report-replacement-warning.js +31 -0
- package/package.json +2 -2
- package/scripts/build-cli-dist.mjs +30 -0
- package/scripts/orizu-source-checkout.d.mts +1 -0
- package/scripts/orizu-source-checkout.mjs +10 -0
- package/scripts/vendor-gepa-python.mjs +187 -4
- package/src/diff-comments-cli.ts +37 -3
- package/src/gepa-engine-dispatch.ts +300 -0
- package/src/gepa-python-command.ts +31 -0
- package/src/gepa-python-paths.ts +53 -0
- package/src/help.ts +4 -4
- package/src/index.ts +35 -43
- package/src/markdown-report-input.ts +19 -1
- package/src/prompt-length-wire.ts +1 -1
- package/src/prompt-report-cli.ts +2 -2
- package/src/report-markdown-blankness.ts +6 -0
- package/src/report-replacement-warning.ts +35 -0
- package/vendor/gepa-python/LICENSE +7 -0
- package/vendor/gepa-python/manifest.json +107 -0
- package/vendor/gepa-python/src/gepa/__init__.py +22 -0
- package/vendor/gepa-python/src/gepa/adapters/__init__.py +0 -0
- package/vendor/gepa-python/src/gepa/adapters/anymaths_adapter/__init__.py +1 -0
- package/vendor/gepa-python/src/gepa/adapters/anymaths_adapter/anymaths_adapter.py +174 -0
- package/vendor/gepa-python/src/gepa/adapters/confidence_adapter/__init__.py +26 -0
- package/vendor/gepa-python/src/gepa/adapters/confidence_adapter/confidence_adapter.py +618 -0
- package/vendor/gepa-python/src/gepa/adapters/confidence_adapter/scoring.py +206 -0
- package/vendor/gepa-python/src/gepa/adapters/default_adapter/__init__.py +0 -0
- package/vendor/gepa-python/src/gepa/adapters/default_adapter/default_adapter.py +206 -0
- package/vendor/gepa-python/src/gepa/adapters/dspy_adapter/__init__.py +0 -0
- package/vendor/gepa-python/src/gepa/adapters/dspy_adapter/dspy_adapter.py +525 -0
- package/vendor/gepa-python/src/gepa/adapters/dspy_adapter/instruction_proposal.py +500 -0
- package/vendor/gepa-python/src/gepa/adapters/dspy_full_program_adapter/__init__.py +6 -0
- package/vendor/gepa-python/src/gepa/adapters/dspy_full_program_adapter/dspy_program_proposal_signature.py +137 -0
- package/vendor/gepa-python/src/gepa/adapters/dspy_full_program_adapter/full_program_adapter.py +269 -0
- package/vendor/gepa-python/src/gepa/adapters/generic_rag_adapter/__init__.py +56 -0
- package/vendor/gepa-python/src/gepa/adapters/generic_rag_adapter/evaluation_metrics.py +226 -0
- package/vendor/gepa-python/src/gepa/adapters/generic_rag_adapter/generic_rag_adapter.py +496 -0
- package/vendor/gepa-python/src/gepa/adapters/generic_rag_adapter/rag_pipeline.py +238 -0
- package/vendor/gepa-python/src/gepa/adapters/generic_rag_adapter/vector_store_interface.py +212 -0
- package/vendor/gepa-python/src/gepa/adapters/generic_rag_adapter/vector_stores/__init__.py +2 -0
- package/vendor/gepa-python/src/gepa/adapters/generic_rag_adapter/vector_stores/chroma_store.py +196 -0
- package/vendor/gepa-python/src/gepa/adapters/generic_rag_adapter/vector_stores/lancedb_store.py +422 -0
- package/vendor/gepa-python/src/gepa/adapters/generic_rag_adapter/vector_stores/milvus_store.py +409 -0
- package/vendor/gepa-python/src/gepa/adapters/generic_rag_adapter/vector_stores/qdrant_store.py +368 -0
- package/vendor/gepa-python/src/gepa/adapters/generic_rag_adapter/vector_stores/weaviate_store.py +418 -0
- package/vendor/gepa-python/src/gepa/adapters/langchain_adapter/__init__.py +11 -0
- package/vendor/gepa-python/src/gepa/adapters/langchain_adapter/langchain_adapter.py +261 -0
- package/vendor/gepa-python/src/gepa/adapters/mcp_adapter/__init__.py +37 -0
- package/vendor/gepa-python/src/gepa/adapters/mcp_adapter/mcp_adapter.py +693 -0
- package/vendor/gepa-python/src/gepa/adapters/mcp_adapter/mcp_client.py +364 -0
- package/vendor/gepa-python/src/gepa/adapters/optimize_anything_adapter/optimize_anything_adapter.py +879 -0
- package/vendor/gepa-python/src/gepa/adapters/terminal_bench_adapter/__init__.py +0 -0
- package/vendor/gepa-python/src/gepa/adapters/terminal_bench_adapter/terminal_bench_adapter.py +217 -0
- package/vendor/gepa-python/src/gepa/api.py +468 -0
- package/vendor/gepa-python/src/gepa/core/__init__.py +0 -0
- package/vendor/gepa-python/src/gepa/core/adapter.py +227 -0
- package/vendor/gepa-python/src/gepa/core/callbacks.py +551 -0
- package/vendor/gepa-python/src/gepa/core/data_loader.py +74 -0
- package/vendor/gepa-python/src/gepa/core/engine.py +1025 -0
- package/vendor/gepa-python/src/gepa/core/result.py +271 -0
- package/vendor/gepa-python/src/gepa/core/state.py +706 -0
- package/vendor/gepa-python/src/gepa/examples/__init__.py +0 -0
- package/vendor/gepa-python/src/gepa/examples/aime.py +24 -0
- package/vendor/gepa-python/src/gepa/examples/anymaths-bench/eval_default.py +111 -0
- package/vendor/gepa-python/src/gepa/examples/anymaths-bench/train_anymaths.py +177 -0
- package/vendor/gepa-python/src/gepa/examples/mcp_adapter/__init__.py +4 -0
- package/vendor/gepa-python/src/gepa/examples/mcp_adapter/mcp_optimization_example.py +456 -0
- package/vendor/gepa-python/src/gepa/examples/rag_adapter/__init__.py +9 -0
- package/vendor/gepa-python/src/gepa/examples/rag_adapter/rag_optimization.py +824 -0
- package/vendor/gepa-python/src/gepa/examples/terminal-bench/train_terminus.py +161 -0
- package/vendor/gepa-python/src/gepa/gepa_utils.py +117 -0
- package/vendor/gepa-python/src/gepa/gskill/__init__.py +1 -0
- package/vendor/gepa-python/src/gepa/gskill/gskill/__init__.py +0 -0
- package/vendor/gepa-python/src/gepa/gskill/gskill/cost_tracker.py +194 -0
- package/vendor/gepa-python/src/gepa/gskill/gskill/evaluate/__init__.py +0 -0
- package/vendor/gepa-python/src/gepa/gskill/gskill/evaluate/claude_code.py +1117 -0
- package/vendor/gepa-python/src/gepa/gskill/gskill/evaluate/claude_code_skills.py +613 -0
- package/vendor/gepa-python/src/gepa/gskill/gskill/evaluate/mini_swe_agent.py +440 -0
- package/vendor/gepa-python/src/gepa/gskill/gskill/experiment_logger.py +367 -0
- package/vendor/gepa-python/src/gepa/gskill/gskill/swe_fitness_fn.py +209 -0
- package/vendor/gepa-python/src/gepa/gskill/gskill/swe_harness.py +352 -0
- package/vendor/gepa-python/src/gepa/gskill/gskill/train_optimize_anything.py +830 -0
- package/vendor/gepa-python/src/gepa/image.py +104 -0
- package/vendor/gepa-python/src/gepa/lm.py +261 -0
- package/vendor/gepa-python/src/gepa/logging/__init__.py +0 -0
- package/vendor/gepa-python/src/gepa/logging/experiment_tracker.py +457 -0
- package/vendor/gepa-python/src/gepa/logging/logger.py +75 -0
- package/vendor/gepa-python/src/gepa/logging/utils.py +130 -0
- package/vendor/gepa-python/src/gepa/optimize_anything.py +1701 -0
- package/vendor/gepa-python/src/gepa/proposer/__init__.py +0 -0
- package/vendor/gepa-python/src/gepa/proposer/base.py +53 -0
- package/vendor/gepa-python/src/gepa/proposer/merge.py +403 -0
- package/vendor/gepa-python/src/gepa/proposer/reflective_mutation/__init__.py +0 -0
- package/vendor/gepa-python/src/gepa/proposer/reflective_mutation/base.py +64 -0
- package/vendor/gepa-python/src/gepa/proposer/reflective_mutation/reflection_lm.py +178 -0
- package/vendor/gepa-python/src/gepa/proposer/reflective_mutation/reflective_mutation.py +641 -0
- package/vendor/gepa-python/src/gepa/py.typed +0 -0
- package/vendor/gepa-python/src/gepa/strategies/__init__.py +0 -0
- package/vendor/gepa-python/src/gepa/strategies/acceptance.py +66 -0
- package/vendor/gepa-python/src/gepa/strategies/batch_sampler.py +103 -0
- package/vendor/gepa-python/src/gepa/strategies/candidate_selector.py +82 -0
- package/vendor/gepa-python/src/gepa/strategies/component_selector.py +36 -0
- package/vendor/gepa-python/src/gepa/strategies/eval_policy.py +64 -0
- package/vendor/gepa-python/src/gepa/strategies/instruction_proposal.py +153 -0
- package/vendor/gepa-python/src/gepa/strategies/proposal_sampling.py +128 -0
- package/vendor/gepa-python/src/gepa/strategies/proposal_selection.py +84 -0
- package/vendor/gepa-python/src/gepa/utils/__init__.py +63 -0
- package/vendor/gepa-python/src/gepa/utils/code_execution.py +626 -0
- package/vendor/gepa-python/src/gepa/utils/stdio_capture.py +145 -0
- package/vendor/gepa-python/src/gepa/utils/stop_condition.py +230 -0
- package/vendor/gepa-python/src/gepa/visualization.py +359 -0
- package/vendor/orizu-gepa/pyproject.toml +18 -0
- package/vendor/orizu-gepa/src/orizu_gepa_connector/__init__.py +8 -0
- package/vendor/orizu-gepa/src/orizu_gepa_connector/__main__.py +5 -0
- package/vendor/orizu-gepa/src/orizu_gepa_connector/adapter.py +132 -0
- package/vendor/orizu-gepa/src/orizu_gepa_connector/callbacks.py +652 -0
- package/vendor/orizu-gepa/src/orizu_gepa_connector/cli.py +7 -0
- package/vendor/orizu-gepa/src/orizu_gepa_connector/engine.py +177 -0
- package/vendor/orizu-gepa/src/orizu_gepa_connector/preflight.py +64 -0
- package/vendor/orizu-gepa/src/orizu_gepa_connector/reflection.py +106 -0
- package/vendor/orizu-gepa/src/orizu_gepa_connector/runtime.py +643 -0
- package/vendor/orizu-gepa/src/orizu_gepa_connector/stop_conditions.py +38 -0
- package/vendor/orizu-gepa/src/orizu_gepa_connector/translator.py +202 -0
- package/vendor/orizu-gepa-python/pyproject.toml +1 -1
- package/vendor/orizu-gepa-python/src/orizu_gepa/cli.py +1 -0
- package/vendor/orizu-gepa-python/src/orizu_gepa/local_log.py +49 -0
- package/vendor/skills/orizu-cli/SKILL.md +1 -1
- package/vendor/skills/orizu-cli/references/optimization-reports.md +1 -1
- package/vendor/skills/orizu-cli/references/optimization-with-gepa.md +1 -1
- package/vendor/skills/orizu-cli/references/prompt-control-plane.md +6 -3
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ALI-1452: a shared, human-readable warning for a replaced prompt-version
|
|
3
|
+
* report on a push/draft response.
|
|
4
|
+
*
|
|
5
|
+
* Re-pushing an unchanged prompt with a report deliberately replaces the
|
|
6
|
+
* version's existing report (reports are correctable; versions are immutable).
|
|
7
|
+
* The server discloses that replacement as `report_replaced:
|
|
8
|
+
* { source_name, updated_at } | null`; this turns a non-null disclosure into
|
|
9
|
+
* the stderr warning line the push commands print. JSON mode prints nothing —
|
|
10
|
+
* the payload already carries `report_replaced`.
|
|
11
|
+
*/
|
|
12
|
+
function isRecord(value) {
|
|
13
|
+
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* A one-line warning when a push response discloses that it replaced an
|
|
17
|
+
* existing report, or null when nothing was replaced (or no report was sent).
|
|
18
|
+
*/
|
|
19
|
+
export function reportReplacementWarning(data) {
|
|
20
|
+
const replaced = data.report_replaced;
|
|
21
|
+
if (!isRecord(replaced))
|
|
22
|
+
return null;
|
|
23
|
+
const sourceName = typeof replaced.source_name === 'string'
|
|
24
|
+
? replaced.source_name
|
|
25
|
+
: 'unknown source';
|
|
26
|
+
const updatedAt = typeof replaced.updated_at === 'string'
|
|
27
|
+
? replaced.updated_at
|
|
28
|
+
: 'unknown time';
|
|
29
|
+
return ('Warning: replaced the existing report for this version ' +
|
|
30
|
+
`(${sourceName}, last updated ${updatedAt})`);
|
|
31
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "orizu",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.20",
|
|
4
4
|
"private": false,
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
],
|
|
17
17
|
"scripts": {
|
|
18
18
|
"build": "tsc -p tsconfig.json",
|
|
19
|
-
"prepack": "node scripts/vendor-gepa-python.mjs && node scripts/vendor-orizu-skill.mjs",
|
|
19
|
+
"prepack": "node scripts/build-cli-dist.mjs && node scripts/vendor-gepa-python.mjs && node scripts/vendor-orizu-skill.mjs",
|
|
20
20
|
"postpack": "node scripts/vendor-gepa-python.mjs --clean && node scripts/vendor-orizu-skill.mjs --clean"
|
|
21
21
|
},
|
|
22
22
|
"dependencies": {
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { existsSync, rmSync } from 'node:fs'
|
|
2
|
+
import { spawnSync } from 'node:child_process'
|
|
3
|
+
import { dirname, resolve } from 'node:path'
|
|
4
|
+
import { fileURLToPath } from 'node:url'
|
|
5
|
+
|
|
6
|
+
import { isOrizuSourceCheckout } from './orizu-source-checkout.mjs'
|
|
7
|
+
|
|
8
|
+
const scriptDir = dirname(fileURLToPath(import.meta.url))
|
|
9
|
+
const cliRoot = resolve(scriptDir, '..')
|
|
10
|
+
const repoRoot = resolve(cliRoot, '..', '..')
|
|
11
|
+
const packedEntrypoint = resolve(cliRoot, 'dist', 'index.js')
|
|
12
|
+
|
|
13
|
+
// A source checkout has the compiler and must always rebuild before packing so
|
|
14
|
+
// ignored dist cannot carry an old CLI. A published tarball has no dev compiler;
|
|
15
|
+
// it may be repacked only when it already carries the built entrypoint.
|
|
16
|
+
if (!isOrizuSourceCheckout(resolve(repoRoot, 'package.json'))) {
|
|
17
|
+
if (!existsSync(packedEntrypoint)) {
|
|
18
|
+
throw new Error('Unable to pack CLI: published package is missing dist/index.js')
|
|
19
|
+
}
|
|
20
|
+
process.exit(0)
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
const npm = process.platform === 'win32' ? 'npm.cmd' : 'npm'
|
|
24
|
+
// Delete old compiler output first: npm pack must never retain a module whose
|
|
25
|
+
// TypeScript source was renamed or removed since the previous build.
|
|
26
|
+
rmSync(resolve(cliRoot, 'dist'), { recursive: true, force: true })
|
|
27
|
+
const result = spawnSync(npm, ['run', 'build'], { cwd: cliRoot, stdio: 'inherit' })
|
|
28
|
+
if (result.status !== 0) {
|
|
29
|
+
throw new Error(`Unable to build CLI dist before packing: ${result.error?.message || 'npm run build failed'}`)
|
|
30
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export function isOrizuSourceCheckout(packageJsonPath: string): boolean
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { readFileSync } from 'node:fs'
|
|
2
|
+
|
|
3
|
+
/** True only for the Orizu monorepo, never merely for a consumer Git checkout. */
|
|
4
|
+
export function isOrizuSourceCheckout(packageJsonPath) {
|
|
5
|
+
try {
|
|
6
|
+
return JSON.parse(readFileSync(packageJsonPath, 'utf8')).name === 'orizu'
|
|
7
|
+
} catch {
|
|
8
|
+
return false
|
|
9
|
+
}
|
|
10
|
+
}
|
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
import { cpSync, existsSync, mkdirSync, rmSync } from 'node:fs'
|
|
1
|
+
import { cpSync, existsSync, mkdirSync, readdirSync, rmSync, statSync, writeFileSync, readFileSync } from 'node:fs'
|
|
2
|
+
import { createHash } from 'node:crypto'
|
|
3
|
+
import { spawnSync } from 'node:child_process'
|
|
2
4
|
import { dirname, resolve } from 'node:path'
|
|
3
5
|
import { fileURLToPath } from 'node:url'
|
|
4
6
|
|
|
@@ -7,32 +9,194 @@ const cliRoot = resolve(scriptDir, '..')
|
|
|
7
9
|
const repoRoot = resolve(cliRoot, '..', '..')
|
|
8
10
|
const sourceRoot = resolve(repoRoot, 'packages', 'orizu-gepa-python')
|
|
9
11
|
const vendorRoot = resolve(cliRoot, 'vendor', 'orizu-gepa-python')
|
|
12
|
+
const connectorSourceRoot = resolve(repoRoot, 'packages', 'orizu-gepa')
|
|
13
|
+
const connectorVendorRoot = resolve(cliRoot, 'vendor', 'orizu-gepa')
|
|
14
|
+
const officialArchive = resolve(cliRoot, 'gepa-python-source.zip')
|
|
15
|
+
const officialVendorRoot = resolve(cliRoot, 'vendor', 'gepa-python')
|
|
10
16
|
const shouldClean = process.argv.includes('--clean')
|
|
17
|
+
const shouldRefresh = process.argv.includes('--refresh')
|
|
18
|
+
const archiveArgumentIndex = process.argv.indexOf('--archive')
|
|
19
|
+
const suppliedArchive = archiveArgumentIndex === -1
|
|
20
|
+
? null
|
|
21
|
+
: process.argv[archiveArgumentIndex + 1]
|
|
11
22
|
const sourceSrc = resolve(sourceRoot, 'src')
|
|
12
23
|
const sourcePyproject = resolve(sourceRoot, 'pyproject.toml')
|
|
13
24
|
const sourceManifest = resolve(sourceRoot, 'manifest.json')
|
|
14
25
|
const vendoredSrc = resolve(vendorRoot, 'src')
|
|
15
26
|
const vendoredPyproject = resolve(vendorRoot, 'pyproject.toml')
|
|
16
27
|
const vendoredManifest = resolve(vendorRoot, 'manifest.json')
|
|
28
|
+
const officialVendoredManifest = resolve(officialVendorRoot, 'manifest.json')
|
|
29
|
+
const officialVendoredGepa = resolve(officialVendorRoot, 'src', 'gepa', '__init__.py')
|
|
30
|
+
const GEPA_VERSION = '0.1.4'
|
|
31
|
+
const GEPA_RELEASE_COMMIT = '8b0ce6cd99a234f6b74daf37558a2ac0ce18f975'
|
|
32
|
+
const GEPA_WHEEL_FILENAME = 'gepa-0.1.4-py3-none-any.whl'
|
|
33
|
+
const GEPA_WHEEL_SHA256 = '12b971039599625c156d2231f6d72a29c31a22e9c237689459b5f1a3c353f532'
|
|
17
34
|
const hasSourcePackage = existsSync(sourceSrc)
|
|
18
35
|
&& existsSync(sourcePyproject)
|
|
19
36
|
&& existsSync(sourceManifest)
|
|
37
|
+
const hasConnectorSourcePackage = existsSync(resolve(connectorSourceRoot, 'src'))
|
|
38
|
+
&& existsSync(resolve(connectorSourceRoot, 'pyproject.toml'))
|
|
20
39
|
const hasVendoredPackage = existsSync(vendoredSrc)
|
|
21
40
|
&& existsSync(vendoredPyproject)
|
|
22
41
|
&& existsSync(vendoredManifest)
|
|
42
|
+
const hasVendoredConnectorPackage = existsSync(resolve(connectorVendorRoot, 'src', 'orizu_gepa_connector', '__main__.py'))
|
|
43
|
+
&& existsSync(resolve(connectorVendorRoot, 'pyproject.toml'))
|
|
44
|
+
const hasOfficialVendoredPackage = existsSync(officialVendoredManifest)
|
|
45
|
+
&& existsSync(officialVendoredGepa)
|
|
46
|
+
|
|
47
|
+
function sha256File(path) {
|
|
48
|
+
return createHash('sha256').update(readFileSync(path)).digest('hex')
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function assertPinnedGepaArchive(path) {
|
|
52
|
+
if (!existsSync(path)) {
|
|
53
|
+
throw new Error(`Unable to vendor official GEPA: source archive not found at ${path}`)
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
const actualSha256 = sha256File(path)
|
|
57
|
+
if (actualSha256 !== GEPA_WHEEL_SHA256) {
|
|
58
|
+
throw new Error(
|
|
59
|
+
`Official GEPA source archive sha256 mismatch: expected ${GEPA_WHEEL_SHA256}, got ${actualSha256}`
|
|
60
|
+
)
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function collectFileHashes(root, prefix = '') {
|
|
65
|
+
const files = {}
|
|
66
|
+
for (const entry of readdirSync(root).sort()) {
|
|
67
|
+
const path = resolve(root, entry)
|
|
68
|
+
const relativePath = prefix ? `${prefix}/${entry}` : entry
|
|
69
|
+
if (statSync(path).isDirectory()) {
|
|
70
|
+
Object.assign(files, collectFileHashes(path, relativePath))
|
|
71
|
+
} else {
|
|
72
|
+
files[relativePath] = sha256File(path)
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
return files
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
function assertOfficialVendoredManifest() {
|
|
79
|
+
let manifest
|
|
80
|
+
try {
|
|
81
|
+
manifest = JSON.parse(readFileSync(officialVendoredManifest, 'utf8'))
|
|
82
|
+
} catch (error) {
|
|
83
|
+
throw new Error(`Official GEPA vendored manifest is unreadable: ${error.message}`)
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
if (!manifest.files || typeof manifest.files !== 'object' || Array.isArray(manifest.files)) {
|
|
87
|
+
throw new Error('Official GEPA vendored manifest is missing file hashes')
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
const actualFiles = collectFileHashes(officialVendorRoot)
|
|
91
|
+
delete actualFiles['manifest.json']
|
|
92
|
+
const expectedEntries = Object.entries(manifest.files).sort(([left], [right]) => left.localeCompare(right))
|
|
93
|
+
const actualEntries = Object.entries(actualFiles).sort(([left], [right]) => left.localeCompare(right))
|
|
94
|
+
if (expectedEntries.length !== actualEntries.length) {
|
|
95
|
+
throw new Error('Official GEPA vendored manifest file count does not match extracted files')
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
for (let index = 0; index < expectedEntries.length; index += 1) {
|
|
99
|
+
const [expectedPath, expectedSha256] = expectedEntries[index]
|
|
100
|
+
const [actualPath, actualSha256] = actualEntries[index]
|
|
101
|
+
if (expectedPath !== actualPath || expectedSha256 !== actualSha256) {
|
|
102
|
+
throw new Error(`Official GEPA vendored manifest mismatch at ${expectedPath}`)
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
function extractPinnedGepa(archivePath) {
|
|
108
|
+
const extractor = String.raw`
|
|
109
|
+
from pathlib import Path, PurePosixPath
|
|
110
|
+
import shutil
|
|
111
|
+
import sys
|
|
112
|
+
import zipfile
|
|
113
|
+
|
|
114
|
+
archive_path = Path(sys.argv[1])
|
|
115
|
+
destination_root = Path(sys.argv[2])
|
|
116
|
+
license_member = 'gepa-0.1.4.dist-info/licenses/LICENSE'
|
|
117
|
+
|
|
118
|
+
with zipfile.ZipFile(archive_path) as archive:
|
|
119
|
+
for member in archive.infolist():
|
|
120
|
+
if member.is_dir():
|
|
121
|
+
continue
|
|
122
|
+
if member.filename.startswith('gepa/'):
|
|
123
|
+
relative_path = PurePosixPath('src') / PurePosixPath(member.filename)
|
|
124
|
+
elif member.filename == license_member:
|
|
125
|
+
relative_path = PurePosixPath('LICENSE')
|
|
126
|
+
else:
|
|
127
|
+
continue
|
|
128
|
+
if relative_path.is_absolute() or '..' in relative_path.parts:
|
|
129
|
+
raise ValueError(f'unsafe GEPA wheel member: {member.filename}')
|
|
130
|
+
destination = destination_root.joinpath(*relative_path.parts)
|
|
131
|
+
destination.parent.mkdir(parents=True, exist_ok=True)
|
|
132
|
+
with archive.open(member) as source, destination.open('wb') as output:
|
|
133
|
+
shutil.copyfileobj(source, output)
|
|
134
|
+
`
|
|
135
|
+
const result = spawnSync('python3', ['-c', extractor, archivePath, officialVendorRoot], {
|
|
136
|
+
encoding: 'utf8',
|
|
137
|
+
})
|
|
138
|
+
if (result.status !== 0) {
|
|
139
|
+
const details = result.error?.message || result.stderr || result.stdout || 'no subprocess output'
|
|
140
|
+
throw new Error(`Unable to extract verified official GEPA wheel; python3 is required: ${details}`)
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
function vendorOfficialGepa(archivePath) {
|
|
145
|
+
assertPinnedGepaArchive(archivePath)
|
|
146
|
+
rmSync(officialVendorRoot, { recursive: true, force: true })
|
|
147
|
+
mkdirSync(officialVendorRoot, { recursive: true })
|
|
148
|
+
extractPinnedGepa(archivePath)
|
|
149
|
+
|
|
150
|
+
const files = collectFileHashes(officialVendorRoot)
|
|
151
|
+
writeFileSync(officialVendoredManifest, `${JSON.stringify({
|
|
152
|
+
schemaVersion: 'gepa-vendor.v1',
|
|
153
|
+
upstream: {
|
|
154
|
+
package: 'gepa',
|
|
155
|
+
version: GEPA_VERSION,
|
|
156
|
+
repositoryCommit: GEPA_RELEASE_COMMIT,
|
|
157
|
+
wheel: {
|
|
158
|
+
filename: GEPA_WHEEL_FILENAME,
|
|
159
|
+
sha256: GEPA_WHEEL_SHA256,
|
|
160
|
+
},
|
|
161
|
+
},
|
|
162
|
+
files,
|
|
163
|
+
}, null, 2)}\n`)
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
if (archiveArgumentIndex !== -1 && (!suppliedArchive || suppliedArchive.startsWith('--'))) {
|
|
167
|
+
throw new Error('Expected a source archive path after --archive')
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
if (shouldRefresh) {
|
|
171
|
+
if (!suppliedArchive) {
|
|
172
|
+
throw new Error('Refreshing official GEPA requires --archive <verified-wheel-path>')
|
|
173
|
+
}
|
|
174
|
+
assertPinnedGepaArchive(suppliedArchive)
|
|
175
|
+
cpSync(suppliedArchive, officialArchive)
|
|
176
|
+
}
|
|
23
177
|
|
|
24
178
|
if (shouldClean) {
|
|
25
179
|
if (hasSourcePackage) {
|
|
26
180
|
rmSync(vendorRoot, { recursive: true, force: true })
|
|
27
181
|
}
|
|
182
|
+
if (hasConnectorSourcePackage) {
|
|
183
|
+
rmSync(connectorVendorRoot, { recursive: true, force: true })
|
|
184
|
+
}
|
|
185
|
+
if (hasSourcePackage || hasConnectorSourcePackage) {
|
|
186
|
+
rmSync(officialVendorRoot, { recursive: true, force: true })
|
|
187
|
+
}
|
|
28
188
|
process.exit(0)
|
|
29
189
|
}
|
|
30
190
|
|
|
31
|
-
if (!hasSourcePackage) {
|
|
32
|
-
if (hasVendoredPackage) {
|
|
191
|
+
if (!hasSourcePackage || !hasConnectorSourcePackage) {
|
|
192
|
+
if (hasVendoredPackage && hasVendoredConnectorPackage && hasOfficialVendoredPackage) {
|
|
193
|
+
assertOfficialVendoredManifest()
|
|
33
194
|
process.exit(0)
|
|
34
195
|
}
|
|
35
|
-
|
|
196
|
+
if (hasVendoredPackage || hasVendoredConnectorPackage || hasOfficialVendoredPackage) {
|
|
197
|
+
throw new Error('Unable to vendor GEPA packages: vendored legacy, connector, or official package is incomplete')
|
|
198
|
+
}
|
|
199
|
+
throw new Error(`Unable to vendor GEPA packages: source package not found at ${sourceRoot} or ${connectorSourceRoot}`)
|
|
36
200
|
}
|
|
37
201
|
|
|
38
202
|
rmSync(vendorRoot, { recursive: true, force: true })
|
|
@@ -52,3 +216,22 @@ cpSync(sourceSrc, resolve(vendorRoot, 'src'), {
|
|
|
52
216
|
&& !normalizedPath.endsWith('/.DS_Store')
|
|
53
217
|
},
|
|
54
218
|
})
|
|
219
|
+
|
|
220
|
+
rmSync(connectorVendorRoot, { recursive: true, force: true })
|
|
221
|
+
mkdirSync(connectorVendorRoot, { recursive: true })
|
|
222
|
+
cpSync(resolve(connectorSourceRoot, 'pyproject.toml'), resolve(connectorVendorRoot, 'pyproject.toml'))
|
|
223
|
+
cpSync(resolve(connectorSourceRoot, 'src'), resolve(connectorVendorRoot, 'src'), {
|
|
224
|
+
recursive: true,
|
|
225
|
+
filter: sourcePath => {
|
|
226
|
+
const normalizedPath = sourcePath.replace(/\\/g, '/')
|
|
227
|
+
return !normalizedPath.endsWith('/__pycache__')
|
|
228
|
+
&& !normalizedPath.includes('/__pycache__/')
|
|
229
|
+
&& !normalizedPath.endsWith('.pyc')
|
|
230
|
+
&& !normalizedPath.endsWith('.pyo')
|
|
231
|
+
&& !normalizedPath.endsWith('/.pytest_cache')
|
|
232
|
+
&& !normalizedPath.includes('/.pytest_cache/')
|
|
233
|
+
&& !normalizedPath.endsWith('/.DS_Store')
|
|
234
|
+
},
|
|
235
|
+
})
|
|
236
|
+
|
|
237
|
+
vendorOfficialGepa(suppliedArchive ?? officialArchive)
|
package/src/diff-comments-cli.ts
CHANGED
|
@@ -50,7 +50,11 @@ interface DiffCommentPayloadPairContext {
|
|
|
50
50
|
bodies: { from: string; to: string } | null
|
|
51
51
|
degraded: { reason: DiffCommentContextUnavailableReason } | null
|
|
52
52
|
lengthStats: CliLengthStatsPair | null
|
|
53
|
-
lengthDelta:
|
|
53
|
+
lengthDelta: (
|
|
54
|
+
Partial<Record<keyof Omit<CliLengthDelta, 'splitUnavailableReason'>, unknown>> & {
|
|
55
|
+
splitUnavailableReason?: unknown
|
|
56
|
+
}
|
|
57
|
+
) | null
|
|
54
58
|
lengthDeltaUnavailableReason?: CliLengthMeasurementUnavailableReason
|
|
55
59
|
comments: DiffCommentPayloadComment[]
|
|
56
60
|
}
|
|
@@ -76,6 +80,12 @@ interface DiffCommentsPayload {
|
|
|
76
80
|
pairs: DiffCommentPayloadPair[]
|
|
77
81
|
}
|
|
78
82
|
|
|
83
|
+
interface RenderableLengthMetricDelta {
|
|
84
|
+
removed: number | null
|
|
85
|
+
added: number | null
|
|
86
|
+
net: number | null
|
|
87
|
+
}
|
|
88
|
+
|
|
79
89
|
export interface DiffCommentsCliContext {
|
|
80
90
|
getArg: (name: string) => string | null
|
|
81
91
|
rejectDashPrefixedOptionValue: (name: string, value: string | null) => void
|
|
@@ -171,6 +181,22 @@ function formatDeltaValue(
|
|
|
171
181
|
return metric === 'tokens' ? `~${formatted}` : formatted
|
|
172
182
|
}
|
|
173
183
|
|
|
184
|
+
function isLengthMetricDelta(
|
|
185
|
+
value: unknown
|
|
186
|
+
): value is RenderableLengthMetricDelta {
|
|
187
|
+
if (typeof value !== 'object' || value === null || Array.isArray(value)) {
|
|
188
|
+
return false
|
|
189
|
+
}
|
|
190
|
+
const delta = value as Record<string, unknown>
|
|
191
|
+
const isNullableFiniteNumber = (candidate: unknown) =>
|
|
192
|
+
candidate === null || (
|
|
193
|
+
typeof candidate === 'number' && Number.isFinite(candidate)
|
|
194
|
+
)
|
|
195
|
+
return isNullableFiniteNumber(delta.removed) &&
|
|
196
|
+
isNullableFiniteNumber(delta.added) &&
|
|
197
|
+
isNullableFiniteNumber(delta.net)
|
|
198
|
+
}
|
|
199
|
+
|
|
174
200
|
function printLengthMeasurements(
|
|
175
201
|
ctx: DiffCommentsCliContext,
|
|
176
202
|
pair: DiffCommentPayloadPair
|
|
@@ -210,11 +236,15 @@ function printLengthMeasurements(
|
|
|
210
236
|
return
|
|
211
237
|
}
|
|
212
238
|
|
|
213
|
-
|
|
239
|
+
const splitUnavailableReason = pair.lengthDelta.splitUnavailableReason
|
|
240
|
+
if (
|
|
241
|
+
typeof splitUnavailableReason === 'string' &&
|
|
242
|
+
splitUnavailableReason.length > 0
|
|
243
|
+
) {
|
|
214
244
|
ctx.printLine(
|
|
215
245
|
` Split unavailable: ${sanitizeHumanInlineText(
|
|
216
246
|
ctx.sanitizeTerminalText,
|
|
217
|
-
|
|
247
|
+
splitUnavailableReason
|
|
218
248
|
)}`
|
|
219
249
|
)
|
|
220
250
|
}
|
|
@@ -225,6 +255,10 @@ function printLengthMeasurements(
|
|
|
225
255
|
['words', 'Words'],
|
|
226
256
|
] as const) {
|
|
227
257
|
const delta = pair.lengthDelta[metric]
|
|
258
|
+
if (!isLengthMetricDelta(delta)) {
|
|
259
|
+
ctx.printLine(` ${label}: unavailable`)
|
|
260
|
+
continue
|
|
261
|
+
}
|
|
228
262
|
ctx.printLine(
|
|
229
263
|
` ${label}: removed ${formatDeltaValue(delta.removed, metric)} · ` +
|
|
230
264
|
`added ${formatDeltaValue(delta.added, metric)} · ` +
|