@agentskit/cli 0.11.3 → 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 +786 -26
- package/dist/bin.cjs.map +1 -1
- package/dist/bin.js +1 -1
- package/dist/{chunk-7SBFFCM7.js → chunk-YT74CXQA.js} +789 -29
- package/dist/chunk-YT74CXQA.js.map +1 -0
- package/dist/index.cjs +786 -26
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +1 -1
- package/package.json +23 -18
- package/dist/chunk-7SBFFCM7.js.map +0 -1
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { readdir, stat, mkdir, writeFile, glob, readFile } from 'fs/promises';
|
|
3
3
|
import { homedir } from 'os';
|
|
4
|
-
import path, { join, resolve, isAbsolute, basename } from 'path';
|
|
4
|
+
import path, { join, resolve, isAbsolute, basename, dirname } from 'path';
|
|
5
5
|
import { kimi, grok, deepseek, ollama, gemini, anthropic, openai } from '@agentskit/adapters';
|
|
6
6
|
import { randomBytes, createHash } from 'crypto';
|
|
7
7
|
import { writeFileSync, existsSync, readdirSync, statSync, readFileSync, mkdirSync } from 'fs';
|
|
@@ -12,6 +12,7 @@ import { useChat, StatusHeader, ChatContainer, Message, ToolCallView, ToolConfir
|
|
|
12
12
|
import { shell, filesystem, fetchUrl, webSearch } from '@agentskit/tools';
|
|
13
13
|
import { summarizer, critic, planner, coder, researcher, composeSkills } from '@agentskit/skills';
|
|
14
14
|
import { fileVectorMemory, fileChatMemory, sqliteChatMemory } from '@agentskit/memory';
|
|
15
|
+
import { getIntegration, integrationToolsFromEnv } from '@agentskit/integrations';
|
|
15
16
|
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
16
17
|
import { pathToFileURL } from 'url';
|
|
17
18
|
import { createRuntime, validateFlow, flowToMermaid, compileFlow, createFileStepLog } from '@agentskit/runtime';
|
|
@@ -22,6 +23,8 @@ import { Command } from 'commander';
|
|
|
22
23
|
import { input, select, checkbox, confirm } from '@inquirer/prompts';
|
|
23
24
|
import { validateAgentSchema } from '@agentskit/core/agent-schema';
|
|
24
25
|
import { parse } from 'yaml';
|
|
26
|
+
import { validatePIITaxonomy } from '@agentskit/core/security';
|
|
27
|
+
import { ConfigError, ErrorCodes } from '@agentskit/core';
|
|
25
28
|
|
|
26
29
|
async function loadJsonConfig(path5) {
|
|
27
30
|
try {
|
|
@@ -143,7 +146,7 @@ function createDemoAdapter(provider, model) {
|
|
|
143
146
|
].join(" ");
|
|
144
147
|
for (const chunk of reply.match(/.{1,18}/g) ?? []) {
|
|
145
148
|
if (cancelled) return;
|
|
146
|
-
await new Promise((
|
|
149
|
+
await new Promise((resolve6) => setTimeout(resolve6, 35));
|
|
147
150
|
yield { type: "text", content: chunk };
|
|
148
151
|
}
|
|
149
152
|
yield { type: "done" };
|
|
@@ -464,20 +467,39 @@ function configHooksToHandlers(config) {
|
|
|
464
467
|
function runShellHook(entry, payload) {
|
|
465
468
|
return new Promise((resolvePromise) => {
|
|
466
469
|
const timeoutMs = entry.timeout ?? 5e3;
|
|
470
|
+
let settled = false;
|
|
471
|
+
const settle = (result) => {
|
|
472
|
+
if (settled) return;
|
|
473
|
+
settled = true;
|
|
474
|
+
clearTimeout(timer);
|
|
475
|
+
resolvePromise(result);
|
|
476
|
+
};
|
|
467
477
|
const child = spawn("sh", ["-c", entry.run], {
|
|
468
|
-
stdio: ["pipe", "pipe", "inherit"]
|
|
478
|
+
stdio: ["pipe", "pipe", "inherit"],
|
|
479
|
+
detached: true
|
|
469
480
|
});
|
|
470
481
|
let stdout = "";
|
|
471
482
|
child.stdout.on("data", (chunk) => {
|
|
472
483
|
stdout += chunk.toString();
|
|
473
484
|
});
|
|
474
485
|
const timer = setTimeout(() => {
|
|
475
|
-
child.
|
|
486
|
+
if (child.pid !== void 0) {
|
|
487
|
+
try {
|
|
488
|
+
process.kill(-child.pid, "SIGKILL");
|
|
489
|
+
} catch {
|
|
490
|
+
}
|
|
491
|
+
}
|
|
492
|
+
try {
|
|
493
|
+
child.kill("SIGKILL");
|
|
494
|
+
} catch {
|
|
495
|
+
}
|
|
496
|
+
settle({ decision: "block", reason: `shell hook timed out after ${timeoutMs}ms` });
|
|
476
497
|
}, timeoutMs);
|
|
498
|
+
child.stdin.on("error", () => {
|
|
499
|
+
});
|
|
477
500
|
child.on("close", (code) => {
|
|
478
|
-
clearTimeout(timer);
|
|
479
501
|
if (code !== 0) {
|
|
480
|
-
|
|
502
|
+
settle({
|
|
481
503
|
decision: "block",
|
|
482
504
|
reason: `shell hook exited with code ${code}`
|
|
483
505
|
});
|
|
@@ -485,19 +507,18 @@ function runShellHook(entry, payload) {
|
|
|
485
507
|
}
|
|
486
508
|
const trimmed = stdout.trim();
|
|
487
509
|
if (!trimmed) {
|
|
488
|
-
|
|
510
|
+
settle({ decision: "continue" });
|
|
489
511
|
return;
|
|
490
512
|
}
|
|
491
513
|
try {
|
|
492
514
|
const parsed = JSON.parse(trimmed);
|
|
493
|
-
|
|
515
|
+
settle(parsed);
|
|
494
516
|
} catch {
|
|
495
|
-
|
|
517
|
+
settle({ decision: "continue" });
|
|
496
518
|
}
|
|
497
519
|
});
|
|
498
520
|
child.on("error", (err) => {
|
|
499
|
-
|
|
500
|
-
resolvePromise({ decision: "block", reason: err.message });
|
|
521
|
+
settle({ decision: "block", reason: err.message });
|
|
501
522
|
});
|
|
502
523
|
try {
|
|
503
524
|
child.stdin.write(JSON.stringify(payload));
|
|
@@ -737,7 +758,7 @@ function instantiate(kind) {
|
|
|
737
758
|
case "filesystem":
|
|
738
759
|
return filesystem({ basePath: process.cwd() });
|
|
739
760
|
case "shell":
|
|
740
|
-
return [shell({ timeout: 3e4 })];
|
|
761
|
+
return [shell({ timeout: 3e4, allowAny: true })];
|
|
741
762
|
}
|
|
742
763
|
}
|
|
743
764
|
function gateTool(tool) {
|
|
@@ -757,9 +778,19 @@ function resolveTools(toolNames) {
|
|
|
757
778
|
case "shell":
|
|
758
779
|
tools.push(...instantiate(name));
|
|
759
780
|
break;
|
|
760
|
-
default:
|
|
761
|
-
|
|
781
|
+
default: {
|
|
782
|
+
if (getIntegration(name)) {
|
|
783
|
+
const { tools: projected, credentialFound, envVar } = integrationToolsFromEnv(name, process.env);
|
|
784
|
+
if (!credentialFound) {
|
|
785
|
+
process.stderr.write(`Integration "${name}" needs ${envVar} set in the environment.
|
|
786
|
+
`);
|
|
787
|
+
}
|
|
788
|
+
tools.push(...projected);
|
|
789
|
+
} else {
|
|
790
|
+
process.stderr.write(`Unknown tool: ${name}
|
|
762
791
|
`);
|
|
792
|
+
}
|
|
793
|
+
}
|
|
763
794
|
}
|
|
764
795
|
}
|
|
765
796
|
return tools;
|
|
@@ -3813,13 +3844,6 @@ function registerConfigCommand(program) {
|
|
|
3813
3844
|
`);
|
|
3814
3845
|
process.exit(2);
|
|
3815
3846
|
}
|
|
3816
|
-
if (existsSync(targetPath) && !options.force) {
|
|
3817
|
-
process.stderr.write(
|
|
3818
|
-
`Config already exists at ${targetPath}. Re-run with --force to overwrite.
|
|
3819
|
-
`
|
|
3820
|
-
);
|
|
3821
|
-
process.exit(1);
|
|
3822
|
-
}
|
|
3823
3847
|
const template = {
|
|
3824
3848
|
defaults: {
|
|
3825
3849
|
provider: "openai",
|
|
@@ -3830,7 +3854,20 @@ function registerConfigCommand(program) {
|
|
|
3830
3854
|
}
|
|
3831
3855
|
};
|
|
3832
3856
|
mkdirSync(path.dirname(targetPath), { recursive: true });
|
|
3833
|
-
|
|
3857
|
+
try {
|
|
3858
|
+
writeFileSync(targetPath, JSON.stringify(template, null, 2) + "\n", {
|
|
3859
|
+
flag: options.force ? "w" : "wx"
|
|
3860
|
+
});
|
|
3861
|
+
} catch (err) {
|
|
3862
|
+
if (err.code === "EEXIST") {
|
|
3863
|
+
process.stderr.write(
|
|
3864
|
+
`Config already exists at ${targetPath}. Re-run with --force to overwrite.
|
|
3865
|
+
`
|
|
3866
|
+
);
|
|
3867
|
+
process.exit(1);
|
|
3868
|
+
}
|
|
3869
|
+
throw err;
|
|
3870
|
+
}
|
|
3834
3871
|
process.stdout.write(
|
|
3835
3872
|
`Wrote ${targetPath}
|
|
3836
3873
|
Edit it to taste, then run:
|
|
@@ -3993,12 +4030,12 @@ function scaffoldAgent(schema) {
|
|
|
3993
4030
|
return files;
|
|
3994
4031
|
}
|
|
3995
4032
|
async function writeScaffold(files, outDir, opts = {}) {
|
|
3996
|
-
const { writeFile:
|
|
3997
|
-
const { dirname, join:
|
|
4033
|
+
const { writeFile: writeFile5, mkdir: mkdir5, access } = await import('fs/promises');
|
|
4034
|
+
const { dirname: dirname4, join: join8 } = await import('path');
|
|
3998
4035
|
const written = [];
|
|
3999
4036
|
for (const f of files) {
|
|
4000
|
-
const full =
|
|
4001
|
-
await
|
|
4037
|
+
const full = join8(outDir, f.path);
|
|
4038
|
+
await mkdir5(dirname4(full), { recursive: true });
|
|
4002
4039
|
if (!opts.overwrite) {
|
|
4003
4040
|
try {
|
|
4004
4041
|
await access(full);
|
|
@@ -4006,7 +4043,7 @@ async function writeScaffold(files, outDir, opts = {}) {
|
|
|
4006
4043
|
} catch {
|
|
4007
4044
|
}
|
|
4008
4045
|
}
|
|
4009
|
-
await
|
|
4046
|
+
await writeFile5(full, f.content, "utf8");
|
|
4010
4047
|
written.push(f.path);
|
|
4011
4048
|
}
|
|
4012
4049
|
return written;
|
|
@@ -4159,6 +4196,724 @@ function registerFlowCommand(program) {
|
|
|
4159
4196
|
}
|
|
4160
4197
|
});
|
|
4161
4198
|
}
|
|
4199
|
+
function lintTaxonomyFile(filePath) {
|
|
4200
|
+
const absolute = resolve(filePath);
|
|
4201
|
+
let raw;
|
|
4202
|
+
try {
|
|
4203
|
+
raw = readFileSync(absolute, "utf8");
|
|
4204
|
+
} catch (err) {
|
|
4205
|
+
return {
|
|
4206
|
+
file: absolute,
|
|
4207
|
+
ruleCount: 0,
|
|
4208
|
+
result: {
|
|
4209
|
+
ok: false,
|
|
4210
|
+
issues: [{ index: -1, path: "", message: `cannot read file: ${err.message}` }]
|
|
4211
|
+
}
|
|
4212
|
+
};
|
|
4213
|
+
}
|
|
4214
|
+
let parsed;
|
|
4215
|
+
try {
|
|
4216
|
+
parsed = JSON.parse(raw);
|
|
4217
|
+
} catch (err) {
|
|
4218
|
+
return {
|
|
4219
|
+
file: absolute,
|
|
4220
|
+
ruleCount: 0,
|
|
4221
|
+
result: {
|
|
4222
|
+
ok: false,
|
|
4223
|
+
issues: [{ index: -1, path: "", message: `invalid JSON: ${err.message}` }]
|
|
4224
|
+
}
|
|
4225
|
+
};
|
|
4226
|
+
}
|
|
4227
|
+
const result = validatePIITaxonomy(parsed);
|
|
4228
|
+
const ruleCount = parsed && typeof parsed === "object" && Array.isArray(parsed.rules) ? parsed.rules.length : 0;
|
|
4229
|
+
return { file: absolute, result, ruleCount };
|
|
4230
|
+
}
|
|
4231
|
+
function renderLintReport(report, opts = {}) {
|
|
4232
|
+
const { color = false } = opts;
|
|
4233
|
+
const red = (s) => color ? `\x1B[31m${s}\x1B[0m` : s;
|
|
4234
|
+
const green = (s) => color ? `\x1B[32m${s}\x1B[0m` : s;
|
|
4235
|
+
const dim = (s) => color ? `\x1B[2m${s}\x1B[0m` : s;
|
|
4236
|
+
const lines = [];
|
|
4237
|
+
lines.push(dim(report.file));
|
|
4238
|
+
if (report.result.ok) {
|
|
4239
|
+
lines.push(green(`\u2713 valid \xB7 ${report.ruleCount} rule${report.ruleCount === 1 ? "" : "s"}`));
|
|
4240
|
+
} else {
|
|
4241
|
+
lines.push(red(`\u2717 ${report.result.issues.length} issue${report.result.issues.length === 1 ? "" : "s"}`));
|
|
4242
|
+
for (const issue of report.result.issues) {
|
|
4243
|
+
lines.push(` ${red("\u2022")} ${issue.path || "<root>"}: ${issue.message}`);
|
|
4244
|
+
}
|
|
4245
|
+
}
|
|
4246
|
+
return `${lines.join("\n")}
|
|
4247
|
+
`;
|
|
4248
|
+
}
|
|
4249
|
+
|
|
4250
|
+
// src/commands/pii.ts
|
|
4251
|
+
function registerPiiCommand(program) {
|
|
4252
|
+
const pii = program.command("pii").description("Inspect and validate PII taxonomies.");
|
|
4253
|
+
pii.command("lint <file...>").description("Validate one or more PII taxonomy JSON files.").option("--json", "Emit JSON instead of formatted output").action((files, options) => {
|
|
4254
|
+
const reports = files.map(lintTaxonomyFile);
|
|
4255
|
+
const failed = reports.filter((r) => !r.result.ok).length;
|
|
4256
|
+
if (options.json) {
|
|
4257
|
+
process.stdout.write(JSON.stringify(reports, null, 2) + "\n");
|
|
4258
|
+
} else {
|
|
4259
|
+
for (const report of reports) {
|
|
4260
|
+
process.stdout.write(renderLintReport(report, { color: process.stdout.isTTY }));
|
|
4261
|
+
}
|
|
4262
|
+
if (failed > 0) {
|
|
4263
|
+
process.stderr.write(`
|
|
4264
|
+
${failed} of ${reports.length} taxonomy file${reports.length === 1 ? "" : "s"} failed validation
|
|
4265
|
+
`);
|
|
4266
|
+
}
|
|
4267
|
+
}
|
|
4268
|
+
if (failed > 0) process.exit(1);
|
|
4269
|
+
});
|
|
4270
|
+
}
|
|
4271
|
+
|
|
4272
|
+
// src/rules/cursor.ts
|
|
4273
|
+
var CURSOR_RULE = `---
|
|
4274
|
+
description: AgentsKit conventions \u2014 apply to every file in this workspace
|
|
4275
|
+
globs: ["**/*.ts", "**/*.tsx"]
|
|
4276
|
+
alwaysApply: true
|
|
4277
|
+
---
|
|
4278
|
+
|
|
4279
|
+
# AgentsKit project rules
|
|
4280
|
+
|
|
4281
|
+
When writing or editing TypeScript in this workspace, follow these rules. They
|
|
4282
|
+
are non-negotiable and enforced by CI.
|
|
4283
|
+
|
|
4284
|
+
## Imports
|
|
4285
|
+
|
|
4286
|
+
- Use **named exports only**. No \`export default\`.
|
|
4287
|
+
- Import from package roots: \`@agentskit/core\`, \`@agentskit/runtime\`, \`@agentskit/react\`,
|
|
4288
|
+
\`@agentskit/ink\`, \`@agentskit/adapters\`, \`@agentskit/tools\`, \`@agentskit/skills\`,
|
|
4289
|
+
\`@agentskit/memory\`, \`@agentskit/rag\`, \`@agentskit/observability\`, \`@agentskit/eval\`,
|
|
4290
|
+
\`@agentskit/sandbox\`, \`@agentskit/cli\`, \`@agentskit/templates\`.
|
|
4291
|
+
- For tools subpaths, use \`@agentskit/tools/integrations\`, \`@agentskit/tools/mcp\`,
|
|
4292
|
+
\`@agentskit/tools/mcp-devtools\`.
|
|
4293
|
+
|
|
4294
|
+
## Types
|
|
4295
|
+
|
|
4296
|
+
- TypeScript strict mode is on. **Do not use \`any\`** \u2014 use \`unknown\` and narrow.
|
|
4297
|
+
- Headless React components: no hardcoded styles, use \`data-ak-*\` attributes.
|
|
4298
|
+
|
|
4299
|
+
## Errors
|
|
4300
|
+
|
|
4301
|
+
- Never \`throw new Error(...)\` inside package source. Use the typed errors from
|
|
4302
|
+
\`@agentskit/core\`: \`AdapterError\`, \`ToolError\`, \`MemoryError\`, \`RuntimeError\`,
|
|
4303
|
+
\`SandboxError\`, \`SkillError\`, \`ConfigError\`. Pair with \`ErrorCodes.<...>\`.
|
|
4304
|
+
|
|
4305
|
+
## Tests
|
|
4306
|
+
|
|
4307
|
+
- vitest. Place tests under \`packages/<pkg>/tests/\` mirroring \`src/\`.
|
|
4308
|
+
- E2E lives in \`apps/example-*\` with Playwright.
|
|
4309
|
+
|
|
4310
|
+
## Versioning
|
|
4311
|
+
|
|
4312
|
+
- Every PR with a behavior change requires a Changeset (\`pnpm changeset\`).
|
|
4313
|
+
|
|
4314
|
+
## Where to look first
|
|
4315
|
+
|
|
4316
|
+
- Architecture, contracts, ADRs: \`docs/architecture/adrs/\`
|
|
4317
|
+
- Per-package conventions: \`packages/<pkg>/CONVENTIONS.md\`
|
|
4318
|
+
- Agent-facing index: \`AGENTS.md\` and \`apps/docs-next/content/docs/for-agents/\`
|
|
4319
|
+
`;
|
|
4320
|
+
|
|
4321
|
+
// src/rules/windsurf.ts
|
|
4322
|
+
var WINDSURF_RULE = `# AgentsKit project rules (read first)
|
|
4323
|
+
|
|
4324
|
+
This workspace builds AgentsKit \u2014 a JavaScript agent toolkit with a 10 KB core,
|
|
4325
|
+
six formal contracts, and ~19 plug-and-play packages. When generating or
|
|
4326
|
+
editing code, follow these rules \u2014 they are enforced by CI.
|
|
4327
|
+
|
|
4328
|
+
## Imports
|
|
4329
|
+
- **Named exports only.** No \`export default\`.
|
|
4330
|
+
- Import from package roots (\`@agentskit/core\`, \`@agentskit/runtime\`, \`@agentskit/react\`, etc.).
|
|
4331
|
+
- Tools subpaths: \`@agentskit/tools/integrations\`, \`@agentskit/tools/mcp\`, \`@agentskit/tools/mcp-devtools\`.
|
|
4332
|
+
|
|
4333
|
+
## Types
|
|
4334
|
+
- Strict mode TypeScript. **No \`any\`** \u2014 use \`unknown\` and narrow.
|
|
4335
|
+
|
|
4336
|
+
## Errors
|
|
4337
|
+
- **Do not** \`throw new Error(...)\` in package source. Use \`AdapterError\` /
|
|
4338
|
+
\`ToolError\` / \`MemoryError\` / \`RuntimeError\` / \`SandboxError\` / \`SkillError\` /
|
|
4339
|
+
\`ConfigError\` from \`@agentskit/core\`, paired with \`ErrorCodes\`.
|
|
4340
|
+
|
|
4341
|
+
## Tests
|
|
4342
|
+
- vitest. Tests live in \`packages/<pkg>/tests/\` mirroring \`src/\`.
|
|
4343
|
+
- E2E lives in \`apps/example-*\` with Playwright.
|
|
4344
|
+
|
|
4345
|
+
## Versioning
|
|
4346
|
+
- Every behavior change needs a Changeset (\`pnpm changeset\`).
|
|
4347
|
+
|
|
4348
|
+
## Read first
|
|
4349
|
+
- \`AGENTS.md\` \u2014 universal agent guidance
|
|
4350
|
+
- \`apps/docs-next/content/docs/for-agents/\` \u2014 per-package agent docs
|
|
4351
|
+
- \`docs/architecture/adrs/\` \u2014 six core contracts (Adapter, Tool, Memory, Retriever, Skill, Runtime)
|
|
4352
|
+
- \`packages/<pkg>/CONVENTIONS.md\` \u2014 per-package contribution rules
|
|
4353
|
+
`;
|
|
4354
|
+
|
|
4355
|
+
// src/rules/codex.ts
|
|
4356
|
+
var CODEX_PROFILE = `<!-- agentskit-codex-profile:start -->
|
|
4357
|
+
## Codex / Aider profile
|
|
4358
|
+
|
|
4359
|
+
Structured hints for CLI coding agents (OpenAI Codex, Aider, Claude Code,
|
|
4360
|
+
Cursor) running against this workspace. Update via \`agentskit rules codex\`.
|
|
4361
|
+
|
|
4362
|
+
\`\`\`yaml
|
|
4363
|
+
# AgentsKit Codex profile v1
|
|
4364
|
+
profile: agentskit
|
|
4365
|
+
runtime: node-25
|
|
4366
|
+
package_manager: pnpm
|
|
4367
|
+
test_runner: vitest
|
|
4368
|
+
build_runner: turborepo
|
|
4369
|
+
|
|
4370
|
+
allowed_commands:
|
|
4371
|
+
- pnpm install
|
|
4372
|
+
- pnpm build
|
|
4373
|
+
- pnpm test
|
|
4374
|
+
- pnpm lint
|
|
4375
|
+
- pnpm changeset
|
|
4376
|
+
- pnpm --filter @agentskit/* test
|
|
4377
|
+
- pnpm --filter @agentskit/* lint
|
|
4378
|
+
- pnpm --filter @agentskit/* build
|
|
4379
|
+
|
|
4380
|
+
restricted_paths:
|
|
4381
|
+
- packages/core/src/errors.ts # Touch carefully \u2014 every package depends on the typed errors here.
|
|
4382
|
+
- packages/core/src/security/ # Security-sensitive \u2014 small surface, requires review.
|
|
4383
|
+
- docs/architecture/adrs/ # Contract changes need a new ADR + major bump.
|
|
4384
|
+
|
|
4385
|
+
models_recommended:
|
|
4386
|
+
- claude-sonnet-4-6 # Default \u2014 long context, fast.
|
|
4387
|
+
- gpt-5 # Strong reasoning for refactors / cross-package work.
|
|
4388
|
+
- claude-opus-4-7 # Heavy refactors, contract redesigns.
|
|
4389
|
+
|
|
4390
|
+
invariants:
|
|
4391
|
+
core_max_kb_gzip: 10
|
|
4392
|
+
no_default_exports: true
|
|
4393
|
+
strict_typescript: true
|
|
4394
|
+
no_bare_throw_new_error: true
|
|
4395
|
+
named_exports_only: true
|
|
4396
|
+
changeset_required_for_behavior_changes: true
|
|
4397
|
+
|
|
4398
|
+
read_first:
|
|
4399
|
+
- AGENTS.md
|
|
4400
|
+
- apps/docs-next/content/docs/for-agents/
|
|
4401
|
+
- docs/architecture/adrs/
|
|
4402
|
+
\`\`\`
|
|
4403
|
+
<!-- agentskit-codex-profile:end -->
|
|
4404
|
+
`;
|
|
4405
|
+
|
|
4406
|
+
// src/rules/claude-code.ts
|
|
4407
|
+
var CLAUDE_CODE_SKILL = [
|
|
4408
|
+
{
|
|
4409
|
+
path: "SKILL.md",
|
|
4410
|
+
contents: `---
|
|
4411
|
+
name: agentskit
|
|
4412
|
+
description: Scaffold AgentsKit projects, add tools/skills, run doctor, and inspect the runtime \u2014 wraps the agentskit CLI.
|
|
4413
|
+
---
|
|
4414
|
+
|
|
4415
|
+
# AgentsKit
|
|
4416
|
+
|
|
4417
|
+
Skill bundle for working with the AgentsKit toolkit from inside Claude Code.
|
|
4418
|
+
|
|
4419
|
+
Pair this skill with the project-scoped slash commands at \`.claude/commands/agentskit-*.md\`:
|
|
4420
|
+
|
|
4421
|
+
- \`/agentskit-new-agent\` \u2014 interactive scaffold (\`agentskit init\`)
|
|
4422
|
+
- \`/agentskit-doctor\` \u2014 diagnose the local environment (\`agentskit doctor\`)
|
|
4423
|
+
- \`/agentskit-add-tool\` \u2014 add a tool integration template
|
|
4424
|
+
- \`/agentskit-add-skill\` \u2014 add a skill template
|
|
4425
|
+
- \`/agentskit-lint-pii\` \u2014 validate a PII taxonomy file
|
|
4426
|
+
- \`/agentskit-rules\` \u2014 write \`.cursor/rules\` / \`.windsurfrules\` / Codex profile
|
|
4427
|
+
|
|
4428
|
+
When the user is inside an AgentsKit workspace, prefer the slash commands over
|
|
4429
|
+
hand-rolling shell invocations \u2014 they share the canonical defaults.
|
|
4430
|
+
|
|
4431
|
+
For convention reminders (named exports only, no bare throw, etc.), read
|
|
4432
|
+
\`AGENTS.md\` at the workspace root.
|
|
4433
|
+
`
|
|
4434
|
+
}
|
|
4435
|
+
];
|
|
4436
|
+
var CLAUDE_CODE_SLASH_COMMANDS = [
|
|
4437
|
+
{
|
|
4438
|
+
path: "agentskit-new-agent.md",
|
|
4439
|
+
contents: `---
|
|
4440
|
+
description: Scaffold a new AgentsKit project (interactive)
|
|
4441
|
+
allowed-tools: Bash(npx agentskit init:*)
|
|
4442
|
+
---
|
|
4443
|
+
|
|
4444
|
+
Run \`npx @agentskit/cli init\` interactively in the user's chosen directory.
|
|
4445
|
+
After scaffold completes, summarise the layout (templates created, next
|
|
4446
|
+
commands the user should run).
|
|
4447
|
+
`
|
|
4448
|
+
},
|
|
4449
|
+
{
|
|
4450
|
+
path: "agentskit-doctor.md",
|
|
4451
|
+
contents: `---
|
|
4452
|
+
description: Run the AgentsKit environment doctor and summarise findings
|
|
4453
|
+
allowed-tools: Bash(npx agentskit doctor:*)
|
|
4454
|
+
---
|
|
4455
|
+
|
|
4456
|
+
Run \`npx @agentskit/cli doctor\` in the workspace root. Format the output
|
|
4457
|
+
into pass / warn / fail buckets and propose a fix for each fail / warn.
|
|
4458
|
+
`
|
|
4459
|
+
},
|
|
4460
|
+
{
|
|
4461
|
+
path: "agentskit-add-tool.md",
|
|
4462
|
+
contents: `---
|
|
4463
|
+
description: Add a tool template to the current package
|
|
4464
|
+
---
|
|
4465
|
+
|
|
4466
|
+
Ask the user which tool to add. Use \`packages/templates/src/blueprints/tool.ts\`
|
|
4467
|
+
to scaffold the file under \`packages/<pkg>/src/tools/\`. Update the package's
|
|
4468
|
+
\`src/index.ts\` to re-export the new tool. Add a vitest mock test under
|
|
4469
|
+
\`packages/<pkg>/tests/\`.
|
|
4470
|
+
`
|
|
4471
|
+
},
|
|
4472
|
+
{
|
|
4473
|
+
path: "agentskit-add-skill.md",
|
|
4474
|
+
contents: `---
|
|
4475
|
+
description: Add a skill template to @agentskit/skills
|
|
4476
|
+
---
|
|
4477
|
+
|
|
4478
|
+
Use \`packages/templates/src/blueprints/skill.ts\` to scaffold a new skill
|
|
4479
|
+
under \`packages/skills/src/\`. Re-export from the package index. Add a
|
|
4480
|
+
golden-dataset test fixture under \`packages/skills/tests/\` (10\u201350 input/
|
|
4481
|
+
expected examples, per the conventions).
|
|
4482
|
+
`
|
|
4483
|
+
},
|
|
4484
|
+
{
|
|
4485
|
+
path: "agentskit-lint-pii.md",
|
|
4486
|
+
contents: `---
|
|
4487
|
+
description: Validate a PII taxonomy JSON file
|
|
4488
|
+
allowed-tools: Bash(npx agentskit pii lint:*)
|
|
4489
|
+
---
|
|
4490
|
+
|
|
4491
|
+
Ask the user for a path. Run \`npx @agentskit/cli pii lint <path>\` and
|
|
4492
|
+
display the report. If issues exist, suggest concrete fixes per the
|
|
4493
|
+
issue messages.
|
|
4494
|
+
`
|
|
4495
|
+
},
|
|
4496
|
+
{
|
|
4497
|
+
path: "agentskit-rules.md",
|
|
4498
|
+
contents: `---
|
|
4499
|
+
description: Write editor rule files (Cursor / Windsurf / Codex / Claude Code)
|
|
4500
|
+
allowed-tools: Bash(npx agentskit rules:*)
|
|
4501
|
+
---
|
|
4502
|
+
|
|
4503
|
+
Ask which editor (or "all"). Run the matching:
|
|
4504
|
+
- \`npx @agentskit/cli rules cursor\`
|
|
4505
|
+
- \`npx @agentskit/cli rules windsurf\`
|
|
4506
|
+
- \`npx @agentskit/cli rules codex\`
|
|
4507
|
+
- \`npx @agentskit/cli rules claude-code\`
|
|
4508
|
+
|
|
4509
|
+
After writing, summarise which files landed and what each one does.
|
|
4510
|
+
`
|
|
4511
|
+
}
|
|
4512
|
+
];
|
|
4513
|
+
|
|
4514
|
+
// src/rules.ts
|
|
4515
|
+
var CODEX_BLOCK_START = "<!-- agentskit-codex-profile:start -->";
|
|
4516
|
+
var CODEX_BLOCK_END = "<!-- agentskit-codex-profile:end -->";
|
|
4517
|
+
async function ensureDir2(path5) {
|
|
4518
|
+
await mkdir(dirname(path5), { recursive: true });
|
|
4519
|
+
}
|
|
4520
|
+
async function writeIfChanged(absPath, contents, force) {
|
|
4521
|
+
let existing;
|
|
4522
|
+
try {
|
|
4523
|
+
existing = await readFile(absPath, "utf8");
|
|
4524
|
+
} catch {
|
|
4525
|
+
}
|
|
4526
|
+
if (existing === contents) return "skipped";
|
|
4527
|
+
if (existing !== void 0 && !force) {
|
|
4528
|
+
return "skipped";
|
|
4529
|
+
}
|
|
4530
|
+
await ensureDir2(absPath);
|
|
4531
|
+
await writeFile(absPath, contents, "utf8");
|
|
4532
|
+
return existing === void 0 ? "wrote" : "updated";
|
|
4533
|
+
}
|
|
4534
|
+
async function writeCursor(rootDir, force) {
|
|
4535
|
+
const path5 = join(rootDir, ".cursor", "rules", "agentskit.mdc");
|
|
4536
|
+
const action = await writeIfChanged(path5, CURSOR_RULE, force);
|
|
4537
|
+
return [{ path: path5, action }];
|
|
4538
|
+
}
|
|
4539
|
+
async function writeWindsurf(rootDir, force) {
|
|
4540
|
+
const path5 = join(rootDir, ".windsurfrules");
|
|
4541
|
+
const action = await writeIfChanged(path5, WINDSURF_RULE, force);
|
|
4542
|
+
return [{ path: path5, action }];
|
|
4543
|
+
}
|
|
4544
|
+
async function writeCodex(rootDir, force) {
|
|
4545
|
+
const path5 = join(rootDir, "AGENTS.md");
|
|
4546
|
+
let existing = "";
|
|
4547
|
+
try {
|
|
4548
|
+
existing = await readFile(path5, "utf8");
|
|
4549
|
+
} catch {
|
|
4550
|
+
}
|
|
4551
|
+
const startIdx = existing.indexOf(CODEX_BLOCK_START);
|
|
4552
|
+
const endIdx = startIdx >= 0 ? existing.lastIndexOf(CODEX_BLOCK_END, existing.length) : -1;
|
|
4553
|
+
if (startIdx >= 0 && endIdx <= startIdx) {
|
|
4554
|
+
throw new ConfigError({
|
|
4555
|
+
code: ErrorCodes.AK_CONFIG_INVALID,
|
|
4556
|
+
message: `${path5}: found agentskit-codex-profile:start sentinel but no matching :end after it \u2014 refusing to modify a half-edited block.`,
|
|
4557
|
+
hint: "Restore the closing sentinel or remove the partial block, then re-run."
|
|
4558
|
+
});
|
|
4559
|
+
}
|
|
4560
|
+
let next;
|
|
4561
|
+
if (startIdx >= 0 && endIdx > startIdx) {
|
|
4562
|
+
next = existing.slice(0, startIdx) + CODEX_PROFILE.trimEnd() + existing.slice(endIdx + CODEX_BLOCK_END.length);
|
|
4563
|
+
} else if (existing) {
|
|
4564
|
+
next = `${existing.replace(/\s+$/, "")}
|
|
4565
|
+
|
|
4566
|
+
${CODEX_PROFILE}`;
|
|
4567
|
+
} else {
|
|
4568
|
+
next = CODEX_PROFILE;
|
|
4569
|
+
}
|
|
4570
|
+
if (next === existing) return [{ path: path5, action: "skipped" }];
|
|
4571
|
+
if (existing && !force) {
|
|
4572
|
+
return [{ path: path5, action: "skipped" }];
|
|
4573
|
+
}
|
|
4574
|
+
await ensureDir2(path5);
|
|
4575
|
+
await writeFile(path5, next, "utf8");
|
|
4576
|
+
return [{ path: path5, action: existing ? "updated" : "wrote" }];
|
|
4577
|
+
}
|
|
4578
|
+
async function writeClaudeCode(rootDir, force) {
|
|
4579
|
+
const out = [];
|
|
4580
|
+
const skillRoot = join(rootDir, ".claude", "skills", "agentskit");
|
|
4581
|
+
for (const file of CLAUDE_CODE_SKILL) {
|
|
4582
|
+
const abs = join(skillRoot, file.path);
|
|
4583
|
+
const action = await writeIfChanged(abs, file.contents, force);
|
|
4584
|
+
out.push({ path: abs, action });
|
|
4585
|
+
}
|
|
4586
|
+
const commandsRoot = join(rootDir, ".claude", "commands");
|
|
4587
|
+
for (const cmd of CLAUDE_CODE_SLASH_COMMANDS) {
|
|
4588
|
+
const abs = join(commandsRoot, cmd.path);
|
|
4589
|
+
const action = await writeIfChanged(abs, cmd.contents, force);
|
|
4590
|
+
out.push({ path: abs, action });
|
|
4591
|
+
}
|
|
4592
|
+
return out;
|
|
4593
|
+
}
|
|
4594
|
+
async function writeRules(editor, options = {}) {
|
|
4595
|
+
const root = resolve(options.rootDir ?? process.cwd());
|
|
4596
|
+
const force = options.force === true;
|
|
4597
|
+
if (editor === "all") {
|
|
4598
|
+
return [
|
|
4599
|
+
{ editor: "cursor", files: await writeCursor(root, force) },
|
|
4600
|
+
{ editor: "windsurf", files: await writeWindsurf(root, force) },
|
|
4601
|
+
{ editor: "codex", files: await writeCodex(root, force) },
|
|
4602
|
+
{ editor: "claude-code", files: await writeClaudeCode(root, force) }
|
|
4603
|
+
];
|
|
4604
|
+
}
|
|
4605
|
+
switch (editor) {
|
|
4606
|
+
case "cursor":
|
|
4607
|
+
return [{ editor, files: await writeCursor(root, force) }];
|
|
4608
|
+
case "windsurf":
|
|
4609
|
+
return [{ editor, files: await writeWindsurf(root, force) }];
|
|
4610
|
+
case "codex":
|
|
4611
|
+
return [{ editor, files: await writeCodex(root, force) }];
|
|
4612
|
+
case "claude-code":
|
|
4613
|
+
return [{ editor, files: await writeClaudeCode(root, force) }];
|
|
4614
|
+
}
|
|
4615
|
+
}
|
|
4616
|
+
|
|
4617
|
+
// src/commands/rules.ts
|
|
4618
|
+
var VALID = ["cursor", "windsurf", "codex", "claude-code", "all"];
|
|
4619
|
+
function registerRulesCommand(program) {
|
|
4620
|
+
program.command("rules <editor>").description(
|
|
4621
|
+
"Write editor rule files (cursor | windsurf | codex | claude-code | all). Teaches the editor AgentsKit conventions so generated code respects named-export-only, package boundaries, and the for-agents/* manifest."
|
|
4622
|
+
).option("--out <dir>", "Workspace root to write files into (default: cwd)").option("-f, --force", "Overwrite existing rule files (codex / claude-code skill always update in place)").action(async (editor, options) => {
|
|
4623
|
+
if (!VALID.includes(editor)) {
|
|
4624
|
+
process.stderr.write(`unknown editor "${editor}". Valid: ${VALID.join(", ")}
|
|
4625
|
+
`);
|
|
4626
|
+
process.exit(1);
|
|
4627
|
+
}
|
|
4628
|
+
try {
|
|
4629
|
+
const results = await writeRules(editor, {
|
|
4630
|
+
rootDir: options.out,
|
|
4631
|
+
force: options.force === true
|
|
4632
|
+
});
|
|
4633
|
+
const counts = { wrote: 0, updated: 0, skipped: 0 };
|
|
4634
|
+
for (const { editor: ed, files } of results) {
|
|
4635
|
+
process.stdout.write(`
|
|
4636
|
+
[${ed}]
|
|
4637
|
+
`);
|
|
4638
|
+
for (const f of files) {
|
|
4639
|
+
counts[f.action]++;
|
|
4640
|
+
process.stdout.write(` ${f.action.padEnd(7)} ${f.path}
|
|
4641
|
+
`);
|
|
4642
|
+
}
|
|
4643
|
+
}
|
|
4644
|
+
process.stdout.write(
|
|
4645
|
+
`
|
|
4646
|
+
Done \u2014 ${counts.wrote} wrote, ${counts.updated} updated, ${counts.skipped} skipped.
|
|
4647
|
+
`
|
|
4648
|
+
);
|
|
4649
|
+
if (counts.skipped > 0 && options.force !== true) {
|
|
4650
|
+
process.stdout.write(`(re-run with --force to overwrite skipped files)
|
|
4651
|
+
`);
|
|
4652
|
+
}
|
|
4653
|
+
} catch (err) {
|
|
4654
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
4655
|
+
process.stderr.write(`
|
|
4656
|
+
rules failed: ${message}
|
|
4657
|
+
`);
|
|
4658
|
+
process.exit(1);
|
|
4659
|
+
}
|
|
4660
|
+
});
|
|
4661
|
+
}
|
|
4662
|
+
var RAW_BASE = "https://raw.githubusercontent.com/AgentsKit-io/agentskit-registry/main";
|
|
4663
|
+
var HOSTED_BASE = `${RAW_BASE}/public/r`;
|
|
4664
|
+
async function getJson(url, fetchImpl) {
|
|
4665
|
+
const res = await fetchImpl(url);
|
|
4666
|
+
if (!res.ok) throw new Error(`${res.status} ${res.statusText}`);
|
|
4667
|
+
return res.json();
|
|
4668
|
+
}
|
|
4669
|
+
async function getText(url, fetchImpl) {
|
|
4670
|
+
const res = await fetchImpl(url);
|
|
4671
|
+
if (!res.ok) throw new Error(`${res.status} ${res.statusText}`);
|
|
4672
|
+
return res.text();
|
|
4673
|
+
}
|
|
4674
|
+
async function fetchAgent(id, options = {}) {
|
|
4675
|
+
const fetchImpl = options.fetchImpl ?? globalThis.fetch;
|
|
4676
|
+
try {
|
|
4677
|
+
const hosted = await getJson(`${HOSTED_BASE}/${id}.json`, fetchImpl);
|
|
4678
|
+
if (hosted?.sources?.length) return hosted;
|
|
4679
|
+
throw new Error("hosted entry missing sources");
|
|
4680
|
+
} catch {
|
|
4681
|
+
const meta = await getJson(`${RAW_BASE}/registry/${id}/meta.json`, fetchImpl);
|
|
4682
|
+
const sources = await Promise.all(
|
|
4683
|
+
meta.files.map(async (rel) => ({
|
|
4684
|
+
path: rel,
|
|
4685
|
+
content: await getText(`${RAW_BASE}/registry/${id}/${rel}`, fetchImpl)
|
|
4686
|
+
}))
|
|
4687
|
+
);
|
|
4688
|
+
return { ...meta, sources };
|
|
4689
|
+
}
|
|
4690
|
+
}
|
|
4691
|
+
function resolveSystemPrompt(agent) {
|
|
4692
|
+
if (agent.skill?.systemPrompt) return agent.skill.systemPrompt;
|
|
4693
|
+
const src = agent.sources.find((f) => f.path === "agent.ts")?.content;
|
|
4694
|
+
if (!src) return null;
|
|
4695
|
+
const m = src.match(/systemPrompt:\s*`((?:\\.|[^`\\])*)`/);
|
|
4696
|
+
return m ? m[1].replace(/\\`/g, "`").replace(/\\\$\{/g, "${") : null;
|
|
4697
|
+
}
|
|
4698
|
+
async function defaultExists(path5) {
|
|
4699
|
+
const { access } = await import('fs/promises');
|
|
4700
|
+
try {
|
|
4701
|
+
await access(path5);
|
|
4702
|
+
return true;
|
|
4703
|
+
} catch {
|
|
4704
|
+
return false;
|
|
4705
|
+
}
|
|
4706
|
+
}
|
|
4707
|
+
async function addAgent(id, options = {}) {
|
|
4708
|
+
const agent = await fetchAgent(id, options);
|
|
4709
|
+
const baseDir = options.outDir ?? "agents";
|
|
4710
|
+
const targetDir = join(baseDir, id);
|
|
4711
|
+
const exists = options.existsImpl ?? defaultExists;
|
|
4712
|
+
const write = options.writeFileImpl ?? (async (path5, content) => {
|
|
4713
|
+
await mkdir(dirname(path5), { recursive: true });
|
|
4714
|
+
await writeFile(path5, content, "utf8");
|
|
4715
|
+
});
|
|
4716
|
+
const written = [];
|
|
4717
|
+
for (const file of agent.sources) {
|
|
4718
|
+
const dest = join(targetDir, file.path);
|
|
4719
|
+
if (!options.force && await exists(dest)) {
|
|
4720
|
+
throw new Error(`${dest} already exists (re-run with --force to overwrite)`);
|
|
4721
|
+
}
|
|
4722
|
+
await write(dest, file.content);
|
|
4723
|
+
written.push(dest);
|
|
4724
|
+
}
|
|
4725
|
+
return { agent, written, targetDir };
|
|
4726
|
+
}
|
|
4727
|
+
function lineDiff(a, b) {
|
|
4728
|
+
const x = a.split("\n");
|
|
4729
|
+
const y = b.split("\n");
|
|
4730
|
+
const m = x.length;
|
|
4731
|
+
const n = y.length;
|
|
4732
|
+
const lcs = Array.from({ length: m + 1 }, () => new Array(n + 1).fill(0));
|
|
4733
|
+
for (let i2 = m - 1; i2 >= 0; i2--) {
|
|
4734
|
+
for (let j2 = n - 1; j2 >= 0; j2--) {
|
|
4735
|
+
lcs[i2][j2] = x[i2] === y[j2] ? lcs[i2 + 1][j2 + 1] + 1 : Math.max(lcs[i2 + 1][j2], lcs[i2][j2 + 1]);
|
|
4736
|
+
}
|
|
4737
|
+
}
|
|
4738
|
+
const out = [];
|
|
4739
|
+
let i = 0;
|
|
4740
|
+
let j = 0;
|
|
4741
|
+
while (i < m && j < n) {
|
|
4742
|
+
if (x[i] === y[j]) {
|
|
4743
|
+
out.push({ type: " ", text: x[i] });
|
|
4744
|
+
i++;
|
|
4745
|
+
j++;
|
|
4746
|
+
} else if (lcs[i + 1][j] >= lcs[i][j + 1]) {
|
|
4747
|
+
out.push({ type: "-", text: x[i++] });
|
|
4748
|
+
} else {
|
|
4749
|
+
out.push({ type: "+", text: y[j++] });
|
|
4750
|
+
}
|
|
4751
|
+
}
|
|
4752
|
+
while (i < m) out.push({ type: "-", text: x[i++] });
|
|
4753
|
+
while (j < n) out.push({ type: "+", text: y[j++] });
|
|
4754
|
+
return out;
|
|
4755
|
+
}
|
|
4756
|
+
async function diffAgent(id, options = {}) {
|
|
4757
|
+
const agent = await fetchAgent(id, options);
|
|
4758
|
+
const targetDir = join(options.outDir ?? "agents", id);
|
|
4759
|
+
const readLocal = options.readFileImpl ?? (async (p) => {
|
|
4760
|
+
const { readFile: readFile6 } = await import('fs/promises');
|
|
4761
|
+
try {
|
|
4762
|
+
return await readFile6(p, "utf8");
|
|
4763
|
+
} catch {
|
|
4764
|
+
return null;
|
|
4765
|
+
}
|
|
4766
|
+
});
|
|
4767
|
+
const files = [];
|
|
4768
|
+
for (const f of agent.sources) {
|
|
4769
|
+
const local = await readLocal(join(targetDir, f.path));
|
|
4770
|
+
if (local == null) {
|
|
4771
|
+
files.push({ path: f.path, status: "missing-local", upstream: f.content });
|
|
4772
|
+
} else if (local === f.content) {
|
|
4773
|
+
files.push({ path: f.path, status: "unchanged", upstream: f.content });
|
|
4774
|
+
} else {
|
|
4775
|
+
files.push({ path: f.path, status: "modified", diff: lineDiff(local, f.content), upstream: f.content });
|
|
4776
|
+
}
|
|
4777
|
+
}
|
|
4778
|
+
return { agent, targetDir, files };
|
|
4779
|
+
}
|
|
4780
|
+
|
|
4781
|
+
// src/commands/add.ts
|
|
4782
|
+
function registerAddCommand(program) {
|
|
4783
|
+
program.command("add <agent>").description(
|
|
4784
|
+
'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`.'
|
|
4785
|
+
).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(
|
|
4786
|
+
async (agent, options) => {
|
|
4787
|
+
try {
|
|
4788
|
+
const result = await addAgent(agent, { outDir: options.out, force: options.force === true });
|
|
4789
|
+
process.stdout.write(`
|
|
4790
|
+
Added "${result.agent.title}" \u2192 ${result.targetDir}/
|
|
4791
|
+
`);
|
|
4792
|
+
for (const f of result.written) process.stdout.write(` wrote ${f}
|
|
4793
|
+
`);
|
|
4794
|
+
if (result.agent.packages.length > 0) {
|
|
4795
|
+
process.stdout.write(`
|
|
4796
|
+
Install the packages it uses:
|
|
4797
|
+
`);
|
|
4798
|
+
process.stdout.write(` npm install ${result.agent.packages.join(" ")} @agentskit/adapters
|
|
4799
|
+
`);
|
|
4800
|
+
}
|
|
4801
|
+
const required = (result.agent.env ?? []).filter((e) => e.required);
|
|
4802
|
+
if (required.length > 0) {
|
|
4803
|
+
process.stdout.write(`
|
|
4804
|
+
Required environment:
|
|
4805
|
+
`);
|
|
4806
|
+
for (const e of required) process.stdout.write(` ${e.name} \u2014 ${e.description}
|
|
4807
|
+
`);
|
|
4808
|
+
}
|
|
4809
|
+
const readme2 = result.written.find((f) => f.toLowerCase().endsWith("readme.md"));
|
|
4810
|
+
process.stdout.write(readme2 ? `
|
|
4811
|
+
See ${readme2} for usage.
|
|
4812
|
+
` : "\n");
|
|
4813
|
+
if (options.run) {
|
|
4814
|
+
const systemPrompt = resolveSystemPrompt(result.agent);
|
|
4815
|
+
if (!systemPrompt) {
|
|
4816
|
+
process.stderr.write(
|
|
4817
|
+
`
|
|
4818
|
+
--run is not supported for "${agent}" (it composes tools/keys). Use it as a library \u2014 see the README.
|
|
4819
|
+
`
|
|
4820
|
+
);
|
|
4821
|
+
process.exit(1);
|
|
4822
|
+
}
|
|
4823
|
+
process.stdout.write(`
|
|
4824
|
+
Running "${result.agent.title}" via ${options.provider}\u2026
|
|
4825
|
+
|
|
4826
|
+
`);
|
|
4827
|
+
await runAgent(options.run, {
|
|
4828
|
+
provider: options.provider,
|
|
4829
|
+
model: options.model,
|
|
4830
|
+
apiKey: options.apiKey,
|
|
4831
|
+
systemPrompt,
|
|
4832
|
+
maxSteps: "8"
|
|
4833
|
+
});
|
|
4834
|
+
}
|
|
4835
|
+
} catch (err) {
|
|
4836
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
4837
|
+
process.stderr.write(`
|
|
4838
|
+
add failed: ${message}
|
|
4839
|
+
`);
|
|
4840
|
+
process.stderr.write(`(browse agents at https://registry.agentskit.io)
|
|
4841
|
+
`);
|
|
4842
|
+
process.exit(1);
|
|
4843
|
+
}
|
|
4844
|
+
}
|
|
4845
|
+
);
|
|
4846
|
+
}
|
|
4847
|
+
function registerDiffCommand(program) {
|
|
4848
|
+
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) => {
|
|
4849
|
+
try {
|
|
4850
|
+
const { targetDir, files } = await diffAgent(agent, { outDir: options.out });
|
|
4851
|
+
let changed = 0;
|
|
4852
|
+
for (const f of files) {
|
|
4853
|
+
if (f.status === "unchanged") continue;
|
|
4854
|
+
changed++;
|
|
4855
|
+
process.stdout.write(`
|
|
4856
|
+
${f.status === "missing-local" ? "missing" : "modified"}: ${join(targetDir, f.path)}
|
|
4857
|
+
`);
|
|
4858
|
+
if (f.diff) {
|
|
4859
|
+
for (const line of f.diff) {
|
|
4860
|
+
if (line.type === " ") continue;
|
|
4861
|
+
process.stdout.write(` ${line.type} ${line.text}
|
|
4862
|
+
`);
|
|
4863
|
+
}
|
|
4864
|
+
}
|
|
4865
|
+
}
|
|
4866
|
+
process.stdout.write(
|
|
4867
|
+
changed === 0 ? `
|
|
4868
|
+
${agent}: up to date with the registry.
|
|
4869
|
+
` : `
|
|
4870
|
+
${changed} file(s) differ. Run \`agentskit update ${agent}\` to apply the registry version.
|
|
4871
|
+
`
|
|
4872
|
+
);
|
|
4873
|
+
} catch (err) {
|
|
4874
|
+
process.stderr.write(`
|
|
4875
|
+
diff failed: ${err instanceof Error ? err.message : String(err)}
|
|
4876
|
+
`);
|
|
4877
|
+
process.exit(1);
|
|
4878
|
+
}
|
|
4879
|
+
});
|
|
4880
|
+
}
|
|
4881
|
+
function registerUpdateCommand(program) {
|
|
4882
|
+
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) => {
|
|
4883
|
+
try {
|
|
4884
|
+
const { targetDir, files } = await diffAgent(agent, { outDir: options.out });
|
|
4885
|
+
const changed = files.filter((f) => f.status !== "unchanged");
|
|
4886
|
+
if (changed.length === 0) {
|
|
4887
|
+
process.stdout.write(`
|
|
4888
|
+
${agent}: already up to date.
|
|
4889
|
+
`);
|
|
4890
|
+
return;
|
|
4891
|
+
}
|
|
4892
|
+
if (!options.force) {
|
|
4893
|
+
process.stdout.write(`
|
|
4894
|
+
Will overwrite ${changed.length} file(s) with the registry version:
|
|
4895
|
+
`);
|
|
4896
|
+
for (const f of changed) process.stdout.write(` ${f.path} (${f.status})
|
|
4897
|
+
`);
|
|
4898
|
+
}
|
|
4899
|
+
for (const f of changed) {
|
|
4900
|
+
const dest = join(targetDir, f.path);
|
|
4901
|
+
await mkdir(dirname(dest), { recursive: true });
|
|
4902
|
+
await writeFile(dest, f.upstream, "utf8");
|
|
4903
|
+
process.stdout.write(` updated ${dest}
|
|
4904
|
+
`);
|
|
4905
|
+
}
|
|
4906
|
+
process.stdout.write(`
|
|
4907
|
+
Updated ${agent}. Review the changes with your VCS before committing.
|
|
4908
|
+
`);
|
|
4909
|
+
} catch (err) {
|
|
4910
|
+
process.stderr.write(`
|
|
4911
|
+
update failed: ${err instanceof Error ? err.message : String(err)}
|
|
4912
|
+
`);
|
|
4913
|
+
process.exit(1);
|
|
4914
|
+
}
|
|
4915
|
+
});
|
|
4916
|
+
}
|
|
4162
4917
|
|
|
4163
4918
|
// src/commands/index.ts
|
|
4164
4919
|
function createCli() {
|
|
@@ -4174,9 +4929,14 @@ function createCli() {
|
|
|
4174
4929
|
registerRagCommand(program);
|
|
4175
4930
|
registerAiCommand(program);
|
|
4176
4931
|
registerFlowCommand(program);
|
|
4932
|
+
registerPiiCommand(program);
|
|
4933
|
+
registerRulesCommand(program);
|
|
4934
|
+
registerAddCommand(program);
|
|
4935
|
+
registerDiffCommand(program);
|
|
4936
|
+
registerUpdateCommand(program);
|
|
4177
4937
|
return program;
|
|
4178
4938
|
}
|
|
4179
4939
|
|
|
4180
4940
|
export { ChatApp, HookDispatcher, McpClient, applyPolicyToTool, applyPolicyToTools, bridgeMcpServers, buildRagFromConfig, computeCost, configHooksToHandlers, createCli, createOpenAiEmbedder, defaultPolicy, derivePreview, disposeMcpClients, evaluatePolicy, findLatestSession, findSession, forkSession, generateSessionId, getPricing, indexSources, listSessions, loadConfig, loadPlugins, mergePluginsIntoBundle, registerPricing, renameSession, renderChatHeader, renderReport, resolveChatProvider, resolveSession, runAgent, runDoctor, sessionFilePath, startDev, startTunnel, writeSessionMeta, writeStarterProject };
|
|
4181
|
-
//# sourceMappingURL=chunk-
|
|
4182
|
-
//# sourceMappingURL=chunk-
|
|
4941
|
+
//# sourceMappingURL=chunk-YT74CXQA.js.map
|
|
4942
|
+
//# sourceMappingURL=chunk-YT74CXQA.js.map
|