joonecli 0.1.0 → 0.1.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 +12 -12
- package/dist/__tests__/optimizations.test.js.map +1 -1
- package/dist/__tests__/promptBuilder.test.js +14 -20
- package/dist/__tests__/promptBuilder.test.js.map +1 -1
- package/dist/agents/agentRegistry.d.ts +37 -0
- package/dist/agents/agentRegistry.js +58 -0
- package/dist/agents/agentRegistry.js.map +1 -0
- package/dist/agents/agentSpec.d.ts +54 -0
- package/dist/agents/agentSpec.js +9 -0
- package/dist/agents/agentSpec.js.map +1 -0
- package/dist/agents/builtinAgents.d.ts +20 -0
- package/dist/agents/builtinAgents.js +125 -0
- package/dist/agents/builtinAgents.js.map +1 -0
- package/dist/cli/config.d.ts +4 -0
- package/dist/cli/config.js.map +1 -1
- package/dist/cli/index.js +25 -1
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/postinstall.d.ts +2 -0
- package/dist/cli/postinstall.js +25 -0
- package/dist/cli/postinstall.js.map +1 -0
- package/dist/commands/builtinCommands.d.ts +21 -0
- package/dist/commands/builtinCommands.js +241 -0
- package/dist/commands/builtinCommands.js.map +1 -0
- package/dist/commands/commandRegistry.d.ts +90 -0
- package/dist/commands/commandRegistry.js +128 -0
- package/dist/commands/commandRegistry.js.map +1 -0
- package/dist/core/agentLoop.d.ts +4 -1
- package/dist/core/agentLoop.js +21 -9
- package/dist/core/agentLoop.js.map +1 -1
- package/dist/core/autoSave.d.ts +41 -0
- package/dist/core/autoSave.js +69 -0
- package/dist/core/autoSave.js.map +1 -0
- package/dist/core/compactor.d.ts +66 -0
- package/dist/core/compactor.js +170 -0
- package/dist/core/compactor.js.map +1 -0
- package/dist/core/contextGuard.d.ts +33 -0
- package/dist/core/contextGuard.js +95 -0
- package/dist/core/contextGuard.js.map +1 -0
- package/dist/core/promptBuilder.d.ts +16 -1
- package/dist/core/promptBuilder.js +27 -14
- package/dist/core/promptBuilder.js.map +1 -1
- package/dist/core/sessionResumer.js +3 -3
- package/dist/core/sessionResumer.js.map +1 -1
- package/dist/core/subAgent.d.ts +56 -0
- package/dist/core/subAgent.js +240 -0
- package/dist/core/subAgent.js.map +1 -0
- package/dist/debug_google.d.ts +1 -0
- package/dist/debug_google.js +23 -0
- package/dist/debug_google.js.map +1 -0
- package/dist/test_google.d.ts +1 -0
- package/dist/test_google.js +32 -89
- package/dist/test_google.js.map +1 -0
- package/dist/tools/router.js +2 -0
- package/dist/tools/router.js.map +1 -1
- package/dist/tools/spawnAgent.d.ts +19 -0
- package/dist/tools/spawnAgent.js +130 -0
- package/dist/tools/spawnAgent.js.map +1 -0
- package/dist/ui/App.js +88 -5
- package/dist/ui/App.js.map +1 -1
- package/package.json +3 -2
- package/src/cli/index.ts +12 -0
- package/src/cli/postinstall.ts +28 -0
- package/src/core/compactor.ts +2 -2
- package/src/core/contextGuard.ts +4 -4
- package/src/core/sessionStore.ts +2 -1
- package/src/core/subAgent.ts +2 -2
- package/tests/core/sessionStore.test.ts +2 -2
- package/src/test_google.js +0 -40
- package/src/test_google.ts +0 -40
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Context Guard
|
|
3
|
+
*
|
|
4
|
+
* Proactively monitors token usage during the agent loop and triggers auto-compaction
|
|
5
|
+
* before the model's context window is exceeded.
|
|
6
|
+
*
|
|
7
|
+
* Thresholds:
|
|
8
|
+
* - 80% (WARN): Triggers standard LLM-powered context compaction
|
|
9
|
+
* - 95% (CRITICAL): Forces emergency truncation if compaction fails
|
|
10
|
+
*/
|
|
11
|
+
import { SystemMessage } from "@langchain/core/messages";
|
|
12
|
+
import { CacheOptimizedPromptBuilder } from "./promptBuilder.js";
|
|
13
|
+
import { countMessageTokens } from "./tokenCounter.js";
|
|
14
|
+
import { createHandoffPrompt } from "./compactor.js";
|
|
15
|
+
export class ContextGuard {
|
|
16
|
+
promptBuilder;
|
|
17
|
+
llm;
|
|
18
|
+
maxTokens;
|
|
19
|
+
constructor(llm, maxTokens, promptBuilder = new CacheOptimizedPromptBuilder()) {
|
|
20
|
+
this.llm = llm;
|
|
21
|
+
this.maxTokens = maxTokens;
|
|
22
|
+
this.promptBuilder = promptBuilder;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Checks the token usage of the current state and compacts if necessary.
|
|
26
|
+
* Returns updated state and metrics about the action taken.
|
|
27
|
+
*/
|
|
28
|
+
async ensureCapacity(state, warnThreshold = 0.8, criticalThreshold = 0.95) {
|
|
29
|
+
const fullPrompt = this.promptBuilder.buildPrompt(state);
|
|
30
|
+
const tokenCount = countMessageTokens(fullPrompt);
|
|
31
|
+
// 1. Under limit — do nothing
|
|
32
|
+
if (tokenCount < this.maxTokens * warnThreshold) {
|
|
33
|
+
return {
|
|
34
|
+
state,
|
|
35
|
+
metrics: {
|
|
36
|
+
originalTokens: tokenCount,
|
|
37
|
+
newTokens: tokenCount,
|
|
38
|
+
messagesEvicted: 0,
|
|
39
|
+
actionTaken: "none",
|
|
40
|
+
},
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
// 2. Over WARN but below CRITICAL — try standard LLM compaction
|
|
44
|
+
if (tokenCount < this.maxTokens * criticalThreshold) {
|
|
45
|
+
const result = await this.promptBuilder.compactHistoryWithLLM(state.conversationHistory, this.llm, 8 // keep last 8 messages
|
|
46
|
+
);
|
|
47
|
+
return {
|
|
48
|
+
state: {
|
|
49
|
+
...state,
|
|
50
|
+
conversationHistory: result.compactedHistory,
|
|
51
|
+
},
|
|
52
|
+
metrics: {
|
|
53
|
+
originalTokens: tokenCount,
|
|
54
|
+
newTokens: result.tokensAfter,
|
|
55
|
+
messagesEvicted: result.evictedCount,
|
|
56
|
+
actionTaken: "compacted",
|
|
57
|
+
},
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
// 3. CRITICAL overflow (or standard compaction didn't free enough space)
|
|
61
|
+
// Emergency truncation: drop everything except the last 4 messages and inject an emergency handoff
|
|
62
|
+
const keepLast = 4;
|
|
63
|
+
// If we're already at or below 4 messages, we literally can't truncate more
|
|
64
|
+
if (state.conversationHistory.length <= keepLast) {
|
|
65
|
+
return {
|
|
66
|
+
state,
|
|
67
|
+
metrics: { originalTokens: tokenCount, newTokens: tokenCount, messagesEvicted: 0, actionTaken: "none" }
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
const recentMsgs = state.conversationHistory.slice(-keepLast);
|
|
71
|
+
const evictedCount = state.conversationHistory.length - keepLast;
|
|
72
|
+
const emergencySystemMsg = new SystemMessage(`[EMERGENCY CONTEXT TRUNCATION]\n` +
|
|
73
|
+
`The conversation exceeded the maximum context window (${this.maxTokens} tokens). ` +
|
|
74
|
+
`Older messages were aggressively deleted without summarization to prevent an immediate crash.\n` +
|
|
75
|
+
`You are the same agent. ` + createHandoffPrompt(new Date().toISOString()));
|
|
76
|
+
const newHistory = [emergencySystemMsg, ...recentMsgs];
|
|
77
|
+
const newTokens = countMessageTokens(this.promptBuilder.buildPrompt({
|
|
78
|
+
...state,
|
|
79
|
+
conversationHistory: newHistory
|
|
80
|
+
}));
|
|
81
|
+
return {
|
|
82
|
+
state: {
|
|
83
|
+
...state,
|
|
84
|
+
conversationHistory: newHistory,
|
|
85
|
+
},
|
|
86
|
+
metrics: {
|
|
87
|
+
originalTokens: tokenCount,
|
|
88
|
+
newTokens,
|
|
89
|
+
messagesEvicted: evictedCount,
|
|
90
|
+
actionTaken: "emergency_truncated",
|
|
91
|
+
},
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
//# sourceMappingURL=contextGuard.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"contextGuard.js","sourceRoot":"","sources":["../../src/core/contextGuard.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAe,aAAa,EAAE,MAAM,0BAA0B,CAAC;AAGtE,OAAO,EAAE,2BAA2B,EAAgB,MAAM,oBAAoB,CAAC;AAC/E,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AACvD,OAAO,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AASrD,MAAM,OAAO,YAAY;IACf,aAAa,CAA8B;IAC3C,GAAG,CAA2B;IAC9B,SAAS,CAAS;IAE1B,YACE,GAA6B,EAC7B,SAAiB,EACjB,gBAA6C,IAAI,2BAA2B,EAAE;QAE9E,IAAI,CAAC,GAAG,GAAG,GAAG,CAAC;QACf,IAAI,CAAC,SAAS,GAAG,SAAS,CAAC;QAC3B,IAAI,CAAC,aAAa,GAAG,aAAa,CAAC;IACrC,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,cAAc,CAClB,KAAmB,EACnB,aAAa,GAAG,GAAG,EACnB,iBAAiB,GAAG,IAAI;QAExB,MAAM,UAAU,GAAG,IAAI,CAAC,aAAa,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;QACzD,MAAM,UAAU,GAAG,kBAAkB,CAAC,UAAU,CAAC,CAAC;QAElD,8BAA8B;QAC9B,IAAI,UAAU,GAAG,IAAI,CAAC,SAAS,GAAG,aAAa,EAAE,CAAC;YAChD,OAAO;gBACL,KAAK;gBACL,OAAO,EAAE;oBACP,cAAc,EAAE,UAAU;oBAC1B,SAAS,EAAE,UAAU;oBACrB,eAAe,EAAE,CAAC;oBAClB,WAAW,EAAE,MAAM;iBACpB;aACF,CAAC;QACJ,CAAC;QAED,gEAAgE;QAChE,IAAI,UAAU,GAAG,IAAI,CAAC,SAAS,GAAG,iBAAiB,EAAE,CAAC;YACpD,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,aAAa,CAAC,qBAAqB,CAC3D,KAAK,CAAC,mBAAmB,EACzB,IAAI,CAAC,GAAG,EACR,CAAC,CAAC,uBAAuB;aAC1B,CAAC;YAEF,OAAO;gBACL,KAAK,EAAE;oBACL,GAAG,KAAK;oBACR,mBAAmB,EAAE,MAAM,CAAC,gBAAgB;iBAC7C;gBACD,OAAO,EAAE;oBACP,cAAc,EAAE,UAAU;oBAC1B,SAAS,EAAE,MAAM,CAAC,WAAW;oBAC7B,eAAe,EAAE,MAAM,CAAC,YAAY;oBACpC,WAAW,EAAE,WAAW;iBACzB;aACF,CAAC;QACJ,CAAC;QAED,yEAAyE;QACzE,mGAAmG;QACnG,MAAM,QAAQ,GAAG,CAAC,CAAC;QAEnB,4EAA4E;QAC5E,IAAI,KAAK,CAAC,mBAAmB,CAAC,MAAM,IAAI,QAAQ,EAAE,CAAC;YAChD,OAAO;gBACL,KAAK;gBACL,OAAO,EAAE,EAAE,cAAc,EAAE,UAAU,EAAE,SAAS,EAAE,UAAU,EAAE,eAAe,EAAE,CAAC,EAAE,WAAW,EAAE,MAAM,EAAE;aACxG,CAAC;QACL,CAAC;QAED,MAAM,UAAU,GAAG,KAAK,CAAC,mBAAmB,CAAC,KAAK,CAAC,CAAC,QAAQ,CAAC,CAAC;QAC9D,MAAM,YAAY,GAAG,KAAK,CAAC,mBAAmB,CAAC,MAAM,GAAG,QAAQ,CAAC;QAEjE,MAAM,kBAAkB,GAAG,IAAI,aAAa,CAC1C,kCAAkC;YAClC,yDAAyD,IAAI,CAAC,SAAS,YAAY;YACnF,iGAAiG;YACjG,0BAA0B,GAAG,mBAAmB,CAAC,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC,CAC3E,CAAC;QAEF,MAAM,UAAU,GAAG,CAAC,kBAAkB,EAAE,GAAG,UAAU,CAAC,CAAC;QACvD,MAAM,SAAS,GAAG,kBAAkB,CAAC,IAAI,CAAC,aAAa,CAAC,WAAW,CAAC;YACjE,GAAG,KAAK;YACR,mBAAmB,EAAE,UAAU;SACjC,CAAC,CAAC,CAAC;QAEJ,OAAO;YACL,KAAK,EAAE;gBACL,GAAG,KAAK;gBACR,mBAAmB,EAAE,UAAU;aAChC;YACD,OAAO,EAAE;gBACP,cAAc,EAAE,UAAU;gBAC1B,SAAS;gBACT,eAAe,EAAE,YAAY;gBAC7B,WAAW,EAAE,qBAAqB;aACnC;SACF,CAAC;IACJ,CAAC;CACF"}
|
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
import { BaseMessage } from "@langchain/core/messages";
|
|
2
|
+
import { BaseChatModel } from "@langchain/core/language_models/chat_models";
|
|
3
|
+
import { Runnable } from "@langchain/core/runnables";
|
|
4
|
+
import { CompactionResult } from "./compactor.js";
|
|
2
5
|
export interface ContextState {
|
|
3
6
|
globalSystemInstructions: string;
|
|
4
7
|
projectMemory: string;
|
|
@@ -29,7 +32,7 @@ export declare class CacheOptimizedPromptBuilder {
|
|
|
29
32
|
*/
|
|
30
33
|
injectSystemReminder(history: BaseMessage[], reminder: string): BaseMessage[];
|
|
31
34
|
/**
|
|
32
|
-
* Cache-Safe Compaction
|
|
35
|
+
* Cache-Safe Compaction (string-based fallback)
|
|
33
36
|
* When history gets too long, we preserve the last N messages (recent context)
|
|
34
37
|
* and replace older messages with a summary. The static system prefix is untouched.
|
|
35
38
|
*
|
|
@@ -38,6 +41,18 @@ export declare class CacheOptimizedPromptBuilder {
|
|
|
38
41
|
* @param keepLastN - Number of recent messages to preserve (default: 6).
|
|
39
42
|
*/
|
|
40
43
|
compactHistory(history: BaseMessage[], summary: string, keepLastN?: number): BaseMessage[];
|
|
44
|
+
/**
|
|
45
|
+
* LLM-Powered Compaction with Handoff
|
|
46
|
+
* Uses a dedicated LLM call to generate a structured summary, then injects
|
|
47
|
+
* a handoff prompt to orient the agent. Falls back to string-based compaction
|
|
48
|
+
* if the LLM call fails.
|
|
49
|
+
*
|
|
50
|
+
* @param history - The full conversation history.
|
|
51
|
+
* @param llm - The LLM to use for summarization (should be a fast/cheap model).
|
|
52
|
+
* @param keepLastN - Number of recent messages to preserve (default: 8).
|
|
53
|
+
* @returns CompactionResult with the new history and metrics.
|
|
54
|
+
*/
|
|
55
|
+
compactHistoryWithLLM(history: BaseMessage[], llm: Runnable | BaseChatModel, keepLastN?: number): Promise<CompactionResult>;
|
|
41
56
|
/**
|
|
42
57
|
* Checks if the conversation should be compacted based on token usage.
|
|
43
58
|
*
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { SystemMessage, HumanMessage, } from "@langchain/core/messages";
|
|
2
2
|
import { countMessageTokens } from "./tokenCounter.js";
|
|
3
|
+
import { ConversationCompactor } from "./compactor.js";
|
|
3
4
|
/**
|
|
4
5
|
* CacheOptimizedPromptBuilder
|
|
5
6
|
*
|
|
@@ -20,18 +21,15 @@ export class CacheOptimizedPromptBuilder {
|
|
|
20
21
|
// We use SystemMessages for the static prefix.
|
|
21
22
|
// In @langchain/anthropic, to use cache_control, we can inject it into the final message of each tier if needed,
|
|
22
23
|
// but preserving the exact order of the system prompts is the main requirement.
|
|
24
|
+
const unifiedContent = [
|
|
25
|
+
state.globalSystemInstructions,
|
|
26
|
+
`--- Project Context ---\n${state.projectMemory}`,
|
|
27
|
+
`--- Session Rules ---\n${state.sessionContext}`,
|
|
28
|
+
].join("\n\n");
|
|
23
29
|
const systemMessages = [
|
|
24
30
|
new SystemMessage({
|
|
25
|
-
content:
|
|
26
|
-
name: "
|
|
27
|
-
}),
|
|
28
|
-
new SystemMessage({
|
|
29
|
-
content: `--- Project Context ---\n${state.projectMemory}`,
|
|
30
|
-
name: "project_context",
|
|
31
|
-
}),
|
|
32
|
-
new SystemMessage({
|
|
33
|
-
content: `--- Session Rules ---\n${state.sessionContext}`,
|
|
34
|
-
name: "session_context",
|
|
31
|
+
content: unifiedContent,
|
|
32
|
+
name: "global_context",
|
|
35
33
|
}),
|
|
36
34
|
];
|
|
37
35
|
// Combine the static prefix with the dynamic conversation history
|
|
@@ -49,7 +47,7 @@ export class CacheOptimizedPromptBuilder {
|
|
|
49
47
|
return [...history, reminderMsg];
|
|
50
48
|
}
|
|
51
49
|
/**
|
|
52
|
-
* Cache-Safe Compaction
|
|
50
|
+
* Cache-Safe Compaction (string-based fallback)
|
|
53
51
|
* When history gets too long, we preserve the last N messages (recent context)
|
|
54
52
|
* and replace older messages with a summary. The static system prefix is untouched.
|
|
55
53
|
*
|
|
@@ -61,13 +59,28 @@ export class CacheOptimizedPromptBuilder {
|
|
|
61
59
|
if (history.length === 0) {
|
|
62
60
|
return history;
|
|
63
61
|
}
|
|
64
|
-
// Use
|
|
65
|
-
//
|
|
66
|
-
const compactedMessage = new
|
|
62
|
+
// Use HumanMessage formatted as a system update to avoid breaking Google's validation
|
|
63
|
+
// and maintaining proper user/assistant flow.
|
|
64
|
+
const compactedMessage = new HumanMessage(`<system-update>\n[The previous conversation history has been compacted.]\nSummary:\n${summary}\n</system-update>`);
|
|
67
65
|
// Preserve recent messages for continuity
|
|
68
66
|
const recentMessages = history.slice(-keepLastN);
|
|
69
67
|
return [compactedMessage, ...recentMessages];
|
|
70
68
|
}
|
|
69
|
+
/**
|
|
70
|
+
* LLM-Powered Compaction with Handoff
|
|
71
|
+
* Uses a dedicated LLM call to generate a structured summary, then injects
|
|
72
|
+
* a handoff prompt to orient the agent. Falls back to string-based compaction
|
|
73
|
+
* if the LLM call fails.
|
|
74
|
+
*
|
|
75
|
+
* @param history - The full conversation history.
|
|
76
|
+
* @param llm - The LLM to use for summarization (should be a fast/cheap model).
|
|
77
|
+
* @param keepLastN - Number of recent messages to preserve (default: 8).
|
|
78
|
+
* @returns CompactionResult with the new history and metrics.
|
|
79
|
+
*/
|
|
80
|
+
async compactHistoryWithLLM(history, llm, keepLastN = 8) {
|
|
81
|
+
const compactor = new ConversationCompactor();
|
|
82
|
+
return compactor.compact(history, llm, { keepLastN });
|
|
83
|
+
}
|
|
71
84
|
/**
|
|
72
85
|
* Checks if the conversation should be compacted based on token usage.
|
|
73
86
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"promptBuilder.js","sourceRoot":"","sources":["../../src/core/promptBuilder.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,aAAa,EACb,YAAY,GAEb,MAAM,0BAA0B,CAAC;
|
|
1
|
+
{"version":3,"file":"promptBuilder.js","sourceRoot":"","sources":["../../src/core/promptBuilder.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,aAAa,EACb,YAAY,GAEb,MAAM,0BAA0B,CAAC;AAGlC,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AACvD,OAAO,EAAE,qBAAqB,EAAoB,MAAM,gBAAgB,CAAC;AASzE;;;;;;;;;;GAUG;AACH,MAAM,OAAO,2BAA2B;IACtC;;;OAGG;IACI,WAAW,CAAC,KAAmB;QACpC,+CAA+C;QAC/C,iHAAiH;QACjH,gFAAgF;QAEhF,MAAM,cAAc,GAAG;YACrB,KAAK,CAAC,wBAAwB;YAC9B,4BAA4B,KAAK,CAAC,aAAa,EAAE;YACjD,0BAA0B,KAAK,CAAC,cAAc,EAAE;SACjD,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAEf,MAAM,cAAc,GAAkB;YACpC,IAAI,aAAa,CAAC;gBAChB,OAAO,EAAE,cAAc;gBACvB,IAAI,EAAE,gBAAgB;aACvB,CAAC;SACH,CAAC;QAEF,kEAAkE;QAClE,OAAO,CAAC,GAAG,cAAc,EAAE,GAAG,KAAK,CAAC,mBAAmB,CAAC,CAAC;IAC3D,CAAC;IAED;;;;OAIG;IACI,oBAAoB,CACzB,OAAsB,EACtB,QAAgB;QAEhB,MAAM,WAAW,GAAG,IAAI,YAAY,CAAC;YACnC,OAAO,EAAE,sBAAsB,QAAQ,sBAAsB;SAC9D,CAAC,CAAC;QACH,OAAO,CAAC,GAAG,OAAO,EAAE,WAAW,CAAC,CAAC;IACnC,CAAC;IAED;;;;;;;;OAQG;IACI,cAAc,CACnB,OAAsB,EACtB,OAAe,EACf,SAAS,GAAG,CAAC;QAEb,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACzB,OAAO,OAAO,CAAC;QACjB,CAAC;QAED,sFAAsF;QACtF,8CAA8C;QAC9C,MAAM,gBAAgB,GAAG,IAAI,YAAY,CACvC,uFAAuF,OAAO,oBAAoB,CACnH,CAAC;QAEF,0CAA0C;QAC1C,MAAM,cAAc,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,SAAS,CAAC,CAAC;QAEjD,OAAO,CAAC,gBAAgB,EAAE,GAAG,cAAc,CAAC,CAAC;IAC/C,CAAC;IAED;;;;;;;;;;OAUG;IACI,KAAK,CAAC,qBAAqB,CAChC,OAAsB,EACtB,GAA6B,EAC7B,SAAS,GAAG,CAAC;QAEb,MAAM,SAAS,GAAG,IAAI,qBAAqB,EAAE,CAAC;QAC9C,OAAO,SAAS,CAAC,OAAO,CAAC,OAAO,EAAE,GAAG,EAAE,EAAE,SAAS,EAAE,CAAC,CAAC;IACxD,CAAC;IAED;;;;;;OAMG;IACI,aAAa,CAClB,KAAmB,EACnB,SAAiB,EACjB,SAAS,GAAG,GAAG;QAEf,MAAM,WAAW,GAAG,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;QAC5C,MAAM,KAAK,GAAG,kBAAkB,CAAC,WAAW,CAAC,CAAC;QAC9C,OAAO,KAAK,IAAI,SAAS,GAAG,SAAS,CAAC;IACxC,CAAC;CACF"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as fs from "node:fs";
|
|
2
2
|
import * as path from "node:path";
|
|
3
|
-
import { AIMessage,
|
|
3
|
+
import { AIMessage, HumanMessage } from "@langchain/core/messages";
|
|
4
4
|
export class SessionResumer {
|
|
5
5
|
workspaceDir;
|
|
6
6
|
constructor(workspaceDir) {
|
|
@@ -29,9 +29,9 @@ export class SessionResumer {
|
|
|
29
29
|
else {
|
|
30
30
|
wakeupPrompt += `- No files in your active context appear to have been edited on the host while you were paused.\n`;
|
|
31
31
|
}
|
|
32
|
-
// Inject as a
|
|
32
|
+
// Inject as a Human Message at the very end of the history
|
|
33
33
|
// so it acts as an immediate reminder before the next LLM generation.
|
|
34
|
-
state.conversationHistory.push(new
|
|
34
|
+
state.conversationHistory.push(new HumanMessage(`<system-wakeup>\n${wakeupPrompt}\n</system-wakeup>`));
|
|
35
35
|
return state;
|
|
36
36
|
}
|
|
37
37
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sessionResumer.js","sourceRoot":"","sources":["../../src/core/sessionResumer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAC9B,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAGlC,OAAO,EAAE,SAAS,
|
|
1
|
+
{"version":3,"file":"sessionResumer.js","sourceRoot":"","sources":["../../src/core/sessionResumer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAC9B,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAGlC,OAAO,EAAE,SAAS,EAAE,YAAY,EAA8B,MAAM,0BAA0B,CAAC;AAE/F,MAAM,OAAO,cAAc;IACf,YAAY,CAAS;IAE7B,YAAY,YAAoB;QAC5B,IAAI,CAAC,YAAY,GAAG,YAAY,CAAC;IACrC,CAAC;IAED;;;OAGG;IACI,gBAAgB,CAAC,OAA4B;QAChD,MAAM,KAAK,GAAG,EAAE,GAAG,OAAO,CAAC,KAAK,EAAE,CAAC;QAEnC,uBAAuB;QACvB,MAAM,YAAY,GAAG,IAAI,CAAC,eAAe,CAAC,KAAK,EAAE,OAAO,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;QAE7E,yDAAyD;QACzD,IAAI,YAAY,GAAG,0CAA0C,CAAC;QAC9D,YAAY,IAAI,gFAAgF,CAAC;QACjG,YAAY,IAAI,sBAAsB,CAAC;QACvC,YAAY,IAAI,qLAAqL,CAAC;QAEtM,IAAI,YAAY,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC1B,YAAY,IAAI,6FAA6F,CAAC;YAC9G,KAAK,MAAM,IAAI,IAAI,YAAY,EAAE,CAAC;gBAC9B,YAAY,IAAI,SAAS,IAAI,MAAM,CAAC;YACxC,CAAC;YACD,YAAY,IAAI,wJAAwJ,CAAC;QAC7K,CAAC;aAAM,CAAC;YACJ,YAAY,IAAI,mGAAmG,CAAC;QACxH,CAAC;QAED,2DAA2D;QAC3D,sEAAsE;QACtE,KAAK,CAAC,mBAAmB,CAAC,IAAI,CAAC,IAAI,YAAY,CAAC,oBAAoB,YAAY,oBAAoB,CAAC,CAAC,CAAC;QAEvG,OAAO,KAAK,CAAC;IACjB,CAAC;IAED;;;;OAIG;IACI,eAAe,CAAC,KAAmB,EAAE,WAAmB;QAC3D,MAAM,eAAe,GAAG,IAAI,GAAG,EAAU,CAAC;QAE1C,kEAAkE;QAClE,KAAK,MAAM,GAAG,IAAI,KAAK,CAAC,mBAAmB,EAAE,CAAC;YAC1C,IAAI,GAAG,YAAY,SAAS,IAAI,GAAG,CAAC,UAAU,EAAE,CAAC;gBAC7C,KAAK,MAAM,IAAI,IAAI,GAAG,CAAC,UAAU,EAAE,CAAC;oBAChC,IAAI,IAAI,CAAC,IAAI,KAAK,WAAW,IAAI,IAAI,CAAC,IAAI,KAAK,YAAY,IAAI,IAAI,CAAC,IAAI,KAAK,sBAAsB,IAAI,IAAI,CAAC,IAAI,KAAK,4BAA4B,IAAI,IAAI,CAAC,IAAI,KAAK,WAAW,EAAE,CAAC;wBAC7K,IAAI,UAAU,GAAG,EAAE,CAAC;wBACpB,IAAI,IAAI,CAAC,IAAI,CAAC,IAAI;4BAAE,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC;wBAChD,IAAI,IAAI,CAAC,IAAI,CAAC,YAAY;4BAAE,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,YAAY,CAAC;wBAChE,IAAI,IAAI,CAAC,IAAI,CAAC,UAAU;4BAAE,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC;wBAE5D,IAAI,UAAU,EAAE,CAAC;4BACb,eAAe,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;wBACpC,CAAC;oBACL,CAAC;gBACL,CAAC;YACL,CAAC;QACL,CAAC;QAED,MAAM,OAAO,GAAa,EAAE,CAAC;QAE7B,KAAK,MAAM,IAAI,IAAI,eAAe,EAAE,CAAC;YACjC,kEAAkE;YAClE,MAAM,YAAY,GAAG,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,YAAY,EAAE,IAAI,CAAC,CAAC;YAE1F,IAAI,EAAE,CAAC,UAAU,CAAC,YAAY,CAAC,EAAE,CAAC;gBAC9B,MAAM,KAAK,GAAG,EAAE,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAC;gBACxC,qFAAqF;gBACrF,IAAI,KAAK,CAAC,OAAO,GAAG,WAAW,EAAE,CAAC;oBAC9B,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;gBACvB,CAAC;YACL,CAAC;QACL,CAAC;QAED,OAAO,OAAO,CAAC;IACnB,CAAC;CACJ"}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Sub-Agent Manager
|
|
3
|
+
*
|
|
4
|
+
* Spawns and orchestrates isolated sub-agents for scoped tasks.
|
|
5
|
+
* Each sub-agent gets its own ExecutionHarness with a separate conversation
|
|
6
|
+
* history. Only the final SubAgentResult is returned to the main agent,
|
|
7
|
+
* discarding the sub-agent's internal conversation to save context.
|
|
8
|
+
*
|
|
9
|
+
* Supports both synchronous (blocking) and asynchronous (non-blocking) modes.
|
|
10
|
+
*
|
|
11
|
+
* Safety:
|
|
12
|
+
* - Depth limit of 1: sub-agents cannot spawn other sub-agents
|
|
13
|
+
* - maxTurns cap per agent prevents doom-loops
|
|
14
|
+
* - Concurrent async agent cap of 3 prevents resource exhaustion
|
|
15
|
+
* - Per-agent token budget tracking
|
|
16
|
+
*/
|
|
17
|
+
import { SubAgentResult } from "../agents/agentSpec.js";
|
|
18
|
+
import { AgentRegistry } from "../agents/agentRegistry.js";
|
|
19
|
+
import { DynamicToolInterface } from "../tools/index.js";
|
|
20
|
+
import { BaseChatModel } from "@langchain/core/language_models/chat_models";
|
|
21
|
+
import { Runnable } from "@langchain/core/runnables";
|
|
22
|
+
export declare class SubAgentManager {
|
|
23
|
+
private registry;
|
|
24
|
+
private allTools;
|
|
25
|
+
private llm;
|
|
26
|
+
private asyncTasks;
|
|
27
|
+
private taskCounter;
|
|
28
|
+
constructor(registry: AgentRegistry, tools: DynamicToolInterface[], llm: Runnable | BaseChatModel);
|
|
29
|
+
/**
|
|
30
|
+
* Synchronous spawn — blocks until the sub-agent finishes.
|
|
31
|
+
*/
|
|
32
|
+
spawn(agentName: string, task: string, maxTurnsOverride?: number): Promise<SubAgentResult>;
|
|
33
|
+
/**
|
|
34
|
+
* Asynchronous spawn — returns immediately with a taskId.
|
|
35
|
+
* The main agent can poll with getResult(taskId).
|
|
36
|
+
*/
|
|
37
|
+
spawnAsync(agentName: string, task: string, maxTurnsOverride?: number): Promise<string>;
|
|
38
|
+
/**
|
|
39
|
+
* Check the status or get the result of an async task.
|
|
40
|
+
* Returns the result if completed, or a status message if still running.
|
|
41
|
+
*/
|
|
42
|
+
getResult(taskId: string): Promise<SubAgentResult | string>;
|
|
43
|
+
/**
|
|
44
|
+
* Core execution loop for a sub-agent.
|
|
45
|
+
* Creates an isolated conversation and runs a multi-turn loop.
|
|
46
|
+
*/
|
|
47
|
+
private runAgent;
|
|
48
|
+
/**
|
|
49
|
+
* Creates an error SubAgentResult.
|
|
50
|
+
*/
|
|
51
|
+
private makeErrorResult;
|
|
52
|
+
/**
|
|
53
|
+
* Clean up expired async tasks.
|
|
54
|
+
*/
|
|
55
|
+
private cleanupExpired;
|
|
56
|
+
}
|
|
@@ -0,0 +1,240 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Sub-Agent Manager
|
|
3
|
+
*
|
|
4
|
+
* Spawns and orchestrates isolated sub-agents for scoped tasks.
|
|
5
|
+
* Each sub-agent gets its own ExecutionHarness with a separate conversation
|
|
6
|
+
* history. Only the final SubAgentResult is returned to the main agent,
|
|
7
|
+
* discarding the sub-agent's internal conversation to save context.
|
|
8
|
+
*
|
|
9
|
+
* Supports both synchronous (blocking) and asynchronous (non-blocking) modes.
|
|
10
|
+
*
|
|
11
|
+
* Safety:
|
|
12
|
+
* - Depth limit of 1: sub-agents cannot spawn other sub-agents
|
|
13
|
+
* - maxTurns cap per agent prevents doom-loops
|
|
14
|
+
* - Concurrent async agent cap of 3 prevents resource exhaustion
|
|
15
|
+
* - Per-agent token budget tracking
|
|
16
|
+
*/
|
|
17
|
+
import { countMessageTokens } from "../core/tokenCounter.js";
|
|
18
|
+
import { HumanMessage, SystemMessage, ToolMessage } from "@langchain/core/messages";
|
|
19
|
+
// ─── Constants ──────────────────────────────────────────────────────────────────
|
|
20
|
+
const DEFAULT_MAX_TURNS = 10;
|
|
21
|
+
const MAX_CONCURRENT_ASYNC = 3;
|
|
22
|
+
const ASYNC_EXPIRY_MS = 5 * 60 * 1000; // 5 minutes
|
|
23
|
+
// ─── SubAgentManager ────────────────────────────────────────────────────────────
|
|
24
|
+
export class SubAgentManager {
|
|
25
|
+
registry;
|
|
26
|
+
allTools;
|
|
27
|
+
llm;
|
|
28
|
+
asyncTasks = new Map();
|
|
29
|
+
taskCounter = 0;
|
|
30
|
+
constructor(registry, tools, llm) {
|
|
31
|
+
this.registry = registry;
|
|
32
|
+
// Filter out spawn_agent and check_agent to prevent recursive nesting (depth-1 limit)
|
|
33
|
+
this.allTools = tools.filter((t) => t.name !== "spawn_agent" && t.name !== "check_agent");
|
|
34
|
+
this.llm = llm;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Synchronous spawn — blocks until the sub-agent finishes.
|
|
38
|
+
*/
|
|
39
|
+
async spawn(agentName, task, maxTurnsOverride) {
|
|
40
|
+
const spec = this.registry.get(agentName);
|
|
41
|
+
if (!spec) {
|
|
42
|
+
return this.makeErrorResult(agentName, task, `Unknown agent "${agentName}". Available: ${this.registry.getNames().join(", ")}`);
|
|
43
|
+
}
|
|
44
|
+
return this.runAgent(spec, task, maxTurnsOverride);
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Asynchronous spawn — returns immediately with a taskId.
|
|
48
|
+
* The main agent can poll with getResult(taskId).
|
|
49
|
+
*/
|
|
50
|
+
async spawnAsync(agentName, task, maxTurnsOverride) {
|
|
51
|
+
// Cap concurrent async agents
|
|
52
|
+
this.cleanupExpired();
|
|
53
|
+
const activeCount = Array.from(this.asyncTasks.values())
|
|
54
|
+
.filter((t) => !t.completed).length;
|
|
55
|
+
if (activeCount >= MAX_CONCURRENT_ASYNC) {
|
|
56
|
+
throw new Error(`Maximum concurrent async agents reached (${MAX_CONCURRENT_ASYNC}). ` +
|
|
57
|
+
`Wait for existing tasks to complete or check them with check_agent.`);
|
|
58
|
+
}
|
|
59
|
+
const spec = this.registry.get(agentName);
|
|
60
|
+
if (!spec) {
|
|
61
|
+
throw new Error(`Unknown agent "${agentName}". Available: ${this.registry.getNames().join(", ")}`);
|
|
62
|
+
}
|
|
63
|
+
const taskId = `task_${++this.taskCounter}_${Date.now()}`;
|
|
64
|
+
const promise = this.runAgent(spec, task, maxTurnsOverride).then((result) => {
|
|
65
|
+
const asyncTask = this.asyncTasks.get(taskId);
|
|
66
|
+
if (asyncTask) {
|
|
67
|
+
asyncTask.result = result;
|
|
68
|
+
asyncTask.completed = true;
|
|
69
|
+
}
|
|
70
|
+
return result;
|
|
71
|
+
});
|
|
72
|
+
this.asyncTasks.set(taskId, {
|
|
73
|
+
taskId,
|
|
74
|
+
agentName,
|
|
75
|
+
taskDescription: task,
|
|
76
|
+
promise,
|
|
77
|
+
startedAt: Date.now(),
|
|
78
|
+
completed: false,
|
|
79
|
+
});
|
|
80
|
+
return taskId;
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Check the status or get the result of an async task.
|
|
84
|
+
* Returns the result if completed, or a status message if still running.
|
|
85
|
+
*/
|
|
86
|
+
async getResult(taskId) {
|
|
87
|
+
const asyncTask = this.asyncTasks.get(taskId);
|
|
88
|
+
if (!asyncTask) {
|
|
89
|
+
return `Unknown task ID: ${taskId}. No such async task exists.`;
|
|
90
|
+
}
|
|
91
|
+
if (asyncTask.completed && asyncTask.result) {
|
|
92
|
+
// Clean up the task
|
|
93
|
+
this.asyncTasks.delete(taskId);
|
|
94
|
+
return asyncTask.result;
|
|
95
|
+
}
|
|
96
|
+
const elapsed = Math.round((Date.now() - asyncTask.startedAt) / 1000);
|
|
97
|
+
return `Task "${asyncTask.taskDescription}" (agent: ${asyncTask.agentName}) ` +
|
|
98
|
+
`is still running (${elapsed}s elapsed).`;
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Core execution loop for a sub-agent.
|
|
102
|
+
* Creates an isolated conversation and runs a multi-turn loop.
|
|
103
|
+
*/
|
|
104
|
+
async runAgent(spec, task, maxTurnsOverride) {
|
|
105
|
+
const startTime = Date.now();
|
|
106
|
+
const maxTurns = maxTurnsOverride ?? spec.maxTurns ?? DEFAULT_MAX_TURNS;
|
|
107
|
+
// Resolve available tools for this agent
|
|
108
|
+
const agentTools = spec.tools
|
|
109
|
+
? this.allTools.filter((t) => spec.tools.includes(t.name))
|
|
110
|
+
: this.allTools;
|
|
111
|
+
// Create isolated conversation history
|
|
112
|
+
const systemPrompt = new SystemMessage(`${spec.systemPrompt}\n\n--- Current Task ---\n${task}`);
|
|
113
|
+
const history = [
|
|
114
|
+
new HumanMessage(task),
|
|
115
|
+
];
|
|
116
|
+
let promptTokens = 0;
|
|
117
|
+
let completionTokens = 0;
|
|
118
|
+
let toolCallCount = 0;
|
|
119
|
+
let turnsUsed = 0;
|
|
120
|
+
let lastResponse = "";
|
|
121
|
+
const filesModified = new Set();
|
|
122
|
+
// Build LangChain tool declarations for binding
|
|
123
|
+
const toolDeclarations = agentTools.map((t) => ({
|
|
124
|
+
name: t.name,
|
|
125
|
+
description: t.description,
|
|
126
|
+
schema: t.schema,
|
|
127
|
+
}));
|
|
128
|
+
try {
|
|
129
|
+
// Bind tools to the LLM for this sub-agent session
|
|
130
|
+
let boundLlm;
|
|
131
|
+
if ("bindTools" in this.llm && typeof this.llm.bindTools === "function") {
|
|
132
|
+
boundLlm = this.llm.bindTools(toolDeclarations);
|
|
133
|
+
}
|
|
134
|
+
else {
|
|
135
|
+
boundLlm = this.llm;
|
|
136
|
+
}
|
|
137
|
+
for (let turn = 0; turn < maxTurns; turn++) {
|
|
138
|
+
turnsUsed++;
|
|
139
|
+
// Build the full message array
|
|
140
|
+
const messages = [systemPrompt, ...history];
|
|
141
|
+
const stepPromptTokens = countMessageTokens(messages);
|
|
142
|
+
promptTokens += stepPromptTokens;
|
|
143
|
+
// Invoke the LLM
|
|
144
|
+
const response = await boundLlm.invoke(messages);
|
|
145
|
+
const responseTokens = countMessageTokens([response]);
|
|
146
|
+
completionTokens += responseTokens;
|
|
147
|
+
const aiMessage = response;
|
|
148
|
+
history.push(aiMessage);
|
|
149
|
+
// Extract text content
|
|
150
|
+
if (typeof aiMessage.content === "string" && aiMessage.content.length > 0) {
|
|
151
|
+
lastResponse = aiMessage.content;
|
|
152
|
+
}
|
|
153
|
+
// Check for tool calls
|
|
154
|
+
if (!aiMessage.tool_calls || aiMessage.tool_calls.length === 0) {
|
|
155
|
+
// No tool calls — agent is done
|
|
156
|
+
break;
|
|
157
|
+
}
|
|
158
|
+
// Execute tool calls
|
|
159
|
+
for (const call of aiMessage.tool_calls) {
|
|
160
|
+
if (!call.id)
|
|
161
|
+
continue;
|
|
162
|
+
const tool = agentTools.find((t) => t.name === call.name);
|
|
163
|
+
if (!tool) {
|
|
164
|
+
history.push(new ToolMessage({
|
|
165
|
+
content: `Error: Tool "${call.name}" is not available to this sub-agent.`,
|
|
166
|
+
tool_call_id: call.id,
|
|
167
|
+
}));
|
|
168
|
+
continue;
|
|
169
|
+
}
|
|
170
|
+
toolCallCount++;
|
|
171
|
+
try {
|
|
172
|
+
const result = await tool.execute(call.args);
|
|
173
|
+
const output = typeof result === "string" ? result : result.content;
|
|
174
|
+
// Track file modifications
|
|
175
|
+
if (call.name === "write_file" && call.args?.path) {
|
|
176
|
+
filesModified.add(call.args.path);
|
|
177
|
+
}
|
|
178
|
+
history.push(new ToolMessage({
|
|
179
|
+
content: output,
|
|
180
|
+
tool_call_id: call.id,
|
|
181
|
+
}));
|
|
182
|
+
}
|
|
183
|
+
catch (err) {
|
|
184
|
+
history.push(new ToolMessage({
|
|
185
|
+
content: `Tool error: ${err.message}`,
|
|
186
|
+
tool_call_id: call.id,
|
|
187
|
+
}));
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
// Determine outcome
|
|
192
|
+
const outcome = turnsUsed >= maxTurns ? "partial" : "success";
|
|
193
|
+
return {
|
|
194
|
+
agentName: spec.name,
|
|
195
|
+
taskDescription: task,
|
|
196
|
+
outcome,
|
|
197
|
+
result: lastResponse || "(Sub-agent produced no text output)",
|
|
198
|
+
filesModified: Array.from(filesModified),
|
|
199
|
+
toolCallCount,
|
|
200
|
+
tokenUsage: { prompt: promptTokens, completion: completionTokens },
|
|
201
|
+
duration: Date.now() - startTime,
|
|
202
|
+
turnsUsed,
|
|
203
|
+
};
|
|
204
|
+
}
|
|
205
|
+
catch (error) {
|
|
206
|
+
return this.makeErrorResult(spec.name, task, `Sub-agent error: ${error.message}`, { promptTokens, completionTokens, toolCallCount, turnsUsed, startTime, filesModified });
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
/**
|
|
210
|
+
* Creates an error SubAgentResult.
|
|
211
|
+
*/
|
|
212
|
+
makeErrorResult(agentName, task, errorMsg, partial) {
|
|
213
|
+
return {
|
|
214
|
+
agentName,
|
|
215
|
+
taskDescription: task,
|
|
216
|
+
outcome: "failure",
|
|
217
|
+
result: errorMsg,
|
|
218
|
+
filesModified: partial ? Array.from(partial.filesModified) : [],
|
|
219
|
+
toolCallCount: partial?.toolCallCount ?? 0,
|
|
220
|
+
tokenUsage: {
|
|
221
|
+
prompt: partial?.promptTokens ?? 0,
|
|
222
|
+
completion: partial?.completionTokens ?? 0,
|
|
223
|
+
},
|
|
224
|
+
duration: partial ? Date.now() - partial.startTime : 0,
|
|
225
|
+
turnsUsed: partial?.turnsUsed ?? 0,
|
|
226
|
+
};
|
|
227
|
+
}
|
|
228
|
+
/**
|
|
229
|
+
* Clean up expired async tasks.
|
|
230
|
+
*/
|
|
231
|
+
cleanupExpired() {
|
|
232
|
+
const now = Date.now();
|
|
233
|
+
for (const [taskId, task] of this.asyncTasks.entries()) {
|
|
234
|
+
if (now - task.startedAt > ASYNC_EXPIRY_MS) {
|
|
235
|
+
this.asyncTasks.delete(taskId);
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
//# sourceMappingURL=subAgent.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"subAgent.js","sourceRoot":"","sources":["../../src/core/subAgent.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { ExecutionHarness } from "./core/agentLoop.js";
|
|
2
|
+
import { ChatGoogleGenerativeAI } from "@langchain/google-genai";
|
|
3
|
+
import { HumanMessage } from "@langchain/core/messages";
|
|
4
|
+
async function run() {
|
|
5
|
+
const llm = new ChatGoogleGenerativeAI({ apiKey: "dummy-key", modelName: "gemini-1.5-pro" });
|
|
6
|
+
const harness = new ExecutionHarness(llm, [], undefined, undefined, "google", "gemini-1.5-pro");
|
|
7
|
+
const state = {
|
|
8
|
+
globalSystemInstructions: `You are Joone...`,
|
|
9
|
+
projectMemory: "No project context loaded yet.",
|
|
10
|
+
sessionContext: `Environment: test\nCWD: test`,
|
|
11
|
+
conversationHistory: [
|
|
12
|
+
new HumanMessage("Hello Google AI")
|
|
13
|
+
]
|
|
14
|
+
};
|
|
15
|
+
try {
|
|
16
|
+
await harness.step(state);
|
|
17
|
+
}
|
|
18
|
+
catch (e) {
|
|
19
|
+
console.error("Caught in harness:", e.message);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
run();
|
|
23
|
+
//# sourceMappingURL=debug_google.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"debug_google.js","sourceRoot":"","sources":["../src/debug_google.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AACvD,OAAO,EAAE,sBAAsB,EAAE,MAAM,yBAAyB,CAAC;AACjE,OAAO,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAExD,KAAK,UAAU,GAAG;IAChB,MAAM,GAAG,GAAG,IAAI,sBAAsB,CAAC,EAAE,MAAM,EAAE,WAAW,EAAE,SAAS,EAAE,gBAAgB,EAAE,CAAC,CAAC;IAC7F,MAAM,OAAO,GAAG,IAAI,gBAAgB,CAAC,GAAG,EAAE,EAAE,EAAE,SAAS,EAAE,SAAS,EAAE,QAAQ,EAAE,gBAAgB,CAAC,CAAC;IAEhG,MAAM,KAAK,GAAG;QACZ,wBAAwB,EAAE,kBAAkB;QAC5C,aAAa,EAAE,gCAAgC;QAC/C,cAAc,EAAE,8BAA8B;QAC9C,mBAAmB,EAAE;YACnB,IAAI,YAAY,CAAC,iBAAiB,CAAC;SACpC;KACF,CAAC;IAEF,IAAI,CAAC;QACH,MAAM,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAC5B,CAAC;IAAC,OAAO,CAAM,EAAE,CAAC;QAChB,OAAO,CAAC,KAAK,CAAC,oBAAoB,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC;IACjD,CAAC;AACH,CAAC;AAED,GAAG,EAAE,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|