@sylix/coworker 1.2.6 → 1.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli/index.js +181 -106
- package/dist/cli/index.js.map +1 -1
- package/dist/commands/slash/advanced.d.ts +3 -0
- package/dist/commands/slash/advanced.d.ts.map +1 -0
- package/dist/commands/slash/advanced.js +225 -0
- package/dist/commands/slash/advanced.js.map +1 -0
- package/dist/commands/slash/config.d.ts +3 -0
- package/dist/commands/slash/config.d.ts.map +1 -0
- package/dist/commands/slash/config.js +161 -0
- package/dist/commands/slash/config.js.map +1 -0
- package/dist/commands/slash/context.d.ts +3 -0
- package/dist/commands/slash/context.d.ts.map +1 -0
- package/dist/commands/slash/context.js +127 -0
- package/dist/commands/slash/context.js.map +1 -0
- package/dist/commands/slash/core.d.ts +3 -0
- package/dist/commands/slash/core.d.ts.map +1 -0
- package/dist/commands/slash/core.js +112 -0
- package/dist/commands/slash/core.js.map +1 -0
- package/dist/commands/slash/developer.d.ts +3 -0
- package/dist/commands/slash/developer.d.ts.map +1 -0
- package/dist/commands/slash/developer.js +174 -0
- package/dist/commands/slash/developer.js.map +1 -0
- package/dist/commands/slash/files.d.ts +3 -0
- package/dist/commands/slash/files.d.ts.map +1 -0
- package/dist/commands/slash/files.js +216 -0
- package/dist/commands/slash/files.js.map +1 -0
- package/dist/commands/slash/registry.d.ts +36 -0
- package/dist/commands/slash/registry.d.ts.map +1 -0
- package/dist/commands/slash/registry.js +69 -0
- package/dist/commands/slash/registry.js.map +1 -0
- package/dist/commands/slash/session.d.ts +3 -0
- package/dist/commands/slash/session.d.ts.map +1 -0
- package/dist/commands/slash/session.js +144 -0
- package/dist/commands/slash/session.js.map +1 -0
- package/dist/core/CoWorkerAgent.d.ts +8 -2
- package/dist/core/CoWorkerAgent.d.ts.map +1 -1
- package/dist/core/CoWorkerAgent.js +179 -36
- package/dist/core/CoWorkerAgent.js.map +1 -1
- package/dist/review/CodeReviewEngine.d.ts +78 -0
- package/dist/review/CodeReviewEngine.d.ts.map +1 -0
- package/dist/review/CodeReviewEngine.js +449 -0
- package/dist/review/CodeReviewEngine.js.map +1 -0
- package/dist/session/SessionManager.js +10 -5
- package/dist/session/SessionManager.js.map +1 -1
- package/dist/skills/HookAndSkillManager.d.ts +29 -5
- package/dist/skills/HookAndSkillManager.d.ts.map +1 -1
- package/dist/skills/HookAndSkillManager.js +167 -12
- package/dist/skills/HookAndSkillManager.js.map +1 -1
- package/dist/todos/TodoManager.d.ts +19 -0
- package/dist/todos/TodoManager.d.ts.map +1 -0
- package/dist/todos/TodoManager.js +102 -0
- package/dist/todos/TodoManager.js.map +1 -0
- package/dist/tools/NativeTools.d.ts +98 -0
- package/dist/tools/NativeTools.d.ts.map +1 -1
- package/dist/tools/NativeTools.js +571 -0
- package/dist/tools/NativeTools.js.map +1 -1
- package/dist/tools/Schemas.d.ts +1199 -102
- package/dist/tools/Schemas.d.ts.map +1 -1
- package/dist/tools/Schemas.js +358 -40
- package/dist/tools/Schemas.js.map +1 -1
- package/dist/utils/conversations.d.ts +14 -0
- package/dist/utils/conversations.d.ts.map +1 -0
- package/dist/utils/conversations.js +100 -0
- package/dist/utils/conversations.js.map +1 -0
- package/dist/utils/inputbar.d.ts +87 -0
- package/dist/utils/inputbar.d.ts.map +1 -0
- package/dist/utils/inputbar.js +263 -0
- package/dist/utils/inputbar.js.map +1 -0
- package/dist/utils/output.d.ts +73 -48
- package/dist/utils/output.d.ts.map +1 -1
- package/dist/utils/output.js +349 -158
- package/dist/utils/output.js.map +1 -1
- package/dist/utils/palette.d.ts +25 -0
- package/dist/utils/palette.d.ts.map +1 -0
- package/dist/utils/palette.js +92 -0
- package/dist/utils/palette.js.map +1 -0
- package/dist/utils/welcome.d.ts +2 -0
- package/dist/utils/welcome.d.ts.map +1 -0
- package/dist/utils/welcome.js +130 -0
- package/dist/utils/welcome.js.map +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.COMMANDS = void 0;
|
|
4
|
+
exports.setCommandContext = setCommandContext;
|
|
5
|
+
exports.getCommandContext = getCommandContext;
|
|
6
|
+
exports.resolveCommand = resolveCommand;
|
|
7
|
+
exports.filterCommands = filterCommands;
|
|
8
|
+
exports.getGroups = getGroups;
|
|
9
|
+
exports.getGroupCommands = getGroupCommands;
|
|
10
|
+
// Global context set at CLI boot
|
|
11
|
+
let _ctx = null;
|
|
12
|
+
function setCommandContext(ctx) { _ctx = ctx; }
|
|
13
|
+
function getCommandContext() { return _ctx; }
|
|
14
|
+
// ============================================================================
|
|
15
|
+
// COMMAND REGISTRY — import all groups and merge
|
|
16
|
+
// ============================================================================
|
|
17
|
+
const core_1 = require("./core");
|
|
18
|
+
const files_1 = require("./files");
|
|
19
|
+
const context_1 = require("./context");
|
|
20
|
+
const session_1 = require("./session");
|
|
21
|
+
const config_1 = require("./config");
|
|
22
|
+
const developer_1 = require("./developer");
|
|
23
|
+
const advanced_1 = require("./advanced");
|
|
24
|
+
exports.COMMANDS = [
|
|
25
|
+
...core_1.coreCommands,
|
|
26
|
+
...files_1.fileCommands,
|
|
27
|
+
...context_1.contextCommands,
|
|
28
|
+
...session_1.sessionCommands,
|
|
29
|
+
...config_1.configCommands,
|
|
30
|
+
...developer_1.developerCommands,
|
|
31
|
+
...advanced_1.advancedCommands,
|
|
32
|
+
];
|
|
33
|
+
/**
|
|
34
|
+
* Resolve a slash command by name or alias.
|
|
35
|
+
*/
|
|
36
|
+
function resolveCommand(input) {
|
|
37
|
+
const name = input.startsWith('/') ? input.slice(1).split(' ')[0] : input.split(' ')[0];
|
|
38
|
+
return exports.COMMANDS.find(c => c.name === name || c.aliases?.includes(name));
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Filter commands by partial name (for autocomplete).
|
|
42
|
+
*/
|
|
43
|
+
function filterCommands(partial) {
|
|
44
|
+
const q = partial.toLowerCase().replace(/^\//, '');
|
|
45
|
+
if (!q)
|
|
46
|
+
return exports.COMMANDS;
|
|
47
|
+
return exports.COMMANDS.filter(c => c.name.includes(q) || c.description.toLowerCase().includes(q));
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Get unique group names in order.
|
|
51
|
+
*/
|
|
52
|
+
function getGroups() {
|
|
53
|
+
const seen = new Set();
|
|
54
|
+
const groups = [];
|
|
55
|
+
for (const c of exports.COMMANDS) {
|
|
56
|
+
if (!seen.has(c.group)) {
|
|
57
|
+
seen.add(c.group);
|
|
58
|
+
groups.push(c.group);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
return groups;
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Get commands in a specific group.
|
|
65
|
+
*/
|
|
66
|
+
function getGroupCommands(group) {
|
|
67
|
+
return exports.COMMANDS.filter(c => c.group === group);
|
|
68
|
+
}
|
|
69
|
+
//# sourceMappingURL=registry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"registry.js","sourceRoot":"","sources":["../../../src/commands/slash/registry.ts"],"names":[],"mappings":";;;AAqBA,8CAA4E;AAC5E,8CAA2E;AA2B3E,wCAGC;AAKD,wCAMC;AAKD,8BAUC;AAKD,4CAEC;AAlED,iCAAiC;AACjC,IAAI,IAAI,GAA0B,IAAI,CAAC;AACvC,SAAgB,iBAAiB,CAAC,GAAmB,IAAU,IAAI,GAAG,GAAG,CAAC,CAAC,CAAC;AAC5E,SAAgB,iBAAiB,KAA4B,OAAO,IAAI,CAAC,CAAC,CAAC;AAE3E,+EAA+E;AAC/E,iDAAiD;AACjD,+EAA+E;AAE/E,iCAAsC;AACtC,mCAAuC;AACvC,uCAA4C;AAC5C,uCAA4C;AAC5C,qCAA0C;AAC1C,2CAAgD;AAChD,yCAA8C;AAEjC,QAAA,QAAQ,GAAmB;IACtC,GAAG,mBAAY;IACf,GAAG,oBAAY;IACf,GAAG,yBAAe;IAClB,GAAG,yBAAe;IAClB,GAAG,uBAAc;IACjB,GAAG,6BAAiB;IACpB,GAAG,2BAAgB;CACpB,CAAC;AAEF;;GAEG;AACH,SAAgB,cAAc,CAAC,KAAa;IAC1C,MAAM,IAAI,GAAG,KAAK,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;IACxF,OAAO,gBAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,IAAI,IAAI,CAAC,CAAC,OAAO,EAAE,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC;AAC1E,CAAC;AAED;;GAEG;AACH,SAAgB,cAAc,CAAC,OAAe;IAC5C,MAAM,CAAC,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;IACnD,IAAI,CAAC,CAAC;QAAE,OAAO,gBAAQ,CAAC;IACxB,OAAO,gBAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CACzB,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,WAAW,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC,CAC9D,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,SAAgB,SAAS;IACvB,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;IAC/B,MAAM,MAAM,GAAa,EAAE,CAAC;IAC5B,KAAK,MAAM,CAAC,IAAI,gBAAQ,EAAE,CAAC;QACzB,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC;YACvB,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;YAClB,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;QACvB,CAAC;IACH,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED;;GAEG;AACH,SAAgB,gBAAgB,CAAC,KAAa;IAC5C,OAAO,gBAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,KAAK,KAAK,CAAC,CAAC;AACjD,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session.d.ts","sourceRoot":"","sources":["../../../src/commands/slash/session.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAK1C,eAAO,MAAM,eAAe,EAAE,YAAY,EAmGzC,CAAC"}
|
|
@@ -0,0 +1,144 @@
|
|
|
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.sessionCommands = void 0;
|
|
37
|
+
const output_1 = require("../../utils/output");
|
|
38
|
+
const conversations_1 = require("../../utils/conversations");
|
|
39
|
+
const readline = __importStar(require("readline"));
|
|
40
|
+
exports.sessionCommands = [
|
|
41
|
+
{
|
|
42
|
+
name: 'resume',
|
|
43
|
+
description: 'Resume a previous conversation',
|
|
44
|
+
group: 'session',
|
|
45
|
+
handler: async (agent) => {
|
|
46
|
+
const convos = (0, conversations_1.loadConversations)();
|
|
47
|
+
if (convos.length === 0) {
|
|
48
|
+
console.log(output_1.theme.dim(' No previous conversations.'));
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
console.log('');
|
|
52
|
+
console.log(output_1.theme.dim(' Recent conversations:'));
|
|
53
|
+
console.log('');
|
|
54
|
+
const recent = convos.slice(-5).reverse();
|
|
55
|
+
for (let i = 0; i < recent.length; i++) {
|
|
56
|
+
const c = recent[i];
|
|
57
|
+
const ago = getTimeAgo(c.lastActive);
|
|
58
|
+
const selected = i === 0 ? output_1.theme.brand('›') : ' ';
|
|
59
|
+
console.log(` ${selected} ${output_1.theme.white(`${i + 1}. ${c.name}`)} ${output_1.theme.dim(`· ${ago} · ${c.messageCount} msgs`)}`);
|
|
60
|
+
}
|
|
61
|
+
console.log('');
|
|
62
|
+
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
63
|
+
const answer = await new Promise(r => {
|
|
64
|
+
rl.question(` ${output_1.theme.dim('select (1-5)?')} ${output_1.theme.brand('›')} `, a => { r(a.trim()); rl.close(); });
|
|
65
|
+
});
|
|
66
|
+
const idx = parseInt(answer, 10) - 1;
|
|
67
|
+
if (idx >= 0 && idx < recent.length) {
|
|
68
|
+
agent.sessions.currentSessionId = recent[idx].id;
|
|
69
|
+
await agent.sessions.loadCheckpoint();
|
|
70
|
+
(0, output_1.printSuccess)(`resumed: ${recent[idx].name}`);
|
|
71
|
+
}
|
|
72
|
+
},
|
|
73
|
+
},
|
|
74
|
+
{
|
|
75
|
+
name: 'rename',
|
|
76
|
+
description: 'Rename current conversation',
|
|
77
|
+
group: 'session',
|
|
78
|
+
handler: async (agent) => {
|
|
79
|
+
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
80
|
+
const name = await new Promise(r => {
|
|
81
|
+
rl.question(` ${output_1.theme.dim('new name?')} ${output_1.theme.brand('›')} `, a => { r(a.trim()); rl.close(); });
|
|
82
|
+
});
|
|
83
|
+
if (name) {
|
|
84
|
+
(0, conversations_1.updateConversation)(agent.sessions.currentSessionId, { name });
|
|
85
|
+
(0, output_1.printSuccess)(`renamed to: ${name}`);
|
|
86
|
+
}
|
|
87
|
+
},
|
|
88
|
+
},
|
|
89
|
+
{
|
|
90
|
+
name: 'rewind',
|
|
91
|
+
description: 'Rewind to a previous point',
|
|
92
|
+
group: 'session',
|
|
93
|
+
handler: async (agent) => {
|
|
94
|
+
const msgs = agent.sessions.state.messages;
|
|
95
|
+
const userMsgs = msgs.filter((m) => m.role === 'user');
|
|
96
|
+
if (userMsgs.length < 2) {
|
|
97
|
+
console.log(output_1.theme.dim(' Not enough turns to rewind.'));
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
100
|
+
console.log('');
|
|
101
|
+
console.log(output_1.theme.dim(' Conversation turns:'));
|
|
102
|
+
console.log('');
|
|
103
|
+
for (let i = 0; i < userMsgs.length; i++) {
|
|
104
|
+
const preview = userMsgs[i].content.substring(0, 50);
|
|
105
|
+
console.log(` ${output_1.theme.dim(`${i + 1}.`)} ${output_1.theme.white(`"${preview}${preview.length >= 50 ? '...' : ''}"`)}`);
|
|
106
|
+
}
|
|
107
|
+
console.log('');
|
|
108
|
+
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
109
|
+
const answer = await new Promise(r => {
|
|
110
|
+
rl.question(` ${output_1.theme.dim('rewind to turn?')} ${output_1.theme.brand('›')} `, a => { r(a.trim()); rl.close(); });
|
|
111
|
+
});
|
|
112
|
+
const turn = parseInt(answer, 10);
|
|
113
|
+
if (turn > 0 && turn <= userMsgs.length) {
|
|
114
|
+
// Find the index of the nth user message and truncate after it
|
|
115
|
+
let count = 0;
|
|
116
|
+
let cutIdx = 0;
|
|
117
|
+
for (let i = 0; i < msgs.length; i++) {
|
|
118
|
+
if (msgs[i].role === 'user') {
|
|
119
|
+
count++;
|
|
120
|
+
if (count === turn) {
|
|
121
|
+
cutIdx = i + 1;
|
|
122
|
+
break;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
agent.sessions.state.messages = msgs.slice(0, cutIdx);
|
|
127
|
+
await agent.sessions.saveCheckpoint();
|
|
128
|
+
(0, output_1.printSuccess)(`rewound to turn ${turn}`);
|
|
129
|
+
}
|
|
130
|
+
},
|
|
131
|
+
},
|
|
132
|
+
];
|
|
133
|
+
function getTimeAgo(dateStr) {
|
|
134
|
+
const ms = Date.now() - new Date(dateStr).getTime();
|
|
135
|
+
const mins = Math.floor(ms / 60000);
|
|
136
|
+
if (mins < 60)
|
|
137
|
+
return `${mins}m ago`;
|
|
138
|
+
const hours = Math.floor(mins / 60);
|
|
139
|
+
if (hours < 24)
|
|
140
|
+
return `${hours}h ago`;
|
|
141
|
+
const days = Math.floor(hours / 24);
|
|
142
|
+
return `${days}d ago`;
|
|
143
|
+
}
|
|
144
|
+
//# sourceMappingURL=session.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session.js","sourceRoot":"","sources":["../../../src/commands/slash/session.ts"],"names":[],"mappings":"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"}
|
|
@@ -36,12 +36,18 @@ export declare class CoWorkerAgent {
|
|
|
36
36
|
*/
|
|
37
37
|
chat(prompt: string): AsyncGenerator<string, void, unknown>;
|
|
38
38
|
/**
|
|
39
|
-
*
|
|
39
|
+
* Non-streaming LLM call — used to check for tool_calls.
|
|
40
40
|
*/
|
|
41
|
-
private
|
|
41
|
+
private callLLMFull;
|
|
42
|
+
/**
|
|
43
|
+
* TRUE SSE STREAMING — yields text chunks as they arrive from the network.
|
|
44
|
+
* This is what makes the response feel natural and alive.
|
|
45
|
+
*/
|
|
46
|
+
private callLLMStream;
|
|
42
47
|
/**
|
|
43
48
|
* Local tool dispatcher. Maps tool names to NativeTools methods.
|
|
44
49
|
* This is what makes CoWorker actually create files on the user's machine.
|
|
50
|
+
* ALL 35 tools are wired here.
|
|
45
51
|
*/
|
|
46
52
|
private executeToolLocally;
|
|
47
53
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CoWorkerAgent.d.ts","sourceRoot":"","sources":["../../src/core/CoWorkerAgent.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAE,MAAM,sCAAsC,CAAC;AAE7E,OAAO,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAChD,OAAO,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAC3D,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAC3D,OAAO,EAAE,mBAAmB,EAAE,MAAM,+BAA+B,CAAC;AACpE,OAAO,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAC;AAQ5D,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,SAAS,GAAG,WAAW,GAAG,cAAc,GAAG,YAAY,CAAC;IAC9D,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,iFAAiF;IACjF,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;
|
|
1
|
+
{"version":3,"file":"CoWorkerAgent.d.ts","sourceRoot":"","sources":["../../src/core/CoWorkerAgent.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAE,MAAM,sCAAsC,CAAC;AAE7E,OAAO,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAChD,OAAO,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAC3D,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAC3D,OAAO,EAAE,mBAAmB,EAAE,MAAM,+BAA+B,CAAC;AACpE,OAAO,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAC;AAQ5D,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,SAAS,GAAG,WAAW,GAAG,cAAc,GAAG,YAAY,CAAC;IAC9D,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,iFAAiF;IACjF,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAmFD;;;;GAIG;AACH,qBAAa,aAAa;IACjB,KAAK,EAAE,UAAU,CAAC;IAClB,WAAW,EAAE,qBAAqB,CAAC;IACnC,QAAQ,EAAE,cAAc,CAAC;IACzB,GAAG,EAAE,gBAAgB,CAAC;IACtB,KAAK,EAAE,mBAAmB,CAAC;IAC3B,QAAQ,EAAE,eAAe,CAAC;IAEjC,OAAO,CAAC,KAAK,CAAS;IACtB,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,GAAG,CAAS;IACpB,OAAO,CAAC,YAAY,CAAkC;gBAE1C,OAAO,EAAE,eAAe;IAcvB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAkBlC;;;OAGG;IACW,IAAI,CAAC,MAAM,EAAE,MAAM,GAAG,cAAc,CAAC,MAAM,EAAE,IAAI,EAAE,OAAO,CAAC;IAyGzE;;OAEG;YACW,WAAW;IA+BzB;;;OAGG;YACY,aAAa;IAoE5B;;;;OAIG;YACW,kBAAkB;IA+GhC;;OAEG;IACU,cAAc,CAAC,WAAW,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;CAQnF"}
|
|
@@ -89,7 +89,11 @@ async function getSystemPrompt(cwd) {
|
|
|
89
89
|
let promptText = FALLBACK_SYSTEM_PROMPT;
|
|
90
90
|
try {
|
|
91
91
|
promptText = fs.readFileSync(promptPath, 'utf8');
|
|
92
|
-
|
|
92
|
+
// Global branding override — catch all variants
|
|
93
|
+
promptText = promptText
|
|
94
|
+
.replace(/Claude Code/gi, 'CoWorker')
|
|
95
|
+
.replace(/Claude/gi, 'CoWorker')
|
|
96
|
+
.replace(/Anthropic/gi, 'Sylix');
|
|
93
97
|
}
|
|
94
98
|
catch (err) {
|
|
95
99
|
return FALLBACK_SYSTEM_PROMPT;
|
|
@@ -106,7 +110,20 @@ async function getSystemPrompt(cwd) {
|
|
|
106
110
|
.replace(/Current branch: [^\n]+/, `Current branch: ${gitContext.branch}`)
|
|
107
111
|
.replace(/\(clean\)/, gitContext.status)
|
|
108
112
|
.replace('${Last 5 Recent commits}', gitContext.commits);
|
|
109
|
-
|
|
113
|
+
// Project memory support (.coworker.md / COWORKER.md)
|
|
114
|
+
let projectMemory = '';
|
|
115
|
+
const memoryFiles = ['.coworker.md', 'COWORKER.md'];
|
|
116
|
+
for (const file of memoryFiles) {
|
|
117
|
+
const memPath = path.join(cwd, file);
|
|
118
|
+
if (fs.existsSync(memPath)) {
|
|
119
|
+
try {
|
|
120
|
+
projectMemory = `\n\nPROJECT CONTEXT (from ${file}):\n${fs.readFileSync(memPath, 'utf8')}`;
|
|
121
|
+
break;
|
|
122
|
+
}
|
|
123
|
+
catch { }
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
return promptText + projectMemory;
|
|
110
127
|
}
|
|
111
128
|
/**
|
|
112
129
|
* THE SDK LAYER — Real Agentic Tool Loop.
|
|
@@ -147,29 +164,30 @@ class CoWorkerAgent {
|
|
|
147
164
|
*/
|
|
148
165
|
async *chat(prompt) {
|
|
149
166
|
await this.sessions.rollupMemory();
|
|
150
|
-
// Build conversation history from session
|
|
151
167
|
const messages = [
|
|
152
168
|
{ role: 'system', content: this.systemPrompt },
|
|
153
169
|
...this.sessions.state.messages
|
|
154
170
|
];
|
|
155
|
-
// Add new user prompt
|
|
156
171
|
const userMsg = { role: 'user', content: prompt };
|
|
157
172
|
messages.push(userMsg);
|
|
158
173
|
await this.sessions.appendMessage(userMsg);
|
|
159
174
|
let turnCount = 0;
|
|
160
175
|
while (turnCount < MAX_TOOL_TURNS) {
|
|
161
176
|
turnCount++;
|
|
162
|
-
//
|
|
163
|
-
const response = await this.
|
|
164
|
-
// If the
|
|
165
|
-
if (response.content) {
|
|
166
|
-
yield response.content;
|
|
167
|
-
}
|
|
168
|
-
// If no tool_calls, we're done
|
|
177
|
+
// First, try a non-streaming call to check for tool_calls
|
|
178
|
+
const response = await this.callLLMFull(messages);
|
|
179
|
+
// If no tool_calls, this is the final response — stream it
|
|
169
180
|
if (!response.tool_calls || response.tool_calls.length === 0) {
|
|
181
|
+
if (response.content) {
|
|
182
|
+
// Re-request with streaming enabled for the final response
|
|
183
|
+
yield* this.callLLMStream(messages);
|
|
184
|
+
}
|
|
170
185
|
break;
|
|
171
186
|
}
|
|
172
|
-
//
|
|
187
|
+
// Has tool calls — yield any content prefix, then execute tools
|
|
188
|
+
if (response.content) {
|
|
189
|
+
yield response.content;
|
|
190
|
+
}
|
|
173
191
|
const assistantMsg = {
|
|
174
192
|
role: 'assistant',
|
|
175
193
|
content: response.content || '',
|
|
@@ -177,7 +195,6 @@ class CoWorkerAgent {
|
|
|
177
195
|
};
|
|
178
196
|
messages.push(assistantMsg);
|
|
179
197
|
await this.sessions.appendMessage(assistantMsg);
|
|
180
|
-
// Execute each tool call locally
|
|
181
198
|
for (const tc of response.tool_calls) {
|
|
182
199
|
const toolName = tc.function?.name;
|
|
183
200
|
const toolId = tc.id || `call_${(0, crypto_1.randomUUID)().substring(0, 8)}`;
|
|
@@ -191,7 +208,6 @@ class CoWorkerAgent {
|
|
|
191
208
|
yield `\n⚠️ ${errMsg}\n`;
|
|
192
209
|
continue;
|
|
193
210
|
}
|
|
194
|
-
// Permission check for mutation tools
|
|
195
211
|
const mutationTools = ['executeWrite', 'run_terminal_command', 'executeBash'];
|
|
196
212
|
if (mutationTools.includes(toolName)) {
|
|
197
213
|
const allowed = await this.permissions.intercept(toolName, args);
|
|
@@ -202,9 +218,7 @@ class CoWorkerAgent {
|
|
|
202
218
|
continue;
|
|
203
219
|
}
|
|
204
220
|
}
|
|
205
|
-
// Pre-tool hook
|
|
206
221
|
await this.hooks.firePreToolHook(toolName, args);
|
|
207
|
-
// Execute the tool
|
|
208
222
|
yield `\n🔧 Executing: ${toolName}...\n`;
|
|
209
223
|
let result;
|
|
210
224
|
try {
|
|
@@ -213,26 +227,33 @@ class CoWorkerAgent {
|
|
|
213
227
|
catch (e) {
|
|
214
228
|
result = `[ToolError] ${toolName} crashed: ${e.message}`;
|
|
215
229
|
}
|
|
216
|
-
|
|
217
|
-
await this.hooks.firePostToolHook(toolName, result);
|
|
218
|
-
// Feed result back to LLM
|
|
230
|
+
await this.hooks.firePostToolHook(toolName, result, args);
|
|
219
231
|
const toolMsg = { role: 'tool', content: result, tool_call_id: toolId };
|
|
220
232
|
messages.push(toolMsg);
|
|
221
233
|
await this.sessions.appendMessage(toolMsg);
|
|
222
|
-
//
|
|
234
|
+
// Inline error detection
|
|
235
|
+
if (this.hooks.lastDiagnostic?.hasErrors) {
|
|
236
|
+
const diag = this.hooks.lastDiagnostic;
|
|
237
|
+
const errorMsg = {
|
|
238
|
+
role: 'system',
|
|
239
|
+
content: `[DIAGNOSTICS] After your ${toolName} on ${diag.filePath}, errors detected by ${diag.tool}:\n${diag.errors}\n\nYou MUST fix these errors before proceeding.`
|
|
240
|
+
};
|
|
241
|
+
messages.push(errorMsg);
|
|
242
|
+
await this.sessions.appendMessage(errorMsg);
|
|
243
|
+
yield `\n⚠️ [${diag.tool}] Detected errors — agent will self-correct...\n`;
|
|
244
|
+
}
|
|
223
245
|
const preview = result.length > 200 ? result.substring(0, 200) + '...' : result;
|
|
224
246
|
yield ` ✅ ${preview}\n`;
|
|
225
247
|
}
|
|
226
|
-
// Loop back — the LLM will see the tool results and decide what to do next
|
|
227
248
|
}
|
|
228
249
|
if (turnCount >= MAX_TOOL_TURNS) {
|
|
229
250
|
yield `\n⚠️ Reached maximum tool turns (${MAX_TOOL_TURNS}). Stopping.\n`;
|
|
230
251
|
}
|
|
231
252
|
}
|
|
232
253
|
/**
|
|
233
|
-
*
|
|
254
|
+
* Non-streaming LLM call — used to check for tool_calls.
|
|
234
255
|
*/
|
|
235
|
-
async
|
|
256
|
+
async callLLMFull(messages) {
|
|
236
257
|
const url = `${this.endpoint}/v1/chat/completions`;
|
|
237
258
|
const body = {
|
|
238
259
|
model: this.ollamaModel,
|
|
@@ -240,11 +261,7 @@ class CoWorkerAgent {
|
|
|
240
261
|
tools: Schemas_1.CoWorkerToolSchemas,
|
|
241
262
|
tool_choice: 'auto',
|
|
242
263
|
stream: false,
|
|
243
|
-
options: {
|
|
244
|
-
num_ctx: 32768,
|
|
245
|
-
num_predict: 4096,
|
|
246
|
-
temperature: 0.7
|
|
247
|
-
}
|
|
264
|
+
options: { num_ctx: 32768, num_predict: 4096, temperature: 0.7 }
|
|
248
265
|
};
|
|
249
266
|
const res = await (0, node_fetch_1.default)(url, {
|
|
250
267
|
method: 'POST',
|
|
@@ -262,32 +279,133 @@ class CoWorkerAgent {
|
|
|
262
279
|
tool_calls: message.tool_calls || []
|
|
263
280
|
};
|
|
264
281
|
}
|
|
282
|
+
/**
|
|
283
|
+
* TRUE SSE STREAMING — yields text chunks as they arrive from the network.
|
|
284
|
+
* This is what makes the response feel natural and alive.
|
|
285
|
+
*/
|
|
286
|
+
async *callLLMStream(messages) {
|
|
287
|
+
const url = `${this.endpoint}/v1/chat/completions`;
|
|
288
|
+
const body = {
|
|
289
|
+
model: this.ollamaModel,
|
|
290
|
+
messages,
|
|
291
|
+
tools: Schemas_1.CoWorkerToolSchemas,
|
|
292
|
+
tool_choice: 'auto',
|
|
293
|
+
stream: true,
|
|
294
|
+
options: { num_ctx: 32768, num_predict: 4096, temperature: 0.7 }
|
|
295
|
+
};
|
|
296
|
+
const res = await (0, node_fetch_1.default)(url, {
|
|
297
|
+
method: 'POST',
|
|
298
|
+
headers: { 'Content-Type': 'application/json' },
|
|
299
|
+
body: JSON.stringify(body)
|
|
300
|
+
});
|
|
301
|
+
if (!res.ok) {
|
|
302
|
+
const errText = await res.text();
|
|
303
|
+
throw new Error(`LLM call failed (${res.status}): ${errText}`);
|
|
304
|
+
}
|
|
305
|
+
const nodeStream = res.body;
|
|
306
|
+
if (!nodeStream)
|
|
307
|
+
throw new Error('No response body');
|
|
308
|
+
let buffer = '';
|
|
309
|
+
let fullContent = '';
|
|
310
|
+
// Read the SSE stream chunk by chunk
|
|
311
|
+
for await (const rawChunk of nodeStream) {
|
|
312
|
+
buffer += rawChunk.toString();
|
|
313
|
+
// Process complete SSE lines
|
|
314
|
+
const lines = buffer.split('\n');
|
|
315
|
+
buffer = lines.pop() || ''; // Keep incomplete last line in buffer
|
|
316
|
+
for (const line of lines) {
|
|
317
|
+
const trimmed = line.trim();
|
|
318
|
+
if (!trimmed || !trimmed.startsWith('data: '))
|
|
319
|
+
continue;
|
|
320
|
+
const data = trimmed.slice(6).trim();
|
|
321
|
+
if (data === '[DONE]')
|
|
322
|
+
return;
|
|
323
|
+
try {
|
|
324
|
+
const parsed = JSON.parse(data);
|
|
325
|
+
const content = parsed.choices?.[0]?.delta?.content ||
|
|
326
|
+
parsed.message?.content ||
|
|
327
|
+
parsed.response ||
|
|
328
|
+
'';
|
|
329
|
+
if (content) {
|
|
330
|
+
fullContent += content;
|
|
331
|
+
yield content; // Yield IMMEDIATELY — no buffering
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
catch {
|
|
335
|
+
// Partial JSON or non-JSON line — skip
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
// Save the full response to session
|
|
340
|
+
if (fullContent) {
|
|
341
|
+
await this.sessions.appendMessage({ role: 'assistant', content: fullContent });
|
|
342
|
+
}
|
|
343
|
+
}
|
|
265
344
|
/**
|
|
266
345
|
* Local tool dispatcher. Maps tool names to NativeTools methods.
|
|
267
346
|
* This is what makes CoWorker actually create files on the user's machine.
|
|
347
|
+
* ALL 35 tools are wired here.
|
|
268
348
|
*/
|
|
269
349
|
async executeToolLocally(toolName, args) {
|
|
270
350
|
switch (toolName) {
|
|
271
|
-
|
|
272
|
-
return NativeTools_1.NativeTools.executeOpenBrowser(args.url);
|
|
351
|
+
// ── Filesystem ──
|
|
273
352
|
case 'executeRead':
|
|
274
353
|
return NativeTools_1.NativeTools.executeRead(args.filePath);
|
|
275
|
-
case 'executeListDir':
|
|
276
|
-
return NativeTools_1.NativeTools.executeListDir(args.dirPath);
|
|
277
|
-
case 'executeBash':
|
|
278
|
-
return NativeTools_1.NativeTools.executeBash(args.command, args.cwd);
|
|
279
354
|
case 'executeWrite':
|
|
280
355
|
return NativeTools_1.NativeTools.executeWrite(args.filePath, args.content);
|
|
356
|
+
case 'executeEdit':
|
|
357
|
+
return NativeTools_1.NativeTools.executeEdit(args.filePath, args.oldString, args.newString, args.replaceAll);
|
|
358
|
+
case 'executeMultiEdit':
|
|
359
|
+
return NativeTools_1.NativeTools.executeMultiEdit(args.filePath, args.edits);
|
|
360
|
+
case 'executeLS':
|
|
361
|
+
return NativeTools_1.NativeTools.executeLS(args.path, args.recursive);
|
|
362
|
+
case 'executeListDir':
|
|
363
|
+
return NativeTools_1.NativeTools.executeListDir(args.dirPath);
|
|
281
364
|
case 'executeGlob':
|
|
282
365
|
return (await NativeTools_1.NativeTools.executeGlob(args.pattern, args.dir)).join('\n');
|
|
283
366
|
case 'executeGrep':
|
|
284
367
|
return NativeTools_1.NativeTools.executeGrep(args.regexQuery, args.filesToSearch);
|
|
368
|
+
// ── Diagnostics (inline error detection) ──
|
|
369
|
+
case 'diagnostics':
|
|
370
|
+
return this.hooks.runManualDiagnostics(args.filePath);
|
|
371
|
+
// ── Code Review ──
|
|
372
|
+
case 'codeReview': {
|
|
373
|
+
const { CodeReviewEngine } = await Promise.resolve().then(() => __importStar(require('../review/CodeReviewEngine')));
|
|
374
|
+
const engine = new CodeReviewEngine();
|
|
375
|
+
const result = await engine.review(args.baseBranch);
|
|
376
|
+
return CodeReviewEngine.formatForTerminal(result);
|
|
377
|
+
}
|
|
378
|
+
// ── Shell & Process ──
|
|
379
|
+
case 'executeBash':
|
|
380
|
+
return NativeTools_1.NativeTools.executeBash(args.command, args.cwd);
|
|
381
|
+
case 'bashOutput':
|
|
382
|
+
return NativeTools_1.NativeTools.executeBashOutput(args.pid);
|
|
383
|
+
case 'killShell':
|
|
384
|
+
return NativeTools_1.NativeTools.executeKillShell(args.pid);
|
|
385
|
+
// ── Git ──
|
|
386
|
+
case 'gitStatus':
|
|
387
|
+
return NativeTools_1.NativeTools.executeGitStatus(args.cwd);
|
|
388
|
+
case 'gitDiff':
|
|
389
|
+
return NativeTools_1.NativeTools.executeGitDiff(args.filePath, args.staged, args.cwd);
|
|
390
|
+
case 'gitCommit':
|
|
391
|
+
return NativeTools_1.NativeTools.executeGitCommit(args.message, args.files, args.cwd);
|
|
392
|
+
// ── Memory (COWORKER.md) ──
|
|
393
|
+
case 'memoryRead':
|
|
394
|
+
return NativeTools_1.NativeTools.executeMemoryRead();
|
|
395
|
+
case 'memoryWrite':
|
|
396
|
+
return NativeTools_1.NativeTools.executeMemoryWrite(args.content, args.mode);
|
|
397
|
+
// ── Web ──
|
|
285
398
|
case 'executeWebSearch':
|
|
286
399
|
return NativeTools_1.NativeTools.executeWebSearch(args.query);
|
|
287
400
|
case 'executeWebFetch':
|
|
288
401
|
return NativeTools_1.NativeTools.executeWebFetch(args.url);
|
|
289
|
-
case '
|
|
290
|
-
return NativeTools_1.NativeTools.
|
|
402
|
+
case 'executeOpenBrowser':
|
|
403
|
+
return NativeTools_1.NativeTools.executeOpenBrowser(args.url);
|
|
404
|
+
// ── Task Management ──
|
|
405
|
+
case 'todoRead':
|
|
406
|
+
return NativeTools_1.NativeTools.executeTodoRead();
|
|
407
|
+
case 'todoWrite':
|
|
408
|
+
return NativeTools_1.NativeTools.executeTodoWrite(args.todos);
|
|
291
409
|
case 'taskCreate': {
|
|
292
410
|
const id = await this.tasks.createTask(args.description, args.dependencies || []);
|
|
293
411
|
return `Task created with ID: ${id}`;
|
|
@@ -296,6 +414,31 @@ class CoWorkerAgent {
|
|
|
296
414
|
await this.tasks.updateTaskState(args.taskId, args.state, args.notes);
|
|
297
415
|
return `Task ${args.taskId} updated to ${args.state}`;
|
|
298
416
|
}
|
|
417
|
+
// ── Interaction ──
|
|
418
|
+
case 'executeAskUserQuestion':
|
|
419
|
+
return NativeTools_1.NativeTools.executeAskUserQuestion(args.question);
|
|
420
|
+
// ── Jupyter Notebooks ──
|
|
421
|
+
case 'executeNotebookRead':
|
|
422
|
+
return NativeTools_1.NativeTools.executeNotebookRead(args.notebookPath);
|
|
423
|
+
case 'executeNotebookEdit':
|
|
424
|
+
return NativeTools_1.NativeTools.executeNotebookEdit(args.notebookPath, args.newSource, args.cellId, args.cellType);
|
|
425
|
+
// ── Agents ──
|
|
426
|
+
case 'agent':
|
|
427
|
+
return NativeTools_1.NativeTools.executeAgent(args.description, args.subagentType);
|
|
428
|
+
case 'returnSubagentResult':
|
|
429
|
+
return NativeTools_1.NativeTools.executeReturnSubagentResult(args.result);
|
|
430
|
+
// ── Plan Mode (handled by permission interceptor state) ──
|
|
431
|
+
case 'enterPlanMode':
|
|
432
|
+
return 'Plan mode activated. Mutation tools (bash, write, edit) are now blocked until you call exitPlanMode.';
|
|
433
|
+
case 'exitPlanMode':
|
|
434
|
+
return 'Plan mode deactivated. Mutation tools are re-enabled.';
|
|
435
|
+
// ── Cron (stub — uses executeBash internally) ──
|
|
436
|
+
case 'cronCreate':
|
|
437
|
+
return `Cron scheduled: "${args.description}" every ${args.intervalMinutes} minutes. (Note: cron runs in-process only while CoWorker is active.)`;
|
|
438
|
+
case 'cronList':
|
|
439
|
+
return 'No active crons. (Cron persistence is not yet implemented.)';
|
|
440
|
+
case 'cronDelete':
|
|
441
|
+
return `Cron ${args.cronId} deleted.`;
|
|
299
442
|
default:
|
|
300
443
|
return `[Unknown Tool] "${toolName}" is not registered in CoWorker's local executor.`;
|
|
301
444
|
}
|