@hasna/loops 0.3.43 → 0.3.44
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/cli/index.js +32 -16
- package/dist/daemon/index.js +26 -10
- package/dist/index.js +26 -10
- package/dist/lib/store.js +18 -2
- package/dist/sdk/index.js +21 -5
- package/package.json +1 -1
package/dist/cli/index.js
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
|
|
4
4
|
// src/lib/store.ts
|
|
5
5
|
import { Database } from "bun:sqlite";
|
|
6
|
-
import { mkdirSync as mkdirSync3, mkdtempSync, rmSync } from "fs";
|
|
6
|
+
import { chmodSync, existsSync, mkdirSync as mkdirSync3, mkdtempSync, rmSync } from "fs";
|
|
7
7
|
import { tmpdir } from "os";
|
|
8
8
|
import { dirname, join as join3 } from "path";
|
|
9
9
|
|
|
@@ -824,6 +824,20 @@ function workItemStatusForLoopRun(status, attempt, maxAttempts) {
|
|
|
824
824
|
}
|
|
825
825
|
return;
|
|
826
826
|
}
|
|
827
|
+
function chmodIfExists(path, mode) {
|
|
828
|
+
try {
|
|
829
|
+
if (existsSync(path))
|
|
830
|
+
chmodSync(path, mode);
|
|
831
|
+
} catch {}
|
|
832
|
+
}
|
|
833
|
+
function ensurePrivateStorePath(file) {
|
|
834
|
+
const dir = dirname(file);
|
|
835
|
+
mkdirSync3(dir, { recursive: true, mode: 448 });
|
|
836
|
+
chmodIfExists(dir, 448);
|
|
837
|
+
chmodIfExists(file, 384);
|
|
838
|
+
chmodIfExists(`${file}-wal`, 384);
|
|
839
|
+
chmodIfExists(`${file}-shm`, 384);
|
|
840
|
+
}
|
|
827
841
|
|
|
828
842
|
class Store {
|
|
829
843
|
db;
|
|
@@ -831,11 +845,13 @@ class Store {
|
|
|
831
845
|
constructor(path) {
|
|
832
846
|
const file = path ?? dbPath();
|
|
833
847
|
if (file !== ":memory:")
|
|
834
|
-
|
|
848
|
+
ensurePrivateStorePath(file);
|
|
835
849
|
this.rootDir = file === ":memory:" ? mkdtempSync(join3(tmpdir(), "open-loops-store-")) : dirname(file);
|
|
836
850
|
this.db = new Database(file);
|
|
837
851
|
this.db.exec("PRAGMA busy_timeout = 5000;");
|
|
838
852
|
this.db.exec("PRAGMA journal_mode = WAL;");
|
|
853
|
+
if (file !== ":memory:")
|
|
854
|
+
ensurePrivateStorePath(file);
|
|
839
855
|
this.migrate();
|
|
840
856
|
}
|
|
841
857
|
migrate() {
|
|
@@ -2661,7 +2677,7 @@ class Store {
|
|
|
2661
2677
|
|
|
2662
2678
|
// src/cli/index.ts
|
|
2663
2679
|
import { createHash as createHash3, randomUUID } from "crypto";
|
|
2664
|
-
import { closeSync, existsSync as
|
|
2680
|
+
import { closeSync, existsSync as existsSync5, mkdirSync as mkdirSync6, mkdtempSync as mkdtempSync2, openSync as openSync2, readFileSync as readFileSync2, realpathSync, rmSync as rmSync3, writeFileSync as writeFileSync4 } from "fs";
|
|
2665
2681
|
import { spawnSync as spawnSync5 } from "child_process";
|
|
2666
2682
|
import { join as join6, resolve as resolve2 } from "path";
|
|
2667
2683
|
import { tmpdir as tmpdir2 } from "os";
|
|
@@ -2791,7 +2807,7 @@ import { resolveMachineCommand } from "@hasna/machines/consumer";
|
|
|
2791
2807
|
|
|
2792
2808
|
// src/lib/accounts.ts
|
|
2793
2809
|
import { spawnSync } from "child_process";
|
|
2794
|
-
import { existsSync } from "fs";
|
|
2810
|
+
import { existsSync as existsSync2 } from "fs";
|
|
2795
2811
|
var EXPORT_RE = /^export\s+([A-Za-z_][A-Za-z0-9_]*)=(.*)$/;
|
|
2796
2812
|
function accountToolForProvider(provider) {
|
|
2797
2813
|
switch (provider) {
|
|
@@ -2876,7 +2892,7 @@ function resolveAccountEnv(account, toolHint, env) {
|
|
|
2876
2892
|
const profileDir = (accountDirEnvVar(tool) ? accountEnv[accountDirEnvVar(tool)] : undefined) ?? primaryAccountDir(result.stdout);
|
|
2877
2893
|
if (!profileDir)
|
|
2878
2894
|
throw new Error(`accounts env returned no profile directory for ${account.profile}/${tool}`);
|
|
2879
|
-
if (!
|
|
2895
|
+
if (!existsSync2(profileDir))
|
|
2880
2896
|
throw new Error(`account profile directory does not exist for ${account.profile}/${tool}: ${profileDir}`);
|
|
2881
2897
|
return {
|
|
2882
2898
|
...accountEnv,
|
|
@@ -3240,7 +3256,7 @@ function agentArgs(target) {
|
|
|
3240
3256
|
case "codex":
|
|
3241
3257
|
if (target.variant)
|
|
3242
3258
|
args.push("-c", `model_reasoning_effort=${configStringValue(target.variant)}`);
|
|
3243
|
-
args.push("exec", "--json", "--ephemeral", "--
|
|
3259
|
+
args.push("exec", "--json", "--ephemeral", "--sandbox", codewithLikeSandbox(target), "--skip-git-repo-check");
|
|
3244
3260
|
if (isolation === "safe")
|
|
3245
3261
|
args.push("--ignore-rules");
|
|
3246
3262
|
if (target.cwd)
|
|
@@ -4762,7 +4778,7 @@ async function tick(deps) {
|
|
|
4762
4778
|
}
|
|
4763
4779
|
|
|
4764
4780
|
// src/daemon/control.ts
|
|
4765
|
-
import { existsSync as
|
|
4781
|
+
import { existsSync as existsSync3, mkdirSync as mkdirSync4, readFileSync, rmSync as rmSync2, writeFileSync as writeFileSync2 } from "fs";
|
|
4766
4782
|
import { hostname } from "os";
|
|
4767
4783
|
import { dirname as dirname2 } from "path";
|
|
4768
4784
|
|
|
@@ -4790,7 +4806,7 @@ async function runLoop(opts) {
|
|
|
4790
4806
|
|
|
4791
4807
|
// src/daemon/control.ts
|
|
4792
4808
|
function readPid(path = pidFilePath()) {
|
|
4793
|
-
if (!
|
|
4809
|
+
if (!existsSync3(path))
|
|
4794
4810
|
return;
|
|
4795
4811
|
try {
|
|
4796
4812
|
const pid = Number(readFileSync(path, "utf8").trim());
|
|
@@ -5063,7 +5079,7 @@ async function startDaemon(opts) {
|
|
|
5063
5079
|
}
|
|
5064
5080
|
|
|
5065
5081
|
// src/daemon/install.ts
|
|
5066
|
-
import { chmodSync, mkdirSync as mkdirSync5, writeFileSync as writeFileSync3 } from "fs";
|
|
5082
|
+
import { chmodSync as chmodSync2, mkdirSync as mkdirSync5, writeFileSync as writeFileSync3 } from "fs";
|
|
5067
5083
|
import { spawnSync as spawnSync3 } from "child_process";
|
|
5068
5084
|
import { dirname as dirname3 } from "path";
|
|
5069
5085
|
function installStartup(cliEntry, execPath = process.execPath, args = ["daemon", "run"]) {
|
|
@@ -5122,7 +5138,7 @@ ${args.map((arg) => ` <string>${arg}</string>`).join(`
|
|
|
5122
5138
|
</dict>
|
|
5123
5139
|
</plist>
|
|
5124
5140
|
`);
|
|
5125
|
-
|
|
5141
|
+
chmodSync2(path, 384);
|
|
5126
5142
|
return {
|
|
5127
5143
|
platform: process.platform,
|
|
5128
5144
|
path,
|
|
@@ -5716,7 +5732,7 @@ function buildScriptInventoryReport(store, opts = {}) {
|
|
|
5716
5732
|
// package.json
|
|
5717
5733
|
var package_default = {
|
|
5718
5734
|
name: "@hasna/loops",
|
|
5719
|
-
version: "0.3.
|
|
5735
|
+
version: "0.3.44",
|
|
5720
5736
|
description: "Persistent local loop and workflow runner for deterministic commands and headless AI coding agents",
|
|
5721
5737
|
type: "module",
|
|
5722
5738
|
main: "dist/index.js",
|
|
@@ -5806,7 +5822,7 @@ function packageVersion() {
|
|
|
5806
5822
|
|
|
5807
5823
|
// src/lib/templates.ts
|
|
5808
5824
|
import { execFileSync } from "child_process";
|
|
5809
|
-
import { existsSync as
|
|
5825
|
+
import { existsSync as existsSync4 } from "fs";
|
|
5810
5826
|
import { homedir as homedir3 } from "os";
|
|
5811
5827
|
import { basename as basename3, isAbsolute, join as join5, relative, resolve } from "path";
|
|
5812
5828
|
var TODOS_TASK_WORKER_VERIFIER_TEMPLATE_ID = "todos-task-worker-verifier";
|
|
@@ -6066,7 +6082,7 @@ function defaultWorktreeRoot(root) {
|
|
|
6066
6082
|
return join5(homedir3(), ".hasna", "loops", "worktrees");
|
|
6067
6083
|
}
|
|
6068
6084
|
function gitRootFor(path) {
|
|
6069
|
-
if (!
|
|
6085
|
+
if (!existsSync4(path))
|
|
6070
6086
|
return;
|
|
6071
6087
|
try {
|
|
6072
6088
|
return execFileSync("git", ["-C", path, "rev-parse", "--show-toplevel"], {
|
|
@@ -6526,7 +6542,7 @@ function renderLifecycleBoundedTemplate(id, values) {
|
|
|
6526
6542
|
variant: values.variant,
|
|
6527
6543
|
agent: values.agent,
|
|
6528
6544
|
permissionMode: values.permissionMode,
|
|
6529
|
-
sandbox: values.sandbox,
|
|
6545
|
+
sandbox: values.sandbox ?? (id === REPORT_ONLY_TEMPLATE_ID ? "read-only" : undefined),
|
|
6530
6546
|
manualBreakGlass: booleanVar(values.manualBreakGlass),
|
|
6531
6547
|
worktreeMode: values.worktreeMode ?? (id === REPORT_ONLY_TEMPLATE_ID ? "main" : "required"),
|
|
6532
6548
|
worktreeRoot: values.worktreeRoot,
|
|
@@ -7026,7 +7042,7 @@ function routeCursorsPath() {
|
|
|
7026
7042
|
}
|
|
7027
7043
|
function readRouteCursors() {
|
|
7028
7044
|
const path = routeCursorsPath();
|
|
7029
|
-
if (!
|
|
7045
|
+
if (!existsSync5(path))
|
|
7030
7046
|
return {};
|
|
7031
7047
|
try {
|
|
7032
7048
|
const parsed = JSON.parse(readFileSync2(path, "utf8"));
|
|
@@ -9538,7 +9554,7 @@ ${result.instructions.join(`
|
|
|
9538
9554
|
});
|
|
9539
9555
|
daemon.command("logs").option("-n, --lines <n>", "lines", "80").action((opts) => {
|
|
9540
9556
|
const path = daemonLogPath();
|
|
9541
|
-
if (!
|
|
9557
|
+
if (!existsSync5(path)) {
|
|
9542
9558
|
console.log("");
|
|
9543
9559
|
return;
|
|
9544
9560
|
}
|
package/dist/daemon/index.js
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
|
|
4
4
|
// src/lib/store.ts
|
|
5
5
|
import { Database } from "bun:sqlite";
|
|
6
|
-
import { mkdirSync as mkdirSync3, mkdtempSync, rmSync } from "fs";
|
|
6
|
+
import { chmodSync, existsSync, mkdirSync as mkdirSync3, mkdtempSync, rmSync } from "fs";
|
|
7
7
|
import { tmpdir } from "os";
|
|
8
8
|
import { dirname, join as join3 } from "path";
|
|
9
9
|
|
|
@@ -824,6 +824,20 @@ function workItemStatusForLoopRun(status, attempt, maxAttempts) {
|
|
|
824
824
|
}
|
|
825
825
|
return;
|
|
826
826
|
}
|
|
827
|
+
function chmodIfExists(path, mode) {
|
|
828
|
+
try {
|
|
829
|
+
if (existsSync(path))
|
|
830
|
+
chmodSync(path, mode);
|
|
831
|
+
} catch {}
|
|
832
|
+
}
|
|
833
|
+
function ensurePrivateStorePath(file) {
|
|
834
|
+
const dir = dirname(file);
|
|
835
|
+
mkdirSync3(dir, { recursive: true, mode: 448 });
|
|
836
|
+
chmodIfExists(dir, 448);
|
|
837
|
+
chmodIfExists(file, 384);
|
|
838
|
+
chmodIfExists(`${file}-wal`, 384);
|
|
839
|
+
chmodIfExists(`${file}-shm`, 384);
|
|
840
|
+
}
|
|
827
841
|
|
|
828
842
|
class Store {
|
|
829
843
|
db;
|
|
@@ -831,11 +845,13 @@ class Store {
|
|
|
831
845
|
constructor(path) {
|
|
832
846
|
const file = path ?? dbPath();
|
|
833
847
|
if (file !== ":memory:")
|
|
834
|
-
|
|
848
|
+
ensurePrivateStorePath(file);
|
|
835
849
|
this.rootDir = file === ":memory:" ? mkdtempSync(join3(tmpdir(), "open-loops-store-")) : dirname(file);
|
|
836
850
|
this.db = new Database(file);
|
|
837
851
|
this.db.exec("PRAGMA busy_timeout = 5000;");
|
|
838
852
|
this.db.exec("PRAGMA journal_mode = WAL;");
|
|
853
|
+
if (file !== ":memory:")
|
|
854
|
+
ensurePrivateStorePath(file);
|
|
839
855
|
this.migrate();
|
|
840
856
|
}
|
|
841
857
|
migrate() {
|
|
@@ -2675,7 +2691,7 @@ import { resolveMachineCommand } from "@hasna/machines/consumer";
|
|
|
2675
2691
|
|
|
2676
2692
|
// src/lib/accounts.ts
|
|
2677
2693
|
import { spawnSync } from "child_process";
|
|
2678
|
-
import { existsSync } from "fs";
|
|
2694
|
+
import { existsSync as existsSync2 } from "fs";
|
|
2679
2695
|
var EXPORT_RE = /^export\s+([A-Za-z_][A-Za-z0-9_]*)=(.*)$/;
|
|
2680
2696
|
function accountToolForProvider(provider) {
|
|
2681
2697
|
switch (provider) {
|
|
@@ -2760,7 +2776,7 @@ function resolveAccountEnv(account, toolHint, env) {
|
|
|
2760
2776
|
const profileDir = (accountDirEnvVar(tool) ? accountEnv[accountDirEnvVar(tool)] : undefined) ?? primaryAccountDir(result.stdout);
|
|
2761
2777
|
if (!profileDir)
|
|
2762
2778
|
throw new Error(`accounts env returned no profile directory for ${account.profile}/${tool}`);
|
|
2763
|
-
if (!
|
|
2779
|
+
if (!existsSync2(profileDir))
|
|
2764
2780
|
throw new Error(`account profile directory does not exist for ${account.profile}/${tool}: ${profileDir}`);
|
|
2765
2781
|
return {
|
|
2766
2782
|
...accountEnv,
|
|
@@ -3124,7 +3140,7 @@ function agentArgs(target) {
|
|
|
3124
3140
|
case "codex":
|
|
3125
3141
|
if (target.variant)
|
|
3126
3142
|
args.push("-c", `model_reasoning_effort=${configStringValue(target.variant)}`);
|
|
3127
|
-
args.push("exec", "--json", "--ephemeral", "--
|
|
3143
|
+
args.push("exec", "--json", "--ephemeral", "--sandbox", codewithLikeSandbox(target), "--skip-git-repo-check");
|
|
3128
3144
|
if (isolation === "safe")
|
|
3129
3145
|
args.push("--ignore-rules");
|
|
3130
3146
|
if (target.cwd)
|
|
@@ -4646,7 +4662,7 @@ async function tick(deps) {
|
|
|
4646
4662
|
}
|
|
4647
4663
|
|
|
4648
4664
|
// src/daemon/control.ts
|
|
4649
|
-
import { existsSync as
|
|
4665
|
+
import { existsSync as existsSync3, mkdirSync as mkdirSync4, readFileSync, rmSync as rmSync2, writeFileSync as writeFileSync2 } from "fs";
|
|
4650
4666
|
import { hostname } from "os";
|
|
4651
4667
|
import { dirname as dirname2 } from "path";
|
|
4652
4668
|
|
|
@@ -4674,7 +4690,7 @@ async function runLoop(opts) {
|
|
|
4674
4690
|
|
|
4675
4691
|
// src/daemon/control.ts
|
|
4676
4692
|
function readPid(path = pidFilePath()) {
|
|
4677
|
-
if (!
|
|
4693
|
+
if (!existsSync3(path))
|
|
4678
4694
|
return;
|
|
4679
4695
|
try {
|
|
4680
4696
|
const pid = Number(readFileSync(path, "utf8").trim());
|
|
@@ -4944,7 +4960,7 @@ async function startDaemon(opts) {
|
|
|
4944
4960
|
}
|
|
4945
4961
|
|
|
4946
4962
|
// src/daemon/install.ts
|
|
4947
|
-
import { chmodSync, mkdirSync as mkdirSync5, writeFileSync as writeFileSync3 } from "fs";
|
|
4963
|
+
import { chmodSync as chmodSync2, mkdirSync as mkdirSync5, writeFileSync as writeFileSync3 } from "fs";
|
|
4948
4964
|
import { spawnSync as spawnSync3 } from "child_process";
|
|
4949
4965
|
import { dirname as dirname3 } from "path";
|
|
4950
4966
|
function installStartup(cliEntry, execPath = process.execPath, args = ["daemon", "run"]) {
|
|
@@ -5003,7 +5019,7 @@ ${args.map((arg) => ` <string>${arg}</string>`).join(`
|
|
|
5003
5019
|
</dict>
|
|
5004
5020
|
</plist>
|
|
5005
5021
|
`);
|
|
5006
|
-
|
|
5022
|
+
chmodSync2(path, 384);
|
|
5007
5023
|
return {
|
|
5008
5024
|
platform: process.platform,
|
|
5009
5025
|
path,
|
|
@@ -5030,7 +5046,7 @@ function enableStartup(result) {
|
|
|
5030
5046
|
// package.json
|
|
5031
5047
|
var package_default = {
|
|
5032
5048
|
name: "@hasna/loops",
|
|
5033
|
-
version: "0.3.
|
|
5049
|
+
version: "0.3.44",
|
|
5034
5050
|
description: "Persistent local loop and workflow runner for deterministic commands and headless AI coding agents",
|
|
5035
5051
|
type: "module",
|
|
5036
5052
|
main: "dist/index.js",
|
package/dist/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// @bun
|
|
2
2
|
// src/lib/store.ts
|
|
3
3
|
import { Database } from "bun:sqlite";
|
|
4
|
-
import { mkdirSync as mkdirSync3, mkdtempSync, rmSync } from "fs";
|
|
4
|
+
import { chmodSync, existsSync, mkdirSync as mkdirSync3, mkdtempSync, rmSync } from "fs";
|
|
5
5
|
import { tmpdir } from "os";
|
|
6
6
|
import { dirname, join as join3 } from "path";
|
|
7
7
|
|
|
@@ -822,6 +822,20 @@ function workItemStatusForLoopRun(status, attempt, maxAttempts) {
|
|
|
822
822
|
}
|
|
823
823
|
return;
|
|
824
824
|
}
|
|
825
|
+
function chmodIfExists(path, mode) {
|
|
826
|
+
try {
|
|
827
|
+
if (existsSync(path))
|
|
828
|
+
chmodSync(path, mode);
|
|
829
|
+
} catch {}
|
|
830
|
+
}
|
|
831
|
+
function ensurePrivateStorePath(file) {
|
|
832
|
+
const dir = dirname(file);
|
|
833
|
+
mkdirSync3(dir, { recursive: true, mode: 448 });
|
|
834
|
+
chmodIfExists(dir, 448);
|
|
835
|
+
chmodIfExists(file, 384);
|
|
836
|
+
chmodIfExists(`${file}-wal`, 384);
|
|
837
|
+
chmodIfExists(`${file}-shm`, 384);
|
|
838
|
+
}
|
|
825
839
|
|
|
826
840
|
class Store {
|
|
827
841
|
db;
|
|
@@ -829,11 +843,13 @@ class Store {
|
|
|
829
843
|
constructor(path) {
|
|
830
844
|
const file = path ?? dbPath();
|
|
831
845
|
if (file !== ":memory:")
|
|
832
|
-
|
|
846
|
+
ensurePrivateStorePath(file);
|
|
833
847
|
this.rootDir = file === ":memory:" ? mkdtempSync(join3(tmpdir(), "open-loops-store-")) : dirname(file);
|
|
834
848
|
this.db = new Database(file);
|
|
835
849
|
this.db.exec("PRAGMA busy_timeout = 5000;");
|
|
836
850
|
this.db.exec("PRAGMA journal_mode = WAL;");
|
|
851
|
+
if (file !== ":memory:")
|
|
852
|
+
ensurePrivateStorePath(file);
|
|
837
853
|
this.migrate();
|
|
838
854
|
}
|
|
839
855
|
migrate() {
|
|
@@ -2665,7 +2681,7 @@ import { resolveMachineCommand } from "@hasna/machines/consumer";
|
|
|
2665
2681
|
|
|
2666
2682
|
// src/lib/accounts.ts
|
|
2667
2683
|
import { spawnSync } from "child_process";
|
|
2668
|
-
import { existsSync } from "fs";
|
|
2684
|
+
import { existsSync as existsSync2 } from "fs";
|
|
2669
2685
|
var EXPORT_RE = /^export\s+([A-Za-z_][A-Za-z0-9_]*)=(.*)$/;
|
|
2670
2686
|
function accountToolForProvider(provider) {
|
|
2671
2687
|
switch (provider) {
|
|
@@ -2750,7 +2766,7 @@ function resolveAccountEnv(account, toolHint, env) {
|
|
|
2750
2766
|
const profileDir = (accountDirEnvVar(tool) ? accountEnv[accountDirEnvVar(tool)] : undefined) ?? primaryAccountDir(result.stdout);
|
|
2751
2767
|
if (!profileDir)
|
|
2752
2768
|
throw new Error(`accounts env returned no profile directory for ${account.profile}/${tool}`);
|
|
2753
|
-
if (!
|
|
2769
|
+
if (!existsSync2(profileDir))
|
|
2754
2770
|
throw new Error(`account profile directory does not exist for ${account.profile}/${tool}: ${profileDir}`);
|
|
2755
2771
|
return {
|
|
2756
2772
|
...accountEnv,
|
|
@@ -3114,7 +3130,7 @@ function agentArgs(target) {
|
|
|
3114
3130
|
case "codex":
|
|
3115
3131
|
if (target.variant)
|
|
3116
3132
|
args.push("-c", `model_reasoning_effort=${configStringValue(target.variant)}`);
|
|
3117
|
-
args.push("exec", "--json", "--ephemeral", "--
|
|
3133
|
+
args.push("exec", "--json", "--ephemeral", "--sandbox", codewithLikeSandbox(target), "--skip-git-repo-check");
|
|
3118
3134
|
if (isolation === "safe")
|
|
3119
3135
|
args.push("--ignore-rules");
|
|
3120
3136
|
if (target.cwd)
|
|
@@ -4767,7 +4783,7 @@ function openAutomationsRuntimeBinding(overrides = {}) {
|
|
|
4767
4783
|
}
|
|
4768
4784
|
// src/lib/templates.ts
|
|
4769
4785
|
import { execFileSync } from "child_process";
|
|
4770
|
-
import { existsSync as
|
|
4786
|
+
import { existsSync as existsSync3 } from "fs";
|
|
4771
4787
|
import { homedir as homedir3 } from "os";
|
|
4772
4788
|
import { basename as basename2, isAbsolute, join as join5, relative, resolve } from "path";
|
|
4773
4789
|
var TODOS_TASK_WORKER_VERIFIER_TEMPLATE_ID = "todos-task-worker-verifier";
|
|
@@ -5027,7 +5043,7 @@ function defaultWorktreeRoot(root) {
|
|
|
5027
5043
|
return join5(homedir3(), ".hasna", "loops", "worktrees");
|
|
5028
5044
|
}
|
|
5029
5045
|
function gitRootFor(path) {
|
|
5030
|
-
if (!
|
|
5046
|
+
if (!existsSync3(path))
|
|
5031
5047
|
return;
|
|
5032
5048
|
try {
|
|
5033
5049
|
return execFileSync("git", ["-C", path, "rev-parse", "--show-toplevel"], {
|
|
@@ -5487,7 +5503,7 @@ function renderLifecycleBoundedTemplate(id, values) {
|
|
|
5487
5503
|
variant: values.variant,
|
|
5488
5504
|
agent: values.agent,
|
|
5489
5505
|
permissionMode: values.permissionMode,
|
|
5490
|
-
sandbox: values.sandbox,
|
|
5506
|
+
sandbox: values.sandbox ?? (id === REPORT_ONLY_TEMPLATE_ID ? "read-only" : undefined),
|
|
5491
5507
|
manualBreakGlass: booleanVar(values.manualBreakGlass),
|
|
5492
5508
|
worktreeMode: values.worktreeMode ?? (id === REPORT_ONLY_TEMPLATE_ID ? "main" : "required"),
|
|
5493
5509
|
worktreeRoot: values.worktreeRoot,
|
|
@@ -5704,7 +5720,7 @@ import { spawnSync as spawnSync3 } from "child_process";
|
|
|
5704
5720
|
import { accessSync as accessSync2, constants as constants2 } from "fs";
|
|
5705
5721
|
|
|
5706
5722
|
// src/daemon/control.ts
|
|
5707
|
-
import { existsSync as
|
|
5723
|
+
import { existsSync as existsSync4, mkdirSync as mkdirSync4, readFileSync, rmSync as rmSync2, writeFileSync as writeFileSync2 } from "fs";
|
|
5708
5724
|
import { hostname } from "os";
|
|
5709
5725
|
import { dirname as dirname2 } from "path";
|
|
5710
5726
|
|
|
@@ -5732,7 +5748,7 @@ async function runLoop(opts) {
|
|
|
5732
5748
|
|
|
5733
5749
|
// src/daemon/control.ts
|
|
5734
5750
|
function readPid(path = pidFilePath()) {
|
|
5735
|
-
if (!
|
|
5751
|
+
if (!existsSync4(path))
|
|
5736
5752
|
return;
|
|
5737
5753
|
try {
|
|
5738
5754
|
const pid = Number(readFileSync(path, "utf8").trim());
|
package/dist/lib/store.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// @bun
|
|
2
2
|
// src/lib/store.ts
|
|
3
3
|
import { Database } from "bun:sqlite";
|
|
4
|
-
import { mkdirSync as mkdirSync3, mkdtempSync, rmSync } from "fs";
|
|
4
|
+
import { chmodSync, existsSync, mkdirSync as mkdirSync3, mkdtempSync, rmSync } from "fs";
|
|
5
5
|
import { tmpdir } from "os";
|
|
6
6
|
import { dirname, join as join3 } from "path";
|
|
7
7
|
|
|
@@ -822,6 +822,20 @@ function workItemStatusForLoopRun(status, attempt, maxAttempts) {
|
|
|
822
822
|
}
|
|
823
823
|
return;
|
|
824
824
|
}
|
|
825
|
+
function chmodIfExists(path, mode) {
|
|
826
|
+
try {
|
|
827
|
+
if (existsSync(path))
|
|
828
|
+
chmodSync(path, mode);
|
|
829
|
+
} catch {}
|
|
830
|
+
}
|
|
831
|
+
function ensurePrivateStorePath(file) {
|
|
832
|
+
const dir = dirname(file);
|
|
833
|
+
mkdirSync3(dir, { recursive: true, mode: 448 });
|
|
834
|
+
chmodIfExists(dir, 448);
|
|
835
|
+
chmodIfExists(file, 384);
|
|
836
|
+
chmodIfExists(`${file}-wal`, 384);
|
|
837
|
+
chmodIfExists(`${file}-shm`, 384);
|
|
838
|
+
}
|
|
825
839
|
|
|
826
840
|
class Store {
|
|
827
841
|
db;
|
|
@@ -829,11 +843,13 @@ class Store {
|
|
|
829
843
|
constructor(path) {
|
|
830
844
|
const file = path ?? dbPath();
|
|
831
845
|
if (file !== ":memory:")
|
|
832
|
-
|
|
846
|
+
ensurePrivateStorePath(file);
|
|
833
847
|
this.rootDir = file === ":memory:" ? mkdtempSync(join3(tmpdir(), "open-loops-store-")) : dirname(file);
|
|
834
848
|
this.db = new Database(file);
|
|
835
849
|
this.db.exec("PRAGMA busy_timeout = 5000;");
|
|
836
850
|
this.db.exec("PRAGMA journal_mode = WAL;");
|
|
851
|
+
if (file !== ":memory:")
|
|
852
|
+
ensurePrivateStorePath(file);
|
|
837
853
|
this.migrate();
|
|
838
854
|
}
|
|
839
855
|
migrate() {
|
package/dist/sdk/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// @bun
|
|
2
2
|
// src/lib/store.ts
|
|
3
3
|
import { Database } from "bun:sqlite";
|
|
4
|
-
import { mkdirSync as mkdirSync3, mkdtempSync, rmSync } from "fs";
|
|
4
|
+
import { chmodSync, existsSync, mkdirSync as mkdirSync3, mkdtempSync, rmSync } from "fs";
|
|
5
5
|
import { tmpdir } from "os";
|
|
6
6
|
import { dirname, join as join3 } from "path";
|
|
7
7
|
|
|
@@ -822,6 +822,20 @@ function workItemStatusForLoopRun(status, attempt, maxAttempts) {
|
|
|
822
822
|
}
|
|
823
823
|
return;
|
|
824
824
|
}
|
|
825
|
+
function chmodIfExists(path, mode) {
|
|
826
|
+
try {
|
|
827
|
+
if (existsSync(path))
|
|
828
|
+
chmodSync(path, mode);
|
|
829
|
+
} catch {}
|
|
830
|
+
}
|
|
831
|
+
function ensurePrivateStorePath(file) {
|
|
832
|
+
const dir = dirname(file);
|
|
833
|
+
mkdirSync3(dir, { recursive: true, mode: 448 });
|
|
834
|
+
chmodIfExists(dir, 448);
|
|
835
|
+
chmodIfExists(file, 384);
|
|
836
|
+
chmodIfExists(`${file}-wal`, 384);
|
|
837
|
+
chmodIfExists(`${file}-shm`, 384);
|
|
838
|
+
}
|
|
825
839
|
|
|
826
840
|
class Store {
|
|
827
841
|
db;
|
|
@@ -829,11 +843,13 @@ class Store {
|
|
|
829
843
|
constructor(path) {
|
|
830
844
|
const file = path ?? dbPath();
|
|
831
845
|
if (file !== ":memory:")
|
|
832
|
-
|
|
846
|
+
ensurePrivateStorePath(file);
|
|
833
847
|
this.rootDir = file === ":memory:" ? mkdtempSync(join3(tmpdir(), "open-loops-store-")) : dirname(file);
|
|
834
848
|
this.db = new Database(file);
|
|
835
849
|
this.db.exec("PRAGMA busy_timeout = 5000;");
|
|
836
850
|
this.db.exec("PRAGMA journal_mode = WAL;");
|
|
851
|
+
if (file !== ":memory:")
|
|
852
|
+
ensurePrivateStorePath(file);
|
|
837
853
|
this.migrate();
|
|
838
854
|
}
|
|
839
855
|
migrate() {
|
|
@@ -2665,7 +2681,7 @@ import { resolveMachineCommand } from "@hasna/machines/consumer";
|
|
|
2665
2681
|
|
|
2666
2682
|
// src/lib/accounts.ts
|
|
2667
2683
|
import { spawnSync } from "child_process";
|
|
2668
|
-
import { existsSync } from "fs";
|
|
2684
|
+
import { existsSync as existsSync2 } from "fs";
|
|
2669
2685
|
var EXPORT_RE = /^export\s+([A-Za-z_][A-Za-z0-9_]*)=(.*)$/;
|
|
2670
2686
|
function accountToolForProvider(provider) {
|
|
2671
2687
|
switch (provider) {
|
|
@@ -2750,7 +2766,7 @@ function resolveAccountEnv(account, toolHint, env) {
|
|
|
2750
2766
|
const profileDir = (accountDirEnvVar(tool) ? accountEnv[accountDirEnvVar(tool)] : undefined) ?? primaryAccountDir(result.stdout);
|
|
2751
2767
|
if (!profileDir)
|
|
2752
2768
|
throw new Error(`accounts env returned no profile directory for ${account.profile}/${tool}`);
|
|
2753
|
-
if (!
|
|
2769
|
+
if (!existsSync2(profileDir))
|
|
2754
2770
|
throw new Error(`account profile directory does not exist for ${account.profile}/${tool}: ${profileDir}`);
|
|
2755
2771
|
return {
|
|
2756
2772
|
...accountEnv,
|
|
@@ -3114,7 +3130,7 @@ function agentArgs(target) {
|
|
|
3114
3130
|
case "codex":
|
|
3115
3131
|
if (target.variant)
|
|
3116
3132
|
args.push("-c", `model_reasoning_effort=${configStringValue(target.variant)}`);
|
|
3117
|
-
args.push("exec", "--json", "--ephemeral", "--
|
|
3133
|
+
args.push("exec", "--json", "--ephemeral", "--sandbox", codewithLikeSandbox(target), "--skip-git-repo-check");
|
|
3118
3134
|
if (isolation === "safe")
|
|
3119
3135
|
args.push("--ignore-rules");
|
|
3120
3136
|
if (target.cwd)
|
package/package.json
CHANGED