codeply-cli 0.4.1 → 0.5.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/lib/agent.mjs +12 -4
- package/lib/bots.js +1002 -0
- package/lib/cloud-browser.mjs +143 -0
- package/lib/cloud.mjs +443 -95
- package/lib/native-tools.mjs +2 -1
- package/lib/oauth-connectors.js +51 -9
- package/lib/tools.mjs +40 -12
- package/package.json +1 -1
package/lib/agent.mjs
CHANGED
|
@@ -338,6 +338,7 @@ const PARAMS = {
|
|
|
338
338
|
plan_exit: ['path'],
|
|
339
339
|
plan_enter: ['reason'],
|
|
340
340
|
lsp: ['operation', 'path', 'line', 'character', 'symbol', 'query'],
|
|
341
|
+
ask_bot: ['bot', 'task'], // only offered when the host passes askBot (lib/bots.js)
|
|
341
342
|
};
|
|
342
343
|
|
|
343
344
|
// Names the model actually reaches for when it paraphrases the format.
|
|
@@ -1097,6 +1098,9 @@ export function buildSystemPrompt(mode, cwd, userMessage, opts = {}) {
|
|
|
1097
1098
|
// reference, so it colors how every tool gets used.
|
|
1098
1099
|
const role = opts.roleId ? rolesLib.getSubagent(opts.roleId) : null;
|
|
1099
1100
|
if (role) parts.push('', ROLE_INTRO(role), role.persona);
|
|
1101
|
+
// A bot (lib/bots.js): identity, specialty, tone, approval boundary, memory, team.
|
|
1102
|
+
const botPrompt = typeof opts.botPrompt === 'function' ? opts.botPrompt(!!opts.native) : opts.botPrompt;
|
|
1103
|
+
if (botPrompt) parts.push('', botPrompt);
|
|
1100
1104
|
if (opts.goal) {
|
|
1101
1105
|
parts.push('', `GOAL MODE\nYou are working autonomously toward this goal until it is fully achieved:\n"${opts.goal}"\n` +
|
|
1102
1106
|
'Keep going without asking the user questions - make sensible, conventional decisions yourself and note them in your summary. ' +
|
|
@@ -1424,7 +1428,7 @@ function withoutEmDashes(text) {
|
|
|
1424
1428
|
* "claims an edit it didn't make this turn" check is skipped.
|
|
1425
1429
|
* @yields {{type:string, ...}} text | reasoning | tool_start | tool_end | done | error | aborted
|
|
1426
1430
|
*/
|
|
1427
|
-
export async function* runAgent({ userMessage, history, mode, cwd, approve, browser, images, signal, route, roleId, goal, maxSteps, verifyOnly }) {
|
|
1431
|
+
export async function* runAgent({ userMessage, history, mode, cwd, approve, browser, images, signal, route, roleId, goal, maxSteps, verifyOnly, botPrompt, askBot }) {
|
|
1428
1432
|
let readOnly = READ_ONLY_MODES.has(mode);
|
|
1429
1433
|
const stepBudget = Math.max(1, maxSteps || MAX_STEPS);
|
|
1430
1434
|
// OpenAI-shaped content array only when there's actually an image to carry -
|
|
@@ -1451,6 +1455,7 @@ export async function* runAgent({ userMessage, history, mode, cwd, approve, brow
|
|
|
1451
1455
|
const entries = Object.entries(PARAMS).filter(([n]) => {
|
|
1452
1456
|
if (n === 'plan_exit') return m === 'Plan';
|
|
1453
1457
|
if (n === 'plan_enter') return m === 'Build';
|
|
1458
|
+
if (n === 'ask_bot') return typeof askBot === 'function';
|
|
1454
1459
|
if (ro && MUTATING_ACTIONS.has(n)) return m === 'Plan' && (n === 'write_file' || n === 'edit_file');
|
|
1455
1460
|
return true;
|
|
1456
1461
|
});
|
|
@@ -1458,13 +1463,13 @@ export async function* runAgent({ userMessage, history, mode, cwd, approve, brow
|
|
|
1458
1463
|
};
|
|
1459
1464
|
let toolSchemas = schemasFor(mode);
|
|
1460
1465
|
const messages = [
|
|
1461
|
-
{ role: 'system', content: buildSystemPrompt(mode, cwd, userMessage, { roleId, goal, native, mcp: mcpList }) },
|
|
1466
|
+
{ role: 'system', content: buildSystemPrompt(mode, cwd, userMessage, { roleId, goal, native, mcp: mcpList, botPrompt }) },
|
|
1462
1467
|
...history,
|
|
1463
1468
|
{ role: 'user', content: userContent },
|
|
1464
1469
|
];
|
|
1465
1470
|
|
|
1466
1471
|
// fileState: path -> mtime when this turn last read/wrote it (see tools.mjs).
|
|
1467
|
-
const ctx = { cwd, approve, browser, signal, mode, route, fileState: new Map(), ask: typeof approve?.ask === 'function' ? approve.ask : null };
|
|
1472
|
+
const ctx = { cwd, approve, browser, signal, mode, route, fileState: new Map(), ask: typeof approve?.ask === 'function' ? approve.ask : null, askBot: typeof askBot === 'function' ? askBot : null };
|
|
1468
1473
|
const recentCallKeys = []; // executed calls, in order, for the stuck-loop guard
|
|
1469
1474
|
const lastResultFor = new Map(); // call key -> its most recent result
|
|
1470
1475
|
const transcript = [{ role: 'user', content: userMessage }];
|
|
@@ -1585,7 +1590,7 @@ export async function* runAgent({ userMessage, history, mode, cwd, approve, brow
|
|
|
1585
1590
|
if (native && !attempt.result.success && !signal.aborted && TOOLS_UNSUPPORTED.test(String(attempt.result.error || ''))) {
|
|
1586
1591
|
native = false;
|
|
1587
1592
|
nativeUnsupported.add(nativeKey);
|
|
1588
|
-
messages[0] = { role: 'system', content: buildSystemPrompt(mode, cwd, userMessage, { roleId, goal, native: false, mcp: mcpList }) };
|
|
1593
|
+
messages[0] = { role: 'system', content: buildSystemPrompt(mode, cwd, userMessage, { roleId, goal, native: false, mcp: mcpList, botPrompt }) };
|
|
1589
1594
|
outgoing = [messages[0], ...outgoing.slice(1)];
|
|
1590
1595
|
yield { type: 'notice', level: 'info', text: 'This model does not support native tool calls, so Codeply switched to text actions.' };
|
|
1591
1596
|
attempt = await callModel(outgoing, userMessage, signal, route);
|
|
@@ -1905,6 +1910,9 @@ export async function* runAgent({ userMessage, history, mode, cwd, approve, brow
|
|
|
1905
1910
|
ok: out.ok,
|
|
1906
1911
|
meta: out.meta,
|
|
1907
1912
|
summary: out.meta?.label,
|
|
1913
|
+
// The real reason a tool failed, so the card can show it even when
|
|
1914
|
+
// the model's own summary of it is vague.
|
|
1915
|
+
error: out.ok || out.meta?.rejected ? undefined : String(out.output || '').slice(0, 800),
|
|
1908
1916
|
ms,
|
|
1909
1917
|
needsApproval,
|
|
1910
1918
|
};
|