@andreprado/agentkit 0.1.0-alpha.6 → 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 +4 -0
- package/docs/guides/connect-telegram.md +2 -0
- package/docs/guides/create-agent.md +9 -0
- package/docs/guides/run-evals.md +36 -1
- package/package.json +1 -1
- package/src/cli/cloud-client.ts +10 -2
- package/src/cli/commands/channels.ts +28 -2
- package/src/cli/deploy-chat-ui.ts +7 -0
- package/src/cli/help.ts +18 -2
- package/src/cli/index.ts +124 -4
- package/src/index.ts +44 -1
- package/src/providers/pi.ts +1 -1
- package/src/providers/test.ts +1 -1
- package/src/runtime/config.ts +8 -0
- package/src/runtime/database.ts +93 -2
- package/src/runtime/db-commands.ts +9 -0
- package/src/runtime/dev-server.ts +43 -2
- package/src/runtime/evals.ts +210 -20
- package/src/runtime/inspect.ts +5 -0
- package/src/runtime/spec.ts +152 -0
- package/src/runtime/sync.ts +144 -0
- package/src/runtime/targets/cloudflare/build.ts +45 -0
- package/src/runtime/tools.ts +121 -1
- package/src/runtime/traces.ts +41 -0
- package/src/storage/sqlite.ts +136 -0
- package/src/templates/blank.ts +8 -1
- package/src/templates/dentista.ts +14 -1
- package/src/templates/skills/agentkit-build-agent/SKILL.md +9 -7
- package/src/templates/skills/agentkit-database/SKILL.md +5 -2
- package/src/templates/skills/agentkit-evals/SKILL.md +32 -3
- package/src/templates/skills/agentkit-evals/templates/multi-turn.eval.md +22 -0
- package/src/templates/support.ts +7 -0
package/README.md
CHANGED
|
@@ -37,9 +37,13 @@ agentkit tool <name> [--input <path-or-json>]
|
|
|
37
37
|
agentkit knowledge add <path-or-url>
|
|
38
38
|
agentkit knowledge sync
|
|
39
39
|
agentkit knowledge search <query> [--top-k <number>]
|
|
40
|
+
agentkit spec init --brief <text>
|
|
40
41
|
agentkit db migrate
|
|
42
|
+
agentkit sync run
|
|
41
43
|
agentkit eval run
|
|
44
|
+
agentkit eval from-conversation <conversation-id>
|
|
42
45
|
agentkit conversations list
|
|
46
|
+
agentkit conversations trace <conversation-id>
|
|
43
47
|
```
|
|
44
48
|
|
|
45
49
|
Knowledge indexes local `.md`, `.txt`, and `.csv` sources into the capsule database and registers the internal `agentkit_search_knowledge` chat tool when `knowledge` is configured in `agentkit.config.ts`. `agentkit dev` and `agentkit chat` sync configured sources automatically; when embeddings are configured, local semantic search uses a libSQL vector sidecar. Hosted Cloudflare deploys package configured local Knowledge sources and sync them into the project Turso database automatically during `agentkit deploy`; when embeddings are configured, the deploy also creates and populates the hosted Turso vector index.
|
|
@@ -76,6 +76,8 @@ telegramChannel({
|
|
|
76
76
|
- `secret_token`: `TELEGRAM_WEBHOOK_SECRET`;
|
|
77
77
|
- `allowed_updates`: `["message"]`.
|
|
78
78
|
|
|
79
|
+
Against AgentKit Cloud, `--apply` runs through the Cloud API and uses managed hosted secrets. The legacy local fallback only uses `TELEGRAM_BOT_TOKEN` and `TELEGRAM_WEBHOOK_SECRET` from the shell when the Cloud API does not expose channel setup.
|
|
80
|
+
|
|
79
81
|
## Safety Rules
|
|
80
82
|
|
|
81
83
|
- Use `--apply` only when real Telegram secrets are present.
|
|
@@ -86,6 +86,15 @@ Develop an appointment and intake agent for an ophthalmology office.
|
|
|
86
86
|
|
|
87
87
|
The generated `AGENTS.md`, `AGENTKIT.md`, `CLAUDE.md`, and `skills/` pack tell the coding agent which files to edit, which task skill to load, and which verification commands to run. There is no wizard or recipe layer: the coding agent edits the capsule directly from the scaffold, contract, and owner request. The default router is `skills/agentkit-capsule/SKILL.md`; `llms-full.txt` is reserved for complete-contract checks.
|
|
88
88
|
|
|
89
|
+
After the owner gives the general idea, the coding agent should create or update the implementation contract itself:
|
|
90
|
+
|
|
91
|
+
```sh
|
|
92
|
+
npm run agentkit -- spec init --brief "Develop an appointment and intake agent for an ophthalmology office."
|
|
93
|
+
npm run agentkit -- spec check
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
`AGENT_SPEC.md` is an internal working contract for the coding agent. It is not a form the owner must fill before work starts.
|
|
97
|
+
|
|
89
98
|
Optional shortcut when copying a prompt into another coding agent:
|
|
90
99
|
|
|
91
100
|
```sh
|
package/docs/guides/run-evals.md
CHANGED
|
@@ -22,6 +22,15 @@ Run evals:
|
|
|
22
22
|
agentkit eval run
|
|
23
23
|
```
|
|
24
24
|
|
|
25
|
+
Create an eval from a stored conversation:
|
|
26
|
+
|
|
27
|
+
```sh
|
|
28
|
+
agentkit conversations list
|
|
29
|
+
agentkit conversations trace <conversation-id>
|
|
30
|
+
agentkit eval from-conversation <conversation-id>
|
|
31
|
+
agentkit eval run
|
|
32
|
+
```
|
|
33
|
+
|
|
25
34
|
## Files Created Or Edited
|
|
26
35
|
|
|
27
36
|
Create or edit:
|
|
@@ -62,7 +71,33 @@ matches_regex
|
|
|
62
71
|
persisted_tool_call
|
|
63
72
|
```
|
|
64
73
|
|
|
65
|
-
|
|
74
|
+
Multi-turn conversation evals use `turns`:
|
|
75
|
+
|
|
76
|
+
```ts
|
|
77
|
+
export default {
|
|
78
|
+
name: "buyer under budget",
|
|
79
|
+
turns: [
|
|
80
|
+
{
|
|
81
|
+
input: "I want a house up to 600k near Pinheiros.",
|
|
82
|
+
expect: {
|
|
83
|
+
persisted_tool_call: {
|
|
84
|
+
name: "buscar_imoveis",
|
|
85
|
+
status: "completed",
|
|
86
|
+
input: { maxPrice: 600000 },
|
|
87
|
+
},
|
|
88
|
+
},
|
|
89
|
+
},
|
|
90
|
+
{
|
|
91
|
+
input: "Show me the best two.",
|
|
92
|
+
expect: {
|
|
93
|
+
contains: ["Pinheiros", "R$"],
|
|
94
|
+
},
|
|
95
|
+
},
|
|
96
|
+
],
|
|
97
|
+
};
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
`persisted_tool_call` validates the tool call saved in local SQLite `tool_calls`, not a provider-specific raw response shape. It can be a tool name string or an object with `name`, `input`, `output`, `rendered`, `status`, and/or `visibility`.
|
|
66
101
|
|
|
67
102
|
Use response assertions and persisted tool assertions together when internal operational output must not leak:
|
|
68
103
|
|
package/package.json
CHANGED
package/src/cli/cloud-client.ts
CHANGED
|
@@ -153,9 +153,13 @@ export async function cloudPost<T>(apiUrl: string, path: string, body: unknown):
|
|
|
153
153
|
return payload as T;
|
|
154
154
|
}
|
|
155
155
|
|
|
156
|
-
export function cloudFetch(apiUrl: string, path: string, init: RequestInit = {}): Promise<Response> {
|
|
156
|
+
export async function cloudFetch(apiUrl: string, path: string, init: RequestInit = {}): Promise<Response> {
|
|
157
157
|
const headers = new Headers(init.headers);
|
|
158
|
-
const
|
|
158
|
+
const auth = await readCloudAuth();
|
|
159
|
+
const apiToken =
|
|
160
|
+
auth?.source === "file" && !cloudAuthMatchesApiUrl(auth, apiUrl)
|
|
161
|
+
? undefined
|
|
162
|
+
: auth?.token;
|
|
159
163
|
|
|
160
164
|
if (apiToken && !headers.has("Authorization")) {
|
|
161
165
|
headers.set("Authorization", `Bearer ${apiToken}`);
|
|
@@ -167,6 +171,10 @@ export function cloudFetch(apiUrl: string, path: string, init: RequestInit = {})
|
|
|
167
171
|
});
|
|
168
172
|
}
|
|
169
173
|
|
|
174
|
+
function cloudAuthMatchesApiUrl(auth: CloudAuthConfig, apiUrl: string): boolean {
|
|
175
|
+
return parseCloudApiUrl(auth.apiUrl) === parseCloudApiUrl(apiUrl);
|
|
176
|
+
}
|
|
177
|
+
|
|
170
178
|
export async function cloudApiRequest(apiUrl: string, path: string, init: RequestInit): Promise<unknown> {
|
|
171
179
|
const auth = await readCloudAuth();
|
|
172
180
|
const headers = new Headers(init.headers);
|
|
@@ -99,7 +99,7 @@ export async function handleChannelsCommand(args: ParsedArgs): Promise<void> {
|
|
|
99
99
|
printChannelStatus(channel);
|
|
100
100
|
if (channel.type === "telegram") {
|
|
101
101
|
if (args.flags.apply) {
|
|
102
|
-
await applyTelegramWebhook(channel);
|
|
102
|
+
await applyTelegramWebhook(channel, args.flags.api);
|
|
103
103
|
console.log("Telegram webhook updated.");
|
|
104
104
|
} else {
|
|
105
105
|
console.log(`Setup: call Telegram setWebhook with ${channel.webhook_url}`);
|
|
@@ -201,7 +201,23 @@ export async function handleChannelsCommand(args: ParsedArgs): Promise<void> {
|
|
|
201
201
|
);
|
|
202
202
|
}
|
|
203
203
|
|
|
204
|
-
async function applyTelegramWebhook(
|
|
204
|
+
async function applyTelegramWebhook(
|
|
205
|
+
channel: CloudChannel,
|
|
206
|
+
apiFlag: string | boolean | undefined,
|
|
207
|
+
): Promise<void> {
|
|
208
|
+
try {
|
|
209
|
+
await cloudPost(
|
|
210
|
+
parseCloudApiUrl(apiFlag),
|
|
211
|
+
`/v1/channels/${encodeURIComponent(channel.id)}/setup`,
|
|
212
|
+
{},
|
|
213
|
+
);
|
|
214
|
+
return;
|
|
215
|
+
} catch (error) {
|
|
216
|
+
if (!shouldFallbackToLocalTelegramSetup(error)) {
|
|
217
|
+
throw error;
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
|
|
205
221
|
const botToken = process.env.TELEGRAM_BOT_TOKEN;
|
|
206
222
|
const secretToken = process.env.TELEGRAM_WEBHOOK_SECRET;
|
|
207
223
|
|
|
@@ -232,6 +248,16 @@ async function applyTelegramWebhook(channel: CloudChannel): Promise<void> {
|
|
|
232
248
|
}
|
|
233
249
|
}
|
|
234
250
|
|
|
251
|
+
function shouldFallbackToLocalTelegramSetup(error: unknown): boolean {
|
|
252
|
+
if (!(error instanceof Error)) {
|
|
253
|
+
return false;
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
return /Unknown AgentKit Cloud route|does not support channel delivery records yet|does not support channel resources yet/.test(
|
|
257
|
+
error.message,
|
|
258
|
+
);
|
|
259
|
+
}
|
|
260
|
+
|
|
235
261
|
function isTelegramOk(payload: unknown): payload is { ok: true } {
|
|
236
262
|
return Boolean(payload && typeof payload === "object" && "ok" in payload && payload.ok === true);
|
|
237
263
|
}
|
|
@@ -335,6 +335,13 @@ function renderDeployChatUi(input: { deployUrl: string }): string {
|
|
|
335
335
|
messages.scrollTop = messages.scrollHeight;
|
|
336
336
|
}
|
|
337
337
|
|
|
338
|
+
textarea.addEventListener("keydown", (event) => {
|
|
339
|
+
if (event.key !== "Enter" || event.shiftKey || event.isComposing) return;
|
|
340
|
+
event.preventDefault();
|
|
341
|
+
if (send.disabled) return;
|
|
342
|
+
form.requestSubmit();
|
|
343
|
+
});
|
|
344
|
+
|
|
338
345
|
form.addEventListener("submit", async (event) => {
|
|
339
346
|
event.preventDefault();
|
|
340
347
|
const message = textarea.value.trim();
|
package/src/cli/help.ts
CHANGED
|
@@ -23,9 +23,12 @@ Start:
|
|
|
23
23
|
Build:
|
|
24
24
|
agentkit knowledge add <path>
|
|
25
25
|
agentkit knowledge search <query>
|
|
26
|
+
agentkit spec init --brief <text>
|
|
27
|
+
agentkit sync run
|
|
26
28
|
agentkit tool <name> [--input <path-or-json>]
|
|
27
29
|
agentkit db migrate
|
|
28
30
|
agentkit eval run
|
|
31
|
+
agentkit eval from-conversation <id>
|
|
29
32
|
agentkit conversations list
|
|
30
33
|
|
|
31
34
|
Deploy:
|
|
@@ -59,13 +62,19 @@ Usage:
|
|
|
59
62
|
agentkit knowledge sync
|
|
60
63
|
agentkit knowledge inspect
|
|
61
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>]
|
|
62
69
|
agentkit db migrate
|
|
63
70
|
agentkit db reset --yes
|
|
64
71
|
agentkit db shell
|
|
65
72
|
agentkit db seed [--file <path>]
|
|
66
73
|
agentkit eval run
|
|
74
|
+
agentkit eval from-conversation <conversation-id> [--out <path>] [--force]
|
|
67
75
|
agentkit conversations list
|
|
68
76
|
agentkit conversations show <conversation-id>
|
|
77
|
+
agentkit conversations trace <conversation-id>
|
|
69
78
|
agentkit channels list
|
|
70
79
|
agentkit channels add <website|telegram|whatsapp> <name> [--provider zapster|meta] [--api <url>]
|
|
71
80
|
agentkit channels setup <name> [--apply] [--api <url>]
|
|
@@ -113,9 +122,11 @@ Commands:
|
|
|
113
122
|
chat Send one message to the local Agent Capsule
|
|
114
123
|
tool Run one registered tool directly
|
|
115
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
|
|
116
127
|
db Manage the local SQLite database
|
|
117
|
-
eval Run local eval files
|
|
118
|
-
conversations List and
|
|
128
|
+
eval Run local eval files or create one from a conversation
|
|
129
|
+
conversations List, inspect, and trace stored local conversations
|
|
119
130
|
channels Manage hosted channel resources
|
|
120
131
|
inspect Print machine-readable Agent Capsule state
|
|
121
132
|
build Build a hosted deploy artifact
|
|
@@ -150,6 +161,11 @@ export function renderCommandHelp(command: string): string {
|
|
|
150
161
|
chat: 'agentkit chat --message "hello" [--conversation-id <id>]',
|
|
151
162
|
tool: "agentkit tool <name> [--input <path-or-json>]",
|
|
152
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>",
|
|
153
169
|
deploy:
|
|
154
170
|
'agentkit deploy [--smoke "hello"] | agentkit deploy smoke [--message "hello"] | agentkit deploy doctor | status | pause | resume',
|
|
155
171
|
secret:
|
package/src/cli/index.ts
CHANGED
|
@@ -9,6 +9,7 @@ import { findAgentCapsuleRoot, loadAgentCapsule } from "../runtime/config";
|
|
|
9
9
|
import { readLocalDeployStateIfExists, type LocalDeployState } from "../runtime/core/deploy-state";
|
|
10
10
|
import { resolveBuildTarget, resolveDeployTarget } from "../runtime/core/targets";
|
|
11
11
|
import { getConversationFromCwd, listConversationsFromCwd } from "../runtime/conversations";
|
|
12
|
+
import { getConversationTraceFromCwd } from "../runtime/traces";
|
|
12
13
|
import { runAgentMessageFromCwd } from "../runtime/chat";
|
|
13
14
|
import { deployBuildToAgentKitCloud, writeLocalDeployState } from "../runtime/deploy";
|
|
14
15
|
import {
|
|
@@ -17,9 +18,11 @@ import {
|
|
|
17
18
|
resetLocalDatabase,
|
|
18
19
|
seedLocalDatabase,
|
|
19
20
|
} from "../runtime/db-commands";
|
|
20
|
-
import { runEvalsFromCwd } from "../runtime/evals";
|
|
21
|
+
import { runEvalsFromCwd, writeEvalFromConversation } from "../runtime/evals";
|
|
21
22
|
import { findAgentKitDocs } from "../runtime/docs";
|
|
22
23
|
import { listCapsuleEnv, setCapsuleEnv, unsetCapsuleEnv } from "../runtime/env";
|
|
24
|
+
import { checkAgentSpec, initializeAgentSpec } from "../runtime/spec";
|
|
25
|
+
import { initializeSyncScaffold, runCapsuleSync } from "../runtime/sync";
|
|
23
26
|
import { runToolFromCwd } from "../runtime/tool-runner";
|
|
24
27
|
import { startAgentDevServer } from "../runtime/dev-server";
|
|
25
28
|
import { inspectAgentCapsule } from "../runtime/inspect";
|
|
@@ -147,6 +150,7 @@ async function main() {
|
|
|
147
150
|
console.log(`API: ${devServer.urls.api}`);
|
|
148
151
|
console.log(`Inspect: ${devServer.urls.inspect}`);
|
|
149
152
|
console.log(`Storage: ${devServer.storage ?? "managed"}`);
|
|
153
|
+
console.log("Reload: prompts/config reload per request; restart after changing tool modules or dependencies");
|
|
150
154
|
await waitForShutdown(devServer.stop);
|
|
151
155
|
return;
|
|
152
156
|
}
|
|
@@ -224,6 +228,8 @@ async function main() {
|
|
|
224
228
|
const result = await migrateLocalDatabase(process.cwd());
|
|
225
229
|
console.log("Local database migrated");
|
|
226
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"}`);
|
|
227
233
|
console.log(`Schema: ${result.schemaPath ?? "none"}`);
|
|
228
234
|
return;
|
|
229
235
|
}
|
|
@@ -237,6 +243,8 @@ async function main() {
|
|
|
237
243
|
console.log("Local database reset");
|
|
238
244
|
console.log(`Deleted: ${result.resetPath}`);
|
|
239
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"}`);
|
|
240
248
|
console.log(`Schema: ${result.schemaPath ?? "none"}`);
|
|
241
249
|
return;
|
|
242
250
|
}
|
|
@@ -259,6 +267,8 @@ async function main() {
|
|
|
259
267
|
const result = await seedLocalDatabase(process.cwd(), seedFile);
|
|
260
268
|
console.log("Local database seeded");
|
|
261
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"}`);
|
|
262
272
|
console.log(`Schema: ${result.schemaPath ?? "none"}`);
|
|
263
273
|
console.log(`Seed: ${result.seedPath}`);
|
|
264
274
|
return;
|
|
@@ -268,10 +278,39 @@ async function main() {
|
|
|
268
278
|
}
|
|
269
279
|
|
|
270
280
|
if (args.command === "eval") {
|
|
271
|
-
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
|
+
}
|
|
272
311
|
|
|
273
312
|
if (subcommand !== "run") {
|
|
274
|
-
throw new Error("Usage: agentkit eval run");
|
|
313
|
+
throw new Error("Usage: agentkit eval run | agentkit eval from-conversation <conversation-id> [--out <path>] [--force]");
|
|
275
314
|
}
|
|
276
315
|
|
|
277
316
|
const summary = await runEvalsFromCwd(process.cwd());
|
|
@@ -340,7 +379,17 @@ async function main() {
|
|
|
340
379
|
return;
|
|
341
380
|
}
|
|
342
381
|
|
|
343
|
-
|
|
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>");
|
|
344
393
|
}
|
|
345
394
|
|
|
346
395
|
if (args.command === "knowledge") {
|
|
@@ -348,6 +397,77 @@ async function main() {
|
|
|
348
397
|
return;
|
|
349
398
|
}
|
|
350
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>]');
|
|
469
|
+
}
|
|
470
|
+
|
|
351
471
|
if (args.command === "inspect") {
|
|
352
472
|
const state = await inspectAgentCapsule(process.cwd());
|
|
353
473
|
console.log(JSON.stringify(state, null, 2));
|
package/src/index.ts
CHANGED
|
@@ -105,6 +105,7 @@ export type AgentDatabaseConfig =
|
|
|
105
105
|
| {
|
|
106
106
|
driver: "turso";
|
|
107
107
|
schema?: string;
|
|
108
|
+
migrations?: string;
|
|
108
109
|
};
|
|
109
110
|
|
|
110
111
|
export type AgentFilesConfig =
|
|
@@ -178,9 +179,42 @@ export type DatabaseRunner = {
|
|
|
178
179
|
batch(statements: DatabaseStatement[]): Promise<DatabaseResult[]>;
|
|
179
180
|
};
|
|
180
181
|
|
|
182
|
+
export type ToolRenderField = {
|
|
183
|
+
label: string;
|
|
184
|
+
value: string;
|
|
185
|
+
};
|
|
186
|
+
|
|
187
|
+
export type ToolRenderAction = {
|
|
188
|
+
label: string;
|
|
189
|
+
href?: string;
|
|
190
|
+
};
|
|
191
|
+
|
|
192
|
+
export type ToolRenderBlock =
|
|
193
|
+
| {
|
|
194
|
+
type: "text";
|
|
195
|
+
text: string;
|
|
196
|
+
}
|
|
197
|
+
| {
|
|
198
|
+
type: "card";
|
|
199
|
+
title: string;
|
|
200
|
+
subtitle?: string;
|
|
201
|
+
fields?: ToolRenderField[];
|
|
202
|
+
actions?: ToolRenderAction[];
|
|
203
|
+
};
|
|
204
|
+
|
|
205
|
+
export type ToolRenderResult = {
|
|
206
|
+
text: string;
|
|
207
|
+
blocks?: ToolRenderBlock[];
|
|
208
|
+
};
|
|
209
|
+
|
|
210
|
+
export type ToolRenderContext<Input = unknown> = {
|
|
211
|
+
input: Input;
|
|
212
|
+
runtime: ToolRuntimeContext;
|
|
213
|
+
};
|
|
214
|
+
|
|
181
215
|
export type ToolRuntimeContext = {
|
|
182
216
|
environment: "local" | "hosted" | "eval" | "test";
|
|
183
|
-
invocation: "chat" | "tool" | "dev" | "channel" | "eval";
|
|
217
|
+
invocation: "chat" | "tool" | "dev" | "channel" | "eval" | "sync";
|
|
184
218
|
target: "bun" | "cloudflare";
|
|
185
219
|
database: "sqlite" | "turso" | "none";
|
|
186
220
|
};
|
|
@@ -196,6 +230,13 @@ export type ToolContext = {
|
|
|
196
230
|
};
|
|
197
231
|
};
|
|
198
232
|
|
|
233
|
+
export type SyncContext = {
|
|
234
|
+
env: Record<string, string | undefined>;
|
|
235
|
+
database: DatabaseRunner;
|
|
236
|
+
db: DatabaseRunner;
|
|
237
|
+
runtime: ToolRuntimeContext;
|
|
238
|
+
};
|
|
239
|
+
|
|
199
240
|
export type AgentTool<Input = unknown, Output = unknown> = {
|
|
200
241
|
name: string;
|
|
201
242
|
description: string;
|
|
@@ -206,6 +247,7 @@ export type AgentTool<Input = unknown, Output = unknown> = {
|
|
|
206
247
|
permissions?: string[];
|
|
207
248
|
timeoutMs?: number;
|
|
208
249
|
execute(input: Input, ctx: ToolContext): Promise<Output> | Output;
|
|
250
|
+
render?(output: Output, ctx: ToolRenderContext<Input>): string | ToolRenderResult;
|
|
209
251
|
};
|
|
210
252
|
|
|
211
253
|
export type AgentConfig = {
|
|
@@ -338,6 +380,7 @@ export { loadAgentCapsule, findAgentCapsuleRoot } from "./runtime/config";
|
|
|
338
380
|
export { runAgentMessage, runAgentMessageFromCwd } from "./runtime/chat";
|
|
339
381
|
export { listConversationsFromCwd, getConversationFromCwd } from "./runtime/conversations";
|
|
340
382
|
export { runEvalsFromCwd } from "./runtime/evals";
|
|
383
|
+
export { getConversationTraceFromCwd } from "./runtime/traces";
|
|
341
384
|
export { runToolFromCwd } from "./runtime/tool-runner";
|
|
342
385
|
export { startAgentDevServer } from "./runtime/dev-server";
|
|
343
386
|
export { inspectAgentCapsule } from "./runtime/inspect";
|
package/src/providers/pi.ts
CHANGED
|
@@ -97,7 +97,7 @@ async function runPiProvider(input: ProviderRunInput): Promise<ProviderRunResult
|
|
|
97
97
|
content: [
|
|
98
98
|
{
|
|
99
99
|
type: "text",
|
|
100
|
-
text: JSON.stringify(result.output),
|
|
100
|
+
text: result.rendered?.text ?? JSON.stringify(result.output),
|
|
101
101
|
},
|
|
102
102
|
],
|
|
103
103
|
isError: false,
|
package/src/providers/test.ts
CHANGED
|
@@ -29,7 +29,7 @@ export const testProviderAdapter: ProviderAdapter = {
|
|
|
29
29
|
content:
|
|
30
30
|
toolResult.visibility === "internal"
|
|
31
31
|
? `Tool ${toolResult.name}: completed`
|
|
32
|
-
: `Tool ${toolResult.name}: ${JSON.stringify(toolResult.output)}`,
|
|
32
|
+
: toolResult.rendered?.text ?? `Tool ${toolResult.name}: ${JSON.stringify(toolResult.output)}`,
|
|
33
33
|
},
|
|
34
34
|
raw: {
|
|
35
35
|
toolCalls: [toolResult],
|
package/src/runtime/config.ts
CHANGED
|
@@ -561,6 +561,10 @@ function validateDatabaseConfig(value: unknown): void {
|
|
|
561
561
|
if (value.schema !== undefined && typeof value.schema !== "string") {
|
|
562
562
|
throw invalidConfig("storage.database.schema must be a string when provided.");
|
|
563
563
|
}
|
|
564
|
+
|
|
565
|
+
if (value.migrations !== undefined && typeof value.migrations !== "string") {
|
|
566
|
+
throw invalidConfig("storage.database.migrations must be a string when provided.");
|
|
567
|
+
}
|
|
564
568
|
}
|
|
565
569
|
|
|
566
570
|
function validateFilesConfig(value: unknown): void {
|
|
@@ -631,6 +635,10 @@ function validateTool(value: unknown, index: number): asserts value is AgentTool
|
|
|
631
635
|
if (typeof value.execute !== "function") {
|
|
632
636
|
throw invalidConfig(`tools[${index}].execute must be a function.`);
|
|
633
637
|
}
|
|
638
|
+
|
|
639
|
+
if (value.render !== undefined && typeof value.render !== "function") {
|
|
640
|
+
throw invalidConfig(`tools[${index}].render must be a function when provided.`);
|
|
641
|
+
}
|
|
634
642
|
}
|
|
635
643
|
|
|
636
644
|
function resolvePath(root: string, path: string): string {
|