@sylix/coworker 1.1.4 → 1.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/dist/cli/index.d.ts +7 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +183 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/config/SettingsManager.d.ts +25 -0
- package/dist/config/SettingsManager.d.ts.map +1 -0
- package/dist/config/SettingsManager.js +96 -0
- package/dist/config/SettingsManager.js.map +1 -0
- package/dist/core/CoWorkerAgent.d.ts +52 -0
- package/dist/core/CoWorkerAgent.d.ts.map +1 -0
- package/dist/core/CoWorkerAgent.js +308 -0
- package/dist/core/CoWorkerAgent.js.map +1 -0
- package/dist/mcp/MCPClientManager.d.ts +30 -0
- package/dist/mcp/MCPClientManager.d.ts.map +1 -0
- package/dist/mcp/MCPClientManager.js +100 -0
- package/dist/mcp/MCPClientManager.js.map +1 -0
- package/dist/permissions/PermissionInterceptor.d.ts +21 -0
- package/dist/permissions/PermissionInterceptor.d.ts.map +1 -0
- package/dist/permissions/PermissionInterceptor.js +104 -0
- package/dist/permissions/PermissionInterceptor.js.map +1 -0
- package/dist/session/SessionManager.d.ts +38 -0
- package/dist/session/SessionManager.d.ts.map +1 -0
- package/dist/session/SessionManager.js +129 -0
- package/dist/session/SessionManager.js.map +1 -0
- package/dist/skills/HookAndSkillManager.d.ts +37 -0
- package/dist/skills/HookAndSkillManager.d.ts.map +1 -0
- package/dist/skills/HookAndSkillManager.js +141 -0
- package/dist/skills/HookAndSkillManager.js.map +1 -0
- package/dist/task/TaskEngine.d.ts +29 -0
- package/dist/task/TaskEngine.d.ts.map +1 -0
- package/dist/task/TaskEngine.js +117 -0
- package/dist/task/TaskEngine.js.map +1 -0
- package/dist/tools/CronManager.d.ts +22 -0
- package/dist/tools/CronManager.d.ts.map +1 -0
- package/dist/tools/CronManager.js +44 -0
- package/dist/tools/CronManager.js.map +1 -0
- package/dist/tools/NativeTools.d.ts +33 -0
- package/dist/tools/NativeTools.d.ts.map +1 -0
- package/dist/tools/NativeTools.js +175 -0
- package/dist/tools/NativeTools.js.map +1 -0
- package/dist/tools/Schemas.d.ts +365 -0
- package/dist/tools/Schemas.d.ts.map +1 -0
- package/dist/tools/Schemas.js +177 -0
- package/dist/tools/Schemas.js.map +1 -0
- package/dist/ui/InkUI.d.ts +2 -0
- package/dist/ui/InkUI.d.ts.map +1 -0
- package/dist/ui/InkUI.js +11 -0
- package/dist/ui/InkUI.js.map +1 -0
- package/package.json +18 -8
- package/dist/agents/runner.d.ts +0 -19
- package/dist/agents/runner.d.ts.map +0 -1
- package/dist/agents/runner.js +0 -170
- package/dist/agents/runner.js.map +0 -1
- package/dist/api/sylix.d.ts +0 -53
- package/dist/api/sylix.d.ts.map +0 -1
- package/dist/api/sylix.js +0 -237
- package/dist/api/sylix.js.map +0 -1
- package/dist/cli.d.ts +0 -3
- package/dist/cli.d.ts.map +0 -1
- package/dist/cli.js +0 -369
- package/dist/cli.js.map +0 -1
- package/dist/commands/ask.d.ts +0 -2
- package/dist/commands/ask.d.ts.map +0 -1
- package/dist/commands/ask.js +0 -55
- package/dist/commands/ask.js.map +0 -1
- package/dist/commands/chat.d.ts +0 -8
- package/dist/commands/chat.d.ts.map +0 -1
- package/dist/commands/chat.js +0 -479
- package/dist/commands/chat.js.map +0 -1
- package/dist/commands/commit.d.ts +0 -2
- package/dist/commands/commit.d.ts.map +0 -1
- package/dist/commands/commit.js +0 -163
- package/dist/commands/commit.js.map +0 -1
- package/dist/commands/config.d.ts +0 -3
- package/dist/commands/config.d.ts.map +0 -1
- package/dist/commands/config.js +0 -101
- package/dist/commands/config.js.map +0 -1
- package/dist/commands/edit.d.ts +0 -2
- package/dist/commands/edit.d.ts.map +0 -1
- package/dist/commands/edit.js +0 -112
- package/dist/commands/edit.js.map +0 -1
- package/dist/commands/explain.d.ts +0 -2
- package/dist/commands/explain.d.ts.map +0 -1
- package/dist/commands/explain.js +0 -99
- package/dist/commands/explain.js.map +0 -1
- package/dist/commands/login.d.ts +0 -2
- package/dist/commands/login.d.ts.map +0 -1
- package/dist/commands/login.js +0 -151
- package/dist/commands/login.js.map +0 -1
- package/dist/commands/review.d.ts +0 -2
- package/dist/commands/review.d.ts.map +0 -1
- package/dist/commands/review.js +0 -137
- package/dist/commands/review.js.map +0 -1
- package/dist/commands/run.d.ts +0 -2
- package/dist/commands/run.d.ts.map +0 -1
- package/dist/commands/run.js +0 -136
- package/dist/commands/run.js.map +0 -1
- package/dist/config/settings.d.ts +0 -33
- package/dist/config/settings.d.ts.map +0 -1
- package/dist/config/settings.js +0 -72
- package/dist/config/settings.js.map +0 -1
- package/dist/context/reader.d.ts +0 -24
- package/dist/context/reader.d.ts.map +0 -1
- package/dist/context/reader.js +0 -209
- package/dist/context/reader.js.map +0 -1
- package/dist/hooks/engine.d.ts +0 -9
- package/dist/hooks/engine.d.ts.map +0 -1
- package/dist/hooks/engine.js +0 -85
- package/dist/hooks/engine.js.map +0 -1
- package/dist/mcp/client.d.ts +0 -15
- package/dist/mcp/client.d.ts.map +0 -1
- package/dist/mcp/client.js +0 -211
- package/dist/mcp/client.js.map +0 -1
- package/dist/mcp/transport.d.ts +0 -46
- package/dist/mcp/transport.d.ts.map +0 -1
- package/dist/mcp/transport.js +0 -196
- package/dist/mcp/transport.js.map +0 -1
- package/dist/memory/loader.d.ts +0 -41
- package/dist/memory/loader.d.ts.map +0 -1
- package/dist/memory/loader.js +0 -249
- package/dist/memory/loader.js.map +0 -1
- package/dist/permissions/manager.d.ts +0 -7
- package/dist/permissions/manager.d.ts.map +0 -1
- package/dist/permissions/manager.js +0 -125
- package/dist/permissions/manager.js.map +0 -1
- package/dist/scripts/postinstall.d.ts +0 -7
- package/dist/scripts/postinstall.d.ts.map +0 -1
- package/dist/scripts/postinstall.js +0 -23
- package/dist/scripts/postinstall.js.map +0 -1
- package/dist/session/memory.d.ts +0 -6
- package/dist/session/memory.d.ts.map +0 -1
- package/dist/session/memory.js +0 -81
- package/dist/session/memory.js.map +0 -1
- package/dist/session/store.d.ts +0 -19
- package/dist/session/store.d.ts.map +0 -1
- package/dist/session/store.js +0 -94
- package/dist/session/store.js.map +0 -1
- package/dist/tools/bash.d.ts +0 -2
- package/dist/tools/bash.d.ts.map +0 -1
- package/dist/tools/bash.js +0 -40
- package/dist/tools/bash.js.map +0 -1
- package/dist/tools/chrome.d.ts +0 -10
- package/dist/tools/chrome.d.ts.map +0 -1
- package/dist/tools/chrome.js +0 -228
- package/dist/tools/chrome.js.map +0 -1
- package/dist/tools/edit.d.ts +0 -2
- package/dist/tools/edit.d.ts.map +0 -1
- package/dist/tools/edit.js +0 -67
- package/dist/tools/edit.js.map +0 -1
- package/dist/tools/glob.d.ts +0 -10
- package/dist/tools/glob.d.ts.map +0 -1
- package/dist/tools/glob.js +0 -245
- package/dist/tools/glob.js.map +0 -1
- package/dist/tools/grep.d.ts +0 -10
- package/dist/tools/grep.d.ts.map +0 -1
- package/dist/tools/grep.js +0 -252
- package/dist/tools/grep.js.map +0 -1
- package/dist/tools/ls.d.ts +0 -2
- package/dist/tools/ls.d.ts.map +0 -1
- package/dist/tools/ls.js +0 -75
- package/dist/tools/ls.js.map +0 -1
- package/dist/tools/read.d.ts +0 -2
- package/dist/tools/read.d.ts.map +0 -1
- package/dist/tools/read.js +0 -72
- package/dist/tools/read.js.map +0 -1
- package/dist/tools/registry.d.ts +0 -3
- package/dist/tools/registry.d.ts.map +0 -1
- package/dist/tools/registry.js +0 -281
- package/dist/tools/registry.js.map +0 -1
- package/dist/tools/schema.json +0 -508
- package/dist/tools/task.d.ts +0 -11
- package/dist/tools/task.d.ts.map +0 -1
- package/dist/tools/task.js +0 -118
- package/dist/tools/task.js.map +0 -1
- package/dist/tools/web.d.ts +0 -3
- package/dist/tools/web.d.ts.map +0 -1
- package/dist/tools/web.js +0 -113
- package/dist/tools/web.js.map +0 -1
- package/dist/tools/write.d.ts +0 -18
- package/dist/tools/write.d.ts.map +0 -1
- package/dist/tools/write.js +0 -122
- package/dist/tools/write.js.map +0 -1
- package/dist/utils/output.d.ts +0 -62
- package/dist/utils/output.d.ts.map +0 -1
- package/dist/utils/output.js +0 -487
- package/dist/utils/output.js.map +0 -1
|
@@ -0,0 +1,308 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
36
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
|
+
};
|
|
38
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
+
exports.CoWorkerAgent = void 0;
|
|
40
|
+
const PermissionInterceptor_1 = require("../permissions/PermissionInterceptor");
|
|
41
|
+
const NativeTools_1 = require("../tools/NativeTools");
|
|
42
|
+
const TaskEngine_1 = require("../task/TaskEngine");
|
|
43
|
+
const SessionManager_1 = require("../session/SessionManager");
|
|
44
|
+
const MCPClientManager_1 = require("../mcp/MCPClientManager");
|
|
45
|
+
const HookAndSkillManager_1 = require("../skills/HookAndSkillManager");
|
|
46
|
+
const SettingsManager_1 = require("../config/SettingsManager");
|
|
47
|
+
const Schemas_1 = require("../tools/Schemas");
|
|
48
|
+
const crypto_1 = require("crypto");
|
|
49
|
+
const node_fetch_1 = __importDefault(require("node-fetch"));
|
|
50
|
+
const fs = __importStar(require("fs"));
|
|
51
|
+
const path = __importStar(require("path"));
|
|
52
|
+
const os = __importStar(require("os"));
|
|
53
|
+
const child_process_1 = require("child_process");
|
|
54
|
+
const MAX_TOOL_TURNS = 25;
|
|
55
|
+
// Resolve the agents directory relative to the project root
|
|
56
|
+
function resolveAgentsDir() {
|
|
57
|
+
const candidates = [
|
|
58
|
+
path.join(process.cwd(), 'agents/system-prompts-and-models-of-ai-tools/Anthropic/Claude Code'),
|
|
59
|
+
path.join(__dirname, '../../agents/system-prompts-and-models-of-ai-tools/Anthropic/Claude Code'),
|
|
60
|
+
path.join(__dirname, '../../../agents/system-prompts-and-models-of-ai-tools/Anthropic/Claude Code'),
|
|
61
|
+
];
|
|
62
|
+
for (const candidate of candidates) {
|
|
63
|
+
if (fs.existsSync(candidate))
|
|
64
|
+
return candidate;
|
|
65
|
+
}
|
|
66
|
+
return candidates[0];
|
|
67
|
+
}
|
|
68
|
+
const FALLBACK_SYSTEM_PROMPT = `You are CoWorker, an autonomous AI coding agent by Sylix.
|
|
69
|
+
You help developers write, debug, and understand code.
|
|
70
|
+
You have access to tools to search files, read the web, and write code on the user's local machine.
|
|
71
|
+
Always be concise, direct, and helpful. When creating files, use the executeWrite tool.
|
|
72
|
+
When searching for files, use executeGlob. When searching inside files, use executeGrep.
|
|
73
|
+
Never refuse a reasonable coding request. Execute tools to accomplish the task.`;
|
|
74
|
+
function getGitContext(cwd) {
|
|
75
|
+
try {
|
|
76
|
+
const isRepo = (0, child_process_1.execSync)('git rev-parse --is-inside-work-tree', { cwd, encoding: 'utf8', stdio: 'ignore' });
|
|
77
|
+
const branch = (0, child_process_1.execSync)('git branch --show-current', { cwd, encoding: 'utf8' }).trim();
|
|
78
|
+
const status = (0, child_process_1.execSync)('git status --short', { cwd, encoding: 'utf8' }).trim() || '(clean)';
|
|
79
|
+
const commits = (0, child_process_1.execSync)('git log -n 5 --oneline', { cwd, encoding: 'utf8' }).trim();
|
|
80
|
+
return { isRepo: true, branch, status, commits };
|
|
81
|
+
}
|
|
82
|
+
catch (err) {
|
|
83
|
+
return { isRepo: false, branch: 'unknown', status: 'unknown', commits: 'No git info provided.' };
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
async function getSystemPrompt(cwd) {
|
|
87
|
+
const agentsDir = resolveAgentsDir();
|
|
88
|
+
const promptPath = path.join(agentsDir, 'Prompt.txt');
|
|
89
|
+
let promptText = FALLBACK_SYSTEM_PROMPT;
|
|
90
|
+
try {
|
|
91
|
+
promptText = fs.readFileSync(promptPath, 'utf8');
|
|
92
|
+
promptText = promptText.replace(/Claude Code/g, 'CoWorker');
|
|
93
|
+
}
|
|
94
|
+
catch (err) {
|
|
95
|
+
return FALLBACK_SYSTEM_PROMPT;
|
|
96
|
+
}
|
|
97
|
+
// Hydrate environment variables
|
|
98
|
+
const gitContext = getGitContext(cwd);
|
|
99
|
+
const today = new Date().toISOString().split('T')[0];
|
|
100
|
+
promptText = promptText
|
|
101
|
+
.replace('${Working directory}', cwd)
|
|
102
|
+
.replace('Is directory a git repo: Yes', `Is directory a git repo: ${gitContext.isRepo ? 'Yes' : 'No'}`)
|
|
103
|
+
.replace('Platform: darwin', `Platform: ${os.platform()}`)
|
|
104
|
+
.replace(/OS Version: [^\n]+/, `OS Version: ${os.type()} ${os.release()}`)
|
|
105
|
+
.replace(/Today's date: [^\n]+/, `Today's date: ${today}`)
|
|
106
|
+
.replace(/Current branch: [^\n]+/, `Current branch: ${gitContext.branch}`)
|
|
107
|
+
.replace(/\(clean\)/, gitContext.status)
|
|
108
|
+
.replace('${Last 5 Recent commits}', gitContext.commits);
|
|
109
|
+
return promptText;
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* THE SDK LAYER — Real Agentic Tool Loop.
|
|
113
|
+
* Calls the LLM, parses tool_calls, executes them locally via NativeTools,
|
|
114
|
+
* feeds results back, and loops until the LLM produces a final text response.
|
|
115
|
+
*/
|
|
116
|
+
class CoWorkerAgent {
|
|
117
|
+
constructor(options) {
|
|
118
|
+
this.systemPrompt = FALLBACK_SYSTEM_PROMPT;
|
|
119
|
+
this.model = options.model || 'helix-1.2';
|
|
120
|
+
this.endpoint = options.endpoint || 'https://ollama-ubuntu.sylixide.com';
|
|
121
|
+
this.ollamaModel = 'glm-4.7-flash:q4_K_M'; // Default resolution for helix-1.2
|
|
122
|
+
this.cwd = options.cwd || process.cwd();
|
|
123
|
+
this.tasks = new TaskEngine_1.TaskEngine();
|
|
124
|
+
this.sessions = new SessionManager_1.SessionManager((0, crypto_1.randomUUID)());
|
|
125
|
+
this.mcp = new MCPClientManager_1.MCPClientManager();
|
|
126
|
+
this.hooks = new HookAndSkillManager_1.HookAndSkillManager();
|
|
127
|
+
this.settings = new SettingsManager_1.SettingsManager();
|
|
128
|
+
this.permissions = new PermissionInterceptor_1.PermissionInterceptor();
|
|
129
|
+
}
|
|
130
|
+
async boot() {
|
|
131
|
+
this.systemPrompt = await getSystemPrompt(this.cwd);
|
|
132
|
+
// Load existing session if applicable
|
|
133
|
+
await this.sessions.loadCheckpoint();
|
|
134
|
+
const config = await this.settings.loadSettings();
|
|
135
|
+
this.permissions = new PermissionInterceptor_1.PermissionInterceptor({
|
|
136
|
+
allowedTools: config.allow,
|
|
137
|
+
deniedTools: config.deny
|
|
138
|
+
});
|
|
139
|
+
await this.hooks.loadSkillsFromDirectory();
|
|
140
|
+
for (const [name, server] of Object.entries(config.mcpServers)) {
|
|
141
|
+
await this.mcp.connectServer(name, server.command, server.args);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* The real agentic loop. Calls the LLM, executes tool_calls locally, loops.
|
|
146
|
+
* Yields streaming text chunks for the CLI/UI to render in real-time.
|
|
147
|
+
*/
|
|
148
|
+
async *chat(prompt) {
|
|
149
|
+
await this.sessions.rollupMemory();
|
|
150
|
+
// Build conversation history from session
|
|
151
|
+
const messages = [
|
|
152
|
+
{ role: 'system', content: this.systemPrompt },
|
|
153
|
+
...this.sessions.state.messages
|
|
154
|
+
];
|
|
155
|
+
// Add new user prompt
|
|
156
|
+
const userMsg = { role: 'user', content: prompt };
|
|
157
|
+
messages.push(userMsg);
|
|
158
|
+
await this.sessions.appendMessage(userMsg);
|
|
159
|
+
let turnCount = 0;
|
|
160
|
+
while (turnCount < MAX_TOOL_TURNS) {
|
|
161
|
+
turnCount++;
|
|
162
|
+
// Call the LLM
|
|
163
|
+
const response = await this.callLLM(messages);
|
|
164
|
+
// If the LLM produced text content, yield it
|
|
165
|
+
if (response.content) {
|
|
166
|
+
yield response.content;
|
|
167
|
+
}
|
|
168
|
+
// If no tool_calls, we're done
|
|
169
|
+
if (!response.tool_calls || response.tool_calls.length === 0) {
|
|
170
|
+
break;
|
|
171
|
+
}
|
|
172
|
+
// Add the assistant message with tool_calls to history
|
|
173
|
+
const assistantMsg = {
|
|
174
|
+
role: 'assistant',
|
|
175
|
+
content: response.content || '',
|
|
176
|
+
tool_calls: response.tool_calls
|
|
177
|
+
};
|
|
178
|
+
messages.push(assistantMsg);
|
|
179
|
+
await this.sessions.appendMessage(assistantMsg);
|
|
180
|
+
// Execute each tool call locally
|
|
181
|
+
for (const tc of response.tool_calls) {
|
|
182
|
+
const toolName = tc.function?.name;
|
|
183
|
+
const toolId = tc.id || `call_${(0, crypto_1.randomUUID)().substring(0, 8)}`;
|
|
184
|
+
let args;
|
|
185
|
+
try {
|
|
186
|
+
args = JSON.parse(tc.function?.arguments || '{}');
|
|
187
|
+
}
|
|
188
|
+
catch {
|
|
189
|
+
const errMsg = `[ToolError] Failed to parse arguments for ${toolName}`;
|
|
190
|
+
messages.push({ role: 'tool', content: errMsg, tool_call_id: toolId });
|
|
191
|
+
yield `\n⚠️ ${errMsg}\n`;
|
|
192
|
+
continue;
|
|
193
|
+
}
|
|
194
|
+
// Permission check for mutation tools
|
|
195
|
+
const mutationTools = ['executeWrite', 'run_terminal_command'];
|
|
196
|
+
if (mutationTools.includes(toolName)) {
|
|
197
|
+
const allowed = await this.permissions.intercept(toolName, args);
|
|
198
|
+
if (!allowed) {
|
|
199
|
+
const denied = `[Permission Denied] User blocked execution of ${toolName}`;
|
|
200
|
+
messages.push({ role: 'tool', content: denied, tool_call_id: toolId });
|
|
201
|
+
yield `\n🚫 ${denied}\n`;
|
|
202
|
+
continue;
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
// Pre-tool hook
|
|
206
|
+
await this.hooks.firePreToolHook(toolName, args);
|
|
207
|
+
// Execute the tool
|
|
208
|
+
yield `\n🔧 Executing: ${toolName}...\n`;
|
|
209
|
+
let result;
|
|
210
|
+
try {
|
|
211
|
+
result = await this.executeToolLocally(toolName, args);
|
|
212
|
+
}
|
|
213
|
+
catch (e) {
|
|
214
|
+
result = `[ToolError] ${toolName} crashed: ${e.message}`;
|
|
215
|
+
}
|
|
216
|
+
// Post-tool hook
|
|
217
|
+
await this.hooks.firePostToolHook(toolName, result);
|
|
218
|
+
// Feed result back to LLM
|
|
219
|
+
const toolMsg = { role: 'tool', content: result, tool_call_id: toolId };
|
|
220
|
+
messages.push(toolMsg);
|
|
221
|
+
await this.sessions.appendMessage(toolMsg);
|
|
222
|
+
// Show truncated result to user
|
|
223
|
+
const preview = result.length > 200 ? result.substring(0, 200) + '...' : result;
|
|
224
|
+
yield ` ✅ ${preview}\n`;
|
|
225
|
+
}
|
|
226
|
+
// Loop back — the LLM will see the tool results and decide what to do next
|
|
227
|
+
}
|
|
228
|
+
if (turnCount >= MAX_TOOL_TURNS) {
|
|
229
|
+
yield `\n⚠️ Reached maximum tool turns (${MAX_TOOL_TURNS}). Stopping.\n`;
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
/**
|
|
233
|
+
* Calls helix-1.2 via Ollama's OpenAI-compatible /v1/chat/completions endpoint.
|
|
234
|
+
*/
|
|
235
|
+
async callLLM(messages) {
|
|
236
|
+
const url = `${this.endpoint}/v1/chat/completions`;
|
|
237
|
+
const body = {
|
|
238
|
+
model: this.ollamaModel,
|
|
239
|
+
messages,
|
|
240
|
+
tools: Schemas_1.CoWorkerToolSchemas,
|
|
241
|
+
tool_choice: 'auto',
|
|
242
|
+
stream: false,
|
|
243
|
+
options: {
|
|
244
|
+
num_ctx: 32768,
|
|
245
|
+
num_predict: 4096,
|
|
246
|
+
temperature: 0.7
|
|
247
|
+
}
|
|
248
|
+
};
|
|
249
|
+
const res = await (0, node_fetch_1.default)(url, {
|
|
250
|
+
method: 'POST',
|
|
251
|
+
headers: { 'Content-Type': 'application/json' },
|
|
252
|
+
body: JSON.stringify(body)
|
|
253
|
+
});
|
|
254
|
+
if (!res.ok) {
|
|
255
|
+
const errText = await res.text();
|
|
256
|
+
throw new Error(`LLM call failed (${res.status}): ${errText}`);
|
|
257
|
+
}
|
|
258
|
+
const data = await res.json();
|
|
259
|
+
const message = data.choices?.[0]?.message || data.message || {};
|
|
260
|
+
return {
|
|
261
|
+
content: message.content || '',
|
|
262
|
+
tool_calls: message.tool_calls || []
|
|
263
|
+
};
|
|
264
|
+
}
|
|
265
|
+
/**
|
|
266
|
+
* Local tool dispatcher. Maps tool names to NativeTools methods.
|
|
267
|
+
* This is what makes CoWorker actually create files on the user's machine.
|
|
268
|
+
*/
|
|
269
|
+
async executeToolLocally(toolName, args) {
|
|
270
|
+
switch (toolName) {
|
|
271
|
+
case 'executeWrite':
|
|
272
|
+
return NativeTools_1.NativeTools.executeWrite(args.filePath, args.content);
|
|
273
|
+
case 'executeGlob':
|
|
274
|
+
return (await NativeTools_1.NativeTools.executeGlob(args.pattern, args.dir)).join('\n');
|
|
275
|
+
case 'executeGrep':
|
|
276
|
+
return NativeTools_1.NativeTools.executeGrep(args.regexQuery, args.filesToSearch);
|
|
277
|
+
case 'executeWebSearch':
|
|
278
|
+
return NativeTools_1.NativeTools.executeWebSearch(args.query);
|
|
279
|
+
case 'executeWebFetch':
|
|
280
|
+
return NativeTools_1.NativeTools.executeWebFetch(args.url);
|
|
281
|
+
case 'executeAskUserQuestion':
|
|
282
|
+
return NativeTools_1.NativeTools.executeAskUserQuestion(args.question);
|
|
283
|
+
case 'taskCreate': {
|
|
284
|
+
const id = await this.tasks.createTask(args.description, args.dependencies || []);
|
|
285
|
+
return `Task created with ID: ${id}`;
|
|
286
|
+
}
|
|
287
|
+
case 'taskUpdate': {
|
|
288
|
+
await this.tasks.updateTaskState(args.taskId, args.state, args.notes);
|
|
289
|
+
return `Task ${args.taskId} updated to ${args.state}`;
|
|
290
|
+
}
|
|
291
|
+
default:
|
|
292
|
+
return `[Unknown Tool] "${toolName}" is not registered in CoWorker's local executor.`;
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
/**
|
|
296
|
+
* Subagent: creates a restricted child agent for delegated subtasks.
|
|
297
|
+
*/
|
|
298
|
+
async createSubagent(profileName, subtask) {
|
|
299
|
+
const subAgent = new CoWorkerAgent({ model: this.model, role: 'CodeReviewer' });
|
|
300
|
+
let output = '';
|
|
301
|
+
for await (const chunk of subAgent.chat(subtask)) {
|
|
302
|
+
output += chunk;
|
|
303
|
+
}
|
|
304
|
+
return `[SUBAGENT OUTPUT]: ${output}`;
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
exports.CoWorkerAgent = CoWorkerAgent;
|
|
308
|
+
//# sourceMappingURL=CoWorkerAgent.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CoWorkerAgent.js","sourceRoot":"","sources":["../../src/core/CoWorkerAgent.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
export interface MCPMessage {
|
|
2
|
+
jsonrpc: '2.0';
|
|
3
|
+
id?: string;
|
|
4
|
+
method?: string;
|
|
5
|
+
params?: any;
|
|
6
|
+
result?: any;
|
|
7
|
+
error?: any;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Phase 3: Model Context Protocol (MCP) Stdio JSON-RPC Client.
|
|
11
|
+
* Manages external MCP servers (like Postgres or GitHub integration).
|
|
12
|
+
*/
|
|
13
|
+
export declare class MCPClientManager {
|
|
14
|
+
private connections;
|
|
15
|
+
private requestPromises;
|
|
16
|
+
availableTools: any[];
|
|
17
|
+
/**
|
|
18
|
+
* Spawns an MCP server using StdIO transport.
|
|
19
|
+
*/
|
|
20
|
+
connectServer(name: string, command: string, args: string[]): Promise<void>;
|
|
21
|
+
private handleIncomingMessage;
|
|
22
|
+
private sendRequest;
|
|
23
|
+
private sendNotification;
|
|
24
|
+
refreshTools(serverName: string): Promise<void>;
|
|
25
|
+
/**
|
|
26
|
+
* Executes a remote tool dynamically provided by the MCP server.
|
|
27
|
+
*/
|
|
28
|
+
executeRemoteTool(serverName: string, toolName: string, args: Record<string, any>): Promise<any>;
|
|
29
|
+
}
|
|
30
|
+
//# sourceMappingURL=MCPClientManager.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MCPClientManager.d.ts","sourceRoot":"","sources":["../../src/mcp/MCPClientManager.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE,KAAK,CAAC;IACf,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,GAAG,CAAC;IACb,MAAM,CAAC,EAAE,GAAG,CAAC;IACb,KAAK,CAAC,EAAE,GAAG,CAAC;CACb;AAED;;;GAGG;AACH,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,WAAW,CAAwC;IAC3D,OAAO,CAAC,eAAe,CAAuF;IACvG,cAAc,EAAE,GAAG,EAAE,CAAM;IAElC;;OAEG;IACG,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAgCjF,OAAO,CAAC,qBAAqB;YAaf,WAAW;YAaX,gBAAgB;IAOxB,YAAY,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IASrD;;OAEG;IACG,iBAAiB,CAAC,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,OAAO,CAAC,GAAG,CAAC;CAQvG"}
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.MCPClientManager = void 0;
|
|
4
|
+
const child_process_1 = require("child_process");
|
|
5
|
+
const crypto_1 = require("crypto");
|
|
6
|
+
/**
|
|
7
|
+
* Phase 3: Model Context Protocol (MCP) Stdio JSON-RPC Client.
|
|
8
|
+
* Manages external MCP servers (like Postgres or GitHub integration).
|
|
9
|
+
*/
|
|
10
|
+
class MCPClientManager {
|
|
11
|
+
constructor() {
|
|
12
|
+
this.connections = new Map();
|
|
13
|
+
this.requestPromises = new Map();
|
|
14
|
+
this.availableTools = []; // Stores the external tools
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Spawns an MCP server using StdIO transport.
|
|
18
|
+
*/
|
|
19
|
+
async connectServer(name, command, args) {
|
|
20
|
+
const proc = (0, child_process_1.spawn)(command, args, { stdio: ['pipe', 'pipe', 'inherit'] });
|
|
21
|
+
this.connections.set(name, proc);
|
|
22
|
+
// Listen to stdout from the MCP server
|
|
23
|
+
proc.stdout?.on('data', (data) => {
|
|
24
|
+
const messages = data.toString('utf8').split('\\n').filter(Boolean);
|
|
25
|
+
for (const msgStr of messages) {
|
|
26
|
+
try {
|
|
27
|
+
const msg = JSON.parse(msgStr);
|
|
28
|
+
this.handleIncomingMessage(name, msg);
|
|
29
|
+
}
|
|
30
|
+
catch (e) {
|
|
31
|
+
// Ignore parse errors from non-json stdout noise
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
});
|
|
35
|
+
// Send the initialize handshake
|
|
36
|
+
const initResponse = await this.sendRequest(name, 'initialize', {
|
|
37
|
+
protocolVersion: '2024-11-05',
|
|
38
|
+
capabilities: {},
|
|
39
|
+
clientInfo: { name: 'CoWorker', version: '1.0' }
|
|
40
|
+
});
|
|
41
|
+
// Acknowledge initialization
|
|
42
|
+
await this.sendNotification(name, 'notifications/initialized', {});
|
|
43
|
+
console.log(`[MCP] Successfully initialized connection to: ${name}`);
|
|
44
|
+
// Fetch its available tools immediately upon connection
|
|
45
|
+
await this.refreshTools(name);
|
|
46
|
+
}
|
|
47
|
+
handleIncomingMessage(serverName, msg) {
|
|
48
|
+
// If it has an ID and no method, it's a response to our request
|
|
49
|
+
if (msg.id && !msg.method) {
|
|
50
|
+
const pending = this.requestPromises.get(msg.id);
|
|
51
|
+
if (pending) {
|
|
52
|
+
if (msg.error)
|
|
53
|
+
pending.reject(msg.error);
|
|
54
|
+
else
|
|
55
|
+
pending.resolve(msg.result);
|
|
56
|
+
this.requestPromises.delete(msg.id);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
// Note: servers can also send logging or events via notifications, omitted for brevity.
|
|
60
|
+
}
|
|
61
|
+
async sendRequest(serverName, method, params) {
|
|
62
|
+
const proc = this.connections.get(serverName);
|
|
63
|
+
if (!proc || !proc.stdin)
|
|
64
|
+
throw new Error(`MCP Server ${serverName} not connected.`);
|
|
65
|
+
const id = (0, crypto_1.randomUUID)();
|
|
66
|
+
const req = { jsonrpc: '2.0', id, method, params };
|
|
67
|
+
return new Promise((resolve, reject) => {
|
|
68
|
+
this.requestPromises.set(id, { resolve, reject });
|
|
69
|
+
proc.stdin?.write(JSON.stringify(req) + '\\n');
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
async sendNotification(serverName, method, params) {
|
|
73
|
+
const proc = this.connections.get(serverName);
|
|
74
|
+
if (!proc || !proc.stdin)
|
|
75
|
+
return;
|
|
76
|
+
const req = { jsonrpc: '2.0', method, params };
|
|
77
|
+
proc.stdin.write(JSON.stringify(req) + '\\n');
|
|
78
|
+
}
|
|
79
|
+
async refreshTools(serverName) {
|
|
80
|
+
const res = await this.sendRequest(serverName, 'tools/list', {});
|
|
81
|
+
if (res?.tools) {
|
|
82
|
+
// Annotate the tools with their origin server so we know where to route them later
|
|
83
|
+
const annotatedTools = res.tools.map((t) => ({ ...t, _mcpServer: serverName }));
|
|
84
|
+
this.availableTools.push(...annotatedTools);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Executes a remote tool dynamically provided by the MCP server.
|
|
89
|
+
*/
|
|
90
|
+
async executeRemoteTool(serverName, toolName, args) {
|
|
91
|
+
console.log(`[MCP] Routing tool execution: ${toolName} to ${serverName}`);
|
|
92
|
+
const result = await this.sendRequest(serverName, 'tools/call', {
|
|
93
|
+
name: toolName,
|
|
94
|
+
arguments: args
|
|
95
|
+
});
|
|
96
|
+
return result;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
exports.MCPClientManager = MCPClientManager;
|
|
100
|
+
//# sourceMappingURL=MCPClientManager.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MCPClientManager.js","sourceRoot":"","sources":["../../src/mcp/MCPClientManager.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
export interface PermissionSettings {
|
|
2
|
+
mode: 'plan' | 'auto' | 'acceptEdits';
|
|
3
|
+
allowedTools: string[];
|
|
4
|
+
deniedTools: string[];
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* Phase 1: Security Interceptor.
|
|
8
|
+
* Actually intercepts execution and uses stdin to prompt the user if running in a TTY.
|
|
9
|
+
*/
|
|
10
|
+
export declare class PermissionInterceptor {
|
|
11
|
+
private settings;
|
|
12
|
+
private readonly safeTools;
|
|
13
|
+
constructor(settings?: Partial<PermissionSettings>);
|
|
14
|
+
/**
|
|
15
|
+
* Evaluates a tool call. If it requires human interaction, pauses execution
|
|
16
|
+
* and yields a CLI prompt request using native readline.
|
|
17
|
+
*/
|
|
18
|
+
intercept(toolName: string, args: Record<string, any>): Promise<boolean>;
|
|
19
|
+
private promptUserForPermission;
|
|
20
|
+
}
|
|
21
|
+
//# sourceMappingURL=PermissionInterceptor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PermissionInterceptor.d.ts","sourceRoot":"","sources":["../../src/permissions/PermissionInterceptor.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,aAAa,CAAC;IACtC,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,WAAW,EAAE,MAAM,EAAE,CAAC;CACvB;AAED;;;GAGG;AACH,qBAAa,qBAAqB;IAChC,OAAO,CAAC,QAAQ,CAAqB;IACrC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAA8E;gBAE5F,QAAQ,CAAC,EAAE,OAAO,CAAC,kBAAkB,CAAC;IASlD;;;OAGG;IACU,SAAS,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,OAAO,CAAC,OAAO,CAAC;YAwBvE,uBAAuB;CA0BtC"}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.PermissionInterceptor = void 0;
|
|
37
|
+
const readline = __importStar(require("readline"));
|
|
38
|
+
/**
|
|
39
|
+
* Phase 1: Security Interceptor.
|
|
40
|
+
* Actually intercepts execution and uses stdin to prompt the user if running in a TTY.
|
|
41
|
+
*/
|
|
42
|
+
class PermissionInterceptor {
|
|
43
|
+
constructor(settings) {
|
|
44
|
+
this.safeTools = ['Read', 'Glob', 'Grep', 'web_search', 'web_fetch', 'ls_dir', 'read_file'];
|
|
45
|
+
this.settings = {
|
|
46
|
+
mode: 'acceptEdits',
|
|
47
|
+
allowedTools: [],
|
|
48
|
+
deniedTools: [],
|
|
49
|
+
...settings,
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Evaluates a tool call. If it requires human interaction, pauses execution
|
|
54
|
+
* and yields a CLI prompt request using native readline.
|
|
55
|
+
*/
|
|
56
|
+
async intercept(toolName, args) {
|
|
57
|
+
if (this.safeTools.includes(toolName) || this.settings.mode === 'auto') {
|
|
58
|
+
return true; // Read-only tools bypass prompts
|
|
59
|
+
}
|
|
60
|
+
if (this.settings.allowedTools.includes(toolName)) {
|
|
61
|
+
return true;
|
|
62
|
+
}
|
|
63
|
+
if (this.settings.deniedTools.includes(toolName)) {
|
|
64
|
+
throw new Error(`Permission Denied: Tool ${toolName} is explicitly blocked.`);
|
|
65
|
+
}
|
|
66
|
+
// Trigger interactive IO if not running headlessly
|
|
67
|
+
if (process.stdin.isTTY) {
|
|
68
|
+
return await this.promptUserForPermission(toolName, args);
|
|
69
|
+
}
|
|
70
|
+
else {
|
|
71
|
+
// In a headless environment (like Sylix backend), we have no UI.
|
|
72
|
+
// We must either pass it via WebSocket to the frontend or auto-allow based on strict sandbox logic.
|
|
73
|
+
console.warn(`[WARNING] Auto-allowing ${toolName} due to headless execution.`);
|
|
74
|
+
return true;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
async promptUserForPermission(toolName, args) {
|
|
78
|
+
return new Promise((resolve) => {
|
|
79
|
+
const rl = readline.createInterface({
|
|
80
|
+
input: process.stdin,
|
|
81
|
+
output: process.stdout
|
|
82
|
+
});
|
|
83
|
+
console.warn(`\n\x1b[33m[SECURITY ALERT] CoWorker wants to execute: ${toolName}\x1b[0m`);
|
|
84
|
+
console.warn(`Arguments:`, JSON.stringify(args, null, 2));
|
|
85
|
+
rl.question(`Allow this action? [y/N/a (Always allow)]: `, (answer) => {
|
|
86
|
+
rl.close();
|
|
87
|
+
const response = answer.trim().toLowerCase();
|
|
88
|
+
if (response === 'a') {
|
|
89
|
+
this.settings.allowedTools.push(toolName);
|
|
90
|
+
console.log(`\x1b[32mTool ${toolName} added to session allowlist.\x1b[0m`);
|
|
91
|
+
resolve(true);
|
|
92
|
+
}
|
|
93
|
+
else if (response === 'y') {
|
|
94
|
+
resolve(true);
|
|
95
|
+
}
|
|
96
|
+
else {
|
|
97
|
+
resolve(false);
|
|
98
|
+
}
|
|
99
|
+
});
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
exports.PermissionInterceptor = PermissionInterceptor;
|
|
104
|
+
//# sourceMappingURL=PermissionInterceptor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PermissionInterceptor.js","sourceRoot":"","sources":["../../src/permissions/PermissionInterceptor.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,mDAAqC;AAQrC;;;GAGG;AACH,MAAa,qBAAqB;IAIhC,YAAY,QAAsC;QAFjC,cAAS,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,YAAY,EAAE,WAAW,EAAE,QAAQ,EAAE,WAAW,CAAC,CAAC;QAGtG,IAAI,CAAC,QAAQ,GAAG;YACd,IAAI,EAAE,aAAa;YACnB,YAAY,EAAE,EAAE;YAChB,WAAW,EAAE,EAAE;YACf,GAAG,QAAQ;SACZ,CAAC;IACJ,CAAC;IAED;;;OAGG;IACI,KAAK,CAAC,SAAS,CAAC,QAAgB,EAAE,IAAyB;QAChE,IAAI,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;YACvE,OAAO,IAAI,CAAC,CAAC,iCAAiC;QAChD,CAAC;QAED,IAAI,IAAI,CAAC,QAAQ,CAAC,YAAY,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC;YAClD,OAAO,IAAI,CAAC;QACd,CAAC;QAED,IAAI,IAAI,CAAC,QAAQ,CAAC,WAAW,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC;YACjD,MAAM,IAAI,KAAK,CAAC,2BAA2B,QAAQ,yBAAyB,CAAC,CAAC;QAChF,CAAC;QAED,mDAAmD;QACnD,IAAI,OAAO,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;YACxB,OAAO,MAAM,IAAI,CAAC,uBAAuB,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;QAC5D,CAAC;aAAM,CAAC;YACN,kEAAkE;YAClE,oGAAoG;YACpG,OAAO,CAAC,IAAI,CAAC,2BAA2B,QAAQ,6BAA6B,CAAC,CAAC;YAC/E,OAAO,IAAI,CAAC;QACd,CAAC;IACH,CAAC;IAEO,KAAK,CAAC,uBAAuB,CAAC,QAAgB,EAAE,IAAyB;QAC/E,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;YAC7B,MAAM,EAAE,GAAG,QAAQ,CAAC,eAAe,CAAC;gBAClC,KAAK,EAAE,OAAO,CAAC,KAAK;gBACpB,MAAM,EAAE,OAAO,CAAC,MAAM;aACvB,CAAC,CAAC;YAEH,OAAO,CAAC,IAAI,CAAC,yDAAyD,QAAQ,SAAS,CAAC,CAAC;YACzF,OAAO,CAAC,IAAI,CAAC,YAAY,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;YAE1D,EAAE,CAAC,QAAQ,CAAC,6CAA6C,EAAE,CAAC,MAAM,EAAE,EAAE;gBACpE,EAAE,CAAC,KAAK,EAAE,CAAC;gBACX,MAAM,QAAQ,GAAG,MAAM,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;gBAE7C,IAAI,QAAQ,KAAK,GAAG,EAAE,CAAC;oBACrB,IAAI,CAAC,QAAQ,CAAC,YAAY,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;oBAC1C,OAAO,CAAC,GAAG,CAAC,gBAAgB,QAAQ,qCAAqC,CAAC,CAAC;oBAC3E,OAAO,CAAC,IAAI,CAAC,CAAC;gBAChB,CAAC;qBAAM,IAAI,QAAQ,KAAK,GAAG,EAAE,CAAC;oBAC5B,OAAO,CAAC,IAAI,CAAC,CAAC;gBAChB,CAAC;qBAAM,CAAC;oBACN,OAAO,CAAC,KAAK,CAAC,CAAC;gBACjB,CAAC;YACH,CAAC,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;IACL,CAAC;CACF;AAnED,sDAmEC"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
export interface ChatMessage {
|
|
2
|
+
role: 'user' | 'assistant' | 'system' | 'tool';
|
|
3
|
+
content: string;
|
|
4
|
+
}
|
|
5
|
+
export interface SessionData {
|
|
6
|
+
id: string;
|
|
7
|
+
summary: string;
|
|
8
|
+
messages: ChatMessage[];
|
|
9
|
+
createdAt: string;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Phase 2 & 4: Session Checkpointing and Token Resuming
|
|
13
|
+
* Fully implemented to write memory snapshots mapped by session ID.
|
|
14
|
+
*/
|
|
15
|
+
export declare class SessionManager {
|
|
16
|
+
private readonly baseDir;
|
|
17
|
+
currentSessionId: string;
|
|
18
|
+
state: SessionData;
|
|
19
|
+
constructor(sessionId: string);
|
|
20
|
+
private getSessionFilePath;
|
|
21
|
+
private getCheckpointsDir;
|
|
22
|
+
loadCheckpoint(): Promise<void>;
|
|
23
|
+
saveCheckpoint(): Promise<void>;
|
|
24
|
+
/**
|
|
25
|
+
* Pushes a new turn into the context window and automatically triggers token rollup if needed.
|
|
26
|
+
*/
|
|
27
|
+
appendMessage(message: ChatMessage): Promise<void>;
|
|
28
|
+
/**
|
|
29
|
+
* Token buffer protection. Roughly estimates 4 chars = 1 token.
|
|
30
|
+
* If > 12000 tokens (approx 48000 chars), we snip the old context and summarize.
|
|
31
|
+
*/
|
|
32
|
+
rollupMemory(): Promise<void>;
|
|
33
|
+
/**
|
|
34
|
+
* Used for 'Edit' and 'Write' tools to backup a file before mutating it.
|
|
35
|
+
*/
|
|
36
|
+
backupFileBeforeMutation(targetFilePath: string): Promise<void>;
|
|
37
|
+
}
|
|
38
|
+
//# sourceMappingURL=SessionManager.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SessionManager.d.ts","sourceRoot":"","sources":["../../src/session/SessionManager.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,GAAG,WAAW,GAAG,QAAQ,GAAG,MAAM,CAAC;IAC/C,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,WAAW,EAAE,CAAC;IACxB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED;;;GAGG;AACH,qBAAa,cAAc;IACzB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAwB;IACzC,gBAAgB,EAAE,MAAM,CAAC;IACzB,KAAK,EAAE,WAAW,CAAC;gBAEd,SAAS,EAAE,MAAM;IAU7B,OAAO,CAAC,kBAAkB;IAI1B,OAAO,CAAC,iBAAiB;IAInB,cAAc,IAAI,OAAO,CAAC,IAAI,CAAC;IAY/B,cAAc,IAAI,OAAO,CAAC,IAAI,CAAC;IAUrC;;OAEG;IACG,aAAa,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC;IAMxD;;;OAGG;IACG,YAAY,IAAI,OAAO,CAAC,IAAI,CAAC;IAsBnC;;OAEG;IACG,wBAAwB,CAAC,cAAc,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;CAiBtE"}
|