tryassay 0.2.0 → 0.6.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/dist/cli.js +41 -2
- package/dist/cli.js.map +1 -1
- package/dist/commands/runtime.d.ts +20 -0
- package/dist/commands/runtime.js +192 -6
- package/dist/commands/runtime.js.map +1 -1
- package/dist/runtime/agent-loop.d.ts +16 -1
- package/dist/runtime/agent-loop.js +197 -32
- package/dist/runtime/agent-loop.js.map +1 -1
- package/dist/runtime/agents/code-agent.d.ts +11 -0
- package/dist/runtime/agents/code-agent.js +90 -0
- package/dist/runtime/agents/code-agent.js.map +1 -0
- package/dist/runtime/agents/review-agent.d.ts +11 -0
- package/dist/runtime/agents/review-agent.js +96 -0
- package/dist/runtime/agents/review-agent.js.map +1 -0
- package/dist/runtime/audit-log.d.ts +35 -0
- package/dist/runtime/audit-log.js +115 -0
- package/dist/runtime/audit-log.js.map +1 -0
- package/dist/runtime/composition-verifier.d.ts +22 -0
- package/dist/runtime/composition-verifier.js +265 -0
- package/dist/runtime/composition-verifier.js.map +1 -0
- package/dist/runtime/confidence-calibrator.d.ts +10 -0
- package/dist/runtime/confidence-calibrator.js +95 -0
- package/dist/runtime/confidence-calibrator.js.map +1 -0
- package/dist/runtime/config-loader.d.ts +41 -0
- package/dist/runtime/config-loader.js +116 -0
- package/dist/runtime/config-loader.js.map +1 -0
- package/dist/runtime/control-server.d.ts +25 -0
- package/dist/runtime/control-server.js +83 -0
- package/dist/runtime/control-server.js.map +1 -0
- package/dist/runtime/enriched-prompt-builder.d.ts +25 -0
- package/dist/runtime/enriched-prompt-builder.js +173 -0
- package/dist/runtime/enriched-prompt-builder.js.map +1 -0
- package/dist/runtime/gap-detector.d.ts +6 -0
- package/dist/runtime/gap-detector.js +111 -0
- package/dist/runtime/gap-detector.js.map +1 -0
- package/dist/runtime/logger.d.ts +20 -0
- package/dist/runtime/logger.js +73 -0
- package/dist/runtime/logger.js.map +1 -0
- package/dist/runtime/message-bus.d.ts +57 -0
- package/dist/runtime/message-bus.js +115 -0
- package/dist/runtime/message-bus.js.map +1 -0
- package/dist/runtime/observer.d.ts +5 -1
- package/dist/runtime/observer.js +61 -14
- package/dist/runtime/observer.js.map +1 -1
- package/dist/runtime/pattern-extractor.d.ts +20 -0
- package/dist/runtime/pattern-extractor.js +257 -0
- package/dist/runtime/pattern-extractor.js.map +1 -0
- package/dist/runtime/planner.d.ts +2 -2
- package/dist/runtime/planner.js +10 -7
- package/dist/runtime/planner.js.map +1 -1
- package/dist/runtime/reasoner.d.ts +2 -2
- package/dist/runtime/reasoner.js +22 -7
- package/dist/runtime/reasoner.js.map +1 -1
- package/dist/runtime/reflector.d.ts +7 -1
- package/dist/runtime/reflector.js.map +1 -1
- package/dist/runtime/shadow-runner.d.ts +14 -0
- package/dist/runtime/shadow-runner.js +190 -0
- package/dist/runtime/shadow-runner.js.map +1 -0
- package/dist/runtime/specialized-agent.d.ts +67 -0
- package/dist/runtime/specialized-agent.js +86 -0
- package/dist/runtime/specialized-agent.js.map +1 -0
- package/dist/runtime/strategy-library.d.ts +11 -0
- package/dist/runtime/strategy-library.js +142 -0
- package/dist/runtime/strategy-library.js.map +1 -0
- package/dist/runtime/supabase-experience-store.d.ts +19 -0
- package/dist/runtime/supabase-experience-store.js +215 -0
- package/dist/runtime/supabase-experience-store.js.map +1 -0
- package/dist/runtime/trust-manager.d.ts +33 -0
- package/dist/runtime/trust-manager.js +110 -0
- package/dist/runtime/trust-manager.js.map +1 -0
- package/dist/runtime/two-agent-loop.d.ts +35 -0
- package/dist/runtime/two-agent-loop.js +208 -0
- package/dist/runtime/two-agent-loop.js.map +1 -0
- package/dist/runtime/types.d.ts +291 -1
- package/package.json +1 -1
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
// ============================================================
|
|
2
|
+
// Assay Verified Agent Runtime — Gap Detector
|
|
3
|
+
// Identifies verification hotspots where formal rules could
|
|
4
|
+
// replace LLM verification, and proposes rule candidates.
|
|
5
|
+
// ============================================================
|
|
6
|
+
import { randomUUID } from 'node:crypto';
|
|
7
|
+
import { getClient, MODEL } from '../lib/anthropic.js';
|
|
8
|
+
export class GapDetector {
|
|
9
|
+
async analyze(hotspots) {
|
|
10
|
+
const candidates = [];
|
|
11
|
+
const eligibleHotspots = hotspots.filter(h => h.candidateForFormalRule &&
|
|
12
|
+
h.failRate > 0.2 &&
|
|
13
|
+
h.formalCoverage < 0.1 &&
|
|
14
|
+
h.totalClaims >= 10);
|
|
15
|
+
for (const hotspot of eligibleHotspots) {
|
|
16
|
+
try {
|
|
17
|
+
const candidate = await this.proposeRule(hotspot);
|
|
18
|
+
if (candidate && this.validateTestCases(candidate)) {
|
|
19
|
+
candidates.push(candidate);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
catch {
|
|
23
|
+
// Skip failed proposals
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
return candidates;
|
|
27
|
+
}
|
|
28
|
+
async proposeRule(hotspot) {
|
|
29
|
+
const client = getClient();
|
|
30
|
+
const response = await client.messages.create({
|
|
31
|
+
model: MODEL,
|
|
32
|
+
max_tokens: 2048,
|
|
33
|
+
system: `You design formal verification rules for code. Rules must be regex or AST-based patterns that can be checked deterministically without an LLM.
|
|
34
|
+
|
|
35
|
+
Respond with ONLY JSON, no markdown fences.`,
|
|
36
|
+
messages: [{
|
|
37
|
+
role: 'user',
|
|
38
|
+
content: `This verification hotspot has a ${(hotspot.failRate * 100).toFixed(0)}% failure rate but only ${(hotspot.formalCoverage * 100).toFixed(0)}% formal verification coverage:
|
|
39
|
+
|
|
40
|
+
Category: ${hotspot.claimCategory}
|
|
41
|
+
Total claims: ${hotspot.totalClaims}
|
|
42
|
+
Failed claims: ${hotspot.failedClaims}
|
|
43
|
+
Top failure reasons: ${hotspot.topFailureReasons.join('; ')}
|
|
44
|
+
|
|
45
|
+
Propose a formal rule (regex pattern) that could catch the most common failure pattern in this category.
|
|
46
|
+
|
|
47
|
+
Respond:
|
|
48
|
+
{
|
|
49
|
+
"description": "what the rule checks",
|
|
50
|
+
"rationale": "why this should be formal, not LLM",
|
|
51
|
+
"substrate": "regex",
|
|
52
|
+
"pattern": "the regex pattern",
|
|
53
|
+
"language": "typescript",
|
|
54
|
+
"testCases": [
|
|
55
|
+
{ "input": "code that should FAIL", "language": "typescript", "expectedVerdict": "FAIL", "description": "what this tests" },
|
|
56
|
+
{ "input": "code that should PASS", "language": "typescript", "expectedVerdict": "PASS", "description": "what this tests" }
|
|
57
|
+
],
|
|
58
|
+
"estimatedFormalCoverage": 0.3
|
|
59
|
+
}`,
|
|
60
|
+
}],
|
|
61
|
+
});
|
|
62
|
+
const text = response.content[0].type === 'text' ? response.content[0].text : '';
|
|
63
|
+
try {
|
|
64
|
+
let cleaned = text.trim();
|
|
65
|
+
if (cleaned.startsWith('```')) {
|
|
66
|
+
cleaned = cleaned.replace(/^```(?:json)?\s*/, '').replace(/\s*```$/, '');
|
|
67
|
+
}
|
|
68
|
+
const parsed = JSON.parse(cleaned);
|
|
69
|
+
return {
|
|
70
|
+
id: randomUUID(),
|
|
71
|
+
claimCategory: hotspot.claimCategory,
|
|
72
|
+
description: parsed.description,
|
|
73
|
+
rationale: parsed.rationale,
|
|
74
|
+
substrate: parsed.substrate === 'ast' ? 'ast' : 'regex',
|
|
75
|
+
pattern: parsed.pattern,
|
|
76
|
+
language: parsed.language ?? 'typescript',
|
|
77
|
+
testCases: Array.isArray(parsed.testCases) ? parsed.testCases : [],
|
|
78
|
+
sourceHotspot: hotspot.claimCategory,
|
|
79
|
+
supportingExperiences: [],
|
|
80
|
+
estimatedFormalCoverage: parsed.estimatedFormalCoverage ?? 0,
|
|
81
|
+
status: 'proposed',
|
|
82
|
+
proposedAt: new Date().toISOString(),
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
catch {
|
|
86
|
+
return null;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
validateTestCases(candidate) {
|
|
90
|
+
if (candidate.testCases.length < 2)
|
|
91
|
+
return false;
|
|
92
|
+
if (candidate.substrate !== 'regex')
|
|
93
|
+
return true; // can't validate AST locally
|
|
94
|
+
try {
|
|
95
|
+
const regex = new RegExp(candidate.pattern, 'gm');
|
|
96
|
+
for (const tc of candidate.testCases) {
|
|
97
|
+
const matches = regex.test(tc.input);
|
|
98
|
+
regex.lastIndex = 0; // reset stateful regex
|
|
99
|
+
const formalVerdict = matches ? 'FAIL' : 'PASS';
|
|
100
|
+
if (formalVerdict !== tc.expectedVerdict) {
|
|
101
|
+
return false; // test case doesn't match expected behavior
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
return true;
|
|
105
|
+
}
|
|
106
|
+
catch {
|
|
107
|
+
return false; // invalid regex
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
//# sourceMappingURL=gap-detector.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gap-detector.js","sourceRoot":"","sources":["../../src/runtime/gap-detector.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { AgentPhase } from './types.js';
|
|
2
|
+
export type LogLevel = 'debug' | 'info' | 'warn' | 'error';
|
|
3
|
+
export interface LoggerOptions {
|
|
4
|
+
jsonMode: boolean;
|
|
5
|
+
logFilePath?: string;
|
|
6
|
+
}
|
|
7
|
+
export declare class Logger {
|
|
8
|
+
private readonly jsonMode;
|
|
9
|
+
private readonly logFilePath?;
|
|
10
|
+
private currentPhase;
|
|
11
|
+
private fileReady;
|
|
12
|
+
constructor(opts: LoggerOptions);
|
|
13
|
+
setPhase(phase: AgentPhase): void;
|
|
14
|
+
info(msg: string, data?: Record<string, unknown>): void;
|
|
15
|
+
warn(msg: string, data?: Record<string, unknown>): void;
|
|
16
|
+
error(msg: string, data?: Record<string, unknown>): void;
|
|
17
|
+
debug(msg: string, data?: Record<string, unknown>): void;
|
|
18
|
+
private write;
|
|
19
|
+
private appendToFile;
|
|
20
|
+
}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
// ============================================================
|
|
2
|
+
// Assay Verified Agent Runtime — Structured Logger
|
|
3
|
+
// Dual-mode: human-readable stdout + JSON file append
|
|
4
|
+
// ============================================================
|
|
5
|
+
import { appendFile, mkdir, stat, writeFile } from 'node:fs/promises';
|
|
6
|
+
import { dirname } from 'node:path';
|
|
7
|
+
// ── Logger ──────────────────────────────────────────────────
|
|
8
|
+
export class Logger {
|
|
9
|
+
jsonMode;
|
|
10
|
+
logFilePath;
|
|
11
|
+
currentPhase = 'idle';
|
|
12
|
+
fileReady = false;
|
|
13
|
+
constructor(opts) {
|
|
14
|
+
this.jsonMode = opts.jsonMode;
|
|
15
|
+
this.logFilePath = opts.logFilePath;
|
|
16
|
+
}
|
|
17
|
+
setPhase(phase) {
|
|
18
|
+
this.currentPhase = phase;
|
|
19
|
+
}
|
|
20
|
+
info(msg, data) {
|
|
21
|
+
this.write('info', msg, data);
|
|
22
|
+
}
|
|
23
|
+
warn(msg, data) {
|
|
24
|
+
this.write('warn', msg, data);
|
|
25
|
+
}
|
|
26
|
+
error(msg, data) {
|
|
27
|
+
this.write('error', msg, data);
|
|
28
|
+
}
|
|
29
|
+
debug(msg, data) {
|
|
30
|
+
this.write('debug', msg, data);
|
|
31
|
+
}
|
|
32
|
+
write(level, msg, data) {
|
|
33
|
+
const entry = {
|
|
34
|
+
ts: new Date().toISOString(),
|
|
35
|
+
level,
|
|
36
|
+
phase: this.currentPhase,
|
|
37
|
+
msg,
|
|
38
|
+
...(data && Object.keys(data).length > 0 ? { data } : {}),
|
|
39
|
+
};
|
|
40
|
+
// Write to stdout
|
|
41
|
+
if (this.jsonMode) {
|
|
42
|
+
console.log(JSON.stringify(entry));
|
|
43
|
+
}
|
|
44
|
+
else {
|
|
45
|
+
const time = entry.ts.slice(11, 19);
|
|
46
|
+
const levelTag = level === 'info' ? '' : ` [${level.toUpperCase()}]`;
|
|
47
|
+
console.log(`[${time}]${levelTag} ${msg}`);
|
|
48
|
+
}
|
|
49
|
+
// Write to log file (always JSON, fire-and-forget)
|
|
50
|
+
if (this.logFilePath) {
|
|
51
|
+
this.appendToFile(JSON.stringify(entry) + '\n').catch(() => {
|
|
52
|
+
// Silently ignore file write errors — don't disrupt the agent
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
async appendToFile(line) {
|
|
57
|
+
if (!this.logFilePath)
|
|
58
|
+
return;
|
|
59
|
+
if (!this.fileReady) {
|
|
60
|
+
try {
|
|
61
|
+
await stat(this.logFilePath);
|
|
62
|
+
}
|
|
63
|
+
catch {
|
|
64
|
+
const dir = dirname(this.logFilePath);
|
|
65
|
+
await mkdir(dir, { recursive: true });
|
|
66
|
+
await writeFile(this.logFilePath, '', 'utf-8');
|
|
67
|
+
}
|
|
68
|
+
this.fileReady = true;
|
|
69
|
+
}
|
|
70
|
+
await appendFile(this.logFilePath, line, 'utf-8');
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
//# sourceMappingURL=logger.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logger.js","sourceRoot":"","sources":["../../src/runtime/logger.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { EventEmitter } from 'node:events';
|
|
2
|
+
import type { AgentMessage, MultiAgentMessageType, BoundaryVerificationStatus, BoundaryClaim } from './types.js';
|
|
3
|
+
export interface ConversationThread {
|
|
4
|
+
readonly threadId: string;
|
|
5
|
+
readonly taskId: string;
|
|
6
|
+
readonly participants: string[];
|
|
7
|
+
readonly messages: AgentMessage[];
|
|
8
|
+
readonly status: 'active' | 'completed' | 'blocked' | 'escalated';
|
|
9
|
+
readonly startedAt: string;
|
|
10
|
+
readonly completedAt?: string;
|
|
11
|
+
}
|
|
12
|
+
export declare class MessageBus extends EventEmitter {
|
|
13
|
+
private threads;
|
|
14
|
+
private allMessages;
|
|
15
|
+
/**
|
|
16
|
+
* Send a message from one agent to another.
|
|
17
|
+
* Messages are logged and emitted for consumption.
|
|
18
|
+
*/
|
|
19
|
+
send<T>(sender: string, recipient: string, type: MultiAgentMessageType, payload: T, opts?: {
|
|
20
|
+
threadId?: string;
|
|
21
|
+
replyTo?: string;
|
|
22
|
+
claims?: readonly BoundaryClaim[];
|
|
23
|
+
verificationStatus?: BoundaryVerificationStatus;
|
|
24
|
+
}): AgentMessage<T>;
|
|
25
|
+
/**
|
|
26
|
+
* Update the verification status of a message after boundary verification.
|
|
27
|
+
*/
|
|
28
|
+
updateVerificationStatus(messageId: string, status: BoundaryVerificationStatus, claims?: readonly BoundaryClaim[]): void;
|
|
29
|
+
/**
|
|
30
|
+
* Get all messages for a specific agent (inbox).
|
|
31
|
+
*/
|
|
32
|
+
getInbox(agentId: string): AgentMessage[];
|
|
33
|
+
/**
|
|
34
|
+
* Get all messages sent by a specific agent (outbox).
|
|
35
|
+
*/
|
|
36
|
+
getOutbox(agentId: string): AgentMessage[];
|
|
37
|
+
/**
|
|
38
|
+
* Get a specific conversation thread.
|
|
39
|
+
*/
|
|
40
|
+
getThread(threadId: string): ConversationThread | undefined;
|
|
41
|
+
/**
|
|
42
|
+
* Get all threads.
|
|
43
|
+
*/
|
|
44
|
+
getAllThreads(): ConversationThread[];
|
|
45
|
+
/**
|
|
46
|
+
* Complete a thread.
|
|
47
|
+
*/
|
|
48
|
+
completeThread(threadId: string): void;
|
|
49
|
+
/**
|
|
50
|
+
* Get all messages (for audit trail).
|
|
51
|
+
*/
|
|
52
|
+
getAllMessages(): readonly AgentMessage[];
|
|
53
|
+
/**
|
|
54
|
+
* Get message count for a thread.
|
|
55
|
+
*/
|
|
56
|
+
getThreadMessageCount(threadId: string): number;
|
|
57
|
+
}
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
// ============================================================
|
|
2
|
+
// Assay Verified Agent Runtime — Message Bus
|
|
3
|
+
// Typed, logged, verification-tagged inter-agent communication
|
|
4
|
+
// ============================================================
|
|
5
|
+
import { randomUUID } from 'node:crypto';
|
|
6
|
+
import { EventEmitter } from 'node:events';
|
|
7
|
+
// ── Message Bus ─────────────────────────────────────────────
|
|
8
|
+
export class MessageBus extends EventEmitter {
|
|
9
|
+
threads = new Map();
|
|
10
|
+
allMessages = [];
|
|
11
|
+
/**
|
|
12
|
+
* Send a message from one agent to another.
|
|
13
|
+
* Messages are logged and emitted for consumption.
|
|
14
|
+
*/
|
|
15
|
+
send(sender, recipient, type, payload, opts) {
|
|
16
|
+
const threadId = opts?.threadId ?? randomUUID();
|
|
17
|
+
const message = {
|
|
18
|
+
id: randomUUID(),
|
|
19
|
+
sender,
|
|
20
|
+
recipient,
|
|
21
|
+
type,
|
|
22
|
+
payload,
|
|
23
|
+
verificationStatus: opts?.verificationStatus ?? 'unverified',
|
|
24
|
+
timestamp: new Date().toISOString(),
|
|
25
|
+
replyTo: opts?.replyTo,
|
|
26
|
+
threadId,
|
|
27
|
+
claims: opts?.claims,
|
|
28
|
+
};
|
|
29
|
+
this.allMessages.push(message);
|
|
30
|
+
// Update or create thread
|
|
31
|
+
const thread = this.threads.get(threadId);
|
|
32
|
+
if (thread) {
|
|
33
|
+
thread.messages.push(message);
|
|
34
|
+
if (!thread.participants.includes(sender)) {
|
|
35
|
+
thread.participants.push(sender);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
else {
|
|
39
|
+
this.threads.set(threadId, {
|
|
40
|
+
threadId,
|
|
41
|
+
taskId: threadId,
|
|
42
|
+
participants: [sender, recipient].filter(r => r !== 'broadcast'),
|
|
43
|
+
messages: [message],
|
|
44
|
+
status: 'active',
|
|
45
|
+
startedAt: message.timestamp,
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
// Emit for listeners
|
|
49
|
+
this.emit('message', message);
|
|
50
|
+
this.emit(`message:${recipient}`, message);
|
|
51
|
+
this.emit(`message:type:${type}`, message);
|
|
52
|
+
return message;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Update the verification status of a message after boundary verification.
|
|
56
|
+
*/
|
|
57
|
+
updateVerificationStatus(messageId, status, claims) {
|
|
58
|
+
const message = this.allMessages.find(m => m.id === messageId);
|
|
59
|
+
if (message) {
|
|
60
|
+
// Messages are readonly, but we need to update verification status
|
|
61
|
+
// Use type assertion to update the tracking fields
|
|
62
|
+
message.verificationStatus = status;
|
|
63
|
+
if (claims) {
|
|
64
|
+
message.claims = claims;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Get all messages for a specific agent (inbox).
|
|
70
|
+
*/
|
|
71
|
+
getInbox(agentId) {
|
|
72
|
+
return this.allMessages.filter(m => m.recipient === agentId || m.recipient === 'broadcast');
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Get all messages sent by a specific agent (outbox).
|
|
76
|
+
*/
|
|
77
|
+
getOutbox(agentId) {
|
|
78
|
+
return this.allMessages.filter(m => m.sender === agentId);
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Get a specific conversation thread.
|
|
82
|
+
*/
|
|
83
|
+
getThread(threadId) {
|
|
84
|
+
return this.threads.get(threadId);
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Get all threads.
|
|
88
|
+
*/
|
|
89
|
+
getAllThreads() {
|
|
90
|
+
return Array.from(this.threads.values());
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Complete a thread.
|
|
94
|
+
*/
|
|
95
|
+
completeThread(threadId) {
|
|
96
|
+
const thread = this.threads.get(threadId);
|
|
97
|
+
if (thread) {
|
|
98
|
+
thread.status = 'completed';
|
|
99
|
+
thread.completedAt = new Date().toISOString();
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Get all messages (for audit trail).
|
|
104
|
+
*/
|
|
105
|
+
getAllMessages() {
|
|
106
|
+
return this.allMessages;
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Get message count for a thread.
|
|
110
|
+
*/
|
|
111
|
+
getThreadMessageCount(threadId) {
|
|
112
|
+
return this.threads.get(threadId)?.messages.length ?? 0;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
//# sourceMappingURL=message-bus.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"message-bus.js","sourceRoot":"","sources":["../../src/runtime/message-bus.ts"],"names":[],"mappings":"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"}
|
|
@@ -9,9 +9,13 @@ export declare class FileWatcherAdapter implements SignalAdapter {
|
|
|
9
9
|
readonly type: SignalSourceType;
|
|
10
10
|
private watchers;
|
|
11
11
|
private config;
|
|
12
|
-
|
|
12
|
+
private debounceMs;
|
|
13
|
+
private pendingChanges;
|
|
14
|
+
private debounceTimer;
|
|
15
|
+
constructor(config: FileSystemSignalConfig, debounceMs?: number);
|
|
13
16
|
start(emit: (obs: Observation) => void): Promise<void>;
|
|
14
17
|
stop(): Promise<void>;
|
|
18
|
+
private flushPendingChanges;
|
|
15
19
|
}
|
|
16
20
|
export declare class WebhookAdapter implements SignalAdapter {
|
|
17
21
|
readonly type: SignalSourceType;
|
package/dist/runtime/observer.js
CHANGED
|
@@ -12,8 +12,12 @@ export class FileWatcherAdapter {
|
|
|
12
12
|
type = 'filesystem';
|
|
13
13
|
watchers = [];
|
|
14
14
|
config;
|
|
15
|
-
|
|
15
|
+
debounceMs;
|
|
16
|
+
pendingChanges = new Map();
|
|
17
|
+
debounceTimer = null;
|
|
18
|
+
constructor(config, debounceMs = 500) {
|
|
16
19
|
this.config = config;
|
|
20
|
+
this.debounceMs = debounceMs;
|
|
17
21
|
}
|
|
18
22
|
async start(emit) {
|
|
19
23
|
for (const dirPath of this.config.paths) {
|
|
@@ -25,29 +29,72 @@ export class FileWatcherAdapter {
|
|
|
25
29
|
return;
|
|
26
30
|
}
|
|
27
31
|
const event = eventType === 'rename' ? 'create' : 'modify';
|
|
28
|
-
const
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
payload,
|
|
39
|
-
};
|
|
40
|
-
emit(obs);
|
|
32
|
+
const fullPath = `${resolved}/${filename}`;
|
|
33
|
+
// Accumulate changes in the debounce window
|
|
34
|
+
this.pendingChanges.set(fullPath, { event, path: fullPath });
|
|
35
|
+
// Reset the debounce timer
|
|
36
|
+
if (this.debounceTimer) {
|
|
37
|
+
clearTimeout(this.debounceTimer);
|
|
38
|
+
}
|
|
39
|
+
this.debounceTimer = setTimeout(() => {
|
|
40
|
+
this.flushPendingChanges(emit);
|
|
41
|
+
}, this.debounceMs);
|
|
41
42
|
});
|
|
42
43
|
this.watchers.push(watcher);
|
|
43
44
|
}
|
|
44
45
|
}
|
|
45
46
|
async stop() {
|
|
47
|
+
if (this.debounceTimer) {
|
|
48
|
+
clearTimeout(this.debounceTimer);
|
|
49
|
+
this.debounceTimer = null;
|
|
50
|
+
}
|
|
51
|
+
this.pendingChanges.clear();
|
|
46
52
|
for (const watcher of this.watchers) {
|
|
47
53
|
watcher.close();
|
|
48
54
|
}
|
|
49
55
|
this.watchers = [];
|
|
50
56
|
}
|
|
57
|
+
flushPendingChanges(emit) {
|
|
58
|
+
if (this.pendingChanges.size === 0)
|
|
59
|
+
return;
|
|
60
|
+
const changes = Array.from(this.pendingChanges.values());
|
|
61
|
+
this.pendingChanges.clear();
|
|
62
|
+
this.debounceTimer = null;
|
|
63
|
+
if (changes.length === 1) {
|
|
64
|
+
// Single file change — emit as-is
|
|
65
|
+
const change = changes[0];
|
|
66
|
+
const payload = {
|
|
67
|
+
type: 'file_change',
|
|
68
|
+
event: change.event,
|
|
69
|
+
path: change.path,
|
|
70
|
+
};
|
|
71
|
+
emit({
|
|
72
|
+
id: randomUUID(),
|
|
73
|
+
source: 'filesystem',
|
|
74
|
+
urgency: 'normal',
|
|
75
|
+
timestamp: new Date().toISOString(),
|
|
76
|
+
payload,
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
else {
|
|
80
|
+
// Multiple file changes — emit first as representative, include all paths in observation
|
|
81
|
+
const primary = changes[0];
|
|
82
|
+
const payload = {
|
|
83
|
+
type: 'file_change',
|
|
84
|
+
event: primary.event,
|
|
85
|
+
path: primary.path,
|
|
86
|
+
};
|
|
87
|
+
emit({
|
|
88
|
+
id: randomUUID(),
|
|
89
|
+
source: 'filesystem',
|
|
90
|
+
urgency: 'normal',
|
|
91
|
+
timestamp: new Date().toISOString(),
|
|
92
|
+
payload,
|
|
93
|
+
// Store all changed paths for context
|
|
94
|
+
relatedExperienceIds: changes.map(c => c.path),
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
}
|
|
51
98
|
}
|
|
52
99
|
// ── WebhookAdapter ────────────────────────────────────────────
|
|
53
100
|
export class WebhookAdapter {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"observer.js","sourceRoot":"","sources":["../../src/runtime/observer.ts"],"names":[],"mappings":"AAAA,+DAA+D;AAC/D,oDAAoD;AACpD,6DAA6D;AAC7D,+DAA+D;AAE/D,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EAAE,KAAK,EAAkB,MAAM,SAAS,CAAC;AAChD,OAAO,EAAE,YAAY,EAA0D,MAAM,WAAW,CAAC;AACjG,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAsBpC,iEAAiE;AAEjE,MAAM,OAAO,kBAAkB;IACpB,IAAI,GAAqB,YAAY,CAAC;IACvC,QAAQ,GAAgB,EAAE,CAAC;IAC3B,MAAM,CAAyB;
|
|
1
|
+
{"version":3,"file":"observer.js","sourceRoot":"","sources":["../../src/runtime/observer.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { Experience, PatternEntry, AntiPatternEntry, SkillProfile, VerificationHotspot } from './types.js';
|
|
2
|
+
export interface ExtractionResult {
|
|
3
|
+
patterns: PatternEntry[];
|
|
4
|
+
antiPatterns: AntiPatternEntry[];
|
|
5
|
+
skillProfiles: SkillProfile[];
|
|
6
|
+
verificationHotspots: VerificationHotspot[];
|
|
7
|
+
extractedAt: string;
|
|
8
|
+
}
|
|
9
|
+
export declare class PatternExtractor {
|
|
10
|
+
extract(experiences: Experience[], filter?: {
|
|
11
|
+
domain?: string;
|
|
12
|
+
since?: string;
|
|
13
|
+
}): Promise<ExtractionResult>;
|
|
14
|
+
private extractPatternsFromCluster;
|
|
15
|
+
private computeSkillProfile;
|
|
16
|
+
private computeHotspots;
|
|
17
|
+
private inferClaimCategory;
|
|
18
|
+
private deduplicateHotspots;
|
|
19
|
+
private topN;
|
|
20
|
+
}
|