@hasna/loops 0.4.8 → 0.4.9

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.js CHANGED
@@ -579,7 +579,7 @@ import { isAbsolute, resolve } from "path";
579
579
 
580
580
  // src/lib/agent-adapter.ts
581
581
  import { spawn } from "child_process";
582
- var UNSAFE_CODEWITH_DURABLE_EXTRA_ARGS = new Set([
582
+ var UNSAFE_CODEWITH_EXEC_EXTRA_ARGS = new Set([
583
583
  "e",
584
584
  "exec",
585
585
  "agent",
@@ -628,12 +628,12 @@ function validateAgentOptions(target, label, capabilities) {
628
628
  throw new Error(`${label}.agent is not supported for provider codex`);
629
629
  }
630
630
  if (provider === "codewith" && target.agent !== undefined) {
631
- throw new Error(`${label}.agent is not supported for provider codewith durable background-agent execution`);
631
+ throw new Error(`${label}.agent is not supported for provider codewith`);
632
632
  }
633
633
  if (provider === "codewith") {
634
- const unsafe = target.extraArgs?.find((arg) => UNSAFE_CODEWITH_DURABLE_EXTRA_ARGS.has(arg));
634
+ const unsafe = target.extraArgs?.find((arg) => UNSAFE_CODEWITH_EXEC_EXTRA_ARGS.has(arg));
635
635
  if (unsafe) {
636
- throw new Error(`${label}.extraArgs cannot include ${unsafe}; codewith agent steps use durable agent start, not exec/ephemeral flags`);
636
+ throw new Error(`${label}.extraArgs cannot include ${unsafe}; codewith exec launch flags are managed by the adapter`);
637
637
  }
638
638
  }
639
639
  if (target.addDirs?.length && !["codewith", "codex"].includes(provider)) {
@@ -716,7 +716,10 @@ function buildAgentInvocation(target) {
716
716
  args.push(...target.authProfile ? ["--auth-profile", target.authProfile] : []);
717
717
  if (target.variant)
718
718
  args.push("-c", `model_reasoning_effort=${configStringValue(target.variant)}`);
719
- args.push("--ask-for-approval", "never", "--sandbox", codewithLikeSandbox(target));
719
+ const sandbox = codewithLikeSandbox(target);
720
+ if (sandbox === "workspace-write")
721
+ args.push("-c", "sandbox_workspace_write.network_access=true");
722
+ args.push("--ask-for-approval", "never", "exec", "--json", "--ephemeral", "--sandbox", sandbox, "--skip-git-repo-check");
720
723
  if (target.cwd)
721
724
  args.push("--cd", target.cwd);
722
725
  for (const dir of target.addDirs ?? [])
@@ -724,11 +727,7 @@ function buildAgentInvocation(target) {
724
727
  if (target.model)
725
728
  args.push("--model", target.model);
726
729
  args.push(...target.extraArgs ?? []);
727
- args.push("agent", "start", "--json");
728
- if (target.cwd)
729
- args.push("--cwd", target.cwd);
730
- args.push(target.prompt);
731
- return { command: "codewith", args };
730
+ return { command: "codewith", args, stdin: target.prompt };
732
731
  }
733
732
  case "codex": {
734
733
  if (target.variant)
@@ -781,7 +780,7 @@ function adapterFor(provider, capabilities) {
781
780
  var PROVIDER_ADAPTERS = {
782
781
  claude: adapterFor("claude", { sandbox: [], durable: false, remote: true, promptChannel: "stdin" }),
783
782
  cursor: adapterFor("cursor", { sandbox: CURSOR_SANDBOXES, durable: false, remote: true, promptChannel: "stdin" }),
784
- codewith: adapterFor("codewith", { sandbox: CODEX_LIKE_SANDBOXES, durable: true, remote: false, promptChannel: "argv" }),
783
+ codewith: adapterFor("codewith", { sandbox: CODEX_LIKE_SANDBOXES, durable: false, remote: true, promptChannel: "stdin" }),
785
784
  codex: adapterFor("codex", { sandbox: CODEX_LIKE_SANDBOXES, durable: false, remote: true, promptChannel: "stdin" }),
786
785
  aicopilot: adapterFor("aicopilot", { sandbox: [], durable: false, remote: true, promptChannel: "stdin" }),
787
786
  opencode: adapterFor("opencode", { sandbox: [], durable: false, remote: true, promptChannel: "stdin" })
@@ -4217,7 +4216,7 @@ class Store {
4217
4216
  // package.json
4218
4217
  var package_default = {
4219
4218
  name: "@hasna/loops",
4220
- version: "0.4.8",
4219
+ version: "0.4.9",
4221
4220
  description: "Persistent local loop and workflow runner for deterministic commands and headless AI coding agents",
4222
4221
  type: "module",
4223
4222
  main: "dist/index.js",
@@ -5009,11 +5008,6 @@ var TRANSPORT_ENV_KEYS = new Set([
5009
5008
  "USER",
5010
5009
  "XDG_RUNTIME_DIR"
5011
5010
  ]);
5012
- function boundedText(text, maxBytes) {
5013
- const buffer = new BoundedOutputBuffer(maxBytes);
5014
- buffer.append(text);
5015
- return buffer.value();
5016
- }
5017
5011
  function buildResult(status, startedAt, fields = {}) {
5018
5012
  const finishedAt = fields.finishedAt ?? nowIso();
5019
5013
  return {
@@ -5077,21 +5071,6 @@ function metadataEnv(metadata) {
5077
5071
  env.LOOPS_GOAL_NODE_KEY = metadata.goalNodeKey;
5078
5072
  return env;
5079
5073
  }
5080
- function codewithAgentIdempotencyKey(metadata) {
5081
- const parts = [
5082
- "openloops",
5083
- metadata.workflowRunId ? `workflow-run:${metadata.workflowRunId}` : undefined,
5084
- metadata.workflowStepId ? `step:${metadata.workflowStepId}` : undefined,
5085
- metadata.runId ? `loop-run:${metadata.runId}` : undefined,
5086
- metadata.loopId ? `loop:${metadata.loopId}` : undefined,
5087
- metadata.scheduledFor ? `scheduled:${metadata.scheduledFor}` : undefined,
5088
- metadata.goalId ? `goal:${metadata.goalId}` : undefined,
5089
- metadata.goalNodeKey ? `node:${metadata.goalNodeKey}` : undefined
5090
- ].filter(Boolean);
5091
- if (parts.length > 1)
5092
- return parts.join(":");
5093
- return `openloops:adhoc:${randomBytes2(16).toString("hex")}`;
5094
- }
5095
5074
  function allowlistEnv(allowlist) {
5096
5075
  const env = {};
5097
5076
  if (allowlist?.tools?.length)
@@ -5146,8 +5125,7 @@ function commandSpec(target, opts) {
5146
5125
  preflightAnyOf: invocation.preflightAnyOf,
5147
5126
  stdin: invocation.stdin,
5148
5127
  allowlist: agentTarget.allowlist,
5149
- worktree: agentTarget.worktree,
5150
- codewithDurableAgent: adapter.capabilities.durable ? { target: agentTarget } : undefined
5128
+ worktree: agentTarget.worktree
5151
5129
  };
5152
5130
  }
5153
5131
  function composeExecutionEnv(spec, metadata, opts, accountEnv) {
@@ -5357,266 +5335,6 @@ async function preflightNativeAuthProfile(spec, env) {
5357
5335
  const result = await spawnCapture(spec.command, ["profile", "list"], { env, timeoutMs: 15000 });
5358
5336
  assertCodewithProfileListed(spec.nativeAuthProfile.profile, result);
5359
5337
  }
5360
- function codewithAgentStartArgs(target, idempotencyKey) {
5361
- const args = providerAdapter(target.provider).buildInvocation(target).args;
5362
- const startIndex = args.findIndex((arg, index) => arg === "start" && args[index - 1] === "agent");
5363
- if (startIndex === -1)
5364
- throw new Error("internal error: codewith durable agent args missing agent start");
5365
- args.splice(startIndex + 1, 0, "--idempotency-key", idempotencyKey);
5366
- return args;
5367
- }
5368
- function codewithAgentControlArgs(target, command, agentId) {
5369
- return [
5370
- ...target.authProfile ? ["--auth-profile", target.authProfile] : [],
5371
- "agent",
5372
- command,
5373
- ...command === "logs" ? ["--limit", "20"] : [],
5374
- "--json",
5375
- agentId
5376
- ];
5377
- }
5378
- function extractFirstJsonObject(text) {
5379
- let depth = 0;
5380
- let start = -1;
5381
- let inString = false;
5382
- let escaped = false;
5383
- for (let i = 0;i < text.length; i += 1) {
5384
- const ch = text[i];
5385
- if (inString) {
5386
- if (escaped)
5387
- escaped = false;
5388
- else if (ch === "\\")
5389
- escaped = true;
5390
- else if (ch === '"')
5391
- inString = false;
5392
- continue;
5393
- }
5394
- if (ch === '"') {
5395
- inString = true;
5396
- } else if (ch === "{") {
5397
- if (depth === 0)
5398
- start = i;
5399
- depth += 1;
5400
- } else if (ch === "}") {
5401
- if (depth > 0) {
5402
- depth -= 1;
5403
- if (depth === 0 && start !== -1)
5404
- return text.slice(start, i + 1);
5405
- }
5406
- }
5407
- }
5408
- return;
5409
- }
5410
- function parseJsonOutput(stdout, label) {
5411
- const raw = stdout || "{}";
5412
- const candidates = [raw.trim()];
5413
- const scanned = extractFirstJsonObject(raw);
5414
- if (scanned && scanned !== raw.trim())
5415
- candidates.push(scanned);
5416
- let lastError;
5417
- for (const candidate of candidates) {
5418
- try {
5419
- const value = JSON.parse(candidate);
5420
- if (!value || typeof value !== "object" || Array.isArray(value))
5421
- throw new Error("not an object");
5422
- return value;
5423
- } catch (error) {
5424
- lastError = error;
5425
- }
5426
- }
5427
- throw new Error(`${label} did not return JSON${lastError instanceof Error ? `: ${lastError.message}` : ""}`);
5428
- }
5429
- function recordField(value, key) {
5430
- if (!value || typeof value !== "object" || Array.isArray(value))
5431
- return;
5432
- const field = value[key];
5433
- return field && typeof field === "object" && !Array.isArray(field) ? field : undefined;
5434
- }
5435
- function stringField(value, key) {
5436
- const field = value?.[key];
5437
- return typeof field === "string" ? field : undefined;
5438
- }
5439
- function numberField(value, key) {
5440
- const field = value?.[key];
5441
- return typeof field === "number" && Number.isFinite(field) ? field : undefined;
5442
- }
5443
- function codewithAgentStatus(readJson) {
5444
- return stringField(recordField(readJson, "agent"), "status") ?? stringField(recordField(readJson, "statusSnapshot"), "status");
5445
- }
5446
- function codewithAgentLastEventSeq(readJson) {
5447
- const agentSeq = numberField(recordField(readJson, "agent"), "lastEventSeq");
5448
- const snapshotSeq = numberField(recordField(readJson, "statusSnapshot"), "lastEventSeq");
5449
- if (agentSeq !== undefined && snapshotSeq !== undefined)
5450
- return Math.max(agentSeq, snapshotSeq);
5451
- return agentSeq ?? snapshotSeq;
5452
- }
5453
- function codewithAgentEvidence(startJson, readJson, logsJson) {
5454
- const agent = recordField(readJson, "agent") ?? recordField(startJson, "agent");
5455
- const statusSnapshot = recordField(readJson, "statusSnapshot");
5456
- const events = Array.isArray(logsJson?.data) ? logsJson.data.filter((event) => Boolean(event) && typeof event === "object" && !Array.isArray(event)).map((event) => ({
5457
- seq: numberField(event, "seq"),
5458
- eventType: stringField(event, "eventType"),
5459
- createdAt: numberField(event, "createdAt")
5460
- })) : undefined;
5461
- return JSON.stringify({
5462
- codewithAgent: {
5463
- agentId: stringField(agent, "agentId"),
5464
- status: stringField(agent, "status"),
5465
- desiredState: stringField(agent, "desiredState"),
5466
- statusReason: stringField(agent, "statusReason"),
5467
- threadId: stringField(agent, "threadId"),
5468
- rolloutPath: stringField(agent, "rolloutPath"),
5469
- pid: numberField(agent, "pid"),
5470
- exitCode: numberField(agent, "exitCode"),
5471
- created: typeof startJson.created === "boolean" ? startJson.created : undefined
5472
- },
5473
- statusSnapshot: statusSnapshot ? {
5474
- seq: numberField(statusSnapshot, "seq"),
5475
- status: stringField(statusSnapshot, "status"),
5476
- summary: stringField(statusSnapshot, "summary"),
5477
- pendingInteractionCount: numberField(statusSnapshot, "pendingInteractionCount"),
5478
- lastEventSeq: numberField(statusSnapshot, "lastEventSeq")
5479
- } : undefined,
5480
- events
5481
- }, null, 2);
5482
- }
5483
- function codewithAgentProgress(readJson) {
5484
- const agent = recordField(readJson, "agent");
5485
- const statusSnapshot = recordField(readJson, "statusSnapshot");
5486
- return {
5487
- provider: "codewith",
5488
- agentId: stringField(agent, "agentId"),
5489
- status: stringField(agent, "status") ?? stringField(statusSnapshot, "status"),
5490
- summary: stringField(statusSnapshot, "summary"),
5491
- statusReason: stringField(agent, "statusReason"),
5492
- threadId: stringField(agent, "threadId"),
5493
- rolloutPath: stringField(agent, "rolloutPath"),
5494
- pid: numberField(agent, "pid"),
5495
- lastEventSeq: codewithAgentLastEventSeq(readJson)
5496
- };
5497
- }
5498
- function sleep(ms) {
5499
- return new Promise((resolve3) => setTimeout(resolve3, ms));
5500
- }
5501
- async function executeCodewithDurableAgent(spec, metadata, opts, env, startedAt) {
5502
- const target = spec.codewithDurableAgent?.target;
5503
- if (!target)
5504
- throw new Error("internal error: missing codewith durable target");
5505
- const maxOutputBytes = opts.maxOutputBytes ?? DEFAULT_MAX_OUTPUT_BYTES;
5506
- const idempotencyKey = codewithAgentIdempotencyKey(metadata);
5507
- const start = await spawnCapture(spec.command, codewithAgentStartArgs(target, idempotencyKey), {
5508
- cwd: spec.cwd,
5509
- env,
5510
- timeoutMs: 30000,
5511
- maxOutputBytes
5512
- });
5513
- const stderr = new BoundedOutputBuffer(maxOutputBytes);
5514
- stderr.append(start.stderr);
5515
- if (start.error || (start.status ?? 1) !== 0) {
5516
- return failureResult(startedAt, start.error ?? `codewith agent start exited with code ${start.status ?? "unknown"}`, {
5517
- exitCode: start.status ?? undefined,
5518
- stdout: start.stdout,
5519
- stderr: stderr.value()
5520
- });
5521
- }
5522
- let startJson;
5523
- try {
5524
- startJson = parseJsonOutput(start.stdout || "{}", "codewith agent start");
5525
- } catch (error) {
5526
- return failureResult(startedAt, error instanceof Error ? error.message : String(error), { stdout: start.stdout, stderr: stderr.value() });
5527
- }
5528
- const agentId = stringField(recordField(startJson, "agent"), "agentId");
5529
- if (!agentId) {
5530
- return failureResult(startedAt, "codewith agent start did not return agent.agentId", { stdout: start.stdout, stderr: stderr.value() });
5531
- }
5532
- opts.onAgentProgress?.(codewithAgentProgress(startJson));
5533
- const stopAgent = async () => {
5534
- await spawnCapture(spec.command, codewithAgentControlArgs(target, "stop", agentId), {
5535
- cwd: spec.cwd,
5536
- env,
5537
- timeoutMs: 15000,
5538
- maxOutputBytes
5539
- });
5540
- };
5541
- const pollMs = Math.max(100, Number(opts.env?.LOOPS_CODEWITH_AGENT_POLL_MS ?? process.env.LOOPS_CODEWITH_AGENT_POLL_MS ?? 2000) || 2000);
5542
- let lastReadJson = startJson;
5543
- let lastLogsJson;
5544
- let lastFingerprint;
5545
- let lastProgressAt = Date.now();
5546
- const evidence = () => boundedText(codewithAgentEvidence(startJson, lastReadJson, lastLogsJson), maxOutputBytes);
5547
- while (true) {
5548
- if (opts.signal?.aborted) {
5549
- await stopAgent();
5550
- return failureResult(startedAt, "cancelled", { stdout: evidence(), stderr: stderr.value() });
5551
- }
5552
- const read = await spawnCapture(spec.command, codewithAgentControlArgs(target, "read", agentId), {
5553
- cwd: spec.cwd,
5554
- env,
5555
- timeoutMs: 30000,
5556
- maxOutputBytes
5557
- });
5558
- stderr.append(read.stderr);
5559
- if (read.error || (read.status ?? 1) !== 0) {
5560
- return failureResult(startedAt, read.error ?? `codewith agent read exited with code ${read.status ?? "unknown"}`, {
5561
- exitCode: read.status ?? undefined,
5562
- stdout: evidence(),
5563
- stderr: stderr.value()
5564
- });
5565
- }
5566
- try {
5567
- lastReadJson = parseJsonOutput(read.stdout || "{}", "codewith agent read");
5568
- } catch (error) {
5569
- return failureResult(startedAt, error instanceof Error ? error.message : String(error), {
5570
- stdout: boundedText(read.stdout, maxOutputBytes),
5571
- stderr: stderr.value()
5572
- });
5573
- }
5574
- const status = codewithAgentStatus(lastReadJson);
5575
- const fingerprint = JSON.stringify({
5576
- status,
5577
- agentLastEventSeq: numberField(recordField(lastReadJson, "agent"), "lastEventSeq"),
5578
- snapshot: recordField(lastReadJson, "statusSnapshot") ?? null
5579
- });
5580
- if (fingerprint !== lastFingerprint) {
5581
- lastFingerprint = fingerprint;
5582
- lastProgressAt = Date.now();
5583
- opts.onAgentProgress?.(codewithAgentProgress(lastReadJson));
5584
- }
5585
- if (status === "completed" || status === "failed" || status === "cancelled") {
5586
- const logs = await spawnCapture(spec.command, codewithAgentControlArgs(target, "logs", agentId), {
5587
- cwd: spec.cwd,
5588
- env,
5589
- timeoutMs: 30000,
5590
- maxOutputBytes
5591
- });
5592
- if (!logs.error && (logs.status ?? 1) === 0) {
5593
- try {
5594
- lastLogsJson = parseJsonOutput(logs.stdout || "{}", "codewith agent logs");
5595
- } catch {
5596
- lastLogsJson = undefined;
5597
- }
5598
- } else {
5599
- stderr.append(logs.stderr || logs.error || "");
5600
- }
5601
- if (status === "completed") {
5602
- return successResult(startedAt, { exitCode: 0, stdout: evidence(), stderr: stderr.value() });
5603
- }
5604
- return failureResult(startedAt, stringField(recordField(lastReadJson, "agent"), "statusReason") ?? `codewith agent ${status}`, { exitCode: 1, stdout: evidence(), stderr: stderr.value() });
5605
- }
5606
- if (typeof spec.timeoutMs === "number" && new Date(nowIso()).getTime() - new Date(startedAt).getTime() >= spec.timeoutMs) {
5607
- await stopAgent();
5608
- return timeoutResult(startedAt, `timed out after ${spec.timeoutMs}ms`, { stdout: evidence(), stderr: stderr.value() });
5609
- }
5610
- if (typeof spec.idleTimeoutMs === "number" && Date.now() - lastProgressAt >= spec.idleTimeoutMs) {
5611
- await stopAgent();
5612
- return timeoutResult(startedAt, `idle timed out after ${spec.idleTimeoutMs}ms without agent progress`, {
5613
- stdout: evidence(),
5614
- stderr: stderr.value()
5615
- });
5616
- }
5617
- await sleep(pollMs);
5618
- }
5619
- }
5620
5338
  function resolvedDirEquals(left, right) {
5621
5339
  try {
5622
5340
  return realpathSync(left) === realpathSync(right);
@@ -5850,9 +5568,6 @@ function preflightTarget(target, metadata = {}, opts = {}) {
5850
5568
  async function executeTarget(target, metadata = {}, opts = {}) {
5851
5569
  let spec = commandSpec(target, opts);
5852
5570
  const machine = resolvedMachine(opts);
5853
- if (machine && !machine.local && spec.codewithDurableAgent) {
5854
- return failureResult(nowIso(), "remote Codewith durable background-agent steps require remote status polling support; run this Codewith step locally or add remote durable readback before dispatch");
5855
- }
5856
5571
  if (machine && !machine.local) {
5857
5572
  const remoteFallbackSpec = spec.worktree?.enabled && spec.worktree.mode === "auto" ? worktreeFallbackSpec(target, opts, spec.worktree.originalCwd) : undefined;
5858
5573
  return executeRemoteSpec(spec, machine, metadata, opts, remoteFallbackSpec);
@@ -5883,9 +5598,6 @@ async function executeTarget(target, metadata = {}, opts = {}) {
5883
5598
  if (worktreeEntry?.fallbackCwd) {
5884
5599
  spec = worktreeFallbackSpec(target, opts, worktreeEntry.fallbackCwd) ?? spec;
5885
5600
  }
5886
- if (spec.codewithDurableAgent) {
5887
- return executeCodewithDurableAgent(spec, metadata, opts, env, startedAt);
5888
- }
5889
5601
  const child = spawn2(spec.command, spec.args, {
5890
5602
  cwd: spec.cwd,
5891
5603
  env,
@@ -24,7 +24,7 @@ export interface ProviderAdapter {
24
24
  validate(target: AgentTarget, label?: string): void;
25
25
  buildInvocation(target: AgentTarget): AgentInvocation;
26
26
  }
27
- export declare const UNSAFE_CODEWITH_DURABLE_EXTRA_ARGS: Set<string>;
27
+ export declare const UNSAFE_CODEWITH_EXEC_EXTRA_ARGS: Set<string>;
28
28
  export declare const PROVIDER_ADAPTERS: Record<AgentProvider, ProviderAdapter>;
29
29
  export declare const AGENT_PROVIDERS: AgentProvider[];
30
30
  export declare function providerAdapter(provider: AgentProvider): ProviderAdapter;
package/dist/lib/mode.js CHANGED
@@ -2,7 +2,7 @@
2
2
  // package.json
3
3
  var package_default = {
4
4
  name: "@hasna/loops",
5
- version: "0.4.8",
5
+ version: "0.4.9",
6
6
  description: "Persistent local loop and workflow runner for deterministic commands and headless AI coding agents",
7
7
  type: "module",
8
8
  main: "dist/index.js",
@@ -8,4 +8,14 @@ export interface PrReviewRoutingDecision {
8
8
  selectedReviewer?: string;
9
9
  signals: string[];
10
10
  }
11
- export declare function prReviewRoutingDecision(data: Record<string, unknown>, metadata: Record<string, unknown>, opts: TodosTaskRouteOptions): PrReviewRoutingDecision;
11
+ /** A GitHub PR reference resolvable to `owner/repo#number`. */
12
+ export interface PrReference {
13
+ owner: string;
14
+ repo: string;
15
+ number: number;
16
+ }
17
+ /** Resolves a PR author login from a concrete `owner/repo#number` reference. */
18
+ export type PrAuthorResolver = (ref: PrReference) => string | undefined;
19
+ /** Extracts a concrete owner/repo/number PR reference from route evidence text. */
20
+ export declare function prReferenceFrom(text: string): PrReference | undefined;
21
+ export declare function prReviewRoutingDecision(data: Record<string, unknown>, metadata: Record<string, unknown>, opts: TodosTaskRouteOptions, resolveAuthor?: PrAuthorResolver): PrReviewRoutingDecision;
@@ -579,7 +579,7 @@ import { isAbsolute, resolve } from "path";
579
579
 
580
580
  // src/lib/agent-adapter.ts
581
581
  import { spawn } from "child_process";
582
- var UNSAFE_CODEWITH_DURABLE_EXTRA_ARGS = new Set([
582
+ var UNSAFE_CODEWITH_EXEC_EXTRA_ARGS = new Set([
583
583
  "e",
584
584
  "exec",
585
585
  "agent",
@@ -628,12 +628,12 @@ function validateAgentOptions(target, label, capabilities) {
628
628
  throw new Error(`${label}.agent is not supported for provider codex`);
629
629
  }
630
630
  if (provider === "codewith" && target.agent !== undefined) {
631
- throw new Error(`${label}.agent is not supported for provider codewith durable background-agent execution`);
631
+ throw new Error(`${label}.agent is not supported for provider codewith`);
632
632
  }
633
633
  if (provider === "codewith") {
634
- const unsafe = target.extraArgs?.find((arg) => UNSAFE_CODEWITH_DURABLE_EXTRA_ARGS.has(arg));
634
+ const unsafe = target.extraArgs?.find((arg) => UNSAFE_CODEWITH_EXEC_EXTRA_ARGS.has(arg));
635
635
  if (unsafe) {
636
- throw new Error(`${label}.extraArgs cannot include ${unsafe}; codewith agent steps use durable agent start, not exec/ephemeral flags`);
636
+ throw new Error(`${label}.extraArgs cannot include ${unsafe}; codewith exec launch flags are managed by the adapter`);
637
637
  }
638
638
  }
639
639
  if (target.addDirs?.length && !["codewith", "codex"].includes(provider)) {
@@ -716,7 +716,10 @@ function buildAgentInvocation(target) {
716
716
  args.push(...target.authProfile ? ["--auth-profile", target.authProfile] : []);
717
717
  if (target.variant)
718
718
  args.push("-c", `model_reasoning_effort=${configStringValue(target.variant)}`);
719
- args.push("--ask-for-approval", "never", "--sandbox", codewithLikeSandbox(target));
719
+ const sandbox = codewithLikeSandbox(target);
720
+ if (sandbox === "workspace-write")
721
+ args.push("-c", "sandbox_workspace_write.network_access=true");
722
+ args.push("--ask-for-approval", "never", "exec", "--json", "--ephemeral", "--sandbox", sandbox, "--skip-git-repo-check");
720
723
  if (target.cwd)
721
724
  args.push("--cd", target.cwd);
722
725
  for (const dir of target.addDirs ?? [])
@@ -724,11 +727,7 @@ function buildAgentInvocation(target) {
724
727
  if (target.model)
725
728
  args.push("--model", target.model);
726
729
  args.push(...target.extraArgs ?? []);
727
- args.push("agent", "start", "--json");
728
- if (target.cwd)
729
- args.push("--cwd", target.cwd);
730
- args.push(target.prompt);
731
- return { command: "codewith", args };
730
+ return { command: "codewith", args, stdin: target.prompt };
732
731
  }
733
732
  case "codex": {
734
733
  if (target.variant)
@@ -781,7 +780,7 @@ function adapterFor(provider, capabilities) {
781
780
  var PROVIDER_ADAPTERS = {
782
781
  claude: adapterFor("claude", { sandbox: [], durable: false, remote: true, promptChannel: "stdin" }),
783
782
  cursor: adapterFor("cursor", { sandbox: CURSOR_SANDBOXES, durable: false, remote: true, promptChannel: "stdin" }),
784
- codewith: adapterFor("codewith", { sandbox: CODEX_LIKE_SANDBOXES, durable: true, remote: false, promptChannel: "argv" }),
783
+ codewith: adapterFor("codewith", { sandbox: CODEX_LIKE_SANDBOXES, durable: false, remote: true, promptChannel: "stdin" }),
785
784
  codex: adapterFor("codex", { sandbox: CODEX_LIKE_SANDBOXES, durable: false, remote: true, promptChannel: "stdin" }),
786
785
  aicopilot: adapterFor("aicopilot", { sandbox: [], durable: false, remote: true, promptChannel: "stdin" }),
787
786
  opencode: adapterFor("opencode", { sandbox: [], durable: false, remote: true, promptChannel: "stdin" })
@@ -579,7 +579,7 @@ import { isAbsolute, resolve } from "path";
579
579
 
580
580
  // src/lib/agent-adapter.ts
581
581
  import { spawn } from "child_process";
582
- var UNSAFE_CODEWITH_DURABLE_EXTRA_ARGS = new Set([
582
+ var UNSAFE_CODEWITH_EXEC_EXTRA_ARGS = new Set([
583
583
  "e",
584
584
  "exec",
585
585
  "agent",
@@ -628,12 +628,12 @@ function validateAgentOptions(target, label, capabilities) {
628
628
  throw new Error(`${label}.agent is not supported for provider codex`);
629
629
  }
630
630
  if (provider === "codewith" && target.agent !== undefined) {
631
- throw new Error(`${label}.agent is not supported for provider codewith durable background-agent execution`);
631
+ throw new Error(`${label}.agent is not supported for provider codewith`);
632
632
  }
633
633
  if (provider === "codewith") {
634
- const unsafe = target.extraArgs?.find((arg) => UNSAFE_CODEWITH_DURABLE_EXTRA_ARGS.has(arg));
634
+ const unsafe = target.extraArgs?.find((arg) => UNSAFE_CODEWITH_EXEC_EXTRA_ARGS.has(arg));
635
635
  if (unsafe) {
636
- throw new Error(`${label}.extraArgs cannot include ${unsafe}; codewith agent steps use durable agent start, not exec/ephemeral flags`);
636
+ throw new Error(`${label}.extraArgs cannot include ${unsafe}; codewith exec launch flags are managed by the adapter`);
637
637
  }
638
638
  }
639
639
  if (target.addDirs?.length && !["codewith", "codex"].includes(provider)) {
@@ -716,7 +716,10 @@ function buildAgentInvocation(target) {
716
716
  args.push(...target.authProfile ? ["--auth-profile", target.authProfile] : []);
717
717
  if (target.variant)
718
718
  args.push("-c", `model_reasoning_effort=${configStringValue(target.variant)}`);
719
- args.push("--ask-for-approval", "never", "--sandbox", codewithLikeSandbox(target));
719
+ const sandbox = codewithLikeSandbox(target);
720
+ if (sandbox === "workspace-write")
721
+ args.push("-c", "sandbox_workspace_write.network_access=true");
722
+ args.push("--ask-for-approval", "never", "exec", "--json", "--ephemeral", "--sandbox", sandbox, "--skip-git-repo-check");
720
723
  if (target.cwd)
721
724
  args.push("--cd", target.cwd);
722
725
  for (const dir of target.addDirs ?? [])
@@ -724,11 +727,7 @@ function buildAgentInvocation(target) {
724
727
  if (target.model)
725
728
  args.push("--model", target.model);
726
729
  args.push(...target.extraArgs ?? []);
727
- args.push("agent", "start", "--json");
728
- if (target.cwd)
729
- args.push("--cwd", target.cwd);
730
- args.push(target.prompt);
731
- return { command: "codewith", args };
730
+ return { command: "codewith", args, stdin: target.prompt };
732
731
  }
733
732
  case "codex": {
734
733
  if (target.variant)
@@ -781,7 +780,7 @@ function adapterFor(provider, capabilities) {
781
780
  var PROVIDER_ADAPTERS = {
782
781
  claude: adapterFor("claude", { sandbox: [], durable: false, remote: true, promptChannel: "stdin" }),
783
782
  cursor: adapterFor("cursor", { sandbox: CURSOR_SANDBOXES, durable: false, remote: true, promptChannel: "stdin" }),
784
- codewith: adapterFor("codewith", { sandbox: CODEX_LIKE_SANDBOXES, durable: true, remote: false, promptChannel: "argv" }),
783
+ codewith: adapterFor("codewith", { sandbox: CODEX_LIKE_SANDBOXES, durable: false, remote: true, promptChannel: "stdin" }),
785
784
  codex: adapterFor("codex", { sandbox: CODEX_LIKE_SANDBOXES, durable: false, remote: true, promptChannel: "stdin" }),
786
785
  aicopilot: adapterFor("aicopilot", { sandbox: [], durable: false, remote: true, promptChannel: "stdin" }),
787
786
  opencode: adapterFor("opencode", { sandbox: [], durable: false, remote: true, promptChannel: "stdin" })
package/dist/lib/store.js CHANGED
@@ -579,7 +579,7 @@ import { isAbsolute, resolve } from "path";
579
579
 
580
580
  // src/lib/agent-adapter.ts
581
581
  import { spawn } from "child_process";
582
- var UNSAFE_CODEWITH_DURABLE_EXTRA_ARGS = new Set([
582
+ var UNSAFE_CODEWITH_EXEC_EXTRA_ARGS = new Set([
583
583
  "e",
584
584
  "exec",
585
585
  "agent",
@@ -628,12 +628,12 @@ function validateAgentOptions(target, label, capabilities) {
628
628
  throw new Error(`${label}.agent is not supported for provider codex`);
629
629
  }
630
630
  if (provider === "codewith" && target.agent !== undefined) {
631
- throw new Error(`${label}.agent is not supported for provider codewith durable background-agent execution`);
631
+ throw new Error(`${label}.agent is not supported for provider codewith`);
632
632
  }
633
633
  if (provider === "codewith") {
634
- const unsafe = target.extraArgs?.find((arg) => UNSAFE_CODEWITH_DURABLE_EXTRA_ARGS.has(arg));
634
+ const unsafe = target.extraArgs?.find((arg) => UNSAFE_CODEWITH_EXEC_EXTRA_ARGS.has(arg));
635
635
  if (unsafe) {
636
- throw new Error(`${label}.extraArgs cannot include ${unsafe}; codewith agent steps use durable agent start, not exec/ephemeral flags`);
636
+ throw new Error(`${label}.extraArgs cannot include ${unsafe}; codewith exec launch flags are managed by the adapter`);
637
637
  }
638
638
  }
639
639
  if (target.addDirs?.length && !["codewith", "codex"].includes(provider)) {
@@ -716,7 +716,10 @@ function buildAgentInvocation(target) {
716
716
  args.push(...target.authProfile ? ["--auth-profile", target.authProfile] : []);
717
717
  if (target.variant)
718
718
  args.push("-c", `model_reasoning_effort=${configStringValue(target.variant)}`);
719
- args.push("--ask-for-approval", "never", "--sandbox", codewithLikeSandbox(target));
719
+ const sandbox = codewithLikeSandbox(target);
720
+ if (sandbox === "workspace-write")
721
+ args.push("-c", "sandbox_workspace_write.network_access=true");
722
+ args.push("--ask-for-approval", "never", "exec", "--json", "--ephemeral", "--sandbox", sandbox, "--skip-git-repo-check");
720
723
  if (target.cwd)
721
724
  args.push("--cd", target.cwd);
722
725
  for (const dir of target.addDirs ?? [])
@@ -724,11 +727,7 @@ function buildAgentInvocation(target) {
724
727
  if (target.model)
725
728
  args.push("--model", target.model);
726
729
  args.push(...target.extraArgs ?? []);
727
- args.push("agent", "start", "--json");
728
- if (target.cwd)
729
- args.push("--cwd", target.cwd);
730
- args.push(target.prompt);
731
- return { command: "codewith", args };
730
+ return { command: "codewith", args, stdin: target.prompt };
732
731
  }
733
732
  case "codex": {
734
733
  if (target.variant)
@@ -781,7 +780,7 @@ function adapterFor(provider, capabilities) {
781
780
  var PROVIDER_ADAPTERS = {
782
781
  claude: adapterFor("claude", { sandbox: [], durable: false, remote: true, promptChannel: "stdin" }),
783
782
  cursor: adapterFor("cursor", { sandbox: CURSOR_SANDBOXES, durable: false, remote: true, promptChannel: "stdin" }),
784
- codewith: adapterFor("codewith", { sandbox: CODEX_LIKE_SANDBOXES, durable: true, remote: false, promptChannel: "argv" }),
783
+ codewith: adapterFor("codewith", { sandbox: CODEX_LIKE_SANDBOXES, durable: false, remote: true, promptChannel: "stdin" }),
785
784
  codex: adapterFor("codex", { sandbox: CODEX_LIKE_SANDBOXES, durable: false, remote: true, promptChannel: "stdin" }),
786
785
  aicopilot: adapterFor("aicopilot", { sandbox: [], durable: false, remote: true, promptChannel: "stdin" }),
787
786
  opencode: adapterFor("opencode", { sandbox: [], durable: false, remote: true, promptChannel: "stdin" })