orquesta-cli 0.2.94 → 0.2.96
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.js +6 -10
- package/dist/core/config/config-manager.d.ts +2 -0
- package/dist/core/config/config-manager.js +10 -0
- package/dist/core/config/endpoint-override.d.ts +15 -0
- package/dist/core/config/endpoint-override.js +12 -0
- package/dist/core/slash-command-handler.js +8 -1
- package/dist/orchestration/plan-executor.js +23 -0
- package/dist/types/index.d.ts +1 -0
- package/dist/ui/components/TodoListView.js +2 -2
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -17,6 +17,7 @@ import React from 'react';
|
|
|
17
17
|
import { render } from 'ink';
|
|
18
18
|
import { createRequire } from 'module';
|
|
19
19
|
import { configManager } from './core/config/config-manager.js';
|
|
20
|
+
import { resolveEndpointOverride } from './core/config/endpoint-override.js';
|
|
20
21
|
import { createLLMClient } from './core/llm/llm-client.js';
|
|
21
22
|
import { PlanExecuteApp } from './ui/components/PlanExecuteApp.js';
|
|
22
23
|
import { setAppendedSystemPrompt } from './orchestration/plan-executor.js';
|
|
@@ -155,17 +156,12 @@ program
|
|
|
155
156
|
await configManager.initialize();
|
|
156
157
|
await ensureBatutaFromEnv();
|
|
157
158
|
if (options.endpoint) {
|
|
158
|
-
const wanted = String(options.endpoint).toLowerCase();
|
|
159
159
|
const all = configManager.getAllEndpoints();
|
|
160
|
-
const
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
await configManager.setCurrentEndpoint(ep.id);
|
|
166
|
-
const m = ep.models.find((x) => x.enabled) || ep.models[0];
|
|
167
|
-
if (m)
|
|
168
|
-
await configManager.setCurrentModel(m.id);
|
|
160
|
+
const resolved = resolveEndpointOverride(all, String(options.endpoint));
|
|
161
|
+
if (resolved) {
|
|
162
|
+
await configManager.setCurrentEndpoint(resolved.endpointId);
|
|
163
|
+
if (resolved.modelId)
|
|
164
|
+
await configManager.setCurrentModel(resolved.modelId);
|
|
169
165
|
}
|
|
170
166
|
else {
|
|
171
167
|
logger.warn(`--endpoint "${options.endpoint}" matched no configured endpoint (have: ${all.map(e => e.id).join(', ') || 'none'}); keeping current selection`);
|
|
@@ -60,6 +60,8 @@ export declare class ConfigManager {
|
|
|
60
60
|
setMaxParallelWorkers(n: number): Promise<void>;
|
|
61
61
|
isRefinerEnabled(): boolean;
|
|
62
62
|
setRefinerEnabled(enabled: boolean): Promise<void>;
|
|
63
|
+
isSingleAgentMode(): boolean;
|
|
64
|
+
setSingleAgentMode(enabled: boolean): Promise<void>;
|
|
63
65
|
isWorktreeIsolationEnabled(): boolean;
|
|
64
66
|
setWorktreeIsolationEnabled(enabled: boolean): Promise<void>;
|
|
65
67
|
}
|
|
@@ -415,6 +415,16 @@ export class ConfigManager {
|
|
|
415
415
|
config.orchestration.refinerEnabled = enabled;
|
|
416
416
|
await this.saveConfig();
|
|
417
417
|
}
|
|
418
|
+
isSingleAgentMode() {
|
|
419
|
+
return this.config?.orchestration?.singleAgentMode ?? false;
|
|
420
|
+
}
|
|
421
|
+
async setSingleAgentMode(enabled) {
|
|
422
|
+
const config = this.getConfig();
|
|
423
|
+
if (!config.orchestration)
|
|
424
|
+
config.orchestration = {};
|
|
425
|
+
config.orchestration.singleAgentMode = enabled;
|
|
426
|
+
await this.saveConfig();
|
|
427
|
+
}
|
|
418
428
|
isWorktreeIsolationEnabled() {
|
|
419
429
|
return this.config?.orchestration?.worktreeIsolation ?? false;
|
|
420
430
|
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export interface OverrideEndpoint {
|
|
2
|
+
id: string;
|
|
3
|
+
name?: string;
|
|
4
|
+
provider?: string;
|
|
5
|
+
models?: Array<{
|
|
6
|
+
id: string;
|
|
7
|
+
enabled?: boolean;
|
|
8
|
+
}>;
|
|
9
|
+
}
|
|
10
|
+
export interface ResolvedOverride {
|
|
11
|
+
endpointId: string;
|
|
12
|
+
modelId?: string;
|
|
13
|
+
}
|
|
14
|
+
export declare function resolveEndpointOverride(endpoints: OverrideEndpoint[], wanted: string): ResolvedOverride | null;
|
|
15
|
+
//# sourceMappingURL=endpoint-override.d.ts.map
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export function resolveEndpointOverride(endpoints, wanted) {
|
|
2
|
+
const w = String(wanted).toLowerCase();
|
|
3
|
+
const ep = w === 'batuta'
|
|
4
|
+
? endpoints.find((e) => e.id === 'batuta-proxy' || e.provider === 'batuta')
|
|
5
|
+
: endpoints.find((e) => e.id === wanted) ||
|
|
6
|
+
endpoints.find((e) => (e.name || '').toLowerCase() === w);
|
|
7
|
+
if (!ep)
|
|
8
|
+
return null;
|
|
9
|
+
const m = ep.models?.find((x) => x.enabled) || ep.models?.[0];
|
|
10
|
+
return { endpointId: ep.id, modelId: m?.id };
|
|
11
|
+
}
|
|
12
|
+
//# sourceMappingURL=endpoint-override.js.map
|
|
@@ -141,7 +141,8 @@ export async function executeSlashCommand(command, context) {
|
|
|
141
141
|
const parallel = configManager.getMaxParallelWorkers();
|
|
142
142
|
const refiner = configManager.isRefinerEnabled() ? 'on' : 'off';
|
|
143
143
|
const worktree = configManager.isWorktreeIsolationEnabled() ? 'on' : 'off';
|
|
144
|
-
|
|
144
|
+
const single = configManager.isSingleAgentMode() ? 'on' : 'off';
|
|
145
|
+
return `Multi-role orchestration\n\n${lines.join('\n')}\n\n max parallel workers: ${parallel}\n refiner pass: ${refiner}\n worktree isolation: ${worktree}\n single-agent mode: ${single}\n\nUsage:\n /role planner <model-id>\n /role executor <model-id>\n /role refiner <model-id> | off\n /role parallel <N>\n /role worktree on|off\n /role single on|off (skip planner; one accumulative agent — best for debugging)\n /role clear`;
|
|
145
146
|
};
|
|
146
147
|
let body;
|
|
147
148
|
try {
|
|
@@ -166,6 +167,12 @@ export async function executeSlashCommand(command, context) {
|
|
|
166
167
|
await configManager.setWorktreeIsolationEnabled(args[1] === 'on');
|
|
167
168
|
body = `Worktree isolation: ${args[1]}.`;
|
|
168
169
|
}
|
|
170
|
+
else if (args[0] === 'single' && (args[1] === 'on' || args[1] === 'off')) {
|
|
171
|
+
await configManager.setSingleAgentMode(args[1] === 'on');
|
|
172
|
+
body = args[1] === 'on'
|
|
173
|
+
? 'Single-agent mode ON — planner/orchestrator bypassed; one accumulative agent (best for debugging/investigation).'
|
|
174
|
+
: 'Single-agent mode OFF — planner + orchestrator restored.';
|
|
175
|
+
}
|
|
169
176
|
else if ((args[0] === 'planner' || args[0] === 'executor' || args[0] === 'refiner') && args[1]) {
|
|
170
177
|
const role = args[0];
|
|
171
178
|
if (role === 'refiner' && args[1] === 'off') {
|
|
@@ -106,6 +106,29 @@ export class PlanExecutor {
|
|
|
106
106
|
throw new Error('INTERRUPTED');
|
|
107
107
|
}
|
|
108
108
|
let currentMessages = messages;
|
|
109
|
+
if (configManager.isSingleAgentMode()) {
|
|
110
|
+
logger.flow('Single-agent mode — bypassing planner/orchestrator');
|
|
111
|
+
callbacks.setExecutionPhase('executing');
|
|
112
|
+
callbacks.setCurrentActivity('Working (single-agent)');
|
|
113
|
+
const saTools = toolRegistry.getLLMToolDefinitions();
|
|
114
|
+
const lastUserIdx = currentMessages.map(m => m.role).lastIndexOf('user');
|
|
115
|
+
const saMessages = (lastUserIdx >= 0 && currentMessages[lastUserIdx]?.content === userMessage)
|
|
116
|
+
? currentMessages
|
|
117
|
+
: [...currentMessages, { role: 'user', content: userMessage }];
|
|
118
|
+
const saExecutorModel = configManager.getRoleModel('executor');
|
|
119
|
+
const saResult = await llmClient.chatCompletionWithTools(saMessages, saTools, {
|
|
120
|
+
getPendingMessage: callbacks.getPendingMessage,
|
|
121
|
+
clearPendingMessage: callbacks.clearPendingMessage,
|
|
122
|
+
...(saExecutorModel ? { model: saExecutorModel } : {}),
|
|
123
|
+
});
|
|
124
|
+
currentMessages = [...saMessages, ...saResult.allMessages.slice(saMessages.length)];
|
|
125
|
+
callbacks.setMessages([...currentMessages]);
|
|
126
|
+
sessionManager.autoSaveCurrentSession(currentMessages);
|
|
127
|
+
callbacks.setExecutionPhase('idle');
|
|
128
|
+
auditLog.emit(auditSid, 'run.complete', { runId, mode: 'single-agent', success: true });
|
|
129
|
+
logger.exit('PlanExecutor.executePlanMode', { singleAgent: true });
|
|
130
|
+
return;
|
|
131
|
+
}
|
|
109
132
|
callbacks.setCurrentActivity('Thinking');
|
|
110
133
|
const plannerModel = configManager.getRoleModel('planner');
|
|
111
134
|
const planningLLM = new PlanningLLM(llmClient, plannerModel ?? undefined);
|
package/dist/types/index.d.ts
CHANGED
|
@@ -3,7 +3,7 @@ import { Box, Text } from 'ink';
|
|
|
3
3
|
import Spinner from 'ink-spinner';
|
|
4
4
|
import { logger } from '../../utils/logger.js';
|
|
5
5
|
const STATUS_CONFIG = {
|
|
6
|
-
completed: { icon: '☑', color: '
|
|
6
|
+
completed: { icon: '☑', color: 'green' },
|
|
7
7
|
in_progress: { icon: '☐', color: 'white' },
|
|
8
8
|
failed: { icon: '☒', color: 'red' },
|
|
9
9
|
pending: { icon: '☐', color: 'gray' },
|
|
@@ -57,7 +57,7 @@ export const TodoListView = ({ todos, showProgressBar = true, }) => {
|
|
|
57
57
|
React.createElement(Box, null,
|
|
58
58
|
React.createElement(Box, { width: 2 }, isInProgress ? (React.createElement(Text, { color: "blueBright" },
|
|
59
59
|
React.createElement(Spinner, { type: "dots2" }))) : (React.createElement(Text, { color: config.color }, config.icon))),
|
|
60
|
-
React.createElement(Text, { color: isCompleted ? '
|
|
60
|
+
React.createElement(Text, { color: isCompleted ? 'green' : isInProgress ? 'white' : 'gray', dimColor: false, bold: isInProgress }, todo.title),
|
|
61
61
|
isInProgress && React.createElement(Text, { color: "blueBright" }, " \u2190"),
|
|
62
62
|
todo.dependsOn && todo.dependsOn.length > 0 && (React.createElement(Text, { color: "gray", dimColor: true },
|
|
63
63
|
" (after ",
|