@desplega.ai/agent-swarm 1.92.0 → 1.92.2
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 +1 -1
- package/openapi.json +276 -3
- package/package.json +6 -6
- package/plugin/skills/pages/SKILL.md +5 -2
- package/src/be/db.ts +416 -20
- package/src/be/memory/boot-reembed.ts +85 -0
- package/src/be/memory/constants.ts +44 -2
- package/src/be/memory/providers/openai-embedding.ts +15 -5
- package/src/be/memory/providers/sqlite-store.ts +325 -76
- package/src/be/memory/reranker.ts +35 -17
- package/src/be/memory/types.ts +43 -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 +5622 -2543
- 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 +465 -0
- 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 +34 -439
- package/src/be/seed-scripts/catalog/schedule-health.ts +78 -2
- package/src/be/seed-scripts/catalog/task-failure-audit.ts +48 -1
- package/src/be/seed-scripts/index.ts +32 -4
- package/src/be/seed-skills/index.ts +0 -7
- package/src/be/skill-sync.ts +91 -7
- package/src/commands/runner.ts +6 -2
- package/src/heartbeat/templates.ts +20 -16
- package/src/http/index.ts +50 -7
- package/src/http/mcp-user.ts +23 -0
- package/src/http/mcp.ts +58 -0
- package/src/http/memory.ts +62 -0
- package/src/http/pages.ts +1 -1
- package/src/http/script-runs.ts +2 -0
- package/src/http/scripts.ts +39 -2
- package/src/http/skills.ts +225 -0
- package/src/providers/claude-adapter.ts +56 -24
- package/src/script-workflows/workflow-ctx.ts +7 -3
- package/src/scripts-runtime/sdk-allowlist.ts +1 -0
- package/src/scripts-runtime/swarm-sdk.ts +13 -0
- package/src/scripts-runtime/types/stdlib.d.ts +1 -0
- package/src/scripts-runtime/types/swarm-sdk.d.ts +1 -0
- package/src/server.ts +2 -0
- package/src/tasks/worker-follow-up.ts +12 -0
- package/src/tests/claude-adapter-binary.test.ts +135 -81
- package/src/tests/create-page-tool.test.ts +19 -2
- package/src/tests/heartbeat-checklist.test.ts +36 -0
- package/src/tests/mcp-transport-gc.test.ts +58 -0
- package/src/tests/memory-e2e.test.ts +6 -6
- package/src/tests/memory-health-endpoint.test.ts +78 -0
- package/src/tests/memory-rater-e2e.test.ts +4 -5
- package/src/tests/memory-reranker.test.ts +135 -124
- package/src/tests/memory-store.test.ts +221 -1
- package/src/tests/memory.test.ts +13 -12
- package/src/tests/pages-http.test.ts +20 -2
- package/src/tests/pages-storage.test.ts +26 -0
- package/src/tests/scripts-mcp-e2e.test.ts +53 -0
- package/src/tests/seed-scripts.test.ts +328 -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/task-cascade-fail.test.ts +304 -0
- package/src/tools/create-page.ts +2 -2
- package/src/tools/skills/index.ts +1 -0
- package/src/tools/skills/skill-get-file.ts +80 -0
- package/src/tools/tool-config.ts +2 -1
- package/src/types.ts +20 -0
- package/src/utils/internal-ai/complete-structured.ts +2 -2
- 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/profile-corruption-escalation/content.md +44 -85
- package/templates/skills/sprite-cli/content.md +4 -5
- 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/workflows/llm-safe-release-context/config.json +13 -0
- package/templates/workflows/llm-safe-release-context/content.md +69 -0
- package/templates/skills/scheduled-task-resilience/config.json +0 -14
- package/templates/skills/scheduled-task-resilience/content.md +0 -95
|
@@ -1,7 +1,10 @@
|
|
|
1
|
+
import type { AgentMemorySource } from "@/types";
|
|
1
2
|
import {
|
|
2
3
|
ACCESS_BOOST_MAX_MULTIPLIER,
|
|
3
4
|
ACCESS_BOOST_RECENCY_WINDOW_HOURS,
|
|
5
|
+
RECENCY_DECAY_HALF_LIFE,
|
|
4
6
|
RECENCY_DECAY_HALF_LIFE_DAYS,
|
|
7
|
+
SOURCE_QUALITY_MULTIPLIER,
|
|
5
8
|
} from "./constants";
|
|
6
9
|
import type { MemoryCandidate, RerankOptions } from "./types";
|
|
7
10
|
|
|
@@ -9,13 +12,16 @@ const MS_PER_DAY = 1000 * 60 * 60 * 24;
|
|
|
9
12
|
const MS_PER_HOUR = 1000 * 60 * 60;
|
|
10
13
|
|
|
11
14
|
/**
|
|
12
|
-
* Exponential decay based on age
|
|
13
|
-
*
|
|
15
|
+
* Exponential decay based on age and memory source.
|
|
16
|
+
* Source-aware: manual memories have no decay (Infinity half-life),
|
|
17
|
+
* file_index = 180d, task_completion = 14d, session_summary = 7d.
|
|
14
18
|
*/
|
|
15
|
-
export function recencyDecay(createdAt: string, now: Date): number {
|
|
19
|
+
export function recencyDecay(createdAt: string, now: Date, source?: AgentMemorySource): number {
|
|
20
|
+
const halfLife = source ? RECENCY_DECAY_HALF_LIFE[source] : RECENCY_DECAY_HALF_LIFE_DAYS;
|
|
21
|
+
if (!Number.isFinite(halfLife)) return 1.0;
|
|
16
22
|
const ageDays = (now.getTime() - new Date(createdAt).getTime()) / MS_PER_DAY;
|
|
17
23
|
if (ageDays <= 0) return 1.0;
|
|
18
|
-
return 2 ** (-ageDays /
|
|
24
|
+
return 2 ** (-ageDays / halfLife);
|
|
19
25
|
}
|
|
20
26
|
|
|
21
27
|
/**
|
|
@@ -31,6 +37,14 @@ export function accessBoost(accessedAt: string, accessCount: number, now: Date):
|
|
|
31
37
|
return boost;
|
|
32
38
|
}
|
|
33
39
|
|
|
40
|
+
/**
|
|
41
|
+
* Source-quality multiplier. Manual memories get a 1.5× boost,
|
|
42
|
+
* session summaries get 0.5×. Unknown sources default to 1.0.
|
|
43
|
+
*/
|
|
44
|
+
export function sourceQuality(source: AgentMemorySource): number {
|
|
45
|
+
return SOURCE_QUALITY_MULTIPLIER[source] ?? 1.0;
|
|
46
|
+
}
|
|
47
|
+
|
|
34
48
|
/**
|
|
35
49
|
* Beta-Binomial usefulness factor for reranking.
|
|
36
50
|
*
|
|
@@ -56,33 +70,37 @@ export function usefulness(alpha: number, beta: number): number {
|
|
|
56
70
|
}
|
|
57
71
|
|
|
58
72
|
/**
|
|
59
|
-
* Final score combining similarity, recency decay, access boost,
|
|
60
|
-
* Beta-Binomial usefulness.
|
|
61
|
-
* MEMORY_DEMOTION_FLOOR=1.0, the usefulness factor is exactly 1.0 and this
|
|
62
|
-
* computation matches the pre-rater behaviour byte-for-byte.
|
|
63
|
-
*
|
|
64
|
-
* v2: optional edge-aware boost — see thoughts/taras/plans/2026-05-05-memory-rater-v1.5/root.md
|
|
73
|
+
* Final score combining similarity, recency decay, access boost,
|
|
74
|
+
* source quality, and Beta-Binomial usefulness.
|
|
65
75
|
*/
|
|
66
76
|
export function computeScore(candidate: MemoryCandidate, now: Date): number {
|
|
67
77
|
return (
|
|
68
78
|
candidate.similarity *
|
|
69
|
-
recencyDecay(candidate.createdAt, now) *
|
|
79
|
+
recencyDecay(candidate.createdAt, now, candidate.source) *
|
|
70
80
|
accessBoost(candidate.accessedAt, candidate.accessCount, now) *
|
|
81
|
+
sourceQuality(candidate.source) *
|
|
71
82
|
usefulness(candidate.alpha, candidate.beta)
|
|
72
83
|
);
|
|
73
84
|
}
|
|
74
85
|
|
|
75
86
|
/**
|
|
76
|
-
* Rerank candidates by combining similarity with recency
|
|
77
|
-
* Returns the top `limit` candidates sorted by
|
|
87
|
+
* Rerank candidates by combining similarity with recency, source quality,
|
|
88
|
+
* and access signals. Returns the top `limit` candidates sorted by composite
|
|
89
|
+
* score. Preserves raw similarity in `rawSimilarity` and sets `compositeScore`.
|
|
78
90
|
*/
|
|
79
91
|
export function rerank(candidates: MemoryCandidate[], options: RerankOptions): MemoryCandidate[] {
|
|
80
92
|
const { limit, now = new Date() } = options;
|
|
81
93
|
|
|
82
|
-
const scored = candidates.map((candidate) =>
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
94
|
+
const scored = candidates.map((candidate) => {
|
|
95
|
+
const rawSimilarity = candidate.similarity;
|
|
96
|
+
const compositeScore = computeScore(candidate, now);
|
|
97
|
+
return {
|
|
98
|
+
...candidate,
|
|
99
|
+
rawSimilarity,
|
|
100
|
+
compositeScore,
|
|
101
|
+
similarity: compositeScore,
|
|
102
|
+
};
|
|
103
|
+
});
|
|
86
104
|
|
|
87
105
|
scored.sort((a, b) => b.similarity - a.similarity);
|
|
88
106
|
return scored.slice(0, limit);
|
package/src/be/memory/types.ts
CHANGED
|
@@ -22,11 +22,17 @@ export interface MemoryStore {
|
|
|
22
22
|
peek(id: string): AgentMemory | null;
|
|
23
23
|
search(embedding: Float32Array, agentId: string, options: MemorySearchOptions): MemoryCandidate[];
|
|
24
24
|
list(agentId: string, options: MemoryListOptions): AgentMemory[];
|
|
25
|
+
isSourceProtected(source: AgentMemorySource): boolean;
|
|
26
|
+
listForCuration(
|
|
27
|
+
agentId?: string,
|
|
28
|
+
): { id: string; source: string; name: string; createdAt: string }[];
|
|
25
29
|
listForReembedding(options?: { agentId?: string }): { id: string; content: string }[];
|
|
26
30
|
delete(id: string): boolean;
|
|
27
31
|
deleteBySourcePath(sourcePath: string, agentId: string): number;
|
|
32
|
+
purgeExpired(): number;
|
|
28
33
|
updateEmbedding(id: string, embedding: Float32Array, model: string): void;
|
|
29
34
|
getStats(agentId: string): MemoryStats;
|
|
35
|
+
getHealth(): MemoryHealth;
|
|
30
36
|
}
|
|
31
37
|
|
|
32
38
|
// ============================================================================
|
|
@@ -49,6 +55,10 @@ export interface MemoryInput {
|
|
|
49
55
|
|
|
50
56
|
export interface MemoryCandidate extends AgentMemory {
|
|
51
57
|
similarity: number;
|
|
58
|
+
/** Raw cosine similarity before reranking (preserved for diagnostics). */
|
|
59
|
+
rawSimilarity?: number;
|
|
60
|
+
/** Final composite score after reranking (recency × source × usefulness × access). */
|
|
61
|
+
compositeScore?: number;
|
|
52
62
|
accessCount: number;
|
|
53
63
|
expiresAt: string | null;
|
|
54
64
|
embeddingModel: string | null;
|
|
@@ -81,6 +91,39 @@ export interface MemoryStats {
|
|
|
81
91
|
expired: number;
|
|
82
92
|
}
|
|
83
93
|
|
|
94
|
+
export interface MemoryHealth {
|
|
95
|
+
sqliteVec: {
|
|
96
|
+
extensionLoaded: boolean;
|
|
97
|
+
tableExists: boolean;
|
|
98
|
+
initialized: boolean;
|
|
99
|
+
vectorDimensions: number;
|
|
100
|
+
distanceMetric: "cosine";
|
|
101
|
+
schema: string | null;
|
|
102
|
+
lastPopulate: MemoryVecPopulateStats | null;
|
|
103
|
+
};
|
|
104
|
+
counts: {
|
|
105
|
+
total: number;
|
|
106
|
+
withEmbedding: number;
|
|
107
|
+
validEmbedding: number;
|
|
108
|
+
invalidEmbedding: number;
|
|
109
|
+
searchable: number;
|
|
110
|
+
memoryVec: number;
|
|
111
|
+
missingFromVec: number;
|
|
112
|
+
extraInVec: number;
|
|
113
|
+
};
|
|
114
|
+
retrievalMode: "vec" | "fallback";
|
|
115
|
+
reasons: string[];
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
export interface MemoryVecPopulateStats {
|
|
119
|
+
attempted: number;
|
|
120
|
+
inserted: number;
|
|
121
|
+
skippedInvalidDimensions: number;
|
|
122
|
+
failed: number;
|
|
123
|
+
beforeCount: number;
|
|
124
|
+
afterCount: number;
|
|
125
|
+
}
|
|
126
|
+
|
|
84
127
|
export interface RerankOptions {
|
|
85
128
|
limit: number;
|
|
86
129
|
now?: Date;
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
-- Script Workflows: record real per-step wall-clock duration (ms) measured in the
|
|
2
|
+
-- subprocess, so the dashboard can render a truthful waterfall. Nullable — existing
|
|
3
|
+
-- journal rows stay NULL and are treated as "unmeasured".
|
|
4
|
+
|
|
5
|
+
ALTER TABLE script_run_journal ADD COLUMN durationMs INTEGER;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
-- Discriminate durable script-workflow runs from inline/one-off `/api/scripts/run`
|
|
2
|
+
-- executions so both can be persisted in the same script_runs table.
|
|
3
|
+
-- Existing rows are all durable workflow runs, hence the 'workflow' default.
|
|
4
|
+
|
|
5
|
+
ALTER TABLE script_runs
|
|
6
|
+
ADD COLUMN kind TEXT NOT NULL DEFAULT 'workflow'
|
|
7
|
+
CHECK(kind IN ('workflow', 'inline'));
|
|
8
|
+
|
|
9
|
+
CREATE INDEX IF NOT EXISTS idx_script_runs_kind ON script_runs(kind);
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
-- Flip the SQL-level default for new page rows from public to authed.
|
|
2
|
+
-- Existing row values are preserved; this only changes behavior when a caller
|
|
3
|
+
-- omits authMode at the database layer.
|
|
4
|
+
|
|
5
|
+
CREATE TABLE pages_new (
|
|
6
|
+
id TEXT PRIMARY KEY DEFAULT (lower(hex(randomblob(16)))),
|
|
7
|
+
agentId TEXT NOT NULL,
|
|
8
|
+
slug TEXT NOT NULL,
|
|
9
|
+
title TEXT NOT NULL,
|
|
10
|
+
description TEXT,
|
|
11
|
+
contentType TEXT NOT NULL CHECK (contentType IN ('text/html','application/json')),
|
|
12
|
+
authMode TEXT NOT NULL DEFAULT 'authed' CHECK (authMode IN ('public','authed','password')),
|
|
13
|
+
passwordHash TEXT,
|
|
14
|
+
body TEXT NOT NULL,
|
|
15
|
+
needsCredentials TEXT,
|
|
16
|
+
createdAt TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
17
|
+
updatedAt TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
18
|
+
view_count INTEGER NOT NULL DEFAULT 0,
|
|
19
|
+
created_by TEXT REFERENCES users(id),
|
|
20
|
+
updated_by TEXT REFERENCES users(id),
|
|
21
|
+
UNIQUE (agentId, slug)
|
|
22
|
+
);
|
|
23
|
+
|
|
24
|
+
INSERT INTO pages_new (
|
|
25
|
+
id,
|
|
26
|
+
agentId,
|
|
27
|
+
slug,
|
|
28
|
+
title,
|
|
29
|
+
description,
|
|
30
|
+
contentType,
|
|
31
|
+
authMode,
|
|
32
|
+
passwordHash,
|
|
33
|
+
body,
|
|
34
|
+
needsCredentials,
|
|
35
|
+
createdAt,
|
|
36
|
+
updatedAt,
|
|
37
|
+
view_count,
|
|
38
|
+
created_by,
|
|
39
|
+
updated_by
|
|
40
|
+
)
|
|
41
|
+
SELECT
|
|
42
|
+
id,
|
|
43
|
+
agentId,
|
|
44
|
+
slug,
|
|
45
|
+
title,
|
|
46
|
+
description,
|
|
47
|
+
contentType,
|
|
48
|
+
authMode,
|
|
49
|
+
passwordHash,
|
|
50
|
+
body,
|
|
51
|
+
needsCredentials,
|
|
52
|
+
createdAt,
|
|
53
|
+
updatedAt,
|
|
54
|
+
view_count,
|
|
55
|
+
created_by,
|
|
56
|
+
updated_by
|
|
57
|
+
FROM pages;
|
|
58
|
+
|
|
59
|
+
DROP TABLE pages;
|
|
60
|
+
ALTER TABLE pages_new RENAME TO pages;
|
|
61
|
+
|
|
62
|
+
CREATE INDEX IF NOT EXISTS idx_pages_agentId ON pages(agentId);
|
|
63
|
+
CREATE INDEX IF NOT EXISTS idx_pages_updatedAt ON pages(updatedAt DESC);
|
|
64
|
+
CREATE INDEX IF NOT EXISTS idx_pages_created_by ON pages(created_by) WHERE created_by IS NOT NULL;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
-- Migration 087: skill_files table for complex (multi-file) skills.
|
|
2
|
+
-- Additive only: simple skills have zero rows and existing behavior is unchanged.
|
|
3
|
+
|
|
4
|
+
CREATE TABLE IF NOT EXISTS skill_files (
|
|
5
|
+
id TEXT PRIMARY KEY,
|
|
6
|
+
skillId TEXT NOT NULL REFERENCES skills(id) ON DELETE CASCADE,
|
|
7
|
+
path TEXT NOT NULL,
|
|
8
|
+
content TEXT NOT NULL,
|
|
9
|
+
mimeType TEXT NOT NULL DEFAULT 'text/plain',
|
|
10
|
+
isBinary INTEGER NOT NULL DEFAULT 0,
|
|
11
|
+
size INTEGER,
|
|
12
|
+
createdAt TEXT NOT NULL,
|
|
13
|
+
lastUpdatedAt TEXT NOT NULL,
|
|
14
|
+
created_by TEXT REFERENCES users(id),
|
|
15
|
+
updated_by TEXT REFERENCES users(id),
|
|
16
|
+
UNIQUE(skillId, path)
|
|
17
|
+
);
|
|
18
|
+
|
|
19
|
+
CREATE INDEX IF NOT EXISTS idx_skill_files_skill ON skill_files(skillId);
|