@stackbilt/aegis-core 0.6.4 → 0.7.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.
- package/cli/aegis.mjs +356 -0
- package/package.json +9 -1
- package/schema.sql +4 -0
- package/src/adapters/voice/cloudflare-agent.ts +0 -0
- package/src/auth.ts +19 -7
- package/src/bluesky.ts +0 -0
- package/src/claude-tools/content.ts +0 -0
- package/src/claude-tools/email.ts +0 -0
- package/src/claude.ts +133 -268
- package/src/codebeast.ts +0 -0
- package/src/composite.ts +49 -79
- package/src/content/column.ts +0 -0
- package/src/content/hero-image.ts +0 -0
- package/src/content/index.ts +0 -0
- package/src/content/journal.ts +0 -0
- package/src/content/roundtable.ts +0 -0
- package/src/contracts/agenda-item.contract.ts +0 -0
- package/src/contracts/cc-task.contract.ts +0 -0
- package/src/contracts/goal.contract.ts +0 -0
- package/src/contracts/memory-entry.contract.ts +0 -0
- package/src/core.ts +5 -0
- package/src/dashboard.ts +0 -0
- package/src/decision-docs.ts +0 -0
- package/src/dispatch.ts +0 -0
- package/src/durable-objects/chat-session-auth.ts +20 -0
- package/src/durable-objects/chat-session.ts +251 -0
- package/src/edge-env.ts +0 -0
- package/src/exports.ts +0 -0
- package/src/github-projects.ts +0 -0
- package/src/groq.ts +61 -113
- package/src/index.ts +4 -0
- package/src/kernel/argus-actions.ts +0 -0
- package/src/kernel/argus-correlation.ts +0 -0
- package/src/kernel/board.ts +0 -0
- package/src/kernel/classify-memory-topic.ts +0 -0
- package/src/kernel/disambiguation.ts +55 -0
- package/src/kernel/dispatch.ts +59 -44
- package/src/kernel/dynamic-tools.ts +30 -52
- package/src/kernel/executor-port.ts +0 -0
- package/src/kernel/executor-router.ts +0 -0
- package/src/kernel/executors/claude.ts +1 -0
- package/src/kernel/executors/direct.ts +14 -0
- package/src/kernel/executors/workers-ai.ts +5 -0
- package/src/kernel/grounding/fabrication-detector.ts +0 -0
- package/src/kernel/grounding/fanout.ts +0 -0
- package/src/kernel/grounding/semantic-sanhedrin.ts +0 -0
- package/src/kernel/grounding/verify.ts +0 -0
- package/src/kernel/grounding-layer.ts +0 -0
- package/src/kernel/insight-cache.ts +0 -0
- package/src/kernel/memory/episodic.ts +3 -1
- package/src/kernel/memory/insights.ts +0 -0
- package/src/kernel/memory-guardrails.ts +0 -0
- package/src/kernel/memory-service.ts +0 -0
- package/src/kernel/patterns.ts +0 -0
- package/src/kernel/port.ts +0 -0
- package/src/kernel/provider-factory.ts +0 -0
- package/src/kernel/resilience.ts +0 -0
- package/src/kernel/router.ts +33 -11
- package/src/kernel/scheduled/agent-dispatch.ts +0 -0
- package/src/kernel/scheduled/argus-analytics.ts +0 -0
- package/src/kernel/scheduled/argus-heartbeat.ts +0 -0
- package/src/kernel/scheduled/argus-notify.ts +0 -0
- package/src/kernel/scheduled/board-sync.ts +0 -0
- package/src/kernel/scheduled/ci-watcher.ts +0 -0
- package/src/kernel/scheduled/content-drip.ts +0 -0
- package/src/kernel/scheduled/content.ts +0 -0
- package/src/kernel/scheduled/conversation-facts.ts +9 -7
- package/src/kernel/scheduled/cost-report.ts +0 -0
- package/src/kernel/scheduled/dev-activity.ts +0 -0
- package/src/kernel/scheduled/digest.ts +30 -3
- package/src/kernel/scheduled/dreaming/agenda-triage.ts +0 -0
- package/src/kernel/scheduled/dreaming/facts.ts +0 -0
- package/src/kernel/scheduled/dreaming/index.ts +0 -0
- package/src/kernel/scheduled/dreaming/llm.ts +9 -5
- package/src/kernel/scheduled/dreaming/pattern-synthesis.ts +0 -0
- package/src/kernel/scheduled/dreaming/persona.ts +0 -0
- package/src/kernel/scheduled/dreaming/symbolic.ts +0 -0
- package/src/kernel/scheduled/dreaming/task-proposals.ts +0 -0
- package/src/kernel/scheduled/entropy.ts +0 -0
- package/src/kernel/scheduled/feed-watcher.ts +0 -0
- package/src/kernel/scheduled/inbox-processor.ts +0 -0
- package/src/kernel/scheduled/issue-proposer.ts +0 -0
- package/src/kernel/scheduled/issue-watcher.ts +0 -0
- package/src/kernel/scheduled/pr-automerge.ts +0 -0
- package/src/kernel/scheduled/product-health.ts +0 -0
- package/src/kernel/scheduled/self-improvement.ts +0 -0
- package/src/kernel/scheduled/social-engage.ts +12 -8
- package/src/kernel/scheduled/task-audit.ts +0 -0
- package/src/kernel/types.ts +6 -0
- package/src/landing.ts +0 -0
- package/src/lib/audit-chain/chain.ts +0 -0
- package/src/lib/audit-chain/types.ts +0 -0
- package/src/lib/observability/errors.ts +0 -0
- package/src/operator/config.ts +0 -0
- package/src/operator/persona.ts +0 -0
- package/src/operator/prompt-builder.ts +3 -0
- package/src/pulse.ts +0 -0
- package/src/routes/bluesky.ts +0 -0
- package/src/routes/chat-ws.ts +17 -0
- package/src/routes/codebeast.ts +0 -0
- package/src/routes/content.ts +0 -0
- package/src/routes/dynamic-tools.ts +0 -0
- package/src/routes/observability.ts +0 -0
- package/src/routes/operator-logs.ts +0 -0
- package/src/routes/pages.ts +5 -1
- package/src/schema-enums.ts +0 -0
- package/src/task-intelligence.ts +0 -0
- package/src/types.ts +6 -0
- package/src/ui.ts +594 -2
- package/src/version.ts +3 -3
- package/src/wiki/client.ts +0 -0
- package/src/wiki/types.ts +0 -0
|
@@ -53,7 +53,11 @@ export async function executeGptOss(
|
|
|
53
53
|
githubToken: env.githubToken,
|
|
54
54
|
githubRepo: env.githubRepo,
|
|
55
55
|
braveApiKey: env.braveApiKey,
|
|
56
|
+
roundtableDb: env.roundtableDb,
|
|
57
|
+
memoryBinding: env.memoryBinding,
|
|
58
|
+
resendApiKeys: { resendApiKey: env.resendApiKey, resendApiKeyPersonal: env.resendApiKeyPersonal },
|
|
56
59
|
userQuery: intent.raw,
|
|
60
|
+
edgeEnv: env,
|
|
57
61
|
};
|
|
58
62
|
const { systemPrompt, tools: anthropicTools } = await buildContext(pseudoConfig);
|
|
59
63
|
// toOpenAiTools output matches factory Tool shape exactly
|
|
@@ -105,6 +109,7 @@ export async function executeGptOss(
|
|
|
105
109
|
env.githubToken, env.githubRepo, env.braveApiKey,
|
|
106
110
|
undefined, undefined, env.memoryBinding,
|
|
107
111
|
{ resendApiKey: env.resendApiKey, resendApiKeyPersonal: env.resendApiKeyPersonal },
|
|
112
|
+
env,
|
|
108
113
|
);
|
|
109
114
|
|
|
110
115
|
if (inProcess !== null) {
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
@@ -16,13 +16,15 @@ export function sanitizeEpisodicOutcome(raw: string | null | undefined): Episodi
|
|
|
16
16
|
|
|
17
17
|
export async function recordEpisode(db: D1Database, entry: Omit<EpisodicEntry, 'id' | 'created_at'>): Promise<void> {
|
|
18
18
|
const safeOutcome = sanitizeEpisodicOutcome(entry.outcome);
|
|
19
|
+
const groundingGap = entry.grounding_gap ? 1 : 0;
|
|
19
20
|
await db.prepare(
|
|
20
|
-
'INSERT INTO episodic_memory (intent_class, channel, summary, outcome, cost, latency_ms, near_miss, classifier_confidence, reclassified, thread_id, executor) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)'
|
|
21
|
+
'INSERT INTO episodic_memory (intent_class, channel, summary, outcome, cost, latency_ms, near_miss, classifier_confidence, reclassified, thread_id, executor, grounding_gap) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)'
|
|
21
22
|
).bind(
|
|
22
23
|
entry.intent_class, entry.channel, entry.summary, safeOutcome,
|
|
23
24
|
entry.cost, entry.latency_ms, entry.near_miss ?? null,
|
|
24
25
|
entry.classifier_confidence ?? null, entry.reclassified ? 1 : 0,
|
|
25
26
|
entry.thread_id ?? null, entry.executor ?? null,
|
|
27
|
+
groundingGap,
|
|
26
28
|
).run();
|
|
27
29
|
}
|
|
28
30
|
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
package/src/kernel/patterns.ts
CHANGED
|
File without changes
|
package/src/kernel/port.ts
CHANGED
|
File without changes
|
|
File without changes
|
package/src/kernel/resilience.ts
CHANGED
|
File without changes
|
package/src/kernel/router.ts
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
|
+
import { createLLMProviderFactory } from '@stackbilt/llm-providers';
|
|
1
2
|
import { getProcedure, findNearMiss, procedureKey, PROCEDURE_MIN_SUCCESSES, PROCEDURE_MIN_SUCCESS_RATE, getConversationHistory } from './memory/index.js';
|
|
2
3
|
import { askGroq, askGroqWithLogprobs } from '../groq.js';
|
|
3
4
|
import type { KernelIntent, ExecutionPlan, Executor } from './types.js';
|
|
4
5
|
import { buildClassifySystem, getTaskPatterns } from '../operator/prompt-builder.js';
|
|
5
6
|
import { domainPreFilter } from './domain.js';
|
|
7
|
+
import { detectDisambiguationNeed } from './disambiguation.js';
|
|
6
8
|
|
|
7
9
|
// ─── Confidence Thresholds ──────────────────────────────────
|
|
8
10
|
const CONFIDENCE_TRUST = 0.80; // ≥ 0.80 → use classification as-is
|
|
@@ -72,21 +74,21 @@ async function classifyWithWorkersAI(
|
|
|
72
74
|
systemPrompt: string,
|
|
73
75
|
userPrompt: string,
|
|
74
76
|
): Promise<string> {
|
|
75
|
-
const result = await
|
|
77
|
+
const result = await createLLMProviderFactory({
|
|
78
|
+
cloudflare: { ai },
|
|
79
|
+
fallbackRules: [],
|
|
80
|
+
enableCircuitBreaker: true,
|
|
81
|
+
enableRetries: true,
|
|
82
|
+
}).generateResponse({
|
|
83
|
+
model: '@cf/meta/llama-3.1-8b-instruct',
|
|
84
|
+
systemPrompt,
|
|
76
85
|
messages: [
|
|
77
|
-
{ role: 'system', content: systemPrompt },
|
|
78
86
|
{ role: 'user', content: userPrompt },
|
|
79
87
|
],
|
|
80
|
-
|
|
88
|
+
maxTokens: 200,
|
|
81
89
|
temperature: 0.1,
|
|
82
|
-
})
|
|
83
|
-
|
|
84
|
-
if (typeof raw === 'string') return raw;
|
|
85
|
-
if (raw == null) return '';
|
|
86
|
-
// Workers AI sometimes returns structured responses (objects with tool_calls,
|
|
87
|
-
// arrays of segments, etc.). Coerce to string so downstream .trim()/JSON.parse
|
|
88
|
-
// callers don't crash on non-string payloads.
|
|
89
|
-
return typeof raw === 'object' ? JSON.stringify(raw) : String(raw);
|
|
90
|
+
});
|
|
91
|
+
return result.message ?? '';
|
|
90
92
|
}
|
|
91
93
|
|
|
92
94
|
|
|
@@ -94,6 +96,7 @@ async function classifyWithWorkersAI(
|
|
|
94
96
|
// Fallback routes — used for degraded procedure replanning and when JSON classification fails
|
|
95
97
|
const DEFAULT_ROUTES: Record<string, Executor> = {
|
|
96
98
|
heartbeat: 'direct',
|
|
99
|
+
request_clarification: 'direct',
|
|
97
100
|
bizops_read: 'gpt_oss',
|
|
98
101
|
bizops_mutate: 'gpt_oss',
|
|
99
102
|
general_knowledge: 'gpt_oss',
|
|
@@ -241,6 +244,25 @@ export async function route(
|
|
|
241
244
|
};
|
|
242
245
|
}
|
|
243
246
|
|
|
247
|
+
// ─── Phase 0.25: Disambiguation firewall ──────────────────
|
|
248
|
+
const disambiguation = detectDisambiguationNeed(intent.raw);
|
|
249
|
+
if (disambiguation) {
|
|
250
|
+
intent.classified = 'request_clarification';
|
|
251
|
+
intent.complexity = 0;
|
|
252
|
+
intent.needsTools = false;
|
|
253
|
+
intent.confidence = 1;
|
|
254
|
+
intent.disambiguation = disambiguation;
|
|
255
|
+
return {
|
|
256
|
+
plan: {
|
|
257
|
+
executor: 'direct',
|
|
258
|
+
reasoning: `Disambiguation firewall halted undefined data concept "${disambiguation.concept}"`,
|
|
259
|
+
costCeiling: 'free',
|
|
260
|
+
},
|
|
261
|
+
nearMiss: `disambiguation:${disambiguation.concept}`,
|
|
262
|
+
reclassified: false,
|
|
263
|
+
};
|
|
264
|
+
}
|
|
265
|
+
|
|
244
266
|
// ─── Phase 0.5: Domain pre-filter (observe only) ──────────
|
|
245
267
|
const domainTag = domainPreFilter(intent.raw);
|
|
246
268
|
intent.domain = domainTag.domain;
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
// Workers AI llama-3.1-8b (free tier) as fallback.
|
|
6
6
|
|
|
7
7
|
import { type EdgeEnv } from '../dispatch.js';
|
|
8
|
+
import { buildLLMProviderFactory } from '../provider-factory.js';
|
|
8
9
|
import { recordMemory as recordMemoryAdapter } from '../memory-adapter.js';
|
|
9
10
|
import { askGroq } from '../../groq.js';
|
|
10
11
|
import { pushFactsToMindSpring, type FactEntry } from './mindspring-notebook.js';
|
|
@@ -97,13 +98,14 @@ async function askAi(
|
|
|
97
98
|
}
|
|
98
99
|
// Workers AI fallback — llama-3.1-8b is on the genuine free tier
|
|
99
100
|
if (env.ai) {
|
|
100
|
-
const result = await env.
|
|
101
|
-
'@cf/meta/llama-3.1-8b-instruct'
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
101
|
+
const result = await buildLLMProviderFactory(env).generateResponse({
|
|
102
|
+
model: '@cf/meta/llama-3.1-8b-instruct',
|
|
103
|
+
systemPrompt: system,
|
|
104
|
+
messages: [{ role: 'user', content: user }],
|
|
105
|
+
maxTokens: 1024,
|
|
106
|
+
temperature: 0.2,
|
|
107
|
+
});
|
|
108
|
+
return result.message ?? '';
|
|
107
109
|
}
|
|
108
110
|
throw new Error('[conv-facts] No LLM provider available (groqApiKey and env.ai both missing)');
|
|
109
111
|
}
|
|
File without changes
|
|
File without changes
|
|
@@ -17,9 +17,11 @@ import {
|
|
|
17
17
|
// Operator log runs at 08:00 UTC to generate content before this fires.
|
|
18
18
|
|
|
19
19
|
export async function runDailyDigest(env: EdgeEnv): Promise<void> {
|
|
20
|
-
// Time gate: fire at 09:00 UTC (4:00 AM CT)
|
|
20
|
+
// Time gate: fire at or after 09:00 UTC (4:00 AM CT).
|
|
21
|
+
// The 22h cooldown below prevents double-sends, while allowing same-day
|
|
22
|
+
// catch-up after a transient 09:00 send failure.
|
|
21
23
|
const now = new Date();
|
|
22
|
-
if (now.getUTCHours()
|
|
24
|
+
if (now.getUTCHours() < 9) return;
|
|
23
25
|
|
|
24
26
|
// Cooldown: 22 hours since last digest
|
|
25
27
|
const lastDigest = await env.db.prepare(
|
|
@@ -253,7 +255,7 @@ export async function runDailyDigest(env: EdgeEnv): Promise<void> {
|
|
|
253
255
|
}
|
|
254
256
|
|
|
255
257
|
// ── Send digest email ──
|
|
256
|
-
await
|
|
258
|
+
await sendDailyDigestWithRetry(
|
|
257
259
|
{ resendApiKey: env.resendApiKey, resendApiKeyPersonal: env.resendApiKeyPersonal },
|
|
258
260
|
sections,
|
|
259
261
|
env.notifyEmail,
|
|
@@ -272,6 +274,31 @@ export async function runDailyDigest(env: EdgeEnv): Promise<void> {
|
|
|
272
274
|
console.log(`[digest] Daily digest sent: ${sections.completedTasks.length} completed, ${sections.failedTasks.length} failed, ${sections.proposedTasks.length} proposed, ${sections.healthChecks.length} health checks`);
|
|
273
275
|
}
|
|
274
276
|
|
|
277
|
+
export async function sendDailyDigestWithRetry(
|
|
278
|
+
apiKeys: { resendApiKey: string; resendApiKeyPersonal: string },
|
|
279
|
+
sections: DigestSections,
|
|
280
|
+
notifyEmail?: string,
|
|
281
|
+
delaysMs: number[] = [1_000, 5_000],
|
|
282
|
+
): Promise<void> {
|
|
283
|
+
let attempt = 0;
|
|
284
|
+
for (;;) {
|
|
285
|
+
try {
|
|
286
|
+
await sendDailyDigest(apiKeys, sections, notifyEmail);
|
|
287
|
+
return;
|
|
288
|
+
} catch (err) {
|
|
289
|
+
if (attempt >= delaysMs.length) throw err;
|
|
290
|
+
const delayMs = delaysMs[attempt];
|
|
291
|
+
attempt += 1;
|
|
292
|
+
console.warn(
|
|
293
|
+
`[digest] Daily digest send failed; retrying in ${delayMs}ms ` +
|
|
294
|
+
`(attempt ${attempt + 1}/${delaysMs.length + 1}):`,
|
|
295
|
+
err instanceof Error ? err.message : String(err),
|
|
296
|
+
);
|
|
297
|
+
await new Promise(resolve => setTimeout(resolve, delayMs));
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
|
|
275
302
|
// ─── Health Check Deduplication (#309) ──────────────────────
|
|
276
303
|
// Each DigestHealthCheck has { severity, checks: [{name, status, detail}], timestamp }.
|
|
277
304
|
// Multiple heartbeat runs can produce entries with the same check name (e.g. stale_agenda_151).
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
// Shared LLM helper — Groq first (free, 70B quality), Workers AI 70B fallback
|
|
2
2
|
|
|
3
3
|
import type { EdgeEnv } from '../../dispatch.js';
|
|
4
|
+
import { buildLLMProviderFactory } from '../../provider-factory.js';
|
|
4
5
|
import { askGroq } from '../../../groq.js';
|
|
5
6
|
|
|
6
7
|
export async function askWorkersAiOrGroq(
|
|
@@ -20,11 +21,14 @@ export async function askWorkersAiOrGroq(
|
|
|
20
21
|
}
|
|
21
22
|
// Workers AI fallback — only fires if Groq is unavailable or throws
|
|
22
23
|
if (env.ai) {
|
|
23
|
-
const result = await env.
|
|
24
|
-
'@cf/meta/llama-3.3-70b-instruct-fp8-fast'
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
24
|
+
const result = await buildLLMProviderFactory(env).generateResponse({
|
|
25
|
+
model: '@cf/meta/llama-3.3-70b-instruct-fp8-fast',
|
|
26
|
+
systemPrompt: system,
|
|
27
|
+
messages: [{ role: 'user', content: user }],
|
|
28
|
+
maxTokens: 2048,
|
|
29
|
+
temperature: 0.2,
|
|
30
|
+
});
|
|
31
|
+
return result.message ?? '';
|
|
28
32
|
}
|
|
29
33
|
throw new Error('[dreaming] No LLM provider available (groqApiKey and env.ai both missing)');
|
|
30
34
|
}
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
// Runs every 6 hours. Likes replies, follows back real accounts,
|
|
3
3
|
// replies to substantive comments with Workers AI.
|
|
4
4
|
|
|
5
|
+
import { createLLMProviderFactory } from '@stackbilt/llm-providers';
|
|
5
6
|
import { type EdgeEnv } from '../dispatch.js';
|
|
6
7
|
import {
|
|
7
8
|
getNotifications,
|
|
@@ -153,21 +154,24 @@ async function generateReply(
|
|
|
153
154
|
incomingText: string,
|
|
154
155
|
authorHandle: string,
|
|
155
156
|
): Promise<string | null> {
|
|
156
|
-
const result = await
|
|
157
|
+
const result = await createLLMProviderFactory({
|
|
158
|
+
cloudflare: { ai },
|
|
159
|
+
fallbackRules: [],
|
|
160
|
+
enableCircuitBreaker: true,
|
|
161
|
+
enableRetries: true,
|
|
162
|
+
}).generateResponse({
|
|
163
|
+
model: '@cf/meta/llama-3.1-8b-instruct',
|
|
164
|
+
systemPrompt: `You are the operator's social media voice. Direct, builder-energy, anti-corporate. No emoji spam. No "excited to announce." Keep replies under 200 chars. Be genuine and conversational. If you can't add value, return SKIP.`,
|
|
157
165
|
messages: [
|
|
158
|
-
{
|
|
159
|
-
role: 'system',
|
|
160
|
-
content: `You are the operator's social media voice. Direct, builder-energy, anti-corporate. No emoji spam. No "excited to announce." Keep replies under 200 chars. Be genuine and conversational. If you can't add value, return SKIP.`,
|
|
161
|
-
},
|
|
162
166
|
{
|
|
163
167
|
role: 'user',
|
|
164
168
|
content: `@${authorHandle} replied to our Bluesky post: "${incomingText}"\n\nWrite a brief, genuine reply. Return ONLY the reply text, or SKIP if there's nothing meaningful to add.`,
|
|
165
169
|
},
|
|
166
170
|
],
|
|
167
|
-
|
|
168
|
-
})
|
|
171
|
+
maxTokens: 100,
|
|
172
|
+
});
|
|
169
173
|
|
|
170
|
-
const reply = result.
|
|
174
|
+
const reply = result.message?.trim();
|
|
171
175
|
if (!reply || reply === 'SKIP' || reply.length < 5) return null;
|
|
172
176
|
|
|
173
177
|
// Safety: truncate to 300 chars (Bluesky limit)
|
|
File without changes
|
package/src/kernel/types.ts
CHANGED
|
@@ -18,9 +18,14 @@ export interface KernelIntent {
|
|
|
18
18
|
confidence?: number;
|
|
19
19
|
domain?: string;
|
|
20
20
|
domainConfidence?: number;
|
|
21
|
+
disambiguation?: {
|
|
22
|
+
concept: string;
|
|
23
|
+
question: string;
|
|
24
|
+
};
|
|
21
25
|
timestamp: number;
|
|
22
26
|
costCeiling: 'free' | 'cheap' | 'expensive';
|
|
23
27
|
classifierSource?: 'classify-cast' | 'workers-ai' | 'groq';
|
|
28
|
+
forcedExecutor?: Executor;
|
|
24
29
|
}
|
|
25
30
|
|
|
26
31
|
// ─── Memory Types ────────────────────────────────────────────
|
|
@@ -40,6 +45,7 @@ export interface EpisodicEntry {
|
|
|
40
45
|
executor?: string | null;
|
|
41
46
|
complexity_tier?: string | null;
|
|
42
47
|
executor_config?: string | null;
|
|
48
|
+
grounding_gap?: boolean | number;
|
|
43
49
|
created_at?: string;
|
|
44
50
|
}
|
|
45
51
|
|
package/src/landing.ts
CHANGED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
package/src/operator/config.ts
CHANGED
|
File without changes
|
package/src/operator/persona.ts
CHANGED
|
File without changes
|
|
@@ -81,6 +81,7 @@ If conversation context is provided, use it to understand what the user is reall
|
|
|
81
81
|
|
|
82
82
|
Categories:
|
|
83
83
|
- heartbeat: Explicitly asking to run a health check, status check, or heartbeat — ONLY when the user directly requests a system diagnostic. NOT for pasting technical data, reporting findings, discussing system state, or asking what needs attention
|
|
84
|
+
- request_clarification: The user asks for an internal data or metric concept whose definition is not strictly specified. Halt and ask which definition to use instead of guessing
|
|
84
85
|
${bizopsCategories}
|
|
85
86
|
- general_knowledge: General factual questions, conceptual explanations, abstract advice with NO connection to the operator's businesses, projects, or operations
|
|
86
87
|
- memory_recall: Questions about what the agent remembers, past conversations
|
|
@@ -100,6 +101,7 @@ Tiebreaker: "roundtable", "generate a roundtable", "show roundtable drafts", "pu
|
|
|
100
101
|
Tiebreaker: When the user discusses actions to take on their business infrastructure, projects, migrations, deployments, or asks for recommendations tied to business operations → prefer bizops_mutate over general_knowledge. "general_knowledge" is for questions with NO business/operational context (e.g., "what is OAuth?", "explain quantum computing").
|
|
101
102
|
Tiebreaker: When a message reports a bug, error, broken feature, or asks for help using a Stackbilt product → always support_triage, never bizops_read. "bizops_read" is for the operator querying internal business state, not for end-user support requests.
|
|
102
103
|
Tiebreaker: If the user asks "what do you think?" or "what are your thoughts?" in a conversation about business decisions, projects, or operations → bizops_mutate (they want actionable advice + BizOps actions, not a generic essay).
|
|
104
|
+
Disambiguation firewall: If the user asks for data or metrics and the definition is not strictly defined in context, DO NOT GUESS. Use request_clarification. Example: "what is churn?" is ambiguous; ask whether they mean churn by seat count, account count, revenue, MRR, or another defined basis.
|
|
103
105
|
|
|
104
106
|
Examples:
|
|
105
107
|
- "hi" → {"pattern":"greeting","complexity":0,"needs_tools":false,"confidence":0.99}
|
|
@@ -167,6 +169,7 @@ export function getTaskPatterns(): readonly string[] {
|
|
|
167
169
|
|
|
168
170
|
const patterns: string[] = [
|
|
169
171
|
'heartbeat',
|
|
172
|
+
'request_clarification',
|
|
170
173
|
'general_knowledge',
|
|
171
174
|
'memory_recall',
|
|
172
175
|
'greeting',
|
package/src/pulse.ts
CHANGED
|
File without changes
|
package/src/routes/bluesky.ts
CHANGED
|
File without changes
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { Hono } from 'hono';
|
|
2
|
+
import type { Env } from '../types.js';
|
|
3
|
+
|
|
4
|
+
export const chatWs = new Hono<{ Bindings: Env }>();
|
|
5
|
+
|
|
6
|
+
chatWs.get('/chat/ws', async (c) => {
|
|
7
|
+
if (c.req.header('Upgrade')?.toLowerCase() !== 'websocket') {
|
|
8
|
+
return c.text('Expected WebSocket upgrade', 426);
|
|
9
|
+
}
|
|
10
|
+
if (!c.env.CHAT_SESSION) {
|
|
11
|
+
return c.text('CHAT_SESSION Durable Object binding is not configured', 503);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
const id = c.env.CHAT_SESSION.idFromName('operator');
|
|
15
|
+
const stub = c.env.CHAT_SESSION.get(id);
|
|
16
|
+
return stub.fetch(c.req.raw);
|
|
17
|
+
});
|
package/src/routes/codebeast.ts
CHANGED
|
File without changes
|
package/src/routes/content.ts
CHANGED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
package/src/routes/pages.ts
CHANGED
|
@@ -15,6 +15,10 @@ const pages = new Hono<{ Bindings: Env }>();
|
|
|
15
15
|
// ─── Landing ────────────────────────────────────────────────
|
|
16
16
|
|
|
17
17
|
pages.get('/', (c) => {
|
|
18
|
+
return c.html(chatPage());
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
pages.get('/about', (c) => {
|
|
18
22
|
return c.html(landingPage());
|
|
19
23
|
});
|
|
20
24
|
|
|
@@ -44,7 +48,7 @@ pages.get('/manifest.json', (c) => {
|
|
|
44
48
|
return c.json({
|
|
45
49
|
name: 'AEGIS',
|
|
46
50
|
short_name: 'AEGIS',
|
|
47
|
-
start_url: '/
|
|
51
|
+
start_url: '/',
|
|
48
52
|
display: 'standalone',
|
|
49
53
|
background_color: '#0a0a0f',
|
|
50
54
|
theme_color: '#8b8bff',
|
package/src/schema-enums.ts
CHANGED
|
File without changes
|
package/src/task-intelligence.ts
CHANGED
|
File without changes
|
package/src/types.ts
CHANGED
|
@@ -4,6 +4,7 @@ export interface Env {
|
|
|
4
4
|
DB: D1Database;
|
|
5
5
|
AI: Ai;
|
|
6
6
|
AEGIS_TOKEN: string;
|
|
7
|
+
CHAT_SESSION?: DurableObjectNamespace;
|
|
7
8
|
|
|
8
9
|
// OAuth 2.1 (injected by OAuthProvider wrapper at runtime)
|
|
9
10
|
OAUTH_PROVIDER: OAuthHelpers;
|
|
@@ -190,5 +191,10 @@ export interface MessageMetadata {
|
|
|
190
191
|
confidence?: number;
|
|
191
192
|
reclassified?: boolean;
|
|
192
193
|
probeResult?: string;
|
|
194
|
+
grounded?: boolean;
|
|
195
|
+
sources?: string[];
|
|
196
|
+
unknowns?: string[];
|
|
197
|
+
searched?: string[];
|
|
198
|
+
unverifiedClaims?: string[];
|
|
193
199
|
error?: boolean;
|
|
194
200
|
}
|