@yuaone/core 0.9.8 → 0.9.9
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/__tests__/context-manager.test.js +5 -9
- package/dist/__tests__/context-manager.test.js.map +1 -1
- package/dist/agent-coordinator.d.ts +172 -0
- package/dist/agent-coordinator.d.ts.map +1 -0
- package/dist/agent-coordinator.js +390 -0
- package/dist/agent-coordinator.js.map +1 -0
- package/dist/agent-loop.d.ts +83 -39
- package/dist/agent-loop.d.ts.map +1 -1
- package/dist/agent-loop.js +694 -471
- package/dist/agent-loop.js.map +1 -1
- package/dist/agent-reputation.d.ts +72 -0
- package/dist/agent-reputation.d.ts.map +1 -0
- package/dist/agent-reputation.js +222 -0
- package/dist/agent-reputation.js.map +1 -0
- package/dist/arch-summarizer.d.ts +48 -0
- package/dist/arch-summarizer.d.ts.map +1 -0
- package/dist/arch-summarizer.js +239 -0
- package/dist/arch-summarizer.js.map +1 -0
- package/dist/autonomous/explicit-planner.d.ts +45 -0
- package/dist/autonomous/explicit-planner.d.ts.map +1 -0
- package/dist/autonomous/explicit-planner.js +99 -0
- package/dist/autonomous/explicit-planner.js.map +1 -0
- package/dist/autonomous/incident-debugger.d.ts +78 -0
- package/dist/autonomous/incident-debugger.d.ts.map +1 -0
- package/dist/autonomous/incident-debugger.js +324 -0
- package/dist/autonomous/incident-debugger.js.map +1 -0
- package/dist/autonomous/index.d.ts +15 -0
- package/dist/autonomous/index.d.ts.map +1 -0
- package/dist/autonomous/index.js +10 -0
- package/dist/autonomous/index.js.map +1 -0
- package/dist/autonomous/patch-tournament.d.ts +82 -0
- package/dist/autonomous/patch-tournament.d.ts.map +1 -0
- package/dist/autonomous/patch-tournament.js +150 -0
- package/dist/autonomous/patch-tournament.js.map +1 -0
- package/dist/autonomous/research-agent.d.ts +66 -0
- package/dist/autonomous/research-agent.d.ts.map +1 -0
- package/dist/autonomous/research-agent.js +210 -0
- package/dist/autonomous/research-agent.js.map +1 -0
- package/dist/autonomous/task-memory.d.ts +63 -0
- package/dist/autonomous/task-memory.d.ts.map +1 -0
- package/dist/autonomous/task-memory.js +143 -0
- package/dist/autonomous/task-memory.js.map +1 -0
- package/dist/budget-governor-v2.d.ts +93 -0
- package/dist/budget-governor-v2.d.ts.map +1 -0
- package/dist/budget-governor-v2.js +345 -0
- package/dist/budget-governor-v2.js.map +1 -0
- package/dist/capability-graph.d.ts +102 -0
- package/dist/capability-graph.d.ts.map +1 -0
- package/dist/capability-graph.js +397 -0
- package/dist/capability-graph.js.map +1 -0
- package/dist/capability-self-model.d.ts +144 -0
- package/dist/capability-self-model.d.ts.map +1 -0
- package/dist/capability-self-model.js +312 -0
- package/dist/capability-self-model.js.map +1 -0
- package/dist/checkpoint-manager.d.ts +94 -0
- package/dist/checkpoint-manager.d.ts.map +1 -0
- package/dist/checkpoint-manager.js +225 -0
- package/dist/checkpoint-manager.js.map +1 -0
- package/dist/continuation-engine.js +1 -1
- package/dist/continuation-engine.js.map +1 -1
- package/dist/dag-orchestrator.d.ts +0 -3
- package/dist/dag-orchestrator.d.ts.map +1 -1
- package/dist/dag-orchestrator.js +0 -1
- package/dist/dag-orchestrator.js.map +1 -1
- package/dist/evidence-chain.d.ts +99 -0
- package/dist/evidence-chain.d.ts.map +1 -0
- package/dist/evidence-chain.js +200 -0
- package/dist/evidence-chain.js.map +1 -0
- package/dist/execution-engine.d.ts.map +1 -1
- package/dist/execution-engine.js +0 -1
- package/dist/execution-engine.js.map +1 -1
- package/dist/failure-signature-memory.d.ts +61 -0
- package/dist/failure-signature-memory.d.ts.map +1 -0
- package/dist/failure-signature-memory.js +278 -0
- package/dist/failure-signature-memory.js.map +1 -0
- package/dist/index.d.ts +52 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +48 -7
- package/dist/index.js.map +1 -1
- package/dist/language-detector.d.ts.map +1 -1
- package/dist/language-detector.js +122 -43
- package/dist/language-detector.js.map +1 -1
- package/dist/llm-client.d.ts +0 -7
- package/dist/llm-client.d.ts.map +1 -1
- package/dist/llm-client.js +15 -122
- package/dist/llm-client.js.map +1 -1
- package/dist/mcp-client.js +1 -1
- package/dist/mcp-client.js.map +1 -1
- package/dist/memory.d.ts.map +1 -1
- package/dist/memory.js +0 -15
- package/dist/memory.js.map +1 -1
- package/dist/meta-learning-collector.d.ts +64 -0
- package/dist/meta-learning-collector.d.ts.map +1 -0
- package/dist/meta-learning-collector.js +169 -0
- package/dist/meta-learning-collector.js.map +1 -0
- package/dist/meta-learning-engine.d.ts +61 -0
- package/dist/meta-learning-engine.d.ts.map +1 -0
- package/dist/meta-learning-engine.js +250 -0
- package/dist/meta-learning-engine.js.map +1 -0
- package/dist/overhead-governor.d.ts +105 -0
- package/dist/overhead-governor.d.ts.map +1 -0
- package/dist/overhead-governor.js +239 -0
- package/dist/overhead-governor.js.map +1 -0
- package/dist/playbook-library.d.ts +75 -0
- package/dist/playbook-library.d.ts.map +1 -0
- package/dist/playbook-library.js +241 -0
- package/dist/playbook-library.js.map +1 -0
- package/dist/project-executive.d.ts +97 -0
- package/dist/project-executive.d.ts.map +1 -0
- package/dist/project-executive.js +223 -0
- package/dist/project-executive.js.map +1 -0
- package/dist/reasoning-adapter.d.ts.map +1 -1
- package/dist/reasoning-adapter.js +11 -36
- package/dist/reasoning-adapter.js.map +1 -1
- package/dist/research-loop.d.ts +79 -0
- package/dist/research-loop.d.ts.map +1 -0
- package/dist/research-loop.js +363 -0
- package/dist/research-loop.js.map +1 -0
- package/dist/resolve-memory-path.d.ts +32 -0
- package/dist/resolve-memory-path.d.ts.map +1 -0
- package/dist/resolve-memory-path.js +97 -0
- package/dist/resolve-memory-path.js.map +1 -0
- package/dist/safe-bounds.d.ts +101 -0
- package/dist/safe-bounds.d.ts.map +1 -0
- package/dist/safe-bounds.js +140 -0
- package/dist/safe-bounds.js.map +1 -0
- package/dist/sandbox-tiers.d.ts +5 -0
- package/dist/sandbox-tiers.d.ts.map +1 -1
- package/dist/sandbox-tiers.js +14 -6
- package/dist/sandbox-tiers.js.map +1 -1
- package/dist/security.d.ts.map +1 -1
- package/dist/security.js +3 -0
- package/dist/security.js.map +1 -1
- package/dist/self-improvement-loop.d.ts +64 -0
- package/dist/self-improvement-loop.d.ts.map +1 -0
- package/dist/self-improvement-loop.js +156 -0
- package/dist/self-improvement-loop.js.map +1 -0
- package/dist/session-persistence.d.ts +5 -0
- package/dist/session-persistence.d.ts.map +1 -1
- package/dist/session-persistence.js +19 -3
- package/dist/session-persistence.js.map +1 -1
- package/dist/skill-loader.d.ts +16 -9
- package/dist/skill-loader.d.ts.map +1 -1
- package/dist/skill-loader.js +52 -116
- package/dist/skill-loader.js.map +1 -1
- package/dist/skill-registry.d.ts +60 -0
- package/dist/skill-registry.d.ts.map +1 -0
- package/dist/skill-registry.js +162 -0
- package/dist/skill-registry.js.map +1 -0
- package/dist/stall-detector.d.ts +56 -0
- package/dist/stall-detector.d.ts.map +1 -0
- package/dist/stall-detector.js +142 -0
- package/dist/stall-detector.js.map +1 -0
- package/dist/strategy-learner.d.ts +57 -0
- package/dist/strategy-learner.d.ts.map +1 -0
- package/dist/strategy-learner.js +160 -0
- package/dist/strategy-learner.js.map +1 -0
- package/dist/strategy-market.d.ts +73 -0
- package/dist/strategy-market.d.ts.map +1 -0
- package/dist/strategy-market.js +200 -0
- package/dist/strategy-market.js.map +1 -0
- package/dist/sub-agent.d.ts +0 -3
- package/dist/sub-agent.d.ts.map +1 -1
- package/dist/sub-agent.js +0 -10
- package/dist/sub-agent.js.map +1 -1
- package/dist/system-prompt.d.ts +0 -2
- package/dist/system-prompt.d.ts.map +1 -1
- package/dist/system-prompt.js +97 -490
- package/dist/system-prompt.js.map +1 -1
- package/dist/task-classifier.d.ts.map +1 -1
- package/dist/task-classifier.js +2 -54
- package/dist/task-classifier.js.map +1 -1
- package/dist/tool-synthesizer.d.ts +149 -0
- package/dist/tool-synthesizer.d.ts.map +1 -0
- package/dist/tool-synthesizer.js +455 -0
- package/dist/tool-synthesizer.js.map +1 -0
- package/dist/trace-pattern-extractor.d.ts +76 -0
- package/dist/trace-pattern-extractor.d.ts.map +1 -0
- package/dist/trace-pattern-extractor.js +321 -0
- package/dist/trace-pattern-extractor.js.map +1 -0
- package/dist/trace-recorder.d.ts +38 -0
- package/dist/trace-recorder.d.ts.map +1 -0
- package/dist/trace-recorder.js +94 -0
- package/dist/trace-recorder.js.map +1 -0
- package/dist/trust-economics.d.ts +50 -0
- package/dist/trust-economics.d.ts.map +1 -0
- package/dist/trust-economics.js +148 -0
- package/dist/trust-economics.js.map +1 -0
- package/dist/types.d.ts +273 -4
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/dist/yuan-md-loader.d.ts +22 -0
- package/dist/yuan-md-loader.d.ts.map +1 -0
- package/dist/yuan-md-loader.js +75 -0
- package/dist/yuan-md-loader.js.map +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1,321 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module trace-pattern-extractor
|
|
3
|
+
* @description Reads TraceRecorder JSONL files from ~/.yuan/traces/, detects repeated
|
|
4
|
+
* successful tool sequences, and produces Playbook proposals.
|
|
5
|
+
*
|
|
6
|
+
* Pattern detection rules:
|
|
7
|
+
* - A sequence = ordered list of tool names from tool_call events in a session
|
|
8
|
+
* - A pattern is a contiguous sub-sequence of 3..8 tools
|
|
9
|
+
* - Significant if: appears in 3+ distinct sessions AND success rate >= 60%
|
|
10
|
+
* AND not already proposed (tracked by patternHash)
|
|
11
|
+
*
|
|
12
|
+
* Storage: ~/.yuan/proposals/playbook-proposals.json — array of PlaybookProposal, atomic write
|
|
13
|
+
* Events: emits on single "event" channel like all other modules
|
|
14
|
+
*/
|
|
15
|
+
import { createHash, randomUUID } from "crypto";
|
|
16
|
+
import { EventEmitter } from "events";
|
|
17
|
+
import { existsSync, mkdirSync, readdirSync, readFileSync, renameSync, writeFileSync, } from "fs";
|
|
18
|
+
import { homedir } from "os";
|
|
19
|
+
import { join } from "path";
|
|
20
|
+
// ─── Helpers ───
|
|
21
|
+
/**
|
|
22
|
+
* Infer task type from goal text using keyword matching.
|
|
23
|
+
* Mirrors PlaybookLibrary's classifier for consistency.
|
|
24
|
+
*/
|
|
25
|
+
function inferTaskType(goal) {
|
|
26
|
+
const g = goal.toLowerCase();
|
|
27
|
+
if (/fix|bug|error|crash|fail/.test(g))
|
|
28
|
+
return "ts-bugfix";
|
|
29
|
+
if (/refactor|rename|reorganize|restructure|clean/.test(g))
|
|
30
|
+
return "refactor";
|
|
31
|
+
if (/add|implement|create|build|feature|new/.test(g))
|
|
32
|
+
return "feature-add";
|
|
33
|
+
if (/test|spec|coverage|jest|vitest/.test(g))
|
|
34
|
+
return "test-gen";
|
|
35
|
+
if (/security|vuln|cve|inject|xss|csrf/.test(g))
|
|
36
|
+
return "security-fix";
|
|
37
|
+
if (/doc|readme|comment|jsdoc/.test(g))
|
|
38
|
+
return "docs";
|
|
39
|
+
if (/migrat|upgrade|version|convert/.test(g))
|
|
40
|
+
return "migration";
|
|
41
|
+
if (/perf|optim|speed|slow|latency/.test(g))
|
|
42
|
+
return "performance";
|
|
43
|
+
return "general";
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Compute a short SHA-256 hash of the tool sequence for deduplication.
|
|
47
|
+
*/
|
|
48
|
+
function hashSequence(seq) {
|
|
49
|
+
return createHash("sha256")
|
|
50
|
+
.update(seq.join(","))
|
|
51
|
+
.digest("hex")
|
|
52
|
+
.slice(0, 16);
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Extract all contiguous sub-sequences of length minLen..maxLen from an array.
|
|
56
|
+
*/
|
|
57
|
+
function subSequences(arr, minLen, maxLen) {
|
|
58
|
+
const results = [];
|
|
59
|
+
for (let start = 0; start < arr.length; start++) {
|
|
60
|
+
for (let len = minLen; len <= maxLen && start + len <= arr.length; len++) {
|
|
61
|
+
results.push(arr.slice(start, start + len));
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
return results;
|
|
65
|
+
}
|
|
66
|
+
// ─── TracePatternExtractor ───
|
|
67
|
+
export class TracePatternExtractor extends EventEmitter {
|
|
68
|
+
tracesDir;
|
|
69
|
+
storageDir;
|
|
70
|
+
storageFile;
|
|
71
|
+
minSessions;
|
|
72
|
+
minSuccessRate;
|
|
73
|
+
/** patternHashes of proposals already produced — prevents re-proposing */
|
|
74
|
+
proposedPatterns;
|
|
75
|
+
/** proposalIds marked as applied — excluded from getProposals() */
|
|
76
|
+
appliedProposals;
|
|
77
|
+
proposals;
|
|
78
|
+
constructor(config) {
|
|
79
|
+
super();
|
|
80
|
+
this.tracesDir =
|
|
81
|
+
config?.tracesDir ?? join(homedir(), ".yuan", "traces");
|
|
82
|
+
this.storageDir =
|
|
83
|
+
config?.storageDir ?? join(homedir(), ".yuan", "proposals");
|
|
84
|
+
this.storageFile = join(this.storageDir, "playbook-proposals.json");
|
|
85
|
+
this.minSessions = config?.minSessions ?? 3;
|
|
86
|
+
this.minSuccessRate = config?.minSuccessRate ?? 0.6;
|
|
87
|
+
this.proposedPatterns = new Set();
|
|
88
|
+
this.appliedProposals = new Set();
|
|
89
|
+
this.proposals = this._loadProposals();
|
|
90
|
+
// Seed proposedPatterns from already-stored proposals
|
|
91
|
+
for (const p of this.proposals) {
|
|
92
|
+
this.proposedPatterns.add(p.patternHash);
|
|
93
|
+
}
|
|
94
|
+
mkdirSync(this.storageDir, { recursive: true });
|
|
95
|
+
}
|
|
96
|
+
// ─── Public API ───
|
|
97
|
+
/**
|
|
98
|
+
* Main: scan all JSONL files in tracesDir, extract significant patterns,
|
|
99
|
+
* persist and return newly discovered proposals.
|
|
100
|
+
*/
|
|
101
|
+
async extract() {
|
|
102
|
+
const sessions = this._parseSessions();
|
|
103
|
+
if (sessions.size === 0)
|
|
104
|
+
return [];
|
|
105
|
+
// Build sub-sequence frequency maps
|
|
106
|
+
// Map<patternHash, { seq, sessions: Set<sessionId>, successCount }>
|
|
107
|
+
const patternMap = new Map();
|
|
108
|
+
for (const [sessionId, data] of sessions.entries()) {
|
|
109
|
+
if (!data.ended)
|
|
110
|
+
continue; // skip incomplete sessions
|
|
111
|
+
const subSeqs = subSequences(data.toolCalls, 3, 8);
|
|
112
|
+
const seenInSession = new Set();
|
|
113
|
+
for (const seq of subSeqs) {
|
|
114
|
+
const hash = hashSequence(seq);
|
|
115
|
+
// Count each pattern at most once per session
|
|
116
|
+
if (seenInSession.has(hash))
|
|
117
|
+
continue;
|
|
118
|
+
seenInSession.add(hash);
|
|
119
|
+
if (!patternMap.has(hash)) {
|
|
120
|
+
patternMap.set(hash, { seq, sessions: new Set(), successCount: 0 });
|
|
121
|
+
}
|
|
122
|
+
const entry = patternMap.get(hash);
|
|
123
|
+
entry.sessions.add(sessionId);
|
|
124
|
+
if (data.success)
|
|
125
|
+
entry.successCount++;
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
// Filter for significant patterns not yet proposed
|
|
129
|
+
const newProposals = [];
|
|
130
|
+
for (const [hash, entry] of patternMap.entries()) {
|
|
131
|
+
if (this.proposedPatterns.has(hash))
|
|
132
|
+
continue;
|
|
133
|
+
const sessionCount = entry.sessions.size;
|
|
134
|
+
if (sessionCount < this.minSessions)
|
|
135
|
+
continue;
|
|
136
|
+
const successRate = entry.successCount / sessionCount;
|
|
137
|
+
if (successRate < this.minSuccessRate)
|
|
138
|
+
continue;
|
|
139
|
+
// Infer task type from majority goal of source sessions
|
|
140
|
+
const taskType = this._inferDominantTaskType(entry.sessions, sessions);
|
|
141
|
+
const proposal = {
|
|
142
|
+
id: randomUUID(),
|
|
143
|
+
taskType,
|
|
144
|
+
toolSequence: entry.seq,
|
|
145
|
+
patternHash: hash,
|
|
146
|
+
sessionCount,
|
|
147
|
+
successRate,
|
|
148
|
+
sourceSessionIds: [...entry.sessions],
|
|
149
|
+
proposedAt: new Date().toISOString(),
|
|
150
|
+
};
|
|
151
|
+
newProposals.push(proposal);
|
|
152
|
+
this.proposedPatterns.add(hash);
|
|
153
|
+
// Emit event for each new proposal
|
|
154
|
+
this.emit("event", {
|
|
155
|
+
kind: "agent:playbook_learned",
|
|
156
|
+
proposalId: proposal.id,
|
|
157
|
+
taskType: proposal.taskType,
|
|
158
|
+
toolSequence: proposal.toolSequence,
|
|
159
|
+
successRate: proposal.successRate,
|
|
160
|
+
sessionCount: proposal.sessionCount,
|
|
161
|
+
timestamp: Date.now(),
|
|
162
|
+
});
|
|
163
|
+
}
|
|
164
|
+
if (newProposals.length > 0) {
|
|
165
|
+
// Merge into stored proposals and persist
|
|
166
|
+
this.proposals = [...this.proposals, ...newProposals];
|
|
167
|
+
this._saveProposals();
|
|
168
|
+
}
|
|
169
|
+
return newProposals;
|
|
170
|
+
}
|
|
171
|
+
/**
|
|
172
|
+
* Get all stored proposals, excluding applied ones.
|
|
173
|
+
*/
|
|
174
|
+
getProposals() {
|
|
175
|
+
return this.proposals.filter((p) => !this.appliedProposals.has(p.id));
|
|
176
|
+
}
|
|
177
|
+
/**
|
|
178
|
+
* Mark a proposal as applied so it won't be returned by getProposals().
|
|
179
|
+
* Applied state is in-memory only — not persisted.
|
|
180
|
+
*/
|
|
181
|
+
markApplied(proposalId) {
|
|
182
|
+
this.appliedProposals.add(proposalId);
|
|
183
|
+
}
|
|
184
|
+
// ─── Internal ───
|
|
185
|
+
/**
|
|
186
|
+
* Parse all JSONL files in tracesDir into per-session SessionData.
|
|
187
|
+
*/
|
|
188
|
+
_parseSessions() {
|
|
189
|
+
const sessions = new Map();
|
|
190
|
+
if (!existsSync(this.tracesDir))
|
|
191
|
+
return sessions;
|
|
192
|
+
let files;
|
|
193
|
+
try {
|
|
194
|
+
files = readdirSync(this.tracesDir).filter((f) => f.endsWith(".jsonl"));
|
|
195
|
+
}
|
|
196
|
+
catch {
|
|
197
|
+
return sessions;
|
|
198
|
+
}
|
|
199
|
+
for (const file of files) {
|
|
200
|
+
const filePath = join(this.tracesDir, file);
|
|
201
|
+
let content;
|
|
202
|
+
try {
|
|
203
|
+
content = readFileSync(filePath, "utf-8");
|
|
204
|
+
}
|
|
205
|
+
catch {
|
|
206
|
+
continue;
|
|
207
|
+
}
|
|
208
|
+
const lines = content.split("\n");
|
|
209
|
+
for (const line of lines) {
|
|
210
|
+
const trimmed = line.trim();
|
|
211
|
+
if (!trimmed)
|
|
212
|
+
continue;
|
|
213
|
+
let event;
|
|
214
|
+
try {
|
|
215
|
+
event = JSON.parse(trimmed);
|
|
216
|
+
}
|
|
217
|
+
catch {
|
|
218
|
+
continue; // skip malformed lines
|
|
219
|
+
}
|
|
220
|
+
if (!event.kind || !event.sessionId)
|
|
221
|
+
continue;
|
|
222
|
+
switch (event.kind) {
|
|
223
|
+
case "session_start": {
|
|
224
|
+
sessions.set(event.sessionId, {
|
|
225
|
+
sessionId: event.sessionId,
|
|
226
|
+
goal: event.goal ?? "",
|
|
227
|
+
toolCalls: [],
|
|
228
|
+
success: false,
|
|
229
|
+
ended: false,
|
|
230
|
+
});
|
|
231
|
+
break;
|
|
232
|
+
}
|
|
233
|
+
case "tool_call": {
|
|
234
|
+
if (!event.tool)
|
|
235
|
+
break;
|
|
236
|
+
let session = sessions.get(event.sessionId);
|
|
237
|
+
if (!session) {
|
|
238
|
+
// Handle orphaned tool_call (session_start missed)
|
|
239
|
+
session = {
|
|
240
|
+
sessionId: event.sessionId,
|
|
241
|
+
goal: "",
|
|
242
|
+
toolCalls: [],
|
|
243
|
+
success: false,
|
|
244
|
+
ended: false,
|
|
245
|
+
};
|
|
246
|
+
sessions.set(event.sessionId, session);
|
|
247
|
+
}
|
|
248
|
+
session.toolCalls.push(event.tool);
|
|
249
|
+
break;
|
|
250
|
+
}
|
|
251
|
+
case "session_end": {
|
|
252
|
+
const sess = sessions.get(event.sessionId);
|
|
253
|
+
if (sess) {
|
|
254
|
+
sess.success = event.success ?? false;
|
|
255
|
+
sess.ended = true;
|
|
256
|
+
}
|
|
257
|
+
break;
|
|
258
|
+
}
|
|
259
|
+
// tool_result: not needed for sequence extraction
|
|
260
|
+
default:
|
|
261
|
+
break;
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
return sessions;
|
|
266
|
+
}
|
|
267
|
+
/**
|
|
268
|
+
* Infer the most common task type across a set of session IDs.
|
|
269
|
+
* Falls back to "general" if no goals found.
|
|
270
|
+
*/
|
|
271
|
+
_inferDominantTaskType(sessionIds, allSessions) {
|
|
272
|
+
const typeCounts = new Map();
|
|
273
|
+
for (const sid of sessionIds) {
|
|
274
|
+
const sess = allSessions.get(sid);
|
|
275
|
+
if (!sess || !sess.goal)
|
|
276
|
+
continue;
|
|
277
|
+
const t = inferTaskType(sess.goal);
|
|
278
|
+
typeCounts.set(t, (typeCounts.get(t) ?? 0) + 1);
|
|
279
|
+
}
|
|
280
|
+
if (typeCounts.size === 0)
|
|
281
|
+
return "general";
|
|
282
|
+
let best = "general";
|
|
283
|
+
let bestCount = 0;
|
|
284
|
+
for (const [type, count] of typeCounts.entries()) {
|
|
285
|
+
if (count > bestCount) {
|
|
286
|
+
bestCount = count;
|
|
287
|
+
best = type;
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
return best;
|
|
291
|
+
}
|
|
292
|
+
/**
|
|
293
|
+
* Load persisted proposals from disk.
|
|
294
|
+
*/
|
|
295
|
+
_loadProposals() {
|
|
296
|
+
try {
|
|
297
|
+
if (!existsSync(this.storageFile))
|
|
298
|
+
return [];
|
|
299
|
+
const raw = readFileSync(this.storageFile, "utf-8");
|
|
300
|
+
return JSON.parse(raw);
|
|
301
|
+
}
|
|
302
|
+
catch {
|
|
303
|
+
return [];
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
/**
|
|
307
|
+
* Atomic write of proposals array to disk.
|
|
308
|
+
*/
|
|
309
|
+
_saveProposals() {
|
|
310
|
+
const tmpFile = `${this.storageFile}.tmp`;
|
|
311
|
+
try {
|
|
312
|
+
mkdirSync(this.storageDir, { recursive: true });
|
|
313
|
+
writeFileSync(tmpFile, JSON.stringify(this.proposals, null, 2), "utf-8");
|
|
314
|
+
renameSync(tmpFile, this.storageFile);
|
|
315
|
+
}
|
|
316
|
+
catch {
|
|
317
|
+
// Non-fatal: storage failures should not crash the agent loop
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
//# sourceMappingURL=trace-pattern-extractor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"trace-pattern-extractor.js","sourceRoot":"","sources":["../src/trace-pattern-extractor.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module trace-recorder
|
|
3
|
+
* @description Lightweight append-only session trace recorder.
|
|
4
|
+
*
|
|
5
|
+
* Records every observable agent loop event to `.yuan/traces/<sessionId>.jsonl`.
|
|
6
|
+
* Format: one JSON object per line (JSONL), allowing step-by-step replay.
|
|
7
|
+
*
|
|
8
|
+
* Design constraints:
|
|
9
|
+
* - Never blocks the main loop (all writes are fire-and-forget)
|
|
10
|
+
* - Never throws (all errors are swallowed silently)
|
|
11
|
+
* - File handle stays open during session, closed on stop()
|
|
12
|
+
*/
|
|
13
|
+
import type { AgentEvent } from "./types.js";
|
|
14
|
+
/** One line in a trace file */
|
|
15
|
+
export interface TraceEntry {
|
|
16
|
+
/** ISO timestamp */
|
|
17
|
+
ts: string;
|
|
18
|
+
/** Sequence number within session */
|
|
19
|
+
seq: number;
|
|
20
|
+
/** The agent event payload */
|
|
21
|
+
event: AgentEvent;
|
|
22
|
+
}
|
|
23
|
+
export declare class TraceRecorder {
|
|
24
|
+
private readonly sessionId;
|
|
25
|
+
private stream;
|
|
26
|
+
private seq;
|
|
27
|
+
private readonly tracePath;
|
|
28
|
+
private opened;
|
|
29
|
+
constructor(sessionId: string, traceDir?: string);
|
|
30
|
+
/** Path to the trace file for this session */
|
|
31
|
+
get path(): string;
|
|
32
|
+
/** Record an agent event. Fire-and-forget — never throws. */
|
|
33
|
+
record(event: AgentEvent): void;
|
|
34
|
+
/** Close the trace file. Safe to call multiple times. */
|
|
35
|
+
stop(): void;
|
|
36
|
+
private open;
|
|
37
|
+
}
|
|
38
|
+
//# sourceMappingURL=trace-recorder.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"trace-recorder.d.ts","sourceRoot":"","sources":["../src/trace-recorder.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAKH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAE7C,+BAA+B;AAC/B,MAAM,WAAW,UAAU;IACzB,oBAAoB;IACpB,EAAE,EAAE,MAAM,CAAC;IACX,qCAAqC;IACrC,GAAG,EAAE,MAAM,CAAC;IACZ,8BAA8B;IAC9B,KAAK,EAAE,UAAU,CAAC;CACnB;AAiBD,qBAAa,aAAa;IAMZ,OAAO,CAAC,QAAQ,CAAC,SAAS;IALtC,OAAO,CAAC,MAAM,CAA4B;IAC1C,OAAO,CAAC,GAAG,CAAK;IAChB,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;IACnC,OAAO,CAAC,MAAM,CAAS;gBAEM,SAAS,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM;IAMjE,8CAA8C;IAC9C,IAAI,IAAI,IAAI,MAAM,CAEjB;IAED,6DAA6D;IAC7D,MAAM,CAAC,KAAK,EAAE,UAAU,GAAG,IAAI;IAgB/B,yDAAyD;IACzD,IAAI,IAAI,IAAI;IAaZ,OAAO,CAAC,IAAI;CAYb"}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module trace-recorder
|
|
3
|
+
* @description Lightweight append-only session trace recorder.
|
|
4
|
+
*
|
|
5
|
+
* Records every observable agent loop event to `.yuan/traces/<sessionId>.jsonl`.
|
|
6
|
+
* Format: one JSON object per line (JSONL), allowing step-by-step replay.
|
|
7
|
+
*
|
|
8
|
+
* Design constraints:
|
|
9
|
+
* - Never blocks the main loop (all writes are fire-and-forget)
|
|
10
|
+
* - Never throws (all errors are swallowed silently)
|
|
11
|
+
* - File handle stays open during session, closed on stop()
|
|
12
|
+
*/
|
|
13
|
+
import { mkdirSync, createWriteStream } from "node:fs";
|
|
14
|
+
import { join, dirname } from "node:path";
|
|
15
|
+
import { homedir } from "node:os";
|
|
16
|
+
/** Events worth recording — filter out noisy deltas */
|
|
17
|
+
const TRACE_KINDS = new Set([
|
|
18
|
+
"agent:phase_transition",
|
|
19
|
+
"agent:tool_start",
|
|
20
|
+
"agent:tool_result",
|
|
21
|
+
"agent:file_change",
|
|
22
|
+
"agent:qa_result",
|
|
23
|
+
"agent:evidence_report",
|
|
24
|
+
"agent:iteration",
|
|
25
|
+
"agent:completed",
|
|
26
|
+
"agent:error",
|
|
27
|
+
"agent:approval_needed",
|
|
28
|
+
"agent:bg_update",
|
|
29
|
+
]);
|
|
30
|
+
export class TraceRecorder {
|
|
31
|
+
sessionId;
|
|
32
|
+
stream = null;
|
|
33
|
+
seq = 0;
|
|
34
|
+
tracePath;
|
|
35
|
+
opened = false;
|
|
36
|
+
constructor(sessionId, traceDir) {
|
|
37
|
+
this.sessionId = sessionId;
|
|
38
|
+
const base = traceDir ?? join(homedir(), ".yuan", "traces");
|
|
39
|
+
const date = new Date().toISOString().slice(0, 10); // YYYY-MM-DD
|
|
40
|
+
this.tracePath = join(base, `${date}-${sessionId}.jsonl`);
|
|
41
|
+
}
|
|
42
|
+
/** Path to the trace file for this session */
|
|
43
|
+
get path() {
|
|
44
|
+
return this.tracePath;
|
|
45
|
+
}
|
|
46
|
+
/** Record an agent event. Fire-and-forget — never throws. */
|
|
47
|
+
record(event) {
|
|
48
|
+
if (!TRACE_KINDS.has(event.kind))
|
|
49
|
+
return;
|
|
50
|
+
try {
|
|
51
|
+
if (!this.opened)
|
|
52
|
+
this.open();
|
|
53
|
+
if (!this.stream)
|
|
54
|
+
return;
|
|
55
|
+
const entry = {
|
|
56
|
+
ts: new Date().toISOString(),
|
|
57
|
+
seq: this.seq++,
|
|
58
|
+
event,
|
|
59
|
+
};
|
|
60
|
+
this.stream.write(JSON.stringify(entry) + "\n");
|
|
61
|
+
}
|
|
62
|
+
catch {
|
|
63
|
+
// never block the main loop
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
/** Close the trace file. Safe to call multiple times. */
|
|
67
|
+
stop() {
|
|
68
|
+
try {
|
|
69
|
+
if (this.stream) {
|
|
70
|
+
this.stream.end();
|
|
71
|
+
this.stream = null;
|
|
72
|
+
// Reset so record() can reopen if needed after dispose/restart
|
|
73
|
+
this.opened = false;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
catch {
|
|
77
|
+
// swallow
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
open() {
|
|
81
|
+
try {
|
|
82
|
+
mkdirSync(dirname(this.tracePath), { recursive: true });
|
|
83
|
+
this.stream = createWriteStream(this.tracePath, { flags: "a", encoding: "utf8" });
|
|
84
|
+
this.stream.on("error", () => {
|
|
85
|
+
this.stream = null;
|
|
86
|
+
});
|
|
87
|
+
this.opened = true;
|
|
88
|
+
}
|
|
89
|
+
catch {
|
|
90
|
+
this.opened = true; // prevent retry storms
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
//# sourceMappingURL=trace-recorder.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"trace-recorder.js","sourceRoot":"","sources":["../src/trace-recorder.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module trust-economics
|
|
3
|
+
* @description Trust/Approval Economics — tracks trust scores per action class.
|
|
4
|
+
* Produces trust RECOMMENDATIONS but never auto-relaxes approval thresholds.
|
|
5
|
+
*
|
|
6
|
+
* Storage: ~/.yuan/trust-scores/{projectHash}.json
|
|
7
|
+
*
|
|
8
|
+
* Safety: Trust scores are informational only. ApprovalManager thresholds
|
|
9
|
+
* are NOT modified automatically. No action class is ever auto-approved.
|
|
10
|
+
*/
|
|
11
|
+
import { EventEmitter } from "events";
|
|
12
|
+
export type ActionClass = "file_read" | "file_write" | "file_edit" | "file_delete" | "shell_exec_safe" | "shell_exec_risky" | "git_read" | "git_write" | "network_fetch" | "mcp_call";
|
|
13
|
+
export interface TrustRecord {
|
|
14
|
+
actionClass: ActionClass;
|
|
15
|
+
successCount: number;
|
|
16
|
+
failCount: number;
|
|
17
|
+
lastSuccess: string | null;
|
|
18
|
+
lastFail: string | null;
|
|
19
|
+
/** Never decremented below 0. A single high-risk failure resets to 0. */
|
|
20
|
+
trustScore: number;
|
|
21
|
+
}
|
|
22
|
+
export interface TrustRecommendation {
|
|
23
|
+
actionClass: ActionClass;
|
|
24
|
+
currentTrustScore: number;
|
|
25
|
+
recommendation: "auto_approve_candidate" | "require_review" | "require_explicit_approval";
|
|
26
|
+
reasoning: string;
|
|
27
|
+
}
|
|
28
|
+
export interface TrustEconomicsConfig {
|
|
29
|
+
projectPath?: string;
|
|
30
|
+
storageDir?: string;
|
|
31
|
+
}
|
|
32
|
+
export declare class TrustEconomics extends EventEmitter {
|
|
33
|
+
private readonly storageFile;
|
|
34
|
+
private records;
|
|
35
|
+
constructor(config?: TrustEconomicsConfig);
|
|
36
|
+
/** Record an action outcome. High-risk failure resets trust to 0. */
|
|
37
|
+
record(actionClass: ActionClass, success: boolean, isHighRisk?: boolean): void;
|
|
38
|
+
/**
|
|
39
|
+
* Get trust recommendations (read-only, never modifies approval thresholds).
|
|
40
|
+
* Emits agent:trust_update.
|
|
41
|
+
*/
|
|
42
|
+
getRecommendations(): TrustRecommendation[];
|
|
43
|
+
/** Get trust record for a specific action class. */
|
|
44
|
+
getTrust(actionClass: ActionClass): TrustRecord | null;
|
|
45
|
+
/** Get all trust records. */
|
|
46
|
+
getAll(): TrustRecord[];
|
|
47
|
+
private _load;
|
|
48
|
+
private _save;
|
|
49
|
+
}
|
|
50
|
+
//# sourceMappingURL=trust-economics.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"trust-economics.d.ts","sourceRoot":"","sources":["../src/trust-economics.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AAKtC,MAAM,MAAM,WAAW,GACnB,WAAW,GACX,YAAY,GACZ,WAAW,GACX,aAAa,GACb,iBAAiB,GACjB,kBAAkB,GAClB,UAAU,GACV,WAAW,GACX,eAAe,GACf,UAAU,CAAC;AAEf,MAAM,WAAW,WAAW;IAC1B,WAAW,EAAE,WAAW,CAAC;IACzB,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,yEAAyE;IACzE,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,mBAAmB;IAClC,WAAW,EAAE,WAAW,CAAC;IACzB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,cAAc,EAAE,wBAAwB,GAAG,gBAAgB,GAAG,2BAA2B,CAAC;IAC1F,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,oBAAoB;IACnC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAkCD,qBAAa,cAAe,SAAQ,YAAY;IAC9C,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAS;IACrC,OAAO,CAAC,OAAO,CAAgC;gBAEnC,MAAM,GAAE,oBAAyB;IAY7C,qEAAqE;IACrE,MAAM,CAAC,WAAW,EAAE,WAAW,EAAE,OAAO,EAAE,OAAO,EAAE,UAAU,UAAQ,GAAG,IAAI;IAsC5E;;;OAGG;IACH,kBAAkB,IAAI,mBAAmB,EAAE;IAc3C,oDAAoD;IACpD,QAAQ,CAAC,WAAW,EAAE,WAAW,GAAG,WAAW,GAAG,IAAI;IAItD,6BAA6B;IAC7B,MAAM,IAAI,WAAW,EAAE;IAMvB,OAAO,CAAC,KAAK;IAkBb,OAAO,CAAC,KAAK;CAUd"}
|