@hasna/loops 0.4.8 → 0.4.10
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/CHANGELOG.md +24 -0
- package/README.md +4 -4
- package/dist/api/index.js +1 -1
- package/dist/cli/index.js +226 -368
- package/dist/daemon/index.js +76 -327
- package/dist/index.js +63 -314
- package/dist/lib/agent-adapter.d.ts +1 -1
- package/dist/lib/mode.js +1 -1
- package/dist/lib/route/pr-review.d.ts +18 -1
- package/dist/lib/storage/index.js +40 -22
- package/dist/lib/storage/sqlite.js +40 -22
- package/dist/lib/store.js +40 -22
- package/dist/mcp/index.js +63 -314
- package/dist/runner/index.js +33 -303
- package/dist/sdk/index.js +63 -314
- package/docs/USAGE.md +4 -4
- package/package.json +1 -1
|
@@ -54,8 +54,12 @@ function nowIso() {
|
|
|
54
54
|
import { mkdirSync } from "fs";
|
|
55
55
|
import { homedir } from "os";
|
|
56
56
|
import { join } from "path";
|
|
57
|
+
function homeDir() {
|
|
58
|
+
const home = process.env.HOME?.trim();
|
|
59
|
+
return home ? home : homedir();
|
|
60
|
+
}
|
|
57
61
|
function dataDir() {
|
|
58
|
-
return process.env.LOOPS_DATA_DIR || join(
|
|
62
|
+
return process.env.LOOPS_DATA_DIR || join(homeDir(), ".hasna", "loops");
|
|
59
63
|
}
|
|
60
64
|
function ensureDataDir() {
|
|
61
65
|
const dir = dataDir();
|
|
@@ -72,10 +76,10 @@ function daemonLogPath() {
|
|
|
72
76
|
return join(dataDir(), "daemon.log");
|
|
73
77
|
}
|
|
74
78
|
function systemdServicePath() {
|
|
75
|
-
return join(
|
|
79
|
+
return join(homeDir(), ".config", "systemd", "user", "loops-daemon.service");
|
|
76
80
|
}
|
|
77
81
|
function launchdPlistPath() {
|
|
78
|
-
return join(
|
|
82
|
+
return join(homeDir(), "Library", "LaunchAgents", "com.hasna.loops.daemon.plist");
|
|
79
83
|
}
|
|
80
84
|
|
|
81
85
|
// src/lib/process-identity.ts
|
|
@@ -579,7 +583,7 @@ import { isAbsolute, resolve } from "path";
|
|
|
579
583
|
|
|
580
584
|
// src/lib/agent-adapter.ts
|
|
581
585
|
import { spawn } from "child_process";
|
|
582
|
-
var
|
|
586
|
+
var UNSAFE_CODEWITH_EXEC_EXTRA_ARGS = new Set([
|
|
583
587
|
"e",
|
|
584
588
|
"exec",
|
|
585
589
|
"agent",
|
|
@@ -628,12 +632,12 @@ function validateAgentOptions(target, label, capabilities) {
|
|
|
628
632
|
throw new Error(`${label}.agent is not supported for provider codex`);
|
|
629
633
|
}
|
|
630
634
|
if (provider === "codewith" && target.agent !== undefined) {
|
|
631
|
-
throw new Error(`${label}.agent is not supported for provider codewith
|
|
635
|
+
throw new Error(`${label}.agent is not supported for provider codewith`);
|
|
632
636
|
}
|
|
633
637
|
if (provider === "codewith") {
|
|
634
|
-
const unsafe = target.extraArgs?.find((arg) =>
|
|
638
|
+
const unsafe = target.extraArgs?.find((arg) => UNSAFE_CODEWITH_EXEC_EXTRA_ARGS.has(arg));
|
|
635
639
|
if (unsafe) {
|
|
636
|
-
throw new Error(`${label}.extraArgs cannot include ${unsafe}; codewith
|
|
640
|
+
throw new Error(`${label}.extraArgs cannot include ${unsafe}; codewith exec launch flags are managed by the adapter`);
|
|
637
641
|
}
|
|
638
642
|
}
|
|
639
643
|
if (target.addDirs?.length && !["codewith", "codex"].includes(provider)) {
|
|
@@ -716,7 +720,10 @@ function buildAgentInvocation(target) {
|
|
|
716
720
|
args.push(...target.authProfile ? ["--auth-profile", target.authProfile] : []);
|
|
717
721
|
if (target.variant)
|
|
718
722
|
args.push("-c", `model_reasoning_effort=${configStringValue(target.variant)}`);
|
|
719
|
-
|
|
723
|
+
const sandbox = codewithLikeSandbox(target);
|
|
724
|
+
if (sandbox === "workspace-write")
|
|
725
|
+
args.push("-c", "sandbox_workspace_write.network_access=true");
|
|
726
|
+
args.push("--ask-for-approval", "never", "exec", "--json", "--ephemeral", "--sandbox", sandbox, "--skip-git-repo-check");
|
|
720
727
|
if (target.cwd)
|
|
721
728
|
args.push("--cd", target.cwd);
|
|
722
729
|
for (const dir of target.addDirs ?? [])
|
|
@@ -724,11 +731,7 @@ function buildAgentInvocation(target) {
|
|
|
724
731
|
if (target.model)
|
|
725
732
|
args.push("--model", target.model);
|
|
726
733
|
args.push(...target.extraArgs ?? []);
|
|
727
|
-
|
|
728
|
-
if (target.cwd)
|
|
729
|
-
args.push("--cwd", target.cwd);
|
|
730
|
-
args.push(target.prompt);
|
|
731
|
-
return { command: "codewith", args };
|
|
734
|
+
return { command: "codewith", args, stdin: target.prompt };
|
|
732
735
|
}
|
|
733
736
|
case "codex": {
|
|
734
737
|
if (target.variant)
|
|
@@ -781,7 +784,7 @@ function adapterFor(provider, capabilities) {
|
|
|
781
784
|
var PROVIDER_ADAPTERS = {
|
|
782
785
|
claude: adapterFor("claude", { sandbox: [], durable: false, remote: true, promptChannel: "stdin" }),
|
|
783
786
|
cursor: adapterFor("cursor", { sandbox: CURSOR_SANDBOXES, durable: false, remote: true, promptChannel: "stdin" }),
|
|
784
|
-
codewith: adapterFor("codewith", { sandbox: CODEX_LIKE_SANDBOXES, durable:
|
|
787
|
+
codewith: adapterFor("codewith", { sandbox: CODEX_LIKE_SANDBOXES, durable: false, remote: true, promptChannel: "stdin" }),
|
|
785
788
|
codex: adapterFor("codex", { sandbox: CODEX_LIKE_SANDBOXES, durable: false, remote: true, promptChannel: "stdin" }),
|
|
786
789
|
aicopilot: adapterFor("aicopilot", { sandbox: [], durable: false, remote: true, promptChannel: "stdin" }),
|
|
787
790
|
opencode: adapterFor("opencode", { sandbox: [], durable: false, remote: true, promptChannel: "stdin" })
|
|
@@ -1473,6 +1476,21 @@ function workItemStatusForLoopRun(status, attempt, maxAttempts) {
|
|
|
1473
1476
|
function scrubbedOrNull(value) {
|
|
1474
1477
|
return value == null ? null : scrubSecrets(value);
|
|
1475
1478
|
}
|
|
1479
|
+
var MAX_PERSISTED_RUN_OUTPUT_CHARS = 64 * 1024;
|
|
1480
|
+
function clampPersistedRunOutput(value) {
|
|
1481
|
+
if (value == null || value.length <= MAX_PERSISTED_RUN_OUTPUT_CHARS)
|
|
1482
|
+
return value;
|
|
1483
|
+
const half = Math.floor(MAX_PERSISTED_RUN_OUTPUT_CHARS / 2);
|
|
1484
|
+
const head = value.slice(0, half);
|
|
1485
|
+
const tail = value.slice(value.length - half);
|
|
1486
|
+
const omitted = value.length - head.length - tail.length;
|
|
1487
|
+
return `${head}
|
|
1488
|
+
\u2026[${omitted} chars truncated by loops run-output retention]\u2026
|
|
1489
|
+
${tail}`;
|
|
1490
|
+
}
|
|
1491
|
+
function persistedRunOutput(value) {
|
|
1492
|
+
return clampPersistedRunOutput(scrubbedOrNull(value));
|
|
1493
|
+
}
|
|
1476
1494
|
function chmodIfExists(path, mode) {
|
|
1477
1495
|
try {
|
|
1478
1496
|
if (existsSync(path))
|
|
@@ -3219,8 +3237,8 @@ class Store {
|
|
|
3219
3237
|
))`).run({
|
|
3220
3238
|
$workflowRunId: workflowRunId,
|
|
3221
3239
|
$stepId: stepId,
|
|
3222
|
-
$stdout: progress.stdout === undefined ? null :
|
|
3223
|
-
$stderr: progress.stderr === undefined ? null :
|
|
3240
|
+
$stdout: progress.stdout === undefined ? null : persistedRunOutput(progress.stdout),
|
|
3241
|
+
$stderr: progress.stderr === undefined ? null : persistedRunOutput(progress.stderr),
|
|
3224
3242
|
$updated: now,
|
|
3225
3243
|
$daemonLeaseId: opts.daemonLeaseId ?? null,
|
|
3226
3244
|
$now: now
|
|
@@ -3281,8 +3299,8 @@ class Store {
|
|
|
3281
3299
|
$finished: finishedAt,
|
|
3282
3300
|
$exitCode: patch.exitCode ?? null,
|
|
3283
3301
|
$durationMs: patch.durationMs ?? null,
|
|
3284
|
-
$stdout:
|
|
3285
|
-
$stderr:
|
|
3302
|
+
$stdout: persistedRunOutput(patch.stdout),
|
|
3303
|
+
$stderr: persistedRunOutput(patch.stderr),
|
|
3286
3304
|
$error: error ?? null,
|
|
3287
3305
|
$updated: finishedAt,
|
|
3288
3306
|
$daemonLeaseId: opts.daemonLeaseId ?? null,
|
|
@@ -3660,8 +3678,8 @@ class Store {
|
|
|
3660
3678
|
$pid: patch.pid ?? null,
|
|
3661
3679
|
$exitCode: patch.exitCode ?? null,
|
|
3662
3680
|
$durationMs: patch.durationMs ?? null,
|
|
3663
|
-
$stdout:
|
|
3664
|
-
$stderr:
|
|
3681
|
+
$stdout: persistedRunOutput(patch.stdout),
|
|
3682
|
+
$stderr: persistedRunOutput(patch.stderr),
|
|
3665
3683
|
$error: error ?? null,
|
|
3666
3684
|
$updated: finishedAt,
|
|
3667
3685
|
$claimedBy: opts.claimedBy ?? null,
|
|
@@ -4058,8 +4076,8 @@ class Store {
|
|
|
4058
4076
|
$processStartedAt: run.processStartedAt ?? null,
|
|
4059
4077
|
$exitCode: run.exitCode ?? null,
|
|
4060
4078
|
$durationMs: run.durationMs ?? null,
|
|
4061
|
-
$stdout:
|
|
4062
|
-
$stderr:
|
|
4079
|
+
$stdout: persistedRunOutput(run.stdout),
|
|
4080
|
+
$stderr: persistedRunOutput(run.stderr),
|
|
4063
4081
|
$error: scrubbedOrNull(run.error),
|
|
4064
4082
|
$goalRunId: run.goalRunId ?? null,
|
|
4065
4083
|
$created: run.createdAt,
|
|
@@ -54,8 +54,12 @@ function nowIso() {
|
|
|
54
54
|
import { mkdirSync } from "fs";
|
|
55
55
|
import { homedir } from "os";
|
|
56
56
|
import { join } from "path";
|
|
57
|
+
function homeDir() {
|
|
58
|
+
const home = process.env.HOME?.trim();
|
|
59
|
+
return home ? home : homedir();
|
|
60
|
+
}
|
|
57
61
|
function dataDir() {
|
|
58
|
-
return process.env.LOOPS_DATA_DIR || join(
|
|
62
|
+
return process.env.LOOPS_DATA_DIR || join(homeDir(), ".hasna", "loops");
|
|
59
63
|
}
|
|
60
64
|
function ensureDataDir() {
|
|
61
65
|
const dir = dataDir();
|
|
@@ -72,10 +76,10 @@ function daemonLogPath() {
|
|
|
72
76
|
return join(dataDir(), "daemon.log");
|
|
73
77
|
}
|
|
74
78
|
function systemdServicePath() {
|
|
75
|
-
return join(
|
|
79
|
+
return join(homeDir(), ".config", "systemd", "user", "loops-daemon.service");
|
|
76
80
|
}
|
|
77
81
|
function launchdPlistPath() {
|
|
78
|
-
return join(
|
|
82
|
+
return join(homeDir(), "Library", "LaunchAgents", "com.hasna.loops.daemon.plist");
|
|
79
83
|
}
|
|
80
84
|
|
|
81
85
|
// src/lib/process-identity.ts
|
|
@@ -579,7 +583,7 @@ import { isAbsolute, resolve } from "path";
|
|
|
579
583
|
|
|
580
584
|
// src/lib/agent-adapter.ts
|
|
581
585
|
import { spawn } from "child_process";
|
|
582
|
-
var
|
|
586
|
+
var UNSAFE_CODEWITH_EXEC_EXTRA_ARGS = new Set([
|
|
583
587
|
"e",
|
|
584
588
|
"exec",
|
|
585
589
|
"agent",
|
|
@@ -628,12 +632,12 @@ function validateAgentOptions(target, label, capabilities) {
|
|
|
628
632
|
throw new Error(`${label}.agent is not supported for provider codex`);
|
|
629
633
|
}
|
|
630
634
|
if (provider === "codewith" && target.agent !== undefined) {
|
|
631
|
-
throw new Error(`${label}.agent is not supported for provider codewith
|
|
635
|
+
throw new Error(`${label}.agent is not supported for provider codewith`);
|
|
632
636
|
}
|
|
633
637
|
if (provider === "codewith") {
|
|
634
|
-
const unsafe = target.extraArgs?.find((arg) =>
|
|
638
|
+
const unsafe = target.extraArgs?.find((arg) => UNSAFE_CODEWITH_EXEC_EXTRA_ARGS.has(arg));
|
|
635
639
|
if (unsafe) {
|
|
636
|
-
throw new Error(`${label}.extraArgs cannot include ${unsafe}; codewith
|
|
640
|
+
throw new Error(`${label}.extraArgs cannot include ${unsafe}; codewith exec launch flags are managed by the adapter`);
|
|
637
641
|
}
|
|
638
642
|
}
|
|
639
643
|
if (target.addDirs?.length && !["codewith", "codex"].includes(provider)) {
|
|
@@ -716,7 +720,10 @@ function buildAgentInvocation(target) {
|
|
|
716
720
|
args.push(...target.authProfile ? ["--auth-profile", target.authProfile] : []);
|
|
717
721
|
if (target.variant)
|
|
718
722
|
args.push("-c", `model_reasoning_effort=${configStringValue(target.variant)}`);
|
|
719
|
-
|
|
723
|
+
const sandbox = codewithLikeSandbox(target);
|
|
724
|
+
if (sandbox === "workspace-write")
|
|
725
|
+
args.push("-c", "sandbox_workspace_write.network_access=true");
|
|
726
|
+
args.push("--ask-for-approval", "never", "exec", "--json", "--ephemeral", "--sandbox", sandbox, "--skip-git-repo-check");
|
|
720
727
|
if (target.cwd)
|
|
721
728
|
args.push("--cd", target.cwd);
|
|
722
729
|
for (const dir of target.addDirs ?? [])
|
|
@@ -724,11 +731,7 @@ function buildAgentInvocation(target) {
|
|
|
724
731
|
if (target.model)
|
|
725
732
|
args.push("--model", target.model);
|
|
726
733
|
args.push(...target.extraArgs ?? []);
|
|
727
|
-
|
|
728
|
-
if (target.cwd)
|
|
729
|
-
args.push("--cwd", target.cwd);
|
|
730
|
-
args.push(target.prompt);
|
|
731
|
-
return { command: "codewith", args };
|
|
734
|
+
return { command: "codewith", args, stdin: target.prompt };
|
|
732
735
|
}
|
|
733
736
|
case "codex": {
|
|
734
737
|
if (target.variant)
|
|
@@ -781,7 +784,7 @@ function adapterFor(provider, capabilities) {
|
|
|
781
784
|
var PROVIDER_ADAPTERS = {
|
|
782
785
|
claude: adapterFor("claude", { sandbox: [], durable: false, remote: true, promptChannel: "stdin" }),
|
|
783
786
|
cursor: adapterFor("cursor", { sandbox: CURSOR_SANDBOXES, durable: false, remote: true, promptChannel: "stdin" }),
|
|
784
|
-
codewith: adapterFor("codewith", { sandbox: CODEX_LIKE_SANDBOXES, durable:
|
|
787
|
+
codewith: adapterFor("codewith", { sandbox: CODEX_LIKE_SANDBOXES, durable: false, remote: true, promptChannel: "stdin" }),
|
|
785
788
|
codex: adapterFor("codex", { sandbox: CODEX_LIKE_SANDBOXES, durable: false, remote: true, promptChannel: "stdin" }),
|
|
786
789
|
aicopilot: adapterFor("aicopilot", { sandbox: [], durable: false, remote: true, promptChannel: "stdin" }),
|
|
787
790
|
opencode: adapterFor("opencode", { sandbox: [], durable: false, remote: true, promptChannel: "stdin" })
|
|
@@ -1473,6 +1476,21 @@ function workItemStatusForLoopRun(status, attempt, maxAttempts) {
|
|
|
1473
1476
|
function scrubbedOrNull(value) {
|
|
1474
1477
|
return value == null ? null : scrubSecrets(value);
|
|
1475
1478
|
}
|
|
1479
|
+
var MAX_PERSISTED_RUN_OUTPUT_CHARS = 64 * 1024;
|
|
1480
|
+
function clampPersistedRunOutput(value) {
|
|
1481
|
+
if (value == null || value.length <= MAX_PERSISTED_RUN_OUTPUT_CHARS)
|
|
1482
|
+
return value;
|
|
1483
|
+
const half = Math.floor(MAX_PERSISTED_RUN_OUTPUT_CHARS / 2);
|
|
1484
|
+
const head = value.slice(0, half);
|
|
1485
|
+
const tail = value.slice(value.length - half);
|
|
1486
|
+
const omitted = value.length - head.length - tail.length;
|
|
1487
|
+
return `${head}
|
|
1488
|
+
\u2026[${omitted} chars truncated by loops run-output retention]\u2026
|
|
1489
|
+
${tail}`;
|
|
1490
|
+
}
|
|
1491
|
+
function persistedRunOutput(value) {
|
|
1492
|
+
return clampPersistedRunOutput(scrubbedOrNull(value));
|
|
1493
|
+
}
|
|
1476
1494
|
function chmodIfExists(path, mode) {
|
|
1477
1495
|
try {
|
|
1478
1496
|
if (existsSync(path))
|
|
@@ -3219,8 +3237,8 @@ class Store {
|
|
|
3219
3237
|
))`).run({
|
|
3220
3238
|
$workflowRunId: workflowRunId,
|
|
3221
3239
|
$stepId: stepId,
|
|
3222
|
-
$stdout: progress.stdout === undefined ? null :
|
|
3223
|
-
$stderr: progress.stderr === undefined ? null :
|
|
3240
|
+
$stdout: progress.stdout === undefined ? null : persistedRunOutput(progress.stdout),
|
|
3241
|
+
$stderr: progress.stderr === undefined ? null : persistedRunOutput(progress.stderr),
|
|
3224
3242
|
$updated: now,
|
|
3225
3243
|
$daemonLeaseId: opts.daemonLeaseId ?? null,
|
|
3226
3244
|
$now: now
|
|
@@ -3281,8 +3299,8 @@ class Store {
|
|
|
3281
3299
|
$finished: finishedAt,
|
|
3282
3300
|
$exitCode: patch.exitCode ?? null,
|
|
3283
3301
|
$durationMs: patch.durationMs ?? null,
|
|
3284
|
-
$stdout:
|
|
3285
|
-
$stderr:
|
|
3302
|
+
$stdout: persistedRunOutput(patch.stdout),
|
|
3303
|
+
$stderr: persistedRunOutput(patch.stderr),
|
|
3286
3304
|
$error: error ?? null,
|
|
3287
3305
|
$updated: finishedAt,
|
|
3288
3306
|
$daemonLeaseId: opts.daemonLeaseId ?? null,
|
|
@@ -3660,8 +3678,8 @@ class Store {
|
|
|
3660
3678
|
$pid: patch.pid ?? null,
|
|
3661
3679
|
$exitCode: patch.exitCode ?? null,
|
|
3662
3680
|
$durationMs: patch.durationMs ?? null,
|
|
3663
|
-
$stdout:
|
|
3664
|
-
$stderr:
|
|
3681
|
+
$stdout: persistedRunOutput(patch.stdout),
|
|
3682
|
+
$stderr: persistedRunOutput(patch.stderr),
|
|
3665
3683
|
$error: error ?? null,
|
|
3666
3684
|
$updated: finishedAt,
|
|
3667
3685
|
$claimedBy: opts.claimedBy ?? null,
|
|
@@ -4058,8 +4076,8 @@ class Store {
|
|
|
4058
4076
|
$processStartedAt: run.processStartedAt ?? null,
|
|
4059
4077
|
$exitCode: run.exitCode ?? null,
|
|
4060
4078
|
$durationMs: run.durationMs ?? null,
|
|
4061
|
-
$stdout:
|
|
4062
|
-
$stderr:
|
|
4079
|
+
$stdout: persistedRunOutput(run.stdout),
|
|
4080
|
+
$stderr: persistedRunOutput(run.stderr),
|
|
4063
4081
|
$error: scrubbedOrNull(run.error),
|
|
4064
4082
|
$goalRunId: run.goalRunId ?? null,
|
|
4065
4083
|
$created: run.createdAt,
|
package/dist/lib/store.js
CHANGED
|
@@ -54,8 +54,12 @@ function nowIso() {
|
|
|
54
54
|
import { mkdirSync } from "fs";
|
|
55
55
|
import { homedir } from "os";
|
|
56
56
|
import { join } from "path";
|
|
57
|
+
function homeDir() {
|
|
58
|
+
const home = process.env.HOME?.trim();
|
|
59
|
+
return home ? home : homedir();
|
|
60
|
+
}
|
|
57
61
|
function dataDir() {
|
|
58
|
-
return process.env.LOOPS_DATA_DIR || join(
|
|
62
|
+
return process.env.LOOPS_DATA_DIR || join(homeDir(), ".hasna", "loops");
|
|
59
63
|
}
|
|
60
64
|
function ensureDataDir() {
|
|
61
65
|
const dir = dataDir();
|
|
@@ -72,10 +76,10 @@ function daemonLogPath() {
|
|
|
72
76
|
return join(dataDir(), "daemon.log");
|
|
73
77
|
}
|
|
74
78
|
function systemdServicePath() {
|
|
75
|
-
return join(
|
|
79
|
+
return join(homeDir(), ".config", "systemd", "user", "loops-daemon.service");
|
|
76
80
|
}
|
|
77
81
|
function launchdPlistPath() {
|
|
78
|
-
return join(
|
|
82
|
+
return join(homeDir(), "Library", "LaunchAgents", "com.hasna.loops.daemon.plist");
|
|
79
83
|
}
|
|
80
84
|
|
|
81
85
|
// src/lib/process-identity.ts
|
|
@@ -579,7 +583,7 @@ import { isAbsolute, resolve } from "path";
|
|
|
579
583
|
|
|
580
584
|
// src/lib/agent-adapter.ts
|
|
581
585
|
import { spawn } from "child_process";
|
|
582
|
-
var
|
|
586
|
+
var UNSAFE_CODEWITH_EXEC_EXTRA_ARGS = new Set([
|
|
583
587
|
"e",
|
|
584
588
|
"exec",
|
|
585
589
|
"agent",
|
|
@@ -628,12 +632,12 @@ function validateAgentOptions(target, label, capabilities) {
|
|
|
628
632
|
throw new Error(`${label}.agent is not supported for provider codex`);
|
|
629
633
|
}
|
|
630
634
|
if (provider === "codewith" && target.agent !== undefined) {
|
|
631
|
-
throw new Error(`${label}.agent is not supported for provider codewith
|
|
635
|
+
throw new Error(`${label}.agent is not supported for provider codewith`);
|
|
632
636
|
}
|
|
633
637
|
if (provider === "codewith") {
|
|
634
|
-
const unsafe = target.extraArgs?.find((arg) =>
|
|
638
|
+
const unsafe = target.extraArgs?.find((arg) => UNSAFE_CODEWITH_EXEC_EXTRA_ARGS.has(arg));
|
|
635
639
|
if (unsafe) {
|
|
636
|
-
throw new Error(`${label}.extraArgs cannot include ${unsafe}; codewith
|
|
640
|
+
throw new Error(`${label}.extraArgs cannot include ${unsafe}; codewith exec launch flags are managed by the adapter`);
|
|
637
641
|
}
|
|
638
642
|
}
|
|
639
643
|
if (target.addDirs?.length && !["codewith", "codex"].includes(provider)) {
|
|
@@ -716,7 +720,10 @@ function buildAgentInvocation(target) {
|
|
|
716
720
|
args.push(...target.authProfile ? ["--auth-profile", target.authProfile] : []);
|
|
717
721
|
if (target.variant)
|
|
718
722
|
args.push("-c", `model_reasoning_effort=${configStringValue(target.variant)}`);
|
|
719
|
-
|
|
723
|
+
const sandbox = codewithLikeSandbox(target);
|
|
724
|
+
if (sandbox === "workspace-write")
|
|
725
|
+
args.push("-c", "sandbox_workspace_write.network_access=true");
|
|
726
|
+
args.push("--ask-for-approval", "never", "exec", "--json", "--ephemeral", "--sandbox", sandbox, "--skip-git-repo-check");
|
|
720
727
|
if (target.cwd)
|
|
721
728
|
args.push("--cd", target.cwd);
|
|
722
729
|
for (const dir of target.addDirs ?? [])
|
|
@@ -724,11 +731,7 @@ function buildAgentInvocation(target) {
|
|
|
724
731
|
if (target.model)
|
|
725
732
|
args.push("--model", target.model);
|
|
726
733
|
args.push(...target.extraArgs ?? []);
|
|
727
|
-
|
|
728
|
-
if (target.cwd)
|
|
729
|
-
args.push("--cwd", target.cwd);
|
|
730
|
-
args.push(target.prompt);
|
|
731
|
-
return { command: "codewith", args };
|
|
734
|
+
return { command: "codewith", args, stdin: target.prompt };
|
|
732
735
|
}
|
|
733
736
|
case "codex": {
|
|
734
737
|
if (target.variant)
|
|
@@ -781,7 +784,7 @@ function adapterFor(provider, capabilities) {
|
|
|
781
784
|
var PROVIDER_ADAPTERS = {
|
|
782
785
|
claude: adapterFor("claude", { sandbox: [], durable: false, remote: true, promptChannel: "stdin" }),
|
|
783
786
|
cursor: adapterFor("cursor", { sandbox: CURSOR_SANDBOXES, durable: false, remote: true, promptChannel: "stdin" }),
|
|
784
|
-
codewith: adapterFor("codewith", { sandbox: CODEX_LIKE_SANDBOXES, durable:
|
|
787
|
+
codewith: adapterFor("codewith", { sandbox: CODEX_LIKE_SANDBOXES, durable: false, remote: true, promptChannel: "stdin" }),
|
|
785
788
|
codex: adapterFor("codex", { sandbox: CODEX_LIKE_SANDBOXES, durable: false, remote: true, promptChannel: "stdin" }),
|
|
786
789
|
aicopilot: adapterFor("aicopilot", { sandbox: [], durable: false, remote: true, promptChannel: "stdin" }),
|
|
787
790
|
opencode: adapterFor("opencode", { sandbox: [], durable: false, remote: true, promptChannel: "stdin" })
|
|
@@ -1473,6 +1476,21 @@ function workItemStatusForLoopRun(status, attempt, maxAttempts) {
|
|
|
1473
1476
|
function scrubbedOrNull(value) {
|
|
1474
1477
|
return value == null ? null : scrubSecrets(value);
|
|
1475
1478
|
}
|
|
1479
|
+
var MAX_PERSISTED_RUN_OUTPUT_CHARS = 64 * 1024;
|
|
1480
|
+
function clampPersistedRunOutput(value) {
|
|
1481
|
+
if (value == null || value.length <= MAX_PERSISTED_RUN_OUTPUT_CHARS)
|
|
1482
|
+
return value;
|
|
1483
|
+
const half = Math.floor(MAX_PERSISTED_RUN_OUTPUT_CHARS / 2);
|
|
1484
|
+
const head = value.slice(0, half);
|
|
1485
|
+
const tail = value.slice(value.length - half);
|
|
1486
|
+
const omitted = value.length - head.length - tail.length;
|
|
1487
|
+
return `${head}
|
|
1488
|
+
\u2026[${omitted} chars truncated by loops run-output retention]\u2026
|
|
1489
|
+
${tail}`;
|
|
1490
|
+
}
|
|
1491
|
+
function persistedRunOutput(value) {
|
|
1492
|
+
return clampPersistedRunOutput(scrubbedOrNull(value));
|
|
1493
|
+
}
|
|
1476
1494
|
function chmodIfExists(path, mode) {
|
|
1477
1495
|
try {
|
|
1478
1496
|
if (existsSync(path))
|
|
@@ -3219,8 +3237,8 @@ class Store {
|
|
|
3219
3237
|
))`).run({
|
|
3220
3238
|
$workflowRunId: workflowRunId,
|
|
3221
3239
|
$stepId: stepId,
|
|
3222
|
-
$stdout: progress.stdout === undefined ? null :
|
|
3223
|
-
$stderr: progress.stderr === undefined ? null :
|
|
3240
|
+
$stdout: progress.stdout === undefined ? null : persistedRunOutput(progress.stdout),
|
|
3241
|
+
$stderr: progress.stderr === undefined ? null : persistedRunOutput(progress.stderr),
|
|
3224
3242
|
$updated: now,
|
|
3225
3243
|
$daemonLeaseId: opts.daemonLeaseId ?? null,
|
|
3226
3244
|
$now: now
|
|
@@ -3281,8 +3299,8 @@ class Store {
|
|
|
3281
3299
|
$finished: finishedAt,
|
|
3282
3300
|
$exitCode: patch.exitCode ?? null,
|
|
3283
3301
|
$durationMs: patch.durationMs ?? null,
|
|
3284
|
-
$stdout:
|
|
3285
|
-
$stderr:
|
|
3302
|
+
$stdout: persistedRunOutput(patch.stdout),
|
|
3303
|
+
$stderr: persistedRunOutput(patch.stderr),
|
|
3286
3304
|
$error: error ?? null,
|
|
3287
3305
|
$updated: finishedAt,
|
|
3288
3306
|
$daemonLeaseId: opts.daemonLeaseId ?? null,
|
|
@@ -3660,8 +3678,8 @@ class Store {
|
|
|
3660
3678
|
$pid: patch.pid ?? null,
|
|
3661
3679
|
$exitCode: patch.exitCode ?? null,
|
|
3662
3680
|
$durationMs: patch.durationMs ?? null,
|
|
3663
|
-
$stdout:
|
|
3664
|
-
$stderr:
|
|
3681
|
+
$stdout: persistedRunOutput(patch.stdout),
|
|
3682
|
+
$stderr: persistedRunOutput(patch.stderr),
|
|
3665
3683
|
$error: error ?? null,
|
|
3666
3684
|
$updated: finishedAt,
|
|
3667
3685
|
$claimedBy: opts.claimedBy ?? null,
|
|
@@ -4058,8 +4076,8 @@ class Store {
|
|
|
4058
4076
|
$processStartedAt: run.processStartedAt ?? null,
|
|
4059
4077
|
$exitCode: run.exitCode ?? null,
|
|
4060
4078
|
$durationMs: run.durationMs ?? null,
|
|
4061
|
-
$stdout:
|
|
4062
|
-
$stderr:
|
|
4079
|
+
$stdout: persistedRunOutput(run.stdout),
|
|
4080
|
+
$stderr: persistedRunOutput(run.stderr),
|
|
4063
4081
|
$error: scrubbedOrNull(run.error),
|
|
4064
4082
|
$goalRunId: run.goalRunId ?? null,
|
|
4065
4083
|
$created: run.createdAt,
|