@sylix/coworker 1.4.2 → 1.5.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.
Files changed (47) hide show
  1. package/dist/cli/index.d.ts.map +1 -1
  2. package/dist/cli/index.js +56 -12
  3. package/dist/cli/index.js.map +1 -1
  4. package/dist/commands/slash/branch.d.ts +3 -0
  5. package/dist/commands/slash/branch.d.ts.map +1 -0
  6. package/dist/commands/slash/branch.js +45 -0
  7. package/dist/commands/slash/branch.js.map +1 -0
  8. package/dist/commands/slash/config.d.ts.map +1 -1
  9. package/dist/commands/slash/config.js +43 -0
  10. package/dist/commands/slash/config.js.map +1 -1
  11. package/dist/commands/slash/core.d.ts.map +1 -1
  12. package/dist/commands/slash/core.js +36 -6
  13. package/dist/commands/slash/core.js.map +1 -1
  14. package/dist/commands/slash/registry.d.ts.map +1 -1
  15. package/dist/commands/slash/registry.js +2 -0
  16. package/dist/commands/slash/registry.js.map +1 -1
  17. package/dist/core/CoWorkerAgent.d.ts +2 -21
  18. package/dist/core/CoWorkerAgent.d.ts.map +1 -1
  19. package/dist/core/CoWorkerAgent.js +149 -297
  20. package/dist/core/CoWorkerAgent.js.map +1 -1
  21. package/dist/core/ContextReader.d.ts +10 -0
  22. package/dist/core/ContextReader.d.ts.map +1 -0
  23. package/dist/core/ContextReader.js +122 -0
  24. package/dist/core/ContextReader.js.map +1 -0
  25. package/dist/session/SessionManager.d.ts +5 -0
  26. package/dist/session/SessionManager.d.ts.map +1 -1
  27. package/dist/session/SessionManager.js +3 -4
  28. package/dist/session/SessionManager.js.map +1 -1
  29. package/dist/utils/inputbar.d.ts.map +1 -1
  30. package/dist/utils/inputbar.js +2 -1
  31. package/dist/utils/inputbar.js.map +1 -1
  32. package/dist/utils/output.d.ts +2 -1
  33. package/dist/utils/output.d.ts.map +1 -1
  34. package/dist/utils/output.js +5 -1
  35. package/dist/utils/output.js.map +1 -1
  36. package/dist/utils/string.d.ts +6 -0
  37. package/dist/utils/string.d.ts.map +1 -0
  38. package/dist/utils/string.js +18 -0
  39. package/dist/utils/string.js.map +1 -0
  40. package/dist/utils/string.test.d.ts +2 -0
  41. package/dist/utils/string.test.d.ts.map +1 -0
  42. package/dist/utils/string.test.js +19 -0
  43. package/dist/utils/string.test.js.map +1 -0
  44. package/dist/utils/welcome.d.ts.map +1 -1
  45. package/dist/utils/welcome.js +2 -0
  46. package/dist/utils/welcome.js.map +1 -1
  47. package/package.json +4 -3
@@ -52,94 +52,17 @@ const fs = __importStar(require("fs"));
52
52
  const path = __importStar(require("path"));
53
53
  const os = __importStar(require("os"));
54
54
  const child_process_1 = require("child_process");
55
+ const ContextReader_1 = require("./ContextReader");
55
56
  const MAX_TOOL_TURNS = 25;
56
- // Resolve the agents directory relative to the project root
57
- function resolveAgentsDir() {
58
- const candidates = [
59
- path.join(process.cwd(), '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
- path.join(__dirname, '../../../agents/system-prompts-and-models-of-ai-tools/Anthropic/Claude Code'),
62
- ];
63
- for (const candidate of candidates) {
64
- if (fs.existsSync(candidate))
65
- return candidate;
66
- }
67
- return candidates[0];
68
- }
69
- const FALLBACK_SYSTEM_PROMPT = `You are CoWorker, an autonomous AI coding agent by Sylix.
70
- You help developers write, debug, and understand code.
71
- You have access to tools to search files, read the web, and write code on the user's local machine.
72
- Always be concise, direct, and helpful. When creating files, use the executeWrite tool.
73
- When searching for files, use executeGlob. When searching inside files, use executeGrep.
74
- Never refuse a reasonable coding request. Execute tools to accomplish the task.`;
75
- function getGitContext(cwd) {
76
- try {
77
- const isRepo = (0, child_process_1.execSync)('git rev-parse --is-inside-work-tree', { cwd, encoding: 'utf8', stdio: 'ignore' });
78
- const branch = (0, child_process_1.execSync)('git branch --show-current', { cwd, encoding: 'utf8' }).trim();
79
- const status = (0, child_process_1.execSync)('git status --short', { cwd, encoding: 'utf8' }).trim() || '(clean)';
80
- const commits = (0, child_process_1.execSync)('git log -n 5 --oneline', { cwd, encoding: 'utf8' }).trim();
81
- return { isRepo: true, branch, status, commits };
82
- }
83
- catch (err) {
84
- return { isRepo: false, branch: 'unknown', status: 'unknown', commits: 'No git info provided.' };
85
- }
86
- }
87
- async function getSystemPrompt(cwd) {
88
- const agentsDir = resolveAgentsDir();
89
- const promptPath = path.join(agentsDir, 'Prompt.txt');
90
- let promptText = FALLBACK_SYSTEM_PROMPT;
91
- try {
92
- promptText = fs.readFileSync(promptPath, 'utf8');
93
- // Global branding override — catch all variants
94
- promptText = promptText
95
- .replace(/Claude Code/gi, 'CoWorker')
96
- .replace(/Claude/gi, 'CoWorker')
97
- .replace(/Anthropic/gi, 'Sylix');
98
- }
99
- catch (err) {
100
- return FALLBACK_SYSTEM_PROMPT;
101
- }
102
- // Hydrate environment variables
103
- const gitContext = getGitContext(cwd);
104
- const today = new Date().toISOString().split('T')[0];
105
- promptText = promptText
106
- .replace('${Working directory}', cwd)
107
- .replace('Is directory a git repo: Yes', `Is directory a git repo: ${gitContext.isRepo ? 'Yes' : 'No'}`)
108
- .replace('Platform: darwin', `Platform: ${os.platform()}`)
109
- .replace(/OS Version: [^\n]+/, `OS Version: ${os.type()} ${os.release()}`)
110
- .replace(/Today's date: [^\n]+/, `Today's date: ${today}`)
111
- .replace(/Current branch: [^\n]+/, `Current branch: ${gitContext.branch}`)
112
- .replace(/\(clean\)/, gitContext.status)
113
- .replace('${Last 5 Recent commits}', gitContext.commits);
114
- // Project memory support (.coworker.md / COWORKER.md)
115
- let projectMemory = '';
116
- const memoryFiles = ['.coworker.md', 'COWORKER.md'];
117
- for (const file of memoryFiles) {
118
- const memPath = path.join(cwd, file);
119
- if (fs.existsSync(memPath)) {
120
- try {
121
- projectMemory = `\n\nPROJECT CONTEXT (from ${file}):\n${fs.readFileSync(memPath, 'utf8')}`;
122
- break;
123
- }
124
- catch { }
125
- }
126
- }
127
- return promptText + projectMemory;
128
- }
129
- async function getSkillsPromptFragment(hooks) {
130
- return hooks.getSkillsSummary();
131
- }
132
57
  /**
133
- * THE SDK LAYER — Real Agentic Tool Loop.
134
- * Calls the LLM, parses tool_calls, executes them locally via NativeTools,
135
- * feeds results back, and loops until the LLM produces a final text response.
58
+ * THE SDK LAYER — Real Agentic Tool Loop for CoWorker v1.5.0.
136
59
  */
137
60
  class CoWorkerAgent {
138
61
  constructor(options) {
139
- this.systemPrompt = FALLBACK_SYSTEM_PROMPT;
62
+ this.systemPrompt = '';
140
63
  this.model = options.model || 'helix-1.2';
141
64
  this.endpoint = options.endpoint || 'https://ollama-ubuntu.sylixide.com';
142
- this.ollamaModel = 'glm-4.7-flash:q4_K_M'; // Default resolution for helix-1.2
65
+ this.ollamaModel = 'glm-4.7-flash:q4_K_M';
143
66
  this.cwd = options.cwd || process.cwd();
144
67
  this.tasks = new TaskEngine_1.TaskEngine();
145
68
  this.sessions = new SessionManager_1.SessionManager((0, crypto_1.randomUUID)());
@@ -150,28 +73,24 @@ class CoWorkerAgent {
150
73
  }
151
74
  async boot() {
152
75
  await this.hooks.loadSkillsFromDirectory();
153
- this.systemPrompt = await getSystemPrompt(this.cwd);
76
+ const context = await ContextReader_1.ContextReader.getProjectContext(this.cwd);
77
+ this.systemPrompt = await getSystemPrompt(this.cwd, context);
154
78
  this.systemPrompt += await getSkillsPromptFragment(this.hooks);
155
- // Load existing session if applicable
156
79
  await this.sessions.loadCheckpoint();
157
80
  const config = await this.settings.loadSettings();
158
81
  this.permissions = new PermissionInterceptor_1.PermissionInterceptor({
159
82
  allowedTools: config.allow,
160
83
  deniedTools: config.deny
161
84
  });
162
- await this.hooks.loadSkillsFromDirectory();
163
85
  for (const [name, server] of Object.entries(config.mcpServers)) {
164
86
  await this.mcp.connectServer(name, server.command, server.args);
165
87
  }
166
88
  }
167
- /**
168
- * The real agentic loop. Streams LLM responses in real-time.
169
- * Uses a single streaming call that detects both text and tool_calls
170
- * from the same SSE stream — no double-request pattern.
171
- */
172
89
  async *chat(prompt) {
173
90
  await this.sessions.rollupMemory();
174
- let fullSystemPrompt = this.systemPrompt;
91
+ const liveContext = await ContextReader_1.ContextReader.getProjectContext(this.cwd);
92
+ const enrichedPrompt = this.enrichMessage(prompt, this.sessions.state.messages);
93
+ let fullSystemPrompt = this.systemPrompt + `\n\n## LIVE CONTEXT (Current State)\n${liveContext}`;
175
94
  if (this.hooks.activeSkill) {
176
95
  const skillPrompt = this.hooks.getSkillPrompt(this.hooks.activeSkill);
177
96
  if (skillPrompt)
@@ -179,26 +98,21 @@ class CoWorkerAgent {
179
98
  }
180
99
  const messages = [
181
100
  { role: 'system', content: fullSystemPrompt },
182
- ...this.sessions.state.messages
101
+ ...this.sessions.state.messages,
102
+ { role: 'user', content: enrichedPrompt }
183
103
  ];
184
- const userMsg = { role: 'user', content: prompt };
185
- messages.push(userMsg);
186
- await this.sessions.appendMessage(userMsg);
104
+ await this.sessions.appendMessage({ role: 'user', content: prompt });
187
105
  let turnCount = 0;
188
106
  while (turnCount < MAX_TOOL_TURNS) {
189
107
  turnCount++;
190
- // Single streaming call — yields text AND detects tool_calls
191
108
  const collected = { content: '', tool_calls: [] };
192
109
  yield* this.callLLMStreamUnified(messages, collected);
193
- // If no tool_calls, we're done — text was already streamed
194
110
  if (!collected.tool_calls || collected.tool_calls.length === 0) {
195
- // Save the streamed content to session
196
111
  if (collected.content) {
197
112
  await this.sessions.appendMessage({ role: 'assistant', content: collected.content });
198
113
  }
199
114
  break;
200
115
  }
201
- // Has tool calls — content was already streamed, now execute tools
202
116
  const assistantMsg = {
203
117
  role: 'assistant',
204
118
  content: collected.content || '',
@@ -230,15 +144,7 @@ class CoWorkerAgent {
230
144
  }
231
145
  }
232
146
  await this.hooks.firePreToolHook(toolName, args);
233
- // ── TOOL TITLE ──
234
- let toolTitle = `\n ◈ ${output_1.theme.brand(toolName)}`;
235
- if (args.path || args.dir || args.filePath) {
236
- toolTitle += output_1.theme.dim(` \u00b7 ${args.path || args.dir || args.filePath}`);
237
- }
238
- else if (args.pattern) {
239
- toolTitle += output_1.theme.dim(` \u00b7 ${args.pattern}`);
240
- }
241
- yield toolTitle + '\n';
147
+ yield `\n ◈ ${output_1.theme.brand(toolName)}` + (args.path || args.dir || args.filePath || args.pattern ? output_1.theme.dim(` \u00b7 ${args.path || args.dir || args.filePath || args.pattern}`) : '') + '\n';
242
148
  let result;
243
149
  try {
244
150
  result = await this.executeToolLocally(toolName, args);
@@ -250,117 +156,66 @@ class CoWorkerAgent {
250
156
  const toolMsg = { role: 'tool', content: result, tool_call_id: toolId };
251
157
  messages.push(toolMsg);
252
158
  await this.sessions.appendMessage(toolMsg);
253
- // Inline error detection
254
- if (this.hooks.lastDiagnostic?.hasErrors) {
255
- const diag = this.hooks.lastDiagnostic;
256
- const errorMsg = {
257
- role: 'system',
258
- content: `[DIAGNOSTICS] After your ${toolName} on ${diag.filePath}, errors detected by ${diag.tool}:\n${diag.errors}\n\nYou MUST fix these errors before proceeding.`
259
- };
260
- messages.push(errorMsg);
261
- await this.sessions.appendMessage(errorMsg);
262
- yield ` ✗ ${output_1.theme.error(`[${diag.tool}]`)} ${output_1.theme.dim('errors detected \u2014 agent will self-correct')}\n`;
263
- }
264
- // ── TOOL SUMMARIZATION ──
265
159
  const resultLines = result.split('\n').filter(l => l.trim());
266
- if (toolName === 'executeLS' || toolName === 'executeListDir') {
267
- const count = resultLines.length;
268
- yield ` ${output_1.theme.dim('\u2514')} ${output_1.theme.dim(`${count} items found`)}\n`;
269
- }
270
- else if (toolName === 'executeGlob') {
271
- const count = resultLines.length;
272
- yield ` ${output_1.theme.dim('\u2514')} ${output_1.theme.dim(`${count} files matched`)}\n`;
273
- }
274
- else if (result.includes('[ToolError]') || result.includes('\u2717')) {
275
- yield ` ${output_1.theme.dim('\u2514')} ${output_1.theme.error(result.split('\n')[0].substring(0, 80))}\n`;
276
- }
277
- else if (resultLines.length <= 2) {
278
- for (const line of resultLines) {
160
+ if (resultLines.length <= 2) {
161
+ for (const line of resultLines)
279
162
  yield ` ${output_1.theme.dim('\u2514')} ${output_1.theme.dim(line.substring(0, 80))}\n`;
280
- }
281
163
  }
282
164
  else {
283
- // Default: show first 2 lines plus count
284
- for (const line of resultLines.slice(0, 2)) {
165
+ for (const line of resultLines.slice(0, 2))
285
166
  yield ` ${output_1.theme.dim('\u2514')} ${output_1.theme.dim(line.substring(0, 80))}\n`;
286
- }
287
167
  yield ` ${output_1.theme.dim(`...and ${resultLines.length - 2} more lines`)}\n`;
288
168
  }
289
169
  }
290
170
  }
291
- if (turnCount >= MAX_TOOL_TURNS) {
292
- yield `\n \u2717 Reached maximum tool turns (${MAX_TOOL_TURNS}). Stopping.\n`;
293
- }
294
171
  }
295
- /**
296
- * UNIFIED STREAMING — yields text chunks as they arrive AND collects tool_calls.
297
- * The `collected` object is populated with accumulated content and tool_calls
298
- * so the caller can inspect them after the stream completes.
299
- */
300
172
  async *callLLMStreamUnified(messages, collected) {
301
173
  const url = `${this.endpoint}/v1/chat/completions`;
302
- const body = {
303
- model: this.ollamaModel,
304
- messages,
305
- tools: Schemas_1.CoWorkerToolSchemas,
306
- tool_choice: 'auto',
307
- stream: true,
308
- options: { num_ctx: 32768, num_predict: 4096, temperature: 0.7 }
309
- };
310
174
  const res = await (0, node_fetch_1.default)(url, {
311
175
  method: 'POST',
312
176
  headers: { 'Content-Type': 'application/json' },
313
- body: JSON.stringify(body)
177
+ body: JSON.stringify({
178
+ model: this.ollamaModel,
179
+ messages,
180
+ tools: Schemas_1.CoWorkerToolSchemas,
181
+ tool_choice: 'auto',
182
+ stream: true,
183
+ options: { num_ctx: 32768, num_predict: 4096, temperature: 0.7 }
184
+ })
314
185
  });
315
- if (!res.ok) {
316
- const errText = await res.text();
317
- throw new Error(`LLM call failed (${res.status}): ${errText}`);
318
- }
186
+ if (!res.ok)
187
+ throw new Error(`LLM call failed (${res.status}): ${await res.text()}`);
319
188
  const nodeStream = res.body;
320
189
  if (!nodeStream)
321
190
  throw new Error('No response body');
322
191
  let buffer = '';
323
- // Track tool call assembly from streaming deltas
324
192
  const toolCallMap = new Map();
325
- // Read the SSE stream chunk by chunk
326
193
  for await (const rawChunk of nodeStream) {
327
194
  buffer += rawChunk.toString();
328
- // Process complete SSE lines
329
195
  const lines = buffer.split('\n');
330
- buffer = lines.pop() || ''; // Keep incomplete last line in buffer
196
+ buffer = lines.pop() || '';
331
197
  for (const line of lines) {
332
- const trimmed = line.trim();
333
- if (!trimmed || !trimmed.startsWith('data: '))
198
+ if (!line.trim().startsWith('data: '))
334
199
  continue;
335
- const data = trimmed.slice(6).trim();
200
+ const data = line.trim().slice(6).trim();
336
201
  if (data === '[DONE]') {
337
- // Finalize collected tool_calls
338
- if (toolCallMap.size > 0) {
202
+ if (toolCallMap.size > 0)
339
203
  collected.tool_calls = Array.from(toolCallMap.values());
340
- }
341
204
  return;
342
205
  }
343
206
  try {
344
207
  const parsed = JSON.parse(data);
345
- // Handle streaming text content
346
- const content = parsed.choices?.[0]?.delta?.content ||
347
- parsed.message?.content ||
348
- parsed.response ||
349
- '';
208
+ const content = parsed.choices?.[0]?.delta?.content || '';
350
209
  if (content) {
351
210
  collected.content += content;
352
- yield content; // Yield IMMEDIATELY — no buffering
211
+ yield content;
353
212
  }
354
- // Handle streaming tool_calls (deltas)
355
- const deltaToolCalls = parsed.choices?.[0]?.delta?.tool_calls;
356
- if (deltaToolCalls && Array.isArray(deltaToolCalls)) {
357
- for (const tc of deltaToolCalls) {
213
+ const deltas = parsed.choices?.[0]?.delta?.tool_calls;
214
+ if (deltas) {
215
+ for (const tc of deltas) {
358
216
  const idx = tc.index ?? 0;
359
217
  if (!toolCallMap.has(idx)) {
360
- toolCallMap.set(idx, {
361
- id: tc.id || `call_${(0, crypto_1.randomUUID)().substring(0, 8)}`,
362
- function: { name: '', arguments: '' }
363
- });
218
+ toolCallMap.set(idx, { id: tc.id || `call_${(0, crypto_1.randomUUID)().substring(0, 8)}`, function: { name: '', arguments: '' } });
364
219
  }
365
220
  const existing = toolCallMap.get(idx);
366
221
  if (tc.id)
@@ -371,141 +226,138 @@ class CoWorkerAgent {
371
226
  existing.function.arguments += tc.function.arguments;
372
227
  }
373
228
  }
374
- // Handle non-streaming tool_calls (full response in single message)
375
- const msgToolCalls = parsed.choices?.[0]?.message?.tool_calls || parsed.message?.tool_calls;
376
- if (msgToolCalls && Array.isArray(msgToolCalls)) {
377
- collected.tool_calls = msgToolCalls;
378
- }
379
- // Handle non-streaming full content
380
- const msgContent = parsed.choices?.[0]?.message?.content;
381
- if (msgContent && !content) {
382
- collected.content += msgContent;
383
- yield msgContent;
384
- }
385
- }
386
- catch {
387
- // Partial JSON or non-JSON line — skip
388
229
  }
230
+ catch { }
389
231
  }
390
232
  }
391
- // Finalize any tool calls assembled from deltas
392
233
  if (toolCallMap.size > 0 && collected.tool_calls.length === 0) {
393
234
  collected.tool_calls = Array.from(toolCallMap.values());
394
235
  }
395
236
  }
396
- /**
397
- * Local tool dispatcher. Maps tool names to NativeTools methods.
398
- * This is what makes CoWorker actually create files on the user's machine.
399
- * ALL 35 tools are wired here.
400
- */
401
237
  async executeToolLocally(toolName, args) {
402
238
  switch (toolName) {
403
- // ── Filesystem ──
404
- case 'executeRead':
405
- return NativeTools_1.NativeTools.executeRead(args.filePath);
406
- case 'executeWrite':
407
- return NativeTools_1.NativeTools.executeWrite(args.filePath, args.content);
408
- case 'executeEdit':
409
- return NativeTools_1.NativeTools.executeEdit(args.filePath, args.oldString, args.newString, args.replaceAll);
410
- case 'executeMultiEdit':
411
- return NativeTools_1.NativeTools.executeMultiEdit(args.filePath, args.edits);
412
- case 'executeLS':
413
- return NativeTools_1.NativeTools.executeLS(args.path, args.recursive);
414
- case 'executeListDir':
415
- return NativeTools_1.NativeTools.executeListDir(args.dirPath);
416
- case 'executeGlob':
417
- return (await NativeTools_1.NativeTools.executeGlob(args.pattern, args.dir)).join('\n');
418
- case 'executeGrep':
419
- return NativeTools_1.NativeTools.executeGrep(args.regexQuery, args.filesToSearch);
420
- // ── Diagnostics (inline error detection) ──
421
- case 'diagnostics':
422
- return this.hooks.runManualDiagnostics(args.filePath);
423
- // ── Code Review ──
424
- case 'codeReview': {
425
- const { CodeReviewEngine } = await Promise.resolve().then(() => __importStar(require('../review/CodeReviewEngine')));
426
- const engine = new CodeReviewEngine();
427
- const result = await engine.review(args.baseBranch);
428
- return CodeReviewEngine.formatForTerminal(result);
429
- }
430
- // ── Shell & Process ──
431
- case 'executeBash':
432
- return NativeTools_1.NativeTools.executeBash(args.command, args.cwd);
433
- case 'bashOutput':
434
- return NativeTools_1.NativeTools.executeBashOutput(args.pid);
435
- case 'killShell':
436
- return NativeTools_1.NativeTools.executeKillShell(args.pid);
437
- // ── Git ──
438
- case 'gitStatus':
439
- return NativeTools_1.NativeTools.executeGitStatus(args.cwd);
440
- case 'gitDiff':
441
- return NativeTools_1.NativeTools.executeGitDiff(args.filePath, args.staged, args.cwd);
442
- case 'gitCommit':
443
- return NativeTools_1.NativeTools.executeGitCommit(args.message, args.files, args.cwd);
444
- // ── Memory (COWORKER.md) ──
445
- case 'memoryRead':
446
- return NativeTools_1.NativeTools.executeMemoryRead();
447
- case 'memoryWrite':
448
- return NativeTools_1.NativeTools.executeMemoryWrite(args.content, args.mode);
449
- // ── Web ──
450
- case 'executeWebSearch':
451
- return NativeTools_1.NativeTools.executeWebSearch(args.query);
452
- case 'executeWebFetch':
453
- return NativeTools_1.NativeTools.executeWebFetch(args.url);
454
- case 'executeOpenBrowser':
455
- return NativeTools_1.NativeTools.executeOpenBrowser(args.url);
456
- // ── Task Management ──
457
- case 'todoRead':
458
- return NativeTools_1.NativeTools.executeTodoRead();
459
- case 'todoWrite':
460
- return NativeTools_1.NativeTools.executeTodoWrite(args.todos);
461
- case 'taskCreate': {
462
- const id = await this.tasks.createTask(args.description, args.dependencies || []);
463
- return `Task created with ID: ${id}`;
464
- }
465
- case 'taskUpdate': {
239
+ case 'executeRead': return NativeTools_1.NativeTools.executeRead(args.filePath);
240
+ case 'executeWrite': return NativeTools_1.NativeTools.executeWrite(args.filePath, args.content);
241
+ case 'executeEdit': return NativeTools_1.NativeTools.executeEdit(args.filePath, args.oldString, args.newString, args.replaceAll);
242
+ case 'executeMultiEdit': return NativeTools_1.NativeTools.executeMultiEdit(args.filePath, args.edits);
243
+ case 'executeLS': return NativeTools_1.NativeTools.executeLS(args.path, args.recursive);
244
+ case 'executeListDir': return NativeTools_1.NativeTools.executeListDir(args.dirPath);
245
+ case 'executeGlob': return (await NativeTools_1.NativeTools.executeGlob(args.pattern, args.dir)).join('\n');
246
+ case 'executeGrep': return NativeTools_1.NativeTools.executeGrep(args.regexQuery, args.filesToSearch);
247
+ case 'diagnostics': return this.hooks.runManualDiagnostics(args.filePath);
248
+ case 'executeBash': return NativeTools_1.NativeTools.executeBash(args.command, args.cwd);
249
+ case 'bashOutput': return NativeTools_1.NativeTools.executeBashOutput(args.pid);
250
+ case 'killShell': return NativeTools_1.NativeTools.executeKillShell(args.pid);
251
+ case 'gitStatus': return NativeTools_1.NativeTools.executeGitStatus(args.cwd);
252
+ case 'gitDiff': return NativeTools_1.NativeTools.executeGitDiff(args.filePath, args.staged, args.cwd);
253
+ case 'gitCommit': return NativeTools_1.NativeTools.executeGitCommit(args.message, args.files, args.cwd);
254
+ case 'memoryRead': return NativeTools_1.NativeTools.executeMemoryRead();
255
+ case 'memoryWrite': return NativeTools_1.NativeTools.executeMemoryWrite(args.content, args.mode);
256
+ case 'executeWebSearch': return NativeTools_1.NativeTools.executeWebSearch(args.query);
257
+ case 'executeWebFetch': return NativeTools_1.NativeTools.executeWebFetch(args.url);
258
+ case 'executeOpenBrowser': return NativeTools_1.NativeTools.executeOpenBrowser(args.url);
259
+ case 'todoRead': return NativeTools_1.NativeTools.executeTodoRead();
260
+ case 'todoWrite': return NativeTools_1.NativeTools.executeTodoWrite(args.todos);
261
+ case 'taskCreate': return `Task created with ID: ${await this.tasks.createTask(args.description, args.dependencies || [])}`;
262
+ case 'taskUpdate':
466
263
  await this.tasks.updateTaskState(args.taskId, args.state, args.notes);
467
264
  return `Task ${args.taskId} updated to ${args.state}`;
468
- }
469
- // ── Interaction ──
470
- case 'executeAskUserQuestion':
471
- return NativeTools_1.NativeTools.executeAskUserQuestion(args.question);
472
- // ── Jupyter Notebooks ──
473
- case 'executeNotebookRead':
474
- return NativeTools_1.NativeTools.executeNotebookRead(args.notebookPath);
475
- case 'executeNotebookEdit':
476
- return NativeTools_1.NativeTools.executeNotebookEdit(args.notebookPath, args.newSource, args.cellId, args.cellType);
477
- // ── Agents ──
478
- case 'agent':
479
- return NativeTools_1.NativeTools.executeAgent(args.description, args.subagentType);
480
- case 'returnSubagentResult':
481
- return NativeTools_1.NativeTools.executeReturnSubagentResult(args.result);
482
- // ── Plan Mode (handled by permission interceptor state) ──
483
- case 'enterPlanMode':
484
- return 'Plan mode activated. Mutation tools (bash, write, edit) are now blocked until you call exitPlanMode.';
485
- case 'exitPlanMode':
486
- return 'Plan mode deactivated. Mutation tools are re-enabled.';
487
- // ── Cron (stub — uses executeBash internally) ──
488
- case 'cronCreate':
489
- return `Cron scheduled: "${args.description}" every ${args.intervalMinutes} minutes. (Note: cron runs in-process only while CoWorker is active.)`;
490
- case 'cronList':
491
- return 'No active crons. (Cron persistence is not yet implemented.)';
492
- case 'cronDelete':
493
- return `Cron ${args.cronId} deleted.`;
494
- default:
495
- return `[Unknown Tool] "${toolName}" is not registered in CoWorker's local executor.`;
265
+ case 'executeAskUserQuestion': return NativeTools_1.NativeTools.executeAskUserQuestion(args.question);
266
+ case 'executeNotebookRead': return NativeTools_1.NativeTools.executeNotebookRead(args.notebookPath);
267
+ case 'executeNotebookEdit': return NativeTools_1.NativeTools.executeNotebookEdit(args.notebookPath, args.newSource, args.cellId, args.cellType);
268
+ case 'agent': return NativeTools_1.NativeTools.executeAgent(args.description, args.subagentType);
269
+ case 'returnSubagentResult': return NativeTools_1.NativeTools.executeReturnSubagentResult(args.result);
270
+ case 'enterPlanMode': return 'Plan mode activated. Mutation tools are blocked.';
271
+ case 'exitPlanMode': return 'Plan mode deactivated.';
272
+ default: return `[Unknown Tool] "${toolName}" is not registered.`;
496
273
  }
497
274
  }
498
- /**
499
- * Subagent: creates a restricted child agent for delegated subtasks.
500
- */
501
275
  async createSubagent(profileName, subtask) {
502
276
  const subAgent = new CoWorkerAgent({ model: this.model, role: 'CodeReviewer' });
503
277
  let output = '';
504
- for await (const chunk of subAgent.chat(subtask)) {
278
+ for await (const chunk of subAgent.chat(subtask))
505
279
  output += chunk;
506
- }
507
280
  return `[SUBAGENT OUTPUT]: ${output}`;
508
281
  }
282
+ enrichMessage(prompt, history) {
283
+ const lastAi = history.filter(m => m.role === 'assistant').pop();
284
+ const trimmed = prompt.trim();
285
+ if (/^\d+$/.test(trimmed) && lastAi) {
286
+ return `${prompt} (Refers to step ${trimmed} from: "${lastAi.content.substring(0, 80).replace(/\\n/g, ' ')}...")`;
287
+ }
288
+ if (/^run.*test/i.test(trimmed))
289
+ return `${prompt} (Identify framework and run tests automatically)`;
290
+ if (/^fix (it|this|the error|that)/i.test(trimmed))
291
+ return `${prompt} (Refer to the previous context or error logs)`;
292
+ return prompt;
293
+ }
509
294
  }
510
295
  exports.CoWorkerAgent = CoWorkerAgent;
296
+ function resolveAgentsDir() {
297
+ const candidates = [
298
+ path.join(process.cwd(), 'agents/system-prompts-and-models-of-ai-tools/Anthropic/Claude Code'),
299
+ path.join(__dirname, '../../agents/system-prompts-and-models-of-ai-tools/Anthropic/Claude Code'),
300
+ path.join(__dirname, '../../../agents/system-prompts-and-models-of-ai-tools/Anthropic/Claude Code'),
301
+ ];
302
+ for (const candidate of candidates)
303
+ if (fs.existsSync(candidate))
304
+ return candidate;
305
+ return candidates[0];
306
+ }
307
+ function getGitContext(cwd) {
308
+ try {
309
+ const branch = (0, child_process_1.execSync)('git branch --show-current', { cwd, encoding: 'utf8' }).trim();
310
+ const status = (0, child_process_1.execSync)('git status --short', { cwd, encoding: 'utf8' }).trim() || '(clean)';
311
+ const commits = (0, child_process_1.execSync)('git log -n 5 --oneline', { cwd, encoding: 'utf8' }).trim();
312
+ return { isRepo: true, branch, status, commits };
313
+ }
314
+ catch {
315
+ return { isRepo: false, branch: 'unknown', status: 'unknown', commits: 'No git info provided.' };
316
+ }
317
+ }
318
+ async function getSystemPrompt(cwd, autoContext) {
319
+ const agentsDir = resolveAgentsDir();
320
+ const promptPath = path.join(agentsDir, 'Prompt.txt');
321
+ let promptText = FALLBACK_SYSTEM_PROMPT;
322
+ try {
323
+ promptText = fs.readFileSync(promptPath, 'utf8')
324
+ .replace(/Claude Code/gi, 'CoWorker').replace(/Claude/gi, 'CoWorker').replace(/Anthropic/gi, 'Sylix');
325
+ }
326
+ catch { }
327
+ const gitContext = getGitContext(cwd);
328
+ promptText = promptText
329
+ .replace('${Working directory}', cwd)
330
+ .replace(/Is directory a git repo: [^\n]+/, `Is directory a git repo: ${gitContext.isRepo ? 'Yes' : 'No'}`)
331
+ .replace('Platform: darwin', `Platform: ${os.platform()}`)
332
+ .replace(/OS Version: [^\n]+/, `OS Version: ${os.type()} ${os.release()}`)
333
+ .replace(/Today's date: [^\n]+/, `Today's date: ${new Date().toISOString().split('T')[0]}`)
334
+ .replace(/Current branch: [^\n]+/, `Current branch: ${gitContext.branch}`)
335
+ .replace('${Last 5 Recent commits}', gitContext.commits);
336
+ if (autoContext)
337
+ promptText += `\n\n## Automated Project Context\n${autoContext}`;
338
+ const memoryFiles = ['.coworker.md', 'COWORKER.md'];
339
+ for (const file of memoryFiles) {
340
+ const memPath = path.join(cwd, file);
341
+ if (fs.existsSync(memPath)) {
342
+ try {
343
+ promptText += `\n\nPROJECT MEMORY (${file}):\n${fs.readFileSync(memPath, 'utf8')}`;
344
+ break;
345
+ }
346
+ catch { }
347
+ }
348
+ }
349
+ promptText += `
350
+ \n## CRITICAL COLLABORATION RULES
351
+ 1. NEVER ask for information you can fetch yourself (CWD, files, project type).
352
+ 2. If the user refers to a number, it's a step from your previous list.
353
+ 3. If the user says "run the test", check package.json and execute bash automatically.
354
+ 4. Don't ask 'which project?' — look at the file tree in the context.
355
+ 5. Always look at the conversation history to maintain context.
356
+ `;
357
+ return promptText;
358
+ }
359
+ async function getSkillsPromptFragment(hooks) {
360
+ return hooks.getSkillsSummary();
361
+ }
362
+ const FALLBACK_SYSTEM_PROMPT = `You are CoWorker, an autonomous AI coding agent by Sylix.`;
511
363
  //# sourceMappingURL=CoWorkerAgent.js.map