@fml-inc/fml 0.8.12 → 0.8.13-rc.1
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/.claude-plugin/plugin.json +1 -1
- package/README.md +16 -0
- package/dist/{chunk-Z7MXNJ6X.js → chunk-3VN2SQTP.js} +1 -1
- package/dist/{chunk-JK5JGPUN.js → chunk-HVD2GMN3.js} +1 -1
- package/dist/{chunk-VFZWTVPD.js → chunk-U7SITLCL.js} +99 -74
- package/dist/cli.js +7 -17
- package/dist/observer-server.js +4 -4
- package/dist/pi/extension.js +123 -120
- package/dist/sync-cycle.js +2 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -214,6 +214,22 @@ Grok, Cursor, Pi, mini-swe-agent, Copilot CLI, and Factory Droid, including
|
|
|
214
214
|
archived Codex sessions and managed mini full-trajectory snapshots.
|
|
215
215
|
Availability depends on which harnesses have written artifacts on the machine.
|
|
216
216
|
|
|
217
|
+
Pi discovery scans only `<agentDir>/sessions`, using the same agent directory
|
|
218
|
+
as the extension installer. `PI_CODING_AGENT_DIR` is trimmed; unset, empty, or
|
|
219
|
+
whitespace-only values use `~/.pi/agent`. FML expands `~`, `~/`, and `~\\`
|
|
220
|
+
against the selected home directory and normalizes paths for the platform.
|
|
221
|
+
A nonblank custom root replaces the default even when absent or empty; FML
|
|
222
|
+
does not scan both roots.
|
|
223
|
+
|
|
224
|
+
Use an absolute or home-relative `PI_CODING_AGENT_DIR` for the background
|
|
225
|
+
observer. Relative values retain caller-working-directory-relative semantics;
|
|
226
|
+
configurations used across different working directories are unsupported.
|
|
227
|
+
Start or restart the observer from a shell with the desired variable set:
|
|
228
|
+
the observer and its sync subprocess inherit the launching process environment.
|
|
229
|
+
Changing the variable in another shell does not update an already-running
|
|
230
|
+
observer. Changing the effective Pi root invalidates reusable discovery results;
|
|
231
|
+
this does not reset existing upload watermarks or recover historical files.
|
|
232
|
+
|
|
217
233
|
Sync has one persistent setting: enabled or disabled. It defaults to enabled.
|
|
218
234
|
The backend environment, login, and selected organization determine the upload
|
|
219
235
|
destination; there is no user-configurable sync-target list.
|
|
@@ -53,7 +53,7 @@ var PACKAGE_NAME = "@fml-inc/fml";
|
|
|
53
53
|
var UPDATE_TIMEOUT_MS = 12e4;
|
|
54
54
|
var SETUP_TIMEOUT_MS = 3e5;
|
|
55
55
|
function getCurrentVersion() {
|
|
56
|
-
return true ? "0.8.
|
|
56
|
+
return true ? "0.8.13-rc.1+cdaf24a5" : "unknown";
|
|
57
57
|
}
|
|
58
58
|
function parseVersion(version) {
|
|
59
59
|
const match = SEMVER_PATTERN.exec(version);
|
|
@@ -189,26 +189,41 @@ function setSyncEnabled(settingsFile, enabled) {
|
|
|
189
189
|
import { createHash as createHash5, randomUUID as randomUUID3 } from "crypto";
|
|
190
190
|
import fs9 from "fs";
|
|
191
191
|
import os3 from "os";
|
|
192
|
-
import
|
|
192
|
+
import path20 from "path";
|
|
193
|
+
|
|
194
|
+
// ../../packages/agent-targets/src/pi-agent-dir.ts
|
|
195
|
+
import path6 from "path";
|
|
196
|
+
function resolvePiAgentDir(context) {
|
|
197
|
+
const pathApi = (context.platform ?? process.platform) === "win32" ? path6.win32 : path6.posix;
|
|
198
|
+
const configured = context.env.PI_CODING_AGENT_DIR?.trim();
|
|
199
|
+
if (!configured) {
|
|
200
|
+
return pathApi.join(context.homeDir, ".pi", "agent");
|
|
201
|
+
}
|
|
202
|
+
if (configured === "~") return context.homeDir;
|
|
203
|
+
if (configured.startsWith("~/") || configured.startsWith("~\\")) {
|
|
204
|
+
return pathApi.join(context.homeDir, configured.slice(2));
|
|
205
|
+
}
|
|
206
|
+
return pathApi.normalize(configured);
|
|
207
|
+
}
|
|
193
208
|
|
|
194
209
|
// ../../packages/agent-targets/src/artifacts/targets/claude.ts
|
|
195
|
-
import
|
|
210
|
+
import path9 from "path";
|
|
196
211
|
|
|
197
212
|
// ../../packages/agent-targets/src/config-paths.ts
|
|
198
|
-
import
|
|
213
|
+
import path7 from "path";
|
|
199
214
|
function claudeConfigDirectory(context) {
|
|
200
215
|
const configuredDir = context.claudeConfigDir ?? context.env?.CLAUDE_CONFIG_DIR;
|
|
201
|
-
return typeof configuredDir === "string" && configuredDir.trim().length > 0 ?
|
|
216
|
+
return typeof configuredDir === "string" && configuredDir.trim().length > 0 ? path7.resolve(configuredDir) : path7.join(context.homeDir, ".claude");
|
|
202
217
|
}
|
|
203
218
|
function geminiConfigDirectory(context) {
|
|
204
219
|
const configuredHome = context.env.GEMINI_CLI_HOME;
|
|
205
|
-
const homeRoot = typeof configuredHome === "string" && configuredHome.trim().length > 0 ?
|
|
206
|
-
return
|
|
220
|
+
const homeRoot = typeof configuredHome === "string" && configuredHome.trim().length > 0 ? path7.resolve(configuredHome) : context.homeDir;
|
|
221
|
+
return path7.join(homeRoot, ".gemini");
|
|
207
222
|
}
|
|
208
223
|
|
|
209
224
|
// ../../packages/agent-targets/src/artifacts/filesystem.ts
|
|
210
225
|
import fs3 from "fs";
|
|
211
|
-
import
|
|
226
|
+
import path8 from "path";
|
|
212
227
|
var DEFAULT_SKIP_DIRS = /* @__PURE__ */ new Set([
|
|
213
228
|
"node_modules",
|
|
214
229
|
"dist",
|
|
@@ -225,7 +240,7 @@ var DEFAULT_SKIP_DIRS = /* @__PURE__ */ new Set([
|
|
|
225
240
|
"designqc-captures"
|
|
226
241
|
]);
|
|
227
242
|
function normalizeFilePath(filePath) {
|
|
228
|
-
return
|
|
243
|
+
return path8.resolve(filePath);
|
|
229
244
|
}
|
|
230
245
|
function safeReaddir(dir) {
|
|
231
246
|
try {
|
|
@@ -242,7 +257,7 @@ function walkFiles(input) {
|
|
|
242
257
|
function walk(dir, depth) {
|
|
243
258
|
if (depth > input.maxDepth) return;
|
|
244
259
|
for (const entry of safeReaddir(dir)) {
|
|
245
|
-
const entryPath =
|
|
260
|
+
const entryPath = path8.join(dir, entry.name);
|
|
246
261
|
if (entry.isDirectory()) {
|
|
247
262
|
if (!skipDirs.has(entry.name)) walk(entryPath, depth + 1);
|
|
248
263
|
continue;
|
|
@@ -467,9 +482,9 @@ var claudeArtifactDiscovery = Object.freeze({
|
|
|
467
482
|
discover: (context) => {
|
|
468
483
|
const { homeDir, env } = context;
|
|
469
484
|
const configDir = claudeConfigDirectory({ homeDir, env });
|
|
470
|
-
const harnessInstallId = readClaudeMachineId(
|
|
485
|
+
const harnessInstallId = readClaudeMachineId(path9.join(configDir, ".claude.json")) ?? readClaudeMachineId(path9.join(homeDir, ".claude.json"));
|
|
471
486
|
return walkFiles({
|
|
472
|
-
root:
|
|
487
|
+
root: path9.join(configDir, "projects"),
|
|
473
488
|
maxDepth: 6,
|
|
474
489
|
includeFile: (filePath) => filePath.endsWith(".jsonl")
|
|
475
490
|
}).map(
|
|
@@ -479,10 +494,10 @@ var claudeArtifactDiscovery = Object.freeze({
|
|
|
479
494
|
});
|
|
480
495
|
|
|
481
496
|
// ../../packages/agent-targets/src/artifacts/targets/codex.ts
|
|
482
|
-
import
|
|
497
|
+
import path10 from "path";
|
|
483
498
|
var CODEX_ROLLOUT_ID = /-([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})\.jsonl(?:\.zst)?$/i;
|
|
484
499
|
function codexRolloutId(sourcePath) {
|
|
485
|
-
return CODEX_ROLLOUT_ID.exec(
|
|
500
|
+
return CODEX_ROLLOUT_ID.exec(path10.basename(sourcePath))?.[1]?.toLowerCase() ?? null;
|
|
486
501
|
}
|
|
487
502
|
function codexTranscriptCandidate(sourcePath, readPath, store, context, harnessInstallId) {
|
|
488
503
|
const rolloutId = codexRolloutId(sourcePath);
|
|
@@ -552,15 +567,15 @@ var codexArtifactDiscovery = Object.freeze({
|
|
|
552
567
|
discover: (context) => {
|
|
553
568
|
const { homeDir, env } = context;
|
|
554
569
|
const configuredHome = env.CODEX_HOME?.trim();
|
|
555
|
-
const codexHome = configuredHome ?
|
|
570
|
+
const codexHome = configuredHome ? path10.resolve(configuredHome) : path10.join(homeDir, ".codex");
|
|
556
571
|
const harnessInstallId = readHarnessInstallIdFile(
|
|
557
|
-
|
|
572
|
+
path10.join(codexHome, "installation_id")
|
|
558
573
|
);
|
|
559
574
|
const roots = [
|
|
560
|
-
{ store: "sessions", root:
|
|
575
|
+
{ store: "sessions", root: path10.join(codexHome, "sessions") },
|
|
561
576
|
{
|
|
562
577
|
store: "archived_sessions",
|
|
563
|
-
root:
|
|
578
|
+
root: path10.join(codexHome, "archived_sessions")
|
|
564
579
|
}
|
|
565
580
|
];
|
|
566
581
|
const files = roots.flatMap(
|
|
@@ -598,27 +613,27 @@ var codexArtifactDiscovery = Object.freeze({
|
|
|
598
613
|
});
|
|
599
614
|
|
|
600
615
|
// ../../packages/agent-targets/src/artifacts/targets/copilot-cli.ts
|
|
601
|
-
import
|
|
616
|
+
import path11 from "path";
|
|
602
617
|
var copilotCliArtifactDiscovery = Object.freeze({
|
|
603
618
|
targetId: "copilot-cli",
|
|
604
619
|
discover: ({ homeDir }) => walkFiles({
|
|
605
|
-
root:
|
|
620
|
+
root: path11.join(homeDir, ".copilot", "session-state"),
|
|
606
621
|
maxDepth: 3,
|
|
607
|
-
includeFile: (filePath) =>
|
|
622
|
+
includeFile: (filePath) => path11.basename(filePath) === "events.jsonl"
|
|
608
623
|
}).map(
|
|
609
624
|
(sourcePath) => transcriptCandidate({ targetId: "copilot-cli", sourcePath })
|
|
610
625
|
)
|
|
611
626
|
});
|
|
612
627
|
|
|
613
628
|
// ../../packages/agent-targets/src/artifacts/targets/cursor.ts
|
|
614
|
-
import
|
|
629
|
+
import path12 from "path";
|
|
615
630
|
function hasPathSegment(filePath, segment) {
|
|
616
|
-
return normalizeFilePath(filePath).split(
|
|
631
|
+
return normalizeFilePath(filePath).split(path12.sep).includes(segment);
|
|
617
632
|
}
|
|
618
633
|
var cursorArtifactDiscovery = Object.freeze({
|
|
619
634
|
targetId: "cursor",
|
|
620
635
|
discover: ({ homeDir }) => walkFiles({
|
|
621
|
-
root:
|
|
636
|
+
root: path12.join(homeDir, ".cursor", "projects"),
|
|
622
637
|
maxDepth: 5,
|
|
623
638
|
includeFile: (filePath) => filePath.endsWith(".jsonl") && hasPathSegment(filePath, "agent-transcripts")
|
|
624
639
|
}).map(
|
|
@@ -627,11 +642,11 @@ var cursorArtifactDiscovery = Object.freeze({
|
|
|
627
642
|
});
|
|
628
643
|
|
|
629
644
|
// ../../packages/agent-targets/src/artifacts/targets/factory-droid.ts
|
|
630
|
-
import
|
|
645
|
+
import path13 from "path";
|
|
631
646
|
var factoryDroidArtifactDiscovery = Object.freeze({
|
|
632
647
|
targetId: "factory-droid",
|
|
633
648
|
discover: ({ homeDir }) => walkFiles({
|
|
634
|
-
root:
|
|
649
|
+
root: path13.join(homeDir, ".factory", "sessions"),
|
|
635
650
|
maxDepth: 4,
|
|
636
651
|
includeFile: (filePath) => filePath.endsWith(".jsonl")
|
|
637
652
|
}).map(
|
|
@@ -640,7 +655,7 @@ var factoryDroidArtifactDiscovery = Object.freeze({
|
|
|
640
655
|
});
|
|
641
656
|
|
|
642
657
|
// ../../packages/agent-targets/src/artifacts/targets/gemini.ts
|
|
643
|
-
import
|
|
658
|
+
import path14 from "path";
|
|
644
659
|
var GEMINI_DISCOVER_SKIP_DIRS = /* @__PURE__ */ new Set([
|
|
645
660
|
"bin",
|
|
646
661
|
"checkpoints",
|
|
@@ -655,15 +670,15 @@ var geminiArtifactDiscovery = Object.freeze({
|
|
|
655
670
|
discover: ({ homeDir, env }) => {
|
|
656
671
|
const geminiDir = geminiConfigDirectory({ homeDir, env });
|
|
657
672
|
const harnessInstallId = readHarnessInstallIdFile(
|
|
658
|
-
|
|
673
|
+
path14.join(geminiDir, "installation_id")
|
|
659
674
|
);
|
|
660
|
-
const root =
|
|
675
|
+
const root = path14.join(geminiDir, "tmp");
|
|
661
676
|
const files = [];
|
|
662
677
|
const seen = /* @__PURE__ */ new Set();
|
|
663
678
|
function walk(dir, depth) {
|
|
664
679
|
if (depth > 4) return;
|
|
665
680
|
for (const entry of safeReaddir(dir)) {
|
|
666
|
-
const entryPath =
|
|
681
|
+
const entryPath = path14.join(dir, entry.name);
|
|
667
682
|
if (!entry.isDirectory()) continue;
|
|
668
683
|
if (GEMINI_DISCOVER_SKIP_DIRS.has(entry.name)) continue;
|
|
669
684
|
if (entry.name === "chats") {
|
|
@@ -672,7 +687,7 @@ var geminiArtifactDiscovery = Object.freeze({
|
|
|
672
687
|
continue;
|
|
673
688
|
}
|
|
674
689
|
const sourcePath = normalizeFilePath(
|
|
675
|
-
|
|
690
|
+
path14.join(entryPath, chatEntry.name)
|
|
676
691
|
);
|
|
677
692
|
if (seen.has(sourcePath)) continue;
|
|
678
693
|
seen.add(sourcePath);
|
|
@@ -695,17 +710,17 @@ var geminiArtifactDiscovery = Object.freeze({
|
|
|
695
710
|
});
|
|
696
711
|
|
|
697
712
|
// ../../packages/agent-targets/src/artifacts/targets/grok.ts
|
|
698
|
-
import
|
|
713
|
+
import path15 from "path";
|
|
699
714
|
function grokHome(homeDir, env) {
|
|
700
715
|
const configuredHome = env.GROK_HOME?.trim();
|
|
701
|
-
return configuredHome ?
|
|
716
|
+
return configuredHome ? path15.resolve(configuredHome) : path15.join(homeDir, ".grok");
|
|
702
717
|
}
|
|
703
718
|
var grokArtifactDiscovery = Object.freeze({
|
|
704
719
|
targetId: "grok",
|
|
705
720
|
discover: ({ homeDir, env }) => walkFiles({
|
|
706
|
-
root:
|
|
721
|
+
root: path15.join(grokHome(homeDir, env), "sessions"),
|
|
707
722
|
maxDepth: 5,
|
|
708
|
-
includeFile: (filePath) =>
|
|
723
|
+
includeFile: (filePath) => path15.basename(filePath) === "updates.jsonl"
|
|
709
724
|
}).map(
|
|
710
725
|
(sourcePath) => transcriptCandidate({ targetId: "grok", sourcePath })
|
|
711
726
|
)
|
|
@@ -713,24 +728,24 @@ var grokArtifactDiscovery = Object.freeze({
|
|
|
713
728
|
|
|
714
729
|
// ../../packages/agent-targets/src/artifacts/targets/mini-swe-agent.ts
|
|
715
730
|
import fs6 from "fs";
|
|
716
|
-
import
|
|
731
|
+
import path16 from "path";
|
|
717
732
|
var SESSION_ID_PATTERN = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
718
733
|
function dataDirectory({ homeDir, env }) {
|
|
719
734
|
if (env.FML_DATA_DIR?.trim()) {
|
|
720
|
-
if (!
|
|
735
|
+
if (!path16.isAbsolute(env.FML_DATA_DIR)) {
|
|
721
736
|
throw new Error("FML_DATA_DIR must be an absolute path");
|
|
722
737
|
}
|
|
723
|
-
return
|
|
738
|
+
return path16.normalize(env.FML_DATA_DIR);
|
|
724
739
|
}
|
|
725
740
|
if (process.platform === "darwin") {
|
|
726
|
-
return
|
|
741
|
+
return path16.join(homeDir, "Library", "Application Support", "fml");
|
|
727
742
|
}
|
|
728
743
|
if (process.platform === "win32") {
|
|
729
|
-
const roaming = env.APPDATA &&
|
|
730
|
-
return
|
|
744
|
+
const roaming = env.APPDATA && path16.isAbsolute(env.APPDATA) ? env.APPDATA : path16.join(homeDir, "AppData", "Roaming");
|
|
745
|
+
return path16.join(roaming, "fml");
|
|
731
746
|
}
|
|
732
|
-
const xdgDataHome = env.XDG_DATA_HOME &&
|
|
733
|
-
return
|
|
747
|
+
const xdgDataHome = env.XDG_DATA_HOME && path16.isAbsolute(env.XDG_DATA_HOME) ? env.XDG_DATA_HOME : path16.join(homeDir, ".local", "share");
|
|
748
|
+
return path16.join(xdgDataHome, "fml");
|
|
734
749
|
}
|
|
735
750
|
function snapshotCandidate(sourcePath, context) {
|
|
736
751
|
let file;
|
|
@@ -794,7 +809,7 @@ function snapshotCandidate(sourcePath, context) {
|
|
|
794
809
|
var miniSweAgentArtifactDiscovery = Object.freeze({
|
|
795
810
|
targetId: "mini-swe-agent",
|
|
796
811
|
discover: (context) => walkFiles({
|
|
797
|
-
root:
|
|
812
|
+
root: path16.join(dataDirectory(context), "mini-swe-agent", "trajectories"),
|
|
798
813
|
maxDepth: 0,
|
|
799
814
|
includeFile: (filePath) => filePath.endsWith(".traj.json")
|
|
800
815
|
}).flatMap((sourcePath) => {
|
|
@@ -804,7 +819,7 @@ var miniSweAgentArtifactDiscovery = Object.freeze({
|
|
|
804
819
|
});
|
|
805
820
|
|
|
806
821
|
// ../../packages/agent-targets/src/artifacts/targets/pi.ts
|
|
807
|
-
import
|
|
822
|
+
import path17 from "path";
|
|
808
823
|
|
|
809
824
|
// ../../packages/agent-targets/src/artifacts/pi-repository-origin.ts
|
|
810
825
|
import { z } from "zod";
|
|
@@ -866,9 +881,8 @@ function piTranscriptCandidate(sourcePath) {
|
|
|
866
881
|
var piArtifactDiscovery = Object.freeze({
|
|
867
882
|
targetId: "pi",
|
|
868
883
|
discover: (context) => {
|
|
869
|
-
const { homeDir } = context;
|
|
870
884
|
return walkFiles({
|
|
871
|
-
root:
|
|
885
|
+
root: path17.join(resolvePiAgentDir(context), "sessions"),
|
|
872
886
|
maxDepth: 8,
|
|
873
887
|
includeFile: (filePath) => filePath.endsWith(".jsonl"),
|
|
874
888
|
skipDirs: PI_SKIP_DIRS
|
|
@@ -902,12 +916,12 @@ function discoverTargetArtifactCandidates(context) {
|
|
|
902
916
|
// ../../packages/agent-targets/src/artifacts/materialize.ts
|
|
903
917
|
import { createHash as createHash3 } from "crypto";
|
|
904
918
|
import fs7 from "fs";
|
|
905
|
-
import
|
|
919
|
+
import path18 from "path";
|
|
906
920
|
import zlib from "zlib";
|
|
907
921
|
var MAX_MATERIALIZED_ARTIFACT_BYTES = 100 * 1024 * 1024;
|
|
908
922
|
var DEFAULT_MATERIALIZED_CACHE_BYTES = 2 * 1024 * 1024 * 1024;
|
|
909
923
|
function cacheEntryName(sourcePath, stat) {
|
|
910
|
-
const identity = `${
|
|
924
|
+
const identity = `${path18.resolve(sourcePath)}\0${stat.size}\0${Math.floor(
|
|
911
925
|
stat.mtimeMs
|
|
912
926
|
)}`;
|
|
913
927
|
const digest = createHash3("sha256").update(identity).digest("hex");
|
|
@@ -931,7 +945,7 @@ function materializedArtifactPath(input) {
|
|
|
931
945
|
try {
|
|
932
946
|
const stat = fs7.statSync(input.sourcePath);
|
|
933
947
|
if (!stat.isFile() || stat.size === 0) return null;
|
|
934
|
-
return
|
|
948
|
+
return path18.join(input.cacheDir, cacheEntryName(input.sourcePath, stat));
|
|
935
949
|
} catch {
|
|
936
950
|
return null;
|
|
937
951
|
}
|
|
@@ -944,7 +958,7 @@ function materializeCompressedArtifact(input) {
|
|
|
944
958
|
return null;
|
|
945
959
|
}
|
|
946
960
|
if (!stat.isFile() || stat.size === 0) return null;
|
|
947
|
-
const cachePath =
|
|
961
|
+
const cachePath = path18.join(
|
|
948
962
|
input.cacheDir,
|
|
949
963
|
cacheEntryName(input.sourcePath, stat)
|
|
950
964
|
);
|
|
@@ -985,7 +999,7 @@ function pruneMaterializedCache(input) {
|
|
|
985
999
|
const files = [];
|
|
986
1000
|
for (const entry of entries) {
|
|
987
1001
|
if (!entry.isFile()) continue;
|
|
988
|
-
const filePath =
|
|
1002
|
+
const filePath = path18.join(input.cacheDir, entry.name);
|
|
989
1003
|
try {
|
|
990
1004
|
const stat = fs7.statSync(filePath);
|
|
991
1005
|
files.push({ path: filePath, size: stat.size, atimeMs: stat.atimeMs });
|
|
@@ -1015,7 +1029,7 @@ function pruneMaterializedCache(input) {
|
|
|
1015
1029
|
import { execFileSync } from "child_process";
|
|
1016
1030
|
import { createHash as createHash4 } from "crypto";
|
|
1017
1031
|
import fs8 from "fs";
|
|
1018
|
-
import
|
|
1032
|
+
import path19 from "path";
|
|
1019
1033
|
var MAX_CWD_BYTES2 = 4096;
|
|
1020
1034
|
var GIT_OUTPUT_BYTES = 16 * 1024;
|
|
1021
1035
|
var GIT_CONFIG_OUTPUT_BYTES = 4 * 1024 * 1024;
|
|
@@ -1199,9 +1213,9 @@ function readSmallText(filePath) {
|
|
|
1199
1213
|
}
|
|
1200
1214
|
}
|
|
1201
1215
|
function findGitDirectory(cwd) {
|
|
1202
|
-
let current =
|
|
1216
|
+
let current = path19.resolve(cwd);
|
|
1203
1217
|
for (; ; ) {
|
|
1204
|
-
const candidate =
|
|
1218
|
+
const candidate = path19.join(current, ".git");
|
|
1205
1219
|
let stat;
|
|
1206
1220
|
try {
|
|
1207
1221
|
stat = fs8.statSync(candidate);
|
|
@@ -1215,20 +1229,20 @@ function findGitDirectory(cwd) {
|
|
|
1215
1229
|
const pointer = readSmallText(candidate);
|
|
1216
1230
|
const match = pointer ? /^gitdir:\s*(.+)$/u.exec(pointer) : null;
|
|
1217
1231
|
if (!match?.[1]) return null;
|
|
1218
|
-
const gitDir =
|
|
1219
|
-
const common = readSmallText(
|
|
1232
|
+
const gitDir = path19.resolve(current, match[1]);
|
|
1233
|
+
const common = readSmallText(path19.join(gitDir, "commondir"));
|
|
1220
1234
|
return {
|
|
1221
1235
|
gitDir,
|
|
1222
|
-
commonDir: common ?
|
|
1236
|
+
commonDir: common ? path19.resolve(gitDir, common) : gitDir
|
|
1223
1237
|
};
|
|
1224
1238
|
}
|
|
1225
|
-
const parent =
|
|
1239
|
+
const parent = path19.dirname(current);
|
|
1226
1240
|
if (parent === current) return null;
|
|
1227
1241
|
current = parent;
|
|
1228
1242
|
}
|
|
1229
1243
|
}
|
|
1230
1244
|
function checkoutSignature(layout, cwd) {
|
|
1231
|
-
const headPath =
|
|
1245
|
+
const headPath = path19.join(layout.gitDir, "HEAD");
|
|
1232
1246
|
const head = readSmallText(headPath);
|
|
1233
1247
|
const configIdentity = effectiveConfigIdentity(cwd);
|
|
1234
1248
|
if (head === null || configIdentity === null) {
|
|
@@ -1237,14 +1251,14 @@ function checkoutSignature(layout, cwd) {
|
|
|
1237
1251
|
const parts = [layout.gitDir, head, configIdentity];
|
|
1238
1252
|
const ref = /^ref:\s*(.+)$/u.exec(head)?.[1];
|
|
1239
1253
|
if (ref) {
|
|
1240
|
-
const looseRefPath =
|
|
1254
|
+
const looseRefPath = path19.join(layout.commonDir, ref);
|
|
1241
1255
|
if (/^ref:/u.test(readSmallText(looseRefPath) ?? "")) return null;
|
|
1242
1256
|
const looseRefIdentity = fileContentIdentity(looseRefPath);
|
|
1243
1257
|
const packedIdentity = packedRefsIdentity(
|
|
1244
|
-
|
|
1258
|
+
path19.join(layout.commonDir, "packed-refs")
|
|
1245
1259
|
);
|
|
1246
1260
|
const reftableIdentity = fileContentIdentity(
|
|
1247
|
-
|
|
1261
|
+
path19.join(layout.commonDir, "reftable", "tables.list")
|
|
1248
1262
|
);
|
|
1249
1263
|
if (!looseRefIdentity || !packedIdentity || !reftableIdentity || looseRefIdentity === "missing" && packedIdentity === "missing" && reftableIdentity === "missing") {
|
|
1250
1264
|
return null;
|
|
@@ -1266,7 +1280,7 @@ function readPersistentOriginCache(cacheFile) {
|
|
|
1266
1280
|
function writePersistentOriginCache(cacheFile, cache) {
|
|
1267
1281
|
const temporary = `${cacheFile}.${process.pid}.tmp`;
|
|
1268
1282
|
try {
|
|
1269
|
-
fs8.mkdirSync(
|
|
1283
|
+
fs8.mkdirSync(path19.dirname(cacheFile), { recursive: true, mode: 448 });
|
|
1270
1284
|
fs8.writeFileSync(temporary, `${JSON.stringify(cache)}
|
|
1271
1285
|
`, { mode: 384 });
|
|
1272
1286
|
fs8.renameSync(temporary, cacheFile);
|
|
@@ -1366,7 +1380,7 @@ function safeStat(filePath) {
|
|
|
1366
1380
|
}
|
|
1367
1381
|
}
|
|
1368
1382
|
function normalizeFilePath2(filePath) {
|
|
1369
|
-
return
|
|
1383
|
+
return path20.resolve(filePath);
|
|
1370
1384
|
}
|
|
1371
1385
|
function artifactReadPath(artifact) {
|
|
1372
1386
|
return normalizeFilePath2(artifact.readPath ?? artifact.sourcePath);
|
|
@@ -1381,7 +1395,7 @@ function statCandidateSource(sourcePath, transientStatErrors) {
|
|
|
1381
1395
|
}
|
|
1382
1396
|
}
|
|
1383
1397
|
function contentTypeForPath(filePath) {
|
|
1384
|
-
const ext =
|
|
1398
|
+
const ext = path20.extname(filePath).toLowerCase();
|
|
1385
1399
|
if (ext === ".json" || ext === ".jsonl") return "application/json";
|
|
1386
1400
|
if (ext === ".md") return "text/markdown";
|
|
1387
1401
|
if (ext === ".toml") return "application/toml";
|
|
@@ -1511,7 +1525,7 @@ function readArtifactQueue(queueFile) {
|
|
|
1511
1525
|
}
|
|
1512
1526
|
}
|
|
1513
1527
|
function writeArtifactQueue(queueFile, queue) {
|
|
1514
|
-
fs9.mkdirSync(
|
|
1528
|
+
fs9.mkdirSync(path20.dirname(queueFile), { recursive: true, mode: 448 });
|
|
1515
1529
|
const tempFile = `${queueFile}.${process.pid}.${Date.now()}.tmp`;
|
|
1516
1530
|
fs9.writeFileSync(tempFile, `${JSON.stringify(queue, null, 2)}
|
|
1517
1531
|
`, {
|
|
@@ -2270,7 +2284,7 @@ function queueLockFileMatchesOwner(lockFile, fd, ownerToken) {
|
|
|
2270
2284
|
}
|
|
2271
2285
|
function acquireQueueLock(queueFile, deps) {
|
|
2272
2286
|
const lockFile = queueLockFile(queueFile);
|
|
2273
|
-
fs9.mkdirSync(
|
|
2287
|
+
fs9.mkdirSync(path20.dirname(lockFile), { recursive: true, mode: 448 });
|
|
2274
2288
|
for (let attempt = 0; attempt < 2; attempt += 1) {
|
|
2275
2289
|
try {
|
|
2276
2290
|
const fd = fs9.openSync(lockFile, "wx+", 384);
|
|
@@ -2389,7 +2403,7 @@ async function postRawArtifact(url, metadata, content, headers, fetchImpl = fetc
|
|
|
2389
2403
|
form.append(
|
|
2390
2404
|
"file",
|
|
2391
2405
|
new Blob([new Uint8Array(content)], { type: metadata.contentType }),
|
|
2392
|
-
|
|
2406
|
+
path20.basename(metadata.sourcePath) || "raw-artifact"
|
|
2393
2407
|
);
|
|
2394
2408
|
const abort = new AbortController();
|
|
2395
2409
|
const timeout = setTimeout(() => abort.abort(), timeoutMs);
|
|
@@ -3279,7 +3293,8 @@ async function uploadPendingArtifactsLocked(options, run) {
|
|
|
3279
3293
|
|
|
3280
3294
|
// ../../packages/panopticon/src/raw-sync.ts
|
|
3281
3295
|
import fs11 from "fs";
|
|
3282
|
-
import
|
|
3296
|
+
import path21 from "path";
|
|
3297
|
+
import os4 from "os";
|
|
3283
3298
|
|
|
3284
3299
|
// ../../packages/panopticon/src/artifact-materializer.ts
|
|
3285
3300
|
import fs10 from "fs";
|
|
@@ -3345,15 +3360,15 @@ function getRawArtifactSyncPaths(stateDir) {
|
|
|
3345
3360
|
if (stateDir.length === 0) {
|
|
3346
3361
|
throw new Error("raw artifact sync state directory must not be empty");
|
|
3347
3362
|
}
|
|
3348
|
-
const root =
|
|
3363
|
+
const root = path21.resolve(stateDir);
|
|
3349
3364
|
const managed = getManagedClientPaths({ PANOPTICON_HOME: root });
|
|
3350
3365
|
return {
|
|
3351
3366
|
root,
|
|
3352
3367
|
settingsFile: managed.syncSettingsFile,
|
|
3353
3368
|
queueFile: managed.artifactQueue,
|
|
3354
3369
|
artifactCacheDir: managed.artifactCache,
|
|
3355
|
-
discoveryCacheFile:
|
|
3356
|
-
githubOriginCacheFile:
|
|
3370
|
+
discoveryCacheFile: path21.join(root, "discovery.cache.json"),
|
|
3371
|
+
githubOriginCacheFile: path21.join(root, "github-origins.cache.json")
|
|
3357
3372
|
};
|
|
3358
3373
|
}
|
|
3359
3374
|
function invalidateRawArtifactDiscoveryCache(stateDir) {
|
|
@@ -3460,7 +3475,16 @@ function createRawArtifactSync(options) {
|
|
|
3460
3475
|
const discoveryInputs = () => JSON.stringify([
|
|
3461
3476
|
options.homeDir ?? null,
|
|
3462
3477
|
options.projectRoots ?? null,
|
|
3463
|
-
options.maxFileBytes ?? null
|
|
3478
|
+
options.maxFileBytes ?? null,
|
|
3479
|
+
path21.resolve(
|
|
3480
|
+
resolvePiAgentDir({
|
|
3481
|
+
homeDir: path21.resolve(
|
|
3482
|
+
options.homeDir ?? process.env.HOME ?? os4.homedir()
|
|
3483
|
+
),
|
|
3484
|
+
env: process.env
|
|
3485
|
+
}),
|
|
3486
|
+
"sessions"
|
|
3487
|
+
)
|
|
3464
3488
|
]);
|
|
3465
3489
|
const readReusableDiscovery = (nowMs) => {
|
|
3466
3490
|
const reuseMs = options.discoveryReuseMs ?? 0;
|
|
@@ -3483,7 +3507,7 @@ function createRawArtifactSync(options) {
|
|
|
3483
3507
|
if ((options.discoveryReuseMs ?? 0) <= 0) return;
|
|
3484
3508
|
const temporary = `${paths.discoveryCacheFile}.${process.pid}.tmp`;
|
|
3485
3509
|
try {
|
|
3486
|
-
fs11.mkdirSync(
|
|
3510
|
+
fs11.mkdirSync(path21.dirname(paths.discoveryCacheFile), {
|
|
3487
3511
|
recursive: true,
|
|
3488
3512
|
mode: 448
|
|
3489
3513
|
});
|
|
@@ -3694,6 +3718,7 @@ async function runRawSyncOnce(opts = {}) {
|
|
|
3694
3718
|
}
|
|
3695
3719
|
|
|
3696
3720
|
export {
|
|
3721
|
+
resolvePiAgentDir,
|
|
3697
3722
|
claudeConfigDirectory,
|
|
3698
3723
|
geminiConfigDirectory,
|
|
3699
3724
|
initializeSyncSettings,
|
package/dist/cli.js
CHANGED
|
@@ -7,7 +7,7 @@ import {
|
|
|
7
7
|
execBinSync,
|
|
8
8
|
handleUpdate,
|
|
9
9
|
resolveBin
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-3VN2SQTP.js";
|
|
11
11
|
import {
|
|
12
12
|
openObserverLog,
|
|
13
13
|
readJsonFile,
|
|
@@ -37,8 +37,9 @@ import {
|
|
|
37
37
|
createRawArtifactSync,
|
|
38
38
|
geminiConfigDirectory,
|
|
39
39
|
initializeSyncSettings,
|
|
40
|
+
resolvePiAgentDir,
|
|
40
41
|
runRawSyncOnce
|
|
41
|
-
} from "./chunk-
|
|
42
|
+
} from "./chunk-U7SITLCL.js";
|
|
42
43
|
import {
|
|
43
44
|
resolvePackageRoot
|
|
44
45
|
} from "./chunk-CSOFP7MT.js";
|
|
@@ -132,7 +133,7 @@ var STOP_TIMEOUT_MS = 5e3;
|
|
|
132
133
|
var FORCE_STOP_TIMEOUT_MS = 2e3;
|
|
133
134
|
var POLL_INTERVAL_MS = 50;
|
|
134
135
|
function expectedObserverVersion() {
|
|
135
|
-
return true ? "0.8.
|
|
136
|
+
return true ? "0.8.13-rc.1+cdaf24a5" : "dev";
|
|
136
137
|
}
|
|
137
138
|
function delay(ms) {
|
|
138
139
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
@@ -2553,17 +2554,6 @@ var LEGACY_PI_EXTENSION_SIGNATURES = Object.freeze([
|
|
|
2553
2554
|
function pathApiFor(platform) {
|
|
2554
2555
|
return platform === "win32" ? path11.win32 : path11.posix;
|
|
2555
2556
|
}
|
|
2556
|
-
function resolvePiAgentDir(context, pathApi) {
|
|
2557
|
-
const configured = context.env.PI_CODING_AGENT_DIR?.trim();
|
|
2558
|
-
if (!configured) {
|
|
2559
|
-
return pathApi.join(context.homeDir, ".pi", "agent");
|
|
2560
|
-
}
|
|
2561
|
-
if (configured === "~") return context.homeDir;
|
|
2562
|
-
if (configured.startsWith("~/") || configured.startsWith("~\\")) {
|
|
2563
|
-
return pathApi.join(context.homeDir, configured.slice(2));
|
|
2564
|
-
}
|
|
2565
|
-
return pathApi.normalize(configured);
|
|
2566
|
-
}
|
|
2567
2557
|
function readFileIfPresent(filePath) {
|
|
2568
2558
|
try {
|
|
2569
2559
|
return fs6.readFileSync(filePath, "utf8");
|
|
@@ -2606,7 +2596,7 @@ var PI_EXTENSION_INSTALLER = Object.freeze({
|
|
|
2606
2596
|
resolvePaths(context) {
|
|
2607
2597
|
const pathApi = pathApiFor(context.platform);
|
|
2608
2598
|
const extensionsDir = pathApi.join(
|
|
2609
|
-
resolvePiAgentDir(context
|
|
2599
|
+
resolvePiAgentDir(context),
|
|
2610
2600
|
"extensions"
|
|
2611
2601
|
);
|
|
2612
2602
|
return {
|
|
@@ -9736,7 +9726,7 @@ async function handleConfigDetail(opts) {
|
|
|
9736
9726
|
// src/commands/tools.ts
|
|
9737
9727
|
import { readFileSync } from "fs";
|
|
9738
9728
|
import path31 from "path";
|
|
9739
|
-
var pluginVersion = true ? "0.8.
|
|
9729
|
+
var pluginVersion = true ? "0.8.13-rc.1+cdaf24a5" : void 0;
|
|
9740
9730
|
async function getApi() {
|
|
9741
9731
|
const api = await getAuthenticatedClient();
|
|
9742
9732
|
if (!api) {
|
|
@@ -9893,7 +9883,7 @@ if (process.argv.length <= 2 || process.argv.includes("--help") || process.argv.
|
|
|
9893
9883
|
printBanner();
|
|
9894
9884
|
}
|
|
9895
9885
|
var program = new Command().name("fml").description("FML CLI and agent tools").version(
|
|
9896
|
-
true ? "0.8.
|
|
9886
|
+
true ? "0.8.13-rc.1+cdaf24a5" : "dev"
|
|
9897
9887
|
);
|
|
9898
9888
|
function formatCommandInventory(cmd, prefix = "") {
|
|
9899
9889
|
const name = prefix ? `${prefix} ${cmd.name()}` : cmd.name();
|
package/dist/observer-server.js
CHANGED
|
@@ -5,7 +5,7 @@ import {
|
|
|
5
5
|
isWinShim,
|
|
6
6
|
quoteWinArg,
|
|
7
7
|
resolveBin
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-3VN2SQTP.js";
|
|
9
9
|
import {
|
|
10
10
|
createHookSyncLoop,
|
|
11
11
|
getActiveHookDestinationBinding
|
|
@@ -35,11 +35,11 @@ import "./chunk-EX5J3MPG.js";
|
|
|
35
35
|
import {
|
|
36
36
|
ObserverSyncCycleAbortedError,
|
|
37
37
|
runObserverSyncCycleSubprocess
|
|
38
|
-
} from "./chunk-
|
|
38
|
+
} from "./chunk-HVD2GMN3.js";
|
|
39
39
|
import {
|
|
40
40
|
createCliRawSync,
|
|
41
41
|
invalidateCliRawSyncDiscoveryCache
|
|
42
|
-
} from "./chunk-
|
|
42
|
+
} from "./chunk-U7SITLCL.js";
|
|
43
43
|
import "./chunk-CSOFP7MT.js";
|
|
44
44
|
import {
|
|
45
45
|
FML_OBSERVER_AUTH_TOKEN_FILE,
|
|
@@ -1563,7 +1563,7 @@ var hookRejectionStatus = () => ({
|
|
|
1563
1563
|
...lastRejectedReason !== void 0 ? { lastRejectedReason } : {},
|
|
1564
1564
|
...lastRejectedTarget !== void 0 ? { lastRejectedTarget } : {}
|
|
1565
1565
|
});
|
|
1566
|
-
var packageVersion = true ? "0.8.
|
|
1566
|
+
var packageVersion = true ? "0.8.13-rc.1+cdaf24a5" : "dev";
|
|
1567
1567
|
var health = () => ({
|
|
1568
1568
|
status: "ok",
|
|
1569
1569
|
service: OBSERVER_SERVICE_NAME,
|