orquesta-agent 0.2.114 → 0.2.117

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.
@@ -45,6 +45,9 @@ export interface AuthConfig {
45
45
  }
46
46
  export declare function configureAuth(config: AuthConfig): void;
47
47
  export declare function setPermissionMode(mode: PermissionMode): void;
48
+ export declare function setSandboxConfig(enabled: boolean, extraPaths?: string[]): void;
49
+ /** Reported to the dashboard so the UI can show Active / Unavailable / Off. */
50
+ export declare function getSandboxStatus(): 'active' | 'unavailable' | 'off';
48
51
  export type CliPreference = 'auto' | 'orquesta' | 'claude';
49
52
  export declare function setCliPreference(preference: CliPreference): void;
50
53
  export declare function isOrquestaCliAvailable(): boolean;
@@ -1 +1 @@
1
- {"version":3,"file":"executor.d.ts","sourceRoot":"","sources":["../src/executor.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"executor.d.ts","sourceRoot":"","sources":["../src/executor.ts"],"names":[],"mappings":"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"}
package/dist/executor.js CHANGED
@@ -17,6 +17,7 @@ import * as fs from 'fs';
17
17
  import * as path from 'path';
18
18
  import * as os from 'os';
19
19
  import * as logger from './logger.js';
20
+ import { isSandboxAvailable, buildBwrapArgs, shQuote } from './sandbox.js';
20
21
  import { sendOutput, sendComplete, sendError, sendSupervisionRequest, sendExecutionResumed, updatePromptStatus, persistOutputLogs, clearOutputBuffer, sendRequirement, persistRequirement, sendQAInstructions, persistQAInstructions, sendPlanItemsGenerated, sendSessionOutput, sendSessionStarted, sendSessionEnded, sendSessionError } from './supabase.js';
21
22
  import { createThinkingLog, createToolCallLog, createToolResultLog, createOutputLog, createErrorLog, createSystemLog, } from './types/agent-logs.js';
22
23
  /**
@@ -301,6 +302,66 @@ export function setPermissionMode(mode) {
301
302
  globalPermissionMode = mode;
302
303
  logger.info(`Permission mode set to: ${mode}`);
303
304
  }
305
+ // Filesystem sandbox (bubblewrap). When enabled, every spawned CLI is confined
306
+ // to its working directory for writes; the rest of the host is read-only.
307
+ let globalSandbox = false;
308
+ let globalSandboxExtraPaths = [];
309
+ let sandboxUnavailableWarned = false;
310
+ // Set global sandbox config
311
+ export function setSandboxConfig(enabled, extraPaths = []) {
312
+ globalSandbox = enabled;
313
+ globalSandboxExtraPaths = Array.isArray(extraPaths) ? extraPaths : [];
314
+ if (enabled) {
315
+ logger.info(`Sandbox enabled${globalSandboxExtraPaths.length ? ` (extra rw: ${globalSandboxExtraPaths.join(', ')})` : ''}`);
316
+ }
317
+ else {
318
+ logger.info('Sandbox disabled');
319
+ }
320
+ sandboxUnavailableWarned = false;
321
+ }
322
+ /**
323
+ * Whether the sandbox should actually wrap spawns right now: enabled by config
324
+ * AND bwrap usable on this host. Logs a one-time warning (per config change)
325
+ * when enabled but unavailable, then falls back to running unsandboxed.
326
+ */
327
+ function sandboxActive() {
328
+ if (!globalSandbox)
329
+ return false;
330
+ if (isSandboxAvailable())
331
+ return true;
332
+ if (!sandboxUnavailableWarned) {
333
+ logger.warn('Sandbox enabled but bwrap not found — running without isolation. Install bubblewrap (apt install bubblewrap).');
334
+ sandboxUnavailableWarned = true;
335
+ }
336
+ return false;
337
+ }
338
+ /** Reported to the dashboard so the UI can show Active / Unavailable / Off. */
339
+ export function getSandboxStatus() {
340
+ if (!globalSandbox)
341
+ return 'off';
342
+ return isSandboxAvailable() ? 'active' : 'unavailable';
343
+ }
344
+ /**
345
+ * Wrap an argv-style spawn (file + args) in bwrap when the sandbox is active.
346
+ * Returns the file/args to actually pass to spawn()/ptySpawn().
347
+ */
348
+ function sandboxArgv(file, args, cwd) {
349
+ if (!sandboxActive())
350
+ return { file, args };
351
+ const bwrap = buildBwrapArgs({ workingDir: cwd, extraWritablePaths: globalSandboxExtraPaths });
352
+ return { file: 'bwrap', args: [...bwrap, file, ...args] };
353
+ }
354
+ /**
355
+ * Prefix a shell command string with the bwrap invocation when the sandbox is
356
+ * active (for the execSync `script -q -c "…" /dev/null` call sites). Returns ''
357
+ * when inactive, so callers just template `${prefix}script …`.
358
+ */
359
+ function sandboxShellPrefix(cwd) {
360
+ if (!sandboxActive())
361
+ return '';
362
+ const bwrap = buildBwrapArgs({ workingDir: cwd, extraWritablePaths: globalSandboxExtraPaths });
363
+ return `bwrap ${bwrap.map(shQuote).join(' ')} `;
364
+ }
304
365
  let globalCliPreference = 'auto';
305
366
  // Set CLI preference
306
367
  export function setCliPreference(preference) {
@@ -1256,7 +1317,13 @@ ${userRequestBody}`;
1256
1317
  });
1257
1318
  }
1258
1319
  else {
1259
- claude = spawn('script', scriptWrapArgs(command), {
1320
+ // Sandbox wraps the `script` invocation in bwrap when active (Linux only);
1321
+ // no-op otherwise.
1322
+ const { file: spawnFile, args: spawnArgs } = sandboxArgv('script', scriptWrapArgs(command), cwd);
1323
+ if (spawnFile === 'bwrap') {
1324
+ logger.info(`Sandbox active — confining writes to ${cwd}`);
1325
+ }
1326
+ claude = spawn(spawnFile, spawnArgs, {
1260
1327
  cwd,
1261
1328
  env,
1262
1329
  stdio: ['pipe', 'pipe', 'pipe'],
@@ -1979,7 +2046,7 @@ Return ONLY valid JSON in this exact format (no markdown, no explanation):
1979
2046
  const command = `${cliCommand} -p '${escapedContent}' --dangerously-skip-permissions --output-format text`;
1980
2047
  const { execSync } = await import('child_process');
1981
2048
  try {
1982
- const output = execSync(`script -q -c "${command.replace(/"/g, '\\"')}" /dev/null`, {
2049
+ const output = execSync(`${sandboxShellPrefix(cwd)}script -q -c "${command.replace(/"/g, '\\"')}" /dev/null`, {
1983
2050
  cwd,
1984
2051
  env,
1985
2052
  timeout: 60000, // 60 second timeout for evaluation
@@ -2193,7 +2260,7 @@ export async function generatePlanItems(options) {
2193
2260
  const command = `${cliCommand} -p '${escapedContent}' --dangerously-skip-permissions --output-format text`;
2194
2261
  logger.debug(`Running Claude CLI...`);
2195
2262
  try {
2196
- const output = execSync(`script -q -c "${command.replace(/"/g, '\\"')}" /dev/null`, {
2263
+ const output = execSync(`${sandboxShellPrefix(cwd)}script -q -c "${command.replace(/"/g, '\\"')}" /dev/null`, {
2197
2264
  cwd,
2198
2265
  env,
2199
2266
  timeout: 120000, // 2 minute timeout for generation
@@ -2503,13 +2570,41 @@ export async function startSession(options) {
2503
2570
  // fetchCoordinationContextBlock has its own 1.5s timeout and returns '' on failure,
2504
2571
  // so even if the Orquesta API is slow it won't block session startup by much.
2505
2572
  const liveCoordination = await fetchCoordinationContextBlock();
2506
- const systemPromptBlock = `${BROWSER_TOOLS_PROMPT_BLOCK}\n\n${ORQUESTA_CAPABILITIES_PROMPT_BLOCK}${liveCoordination}`;
2573
+ // Read local CLAUDE.md / AGENT.md from the working directory so the interactive
2574
+ // session starts with project conventions loaded. This mirrors what orquesta-cli's
2575
+ // buildSystemPrompt does, but guarantees the content is present even when the
2576
+ // CLI's own file discovery fails or the cache is stale.
2577
+ const CANDIDATE_MD_FILES = ['CLAUDE.md', '.claude/CLAUDE.md', 'AGENT.md', 'agent.md'];
2578
+ let projectMdContent = '';
2579
+ for (const rel of CANDIDATE_MD_FILES) {
2580
+ const abs = path.join(cwd, rel);
2581
+ try {
2582
+ const stat = fs.statSync(abs);
2583
+ if (stat.isFile()) {
2584
+ let content = fs.readFileSync(abs, 'utf-8');
2585
+ if (Buffer.byteLength(content, 'utf-8') > 32_000) {
2586
+ content = content.slice(0, 32_000) + '\n\n[...truncated for context window]';
2587
+ }
2588
+ projectMdContent = `\n\n## PROJECT CONTEXT\n(from ${rel} — treat as authoritative project conventions)\n\n${content}\n`;
2589
+ break;
2590
+ }
2591
+ }
2592
+ catch { /* file not found — try next */ }
2593
+ }
2594
+ const systemPromptBlock = `${BROWSER_TOOLS_PROMPT_BLOCK}\n\n${ORQUESTA_CAPABILITIES_PROMPT_BLOCK}${liveCoordination}${projectMdContent}`;
2507
2595
  const ptyArgs = [
2508
2596
  '--dangerously-skip-permissions',
2509
2597
  '--append-system-prompt', systemPromptBlock,
2510
2598
  ];
2511
2599
  try {
2512
- ptyProcess = ptySpawn(cliCommand, ptyArgs, {
2600
+ // Sandbox the interactive session too. node-pty allocates the pty on the
2601
+ // host side and bwrap (when active) inherits the slave as its stdio; bwrap's
2602
+ // own `--dev /dev` then exposes a working tty to the CLI inside the namespace.
2603
+ const { file: ptyFile, args: ptyArgsFinal } = sandboxArgv(cliCommand, ptyArgs, cwd);
2604
+ if (ptyFile === 'bwrap') {
2605
+ logger.info(`Sandbox active for interactive session — confining writes to ${cwd}`);
2606
+ }
2607
+ ptyProcess = ptySpawn(ptyFile, ptyArgsFinal, {
2513
2608
  name: 'xterm-256color',
2514
2609
  cols,
2515
2610
  rows,
@@ -2710,28 +2805,55 @@ function writeSessionText(sessionId, input) {
2710
2805
  if (!activeSession || activeSession.sessionId !== sessionId || !activeSession.isActive)
2711
2806
  return;
2712
2807
  const text = input.endsWith('\r') ? input.slice(0, -1) : input;
2808
+ const isOrquesta = activeSession.cliType === 'orquesta';
2713
2809
  // Bracketed paste for non-trivial inputs. Claude's TUI uses it to treat a long
2714
2810
  // block as a coherent paste. But orquesta-cli's Ink stack SWALLOWS the
2715
2811
  // \x1b[200~…\x1b[201~ sequence at its own stdin layer — the text never reaches
2716
2812
  // its input handler, so a long message silently fails to appear/submit. For
2717
2813
  // orquesta-cli, send the raw text instead (its input handles multi-char chunks
2718
2814
  // fine; the separate \r below submits).
2719
- const usePasteMarkers = text.length > 200 && activeSession.cliType !== 'orquesta';
2815
+ const usePasteMarkers = text.length > 200 && !isOrquesta;
2720
2816
  const payload = usePasteMarkers ? `\x1b[200~${text}\x1b[201~` : text;
2721
2817
  activeSession.ptyProcess.write(payload);
2722
- // Scale the wait: base 50ms + ~1ms per 20 chars + 80ms per newline. Multi-line
2723
- // pastes (e.g. rogerthat phone-message block) need more time before the \r
2724
- // submit, otherwise Ink absorbs the Enter into the paste buffer and the
2725
- // prompt just sits there with no submit confirmed via journalctl during
2726
- // the live-monitor E2E test. Capped at 800ms.
2727
- const newlineCount = (text.match(/\n/g) || []).length;
2728
- const delayMs = Math.min(800, 50 + Math.floor(text.length / 20) + newlineCount * 80);
2729
- setTimeout(() => {
2730
- if (activeSession?.sessionId === sessionId && activeSession.isActive) {
2731
- activeSession.ptyProcess.write('\r');
2732
- }
2733
- }, delayMs);
2734
- logger.info(`Session input sent (${text.length} chars, delay=${delayMs}ms${usePasteMarkers ? ', bracketed' : ''}): ${input.slice(0, 50)}${input.length > 50 ? '...' : ''}`);
2818
+ if (isOrquesta) {
2819
+ // orquesta-cli (Ink) drops stdin events while it is rendering / processing.
2820
+ // If we fire \r during an active turn the Enter is queued and only surfaces
2821
+ // when the turn finishes, so the user sees their message "appear late".
2822
+ // Fix: wait until the PTY has been quiet for a short window (300 ms) before
2823
+ // sending \r. While the LLM is streaming or a tool is running there is
2824
+ // constant output; the quiet window only happens when Ink is idle and ready
2825
+ // to read stdin. We poll every 100 ms with a hard ceiling so we never hang.
2826
+ const IDLE_THRESHOLD_MS = 300;
2827
+ const POLL_INTERVAL_MS = 100;
2828
+ const MAX_WAIT_MS = 5000;
2829
+ const startAt = Date.now();
2830
+ const trySubmit = () => {
2831
+ if (!activeSession || activeSession.sessionId !== sessionId || !activeSession.isActive)
2832
+ return;
2833
+ const elapsed = Date.now() - startAt;
2834
+ const idleFor = Date.now() - (activeSession.lastPtyOutputAt ?? 0);
2835
+ if (idleFor >= IDLE_THRESHOLD_MS || elapsed >= MAX_WAIT_MS) {
2836
+ activeSession.ptyProcess.write('\r');
2837
+ logger.info(`Session input submitted (${text.length} chars, idle=${idleFor}ms, elapsed=${elapsed}ms)`);
2838
+ }
2839
+ else {
2840
+ setTimeout(trySubmit, POLL_INTERVAL_MS);
2841
+ }
2842
+ };
2843
+ setTimeout(trySubmit, POLL_INTERVAL_MS);
2844
+ }
2845
+ else {
2846
+ // Claude CLI — scale the wait: base 50ms + ~1ms per 20 chars + 80ms per newline.
2847
+ // Multi-line pastes need more time before the \r submit. Capped at 800ms.
2848
+ const newlineCount = (text.match(/\n/g) || []).length;
2849
+ const delayMs = Math.min(800, 50 + Math.floor(text.length / 20) + newlineCount * 80);
2850
+ setTimeout(() => {
2851
+ if (activeSession?.sessionId === sessionId && activeSession.isActive) {
2852
+ activeSession.ptyProcess.write('\r');
2853
+ }
2854
+ }, delayMs);
2855
+ }
2856
+ logger.info(`Session input written (${text.length} chars${usePasteMarkers ? ', bracketed' : ''}): ${input.slice(0, 50)}${input.length > 50 ? '...' : ''}`);
2735
2857
  }
2736
2858
  /**
2737
2859
  * End the active interactive session.