@andreprado/agentkit 0.1.0-alpha.18 → 0.1.0-alpha.19
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 +3 -0
- package/docs/guides/add-channel.md +12 -6
- package/docs/guides/add-knowledge.md +10 -0
- package/docs/guides/add-managed-composio.md +4 -2
- package/docs/guides/channel-security.md +26 -2
- package/docs/guides/connect-discord.md +178 -0
- package/docs/guides/create-agent.md +13 -0
- package/docs/guides/debug-channel.md +8 -2
- package/docs/guides/improve-from-production.md +151 -0
- package/docs/guides/prepare-deploy.md +29 -8
- package/docs/guides/replay-production-traces.md +72 -0
- package/docs/guides/run-evals.md +18 -0
- package/docs/guides/security-rules.md +5 -5
- package/docs/guides/use-provider.md +11 -1
- package/docs/llms-full.txt +100 -11
- package/docs/llms.txt +17 -1
- package/package.json +1 -1
- package/src/cli/args.ts +23 -2
- package/src/cli/cloud-client.ts +63 -0
- package/src/cli/commands/channels.ts +139 -14
- package/src/cli/deploy-readiness.ts +5 -2
- package/src/cli/help.ts +26 -2
- package/src/cli/index.ts +382 -17
- package/src/create-project.ts +13 -2
- package/src/index.ts +42 -3
- package/src/providers/pi.ts +49 -15
- package/src/runtime/channel-test-harness.ts +4 -1
- package/src/runtime/channels/discord.ts +887 -0
- package/src/runtime/channels.ts +15 -0
- package/src/runtime/config.ts +35 -3
- package/src/runtime/dev-server.ts +149 -8
- package/src/runtime/evals.ts +27 -6
- package/src/runtime/improve.ts +868 -0
- package/src/runtime/knowledge/retrieve.ts +25 -5
- package/src/runtime/knowledge/schema.ts +45 -1
- package/src/runtime/runtime-contract.ts +54 -0
- package/src/runtime/targets/cloudflare/build.ts +248 -193
- package/src/runtime/targets/vps/deploy.ts +1 -1
- package/src/storage/sqlite.ts +7 -2
- package/src/templates/skills/agentkit-capsule/SKILL.md +8 -1
- package/src/templates/skills/agentkit-capsule/references/docs-router.md +1 -2
- package/src/templates/skills/agentkit-channels/SKILL.md +6 -1
- package/src/templates/skills/agentkit-channels/references/channel-debugging.md +2 -1
- package/src/templates/skills/agentkit-channels/references/discord.md +93 -0
- package/src/templates/skills/agentkit-deploy/SKILL.md +6 -0
- package/src/templates/skills/agentkit-evals/SKILL.md +12 -3
- package/src/templates/skills/agentkit-improve/SKILL.md +86 -0
- package/src/templates/skills/agentkit-improve/references/replay-side-effects.md +18 -0
- package/src/templates/skills/agentkit-improve/references/trace-packets.md +22 -0
- package/src/templates/skills/agentkit-improve/templates/regression.eval.md +18 -0
- package/src/templates/skills/agentkit-integrations/SKILL.md +1 -0
- package/src/templates/skills/agentkit-knowledge/SKILL.md +4 -1
- package/src/templates/skills/agentkit-provider/SKILL.md +4 -1
- package/src/templates/skills/agentkit-security/SKILL.md +3 -2
- package/src/templates/skills/agentkit-troubleshooting/SKILL.md +9 -0
- package/src/templates/support.ts +4 -2
|
@@ -108,7 +108,25 @@ async function searchLexical(db: DatabaseRunner, query: string, limit: number):
|
|
|
108
108
|
}
|
|
109
109
|
|
|
110
110
|
async function searchLexicalFallback(db: DatabaseRunner, query: string, limit: number): Promise<KnowledgeSearchResult[]> {
|
|
111
|
-
const
|
|
111
|
+
const tokens = queryTokens(query);
|
|
112
|
+
|
|
113
|
+
if (tokens.length === 0) {
|
|
114
|
+
return [];
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
const conditions = tokens
|
|
118
|
+
.map(
|
|
119
|
+
() => `(
|
|
120
|
+
lower(c.content) LIKE ? ESCAPE '\\'
|
|
121
|
+
OR lower(COALESCE(c.title, '')) LIKE ? ESCAPE '\\'
|
|
122
|
+
OR lower(COALESCE(c.section, '')) LIKE ? ESCAPE '\\'
|
|
123
|
+
)`,
|
|
124
|
+
)
|
|
125
|
+
.join(" AND ");
|
|
126
|
+
const args = tokens.flatMap((token) => {
|
|
127
|
+
const like = likePattern(token);
|
|
128
|
+
return [like, like, like];
|
|
129
|
+
});
|
|
112
130
|
const result = await db.query(
|
|
113
131
|
`
|
|
114
132
|
SELECT
|
|
@@ -121,13 +139,11 @@ async function searchLexicalFallback(db: DatabaseRunner, query: string, limit: n
|
|
|
121
139
|
s.source_key AS source_key
|
|
122
140
|
FROM agentkit_knowledge_chunks c
|
|
123
141
|
JOIN agentkit_knowledge_sources s ON s.id = c.source_id
|
|
124
|
-
WHERE
|
|
125
|
-
OR lower(COALESCE(c.title, '')) LIKE ?
|
|
126
|
-
OR lower(COALESCE(c.section, '')) LIKE ?
|
|
142
|
+
WHERE ${conditions}
|
|
127
143
|
ORDER BY c.created_at DESC, c.ordinal ASC
|
|
128
144
|
LIMIT ?
|
|
129
145
|
`,
|
|
130
|
-
[
|
|
146
|
+
[...args, limit],
|
|
131
147
|
);
|
|
132
148
|
|
|
133
149
|
return result.rows.map((row, index) => knowledgeSearchResultFromRow(row, lexicalScore(index), null));
|
|
@@ -269,6 +285,10 @@ function queryTokens(query: string): string[] {
|
|
|
269
285
|
return Array.from(new Set(query.toLowerCase().match(/[\p{L}\p{N}_-]+/gu) ?? [])).slice(0, 12);
|
|
270
286
|
}
|
|
271
287
|
|
|
288
|
+
function likePattern(token: string): string {
|
|
289
|
+
return `%${token.replace(/[\\%_]/g, (value) => `\\${value}`)}%`;
|
|
290
|
+
}
|
|
291
|
+
|
|
272
292
|
function parseEmbedding(value: unknown): number[] | null {
|
|
273
293
|
if (typeof value !== "string") {
|
|
274
294
|
return null;
|
|
@@ -1,6 +1,12 @@
|
|
|
1
1
|
export const KNOWLEDGE_MIGRATION_ID = "0006_create_knowledge_tables";
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
type KnowledgeSchemaDatabase = {
|
|
4
|
+
exec(sql: string): unknown;
|
|
5
|
+
};
|
|
6
|
+
|
|
7
|
+
export type KnowledgeLexicalIndexMode = "fts5" | "fallback";
|
|
8
|
+
|
|
9
|
+
export const KNOWLEDGE_BASE_SCHEMA_SQL = `
|
|
4
10
|
CREATE TABLE IF NOT EXISTS agentkit_knowledge_sources (
|
|
5
11
|
id TEXT PRIMARY KEY,
|
|
6
12
|
source_key TEXT NOT NULL UNIQUE,
|
|
@@ -43,7 +49,9 @@ export const KNOWLEDGE_SCHEMA_SQL = `
|
|
|
43
49
|
|
|
44
50
|
CREATE INDEX IF NOT EXISTS agentkit_knowledge_chunks_source_ordinal_idx
|
|
45
51
|
ON agentkit_knowledge_chunks(source_id, ordinal);
|
|
52
|
+
`;
|
|
46
53
|
|
|
54
|
+
export const KNOWLEDGE_FTS5_SCHEMA_SQL = `
|
|
47
55
|
CREATE VIRTUAL TABLE IF NOT EXISTS agentkit_knowledge_fts
|
|
48
56
|
USING fts5(
|
|
49
57
|
chunk_id UNINDEXED,
|
|
@@ -54,3 +62,39 @@ export const KNOWLEDGE_SCHEMA_SQL = `
|
|
|
54
62
|
tokenize='unicode61'
|
|
55
63
|
);
|
|
56
64
|
`;
|
|
65
|
+
|
|
66
|
+
export const KNOWLEDGE_FTS_FALLBACK_SCHEMA_SQL = `
|
|
67
|
+
CREATE TABLE IF NOT EXISTS agentkit_knowledge_fts (
|
|
68
|
+
chunk_id TEXT PRIMARY KEY,
|
|
69
|
+
source_id TEXT NOT NULL,
|
|
70
|
+
title TEXT,
|
|
71
|
+
section TEXT,
|
|
72
|
+
content TEXT NOT NULL
|
|
73
|
+
);
|
|
74
|
+
|
|
75
|
+
CREATE INDEX IF NOT EXISTS agentkit_knowledge_fts_source_idx
|
|
76
|
+
ON agentkit_knowledge_fts(source_id);
|
|
77
|
+
`;
|
|
78
|
+
|
|
79
|
+
export const KNOWLEDGE_SCHEMA_SQL = `${KNOWLEDGE_BASE_SCHEMA_SQL}\n${KNOWLEDGE_FTS5_SCHEMA_SQL}`;
|
|
80
|
+
|
|
81
|
+
export function applyKnowledgeSchema(db: KnowledgeSchemaDatabase): KnowledgeLexicalIndexMode {
|
|
82
|
+
db.exec(KNOWLEDGE_BASE_SCHEMA_SQL);
|
|
83
|
+
|
|
84
|
+
try {
|
|
85
|
+
db.exec(KNOWLEDGE_FTS5_SCHEMA_SQL);
|
|
86
|
+
return "fts5";
|
|
87
|
+
} catch (error) {
|
|
88
|
+
if (!isMissingFts5ModuleError(error)) {
|
|
89
|
+
throw error;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
db.exec(KNOWLEDGE_FTS_FALLBACK_SCHEMA_SQL);
|
|
94
|
+
return "fallback";
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
function isMissingFts5ModuleError(error: unknown): boolean {
|
|
98
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
99
|
+
return /no such module:\s*fts5/i.test(message) || /unknown module:\s*fts5/i.test(message);
|
|
100
|
+
}
|
|
@@ -35,6 +35,60 @@ export async function assertRuntimeContract(
|
|
|
35
35
|
expect(inspect.status).toBe(200);
|
|
36
36
|
expect(inspect.body).toMatchObject({ agent: options.expectedAgentName });
|
|
37
37
|
|
|
38
|
+
if (options.auth) {
|
|
39
|
+
const missingAdmin = await fetchJson(`${baseUrl}/_agentkit`);
|
|
40
|
+
expect(missingAdmin.status).toBe(401);
|
|
41
|
+
expect(missingAdmin.body.error.code).toBe("unauthorized");
|
|
42
|
+
|
|
43
|
+
const invalidAdmin = await fetchJson(`${baseUrl}/_agentkit`, {
|
|
44
|
+
headers: { Authorization: "Bearer invalid-admin-token" },
|
|
45
|
+
});
|
|
46
|
+
expect(invalidAdmin.status).toBe(401);
|
|
47
|
+
expect(invalidAdmin.body.error.code).toBe("unauthorized");
|
|
48
|
+
|
|
49
|
+
const missingChat = await fetchJson(`${baseUrl}/chat`, {
|
|
50
|
+
method: "POST",
|
|
51
|
+
headers: { "content-type": "application/json" },
|
|
52
|
+
body: JSON.stringify({ message: "hello" }),
|
|
53
|
+
});
|
|
54
|
+
expect(missingChat.status).toBe(401);
|
|
55
|
+
expect(missingChat.body.error.code).toBe("unauthorized");
|
|
56
|
+
|
|
57
|
+
const invalidChat = await fetchJson(`${baseUrl}/chat`, {
|
|
58
|
+
method: "POST",
|
|
59
|
+
headers: { "content-type": "application/json", Authorization: "Bearer invalid-chat-token" },
|
|
60
|
+
body: JSON.stringify({ message: "hello" }),
|
|
61
|
+
});
|
|
62
|
+
expect(invalidChat.status).toBe(401);
|
|
63
|
+
expect(invalidChat.body.error.code).toBe("unauthorized");
|
|
64
|
+
|
|
65
|
+
const missingTool = await fetchJson(`${baseUrl}/tools/${encodeURIComponent(options.tool.name)}`, {
|
|
66
|
+
method: "POST",
|
|
67
|
+
headers: { "content-type": "application/json" },
|
|
68
|
+
body: JSON.stringify({ input: options.tool.input }),
|
|
69
|
+
});
|
|
70
|
+
expect(missingTool.status).toBe(401);
|
|
71
|
+
expect(missingTool.body.error.code).toBe("unauthorized");
|
|
72
|
+
|
|
73
|
+
const invalidTool = await fetchJson(`${baseUrl}/tools/${encodeURIComponent(options.tool.name)}`, {
|
|
74
|
+
method: "POST",
|
|
75
|
+
headers: { "content-type": "application/json", Authorization: "Bearer invalid-admin-token" },
|
|
76
|
+
body: JSON.stringify({ input: options.tool.input }),
|
|
77
|
+
});
|
|
78
|
+
expect(invalidTool.status).toBe(401);
|
|
79
|
+
expect(invalidTool.body.error.code).toBe("unauthorized");
|
|
80
|
+
|
|
81
|
+
const missingConversations = await fetchJson(`${baseUrl}/v1/conversations`);
|
|
82
|
+
expect(missingConversations.status).toBe(401);
|
|
83
|
+
expect(missingConversations.body.error.code).toBe("unauthorized");
|
|
84
|
+
|
|
85
|
+
const invalidConversations = await fetchJson(`${baseUrl}/v1/conversations`, {
|
|
86
|
+
headers: { Authorization: "Bearer invalid-admin-token" },
|
|
87
|
+
});
|
|
88
|
+
expect(invalidConversations.status).toBe(401);
|
|
89
|
+
expect(invalidConversations.body.error.code).toBe("unauthorized");
|
|
90
|
+
}
|
|
91
|
+
|
|
38
92
|
const unauthorized = await fetchJson(`${baseUrl}/chat`, {
|
|
39
93
|
method: "POST",
|
|
40
94
|
headers: withHeaders({ "content-type": "application/json" }, options.auth?.chat),
|