@yuaone/core 0.4.9 → 0.6.1

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/README.md CHANGED
@@ -1,15 +1,59 @@
1
- # @yuan/core
1
+ # @yuaone/core
2
2
 
3
3
  Agent runtime for YUAN coding agent.
4
4
 
5
- Part of [YUAN](../../README.md).
5
+ ```bash
6
+ npm install @yuaone/core
7
+ ```
6
8
 
7
- ## Install
9
+ ## Usage
8
10
 
9
- ```bash
10
- npm install @yuan/core
11
+ ```typescript
12
+ import { AgentLoop, createAgentLoop } from "@yuaone/core";
13
+
14
+ const loop = createAgentLoop({
15
+ provider: "anthropic",
16
+ apiKey: process.env.ANTHROPIC_API_KEY,
17
+ model: "claude-sonnet-4-6",
18
+ workDir: process.cwd(),
19
+ });
20
+
21
+ for await (const event of loop.run("refactor auth.ts to async/await")) {
22
+ if (event.kind === "agent:token") process.stdout.write(event.content);
23
+ if (event.kind === "agent:completed") break;
24
+ }
25
+ ```
26
+
27
+ ## Architecture
28
+
29
+ | Module | Description |
30
+ |--------|-------------|
31
+ | `AgentLoop` | Core tool-use loop — LLM ↔ tools ↔ approval |
32
+ | `HierarchicalPlanner` | Task decomposition with dependency ordering |
33
+ | `ExecutionPolicyEngine` | Token/cost budget per iteration |
34
+ | `ContinuationEngine` | Checkpoint every 3 iters, recovery on error |
35
+ | `ReflexionEngine` | Per-iteration self-reflection & insight injection |
36
+ | `WorldStateCollector` | Tracks file changes across iterations |
37
+ | `QAPipeline` | Quick + thorough quality checks post-execution |
38
+ | `Governor` | Safety/security scanning before tool execution |
39
+ | `AutoFix` | Automatic lint/type error repair |
40
+ | `ContextManager` | Token budget management & compaction |
41
+
42
+ ## Events
43
+
44
+ ```typescript
45
+ type AgentEvent =
46
+ | { kind: "agent:thinking"; content: string }
47
+ | { kind: "agent:token"; content: string }
48
+ | { kind: "agent:tool_call"; toolName: string; arguments: unknown }
49
+ | { kind: "agent:tool_result"; toolName: string; result: string; durationMs: number }
50
+ | { kind: "agent:approval_needed"; action: { tool: string; input: unknown } }
51
+ | { kind: "agent:completed"; message: string }
52
+ | { kind: "agent:error"; message: string; retryable: boolean }
53
+ | { kind: "agent:token_usage"; input: number; output: number }
54
+ | { kind: "agent:qa_result"; stage: "quick" | "thorough"; passed: boolean; issues: string[] }
11
55
  ```
12
56
 
13
57
  ## License
14
58
 
15
- AGPL-3.0
59
+ AGPL-3.0 — part of [YUAN](https://github.com/yuaone/yuan).
@@ -75,33 +75,6 @@ export interface AgentLoopOptions {
75
75
  /** Enable background agents (persistent monitors, default false — opt-in) */
76
76
  enableBackgroundAgents?: boolean;
77
77
  }
78
- /**
79
- * AgentLoop — YUAN 에이전트의 핵심 실행 루프.
80
- *
81
- * 동작 흐름:
82
- * 1. 사용자 메시지 수신
83
- * 2. 시스템 프롬프트 + 히스토리로 LLM 호출
84
- * 3. LLM 응답에서 tool_call 파싱
85
- * 4. Governor가 안전성 검증
86
- * 5. 도구 실행 → 결과를 히스토리에 추가
87
- * 6. LLM에 결과 피드백 → 2번으로 반복
88
- * 7. 종료 조건 충족 시 결과 반환
89
- *
90
- * @example
91
- * ```typescript
92
- * const loop = new AgentLoop({
93
- * config: agentConfig,
94
- * toolExecutor: executor,
95
- * governorConfig: { planTier: "PRO" },
96
- * });
97
- *
98
- * loop.on("event", (event: AgentEvent) => {
99
- * // SSE 스트리밍
100
- * });
101
- *
102
- * const result = await loop.run("모든 console.log를 제거해줘");
103
- * ```
104
- */
105
78
  export declare class AgentLoop extends EventEmitter {
106
79
  private readonly abortSignal?;
107
80
  private readonly llmClient;
@@ -419,6 +392,11 @@ export declare class AgentLoop extends EventEmitter {
419
392
  private handleSoftContextOverflow;
420
393
  /** MCP 클라이언트 정리 (세션 종료 시 호출) */
421
394
  dispose(): Promise<void>;
395
+ /**
396
+ * Builds a Map<filePath, toolOutput> for all changed files from write/edit tool results.
397
+ * Used by selfReflection deepVerify and quickVerify.
398
+ */
399
+ private buildChangedFilesMap;
422
400
  private emitEvent;
423
401
  private emitReasoning;
424
402
  private emitSubagent;
@@ -1 +1 @@
1
- {"version":3,"file":"agent-loop.d.ts","sourceRoot":"","sources":["../src/agent-loop.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"agent-loop.d.ts","sourceRoot":"","sources":["../src/agent-loop.ts"],"names":[],"mappings":"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"}
@@ -77,6 +77,8 @@ import { QAPipeline } from "./qa-pipeline.js";
77
77
  * const result = await loop.run("모든 console.log를 제거해줘");
78
78
  * ```
79
79
  */
80
+ /** Minimum confidence for classification-based hints/routing to activate */
81
+ const CLASSIFICATION_CONFIDENCE_THRESHOLD = 0.6;
80
82
  export class AgentLoop extends EventEmitter {
81
83
  abortSignal;
82
84
  llmClient;
@@ -481,7 +483,7 @@ export class AgentLoop extends EventEmitter {
481
483
  const learnedSkills = this.skillLearner.getAllSkills();
482
484
  if (learnedSkills.length > 0) {
483
485
  const skillNames = learnedSkills
484
- .filter((s) => s.confidence >= 0.3)
486
+ .filter((s) => s.confidence >= CLASSIFICATION_CONFIDENCE_THRESHOLD)
485
487
  .map((s) => s.id);
486
488
  if (skillNames.length > 0) {
487
489
  this.contextManager.addMessage({
@@ -615,7 +617,7 @@ export class AgentLoop extends EventEmitter {
615
617
  buildMemoryContext(memory) {
616
618
  const parts = [];
617
619
  // 높은 confidence 학습만 포함
618
- const highConfLearnings = memory.learnings.filter((l) => l.confidence >= 0.3);
620
+ const highConfLearnings = memory.learnings.filter((l) => l.confidence >= CLASSIFICATION_CONFIDENCE_THRESHOLD);
619
621
  if (highConfLearnings.length > 0) {
620
622
  parts.push("## Things I've Learned About This Project");
621
623
  for (const l of highConfLearnings.slice(0, 20)) {
@@ -648,6 +650,8 @@ export class AgentLoop extends EventEmitter {
648
650
  this.aborted = false;
649
651
  this.reasoningAggregator.reset();
650
652
  this.reasoningTree.reset();
653
+ // Capture before reset so session snapshot gets accurate file list
654
+ const prevChangedFiles = [...this.changedFiles];
651
655
  if (!this.resumedFromSession) {
652
656
  this.changedFiles = [];
653
657
  this.allToolResults = [];
@@ -698,7 +702,7 @@ export class AgentLoop extends EventEmitter {
698
702
  snapshot,
699
703
  messages: this.contextManager.getMessages(),
700
704
  plan: this.activePlan,
701
- changedFiles: this.changedFiles,
705
+ changedFiles: prevChangedFiles,
702
706
  });
703
707
  }
704
708
  // 사용자 입력 검증 (prompt injection 방어)
@@ -738,7 +742,7 @@ export class AgentLoop extends EventEmitter {
738
742
  }
739
743
  // Task 분류 → 시스템 프롬프트에 tool sequence hint 주입
740
744
  const classification = this.taskClassifier.classify(userMessage);
741
- if (classification.confidence >= 0.3) {
745
+ if (classification.confidence >= CLASSIFICATION_CONFIDENCE_THRESHOLD) {
742
746
  const classificationHint = this.taskClassifier.formatForSystemPrompt(classification);
743
747
  this.contextManager.addMessage({
744
748
  role: "system",
@@ -748,7 +752,7 @@ export class AgentLoop extends EventEmitter {
748
752
  // Specialist routing: 태스크 타입에 맞는 전문 에이전트 설정 주입
749
753
  if (classification.specialistDomain) {
750
754
  const specialistMatch = this.specialistRegistry.findSpecialist(classification.specialistDomain);
751
- if (specialistMatch && specialistMatch.confidence >= 0.5) {
755
+ if (specialistMatch && specialistMatch.confidence >= CLASSIFICATION_CONFIDENCE_THRESHOLD) {
752
756
  this.contextManager.addMessage({
753
757
  role: "system",
754
758
  content: `[Specialist: ${specialistMatch.specialist.name}] ${specialistMatch.specialist.systemPrompt.slice(0, 500)}`,
@@ -756,13 +760,13 @@ export class AgentLoop extends EventEmitter {
756
760
  }
757
761
  }
758
762
  // Tool Planning: 태스크 타입에 맞는 도구 실행 계획 힌트 주입
759
- if (this.enableToolPlanning && classification.confidence >= 0.3) {
763
+ if (this.enableToolPlanning && classification.confidence >= CLASSIFICATION_CONFIDENCE_THRESHOLD) {
760
764
  const planContext = {
761
765
  userMessage,
762
766
  };
763
767
  this.currentToolPlan = this.toolPlanner.planForTask(classification.type, planContext);
764
768
  this.executedToolNames = [];
765
- if (this.currentToolPlan.confidence >= 0.5) {
769
+ if (this.currentToolPlan.confidence >= CLASSIFICATION_CONFIDENCE_THRESHOLD) {
766
770
  const planHint = this.toolPlanner.formatPlanHint(this.currentToolPlan);
767
771
  this.contextManager.addMessage({
768
772
  role: "system",
@@ -903,6 +907,18 @@ export class AgentLoop extends EventEmitter {
903
907
  return result;
904
908
  }
905
909
  catch (err) {
910
+ // Attempt recovery from last checkpoint via ContinuationEngine
911
+ if (this.continuationEngine) {
912
+ try {
913
+ const recovered = await this.continuationEngine.findLatestCheckpoint();
914
+ if (recovered) {
915
+ this.emitReasoning(`recovered from checkpoint at iteration ${recovered.iterationsCompleted ?? "unknown"}`);
916
+ }
917
+ }
918
+ catch {
919
+ // Recovery failure is non-fatal
920
+ }
921
+ }
906
922
  return this.handleFatalError(err);
907
923
  }
908
924
  }
@@ -1409,7 +1425,21 @@ export class AgentLoop extends EventEmitter {
1409
1425
  this.iterationCount = iteration;
1410
1426
  const iterationStart = Date.now();
1411
1427
  this.emitReasoning(`iteration ${iteration}: preparing context`);
1412
- this.iterationSystemMsgCount = 0; // Reset per-iteration system message counter
1428
+ this.iterationSystemMsgCount = 0; // Reset per-iteration (prevents accumulation across iterations)
1429
+ // Policy validation — check cost limits from ExecutionPolicyEngine
1430
+ if (this.policyEngine) {
1431
+ try {
1432
+ const costPolicy = this.policyEngine.get("cost");
1433
+ const iterationTokensUsed = this.tokenUsage.input + this.tokenUsage.output;
1434
+ if (costPolicy.maxTokensPerIteration > 0 && iterationTokensUsed > costPolicy.maxTokensPerIteration) {
1435
+ this.emitReasoning(`policy blocked iteration ${iteration}: token usage ${iterationTokensUsed} exceeds maxTokensPerIteration ${costPolicy.maxTokensPerIteration}`);
1436
+ return { reason: "BUDGET_EXHAUSTED", tokensUsed: iterationTokensUsed };
1437
+ }
1438
+ }
1439
+ catch {
1440
+ // Policy engine failure is non-fatal
1441
+ }
1442
+ }
1413
1443
  // Soft context rollover:
1414
1444
  // checkpoint first, then let ContextManager compact instead of aborting/throwing.
1415
1445
  const contextUsageRatio = this.contextManager.getUsageRatio();
@@ -1576,15 +1606,7 @@ export class AgentLoop extends EventEmitter {
1576
1606
  // Level 2: Deep verification before declaring completion
1577
1607
  if (this.selfReflection && this.changedFiles.length > 0) {
1578
1608
  try {
1579
- const changedFilesMap = new Map();
1580
- for (const filePath of this.changedFiles) {
1581
- const lastWrite = this.allToolResults
1582
- .filter((r) => r.name === "file_write" || r.name === "file_edit")
1583
- .find((r) => r.output.includes(filePath));
1584
- if (lastWrite) {
1585
- changedFilesMap.set(filePath, lastWrite.output);
1586
- }
1587
- }
1609
+ const changedFilesMap = this.buildChangedFilesMap();
1588
1610
  const verifyFn = async (prompt) => {
1589
1611
  const verifyResponse = await this.llmClient.chat([
1590
1612
  { role: "system", content: "You are a meticulous code reviewer." },
@@ -1698,9 +1720,15 @@ export class AgentLoop extends EventEmitter {
1698
1720
  const thoroughFailures = thoroughResult.stages
1699
1721
  .flatMap((s) => s.checks)
1700
1722
  .filter((c) => c.status === "fail");
1723
+ const thoroughIssues = thoroughFailures
1724
+ .slice(0, 10)
1725
+ .map((c) => `[${c.severity}] ${c.name}: ${c.message}`);
1726
+ // Emit structured qa_result event for TUI display
1701
1727
  this.emitEvent({
1702
- kind: "agent:thinking",
1703
- content: `QA thorough check at completion: ${thoroughResult.overall} (${thoroughFailures.length} failure(s) across ${this.changedFiles.length} file(s)).`,
1728
+ kind: "agent:qa_result",
1729
+ stage: "thorough",
1730
+ passed: thoroughFailures.length === 0,
1731
+ issues: thoroughIssues,
1704
1732
  });
1705
1733
  this.lastQAResult = thoroughResult;
1706
1734
  }
@@ -1791,6 +1819,16 @@ export class AgentLoop extends EventEmitter {
1791
1819
  const failedChecks = qaResult.stages
1792
1820
  .flatMap((s) => s.checks)
1793
1821
  .filter((c) => c.status === "fail" || c.status === "warn");
1822
+ const qaIssues = failedChecks
1823
+ .slice(0, 10)
1824
+ .map((c) => `[${c.severity}] ${c.name}: ${c.message}`);
1825
+ // Emit structured qa_result event for TUI display
1826
+ this.emitEvent({
1827
+ kind: "agent:qa_result",
1828
+ stage: "quick",
1829
+ passed: failedChecks.length === 0,
1830
+ issues: qaIssues,
1831
+ });
1794
1832
  if (failedChecks.length > 0 && this.iterationSystemMsgCount < 5) {
1795
1833
  const checkSummary = failedChecks
1796
1834
  .slice(0, 5)
@@ -1801,16 +1839,6 @@ export class AgentLoop extends EventEmitter {
1801
1839
  content: `[QA Quick Check] ${failedChecks.length} issue(s) detected in modified files:\n${checkSummary}`,
1802
1840
  });
1803
1841
  this.iterationSystemMsgCount++;
1804
- this.emitEvent({
1805
- kind: "agent:thinking",
1806
- content: `QA quick check: ${failedChecks.length} issue(s) in ${this.iterationWriteToolPaths.length} file(s).`,
1807
- });
1808
- }
1809
- else if (failedChecks.length === 0) {
1810
- this.emitEvent({
1811
- kind: "agent:thinking",
1812
- content: `QA quick check passed for ${this.iterationWriteToolPaths.length} file(s).`,
1813
- });
1814
1842
  }
1815
1843
  }
1816
1844
  catch {
@@ -1890,20 +1918,41 @@ export class AgentLoop extends EventEmitter {
1890
1918
  };
1891
1919
  await this.sessionPersistence.checkpoint(this.sessionId, checkpoint);
1892
1920
  }
1921
+ // ReflexionEngine: reflect on this iteration's tool results
1922
+ if (this.reflexionEngine && toolResults.length > 0) {
1923
+ try {
1924
+ const iterReflection = this.reflexionEngine.reflect({
1925
+ goal: "",
1926
+ runId: `iter-${iteration}-${randomUUID()}`,
1927
+ termination: { reason: "USER_CANCELLED" },
1928
+ toolResults,
1929
+ messages: this.contextManager.getMessages(),
1930
+ tokensUsed: this.tokenUsage.total,
1931
+ durationMs: Date.now() - iterationStart,
1932
+ changedFiles: this.changedFiles,
1933
+ });
1934
+ // Build insight from available reflection fields
1935
+ const insight = iterReflection.reflection.alternativeApproach ??
1936
+ (iterReflection.reflection.whatFailed.length > 0
1937
+ ? iterReflection.reflection.whatFailed.slice(0, 2).join("; ")
1938
+ : null);
1939
+ if (insight && insight.length > 10 && this.iterationSystemMsgCount < 5) {
1940
+ this.contextManager.addMessage({
1941
+ role: "system",
1942
+ content: `[Reflection] ${insight}`,
1943
+ });
1944
+ this.iterationSystemMsgCount++;
1945
+ }
1946
+ }
1947
+ catch {
1948
+ // Reflection failure is non-fatal
1949
+ }
1950
+ }
1893
1951
  // Level 1: Quick verification after every 3rd iteration
1894
1952
  if (this.selfReflection && iteration % 3 === 0) {
1895
1953
  try {
1896
1954
  this.emitSubagent("verifier", "start", "running quick verification");
1897
- const changedFilesMap = new Map();
1898
- for (const filePath of this.changedFiles) {
1899
- // Collect changed file contents from tool results
1900
- const lastWrite = this.allToolResults
1901
- .filter((r) => r.name === "file_write" || r.name === "file_edit")
1902
- .find((r) => r.output.includes(filePath));
1903
- if (lastWrite) {
1904
- changedFilesMap.set(filePath, lastWrite.output);
1905
- }
1906
- }
1955
+ const changedFilesMap = this.buildChangedFilesMap();
1907
1956
  const quickResult = await this.selfReflection.quickVerify(changedFilesMap, async (prompt) => {
1908
1957
  const verifyResponse = await this.llmClient.chat([
1909
1958
  { role: "system", content: "You are a code verification assistant." },
@@ -2105,6 +2154,28 @@ export class AgentLoop extends EventEmitter {
2105
2154
  await this.saveAutoCheckpoint(iteration);
2106
2155
  this.checkpointSaved = true;
2107
2156
  }
2157
+ // ContinuationEngine: checkpoint current state after each iteration (every 3 iterations, non-fatal)
2158
+ if (this.continuationEngine && iteration > 0 && iteration % 3 === 0 && !this.checkpointSaved) {
2159
+ try {
2160
+ const progress = this.extractProgress();
2161
+ await this.continuationEngine.saveCheckpoint({
2162
+ sessionId: this.sessionId ?? `session-${Date.now()}`,
2163
+ goal: this.contextManager.getMessages().find((m) => m.role === "user")?.content ?? "",
2164
+ progress,
2165
+ changedFiles: [...this.changedFiles].map((p) => ({ path: p, diff: "" })),
2166
+ workingMemory: this.buildWorkingMemorySummary(),
2167
+ yuanMdUpdates: [],
2168
+ errors: [],
2169
+ contextUsageAtSave: this.config.loop.totalTokenBudget > 0 ? this.tokenUsage.total / this.config.loop.totalTokenBudget : 0,
2170
+ totalTokensUsed: this.tokenUsage.total,
2171
+ iterationsCompleted: iteration,
2172
+ createdAt: new Date(),
2173
+ });
2174
+ }
2175
+ catch {
2176
+ // Checkpoint failure is non-fatal
2177
+ }
2178
+ }
2108
2179
  // ContinuousReflection: 매 5 iteration마다 비상 체크포인트 트리거
2109
2180
  // (정기 타이머 외에 iteration 기반 추가 안전망)
2110
2181
  if (this.continuousReflection?.isRunning() &&
@@ -2432,8 +2503,22 @@ export class AgentLoop extends EventEmitter {
2432
2503
  this.iterationTsFilesModified.push(filePathStr);
2433
2504
  }
2434
2505
  this.emitEvent({ kind: "agent:file_change", path: filePathStr, diff: result.output });
2506
+ // Update world state after file modification
2507
+ if (this.config.loop.projectPath) {
2508
+ const wsProjectPath = this.config.loop.projectPath;
2509
+ new WorldStateCollector({ projectPath: wsProjectPath, skipTest: true })
2510
+ .collect()
2511
+ .then((snapshot) => { this.worldState = snapshot; })
2512
+ .catch(() => {
2513
+ // Non-fatal: world state update failure should not interrupt tool execution
2514
+ });
2515
+ }
2435
2516
  if (this.impactAnalyzer) {
2436
- this.analyzeFileImpact(filePathStr).catch(() => { });
2517
+ this.analyzeFileImpact(filePathStr).catch((err) => {
2518
+ // Non-fatal: impact analysis failure should not interrupt tool execution
2519
+ const msg = err instanceof Error ? err.message : String(err);
2520
+ console.warn(`[AgentLoop] impact analysis skipped for ${filePathStr}: ${msg}`);
2521
+ });
2437
2522
  }
2438
2523
  }
2439
2524
  const fixPrompt = await this.validateAndFeedback(toolCall.name, result);
@@ -3022,6 +3107,22 @@ export class AgentLoop extends EventEmitter {
3022
3107
  }
3023
3108
  }
3024
3109
  // ─── Helpers ───
3110
+ /**
3111
+ * Builds a Map<filePath, toolOutput> for all changed files from write/edit tool results.
3112
+ * Used by selfReflection deepVerify and quickVerify.
3113
+ */
3114
+ buildChangedFilesMap() {
3115
+ const map = new Map();
3116
+ for (const filePath of this.changedFiles) {
3117
+ const lastWrite = this.allToolResults
3118
+ .filter((r) => r.name === "file_write" || r.name === "file_edit")
3119
+ .find((r) => r.output.includes(filePath));
3120
+ if (lastWrite) {
3121
+ map.set(filePath, lastWrite.output);
3122
+ }
3123
+ }
3124
+ return map;
3125
+ }
3025
3126
  emitEvent(event) {
3026
3127
  this.emit("event", event);
3027
3128
  }