@ordewell/core 0.4.3 → 0.4.5

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.
@@ -439,8 +439,22 @@ interface ResolveContext {
439
439
  /** All variant ids the assigned model offers — lets {{opencodeVariantConfig}} disable the non-chosen ones. */
440
440
  modelVariants?: string[];
441
441
  mode: string;
442
- /** When true, resolve {{if headless}} blocks and the {{feature:headless}} token. */
442
+ /**
443
+ * Autonomy axis: when true, resolve {{if headless}} blocks and the
444
+ * {{feature:headless}} token so the agent never stops to ask for permission.
445
+ * True for every orchestrated task run — nobody is watching the terminal on
446
+ * Ordewell's behalf — independently of the session *shape* below.
447
+ */
443
448
  headless?: boolean;
449
+ /**
450
+ * Session-shape axis: true when the runner is launched onto a real TTY the
451
+ * user can attach to (a tmux window, a VS Code pseudoterminal), so the
452
+ * runner's own TUI should come up rather than its non-interactive
453
+ * subcommand. Defaults to `!headless` for callers that predate the split.
454
+ */
455
+ interactive?: boolean;
456
+ /** The task's working directory — needed by runners whose autonomy flags name a path. */
457
+ cwd?: string;
444
458
  }
445
459
  interface RunnerInvocation {
446
460
  command: string;
@@ -439,8 +439,22 @@ interface ResolveContext {
439
439
  /** All variant ids the assigned model offers — lets {{opencodeVariantConfig}} disable the non-chosen ones. */
440
440
  modelVariants?: string[];
441
441
  mode: string;
442
- /** When true, resolve {{if headless}} blocks and the {{feature:headless}} token. */
442
+ /**
443
+ * Autonomy axis: when true, resolve {{if headless}} blocks and the
444
+ * {{feature:headless}} token so the agent never stops to ask for permission.
445
+ * True for every orchestrated task run — nobody is watching the terminal on
446
+ * Ordewell's behalf — independently of the session *shape* below.
447
+ */
443
448
  headless?: boolean;
449
+ /**
450
+ * Session-shape axis: true when the runner is launched onto a real TTY the
451
+ * user can attach to (a tmux window, a VS Code pseudoterminal), so the
452
+ * runner's own TUI should come up rather than its non-interactive
453
+ * subcommand. Defaults to `!headless` for callers that predate the split.
454
+ */
455
+ interactive?: boolean;
456
+ /** The task's working directory — needed by runners whose autonomy flags name a path. */
457
+ cwd?: string;
444
458
  }
445
459
  interface RunnerInvocation {
446
460
  command: string;
package/dist/index.d.mts CHANGED
@@ -1,7 +1,7 @@
1
1
  import { h as RunnerId, c as PlanStatus, L as LegacyPlanState, d as ResearchProgress, a as DiscoveredModel, T as Task, R as ResearchLogEntry, C as ConversationMessage, n as TaskSnapshot, Q as QueuedMessage, A as ActiveTaskSession, g as ResearchToolType, u as Verdict, e as ResearchStep, b as PlanState } from './Task-1NwmUImI.mjs';
2
2
  export { D as DiscoveredMode, M as Message, P as PlanModificationWarnings, f as ResearchStepOutcome, S as StreamEvent, i as StreamStepEvent, j as StreamThinkingEvent, k as TaskMode, l as TaskModelAssignment, m as TaskOutputSummary, o as TaskStatus, p as TaskType, q as ThinkingBlock, U as UserPromptEntry, r as UserStep, V as ValidationCheck, s as ValidationContext, t as ValidationResult, v as VerificationCheck, w as addTaskToPlan, x as createEmptyPlan, y as createTask, z as emptyWarnings, B as flattenTasks, E as migrateLegacyPlan, F as migratePlanState, G as migrateTask, H as removeTaskFromPlan, I as renumberTasks, J as updateTaskInPlan, K as validateModifiedPlan, N as warningsText } from './Task-1NwmUImI.mjs';
3
- import { n as IFileSystem, I as IApproval, R as ReadFileOpts, T as ToolOutcome, k as GrepOptions, j as GlobOptions, i as FindSymbolOptions, f as ApprovalRequest, m as IConfig, A as AiProvider, y as ProviderModelLists, c as ApprovalMode, q as ITerminalSession, p as ITerminalRunner, J as RunnerRegistry, s as OrchestratorOption, b as ApprovalKind, g as ApprovalSource, E as RunnerInvocation, o as IPluginStore, H as RunnerPluginManifest, B as ResolveContext } from './ITerminalRunner-D8Bf-HD4.mjs';
4
- export { a as AllProviderModels, d as ApprovalPolicy, e as ApprovalPolicyOptions, C as CatalogModel, D as DENY_ALL, h as DiscoveryCommand, F as FetchAllProviderModelsOptions, G as GREP_DEFAULT_HEAD_LIMIT, l as GrepOutputMode, M as ModelCatalog, r as ModelShortcut, O as ORCHESTRATOR_SHORTCUTS, P as PluginEntry, t as PluginFeatures, u as PluginMode, v as PluginModelDiscovery, w as PluginRunnerDef, x as ProviderCredentialSource, z as ProviderModelsResult, S as SEARCH_EXCLUSIONS, K as collectProviderCredentials, L as enabledRunners, N as fetchAllProviderModels, Q as knownModelId, U as resolveModelShortcut, V as resolveProvider, W as toOrchestratorOptions } from './ITerminalRunner-D8Bf-HD4.mjs';
3
+ import { n as IFileSystem, I as IApproval, R as ReadFileOpts, T as ToolOutcome, k as GrepOptions, j as GlobOptions, i as FindSymbolOptions, f as ApprovalRequest, m as IConfig, A as AiProvider, y as ProviderModelLists, c as ApprovalMode, q as ITerminalSession, p as ITerminalRunner, J as RunnerRegistry, s as OrchestratorOption, b as ApprovalKind, g as ApprovalSource, E as RunnerInvocation, o as IPluginStore, H as RunnerPluginManifest, B as ResolveContext } from './ITerminalRunner-YMVsbfem.mjs';
4
+ export { a as AllProviderModels, d as ApprovalPolicy, e as ApprovalPolicyOptions, C as CatalogModel, D as DENY_ALL, h as DiscoveryCommand, F as FetchAllProviderModelsOptions, G as GREP_DEFAULT_HEAD_LIMIT, l as GrepOutputMode, M as ModelCatalog, r as ModelShortcut, O as ORCHESTRATOR_SHORTCUTS, P as PluginEntry, t as PluginFeatures, u as PluginMode, v as PluginModelDiscovery, w as PluginRunnerDef, x as ProviderCredentialSource, z as ProviderModelsResult, S as SEARCH_EXCLUSIONS, K as collectProviderCredentials, L as enabledRunners, N as fetchAllProviderModels, Q as knownModelId, U as resolveModelShortcut, V as resolveProvider, W as toOrchestratorOptions } from './ITerminalRunner-YMVsbfem.mjs';
5
5
  import { R as RunnerModeInfo, b as PlanParseError } from './parsing-xpozY5ac.mjs';
6
6
  export { M as ManifestLookup, P as PLAN_ENVELOPE_KEY, a as PartialPlanTask, T as TASK_OPS_ENVELOPE_KEY, c as buildModeGuide, d as checkDepsResolve, e as checkImmutableLog, f as checkInProgress, g as checkNoCycles, h as checkUniqueIds, i as escapeControlCharsInStrings, j as extractJsonObject, k as extractObjectWithBalance, l as extractObjectsWithKey, m as filteredBuildModes, n as looksLikePlanAttempt, p as parsePartialPlan, o as parsePlanJson, r as resolveDefaultMode, q as resolveTaskMode, s as runnerModesFrom, t as stripModelNoise, u as stripTrailingCommas, v as validatePlanModification } from './parsing-xpozY5ac.mjs';
7
7
  import { T as TaskOp } from './plan-utils-nfHKSbd3.mjs';
@@ -789,8 +789,14 @@ declare class HeadlessRunner extends AbstractRunner<HeadlessSession> {
789
789
  private hasScriptCmd;
790
790
  private resolvePath;
791
791
  private launchDeps;
792
- /** Session shape when the caller names none; the VS Code runner overrides it to interactive. */
793
- protected readonly defaultHeadless: boolean;
792
+ /**
793
+ * Session shape: a piped subprocess is not a terminal, so runners get their
794
+ * non-interactive subcommand. The VS Code runner owns a pseudoterminal and
795
+ * overrides this to true. Autonomy is a separate axis (see `ResolveContext`)
796
+ * and stays on either way — no surface has a human answering permission
797
+ * prompts on the orchestrator's behalf.
798
+ */
799
+ protected readonly defaultInteractive: boolean;
794
800
  constructor(deps?: HeadlessRunnerDeps);
795
801
  protected createSession(id: string, taskId: string): HeadlessSession;
796
802
  /** Everything up to, but not including, spawning — so a surface that owns its own child reaches the same decisions. */
@@ -2706,6 +2712,8 @@ declare function buildRunnerInvocation(opts: {
2706
2712
  modelVariants?: string[];
2707
2713
  mode?: RunnerMode;
2708
2714
  headless?: boolean;
2715
+ interactive?: boolean;
2716
+ cwd?: string;
2709
2717
  registry: RunnerRegistry;
2710
2718
  }): RunnerInvocation;
2711
2719
 
@@ -2744,6 +2752,7 @@ interface TmuxRunnerDeps {
2744
2752
  resolvePath?: () => Promise<string>;
2745
2753
  pollIntervalMs?: number;
2746
2754
  logDir?: string;
2755
+ clipboardCommand?: () => string | null;
2747
2756
  }
2748
2757
  declare class TmuxSession extends AbstractTerminalSession {
2749
2758
  private tmuxSession;
@@ -2795,6 +2804,7 @@ declare class TmuxRunner extends AbstractRunner<TmuxSession> {
2795
2804
  private resolvePath;
2796
2805
  private pollIntervalMs;
2797
2806
  private logDir;
2807
+ private clipboardCommand;
2798
2808
  /** Retries get a freshly named window so a failed attempt's output stays inspectable. */
2799
2809
  private attempts;
2800
2810
  private ready;
@@ -2810,14 +2820,17 @@ declare class TmuxRunner extends AbstractRunner<TmuxSession> {
2810
2820
  private tmux;
2811
2821
  private createFreshSession;
2812
2822
  /**
2813
- * Makes an attached runner terminal scrollable with the mouse wheel and
2814
- * Page Up/Down. A fresh tmux session ships with `mouse off`, a 2000-line
2815
- * scrollback, and no PageUp binding — none of which lets a user page back
2816
- * through a finished task's output, which is the whole point of opening its
2817
- * window. Scoping is harmless: the daemon owns a private socket
2818
- * (`tmuxSocketName`), so these server-wide options touch nothing but its
2819
- * own session. Best-effort so an ancient or stripped tmux cannot stop tasks
2820
- * from spawning — the session still works without the scroll comforts.
2823
+ * Gives an attached runner terminal wheel/PageUp scrolling over a deep
2824
+ * scrollback, and a mouse selection that reaches the system clipboard — none
2825
+ * of which a default tmux session does. Server-wide scoping is harmless: the
2826
+ * daemon owns a private socket (`tmuxSocketName`).
2827
+ *
2828
+ * `mouse on` is what costs the emulator's own drag-select, so tmux must hand
2829
+ * the selection back out itself: via a clipboard binary when there is one,
2830
+ * and via OSC 52 (`set-clipboard`) for what that cannot cover, such as
2831
+ * viewing over SSH. Naming the binary on the binding as well as in
2832
+ * `copy-command` keeps drag-to-copy working on tmux older than 3.2, which has
2833
+ * no `copy-command`.
2821
2834
  */
2822
2835
  private configureScrolling;
2823
2836
  /**
@@ -2962,6 +2975,15 @@ declare function tmuxWindowName(taskId: string, planSessionId?: string): string;
2962
2975
  type ProbeFn = () => void;
2963
2976
  /** Feature-detects tmux the same way `HeadlessRunner` detects `script`. */
2964
2977
  declare function hasTmux(probe?: ProbeFn): boolean;
2978
+ type HasBinFn = (bin: string) => boolean;
2979
+ /**
2980
+ * Shell command tmux should pipe a copy-mode selection into, so selecting text
2981
+ * in a task's terminal puts it on the *system* clipboard rather than in a tmux
2982
+ * paste buffer no other application can read. Preferred over tmux's OSC 52
2983
+ * bridge, which plenty of emulators (VTE before 0.76, xterm without
2984
+ * `allowWindowOps`) drop on the floor.
2985
+ */
2986
+ declare function clipboardCopyCommand(hasBin?: HasBinFn, platform?: NodeJS.Platform, env?: NodeJS.ProcessEnv): string | null;
2965
2987
 
2966
2988
  declare class FsPluginStore implements IPluginStore {
2967
2989
  getUserPluginsDir(): string;
@@ -3022,4 +3044,4 @@ declare function sanitizeSlug(raw: string): string;
3022
3044
  /** Save the PRD to `<workspace>/.scratch/<slug>/PRD.md` (to-prd native convention). */
3023
3045
  declare function savePrdMarkdown(workspace: string, slug: string, markdown: string): string;
3024
3046
 
3025
- export { ALL_PROVIDERS, AUTO_COMMANDS, AbstractRunner, AbstractTerminalSession, ActiveTaskSession, type AgentAdapter, type AgentAdapterFactory, type AgentEvent, type AgentProcessDeps, type AgentStartOptions, AiProvider, ApprovalKind, ApprovalMode, ApprovalRequest, ApprovalSource, BaseAiService, BaseConfig, BaseFileSystem, CLAUDE_CODE_MANIFEST, CLI_PROVIDERS, CMD_EXE_MAX_COMMAND_LINE, CORE_PLANNER_PROMPT, type CappedRows, type CheckpointListener, ClaudeCodeAdapter, CliAgentAiService, type CliAgentAiServiceDeps, CodexAdapter, type CommandClassification, CommandLineTooLongError, type CommandTier, type ComposeOptions, ConsoleLogger, ContextCollector, ConversationMessage, type ConversationRequest, type ConversationTurn, DiscoveredModel, EmbeddedNewlineError, EnvConfig, type ExecFileFn, type ExecImpl, FindSymbolOptions, FsPluginStore, GIT_READONLY_SUBCOMMANDS, GeminiService, GlobOptions, type GrepInvocation, GrepOptions, HeadlessRunner, type HeadlessRunnerDeps, HeadlessSession, type IAiService, IApproval, IConfig, IFileSystem, type ILogger, type INotification, IPluginStore, ITerminalRunner, ITerminalSession, JSON_REPAIR_INSTRUCTION, type KillTreeDeps, type LaunchDeps, type LaunchPlan, LegacyPlanState, LineBuffer, type MappedTool, ModelResolver, type ModelResolverDeps, type ModifyPlanRequest, type NotificationAction, OPENCODE_MANIFEST, OpenAiService, OpenCodeAdapter, type OrchestratorObserver, OrchestratorOption, PROVIDER_DETECT_PRIORITY, PROVIDER_LABEL, PROVIDER_PRIORITY, PROVIDER_SHORT_LABEL, type PendingApproval, PendingApprovals, type PendingApprovalsOptions, PlanParseError, type PlanRequest, PlanState, PlanStatus, PlanStore, Planner, type PlannerReplyClassification, type PlannerRuntimeToggles, type PrdBlock, type PreparedLaunch, type PriorOutput, type ProbeFn, ProviderModelLists, type ProviderRegistration, QueuedMessage, REFUSED_COMMANDS, ReadFileOpts, type RepairLoopOpts, type RepairVerdict, type ResearchChat, ResearchLogEntry, ResearchProgress, type ResearchShell, type ResearchShellDeps, ResearchStep, ResearchToolType, type ResearchTurn, ResolveContext, type RunnerCatalog, RunnerId, RunnerInstallation, RunnerInvocation, type RunnerMode, RunnerModeInfo, RunnerPluginManifest, RunnerRegistry, type RunnerSpawnOptions, STATE_DIR, SYMBOL_LANGUAGES, type SerializedPlan, type SerializedTask, type SerializedTaskStatus, Session, type SessionBroadcaster, type SessionData, type SessionDeps, type SessionMessage, type SessionMeta, type SessionPlanner, type SessionRuntimeSettings, SettingsService, type ShellDialect, type SpawnSpec, StdioAgentAdapter, TRUNCATED_PLAN_REPAIR_INSTRUCTION, Task, TaskOp, TaskOrchestrator, TaskSnapshot, TmuxRunner, type TmuxRunnerDeps, type ToolCall, ToolOutcome, type ToolResult, type UserSettings, Verdict, VerdictEngine, type VerdictListener, WINDOWS_MAX_COMMAND_LINE, applyHeadLimit, augmentPromptWithPriorOutputs, augmentedPath, buildConversationSystemPrompt, buildFallbackGrepArgs, buildGlobArgs, buildGrepArgs, buildMergePrompt, buildModifyDuringExecutionPrompt, buildModifyPlanPrompt, buildPlanWithResults, buildResearchPrompt, buildResearchToolsPrompt, buildRunnerInvocation, buildShellInvocation, buildSplitPrompt, buildSubagentSystemPrompt, clampThinkingEffort, classifyCommand, classifyPlannerReply, clearAugmentedPathCache, clearResearchShellCache, clearState, coerceAssignments, collectDirectDependencyOutputs, composeAugmentedPrompt, configuredProviders, createAiService, defaultLogger, definitionPattern, deleteSession, discoverGeminiModels, effectiveAllowlist, ensureDir, executionLogBlock, executionSummary, extractPrdBlock, filterFallbackByAnchoredInclude, filterModelsForPrompt, formatSearchOutput, generatePlanWithRepair, getLatestSession, getProviderMeta, getSettingsPath, getStateDir, grantScopeFor, hasTmux, includeGlobFor, isCliProvider, isOpenAiProvider, killTree, languageForId, listSessions, loadSession, loadSessionPlanState, loadState, mapAgentTool, modelContextBlock, modifyValidationFeedback, normalizeAgentArgs, normalizeGeminiModel, pendingEditRulesBlock, planDirectLaunch, planShellLaunch, posixShellQuote, prefixModelId, providerForRunner, reEmitPlanPrompt, reEmitTaskOpsPrompt, referencePattern, renderPlanMap, renderPriorOutputs, repairLoop, researchShellWarning, researchToolsPath, resolveArgs, resolveProviderFromPrefix, resolveResearchShell, resolveWithin, retargetTaskRunner, runnerAssignment, runnerForProvider, sanitizeSlug, savePrdMarkdown, saveSession, saveState, serializePlan, serializeTask, serializeTaskStatus, sessionRuntimeSettings, stateExists, stripAnsi, stripModelPrefix, summarizeOutput, taskOpsRejectedPrompt, tmuxSessionName, tmuxSocketName, tmuxWindowName, truncatedPlanReEmitPrompt, wellKnownBinDirs, windowsCommandLine, withPath, wrapWithPty };
3047
+ export { ALL_PROVIDERS, AUTO_COMMANDS, AbstractRunner, AbstractTerminalSession, ActiveTaskSession, type AgentAdapter, type AgentAdapterFactory, type AgentEvent, type AgentProcessDeps, type AgentStartOptions, AiProvider, ApprovalKind, ApprovalMode, ApprovalRequest, ApprovalSource, BaseAiService, BaseConfig, BaseFileSystem, CLAUDE_CODE_MANIFEST, CLI_PROVIDERS, CMD_EXE_MAX_COMMAND_LINE, CORE_PLANNER_PROMPT, type CappedRows, type CheckpointListener, ClaudeCodeAdapter, CliAgentAiService, type CliAgentAiServiceDeps, CodexAdapter, type CommandClassification, CommandLineTooLongError, type CommandTier, type ComposeOptions, ConsoleLogger, ContextCollector, ConversationMessage, type ConversationRequest, type ConversationTurn, DiscoveredModel, EmbeddedNewlineError, EnvConfig, type ExecFileFn, type ExecImpl, FindSymbolOptions, FsPluginStore, GIT_READONLY_SUBCOMMANDS, GeminiService, GlobOptions, type GrepInvocation, GrepOptions, type HasBinFn, HeadlessRunner, type HeadlessRunnerDeps, HeadlessSession, type IAiService, IApproval, IConfig, IFileSystem, type ILogger, type INotification, IPluginStore, ITerminalRunner, ITerminalSession, JSON_REPAIR_INSTRUCTION, type KillTreeDeps, type LaunchDeps, type LaunchPlan, LegacyPlanState, LineBuffer, type MappedTool, ModelResolver, type ModelResolverDeps, type ModifyPlanRequest, type NotificationAction, OPENCODE_MANIFEST, OpenAiService, OpenCodeAdapter, type OrchestratorObserver, OrchestratorOption, PROVIDER_DETECT_PRIORITY, PROVIDER_LABEL, PROVIDER_PRIORITY, PROVIDER_SHORT_LABEL, type PendingApproval, PendingApprovals, type PendingApprovalsOptions, PlanParseError, type PlanRequest, PlanState, PlanStatus, PlanStore, Planner, type PlannerReplyClassification, type PlannerRuntimeToggles, type PrdBlock, type PreparedLaunch, type PriorOutput, type ProbeFn, ProviderModelLists, type ProviderRegistration, QueuedMessage, REFUSED_COMMANDS, ReadFileOpts, type RepairLoopOpts, type RepairVerdict, type ResearchChat, ResearchLogEntry, ResearchProgress, type ResearchShell, type ResearchShellDeps, ResearchStep, ResearchToolType, type ResearchTurn, ResolveContext, type RunnerCatalog, RunnerId, RunnerInstallation, RunnerInvocation, type RunnerMode, RunnerModeInfo, RunnerPluginManifest, RunnerRegistry, type RunnerSpawnOptions, STATE_DIR, SYMBOL_LANGUAGES, type SerializedPlan, type SerializedTask, type SerializedTaskStatus, Session, type SessionBroadcaster, type SessionData, type SessionDeps, type SessionMessage, type SessionMeta, type SessionPlanner, type SessionRuntimeSettings, SettingsService, type ShellDialect, type SpawnSpec, StdioAgentAdapter, TRUNCATED_PLAN_REPAIR_INSTRUCTION, Task, TaskOp, TaskOrchestrator, TaskSnapshot, TmuxRunner, type TmuxRunnerDeps, type ToolCall, ToolOutcome, type ToolResult, type UserSettings, Verdict, VerdictEngine, type VerdictListener, WINDOWS_MAX_COMMAND_LINE, applyHeadLimit, augmentPromptWithPriorOutputs, augmentedPath, buildConversationSystemPrompt, buildFallbackGrepArgs, buildGlobArgs, buildGrepArgs, buildMergePrompt, buildModifyDuringExecutionPrompt, buildModifyPlanPrompt, buildPlanWithResults, buildResearchPrompt, buildResearchToolsPrompt, buildRunnerInvocation, buildShellInvocation, buildSplitPrompt, buildSubagentSystemPrompt, clampThinkingEffort, classifyCommand, classifyPlannerReply, clearAugmentedPathCache, clearResearchShellCache, clearState, clipboardCopyCommand, coerceAssignments, collectDirectDependencyOutputs, composeAugmentedPrompt, configuredProviders, createAiService, defaultLogger, definitionPattern, deleteSession, discoverGeminiModels, effectiveAllowlist, ensureDir, executionLogBlock, executionSummary, extractPrdBlock, filterFallbackByAnchoredInclude, filterModelsForPrompt, formatSearchOutput, generatePlanWithRepair, getLatestSession, getProviderMeta, getSettingsPath, getStateDir, grantScopeFor, hasTmux, includeGlobFor, isCliProvider, isOpenAiProvider, killTree, languageForId, listSessions, loadSession, loadSessionPlanState, loadState, mapAgentTool, modelContextBlock, modifyValidationFeedback, normalizeAgentArgs, normalizeGeminiModel, pendingEditRulesBlock, planDirectLaunch, planShellLaunch, posixShellQuote, prefixModelId, providerForRunner, reEmitPlanPrompt, reEmitTaskOpsPrompt, referencePattern, renderPlanMap, renderPriorOutputs, repairLoop, researchShellWarning, researchToolsPath, resolveArgs, resolveProviderFromPrefix, resolveResearchShell, resolveWithin, retargetTaskRunner, runnerAssignment, runnerForProvider, sanitizeSlug, savePrdMarkdown, saveSession, saveState, serializePlan, serializeTask, serializeTaskStatus, sessionRuntimeSettings, stateExists, stripAnsi, stripModelPrefix, summarizeOutput, taskOpsRejectedPrompt, tmuxSessionName, tmuxSocketName, tmuxWindowName, truncatedPlanReEmitPrompt, wellKnownBinDirs, windowsCommandLine, withPath, wrapWithPty };
package/dist/index.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import { h as RunnerId, c as PlanStatus, L as LegacyPlanState, d as ResearchProgress, a as DiscoveredModel, T as Task, R as ResearchLogEntry, C as ConversationMessage, n as TaskSnapshot, Q as QueuedMessage, A as ActiveTaskSession, g as ResearchToolType, u as Verdict, e as ResearchStep, b as PlanState } from './Task-1NwmUImI.js';
2
2
  export { D as DiscoveredMode, M as Message, P as PlanModificationWarnings, f as ResearchStepOutcome, S as StreamEvent, i as StreamStepEvent, j as StreamThinkingEvent, k as TaskMode, l as TaskModelAssignment, m as TaskOutputSummary, o as TaskStatus, p as TaskType, q as ThinkingBlock, U as UserPromptEntry, r as UserStep, V as ValidationCheck, s as ValidationContext, t as ValidationResult, v as VerificationCheck, w as addTaskToPlan, x as createEmptyPlan, y as createTask, z as emptyWarnings, B as flattenTasks, E as migrateLegacyPlan, F as migratePlanState, G as migrateTask, H as removeTaskFromPlan, I as renumberTasks, J as updateTaskInPlan, K as validateModifiedPlan, N as warningsText } from './Task-1NwmUImI.js';
3
- import { n as IFileSystem, I as IApproval, R as ReadFileOpts, T as ToolOutcome, k as GrepOptions, j as GlobOptions, i as FindSymbolOptions, f as ApprovalRequest, m as IConfig, A as AiProvider, y as ProviderModelLists, c as ApprovalMode, q as ITerminalSession, p as ITerminalRunner, J as RunnerRegistry, s as OrchestratorOption, b as ApprovalKind, g as ApprovalSource, E as RunnerInvocation, o as IPluginStore, H as RunnerPluginManifest, B as ResolveContext } from './ITerminalRunner-Bbpe8uts.js';
4
- export { a as AllProviderModels, d as ApprovalPolicy, e as ApprovalPolicyOptions, C as CatalogModel, D as DENY_ALL, h as DiscoveryCommand, F as FetchAllProviderModelsOptions, G as GREP_DEFAULT_HEAD_LIMIT, l as GrepOutputMode, M as ModelCatalog, r as ModelShortcut, O as ORCHESTRATOR_SHORTCUTS, P as PluginEntry, t as PluginFeatures, u as PluginMode, v as PluginModelDiscovery, w as PluginRunnerDef, x as ProviderCredentialSource, z as ProviderModelsResult, S as SEARCH_EXCLUSIONS, K as collectProviderCredentials, L as enabledRunners, N as fetchAllProviderModels, Q as knownModelId, U as resolveModelShortcut, V as resolveProvider, W as toOrchestratorOptions } from './ITerminalRunner-Bbpe8uts.js';
3
+ import { n as IFileSystem, I as IApproval, R as ReadFileOpts, T as ToolOutcome, k as GrepOptions, j as GlobOptions, i as FindSymbolOptions, f as ApprovalRequest, m as IConfig, A as AiProvider, y as ProviderModelLists, c as ApprovalMode, q as ITerminalSession, p as ITerminalRunner, J as RunnerRegistry, s as OrchestratorOption, b as ApprovalKind, g as ApprovalSource, E as RunnerInvocation, o as IPluginStore, H as RunnerPluginManifest, B as ResolveContext } from './ITerminalRunner-D7DwHYSg.js';
4
+ export { a as AllProviderModels, d as ApprovalPolicy, e as ApprovalPolicyOptions, C as CatalogModel, D as DENY_ALL, h as DiscoveryCommand, F as FetchAllProviderModelsOptions, G as GREP_DEFAULT_HEAD_LIMIT, l as GrepOutputMode, M as ModelCatalog, r as ModelShortcut, O as ORCHESTRATOR_SHORTCUTS, P as PluginEntry, t as PluginFeatures, u as PluginMode, v as PluginModelDiscovery, w as PluginRunnerDef, x as ProviderCredentialSource, z as ProviderModelsResult, S as SEARCH_EXCLUSIONS, K as collectProviderCredentials, L as enabledRunners, N as fetchAllProviderModels, Q as knownModelId, U as resolveModelShortcut, V as resolveProvider, W as toOrchestratorOptions } from './ITerminalRunner-D7DwHYSg.js';
5
5
  import { R as RunnerModeInfo, b as PlanParseError } from './parsing-RjN9JbyG.js';
6
6
  export { M as ManifestLookup, P as PLAN_ENVELOPE_KEY, a as PartialPlanTask, T as TASK_OPS_ENVELOPE_KEY, c as buildModeGuide, d as checkDepsResolve, e as checkImmutableLog, f as checkInProgress, g as checkNoCycles, h as checkUniqueIds, i as escapeControlCharsInStrings, j as extractJsonObject, k as extractObjectWithBalance, l as extractObjectsWithKey, m as filteredBuildModes, n as looksLikePlanAttempt, p as parsePartialPlan, o as parsePlanJson, r as resolveDefaultMode, q as resolveTaskMode, s as runnerModesFrom, t as stripModelNoise, u as stripTrailingCommas, v as validatePlanModification } from './parsing-RjN9JbyG.js';
7
7
  import { T as TaskOp } from './plan-utils-Cgc0cCH1.js';
@@ -789,8 +789,14 @@ declare class HeadlessRunner extends AbstractRunner<HeadlessSession> {
789
789
  private hasScriptCmd;
790
790
  private resolvePath;
791
791
  private launchDeps;
792
- /** Session shape when the caller names none; the VS Code runner overrides it to interactive. */
793
- protected readonly defaultHeadless: boolean;
792
+ /**
793
+ * Session shape: a piped subprocess is not a terminal, so runners get their
794
+ * non-interactive subcommand. The VS Code runner owns a pseudoterminal and
795
+ * overrides this to true. Autonomy is a separate axis (see `ResolveContext`)
796
+ * and stays on either way — no surface has a human answering permission
797
+ * prompts on the orchestrator's behalf.
798
+ */
799
+ protected readonly defaultInteractive: boolean;
794
800
  constructor(deps?: HeadlessRunnerDeps);
795
801
  protected createSession(id: string, taskId: string): HeadlessSession;
796
802
  /** Everything up to, but not including, spawning — so a surface that owns its own child reaches the same decisions. */
@@ -2706,6 +2712,8 @@ declare function buildRunnerInvocation(opts: {
2706
2712
  modelVariants?: string[];
2707
2713
  mode?: RunnerMode;
2708
2714
  headless?: boolean;
2715
+ interactive?: boolean;
2716
+ cwd?: string;
2709
2717
  registry: RunnerRegistry;
2710
2718
  }): RunnerInvocation;
2711
2719
 
@@ -2744,6 +2752,7 @@ interface TmuxRunnerDeps {
2744
2752
  resolvePath?: () => Promise<string>;
2745
2753
  pollIntervalMs?: number;
2746
2754
  logDir?: string;
2755
+ clipboardCommand?: () => string | null;
2747
2756
  }
2748
2757
  declare class TmuxSession extends AbstractTerminalSession {
2749
2758
  private tmuxSession;
@@ -2795,6 +2804,7 @@ declare class TmuxRunner extends AbstractRunner<TmuxSession> {
2795
2804
  private resolvePath;
2796
2805
  private pollIntervalMs;
2797
2806
  private logDir;
2807
+ private clipboardCommand;
2798
2808
  /** Retries get a freshly named window so a failed attempt's output stays inspectable. */
2799
2809
  private attempts;
2800
2810
  private ready;
@@ -2810,14 +2820,17 @@ declare class TmuxRunner extends AbstractRunner<TmuxSession> {
2810
2820
  private tmux;
2811
2821
  private createFreshSession;
2812
2822
  /**
2813
- * Makes an attached runner terminal scrollable with the mouse wheel and
2814
- * Page Up/Down. A fresh tmux session ships with `mouse off`, a 2000-line
2815
- * scrollback, and no PageUp binding — none of which lets a user page back
2816
- * through a finished task's output, which is the whole point of opening its
2817
- * window. Scoping is harmless: the daemon owns a private socket
2818
- * (`tmuxSocketName`), so these server-wide options touch nothing but its
2819
- * own session. Best-effort so an ancient or stripped tmux cannot stop tasks
2820
- * from spawning — the session still works without the scroll comforts.
2823
+ * Gives an attached runner terminal wheel/PageUp scrolling over a deep
2824
+ * scrollback, and a mouse selection that reaches the system clipboard — none
2825
+ * of which a default tmux session does. Server-wide scoping is harmless: the
2826
+ * daemon owns a private socket (`tmuxSocketName`).
2827
+ *
2828
+ * `mouse on` is what costs the emulator's own drag-select, so tmux must hand
2829
+ * the selection back out itself: via a clipboard binary when there is one,
2830
+ * and via OSC 52 (`set-clipboard`) for what that cannot cover, such as
2831
+ * viewing over SSH. Naming the binary on the binding as well as in
2832
+ * `copy-command` keeps drag-to-copy working on tmux older than 3.2, which has
2833
+ * no `copy-command`.
2821
2834
  */
2822
2835
  private configureScrolling;
2823
2836
  /**
@@ -2962,6 +2975,15 @@ declare function tmuxWindowName(taskId: string, planSessionId?: string): string;
2962
2975
  type ProbeFn = () => void;
2963
2976
  /** Feature-detects tmux the same way `HeadlessRunner` detects `script`. */
2964
2977
  declare function hasTmux(probe?: ProbeFn): boolean;
2978
+ type HasBinFn = (bin: string) => boolean;
2979
+ /**
2980
+ * Shell command tmux should pipe a copy-mode selection into, so selecting text
2981
+ * in a task's terminal puts it on the *system* clipboard rather than in a tmux
2982
+ * paste buffer no other application can read. Preferred over tmux's OSC 52
2983
+ * bridge, which plenty of emulators (VTE before 0.76, xterm without
2984
+ * `allowWindowOps`) drop on the floor.
2985
+ */
2986
+ declare function clipboardCopyCommand(hasBin?: HasBinFn, platform?: NodeJS.Platform, env?: NodeJS.ProcessEnv): string | null;
2965
2987
 
2966
2988
  declare class FsPluginStore implements IPluginStore {
2967
2989
  getUserPluginsDir(): string;
@@ -3022,4 +3044,4 @@ declare function sanitizeSlug(raw: string): string;
3022
3044
  /** Save the PRD to `<workspace>/.scratch/<slug>/PRD.md` (to-prd native convention). */
3023
3045
  declare function savePrdMarkdown(workspace: string, slug: string, markdown: string): string;
3024
3046
 
3025
- export { ALL_PROVIDERS, AUTO_COMMANDS, AbstractRunner, AbstractTerminalSession, ActiveTaskSession, type AgentAdapter, type AgentAdapterFactory, type AgentEvent, type AgentProcessDeps, type AgentStartOptions, AiProvider, ApprovalKind, ApprovalMode, ApprovalRequest, ApprovalSource, BaseAiService, BaseConfig, BaseFileSystem, CLAUDE_CODE_MANIFEST, CLI_PROVIDERS, CMD_EXE_MAX_COMMAND_LINE, CORE_PLANNER_PROMPT, type CappedRows, type CheckpointListener, ClaudeCodeAdapter, CliAgentAiService, type CliAgentAiServiceDeps, CodexAdapter, type CommandClassification, CommandLineTooLongError, type CommandTier, type ComposeOptions, ConsoleLogger, ContextCollector, ConversationMessage, type ConversationRequest, type ConversationTurn, DiscoveredModel, EmbeddedNewlineError, EnvConfig, type ExecFileFn, type ExecImpl, FindSymbolOptions, FsPluginStore, GIT_READONLY_SUBCOMMANDS, GeminiService, GlobOptions, type GrepInvocation, GrepOptions, HeadlessRunner, type HeadlessRunnerDeps, HeadlessSession, type IAiService, IApproval, IConfig, IFileSystem, type ILogger, type INotification, IPluginStore, ITerminalRunner, ITerminalSession, JSON_REPAIR_INSTRUCTION, type KillTreeDeps, type LaunchDeps, type LaunchPlan, LegacyPlanState, LineBuffer, type MappedTool, ModelResolver, type ModelResolverDeps, type ModifyPlanRequest, type NotificationAction, OPENCODE_MANIFEST, OpenAiService, OpenCodeAdapter, type OrchestratorObserver, OrchestratorOption, PROVIDER_DETECT_PRIORITY, PROVIDER_LABEL, PROVIDER_PRIORITY, PROVIDER_SHORT_LABEL, type PendingApproval, PendingApprovals, type PendingApprovalsOptions, PlanParseError, type PlanRequest, PlanState, PlanStatus, PlanStore, Planner, type PlannerReplyClassification, type PlannerRuntimeToggles, type PrdBlock, type PreparedLaunch, type PriorOutput, type ProbeFn, ProviderModelLists, type ProviderRegistration, QueuedMessage, REFUSED_COMMANDS, ReadFileOpts, type RepairLoopOpts, type RepairVerdict, type ResearchChat, ResearchLogEntry, ResearchProgress, type ResearchShell, type ResearchShellDeps, ResearchStep, ResearchToolType, type ResearchTurn, ResolveContext, type RunnerCatalog, RunnerId, RunnerInstallation, RunnerInvocation, type RunnerMode, RunnerModeInfo, RunnerPluginManifest, RunnerRegistry, type RunnerSpawnOptions, STATE_DIR, SYMBOL_LANGUAGES, type SerializedPlan, type SerializedTask, type SerializedTaskStatus, Session, type SessionBroadcaster, type SessionData, type SessionDeps, type SessionMessage, type SessionMeta, type SessionPlanner, type SessionRuntimeSettings, SettingsService, type ShellDialect, type SpawnSpec, StdioAgentAdapter, TRUNCATED_PLAN_REPAIR_INSTRUCTION, Task, TaskOp, TaskOrchestrator, TaskSnapshot, TmuxRunner, type TmuxRunnerDeps, type ToolCall, ToolOutcome, type ToolResult, type UserSettings, Verdict, VerdictEngine, type VerdictListener, WINDOWS_MAX_COMMAND_LINE, applyHeadLimit, augmentPromptWithPriorOutputs, augmentedPath, buildConversationSystemPrompt, buildFallbackGrepArgs, buildGlobArgs, buildGrepArgs, buildMergePrompt, buildModifyDuringExecutionPrompt, buildModifyPlanPrompt, buildPlanWithResults, buildResearchPrompt, buildResearchToolsPrompt, buildRunnerInvocation, buildShellInvocation, buildSplitPrompt, buildSubagentSystemPrompt, clampThinkingEffort, classifyCommand, classifyPlannerReply, clearAugmentedPathCache, clearResearchShellCache, clearState, coerceAssignments, collectDirectDependencyOutputs, composeAugmentedPrompt, configuredProviders, createAiService, defaultLogger, definitionPattern, deleteSession, discoverGeminiModels, effectiveAllowlist, ensureDir, executionLogBlock, executionSummary, extractPrdBlock, filterFallbackByAnchoredInclude, filterModelsForPrompt, formatSearchOutput, generatePlanWithRepair, getLatestSession, getProviderMeta, getSettingsPath, getStateDir, grantScopeFor, hasTmux, includeGlobFor, isCliProvider, isOpenAiProvider, killTree, languageForId, listSessions, loadSession, loadSessionPlanState, loadState, mapAgentTool, modelContextBlock, modifyValidationFeedback, normalizeAgentArgs, normalizeGeminiModel, pendingEditRulesBlock, planDirectLaunch, planShellLaunch, posixShellQuote, prefixModelId, providerForRunner, reEmitPlanPrompt, reEmitTaskOpsPrompt, referencePattern, renderPlanMap, renderPriorOutputs, repairLoop, researchShellWarning, researchToolsPath, resolveArgs, resolveProviderFromPrefix, resolveResearchShell, resolveWithin, retargetTaskRunner, runnerAssignment, runnerForProvider, sanitizeSlug, savePrdMarkdown, saveSession, saveState, serializePlan, serializeTask, serializeTaskStatus, sessionRuntimeSettings, stateExists, stripAnsi, stripModelPrefix, summarizeOutput, taskOpsRejectedPrompt, tmuxSessionName, tmuxSocketName, tmuxWindowName, truncatedPlanReEmitPrompt, wellKnownBinDirs, windowsCommandLine, withPath, wrapWithPty };
3047
+ export { ALL_PROVIDERS, AUTO_COMMANDS, AbstractRunner, AbstractTerminalSession, ActiveTaskSession, type AgentAdapter, type AgentAdapterFactory, type AgentEvent, type AgentProcessDeps, type AgentStartOptions, AiProvider, ApprovalKind, ApprovalMode, ApprovalRequest, ApprovalSource, BaseAiService, BaseConfig, BaseFileSystem, CLAUDE_CODE_MANIFEST, CLI_PROVIDERS, CMD_EXE_MAX_COMMAND_LINE, CORE_PLANNER_PROMPT, type CappedRows, type CheckpointListener, ClaudeCodeAdapter, CliAgentAiService, type CliAgentAiServiceDeps, CodexAdapter, type CommandClassification, CommandLineTooLongError, type CommandTier, type ComposeOptions, ConsoleLogger, ContextCollector, ConversationMessage, type ConversationRequest, type ConversationTurn, DiscoveredModel, EmbeddedNewlineError, EnvConfig, type ExecFileFn, type ExecImpl, FindSymbolOptions, FsPluginStore, GIT_READONLY_SUBCOMMANDS, GeminiService, GlobOptions, type GrepInvocation, GrepOptions, type HasBinFn, HeadlessRunner, type HeadlessRunnerDeps, HeadlessSession, type IAiService, IApproval, IConfig, IFileSystem, type ILogger, type INotification, IPluginStore, ITerminalRunner, ITerminalSession, JSON_REPAIR_INSTRUCTION, type KillTreeDeps, type LaunchDeps, type LaunchPlan, LegacyPlanState, LineBuffer, type MappedTool, ModelResolver, type ModelResolverDeps, type ModifyPlanRequest, type NotificationAction, OPENCODE_MANIFEST, OpenAiService, OpenCodeAdapter, type OrchestratorObserver, OrchestratorOption, PROVIDER_DETECT_PRIORITY, PROVIDER_LABEL, PROVIDER_PRIORITY, PROVIDER_SHORT_LABEL, type PendingApproval, PendingApprovals, type PendingApprovalsOptions, PlanParseError, type PlanRequest, PlanState, PlanStatus, PlanStore, Planner, type PlannerReplyClassification, type PlannerRuntimeToggles, type PrdBlock, type PreparedLaunch, type PriorOutput, type ProbeFn, ProviderModelLists, type ProviderRegistration, QueuedMessage, REFUSED_COMMANDS, ReadFileOpts, type RepairLoopOpts, type RepairVerdict, type ResearchChat, ResearchLogEntry, ResearchProgress, type ResearchShell, type ResearchShellDeps, ResearchStep, ResearchToolType, type ResearchTurn, ResolveContext, type RunnerCatalog, RunnerId, RunnerInstallation, RunnerInvocation, type RunnerMode, RunnerModeInfo, RunnerPluginManifest, RunnerRegistry, type RunnerSpawnOptions, STATE_DIR, SYMBOL_LANGUAGES, type SerializedPlan, type SerializedTask, type SerializedTaskStatus, Session, type SessionBroadcaster, type SessionData, type SessionDeps, type SessionMessage, type SessionMeta, type SessionPlanner, type SessionRuntimeSettings, SettingsService, type ShellDialect, type SpawnSpec, StdioAgentAdapter, TRUNCATED_PLAN_REPAIR_INSTRUCTION, Task, TaskOp, TaskOrchestrator, TaskSnapshot, TmuxRunner, type TmuxRunnerDeps, type ToolCall, ToolOutcome, type ToolResult, type UserSettings, Verdict, VerdictEngine, type VerdictListener, WINDOWS_MAX_COMMAND_LINE, applyHeadLimit, augmentPromptWithPriorOutputs, augmentedPath, buildConversationSystemPrompt, buildFallbackGrepArgs, buildGlobArgs, buildGrepArgs, buildMergePrompt, buildModifyDuringExecutionPrompt, buildModifyPlanPrompt, buildPlanWithResults, buildResearchPrompt, buildResearchToolsPrompt, buildRunnerInvocation, buildShellInvocation, buildSplitPrompt, buildSubagentSystemPrompt, clampThinkingEffort, classifyCommand, classifyPlannerReply, clearAugmentedPathCache, clearResearchShellCache, clearState, clipboardCopyCommand, coerceAssignments, collectDirectDependencyOutputs, composeAugmentedPrompt, configuredProviders, createAiService, defaultLogger, definitionPattern, deleteSession, discoverGeminiModels, effectiveAllowlist, ensureDir, executionLogBlock, executionSummary, extractPrdBlock, filterFallbackByAnchoredInclude, filterModelsForPrompt, formatSearchOutput, generatePlanWithRepair, getLatestSession, getProviderMeta, getSettingsPath, getStateDir, grantScopeFor, hasTmux, includeGlobFor, isCliProvider, isOpenAiProvider, killTree, languageForId, listSessions, loadSession, loadSessionPlanState, loadState, mapAgentTool, modelContextBlock, modifyValidationFeedback, normalizeAgentArgs, normalizeGeminiModel, pendingEditRulesBlock, planDirectLaunch, planShellLaunch, posixShellQuote, prefixModelId, providerForRunner, reEmitPlanPrompt, reEmitTaskOpsPrompt, referencePattern, renderPlanMap, renderPriorOutputs, repairLoop, researchShellWarning, researchToolsPath, resolveArgs, resolveProviderFromPrefix, resolveResearchShell, resolveWithin, retargetTaskRunner, runnerAssignment, runnerForProvider, sanitizeSlug, savePrdMarkdown, saveSession, saveState, serializePlan, serializeTask, serializeTaskStatus, sessionRuntimeSettings, stateExists, stripAnsi, stripModelPrefix, summarizeOutput, taskOpsRejectedPrompt, tmuxSessionName, tmuxSocketName, tmuxWindowName, truncatedPlanReEmitPrompt, wellKnownBinDirs, windowsCommandLine, withPath, wrapWithPty };
package/dist/index.js CHANGED
@@ -124,6 +124,7 @@ __export(index_exports, {
124
124
  clearAugmentedPathCache: () => clearAugmentedPathCache,
125
125
  clearResearchShellCache: () => clearResearchShellCache,
126
126
  clearState: () => clearState,
127
+ clipboardCopyCommand: () => clipboardCopyCommand,
127
128
  coerceAssignments: () => coerceAssignments,
128
129
  collectDirectDependencyOutputs: () => collectDirectDependencyOutputs,
129
130
  collectProviderCredentials: () => collectProviderCredentials,
@@ -11374,8 +11375,12 @@ var Block = /* @__PURE__ */ ((Block2) => {
11374
11375
  Block2[Block2["IfInteractive"] = 7] = "IfInteractive";
11375
11376
  Block2[Block2["IfHeadlessSession"] = 8] = "IfHeadlessSession";
11376
11377
  Block2[Block2["IfInteractiveVariant"] = 9] = "IfInteractiveVariant";
11378
+ Block2[Block2["IfProjectTrust"] = 10] = "IfProjectTrust";
11377
11379
  return Block2;
11378
11380
  })(Block || {});
11381
+ function isInteractive(ctx) {
11382
+ return ctx.interactive ?? !ctx.headless;
11383
+ }
11379
11384
  function resolveArgs(manifest, ctx) {
11380
11385
  const args = [];
11381
11386
  const env = {};
@@ -11444,6 +11449,8 @@ function parseBlockOpen(raw) {
11444
11449
  return 8 /* IfHeadlessSession */;
11445
11450
  case "{{if interactiveVariant}}":
11446
11451
  return 9 /* IfInteractiveVariant */;
11452
+ case "{{if projectTrust}}":
11453
+ return 10 /* IfProjectTrust */;
11447
11454
  default:
11448
11455
  return null;
11449
11456
  }
@@ -11465,19 +11472,24 @@ function shouldIncludeBlock(block, ctx) {
11465
11472
  // `--variant` is a headless-only flag: it exists on `opencode run` but not
11466
11473
  // on the interactive TUI, which exits immediately if handed an unknown flag.
11467
11474
  case 6 /* IfVariant */:
11468
- return !!ctx.thinkingEffort && !!ctx.headless;
11475
+ return !!ctx.thinkingEffort && !isInteractive(ctx);
11469
11476
  // Session-shape blocks: unlike IfHeadless (a permission-flag gate with a
11470
11477
  // plan-mode carve-out), these pick the CLI invocation shape — e.g.
11471
11478
  // opencode's `run` subcommand vs its interactive TUI — so no mode carve-out.
11472
11479
  case 7 /* IfInteractive */:
11473
- return !ctx.headless;
11480
+ return isInteractive(ctx);
11474
11481
  case 8 /* IfHeadlessSession */:
11475
- return !!ctx.headless;
11482
+ return !isInteractive(ctx);
11476
11483
  // Interactive counterpart of IfVariant, for runners whose TUI has no
11477
11484
  // variant flag and must receive the variant via env config instead.
11478
11485
  // Requires a provider-prefixed model: the config pins variant per model.
11479
11486
  case 9 /* IfInteractiveVariant */:
11480
- return !!ctx.thinkingEffort && !!ctx.model?.includes("/") && !ctx.headless;
11487
+ return !!ctx.thinkingEffort && !!ctx.model?.includes("/") && isInteractive(ctx);
11488
+ // Guards the flag/value pair that pre-trusts the workspace directory. The
11489
+ // condition, not the token, is what keeps a bare `-c` out of the args when
11490
+ // there is no cwd to name.
11491
+ case 10 /* IfProjectTrust */:
11492
+ return isInteractive(ctx) && !!ctx.cwd;
11481
11493
  default:
11482
11494
  return true;
11483
11495
  }
@@ -11498,6 +11510,10 @@ function resolveToken(token, manifest, ctx) {
11498
11510
  if (token === "{{model}}") return ctx.model || "";
11499
11511
  if (token === "{{thinkingEffort}}") return ctx.thinkingEffort || "";
11500
11512
  if (token === "{{mode}}") return ctx.mode || "build";
11513
+ if (token === "{{projectTrust}}") {
11514
+ if (!ctx.cwd) return "";
11515
+ return `projects.${JSON.stringify(ctx.cwd)}.trust_level="trusted"`;
11516
+ }
11501
11517
  if (token === "{{feature:thinking}}") {
11502
11518
  return manifest.features.thinkingFlag || "";
11503
11519
  }
@@ -11584,7 +11600,9 @@ function buildRunnerInvocation(opts) {
11584
11600
  thinkingEffort: opts.thinkingEffort,
11585
11601
  modelVariants: opts.modelVariants,
11586
11602
  mode: opts.mode ?? "build",
11587
- headless: opts.headless
11603
+ headless: opts.headless,
11604
+ interactive: opts.interactive,
11605
+ cwd: opts.cwd
11588
11606
  });
11589
11607
  }
11590
11608
 
@@ -11705,8 +11723,14 @@ var HeadlessRunner = class extends AbstractRunner {
11705
11723
  hasScriptCmd;
11706
11724
  resolvePath;
11707
11725
  launchDeps;
11708
- /** Session shape when the caller names none; the VS Code runner overrides it to interactive. */
11709
- defaultHeadless = true;
11726
+ /**
11727
+ * Session shape: a piped subprocess is not a terminal, so runners get their
11728
+ * non-interactive subcommand. The VS Code runner owns a pseudoterminal and
11729
+ * overrides this to true. Autonomy is a separate axis (see `ResolveContext`)
11730
+ * and stays on either way — no surface has a human answering permission
11731
+ * prompts on the orchestrator's behalf.
11732
+ */
11733
+ defaultInteractive = false;
11710
11734
  constructor(deps = {}) {
11711
11735
  super();
11712
11736
  this.spawnImpl = deps.spawnImpl ?? import_child_process6.spawn;
@@ -11719,7 +11743,7 @@ var HeadlessRunner = class extends AbstractRunner {
11719
11743
  }
11720
11744
  /** Everything up to, but not including, spawning — so a surface that owns its own child reaches the same decisions. */
11721
11745
  async prepareLaunch(opts) {
11722
- const headless = opts.headless ?? this.defaultHeadless;
11746
+ const interactive = this.defaultInteractive;
11723
11747
  const invocation = buildRunnerInvocation({
11724
11748
  runner: opts.runner,
11725
11749
  prompt: opts.prompt,
@@ -11727,11 +11751,13 @@ var HeadlessRunner = class extends AbstractRunner {
11727
11751
  thinkingEffort: opts.thinkingEffort,
11728
11752
  modelVariants: opts.modelVariants,
11729
11753
  mode: opts.mode,
11730
- headless,
11754
+ headless: opts.headless ?? true,
11755
+ interactive,
11756
+ cwd: opts.cwd,
11731
11757
  registry: opts.registry
11732
11758
  });
11733
11759
  const manifest = opts.registry?.get(opts.runner)?.manifest;
11734
- const pty = (manifest?.runner.requiresTty === true || !headless) && this.hasScriptCmd();
11760
+ const pty = (manifest?.runner.requiresTty === true || interactive) && this.hasScriptCmd();
11735
11761
  const resolvedPath = await this.resolvePath();
11736
11762
  const { command, args } = pty ? wrapWithPty(invocation.command, invocation.args) : { command: invocation.command, args: invocation.args };
11737
11763
  return {
@@ -11784,6 +11810,28 @@ function hasTmux(probe = defaultProbe) {
11784
11810
  return false;
11785
11811
  }
11786
11812
  }
11813
+ var defaultHasBin = (bin) => {
11814
+ try {
11815
+ (0, import_child_process7.execSync)(`${process.platform === "win32" ? "where" : "which"} ${bin}`, { stdio: "ignore" });
11816
+ return true;
11817
+ } catch {
11818
+ return false;
11819
+ }
11820
+ };
11821
+ function clipboardCopyCommand(hasBin = defaultHasBin, platform = process.platform, env = process.env) {
11822
+ const candidates = platform === "darwin" ? [["pbcopy", "pbcopy"]] : platform === "win32" ? [["clip.exe", "clip.exe"]] : [
11823
+ // Only prefer wl-copy when there is a Wayland display to talk to —
11824
+ // on X11 it is often installed but fails at copy time.
11825
+ ...env.WAYLAND_DISPLAY ? [["wl-copy", "wl-copy"]] : [],
11826
+ ["xclip", "xclip -selection clipboard"],
11827
+ ["xsel", "xsel --clipboard --input"],
11828
+ ["wl-copy", "wl-copy"]
11829
+ ];
11830
+ for (const [bin, command] of candidates) {
11831
+ if (hasBin(bin)) return command;
11832
+ }
11833
+ return null;
11834
+ }
11787
11835
 
11788
11836
  // src/services/TmuxRunner.ts
11789
11837
  var EXIT_RE = /<<<ORDEWELL_TMUX_EXIT:(\d+)>>>/;
@@ -11893,6 +11941,7 @@ var TmuxRunner = class extends AbstractRunner {
11893
11941
  resolvePath;
11894
11942
  pollIntervalMs;
11895
11943
  logDir;
11944
+ clipboardCommand;
11896
11945
  /** Retries get a freshly named window so a failed attempt's output stays inspectable. */
11897
11946
  attempts = /* @__PURE__ */ new Map();
11898
11947
  ready = null;
@@ -11904,6 +11953,7 @@ var TmuxRunner = class extends AbstractRunner {
11904
11953
  this.resolvePath = deps.resolvePath ?? augmentedPath;
11905
11954
  this.pollIntervalMs = deps.pollIntervalMs ?? 500;
11906
11955
  this.logDir = deps.logDir ?? (0, import_os.tmpdir)();
11956
+ this.clipboardCommand = deps.clipboardCommand ?? (() => clipboardCopyCommand());
11907
11957
  }
11908
11958
  /**
11909
11959
  * Reaps a session orphaned by a crashed prior daemon on the same port, then
@@ -11932,25 +11982,44 @@ var TmuxRunner = class extends AbstractRunner {
11932
11982
  await this.configureScrolling();
11933
11983
  }
11934
11984
  /**
11935
- * Makes an attached runner terminal scrollable with the mouse wheel and
11936
- * Page Up/Down. A fresh tmux session ships with `mouse off`, a 2000-line
11937
- * scrollback, and no PageUp binding — none of which lets a user page back
11938
- * through a finished task's output, which is the whole point of opening its
11939
- * window. Scoping is harmless: the daemon owns a private socket
11940
- * (`tmuxSocketName`), so these server-wide options touch nothing but its
11941
- * own session. Best-effort so an ancient or stripped tmux cannot stop tasks
11942
- * from spawning — the session still works without the scroll comforts.
11985
+ * Gives an attached runner terminal wheel/PageUp scrolling over a deep
11986
+ * scrollback, and a mouse selection that reaches the system clipboard — none
11987
+ * of which a default tmux session does. Server-wide scoping is harmless: the
11988
+ * daemon owns a private socket (`tmuxSocketName`).
11989
+ *
11990
+ * `mouse on` is what costs the emulator's own drag-select, so tmux must hand
11991
+ * the selection back out itself: via a clipboard binary when there is one,
11992
+ * and via OSC 52 (`set-clipboard`) for what that cannot cover, such as
11993
+ * viewing over SSH. Naming the binary on the binding as well as in
11994
+ * `copy-command` keeps drag-to-copy working on tmux older than 3.2, which has
11995
+ * no `copy-command`.
11943
11996
  */
11944
11997
  async configureScrolling() {
11945
- try {
11946
- await this.tmux(["set-option", "-g", "history-limit", "100000"]);
11947
- await this.tmux(["set-option", "-g", "mouse", "on"]);
11948
- await this.tmux(["bind-key", "-n", "PageUp", "copy-mode", "-u"]);
11949
- await this.tmux(["bind-key", "-T", "copy-mode", "PageUp", "send-keys", "-X", "page-up"]);
11950
- await this.tmux(["bind-key", "-T", "copy-mode", "PageDown", "send-keys", "-X", "page-down"]);
11951
- await this.tmux(["bind-key", "-T", "copy-mode-vi", "PageUp", "send-keys", "-X", "page-up"]);
11952
- await this.tmux(["bind-key", "-T", "copy-mode-vi", "PageDown", "send-keys", "-X", "page-down"]);
11953
- } catch {
11998
+ const clip = this.clipboardCommand();
11999
+ const copySelection = clip ? ["copy-pipe-and-cancel", clip] : ["copy-pipe-and-cancel"];
12000
+ const commands = [
12001
+ // `history-limit` only governs windows created after it is set, so it
12002
+ // must run before any `new-window` — once, here at session creation.
12003
+ ["set-option", "-g", "history-limit", "100000"],
12004
+ ["set-option", "-g", "mouse", "on"],
12005
+ ["set-option", "-g", "set-clipboard", "on"],
12006
+ ...clip ? [["set-option", "-g", "copy-command", clip]] : [],
12007
+ ["bind-key", "-T", "copy-mode", "MouseDragEnd1Pane", "send-keys", "-X", ...copySelection],
12008
+ ["bind-key", "-T", "copy-mode-vi", "MouseDragEnd1Pane", "send-keys", "-X", ...copySelection],
12009
+ // Root-table PageUp; otherwise the key goes to the inner app and never
12010
+ // reaches tmux's scrollback. Both mode tables, so `mode-keys` can't
12011
+ // decide whether paging works.
12012
+ ["bind-key", "-n", "PageUp", "copy-mode", "-u"],
12013
+ ["bind-key", "-T", "copy-mode", "PageUp", "send-keys", "-X", "page-up"],
12014
+ ["bind-key", "-T", "copy-mode", "PageDown", "send-keys", "-X", "page-down"],
12015
+ ["bind-key", "-T", "copy-mode-vi", "PageUp", "send-keys", "-X", "page-up"],
12016
+ ["bind-key", "-T", "copy-mode-vi", "PageDown", "send-keys", "-X", "page-down"]
12017
+ ];
12018
+ for (const args of commands) {
12019
+ try {
12020
+ await this.tmux(args);
12021
+ } catch {
12022
+ }
11954
12023
  }
11955
12024
  }
11956
12025
  /**
@@ -11975,7 +12044,14 @@ var TmuxRunner = class extends AbstractRunner {
11975
12044
  thinkingEffort: opts.thinkingEffort,
11976
12045
  modelVariants: opts.modelVariants,
11977
12046
  mode: opts.mode,
12047
+ // A tmux window is a real TTY the user can attach to (ADR-0007), so the
12048
+ // runner's own TUI is the point — `interactive`. It is still an
12049
+ // unattended run, so autonomy stays on: the two are separate axes, and
12050
+ // conflating them is what made Codex tasks stream `codex exec` output
12051
+ // into a window that was supposed to show its TUI.
11978
12052
  headless: opts.headless ?? true,
12053
+ interactive: true,
12054
+ cwd: opts.cwd,
11979
12055
  registry: opts.registry
11980
12056
  });
11981
12057
  await this.ensureSession();
@@ -12213,18 +12289,33 @@ var CODEX_MANIFEST = {
12213
12289
  version: "1.0.0",
12214
12290
  runner: {
12215
12291
  command: "codex",
12216
- // Headless surfaces (CLI/web) use the non-interactive `exec` subcommand
12217
- // (`--skip-git-repo-check`: task workspaces aren't always git repos, and
12218
- // exec hard-fails outside one by default); interactive surfaces (VS Code
12219
- // terminal) launch the TUI with the prompt as its positional argument.
12220
- // Reasoning effort has no dedicated flag — it travels as a `-c` config
12221
- // override (see {{feature:reasoningEffortConfig}}). Both `exec` and the
12222
- // TUI accept `-m`, `-c`, and `--sandbox`.
12292
+ // Headless surfaces (a piped subprocess) use the non-interactive `exec`
12293
+ // subcommand (`--skip-git-repo-check`: task workspaces aren't always git
12294
+ // repos, and exec hard-fails outside one by default); interactive surfaces
12295
+ // (a tmux window, the VS Code terminal) launch the TUI with the prompt as
12296
+ // its positional argument. Reasoning effort has no dedicated flag — it
12297
+ // travels as a `-c` config override (see {{feature:reasoningEffortConfig}}).
12298
+ // Both `exec` and the TUI accept `-m`, `-c`, and `--sandbox`.
12299
+ //
12300
+ // The two interactive-only entries restore what `exec` gives implicitly and
12301
+ // the TUI does not: `exec` is non-interactive, so it can neither ask for
12302
+ // command approval nor ask whether the directory is trusted. The TUI asks
12303
+ // for both by default, and an orchestrated task has nobody to answer —
12304
+ // without these it stalls on a menu instead of working. `-a` does not exist
12305
+ // on `exec`, hence the shape gate rather than a `{{if headless}}` one.
12223
12306
  argsTemplate: [
12224
12307
  "{{if headlessSession}}",
12225
12308
  "exec",
12226
12309
  "--skip-git-repo-check",
12227
12310
  "{{/if}}",
12311
+ "{{if interactive}}",
12312
+ "-a",
12313
+ "never",
12314
+ "{{/if}}",
12315
+ "{{if projectTrust}}",
12316
+ "-c",
12317
+ "{{projectTrust}}",
12318
+ "{{/if}}",
12228
12319
  "{{if model}}",
12229
12320
  "-m",
12230
12321
  "{{model}}",
@@ -12244,9 +12335,9 @@ var CODEX_MANIFEST = {
12244
12335
  planMode: true,
12245
12336
  planModeFlag: "--sandbox",
12246
12337
  permissionModeValues: {
12247
- // Map mode IDs to --sandbox CLI values. `codex exec` is non-interactive
12248
- // and has no approval flag, so the sandbox axis is the whole permission
12249
- // story for headless runs.
12338
+ // Map mode IDs to --sandbox CLI values. Approvals are off on both shapes
12339
+ // (implicitly under `exec`, via `-a never` in the TUI), so the sandbox
12340
+ // axis is the whole permission story for a Codex task.
12250
12341
  "agent": "workspace-write",
12251
12342
  "plan": "read-only",
12252
12343
  "fullAccess": "danger-full-access",
@@ -12854,6 +12945,7 @@ var SettingsService = class {
12854
12945
  clearAugmentedPathCache,
12855
12946
  clearResearchShellCache,
12856
12947
  clearState,
12948
+ clipboardCopyCommand,
12857
12949
  coerceAssignments,
12858
12950
  collectDirectDependencyOutputs,
12859
12951
  collectProviderCredentials,