orquesta-cli 0.2.43 → 0.2.45

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.
@@ -2,6 +2,7 @@ import { logger } from '../../utils/logger.js';
2
2
  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
+ import { getMemoryPrompt } from '../../core/memory.js';
5
6
  export class PlanningLLM {
6
7
  llmClient;
7
8
  askUserCallback = null;
@@ -22,7 +23,7 @@ export class PlanningLLM {
22
23
  const toolSummary = toolRegistry.getToolSummaryForPlanning();
23
24
  const optionalToolsInfo = toolRegistry.getEnabledOptionalToolsInfo();
24
25
  const projectContext = getProjectContext();
25
- const systemPrompt = buildPlanningSystemPrompt(toolSummary, optionalToolsInfo) + projectContext;
26
+ const systemPrompt = buildPlanningSystemPrompt(toolSummary, optionalToolsInfo) + projectContext + getMemoryPrompt();
26
27
  const clarificationMessages = [];
27
28
  const messages = [
28
29
  {
@@ -0,0 +1,7 @@
1
+ export declare function getUserMemory(): string;
2
+ export declare function getMemoryPrompt(): string;
3
+ export declare function addMemory(entry: string): void;
4
+ export declare function removeMemory(index: number): boolean;
5
+ export declare function clearMemory(): void;
6
+ export declare function listMemory(): string[];
7
+ //# sourceMappingURL=memory.d.ts.map
@@ -0,0 +1,55 @@
1
+ import * as fs from 'fs';
2
+ import * as path from 'path';
3
+ import { LOCAL_HOME_DIR } from '../constants.js';
4
+ const MEMORY_PATH = path.join(LOCAL_HOME_DIR, 'memory.md');
5
+ let cache = null;
6
+ export function getUserMemory() {
7
+ if (cache !== null)
8
+ return cache;
9
+ try {
10
+ cache = fs.readFileSync(MEMORY_PATH, 'utf-8').trim();
11
+ }
12
+ catch {
13
+ cache = '';
14
+ }
15
+ return cache;
16
+ }
17
+ export function getMemoryPrompt() {
18
+ const memory = getUserMemory();
19
+ if (!memory)
20
+ return '';
21
+ return `\n\n<user_memory>\nThe user has saved these persistent preferences and notes:\n${memory}\n</user_memory>\n`;
22
+ }
23
+ export function addMemory(entry) {
24
+ const current = getUserMemory();
25
+ const timestamp = new Date().toISOString().slice(0, 10);
26
+ const newContent = current ? `${current}\n- ${entry} (${timestamp})` : `- ${entry} (${timestamp})`;
27
+ fs.mkdirSync(path.dirname(MEMORY_PATH), { recursive: true });
28
+ fs.writeFileSync(MEMORY_PATH, newContent, 'utf-8');
29
+ cache = newContent;
30
+ }
31
+ export function removeMemory(index) {
32
+ const current = getUserMemory();
33
+ const lines = current.split('\n').filter(l => l.trim());
34
+ if (index < 1 || index > lines.length)
35
+ return false;
36
+ lines.splice(index - 1, 1);
37
+ const newContent = lines.join('\n');
38
+ fs.writeFileSync(MEMORY_PATH, newContent, 'utf-8');
39
+ cache = newContent;
40
+ return true;
41
+ }
42
+ export function clearMemory() {
43
+ try {
44
+ fs.unlinkSync(MEMORY_PATH);
45
+ }
46
+ catch { }
47
+ cache = '';
48
+ }
49
+ export function listMemory() {
50
+ const current = getUserMemory();
51
+ if (!current)
52
+ return [];
53
+ return current.split('\n').filter(l => l.trim());
54
+ }
55
+ //# sourceMappingURL=memory.js.map
@@ -524,6 +524,41 @@ ${executorLines}
524
524
  context.setMessages(updatedMessages);
525
525
  return { handled: true, shouldContinue: false, updatedContext: { messages: updatedMessages } };
526
526
  }
527
+ if (trimmedCommand.startsWith('/memory')) {
528
+ const sub = trimmedCommand.slice(7).trim();
529
+ const { addMemory, removeMemory, clearMemory, listMemory } = await import('./memory.js');
530
+ const reply = (content) => {
531
+ const updatedMessages = [...context.messages, { role: 'assistant', content }];
532
+ context.setMessages(updatedMessages);
533
+ return { handled: true, shouldContinue: false, updatedContext: { messages: updatedMessages } };
534
+ };
535
+ if (sub.startsWith('add ')) {
536
+ const note = sub.slice(4).trim();
537
+ if (!note)
538
+ return reply('Usage: /memory add <note>');
539
+ addMemory(note);
540
+ return reply(`✓ Saved to memory: "${note}"`);
541
+ }
542
+ if (sub === 'list' || sub === '') {
543
+ const entries = listMemory();
544
+ if (entries.length === 0)
545
+ return reply('Memory is empty. Use `/memory add <note>` to save preferences.');
546
+ const list = entries.map((e, i) => ` ${i + 1}. ${e}`).join('\n');
547
+ return reply(`📝 User memory (${entries.length} entries):\n${list}\n\nCommands: /memory add <note> | remove <n> | clear`);
548
+ }
549
+ if (sub.startsWith('remove ')) {
550
+ const idx = parseInt(sub.slice(7).trim(), 10);
551
+ if (isNaN(idx))
552
+ return reply('Usage: /memory remove <number>');
553
+ const ok = removeMemory(idx);
554
+ return reply(ok ? `✓ Removed entry #${idx}` : `Entry #${idx} not found`);
555
+ }
556
+ if (sub === 'clear') {
557
+ clearMemory();
558
+ return reply('✓ Memory cleared');
559
+ }
560
+ return reply('Usage: /memory add <note> | list | remove <n> | clear');
561
+ }
527
562
  if (trimmedCommand === '/update') {
528
563
  logger.flow('Update command received');
529
564
  const reply = (content) => {
@@ -632,6 +667,7 @@ Available commands:
632
667
  /exit, /quit - Exit the application
633
668
  /clear - Clear conversation and TODOs
634
669
  /compact - Compact conversation to free up context
670
+ /memory - Persistent memory: /memory add <note> | list | remove <n> | clear
635
671
  /settings - Open settings menu
636
672
  /model - Switch between LLM models
637
673
  /project - Switch between Orquesta projects
@@ -9,6 +9,7 @@ import { emitPlanCreated, emitTodoStart, emitTodoComplete, emitTodoFail, emitCom
9
9
  import { toolRegistry } from '../tools/registry.js';
10
10
  import { PLAN_EXECUTE_SYSTEM_PROMPT as PLAN_PROMPT } from '../prompts/system/plan-execute.js';
11
11
  import { getProjectContext } from '../core/project-context.js';
12
+ import { getMemoryPrompt } from '../core/memory.js';
12
13
  import { GIT_COMMIT_RULES } from '../prompts/shared/git-rules.js';
13
14
  import { logger } from '../utils/logger.js';
14
15
  import { getStreamLogger } from '../utils/json-stream-logger.js';
@@ -33,7 +34,7 @@ function buildSystemPrompt() {
33
34
  const projectContext = getProjectContext();
34
35
  const base = isGitRepo ? `${PLAN_PROMPT}\n\n${GIT_COMMIT_RULES}` : PLAN_PROMPT;
35
36
  const appended = appendedSystemPrompt ? `\n\n${appendedSystemPrompt}` : '';
36
- return base + buildEnvironmentContext() + projectContext + appended;
37
+ return base + buildEnvironmentContext() + projectContext + getMemoryPrompt() + appended;
37
38
  }
38
39
  export class PlanExecutor {
39
40
  currentLLMClient = null;
@@ -25,12 +25,33 @@ export function insertFilePaths(input, atPosition, filterLength, filePaths) {
25
25
  }
26
26
  }
27
27
  export function extractFileReferences(input) {
28
- const regex = /@([^\s@]+)/g;
29
28
  const matches = [];
29
+ const seen = new Set();
30
+ const atRegex = /@([^\s@]+)/g;
30
31
  let match;
31
- while ((match = regex.exec(input)) !== null) {
32
+ while ((match = atRegex.exec(input)) !== null) {
32
33
  const filePath = match[1];
33
34
  if (filePath && filePath.length > 1 && (filePath.includes('/') || filePath.includes('.'))) {
35
+ if (!seen.has(filePath)) {
36
+ seen.add(filePath);
37
+ matches.push(filePath);
38
+ }
39
+ }
40
+ }
41
+ const KNOWN_EXTS = /\.(png|jpg|jpeg|gif|webp|bmp|pdf|csv|tsv|json|yaml|yml|xml|txt|md|ts|tsx|js|jsx|py|go|rs|java|kt|swift|sql|sh|toml|html|css|svg)$/i;
42
+ const quotedRegex = /['"]([^'"]+\.[a-z]{2,5})['"]/gi;
43
+ while ((match = quotedRegex.exec(input)) !== null) {
44
+ const filePath = match[1];
45
+ if (filePath && KNOWN_EXTS.test(filePath) && !seen.has(filePath)) {
46
+ seen.add(filePath);
47
+ matches.push(filePath);
48
+ }
49
+ }
50
+ const absRegex = /(?:^|\s)(\/[^\s'"]+\.[a-z]{2,5})(?:\s|$)/gi;
51
+ while ((match = absRegex.exec(input)) !== null) {
52
+ const filePath = match[1];
53
+ if (filePath && KNOWN_EXTS.test(filePath) && !seen.has(filePath)) {
54
+ seen.add(filePath);
34
55
  matches.push(filePath);
35
56
  }
36
57
  }
@@ -57,7 +78,7 @@ export async function processFileReferences(input) {
57
78
  for (const filePath of fileRefs) {
58
79
  try {
59
80
  const resolvedPath = path.resolve(process.cwd(), filePath);
60
- if (!resolvedPath.startsWith(process.cwd())) {
81
+ if (filePath.includes('..') && !resolvedPath.startsWith(process.cwd())) {
61
82
  failedFiles.push(filePath);
62
83
  continue;
63
84
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "orquesta-cli",
3
- "version": "0.2.43",
3
+ "version": "0.2.45",
4
4
  "description": "Orquesta CLI - AI-powered coding assistant with team collaboration",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",