@andreprado/agentkit 0.1.0-alpha.2 → 0.1.0-alpha.4
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 +45 -6
- package/docs/guides/add-tool.md +1 -1
- package/docs/guides/channels-implementation-map.md +243 -0
- package/docs/guides/create-agent.md +23 -4
- package/docs/guides/prepare-deploy.md +18 -6
- package/docs/guides/run-evals.md +28 -2
- package/docs/guides/security-rules.md +1 -1
- package/docs/guides/use-provider.md +16 -2
- package/docs/llms-full.txt +70 -38
- package/docs/llms.txt +15 -4
- package/package.json +1 -2
- package/src/cli/index.ts +1190 -36
- package/src/cloud/artifact.ts +48 -0
- package/src/cloud/client.ts +79 -0
- package/src/cloud/contracts.ts +47 -0
- package/src/cloud/index.ts +3 -0
- package/src/index.ts +1 -1
- package/src/providers/test.ts +51 -0
- package/src/runtime/chat.ts +59 -4
- package/src/runtime/deploy.ts +1 -1
- package/src/runtime/dev-server.ts +154 -16
- package/src/runtime/runtime-contract.ts +16 -2
- package/src/runtime/targets/cloudflare/build.ts +83 -4
- package/src/storage/sqlite.ts +2 -2
- package/src/templates/blank.ts +52 -9
- package/src/templates/dentista.ts +988 -0
- package/src/templates/index.ts +2 -0
- package/src/templates/support.ts +50 -9
- package/src/runtime/targets/cloudflare/deploy.ts +0 -5475
|
@@ -542,9 +542,33 @@ export class AgentKitConversationStore extends DurableObject {
|
|
|
542
542
|
return this.persistMessages(await request.json());
|
|
543
543
|
}
|
|
544
544
|
|
|
545
|
+
if (request.method === "GET" && url.pathname === "/messages") {
|
|
546
|
+
return this.getMessages(url.searchParams.get("conversationId"));
|
|
547
|
+
}
|
|
548
|
+
|
|
545
549
|
return Response.json({ error: { code: "not_found", message: "Unknown Durable Object route." } }, { status: 404 });
|
|
546
550
|
}
|
|
547
551
|
|
|
552
|
+
getMessages(conversationId) {
|
|
553
|
+
if (!conversationId) {
|
|
554
|
+
return Response.json({ messages: [] });
|
|
555
|
+
}
|
|
556
|
+
|
|
557
|
+
const rows = this.sql.exec(
|
|
558
|
+
"SELECT role, content FROM messages WHERE conversation_id = ? ORDER BY rowid ASC",
|
|
559
|
+
String(conversationId),
|
|
560
|
+
).toArray();
|
|
561
|
+
|
|
562
|
+
return Response.json({
|
|
563
|
+
messages: rows
|
|
564
|
+
.filter((row) => row.role === "user" || row.role === "assistant")
|
|
565
|
+
.map((row) => ({
|
|
566
|
+
role: String(row.role),
|
|
567
|
+
content: String(row.content),
|
|
568
|
+
})),
|
|
569
|
+
});
|
|
570
|
+
}
|
|
571
|
+
|
|
548
572
|
persistMessages(input) {
|
|
549
573
|
const now = new Date().toISOString();
|
|
550
574
|
const conversationId = String(input.conversationId || crypto.randomUUID());
|
|
@@ -662,6 +686,10 @@ export default {
|
|
|
662
686
|
});
|
|
663
687
|
}
|
|
664
688
|
|
|
689
|
+
if (request.method === "GET" && url.pathname === "/health") {
|
|
690
|
+
return Response.json({ status: "ok", agent: manifest.name });
|
|
691
|
+
}
|
|
692
|
+
|
|
665
693
|
if (request.method === "POST" && (url.pathname === "/chat" || url.pathname === "/v1/chat")) {
|
|
666
694
|
return handleChat(request, env);
|
|
667
695
|
}
|
|
@@ -911,7 +939,15 @@ async function handleChat(request, env) {
|
|
|
911
939
|
);
|
|
912
940
|
}
|
|
913
941
|
|
|
914
|
-
|
|
942
|
+
let conversationId;
|
|
943
|
+
|
|
944
|
+
try {
|
|
945
|
+
conversationId = normalizeConversationId(body.conversationId) ?? crypto.randomUUID();
|
|
946
|
+
} catch (error) {
|
|
947
|
+
return hostedErrorResponse(error);
|
|
948
|
+
}
|
|
949
|
+
|
|
950
|
+
const previousMessages = await loadConversationMessages(env, conversationId).catch(() => []);
|
|
915
951
|
let content;
|
|
916
952
|
const toolCalls = [];
|
|
917
953
|
|
|
@@ -939,7 +975,7 @@ async function handleChat(request, env) {
|
|
|
939
975
|
|
|
940
976
|
if (content === undefined) {
|
|
941
977
|
try {
|
|
942
|
-
content = await callHostedProvider(env, message, request.signal);
|
|
978
|
+
content = await callHostedProvider(env, [...previousMessages, { role: "user", content: message }], request.signal);
|
|
943
979
|
} catch (error) {
|
|
944
980
|
await persistFailure(env, conversationId, message, error);
|
|
945
981
|
return hostedErrorResponse(error);
|
|
@@ -978,7 +1014,7 @@ function isRecord(value) {
|
|
|
978
1014
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
979
1015
|
}
|
|
980
1016
|
|
|
981
|
-
async function callHostedProvider(env,
|
|
1017
|
+
async function callHostedProvider(env, messages, signal) {
|
|
982
1018
|
const adapter = getProviderAdapter(manifest.provider);
|
|
983
1019
|
const result = await adapter.run({
|
|
984
1020
|
agent: {
|
|
@@ -987,7 +1023,7 @@ async function callHostedProvider(env, message, signal) {
|
|
|
987
1023
|
provider: manifest.provider,
|
|
988
1024
|
},
|
|
989
1025
|
instructions: withToolVisibilityInstructions(instructions, hostedTools),
|
|
990
|
-
messages
|
|
1026
|
+
messages,
|
|
991
1027
|
tools: hostedTools,
|
|
992
1028
|
toolRuntime: createHostedProviderToolRuntime(env, signal),
|
|
993
1029
|
env,
|
|
@@ -1566,6 +1602,49 @@ async function persist(env, input) {
|
|
|
1566
1602
|
return response.json();
|
|
1567
1603
|
}
|
|
1568
1604
|
|
|
1605
|
+
async function loadConversationMessages(env, conversationId) {
|
|
1606
|
+
if (!env.AGENTKIT_CONVERSATIONS || !conversationId) {
|
|
1607
|
+
return [];
|
|
1608
|
+
}
|
|
1609
|
+
|
|
1610
|
+
const id = env.AGENTKIT_CONVERSATIONS.idFromName(conversationId);
|
|
1611
|
+
const stub = env.AGENTKIT_CONVERSATIONS.get(id);
|
|
1612
|
+
const response = await stub.fetch(
|
|
1613
|
+
\`https://agentkit.internal/messages?conversationId=\${encodeURIComponent(conversationId)}\`,
|
|
1614
|
+
);
|
|
1615
|
+
|
|
1616
|
+
if (!response.ok) {
|
|
1617
|
+
return [];
|
|
1618
|
+
}
|
|
1619
|
+
|
|
1620
|
+
const payload = await response.json();
|
|
1621
|
+
return Array.isArray(payload.messages)
|
|
1622
|
+
? payload.messages.filter((message) =>
|
|
1623
|
+
message &&
|
|
1624
|
+
typeof message === "object" &&
|
|
1625
|
+
(message.role === "user" || message.role === "assistant") &&
|
|
1626
|
+
typeof message.content === "string"
|
|
1627
|
+
)
|
|
1628
|
+
: [];
|
|
1629
|
+
}
|
|
1630
|
+
|
|
1631
|
+
function normalizeConversationId(value) {
|
|
1632
|
+
if (value === undefined || value === null) {
|
|
1633
|
+
return null;
|
|
1634
|
+
}
|
|
1635
|
+
|
|
1636
|
+
if (typeof value !== "string") {
|
|
1637
|
+
throw agentKitError("validation_error", "conversationId must be a non-empty string when provided.");
|
|
1638
|
+
}
|
|
1639
|
+
|
|
1640
|
+
const conversationId = value.trim();
|
|
1641
|
+
if (!conversationId) {
|
|
1642
|
+
throw agentKitError("validation_error", "conversationId must be a non-empty string when provided.");
|
|
1643
|
+
}
|
|
1644
|
+
|
|
1645
|
+
return conversationId;
|
|
1646
|
+
}
|
|
1647
|
+
|
|
1569
1648
|
function agentKitError(code, message) {
|
|
1570
1649
|
const error = new Error(message);
|
|
1571
1650
|
error.code = code;
|
package/src/storage/sqlite.ts
CHANGED
|
@@ -218,10 +218,10 @@ export class SqliteAgentKitStore {
|
|
|
218
218
|
this.db.close();
|
|
219
219
|
}
|
|
220
220
|
|
|
221
|
-
createConversation(input: { agentName: string; title: string | null; now?: string }): ConversationSummary {
|
|
221
|
+
createConversation(input: { id?: string; agentName: string; title: string | null; now?: string }): ConversationSummary {
|
|
222
222
|
return this.sqlite(() => {
|
|
223
223
|
const now = input.now ?? new Date().toISOString();
|
|
224
|
-
const id = randomId();
|
|
224
|
+
const id = input.id ?? randomId();
|
|
225
225
|
|
|
226
226
|
this.db
|
|
227
227
|
.prepare(
|
package/src/templates/blank.ts
CHANGED
|
@@ -65,6 +65,7 @@ node_modules/
|
|
|
65
65
|
contents: `# Optional: only needed after switching agentkit.config.ts to a Pi-backed real provider.
|
|
66
66
|
OPENAI_API_KEY=
|
|
67
67
|
ANTHROPIC_API_KEY=
|
|
68
|
+
OPENROUTER_API_KEY=
|
|
68
69
|
`,
|
|
69
70
|
},
|
|
70
71
|
{
|
|
@@ -151,12 +152,13 @@ Start building immediately:
|
|
|
151
152
|
- Edit \`prompts/instructions.md\` for the agent behavior.
|
|
152
153
|
- Edit \`agentkit.config.ts\` for provider, tools, secrets, access, and storage.
|
|
153
154
|
- Add TypeScript tools under \`tools/\` when the requested agent needs actions or external data.
|
|
155
|
+
- Do not wait for a wizard or recipe. AgentKit provides the scaffold and contract; you decide the implementation from the owner's brief.
|
|
154
156
|
- Ask follow-up questions only when missing information blocks a safe local implementation.
|
|
155
157
|
- State assumptions in the final response.
|
|
156
158
|
|
|
157
159
|
## Local Commands
|
|
158
160
|
|
|
159
|
-
- \`npm install\`:
|
|
161
|
+
- \`npm install\`: restore capsule dependencies if this capsule used \`--no-install\`, install failed, or \`node_modules\` was deleted.
|
|
160
162
|
- \`npm run dev\`: run the local Agent Capsule runtime.
|
|
161
163
|
- \`npm run chat -- --message "hello"\`: send one local chat message.
|
|
162
164
|
- \`npm run eval\`: run agent evals.
|
|
@@ -166,10 +168,17 @@ Start building immediately:
|
|
|
166
168
|
- \`npm run agentkit -- db seed --file seed.sql\`: apply local fixture data after migrate.
|
|
167
169
|
- \`npm run agentkit -- db shell\`: inspect local development data when needed.
|
|
168
170
|
- \`npm run agentkit -- inspect\`: print machine-readable capsule state.
|
|
169
|
-
- \`npm run agentkit -- env set <NAME>
|
|
171
|
+
- \`printf %s "$VALUE" | npm run agentkit -- env set <NAME> --stdin\`: write a local secret value to ignored \`.env\` without putting it in shell history.
|
|
170
172
|
- \`npm run agentkit -- env list\`: list local secret names without printing values.
|
|
171
173
|
- \`npm run agentkit -- docs full\`: print the full AgentKit contract path.
|
|
172
174
|
|
|
175
|
+
## Testing With A UI
|
|
176
|
+
|
|
177
|
+
- Local UI: run \`npm run dev\`, open the printed \`Chat:\` URL, and tell the owner the exact URL.
|
|
178
|
+
- Hosted UI: after \`npm run agentkit -- deploy\`, run \`npm run agentkit -- chat-ui --deploy\`, open the printed \`Chat:\` URL, and tell the owner it is connected to the hosted deploy.
|
|
179
|
+
- \`test/fake\` is deterministic. It is useful for scaffold checks, direct tool checks, and fake-provider evals, but it does not validate natural conversation quality.
|
|
180
|
+
- Before claiming real conversation behavior is tested, ask the owner which provider to use: OpenRouter, OpenAI, Anthropic, or another supported provider. Do not choose for them.
|
|
181
|
+
|
|
173
182
|
This blank capsule starts with the built-in \`test/fake\` provider, so local chat works without secrets or internet access. It is also deploy-ready by default: the user can edit the prompt, add tools, and run \`npm run agentkit -- deploy\`.
|
|
174
183
|
|
|
175
184
|
## Local Runtime Contract
|
|
@@ -210,14 +219,16 @@ Use \`ctx.db\` as the canonical helper. \`ctx.database\` and \`ctx.storage.sql\`
|
|
|
210
219
|
- AgentKit owns the hosted runtime, managed database, file storage, and production secret injection.
|
|
211
220
|
- Local scaffold, dev, chat, eval, inspect, database, and build commands are token-free.
|
|
212
221
|
- Hosted deploy requires an invited AgentKit Cloud alpha token. If no token is stored yet, ask the owner for one and run \`npm run agentkit -- login --token <token>\`.
|
|
213
|
-
- Put production secret values into managed secrets with \`npm run agentkit -- secret set <NAME>
|
|
222
|
+
- Put production secret values into managed secrets with \`npm run agentkit -- secret set <NAME> --from-local-env\`, \`--from-env\`, or \`--stdin\`, not into committed files or shell history.
|
|
214
223
|
- The user should not choose a deploy target, create hosted databases, create buckets, copy production secrets into this capsule, or run operator/admin commands.
|
|
215
|
-
-
|
|
224
|
+
- Hosted deploy writes the local chat/UI deploy access token to \`.agentkit/chat-access-token.json\`. Create extra client-facing tokens with \`npm run agentkit -- access token create <name> --out <path>\`.
|
|
225
|
+
- Use \`npm run agentkit -- deploy --smoke "hello"\` or \`npm run agentkit -- deploy smoke --message "hello"\` for an official hosted chat smoke check.
|
|
216
226
|
|
|
217
227
|
## Rules
|
|
218
228
|
|
|
219
229
|
- Keep required local secret names in \`.env.schema\` and values in ignored \`.env\`. AgentKit local commands load \`.env\` directly.
|
|
220
230
|
- Real providers are resolved by AgentKit through the internal Pi SDK backend; keep project code on \`@andreprado/agentkit\`.
|
|
231
|
+
- The owner must choose the real provider before you switch from \`test/fake\`. Update \`agentkit.config.ts\`, \`.env.schema\`, and local/hosted secrets after that choice.
|
|
221
232
|
- Do not commit \`.env\` or \`.agentkit/\`.
|
|
222
233
|
- Edit the agent contract in \`agentkit.config.ts\`.
|
|
223
234
|
- Edit instructions in \`prompts/instructions.md\`.
|
|
@@ -243,26 +254,51 @@ Turn the request into a working local capsule:
|
|
|
243
254
|
- Update \`agentkit.config.ts\` when tools, secrets, provider, or access rules change.
|
|
244
255
|
- Add TypeScript tools under \`tools/\` for real actions or external data.
|
|
245
256
|
- Keep the first version runnable with \`test/fake\` unless the owner explicitly asks for a real provider.
|
|
257
|
+
- Do not use a wizard or recipe. Build the capsule directly from the scaffold, the AgentKit contract, and the owner's brief.
|
|
246
258
|
- Make practical assumptions and list them in your final response.
|
|
247
259
|
- Ask follow-up questions only when missing information blocks a safe local implementation.
|
|
248
260
|
|
|
249
261
|
## Local Commands
|
|
250
262
|
|
|
251
263
|
\`\`\`sh
|
|
252
|
-
npm install
|
|
253
264
|
npm run typecheck
|
|
254
265
|
npm run agentkit -- inspect
|
|
255
266
|
npm run chat -- --message "hello"
|
|
256
267
|
\`\`\`
|
|
257
268
|
|
|
269
|
+
\`test/fake\` proves the scaffold and deterministic tool paths. It does not prove natural conversation quality.
|
|
270
|
+
|
|
271
|
+
\`agentkit new\` installs dependencies by default. Run \`npm install\` only if the capsule was created with \`--no-install\`, install failed, or \`node_modules\` was deleted.
|
|
272
|
+
|
|
258
273
|
Set local development secrets without opening code:
|
|
259
274
|
|
|
260
275
|
\`\`\`sh
|
|
261
|
-
npm run agentkit -- env set OPENAI_API_KEY
|
|
276
|
+
printf %s "$OPENAI_API_KEY" | npm run agentkit -- env set OPENAI_API_KEY --stdin
|
|
262
277
|
npm run agentkit -- inspect
|
|
263
278
|
npm run chat -- --message "hello"
|
|
264
279
|
\`\`\`
|
|
265
280
|
|
|
281
|
+
## Testing With A UI
|
|
282
|
+
|
|
283
|
+
Local UI:
|
|
284
|
+
|
|
285
|
+
\`\`\`sh
|
|
286
|
+
npm run dev
|
|
287
|
+
\`\`\`
|
|
288
|
+
|
|
289
|
+
Open the printed \`Chat:\` URL and tell the owner the exact URL.
|
|
290
|
+
|
|
291
|
+
Hosted deploy UI:
|
|
292
|
+
|
|
293
|
+
\`\`\`sh
|
|
294
|
+
npm run agentkit -- deploy
|
|
295
|
+
npm run agentkit -- chat-ui --deploy
|
|
296
|
+
\`\`\`
|
|
297
|
+
|
|
298
|
+
Open the printed \`Chat:\` URL and tell the owner this local UI is connected to the hosted deploy.
|
|
299
|
+
|
|
300
|
+
Before claiming real conversation behavior has been tested, ask the owner which provider to use: OpenRouter, OpenAI, Anthropic, or another supported provider. Do not choose for them. After they choose, update \`agentkit.config.ts\`, \`.env.schema\`, local secrets, hosted secrets if deploying, then rerun chat/UI checks.
|
|
301
|
+
|
|
266
302
|
If you add a tool, also run a fake-provider tool smoke test:
|
|
267
303
|
|
|
268
304
|
\`\`\`sh
|
|
@@ -283,9 +319,10 @@ This capsule is hosted-deploy ready by default.
|
|
|
283
319
|
2. Put agent-owned tables in \`schema.sql\`. AgentKit applies it locally and migrates/provisions hosted storage during deploy.
|
|
284
320
|
3. Run \`npm run agentkit -- build\` only when you want to validate the artifact locally.
|
|
285
321
|
4. If the owner has not logged in yet, ask for an invited AgentKit Cloud alpha token and run \`npm run agentkit -- login --token <token>\`.
|
|
286
|
-
5. Put production secrets into managed secrets with \`npm run agentkit -- secret set <NAME>
|
|
322
|
+
5. Put production secrets into managed secrets with \`npm run agentkit -- secret set <NAME> --from-local-env\`, \`--from-env\`, or \`--stdin\`.
|
|
287
323
|
6. Run \`npm run agentkit -- deploy\`.
|
|
288
|
-
7. Create client-facing deploy access tokens with \`npm run agentkit -- access token create <name>\` when a website or app needs
|
|
324
|
+
7. Run \`npm run agentkit -- chat-ui --deploy\` to test the hosted agent through a local UI using the auto-created \`.agentkit/chat-access-token.json\`. Create extra client-facing deploy access tokens with \`npm run agentkit -- access token create <name> --out <path>\` when a separate website or app needs its own credential.
|
|
325
|
+
8. Use \`npm run agentkit -- deploy --smoke "hello"\` during deploy or \`npm run agentkit -- deploy smoke --message "hello"\` afterward for an official hosted smoke check.
|
|
289
326
|
|
|
290
327
|
AgentKit owns hosted infrastructure and production secrets. Do not put production secret values in this capsule. Do not run operator/admin commands from a user capsule.
|
|
291
328
|
`,
|
|
@@ -302,6 +339,7 @@ Use AgentKit conventions when editing this project.
|
|
|
302
339
|
- Local runtime state lives in \`.agentkit/\` and should not be committed.
|
|
303
340
|
- The default provider is \`test/fake\`, which needs no secrets.
|
|
304
341
|
- Real providers run through AgentKit's internal Pi SDK backend.
|
|
342
|
+
- Ask the owner which real provider to use before switching from \`test/fake\`; do not choose OpenRouter, OpenAI, or Anthropic automatically.
|
|
305
343
|
- Production secrets must be managed secrets, not committed files.
|
|
306
344
|
- Keep required local secret names in \`.env.schema\` and values in ignored \`.env\`. AgentKit local commands load \`.env\` directly.
|
|
307
345
|
- Treat the owner's natural-language request as the brief and start implementing inside this capsule.
|
|
@@ -316,16 +354,21 @@ Generated by AgentKit as an Agent Capsule.
|
|
|
316
354
|
## Setup
|
|
317
355
|
|
|
318
356
|
\`\`\`sh
|
|
319
|
-
npm install
|
|
320
357
|
npm run chat -- --message "hello"
|
|
321
358
|
npm run dev
|
|
322
359
|
\`\`\`
|
|
323
360
|
|
|
361
|
+
\`agentkit new\` installs dependencies by default. Run \`npm install\` only if this capsule was created with \`--no-install\`, install failed, or \`node_modules\` was deleted.
|
|
362
|
+
|
|
324
363
|
\`agentkit.config.ts\` uses the built-in \`test/fake\` provider by default, so the first chat works without editing \`.env\`.
|
|
325
364
|
When a real provider or tool needs a local development secret, keep the required name in \`.env.schema\`, keep the value in ignored \`.env\`, and run AgentKit commands normally; the local runtime loads \`.env\` directly.
|
|
326
365
|
|
|
327
366
|
\`npm run dev\` runs the whole capsule locally. It should expose local chat, API, inspect, and storage endpoints.
|
|
328
367
|
|
|
368
|
+
For UI testing, run \`npm run dev\` and open the printed \`Chat:\` URL. After hosted deploy, run \`npm run agentkit -- chat-ui --deploy\` and open its printed \`Chat:\` URL.
|
|
369
|
+
|
|
370
|
+
\`test/fake\` does not validate real conversation quality. The owner must choose OpenRouter, OpenAI, Anthropic, or another supported provider before real model behavior is tested.
|
|
371
|
+
|
|
329
372
|
## Files
|
|
330
373
|
|
|
331
374
|
- \`agentkit.config.ts\`: agent contract.
|