@stackbilt/aegis-core 0.1.0

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 (148) hide show
  1. package/package.json +96 -0
  2. package/schema.sql +586 -0
  3. package/src/adapters/voice/cloudflare-agent.ts +34 -0
  4. package/src/auth.ts +124 -0
  5. package/src/bluesky.ts +464 -0
  6. package/src/claude-tools/content.ts +188 -0
  7. package/src/claude-tools/email.ts +69 -0
  8. package/src/claude-tools/github.ts +440 -0
  9. package/src/claude-tools/goals.ts +116 -0
  10. package/src/claude-tools/index.ts +353 -0
  11. package/src/claude-tools/web.ts +59 -0
  12. package/src/claude.ts +406 -0
  13. package/src/codebeast.ts +200 -0
  14. package/src/composite.ts +715 -0
  15. package/src/content/column.ts +80 -0
  16. package/src/content/hero-image.ts +47 -0
  17. package/src/content/index.ts +27 -0
  18. package/src/content/journal.ts +91 -0
  19. package/src/content/roundtable.ts +163 -0
  20. package/src/core.ts +309 -0
  21. package/src/dashboard.ts +620 -0
  22. package/src/decision-docs.ts +284 -0
  23. package/src/dispatch.ts +13 -0
  24. package/src/edge-env.ts +58 -0
  25. package/src/email.ts +850 -0
  26. package/src/exports.ts +156 -0
  27. package/src/github-projects.ts +312 -0
  28. package/src/github.ts +670 -0
  29. package/src/groq.ts +247 -0
  30. package/src/health-page.ts +578 -0
  31. package/src/index.ts +89 -0
  32. package/src/kernel/argus-actions.ts +397 -0
  33. package/src/kernel/argus-correlation.ts +639 -0
  34. package/src/kernel/board.ts +91 -0
  35. package/src/kernel/briefing.ts +177 -0
  36. package/src/kernel/classify-memory-topic.ts +166 -0
  37. package/src/kernel/cognition.ts +377 -0
  38. package/src/kernel/court-cards.ts +163 -0
  39. package/src/kernel/dispatch.ts +587 -0
  40. package/src/kernel/domain.ts +50 -0
  41. package/src/kernel/dynamic-tools.ts +322 -0
  42. package/src/kernel/executor-port.ts +45 -0
  43. package/src/kernel/executors/claude.ts +73 -0
  44. package/src/kernel/executors/direct.ts +237 -0
  45. package/src/kernel/executors/groq.ts +18 -0
  46. package/src/kernel/executors/index.ts +87 -0
  47. package/src/kernel/executors/tarotscript.ts +104 -0
  48. package/src/kernel/executors/workers-ai.ts +54 -0
  49. package/src/kernel/insight-cache.ts +76 -0
  50. package/src/kernel/memory/agenda.ts +200 -0
  51. package/src/kernel/memory/blocks.ts +188 -0
  52. package/src/kernel/memory/consolidation.ts +194 -0
  53. package/src/kernel/memory/episodic.ts +241 -0
  54. package/src/kernel/memory/goals.ts +156 -0
  55. package/src/kernel/memory/graph.ts +290 -0
  56. package/src/kernel/memory/index.ts +11 -0
  57. package/src/kernel/memory/insights.ts +316 -0
  58. package/src/kernel/memory/procedural.ts +467 -0
  59. package/src/kernel/memory/pruning.ts +67 -0
  60. package/src/kernel/memory/recall.ts +367 -0
  61. package/src/kernel/memory/semantic.ts +315 -0
  62. package/src/kernel/memory/synthesis.ts +161 -0
  63. package/src/kernel/memory-adapter.ts +369 -0
  64. package/src/kernel/memory-guardrails.ts +76 -0
  65. package/src/kernel/port.ts +23 -0
  66. package/src/kernel/resilience.ts +322 -0
  67. package/src/kernel/router.ts +471 -0
  68. package/src/kernel/scheduled/agent-dispatch.ts +252 -0
  69. package/src/kernel/scheduled/argus-analytics.ts +247 -0
  70. package/src/kernel/scheduled/argus-heartbeat.ts +320 -0
  71. package/src/kernel/scheduled/argus-notify.ts +348 -0
  72. package/src/kernel/scheduled/board-sync.ts +110 -0
  73. package/src/kernel/scheduled/ci-watcher.ts +125 -0
  74. package/src/kernel/scheduled/cognitive-metrics.ts +377 -0
  75. package/src/kernel/scheduled/consolidation.ts +229 -0
  76. package/src/kernel/scheduled/content-drip.ts +47 -0
  77. package/src/kernel/scheduled/content.ts +6 -0
  78. package/src/kernel/scheduled/conversation-facts.ts +204 -0
  79. package/src/kernel/scheduled/cost-report.ts +84 -0
  80. package/src/kernel/scheduled/curiosity.ts +219 -0
  81. package/src/kernel/scheduled/dev-activity.ts +44 -0
  82. package/src/kernel/scheduled/digest.ts +317 -0
  83. package/src/kernel/scheduled/dreaming/agenda-triage.ts +115 -0
  84. package/src/kernel/scheduled/dreaming/facts.ts +239 -0
  85. package/src/kernel/scheduled/dreaming/index.ts +8 -0
  86. package/src/kernel/scheduled/dreaming/llm.ts +33 -0
  87. package/src/kernel/scheduled/dreaming/pattern-synthesis.ts +124 -0
  88. package/src/kernel/scheduled/dreaming/persona.ts +75 -0
  89. package/src/kernel/scheduled/dreaming/symbolic.ts +31 -0
  90. package/src/kernel/scheduled/dreaming/task-proposals.ts +80 -0
  91. package/src/kernel/scheduled/dreaming.ts +66 -0
  92. package/src/kernel/scheduled/entropy.ts +149 -0
  93. package/src/kernel/scheduled/escalation.ts +192 -0
  94. package/src/kernel/scheduled/feed-watcher.ts +206 -0
  95. package/src/kernel/scheduled/goals.ts +214 -0
  96. package/src/kernel/scheduled/governance.ts +41 -0
  97. package/src/kernel/scheduled/heartbeat.ts +220 -0
  98. package/src/kernel/scheduled/inbox-processor.ts +174 -0
  99. package/src/kernel/scheduled/index.ts +245 -0
  100. package/src/kernel/scheduled/issue-proposer.ts +478 -0
  101. package/src/kernel/scheduled/issue-watcher.ts +128 -0
  102. package/src/kernel/scheduled/pr-automerge.ts +213 -0
  103. package/src/kernel/scheduled/product-health.ts +107 -0
  104. package/src/kernel/scheduled/reflection.ts +373 -0
  105. package/src/kernel/scheduled/self-improvement.ts +114 -0
  106. package/src/kernel/scheduled/social-engage.ts +175 -0
  107. package/src/kernel/scheduled/task-audit.ts +60 -0
  108. package/src/kernel/symbolic.ts +156 -0
  109. package/src/kernel/types.ts +145 -0
  110. package/src/landing.ts +1190 -0
  111. package/src/lib/audit-chain/chain.ts +28 -0
  112. package/src/lib/audit-chain/types.ts +12 -0
  113. package/src/lib/observability/errors.ts +55 -0
  114. package/src/markdown.ts +164 -0
  115. package/src/mcp/handlers.ts +647 -0
  116. package/src/mcp/server.ts +184 -0
  117. package/src/mcp/tools.ts +316 -0
  118. package/src/mcp-client.ts +275 -0
  119. package/src/mcp-server.ts +2 -0
  120. package/src/operator/config.example.ts +60 -0
  121. package/src/operator/config.ts +60 -0
  122. package/src/operator/index.ts +46 -0
  123. package/src/operator/persona.example.ts +34 -0
  124. package/src/operator/persona.ts +34 -0
  125. package/src/operator/prompt-builder.ts +190 -0
  126. package/src/operator/types.ts +43 -0
  127. package/src/pulse.ts +1179 -0
  128. package/src/routes/bluesky.ts +116 -0
  129. package/src/routes/cc-tasks.ts +328 -0
  130. package/src/routes/codebeast.ts +1 -0
  131. package/src/routes/content.ts +194 -0
  132. package/src/routes/conversations.ts +25 -0
  133. package/src/routes/dynamic-tools.ts +111 -0
  134. package/src/routes/feedback.ts +192 -0
  135. package/src/routes/health.ts +147 -0
  136. package/src/routes/messages.ts +228 -0
  137. package/src/routes/observability.ts +82 -0
  138. package/src/routes/operator-logs.ts +42 -0
  139. package/src/routes/pages.ts +96 -0
  140. package/src/routes/sessions.ts +54 -0
  141. package/src/sanitize.ts +73 -0
  142. package/src/schema-enums.ts +155 -0
  143. package/src/search.ts +112 -0
  144. package/src/task-intelligence.ts +497 -0
  145. package/src/types.ts +194 -0
  146. package/src/ui.ts +5 -0
  147. package/src/version.ts +3 -0
  148. package/src/workers-ai-chat.ts +333 -0
@@ -0,0 +1,188 @@
1
+ // Content pipeline in-process tool definitions + handlers
2
+ // Roundtable articles + Dispatch newsletter generation
3
+
4
+ import { runRoundtableGeneration, queueRoundtableTopic } from '../content/index.js';
5
+ import { runDispatchGeneration } from '../dispatch.js';
6
+
7
+ // ─── Tool definitions ────────────────────────────────────────
8
+
9
+ const LIST_ROUNDTABLE_DRAFTS_TOOL = {
10
+ name: 'list_roundtable_drafts',
11
+ description: 'List unpublished roundtable article drafts.',
12
+ input_schema: { type: 'object' as const, properties: {}, required: [] },
13
+ };
14
+
15
+ const PUBLISH_ROUNDTABLE_TOOL = {
16
+ name: 'publish_roundtable',
17
+ description: 'Publish a roundtable article draft by slug.',
18
+ input_schema: {
19
+ type: 'object' as const,
20
+ properties: {
21
+ slug: { type: 'string', description: 'The draft slug to publish' },
22
+ },
23
+ required: ['slug'],
24
+ },
25
+ };
26
+
27
+ const LIST_ROUNDTABLE_TOPICS_TOOL = {
28
+ name: 'list_roundtable_topics',
29
+ description: 'List queued roundtable topics.',
30
+ input_schema: {
31
+ type: 'object' as const,
32
+ properties: {
33
+ status: { type: 'string', description: 'Filter by status (default: queued)' },
34
+ },
35
+ required: [],
36
+ },
37
+ };
38
+
39
+ const GENERATE_ROUNDTABLE_TOOL = {
40
+ name: 'generate_roundtable',
41
+ description: 'Generate a new roundtable article from the topic queue.',
42
+ input_schema: { type: 'object' as const, properties: {}, required: [] },
43
+ };
44
+
45
+ const QUEUE_ROUNDTABLE_TOPIC_TOOL = {
46
+ name: 'queue_roundtable_topic',
47
+ description: 'Add a topic to the roundtable generation queue.',
48
+ input_schema: {
49
+ type: 'object' as const,
50
+ properties: {
51
+ topic: { type: 'string', description: 'Topic title' },
52
+ context: { type: 'string', description: 'Why this topic is relevant' },
53
+ cta_product: { type: 'string', description: 'Product to feature in the CTA' },
54
+ },
55
+ required: ['topic'],
56
+ },
57
+ };
58
+
59
+ const LIST_DISPATCH_DRAFTS_TOOL = {
60
+ name: 'list_dispatch_drafts',
61
+ description: 'List unpublished dispatch newsletter drafts.',
62
+ input_schema: { type: 'object' as const, properties: {}, required: [] },
63
+ };
64
+
65
+ const PUBLISH_DISPATCH_TOOL = {
66
+ name: 'publish_dispatch',
67
+ description: 'Publish a dispatch newsletter draft by slug.',
68
+ input_schema: {
69
+ type: 'object' as const,
70
+ properties: {
71
+ slug: { type: 'string', description: 'The dispatch slug to publish' },
72
+ },
73
+ required: ['slug'],
74
+ },
75
+ };
76
+
77
+ const GENERATE_DISPATCH_TOOL = {
78
+ name: 'generate_dispatch',
79
+ description: 'Generate a new dispatch newsletter.',
80
+ input_schema: { type: 'object' as const, properties: {}, required: [] },
81
+ };
82
+
83
+ export const ROUNDTABLE_TOOLS = [
84
+ LIST_ROUNDTABLE_DRAFTS_TOOL,
85
+ PUBLISH_ROUNDTABLE_TOOL,
86
+ LIST_ROUNDTABLE_TOPICS_TOOL,
87
+ GENERATE_ROUNDTABLE_TOOL,
88
+ QUEUE_ROUNDTABLE_TOPIC_TOOL,
89
+ ];
90
+
91
+ export const DISPATCH_TOOLS = [
92
+ LIST_DISPATCH_DRAFTS_TOOL,
93
+ PUBLISH_DISPATCH_TOOL,
94
+ GENERATE_DISPATCH_TOOL,
95
+ ];
96
+
97
+ // ─── Handler ─────────────────────────────────────────────────
98
+
99
+ export async function handleContentTool(
100
+ name: string,
101
+ input: Record<string, unknown>,
102
+ roundtableDb: D1Database,
103
+ aegisDb: D1Database,
104
+ anthropicConfig?: { apiKey: string; model: string; baseUrl: string },
105
+ githubToken?: string,
106
+ githubRepo?: string,
107
+ ): Promise<string | null> {
108
+ // ── Roundtable tools ──
109
+ if (name === 'list_roundtable_drafts') {
110
+ const { results } = await roundtableDb.prepare(
111
+ "SELECT slug, title, created_at FROM roundtables WHERE status = 'draft' ORDER BY created_at DESC LIMIT 20"
112
+ ).all<{ slug: string; title: string; created_at: string }>();
113
+ if (results.length === 0) return 'No draft roundtables found.';
114
+ return results.map(r =>
115
+ `**${r.title}** (${r.slug}) — ${r.created_at.slice(0, 10)} [preview]`
116
+ ).join('\n');
117
+ }
118
+
119
+ if (name === 'publish_roundtable') {
120
+ const slug = input.slug as string;
121
+ const result = await roundtableDb.prepare(
122
+ "UPDATE roundtables SET status = 'published', published_at = datetime('now') WHERE slug = ? AND status = 'draft'"
123
+ ).bind(slug).run();
124
+ if ((result.meta.changes ?? 0) === 0) return `No draft roundtable found with slug "${slug}".`;
125
+ return `Published roundtable "${slug}".`;
126
+ }
127
+
128
+ if (name === 'list_roundtable_topics') {
129
+ const status = (input.status as string | undefined) ?? 'queued';
130
+ const { results } = await roundtableDb.prepare(
131
+ "SELECT topic, cta_product, status, source FROM topic_queue WHERE status = ? ORDER BY created_at DESC LIMIT 20"
132
+ ).bind(status).all<{ topic: string; cta_product: string; status: string; source: string }>();
133
+ if (results.length === 0) return `No topics found with status "${status}".`;
134
+ return results.map(t =>
135
+ `- **${t.topic}** → ${t.cta_product} [${t.status}] (${t.source})`
136
+ ).join('\n');
137
+ }
138
+
139
+ if (name === 'generate_roundtable') {
140
+ if (!anthropicConfig) return 'Error: Anthropic config not available.';
141
+ const result = await runRoundtableGeneration(
142
+ roundtableDb, aegisDb,
143
+ anthropicConfig.apiKey, anthropicConfig.model, anthropicConfig.baseUrl,
144
+ );
145
+ return `Generated roundtable: "${result.title}" (${result.slug}) — saved as draft. Cost: $${result.cost.toFixed(4)}`;
146
+ }
147
+
148
+ if (name === 'queue_roundtable_topic') {
149
+ const topic = input.topic as string | undefined;
150
+ if (!topic) return 'Error: topic is required.';
151
+ const context = (input.context as string | undefined) ?? '';
152
+ const ctaProduct = (input.cta_product as string | undefined) ?? '';
153
+ await queueRoundtableTopic(roundtableDb, topic, context, ctaProduct, 'aegis_auto');
154
+ return `Queued topic: "${topic}" → ${ctaProduct || 'no product'} (source: aegis_auto)`;
155
+ }
156
+
157
+ // ── Dispatch tools ──
158
+ if (name === 'list_dispatch_drafts') {
159
+ const { results } = await roundtableDb.prepare(
160
+ "SELECT slug, title, paper_title, created_at FROM dispatches WHERE status = 'draft' ORDER BY created_at DESC LIMIT 20"
161
+ ).all<{ slug: string; title: string; paper_title: string; created_at: string }>();
162
+ if (results.length === 0) return 'No draft dispatches found.';
163
+ return results.map(d =>
164
+ `**${d.title}** (${d.slug}) — paper: ${d.paper_title} — ${d.created_at.slice(0, 10)}`
165
+ ).join('\n');
166
+ }
167
+
168
+ if (name === 'publish_dispatch') {
169
+ const slug = input.slug as string;
170
+ const result = await roundtableDb.prepare(
171
+ "UPDATE dispatches SET status = 'published', published_at = datetime('now') WHERE slug = ? AND status = 'draft'"
172
+ ).bind(slug).run();
173
+ if ((result.meta.changes ?? 0) === 0) return `No draft dispatch found with slug "${slug}".`;
174
+ return `Published dispatch "${slug}".`;
175
+ }
176
+
177
+ if (name === 'generate_dispatch') {
178
+ if (!anthropicConfig) return 'Error: Anthropic config not available.';
179
+ const result = await runDispatchGeneration(
180
+ roundtableDb, aegisDb,
181
+ anthropicConfig.apiKey, anthropicConfig.model, anthropicConfig.baseUrl,
182
+ githubToken, githubRepo,
183
+ );
184
+ return `Generated dispatch: "${result.title}" (${result.slug}) — saved as draft. Cost: $${result.cost.toFixed(4)}`;
185
+ }
186
+
187
+ return null;
188
+ }
@@ -0,0 +1,69 @@
1
+ // Email in-process tool definitions + handlers
2
+ // Sends email via Resend API
3
+
4
+ import { resolveEmailProfile } from '../email.js';
5
+
6
+ // ─── Tool definition ─────────────────────────────────────────
7
+
8
+ export const SEND_EMAIL_TOOL = {
9
+ name: 'send_email',
10
+ description: 'Send an email via Resend API',
11
+ input_schema: {
12
+ type: 'object' as const,
13
+ properties: {
14
+ to: { type: 'string', description: 'Recipient email' },
15
+ subject: { type: 'string', description: 'Email subject' },
16
+ body: { type: 'string', description: 'Email body (plain text or HTML)' },
17
+ profile: { type: 'string', description: 'Email profile to use (default: primary)' },
18
+ },
19
+ required: ['to', 'subject', 'body'],
20
+ },
21
+ };
22
+
23
+ // ─── Handler ─────────────────────────────────────────────────
24
+
25
+ export async function handleEmailTool(
26
+ name: string,
27
+ input: Record<string, unknown>,
28
+ resendApiKeys: { resendApiKey: string; resendApiKeyPersonal: string },
29
+ ): Promise<string | null> {
30
+ if (name !== 'send_email') return null;
31
+
32
+ const to = input.to as string;
33
+ const subject = input.subject as string;
34
+ const body = input.body as string;
35
+ const profile = (input.profile as string | undefined) ?? 'primary';
36
+
37
+ const sender = resolveEmailProfile(profile, resendApiKeys);
38
+
39
+ // If body looks like HTML (starts with <), use it as-is; otherwise wrap in simple HTML
40
+ const html = body.trimStart().startsWith('<')
41
+ ? body
42
+ : body.split('\n').map(line => `<p style="margin:0 0 8px;color:#ccc">${line}</p>`).join('');
43
+
44
+ try {
45
+ const res = await fetch('https://api.resend.com/emails', {
46
+ method: 'POST',
47
+ headers: {
48
+ 'Content-Type': 'application/json',
49
+ 'Authorization': `Bearer ${sender.apiKey}`,
50
+ },
51
+ body: JSON.stringify({
52
+ from: sender.from,
53
+ to: [to],
54
+ subject,
55
+ html,
56
+ }),
57
+ });
58
+
59
+ if (!res.ok) {
60
+ const errText = await res.text();
61
+ return `Email send failed (${res.status}): ${errText}`;
62
+ }
63
+
64
+ const data = await res.json() as { id?: string };
65
+ return `Email sent to ${to} — subject: "${subject}" (id: ${data.id ?? 'unknown'})`;
66
+ } catch (err) {
67
+ return `Email send failed: ${err instanceof Error ? err.message : String(err)}`;
68
+ }
69
+ }