orquesta-cli 0.2.38 → 0.2.40
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.
|
@@ -14,5 +14,6 @@ export declare class PlanningLLM {
|
|
|
14
14
|
generateTODOList(userRequest: string, contextMessages?: Message[]): Promise<PlanningResult>;
|
|
15
15
|
generateTODOListWithDocsDecision(userRequest: string, contextMessages?: Message[]): Promise<PlanningWithDocsResult>;
|
|
16
16
|
}
|
|
17
|
+
export declare function extractLeakedToolCallName(text: string): string | null;
|
|
17
18
|
export default PlanningLLM;
|
|
18
19
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -195,6 +195,14 @@ Choose one of your 3 tools now.`,
|
|
|
195
195
|
lastError = new Error('Planning LLM returned empty response.');
|
|
196
196
|
continue;
|
|
197
197
|
}
|
|
198
|
+
const leakedTool = extractLeakedToolCallName(responseText);
|
|
199
|
+
if (leakedTool) {
|
|
200
|
+
logger.warn('respond_to_user response is a leaked tool-call JSON', { leakedTool });
|
|
201
|
+
lastError = new Error(`You attempted to call '${leakedTool}', which is an Execution LLM tool. ` +
|
|
202
|
+
`As the PLANNING LLM you must use create_todos for action requests ` +
|
|
203
|
+
`(the Execution LLM will run '${leakedTool}' for you) or respond_to_user with plain prose.`);
|
|
204
|
+
continue;
|
|
205
|
+
}
|
|
198
206
|
return {
|
|
199
207
|
todos: [],
|
|
200
208
|
complexity: 'simple',
|
|
@@ -254,5 +262,54 @@ Choose one of your 3 tools now.`,
|
|
|
254
262
|
};
|
|
255
263
|
}
|
|
256
264
|
}
|
|
265
|
+
const PLANNING_TOOL_NAMES = new Set(['ask_to_user', 'create_todos', 'respond_to_user']);
|
|
266
|
+
export function extractLeakedToolCallName(text) {
|
|
267
|
+
for (let start = text.indexOf('{'); start !== -1; start = text.indexOf('{', start + 1)) {
|
|
268
|
+
const end = findBalancedObjectEnd(text, start);
|
|
269
|
+
if (end === -1)
|
|
270
|
+
continue;
|
|
271
|
+
let parsed;
|
|
272
|
+
try {
|
|
273
|
+
parsed = JSON.parse(text.slice(start, end + 1));
|
|
274
|
+
}
|
|
275
|
+
catch {
|
|
276
|
+
continue;
|
|
277
|
+
}
|
|
278
|
+
if (parsed && typeof parsed === 'object') {
|
|
279
|
+
const tool = parsed.tool;
|
|
280
|
+
if (typeof tool === 'string' && tool && !PLANNING_TOOL_NAMES.has(tool))
|
|
281
|
+
return tool;
|
|
282
|
+
start = end;
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
return null;
|
|
286
|
+
}
|
|
287
|
+
function findBalancedObjectEnd(s, start) {
|
|
288
|
+
let depth = 0;
|
|
289
|
+
let inString = false;
|
|
290
|
+
let escaped = false;
|
|
291
|
+
for (let i = start; i < s.length; i++) {
|
|
292
|
+
const c = s[i];
|
|
293
|
+
if (inString) {
|
|
294
|
+
if (escaped)
|
|
295
|
+
escaped = false;
|
|
296
|
+
else if (c === '\\')
|
|
297
|
+
escaped = true;
|
|
298
|
+
else if (c === '"')
|
|
299
|
+
inString = false;
|
|
300
|
+
continue;
|
|
301
|
+
}
|
|
302
|
+
if (c === '"')
|
|
303
|
+
inString = true;
|
|
304
|
+
else if (c === '{')
|
|
305
|
+
depth++;
|
|
306
|
+
else if (c === '}') {
|
|
307
|
+
depth--;
|
|
308
|
+
if (depth === 0)
|
|
309
|
+
return i;
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
return -1;
|
|
313
|
+
}
|
|
257
314
|
export default PlanningLLM;
|
|
258
315
|
//# sourceMappingURL=index.js.map
|
|
@@ -437,10 +437,19 @@ ${executorLines}
|
|
|
437
437
|
};
|
|
438
438
|
}
|
|
439
439
|
if (context.onShowProjectSelector) {
|
|
440
|
+
const currentLine = orquestaConfig.projectName
|
|
441
|
+
? `📁 Current project: ${orquestaConfig.projectName}${orquestaConfig.organizationName ? ` (${orquestaConfig.organizationName})` : ''}`
|
|
442
|
+
: '📁 No project selected yet — pick one below.';
|
|
443
|
+
const updatedMessages = [
|
|
444
|
+
...context.messages,
|
|
445
|
+
{ role: 'assistant', content: currentLine },
|
|
446
|
+
];
|
|
447
|
+
context.setMessages(updatedMessages);
|
|
440
448
|
context.onShowProjectSelector();
|
|
441
449
|
return {
|
|
442
450
|
handled: true,
|
|
443
451
|
shouldContinue: false,
|
|
452
|
+
updatedContext: { messages: updatedMessages },
|
|
444
453
|
};
|
|
445
454
|
}
|
|
446
455
|
const projectMessage = `Use /project in interactive mode to switch between projects.\n\nCurrent project: ${orquestaConfig.projectName || 'Unknown'}`;
|
|
@@ -550,24 +559,24 @@ ${executorLines}
|
|
|
550
559
|
const binding = readHookConfig(process.cwd());
|
|
551
560
|
if (sub === 'status') {
|
|
552
561
|
if (!binding)
|
|
553
|
-
return reply('🔌
|
|
562
|
+
return reply('🔌 Session hook: not enabled in this directory.\nEnable it with /hook enable — claude AND orquesta sessions here will stream into your Orquesta project.');
|
|
554
563
|
const name = binding.projectName
|
|
555
564
|
|| (oc?.projectId === binding.projectId && oc?.projectName ? oc.projectName : binding.projectId);
|
|
556
|
-
return reply(`🟢
|
|
565
|
+
return reply(`🟢 Session hook: enabled here → claude & orquesta sessions stream into ${name}\n Project ID: ${binding.projectId}\n Disable with /hook disable.`);
|
|
557
566
|
}
|
|
558
567
|
if (sub === 'disable') {
|
|
559
568
|
if (!binding)
|
|
560
569
|
return reply('Nothing to do — no Orquesta hook is configured in this directory.');
|
|
561
570
|
const changed = disableHooks(process.cwd(), { quiet: true });
|
|
562
571
|
return reply(changed
|
|
563
|
-
? '✅ Hook disabled.
|
|
572
|
+
? '✅ Hook disabled. Sessions in this directory (claude or orquesta) no longer report to Orquesta.'
|
|
564
573
|
: 'Nothing to do — no Orquesta hook was configured here.');
|
|
565
574
|
}
|
|
566
575
|
if (sub === 'enable') {
|
|
567
576
|
if (!oc?.token)
|
|
568
577
|
return reply('❌ Not logged in. Run /login first, then /hook enable.');
|
|
569
578
|
if (!oc.projectId) {
|
|
570
|
-
return reply('⚠️ No project selected for this session.\nRun
|
|
579
|
+
return reply('⚠️ No project selected for this session.\nRun /project to pick one, or `orquesta hook enable` in a shell for the interactive list.');
|
|
571
580
|
}
|
|
572
581
|
const ok = writeHookFiles({
|
|
573
582
|
projectId: oc.projectId,
|
|
@@ -577,10 +586,10 @@ ${executorLines}
|
|
|
577
586
|
quiet: true,
|
|
578
587
|
});
|
|
579
588
|
return reply(ok
|
|
580
|
-
? `🟢
|
|
589
|
+
? `🟢 Session hook enabled → streaming into ${oc.projectName || oc.projectId}.\nEvery claude or orquesta session in this directory now streams into Orquesta.`
|
|
581
590
|
: '❌ Could not write hook files (check directory permissions).');
|
|
582
591
|
}
|
|
583
|
-
return reply('Usage: /hook status | /hook enable | /hook disable\n(To move a directory to a different project, run `orquesta hook switch` in a shell.)');
|
|
592
|
+
return reply('Usage: /hook status | /hook enable | /hook disable\nThe hook mirrors claude AND orquesta sessions in this directory into your project.\n(To move a directory to a different project, run `orquesta hook switch` in a shell.)');
|
|
584
593
|
}
|
|
585
594
|
if (trimmedCommand === '/help') {
|
|
586
595
|
const helpMessage = `
|
|
@@ -1415,7 +1415,7 @@ export const PlanExecuteApp = ({ llmClient: initialLlmClient, modelInfo }) => {
|
|
|
1415
1415
|
"%)"),
|
|
1416
1416
|
React.createElement(Text, { color: "gray" }, " \u2502 ")));
|
|
1417
1417
|
})(),
|
|
1418
|
-
React.createElement(Text, { color: "cyan" }, currentModelInfo.model)))) : (React.createElement(
|
|
1418
|
+
React.createElement(Text, { color: "cyan" }, currentModelInfo.model)))) : (React.createElement(Box, { flexDirection: "column", width: "100%" },
|
|
1419
1419
|
React.createElement(Box, null,
|
|
1420
1420
|
React.createElement(Text, { color: executionMode === 'auto' ? 'green' : 'yellow', bold: true },
|
|
1421
1421
|
"[",
|
|
@@ -1438,17 +1438,22 @@ export const PlanExecuteApp = ({ llmClient: initialLlmClient, modelInfo }) => {
|
|
|
1438
1438
|
getHealthIndicator(),
|
|
1439
1439
|
" "),
|
|
1440
1440
|
React.createElement(Text, { color: "cyan" }, currentModelInfo.model),
|
|
1441
|
-
|
|
1441
|
+
(planExecutionState.todos.length > 0 || batutaUsage) && (React.createElement(React.Fragment, null,
|
|
1442
|
+
React.createElement(Text, { color: "gray" }, " \u2502 "),
|
|
1443
|
+
React.createElement(TodoStatusBar, { todos: planExecutionState.todos, projectName: configManager.getOrquestaConfig()?.projectName, batutaUsage: batutaUsage, isProcessing: isProcessing })))),
|
|
1444
|
+
React.createElement(Box, null,
|
|
1445
|
+
configManager.getOrquestaConfig()?.projectName && (React.createElement(React.Fragment, null,
|
|
1446
|
+
React.createElement(Text, { color: "magenta" },
|
|
1447
|
+
"\u26ED ",
|
|
1448
|
+
configManager.getOrquestaConfig()?.projectName),
|
|
1449
|
+
React.createElement(Text, { color: "gray" }, " \u2502 "))),
|
|
1442
1450
|
React.createElement(Text, { color: "gray" }, shortenPath(process.cwd())),
|
|
1443
1451
|
hookBinding && (React.createElement(React.Fragment, null,
|
|
1444
1452
|
React.createElement(Text, { color: "gray" }, " \u2502 "),
|
|
1445
1453
|
React.createElement(Text, { color: "green" },
|
|
1446
1454
|
"\u2B21 hook \u2192 ",
|
|
1447
1455
|
hookBinding.projectName))),
|
|
1448
|
-
(
|
|
1449
|
-
React.createElement(Text, { color: "gray" }, " \u2502 "),
|
|
1450
|
-
React.createElement(TodoStatusBar, { todos: planExecutionState.todos, projectName: configManager.getOrquestaConfig()?.projectName, batutaUsage: batutaUsage, isProcessing: isProcessing })))),
|
|
1451
|
-
React.createElement(Text, { color: "gray", dimColor: true }, "Tab: mode \u2502 /help")))),
|
|
1456
|
+
React.createElement(Text, { color: "gray", dimColor: true }, " \u2502 Tab: mode \u2502 /help"))))),
|
|
1452
1457
|
showLogFiles && (React.createElement(Box, { marginTop: 0 },
|
|
1453
1458
|
React.createElement(LogBrowser, { onClose: () => setShowLogFiles(false) })))));
|
|
1454
1459
|
};
|