Ctrl K
ComunidadGuías…

scripts/composio-manifests.mjs

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
#!/usr/bin/env node
import { mkdir, readdir, readFile, rm, writeFile } from 'node:fs/promises';
import path from 'node:path';
import { parseArgs } from 'node:util';

import { parseComposioManifest } from '../src/connections/catalog/composio-manifests.ts';
import {
  MANIFEST_DIRECTORY,
  SNAPSHOT_DIRECTORY,
  checkComposioManifestDirectory,
  draftComposioManifest,
  fetchComposioToolkit,
  readSnapshot,
  renderDraftReport,
  reviewedTools,
  snapshotFromComposio,
  writeComposioCatalogModules,
} from './lib/composio-manifests.ts';

const USAGE = `Usage:
  npm run connectors:composio -- snapshot <toolkit> --from <export-directory>
  npm run connectors:composio -- snapshot <toolkit> --fetch   (reads COMPOSIO_API_KEY; GET requests only)
  npm run connectors:composio -- draft <toolkit> [--report <file>] [--validation-arguments <json>]
  npm run connectors:composio -- generate   (lists every manifest but the held ones in the catalog)
  npm run connectors:composio -- check`;

const { positionals, values } = parseArgs({
  allowPositionals: true,
  options: {
    from: { type: 'string' },
    fetch: { type: 'boolean' },
    report: { type: 'string' },
    'validation-arguments': { type: 'string' },
  },
});
const [command, toolkit] = positionals;

if (command === 'generate') {
  await writeComposioCatalogModules();
  console.log('Wrote src/connections/catalog/composio-headers.ts and composio-details.ts.');
} else if (command === 'check') {
  const problems = await checkComposioManifestDirectory();
  for (const problem of problems) console.error(problem);
  if (problems.length > 0) process.exit(1);
  console.log('Composio manifests match their pinned snapshots.');
} else if (command === 'snapshot' && toolkit && (values.fetch || values.from)) {
  const previous = await readManifest(toolkit);
  const [detail, tools] = values.fetch
    ? await fetchComposio(toolkit)
    : await readComposioExport(values.from, toolkit);
  const snapshot = snapshotFromComposio(detail, tools, new Set(previous ? reviewedTools(previous) : []));
  const directory = path.join(SNAPSHOT_DIRECTORY, toolkit);
  await rm(directory, { recursive: true, force: true });
  await mkdir(directory, { recursive: true });
  const file = path.join(directory, `${snapshot.toolkit.version}.json`);
  await writeFile(file, `${JSON.stringify(snapshot, null, 2)}\n`);
  console.log(`Wrote ${path.relative(process.cwd(), file)} with ${snapshot.tools.length} tools.`);
} else if (command === 'draft' && toolkit) {
  const versions = (await readdir(path.join(SNAPSHOT_DIRECTORY, toolkit)).catch(() => []))
    .filter((file) => file.endsWith('.json'))
    .sort();
  if (versions.length !== 1) {
    throw new Error(`Expected exactly one snapshot for ${toolkit}; run the snapshot command first`);
  }
  const snapshot = await readSnapshot(toolkit, versions[0].slice(0, -'.json'.length));
  const validationArguments = values['validation-arguments'] === undefined
    ? undefined : JSON.parse(values['validation-arguments']);
  const { manifest, report } = draftComposioManifest(snapshot, await readManifest(toolkit), { validationArguments });
  await writeFile(
    path.join(MANIFEST_DIRECTORY, `${toolkit}.json`),
    `${JSON.stringify(manifest, null, 2)}\n`,
  );
  const text = renderDraftReport(report);
  if (values.report) await writeFile(values.report, text);
  else process.stdout.write(text);
} else {
  console.error(USAGE);
  process.exit(2);
}

async function readManifest(name) {
  const raw = await readFile(path.join(MANIFEST_DIRECTORY, `${name}.json`), 'utf8').catch((error) => {
    if (error?.code === 'ENOENT') return undefined;
    throw error;
  });
  return raw === undefined ? undefined : parseComposioManifest(JSON.parse(raw));
}

async function readComposioExport(directory, name) {
  return Promise.all([
    readFile(path.join(directory, 'composio-details', `${name}.json`), 'utf8').then(JSON.parse),
    readFile(path.join(directory, 'composio-tools', `${name}.json`), 'utf8').then(JSON.parse),
  ]);
}

async function fetchComposio(name) {
  const apiKey = process.env.COMPOSIO_API_KEY?.trim();
  if (!apiKey) throw new Error('COMPOSIO_API_KEY is not set');
  return fetchComposioToolkit(name, apiKey);
}