joonecli 0.1.0 → 0.2.0
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/{src/agents/builtinAgents.ts → dist/agents/builtinAgents.js} +84 -101
- 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 +29 -2
- 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 +92 -0
- package/dist/commands/commandRegistry.js +128 -0
- package/dist/commands/commandRegistry.js.map +1 -0
- package/dist/core/agentLoop.d.ts +7 -2
- package/dist/core/agentLoop.js +35 -13
- 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 +38 -0
- package/dist/core/contextGuard.js +122 -0
- package/dist/core/contextGuard.js.map +1 -0
- package/dist/core/events.d.ts +45 -0
- package/dist/core/events.js +8 -0
- package/dist/core/events.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/sessionStore.js +3 -2
- package/dist/core/sessionStore.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/core/tokenCounter.d.ts +8 -1
- package/dist/core/tokenCounter.js +28 -0
- package/dist/core/tokenCounter.js.map +1 -1
- 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/middleware/permission.js +1 -0
- package/dist/middleware/permission.js.map +1 -1
- 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/browser.js +4 -1
- package/dist/tools/browser.js.map +1 -1
- package/dist/tools/index.d.ts +2 -1
- package/dist/tools/index.js +11 -3
- package/dist/tools/index.js.map +1 -1
- package/dist/tools/installHostDeps.d.ts +2 -0
- package/dist/tools/installHostDeps.js +37 -0
- package/dist/tools/installHostDeps.js.map +1 -0
- package/dist/tools/router.js +3 -0
- package/dist/tools/router.js.map +1 -1
- package/dist/tools/spawnAgent.d.ts +19 -0
- package/dist/tools/spawnAgent.js +132 -0
- package/dist/tools/spawnAgent.js.map +1 -0
- package/dist/tracing/sessionTracer.d.ts +1 -0
- package/dist/tracing/sessionTracer.js +4 -1
- package/dist/tracing/sessionTracer.js.map +1 -1
- package/dist/ui/App.js +94 -6
- package/dist/ui/App.js.map +1 -1
- package/dist/ui/components/ActionLog.d.ts +7 -0
- package/dist/ui/components/ActionLog.js +63 -0
- package/dist/ui/components/ActionLog.js.map +1 -0
- package/dist/ui/components/FileBrowser.d.ts +2 -0
- package/dist/ui/components/FileBrowser.js +41 -0
- package/dist/ui/components/FileBrowser.js.map +1 -0
- package/package.json +5 -6
- package/AGENTS.md +0 -56
- package/Handover.md +0 -115
- package/PROGRESS.md +0 -160
- package/docs/01_insights_and_patterns.md +0 -27
- package/docs/02_edge_cases_and_mitigations.md +0 -143
- package/docs/03_initial_implementation_plan.md +0 -66
- package/docs/04_tech_stack_proposal.md +0 -20
- package/docs/05_prd.md +0 -87
- package/docs/06_user_stories.md +0 -72
- package/docs/07_system_architecture.md +0 -138
- package/docs/08_roadmap.md +0 -200
- package/e2b/Dockerfile +0 -26
- package/src/__tests__/bootstrap.test.ts +0 -111
- package/src/__tests__/config.test.ts +0 -97
- package/src/__tests__/m55.test.ts +0 -238
- package/src/__tests__/middleware.test.ts +0 -219
- package/src/__tests__/modelFactory.test.ts +0 -63
- package/src/__tests__/optimizations.test.ts +0 -201
- package/src/__tests__/promptBuilder.test.ts +0 -141
- package/src/__tests__/sandbox.test.ts +0 -102
- package/src/__tests__/security.test.ts +0 -122
- package/src/__tests__/streaming.test.ts +0 -82
- package/src/__tests__/toolRouter.test.ts +0 -52
- package/src/__tests__/tools.test.ts +0 -146
- package/src/__tests__/tracing.test.ts +0 -196
- package/src/agents/agentRegistry.ts +0 -69
- package/src/agents/agentSpec.ts +0 -67
- package/src/cli/config.ts +0 -124
- package/src/cli/index.ts +0 -730
- package/src/cli/modelFactory.ts +0 -174
- package/src/cli/providers.ts +0 -107
- package/src/commands/builtinCommands.ts +0 -293
- package/src/commands/commandRegistry.ts +0 -194
- package/src/core/agentLoop.d.ts.map +0 -1
- package/src/core/agentLoop.ts +0 -312
- package/src/core/autoSave.ts +0 -95
- package/src/core/compactor.ts +0 -252
- package/src/core/contextGuard.ts +0 -129
- package/src/core/errors.ts +0 -202
- package/src/core/promptBuilder.d.ts.map +0 -1
- package/src/core/promptBuilder.ts +0 -139
- package/src/core/reasoningRouter.ts +0 -121
- package/src/core/retry.ts +0 -75
- package/src/core/sessionResumer.ts +0 -90
- package/src/core/sessionStore.ts +0 -215
- package/src/core/subAgent.ts +0 -339
- package/src/core/tokenCounter.ts +0 -64
- package/src/evals/dataset.ts +0 -67
- package/src/evals/evaluator.ts +0 -81
- package/src/hitl/bridge.ts +0 -160
- package/src/middleware/commandSanitizer.ts +0 -60
- package/src/middleware/loopDetection.ts +0 -63
- package/src/middleware/permission.ts +0 -72
- package/src/middleware/pipeline.ts +0 -75
- package/src/middleware/preCompletion.ts +0 -94
- package/src/middleware/types.ts +0 -45
- package/src/sandbox/bootstrap.ts +0 -121
- package/src/sandbox/manager.ts +0 -239
- package/src/sandbox/sync.ts +0 -157
- package/src/skills/loader.ts +0 -143
- package/src/skills/tools.ts +0 -99
- package/src/skills/types.ts +0 -13
- package/src/test_cache.ts +0 -72
- package/src/test_google.js +0 -40
- package/src/test_google.ts +0 -40
- package/src/tools/askUser.ts +0 -47
- package/src/tools/browser.ts +0 -137
- package/src/tools/index.d.ts.map +0 -1
- package/src/tools/index.ts +0 -237
- package/src/tools/registry.ts +0 -198
- package/src/tools/router.ts +0 -78
- package/src/tools/security.ts +0 -220
- package/src/tools/spawnAgent.ts +0 -158
- package/src/tools/webSearch.ts +0 -142
- package/src/tracing/analyzer.ts +0 -265
- package/src/tracing/langsmith.ts +0 -63
- package/src/tracing/sessionTracer.ts +0 -202
- package/src/tracing/types.ts +0 -49
- package/src/types/valyu.d.ts +0 -37
- package/src/ui/App.tsx +0 -404
- package/src/ui/components/HITLPrompt.tsx +0 -119
- package/src/ui/components/Header.tsx +0 -51
- package/src/ui/components/MessageBubble.tsx +0 -46
- package/src/ui/components/StatusBar.tsx +0 -138
- package/src/ui/components/StreamingText.tsx +0 -48
- package/src/ui/components/ToolCallPanel.tsx +0 -80
- package/tests/commands/commands.test.ts +0 -356
- package/tests/core/compactor.test.ts +0 -217
- package/tests/core/retryAndErrors.test.ts +0 -164
- package/tests/core/sessionResumer.test.ts +0 -95
- package/tests/core/sessionStore.test.ts +0 -84
- package/tests/core/stability.test.ts +0 -165
- package/tests/core/subAgent.test.ts +0 -238
- package/tests/hitl/hitlBridge.test.ts +0 -115
- package/tsconfig.json +0 -16
- package/vitest.config.ts +0 -10
- package/vitest.out +0 -48
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Conversation Compactor
|
|
3
|
+
*
|
|
4
|
+
* Replaces the simple string-based compaction with an LLM-powered summary.
|
|
5
|
+
* Uses a dedicated compact prompt to produce a high-quality structured summary,
|
|
6
|
+
* then injects a handoff prompt to orient the agent after compaction.
|
|
7
|
+
*
|
|
8
|
+
* Architecture:
|
|
9
|
+
* 1. Evicted messages (all except keepLastN) are sent to a dedicated LLM call
|
|
10
|
+
* 2. The LLM produces a structured markdown summary preserving critical context
|
|
11
|
+
* 3. A handoff prompt is injected after the summary to guide the agent
|
|
12
|
+
* 4. Falls back to string-based compaction if the LLM call fails
|
|
13
|
+
*/
|
|
14
|
+
import { HumanMessage } from "@langchain/core/messages";
|
|
15
|
+
import { countMessageTokens } from "./tokenCounter.js";
|
|
16
|
+
// ─── Compact Prompt ─────────────────────────────────────────────────────────────
|
|
17
|
+
export const COMPACT_SYSTEM_PROMPT = `You are a conversation summarizer. Your task is to produce a structured reference document from the conversation below.
|
|
18
|
+
|
|
19
|
+
PRESERVE ALL of the following (do NOT omit):
|
|
20
|
+
- File paths created, edited, or deleted
|
|
21
|
+
- Tool calls made and their outcomes (success or failure)
|
|
22
|
+
- Key decisions made and the rationale behind them
|
|
23
|
+
- Current task state — what has been completed and what remains
|
|
24
|
+
- Errors encountered and how they were resolved
|
|
25
|
+
- Code snippets or configurations that are critical to the ongoing task
|
|
26
|
+
|
|
27
|
+
FORMAT as structured markdown with clear sections:
|
|
28
|
+
## Files Modified
|
|
29
|
+
## Decisions Made
|
|
30
|
+
## Current State
|
|
31
|
+
## Errors & Resolutions
|
|
32
|
+
|
|
33
|
+
Be thorough but concise. Do NOT include conversational filler or pleasantries.`;
|
|
34
|
+
// ─── Handoff Prompt ─────────────────────────────────────────────────────────────
|
|
35
|
+
export function createHandoffPrompt(compactionTimestamp) {
|
|
36
|
+
return `[CONTEXT HANDOFF] Your earlier conversation has been compacted into the summary above.
|
|
37
|
+
You are the same agent continuing the same task. Key points:
|
|
38
|
+
- The summary preserves all file paths, decisions, tool outcomes, and errors
|
|
39
|
+
- If you need details not included in the summary, re-read the relevant files using read_file
|
|
40
|
+
- Continue from where the conversation left off — do NOT redo work described in the summary
|
|
41
|
+
- Compacted at: ${compactionTimestamp}`;
|
|
42
|
+
}
|
|
43
|
+
// ─── Fast Model Defaults ────────────────────────────────────────────────────────
|
|
44
|
+
/**
|
|
45
|
+
* Maps each provider to its cheapest/fastest model for use in compaction
|
|
46
|
+
* and sub-agent tasks. Users can override via config.compactModel.
|
|
47
|
+
*/
|
|
48
|
+
export const FAST_MODEL_DEFAULTS = {
|
|
49
|
+
anthropic: "claude-3-haiku-20240307",
|
|
50
|
+
openai: "gpt-4o-mini",
|
|
51
|
+
google: "gemini-2.5-flash",
|
|
52
|
+
mistral: "mistral-small-latest",
|
|
53
|
+
groq: "mixtral-8x7b-32768",
|
|
54
|
+
deepseek: "deepseek-chat",
|
|
55
|
+
fireworks: "accounts/fireworks/models/llama-v3p1-70b-instruct",
|
|
56
|
+
together: "meta-llama/Llama-3.1-70B-Instruct-Turbo",
|
|
57
|
+
ollama: "mistral",
|
|
58
|
+
};
|
|
59
|
+
/**
|
|
60
|
+
* Resolves the model to use for compaction/sub-agents.
|
|
61
|
+
* Priority: explicit override > FAST_MODEL_DEFAULTS > main model (fallback)
|
|
62
|
+
*/
|
|
63
|
+
export function resolveFastModel(provider, mainModel, override) {
|
|
64
|
+
if (override)
|
|
65
|
+
return override;
|
|
66
|
+
return FAST_MODEL_DEFAULTS[provider] ?? mainModel;
|
|
67
|
+
}
|
|
68
|
+
// ─── ConversationCompactor ──────────────────────────────────────────────────────
|
|
69
|
+
export class ConversationCompactor {
|
|
70
|
+
/**
|
|
71
|
+
* Compact a conversation history using an LLM to generate a structured summary.
|
|
72
|
+
*
|
|
73
|
+
* @param history — The full conversation history
|
|
74
|
+
* @param llm — The LLM to use for summarization (should be a fast/cheap model)
|
|
75
|
+
* @param options — Compaction options
|
|
76
|
+
* @returns CompactionResult with the new compacted history
|
|
77
|
+
*/
|
|
78
|
+
async compact(history, llm, options = {}) {
|
|
79
|
+
const keepLastN = options.keepLastN ?? 8;
|
|
80
|
+
const maxSummaryTokens = options.maxSummaryTokens ?? 2000;
|
|
81
|
+
if (history.length <= keepLastN) {
|
|
82
|
+
return {
|
|
83
|
+
compactedHistory: history,
|
|
84
|
+
evictedCount: 0,
|
|
85
|
+
tokensBefore: countMessageTokens(history),
|
|
86
|
+
tokensAfter: countMessageTokens(history),
|
|
87
|
+
llmUsed: false,
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
const tokensBefore = countMessageTokens(history);
|
|
91
|
+
const evictedMessages = history.slice(0, history.length - keepLastN);
|
|
92
|
+
const recentMessages = history.slice(-keepLastN);
|
|
93
|
+
const evictedCount = evictedMessages.length;
|
|
94
|
+
// Try LLM-powered compaction
|
|
95
|
+
try {
|
|
96
|
+
const summaryText = await this.generateLLMSummary(evictedMessages, llm, maxSummaryTokens);
|
|
97
|
+
const summaryMessage = new HumanMessage(`<system-summary>\n[COMPACTED CONVERSATION SUMMARY]\n${summaryText}\n</system-summary>`);
|
|
98
|
+
const handoffMessage = new HumanMessage(`<system-handoff>\n${createHandoffPrompt(new Date().toISOString())}\n</system-handoff>`);
|
|
99
|
+
const compactedHistory = [summaryMessage, handoffMessage, ...recentMessages];
|
|
100
|
+
const tokensAfter = countMessageTokens(compactedHistory);
|
|
101
|
+
return {
|
|
102
|
+
compactedHistory,
|
|
103
|
+
evictedCount,
|
|
104
|
+
tokensBefore,
|
|
105
|
+
tokensAfter,
|
|
106
|
+
llmUsed: true,
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
catch (error) {
|
|
110
|
+
// Fallback to string-based compaction
|
|
111
|
+
return this.fallbackCompact(history, evictedMessages, recentMessages, tokensBefore);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Generates a structured summary using the LLM.
|
|
116
|
+
*/
|
|
117
|
+
async generateLLMSummary(evictedMessages, llm, maxSummaryTokens) {
|
|
118
|
+
// Construct the prompt for the compactor LLM
|
|
119
|
+
const compactPrompt = new HumanMessage(`<system-directive>\n${COMPACT_SYSTEM_PROMPT}\n\nKeep your summary under ${maxSummaryTokens} tokens.\n</system-directive>`);
|
|
120
|
+
// Convert evicted messages into a readable format for the summarizer
|
|
121
|
+
const conversationText = evictedMessages
|
|
122
|
+
.map((msg) => {
|
|
123
|
+
const role = msg._getType();
|
|
124
|
+
const content = typeof msg.content === "string"
|
|
125
|
+
? msg.content
|
|
126
|
+
: JSON.stringify(msg.content);
|
|
127
|
+
return `[${role}]: ${content}`;
|
|
128
|
+
})
|
|
129
|
+
.join("\n\n");
|
|
130
|
+
const summaryRequest = new HumanMessage(`Summarize this conversation:\n\n${conversationText}`);
|
|
131
|
+
const response = await llm.invoke([compactPrompt, summaryRequest]);
|
|
132
|
+
// Extract text from response
|
|
133
|
+
if (typeof response === "string")
|
|
134
|
+
return response;
|
|
135
|
+
if ("content" in response && typeof response.content === "string") {
|
|
136
|
+
return response.content;
|
|
137
|
+
}
|
|
138
|
+
throw new Error("Unexpected LLM response format during compaction");
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* Fallback compaction using a simple heuristic summary (no LLM call).
|
|
142
|
+
* Used when the LLM call fails.
|
|
143
|
+
*/
|
|
144
|
+
fallbackCompact(_fullHistory, evictedMessages, recentMessages, tokensBefore) {
|
|
145
|
+
// Build a basic summary from message roles and lengths
|
|
146
|
+
const humanMsgCount = evictedMessages.filter(m => m._getType() === "human").length;
|
|
147
|
+
const aiMsgCount = evictedMessages.filter(m => m._getType() === "ai").length;
|
|
148
|
+
const toolMsgCount = evictedMessages.filter(m => m._getType() === "tool").length;
|
|
149
|
+
const summaryText = [
|
|
150
|
+
`[Fallback Compaction — LLM summary unavailable]`,
|
|
151
|
+
`Evicted ${evictedMessages.length} messages:`,
|
|
152
|
+
` - ${humanMsgCount} user messages`,
|
|
153
|
+
` - ${aiMsgCount} agent responses`,
|
|
154
|
+
` - ${toolMsgCount} tool results`,
|
|
155
|
+
`The conversation is continuing below.`,
|
|
156
|
+
].join("\n");
|
|
157
|
+
const summaryMessage = new HumanMessage(`<system-summary>\n${summaryText}\n</system-summary>`);
|
|
158
|
+
const handoffMessage = new HumanMessage(`<system-handoff>\n${createHandoffPrompt(new Date().toISOString())}\n</system-handoff>`);
|
|
159
|
+
const compactedHistory = [summaryMessage, handoffMessage, ...recentMessages];
|
|
160
|
+
const tokensAfter = countMessageTokens(compactedHistory);
|
|
161
|
+
return {
|
|
162
|
+
compactedHistory,
|
|
163
|
+
evictedCount: evictedMessages.length,
|
|
164
|
+
tokensBefore,
|
|
165
|
+
tokensAfter,
|
|
166
|
+
llmUsed: false,
|
|
167
|
+
};
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
//# sourceMappingURL=compactor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"compactor.js","sourceRoot":"","sources":["../../src/core/compactor.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,38 @@
|
|
|
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 { BaseChatModel } from "@langchain/core/language_models/chat_models";
|
|
12
|
+
import { Runnable } from "@langchain/core/runnables";
|
|
13
|
+
import { CacheOptimizedPromptBuilder, ContextState } from "./promptBuilder.js";
|
|
14
|
+
export interface ContextGuardMetrics {
|
|
15
|
+
originalTokens: number;
|
|
16
|
+
newTokens: number;
|
|
17
|
+
messagesEvicted: number;
|
|
18
|
+
actionTaken: "none" | "compacted" | "emergency_truncated";
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Maps providers and models to their actual maximum context windows,
|
|
22
|
+
* decoupling the context limit from the completion size maxTokens flag.
|
|
23
|
+
*/
|
|
24
|
+
export declare function getProviderContextLimit(provider: string, model: string): number;
|
|
25
|
+
export declare class ContextGuard {
|
|
26
|
+
private promptBuilder;
|
|
27
|
+
private llm;
|
|
28
|
+
private maxTokens;
|
|
29
|
+
constructor(llm: Runnable | BaseChatModel, maxTokens: number, promptBuilder?: CacheOptimizedPromptBuilder);
|
|
30
|
+
/**
|
|
31
|
+
* Checks the token usage of the current state and compacts if necessary.
|
|
32
|
+
* Returns updated state and metrics about the action taken.
|
|
33
|
+
*/
|
|
34
|
+
ensureCapacity(state: ContextState, warnThreshold?: number, criticalThreshold?: number): Promise<{
|
|
35
|
+
state: ContextState;
|
|
36
|
+
metrics: ContextGuardMetrics;
|
|
37
|
+
}>;
|
|
38
|
+
}
|
|
@@ -0,0 +1,122 @@
|
|
|
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 { HumanMessage } from "@langchain/core/messages";
|
|
12
|
+
import { CacheOptimizedPromptBuilder } from "./promptBuilder.js";
|
|
13
|
+
import { countMessageTokens } from "./tokenCounter.js";
|
|
14
|
+
import { createHandoffPrompt } from "./compactor.js";
|
|
15
|
+
/**
|
|
16
|
+
* Maps providers and models to their actual maximum context windows,
|
|
17
|
+
* decoupling the context limit from the completion size maxTokens flag.
|
|
18
|
+
*/
|
|
19
|
+
export function getProviderContextLimit(provider, model) {
|
|
20
|
+
const p = provider.toLowerCase();
|
|
21
|
+
const m = model.toLowerCase();
|
|
22
|
+
if (p === "google-genai" || p === "google" || p === "google-vertexai") {
|
|
23
|
+
return 1_000_000;
|
|
24
|
+
}
|
|
25
|
+
if (p === "anthropic") {
|
|
26
|
+
return 200_000;
|
|
27
|
+
}
|
|
28
|
+
if (p === "openai") {
|
|
29
|
+
return 128_000;
|
|
30
|
+
}
|
|
31
|
+
if (p === "mistral") {
|
|
32
|
+
return 32_000;
|
|
33
|
+
}
|
|
34
|
+
if (p === "groq") {
|
|
35
|
+
if (m.includes("llama-3.1") || m.includes("llama3"))
|
|
36
|
+
return 128_000;
|
|
37
|
+
return 32_000;
|
|
38
|
+
}
|
|
39
|
+
// Default fallback
|
|
40
|
+
return 100_000;
|
|
41
|
+
}
|
|
42
|
+
export class ContextGuard {
|
|
43
|
+
promptBuilder;
|
|
44
|
+
llm;
|
|
45
|
+
maxTokens;
|
|
46
|
+
constructor(llm, maxTokens, promptBuilder = new CacheOptimizedPromptBuilder()) {
|
|
47
|
+
this.llm = llm;
|
|
48
|
+
this.maxTokens = maxTokens;
|
|
49
|
+
this.promptBuilder = promptBuilder;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Checks the token usage of the current state and compacts if necessary.
|
|
53
|
+
* Returns updated state and metrics about the action taken.
|
|
54
|
+
*/
|
|
55
|
+
async ensureCapacity(state, warnThreshold = 0.8, criticalThreshold = 0.95) {
|
|
56
|
+
const fullPrompt = this.promptBuilder.buildPrompt(state);
|
|
57
|
+
const tokenCount = countMessageTokens(fullPrompt);
|
|
58
|
+
// 1. Under limit — do nothing
|
|
59
|
+
if (tokenCount < this.maxTokens * warnThreshold) {
|
|
60
|
+
return {
|
|
61
|
+
state,
|
|
62
|
+
metrics: {
|
|
63
|
+
originalTokens: tokenCount,
|
|
64
|
+
newTokens: tokenCount,
|
|
65
|
+
messagesEvicted: 0,
|
|
66
|
+
actionTaken: "none",
|
|
67
|
+
},
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
// 2. Over WARN but below CRITICAL — try standard LLM compaction
|
|
71
|
+
if (tokenCount < this.maxTokens * criticalThreshold) {
|
|
72
|
+
const result = await this.promptBuilder.compactHistoryWithLLM(state.conversationHistory, this.llm, 8 // keep last 8 messages
|
|
73
|
+
);
|
|
74
|
+
return {
|
|
75
|
+
state: {
|
|
76
|
+
...state,
|
|
77
|
+
conversationHistory: result.compactedHistory,
|
|
78
|
+
},
|
|
79
|
+
metrics: {
|
|
80
|
+
originalTokens: tokenCount,
|
|
81
|
+
newTokens: result.tokensAfter,
|
|
82
|
+
messagesEvicted: result.evictedCount,
|
|
83
|
+
actionTaken: "compacted",
|
|
84
|
+
},
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
// 3. CRITICAL overflow (or standard compaction didn't free enough space)
|
|
88
|
+
// Emergency truncation: drop everything except the last 4 messages and inject an emergency handoff
|
|
89
|
+
const keepLast = 4;
|
|
90
|
+
// If we're already at or below 4 messages, we literally can't truncate more
|
|
91
|
+
if (state.conversationHistory.length <= keepLast) {
|
|
92
|
+
return {
|
|
93
|
+
state,
|
|
94
|
+
metrics: { originalTokens: tokenCount, newTokens: tokenCount, messagesEvicted: 0, actionTaken: "none" }
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
const recentMsgs = state.conversationHistory.slice(-keepLast);
|
|
98
|
+
const evictedCount = state.conversationHistory.length - keepLast;
|
|
99
|
+
const emergencySystemMsg = new HumanMessage(`<system-alert>\n[EMERGENCY CONTEXT TRUNCATION]\n` +
|
|
100
|
+
`The conversation exceeded the maximum context window (${this.maxTokens} tokens). ` +
|
|
101
|
+
`Older messages were aggressively deleted without summarization to prevent an immediate crash.\n` +
|
|
102
|
+
`You are the same agent. ` + createHandoffPrompt(new Date().toISOString()) + `\n</system-alert>`);
|
|
103
|
+
const newHistory = [emergencySystemMsg, ...recentMsgs];
|
|
104
|
+
const newTokens = countMessageTokens(this.promptBuilder.buildPrompt({
|
|
105
|
+
...state,
|
|
106
|
+
conversationHistory: newHistory
|
|
107
|
+
}));
|
|
108
|
+
return {
|
|
109
|
+
state: {
|
|
110
|
+
...state,
|
|
111
|
+
conversationHistory: newHistory,
|
|
112
|
+
},
|
|
113
|
+
metrics: {
|
|
114
|
+
originalTokens: tokenCount,
|
|
115
|
+
newTokens,
|
|
116
|
+
messagesEvicted: evictedCount,
|
|
117
|
+
actionTaken: "emergency_truncated",
|
|
118
|
+
},
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
//# sourceMappingURL=contextGuard.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"contextGuard.js","sourceRoot":"","sources":["../../src/core/contextGuard.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Agent Event System
|
|
3
|
+
*
|
|
4
|
+
* Defines the strongly typed events emitted by the ExecutionHarness
|
|
5
|
+
* for real-time tracking of agent actions within the TUI.
|
|
6
|
+
*/
|
|
7
|
+
export type AgentEvent = {
|
|
8
|
+
type: "agent:stream";
|
|
9
|
+
token: string;
|
|
10
|
+
} | {
|
|
11
|
+
type: "tool:start";
|
|
12
|
+
toolName: string;
|
|
13
|
+
args: string;
|
|
14
|
+
} | {
|
|
15
|
+
type: "tool:end";
|
|
16
|
+
toolName: string;
|
|
17
|
+
result: string;
|
|
18
|
+
durationMs: number;
|
|
19
|
+
} | {
|
|
20
|
+
type: "subagent:spawn";
|
|
21
|
+
agentName: string;
|
|
22
|
+
task: string;
|
|
23
|
+
} | {
|
|
24
|
+
type: "file:io";
|
|
25
|
+
action: "read" | "write";
|
|
26
|
+
path: string;
|
|
27
|
+
} | {
|
|
28
|
+
type: "system:script_exec";
|
|
29
|
+
command: string;
|
|
30
|
+
location: "host" | "sandbox";
|
|
31
|
+
} | {
|
|
32
|
+
type: "browser:nav";
|
|
33
|
+
url: string;
|
|
34
|
+
} | {
|
|
35
|
+
type: "system:save";
|
|
36
|
+
sessionId: string;
|
|
37
|
+
};
|
|
38
|
+
/**
|
|
39
|
+
* Interface for typed event emitters overriding Node's EventEmitter
|
|
40
|
+
*/
|
|
41
|
+
export interface AgentEventEmitter {
|
|
42
|
+
on(event: "agent:event", listener: (e: AgentEvent) => void): this;
|
|
43
|
+
emit(event: "agent:event", e: AgentEvent): boolean;
|
|
44
|
+
off(event: "agent:event", listener: (e: AgentEvent) => void): this;
|
|
45
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"events.js","sourceRoot":"","sources":["../../src/core/events.ts"],"names":[],"mappings":"AAAA;;;;;GAKG"}
|
|
@@ -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":"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"}
|
|
@@ -2,7 +2,7 @@ import * as fs from "node:fs";
|
|
|
2
2
|
import * as path from "node:path";
|
|
3
3
|
import * as os from "node:os";
|
|
4
4
|
import * as readline from "node:readline";
|
|
5
|
-
import { HumanMessage, AIMessage,
|
|
5
|
+
import { HumanMessage, AIMessage, ToolMessage } from "@langchain/core/messages";
|
|
6
6
|
// Ensure the sessions directory exists
|
|
7
7
|
const SESSIONS_DIR = path.join(os.homedir(), ".joone", "sessions");
|
|
8
8
|
/**
|
|
@@ -43,7 +43,8 @@ export class SessionStore {
|
|
|
43
43
|
tool_calls: raw.tool_calls || undefined,
|
|
44
44
|
});
|
|
45
45
|
case "system":
|
|
46
|
-
|
|
46
|
+
// Remap old saved SystemMessages to HumanMessages to prevent provider index errors
|
|
47
|
+
return new HumanMessage(`<system-reminder>\n${raw.content}\n</system-reminder>`);
|
|
47
48
|
case "tool":
|
|
48
49
|
return new ToolMessage({
|
|
49
50
|
content: raw.content,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sessionStore.js","sourceRoot":"","sources":["../../src/core/sessionStore.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAC9B,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAClC,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAC9B,OAAO,KAAK,QAAQ,MAAM,eAAe,CAAC;AAC1C,OAAO,EAEH,YAAY,EACZ,SAAS,
|
|
1
|
+
{"version":3,"file":"sessionStore.js","sourceRoot":"","sources":["../../src/core/sessionStore.ts"],"names":[],"mappings":"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"}
|