@yuaone/core 0.9.14 → 0.9.15
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 +218 -21
- 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 +262 -36
- 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 생성
|
|
@@ -988,6 +1024,39 @@ export class AgentLoop extends EventEmitter {
|
|
|
988
1024
|
if (this.personaManager) {
|
|
989
1025
|
this.personaManager.analyzeUserMessage(userMessage);
|
|
990
1026
|
}
|
|
1027
|
+
// Vision Intent Detection — user message
|
|
1028
|
+
// If the user signals they want to look at an image, auto-read it and inject as vision.
|
|
1029
|
+
try {
|
|
1030
|
+
const visionIntent = this.visionIntentDetector.detect(userMessage);
|
|
1031
|
+
if (visionIntent && visionIntent.confidence >= 0.5) {
|
|
1032
|
+
this.emitEvent({
|
|
1033
|
+
kind: "agent:thinking",
|
|
1034
|
+
content: `[Vision] Detected intent to view "${visionIntent.filePath}" (${visionIntent.detectedLanguage}, confidence ${visionIntent.confidence}). Auto-reading…`,
|
|
1035
|
+
});
|
|
1036
|
+
const visionResult = await this.toolExecutor.execute({
|
|
1037
|
+
id: `vision-auto-${Date.now()}`,
|
|
1038
|
+
name: "file_read",
|
|
1039
|
+
arguments: { path: visionIntent.filePath },
|
|
1040
|
+
});
|
|
1041
|
+
if (visionResult.output.startsWith("[IMAGE_BLOCK]\n")) {
|
|
1042
|
+
const jsonStr = visionResult.output.slice("[IMAGE_BLOCK]\n".length);
|
|
1043
|
+
const parsed = JSON.parse(jsonStr);
|
|
1044
|
+
const validMediaTypes = ["image/png", "image/jpeg", "image/gif", "image/webp"];
|
|
1045
|
+
const mediaType = validMediaTypes.includes(parsed.mediaType)
|
|
1046
|
+
? parsed.mediaType
|
|
1047
|
+
: "image/png";
|
|
1048
|
+
this.contextManager.addMessage({
|
|
1049
|
+
role: "user",
|
|
1050
|
+
content: [
|
|
1051
|
+
{ type: "image", data: parsed.data, mediaType },
|
|
1052
|
+
],
|
|
1053
|
+
});
|
|
1054
|
+
}
|
|
1055
|
+
}
|
|
1056
|
+
}
|
|
1057
|
+
catch {
|
|
1058
|
+
// Vision intent detection is non-fatal; continue normally
|
|
1059
|
+
}
|
|
991
1060
|
this.emitEvent({ kind: "agent:start", goal: userMessage });
|
|
992
1061
|
try {
|
|
993
1062
|
// Persona injection — 유저 선호도/언어/스타일 어댑테이션을 시스템 메시지로 주입
|
|
@@ -1512,8 +1581,66 @@ export class AgentLoop extends EventEmitter {
|
|
|
1512
1581
|
completedTasks: progress.completedTasks,
|
|
1513
1582
|
currentTask: progress.currentTask,
|
|
1514
1583
|
remainingTasks: progress.remainingTasks,
|
|
1584
|
+
hypothesis: this.agentHypothesis,
|
|
1585
|
+
failureSignature: this.agentFailureSig,
|
|
1586
|
+
verifyState: this.agentVerifyState,
|
|
1515
1587
|
};
|
|
1516
1588
|
}
|
|
1589
|
+
/**
|
|
1590
|
+
* 매 이터레이션 LLM 호출 전 compact AgentState를 컨텍스트에 주입한다.
|
|
1591
|
+
* 3 이터레이션마다 갱신하여 컨텍스트 팽창 방지.
|
|
1592
|
+
*/
|
|
1593
|
+
injectAgentStateIfNeeded(iteration) {
|
|
1594
|
+
// 첫 이터레이션 or 3회마다 or 상태 변화 시 주입
|
|
1595
|
+
const stateChanged = this.agentHypothesis !== undefined ||
|
|
1596
|
+
this.agentFailureSig !== undefined ||
|
|
1597
|
+
this.agentVerifyState === "fail";
|
|
1598
|
+
const shouldInject = iteration <= 1 ||
|
|
1599
|
+
iteration - this.lastAgentStateInjection >= 3 ||
|
|
1600
|
+
stateChanged;
|
|
1601
|
+
if (!shouldInject)
|
|
1602
|
+
return;
|
|
1603
|
+
const budgetPct = this.config?.loop?.totalTokenBudget
|
|
1604
|
+
? Math.round((this.tokenUsage.total / this.config.loop.totalTokenBudget) * 100)
|
|
1605
|
+
: 0;
|
|
1606
|
+
const remaining = 100 - budgetPct;
|
|
1607
|
+
const lines = [`[AgentState] iteration=${iteration}`];
|
|
1608
|
+
if (this.agentHypothesis)
|
|
1609
|
+
lines.push(`hypothesis: ${this.agentHypothesis}`);
|
|
1610
|
+
if (this.agentFailureSig)
|
|
1611
|
+
lines.push(`last_failure: ${this.agentFailureSig}`);
|
|
1612
|
+
if (this.agentVerifyState)
|
|
1613
|
+
lines.push(`verify: ${this.agentVerifyState}`);
|
|
1614
|
+
if (this.changedFiles.length > 0) {
|
|
1615
|
+
const files = this.changedFiles.slice(-4).join(", ");
|
|
1616
|
+
lines.push(`changed: ${files}`);
|
|
1617
|
+
}
|
|
1618
|
+
lines.push(`token_budget: ${remaining}% remaining`);
|
|
1619
|
+
if (this.iterationSystemMsgCount < 5) {
|
|
1620
|
+
this.contextManager.addMessage({ role: "system", content: lines.join(" | ") });
|
|
1621
|
+
this.lastAgentStateInjection = iteration;
|
|
1622
|
+
this.iterationSystemMsgCount++;
|
|
1623
|
+
}
|
|
1624
|
+
}
|
|
1625
|
+
/**
|
|
1626
|
+
* LLM 응답 텍스트에서 "Updated hypothesis:" 마커를 파싱해 hypothesis를 갱신한다.
|
|
1627
|
+
*/
|
|
1628
|
+
updateHypothesisFromResponse(text) {
|
|
1629
|
+
const match = text.match(/Updated hypothesis:\s*(.+?)(?:\n|$)/i);
|
|
1630
|
+
if (match?.[1]) {
|
|
1631
|
+
this.agentHypothesis = match[1].trim().slice(0, 300);
|
|
1632
|
+
}
|
|
1633
|
+
}
|
|
1634
|
+
/**
|
|
1635
|
+
* 검증 결과를 기록한다. CausalChainResolver 트리거에 사용.
|
|
1636
|
+
*/
|
|
1637
|
+
recordVerifyResult(state, signature) {
|
|
1638
|
+
this.agentVerifyState = state;
|
|
1639
|
+
if (signature)
|
|
1640
|
+
this.agentFailureSig = signature;
|
|
1641
|
+
if (state === "pass")
|
|
1642
|
+
this.agentFailureSig = undefined;
|
|
1643
|
+
}
|
|
1517
1644
|
/**
|
|
1518
1645
|
* ContinuousReflection 인스턴스를 반환한다.
|
|
1519
1646
|
* 외부에서 ESC 토글(pause/resume) 또는 이벤트 구독에 사용.
|
|
@@ -1894,8 +2021,6 @@ export class AgentLoop extends EventEmitter {
|
|
|
1894
2021
|
if (this.abortSignal?.aborted) {
|
|
1895
2022
|
return { reason: "USER_CANCELLED" };
|
|
1896
2023
|
}
|
|
1897
|
-
if (iteration === 0)
|
|
1898
|
-
this.emitReasoning("starting agent loop");
|
|
1899
2024
|
// Interrupt: pause 상태이면 resume될 때까지 대기
|
|
1900
2025
|
if (this.interruptManager.isPaused()) {
|
|
1901
2026
|
await this.waitForResume();
|
|
@@ -1933,7 +2058,6 @@ export class AgentLoop extends EventEmitter {
|
|
|
1933
2058
|
// Cap allToolResults (prevents unbounded memory growth)
|
|
1934
2059
|
this.allToolResults = cap(this.allToolResults, BOUNDS.allToolResults);
|
|
1935
2060
|
this.allToolResultsSinceLastReplan = cap(this.allToolResultsSinceLastReplan, BOUNDS.toolResultsSinceReplan);
|
|
1936
|
-
this.emitReasoning(`iteration ${iteration}: preparing context`);
|
|
1937
2061
|
// Proactive replanning check (every 10 iterations when plan is active)
|
|
1938
2062
|
if (this.replanningEngine &&
|
|
1939
2063
|
this.activePlan &&
|
|
@@ -2091,7 +2215,8 @@ export class AgentLoop extends EventEmitter {
|
|
|
2091
2215
|
}
|
|
2092
2216
|
}
|
|
2093
2217
|
}
|
|
2094
|
-
// 1. 컨텍스트 준비
|
|
2218
|
+
// 1. 컨텍스트 준비 + AgentState 주입 (매 이터레이션, compact)
|
|
2219
|
+
this.injectAgentStateIfNeeded(iteration);
|
|
2095
2220
|
const messages = this.contextManager.prepareForLLM();
|
|
2096
2221
|
// 2. LLM 호출 (streaming)
|
|
2097
2222
|
// Before LLM call, check executor budget
|
|
@@ -2104,7 +2229,6 @@ export class AgentLoop extends EventEmitter {
|
|
|
2104
2229
|
// Try rebalancing to free up budget from idle roles
|
|
2105
2230
|
this.tokenBudgetManager.rebalance();
|
|
2106
2231
|
}
|
|
2107
|
-
this.emitReasoning(`iteration ${iteration}: calling model`);
|
|
2108
2232
|
let response;
|
|
2109
2233
|
try {
|
|
2110
2234
|
response = await this.callLLMStreaming(messages);
|
|
@@ -2134,6 +2258,10 @@ export class AgentLoop extends EventEmitter {
|
|
|
2134
2258
|
input: this.tokenUsage.input,
|
|
2135
2259
|
output: this.tokenUsage.output,
|
|
2136
2260
|
});
|
|
2261
|
+
// hypothesis 업데이트 — LLM 응답에서 "Updated hypothesis:" 마커 파싱
|
|
2262
|
+
if (response.content) {
|
|
2263
|
+
this.updateHypothesisFromResponse(response.content);
|
|
2264
|
+
}
|
|
2137
2265
|
// LLM 응답 살균 — 간접 프롬프트 인젝션 방어
|
|
2138
2266
|
if (response.content) {
|
|
2139
2267
|
const llmSanitized = this.promptDefense.sanitizeToolOutput("llm_response", response.content);
|
|
@@ -2147,6 +2275,49 @@ export class AgentLoop extends EventEmitter {
|
|
|
2147
2275
|
response = { ...response, content: llmSanitized.output };
|
|
2148
2276
|
}
|
|
2149
2277
|
}
|
|
2278
|
+
// Vision Intent Detection — LLM reasoning/response
|
|
2279
|
+
// If the LLM signals it wants to look at an image in its content/reasoning,
|
|
2280
|
+
// auto-read it and inject as a user-side vision message for the next iteration.
|
|
2281
|
+
if (response.content) {
|
|
2282
|
+
try {
|
|
2283
|
+
const visionIntent = this.visionIntentDetector.detect(response.content);
|
|
2284
|
+
if (visionIntent && visionIntent.confidence >= 0.5 && response.toolCalls.length === 0) {
|
|
2285
|
+
this.emitEvent({
|
|
2286
|
+
kind: "agent:thinking",
|
|
2287
|
+
content: `[Vision] LLM requested view of "${visionIntent.filePath}" (${visionIntent.detectedLanguage}, confidence ${visionIntent.confidence}). Auto-reading…`,
|
|
2288
|
+
});
|
|
2289
|
+
const visionResult = await this.toolExecutor.execute({
|
|
2290
|
+
id: `vision-auto-llm-${Date.now()}`,
|
|
2291
|
+
name: "file_read",
|
|
2292
|
+
arguments: { path: visionIntent.filePath },
|
|
2293
|
+
});
|
|
2294
|
+
if (visionResult.output.startsWith("[IMAGE_BLOCK]\n")) {
|
|
2295
|
+
const jsonStr = visionResult.output.slice("[IMAGE_BLOCK]\n".length);
|
|
2296
|
+
const parsed = JSON.parse(jsonStr);
|
|
2297
|
+
const validMediaTypes = ["image/png", "image/jpeg", "image/gif", "image/webp"];
|
|
2298
|
+
const mediaType = validMediaTypes.includes(parsed.mediaType)
|
|
2299
|
+
? parsed.mediaType
|
|
2300
|
+
: "image/png";
|
|
2301
|
+
// Add LLM response to context first, then inject vision as user follow-up
|
|
2302
|
+
this.contextManager.addMessage({
|
|
2303
|
+
role: "assistant",
|
|
2304
|
+
content: response.content,
|
|
2305
|
+
});
|
|
2306
|
+
this.contextManager.addMessage({
|
|
2307
|
+
role: "user",
|
|
2308
|
+
content: [
|
|
2309
|
+
{ type: "image", data: parsed.data, mediaType },
|
|
2310
|
+
],
|
|
2311
|
+
});
|
|
2312
|
+
// Continue loop so LLM gets the image on the next iteration
|
|
2313
|
+
continue;
|
|
2314
|
+
}
|
|
2315
|
+
}
|
|
2316
|
+
}
|
|
2317
|
+
catch {
|
|
2318
|
+
// Vision intent detection from LLM response is non-fatal
|
|
2319
|
+
}
|
|
2320
|
+
}
|
|
2150
2321
|
// 3. 응답 처리
|
|
2151
2322
|
if (response.toolCalls.length === 0) {
|
|
2152
2323
|
const content = response.content ?? "";
|
|
@@ -2157,10 +2328,12 @@ export class AgentLoop extends EventEmitter {
|
|
|
2157
2328
|
// Run cheap checks — if they fail, stay in implement and continue loop
|
|
2158
2329
|
const cheapOk = await this.runCheapChecks();
|
|
2159
2330
|
if (cheapOk) {
|
|
2331
|
+
this.recordVerifyResult("pass");
|
|
2160
2332
|
this.transitionPhase("finalize", "cheap checks passed");
|
|
2161
2333
|
}
|
|
2162
2334
|
else {
|
|
2163
2335
|
// cheap checks failed — stay in implement, let LLM fix
|
|
2336
|
+
this.recordVerifyResult("fail", "cheap checks failed");
|
|
2164
2337
|
this.transitionPhase("implement", "cheap check failed, continuing");
|
|
2165
2338
|
continue;
|
|
2166
2339
|
}
|
|
@@ -2360,6 +2533,33 @@ export class AgentLoop extends EventEmitter {
|
|
|
2360
2533
|
retryable: false,
|
|
2361
2534
|
});
|
|
2362
2535
|
}
|
|
2536
|
+
// Image block from file_read — inject as vision ContentBlock
|
|
2537
|
+
if (sanitized.output.startsWith("[IMAGE_BLOCK]\n")) {
|
|
2538
|
+
try {
|
|
2539
|
+
const jsonStr = sanitized.output.slice("[IMAGE_BLOCK]\n".length);
|
|
2540
|
+
const parsed = JSON.parse(jsonStr);
|
|
2541
|
+
const validMediaTypes = ["image/png", "image/jpeg", "image/gif", "image/webp"];
|
|
2542
|
+
const mediaType = validMediaTypes.includes(parsed.mediaType)
|
|
2543
|
+
? parsed.mediaType
|
|
2544
|
+
: "image/png";
|
|
2545
|
+
this.contextManager.addMessage({
|
|
2546
|
+
role: "tool",
|
|
2547
|
+
content: [
|
|
2548
|
+
{ type: "image", data: parsed.data, mediaType },
|
|
2549
|
+
],
|
|
2550
|
+
tool_call_id: result.tool_call_id,
|
|
2551
|
+
});
|
|
2552
|
+
}
|
|
2553
|
+
catch {
|
|
2554
|
+
// Fallback: treat as plain text if parsing fails
|
|
2555
|
+
this.contextManager.addMessage({
|
|
2556
|
+
role: "tool",
|
|
2557
|
+
content: sanitized.output,
|
|
2558
|
+
tool_call_id: result.tool_call_id,
|
|
2559
|
+
});
|
|
2560
|
+
}
|
|
2561
|
+
continue;
|
|
2562
|
+
}
|
|
2363
2563
|
// 큰 결과는 추가 압축
|
|
2364
2564
|
const compressedOutput = this.contextManager.compressToolResult(result.name, sanitized.output);
|
|
2365
2565
|
this.contextManager.addMessage({
|
|
@@ -2826,8 +3026,8 @@ export class AgentLoop extends EventEmitter {
|
|
|
2826
3026
|
// 텍스트 버퍼링 — 1토큰씩 emit하지 않고 청크 단위로 모아서 emit
|
|
2827
3027
|
let textBuffer = "";
|
|
2828
3028
|
let flushTimer = null;
|
|
2829
|
-
const FLUSH_INTERVAL_MS =
|
|
2830
|
-
const FLUSH_SIZE_THRESHOLD =
|
|
3029
|
+
const FLUSH_INTERVAL_MS = 20; // 20ms마다 flush (faster first-token display)
|
|
3030
|
+
const FLUSH_SIZE_THRESHOLD = 15; // 15자 이상이면 즉시 flush
|
|
2831
3031
|
const SENTENCE_BREAKS = /[.!?\n。!?\n]\s*$/; // 문장 경계에서도 flush
|
|
2832
3032
|
const flushTextBuffer = () => {
|
|
2833
3033
|
if (flushTimer) {
|
|
@@ -3100,7 +3300,6 @@ export class AgentLoop extends EventEmitter {
|
|
|
3100
3300
|
: result.output,
|
|
3101
3301
|
durationMs: result.durationMs,
|
|
3102
3302
|
});
|
|
3103
|
-
this.emitReasoning(`success: ${toolCall.name}`);
|
|
3104
3303
|
this.reasoningTree.add("tool", `success: ${toolCall.name}`);
|
|
3105
3304
|
if (["file_write", "file_edit"].includes(toolCall.name) && result.success) {
|
|
3106
3305
|
// Phase transition: explore → implement on first write
|
|
@@ -3348,7 +3547,6 @@ export class AgentLoop extends EventEmitter {
|
|
|
3348
3547
|
}
|
|
3349
3548
|
else {
|
|
3350
3549
|
// Multi-tool — parallel execution
|
|
3351
|
-
this.emitReasoning(`⚡ running ${batch.label} in parallel`);
|
|
3352
3550
|
const settled = await Promise.allSettled(batch.calls.map((tc) => this.executeSingleTool(tc, toolCalls)));
|
|
3353
3551
|
for (let i = 0; i < settled.length; i++) {
|
|
3354
3552
|
const s = settled[i];
|
|
@@ -3997,7 +4195,6 @@ export class AgentLoop extends EventEmitter {
|
|
|
3997
4195
|
iteration: this.iterationCount,
|
|
3998
4196
|
trigger,
|
|
3999
4197
|
});
|
|
4000
|
-
this.emitReasoning(`phase: ${from} → ${to} (${trigger})`);
|
|
4001
4198
|
}
|
|
4002
4199
|
/**
|
|
4003
4200
|
* Cheap local checks run in verify phase — no LLM.
|
|
@@ -4013,7 +4210,7 @@ export class AgentLoop extends EventEmitter {
|
|
|
4013
4210
|
for (const f of this.changedFiles) {
|
|
4014
4211
|
const abs = projectPath ? `${projectPath}/${f}` : f;
|
|
4015
4212
|
if (f.startsWith("/") ? !existsSync(f) : !existsSync(abs)) {
|
|
4016
|
-
|
|
4213
|
+
// cheap check: file missing — stay in verify
|
|
4017
4214
|
return false;
|
|
4018
4215
|
}
|
|
4019
4216
|
}
|
|
@@ -4033,7 +4230,7 @@ export class AgentLoop extends EventEmitter {
|
|
|
4033
4230
|
if (result.success && result.output) {
|
|
4034
4231
|
const hasErrors = result.output.includes(": error TS");
|
|
4035
4232
|
if (hasErrors) {
|
|
4036
|
-
|
|
4233
|
+
// cheap check: tsc errors found — staying in verify
|
|
4037
4234
|
// Inject TS errors so LLM sees them and fixes them
|
|
4038
4235
|
if (this.iterationSystemMsgCount < 5) {
|
|
4039
4236
|
const truncated = result.output.length > 1000
|