@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.
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fml",
3
- "version": "0.8.12",
3
+ "version": "0.8.13-rc.1",
4
4
  "description": "FML agent tools for Claude Code",
5
5
  "mcpServers": {
6
6
  "fml": {
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.12+bc772cee" : "unknown";
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);
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  runRawSyncOnce
3
- } from "./chunk-VFZWTVPD.js";
3
+ } from "./chunk-U7SITLCL.js";
4
4
  import {
5
5
  resolvePackageRoot
6
6
  } from "./chunk-CSOFP7MT.js";
@@ -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 path19 from "path";
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 path8 from "path";
210
+ import path9 from "path";
196
211
 
197
212
  // ../../packages/agent-targets/src/config-paths.ts
198
- import path6 from "path";
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 ? path6.resolve(configuredDir) : path6.join(context.homeDir, ".claude");
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 ? path6.resolve(configuredHome) : context.homeDir;
206
- return path6.join(homeRoot, ".gemini");
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 path7 from "path";
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 path7.resolve(filePath);
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 = path7.join(dir, entry.name);
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(path8.join(configDir, ".claude.json")) ?? readClaudeMachineId(path8.join(homeDir, ".claude.json"));
485
+ const harnessInstallId = readClaudeMachineId(path9.join(configDir, ".claude.json")) ?? readClaudeMachineId(path9.join(homeDir, ".claude.json"));
471
486
  return walkFiles({
472
- root: path8.join(configDir, "projects"),
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 path9 from "path";
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(path9.basename(sourcePath))?.[1]?.toLowerCase() ?? null;
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 ? path9.resolve(configuredHome) : path9.join(homeDir, ".codex");
570
+ const codexHome = configuredHome ? path10.resolve(configuredHome) : path10.join(homeDir, ".codex");
556
571
  const harnessInstallId = readHarnessInstallIdFile(
557
- path9.join(codexHome, "installation_id")
572
+ path10.join(codexHome, "installation_id")
558
573
  );
559
574
  const roots = [
560
- { store: "sessions", root: path9.join(codexHome, "sessions") },
575
+ { store: "sessions", root: path10.join(codexHome, "sessions") },
561
576
  {
562
577
  store: "archived_sessions",
563
- root: path9.join(codexHome, "archived_sessions")
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 path10 from "path";
616
+ import path11 from "path";
602
617
  var copilotCliArtifactDiscovery = Object.freeze({
603
618
  targetId: "copilot-cli",
604
619
  discover: ({ homeDir }) => walkFiles({
605
- root: path10.join(homeDir, ".copilot", "session-state"),
620
+ root: path11.join(homeDir, ".copilot", "session-state"),
606
621
  maxDepth: 3,
607
- includeFile: (filePath) => path10.basename(filePath) === "events.jsonl"
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 path11 from "path";
629
+ import path12 from "path";
615
630
  function hasPathSegment(filePath, segment) {
616
- return normalizeFilePath(filePath).split(path11.sep).includes(segment);
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: path11.join(homeDir, ".cursor", "projects"),
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 path12 from "path";
645
+ import path13 from "path";
631
646
  var factoryDroidArtifactDiscovery = Object.freeze({
632
647
  targetId: "factory-droid",
633
648
  discover: ({ homeDir }) => walkFiles({
634
- root: path12.join(homeDir, ".factory", "sessions"),
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 path13 from "path";
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
- path13.join(geminiDir, "installation_id")
673
+ path14.join(geminiDir, "installation_id")
659
674
  );
660
- const root = path13.join(geminiDir, "tmp");
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 = path13.join(dir, entry.name);
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
- path13.join(entryPath, chatEntry.name)
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 path14 from "path";
713
+ import path15 from "path";
699
714
  function grokHome(homeDir, env) {
700
715
  const configuredHome = env.GROK_HOME?.trim();
701
- return configuredHome ? path14.resolve(configuredHome) : path14.join(homeDir, ".grok");
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: path14.join(grokHome(homeDir, env), "sessions"),
721
+ root: path15.join(grokHome(homeDir, env), "sessions"),
707
722
  maxDepth: 5,
708
- includeFile: (filePath) => path14.basename(filePath) === "updates.jsonl"
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 path15 from "path";
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 (!path15.isAbsolute(env.FML_DATA_DIR)) {
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 path15.normalize(env.FML_DATA_DIR);
738
+ return path16.normalize(env.FML_DATA_DIR);
724
739
  }
725
740
  if (process.platform === "darwin") {
726
- return path15.join(homeDir, "Library", "Application Support", "fml");
741
+ return path16.join(homeDir, "Library", "Application Support", "fml");
727
742
  }
728
743
  if (process.platform === "win32") {
729
- const roaming = env.APPDATA && path15.isAbsolute(env.APPDATA) ? env.APPDATA : path15.join(homeDir, "AppData", "Roaming");
730
- return path15.join(roaming, "fml");
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 && path15.isAbsolute(env.XDG_DATA_HOME) ? env.XDG_DATA_HOME : path15.join(homeDir, ".local", "share");
733
- return path15.join(xdgDataHome, "fml");
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: path15.join(dataDirectory(context), "mini-swe-agent", "trajectories"),
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 path16 from "path";
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: path16.join(homeDir, ".pi", "agent", "sessions"),
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 path17 from "path";
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 = `${path17.resolve(sourcePath)}\0${stat.size}\0${Math.floor(
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 path17.join(input.cacheDir, cacheEntryName(input.sourcePath, stat));
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 = path17.join(
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 = path17.join(input.cacheDir, entry.name);
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 path18 from "path";
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 = path18.resolve(cwd);
1216
+ let current = path19.resolve(cwd);
1203
1217
  for (; ; ) {
1204
- const candidate = path18.join(current, ".git");
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 = path18.resolve(current, match[1]);
1219
- const common = readSmallText(path18.join(gitDir, "commondir"));
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 ? path18.resolve(gitDir, common) : gitDir
1236
+ commonDir: common ? path19.resolve(gitDir, common) : gitDir
1223
1237
  };
1224
1238
  }
1225
- const parent = path18.dirname(current);
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 = path18.join(layout.gitDir, "HEAD");
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 = path18.join(layout.commonDir, ref);
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
- path18.join(layout.commonDir, "packed-refs")
1258
+ path19.join(layout.commonDir, "packed-refs")
1245
1259
  );
1246
1260
  const reftableIdentity = fileContentIdentity(
1247
- path18.join(layout.commonDir, "reftable", "tables.list")
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(path18.dirname(cacheFile), { recursive: true, mode: 448 });
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 path19.resolve(filePath);
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 = path19.extname(filePath).toLowerCase();
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(path19.dirname(queueFile), { recursive: true, mode: 448 });
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(path19.dirname(lockFile), { recursive: true, mode: 448 });
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
- path19.basename(metadata.sourcePath) || "raw-artifact"
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 path20 from "path";
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 = path20.resolve(stateDir);
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: path20.join(root, "discovery.cache.json"),
3356
- githubOriginCacheFile: path20.join(root, "github-origins.cache.json")
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(path20.dirname(paths.discoveryCacheFile), {
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-Z7MXNJ6X.js";
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-VFZWTVPD.js";
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.12+bc772cee" : "dev";
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, pathApi),
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.12+bc772cee" : void 0;
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.12+bc772cee" : "dev"
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();
@@ -5,7 +5,7 @@ import {
5
5
  isWinShim,
6
6
  quoteWinArg,
7
7
  resolveBin
8
- } from "./chunk-Z7MXNJ6X.js";
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-JK5JGPUN.js";
38
+ } from "./chunk-HVD2GMN3.js";
39
39
  import {
40
40
  createCliRawSync,
41
41
  invalidateCliRawSyncDiscoveryCache
42
- } from "./chunk-VFZWTVPD.js";
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.12+bc772cee" : "dev";
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,