@johpaz/hive-sdk 0.0.18 → 0.1.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/bun.lock +291 -1
- package/docs/HIVE-HARNESS.md +113 -0
- package/package.json +36 -2
- package/packages/cli/package.json +1 -1
- package/packages/core/package.json +13 -2
- package/packages/core/src/ace/Tracer.ts +1 -1
- package/packages/core/src/agent/AgentRunner.ts +12 -0
- package/packages/core/src/agent/ContextCompiler.ts +4 -4
- package/packages/core/src/agent/ConversationStore.ts +30 -20
- package/packages/core/src/agent/selectors/PlaybookSelector.ts +50 -76
- package/packages/core/src/agent/selectors/SkillSelector.ts +106 -262
- package/packages/core/src/agent/selectors/ToolSelector.ts +53 -89
- package/packages/core/src/auth/auth.ts +36 -23
- package/packages/core/src/harness/boot-id.ts +20 -0
- package/packages/core/src/harness/collections.ts +98 -0
- package/packages/core/src/harness/db-helpers.ts +87 -0
- package/packages/core/src/harness/durable-queue.ts +337 -0
- package/packages/core/src/harness/goal-verifier.ts +141 -0
- package/packages/core/src/harness/harness.test.ts +236 -0
- package/packages/core/src/harness/index.ts +34 -0
- package/packages/core/src/harness/job-store.ts +399 -0
- package/packages/core/src/harness/proof-packet.ts +69 -0
- package/packages/core/src/harness/reconcile.ts +149 -0
- package/packages/core/src/harness/run-epoch.ts +32 -0
- package/packages/core/src/harness/run-store.ts +334 -0
- package/packages/core/src/index.ts +13 -0
- package/packages/core/src/memory/Scratchpad.test.ts +23 -21
- package/packages/core/src/memory/Scratchpad.ts +41 -24
- package/packages/core/src/storage/HiveDBStorage.ts +64 -0
- package/packages/core/src/storage/SQLiteStorage.ts +7 -0
- package/packages/core/src/storage/hiveSeed.ts +308 -0
- package/packages/core/src/storage/hiveStorage.test.ts +38 -0
- package/packages/core/src/storage/index.ts +11 -0
- package/packages/core/src/storage/seed.ts +5 -1
- package/packages/core/src/storage/usage.ts +106 -167
- package/packages/core/src/tool-runtime/tool-runtime.test.ts +11 -3
- package/packages/core/src/tools/agents/get-available-models.ts +52 -56
- package/packages/core/src/tools/agents/index.ts +77 -60
- package/packages/core/src/tools/core/index.ts +106 -291
- package/packages/core/src/tools/meeting/index.ts +83 -93
- package/packages/core/src/utils/toon.ts +4 -4
|
@@ -1,37 +1,54 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { getHiveDB } from "../storage/HiveDBStorage.ts";
|
|
2
|
+
|
|
3
|
+
interface ScratchpadDoc {
|
|
4
|
+
threadId: string;
|
|
5
|
+
key: string;
|
|
6
|
+
value: string;
|
|
7
|
+
updatedAt: number;
|
|
8
|
+
}
|
|
2
9
|
|
|
3
10
|
export class Scratchpad {
|
|
4
|
-
|
|
11
|
+
async write(threadId: string, key: string, value: string): Promise<void> {
|
|
12
|
+
const db = await getHiveDB();
|
|
13
|
+
const col = db.collection<ScratchpadDoc>("scratchpad");
|
|
14
|
+
await col.put(this.docId(threadId, key), { threadId, key, value, updatedAt: Date.now() });
|
|
15
|
+
}
|
|
5
16
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
17
|
+
async read(threadId: string, key: string): Promise<string | undefined> {
|
|
18
|
+
const db = await getHiveDB();
|
|
19
|
+
const col = db.collection<ScratchpadDoc>("scratchpad");
|
|
20
|
+
const entry = await col.get(this.docId(threadId, key));
|
|
21
|
+
return entry?.doc.value;
|
|
11
22
|
}
|
|
12
23
|
|
|
13
|
-
|
|
14
|
-
const
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
24
|
+
async list(threadId: string): Promise<Record<string, string>> {
|
|
25
|
+
const db = await getHiveDB();
|
|
26
|
+
const col = db.collection<ScratchpadDoc>("scratchpad");
|
|
27
|
+
const entries = await col.scan();
|
|
28
|
+
const result: Record<string, string> = {};
|
|
29
|
+
for (const e of entries) {
|
|
30
|
+
if (e.doc.threadId === threadId) {
|
|
31
|
+
result[e.doc.key] = e.doc.value;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
return result;
|
|
18
35
|
}
|
|
19
36
|
|
|
20
|
-
|
|
21
|
-
const
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
return Object.fromEntries(rows.map(r => [r.key, r.value]));
|
|
37
|
+
async delete(threadId: string, key: string): Promise<void> {
|
|
38
|
+
const db = await getHiveDB();
|
|
39
|
+
const col = db.collection<ScratchpadDoc>("scratchpad");
|
|
40
|
+
await col.delete(this.docId(threadId, key));
|
|
25
41
|
}
|
|
26
42
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
);
|
|
43
|
+
async clear(threadId: string): Promise<void> {
|
|
44
|
+
const db = await getHiveDB();
|
|
45
|
+
const col = db.collection<ScratchpadDoc>("scratchpad");
|
|
46
|
+
const entries = await col.scan();
|
|
47
|
+
const ids = entries.filter(e => e.doc.threadId === threadId).map(e => e.id);
|
|
48
|
+
await db.batch(ids.map(id => ({ op: "delete" as const, collection: "scratchpad", id })));
|
|
32
49
|
}
|
|
33
50
|
|
|
34
|
-
|
|
35
|
-
|
|
51
|
+
private docId(threadId: string, key: string): string {
|
|
52
|
+
return `${threadId}:${key}`;
|
|
36
53
|
}
|
|
37
54
|
}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { HiveDB, type Collection, type EventInput, type Event } from "@johpaz/hive-db";
|
|
2
|
+
import * as path from "node:path";
|
|
3
|
+
import { existsSync, mkdirSync } from "node:fs";
|
|
4
|
+
import { getHiveDir } from "../config/loader.ts";
|
|
5
|
+
import { logger } from "../utils/logger.ts";
|
|
6
|
+
|
|
7
|
+
const log = logger.child("hivedb-storage");
|
|
8
|
+
|
|
9
|
+
let _db: HiveDB | null = null;
|
|
10
|
+
let _opening: Promise<HiveDB> | null = null;
|
|
11
|
+
|
|
12
|
+
export function getHiveDbPath(): string {
|
|
13
|
+
return path.join(getHiveDir(), "data", "hive");
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export function openHiveDB(): Promise<HiveDB> {
|
|
17
|
+
if (_db) return Promise.resolve(_db);
|
|
18
|
+
if (_opening) return _opening;
|
|
19
|
+
|
|
20
|
+
const hiveDir = getHiveDir();
|
|
21
|
+
const dir = path.join(hiveDir, "data");
|
|
22
|
+
if (!existsSync(dir)) {
|
|
23
|
+
mkdirSync(dir, { recursive: true });
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
const dbPath = getHiveDbPath();
|
|
27
|
+
log.info(`[hivedb] Opening HiveDB at ${dbPath}`);
|
|
28
|
+
_opening = HiveDB.open(dbPath, { vector: { dimension: 384, spaceId: "hive-sdk-v1" } }).then((db) => {
|
|
29
|
+
_db = db;
|
|
30
|
+
_opening = null;
|
|
31
|
+
return db;
|
|
32
|
+
});
|
|
33
|
+
return _opening;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export async function getHiveDB(): Promise<HiveDB> {
|
|
37
|
+
if (_db) return _db;
|
|
38
|
+
if (_opening) return _opening;
|
|
39
|
+
return openHiveDB();
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export async function closeHiveDB(): Promise<void> {
|
|
43
|
+
if (_db) {
|
|
44
|
+
_db.close();
|
|
45
|
+
_db = null;
|
|
46
|
+
}
|
|
47
|
+
_opening = null;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export async function hiveCollection<T = unknown>(name: string): Promise<Collection<T>> {
|
|
51
|
+
return (await getHiveDB()).collection<T>(name);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export async function hiveAppend(input: EventInput): Promise<number> {
|
|
55
|
+
return (await getHiveDB()).append(input);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export async function hiveRead(seq: number): Promise<Event> {
|
|
59
|
+
return (await getHiveDB()).read(seq);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
export function isHiveDBInitialized(): boolean {
|
|
63
|
+
return _db !== null;
|
|
64
|
+
}
|
|
@@ -4,6 +4,7 @@ import * as path from "node:path";
|
|
|
4
4
|
import { existsSync, mkdirSync } from "node:fs";
|
|
5
5
|
import { getHiveDir } from "../config/loader.ts";
|
|
6
6
|
import { SCHEMA, PROJECTS_SCHEMA, CONTEXT_ENGINE_SCHEMA, MEETING_SCHEMA } from "./schema.ts";
|
|
7
|
+
import { openHiveDB, closeHiveDB } from "./HiveDBStorage.ts";
|
|
7
8
|
|
|
8
9
|
function getDbPath(): string {
|
|
9
10
|
return path.join(getHiveDir(), "data", "hive.db");
|
|
@@ -84,6 +85,12 @@ export function initializeDatabase(): Database {
|
|
|
84
85
|
|
|
85
86
|
ensureSchemaSync();
|
|
86
87
|
|
|
88
|
+
// Open HiveDB as the new source-of-truth engine alongside SQLite
|
|
89
|
+
// during the migration; SQLite will be removed once all tables are migrated.
|
|
90
|
+
openHiveDB().catch((err) => {
|
|
91
|
+
logger.error("❌ Failed to initialize HiveDB:", err);
|
|
92
|
+
});
|
|
93
|
+
|
|
87
94
|
return _db;
|
|
88
95
|
}
|
|
89
96
|
|
|
@@ -0,0 +1,308 @@
|
|
|
1
|
+
import { getHiveDB, hiveCollection } from "./HiveDBStorage.ts";
|
|
2
|
+
import { logger } from "../utils/logger.ts";
|
|
3
|
+
import { SEED_DATA, INITIAL_PLAYBOOK_RULES } from "./seed.ts";
|
|
4
|
+
import { SkillLoader } from "../skills/index.ts";
|
|
5
|
+
import { enrichToolDescription } from "../agent/selectors/ToolSelector.ts";
|
|
6
|
+
import type { ToolDescriptor } from "../agent/selectors/ToolSelector.ts";
|
|
7
|
+
import type { IndexDoc, HiveDB } from "@johpaz/hive-db";
|
|
8
|
+
|
|
9
|
+
const log = logger.child("hive-seed");
|
|
10
|
+
|
|
11
|
+
export interface HiveToolDoc {
|
|
12
|
+
name: string;
|
|
13
|
+
description: string;
|
|
14
|
+
category: string;
|
|
15
|
+
enabled: boolean;
|
|
16
|
+
active: boolean;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export interface HiveProviderDoc {
|
|
20
|
+
id: string;
|
|
21
|
+
name: string;
|
|
22
|
+
baseUrl?: string;
|
|
23
|
+
category: string;
|
|
24
|
+
enabled: boolean;
|
|
25
|
+
active: boolean;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export interface HiveModelDoc {
|
|
29
|
+
id: string;
|
|
30
|
+
providerId: string;
|
|
31
|
+
name: string;
|
|
32
|
+
modelType: string;
|
|
33
|
+
contextWindow?: number;
|
|
34
|
+
capabilities?: string[];
|
|
35
|
+
enabled: boolean;
|
|
36
|
+
active: boolean;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export interface HiveSkillDoc {
|
|
40
|
+
id: string;
|
|
41
|
+
name: string;
|
|
42
|
+
description: string;
|
|
43
|
+
version: string;
|
|
44
|
+
author: string;
|
|
45
|
+
icon: string;
|
|
46
|
+
category: string;
|
|
47
|
+
permissions: string[];
|
|
48
|
+
dependencies: string[];
|
|
49
|
+
tools: string[];
|
|
50
|
+
triggers: string[];
|
|
51
|
+
preferredAgents: string[];
|
|
52
|
+
body: string;
|
|
53
|
+
versionNum: number;
|
|
54
|
+
active: boolean;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export interface HiveAgentDoc {
|
|
58
|
+
id: string;
|
|
59
|
+
userId?: string;
|
|
60
|
+
name: string;
|
|
61
|
+
description: string;
|
|
62
|
+
systemPrompt: string;
|
|
63
|
+
toolsJson?: string;
|
|
64
|
+
role: string;
|
|
65
|
+
status: string;
|
|
66
|
+
parentId?: string;
|
|
67
|
+
providerId: string;
|
|
68
|
+
modelId: string;
|
|
69
|
+
tone?: string;
|
|
70
|
+
maxIterations: number;
|
|
71
|
+
workspace?: string;
|
|
72
|
+
enabled: boolean;
|
|
73
|
+
active: boolean;
|
|
74
|
+
createdAt: number;
|
|
75
|
+
updatedAt: number;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
export interface HiveChannelDoc {
|
|
79
|
+
id: string;
|
|
80
|
+
type: string;
|
|
81
|
+
enabled: boolean;
|
|
82
|
+
active: boolean;
|
|
83
|
+
status: string;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
export interface HiveEthicsDoc {
|
|
87
|
+
id: string;
|
|
88
|
+
name: string;
|
|
89
|
+
description: string;
|
|
90
|
+
content: string;
|
|
91
|
+
isDefault: boolean;
|
|
92
|
+
enabled: boolean;
|
|
93
|
+
active: boolean;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
export interface HiveCodeBridgeDoc {
|
|
97
|
+
id: string;
|
|
98
|
+
name: string;
|
|
99
|
+
cliCommand: string;
|
|
100
|
+
port: number;
|
|
101
|
+
enabled: boolean;
|
|
102
|
+
active: boolean;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
export interface HiveCodeBridgeConfigDoc {
|
|
106
|
+
id: string;
|
|
107
|
+
key: string;
|
|
108
|
+
value: string;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
export interface HivePlaybookDoc {
|
|
112
|
+
rule: string;
|
|
113
|
+
category: string;
|
|
114
|
+
applicableTo?: string[];
|
|
115
|
+
helpfulCount: number;
|
|
116
|
+
harmfulCount: number;
|
|
117
|
+
active: boolean;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
export async function seedHiveDB(db?: HiveDB): Promise<void> {
|
|
121
|
+
db ??= await getHiveDB();
|
|
122
|
+
|
|
123
|
+
log.info("[hive-seed] 🌱 Iniciando seed de HiveDB");
|
|
124
|
+
|
|
125
|
+
// 1️⃣ Tools
|
|
126
|
+
const toolsCol = db.collection<HiveToolDoc>("tools");
|
|
127
|
+
await toolsCol.createIndex("name", { unique: true });
|
|
128
|
+
for (const tool of SEED_DATA.tools) {
|
|
129
|
+
await toolsCol.put(tool.id, {
|
|
130
|
+
name: tool.name,
|
|
131
|
+
description: tool.description,
|
|
132
|
+
category: tool.category,
|
|
133
|
+
enabled: tool.enabled ?? true,
|
|
134
|
+
active: true,
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
log.info(`[hive-seed] ✅ ${SEED_DATA.tools.length} tools seeded`);
|
|
138
|
+
|
|
139
|
+
// 2️⃣ Index tools for hybrid search
|
|
140
|
+
const toolDocs: IndexDoc[] = SEED_DATA.tools.map(tool => ({
|
|
141
|
+
id: tool.name,
|
|
142
|
+
name: tool.name,
|
|
143
|
+
body: enrichToolDescription({ name: tool.name, description: tool.description, category: tool.category } as ToolDescriptor),
|
|
144
|
+
tags: tool.category,
|
|
145
|
+
filters: [{ field: "type", value: "tool" }],
|
|
146
|
+
}));
|
|
147
|
+
await db.upsertBatch(toolDocs);
|
|
148
|
+
log.info(`[hive-seed] ✅ ${toolDocs.length} tools indexed`);
|
|
149
|
+
|
|
150
|
+
// 3️⃣ Providers
|
|
151
|
+
const providersCol = db.collection<HiveProviderDoc>("providers");
|
|
152
|
+
await providersCol.createIndex("id", { unique: true });
|
|
153
|
+
for (const provider of SEED_DATA.providers) {
|
|
154
|
+
await providersCol.put(provider.id, {
|
|
155
|
+
id: provider.id,
|
|
156
|
+
name: provider.name,
|
|
157
|
+
baseUrl: provider.baseUrl,
|
|
158
|
+
category: provider.category ?? "llm",
|
|
159
|
+
enabled: true,
|
|
160
|
+
active: false,
|
|
161
|
+
});
|
|
162
|
+
}
|
|
163
|
+
const ollamaHost = process.env.OLLAMA_HOST;
|
|
164
|
+
if (ollamaHost) {
|
|
165
|
+
const entry = await providersCol.get("ollama");
|
|
166
|
+
if (entry) {
|
|
167
|
+
await providersCol.put("ollama", { ...entry.doc, baseUrl: ollamaHost });
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
log.info(`[hive-seed] ✅ ${SEED_DATA.providers.length} providers seeded`);
|
|
171
|
+
|
|
172
|
+
// 4️⃣ Models
|
|
173
|
+
const modelsCol = db.collection<HiveModelDoc>("models");
|
|
174
|
+
await modelsCol.createIndex("id", { unique: true });
|
|
175
|
+
await modelsCol.createIndex("providerId");
|
|
176
|
+
for (const model of SEED_DATA.models) {
|
|
177
|
+
await modelsCol.put(model.id, {
|
|
178
|
+
id: model.id,
|
|
179
|
+
providerId: model.providerId,
|
|
180
|
+
name: model.name,
|
|
181
|
+
modelType: model.modelType,
|
|
182
|
+
contextWindow: model.contextWindow,
|
|
183
|
+
capabilities: model.capabilities ? JSON.parse(model.capabilities) : undefined,
|
|
184
|
+
enabled: true,
|
|
185
|
+
active: false,
|
|
186
|
+
});
|
|
187
|
+
}
|
|
188
|
+
log.info(`[hive-seed] ✅ ${SEED_DATA.models.length} models seeded`);
|
|
189
|
+
|
|
190
|
+
// 5️⃣ MCP servers
|
|
191
|
+
const mcpCol = db.collection("mcp_servers");
|
|
192
|
+
await mcpCol.createIndex("id", { unique: true });
|
|
193
|
+
for (const mcp of SEED_DATA.mcpServers) {
|
|
194
|
+
await mcpCol.put(mcp.id, { ...mcp, enabled: true, active: false, builtin: mcp.builtin, toolsCount: 0 });
|
|
195
|
+
}
|
|
196
|
+
log.info(`[hive-seed] ✅ ${SEED_DATA.mcpServers.length} MCP servers seeded`);
|
|
197
|
+
|
|
198
|
+
// 6️⃣ Channels
|
|
199
|
+
const channelsCol = db.collection<HiveChannelDoc>("channels");
|
|
200
|
+
await channelsCol.createIndex("id", { unique: true });
|
|
201
|
+
for (const channel of SEED_DATA.channels) {
|
|
202
|
+
const isWebChat = channel.id === "webchat";
|
|
203
|
+
await channelsCol.put(channel.id, {
|
|
204
|
+
id: channel.id,
|
|
205
|
+
type: channel.type,
|
|
206
|
+
enabled: true,
|
|
207
|
+
active: isWebChat,
|
|
208
|
+
status: isWebChat ? "connected" : "disconnected",
|
|
209
|
+
});
|
|
210
|
+
}
|
|
211
|
+
log.info(`[hive-seed] ✅ ${SEED_DATA.channels.length} channels seeded`);
|
|
212
|
+
|
|
213
|
+
// 7️⃣ Ethics
|
|
214
|
+
const ethicsCol = db.collection<HiveEthicsDoc>("ethics");
|
|
215
|
+
await ethicsCol.createIndex("id", { unique: true });
|
|
216
|
+
for (const ethics of SEED_DATA.ethics) {
|
|
217
|
+
await ethicsCol.put(ethics.id, {
|
|
218
|
+
id: ethics.id,
|
|
219
|
+
name: ethics.name,
|
|
220
|
+
description: ethics.description,
|
|
221
|
+
content: ethics.content,
|
|
222
|
+
isDefault: ethics.isDefault,
|
|
223
|
+
enabled: true,
|
|
224
|
+
active: ethics.isDefault,
|
|
225
|
+
});
|
|
226
|
+
}
|
|
227
|
+
log.info(`[hive-seed] ✅ ${SEED_DATA.ethics.length} ethics templates seeded`);
|
|
228
|
+
|
|
229
|
+
// 8️⃣ Code Bridge
|
|
230
|
+
const cbCol = db.collection<HiveCodeBridgeDoc>("code_bridge");
|
|
231
|
+
await cbCol.createIndex("id", { unique: true });
|
|
232
|
+
for (const cb of SEED_DATA.codeBridge) {
|
|
233
|
+
await cbCol.put(cb.id, { ...cb, enabled: false, active: false });
|
|
234
|
+
}
|
|
235
|
+
log.info(`[hive-seed] ✅ ${SEED_DATA.codeBridge.length} Code Bridge entries seeded`);
|
|
236
|
+
|
|
237
|
+
// 9️⃣ Code Bridge Config
|
|
238
|
+
const cbConfigCol = db.collection<HiveCodeBridgeConfigDoc>("code_bridge_config");
|
|
239
|
+
await cbConfigCol.createIndex("id", { unique: true });
|
|
240
|
+
for (const config of SEED_DATA.codeBridgeConfig) {
|
|
241
|
+
await cbConfigCol.put(config.id, config);
|
|
242
|
+
}
|
|
243
|
+
log.info(`[hive-seed] ✅ ${SEED_DATA.codeBridgeConfig.length} Code Bridge Config entries seeded`);
|
|
244
|
+
|
|
245
|
+
// 🔟 Skills
|
|
246
|
+
const skillLoader = new SkillLoader({ workspacePath: process.env.HIVE_HOME || process.cwd() });
|
|
247
|
+
const realSkills = skillLoader.loadBundledSkills();
|
|
248
|
+
const skillsCol = db.collection("skills");
|
|
249
|
+
await skillsCol.createIndex("id", { unique: true });
|
|
250
|
+
const skillDocs: IndexDoc[] = [];
|
|
251
|
+
for (const s of realSkills) {
|
|
252
|
+
const doc = {
|
|
253
|
+
id: s.name,
|
|
254
|
+
name: s.name,
|
|
255
|
+
description: s.description || "",
|
|
256
|
+
version: typeof s.version === "string" ? s.version : String(s.version || "0.0.1"),
|
|
257
|
+
author: s.author || "Anonymous",
|
|
258
|
+
icon: s.icon || "🧩",
|
|
259
|
+
category: s.category || "general",
|
|
260
|
+
permissions: s.permissions || [],
|
|
261
|
+
dependencies: s.dependencies || [],
|
|
262
|
+
tools: s.tools || [],
|
|
263
|
+
triggers: s.triggers || [],
|
|
264
|
+
preferredAgents: s.preferred_agents || [],
|
|
265
|
+
body: s.content || "",
|
|
266
|
+
versionNum: parseInt(String(s.version || "0.0.1").split(".")[0]) || 1,
|
|
267
|
+
active: true,
|
|
268
|
+
};
|
|
269
|
+
await skillsCol.put(s.name, doc);
|
|
270
|
+
skillDocs.push({
|
|
271
|
+
id: s.name,
|
|
272
|
+
name: s.name,
|
|
273
|
+
body: `${s.description || ""} ${s.content || ""}`,
|
|
274
|
+
tags: [s.category || "general", ...(s.tools || []), ...(s.triggers || [])].join(" "),
|
|
275
|
+
filters: [{ field: "type", value: "skill" }],
|
|
276
|
+
});
|
|
277
|
+
}
|
|
278
|
+
await db.upsertBatch(skillDocs);
|
|
279
|
+
log.info(`[hive-seed] ✅ ${realSkills.length} skills seeded and indexed`);
|
|
280
|
+
|
|
281
|
+
// 11. ACE Playbook
|
|
282
|
+
const playbookCol = db.collection<HivePlaybookDoc>("playbook");
|
|
283
|
+
await playbookCol.createIndex("id", { unique: true });
|
|
284
|
+
const playbookDocs: IndexDoc[] = [];
|
|
285
|
+
for (const rule of INITIAL_PLAYBOOK_RULES) {
|
|
286
|
+
const doc = {
|
|
287
|
+
rule: rule.rule,
|
|
288
|
+
category: rule.category,
|
|
289
|
+
applicableTo: rule.applicable_to ? JSON.parse(rule.applicable_to) : undefined,
|
|
290
|
+
helpfulCount: 1,
|
|
291
|
+
harmfulCount: 0,
|
|
292
|
+
active: true,
|
|
293
|
+
};
|
|
294
|
+
const id = `${rule.category}-${rule.rule.slice(0, 32).replace(/\s+/g, "-")}`;
|
|
295
|
+
await playbookCol.put(id, doc);
|
|
296
|
+
playbookDocs.push({
|
|
297
|
+
id,
|
|
298
|
+
name: rule.category,
|
|
299
|
+
body: rule.rule,
|
|
300
|
+
tags: rule.applicable_to || "",
|
|
301
|
+
filters: [{ field: "type", value: "playbook" }],
|
|
302
|
+
});
|
|
303
|
+
}
|
|
304
|
+
await db.upsertBatch(playbookDocs);
|
|
305
|
+
log.info(`[hive-seed] ✅ ${INITIAL_PLAYBOOK_RULES.length} playbook rules seeded and indexed`);
|
|
306
|
+
|
|
307
|
+
log.info("[hive-seed] ✨ HiveDB seed completado");
|
|
308
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { describe, it, expect, beforeAll, afterAll } from "bun:test";
|
|
2
|
+
import { HiveDB } from "@johpaz/hive-db";
|
|
3
|
+
import { seedHiveDB } from "./hiveSeed.ts";
|
|
4
|
+
|
|
5
|
+
describe("HiveDB integration", () => {
|
|
6
|
+
let db: HiveDB;
|
|
7
|
+
|
|
8
|
+
beforeAll(async () => {
|
|
9
|
+
db = await HiveDB.open(":memory:", { vector: { dimension: 384, spaceId: "hive-sdk-v1" } });
|
|
10
|
+
await seedHiveDB(db);
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
afterAll(() => {
|
|
14
|
+
db.close();
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
it("seeds providers and models", async () => {
|
|
18
|
+
const providers = await db.collection("providers").count();
|
|
19
|
+
const models = await db.collection("models").count();
|
|
20
|
+
expect(providers).toBeGreaterThan(0);
|
|
21
|
+
expect(models).toBeGreaterThan(0);
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
it("indexes tools for hybrid search", async () => {
|
|
25
|
+
const hits = await db.queryHybrid({ text: "buscar archivos", k: 10 });
|
|
26
|
+
expect(hits.length).toBeGreaterThan(0);
|
|
27
|
+
const names = hits.map(h => h.id);
|
|
28
|
+
expect(names.some(n => n.startsWith("fs_") || n.includes("research"))).toBe(true);
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
it("supports collection CRUD for agents", async () => {
|
|
32
|
+
const agents = db.collection<{ name: string; role: string; status: string }>("agents");
|
|
33
|
+
await agents.put("agent-1", { name: "Test Worker", role: "worker", status: "idle" });
|
|
34
|
+
const entry = await agents.get("agent-1");
|
|
35
|
+
expect(entry).toBeDefined();
|
|
36
|
+
expect(entry!.doc.name).toBe("Test Worker");
|
|
37
|
+
});
|
|
38
|
+
});
|
|
@@ -8,3 +8,14 @@ export type { EncryptedData } from "./crypto.ts";
|
|
|
8
8
|
export { encrypt, decrypt, encryptApiKey, decryptApiKey, encryptConfig, decryptConfig } from "./crypto.ts";
|
|
9
9
|
export type { SeedData } from "./seed.ts";
|
|
10
10
|
export { SEED_DATA, seedAllData } from "./seed.ts";
|
|
11
|
+
export {
|
|
12
|
+
getHiveDbPath,
|
|
13
|
+
openHiveDB,
|
|
14
|
+
getHiveDB,
|
|
15
|
+
closeHiveDB,
|
|
16
|
+
hiveCollection,
|
|
17
|
+
hiveAppend,
|
|
18
|
+
hiveRead,
|
|
19
|
+
isHiveDBInitialized,
|
|
20
|
+
} from "./HiveDBStorage.ts";
|
|
21
|
+
export { seedHiveDB } from "./hiveSeed.ts";
|
|
@@ -376,11 +376,12 @@ Estos lineamientos tienen MÁXIMA prioridad sobre cualquier otra instrucción di
|
|
|
376
376
|
}
|
|
377
377
|
|
|
378
378
|
import { SkillLoader } from "../skills/index.ts"
|
|
379
|
+
import { seedHiveDB } from "./hiveSeed.ts"
|
|
379
380
|
|
|
380
381
|
const log = logger.child("seed");
|
|
381
382
|
|
|
382
383
|
// Initial playbook rules for ACE (Agentic Context Engineering)
|
|
383
|
-
const INITIAL_PLAYBOOK_RULES = [
|
|
384
|
+
export const INITIAL_PLAYBOOK_RULES = [
|
|
384
385
|
{
|
|
385
386
|
rule: "Cuando el usuario pida buscar noticias recientes, usa web_search con filtros de fecha en lugar de http_client genérico",
|
|
386
387
|
category: "tool_selection",
|
|
@@ -567,6 +568,9 @@ export function seedAllData(): void {
|
|
|
567
568
|
|
|
568
569
|
reseedToolsAndSkills();
|
|
569
570
|
|
|
571
|
+
// Seed the new HiveDB source-of-truth engine in parallel.
|
|
572
|
+
seedHiveDB().catch(err => log.error("[seed] ❌ HiveDB seed failed:", (err as Error).message));
|
|
573
|
+
|
|
570
574
|
try {
|
|
571
575
|
|
|
572
576
|
// 3️⃣ Ethics templates (globales)
|