orquesta-cli 0.2.45 → 0.2.46
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/agents/planner/index.js +2 -1
- package/dist/cli.js +17 -16
- package/dist/constants.d.ts +1 -1
- package/dist/constants.js +1 -1
- package/dist/core/commands/clear.d.ts +3 -0
- package/dist/core/commands/clear.js +22 -0
- package/dist/core/commands/compact.d.ts +3 -0
- package/dist/core/commands/compact.js +45 -0
- package/dist/core/commands/help.d.ts +3 -0
- package/dist/core/commands/help.js +50 -0
- package/dist/core/commands/index.d.ts +3 -0
- package/dist/core/commands/index.js +11 -0
- package/dist/core/commands/memory.d.ts +3 -0
- package/dist/core/commands/memory.js +40 -0
- package/dist/core/commands/registry.d.ts +11 -0
- package/dist/core/commands/registry.js +25 -0
- package/dist/core/commands/types.d.ts +10 -0
- package/dist/core/commands/types.js +2 -0
- package/dist/core/event-bus.d.ts +20 -0
- package/dist/core/event-bus.js +35 -0
- package/dist/core/git-context.d.ts +11 -0
- package/dist/core/git-context.js +62 -0
- package/dist/core/ignore-filter.d.ts +4 -0
- package/dist/core/ignore-filter.js +50 -0
- package/dist/core/llm/llm-client.d.ts +1 -0
- package/dist/core/llm/llm-client.js +118 -40
- package/dist/core/onboarding.d.ts +3 -0
- package/dist/core/onboarding.js +48 -0
- package/dist/core/slash-command-handler.js +8 -135
- package/dist/orchestration/plan-executor.js +77 -71
- package/dist/prompts/shared/tool-usage.js +0 -1
- package/dist/prompts/system/plan-execute.js +50 -57
- package/dist/tools/llm/simple/file-tools.js +12 -1
- package/dist/tools/llm/simple/final-response-tool.js +7 -11
- package/dist/tools/registry.js +63 -10
- package/dist/ui/components/PlanExecuteApp.d.ts +1 -0
- package/dist/ui/components/PlanExecuteApp.js +59 -22
- package/package.json +8 -4
|
@@ -3,6 +3,7 @@ import { buildPlanningSystemPrompt } from '../../prompts/agents/planning.js';
|
|
|
3
3
|
import { toolRegistry } from '../../tools/registry.js';
|
|
4
4
|
import { getProjectContext } from '../../core/project-context.js';
|
|
5
5
|
import { getMemoryPrompt } from '../../core/memory.js';
|
|
6
|
+
import { getGitContextPrompt } from '../../core/git-context.js';
|
|
6
7
|
export class PlanningLLM {
|
|
7
8
|
llmClient;
|
|
8
9
|
askUserCallback = null;
|
|
@@ -23,7 +24,7 @@ export class PlanningLLM {
|
|
|
23
24
|
const toolSummary = toolRegistry.getToolSummaryForPlanning();
|
|
24
25
|
const optionalToolsInfo = toolRegistry.getEnabledOptionalToolsInfo();
|
|
25
26
|
const projectContext = getProjectContext();
|
|
26
|
-
const systemPrompt = buildPlanningSystemPrompt(toolSummary, optionalToolsInfo) + projectContext + getMemoryPrompt();
|
|
27
|
+
const systemPrompt = buildPlanningSystemPrompt(toolSummary, optionalToolsInfo) + projectContext + getMemoryPrompt() + getGitContextPrompt();
|
|
27
28
|
const clarificationMessages = [];
|
|
28
29
|
const messages = [
|
|
29
30
|
{
|
package/dist/cli.js
CHANGED
|
@@ -28,6 +28,7 @@ import { connectWithToken, showConnectionStatus, disconnectFromOrquesta, switchP
|
|
|
28
28
|
import { syncOrquestaConfigs } from './orquesta/config-sync.js';
|
|
29
29
|
import { scanProviders, scanProvider, toEndpointConfig } from './core/config/auto-detect.js';
|
|
30
30
|
import { PROVIDERS } from './core/config/providers.js';
|
|
31
|
+
import { shouldShowOnboarding, runOnboarding } from './core/onboarding.js';
|
|
31
32
|
const require = createRequire(import.meta.url);
|
|
32
33
|
const packageJson = require('../package.json');
|
|
33
34
|
const program = new Command();
|
|
@@ -75,7 +76,7 @@ program
|
|
|
75
76
|
.name('orquesta')
|
|
76
77
|
.description('Orquesta CLI - AI-powered coding assistant with local LLM support')
|
|
77
78
|
.version(packageJson.version)
|
|
78
|
-
.helpOption(
|
|
79
|
+
.helpOption('-h, --help', 'Show help');
|
|
79
80
|
program
|
|
80
81
|
.option('-p, --print <prompt>', 'Execute a prompt and exit (non-interactive mode)')
|
|
81
82
|
.option('--dangerously-skip-permissions', 'Skip all permission prompts (auto-approve)')
|
|
@@ -96,6 +97,7 @@ program
|
|
|
96
97
|
.option('--init', 'Enable the Claude Code hook in this directory (reuses your login; or pass --token)')
|
|
97
98
|
.option('--disable-hook', 'Disable the Claude Code hook in this directory')
|
|
98
99
|
.option('--update', 'Update orquesta-cli to the latest published version and exit')
|
|
100
|
+
.option('-c, --continue', 'Resume the most recent conversation session')
|
|
99
101
|
.action(async (options) => {
|
|
100
102
|
if (options.appendSystemPrompt) {
|
|
101
103
|
setAppendedSystemPrompt(options.appendSystemPrompt);
|
|
@@ -118,6 +120,9 @@ program
|
|
|
118
120
|
return;
|
|
119
121
|
}
|
|
120
122
|
await configManager.initialize();
|
|
123
|
+
if (shouldShowOnboarding()) {
|
|
124
|
+
await runOnboarding();
|
|
125
|
+
}
|
|
121
126
|
if (options.status) {
|
|
122
127
|
showConnectionStatus();
|
|
123
128
|
return;
|
|
@@ -273,24 +278,19 @@ program
|
|
|
273
278
|
nodeVersion: process.version,
|
|
274
279
|
});
|
|
275
280
|
logger.flow('Config manager already initialized');
|
|
276
|
-
spinner.text = chalk.cyan('Loading
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
logger.flow('Auto-syncing with Orquesta');
|
|
283
|
-
try {
|
|
284
|
-
const syncResult = await syncOrquestaConfigs();
|
|
281
|
+
spinner.text = chalk.cyan('Loading...');
|
|
282
|
+
const toolsPromise = initializeOptionalTools().then(() => {
|
|
283
|
+
logger.flow('Optional tools initialized');
|
|
284
|
+
});
|
|
285
|
+
const syncPromise = (configManager.hasOrquestaConnection() && configManager.shouldAutoSync())
|
|
286
|
+
? syncOrquestaConfigs().then(syncResult => {
|
|
285
287
|
if (syncResult.success && (syncResult.added > 0 || syncResult.updated > 0)) {
|
|
286
288
|
logger.flow('Orquesta sync complete', { added: syncResult.added, updated: syncResult.updated });
|
|
287
289
|
}
|
|
288
|
-
}
|
|
289
|
-
catch (error) {
|
|
290
|
+
}).catch(error => {
|
|
290
291
|
logger.warn('Orquesta sync failed', { error: error instanceof Error ? error.message : String(error) });
|
|
291
|
-
}
|
|
292
|
-
|
|
293
|
-
spinner.text = chalk.cyan('Connecting to LLM...');
|
|
292
|
+
})
|
|
293
|
+
: Promise.resolve();
|
|
294
294
|
let llmClient = null;
|
|
295
295
|
let modelInfo = { model: 'Not configured', endpoint: 'Not configured' };
|
|
296
296
|
if (configManager.hasEndpoints()) {
|
|
@@ -307,13 +307,14 @@ program
|
|
|
307
307
|
else {
|
|
308
308
|
logger.flow('No LLM endpoints configured');
|
|
309
309
|
}
|
|
310
|
+
await Promise.all([toolsPromise, syncPromise]);
|
|
310
311
|
spinner.stop();
|
|
311
312
|
process.stdout.write('\x1B[2J\x1B[0f');
|
|
312
313
|
if (options.verbose || options.debug) {
|
|
313
314
|
console.log(chalk.cyan('Starting Orquesta CLI...\n'));
|
|
314
315
|
}
|
|
315
316
|
try {
|
|
316
|
-
const { waitUntilExit } = render(React.createElement(PlanExecuteApp, { llmClient, modelInfo }), { exitOnCtrlC: false });
|
|
317
|
+
const { waitUntilExit } = render(React.createElement(PlanExecuteApp, { llmClient, modelInfo, resumeLastSession: !!options.continue }), { exitOnCtrlC: false });
|
|
317
318
|
await waitUntilExit();
|
|
318
319
|
}
|
|
319
320
|
catch (error) {
|
package/dist/constants.d.ts
CHANGED
|
@@ -5,5 +5,5 @@ export declare const DOCS_DIR: string;
|
|
|
5
5
|
export declare const BACKUPS_DIR: string;
|
|
6
6
|
export declare const PROJECTS_DIR: string;
|
|
7
7
|
export declare function cwdToProjectSegment(cwd?: string): string;
|
|
8
|
-
export declare const APP_VERSION = "
|
|
8
|
+
export declare const APP_VERSION = "0.2.45";
|
|
9
9
|
//# sourceMappingURL=constants.d.ts.map
|
package/dist/constants.js
CHANGED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { logger } from '../../utils/logger.js';
|
|
2
|
+
import { resetBatutaSession } from '../routing-state.js';
|
|
3
|
+
export const clearCommand = {
|
|
4
|
+
name: '/clear',
|
|
5
|
+
description: 'Clear conversation and TODOs',
|
|
6
|
+
async execute(context, _rawInput) {
|
|
7
|
+
logger.flow('Clear command - resetting messages and todos');
|
|
8
|
+
context.setMessages([]);
|
|
9
|
+
context.setTodos([]);
|
|
10
|
+
resetBatutaSession();
|
|
11
|
+
logger.exit('executeSlashCommand', { handled: true, command: 'clear' });
|
|
12
|
+
return {
|
|
13
|
+
handled: true,
|
|
14
|
+
shouldContinue: false,
|
|
15
|
+
updatedContext: {
|
|
16
|
+
messages: [],
|
|
17
|
+
todos: [],
|
|
18
|
+
},
|
|
19
|
+
};
|
|
20
|
+
},
|
|
21
|
+
};
|
|
22
|
+
//# sourceMappingURL=clear.js.map
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { logger } from '../../utils/logger.js';
|
|
2
|
+
export const compactCommand = {
|
|
3
|
+
name: '/compact',
|
|
4
|
+
description: 'Compact conversation to free up context',
|
|
5
|
+
async execute(context, _rawInput) {
|
|
6
|
+
logger.flow('Compact command received');
|
|
7
|
+
if (context.onCompact) {
|
|
8
|
+
logger.flow('Executing compact callback');
|
|
9
|
+
const result = await context.onCompact();
|
|
10
|
+
logger.vars({ name: 'compactSuccess', value: result.success }, { name: 'originalCount', value: result.originalMessageCount }, { name: 'newCount', value: result.newMessageCount });
|
|
11
|
+
const compactMessage = result.success
|
|
12
|
+
? `✅ Conversation compacted successfully. (${result.originalMessageCount} → ${result.newMessageCount} messages)`
|
|
13
|
+
: `❌ Compact failed: ${result.error}`;
|
|
14
|
+
const baseMessages = (result.success && result.compactedMessages)
|
|
15
|
+
? result.compactedMessages
|
|
16
|
+
: context.messages;
|
|
17
|
+
const updatedMessages = [
|
|
18
|
+
...baseMessages,
|
|
19
|
+
{ role: 'assistant', content: compactMessage },
|
|
20
|
+
];
|
|
21
|
+
context.setMessages(updatedMessages);
|
|
22
|
+
return {
|
|
23
|
+
handled: true,
|
|
24
|
+
shouldContinue: false,
|
|
25
|
+
updatedContext: {
|
|
26
|
+
messages: updatedMessages,
|
|
27
|
+
},
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
const fallbackMessage = '/compact is only available in interactive mode.';
|
|
31
|
+
const updatedMessages = [
|
|
32
|
+
...context.messages,
|
|
33
|
+
{ role: 'assistant', content: fallbackMessage },
|
|
34
|
+
];
|
|
35
|
+
context.setMessages(updatedMessages);
|
|
36
|
+
return {
|
|
37
|
+
handled: true,
|
|
38
|
+
shouldContinue: false,
|
|
39
|
+
updatedContext: {
|
|
40
|
+
messages: updatedMessages,
|
|
41
|
+
},
|
|
42
|
+
};
|
|
43
|
+
},
|
|
44
|
+
};
|
|
45
|
+
//# sourceMappingURL=compact.js.map
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
export const helpCommand = {
|
|
2
|
+
name: '/help',
|
|
3
|
+
description: 'Show available commands',
|
|
4
|
+
async execute(context, _rawInput) {
|
|
5
|
+
const helpMessage = `
|
|
6
|
+
Available commands:
|
|
7
|
+
/exit, /quit - Exit the application
|
|
8
|
+
/clear - Clear conversation and TODOs
|
|
9
|
+
/compact - Compact conversation to free up context
|
|
10
|
+
/memory - Persistent memory: /memory add <note> | list | remove <n> | clear
|
|
11
|
+
/settings - Open settings menu
|
|
12
|
+
/model - Switch between LLM models
|
|
13
|
+
/project - Switch between Orquesta projects
|
|
14
|
+
/tool - Enable/disable optional tools (Browser, Background)
|
|
15
|
+
/load - Load a saved session
|
|
16
|
+
/usage - Show token usage statistics
|
|
17
|
+
/cost - Estimated USD spend this process (by model)
|
|
18
|
+
/route - Pin Batuta Auto tier (fast/balanced/premium/auto)
|
|
19
|
+
/sync - Bidirectional sync with Orquesta dashboard (pull & push LLM configs)
|
|
20
|
+
/login - Sign in to Orquesta via browser (opens getorquesta.com)
|
|
21
|
+
/logout - Sign out of Orquesta (clears token, keeps local LLM configs)
|
|
22
|
+
/whoami - Show current Orquesta connection
|
|
23
|
+
/hook - Claude Code hook here: /hook status | enable | disable
|
|
24
|
+
/remote-phone - Drive this session from your phone: on | off | status
|
|
25
|
+
/update - Update orquesta-cli to the latest version
|
|
26
|
+
|
|
27
|
+
Keyboard shortcuts:
|
|
28
|
+
Ctrl+C - Exit
|
|
29
|
+
Ctrl+T - Toggle TODO details
|
|
30
|
+
ESC - Interrupt current execution
|
|
31
|
+
@ - File browser
|
|
32
|
+
/ - Command autocomplete
|
|
33
|
+
|
|
34
|
+
Note: All conversations are automatically saved.
|
|
35
|
+
`;
|
|
36
|
+
const updatedMessages = [
|
|
37
|
+
...context.messages,
|
|
38
|
+
{ role: 'assistant', content: helpMessage },
|
|
39
|
+
];
|
|
40
|
+
context.setMessages(updatedMessages);
|
|
41
|
+
return {
|
|
42
|
+
handled: true,
|
|
43
|
+
shouldContinue: false,
|
|
44
|
+
updatedContext: {
|
|
45
|
+
messages: updatedMessages,
|
|
46
|
+
},
|
|
47
|
+
};
|
|
48
|
+
},
|
|
49
|
+
};
|
|
50
|
+
//# sourceMappingURL=help.js.map
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { commandRegistry } from './registry.js';
|
|
2
|
+
import { clearCommand } from './clear.js';
|
|
3
|
+
import { compactCommand } from './compact.js';
|
|
4
|
+
import { memoryCommand } from './memory.js';
|
|
5
|
+
import { helpCommand } from './help.js';
|
|
6
|
+
commandRegistry.register(clearCommand);
|
|
7
|
+
commandRegistry.register(compactCommand);
|
|
8
|
+
commandRegistry.register(memoryCommand);
|
|
9
|
+
commandRegistry.register(helpCommand);
|
|
10
|
+
export { commandRegistry } from './registry.js';
|
|
11
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { addMemory, removeMemory, clearMemory, listMemory } from '../memory.js';
|
|
2
|
+
export const memoryCommand = {
|
|
3
|
+
name: '/memory',
|
|
4
|
+
description: 'Persistent memory: /memory add <note> | list | remove <n> | clear',
|
|
5
|
+
async execute(context, rawInput) {
|
|
6
|
+
const sub = rawInput.slice('/memory'.length).trim();
|
|
7
|
+
const reply = (content) => {
|
|
8
|
+
const updatedMessages = [...context.messages, { role: 'assistant', content }];
|
|
9
|
+
context.setMessages(updatedMessages);
|
|
10
|
+
return { handled: true, shouldContinue: false, updatedContext: { messages: updatedMessages } };
|
|
11
|
+
};
|
|
12
|
+
if (sub.startsWith('add ')) {
|
|
13
|
+
const note = sub.slice(4).trim();
|
|
14
|
+
if (!note)
|
|
15
|
+
return reply('Usage: /memory add <note>');
|
|
16
|
+
addMemory(note);
|
|
17
|
+
return reply(`✓ Saved to memory: "${note}"`);
|
|
18
|
+
}
|
|
19
|
+
if (sub === 'list' || sub === '') {
|
|
20
|
+
const entries = listMemory();
|
|
21
|
+
if (entries.length === 0)
|
|
22
|
+
return reply('Memory is empty. Use `/memory add <note>` to save preferences.');
|
|
23
|
+
const list = entries.map((e, i) => ` ${i + 1}. ${e}`).join('\n');
|
|
24
|
+
return reply(`📝 User memory (${entries.length} entries):\n${list}\n\nCommands: /memory add <note> | remove <n> | clear`);
|
|
25
|
+
}
|
|
26
|
+
if (sub.startsWith('remove ')) {
|
|
27
|
+
const idx = parseInt(sub.slice(7).trim(), 10);
|
|
28
|
+
if (isNaN(idx))
|
|
29
|
+
return reply('Usage: /memory remove <number>');
|
|
30
|
+
const ok = removeMemory(idx);
|
|
31
|
+
return reply(ok ? `✓ Removed entry #${idx}` : `Entry #${idx} not found`);
|
|
32
|
+
}
|
|
33
|
+
if (sub === 'clear') {
|
|
34
|
+
clearMemory();
|
|
35
|
+
return reply('✓ Memory cleared');
|
|
36
|
+
}
|
|
37
|
+
return reply('Usage: /memory add <note> | list | remove <n> | clear');
|
|
38
|
+
},
|
|
39
|
+
};
|
|
40
|
+
//# sourceMappingURL=memory.js.map
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { SlashCommand, CommandContext, CommandResult } from './types.js';
|
|
2
|
+
declare class CommandRegistry {
|
|
3
|
+
private commands;
|
|
4
|
+
register(command: SlashCommand): void;
|
|
5
|
+
get(name: string): SlashCommand | undefined;
|
|
6
|
+
execute(commandName: string, context: CommandContext, rawInput: string): Promise<CommandResult | null>;
|
|
7
|
+
getAll(): SlashCommand[];
|
|
8
|
+
}
|
|
9
|
+
export declare const commandRegistry: CommandRegistry;
|
|
10
|
+
export {};
|
|
11
|
+
//# sourceMappingURL=registry.d.ts.map
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
class CommandRegistry {
|
|
2
|
+
commands = new Map();
|
|
3
|
+
register(command) {
|
|
4
|
+
this.commands.set(command.name, command);
|
|
5
|
+
if (command.aliases) {
|
|
6
|
+
for (const alias of command.aliases) {
|
|
7
|
+
this.commands.set(alias, command);
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
get(name) {
|
|
12
|
+
return this.commands.get(name);
|
|
13
|
+
}
|
|
14
|
+
async execute(commandName, context, rawInput) {
|
|
15
|
+
const command = this.commands.get(commandName);
|
|
16
|
+
if (!command)
|
|
17
|
+
return null;
|
|
18
|
+
return command.execute(context, rawInput);
|
|
19
|
+
}
|
|
20
|
+
getAll() {
|
|
21
|
+
return [...new Set(this.commands.values())];
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
export const commandRegistry = new CommandRegistry();
|
|
25
|
+
//# sourceMappingURL=registry.js.map
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { CommandHandlerContext, CommandExecutionResult } from '../slash-command-handler.js';
|
|
2
|
+
export type CommandContext = CommandHandlerContext;
|
|
3
|
+
export type CommandResult = CommandExecutionResult;
|
|
4
|
+
export interface SlashCommand {
|
|
5
|
+
name: string;
|
|
6
|
+
aliases?: string[];
|
|
7
|
+
description: string;
|
|
8
|
+
execute(context: CommandContext, rawInput: string): Promise<CommandResult>;
|
|
9
|
+
}
|
|
10
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
type EventHandler<T = unknown> = (data: T) => void;
|
|
2
|
+
declare class EventBus {
|
|
3
|
+
private handlers;
|
|
4
|
+
on<T>(event: string, handler: EventHandler<T>): () => void;
|
|
5
|
+
emit<T>(event: string, data: T): void;
|
|
6
|
+
off(event: string, handler: EventHandler): void;
|
|
7
|
+
clear(): void;
|
|
8
|
+
}
|
|
9
|
+
export declare const eventBus: EventBus;
|
|
10
|
+
export declare const Events: {
|
|
11
|
+
readonly TOOL_START: "tool:start";
|
|
12
|
+
readonly TOOL_RESULT: "tool:result";
|
|
13
|
+
readonly TODO_UPDATE: "todo:update";
|
|
14
|
+
readonly STREAMING_TOKEN: "streaming:token";
|
|
15
|
+
readonly MODEL_CHANGED: "model:changed";
|
|
16
|
+
readonly SESSION_SAVED: "session:saved";
|
|
17
|
+
readonly FINAL_RESPONSE: "final:response";
|
|
18
|
+
};
|
|
19
|
+
export {};
|
|
20
|
+
//# sourceMappingURL=event-bus.d.ts.map
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
class EventBus {
|
|
2
|
+
handlers = new Map();
|
|
3
|
+
on(event, handler) {
|
|
4
|
+
if (!this.handlers.has(event)) {
|
|
5
|
+
this.handlers.set(event, new Set());
|
|
6
|
+
}
|
|
7
|
+
this.handlers.get(event).add(handler);
|
|
8
|
+
return () => this.off(event, handler);
|
|
9
|
+
}
|
|
10
|
+
emit(event, data) {
|
|
11
|
+
const handlers = this.handlers.get(event);
|
|
12
|
+
if (handlers) {
|
|
13
|
+
for (const handler of handlers) {
|
|
14
|
+
handler(data);
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
off(event, handler) {
|
|
19
|
+
this.handlers.get(event)?.delete(handler);
|
|
20
|
+
}
|
|
21
|
+
clear() {
|
|
22
|
+
this.handlers.clear();
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
export const eventBus = new EventBus();
|
|
26
|
+
export const Events = {
|
|
27
|
+
TOOL_START: 'tool:start',
|
|
28
|
+
TOOL_RESULT: 'tool:result',
|
|
29
|
+
TODO_UPDATE: 'todo:update',
|
|
30
|
+
STREAMING_TOKEN: 'streaming:token',
|
|
31
|
+
MODEL_CHANGED: 'model:changed',
|
|
32
|
+
SESSION_SAVED: 'session:saved',
|
|
33
|
+
FINAL_RESPONSE: 'final:response',
|
|
34
|
+
};
|
|
35
|
+
//# sourceMappingURL=event-bus.js.map
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
interface GitContext {
|
|
2
|
+
branch: string;
|
|
3
|
+
staged: string[];
|
|
4
|
+
unstaged: string[];
|
|
5
|
+
untracked: string[];
|
|
6
|
+
diffSummary: string;
|
|
7
|
+
}
|
|
8
|
+
export declare function getGitContext(): GitContext | null;
|
|
9
|
+
export declare function getGitContextPrompt(): string;
|
|
10
|
+
export {};
|
|
11
|
+
//# sourceMappingURL=git-context.d.ts.map
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { execSync } from 'child_process';
|
|
2
|
+
import { detectGitRepo } from '../utils/git-utils.js';
|
|
3
|
+
const MAX_DIFF_CHARS = 8000;
|
|
4
|
+
function run(cmd) {
|
|
5
|
+
try {
|
|
6
|
+
return execSync(cmd, { encoding: 'utf-8', timeout: 5000, stdio: ['pipe', 'pipe', 'pipe'] }).trim();
|
|
7
|
+
}
|
|
8
|
+
catch {
|
|
9
|
+
return '';
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
export function getGitContext() {
|
|
13
|
+
if (!detectGitRepo())
|
|
14
|
+
return null;
|
|
15
|
+
const branch = run('git branch --show-current') || 'HEAD';
|
|
16
|
+
const statusOutput = run('git status --porcelain');
|
|
17
|
+
if (!statusOutput)
|
|
18
|
+
return { branch, staged: [], unstaged: [], untracked: [], diffSummary: '' };
|
|
19
|
+
const staged = [];
|
|
20
|
+
const unstaged = [];
|
|
21
|
+
const untracked = [];
|
|
22
|
+
for (const line of statusOutput.split('\n')) {
|
|
23
|
+
if (!line)
|
|
24
|
+
continue;
|
|
25
|
+
const x = line[0], y = line[1];
|
|
26
|
+
const file = line.slice(3);
|
|
27
|
+
if (x === '?') {
|
|
28
|
+
untracked.push(file);
|
|
29
|
+
continue;
|
|
30
|
+
}
|
|
31
|
+
if (x !== ' ' && x !== '?')
|
|
32
|
+
staged.push(file);
|
|
33
|
+
if (y !== ' ' && y !== '?')
|
|
34
|
+
unstaged.push(file);
|
|
35
|
+
}
|
|
36
|
+
let diffSummary = run('git diff --stat HEAD 2>/dev/null');
|
|
37
|
+
if (diffSummary.length > MAX_DIFF_CHARS) {
|
|
38
|
+
diffSummary = diffSummary.slice(0, MAX_DIFF_CHARS) + '\n[...truncated]';
|
|
39
|
+
}
|
|
40
|
+
return { branch, staged, unstaged, untracked, diffSummary };
|
|
41
|
+
}
|
|
42
|
+
export function getGitContextPrompt() {
|
|
43
|
+
const ctx = getGitContext();
|
|
44
|
+
if (!ctx)
|
|
45
|
+
return '';
|
|
46
|
+
const totalChanged = ctx.staged.length + ctx.unstaged.length + ctx.untracked.length;
|
|
47
|
+
if (totalChanged === 0)
|
|
48
|
+
return '';
|
|
49
|
+
const parts = ['\n\n<git_context>', `Branch: ${ctx.branch}`];
|
|
50
|
+
if (ctx.staged.length > 0) {
|
|
51
|
+
parts.push(`Staged (${ctx.staged.length}): ${ctx.staged.slice(0, 15).join(', ')}${ctx.staged.length > 15 ? '...' : ''}`);
|
|
52
|
+
}
|
|
53
|
+
if (ctx.unstaged.length > 0) {
|
|
54
|
+
parts.push(`Modified (${ctx.unstaged.length}): ${ctx.unstaged.slice(0, 15).join(', ')}${ctx.unstaged.length > 15 ? '...' : ''}`);
|
|
55
|
+
}
|
|
56
|
+
if (ctx.untracked.length > 0) {
|
|
57
|
+
parts.push(`Untracked (${ctx.untracked.length}): ${ctx.untracked.slice(0, 10).join(', ')}${ctx.untracked.length > 10 ? '...' : ''}`);
|
|
58
|
+
}
|
|
59
|
+
parts.push('</git_context>');
|
|
60
|
+
return parts.join('\n');
|
|
61
|
+
}
|
|
62
|
+
//# sourceMappingURL=git-context.js.map
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import * as fs from 'fs';
|
|
2
|
+
import * as path from 'path';
|
|
3
|
+
import { minimatch } from 'minimatch';
|
|
4
|
+
let patterns = null;
|
|
5
|
+
function loadPatterns() {
|
|
6
|
+
if (patterns !== null)
|
|
7
|
+
return patterns;
|
|
8
|
+
const cwd = process.cwd();
|
|
9
|
+
const orquestaIgnore = path.join(cwd, '.orquestaignore');
|
|
10
|
+
const gitIgnore = path.join(cwd, '.gitignore');
|
|
11
|
+
let content = '';
|
|
12
|
+
try {
|
|
13
|
+
content = fs.readFileSync(orquestaIgnore, 'utf-8');
|
|
14
|
+
}
|
|
15
|
+
catch {
|
|
16
|
+
try {
|
|
17
|
+
content = fs.readFileSync(gitIgnore, 'utf-8');
|
|
18
|
+
}
|
|
19
|
+
catch {
|
|
20
|
+
patterns = [];
|
|
21
|
+
return patterns;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
patterns = content
|
|
25
|
+
.split('\n')
|
|
26
|
+
.map(line => line.trim())
|
|
27
|
+
.filter(line => line.length > 0 && !line.startsWith('#'));
|
|
28
|
+
return patterns;
|
|
29
|
+
}
|
|
30
|
+
export function getIgnorePatterns() {
|
|
31
|
+
return loadPatterns();
|
|
32
|
+
}
|
|
33
|
+
export function shouldIgnore(filePath) {
|
|
34
|
+
const pats = loadPatterns();
|
|
35
|
+
const rel = path.relative(process.cwd(), path.resolve(filePath)).replace(/\\/g, '/');
|
|
36
|
+
for (const pat of pats) {
|
|
37
|
+
if (minimatch(rel, pat, { dot: true }) || minimatch(rel, `${pat}/**`, { dot: true })) {
|
|
38
|
+
return true;
|
|
39
|
+
}
|
|
40
|
+
const basename = path.basename(rel);
|
|
41
|
+
if (!pat.includes('/') && minimatch(basename, pat, { dot: true })) {
|
|
42
|
+
return true;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
return false;
|
|
46
|
+
}
|
|
47
|
+
export function resetIgnoreCache() {
|
|
48
|
+
patterns = null;
|
|
49
|
+
}
|
|
50
|
+
//# sourceMappingURL=ignore-filter.js.map
|
|
@@ -45,6 +45,7 @@ export declare class LLMClient {
|
|
|
45
45
|
private modelName;
|
|
46
46
|
private currentAbortController;
|
|
47
47
|
private isInterrupted;
|
|
48
|
+
onStreamingContent: ((token: string) => void) | null;
|
|
48
49
|
private static readonly DEFAULT_MAX_RETRIES;
|
|
49
50
|
constructor();
|
|
50
51
|
private preprocessMessages;
|