@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.
Files changed (90) hide show
  1. package/README.md +1 -1
  2. package/openapi.json +276 -3
  3. package/package.json +6 -6
  4. package/plugin/skills/pages/SKILL.md +5 -2
  5. package/src/be/db.ts +416 -20
  6. package/src/be/memory/boot-reembed.ts +85 -0
  7. package/src/be/memory/constants.ts +44 -2
  8. package/src/be/memory/providers/openai-embedding.ts +15 -5
  9. package/src/be/memory/providers/sqlite-store.ts +325 -76
  10. package/src/be/memory/reranker.ts +35 -17
  11. package/src/be/memory/types.ts +43 -0
  12. package/src/be/migrations/084_script_run_journal_duration.sql +5 -0
  13. package/src/be/migrations/085_script_runs_kind.sql +9 -0
  14. package/src/be/migrations/086_pages_default_authed.sql +64 -0
  15. package/src/be/migrations/087_skill_files.sql +19 -0
  16. package/src/be/modelsdev-cache.json +5622 -2543
  17. package/src/be/seed-scripts/catalog/boot-triage.ts +221 -0
  18. package/src/be/seed-scripts/catalog/catalog-report.ts +457 -0
  19. package/src/be/seed-scripts/catalog/compound-insights.ts +465 -0
  20. package/src/be/seed-scripts/catalog/gh-pr-snapshot.ts +1 -1
  21. package/src/be/seed-scripts/catalog/memory-eval.ts +1059 -0
  22. package/src/be/seed-scripts/catalog/ops-catalog-audit.ts +34 -439
  23. package/src/be/seed-scripts/catalog/schedule-health.ts +78 -2
  24. package/src/be/seed-scripts/catalog/task-failure-audit.ts +48 -1
  25. package/src/be/seed-scripts/index.ts +32 -4
  26. package/src/be/seed-skills/index.ts +0 -7
  27. package/src/be/skill-sync.ts +91 -7
  28. package/src/commands/runner.ts +6 -2
  29. package/src/heartbeat/templates.ts +20 -16
  30. package/src/http/index.ts +50 -7
  31. package/src/http/mcp-user.ts +23 -0
  32. package/src/http/mcp.ts +58 -0
  33. package/src/http/memory.ts +62 -0
  34. package/src/http/pages.ts +1 -1
  35. package/src/http/script-runs.ts +2 -0
  36. package/src/http/scripts.ts +39 -2
  37. package/src/http/skills.ts +225 -0
  38. package/src/providers/claude-adapter.ts +56 -24
  39. package/src/script-workflows/workflow-ctx.ts +7 -3
  40. package/src/scripts-runtime/sdk-allowlist.ts +1 -0
  41. package/src/scripts-runtime/swarm-sdk.ts +13 -0
  42. package/src/scripts-runtime/types/stdlib.d.ts +1 -0
  43. package/src/scripts-runtime/types/swarm-sdk.d.ts +1 -0
  44. package/src/server.ts +2 -0
  45. package/src/tasks/worker-follow-up.ts +12 -0
  46. package/src/tests/claude-adapter-binary.test.ts +135 -81
  47. package/src/tests/create-page-tool.test.ts +19 -2
  48. package/src/tests/heartbeat-checklist.test.ts +36 -0
  49. package/src/tests/mcp-transport-gc.test.ts +58 -0
  50. package/src/tests/memory-e2e.test.ts +6 -6
  51. package/src/tests/memory-health-endpoint.test.ts +78 -0
  52. package/src/tests/memory-rater-e2e.test.ts +4 -5
  53. package/src/tests/memory-reranker.test.ts +135 -124
  54. package/src/tests/memory-store.test.ts +221 -1
  55. package/src/tests/memory.test.ts +13 -12
  56. package/src/tests/pages-http.test.ts +20 -2
  57. package/src/tests/pages-storage.test.ts +26 -0
  58. package/src/tests/scripts-mcp-e2e.test.ts +53 -0
  59. package/src/tests/seed-scripts.test.ts +328 -3
  60. package/src/tests/skill-files-http.test.ts +171 -0
  61. package/src/tests/skill-files.test.ts +162 -0
  62. package/src/tests/skill-get-file-tool.test.ts +110 -0
  63. package/src/tests/skill-sync.test.ts +125 -6
  64. package/src/tests/task-cascade-fail.test.ts +304 -0
  65. package/src/tools/create-page.ts +2 -2
  66. package/src/tools/skills/index.ts +1 -0
  67. package/src/tools/skills/skill-get-file.ts +80 -0
  68. package/src/tools/tool-config.ts +2 -1
  69. package/src/types.ts +20 -0
  70. package/src/utils/internal-ai/complete-structured.ts +2 -2
  71. package/templates/schedules/daily-blocker-digest/content.md +68 -54
  72. package/templates/schedules/daily-compounding-reflection/content.md +4 -4
  73. package/templates/schedules/daily-hn-briefing/content.md +5 -5
  74. package/templates/schedules/daily-workflow-health-audit/content.md +6 -6
  75. package/templates/schedules/gtm-weekly-review/content.md +9 -9
  76. package/templates/schedules/weekly-dependabot-triage/content.md +24 -20
  77. package/templates/skills/agentmail-sending/content.md +6 -7
  78. package/templates/skills/desloppify/content.md +8 -9
  79. package/templates/skills/jira-interaction/content.md +25 -33
  80. package/templates/skills/kapso-whatsapp/content.md +29 -30
  81. package/templates/skills/linear-interaction/content.md +8 -9
  82. package/templates/skills/profile-corruption-escalation/content.md +44 -85
  83. package/templates/skills/sprite-cli/content.md +4 -5
  84. package/templates/skills/turso-interaction/content.md +14 -17
  85. package/templates/skills/workflow-iterate/content.md +38 -391
  86. package/templates/skills/x-api-interactions/content.md +4 -6
  87. package/templates/workflows/llm-safe-release-context/config.json +13 -0
  88. package/templates/workflows/llm-safe-release-context/content.md +69 -0
  89. package/templates/skills/scheduled-task-resilience/config.json +0 -14
  90. 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. A memory at exactly HALF_LIFE_DAYS old
13
- * gets multiplied by 0.5. Fresh memories get ~1.0.
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 / RECENCY_DECAY_HALF_LIFE_DAYS);
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, and
60
- * Beta-Binomial usefulness. With default Beta(1,1) and default
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 and access signals.
77
- * Returns the top `limit` candidates sorted by final score.
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
- ...candidate,
84
- similarity: computeScore(candidate, now),
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);
@@ -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);