orquesta-cli 0.2.93 → 0.2.94

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 CHANGED
@@ -152,9 +152,9 @@ program
152
152
  if (options.appendSystemPrompt) {
153
153
  setAppendedSystemPrompt(options.appendSystemPrompt);
154
154
  }
155
+ await configManager.initialize();
156
+ await ensureBatutaFromEnv();
155
157
  if (options.endpoint) {
156
- await configManager.initialize();
157
- await ensureBatutaFromEnv();
158
158
  const wanted = String(options.endpoint).toLowerCase();
159
159
  const all = configManager.getAllEndpoints();
160
160
  const ep = wanted === 'batuta'
@@ -188,8 +188,6 @@ program
188
188
  disableHooks();
189
189
  return;
190
190
  }
191
- await configManager.initialize();
192
- await ensureBatutaFromEnv();
193
191
  if (shouldShowOnboarding()) {
194
192
  await runOnboarding();
195
193
  }
@@ -424,9 +424,10 @@ export class LLMClient {
424
424
  currentAttempt: currentAttempt + 1,
425
425
  });
426
426
  }
427
- if (!this.triedBatutaFallback && this.isConnectionError(error) && this.switchToBatutaProxy()) {
427
+ const upstream5xx = axios.isAxiosError(error) && (error.response?.status ?? 0) >= 500;
428
+ if (!this.triedBatutaFallback && (this.isConnectionError(error) || upstream5xx) && this.switchToBatutaProxy()) {
428
429
  this.triedBatutaFallback = true;
429
- logger.flow('Primary endpoint unreachable — falling back to Batuta');
430
+ logger.flow('Primary endpoint failed — falling back to Batuta');
430
431
  return this.chatCompletion(options, { maxRetries, currentAttempt: 1 });
431
432
  }
432
433
  logger.flow('API call failed - Error handling');
@@ -15,6 +15,7 @@ declare class AuditLogger {
15
15
  startRun(sessionId: string, data?: Record<string, unknown>): string;
16
16
  emit(sessionId: string, kind: AuditEventKind, data?: Record<string, unknown>): void;
17
17
  private write;
18
+ private rotateIfNeeded;
18
19
  tail(n?: number): Promise<AuditEvent[]>;
19
20
  stats(opts?: {
20
21
  sinceDays?: number;
@@ -31,12 +31,24 @@ class AuditLogger {
31
31
  await fs.mkdir(LOCAL_HOME_DIR, { recursive: true });
32
32
  this.initialized = true;
33
33
  }
34
+ await this.rotateIfNeeded();
34
35
  await fs.appendFile(AUDIT_LOG_PATH, JSON.stringify(event) + '\n', 'utf8');
35
36
  }
36
37
  catch (error) {
37
38
  logger.warn('Audit log write failed', { error: error.message });
38
39
  }
39
40
  }
41
+ async rotateIfNeeded() {
42
+ try {
43
+ const max = Number(process.env['ORQUESTA_AUDIT_MAX_BYTES']) || 10 * 1024 * 1024;
44
+ const { size } = await fs.stat(AUDIT_LOG_PATH);
45
+ if (size < max)
46
+ return;
47
+ await fs.rename(AUDIT_LOG_PATH, `${AUDIT_LOG_PATH}.1`).catch(() => undefined);
48
+ }
49
+ catch {
50
+ }
51
+ }
40
52
  async tail(n = 50) {
41
53
  try {
42
54
  const raw = await fs.readFile(AUDIT_LOG_PATH, 'utf8');
@@ -53,10 +53,11 @@ Use this ONLY for pure questions that need NO action:
53
53
  ## Guidelines
54
54
 
55
55
  ### For create_todos:
56
- 1. **1-5 high-level TODOs** - Even 1 TODO is fine! Don't be too granular, let Execution LLM handle details
57
- 2. **Actionable titles** - Clear what needs to be done
58
- 3. **Sequential order** - Execution order matters
59
- 4. **User's language** - Write titles in the same language as the user
56
+ 1. **Create the MINIMUM number of TODOs.** 1 task is the ideal and most common case. Only add more when the work is genuinely separable AND benefits from it. Debugging, investigation, and "figure out / fix X" are SEQUENTIAL by nature — each finding informs the next step — so they should be a SINGLE task, never split. Add multiple tasks only for genuinely independent, parallelizable implementation work (e.g. "build feature A" + "build unrelated feature B"). When unsure, prefer fewer.
57
+ 2. **dependsOn for ordered steps** - If task B needs task A's result (build → upload → restart), set B.dependsOn=[A]. Tasks that touch the filesystem with no declared deps run sequentially in listed order.
58
+ 3. **Actionable titles** - Clear what needs to be done
59
+ 4. **Sequential order** - List tasks in execution order
60
+ 5. **User's language** - Write titles in the same language as the user
60
61
 
61
62
  ### For respond_to_user:
62
63
  1. **Clear and helpful** - Answer the question directly
@@ -4,7 +4,10 @@ import { promisify } from 'util';
4
4
  const mkdir = promisify(fs.mkdir);
5
5
  const readFile = promisify(fs.readFile);
6
6
  const writeFile = promisify(fs.writeFile);
7
+ const rename = promisify(fs.rename);
8
+ const unlink = promisify(fs.unlink);
7
9
  const access = promisify(fs.access);
10
+ let tmpCounter = 0;
8
11
  const stat = promisify(fs.stat);
9
12
  export async function directoryExists(dirPath) {
10
13
  try {
@@ -51,7 +54,18 @@ export async function writeJsonFile(filePath, data) {
51
54
  const dirPath = path.dirname(filePath);
52
55
  await ensureDirectory(dirPath);
53
56
  const content = JSON.stringify(data, null, 2);
54
- await writeFile(filePath, content, 'utf-8');
57
+ const tmpPath = `${filePath}.tmp.${process.pid}.${tmpCounter++}`;
58
+ try {
59
+ await writeFile(tmpPath, content, 'utf-8');
60
+ await rename(tmpPath, filePath);
61
+ }
62
+ catch (err) {
63
+ try {
64
+ await unlink(tmpPath);
65
+ }
66
+ catch { }
67
+ throw err;
68
+ }
55
69
  }
56
70
  catch (error) {
57
71
  if (error instanceof Error) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "orquesta-cli",
3
- "version": "0.2.93",
3
+ "version": "0.2.94",
4
4
  "description": "Orquesta CLI - AI-powered coding assistant with team collaboration",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",