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