@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.
Files changed (87) hide show
  1. package/README.md +9 -0
  2. package/docs/guides/add-channel.md +25 -0
  3. package/docs/guides/add-knowledge.md +134 -0
  4. package/docs/guides/agentkit-skills-architecture.md +471 -0
  5. package/docs/guides/channels-production-handoff.md +2 -0
  6. package/docs/guides/connect-telegram.md +17 -0
  7. package/docs/guides/connect-whatsapp-zapster.md +16 -0
  8. package/docs/guides/create-agent.md +10 -1
  9. package/docs/guides/run-evals.md +36 -1
  10. package/docs/llms-full.txt +90 -1
  11. package/docs/llms.txt +9 -2
  12. package/package.json +2 -1
  13. package/src/cli/cloud-client.ts +10 -2
  14. package/src/cli/commands/channels.ts +67 -3
  15. package/src/cli/commands/knowledge.ts +136 -0
  16. package/src/cli/deploy-chat-ui.ts +7 -0
  17. package/src/cli/deploy-readiness.ts +19 -0
  18. package/src/cli/help.ts +26 -2
  19. package/src/cli/index.ts +140 -8
  20. package/src/cloud/artifact.ts +92 -1
  21. package/src/cloud/contracts.ts +16 -0
  22. package/src/create-project.ts +38 -6
  23. package/src/index.ts +142 -1
  24. package/src/providers/pi.ts +1 -1
  25. package/src/providers/test.ts +1 -1
  26. package/src/runtime/channel-buffer.ts +30 -0
  27. package/src/runtime/channels.ts +1 -0
  28. package/src/runtime/chat.ts +21 -2
  29. package/src/runtime/config.ts +175 -0
  30. package/src/runtime/core/manifest.ts +37 -0
  31. package/src/runtime/database.ts +93 -2
  32. package/src/runtime/db-commands.ts +9 -0
  33. package/src/runtime/deploy-readiness.ts +12 -0
  34. package/src/runtime/dev-server.ts +201 -11
  35. package/src/runtime/evals.ts +210 -20
  36. package/src/runtime/inspect.ts +39 -0
  37. package/src/runtime/knowledge/chunk.ts +333 -0
  38. package/src/runtime/knowledge/config.ts +135 -0
  39. package/src/runtime/knowledge/embeddings.ts +133 -0
  40. package/src/runtime/knowledge/ingest.ts +521 -0
  41. package/src/runtime/knowledge/prompt-policy.ts +30 -0
  42. package/src/runtime/knowledge/retrieve.ts +283 -0
  43. package/src/runtime/knowledge/schema.ts +56 -0
  44. package/src/runtime/knowledge/tool.ts +64 -0
  45. package/src/runtime/knowledge/vector.ts +258 -0
  46. package/src/runtime/spec.ts +152 -0
  47. package/src/runtime/sync.ts +144 -0
  48. package/src/runtime/targets/cloudflare/build.ts +514 -4
  49. package/src/runtime/tools.ts +121 -1
  50. package/src/runtime/traces.ts +41 -0
  51. package/src/storage/sqlite.ts +141 -0
  52. package/src/templates/blank.ts +16 -5
  53. package/src/templates/dentista.ts +17 -2
  54. package/src/templates/skills/agentkit-build-agent/SKILL.md +51 -0
  55. package/src/templates/skills/agentkit-build-agent/templates/appointment-intake.instructions.md +20 -0
  56. package/src/templates/skills/agentkit-build-agent/templates/sales-qualifier.instructions.md +17 -0
  57. package/src/templates/skills/agentkit-build-agent/templates/support-agent.instructions.md +16 -0
  58. package/src/templates/skills/agentkit-capsule/SKILL.md +62 -0
  59. package/src/templates/skills/agentkit-capsule/references/docs-router.md +15 -0
  60. package/src/templates/skills/agentkit-channels/SKILL.md +62 -0
  61. package/src/templates/skills/agentkit-channels/references/channel-buffering.md +58 -0
  62. package/src/templates/skills/agentkit-channels/references/channel-debugging.md +37 -0
  63. package/src/templates/skills/agentkit-channels/references/telegram.md +37 -0
  64. package/src/templates/skills/agentkit-channels/references/whatsapp-zapster.md +37 -0
  65. package/src/templates/skills/agentkit-database/SKILL.md +45 -0
  66. package/src/templates/skills/agentkit-database/templates/appointments.schema.sql +15 -0
  67. package/src/templates/skills/agentkit-database/templates/leads.schema.sql +17 -0
  68. package/src/templates/skills/agentkit-deploy/SKILL.md +44 -0
  69. package/src/templates/skills/agentkit-evals/SKILL.md +60 -0
  70. package/src/templates/skills/agentkit-evals/templates/multi-turn.eval.md +22 -0
  71. package/src/templates/skills/agentkit-evals/templates/no-leak.eval.md +14 -0
  72. package/src/templates/skills/agentkit-evals/templates/smoke.eval.md +14 -0
  73. package/src/templates/skills/agentkit-evals/templates/tool-call.eval.md +18 -0
  74. package/src/templates/skills/agentkit-knowledge/SKILL.md +40 -0
  75. package/src/templates/skills/agentkit-knowledge/templates/faq.md +14 -0
  76. package/src/templates/skills/agentkit-knowledge/templates/policies.md +14 -0
  77. package/src/templates/skills/agentkit-knowledge/templates/prices.csv +3 -0
  78. package/src/templates/skills/agentkit-prompts/SKILL.md +45 -0
  79. package/src/templates/skills/agentkit-prompts/templates/knowledge-grounded-faq.instructions.md +11 -0
  80. package/src/templates/skills/agentkit-provider/SKILL.md +57 -0
  81. package/src/templates/skills/agentkit-security/SKILL.md +55 -0
  82. package/src/templates/skills/agentkit-tools/SKILL.md +36 -0
  83. package/src/templates/skills/agentkit-tools/examples/database-write.tool.md +35 -0
  84. package/src/templates/skills/agentkit-tools/examples/eval-safe-external-action.tool.md +37 -0
  85. package/src/templates/skills/agentkit-tools/examples/lookup-order.tool.md +46 -0
  86. package/src/templates/skills/agentkit-troubleshooting/SKILL.md +52 -0
  87. 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 inspect stored local conversations
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
- throw new Error("Usage: agentkit conversations list | agentkit conversations show <conversation-id>");
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, docsFull: docs.llmsFull, goal: goalParts.join(" ").trim() }));
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; docsFull: string; goal: string }): 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.docsFull}
873
+ ${skillLine}- ${input.docsLlms}
744
874
 
745
875
  ${goal}
746
876
 
747
877
  Rules:
748
- - Follow the AgentKit contract in llms-full.txt.
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.
@@ -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
  }
@@ -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
 
@@ -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 = template.files(target.name, {
31
- agentkitDependency: await resolveAgentKitDependency(),
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);