@yuaone/core 0.9.14 → 0.9.17
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/agent-loop.d.ts +19 -0
- package/dist/agent-loop.d.ts.map +1 -1
- package/dist/agent-loop.js +220 -22
- package/dist/agent-loop.js.map +1 -1
- package/dist/causal-chain-resolver.d.ts +45 -0
- package/dist/causal-chain-resolver.d.ts.map +1 -0
- package/dist/causal-chain-resolver.js +345 -0
- package/dist/causal-chain-resolver.js.map +1 -0
- package/dist/continuous-reflection.d.ts +8 -0
- package/dist/continuous-reflection.d.ts.map +1 -1
- package/dist/continuous-reflection.js.map +1 -1
- package/dist/index.d.ts +5 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -0
- package/dist/index.js.map +1 -1
- package/dist/language-registry.d.ts.map +1 -1
- package/dist/language-registry.js +127 -0
- package/dist/language-registry.js.map +1 -1
- package/dist/llm-client.d.ts +5 -0
- package/dist/llm-client.d.ts.map +1 -1
- package/dist/llm-client.js +262 -14
- package/dist/llm-client.js.map +1 -1
- package/dist/mcp-config-loader.d.ts +30 -0
- package/dist/mcp-config-loader.d.ts.map +1 -0
- package/dist/mcp-config-loader.js +82 -0
- package/dist/mcp-config-loader.js.map +1 -0
- package/dist/system-prompt.d.ts.map +1 -1
- package/dist/system-prompt.js +275 -49
- package/dist/system-prompt.js.map +1 -1
- package/dist/vision-intent-detector.d.ts +35 -0
- package/dist/vision-intent-detector.d.ts.map +1 -0
- package/dist/vision-intent-detector.js +241 -0
- package/dist/vision-intent-detector.js.map +1 -0
- package/package.json +1 -1
package/dist/agent-loop.d.ts
CHANGED
|
@@ -128,6 +128,10 @@ export declare class AgentLoop extends EventEmitter {
|
|
|
128
128
|
private readonly policyOverrides?;
|
|
129
129
|
private checkpointSaved;
|
|
130
130
|
private iterationCount;
|
|
131
|
+
private agentHypothesis;
|
|
132
|
+
private agentFailureSig;
|
|
133
|
+
private agentVerifyState;
|
|
134
|
+
private lastAgentStateInjection;
|
|
131
135
|
private originalSnapshots;
|
|
132
136
|
private previousStrategies;
|
|
133
137
|
private pluginRegistry;
|
|
@@ -217,6 +221,8 @@ export declare class AgentLoop extends EventEmitter {
|
|
|
217
221
|
private capabilitySelfModel;
|
|
218
222
|
private strategyMarket;
|
|
219
223
|
private sessionRunCount;
|
|
224
|
+
/** Vision Intent Detector — auto-triggers image reads when LLM/user signals intent */
|
|
225
|
+
private readonly visionIntentDetector;
|
|
220
226
|
/**
|
|
221
227
|
* Restore AgentLoop state from persisted session (yuan resume)
|
|
222
228
|
*/
|
|
@@ -280,6 +286,19 @@ export declare class AgentLoop extends EventEmitter {
|
|
|
280
286
|
* 읽기 전용 — reflection tick마다 호출된다.
|
|
281
287
|
*/
|
|
282
288
|
getStateSnapshot(): AgentStateSnapshot;
|
|
289
|
+
/**
|
|
290
|
+
* 매 이터레이션 LLM 호출 전 compact AgentState를 컨텍스트에 주입한다.
|
|
291
|
+
* 3 이터레이션마다 갱신하여 컨텍스트 팽창 방지.
|
|
292
|
+
*/
|
|
293
|
+
private injectAgentStateIfNeeded;
|
|
294
|
+
/**
|
|
295
|
+
* LLM 응답 텍스트에서 "Updated hypothesis:" 마커를 파싱해 hypothesis를 갱신한다.
|
|
296
|
+
*/
|
|
297
|
+
updateHypothesisFromResponse(text: string): void;
|
|
298
|
+
/**
|
|
299
|
+
* 검증 결과를 기록한다. CausalChainResolver 트리거에 사용.
|
|
300
|
+
*/
|
|
301
|
+
recordVerifyResult(state: "pass" | "fail" | "pending", signature?: string): void;
|
|
283
302
|
/**
|
|
284
303
|
* ContinuousReflection 인스턴스를 반환한다.
|
|
285
304
|
* 외부에서 ESC 토글(pause/resume) 또는 이벤트 구독에 사용.
|
package/dist/agent-loop.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agent-loop.d.ts","sourceRoot":"","sources":["../src/agent-loop.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAI3C,OAAO,KAAK,EACV,WAAW,EAEX,gBAAgB,EAChB,OAAO,EAGP,YAAY,EACZ,UAAU,EACX,MAAM,YAAY,CAAC;AAEpB,OAAO,EAAY,KAAK,cAAc,EAAE,MAAM,eAAe,CAAC;AAC9D,OAAO,EAAkB,KAAK,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AACjF,OAAO,EAEL,KAAK,WAAW,EAGjB,MAAM,0BAA0B,CAAC;AAQlC,OAAO,EACL,eAAe,EACf,KAAK,eAAe,EAEpB,KAAK,kBAAkB,EACxB,MAAM,eAAe,CAAC;AACvB,OAAO,EACL,WAAW,EACX,KAAK,aAAa,EAEnB,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC1D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAGlD,OAAO,EAAqB,KAAK,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAC7E,OAAO,EAEL,KAAK,gBAAgB,EAGtB,MAAM,2BAA2B,CAAC;AAInC,OAAO,EAAE,kBAAkB,EAAmB,MAAM,mBAAmB,CAAC;AACxE,OAAO,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AAG9D,OAAO,EAAa,KAAK,eAAe,EAAE,MAAM,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"agent-loop.d.ts","sourceRoot":"","sources":["../src/agent-loop.ts"],"names":[],"mappings":"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"}
|
package/dist/agent-loop.js
CHANGED
|
@@ -29,6 +29,7 @@ import { TokenBudgetManager } from "./token-budget.js";
|
|
|
29
29
|
import { ContinuationEngine } from "./continuation-engine.js";
|
|
30
30
|
import { MemoryUpdater } from "./memory-updater.js";
|
|
31
31
|
import { MCPClient } from "./mcp-client.js";
|
|
32
|
+
import { loadMCPConfig } from "./mcp-config-loader.js";
|
|
32
33
|
import { BOUNDS, cap } from "./safe-bounds.js";
|
|
33
34
|
import { WorldStateCollector } from "./world-state.js";
|
|
34
35
|
import { FailureRecovery } from "./failure-recovery.js";
|
|
@@ -80,6 +81,7 @@ import { recordBudgetUsage, checkBudgetShouldHalt } from "./extensions/budget-wi
|
|
|
80
81
|
import { registerToolsInGraph, recordToolOutcomeInGraph } from "./extensions/cap-graph-wiring.js";
|
|
81
82
|
import { getSelfWeaknessContext } from "./extensions/self-model-wiring.js";
|
|
82
83
|
import { initMarketPlaybooks, selectMarketStrategy } from "./extensions/strategy-wiring.js";
|
|
84
|
+
import { VisionIntentDetector } from "./vision-intent-detector.js";
|
|
83
85
|
/**
|
|
84
86
|
* AgentLoop — YUAN 에이전트의 핵심 실행 루프.
|
|
85
87
|
*
|
|
@@ -159,6 +161,10 @@ export class AgentLoop extends EventEmitter {
|
|
|
159
161
|
policyOverrides;
|
|
160
162
|
checkpointSaved = false;
|
|
161
163
|
iterationCount = 0;
|
|
164
|
+
agentHypothesis = undefined;
|
|
165
|
+
agentFailureSig = undefined;
|
|
166
|
+
agentVerifyState = undefined;
|
|
167
|
+
lastAgentStateInjection = 0;
|
|
162
168
|
originalSnapshots = new Map();
|
|
163
169
|
previousStrategies = [];
|
|
164
170
|
pluginRegistry;
|
|
@@ -259,6 +265,8 @@ export class AgentLoop extends EventEmitter {
|
|
|
259
265
|
capabilitySelfModel = null;
|
|
260
266
|
strategyMarket = null;
|
|
261
267
|
sessionRunCount = 0;
|
|
268
|
+
/** Vision Intent Detector — auto-triggers image reads when LLM/user signals intent */
|
|
269
|
+
visionIntentDetector = new VisionIntentDetector();
|
|
262
270
|
/**
|
|
263
271
|
* Restore AgentLoop state from persisted session (yuan resume)
|
|
264
272
|
*/
|
|
@@ -527,18 +535,46 @@ export class AgentLoop extends EventEmitter {
|
|
|
527
535
|
// 체크포인트 복원 실패는 치명적이지 않음
|
|
528
536
|
}
|
|
529
537
|
// MCP 클라이언트 연결
|
|
530
|
-
|
|
538
|
+
// Auto-load ~/.yuan/mcp.json and merge with any programmatically supplied configs
|
|
539
|
+
{
|
|
540
|
+
let mergedMCPConfigs = [...this.mcpServerConfigs];
|
|
531
541
|
try {
|
|
532
|
-
|
|
533
|
-
|
|
542
|
+
const fileConfig = await loadMCPConfig();
|
|
543
|
+
if (fileConfig && fileConfig.servers.length > 0) {
|
|
544
|
+
// Deduplicate by name — programmatic configs take precedence
|
|
545
|
+
const existingNames = new Set(mergedMCPConfigs.map((s) => s.name));
|
|
546
|
+
for (const server of fileConfig.servers) {
|
|
547
|
+
if (!existingNames.has(server.name)) {
|
|
548
|
+
mergedMCPConfigs.push(server);
|
|
549
|
+
}
|
|
550
|
+
}
|
|
551
|
+
}
|
|
552
|
+
}
|
|
553
|
+
catch (mcpLoadErr) {
|
|
554
|
+
// Config parse error — warn and continue without file-based servers
|
|
555
|
+
this.emitEvent({
|
|
556
|
+
kind: "agent:error",
|
|
557
|
+
message: `MCP config load warning: ${mcpLoadErr instanceof Error ? mcpLoadErr.message : String(mcpLoadErr)}`,
|
|
558
|
+
retryable: false,
|
|
534
559
|
});
|
|
535
|
-
await this.mcpClient.connectAll();
|
|
536
|
-
this.mcpToolDefinitions = this.mcpClient.toToolDefinitions();
|
|
537
560
|
}
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
561
|
+
if (mergedMCPConfigs.length > 0) {
|
|
562
|
+
try {
|
|
563
|
+
this.mcpClient = new MCPClient({
|
|
564
|
+
servers: mergedMCPConfigs,
|
|
565
|
+
});
|
|
566
|
+
await this.mcpClient.connectAll();
|
|
567
|
+
this.mcpToolDefinitions = this.mcpClient.toToolDefinitions();
|
|
568
|
+
this.emitEvent({
|
|
569
|
+
kind: "agent:thinking",
|
|
570
|
+
content: `MCP: loaded ${this.mcpToolDefinitions.length} tools from ${mergedMCPConfigs.length} server(s)`,
|
|
571
|
+
});
|
|
572
|
+
}
|
|
573
|
+
catch {
|
|
574
|
+
// MCP 연결 실패는 치명적이지 않음 — 로컬 도구만 사용
|
|
575
|
+
this.mcpClient = null;
|
|
576
|
+
this.mcpToolDefinitions = [];
|
|
577
|
+
}
|
|
542
578
|
}
|
|
543
579
|
}
|
|
544
580
|
// ReflexionEngine 생성
|
|
@@ -905,6 +941,8 @@ export class AgentLoop extends EventEmitter {
|
|
|
905
941
|
this.costOptimizer.reset();
|
|
906
942
|
this.tokenBudgetManager.reset();
|
|
907
943
|
const runStartTime = Date.now();
|
|
944
|
+
// 즉시 start 이벤트 emit — init 전에 TUI 타이머/상태 시작
|
|
945
|
+
this.emitEvent({ kind: "agent:start", goal: userMessage });
|
|
908
946
|
// 첫 실행 시 메모리/프로젝트 컨텍스트 자동 로드
|
|
909
947
|
await this.init();
|
|
910
948
|
if (!this.sessionId) {
|
|
@@ -988,7 +1026,39 @@ export class AgentLoop extends EventEmitter {
|
|
|
988
1026
|
if (this.personaManager) {
|
|
989
1027
|
this.personaManager.analyzeUserMessage(userMessage);
|
|
990
1028
|
}
|
|
991
|
-
|
|
1029
|
+
// Vision Intent Detection — user message
|
|
1030
|
+
// If the user signals they want to look at an image, auto-read it and inject as vision.
|
|
1031
|
+
try {
|
|
1032
|
+
const visionIntent = this.visionIntentDetector.detect(userMessage);
|
|
1033
|
+
if (visionIntent && visionIntent.confidence >= 0.5) {
|
|
1034
|
+
this.emitEvent({
|
|
1035
|
+
kind: "agent:thinking",
|
|
1036
|
+
content: `[Vision] Detected intent to view "${visionIntent.filePath}" (${visionIntent.detectedLanguage}, confidence ${visionIntent.confidence}). Auto-reading…`,
|
|
1037
|
+
});
|
|
1038
|
+
const visionResult = await this.toolExecutor.execute({
|
|
1039
|
+
id: `vision-auto-${Date.now()}`,
|
|
1040
|
+
name: "file_read",
|
|
1041
|
+
arguments: { path: visionIntent.filePath },
|
|
1042
|
+
});
|
|
1043
|
+
if (visionResult.output.startsWith("[IMAGE_BLOCK]\n")) {
|
|
1044
|
+
const jsonStr = visionResult.output.slice("[IMAGE_BLOCK]\n".length);
|
|
1045
|
+
const parsed = JSON.parse(jsonStr);
|
|
1046
|
+
const validMediaTypes = ["image/png", "image/jpeg", "image/gif", "image/webp"];
|
|
1047
|
+
const mediaType = validMediaTypes.includes(parsed.mediaType)
|
|
1048
|
+
? parsed.mediaType
|
|
1049
|
+
: "image/png";
|
|
1050
|
+
this.contextManager.addMessage({
|
|
1051
|
+
role: "user",
|
|
1052
|
+
content: [
|
|
1053
|
+
{ type: "image", data: parsed.data, mediaType },
|
|
1054
|
+
],
|
|
1055
|
+
});
|
|
1056
|
+
}
|
|
1057
|
+
}
|
|
1058
|
+
}
|
|
1059
|
+
catch {
|
|
1060
|
+
// Vision intent detection is non-fatal; continue normally
|
|
1061
|
+
}
|
|
992
1062
|
try {
|
|
993
1063
|
// Persona injection — 유저 선호도/언어/스타일 어댑테이션을 시스템 메시지로 주입
|
|
994
1064
|
if (this.personaManager) {
|
|
@@ -1512,8 +1582,66 @@ export class AgentLoop extends EventEmitter {
|
|
|
1512
1582
|
completedTasks: progress.completedTasks,
|
|
1513
1583
|
currentTask: progress.currentTask,
|
|
1514
1584
|
remainingTasks: progress.remainingTasks,
|
|
1585
|
+
hypothesis: this.agentHypothesis,
|
|
1586
|
+
failureSignature: this.agentFailureSig,
|
|
1587
|
+
verifyState: this.agentVerifyState,
|
|
1515
1588
|
};
|
|
1516
1589
|
}
|
|
1590
|
+
/**
|
|
1591
|
+
* 매 이터레이션 LLM 호출 전 compact AgentState를 컨텍스트에 주입한다.
|
|
1592
|
+
* 3 이터레이션마다 갱신하여 컨텍스트 팽창 방지.
|
|
1593
|
+
*/
|
|
1594
|
+
injectAgentStateIfNeeded(iteration) {
|
|
1595
|
+
// 첫 이터레이션 or 3회마다 or 상태 변화 시 주입
|
|
1596
|
+
const stateChanged = this.agentHypothesis !== undefined ||
|
|
1597
|
+
this.agentFailureSig !== undefined ||
|
|
1598
|
+
this.agentVerifyState === "fail";
|
|
1599
|
+
const shouldInject = iteration <= 1 ||
|
|
1600
|
+
iteration - this.lastAgentStateInjection >= 3 ||
|
|
1601
|
+
stateChanged;
|
|
1602
|
+
if (!shouldInject)
|
|
1603
|
+
return;
|
|
1604
|
+
const budgetPct = this.config?.loop?.totalTokenBudget
|
|
1605
|
+
? Math.round((this.tokenUsage.total / this.config.loop.totalTokenBudget) * 100)
|
|
1606
|
+
: 0;
|
|
1607
|
+
const remaining = 100 - budgetPct;
|
|
1608
|
+
const lines = [`[AgentState] iteration=${iteration}`];
|
|
1609
|
+
if (this.agentHypothesis)
|
|
1610
|
+
lines.push(`hypothesis: ${this.agentHypothesis}`);
|
|
1611
|
+
if (this.agentFailureSig)
|
|
1612
|
+
lines.push(`last_failure: ${this.agentFailureSig}`);
|
|
1613
|
+
if (this.agentVerifyState)
|
|
1614
|
+
lines.push(`verify: ${this.agentVerifyState}`);
|
|
1615
|
+
if (this.changedFiles.length > 0) {
|
|
1616
|
+
const files = this.changedFiles.slice(-4).join(", ");
|
|
1617
|
+
lines.push(`changed: ${files}`);
|
|
1618
|
+
}
|
|
1619
|
+
lines.push(`token_budget: ${remaining}% remaining`);
|
|
1620
|
+
if (this.iterationSystemMsgCount < 5) {
|
|
1621
|
+
this.contextManager.addMessage({ role: "system", content: lines.join(" | ") });
|
|
1622
|
+
this.lastAgentStateInjection = iteration;
|
|
1623
|
+
this.iterationSystemMsgCount++;
|
|
1624
|
+
}
|
|
1625
|
+
}
|
|
1626
|
+
/**
|
|
1627
|
+
* LLM 응답 텍스트에서 "Updated hypothesis:" 마커를 파싱해 hypothesis를 갱신한다.
|
|
1628
|
+
*/
|
|
1629
|
+
updateHypothesisFromResponse(text) {
|
|
1630
|
+
const match = text.match(/Updated hypothesis:\s*(.+?)(?:\n|$)/i);
|
|
1631
|
+
if (match?.[1]) {
|
|
1632
|
+
this.agentHypothesis = match[1].trim().slice(0, 300);
|
|
1633
|
+
}
|
|
1634
|
+
}
|
|
1635
|
+
/**
|
|
1636
|
+
* 검증 결과를 기록한다. CausalChainResolver 트리거에 사용.
|
|
1637
|
+
*/
|
|
1638
|
+
recordVerifyResult(state, signature) {
|
|
1639
|
+
this.agentVerifyState = state;
|
|
1640
|
+
if (signature)
|
|
1641
|
+
this.agentFailureSig = signature;
|
|
1642
|
+
if (state === "pass")
|
|
1643
|
+
this.agentFailureSig = undefined;
|
|
1644
|
+
}
|
|
1517
1645
|
/**
|
|
1518
1646
|
* ContinuousReflection 인스턴스를 반환한다.
|
|
1519
1647
|
* 외부에서 ESC 토글(pause/resume) 또는 이벤트 구독에 사용.
|
|
@@ -1894,8 +2022,6 @@ export class AgentLoop extends EventEmitter {
|
|
|
1894
2022
|
if (this.abortSignal?.aborted) {
|
|
1895
2023
|
return { reason: "USER_CANCELLED" };
|
|
1896
2024
|
}
|
|
1897
|
-
if (iteration === 0)
|
|
1898
|
-
this.emitReasoning("starting agent loop");
|
|
1899
2025
|
// Interrupt: pause 상태이면 resume될 때까지 대기
|
|
1900
2026
|
if (this.interruptManager.isPaused()) {
|
|
1901
2027
|
await this.waitForResume();
|
|
@@ -1933,7 +2059,6 @@ export class AgentLoop extends EventEmitter {
|
|
|
1933
2059
|
// Cap allToolResults (prevents unbounded memory growth)
|
|
1934
2060
|
this.allToolResults = cap(this.allToolResults, BOUNDS.allToolResults);
|
|
1935
2061
|
this.allToolResultsSinceLastReplan = cap(this.allToolResultsSinceLastReplan, BOUNDS.toolResultsSinceReplan);
|
|
1936
|
-
this.emitReasoning(`iteration ${iteration}: preparing context`);
|
|
1937
2062
|
// Proactive replanning check (every 10 iterations when plan is active)
|
|
1938
2063
|
if (this.replanningEngine &&
|
|
1939
2064
|
this.activePlan &&
|
|
@@ -2091,7 +2216,8 @@ export class AgentLoop extends EventEmitter {
|
|
|
2091
2216
|
}
|
|
2092
2217
|
}
|
|
2093
2218
|
}
|
|
2094
|
-
// 1. 컨텍스트 준비
|
|
2219
|
+
// 1. 컨텍스트 준비 + AgentState 주입 (매 이터레이션, compact)
|
|
2220
|
+
this.injectAgentStateIfNeeded(iteration);
|
|
2095
2221
|
const messages = this.contextManager.prepareForLLM();
|
|
2096
2222
|
// 2. LLM 호출 (streaming)
|
|
2097
2223
|
// Before LLM call, check executor budget
|
|
@@ -2104,7 +2230,6 @@ export class AgentLoop extends EventEmitter {
|
|
|
2104
2230
|
// Try rebalancing to free up budget from idle roles
|
|
2105
2231
|
this.tokenBudgetManager.rebalance();
|
|
2106
2232
|
}
|
|
2107
|
-
this.emitReasoning(`iteration ${iteration}: calling model`);
|
|
2108
2233
|
let response;
|
|
2109
2234
|
try {
|
|
2110
2235
|
response = await this.callLLMStreaming(messages);
|
|
@@ -2134,6 +2259,10 @@ export class AgentLoop extends EventEmitter {
|
|
|
2134
2259
|
input: this.tokenUsage.input,
|
|
2135
2260
|
output: this.tokenUsage.output,
|
|
2136
2261
|
});
|
|
2262
|
+
// hypothesis 업데이트 — LLM 응답에서 "Updated hypothesis:" 마커 파싱
|
|
2263
|
+
if (response.content) {
|
|
2264
|
+
this.updateHypothesisFromResponse(response.content);
|
|
2265
|
+
}
|
|
2137
2266
|
// LLM 응답 살균 — 간접 프롬프트 인젝션 방어
|
|
2138
2267
|
if (response.content) {
|
|
2139
2268
|
const llmSanitized = this.promptDefense.sanitizeToolOutput("llm_response", response.content);
|
|
@@ -2147,6 +2276,49 @@ export class AgentLoop extends EventEmitter {
|
|
|
2147
2276
|
response = { ...response, content: llmSanitized.output };
|
|
2148
2277
|
}
|
|
2149
2278
|
}
|
|
2279
|
+
// Vision Intent Detection — LLM reasoning/response
|
|
2280
|
+
// If the LLM signals it wants to look at an image in its content/reasoning,
|
|
2281
|
+
// auto-read it and inject as a user-side vision message for the next iteration.
|
|
2282
|
+
if (response.content) {
|
|
2283
|
+
try {
|
|
2284
|
+
const visionIntent = this.visionIntentDetector.detect(response.content);
|
|
2285
|
+
if (visionIntent && visionIntent.confidence >= 0.5 && response.toolCalls.length === 0) {
|
|
2286
|
+
this.emitEvent({
|
|
2287
|
+
kind: "agent:thinking",
|
|
2288
|
+
content: `[Vision] LLM requested view of "${visionIntent.filePath}" (${visionIntent.detectedLanguage}, confidence ${visionIntent.confidence}). Auto-reading…`,
|
|
2289
|
+
});
|
|
2290
|
+
const visionResult = await this.toolExecutor.execute({
|
|
2291
|
+
id: `vision-auto-llm-${Date.now()}`,
|
|
2292
|
+
name: "file_read",
|
|
2293
|
+
arguments: { path: visionIntent.filePath },
|
|
2294
|
+
});
|
|
2295
|
+
if (visionResult.output.startsWith("[IMAGE_BLOCK]\n")) {
|
|
2296
|
+
const jsonStr = visionResult.output.slice("[IMAGE_BLOCK]\n".length);
|
|
2297
|
+
const parsed = JSON.parse(jsonStr);
|
|
2298
|
+
const validMediaTypes = ["image/png", "image/jpeg", "image/gif", "image/webp"];
|
|
2299
|
+
const mediaType = validMediaTypes.includes(parsed.mediaType)
|
|
2300
|
+
? parsed.mediaType
|
|
2301
|
+
: "image/png";
|
|
2302
|
+
// Add LLM response to context first, then inject vision as user follow-up
|
|
2303
|
+
this.contextManager.addMessage({
|
|
2304
|
+
role: "assistant",
|
|
2305
|
+
content: response.content,
|
|
2306
|
+
});
|
|
2307
|
+
this.contextManager.addMessage({
|
|
2308
|
+
role: "user",
|
|
2309
|
+
content: [
|
|
2310
|
+
{ type: "image", data: parsed.data, mediaType },
|
|
2311
|
+
],
|
|
2312
|
+
});
|
|
2313
|
+
// Continue loop so LLM gets the image on the next iteration
|
|
2314
|
+
continue;
|
|
2315
|
+
}
|
|
2316
|
+
}
|
|
2317
|
+
}
|
|
2318
|
+
catch {
|
|
2319
|
+
// Vision intent detection from LLM response is non-fatal
|
|
2320
|
+
}
|
|
2321
|
+
}
|
|
2150
2322
|
// 3. 응답 처리
|
|
2151
2323
|
if (response.toolCalls.length === 0) {
|
|
2152
2324
|
const content = response.content ?? "";
|
|
@@ -2157,10 +2329,12 @@ export class AgentLoop extends EventEmitter {
|
|
|
2157
2329
|
// Run cheap checks — if they fail, stay in implement and continue loop
|
|
2158
2330
|
const cheapOk = await this.runCheapChecks();
|
|
2159
2331
|
if (cheapOk) {
|
|
2332
|
+
this.recordVerifyResult("pass");
|
|
2160
2333
|
this.transitionPhase("finalize", "cheap checks passed");
|
|
2161
2334
|
}
|
|
2162
2335
|
else {
|
|
2163
2336
|
// cheap checks failed — stay in implement, let LLM fix
|
|
2337
|
+
this.recordVerifyResult("fail", "cheap checks failed");
|
|
2164
2338
|
this.transitionPhase("implement", "cheap check failed, continuing");
|
|
2165
2339
|
continue;
|
|
2166
2340
|
}
|
|
@@ -2360,6 +2534,33 @@ export class AgentLoop extends EventEmitter {
|
|
|
2360
2534
|
retryable: false,
|
|
2361
2535
|
});
|
|
2362
2536
|
}
|
|
2537
|
+
// Image block from file_read — inject as vision ContentBlock
|
|
2538
|
+
if (sanitized.output.startsWith("[IMAGE_BLOCK]\n")) {
|
|
2539
|
+
try {
|
|
2540
|
+
const jsonStr = sanitized.output.slice("[IMAGE_BLOCK]\n".length);
|
|
2541
|
+
const parsed = JSON.parse(jsonStr);
|
|
2542
|
+
const validMediaTypes = ["image/png", "image/jpeg", "image/gif", "image/webp"];
|
|
2543
|
+
const mediaType = validMediaTypes.includes(parsed.mediaType)
|
|
2544
|
+
? parsed.mediaType
|
|
2545
|
+
: "image/png";
|
|
2546
|
+
this.contextManager.addMessage({
|
|
2547
|
+
role: "tool",
|
|
2548
|
+
content: [
|
|
2549
|
+
{ type: "image", data: parsed.data, mediaType },
|
|
2550
|
+
],
|
|
2551
|
+
tool_call_id: result.tool_call_id,
|
|
2552
|
+
});
|
|
2553
|
+
}
|
|
2554
|
+
catch {
|
|
2555
|
+
// Fallback: treat as plain text if parsing fails
|
|
2556
|
+
this.contextManager.addMessage({
|
|
2557
|
+
role: "tool",
|
|
2558
|
+
content: sanitized.output,
|
|
2559
|
+
tool_call_id: result.tool_call_id,
|
|
2560
|
+
});
|
|
2561
|
+
}
|
|
2562
|
+
continue;
|
|
2563
|
+
}
|
|
2363
2564
|
// 큰 결과는 추가 압축
|
|
2364
2565
|
const compressedOutput = this.contextManager.compressToolResult(result.name, sanitized.output);
|
|
2365
2566
|
this.contextManager.addMessage({
|
|
@@ -2826,8 +3027,8 @@ export class AgentLoop extends EventEmitter {
|
|
|
2826
3027
|
// 텍스트 버퍼링 — 1토큰씩 emit하지 않고 청크 단위로 모아서 emit
|
|
2827
3028
|
let textBuffer = "";
|
|
2828
3029
|
let flushTimer = null;
|
|
2829
|
-
const FLUSH_INTERVAL_MS =
|
|
2830
|
-
const FLUSH_SIZE_THRESHOLD =
|
|
3030
|
+
const FLUSH_INTERVAL_MS = 20; // 20ms마다 flush (faster first-token display)
|
|
3031
|
+
const FLUSH_SIZE_THRESHOLD = 15; // 15자 이상이면 즉시 flush
|
|
2831
3032
|
const SENTENCE_BREAKS = /[.!?\n。!?\n]\s*$/; // 문장 경계에서도 flush
|
|
2832
3033
|
const flushTextBuffer = () => {
|
|
2833
3034
|
if (flushTimer) {
|
|
@@ -3100,7 +3301,6 @@ export class AgentLoop extends EventEmitter {
|
|
|
3100
3301
|
: result.output,
|
|
3101
3302
|
durationMs: result.durationMs,
|
|
3102
3303
|
});
|
|
3103
|
-
this.emitReasoning(`success: ${toolCall.name}`);
|
|
3104
3304
|
this.reasoningTree.add("tool", `success: ${toolCall.name}`);
|
|
3105
3305
|
if (["file_write", "file_edit"].includes(toolCall.name) && result.success) {
|
|
3106
3306
|
// Phase transition: explore → implement on first write
|
|
@@ -3348,7 +3548,6 @@ export class AgentLoop extends EventEmitter {
|
|
|
3348
3548
|
}
|
|
3349
3549
|
else {
|
|
3350
3550
|
// Multi-tool — parallel execution
|
|
3351
|
-
this.emitReasoning(`⚡ running ${batch.label} in parallel`);
|
|
3352
3551
|
const settled = await Promise.allSettled(batch.calls.map((tc) => this.executeSingleTool(tc, toolCalls)));
|
|
3353
3552
|
for (let i = 0; i < settled.length; i++) {
|
|
3354
3553
|
const s = settled[i];
|
|
@@ -3997,7 +4196,6 @@ export class AgentLoop extends EventEmitter {
|
|
|
3997
4196
|
iteration: this.iterationCount,
|
|
3998
4197
|
trigger,
|
|
3999
4198
|
});
|
|
4000
|
-
this.emitReasoning(`phase: ${from} → ${to} (${trigger})`);
|
|
4001
4199
|
}
|
|
4002
4200
|
/**
|
|
4003
4201
|
* Cheap local checks run in verify phase — no LLM.
|
|
@@ -4013,7 +4211,7 @@ export class AgentLoop extends EventEmitter {
|
|
|
4013
4211
|
for (const f of this.changedFiles) {
|
|
4014
4212
|
const abs = projectPath ? `${projectPath}/${f}` : f;
|
|
4015
4213
|
if (f.startsWith("/") ? !existsSync(f) : !existsSync(abs)) {
|
|
4016
|
-
|
|
4214
|
+
// cheap check: file missing — stay in verify
|
|
4017
4215
|
return false;
|
|
4018
4216
|
}
|
|
4019
4217
|
}
|
|
@@ -4033,7 +4231,7 @@ export class AgentLoop extends EventEmitter {
|
|
|
4033
4231
|
if (result.success && result.output) {
|
|
4034
4232
|
const hasErrors = result.output.includes(": error TS");
|
|
4035
4233
|
if (hasErrors) {
|
|
4036
|
-
|
|
4234
|
+
// cheap check: tsc errors found — staying in verify
|
|
4037
4235
|
// Inject TS errors so LLM sees them and fixes them
|
|
4038
4236
|
if (this.iterationSystemMsgCount < 5) {
|
|
4039
4237
|
const truncated = result.output.length > 1000
|