@ai-hero/sandcastle 0.7.0 → 0.8.0

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/README.md CHANGED
@@ -775,7 +775,7 @@ Removes the Podman image.
775
775
 
776
776
  | Option | Type | Default | Description |
777
777
  | -------------------------- | ------------------ | ----------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
778
- | `agent` | AgentProvider | — | **Required.** Agent provider (e.g. `claudeCode("claude-opus-4-7")`, `pi("claude-sonnet-4-6")`, `codex("gpt-5.4-mini")`, `cursor("composer-2")`, `opencode("opencode/big-pickle")`, `copilot("claude-sonnet-4.5")`) |
778
+ | `agent` | AgentProvider | — | **Required.** Agent provider (e.g. `claudeCode("claude-opus-4-7")`, `pi("claude-sonnet-4-6")`, `codex("gpt-5.4")`, `cursor("composer-2")`, `opencode("opencode/big-pickle")`, `copilot("claude-sonnet-4.5")`) |
779
779
  | `sandbox` | SandboxProvider | — | **Required.** Sandbox provider (e.g. `docker()`, `podman()`, `docker({ imageName: "sandcastle:local" })`) |
780
780
  | `cwd` | string | `process.cwd()` | Host repo directory — anchor for `.sandcastle/` artifacts and git operations. Relative paths resolve against `process.cwd()`. |
781
781
  | `prompt` | string | — | Inline prompt (mutually exclusive with `promptFile`) |
@@ -847,7 +847,7 @@ You can also continue the last captured session from a result:
847
847
 
848
848
  ```typescript
849
849
  const first = await run({
850
- agent: codex("gpt-5.4-mini"),
850
+ agent: codex("gpt-5.4"),
851
851
  sandbox: docker(),
852
852
  prompt: "Draft a plan",
853
853
  });
@@ -901,11 +901,12 @@ The `claudeCode()` factory accepts an optional second argument for provider-spec
901
901
  agent: claudeCode("claude-opus-4-7", { effort: "high" });
902
902
  ```
903
903
 
904
- | Option | Type | Default | Description |
905
- | ----------------- | --------------------------------------------------------- | ------- | --------------------------------------------------------- |
906
- | `effort` | `"low"` \| `"medium"` \| `"high"` \| `"xhigh"` \| `"max"` | — | Claude Code reasoning effort level (`max` is Opus only) |
907
- | `env` | `Record<string, string>` | `{}` | Environment variables injected by this agent provider |
908
- | `captureSessions` | `boolean` | `true` | Capture agent session JSONL to host for `claude --resume` |
904
+ | Option | Type | Default | Description |
905
+ | ----------------- | ---------------------------------------------------------------------------------------------- | ------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
906
+ | `effort` | `"low"` \| `"medium"` \| `"high"` \| `"xhigh"` \| `"max"` | — | Claude Code reasoning effort level (`max` is Opus only) |
907
+ | `env` | `Record<string, string>` | `{}` | Environment variables injected by this agent provider |
908
+ | `captureSessions` | `boolean` | `true` | Capture agent session JSONL to host for `claude --resume` |
909
+ | `permissionMode` | `"default"` \| `"acceptEdits"` \| `"plan"` \| `"auto"` \| `"dontAsk"` \| `"bypassPermissions"` | — | Maps to Claude's `--permission-mode` flag. When set, replaces Sandcastle's default `--dangerously-skip-permissions` on AFK runs. Use `"auto"` for AI-mediated per-tool approve/deny without bypass. |
909
910
 
910
911
  ### `CodexOptions`
911
912
 
@@ -915,11 +916,12 @@ The `codex()` factory accepts an optional second argument for provider-specific
915
916
  agent: codex("gpt-5.4", { effort: "high" });
916
917
  ```
917
918
 
918
- | Option | Type | Default | Description |
919
- | ----------------- | ---------------------------------------------- | ------- | --------------------------------------------------------- |
920
- | `effort` | `"low"` \| `"medium"` \| `"high"` \| `"xhigh"` | — | Codex reasoning effort level via `model_reasoning_effort` |
921
- | `env` | `Record<string, string>` | `{}` | Environment variables injected by this agent provider |
922
- | `captureSessions` | `boolean` | `true` | Capture Codex rollout JSONL to host for resume |
919
+ | Option | Type | Default | Description |
920
+ | ------------------- | ---------------------------------------------- | ------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
921
+ | `effort` | `"low"` \| `"medium"` \| `"high"` \| `"xhigh"` | — | Codex reasoning effort level via `model_reasoning_effort` |
922
+ | `env` | `Record<string, string>` | `{}` | Environment variables injected by this agent provider |
923
+ | `captureSessions` | `boolean` | `true` | Capture Codex rollout JSONL to host for resume |
924
+ | `approvalsReviewer` | `"user"` \| `"auto_review"` | — | Maps to Codex's `approvals_reviewer` config. When `"auto_review"`, swaps `--dangerously-bypass-approvals-and-sandbox` for `-a on-request -s danger-full-access` so the reviewer agent evaluates each approval prompt. |
923
925
 
924
926
  ### `PiOptions`
925
927
 
package/dist/index.d.ts CHANGED
@@ -175,6 +175,16 @@ interface CodexOptions {
175
175
  readonly hostSessionsDir?: string;
176
176
  readonly sandboxSessionsDir?: string;
177
177
  };
178
+ /**
179
+ * Maps to Codex's `approvals_reviewer` config key (set via
180
+ * `-c approvals_reviewer="<value>"`). When set to `"auto_review"`, the
181
+ * provider swaps the default `--dangerously-bypass-approvals-and-sandbox`
182
+ * for an interactive approval policy (`-a on-request`) and Codex's most
183
+ * permissive sandbox (`-s danger-full-access`) — auto-review needs
184
+ * something to review, and the safety boundary is the reviewer agent
185
+ * rather than the filesystem sandbox.
186
+ */
187
+ readonly approvalsReviewer?: "user" | "auto_review";
178
188
  }
179
189
  declare const codex: (model: string, options?: CodexOptions) => AgentProvider & {
180
190
  readonly sessionStorage: AgentSessionStorage;
@@ -218,6 +228,13 @@ interface ClaudeCodeOptions {
218
228
  readonly hostProjectsDir?: string;
219
229
  readonly sandboxProjectsDir?: string;
220
230
  };
231
+ /**
232
+ * Maps directly to Claude's `--permission-mode` flag. When set, replaces the
233
+ * default `--dangerously-skip-permissions` Sandcastle passes on AFK runs —
234
+ * the two flags are mutually exclusive on Claude's CLI. Use `"auto"` for
235
+ * AI-mediated per-tool approve/deny on unsandboxed host runs.
236
+ */
237
+ readonly permissionMode?: "default" | "acceptEdits" | "plan" | "auto" | "dontAsk" | "bypassPermissions";
221
238
  }
222
239
  declare const claudeCode: (model: string, options?: ClaudeCodeOptions) => AgentProvider & {
223
240
  readonly sessionStorage: AgentSessionStorage;
package/dist/index.js CHANGED
@@ -2961,6 +2961,7 @@ var codex = (model, options) => ({
2961
2961
  forkSession
2962
2962
  }) {
2963
2963
  const effortFlag = options?.effort ? ` -c ${shellEscape(`model_reasoning_effort="${options.effort}"`)}` : "";
2964
+ const approvalsFlags = options?.approvalsReviewer === "auto_review" ? ` -a on-request -s danger-full-access -c ${shellEscape(`approvals_reviewer="auto_review"`)}` : " --dangerously-bypass-approvals-and-sandbox";
2964
2965
  let base;
2965
2966
  if (resumeSession && forkSession) {
2966
2967
  base = `codex exec fork ${shellEscape(resumeSession)}`;
@@ -2971,7 +2972,7 @@ var codex = (model, options) => ({
2971
2972
  }
2972
2973
  const stdinArg = resumeSession ? " -" : "";
2973
2974
  return {
2974
- command: `${base} --json --dangerously-bypass-approvals-and-sandbox -m ${shellEscape(model)}${effortFlag}${stdinArg}`,
2975
+ command: `${base} --json${approvalsFlags} -m ${shellEscape(model)}${effortFlag}${stdinArg}`,
2975
2976
  stdin: prompt
2976
2977
  };
2977
2978
  },
@@ -3070,7 +3071,7 @@ var opencode = (model, options) => ({
3070
3071
  buildInteractiveArgs({ prompt }) {
3071
3072
  const args = ["opencode", "--model", model];
3072
3073
  if (options?.agent) args.push("--agent", options.agent);
3073
- if (prompt) args.push("-p", prompt);
3074
+ if (prompt) args.push("--prompt", prompt);
3074
3075
  return args;
3075
3076
  },
3076
3077
  parseStreamLine(line) {
@@ -3160,12 +3161,12 @@ var claudeCode = (model, options) => ({
3160
3161
  resumeSession,
3161
3162
  forkSession
3162
3163
  }) {
3163
- const skipPerms = dangerouslySkipPermissions ? " --dangerously-skip-permissions" : "";
3164
+ const permissionFlag = options?.permissionMode ? ` --permission-mode ${options.permissionMode}` : dangerouslySkipPermissions ? " --dangerously-skip-permissions" : "";
3164
3165
  const effortFlag = options?.effort ? ` --effort ${options.effort}` : "";
3165
3166
  const resumeFlag = resumeSession ? ` --resume ${shellEscape(resumeSession)}` : "";
3166
3167
  const forkFlag = resumeSession && forkSession ? " --fork-session" : "";
3167
3168
  return {
3168
- command: `claude --print --verbose${skipPerms} --output-format stream-json --model ${shellEscape(model)}${effortFlag}${resumeFlag}${forkFlag} -p -`,
3169
+ command: `claude --print --verbose${permissionFlag} --output-format stream-json --model ${shellEscape(model)}${effortFlag}${resumeFlag}${forkFlag} -p -`,
3169
3170
  stdin: prompt
3170
3171
  };
3171
3172
  },
@@ -3174,7 +3175,11 @@ var claudeCode = (model, options) => ({
3174
3175
  dangerouslySkipPermissions
3175
3176
  }) {
3176
3177
  const args = ["claude"];
3177
- if (dangerouslySkipPermissions) args.push("--dangerously-skip-permissions");
3178
+ if (options?.permissionMode) {
3179
+ args.push("--permission-mode", options.permissionMode);
3180
+ } else if (dangerouslySkipPermissions) {
3181
+ args.push("--dangerously-skip-permissions");
3182
+ }
3178
3183
  args.push("--model", model);
3179
3184
  if (options?.effort) args.push("--effort", options.effort);
3180
3185
  if (prompt) args.push(prompt);