@ordewell/core 0.4.3 → 0.4.4

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/index.mjs CHANGED
@@ -9890,8 +9890,12 @@ var Block = /* @__PURE__ */ ((Block2) => {
9890
9890
  Block2[Block2["IfInteractive"] = 7] = "IfInteractive";
9891
9891
  Block2[Block2["IfHeadlessSession"] = 8] = "IfHeadlessSession";
9892
9892
  Block2[Block2["IfInteractiveVariant"] = 9] = "IfInteractiveVariant";
9893
+ Block2[Block2["IfProjectTrust"] = 10] = "IfProjectTrust";
9893
9894
  return Block2;
9894
9895
  })(Block || {});
9896
+ function isInteractive(ctx) {
9897
+ return ctx.interactive ?? !ctx.headless;
9898
+ }
9895
9899
  function resolveArgs(manifest, ctx) {
9896
9900
  const args = [];
9897
9901
  const env = {};
@@ -9960,6 +9964,8 @@ function parseBlockOpen(raw) {
9960
9964
  return 8 /* IfHeadlessSession */;
9961
9965
  case "{{if interactiveVariant}}":
9962
9966
  return 9 /* IfInteractiveVariant */;
9967
+ case "{{if projectTrust}}":
9968
+ return 10 /* IfProjectTrust */;
9963
9969
  default:
9964
9970
  return null;
9965
9971
  }
@@ -9981,19 +9987,24 @@ function shouldIncludeBlock(block, ctx) {
9981
9987
  // `--variant` is a headless-only flag: it exists on `opencode run` but not
9982
9988
  // on the interactive TUI, which exits immediately if handed an unknown flag.
9983
9989
  case 6 /* IfVariant */:
9984
- return !!ctx.thinkingEffort && !!ctx.headless;
9990
+ return !!ctx.thinkingEffort && !isInteractive(ctx);
9985
9991
  // Session-shape blocks: unlike IfHeadless (a permission-flag gate with a
9986
9992
  // plan-mode carve-out), these pick the CLI invocation shape — e.g.
9987
9993
  // opencode's `run` subcommand vs its interactive TUI — so no mode carve-out.
9988
9994
  case 7 /* IfInteractive */:
9989
- return !ctx.headless;
9995
+ return isInteractive(ctx);
9990
9996
  case 8 /* IfHeadlessSession */:
9991
- return !!ctx.headless;
9997
+ return !isInteractive(ctx);
9992
9998
  // Interactive counterpart of IfVariant, for runners whose TUI has no
9993
9999
  // variant flag and must receive the variant via env config instead.
9994
10000
  // Requires a provider-prefixed model: the config pins variant per model.
9995
10001
  case 9 /* IfInteractiveVariant */:
9996
- return !!ctx.thinkingEffort && !!ctx.model?.includes("/") && !ctx.headless;
10002
+ return !!ctx.thinkingEffort && !!ctx.model?.includes("/") && isInteractive(ctx);
10003
+ // Guards the flag/value pair that pre-trusts the workspace directory. The
10004
+ // condition, not the token, is what keeps a bare `-c` out of the args when
10005
+ // there is no cwd to name.
10006
+ case 10 /* IfProjectTrust */:
10007
+ return isInteractive(ctx) && !!ctx.cwd;
9997
10008
  default:
9998
10009
  return true;
9999
10010
  }
@@ -10014,6 +10025,10 @@ function resolveToken(token, manifest, ctx) {
10014
10025
  if (token === "{{model}}") return ctx.model || "";
10015
10026
  if (token === "{{thinkingEffort}}") return ctx.thinkingEffort || "";
10016
10027
  if (token === "{{mode}}") return ctx.mode || "build";
10028
+ if (token === "{{projectTrust}}") {
10029
+ if (!ctx.cwd) return "";
10030
+ return `projects.${JSON.stringify(ctx.cwd)}.trust_level="trusted"`;
10031
+ }
10017
10032
  if (token === "{{feature:thinking}}") {
10018
10033
  return manifest.features.thinkingFlag || "";
10019
10034
  }
@@ -10100,7 +10115,9 @@ function buildRunnerInvocation(opts) {
10100
10115
  thinkingEffort: opts.thinkingEffort,
10101
10116
  modelVariants: opts.modelVariants,
10102
10117
  mode: opts.mode ?? "build",
10103
- headless: opts.headless
10118
+ headless: opts.headless,
10119
+ interactive: opts.interactive,
10120
+ cwd: opts.cwd
10104
10121
  });
10105
10122
  }
10106
10123
 
@@ -10221,8 +10238,14 @@ var HeadlessRunner = class extends AbstractRunner {
10221
10238
  hasScriptCmd;
10222
10239
  resolvePath;
10223
10240
  launchDeps;
10224
- /** Session shape when the caller names none; the VS Code runner overrides it to interactive. */
10225
- defaultHeadless = true;
10241
+ /**
10242
+ * Session shape: a piped subprocess is not a terminal, so runners get their
10243
+ * non-interactive subcommand. The VS Code runner owns a pseudoterminal and
10244
+ * overrides this to true. Autonomy is a separate axis (see `ResolveContext`)
10245
+ * and stays on either way — no surface has a human answering permission
10246
+ * prompts on the orchestrator's behalf.
10247
+ */
10248
+ defaultInteractive = false;
10226
10249
  constructor(deps = {}) {
10227
10250
  super();
10228
10251
  this.spawnImpl = deps.spawnImpl ?? nodeSpawn2;
@@ -10235,7 +10258,7 @@ var HeadlessRunner = class extends AbstractRunner {
10235
10258
  }
10236
10259
  /** Everything up to, but not including, spawning — so a surface that owns its own child reaches the same decisions. */
10237
10260
  async prepareLaunch(opts) {
10238
- const headless = opts.headless ?? this.defaultHeadless;
10261
+ const interactive = this.defaultInteractive;
10239
10262
  const invocation = buildRunnerInvocation({
10240
10263
  runner: opts.runner,
10241
10264
  prompt: opts.prompt,
@@ -10243,11 +10266,13 @@ var HeadlessRunner = class extends AbstractRunner {
10243
10266
  thinkingEffort: opts.thinkingEffort,
10244
10267
  modelVariants: opts.modelVariants,
10245
10268
  mode: opts.mode,
10246
- headless,
10269
+ headless: opts.headless ?? true,
10270
+ interactive,
10271
+ cwd: opts.cwd,
10247
10272
  registry: opts.registry
10248
10273
  });
10249
10274
  const manifest = opts.registry?.get(opts.runner)?.manifest;
10250
- const pty = (manifest?.runner.requiresTty === true || !headless) && this.hasScriptCmd();
10275
+ const pty = (manifest?.runner.requiresTty === true || interactive) && this.hasScriptCmd();
10251
10276
  const resolvedPath = await this.resolvePath();
10252
10277
  const { command, args } = pty ? wrapWithPty(invocation.command, invocation.args) : { command: invocation.command, args: invocation.args };
10253
10278
  return {
@@ -10491,7 +10516,14 @@ var TmuxRunner = class extends AbstractRunner {
10491
10516
  thinkingEffort: opts.thinkingEffort,
10492
10517
  modelVariants: opts.modelVariants,
10493
10518
  mode: opts.mode,
10519
+ // A tmux window is a real TTY the user can attach to (ADR-0007), so the
10520
+ // runner's own TUI is the point — `interactive`. It is still an
10521
+ // unattended run, so autonomy stays on: the two are separate axes, and
10522
+ // conflating them is what made Codex tasks stream `codex exec` output
10523
+ // into a window that was supposed to show its TUI.
10494
10524
  headless: opts.headless ?? true,
10525
+ interactive: true,
10526
+ cwd: opts.cwd,
10495
10527
  registry: opts.registry
10496
10528
  });
10497
10529
  await this.ensureSession();
@@ -10729,18 +10761,33 @@ var CODEX_MANIFEST = {
10729
10761
  version: "1.0.0",
10730
10762
  runner: {
10731
10763
  command: "codex",
10732
- // Headless surfaces (CLI/web) use the non-interactive `exec` subcommand
10733
- // (`--skip-git-repo-check`: task workspaces aren't always git repos, and
10734
- // exec hard-fails outside one by default); interactive surfaces (VS Code
10735
- // terminal) launch the TUI with the prompt as its positional argument.
10736
- // Reasoning effort has no dedicated flag — it travels as a `-c` config
10737
- // override (see {{feature:reasoningEffortConfig}}). Both `exec` and the
10738
- // TUI accept `-m`, `-c`, and `--sandbox`.
10764
+ // Headless surfaces (a piped subprocess) use the non-interactive `exec`
10765
+ // subcommand (`--skip-git-repo-check`: task workspaces aren't always git
10766
+ // repos, and exec hard-fails outside one by default); interactive surfaces
10767
+ // (a tmux window, the VS Code terminal) launch the TUI with the prompt as
10768
+ // its positional argument. Reasoning effort has no dedicated flag — it
10769
+ // travels as a `-c` config override (see {{feature:reasoningEffortConfig}}).
10770
+ // Both `exec` and the TUI accept `-m`, `-c`, and `--sandbox`.
10771
+ //
10772
+ // The two interactive-only entries restore what `exec` gives implicitly and
10773
+ // the TUI does not: `exec` is non-interactive, so it can neither ask for
10774
+ // command approval nor ask whether the directory is trusted. The TUI asks
10775
+ // for both by default, and an orchestrated task has nobody to answer —
10776
+ // without these it stalls on a menu instead of working. `-a` does not exist
10777
+ // on `exec`, hence the shape gate rather than a `{{if headless}}` one.
10739
10778
  argsTemplate: [
10740
10779
  "{{if headlessSession}}",
10741
10780
  "exec",
10742
10781
  "--skip-git-repo-check",
10743
10782
  "{{/if}}",
10783
+ "{{if interactive}}",
10784
+ "-a",
10785
+ "never",
10786
+ "{{/if}}",
10787
+ "{{if projectTrust}}",
10788
+ "-c",
10789
+ "{{projectTrust}}",
10790
+ "{{/if}}",
10744
10791
  "{{if model}}",
10745
10792
  "-m",
10746
10793
  "{{model}}",
@@ -10760,9 +10807,9 @@ var CODEX_MANIFEST = {
10760
10807
  planMode: true,
10761
10808
  planModeFlag: "--sandbox",
10762
10809
  permissionModeValues: {
10763
- // Map mode IDs to --sandbox CLI values. `codex exec` is non-interactive
10764
- // and has no approval flag, so the sandbox axis is the whole permission
10765
- // story for headless runs.
10810
+ // Map mode IDs to --sandbox CLI values. Approvals are off on both shapes
10811
+ // (implicitly under `exec`, via `-a never` in the TUI), so the sandbox
10812
+ // axis is the whole permission story for a Codex task.
10766
10813
  "agent": "workspace-write",
10767
10814
  "plan": "read-only",
10768
10815
  "fullAccess": "danger-full-access",