@agentskit/cli 0.12.0 → 0.13.1

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/bin.cjs CHANGED
@@ -4031,12 +4031,12 @@ function scaffoldAgent(schema) {
4031
4031
  return files;
4032
4032
  }
4033
4033
  async function writeScaffold(files, outDir, opts = {}) {
4034
- const { writeFile: writeFile3, mkdir: mkdir3, access } = await import('fs/promises');
4035
- const { dirname: dirname2, join: join6 } = await import('path');
4034
+ const { writeFile: writeFile5, mkdir: mkdir5, access } = await import('fs/promises');
4035
+ const { dirname: dirname4, join: join8 } = await import('path');
4036
4036
  const written = [];
4037
4037
  for (const f of files) {
4038
- const full = join6(outDir, f.path);
4039
- await mkdir3(dirname2(full), { recursive: true });
4038
+ const full = join8(outDir, f.path);
4039
+ await mkdir5(dirname4(full), { recursive: true });
4040
4040
  if (!opts.overwrite) {
4041
4041
  try {
4042
4042
  await access(full);
@@ -4044,7 +4044,7 @@ async function writeScaffold(files, outDir, opts = {}) {
4044
4044
  } catch {
4045
4045
  }
4046
4046
  }
4047
- await writeFile3(full, f.content, "utf8");
4047
+ await writeFile5(full, f.content, "utf8");
4048
4048
  written.push(f.path);
4049
4049
  }
4050
4050
  return written;
@@ -4660,6 +4660,261 @@ rules failed: ${message}
4660
4660
  }
4661
4661
  });
4662
4662
  }
4663
+ var RAW_BASE = "https://raw.githubusercontent.com/AgentsKit-io/agentskit-registry/main";
4664
+ var HOSTED_BASE = `${RAW_BASE}/public/r`;
4665
+ async function getJson(url, fetchImpl) {
4666
+ const res = await fetchImpl(url);
4667
+ if (!res.ok) throw new Error(`${res.status} ${res.statusText}`);
4668
+ return res.json();
4669
+ }
4670
+ async function getText(url, fetchImpl) {
4671
+ const res = await fetchImpl(url);
4672
+ if (!res.ok) throw new Error(`${res.status} ${res.statusText}`);
4673
+ return res.text();
4674
+ }
4675
+ async function fetchAgent(id, options = {}) {
4676
+ const fetchImpl = options.fetchImpl ?? globalThis.fetch;
4677
+ try {
4678
+ const hosted = await getJson(`${HOSTED_BASE}/${id}.json`, fetchImpl);
4679
+ if (hosted?.sources?.length) return hosted;
4680
+ throw new Error("hosted entry missing sources");
4681
+ } catch {
4682
+ const meta = await getJson(`${RAW_BASE}/registry/${id}/meta.json`, fetchImpl);
4683
+ const sources = await Promise.all(
4684
+ meta.files.map(async (rel) => ({
4685
+ path: rel,
4686
+ content: await getText(`${RAW_BASE}/registry/${id}/${rel}`, fetchImpl)
4687
+ }))
4688
+ );
4689
+ return { ...meta, sources };
4690
+ }
4691
+ }
4692
+ function resolveSystemPrompt(agent) {
4693
+ if (agent.skill?.systemPrompt) return agent.skill.systemPrompt;
4694
+ const src = agent.sources.find((f) => f.path === "agent.ts")?.content;
4695
+ if (!src) return null;
4696
+ const m = src.match(/systemPrompt:\s*`((?:\\.|[^`\\])*)`/);
4697
+ return m ? m[1].replace(/\\`/g, "`").replace(/\\\$\{/g, "${") : null;
4698
+ }
4699
+ async function defaultExists(path5) {
4700
+ const { access } = await import('fs/promises');
4701
+ try {
4702
+ await access(path5);
4703
+ return true;
4704
+ } catch {
4705
+ return false;
4706
+ }
4707
+ }
4708
+ async function addAgent(id, options = {}) {
4709
+ const agent = await fetchAgent(id, options);
4710
+ const baseDir = options.outDir ?? "agents";
4711
+ const targetDir = path.join(baseDir, id);
4712
+ const exists = options.existsImpl ?? defaultExists;
4713
+ const write = options.writeFileImpl ?? (async (path5, content) => {
4714
+ await promises.mkdir(path.dirname(path5), { recursive: true });
4715
+ await promises.writeFile(path5, content, "utf8");
4716
+ });
4717
+ const written = [];
4718
+ for (const file of agent.sources) {
4719
+ const dest = path.join(targetDir, file.path);
4720
+ if (!options.force && await exists(dest)) {
4721
+ throw new Error(`${dest} already exists (re-run with --force to overwrite)`);
4722
+ }
4723
+ await write(dest, file.content);
4724
+ written.push(dest);
4725
+ }
4726
+ return { agent, written, targetDir };
4727
+ }
4728
+ function lineDiff(a, b) {
4729
+ const x = a.split("\n");
4730
+ const y = b.split("\n");
4731
+ const m = x.length;
4732
+ const n = y.length;
4733
+ const lcs = Array.from({ length: m + 1 }, () => new Array(n + 1).fill(0));
4734
+ for (let i2 = m - 1; i2 >= 0; i2--) {
4735
+ for (let j2 = n - 1; j2 >= 0; j2--) {
4736
+ lcs[i2][j2] = x[i2] === y[j2] ? lcs[i2 + 1][j2 + 1] + 1 : Math.max(lcs[i2 + 1][j2], lcs[i2][j2 + 1]);
4737
+ }
4738
+ }
4739
+ const out = [];
4740
+ let i = 0;
4741
+ let j = 0;
4742
+ while (i < m && j < n) {
4743
+ if (x[i] === y[j]) {
4744
+ out.push({ type: " ", text: x[i] });
4745
+ i++;
4746
+ j++;
4747
+ } else if (lcs[i + 1][j] >= lcs[i][j + 1]) {
4748
+ out.push({ type: "-", text: x[i++] });
4749
+ } else {
4750
+ out.push({ type: "+", text: y[j++] });
4751
+ }
4752
+ }
4753
+ while (i < m) out.push({ type: "-", text: x[i++] });
4754
+ while (j < n) out.push({ type: "+", text: y[j++] });
4755
+ return out;
4756
+ }
4757
+ async function diffAgent(id, options = {}) {
4758
+ const agent = await fetchAgent(id, options);
4759
+ const targetDir = path.join(options.outDir ?? "agents", id);
4760
+ const readLocal = options.readFileImpl ?? (async (p) => {
4761
+ const { readFile: readFile6 } = await import('fs/promises');
4762
+ try {
4763
+ return await readFile6(p, "utf8");
4764
+ } catch {
4765
+ return null;
4766
+ }
4767
+ });
4768
+ const files = [];
4769
+ for (const f of agent.sources) {
4770
+ const local = await readLocal(path.join(targetDir, f.path));
4771
+ if (local == null) {
4772
+ files.push({ path: f.path, status: "missing-local", upstream: f.content });
4773
+ } else if (local === f.content) {
4774
+ files.push({ path: f.path, status: "unchanged", upstream: f.content });
4775
+ } else {
4776
+ files.push({ path: f.path, status: "modified", diff: lineDiff(local, f.content), upstream: f.content });
4777
+ }
4778
+ }
4779
+ return { agent, targetDir, files };
4780
+ }
4781
+
4782
+ // src/commands/add.ts
4783
+ function registerAddCommand(program) {
4784
+ program.command("add <agent>").description(
4785
+ 'Add a ready-made agent from the AgentsKit registry (registry.agentskit.io). Copies the agent source into your project \u2014 you own the code. With --run, also executes it. e.g. `agentskit add research` or `agentskit add legal-contract-reviewer --run "review this NDA\u2026" --provider ollama`.'
4786
+ ).option("--out <dir>", "Directory to write the agent into (default: ./agents)").option("-f, --force", "Overwrite existing files").option("--run <task>", "Run the agent on this task right after adding it").option("--provider <provider>", "Provider for --run (openai, anthropic, gemini, ollama, demo)", "demo").option("--model <model>", "Model for --run").option("--api-key <key>", "API key for --run (else read from the provider env var)").action(
4787
+ async (agent, options) => {
4788
+ try {
4789
+ const result = await addAgent(agent, { outDir: options.out, force: options.force === true });
4790
+ process.stdout.write(`
4791
+ Added "${result.agent.title}" \u2192 ${result.targetDir}/
4792
+ `);
4793
+ for (const f of result.written) process.stdout.write(` wrote ${f}
4794
+ `);
4795
+ if (result.agent.packages.length > 0) {
4796
+ process.stdout.write(`
4797
+ Install the packages it uses:
4798
+ `);
4799
+ process.stdout.write(` npm install ${result.agent.packages.join(" ")} @agentskit/adapters
4800
+ `);
4801
+ }
4802
+ const required = (result.agent.env ?? []).filter((e) => e.required);
4803
+ if (required.length > 0) {
4804
+ process.stdout.write(`
4805
+ Required environment:
4806
+ `);
4807
+ for (const e of required) process.stdout.write(` ${e.name} \u2014 ${e.description}
4808
+ `);
4809
+ }
4810
+ const readme2 = result.written.find((f) => f.toLowerCase().endsWith("readme.md"));
4811
+ process.stdout.write(readme2 ? `
4812
+ See ${readme2} for usage.
4813
+ ` : "\n");
4814
+ if (options.run) {
4815
+ const systemPrompt = resolveSystemPrompt(result.agent);
4816
+ if (!systemPrompt) {
4817
+ process.stderr.write(
4818
+ `
4819
+ --run is not supported for "${agent}" (it composes tools/keys). Use it as a library \u2014 see the README.
4820
+ `
4821
+ );
4822
+ process.exit(1);
4823
+ }
4824
+ process.stdout.write(`
4825
+ Running "${result.agent.title}" via ${options.provider}\u2026
4826
+
4827
+ `);
4828
+ await runAgent(options.run, {
4829
+ provider: options.provider,
4830
+ model: options.model,
4831
+ apiKey: options.apiKey,
4832
+ systemPrompt,
4833
+ maxSteps: "8"
4834
+ });
4835
+ }
4836
+ } catch (err) {
4837
+ const message = err instanceof Error ? err.message : String(err);
4838
+ process.stderr.write(`
4839
+ add failed: ${message}
4840
+ `);
4841
+ process.stderr.write(`(browse agents at https://registry.agentskit.io)
4842
+ `);
4843
+ process.exit(1);
4844
+ }
4845
+ }
4846
+ );
4847
+ }
4848
+ function registerDiffCommand(program) {
4849
+ program.command("diff <agent>").description("Show how your local copy of a registry agent differs from the current registry source.").option("--out <dir>", "Directory the agent was added into (default: ./agents)").action(async (agent, options) => {
4850
+ try {
4851
+ const { targetDir, files } = await diffAgent(agent, { outDir: options.out });
4852
+ let changed = 0;
4853
+ for (const f of files) {
4854
+ if (f.status === "unchanged") continue;
4855
+ changed++;
4856
+ process.stdout.write(`
4857
+ ${f.status === "missing-local" ? "missing" : "modified"}: ${path.join(targetDir, f.path)}
4858
+ `);
4859
+ if (f.diff) {
4860
+ for (const line of f.diff) {
4861
+ if (line.type === " ") continue;
4862
+ process.stdout.write(` ${line.type} ${line.text}
4863
+ `);
4864
+ }
4865
+ }
4866
+ }
4867
+ process.stdout.write(
4868
+ changed === 0 ? `
4869
+ ${agent}: up to date with the registry.
4870
+ ` : `
4871
+ ${changed} file(s) differ. Run \`agentskit update ${agent}\` to apply the registry version.
4872
+ `
4873
+ );
4874
+ } catch (err) {
4875
+ process.stderr.write(`
4876
+ diff failed: ${err instanceof Error ? err.message : String(err)}
4877
+ `);
4878
+ process.exit(1);
4879
+ }
4880
+ });
4881
+ }
4882
+ function registerUpdateCommand(program) {
4883
+ program.command("update <agent>").description("Update your local copy of a registry agent to the current registry source.").option("--out <dir>", "Directory the agent was added into (default: ./agents)").option("-f, --force", "Apply without listing the changes first").action(async (agent, options) => {
4884
+ try {
4885
+ const { targetDir, files } = await diffAgent(agent, { outDir: options.out });
4886
+ const changed = files.filter((f) => f.status !== "unchanged");
4887
+ if (changed.length === 0) {
4888
+ process.stdout.write(`
4889
+ ${agent}: already up to date.
4890
+ `);
4891
+ return;
4892
+ }
4893
+ if (!options.force) {
4894
+ process.stdout.write(`
4895
+ Will overwrite ${changed.length} file(s) with the registry version:
4896
+ `);
4897
+ for (const f of changed) process.stdout.write(` ${f.path} (${f.status})
4898
+ `);
4899
+ }
4900
+ for (const f of changed) {
4901
+ const dest = path.join(targetDir, f.path);
4902
+ await promises.mkdir(path.dirname(dest), { recursive: true });
4903
+ await promises.writeFile(dest, f.upstream, "utf8");
4904
+ process.stdout.write(` updated ${dest}
4905
+ `);
4906
+ }
4907
+ process.stdout.write(`
4908
+ Updated ${agent}. Review the changes with your VCS before committing.
4909
+ `);
4910
+ } catch (err) {
4911
+ process.stderr.write(`
4912
+ update failed: ${err instanceof Error ? err.message : String(err)}
4913
+ `);
4914
+ process.exit(1);
4915
+ }
4916
+ });
4917
+ }
4663
4918
 
4664
4919
  // src/commands/index.ts
4665
4920
  function createCli() {
@@ -4677,6 +4932,9 @@ function createCli() {
4677
4932
  registerFlowCommand(program);
4678
4933
  registerPiiCommand(program);
4679
4934
  registerRulesCommand(program);
4935
+ registerAddCommand(program);
4936
+ registerDiffCommand(program);
4937
+ registerUpdateCommand(program);
4680
4938
  return program;
4681
4939
  }
4682
4940