@andreprado/agentkit 0.1.0-alpha.5 → 0.1.0-alpha.7
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/README.md +9 -0
- package/docs/guides/add-channel.md +25 -0
- package/docs/guides/add-knowledge.md +134 -0
- package/docs/guides/agentkit-skills-architecture.md +471 -0
- package/docs/guides/channels-production-handoff.md +2 -0
- package/docs/guides/connect-telegram.md +17 -0
- package/docs/guides/connect-whatsapp-zapster.md +16 -0
- package/docs/guides/create-agent.md +10 -1
- package/docs/guides/run-evals.md +36 -1
- package/docs/llms-full.txt +90 -1
- package/docs/llms.txt +9 -2
- package/package.json +2 -1
- package/src/cli/cloud-client.ts +10 -2
- package/src/cli/commands/channels.ts +67 -3
- package/src/cli/commands/knowledge.ts +136 -0
- package/src/cli/deploy-chat-ui.ts +7 -0
- package/src/cli/deploy-readiness.ts +19 -0
- package/src/cli/help.ts +26 -2
- package/src/cli/index.ts +140 -8
- package/src/cloud/artifact.ts +92 -1
- package/src/cloud/contracts.ts +16 -0
- package/src/create-project.ts +38 -6
- package/src/index.ts +142 -1
- package/src/providers/pi.ts +1 -1
- package/src/providers/test.ts +1 -1
- package/src/runtime/channel-buffer.ts +30 -0
- package/src/runtime/channels.ts +1 -0
- package/src/runtime/chat.ts +21 -2
- package/src/runtime/config.ts +175 -0
- package/src/runtime/core/manifest.ts +37 -0
- package/src/runtime/database.ts +93 -2
- package/src/runtime/db-commands.ts +9 -0
- package/src/runtime/deploy-readiness.ts +12 -0
- package/src/runtime/dev-server.ts +201 -11
- package/src/runtime/evals.ts +210 -20
- package/src/runtime/inspect.ts +39 -0
- package/src/runtime/knowledge/chunk.ts +333 -0
- package/src/runtime/knowledge/config.ts +135 -0
- package/src/runtime/knowledge/embeddings.ts +133 -0
- package/src/runtime/knowledge/ingest.ts +521 -0
- package/src/runtime/knowledge/prompt-policy.ts +30 -0
- package/src/runtime/knowledge/retrieve.ts +283 -0
- package/src/runtime/knowledge/schema.ts +56 -0
- package/src/runtime/knowledge/tool.ts +64 -0
- package/src/runtime/knowledge/vector.ts +258 -0
- package/src/runtime/spec.ts +152 -0
- package/src/runtime/sync.ts +144 -0
- package/src/runtime/targets/cloudflare/build.ts +514 -4
- package/src/runtime/tools.ts +121 -1
- package/src/runtime/traces.ts +41 -0
- package/src/storage/sqlite.ts +141 -0
- package/src/templates/blank.ts +16 -5
- package/src/templates/dentista.ts +17 -2
- package/src/templates/skills/agentkit-build-agent/SKILL.md +51 -0
- package/src/templates/skills/agentkit-build-agent/templates/appointment-intake.instructions.md +20 -0
- package/src/templates/skills/agentkit-build-agent/templates/sales-qualifier.instructions.md +17 -0
- package/src/templates/skills/agentkit-build-agent/templates/support-agent.instructions.md +16 -0
- package/src/templates/skills/agentkit-capsule/SKILL.md +62 -0
- package/src/templates/skills/agentkit-capsule/references/docs-router.md +15 -0
- package/src/templates/skills/agentkit-channels/SKILL.md +62 -0
- package/src/templates/skills/agentkit-channels/references/channel-buffering.md +58 -0
- package/src/templates/skills/agentkit-channels/references/channel-debugging.md +37 -0
- package/src/templates/skills/agentkit-channels/references/telegram.md +37 -0
- package/src/templates/skills/agentkit-channels/references/whatsapp-zapster.md +37 -0
- package/src/templates/skills/agentkit-database/SKILL.md +45 -0
- package/src/templates/skills/agentkit-database/templates/appointments.schema.sql +15 -0
- package/src/templates/skills/agentkit-database/templates/leads.schema.sql +17 -0
- package/src/templates/skills/agentkit-deploy/SKILL.md +44 -0
- package/src/templates/skills/agentkit-evals/SKILL.md +60 -0
- package/src/templates/skills/agentkit-evals/templates/multi-turn.eval.md +22 -0
- package/src/templates/skills/agentkit-evals/templates/no-leak.eval.md +14 -0
- package/src/templates/skills/agentkit-evals/templates/smoke.eval.md +14 -0
- package/src/templates/skills/agentkit-evals/templates/tool-call.eval.md +18 -0
- package/src/templates/skills/agentkit-knowledge/SKILL.md +40 -0
- package/src/templates/skills/agentkit-knowledge/templates/faq.md +14 -0
- package/src/templates/skills/agentkit-knowledge/templates/policies.md +14 -0
- package/src/templates/skills/agentkit-knowledge/templates/prices.csv +3 -0
- package/src/templates/skills/agentkit-prompts/SKILL.md +45 -0
- package/src/templates/skills/agentkit-prompts/templates/knowledge-grounded-faq.instructions.md +11 -0
- package/src/templates/skills/agentkit-provider/SKILL.md +57 -0
- package/src/templates/skills/agentkit-security/SKILL.md +55 -0
- package/src/templates/skills/agentkit-tools/SKILL.md +36 -0
- package/src/templates/skills/agentkit-tools/examples/database-write.tool.md +35 -0
- package/src/templates/skills/agentkit-tools/examples/eval-safe-external-action.tool.md +37 -0
- package/src/templates/skills/agentkit-tools/examples/lookup-order.tool.md +46 -0
- package/src/templates/skills/agentkit-troubleshooting/SKILL.md +52 -0
- package/src/templates/support.ts +15 -4
package/src/cli/help.ts
CHANGED
|
@@ -21,9 +21,14 @@ Start:
|
|
|
21
21
|
agentkit inspect
|
|
22
22
|
|
|
23
23
|
Build:
|
|
24
|
+
agentkit knowledge add <path>
|
|
25
|
+
agentkit knowledge search <query>
|
|
26
|
+
agentkit spec init --brief <text>
|
|
27
|
+
agentkit sync run
|
|
24
28
|
agentkit tool <name> [--input <path-or-json>]
|
|
25
29
|
agentkit db migrate
|
|
26
30
|
agentkit eval run
|
|
31
|
+
agentkit eval from-conversation <id>
|
|
27
32
|
agentkit conversations list
|
|
28
33
|
|
|
29
34
|
Deploy:
|
|
@@ -53,13 +58,23 @@ Usage:
|
|
|
53
58
|
agentkit chat-ui --deploy [--port <number>] [--token-file <path>]
|
|
54
59
|
agentkit chat --message <text> [--conversation-id <id>]
|
|
55
60
|
agentkit tool <name> [--input <path-or-json>]
|
|
61
|
+
agentkit knowledge add <path-or-url>
|
|
62
|
+
agentkit knowledge sync
|
|
63
|
+
agentkit knowledge inspect
|
|
64
|
+
agentkit knowledge search <query> [--top-k <number>]
|
|
65
|
+
agentkit spec init --brief <text> [--out <path>] [--force]
|
|
66
|
+
agentkit spec check [--file <path>]
|
|
67
|
+
agentkit sync init [--force]
|
|
68
|
+
agentkit sync run [--file <path>]
|
|
56
69
|
agentkit db migrate
|
|
57
70
|
agentkit db reset --yes
|
|
58
71
|
agentkit db shell
|
|
59
72
|
agentkit db seed [--file <path>]
|
|
60
73
|
agentkit eval run
|
|
74
|
+
agentkit eval from-conversation <conversation-id> [--out <path>] [--force]
|
|
61
75
|
agentkit conversations list
|
|
62
76
|
agentkit conversations show <conversation-id>
|
|
77
|
+
agentkit conversations trace <conversation-id>
|
|
63
78
|
agentkit channels list
|
|
64
79
|
agentkit channels add <website|telegram|whatsapp> <name> [--provider zapster|meta] [--api <url>]
|
|
65
80
|
agentkit channels setup <name> [--apply] [--api <url>]
|
|
@@ -106,9 +121,12 @@ Commands:
|
|
|
106
121
|
chat-ui Run a local chat UI, optionally pointed at a hosted deploy
|
|
107
122
|
chat Send one message to the local Agent Capsule
|
|
108
123
|
tool Run one registered tool directly
|
|
124
|
+
knowledge Add, sync, inspect, and search local Knowledge sources
|
|
125
|
+
spec Create or check the agent implementation contract from the owner brief
|
|
126
|
+
sync Run or scaffold catalog/data synchronization
|
|
109
127
|
db Manage the local SQLite database
|
|
110
|
-
eval Run local eval files
|
|
111
|
-
conversations List and
|
|
128
|
+
eval Run local eval files or create one from a conversation
|
|
129
|
+
conversations List, inspect, and trace stored local conversations
|
|
112
130
|
channels Manage hosted channel resources
|
|
113
131
|
inspect Print machine-readable Agent Capsule state
|
|
114
132
|
build Build a hosted deploy artifact
|
|
@@ -142,6 +160,12 @@ export function renderCommandHelp(command: string): string {
|
|
|
142
160
|
"chat-ui": "agentkit chat-ui --deploy [--port <number>] [--token-file <path>]",
|
|
143
161
|
chat: 'agentkit chat --message "hello" [--conversation-id <id>]',
|
|
144
162
|
tool: "agentkit tool <name> [--input <path-or-json>]",
|
|
163
|
+
knowledge: "agentkit knowledge add <path-or-url> | sync | inspect | search <query> [--top-k <number>]",
|
|
164
|
+
spec: 'agentkit spec init --brief "owner request" | agentkit spec check',
|
|
165
|
+
sync: "agentkit sync init [--force] | agentkit sync run [--file <path>]",
|
|
166
|
+
eval: "agentkit eval run | agentkit eval from-conversation <conversation-id> [--out <path>] [--force]",
|
|
167
|
+
conversations:
|
|
168
|
+
"agentkit conversations list | agentkit conversations show <conversation-id> | agentkit conversations trace <conversation-id>",
|
|
145
169
|
deploy:
|
|
146
170
|
'agentkit deploy [--smoke "hello"] | agentkit deploy smoke [--message "hello"] | agentkit deploy doctor | status | pause | resume',
|
|
147
171
|
secret:
|
package/src/cli/index.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { spawn } from "node:child_process";
|
|
2
|
+
import { existsSync } from "node:fs";
|
|
2
3
|
import { mkdir, readFile, writeFile } from "node:fs/promises";
|
|
3
4
|
import { dirname, join, relative, resolve } from "node:path";
|
|
4
5
|
|
|
@@ -8,6 +9,7 @@ import { findAgentCapsuleRoot, loadAgentCapsule } from "../runtime/config";
|
|
|
8
9
|
import { readLocalDeployStateIfExists, type LocalDeployState } from "../runtime/core/deploy-state";
|
|
9
10
|
import { resolveBuildTarget, resolveDeployTarget } from "../runtime/core/targets";
|
|
10
11
|
import { getConversationFromCwd, listConversationsFromCwd } from "../runtime/conversations";
|
|
12
|
+
import { getConversationTraceFromCwd } from "../runtime/traces";
|
|
11
13
|
import { runAgentMessageFromCwd } from "../runtime/chat";
|
|
12
14
|
import { deployBuildToAgentKitCloud, writeLocalDeployState } from "../runtime/deploy";
|
|
13
15
|
import {
|
|
@@ -16,9 +18,11 @@ import {
|
|
|
16
18
|
resetLocalDatabase,
|
|
17
19
|
seedLocalDatabase,
|
|
18
20
|
} from "../runtime/db-commands";
|
|
19
|
-
import { runEvalsFromCwd } from "../runtime/evals";
|
|
21
|
+
import { runEvalsFromCwd, writeEvalFromConversation } from "../runtime/evals";
|
|
20
22
|
import { findAgentKitDocs } from "../runtime/docs";
|
|
21
23
|
import { listCapsuleEnv, setCapsuleEnv, unsetCapsuleEnv } from "../runtime/env";
|
|
24
|
+
import { checkAgentSpec, initializeAgentSpec } from "../runtime/spec";
|
|
25
|
+
import { initializeSyncScaffold, runCapsuleSync } from "../runtime/sync";
|
|
22
26
|
import { runToolFromCwd } from "../runtime/tool-runner";
|
|
23
27
|
import { startAgentDevServer } from "../runtime/dev-server";
|
|
24
28
|
import { inspectAgentCapsule } from "../runtime/inspect";
|
|
@@ -61,6 +65,7 @@ import {
|
|
|
61
65
|
import { renderCommandHelp, renderCommandReference, renderHelp } from "./help";
|
|
62
66
|
import { runInheritedCommand, waitForShutdown } from "./process";
|
|
63
67
|
import { handleChannelsCommand } from "./commands/channels";
|
|
68
|
+
import { handleKnowledgeCommand } from "./commands/knowledge";
|
|
64
69
|
|
|
65
70
|
async function main() {
|
|
66
71
|
const args = parseArgs(process.argv.slice(2));
|
|
@@ -118,6 +123,7 @@ async function main() {
|
|
|
118
123
|
console.log(" npm install");
|
|
119
124
|
}
|
|
120
125
|
console.log(" open this folder in Codex or Claude Code");
|
|
126
|
+
console.log(" coding agents start at skills/agentkit-capsule/SKILL.md");
|
|
121
127
|
console.log(' ask: "Develop an appointment and intake agent for an ophthalmology office"');
|
|
122
128
|
console.log(' npm run chat -- --message "hello"');
|
|
123
129
|
console.log(" npm run dev");
|
|
@@ -144,6 +150,7 @@ async function main() {
|
|
|
144
150
|
console.log(`API: ${devServer.urls.api}`);
|
|
145
151
|
console.log(`Inspect: ${devServer.urls.inspect}`);
|
|
146
152
|
console.log(`Storage: ${devServer.storage ?? "managed"}`);
|
|
153
|
+
console.log("Reload: prompts/config reload per request; restart after changing tool modules or dependencies");
|
|
147
154
|
await waitForShutdown(devServer.stop);
|
|
148
155
|
return;
|
|
149
156
|
}
|
|
@@ -221,6 +228,8 @@ async function main() {
|
|
|
221
228
|
const result = await migrateLocalDatabase(process.cwd());
|
|
222
229
|
console.log("Local database migrated");
|
|
223
230
|
console.log(`Database: ${result.databasePath}`);
|
|
231
|
+
console.log(`Migrations: ${result.migrationsPath ?? "none"}`);
|
|
232
|
+
console.log(`Applied: ${result.migrationsApplied.length > 0 ? result.migrationsApplied.join(", ") : "none"}`);
|
|
224
233
|
console.log(`Schema: ${result.schemaPath ?? "none"}`);
|
|
225
234
|
return;
|
|
226
235
|
}
|
|
@@ -234,6 +243,8 @@ async function main() {
|
|
|
234
243
|
console.log("Local database reset");
|
|
235
244
|
console.log(`Deleted: ${result.resetPath}`);
|
|
236
245
|
console.log(`Database: ${result.databasePath}`);
|
|
246
|
+
console.log(`Migrations: ${result.migrationsPath ?? "none"}`);
|
|
247
|
+
console.log(`Applied: ${result.migrationsApplied.length > 0 ? result.migrationsApplied.join(", ") : "none"}`);
|
|
237
248
|
console.log(`Schema: ${result.schemaPath ?? "none"}`);
|
|
238
249
|
return;
|
|
239
250
|
}
|
|
@@ -256,6 +267,8 @@ async function main() {
|
|
|
256
267
|
const result = await seedLocalDatabase(process.cwd(), seedFile);
|
|
257
268
|
console.log("Local database seeded");
|
|
258
269
|
console.log(`Database: ${result.databasePath}`);
|
|
270
|
+
console.log(`Migrations: ${result.migrationsPath ?? "none"}`);
|
|
271
|
+
console.log(`Applied: ${result.migrationsApplied.length > 0 ? result.migrationsApplied.join(", ") : "none"}`);
|
|
259
272
|
console.log(`Schema: ${result.schemaPath ?? "none"}`);
|
|
260
273
|
console.log(`Seed: ${result.seedPath}`);
|
|
261
274
|
return;
|
|
@@ -265,10 +278,39 @@ async function main() {
|
|
|
265
278
|
}
|
|
266
279
|
|
|
267
280
|
if (args.command === "eval") {
|
|
268
|
-
const [subcommand] = args.positional;
|
|
281
|
+
const [subcommand, conversationId] = args.positional;
|
|
282
|
+
|
|
283
|
+
if (subcommand === "from-conversation") {
|
|
284
|
+
if (!conversationId) {
|
|
285
|
+
throw new Error("Missing conversation id. Usage: agentkit eval from-conversation <conversation-id> [--out <path>] [--force]");
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
const out = parseOptionalStringFlag(
|
|
289
|
+
args.flags.out,
|
|
290
|
+
"out",
|
|
291
|
+
"agentkit eval from-conversation <conversation-id> --out <path>",
|
|
292
|
+
);
|
|
293
|
+
const name = parseOptionalStringFlag(
|
|
294
|
+
args.flags.name,
|
|
295
|
+
"name",
|
|
296
|
+
"agentkit eval from-conversation <conversation-id> --name <name>",
|
|
297
|
+
);
|
|
298
|
+
const result = await writeEvalFromConversation(process.cwd(), {
|
|
299
|
+
conversationId,
|
|
300
|
+
out,
|
|
301
|
+
name,
|
|
302
|
+
force: args.flags.force === true,
|
|
303
|
+
});
|
|
304
|
+
|
|
305
|
+
console.log("Eval created from conversation");
|
|
306
|
+
console.log(`Conversation: ${result.conversationId}`);
|
|
307
|
+
console.log(`File: ${relativePath(result.root, result.file)}`);
|
|
308
|
+
console.log(`Turns: ${result.turns}`);
|
|
309
|
+
return;
|
|
310
|
+
}
|
|
269
311
|
|
|
270
312
|
if (subcommand !== "run") {
|
|
271
|
-
throw new Error("Usage: agentkit eval run");
|
|
313
|
+
throw new Error("Usage: agentkit eval run | agentkit eval from-conversation <conversation-id> [--out <path>] [--force]");
|
|
272
314
|
}
|
|
273
315
|
|
|
274
316
|
const summary = await runEvalsFromCwd(process.cwd());
|
|
@@ -337,7 +379,93 @@ async function main() {
|
|
|
337
379
|
return;
|
|
338
380
|
}
|
|
339
381
|
|
|
340
|
-
|
|
382
|
+
if (subcommand === "trace") {
|
|
383
|
+
if (!conversationId) {
|
|
384
|
+
throw new Error("Missing conversation id. Usage: agentkit conversations trace <conversation-id>");
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
const trace = await getConversationTraceFromCwd(process.cwd(), conversationId);
|
|
388
|
+
console.log(JSON.stringify(trace, null, 2));
|
|
389
|
+
return;
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
throw new Error("Usage: agentkit conversations list | agentkit conversations show <conversation-id> | agentkit conversations trace <conversation-id>");
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
if (args.command === "knowledge") {
|
|
396
|
+
await handleKnowledgeCommand(args);
|
|
397
|
+
return;
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
if (args.command === "sync") {
|
|
401
|
+
const [subcommand] = args.positional;
|
|
402
|
+
|
|
403
|
+
if (subcommand === "init") {
|
|
404
|
+
const result = await initializeSyncScaffold(process.cwd(), {
|
|
405
|
+
force: args.flags.force === true,
|
|
406
|
+
});
|
|
407
|
+
|
|
408
|
+
console.log("Sync scaffold ready");
|
|
409
|
+
if (result.files.length === 0) {
|
|
410
|
+
console.log("Files: none written; existing files kept");
|
|
411
|
+
} else {
|
|
412
|
+
console.log(`Files: ${result.files.join(", ")}`);
|
|
413
|
+
}
|
|
414
|
+
return;
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
if (subcommand === "run") {
|
|
418
|
+
const file = parseOptionalStringFlag(args.flags.file, "file", "agentkit sync run --file <path>");
|
|
419
|
+
const result = await runCapsuleSync(process.cwd(), { file });
|
|
420
|
+
|
|
421
|
+
console.log("Sync completed");
|
|
422
|
+
console.log(`File: ${relativePath(result.root, result.file)}`);
|
|
423
|
+
console.log(`Output: ${JSON.stringify(result.output)}`);
|
|
424
|
+
return;
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
throw new Error("Usage: agentkit sync init [--force] | agentkit sync run [--file <path>]");
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
if (args.command === "spec") {
|
|
431
|
+
const [subcommand] = args.positional;
|
|
432
|
+
|
|
433
|
+
if (subcommand === "init") {
|
|
434
|
+
const brief = parseRequiredStringFlag(
|
|
435
|
+
args.flags.brief,
|
|
436
|
+
"brief",
|
|
437
|
+
'agentkit spec init --brief "agent for a real estate brokerage"',
|
|
438
|
+
);
|
|
439
|
+
const out = parseOptionalStringFlag(args.flags.out, "out", "agentkit spec init --out <path>");
|
|
440
|
+
const result = await initializeAgentSpec(process.cwd(), {
|
|
441
|
+
brief,
|
|
442
|
+
out,
|
|
443
|
+
force: args.flags.force === true,
|
|
444
|
+
});
|
|
445
|
+
|
|
446
|
+
console.log("Agent spec created");
|
|
447
|
+
console.log(`File: ${relativePath(result.root, result.file)}`);
|
|
448
|
+
return;
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
if (subcommand === "check") {
|
|
452
|
+
const file = parseOptionalStringFlag(args.flags.file, "file", "agentkit spec check --file <path>");
|
|
453
|
+
const result = await checkAgentSpec(process.cwd(), file);
|
|
454
|
+
|
|
455
|
+
if (result.ok) {
|
|
456
|
+
console.log(`Agent spec ok: ${relativePath(result.root, result.file)}`);
|
|
457
|
+
return;
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
console.log(`Agent spec incomplete: ${relativePath(result.root, result.file)}`);
|
|
461
|
+
for (const heading of result.missingHeadings) {
|
|
462
|
+
console.log(` - missing ## ${heading}`);
|
|
463
|
+
}
|
|
464
|
+
process.exitCode = 1;
|
|
465
|
+
return;
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
throw new Error('Usage: agentkit spec init --brief "<owner request>" [--out <path>] [--force] | agentkit spec check [--file <path>]');
|
|
341
469
|
}
|
|
342
470
|
|
|
343
471
|
if (args.command === "inspect") {
|
|
@@ -718,15 +846,17 @@ async function main() {
|
|
|
718
846
|
|
|
719
847
|
const root = await findAgentCapsuleRoot(process.cwd());
|
|
720
848
|
const docs = findAgentKitDocs();
|
|
721
|
-
console.log(renderHandoffPrompt({ target, root,
|
|
849
|
+
console.log(renderHandoffPrompt({ target, root, docsLlms: docs.llms, goal: goalParts.join(" ").trim() }));
|
|
722
850
|
return;
|
|
723
851
|
}
|
|
724
852
|
|
|
725
853
|
throw new Error(`Unknown command: ${args.command}`);
|
|
726
854
|
}
|
|
727
855
|
|
|
728
|
-
function renderHandoffPrompt(input: { target: string; root: string;
|
|
856
|
+
function renderHandoffPrompt(input: { target: string; root: string; docsLlms: string; goal: string }): string {
|
|
729
857
|
const agentName = input.target === "claude" ? "Claude Code" : "Codex";
|
|
858
|
+
const skillRouter = join(input.root, "skills/agentkit-capsule/SKILL.md");
|
|
859
|
+
const skillLine = existsSync(skillRouter) ? `- ${skillRouter}\n` : "";
|
|
730
860
|
const goal = input.goal
|
|
731
861
|
? `Owner request:
|
|
732
862
|
${input.goal}`
|
|
@@ -740,12 +870,14 @@ ${input.root}
|
|
|
740
870
|
Read these files first:
|
|
741
871
|
|
|
742
872
|
- ${join(input.root, "AGENTKIT.md")}
|
|
743
|
-
- ${input.
|
|
873
|
+
${skillLine}- ${input.docsLlms}
|
|
744
874
|
|
|
745
875
|
${goal}
|
|
746
876
|
|
|
747
877
|
Rules:
|
|
748
|
-
-
|
|
878
|
+
- Start with the AgentKit capsule skill when it exists.
|
|
879
|
+
- Use llms.txt as the docs router.
|
|
880
|
+
- Read llms-full.txt only when a skill or ambiguous framework behavior requires the complete contract.
|
|
749
881
|
- Treat the owner's request as the brief.
|
|
750
882
|
- Build or update the agent inside this capsule as far as you can without asking for obvious restatements.
|
|
751
883
|
- Do not wait for a wizard or recipe; implement directly in the capsule files.
|
package/src/cloud/artifact.ts
CHANGED
|
@@ -1,10 +1,15 @@
|
|
|
1
1
|
import { createHash } from "node:crypto";
|
|
2
|
-
import { readFile } from "node:fs/promises";
|
|
2
|
+
import { readFile, stat } from "node:fs/promises";
|
|
3
|
+
import { extname, isAbsolute, relative, resolve } from "node:path";
|
|
3
4
|
|
|
4
5
|
import type { AgentBuildResult, AgentManifestWithBundle } from "../runtime/targets/cloudflare/build";
|
|
5
6
|
import { AgentKitError } from "../runtime/errors";
|
|
6
7
|
import type { HostedDeployArtifact } from "./contracts";
|
|
7
8
|
|
|
9
|
+
const HOSTED_KNOWLEDGE_MAX_SOURCE_BYTES = 5 * 1024 * 1024;
|
|
10
|
+
const HOSTED_KNOWLEDGE_MAX_TOTAL_BYTES = 9 * 1024 * 1024;
|
|
11
|
+
const HOSTED_KNOWLEDGE_SUPPORTED_EXTENSIONS = new Set([".md", ".markdown", ".txt", ".csv"]);
|
|
12
|
+
|
|
8
13
|
export async function createHostedDeployArtifact(build: AgentBuildResult): Promise<HostedDeployArtifact> {
|
|
9
14
|
const [manifestSource, workerSource, wranglerSource] = await Promise.all([
|
|
10
15
|
readFile(build.manifestPath, "utf8"),
|
|
@@ -40,9 +45,95 @@ export async function createHostedDeployArtifact(build: AgentBuildResult): Promi
|
|
|
40
45
|
};
|
|
41
46
|
}
|
|
42
47
|
|
|
48
|
+
if (manifest.knowledge.enabled) {
|
|
49
|
+
artifact.knowledge_sources = await createHostedKnowledgeSources(build.root, manifest);
|
|
50
|
+
}
|
|
51
|
+
|
|
43
52
|
return artifact;
|
|
44
53
|
}
|
|
45
54
|
|
|
55
|
+
async function createHostedKnowledgeSources(
|
|
56
|
+
root: string,
|
|
57
|
+
manifest: AgentManifestWithBundle,
|
|
58
|
+
): Promise<NonNullable<HostedDeployArtifact["knowledge_sources"]>> {
|
|
59
|
+
const sources: NonNullable<HostedDeployArtifact["knowledge_sources"]>["sources"] = [];
|
|
60
|
+
let totalBytes = 0;
|
|
61
|
+
|
|
62
|
+
for (const source of manifest.knowledge.sources) {
|
|
63
|
+
if (source.kind === "url") {
|
|
64
|
+
throw new AgentKitError(
|
|
65
|
+
"artifact_knowledge_source_unsupported",
|
|
66
|
+
"Hosted deploy can automatically sync local Knowledge files only. URL Knowledge sources require a hosted ingestion connector.",
|
|
67
|
+
);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
const absolutePath = resolve(root, source.value);
|
|
71
|
+
const sourceKey = capsuleRelativePath(root, absolutePath);
|
|
72
|
+
const extension = extname(sourceKey).toLowerCase();
|
|
73
|
+
|
|
74
|
+
if (!HOSTED_KNOWLEDGE_SUPPORTED_EXTENSIONS.has(extension)) {
|
|
75
|
+
throw new AgentKitError(
|
|
76
|
+
"artifact_knowledge_source_unsupported",
|
|
77
|
+
`Knowledge source "${sourceKey}" is not supported for hosted deploy. Use .md, .txt, or .csv.`,
|
|
78
|
+
);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
const stats = await stat(absolutePath).catch((error) => {
|
|
82
|
+
throw new AgentKitError("artifact_knowledge_source_missing", `Knowledge source "${sourceKey}" was not found.`, {
|
|
83
|
+
cause: error,
|
|
84
|
+
});
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
if (!stats.isFile()) {
|
|
88
|
+
throw new AgentKitError("artifact_knowledge_source_invalid", `Knowledge source "${sourceKey}" must be a file.`);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
if (stats.size > HOSTED_KNOWLEDGE_MAX_SOURCE_BYTES) {
|
|
92
|
+
throw new AgentKitError(
|
|
93
|
+
"artifact_knowledge_source_too_large",
|
|
94
|
+
`Knowledge source "${sourceKey}" is too large for automatic deploy sync. Keep each source under 5MB.`,
|
|
95
|
+
);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
totalBytes += stats.size;
|
|
99
|
+
|
|
100
|
+
if (totalBytes > HOSTED_KNOWLEDGE_MAX_TOTAL_BYTES) {
|
|
101
|
+
throw new AgentKitError(
|
|
102
|
+
"artifact_knowledge_sources_too_large",
|
|
103
|
+
"Knowledge sources are too large for automatic deploy sync. Keep total packaged Knowledge under 9MB.",
|
|
104
|
+
);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
const content = await readFile(absolutePath, "utf8");
|
|
108
|
+
sources.push({
|
|
109
|
+
kind: "file",
|
|
110
|
+
source_key: sourceKey,
|
|
111
|
+
title: source.title,
|
|
112
|
+
content,
|
|
113
|
+
sha256: sha256(content),
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
return {
|
|
118
|
+
content_type: "application/json",
|
|
119
|
+
sources,
|
|
120
|
+
sha256: sha256(JSON.stringify(sources)),
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
function capsuleRelativePath(root: string, absolutePath: string): string {
|
|
125
|
+
const relativePath = relative(root, absolutePath);
|
|
126
|
+
|
|
127
|
+
if (!relativePath || relativePath.startsWith("..") || isAbsolute(relativePath)) {
|
|
128
|
+
throw new AgentKitError(
|
|
129
|
+
"artifact_knowledge_source_outside_capsule",
|
|
130
|
+
"Knowledge source paths must stay inside the Agent Capsule.",
|
|
131
|
+
);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
return relativePath.split("\\").join("/");
|
|
135
|
+
}
|
|
136
|
+
|
|
46
137
|
function sha256(source: string): string {
|
|
47
138
|
return createHash("sha256").update(source).digest("hex");
|
|
48
139
|
}
|
package/src/cloud/contracts.ts
CHANGED
|
@@ -16,6 +16,17 @@ export type HostedDeployArtifact = {
|
|
|
16
16
|
source: string;
|
|
17
17
|
sha256: string;
|
|
18
18
|
};
|
|
19
|
+
knowledge_sources?: {
|
|
20
|
+
content_type: "application/json";
|
|
21
|
+
sources: Array<{
|
|
22
|
+
kind: "file";
|
|
23
|
+
source_key: string;
|
|
24
|
+
title: string | null;
|
|
25
|
+
content: string;
|
|
26
|
+
sha256: string;
|
|
27
|
+
}>;
|
|
28
|
+
sha256: string;
|
|
29
|
+
};
|
|
19
30
|
};
|
|
20
31
|
|
|
21
32
|
export type CreateDeployRequest = {
|
|
@@ -37,6 +48,11 @@ export type CreateDeployResponse = {
|
|
|
37
48
|
mode: string;
|
|
38
49
|
private_token?: string;
|
|
39
50
|
};
|
|
51
|
+
knowledge?: {
|
|
52
|
+
enabled: boolean;
|
|
53
|
+
sources: number;
|
|
54
|
+
chunks: number;
|
|
55
|
+
};
|
|
40
56
|
};
|
|
41
57
|
};
|
|
42
58
|
|
package/src/create-project.ts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { execFile } from "node:child_process";
|
|
2
|
-
import { mkdir, readFile, stat, writeFile } from "node:fs/promises";
|
|
3
|
-
import { basename, dirname, join, resolve } from "node:path";
|
|
2
|
+
import { mkdir, readFile, readdir, stat, writeFile } from "node:fs/promises";
|
|
3
|
+
import { basename, dirname, join, relative, resolve } from "node:path";
|
|
4
4
|
import { promisify } from "node:util";
|
|
5
5
|
import { fileURLToPath } from "node:url";
|
|
6
6
|
|
|
7
|
-
import { getTemplate } from "./templates";
|
|
7
|
+
import { getTemplate, type TemplateFile } from "./templates";
|
|
8
8
|
|
|
9
9
|
const execFileAsync = promisify(execFile);
|
|
10
10
|
const moduleDir = dirname(fileURLToPath(import.meta.url));
|
|
@@ -27,9 +27,12 @@ export async function createProject(options: CreateProjectOptions): Promise<Crea
|
|
|
27
27
|
|
|
28
28
|
const template = getTemplate(options.template);
|
|
29
29
|
const projectPath = target.path;
|
|
30
|
-
const files =
|
|
31
|
-
|
|
32
|
-
|
|
30
|
+
const files = [
|
|
31
|
+
...template.files(target.name, {
|
|
32
|
+
agentkitDependency: await resolveAgentKitDependency(),
|
|
33
|
+
}),
|
|
34
|
+
...(await loadDefaultSkillFiles()),
|
|
35
|
+
];
|
|
33
36
|
|
|
34
37
|
if (target.currentDirectory) {
|
|
35
38
|
await ensureNoFileCollisions(projectPath, files.map((file) => file.path));
|
|
@@ -126,6 +129,35 @@ async function resolveAgentKitDependency(): Promise<string> {
|
|
|
126
129
|
return packageJson.version;
|
|
127
130
|
}
|
|
128
131
|
|
|
132
|
+
async function loadDefaultSkillFiles(): Promise<TemplateFile[]> {
|
|
133
|
+
const sourceRoot = join(moduleDir, "templates", "skills");
|
|
134
|
+
const sourceFiles = await listFiles(sourceRoot);
|
|
135
|
+
|
|
136
|
+
return Promise.all(
|
|
137
|
+
sourceFiles.map(async (sourcePath) => ({
|
|
138
|
+
path: join("skills", relative(sourceRoot, sourcePath)).replaceAll("\\", "/"),
|
|
139
|
+
contents: await readFile(sourcePath, "utf8"),
|
|
140
|
+
})),
|
|
141
|
+
);
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
async function listFiles(directory: string): Promise<string[]> {
|
|
145
|
+
const entries = await readdir(directory, { withFileTypes: true });
|
|
146
|
+
const files = await Promise.all(
|
|
147
|
+
entries.map(async (entry) => {
|
|
148
|
+
const path = join(directory, entry.name);
|
|
149
|
+
|
|
150
|
+
if (entry.isDirectory()) {
|
|
151
|
+
return listFiles(path);
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
return entry.isFile() ? [path] : [];
|
|
155
|
+
}),
|
|
156
|
+
);
|
|
157
|
+
|
|
158
|
+
return files.flat().sort();
|
|
159
|
+
}
|
|
160
|
+
|
|
129
161
|
async function directoryExists(path: string): Promise<boolean> {
|
|
130
162
|
try {
|
|
131
163
|
const result = await stat(path);
|