Files
cleveragents-core/.opencode/skills/templating-vault/scripts/extract.ts
freemo 1885990081
CI / build (push) Waiting to run
CI / docker (push) Blocked by required conditions
CI / helm (push) Waiting to run
CI / push-validation (push) Waiting to run
CI / status-check (push) Blocked by required conditions
CI / lint (push) Waiting to run
CI / typecheck (push) Waiting to run
CI / security (push) Waiting to run
CI / quality (push) Waiting to run
CI / unit_tests (push) Waiting to run
CI / integration_tests (push) Waiting to run
CI / e2e_tests (push) Waiting to run
CI / coverage (push) Blocked by required conditions
CI / benchmark-publish (push) Waiting to run
build: auto opencode agents rewritten
2026-04-27 12:49:08 -04:00

167 lines
5.2 KiB
TypeScript

#!/usr/bin/env -S npx --yes tsx
// =============================================================================
// extract.ts — Extract a value from source text using regex and store it
//
// Part of: .opencode/skills/templating-vault/scripts/
//
// The ONLY way to set literal variables. The LLM provides a regex pattern;
// this script applies it against the source text (from a vault key or file)
// and stores the captured value. The LLM never sees or reproduces the raw
// value — it only provides the regex.
//
// USAGE:
// extract.ts --source-key <key> --key <target_key> --regex <pattern>
// [--capture-group <n>] [--owner <id>]
// [--config <path>] [--store-dir <path>]
//
// extract.ts --source-file <path> --key <target_key> --regex <pattern>
// [--capture-group <n>] [--owner <id>]
// [--config <path>] [--store-dir <path>]
//
// OUTPUT (stdout): JSON result
// =============================================================================
import * as fs from 'node:fs';
import { fileURLToPath } from 'node:url';
import {
parseCommonFlags, getFlag, hasFlag, output, log,
loadConfig, readValue, resolveStore, writeValue,
loadKeyMeta, saveKeyMeta, validateValue,
type KeyMeta,
} from './api.ts';
async function main(): Promise<void> {
const { config: cfgPath, storeDirs, rest } = parseCommonFlags(process.argv);
const config = loadConfig(cfgPath, storeDirs.length > 0 ? storeDirs : undefined);
const sourceKey = getFlag(rest, '--source-key');
const sourceFile = getFlag(rest, '--source-file');
const targetKey = getFlag(rest, '--key');
const regexStr = getFlag(rest, '--regex');
const captureGroupStr = getFlag(rest, '--capture-group');
const owner = getFlag(rest, '--owner');
const writeOnce = hasFlag(rest, '--write-once');
if (!targetKey) {
output({ extracted: false, error: '--key is required' });
process.exit(1);
}
if (!regexStr) {
output({ extracted: false, error: '--regex is required' });
process.exit(1);
}
if (!sourceKey && !sourceFile) {
output({ extracted: false, error: '--source-key or --source-file is required' });
process.exit(1);
}
// Check access
const resolved = resolveStore(config, targetKey);
if (resolved.mapping.access === 'readonly') {
output({ extracted: false, error: `Store for prefix "${resolved.mapping.prefix}" is readonly` });
process.exit(1);
}
// Load source text
let sourceText: string;
if (sourceKey) {
const val = readValue(config, sourceKey);
if (val === null) {
output({ extracted: false, error: `Source key "${sourceKey}" not found in vault` });
process.exit(1);
}
sourceText = val;
} else {
if (!fs.existsSync(sourceFile!)) {
output({ extracted: false, error: `Source file "${sourceFile}" not found` });
process.exit(1);
}
sourceText = fs.readFileSync(sourceFile!, 'utf-8');
}
// Apply regex
const captureGroup = captureGroupStr ? parseInt(captureGroupStr, 10) : 1;
let regex: RegExp;
try {
regex = new RegExp(regexStr, 'm');
} catch (err) {
output({
extracted: false,
error: `Invalid regex: ${err instanceof Error ? err.message : String(err)}`,
});
process.exit(1);
}
const match = regex.exec(sourceText);
if (!match) {
// Provide context hints without exposing full source
const lines = sourceText.split('\n');
output({
extracted: false,
error: 'Regex did not match any text in the source',
hints: {
source_lines: lines.length,
source_chars: sourceText.length,
first_200_chars: sourceText.slice(0, 200),
regex_used: regexStr,
},
});
process.exit(1);
}
if (captureGroup >= match.length) {
output({
extracted: false,
error: `Capture group ${captureGroup} does not exist. Regex matched ${match.length - 1} group(s).`,
});
process.exit(1);
}
const extractedValue = match[captureGroup] ?? match[0];
// Check write-once on target
const meta = loadKeyMeta(config, targetKey);
if (meta.write_once && readValue(config, targetKey) !== null) {
output({
extracted: false,
error: `Key "${targetKey}" is write-once and already has a value`,
});
process.exit(1);
}
// Validate
const validationError = validateValue(extractedValue, meta);
if (validationError) {
output({
extracted: false,
error: `Validation failed for "${targetKey}": ${validationError}`,
extracted_length: extractedValue.length,
});
process.exit(1);
}
// Store value (using --force-literal internally to bypass literal check in writeValue)
writeValue(config, targetKey, extractedValue);
// Update metadata
const updatedMeta: KeyMeta = { ...meta };
if (owner) updatedMeta.owner = owner;
if (writeOnce) updatedMeta.write_once = true;
if (owner || writeOnce) {
saveKeyMeta(config, targetKey, updatedMeta);
}
output({
extracted: true,
key: targetKey,
stored: true,
value_length: extractedValue.length,
});
}
if (process.argv[1] === fileURLToPath(import.meta.url)) {
main().catch((err: unknown) => {
output({ extracted: false, error: String(err instanceof Error ? err.message : err) });
process.exit(1);
});
}