@desplega.ai/agent-swarm 1.91.0 → 1.92.1
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 -2
- package/openapi.json +1005 -152
- package/package.json +6 -6
- package/plugin/skills/pages/SKILL.md +5 -2
- package/src/be/db.ts +662 -19
- package/src/be/memory/constants.ts +2 -1
- package/src/be/memory/providers/openai-embedding.ts +2 -5
- package/src/be/memory/providers/sqlite-store.ts +293 -76
- package/src/be/memory/types.ts +35 -0
- package/src/be/migrations/083_script_workflows.sql +51 -0
- package/src/be/migrations/084_script_run_journal_duration.sql +5 -0
- package/src/be/migrations/085_script_runs_kind.sql +9 -0
- package/src/be/migrations/086_pages_default_authed.sql +64 -0
- package/src/be/migrations/087_skill_files.sql +19 -0
- package/src/be/modelsdev-cache.json +42310 -38617
- package/src/be/scripts/typecheck.ts +49 -0
- package/src/be/seed-scripts/catalog/boot-triage.ts +221 -0
- package/src/be/seed-scripts/catalog/catalog-report.ts +457 -0
- package/src/be/seed-scripts/catalog/compound-insights.ts +310 -6
- package/src/be/seed-scripts/catalog/gh-pr-snapshot.ts +1 -1
- package/src/be/seed-scripts/catalog/memory-eval.ts +1059 -0
- package/src/be/seed-scripts/catalog/ops-catalog-audit.ts +506 -0
- package/src/be/seed-scripts/catalog/schedule-health.ts +78 -2
- package/src/be/seed-scripts/catalog/task-context-gathering.ts +92 -0
- package/src/be/seed-scripts/catalog/task-failure-audit.ts +48 -1
- package/src/be/seed-scripts/catalog/tool-usage.ts +6 -3
- package/src/be/seed-scripts/index.ts +51 -5
- package/src/be/seed-skills/index.ts +3 -3
- package/src/be/skill-sync.ts +91 -7
- package/src/be/swarm-config-guard.ts +17 -0
- package/src/commands/runner.ts +49 -4
- package/src/heartbeat/templates.ts +20 -16
- package/src/http/db-query.ts +20 -5
- package/src/http/index.ts +51 -7
- package/src/http/mcp-user.ts +23 -0
- package/src/http/mcp.ts +58 -0
- package/src/http/memory.ts +58 -0
- package/src/http/pages.ts +1 -1
- package/src/http/script-runs.ts +557 -0
- package/src/http/scripts.ts +39 -2
- package/src/http/skills.ts +225 -0
- package/src/prompts/session-templates.ts +24 -4
- package/src/providers/claude-adapter.ts +107 -28
- package/src/script-workflows/executor.ts +110 -0
- package/src/script-workflows/harness.ts +73 -0
- package/src/script-workflows/label-lint.ts +51 -0
- package/src/script-workflows/limits.ts +22 -0
- package/src/script-workflows/supervisor.ts +139 -0
- package/src/script-workflows/workflow-ctx.ts +209 -0
- package/src/scripts-runtime/sdk-allowlist.ts +4 -0
- package/src/scripts-runtime/swarm-sdk.ts +13 -0
- package/src/scripts-runtime/types/stdlib.d.ts +61 -0
- package/src/scripts-runtime/types/swarm-sdk.d.ts +61 -0
- package/src/server.ts +4 -0
- package/src/slack/handlers.ts +11 -4
- package/src/slack/message-text.ts +98 -0
- package/src/slack/thread-buffer.ts +5 -3
- package/src/tests/claude-adapter-binary.test.ts +271 -74
- package/src/tests/create-page-tool.test.ts +19 -2
- package/src/tests/db-query.test.ts +28 -0
- package/src/tests/error-tracker.test.ts +121 -0
- package/src/tests/harness-provider-resolution.test.ts +33 -0
- package/src/tests/heartbeat-checklist.test.ts +36 -0
- package/src/tests/mcp-tools.test.ts +6 -0
- package/src/tests/mcp-transport-gc.test.ts +58 -0
- package/src/tests/memory-health-endpoint.test.ts +78 -0
- package/src/tests/memory-store.test.ts +221 -1
- package/src/tests/pages-http.test.ts +20 -2
- package/src/tests/pages-storage.test.ts +26 -0
- package/src/tests/prompt-template-session.test.ts +34 -5
- package/src/tests/script-runs-http.test.ts +278 -0
- package/src/tests/script-workflows-label-lint.test.ts +43 -0
- package/src/tests/script-workflows-runtime-e2e.test.ts +170 -0
- package/src/tests/scripts-mcp-e2e.test.ts +102 -2
- package/src/tests/seed-scripts.test.ts +468 -3
- package/src/tests/skill-files-http.test.ts +171 -0
- package/src/tests/skill-files.test.ts +162 -0
- package/src/tests/skill-get-file-tool.test.ts +110 -0
- package/src/tests/skill-sync.test.ts +125 -6
- package/src/tests/slack-message-text.test.ts +250 -0
- package/src/tests/system-default-skills.test.ts +40 -0
- package/src/tools/create-page.ts +2 -2
- package/src/tools/db-query.ts +16 -6
- package/src/tools/script-runs.ts +123 -0
- package/src/tools/skills/index.ts +1 -0
- package/src/tools/skills/skill-get-file.ts +80 -0
- package/src/tools/slack-read.ts +12 -3
- package/src/tools/tool-config.ts +6 -2
- package/src/types.ts +72 -0
- package/src/utils/error-tracker.ts +40 -1
- package/src/utils/internal-ai/complete-structured.ts +10 -4
- package/src/workflows/executors/raw-llm.ts +76 -59
- package/templates/schedules/daily-blocker-digest/content.md +68 -54
- package/templates/schedules/daily-compounding-reflection/content.md +4 -4
- package/templates/schedules/daily-hn-briefing/content.md +5 -5
- package/templates/schedules/daily-workflow-health-audit/content.md +6 -6
- package/templates/schedules/gtm-weekly-review/content.md +9 -9
- package/templates/schedules/weekly-dependabot-triage/content.md +24 -20
- package/templates/skills/agentmail-sending/content.md +6 -7
- package/templates/skills/desloppify/content.md +8 -9
- package/templates/skills/jira-interaction/content.md +25 -33
- package/templates/skills/kapso-whatsapp/content.md +29 -30
- package/templates/skills/linear-interaction/content.md +8 -9
- package/templates/skills/pages/content.md +205 -55
- package/templates/skills/profile-corruption-escalation/content.md +44 -85
- package/templates/skills/script-workflows/config.json +14 -0
- package/templates/skills/script-workflows/content.md +68 -0
- package/templates/skills/sprite-cli/content.md +4 -5
- package/templates/skills/swarm-scripts/content.md +2 -3
- package/templates/skills/turso-interaction/content.md +14 -17
- package/templates/skills/workflow-iterate/content.md +38 -391
- package/templates/skills/x-api-interactions/content.md +4 -6
- package/templates/skills/scheduled-task-resilience/config.json +0 -14
- package/templates/skills/scheduled-task-resilience/content.md +0 -95
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { afterAll, beforeAll, describe, expect, test } from "bun:test";
|
|
2
2
|
import { unlink } from "node:fs/promises";
|
|
3
|
-
import { closeDb, createAgent, initDb } from "../be/db";
|
|
3
|
+
import { closeDb, createAgent, getDb, initDb } from "../be/db";
|
|
4
|
+
import { serializeEmbedding } from "../be/embedding";
|
|
4
5
|
import { SqliteMemoryStore } from "../be/memory/providers/sqlite-store";
|
|
5
6
|
|
|
6
7
|
const TEST_DB_PATH = "./test-memory-store.sqlite";
|
|
@@ -10,6 +11,14 @@ describe("SqliteMemoryStore", () => {
|
|
|
10
11
|
const agentB = "bbbb0000-0000-4000-8000-000000000002";
|
|
11
12
|
let store: SqliteMemoryStore;
|
|
12
13
|
|
|
14
|
+
function vector(values: Record<number, number>): Float32Array {
|
|
15
|
+
const embedding = new Float32Array(512);
|
|
16
|
+
for (const [index, value] of Object.entries(values)) {
|
|
17
|
+
embedding[Number(index)] = value;
|
|
18
|
+
}
|
|
19
|
+
return embedding;
|
|
20
|
+
}
|
|
21
|
+
|
|
13
22
|
beforeAll(async () => {
|
|
14
23
|
for (const suffix of ["", "-wal", "-shm"]) {
|
|
15
24
|
try {
|
|
@@ -210,6 +219,95 @@ describe("SqliteMemoryStore", () => {
|
|
|
210
219
|
const agents = new Set(results.map((r) => r.agentId));
|
|
211
220
|
expect(agents.size).toBeGreaterThanOrEqual(1);
|
|
212
221
|
});
|
|
222
|
+
|
|
223
|
+
test("uses sqlite-vec for 512d embeddings with scope-filter parity", () => {
|
|
224
|
+
for (let i = 0; i < 6; i++) {
|
|
225
|
+
const otherAgent = store.store({
|
|
226
|
+
agentId: agentB,
|
|
227
|
+
scope: "agent",
|
|
228
|
+
name: `vec-other-agent-exact-${i}`,
|
|
229
|
+
content: "exact but invisible to agentA",
|
|
230
|
+
source: "manual",
|
|
231
|
+
});
|
|
232
|
+
store.updateEmbedding(otherAgent.id, vector({ 0: 1 }), "test-model");
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
const visible = store.store({
|
|
236
|
+
agentId: agentA,
|
|
237
|
+
scope: "agent",
|
|
238
|
+
name: "vec-agent-visible",
|
|
239
|
+
content: "visible to agentA",
|
|
240
|
+
source: "manual",
|
|
241
|
+
});
|
|
242
|
+
store.updateEmbedding(visible.id, vector({ 0: 0.8, 1: 0.2 }), "test-model");
|
|
243
|
+
|
|
244
|
+
const query = vector({ 0: 1 });
|
|
245
|
+
const results = store.search(query, agentA, { scope: "agent", limit: 5 });
|
|
246
|
+
|
|
247
|
+
expect(results[0]!.id).toBe(visible.id);
|
|
248
|
+
expect(results.every((r) => r.agentId === agentA && r.scope === "agent")).toBe(true);
|
|
249
|
+
|
|
250
|
+
const health = store.getHealth();
|
|
251
|
+
expect(health.sqliteVec.schema).toContain("distance_metric=cosine");
|
|
252
|
+
expect(health.counts.memoryVec).toBeGreaterThanOrEqual(2);
|
|
253
|
+
expect(health.retrievalMode).toBe("vec");
|
|
254
|
+
});
|
|
255
|
+
});
|
|
256
|
+
|
|
257
|
+
describe("memory_vec population", () => {
|
|
258
|
+
test("populates existing embeddings on startup and reports health counts", () => {
|
|
259
|
+
const raw = store.store({
|
|
260
|
+
agentId: agentA,
|
|
261
|
+
scope: "agent",
|
|
262
|
+
name: "raw-existing-embedding",
|
|
263
|
+
content: "raw existing embedding",
|
|
264
|
+
source: "manual",
|
|
265
|
+
});
|
|
266
|
+
getDb()
|
|
267
|
+
.prepare("UPDATE agent_memory SET embedding = ?, embeddingModel = ? WHERE id = ?")
|
|
268
|
+
.run(serializeEmbedding(vector({ 2: 1 })), "test-model", raw.id);
|
|
269
|
+
getDb().prepare("DELETE FROM memory_vec WHERE memory_id = ?").run(raw.id);
|
|
270
|
+
|
|
271
|
+
const freshStore = new SqliteMemoryStore();
|
|
272
|
+
const health = freshStore.getHealth();
|
|
273
|
+
|
|
274
|
+
expect(health.counts.missingFromVec).toBe(0);
|
|
275
|
+
expect(health.sqliteVec.lastPopulate?.attempted).toBeGreaterThanOrEqual(1);
|
|
276
|
+
expect(health.sqliteVec.lastPopulate?.failed).toBe(0);
|
|
277
|
+
|
|
278
|
+
const resultIds = freshStore
|
|
279
|
+
.search(vector({ 2: 1 }), agentA, { scope: "agent", limit: 20 })
|
|
280
|
+
.map((r) => r.id);
|
|
281
|
+
expect(resultIds).toContain(raw.id);
|
|
282
|
+
});
|
|
283
|
+
|
|
284
|
+
test("rebuilds an old non-cosine memory_vec table from agent_memory", () => {
|
|
285
|
+
const raw = store.store({
|
|
286
|
+
agentId: agentA,
|
|
287
|
+
scope: "agent",
|
|
288
|
+
name: "stale-schema-embedding",
|
|
289
|
+
content: "stale schema embedding",
|
|
290
|
+
source: "manual",
|
|
291
|
+
});
|
|
292
|
+
getDb()
|
|
293
|
+
.prepare("UPDATE agent_memory SET embedding = ?, embeddingModel = ? WHERE id = ?")
|
|
294
|
+
.run(serializeEmbedding(vector({ 3: 1 })), "test-model", raw.id);
|
|
295
|
+
|
|
296
|
+
getDb().run("DROP TABLE memory_vec");
|
|
297
|
+
getDb().run(`
|
|
298
|
+
CREATE VIRTUAL TABLE memory_vec USING vec0(
|
|
299
|
+
memory_id TEXT PRIMARY KEY,
|
|
300
|
+
embedding float[512]
|
|
301
|
+
)
|
|
302
|
+
`);
|
|
303
|
+
|
|
304
|
+
const freshStore = new SqliteMemoryStore();
|
|
305
|
+
const health = freshStore.getHealth();
|
|
306
|
+
|
|
307
|
+
expect(health.sqliteVec.schema).toContain("distance_metric=cosine");
|
|
308
|
+
expect(health.counts.missingFromVec).toBe(0);
|
|
309
|
+
expect(health.retrievalMode).toBe("vec");
|
|
310
|
+
});
|
|
213
311
|
});
|
|
214
312
|
|
|
215
313
|
describe("delete()", () => {
|
|
@@ -326,4 +424,126 @@ describe("SqliteMemoryStore", () => {
|
|
|
326
424
|
expect(filtered.length).toBeGreaterThan(0);
|
|
327
425
|
});
|
|
328
426
|
});
|
|
427
|
+
|
|
428
|
+
describe("purgeExpired()", () => {
|
|
429
|
+
const purgeAgent = "cccc0000-0000-4000-8000-000000000003";
|
|
430
|
+
|
|
431
|
+
beforeAll(() => {
|
|
432
|
+
try {
|
|
433
|
+
createAgent({ id: purgeAgent, name: "Purge Agent", isLead: false, status: "idle" });
|
|
434
|
+
} catch {
|
|
435
|
+
// agent may already exist from a prior run
|
|
436
|
+
}
|
|
437
|
+
});
|
|
438
|
+
|
|
439
|
+
test("deletes rows past their expiresAt and returns count", () => {
|
|
440
|
+
const db = getDb();
|
|
441
|
+
|
|
442
|
+
// Store a session_summary (3-day TTL) then backdateits expiresAt to the past
|
|
443
|
+
const mem = store.store({
|
|
444
|
+
agentId: purgeAgent,
|
|
445
|
+
scope: "agent",
|
|
446
|
+
name: "expired session",
|
|
447
|
+
content: "old session data",
|
|
448
|
+
source: "session_summary",
|
|
449
|
+
});
|
|
450
|
+
db.prepare("UPDATE agent_memory SET expiresAt = datetime('now', '-1 day') WHERE id = ?").run(
|
|
451
|
+
mem.id,
|
|
452
|
+
);
|
|
453
|
+
|
|
454
|
+
// Store a manual memory (never expires) — should survive
|
|
455
|
+
const keeper = store.store({
|
|
456
|
+
agentId: purgeAgent,
|
|
457
|
+
scope: "agent",
|
|
458
|
+
name: "keeper",
|
|
459
|
+
content: "manual content",
|
|
460
|
+
source: "manual",
|
|
461
|
+
});
|
|
462
|
+
|
|
463
|
+
const purged = store.purgeExpired();
|
|
464
|
+
expect(purged).toBeGreaterThanOrEqual(1);
|
|
465
|
+
|
|
466
|
+
expect(store.get(mem.id)).toBeNull();
|
|
467
|
+
expect(store.get(keeper.id)).not.toBeNull();
|
|
468
|
+
});
|
|
469
|
+
|
|
470
|
+
test("returns 0 when nothing is expired", () => {
|
|
471
|
+
const purged = store.purgeExpired();
|
|
472
|
+
expect(purged).toBe(0);
|
|
473
|
+
});
|
|
474
|
+
|
|
475
|
+
test("also removes corresponding vec rows", () => {
|
|
476
|
+
const db = getDb();
|
|
477
|
+
const emb = vector({ 0: 0.9, 100: 0.1 });
|
|
478
|
+
|
|
479
|
+
const mem = store.store({
|
|
480
|
+
agentId: purgeAgent,
|
|
481
|
+
scope: "agent",
|
|
482
|
+
name: "vec-purge-test",
|
|
483
|
+
content: "will be purged",
|
|
484
|
+
source: "task_completion",
|
|
485
|
+
});
|
|
486
|
+
store.updateEmbedding(mem.id, emb, "test-model");
|
|
487
|
+
|
|
488
|
+
const vecBefore = db
|
|
489
|
+
.prepare<{ count: number }, [string]>(
|
|
490
|
+
"SELECT COUNT(*) as count FROM memory_vec WHERE memory_id = ?",
|
|
491
|
+
)
|
|
492
|
+
.get(mem.id);
|
|
493
|
+
|
|
494
|
+
// Only check vec cleanup if the row was actually inserted
|
|
495
|
+
if (vecBefore && vecBefore.count > 0) {
|
|
496
|
+
db.prepare(
|
|
497
|
+
"UPDATE agent_memory SET expiresAt = datetime('now', '-1 day') WHERE id = ?",
|
|
498
|
+
).run(mem.id);
|
|
499
|
+
|
|
500
|
+
store.purgeExpired();
|
|
501
|
+
|
|
502
|
+
const vecAfter = db
|
|
503
|
+
.prepare<{ count: number }, [string]>(
|
|
504
|
+
"SELECT COUNT(*) as count FROM memory_vec WHERE memory_id = ?",
|
|
505
|
+
)
|
|
506
|
+
.get(mem.id);
|
|
507
|
+
expect(vecAfter?.count ?? 0).toBe(0);
|
|
508
|
+
}
|
|
509
|
+
});
|
|
510
|
+
});
|
|
511
|
+
|
|
512
|
+
describe("knn-k cap", () => {
|
|
513
|
+
test("search does not throw when vec table exceeds 4096 rows", () => {
|
|
514
|
+
const db = getDb();
|
|
515
|
+
const emb = vector({ 0: 1.0 });
|
|
516
|
+
const embBuffer = serializeEmbedding(emb);
|
|
517
|
+
|
|
518
|
+
// Check if vec is available — if not, skip (test is meaningful only with vec)
|
|
519
|
+
const health = store.getHealth();
|
|
520
|
+
if (health.retrievalMode !== "vec") return;
|
|
521
|
+
|
|
522
|
+
// Insert enough rows to exceed 4096 in the vec table
|
|
523
|
+
const currentCount =
|
|
524
|
+
db.prepare<{ c: number }, []>("SELECT COUNT(*) as c FROM memory_vec").get()?.c ?? 0;
|
|
525
|
+
const needed = Math.max(0, 4097 - currentCount);
|
|
526
|
+
|
|
527
|
+
for (let i = 0; i < needed; i++) {
|
|
528
|
+
const id = `knn-test-${i}-${Date.now()}`;
|
|
529
|
+
db.prepare(
|
|
530
|
+
"INSERT INTO agent_memory (id, agentId, scope, name, content, source, embedding, chunkIndex, totalChunks, tags, alpha, beta, createdAt, accessedAt) VALUES (?, ?, 'agent', ?, 'knn test', 'manual', ?, 0, 1, '[]', 1, 1, datetime('now'), datetime('now'))",
|
|
531
|
+
).run(id, agentA, `knn-${i}`, embBuffer);
|
|
532
|
+
const vecBuf = new Float32Array(emb);
|
|
533
|
+
db.prepare("INSERT INTO memory_vec (memory_id, embedding) VALUES (?, ?)").run(
|
|
534
|
+
id,
|
|
535
|
+
Buffer.from(vecBuf.buffer),
|
|
536
|
+
);
|
|
537
|
+
}
|
|
538
|
+
|
|
539
|
+
const vecCount =
|
|
540
|
+
db.prepare<{ c: number }, []>("SELECT COUNT(*) as c FROM memory_vec").get()?.c ?? 0;
|
|
541
|
+
expect(vecCount).toBeGreaterThanOrEqual(4097);
|
|
542
|
+
|
|
543
|
+
// This should NOT throw — it should clamp k to 4096
|
|
544
|
+
const results = store.search(emb, agentA, { scope: "agent", limit: 10 });
|
|
545
|
+
expect(results).toBeDefined();
|
|
546
|
+
expect(Array.isArray(results)).toBe(true);
|
|
547
|
+
});
|
|
548
|
+
});
|
|
329
549
|
});
|
|
@@ -61,14 +61,13 @@ describe("Pages HTTP API", () => {
|
|
|
61
61
|
}
|
|
62
62
|
});
|
|
63
63
|
|
|
64
|
-
test("POST /api/pages creates
|
|
64
|
+
test("POST /api/pages creates an authed page by default and returns {id, version}", async () => {
|
|
65
65
|
const res = await fetch(`${baseUrl}/api/pages`, {
|
|
66
66
|
method: "POST",
|
|
67
67
|
headers,
|
|
68
68
|
body: JSON.stringify({
|
|
69
69
|
title: "Hello",
|
|
70
70
|
contentType: "text/html",
|
|
71
|
-
authMode: "public",
|
|
72
71
|
body: "<h1>hi</h1>",
|
|
73
72
|
}),
|
|
74
73
|
});
|
|
@@ -87,6 +86,25 @@ describe("Pages HTTP API", () => {
|
|
|
87
86
|
expect(page.agentId).toBe(agentId);
|
|
88
87
|
expect(page.slug).toBe("hello"); // auto-slug from title
|
|
89
88
|
expect(page.contentType).toBe("text/html");
|
|
89
|
+
expect(page.authMode).toBe("authed");
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
test("POST /api/pages can explicitly opt in to public auth", async () => {
|
|
93
|
+
const res = await fetch(`${baseUrl}/api/pages`, {
|
|
94
|
+
method: "POST",
|
|
95
|
+
headers,
|
|
96
|
+
body: JSON.stringify({
|
|
97
|
+
title: "Public",
|
|
98
|
+
contentType: "text/html",
|
|
99
|
+
authMode: "public",
|
|
100
|
+
body: "<h1>public</h1>",
|
|
101
|
+
}),
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
expect(res.status).toBe(201);
|
|
105
|
+
const json = (await res.json()) as { id: string };
|
|
106
|
+
const got = await fetch(`${baseUrl}/api/pages/${json.id}`, { headers });
|
|
107
|
+
const page = (await got.json()) as Page;
|
|
90
108
|
expect(page.authMode).toBe("public");
|
|
91
109
|
});
|
|
92
110
|
|
|
@@ -5,6 +5,7 @@ import {
|
|
|
5
5
|
closeDb,
|
|
6
6
|
createPage,
|
|
7
7
|
deletePage,
|
|
8
|
+
getDb,
|
|
8
9
|
getPage,
|
|
9
10
|
getPageBySlug,
|
|
10
11
|
getPageVersion,
|
|
@@ -81,6 +82,31 @@ describe("pages storage CRUD", () => {
|
|
|
81
82
|
expect(getPageVersions(created.id)).toHaveLength(0);
|
|
82
83
|
});
|
|
83
84
|
|
|
85
|
+
test("createPage defaults authMode to authed when omitted", () => {
|
|
86
|
+
const agentId = makeAgentId();
|
|
87
|
+
const created = createPage({
|
|
88
|
+
agentId,
|
|
89
|
+
slug: "default-auth",
|
|
90
|
+
title: "Default Auth",
|
|
91
|
+
contentType: "text/html",
|
|
92
|
+
body: "<h1>default</h1>",
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
expect(created.authMode).toBe("authed");
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
test("pages table defaults authMode to authed when omitted", () => {
|
|
99
|
+
const agentId = makeAgentId();
|
|
100
|
+
const row = getDb()
|
|
101
|
+
.prepare<{ authMode: string }, [string, string, string, string, string]>(
|
|
102
|
+
`INSERT INTO pages (agentId, slug, title, contentType, body)
|
|
103
|
+
VALUES (?, ?, ?, ?, ?) RETURNING authMode`,
|
|
104
|
+
)
|
|
105
|
+
.get(agentId, "sql-default-auth", "SQL Default Auth", "text/html", "<h1>default</h1>");
|
|
106
|
+
|
|
107
|
+
expect(row?.authMode).toBe("authed");
|
|
108
|
+
});
|
|
109
|
+
|
|
84
110
|
test("snapshotPage captures PRE-update content; post-update lives on parent", () => {
|
|
85
111
|
const agentId = makeAgentId();
|
|
86
112
|
const page = createPage({
|
|
@@ -54,7 +54,7 @@ describe("Session templates — registration", () => {
|
|
|
54
54
|
await ensureTemplatesRegistered();
|
|
55
55
|
});
|
|
56
56
|
|
|
57
|
-
test("all
|
|
57
|
+
test("all 15 system templates are registered", () => {
|
|
58
58
|
const systemTemplates = [
|
|
59
59
|
"system.agent.role",
|
|
60
60
|
"system.agent.register",
|
|
@@ -66,6 +66,7 @@ describe("Session templates — registration", () => {
|
|
|
66
66
|
"system.agent.agent_fs",
|
|
67
67
|
"system.agent.self_awareness",
|
|
68
68
|
"system.agent.context_mode",
|
|
69
|
+
"system.agent.seed_scripts",
|
|
69
70
|
|
|
70
71
|
"system.agent.system",
|
|
71
72
|
"system.agent.services",
|
|
@@ -90,12 +91,12 @@ describe("Session templates — registration", () => {
|
|
|
90
91
|
}
|
|
91
92
|
});
|
|
92
93
|
|
|
93
|
-
test("total of
|
|
94
|
+
test("total of 21 session/system templates registered", () => {
|
|
94
95
|
const all = getAllTemplateDefinitions();
|
|
95
96
|
const sessionSystem = all.filter((d) => d.category === "system" || d.category === "session");
|
|
96
|
-
//
|
|
97
|
-
// composite
|
|
98
|
-
expect(sessionSystem.length).toBe(
|
|
97
|
+
// 21 = the original 19 + `system.session.worker.pi` + `system.agent.seed_scripts`.
|
|
98
|
+
// The pi composite omits script nudges because pi workers do not have MCP.
|
|
99
|
+
expect(sessionSystem.length).toBe(21);
|
|
99
100
|
});
|
|
100
101
|
});
|
|
101
102
|
|
|
@@ -187,6 +188,15 @@ describe("Session templates — individual resolution", () => {
|
|
|
187
188
|
expect(result.text).toContain("batch_execute");
|
|
188
189
|
});
|
|
189
190
|
|
|
191
|
+
test("system.agent.seed_scripts points agents at task-start scripts", () => {
|
|
192
|
+
const result = resolveTemplate("system.agent.seed_scripts", {});
|
|
193
|
+
expect(result.text).toContain("Pre-built Seed Scripts");
|
|
194
|
+
expect(result.text).toContain("task-context-gathering");
|
|
195
|
+
expect(result.text).toContain("smart-recall");
|
|
196
|
+
expect(result.text).toContain("script-search");
|
|
197
|
+
expect(result.text).not.toContain("compound-insights");
|
|
198
|
+
});
|
|
199
|
+
|
|
190
200
|
// system.agent.guidelines was removed — its content was redundant with worker/lead templates
|
|
191
201
|
|
|
192
202
|
test("system.agent.system contains package info", () => {
|
|
@@ -240,6 +250,7 @@ describe("Session templates — composite resolution", () => {
|
|
|
240
250
|
|
|
241
251
|
// Contains context_mode
|
|
242
252
|
expect(result.text).toContain("Context Window Management");
|
|
253
|
+
expect(result.text).toContain("Pre-built Seed Scripts");
|
|
243
254
|
|
|
244
255
|
// Guidelines template was removed (redundant with lead/worker templates)
|
|
245
256
|
|
|
@@ -275,6 +286,7 @@ describe("Session templates — composite resolution", () => {
|
|
|
275
286
|
|
|
276
287
|
// Contains context_mode
|
|
277
288
|
expect(result.text).toContain("Context Window Management");
|
|
289
|
+
expect(result.text).toContain("Pre-built Seed Scripts");
|
|
278
290
|
|
|
279
291
|
// Guidelines template was removed (redundant with lead/worker templates)
|
|
280
292
|
|
|
@@ -309,6 +321,8 @@ describe("Session templates — composite resolution", () => {
|
|
|
309
321
|
expect(workerResult.text).toContain("join-swarm");
|
|
310
322
|
expect(leadResult.text).toContain("How You Are Built");
|
|
311
323
|
expect(workerResult.text).toContain("How You Are Built");
|
|
324
|
+
expect(leadResult.text).toContain("Pre-built Seed Scripts");
|
|
325
|
+
expect(workerResult.text).toContain("Pre-built Seed Scripts");
|
|
312
326
|
|
|
313
327
|
// Lead has lead content, not worker
|
|
314
328
|
expect(leadResult.text).toContain("CRITICAL: You are a coordinator");
|
|
@@ -343,6 +357,7 @@ describe("Session templates — getBasePrompt integration", () => {
|
|
|
343
357
|
expect(result).toContain("join-swarm");
|
|
344
358
|
expect(result).toContain("store-progress");
|
|
345
359
|
expect(result).toContain("How You Are Built");
|
|
360
|
+
expect(result).toContain("Pre-built Seed Scripts");
|
|
346
361
|
expect(result).toContain("System packages available");
|
|
347
362
|
|
|
348
363
|
// Conditional sections (services included by default)
|
|
@@ -365,8 +380,22 @@ describe("Session templates — getBasePrompt integration", () => {
|
|
|
365
380
|
expect(result).toContain("your role is: lead");
|
|
366
381
|
expect(result).toContain("integration-test-lead");
|
|
367
382
|
expect(result).toContain("CRITICAL: You are a coordinator");
|
|
383
|
+
expect(result).toContain("Pre-built Seed Scripts");
|
|
368
384
|
|
|
369
385
|
// Should NOT have worker content
|
|
370
386
|
expect(result).not.toContain("task-action");
|
|
371
387
|
});
|
|
388
|
+
|
|
389
|
+
test("getBasePrompt excludes seed_scripts for pi worker", async () => {
|
|
390
|
+
const { getBasePrompt } = await import("../prompts/base-prompt");
|
|
391
|
+
const result = await getBasePrompt({
|
|
392
|
+
role: "worker",
|
|
393
|
+
agentId: "integration-test-pi",
|
|
394
|
+
swarmUrl: "swarm.test.com",
|
|
395
|
+
provider: "pi",
|
|
396
|
+
});
|
|
397
|
+
|
|
398
|
+
expect(result).not.toContain("Pre-built Seed Scripts");
|
|
399
|
+
expect(result).not.toContain("task-context-gathering");
|
|
400
|
+
});
|
|
372
401
|
});
|