greprag 5.77.0 → 5.78.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/app/app.css +342 -0
- package/app/app.js +360 -0
- package/app/favicon.svg +4 -0
- package/app/index.html +54 -0
- package/dist/app-settings.js +162 -0
- package/dist/commands/app-model.js +308 -0
- package/dist/commands/app.js +310 -0
- package/dist/commands/opencode-interrupt.js +4 -3
- package/dist/hook.js +5 -2
- package/dist/index.js +12 -1
- package/dist/opencode-plugin.bundle.js +300 -272
- package/dist/reminder-injector.js +2 -1
- package/package.json +2 -1
- package/scripts/postinstall.js +2 -1
|
@@ -24,9 +24,9 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
24
24
|
|
|
25
25
|
// src/opencode-plugin.ts
|
|
26
26
|
var crypto5 = __toESM(require("crypto"));
|
|
27
|
-
var
|
|
28
|
-
var
|
|
29
|
-
var
|
|
27
|
+
var fs8 = __toESM(require("fs"));
|
|
28
|
+
var os3 = __toESM(require("os"));
|
|
29
|
+
var path8 = __toESM(require("path"));
|
|
30
30
|
|
|
31
31
|
// src/opencode-plugin-helpers.ts
|
|
32
32
|
var crypto = __toESM(require("crypto"));
|
|
@@ -2572,6 +2572,216 @@ function collectAnnounces(env, registry = REGISTRY) {
|
|
|
2572
2572
|
return out;
|
|
2573
2573
|
}
|
|
2574
2574
|
|
|
2575
|
+
// src/app-settings.ts
|
|
2576
|
+
var fs3 = __toESM(require("node:fs"));
|
|
2577
|
+
var os2 = __toESM(require("node:os"));
|
|
2578
|
+
var path3 = __toESM(require("node:path"));
|
|
2579
|
+
|
|
2580
|
+
// src/project-anchor.ts
|
|
2581
|
+
var path2 = __toESM(require("path"));
|
|
2582
|
+
var fs2 = __toESM(require("fs"));
|
|
2583
|
+
var crypto2 = __toESM(require("crypto"));
|
|
2584
|
+
var os = __toESM(require("os"));
|
|
2585
|
+
var ANCHOR_DIR = ".greprag";
|
|
2586
|
+
var ANCHOR_FILE = "project.json";
|
|
2587
|
+
var LEGACY_ANCHOR_DIR = ".claude";
|
|
2588
|
+
function anchorPathIn(dir) {
|
|
2589
|
+
return path2.join(dir, ANCHOR_DIR, ANCHOR_FILE);
|
|
2590
|
+
}
|
|
2591
|
+
function legacyAnchorPathIn(dir) {
|
|
2592
|
+
return path2.join(dir, LEGACY_ANCHOR_DIR, ANCHOR_FILE);
|
|
2593
|
+
}
|
|
2594
|
+
function globalAnchorPath() {
|
|
2595
|
+
return anchorPathIn(os.homedir());
|
|
2596
|
+
}
|
|
2597
|
+
function legacyGlobalAnchorPath() {
|
|
2598
|
+
return legacyAnchorPathIn(os.homedir());
|
|
2599
|
+
}
|
|
2600
|
+
function findExistingAnchor(startDir) {
|
|
2601
|
+
const homeAnchor = globalAnchorPath();
|
|
2602
|
+
const legacyHomeAnchor = legacyGlobalAnchorPath();
|
|
2603
|
+
let dir = path2.resolve(startDir);
|
|
2604
|
+
while (true) {
|
|
2605
|
+
const candidate = anchorPathIn(dir);
|
|
2606
|
+
if (candidate !== homeAnchor && fs2.existsSync(candidate))
|
|
2607
|
+
return candidate;
|
|
2608
|
+
const legacyCandidate = legacyAnchorPathIn(dir);
|
|
2609
|
+
if (legacyCandidate !== legacyHomeAnchor && fs2.existsSync(legacyCandidate))
|
|
2610
|
+
return legacyCandidate;
|
|
2611
|
+
const parent = path2.dirname(dir);
|
|
2612
|
+
if (parent === dir)
|
|
2613
|
+
return null;
|
|
2614
|
+
dir = parent;
|
|
2615
|
+
}
|
|
2616
|
+
}
|
|
2617
|
+
function isEphemeralCwd2(cwd) {
|
|
2618
|
+
const norm = path2.resolve(cwd).replace(/\\/g, "/").toLowerCase();
|
|
2619
|
+
if (norm.includes("/appdata/roaming/claude/local-agent-mode-sessions/"))
|
|
2620
|
+
return true;
|
|
2621
|
+
if (norm.includes("/appdata/local/claude/local-agent-mode-sessions/"))
|
|
2622
|
+
return true;
|
|
2623
|
+
if (norm.startsWith("/tmp/"))
|
|
2624
|
+
return true;
|
|
2625
|
+
if (norm.startsWith("/var/tmp/"))
|
|
2626
|
+
return true;
|
|
2627
|
+
if (norm.startsWith("/private/tmp/"))
|
|
2628
|
+
return true;
|
|
2629
|
+
return false;
|
|
2630
|
+
}
|
|
2631
|
+
function computeGitDerivedProjectId2(workingDir) {
|
|
2632
|
+
try {
|
|
2633
|
+
const out = safeExecSync("git rev-list --max-parents=0 HEAD", {
|
|
2634
|
+
cwd: workingDir,
|
|
2635
|
+
encoding: "utf-8",
|
|
2636
|
+
stdio: ["pipe", "pipe", "pipe"]
|
|
2637
|
+
});
|
|
2638
|
+
const roots = out.trim().split(/\s+/).filter(Boolean).sort();
|
|
2639
|
+
if (roots.length === 0)
|
|
2640
|
+
return null;
|
|
2641
|
+
const hash = crypto2.createHash("sha256").update(roots.join("\n")).digest("hex");
|
|
2642
|
+
return [
|
|
2643
|
+
hash.slice(0, 8),
|
|
2644
|
+
hash.slice(8, 12),
|
|
2645
|
+
"4" + hash.slice(13, 16),
|
|
2646
|
+
// version 4 nibble
|
|
2647
|
+
"8" + hash.slice(17, 20),
|
|
2648
|
+
// variant nibble
|
|
2649
|
+
hash.slice(20, 32)
|
|
2650
|
+
].join("-");
|
|
2651
|
+
} catch {
|
|
2652
|
+
return null;
|
|
2653
|
+
}
|
|
2654
|
+
}
|
|
2655
|
+
function deterministicProjectId2(workingDir) {
|
|
2656
|
+
const normalized = path2.resolve(workingDir).toLowerCase();
|
|
2657
|
+
const hash = crypto2.createHash("sha256").update(normalized).digest("hex");
|
|
2658
|
+
return [
|
|
2659
|
+
hash.slice(0, 8),
|
|
2660
|
+
hash.slice(8, 12),
|
|
2661
|
+
"4" + hash.slice(13, 16),
|
|
2662
|
+
// version 4 nibble
|
|
2663
|
+
"8" + hash.slice(17, 20),
|
|
2664
|
+
// variant nibble
|
|
2665
|
+
hash.slice(20, 32)
|
|
2666
|
+
].join("-");
|
|
2667
|
+
}
|
|
2668
|
+
function tryReadAnchorFileContents(filePath) {
|
|
2669
|
+
try {
|
|
2670
|
+
const raw = JSON.parse(fs2.readFileSync(filePath, "utf-8"));
|
|
2671
|
+
const notifyRaw = raw.inbox_notify;
|
|
2672
|
+
const inboxNotify = notifyRaw === "off" || notifyRaw === "session_start_only" ? notifyRaw : "every_turn";
|
|
2673
|
+
return {
|
|
2674
|
+
projectId: raw.project_id,
|
|
2675
|
+
projectName: raw.project_name,
|
|
2676
|
+
created: raw.created,
|
|
2677
|
+
memoryCapture: raw.memory_capture !== false,
|
|
2678
|
+
sessionStartRecap: raw.session_start_recap !== false,
|
|
2679
|
+
inboxNotify,
|
|
2680
|
+
emailDir: typeof raw.email_dir === "string" ? raw.email_dir : void 0,
|
|
2681
|
+
emailAutosave: raw.email_autosave === true,
|
|
2682
|
+
role: typeof raw.role === "string" ? raw.role : void 0
|
|
2683
|
+
};
|
|
2684
|
+
} catch {
|
|
2685
|
+
return null;
|
|
2686
|
+
}
|
|
2687
|
+
}
|
|
2688
|
+
function readAnchor2(cwd) {
|
|
2689
|
+
const existingPath = findExistingAnchor(cwd);
|
|
2690
|
+
const fileContents = existingPath ? tryReadAnchorFileContents(existingPath) : null;
|
|
2691
|
+
if (existingPath && fileContents && fileContents.projectId && fileContents.projectName) {
|
|
2692
|
+
return {
|
|
2693
|
+
projectId: fileContents.projectId,
|
|
2694
|
+
projectName: fileContents.projectName,
|
|
2695
|
+
initialized: true,
|
|
2696
|
+
source: "file",
|
|
2697
|
+
anchorPath: existingPath,
|
|
2698
|
+
created: fileContents.created,
|
|
2699
|
+
memoryCapture: fileContents.memoryCapture,
|
|
2700
|
+
sessionStartRecap: fileContents.sessionStartRecap,
|
|
2701
|
+
inboxNotify: fileContents.inboxNotify,
|
|
2702
|
+
emailDir: fileContents.emailDir,
|
|
2703
|
+
emailAutosave: fileContents.emailAutosave,
|
|
2704
|
+
role: fileContents.role
|
|
2705
|
+
};
|
|
2706
|
+
}
|
|
2707
|
+
const gitId = computeGitDerivedProjectId2(cwd);
|
|
2708
|
+
if (gitId) {
|
|
2709
|
+
const root2 = path2.resolve(cwd);
|
|
2710
|
+
return {
|
|
2711
|
+
projectId: gitId,
|
|
2712
|
+
projectName: fileContents?.projectName || path2.basename(root2).toLowerCase(),
|
|
2713
|
+
initialized: true,
|
|
2714
|
+
source: "git",
|
|
2715
|
+
anchorPath: existingPath || anchorPathIn(root2),
|
|
2716
|
+
created: fileContents?.created,
|
|
2717
|
+
memoryCapture: fileContents?.memoryCapture ?? true,
|
|
2718
|
+
sessionStartRecap: fileContents?.sessionStartRecap ?? true,
|
|
2719
|
+
inboxNotify: fileContents?.inboxNotify ?? "every_turn",
|
|
2720
|
+
emailDir: fileContents?.emailDir,
|
|
2721
|
+
emailAutosave: fileContents?.emailAutosave,
|
|
2722
|
+
role: fileContents?.role
|
|
2723
|
+
};
|
|
2724
|
+
}
|
|
2725
|
+
if (isEphemeralCwd2(cwd)) {
|
|
2726
|
+
const globalPath = fs2.existsSync(globalAnchorPath()) ? globalAnchorPath() : legacyGlobalAnchorPath();
|
|
2727
|
+
const globalContents = tryReadAnchorFileContents(globalPath);
|
|
2728
|
+
if (globalContents && globalContents.projectId && globalContents.projectName) {
|
|
2729
|
+
return {
|
|
2730
|
+
projectId: globalContents.projectId,
|
|
2731
|
+
projectName: globalContents.projectName,
|
|
2732
|
+
initialized: true,
|
|
2733
|
+
source: "global",
|
|
2734
|
+
anchorPath: globalPath,
|
|
2735
|
+
created: globalContents.created,
|
|
2736
|
+
memoryCapture: globalContents.memoryCapture,
|
|
2737
|
+
sessionStartRecap: globalContents.sessionStartRecap,
|
|
2738
|
+
inboxNotify: globalContents.inboxNotify,
|
|
2739
|
+
emailDir: globalContents.emailDir,
|
|
2740
|
+
emailAutosave: globalContents.emailAutosave,
|
|
2741
|
+
role: globalContents.role
|
|
2742
|
+
};
|
|
2743
|
+
}
|
|
2744
|
+
}
|
|
2745
|
+
const root = path2.resolve(cwd);
|
|
2746
|
+
return {
|
|
2747
|
+
projectId: deterministicProjectId2(root),
|
|
2748
|
+
projectName: fileContents?.projectName || path2.basename(root).toLowerCase(),
|
|
2749
|
+
initialized: false,
|
|
2750
|
+
source: "hash",
|
|
2751
|
+
anchorPath: existingPath || anchorPathIn(root),
|
|
2752
|
+
created: fileContents?.created,
|
|
2753
|
+
memoryCapture: fileContents?.memoryCapture ?? true,
|
|
2754
|
+
sessionStartRecap: fileContents?.sessionStartRecap ?? true,
|
|
2755
|
+
inboxNotify: fileContents?.inboxNotify ?? "every_turn",
|
|
2756
|
+
emailDir: fileContents?.emailDir,
|
|
2757
|
+
emailAutosave: fileContents?.emailAutosave,
|
|
2758
|
+
role: fileContents?.role
|
|
2759
|
+
};
|
|
2760
|
+
}
|
|
2761
|
+
|
|
2762
|
+
// src/app-settings.ts
|
|
2763
|
+
function readJson(file) {
|
|
2764
|
+
try {
|
|
2765
|
+
const parsed = JSON.parse(fs3.readFileSync(file, "utf8"));
|
|
2766
|
+
return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : {};
|
|
2767
|
+
} catch {
|
|
2768
|
+
return {};
|
|
2769
|
+
}
|
|
2770
|
+
}
|
|
2771
|
+
function localAppSettingsPath(homeDir = os2.homedir()) {
|
|
2772
|
+
return path3.join(homeDir, ".greprag", "settings.json");
|
|
2773
|
+
}
|
|
2774
|
+
function readLocalAppSettings(homeDir = os2.homedir()) {
|
|
2775
|
+
const raw = readJson(localAppSettingsPath(homeDir));
|
|
2776
|
+
const interrupts = raw.interrupts && typeof raw.interrupts === "object" ? raw.interrupts : {};
|
|
2777
|
+
const disabled = Array.isArray(interrupts.disabled) ? [...new Set(interrupts.disabled.filter((id) => typeof id === "string" && /^[a-z0-9-]{1,80}$/.test(id)))] : [];
|
|
2778
|
+
return { version: 1, interrupts: { disabled } };
|
|
2779
|
+
}
|
|
2780
|
+
function filterEnabledInterrupts(modules, settings = readLocalAppSettings()) {
|
|
2781
|
+
const disabled = new Set(settings.interrupts.disabled);
|
|
2782
|
+
return modules.filter((module2) => !disabled.has(module2.id));
|
|
2783
|
+
}
|
|
2784
|
+
|
|
2575
2785
|
// src/commands/opencode-interrupt.ts
|
|
2576
2786
|
var opencodeRegistry = harnessModules("opencode");
|
|
2577
2787
|
var OPENCODE_QUOTA_WAITLIST_ANNOUNCE = [
|
|
@@ -2606,18 +2816,18 @@ function buildOpenCodeEnv(params) {
|
|
|
2606
2816
|
};
|
|
2607
2817
|
}
|
|
2608
2818
|
function getOpenCodeAnnounces(env) {
|
|
2609
|
-
return [...collectAnnounces(env, opencodeRegistry), OPENCODE_QUOTA_WAITLIST_ANNOUNCE];
|
|
2819
|
+
return [...collectAnnounces(env, filterEnabledInterrupts(opencodeRegistry)), OPENCODE_QUOTA_WAITLIST_ANNOUNCE];
|
|
2610
2820
|
}
|
|
2611
2821
|
function getOpenCodePersistentAnnounces(env) {
|
|
2612
|
-
return collectAnnounces(env, opencodeRegistry.filter((m) => m.id === "persona-announce"));
|
|
2822
|
+
return collectAnnounces(env, filterEnabledInterrupts(opencodeRegistry.filter((m) => m.id === "persona-announce")));
|
|
2613
2823
|
}
|
|
2614
2824
|
function getOpenCodeReminders(env) {
|
|
2615
|
-
return collectReminders(env, opencodeRegistry);
|
|
2825
|
+
return collectReminders(env, filterEnabledInterrupts(opencodeRegistry));
|
|
2616
2826
|
}
|
|
2617
2827
|
|
|
2618
2828
|
// src/procedure.ts
|
|
2619
|
-
var
|
|
2620
|
-
var
|
|
2829
|
+
var path4 = __toESM(require("path"));
|
|
2830
|
+
var fs4 = __toESM(require("fs"));
|
|
2621
2831
|
|
|
2622
2832
|
// src/delivery-lifecycle.ts
|
|
2623
2833
|
var DELIVERY_LIFECYCLE_VERBS = [
|
|
@@ -2636,14 +2846,14 @@ function isDeliveryLifecycleVerb(verb) {
|
|
|
2636
2846
|
var PROCEDURE_STORE_VERSION = "2";
|
|
2637
2847
|
function stateDir() {
|
|
2638
2848
|
const home = process.env.HOME || process.env.USERPROFILE || "";
|
|
2639
|
-
return
|
|
2849
|
+
return path4.join(home, ".greprag", "state");
|
|
2640
2850
|
}
|
|
2641
2851
|
function procedureStorePath(projectId) {
|
|
2642
|
-
return
|
|
2852
|
+
return path4.join(stateDir(), `procedures-${projectId}.json`);
|
|
2643
2853
|
}
|
|
2644
2854
|
function readProcedureStore(projectId) {
|
|
2645
2855
|
try {
|
|
2646
|
-
const raw =
|
|
2856
|
+
const raw = fs4.readFileSync(procedureStorePath(projectId), "utf-8");
|
|
2647
2857
|
const parsed = JSON.parse(raw);
|
|
2648
2858
|
if (parsed && Array.isArray(parsed.procedures)) {
|
|
2649
2859
|
return normalizeProcedureStore({
|
|
@@ -2876,191 +3086,9 @@ function activeProcedureAnnounces(store) {
|
|
|
2876
3086
|
// src/procedure-runtime.ts
|
|
2877
3087
|
var crypto4 = __toESM(require("crypto"));
|
|
2878
3088
|
|
|
2879
|
-
// src/project-anchor.ts
|
|
2880
|
-
var path3 = __toESM(require("path"));
|
|
2881
|
-
var fs3 = __toESM(require("fs"));
|
|
2882
|
-
var crypto2 = __toESM(require("crypto"));
|
|
2883
|
-
var os = __toESM(require("os"));
|
|
2884
|
-
var ANCHOR_DIR = ".greprag";
|
|
2885
|
-
var ANCHOR_FILE = "project.json";
|
|
2886
|
-
var LEGACY_ANCHOR_DIR = ".claude";
|
|
2887
|
-
function anchorPathIn(dir) {
|
|
2888
|
-
return path3.join(dir, ANCHOR_DIR, ANCHOR_FILE);
|
|
2889
|
-
}
|
|
2890
|
-
function legacyAnchorPathIn(dir) {
|
|
2891
|
-
return path3.join(dir, LEGACY_ANCHOR_DIR, ANCHOR_FILE);
|
|
2892
|
-
}
|
|
2893
|
-
function globalAnchorPath() {
|
|
2894
|
-
return anchorPathIn(os.homedir());
|
|
2895
|
-
}
|
|
2896
|
-
function legacyGlobalAnchorPath() {
|
|
2897
|
-
return legacyAnchorPathIn(os.homedir());
|
|
2898
|
-
}
|
|
2899
|
-
function findExistingAnchor(startDir) {
|
|
2900
|
-
const homeAnchor = globalAnchorPath();
|
|
2901
|
-
const legacyHomeAnchor = legacyGlobalAnchorPath();
|
|
2902
|
-
let dir = path3.resolve(startDir);
|
|
2903
|
-
while (true) {
|
|
2904
|
-
const candidate = anchorPathIn(dir);
|
|
2905
|
-
if (candidate !== homeAnchor && fs3.existsSync(candidate))
|
|
2906
|
-
return candidate;
|
|
2907
|
-
const legacyCandidate = legacyAnchorPathIn(dir);
|
|
2908
|
-
if (legacyCandidate !== legacyHomeAnchor && fs3.existsSync(legacyCandidate))
|
|
2909
|
-
return legacyCandidate;
|
|
2910
|
-
const parent = path3.dirname(dir);
|
|
2911
|
-
if (parent === dir)
|
|
2912
|
-
return null;
|
|
2913
|
-
dir = parent;
|
|
2914
|
-
}
|
|
2915
|
-
}
|
|
2916
|
-
function isEphemeralCwd2(cwd) {
|
|
2917
|
-
const norm = path3.resolve(cwd).replace(/\\/g, "/").toLowerCase();
|
|
2918
|
-
if (norm.includes("/appdata/roaming/claude/local-agent-mode-sessions/"))
|
|
2919
|
-
return true;
|
|
2920
|
-
if (norm.includes("/appdata/local/claude/local-agent-mode-sessions/"))
|
|
2921
|
-
return true;
|
|
2922
|
-
if (norm.startsWith("/tmp/"))
|
|
2923
|
-
return true;
|
|
2924
|
-
if (norm.startsWith("/var/tmp/"))
|
|
2925
|
-
return true;
|
|
2926
|
-
if (norm.startsWith("/private/tmp/"))
|
|
2927
|
-
return true;
|
|
2928
|
-
return false;
|
|
2929
|
-
}
|
|
2930
|
-
function computeGitDerivedProjectId2(workingDir) {
|
|
2931
|
-
try {
|
|
2932
|
-
const out = safeExecSync("git rev-list --max-parents=0 HEAD", {
|
|
2933
|
-
cwd: workingDir,
|
|
2934
|
-
encoding: "utf-8",
|
|
2935
|
-
stdio: ["pipe", "pipe", "pipe"]
|
|
2936
|
-
});
|
|
2937
|
-
const roots = out.trim().split(/\s+/).filter(Boolean).sort();
|
|
2938
|
-
if (roots.length === 0)
|
|
2939
|
-
return null;
|
|
2940
|
-
const hash = crypto2.createHash("sha256").update(roots.join("\n")).digest("hex");
|
|
2941
|
-
return [
|
|
2942
|
-
hash.slice(0, 8),
|
|
2943
|
-
hash.slice(8, 12),
|
|
2944
|
-
"4" + hash.slice(13, 16),
|
|
2945
|
-
// version 4 nibble
|
|
2946
|
-
"8" + hash.slice(17, 20),
|
|
2947
|
-
// variant nibble
|
|
2948
|
-
hash.slice(20, 32)
|
|
2949
|
-
].join("-");
|
|
2950
|
-
} catch {
|
|
2951
|
-
return null;
|
|
2952
|
-
}
|
|
2953
|
-
}
|
|
2954
|
-
function deterministicProjectId2(workingDir) {
|
|
2955
|
-
const normalized = path3.resolve(workingDir).toLowerCase();
|
|
2956
|
-
const hash = crypto2.createHash("sha256").update(normalized).digest("hex");
|
|
2957
|
-
return [
|
|
2958
|
-
hash.slice(0, 8),
|
|
2959
|
-
hash.slice(8, 12),
|
|
2960
|
-
"4" + hash.slice(13, 16),
|
|
2961
|
-
// version 4 nibble
|
|
2962
|
-
"8" + hash.slice(17, 20),
|
|
2963
|
-
// variant nibble
|
|
2964
|
-
hash.slice(20, 32)
|
|
2965
|
-
].join("-");
|
|
2966
|
-
}
|
|
2967
|
-
function tryReadAnchorFileContents(filePath) {
|
|
2968
|
-
try {
|
|
2969
|
-
const raw = JSON.parse(fs3.readFileSync(filePath, "utf-8"));
|
|
2970
|
-
const notifyRaw = raw.inbox_notify;
|
|
2971
|
-
const inboxNotify = notifyRaw === "off" || notifyRaw === "session_start_only" ? notifyRaw : "every_turn";
|
|
2972
|
-
return {
|
|
2973
|
-
projectId: raw.project_id,
|
|
2974
|
-
projectName: raw.project_name,
|
|
2975
|
-
created: raw.created,
|
|
2976
|
-
memoryCapture: raw.memory_capture !== false,
|
|
2977
|
-
sessionStartRecap: raw.session_start_recap !== false,
|
|
2978
|
-
inboxNotify,
|
|
2979
|
-
emailDir: typeof raw.email_dir === "string" ? raw.email_dir : void 0,
|
|
2980
|
-
emailAutosave: raw.email_autosave === true,
|
|
2981
|
-
role: typeof raw.role === "string" ? raw.role : void 0
|
|
2982
|
-
};
|
|
2983
|
-
} catch {
|
|
2984
|
-
return null;
|
|
2985
|
-
}
|
|
2986
|
-
}
|
|
2987
|
-
function readAnchor2(cwd) {
|
|
2988
|
-
const existingPath = findExistingAnchor(cwd);
|
|
2989
|
-
const fileContents = existingPath ? tryReadAnchorFileContents(existingPath) : null;
|
|
2990
|
-
if (existingPath && fileContents && fileContents.projectId && fileContents.projectName) {
|
|
2991
|
-
return {
|
|
2992
|
-
projectId: fileContents.projectId,
|
|
2993
|
-
projectName: fileContents.projectName,
|
|
2994
|
-
initialized: true,
|
|
2995
|
-
source: "file",
|
|
2996
|
-
anchorPath: existingPath,
|
|
2997
|
-
created: fileContents.created,
|
|
2998
|
-
memoryCapture: fileContents.memoryCapture,
|
|
2999
|
-
sessionStartRecap: fileContents.sessionStartRecap,
|
|
3000
|
-
inboxNotify: fileContents.inboxNotify,
|
|
3001
|
-
emailDir: fileContents.emailDir,
|
|
3002
|
-
emailAutosave: fileContents.emailAutosave,
|
|
3003
|
-
role: fileContents.role
|
|
3004
|
-
};
|
|
3005
|
-
}
|
|
3006
|
-
const gitId = computeGitDerivedProjectId2(cwd);
|
|
3007
|
-
if (gitId) {
|
|
3008
|
-
const root2 = path3.resolve(cwd);
|
|
3009
|
-
return {
|
|
3010
|
-
projectId: gitId,
|
|
3011
|
-
projectName: fileContents?.projectName || path3.basename(root2).toLowerCase(),
|
|
3012
|
-
initialized: true,
|
|
3013
|
-
source: "git",
|
|
3014
|
-
anchorPath: existingPath || anchorPathIn(root2),
|
|
3015
|
-
created: fileContents?.created,
|
|
3016
|
-
memoryCapture: fileContents?.memoryCapture ?? true,
|
|
3017
|
-
sessionStartRecap: fileContents?.sessionStartRecap ?? true,
|
|
3018
|
-
inboxNotify: fileContents?.inboxNotify ?? "every_turn",
|
|
3019
|
-
emailDir: fileContents?.emailDir,
|
|
3020
|
-
emailAutosave: fileContents?.emailAutosave,
|
|
3021
|
-
role: fileContents?.role
|
|
3022
|
-
};
|
|
3023
|
-
}
|
|
3024
|
-
if (isEphemeralCwd2(cwd)) {
|
|
3025
|
-
const globalPath = fs3.existsSync(globalAnchorPath()) ? globalAnchorPath() : legacyGlobalAnchorPath();
|
|
3026
|
-
const globalContents = tryReadAnchorFileContents(globalPath);
|
|
3027
|
-
if (globalContents && globalContents.projectId && globalContents.projectName) {
|
|
3028
|
-
return {
|
|
3029
|
-
projectId: globalContents.projectId,
|
|
3030
|
-
projectName: globalContents.projectName,
|
|
3031
|
-
initialized: true,
|
|
3032
|
-
source: "global",
|
|
3033
|
-
anchorPath: globalPath,
|
|
3034
|
-
created: globalContents.created,
|
|
3035
|
-
memoryCapture: globalContents.memoryCapture,
|
|
3036
|
-
sessionStartRecap: globalContents.sessionStartRecap,
|
|
3037
|
-
inboxNotify: globalContents.inboxNotify,
|
|
3038
|
-
emailDir: globalContents.emailDir,
|
|
3039
|
-
emailAutosave: globalContents.emailAutosave,
|
|
3040
|
-
role: globalContents.role
|
|
3041
|
-
};
|
|
3042
|
-
}
|
|
3043
|
-
}
|
|
3044
|
-
const root = path3.resolve(cwd);
|
|
3045
|
-
return {
|
|
3046
|
-
projectId: deterministicProjectId2(root),
|
|
3047
|
-
projectName: fileContents?.projectName || path3.basename(root).toLowerCase(),
|
|
3048
|
-
initialized: false,
|
|
3049
|
-
source: "hash",
|
|
3050
|
-
anchorPath: existingPath || anchorPathIn(root),
|
|
3051
|
-
created: fileContents?.created,
|
|
3052
|
-
memoryCapture: fileContents?.memoryCapture ?? true,
|
|
3053
|
-
sessionStartRecap: fileContents?.sessionStartRecap ?? true,
|
|
3054
|
-
inboxNotify: fileContents?.inboxNotify ?? "every_turn",
|
|
3055
|
-
emailDir: fileContents?.emailDir,
|
|
3056
|
-
emailAutosave: fileContents?.emailAutosave,
|
|
3057
|
-
role: fileContents?.role
|
|
3058
|
-
};
|
|
3059
|
-
}
|
|
3060
|
-
|
|
3061
3089
|
// src/procedure-watch.ts
|
|
3062
|
-
var
|
|
3063
|
-
var
|
|
3090
|
+
var path5 = __toESM(require("path"));
|
|
3091
|
+
var fs5 = __toESM(require("fs"));
|
|
3064
3092
|
var TIER1_LEARN_TRIGGERS = [
|
|
3065
3093
|
{ verb: "deploy", triggers: ["deploy", "deploy the api", "deploy the worker", "redeploy"], steps: "", status: "seeded" },
|
|
3066
3094
|
{ verb: "push", triggers: ["push", "git push", "push to remote", "push it up", "push upstream"], steps: "", status: "seeded", destructive: true },
|
|
@@ -3093,24 +3121,24 @@ function openWatch(verb, phase, openedAt, shadowRunId) {
|
|
|
3093
3121
|
}
|
|
3094
3122
|
function stateDir2() {
|
|
3095
3123
|
const home = process.env.HOME || process.env.USERPROFILE || "";
|
|
3096
|
-
return
|
|
3124
|
+
return path5.join(home, ".greprag", "state");
|
|
3097
3125
|
}
|
|
3098
3126
|
function procedureWatchPath(projectId) {
|
|
3099
|
-
return
|
|
3127
|
+
return path5.join(stateDir2(), `procedure-watch-${projectId}.json`);
|
|
3100
3128
|
}
|
|
3101
3129
|
function hasProcedureWatch(projectId) {
|
|
3102
3130
|
try {
|
|
3103
|
-
return
|
|
3131
|
+
return fs5.existsSync(procedureWatchPath(projectId));
|
|
3104
3132
|
} catch {
|
|
3105
3133
|
return false;
|
|
3106
3134
|
}
|
|
3107
3135
|
}
|
|
3108
3136
|
function writeProcedureWatch(projectId, watch) {
|
|
3109
3137
|
const file = procedureWatchPath(projectId);
|
|
3110
|
-
const dir =
|
|
3111
|
-
if (!
|
|
3112
|
-
|
|
3113
|
-
|
|
3138
|
+
const dir = path5.dirname(file);
|
|
3139
|
+
if (!fs5.existsSync(dir))
|
|
3140
|
+
fs5.mkdirSync(dir, { recursive: true });
|
|
3141
|
+
fs5.writeFileSync(file, JSON.stringify(watch, null, 2) + "\n");
|
|
3114
3142
|
}
|
|
3115
3143
|
function openWatchIfIdle(projectId, verb, phase, shadowRunId) {
|
|
3116
3144
|
if (hasProcedureWatch(projectId))
|
|
@@ -3121,20 +3149,20 @@ function openWatchIfIdle(projectId, verb, phase, shadowRunId) {
|
|
|
3121
3149
|
|
|
3122
3150
|
// src/procedure-shadow.ts
|
|
3123
3151
|
var crypto3 = __toESM(require("crypto"));
|
|
3124
|
-
var
|
|
3125
|
-
var
|
|
3152
|
+
var fs6 = __toESM(require("fs"));
|
|
3153
|
+
var path6 = __toESM(require("path"));
|
|
3126
3154
|
function stateDir3() {
|
|
3127
3155
|
const home = process.env.HOME || process.env.USERPROFILE || "";
|
|
3128
|
-
return
|
|
3156
|
+
return path6.join(home, ".greprag", "state");
|
|
3129
3157
|
}
|
|
3130
3158
|
function procedureShadowPath(projectId) {
|
|
3131
|
-
return
|
|
3159
|
+
return path6.join(stateDir3(), `procedure-shadow-${projectId}.jsonl`);
|
|
3132
3160
|
}
|
|
3133
3161
|
function appendShadowEvent(projectId, event) {
|
|
3134
3162
|
try {
|
|
3135
3163
|
const file = procedureShadowPath(projectId);
|
|
3136
|
-
|
|
3137
|
-
|
|
3164
|
+
fs6.mkdirSync(path6.dirname(file), { recursive: true });
|
|
3165
|
+
fs6.appendFileSync(file, JSON.stringify(event) + "\n");
|
|
3138
3166
|
} catch {
|
|
3139
3167
|
}
|
|
3140
3168
|
}
|
|
@@ -3854,29 +3882,29 @@ function recodeMessagesToPng(messages, opts) {
|
|
|
3854
3882
|
}
|
|
3855
3883
|
|
|
3856
3884
|
// src/skill-activation-manifest.ts
|
|
3857
|
-
var
|
|
3858
|
-
var
|
|
3885
|
+
var fs7 = __toESM(require("fs"));
|
|
3886
|
+
var path7 = __toESM(require("path"));
|
|
3859
3887
|
var MAX_NATIVE_SKILL_FILES = 1500;
|
|
3860
3888
|
var MAX_SCAN_DEPTH = 7;
|
|
3861
3889
|
function homeRoots(homeDir, platform) {
|
|
3862
3890
|
if (platform === "claude-code") {
|
|
3863
|
-
return [
|
|
3891
|
+
return [path7.join(homeDir, ".claude", "skills")];
|
|
3864
3892
|
}
|
|
3865
3893
|
if (platform === "codex") {
|
|
3866
3894
|
return [
|
|
3867
|
-
|
|
3868
|
-
|
|
3869
|
-
|
|
3895
|
+
path7.join(homeDir, ".codex", "skills"),
|
|
3896
|
+
path7.join(homeDir, ".agents", "skills"),
|
|
3897
|
+
path7.join(homeDir, ".codex", "plugins", "cache")
|
|
3870
3898
|
];
|
|
3871
3899
|
}
|
|
3872
|
-
return [
|
|
3900
|
+
return [path7.join(homeDir, ".config", "opencode", "skills")];
|
|
3873
3901
|
}
|
|
3874
3902
|
function ancestorDirs(cwd) {
|
|
3875
3903
|
const dirs = [];
|
|
3876
|
-
let current =
|
|
3904
|
+
let current = path7.resolve(cwd);
|
|
3877
3905
|
for (let depth = 0; depth < 16; depth++) {
|
|
3878
3906
|
dirs.push(current);
|
|
3879
|
-
const parent =
|
|
3907
|
+
const parent = path7.dirname(current);
|
|
3880
3908
|
if (parent === current)
|
|
3881
3909
|
break;
|
|
3882
3910
|
current = parent;
|
|
@@ -3886,11 +3914,11 @@ function ancestorDirs(cwd) {
|
|
|
3886
3914
|
function repoRoots(cwd, platform) {
|
|
3887
3915
|
return ancestorDirs(cwd).flatMap((dir) => {
|
|
3888
3916
|
if (platform === "claude-code")
|
|
3889
|
-
return [
|
|
3917
|
+
return [path7.join(dir, ".claude", "skills")];
|
|
3890
3918
|
if (platform === "codex") {
|
|
3891
|
-
return [
|
|
3919
|
+
return [path7.join(dir, ".codex", "skills"), path7.join(dir, ".agents", "skills")];
|
|
3892
3920
|
}
|
|
3893
|
-
return [
|
|
3921
|
+
return [path7.join(dir, ".opencode", "skills")];
|
|
3894
3922
|
});
|
|
3895
3923
|
}
|
|
3896
3924
|
function frontmatterName(content) {
|
|
@@ -3906,14 +3934,14 @@ function readNativeSkillNames(params) {
|
|
|
3906
3934
|
return;
|
|
3907
3935
|
let entries;
|
|
3908
3936
|
try {
|
|
3909
|
-
entries =
|
|
3937
|
+
entries = fs7.readdirSync(dir, { withFileTypes: true });
|
|
3910
3938
|
} catch {
|
|
3911
3939
|
return;
|
|
3912
3940
|
}
|
|
3913
3941
|
for (const entry of entries) {
|
|
3914
3942
|
if (visited >= MAX_NATIVE_SKILL_FILES)
|
|
3915
3943
|
return;
|
|
3916
|
-
const full =
|
|
3944
|
+
const full = path7.join(dir, entry.name);
|
|
3917
3945
|
if (entry.isDirectory()) {
|
|
3918
3946
|
walk(full, depth + 1);
|
|
3919
3947
|
continue;
|
|
@@ -3921,9 +3949,9 @@ function readNativeSkillNames(params) {
|
|
|
3921
3949
|
if (!entry.isFile() || entry.name.toLowerCase() !== "skill.md")
|
|
3922
3950
|
continue;
|
|
3923
3951
|
visited++;
|
|
3924
|
-
names.add(
|
|
3952
|
+
names.add(path7.basename(path7.dirname(full)).toLowerCase());
|
|
3925
3953
|
try {
|
|
3926
|
-
const declared = frontmatterName(
|
|
3954
|
+
const declared = frontmatterName(fs7.readFileSync(full, "utf8"));
|
|
3927
3955
|
if (declared)
|
|
3928
3956
|
names.add(declared.toLowerCase());
|
|
3929
3957
|
} catch {
|
|
@@ -3955,14 +3983,14 @@ function activationFromApiRows(params) {
|
|
|
3955
3983
|
}
|
|
3956
3984
|
|
|
3957
3985
|
// src/opencode-plugin.ts
|
|
3958
|
-
var DEBUG_LOG_PATH =
|
|
3986
|
+
var DEBUG_LOG_PATH = path8.join(os3.homedir(), ".greprag", "opencode-plugin-debug.log");
|
|
3959
3987
|
var _debugLogReady = false;
|
|
3960
3988
|
function dlogInit() {
|
|
3961
3989
|
if (_debugLogReady)
|
|
3962
3990
|
return;
|
|
3963
3991
|
_debugLogReady = true;
|
|
3964
3992
|
try {
|
|
3965
|
-
|
|
3993
|
+
fs8.writeFileSync(DEBUG_LOG_PATH, "");
|
|
3966
3994
|
} catch {
|
|
3967
3995
|
}
|
|
3968
3996
|
}
|
|
@@ -3971,7 +3999,7 @@ function dlog(msg) {
|
|
|
3971
3999
|
const line = `[${(/* @__PURE__ */ new Date()).toISOString()}] [greprag-memory] ${msg}
|
|
3972
4000
|
`;
|
|
3973
4001
|
try {
|
|
3974
|
-
|
|
4002
|
+
fs8.appendFileSync(DEBUG_LOG_PATH, line);
|
|
3975
4003
|
} catch {
|
|
3976
4004
|
}
|
|
3977
4005
|
}
|
|
@@ -3979,9 +4007,9 @@ dlog(`module top reached: pid=${process.pid} argv0=${process.argv[0]} distPath=$
|
|
|
3979
4007
|
var API_URL = "https://api.greprag.com";
|
|
3980
4008
|
function loadEnvFile(filePath) {
|
|
3981
4009
|
try {
|
|
3982
|
-
if (!
|
|
4010
|
+
if (!fs8.existsSync(filePath))
|
|
3983
4011
|
return;
|
|
3984
|
-
const raw =
|
|
4012
|
+
const raw = fs8.readFileSync(filePath, "utf-8");
|
|
3985
4013
|
for (const line of raw.split(/\r?\n/)) {
|
|
3986
4014
|
const trimmed = line.trim();
|
|
3987
4015
|
if (!trimmed || trimmed.startsWith("#"))
|
|
@@ -4001,12 +4029,12 @@ function loadEnvFile(filePath) {
|
|
|
4001
4029
|
}
|
|
4002
4030
|
}
|
|
4003
4031
|
function loadGrepragEnv() {
|
|
4004
|
-
loadEnvFile(
|
|
4032
|
+
loadEnvFile(path8.join(HOME, ".greprag", ".env"));
|
|
4005
4033
|
try {
|
|
4006
|
-
const p =
|
|
4007
|
-
if (!
|
|
4034
|
+
const p = path8.join(HOME, ".claude", "settings.json");
|
|
4035
|
+
if (!fs8.existsSync(p))
|
|
4008
4036
|
return;
|
|
4009
|
-
const data = JSON.parse(
|
|
4037
|
+
const data = JSON.parse(fs8.readFileSync(p, "utf-8"));
|
|
4010
4038
|
if (data && data.env && typeof data.env === "object") {
|
|
4011
4039
|
for (const [key, val] of Object.entries(data.env)) {
|
|
4012
4040
|
if (!process.env[key] && typeof val === "string") {
|
|
@@ -4019,11 +4047,11 @@ function loadGrepragEnv() {
|
|
|
4019
4047
|
}
|
|
4020
4048
|
loadGrepragEnv();
|
|
4021
4049
|
dlog(`env loaded: MEMORY_HOOK_ENABLED=${process.env.MEMORY_HOOK_ENABLED || "<unset>"} GREPRAG_API_KEY=${process.env.GREPRAG_API_KEY ? "set" : "<unset>"} GREPRAG_OPENCODE_CAPTURE=${process.env.GREPRAG_OPENCODE_CAPTURE || "<unset>"}`);
|
|
4022
|
-
var WATCHER_LOCK =
|
|
4050
|
+
var WATCHER_LOCK = path8.join(HOME || os3.homedir(), ".greprag", "opencode-watch.lock");
|
|
4023
4051
|
var WATCHER_STALE_MS = 3e4;
|
|
4024
4052
|
function findGrepragBinary() {
|
|
4025
4053
|
const override = process.env.GREPRAG_BIN;
|
|
4026
|
-
if (override &&
|
|
4054
|
+
if (override && fs8.existsSync(override))
|
|
4027
4055
|
return override;
|
|
4028
4056
|
const binaryName = process.platform === "win32" ? "greprag.cmd" : "greprag";
|
|
4029
4057
|
try {
|
|
@@ -4032,14 +4060,14 @@ function findGrepragBinary() {
|
|
|
4032
4060
|
const candidate = line.trim();
|
|
4033
4061
|
if (!candidate)
|
|
4034
4062
|
continue;
|
|
4035
|
-
if (!
|
|
4063
|
+
if (!fs8.existsSync(candidate))
|
|
4036
4064
|
continue;
|
|
4037
4065
|
if (process.platform === "win32") {
|
|
4038
|
-
const ext =
|
|
4066
|
+
const ext = path8.extname(candidate).toLowerCase();
|
|
4039
4067
|
if (ext === ".cmd" || ext === ".exe" || ext === ".bat")
|
|
4040
4068
|
return candidate;
|
|
4041
4069
|
const cmdSibling = candidate + ".cmd";
|
|
4042
|
-
if (
|
|
4070
|
+
if (fs8.existsSync(cmdSibling))
|
|
4043
4071
|
return cmdSibling;
|
|
4044
4072
|
continue;
|
|
4045
4073
|
}
|
|
@@ -4048,19 +4076,19 @@ function findGrepragBinary() {
|
|
|
4048
4076
|
} catch {
|
|
4049
4077
|
}
|
|
4050
4078
|
const candidates = process.platform === "win32" ? [
|
|
4051
|
-
|
|
4052
|
-
|
|
4053
|
-
|
|
4054
|
-
|
|
4079
|
+
path8.join(HOME, "AppData", "Roaming", "npm", "greprag.cmd"),
|
|
4080
|
+
path8.join(HOME, "AppData", "Roaming", "npm", "greprag"),
|
|
4081
|
+
path8.join(HOME, "AppData", "Local", "Yarn", "bin", "greprag.cmd"),
|
|
4082
|
+
path8.join(HOME, "AppData", "Local", "pnpm", "bin", "greprag.cmd")
|
|
4055
4083
|
] : [
|
|
4056
4084
|
"/usr/local/bin/greprag",
|
|
4057
4085
|
"/opt/homebrew/bin/greprag",
|
|
4058
|
-
|
|
4059
|
-
|
|
4086
|
+
path8.join(HOME || "", ".local", "bin", "greprag"),
|
|
4087
|
+
path8.join(HOME || "", ".yarn", "bin", "greprag")
|
|
4060
4088
|
];
|
|
4061
4089
|
for (const c of candidates) {
|
|
4062
4090
|
try {
|
|
4063
|
-
if (c &&
|
|
4091
|
+
if (c && fs8.existsSync(c))
|
|
4064
4092
|
return c;
|
|
4065
4093
|
} catch {
|
|
4066
4094
|
}
|
|
@@ -4069,18 +4097,18 @@ function findGrepragBinary() {
|
|
|
4069
4097
|
}
|
|
4070
4098
|
function tryClaimWatcherLock() {
|
|
4071
4099
|
try {
|
|
4072
|
-
const fd =
|
|
4100
|
+
const fd = fs8.openSync(WATCHER_LOCK, "wx");
|
|
4073
4101
|
return { ok: true, fd };
|
|
4074
4102
|
} catch (err) {
|
|
4075
4103
|
if (err.code !== "EEXIST") {
|
|
4076
4104
|
return { ok: false, reason: "lock-create-failed" };
|
|
4077
4105
|
}
|
|
4078
4106
|
try {
|
|
4079
|
-
const stat =
|
|
4107
|
+
const stat = fs8.statSync(WATCHER_LOCK);
|
|
4080
4108
|
const ageMs = Date.now() - stat.mtimeMs;
|
|
4081
4109
|
let pidAlive = false;
|
|
4082
4110
|
try {
|
|
4083
|
-
const pid = parseInt(
|
|
4111
|
+
const pid = parseInt(fs8.readFileSync(WATCHER_LOCK, "utf-8").trim(), 10);
|
|
4084
4112
|
pidAlive = pid > 0 && isPidAlive(pid);
|
|
4085
4113
|
} catch {
|
|
4086
4114
|
}
|
|
@@ -4088,10 +4116,10 @@ function tryClaimWatcherLock() {
|
|
|
4088
4116
|
return { ok: false, reason: "busy" };
|
|
4089
4117
|
}
|
|
4090
4118
|
try {
|
|
4091
|
-
|
|
4119
|
+
fs8.unlinkSync(WATCHER_LOCK);
|
|
4092
4120
|
} catch {
|
|
4093
4121
|
}
|
|
4094
|
-
const fd =
|
|
4122
|
+
const fd = fs8.openSync(WATCHER_LOCK, "wx");
|
|
4095
4123
|
return { ok: true, fd };
|
|
4096
4124
|
} catch (err2) {
|
|
4097
4125
|
return { ok: false, reason: "lock-stale-replace-failed" };
|
|
@@ -4132,11 +4160,11 @@ function startCaptureWatcher() {
|
|
|
4132
4160
|
return;
|
|
4133
4161
|
}
|
|
4134
4162
|
try {
|
|
4135
|
-
|
|
4136
|
-
|
|
4163
|
+
fs8.writeSync(claim.fd, String(process.pid));
|
|
4164
|
+
fs8.closeSync(claim.fd);
|
|
4137
4165
|
} catch {
|
|
4138
4166
|
try {
|
|
4139
|
-
|
|
4167
|
+
fs8.unlinkSync(WATCHER_LOCK);
|
|
4140
4168
|
} catch {
|
|
4141
4169
|
}
|
|
4142
4170
|
return;
|
|
@@ -4152,11 +4180,11 @@ function startCaptureWatcher() {
|
|
|
4152
4180
|
const claim2 = tryClaimWatcherLock();
|
|
4153
4181
|
if (claim2.ok) {
|
|
4154
4182
|
try {
|
|
4155
|
-
|
|
4156
|
-
|
|
4183
|
+
fs8.writeSync(claim2.fd, String(process.pid));
|
|
4184
|
+
fs8.closeSync(claim2.fd);
|
|
4157
4185
|
} catch {
|
|
4158
4186
|
try {
|
|
4159
|
-
|
|
4187
|
+
fs8.unlinkSync(WATCHER_LOCK);
|
|
4160
4188
|
} catch {
|
|
4161
4189
|
}
|
|
4162
4190
|
return false;
|
|
@@ -4199,7 +4227,7 @@ function startCaptureWatcher() {
|
|
|
4199
4227
|
childStartTime = Date.now();
|
|
4200
4228
|
dlog(`startCaptureWatcher: spawned 'greprag opencode watch' pid=${child.pid ?? "<none>"}`);
|
|
4201
4229
|
try {
|
|
4202
|
-
|
|
4230
|
+
fs8.writeFileSync(WATCHER_LOCK, String(child.pid));
|
|
4203
4231
|
} catch {
|
|
4204
4232
|
}
|
|
4205
4233
|
child.stderr?.on("data", (chunk2) => {
|
|
@@ -4211,9 +4239,9 @@ function startCaptureWatcher() {
|
|
|
4211
4239
|
child.on("exit", (code, signal) => {
|
|
4212
4240
|
dlog(`startCaptureWatcher: child pid=${child.pid ?? "<none>"} exited code=${code} signal=${signal || "none"}`);
|
|
4213
4241
|
try {
|
|
4214
|
-
const current =
|
|
4242
|
+
const current = fs8.readFileSync(WATCHER_LOCK, "utf-8").trim();
|
|
4215
4243
|
if (current === String(child.pid))
|
|
4216
|
-
|
|
4244
|
+
fs8.unlinkSync(WATCHER_LOCK);
|
|
4217
4245
|
} catch {
|
|
4218
4246
|
}
|
|
4219
4247
|
currentChild = null;
|
|
@@ -4242,7 +4270,7 @@ function startCaptureWatcher() {
|
|
|
4242
4270
|
`
|
|
4243
4271
|
);
|
|
4244
4272
|
try {
|
|
4245
|
-
|
|
4273
|
+
fs8.unlinkSync(WATCHER_LOCK);
|
|
4246
4274
|
} catch {
|
|
4247
4275
|
}
|
|
4248
4276
|
return;
|
|
@@ -4274,7 +4302,7 @@ function startCaptureWatcher() {
|
|
|
4274
4302
|
}, 2e3).unref();
|
|
4275
4303
|
}
|
|
4276
4304
|
try {
|
|
4277
|
-
|
|
4305
|
+
fs8.unlinkSync(WATCHER_LOCK);
|
|
4278
4306
|
} catch {
|
|
4279
4307
|
}
|
|
4280
4308
|
};
|
|
@@ -4411,11 +4439,11 @@ function startSessionRelay(sessionId, serverUrl) {
|
|
|
4411
4439
|
return;
|
|
4412
4440
|
}
|
|
4413
4441
|
try {
|
|
4414
|
-
|
|
4415
|
-
|
|
4442
|
+
fs8.writeSync(claim.fd, String(process.pid));
|
|
4443
|
+
fs8.closeSync(claim.fd);
|
|
4416
4444
|
} catch {
|
|
4417
4445
|
try {
|
|
4418
|
-
|
|
4446
|
+
fs8.unlinkSync(lockPath);
|
|
4419
4447
|
} catch {
|
|
4420
4448
|
}
|
|
4421
4449
|
return;
|
|
@@ -4430,11 +4458,11 @@ function startSessionRelay(sessionId, serverUrl) {
|
|
|
4430
4458
|
const claim2 = tryClaimRelayLock(lockPath);
|
|
4431
4459
|
if (claim2.ok) {
|
|
4432
4460
|
try {
|
|
4433
|
-
|
|
4434
|
-
|
|
4461
|
+
fs8.writeSync(claim2.fd, String(process.pid));
|
|
4462
|
+
fs8.closeSync(claim2.fd);
|
|
4435
4463
|
} catch {
|
|
4436
4464
|
try {
|
|
4437
|
-
|
|
4465
|
+
fs8.unlinkSync(lockPath);
|
|
4438
4466
|
} catch {
|
|
4439
4467
|
}
|
|
4440
4468
|
return false;
|
|
@@ -4470,7 +4498,7 @@ function startSessionRelay(sessionId, serverUrl) {
|
|
|
4470
4498
|
childStartTime = Date.now();
|
|
4471
4499
|
dlog(`startSessionRelay: spawned 'greprag opencode relay' pid=${child.pid ?? "<none>"}`);
|
|
4472
4500
|
try {
|
|
4473
|
-
|
|
4501
|
+
fs8.writeFileSync(lockPath, String(child.pid));
|
|
4474
4502
|
} catch {
|
|
4475
4503
|
}
|
|
4476
4504
|
child.stderr?.on("data", (chunk2) => {
|
|
@@ -4481,9 +4509,9 @@ function startSessionRelay(sessionId, serverUrl) {
|
|
|
4481
4509
|
});
|
|
4482
4510
|
child.on("exit", (code, signal) => {
|
|
4483
4511
|
try {
|
|
4484
|
-
const current =
|
|
4512
|
+
const current = fs8.readFileSync(lockPath, "utf-8").trim();
|
|
4485
4513
|
if (current === String(child.pid))
|
|
4486
|
-
|
|
4514
|
+
fs8.unlinkSync(lockPath);
|
|
4487
4515
|
} catch {
|
|
4488
4516
|
}
|
|
4489
4517
|
currentChild = null;
|
|
@@ -4510,7 +4538,7 @@ function startSessionRelay(sessionId, serverUrl) {
|
|
|
4510
4538
|
`
|
|
4511
4539
|
);
|
|
4512
4540
|
try {
|
|
4513
|
-
|
|
4541
|
+
fs8.unlinkSync(lockPath);
|
|
4514
4542
|
} catch {
|
|
4515
4543
|
}
|
|
4516
4544
|
return;
|
|
@@ -4542,7 +4570,7 @@ function startSessionRelay(sessionId, serverUrl) {
|
|
|
4542
4570
|
}, 2e3).unref();
|
|
4543
4571
|
}
|
|
4544
4572
|
try {
|
|
4545
|
-
|
|
4573
|
+
fs8.unlinkSync(lockPath);
|
|
4546
4574
|
} catch {
|
|
4547
4575
|
}
|
|
4548
4576
|
};
|