@fml-inc/fml 0.8.10-dev.1 → 0.8.11-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 +114 -3
- package/agent-assets/mini-swe-agent/FML_WORKFLOW.md +62 -0
- package/agent-assets/mini-swe-agent/fml_mini_agent.py +483 -0
- package/agent-assets/mini-swe-agent/fml_mini_bootstrap.py +141 -0
- package/bin/fml +18 -4
- package/dist/{chunk-WE7MAWAW.js → chunk-4YLCUJ6C.js} +4 -3
- package/dist/{chunk-5PEFBQNX.js → chunk-5VP4C72Z.js} +25 -6
- package/dist/{chunk-5SI6S4HW.js → chunk-B46WIVL7.js} +1 -1
- package/dist/chunk-CSOFP7MT.js +67 -0
- package/dist/{chunk-7V7G7NVF.js → chunk-EX5J3MPG.js} +2 -2
- package/dist/{chunk-GDOXY4W2.js → chunk-IUFDFBU7.js} +1 -1
- package/dist/{chunk-2DGHAVVR.js → chunk-JK5JGPUN.js} +2 -2
- package/dist/{chunk-JPHN4VKM.js → chunk-VFZWTVPD.js} +247 -162
- package/dist/cli.js +4603 -3885
- package/dist/hook-handler.js +42 -14
- package/dist/mcp/server.js +7 -7
- package/dist/observer-server.js +8 -8
- package/dist/pi/extension.js +13737 -397
- package/dist/sync-cycle.js +3 -3
- package/package.json +2 -2
- package/dist/chunk-F57IFY3K.js +0 -21
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
import {
|
|
2
|
+
canonicalGitHubRepository
|
|
3
|
+
} from "./chunk-CSOFP7MT.js";
|
|
1
4
|
import {
|
|
2
5
|
FML_INSTALLATION_ID_FILE,
|
|
3
6
|
FML_OBSERVER_DIR,
|
|
@@ -184,9 +187,9 @@ function setSyncEnabled(settingsFile, enabled) {
|
|
|
184
187
|
|
|
185
188
|
// ../../packages/panopticon/src/artifacts.ts
|
|
186
189
|
import { createHash as createHash5, randomUUID as randomUUID3 } from "crypto";
|
|
187
|
-
import
|
|
190
|
+
import fs9 from "fs";
|
|
188
191
|
import os3 from "os";
|
|
189
|
-
import
|
|
192
|
+
import path19 from "path";
|
|
190
193
|
|
|
191
194
|
// ../../packages/agent-targets/src/artifacts/targets/claude.ts
|
|
192
195
|
import path8 from "path";
|
|
@@ -326,65 +329,18 @@ function readClaudeMachineId(configFile) {
|
|
|
326
329
|
// ../../packages/agent-targets/src/artifacts/repository-context.ts
|
|
327
330
|
import { createHash as createHash2 } from "crypto";
|
|
328
331
|
import fs5 from "fs";
|
|
329
|
-
|
|
330
|
-
// ../../packages/shared/src/github-repository.ts
|
|
331
|
-
var MAX_REPOSITORY_BYTES = 201;
|
|
332
|
-
var UTF8_ENCODER = new TextEncoder();
|
|
333
|
-
function utf8Bytes(value) {
|
|
334
|
-
return UTF8_ENCODER.encode(value).byteLength;
|
|
335
|
-
}
|
|
336
|
-
function githubRepositoryPath(pathname) {
|
|
337
|
-
const parts = pathname.replace(/^\/+|\/+$/g, "").split("/");
|
|
338
|
-
if (parts.length !== 2) return null;
|
|
339
|
-
const owner = parts[0];
|
|
340
|
-
const repository = parts[1]?.replace(/\.git$/i, "");
|
|
341
|
-
if (!owner || !repository) return null;
|
|
342
|
-
const segmentPattern = /^[A-Za-z0-9_.-]+$/;
|
|
343
|
-
if (!segmentPattern.test(owner) || !segmentPattern.test(repository)) {
|
|
344
|
-
return null;
|
|
345
|
-
}
|
|
346
|
-
const canonical = `${owner.toLowerCase()}/${repository.toLowerCase()}`;
|
|
347
|
-
if (canonical.startsWith("./") || canonical.startsWith("../") || repository === "." || repository === ".." || repository.toLowerCase().endsWith(".git")) {
|
|
348
|
-
return null;
|
|
349
|
-
}
|
|
350
|
-
return utf8Bytes(canonical) <= MAX_REPOSITORY_BYTES ? canonical : null;
|
|
351
|
-
}
|
|
352
|
-
function canonicalGitHubRepository(remote) {
|
|
353
|
-
const trimmed = remote.trim();
|
|
354
|
-
if (!trimmed || trimmed.includes("\0")) return null;
|
|
355
|
-
const scp = trimmed.match(/^git@github\.com:([^?#]+)$/i);
|
|
356
|
-
if (scp?.[1]) return githubRepositoryPath(scp[1]);
|
|
357
|
-
let url;
|
|
358
|
-
try {
|
|
359
|
-
url = new URL(trimmed);
|
|
360
|
-
} catch {
|
|
361
|
-
return null;
|
|
362
|
-
}
|
|
363
|
-
if (url.hostname.toLowerCase() !== "github.com") return null;
|
|
364
|
-
if (url.search || url.hash || url.password || url.port) return null;
|
|
365
|
-
if (url.protocol === "https:" || url.protocol === "http:") {
|
|
366
|
-
if (url.username) return null;
|
|
367
|
-
} else if (url.protocol === "ssh:") {
|
|
368
|
-
if (url.username && url.username !== "git") return null;
|
|
369
|
-
} else {
|
|
370
|
-
return null;
|
|
371
|
-
}
|
|
372
|
-
return githubRepositoryPath(url.pathname);
|
|
373
|
-
}
|
|
374
|
-
|
|
375
|
-
// ../../packages/agent-targets/src/artifacts/repository-context.ts
|
|
376
332
|
var MAX_ARTIFACT_CONTEXT_PREFIX_BYTES = 256 * 1024;
|
|
377
333
|
var MAX_ARTIFACT_CONTEXT_RECORDS = 64;
|
|
378
334
|
var ARTIFACT_CONTEXT_READ_CHUNK_BYTES = 32 * 1024;
|
|
379
335
|
var MAX_CWD_BYTES = 4096;
|
|
380
336
|
var MAX_BRANCH_BYTES = 1024;
|
|
381
|
-
function
|
|
337
|
+
function utf8Bytes(value) {
|
|
382
338
|
return Buffer.byteLength(value, "utf8");
|
|
383
339
|
}
|
|
384
340
|
function boundedOptionalString(value, maxBytes) {
|
|
385
341
|
if (typeof value !== "string") return void 0;
|
|
386
342
|
const trimmed = value.trim();
|
|
387
|
-
if (!trimmed || new RegExp("\\p{Cc}", "u").test(trimmed) ||
|
|
343
|
+
if (!trimmed || new RegExp("\\p{Cc}", "u").test(trimmed) || utf8Bytes(trimmed) > maxBytes) {
|
|
388
344
|
return void 0;
|
|
389
345
|
}
|
|
390
346
|
return trimmed;
|
|
@@ -755,50 +711,168 @@ var grokArtifactDiscovery = Object.freeze({
|
|
|
755
711
|
)
|
|
756
712
|
});
|
|
757
713
|
|
|
758
|
-
// ../../packages/agent-targets/src/artifacts/targets/
|
|
714
|
+
// ../../packages/agent-targets/src/artifacts/targets/mini-swe-agent.ts
|
|
715
|
+
import fs6 from "fs";
|
|
759
716
|
import path15 from "path";
|
|
760
|
-
var
|
|
761
|
-
function
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
const sessionId = typeof record.id === "string" && record.id.trim() ? record.id.trim() : null;
|
|
766
|
-
if (typeof record.cwd !== "string" || !record.cwd.trim()) {
|
|
767
|
-
return transcriptCandidate({
|
|
768
|
-
targetId: "pi",
|
|
769
|
-
sourcePath,
|
|
770
|
-
sessionId
|
|
771
|
-
});
|
|
717
|
+
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
|
+
function dataDirectory({ homeDir, env }) {
|
|
719
|
+
if (env.FML_DATA_DIR?.trim()) {
|
|
720
|
+
if (!path15.isAbsolute(env.FML_DATA_DIR)) {
|
|
721
|
+
throw new Error("FML_DATA_DIR must be an absolute path");
|
|
772
722
|
}
|
|
773
|
-
|
|
723
|
+
return path15.normalize(env.FML_DATA_DIR);
|
|
724
|
+
}
|
|
725
|
+
if (process.platform === "darwin") {
|
|
726
|
+
return path15.join(homeDir, "Library", "Application Support", "fml");
|
|
727
|
+
}
|
|
728
|
+
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");
|
|
731
|
+
}
|
|
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");
|
|
734
|
+
}
|
|
735
|
+
function snapshotCandidate(sourcePath, context) {
|
|
736
|
+
let file;
|
|
737
|
+
try {
|
|
738
|
+
file = fs6.openSync(sourcePath, "r");
|
|
739
|
+
} catch {
|
|
740
|
+
return null;
|
|
741
|
+
}
|
|
742
|
+
try {
|
|
743
|
+
const stat = fs6.fstatSync(file);
|
|
744
|
+
if (!stat.isFile()) return null;
|
|
745
|
+
if (context.maxFileBytes !== void 0 && stat.size > context.maxFileBytes) {
|
|
746
|
+
return transcriptCandidate({ targetId: "mini-swe-agent", sourcePath });
|
|
747
|
+
}
|
|
748
|
+
const bytes = Buffer.allocUnsafe(stat.size);
|
|
749
|
+
let offset = 0;
|
|
750
|
+
while (offset < bytes.length) {
|
|
751
|
+
const read = fs6.readSync(
|
|
752
|
+
file,
|
|
753
|
+
bytes,
|
|
754
|
+
offset,
|
|
755
|
+
bytes.length - offset,
|
|
756
|
+
offset
|
|
757
|
+
);
|
|
758
|
+
if (read <= 0) return null;
|
|
759
|
+
offset += read;
|
|
760
|
+
}
|
|
761
|
+
if (fs6.fstatSync(file).size !== stat.size) return null;
|
|
762
|
+
const value = JSON.parse(bytes.toString("utf8"));
|
|
763
|
+
if (typeof value !== "object" || value === null || !("fml" in value)) {
|
|
764
|
+
return null;
|
|
765
|
+
}
|
|
766
|
+
const metadata = value.fml;
|
|
767
|
+
if (typeof metadata !== "object" || metadata === null || !("version" in metadata) || metadata.version !== 1 || !("session_id" in metadata) || typeof metadata.session_id !== "string" || !SESSION_ID_PATTERN.test(metadata.session_id)) {
|
|
768
|
+
return null;
|
|
769
|
+
}
|
|
770
|
+
const cwd = "cwd" in metadata && typeof metadata.cwd === "string" ? metadata.cwd : void 0;
|
|
771
|
+
const origin = cwd ? context.resolveGitHubOrigin?.(cwd) : null;
|
|
774
772
|
return transcriptCandidate({
|
|
775
|
-
targetId: "
|
|
773
|
+
targetId: "mini-swe-agent",
|
|
776
774
|
sourcePath,
|
|
777
|
-
sessionId,
|
|
775
|
+
sessionId: metadata.session_id,
|
|
776
|
+
metadata: { store: "managed_snapshots" },
|
|
778
777
|
repositoryObservations: origin ? [
|
|
779
778
|
repositoryObservation({
|
|
780
779
|
repository: origin.repository,
|
|
781
780
|
source: "git_origin",
|
|
782
|
-
observedAtMs:
|
|
783
|
-
cwd
|
|
781
|
+
observedAtMs: (context.nowMs ?? Date.now)(),
|
|
782
|
+
cwd,
|
|
784
783
|
branch: origin.branch,
|
|
785
784
|
commitHash: origin.commitHash
|
|
786
785
|
})
|
|
787
786
|
] : []
|
|
788
787
|
});
|
|
788
|
+
} catch {
|
|
789
|
+
return null;
|
|
790
|
+
} finally {
|
|
791
|
+
fs6.closeSync(file);
|
|
792
|
+
}
|
|
793
|
+
}
|
|
794
|
+
var miniSweAgentArtifactDiscovery = Object.freeze({
|
|
795
|
+
targetId: "mini-swe-agent",
|
|
796
|
+
discover: (context) => walkFiles({
|
|
797
|
+
root: path15.join(dataDirectory(context), "mini-swe-agent", "trajectories"),
|
|
798
|
+
maxDepth: 0,
|
|
799
|
+
includeFile: (filePath) => filePath.endsWith(".traj.json")
|
|
800
|
+
}).flatMap((sourcePath) => {
|
|
801
|
+
const candidate = snapshotCandidate(sourcePath, context);
|
|
802
|
+
return candidate ? [candidate] : [];
|
|
803
|
+
})
|
|
804
|
+
});
|
|
805
|
+
|
|
806
|
+
// ../../packages/agent-targets/src/artifacts/targets/pi.ts
|
|
807
|
+
import path16 from "path";
|
|
808
|
+
|
|
809
|
+
// ../../packages/agent-targets/src/artifacts/pi-repository-origin.ts
|
|
810
|
+
import { z } from "zod";
|
|
811
|
+
var PI_REPOSITORY_ORIGIN_ENTRY_TYPE = "fml-repository-origin";
|
|
812
|
+
var RepositorySlugSchema = z.string().regex(/^[A-Za-z0-9_.-]+\/[A-Za-z0-9_.-]+$/u).transform((slug) => canonicalGitHubRepository(`https://github.com/${slug}`)).pipe(z.string());
|
|
813
|
+
var PiRepositoryOriginDataSchema = z.object({
|
|
814
|
+
version: z.literal(1),
|
|
815
|
+
repository: RepositorySlugSchema.nullable(),
|
|
816
|
+
cwd: z.string().min(1).refine(
|
|
817
|
+
(cwd) => cwd.trim().length > 0 && !new RegExp("\\p{Cc}", "u").test(cwd) && Buffer.byteLength(cwd, "utf8") <= 4096
|
|
818
|
+
)
|
|
819
|
+
});
|
|
820
|
+
var NativeOriginMarkerSchema = z.object({
|
|
821
|
+
customType: z.literal(PI_REPOSITORY_ORIGIN_ENTRY_TYPE)
|
|
822
|
+
});
|
|
823
|
+
var NativeOriginEntrySchema = z.object({
|
|
824
|
+
type: z.literal("custom"),
|
|
825
|
+
customType: z.literal(PI_REPOSITORY_ORIGIN_ENTRY_TYPE),
|
|
826
|
+
timestamp: z.iso.datetime({ offset: true }).transform((value) => Date.parse(value)).pipe(z.number().int().nonnegative()),
|
|
827
|
+
data: PiRepositoryOriginDataSchema
|
|
828
|
+
});
|
|
829
|
+
function readPiRepositoryOrigin(entries) {
|
|
830
|
+
let snapshot;
|
|
831
|
+
for (const entry of entries) {
|
|
832
|
+
if (!NativeOriginMarkerSchema.safeParse(entry).success) continue;
|
|
833
|
+
const parsed = NativeOriginEntrySchema.safeParse(entry);
|
|
834
|
+
if (!parsed.success) return { status: "invalid" };
|
|
835
|
+
const next = { ...parsed.data.data, observedAtMs: parsed.data.timestamp };
|
|
836
|
+
if (snapshot && (snapshot.repository !== next.repository || snapshot.cwd !== next.cwd || snapshot.observedAtMs !== next.observedAtMs)) {
|
|
837
|
+
return { status: "invalid" };
|
|
838
|
+
}
|
|
839
|
+
snapshot = next;
|
|
789
840
|
}
|
|
790
|
-
return
|
|
841
|
+
return snapshot ? { status: "captured", snapshot } : { status: "absent" };
|
|
842
|
+
}
|
|
843
|
+
|
|
844
|
+
// ../../packages/agent-targets/src/artifacts/targets/pi.ts
|
|
845
|
+
var PI_SKIP_DIRS = /* @__PURE__ */ new Set(["subagent-artifacts"]);
|
|
846
|
+
function piTranscriptCandidate(sourcePath) {
|
|
847
|
+
const records = readJsonlContextRecords(sourcePath);
|
|
848
|
+
const header = records.find((record) => record.type === "session");
|
|
849
|
+
const sessionId = typeof header?.id === "string" && header.id.trim() ? header.id.trim() : null;
|
|
850
|
+
const evidence = readPiRepositoryOrigin(records);
|
|
851
|
+
const snapshot = evidence.status === "captured" ? evidence.snapshot : null;
|
|
852
|
+
return transcriptCandidate({
|
|
853
|
+
targetId: "pi",
|
|
854
|
+
sourcePath,
|
|
855
|
+
sessionId,
|
|
856
|
+
repositoryObservations: snapshot?.repository ? [
|
|
857
|
+
repositoryObservation({
|
|
858
|
+
repository: snapshot.repository,
|
|
859
|
+
source: "git_origin",
|
|
860
|
+
observedAtMs: snapshot.observedAtMs,
|
|
861
|
+
cwd: snapshot.cwd
|
|
862
|
+
})
|
|
863
|
+
] : []
|
|
864
|
+
});
|
|
791
865
|
}
|
|
792
866
|
var piArtifactDiscovery = Object.freeze({
|
|
793
867
|
targetId: "pi",
|
|
794
868
|
discover: (context) => {
|
|
795
869
|
const { homeDir } = context;
|
|
796
870
|
return walkFiles({
|
|
797
|
-
root:
|
|
871
|
+
root: path16.join(homeDir, ".pi", "agent", "sessions"),
|
|
798
872
|
maxDepth: 8,
|
|
799
873
|
includeFile: (filePath) => filePath.endsWith(".jsonl"),
|
|
800
874
|
skipDirs: PI_SKIP_DIRS
|
|
801
|
-
}).map((sourcePath) => piTranscriptCandidate(sourcePath
|
|
875
|
+
}).map((sourcePath) => piTranscriptCandidate(sourcePath));
|
|
802
876
|
}
|
|
803
877
|
});
|
|
804
878
|
|
|
@@ -809,6 +883,7 @@ var ARTIFACT_DISCOVERY_CAPABILITIES = Object.freeze([
|
|
|
809
883
|
geminiArtifactDiscovery,
|
|
810
884
|
grokArtifactDiscovery,
|
|
811
885
|
piArtifactDiscovery,
|
|
886
|
+
miniSweAgentArtifactDiscovery,
|
|
812
887
|
cursorArtifactDiscovery,
|
|
813
888
|
copilotCliArtifactDiscovery,
|
|
814
889
|
factoryDroidArtifactDiscovery
|
|
@@ -826,13 +901,13 @@ function discoverTargetArtifactCandidates(context) {
|
|
|
826
901
|
|
|
827
902
|
// ../../packages/agent-targets/src/artifacts/materialize.ts
|
|
828
903
|
import { createHash as createHash3 } from "crypto";
|
|
829
|
-
import
|
|
830
|
-
import
|
|
904
|
+
import fs7 from "fs";
|
|
905
|
+
import path17 from "path";
|
|
831
906
|
import zlib from "zlib";
|
|
832
907
|
var MAX_MATERIALIZED_ARTIFACT_BYTES = 100 * 1024 * 1024;
|
|
833
908
|
var DEFAULT_MATERIALIZED_CACHE_BYTES = 2 * 1024 * 1024 * 1024;
|
|
834
909
|
function cacheEntryName(sourcePath, stat) {
|
|
835
|
-
const identity = `${
|
|
910
|
+
const identity = `${path17.resolve(sourcePath)}\0${stat.size}\0${Math.floor(
|
|
836
911
|
stat.mtimeMs
|
|
837
912
|
)}`;
|
|
838
913
|
const digest = createHash3("sha256").update(identity).digest("hex");
|
|
@@ -845,7 +920,7 @@ function decodeZstd(sourcePath, maxOutputBytes) {
|
|
|
845
920
|
const decompress = zlib.zstdDecompressSync;
|
|
846
921
|
if (typeof decompress !== "function") return null;
|
|
847
922
|
try {
|
|
848
|
-
return decompress(
|
|
923
|
+
return decompress(fs7.readFileSync(sourcePath), {
|
|
849
924
|
maxOutputLength: maxOutputBytes
|
|
850
925
|
});
|
|
851
926
|
} catch {
|
|
@@ -854,9 +929,9 @@ function decodeZstd(sourcePath, maxOutputBytes) {
|
|
|
854
929
|
}
|
|
855
930
|
function materializedArtifactPath(input) {
|
|
856
931
|
try {
|
|
857
|
-
const stat =
|
|
932
|
+
const stat = fs7.statSync(input.sourcePath);
|
|
858
933
|
if (!stat.isFile() || stat.size === 0) return null;
|
|
859
|
-
return
|
|
934
|
+
return path17.join(input.cacheDir, cacheEntryName(input.sourcePath, stat));
|
|
860
935
|
} catch {
|
|
861
936
|
return null;
|
|
862
937
|
}
|
|
@@ -864,20 +939,20 @@ function materializedArtifactPath(input) {
|
|
|
864
939
|
function materializeCompressedArtifact(input) {
|
|
865
940
|
let stat;
|
|
866
941
|
try {
|
|
867
|
-
stat =
|
|
942
|
+
stat = fs7.statSync(input.sourcePath);
|
|
868
943
|
} catch {
|
|
869
944
|
return null;
|
|
870
945
|
}
|
|
871
946
|
if (!stat.isFile() || stat.size === 0) return null;
|
|
872
|
-
const cachePath =
|
|
947
|
+
const cachePath = path17.join(
|
|
873
948
|
input.cacheDir,
|
|
874
949
|
cacheEntryName(input.sourcePath, stat)
|
|
875
950
|
);
|
|
876
951
|
try {
|
|
877
|
-
if (
|
|
952
|
+
if (fs7.statSync(cachePath).isFile()) {
|
|
878
953
|
const now = /* @__PURE__ */ new Date();
|
|
879
954
|
try {
|
|
880
|
-
|
|
955
|
+
fs7.utimesSync(cachePath, now, now);
|
|
881
956
|
} catch {
|
|
882
957
|
}
|
|
883
958
|
return cachePath;
|
|
@@ -890,10 +965,10 @@ function materializeCompressedArtifact(input) {
|
|
|
890
965
|
);
|
|
891
966
|
if (!decoded) return null;
|
|
892
967
|
try {
|
|
893
|
-
|
|
968
|
+
fs7.mkdirSync(input.cacheDir, { recursive: true, mode: 448 });
|
|
894
969
|
const tempPath = `${cachePath}.${process.pid}.tmp`;
|
|
895
|
-
|
|
896
|
-
|
|
970
|
+
fs7.writeFileSync(tempPath, decoded, { mode: 384 });
|
|
971
|
+
fs7.renameSync(tempPath, cachePath);
|
|
897
972
|
return cachePath;
|
|
898
973
|
} catch {
|
|
899
974
|
return null;
|
|
@@ -903,16 +978,16 @@ function pruneMaterializedCache(input) {
|
|
|
903
978
|
const maxTotalBytes = input.maxTotalBytes ?? DEFAULT_MATERIALIZED_CACHE_BYTES;
|
|
904
979
|
let entries;
|
|
905
980
|
try {
|
|
906
|
-
entries =
|
|
981
|
+
entries = fs7.readdirSync(input.cacheDir, { withFileTypes: true });
|
|
907
982
|
} catch {
|
|
908
983
|
return { removed: 0, retainedBytes: 0 };
|
|
909
984
|
}
|
|
910
985
|
const files = [];
|
|
911
986
|
for (const entry of entries) {
|
|
912
987
|
if (!entry.isFile()) continue;
|
|
913
|
-
const filePath =
|
|
988
|
+
const filePath = path17.join(input.cacheDir, entry.name);
|
|
914
989
|
try {
|
|
915
|
-
const stat =
|
|
990
|
+
const stat = fs7.statSync(filePath);
|
|
916
991
|
files.push({ path: filePath, size: stat.size, atimeMs: stat.atimeMs });
|
|
917
992
|
} catch {
|
|
918
993
|
}
|
|
@@ -927,7 +1002,7 @@ function pruneMaterializedCache(input) {
|
|
|
927
1002
|
continue;
|
|
928
1003
|
}
|
|
929
1004
|
try {
|
|
930
|
-
|
|
1005
|
+
fs7.rmSync(file.path);
|
|
931
1006
|
removed += 1;
|
|
932
1007
|
} catch {
|
|
933
1008
|
retainedBytes += file.size;
|
|
@@ -939,8 +1014,8 @@ function pruneMaterializedCache(input) {
|
|
|
939
1014
|
// ../../packages/panopticon/src/repository-context.ts
|
|
940
1015
|
import { execFileSync } from "child_process";
|
|
941
1016
|
import { createHash as createHash4 } from "crypto";
|
|
942
|
-
import
|
|
943
|
-
import
|
|
1017
|
+
import fs8 from "fs";
|
|
1018
|
+
import path18 from "path";
|
|
944
1019
|
var MAX_CWD_BYTES2 = 4096;
|
|
945
1020
|
var GIT_OUTPUT_BYTES = 16 * 1024;
|
|
946
1021
|
var GIT_CONFIG_OUTPUT_BYTES = 4 * 1024 * 1024;
|
|
@@ -1080,7 +1155,7 @@ var PERSISTENT_ORIGIN_CACHE_SCHEMA_VERSION = 2;
|
|
|
1080
1155
|
var DEFAULT_PERSISTENT_ORIGIN_CACHE_MAX_ENTRIES = 512;
|
|
1081
1156
|
function fileContentIdentity(filePath) {
|
|
1082
1157
|
try {
|
|
1083
|
-
const contents =
|
|
1158
|
+
const contents = fs8.readFileSync(filePath);
|
|
1084
1159
|
return `sha256:${createHash4("sha256").update(contents).digest("hex")}`;
|
|
1085
1160
|
} catch (error) {
|
|
1086
1161
|
const code = error && typeof error === "object" && "code" in error ? error.code : void 0;
|
|
@@ -1089,7 +1164,7 @@ function fileContentIdentity(filePath) {
|
|
|
1089
1164
|
}
|
|
1090
1165
|
function packedRefsIdentity(filePath) {
|
|
1091
1166
|
try {
|
|
1092
|
-
const stat =
|
|
1167
|
+
const stat = fs8.statSync(filePath, { bigint: true });
|
|
1093
1168
|
if (!stat.isFile() || stat.ino === 0n) return null;
|
|
1094
1169
|
return [stat.dev, stat.ino, stat.size, stat.mtimeNs, stat.ctimeNs].join(
|
|
1095
1170
|
":"
|
|
@@ -1118,18 +1193,18 @@ function effectiveConfigIdentity(cwd) {
|
|
|
1118
1193
|
}
|
|
1119
1194
|
function readSmallText(filePath) {
|
|
1120
1195
|
try {
|
|
1121
|
-
return
|
|
1196
|
+
return fs8.readFileSync(filePath, "utf8").trim();
|
|
1122
1197
|
} catch {
|
|
1123
1198
|
return null;
|
|
1124
1199
|
}
|
|
1125
1200
|
}
|
|
1126
1201
|
function findGitDirectory(cwd) {
|
|
1127
|
-
let current =
|
|
1202
|
+
let current = path18.resolve(cwd);
|
|
1128
1203
|
for (; ; ) {
|
|
1129
|
-
const candidate =
|
|
1204
|
+
const candidate = path18.join(current, ".git");
|
|
1130
1205
|
let stat;
|
|
1131
1206
|
try {
|
|
1132
|
-
stat =
|
|
1207
|
+
stat = fs8.statSync(candidate);
|
|
1133
1208
|
} catch {
|
|
1134
1209
|
stat = void 0;
|
|
1135
1210
|
}
|
|
@@ -1140,20 +1215,20 @@ function findGitDirectory(cwd) {
|
|
|
1140
1215
|
const pointer = readSmallText(candidate);
|
|
1141
1216
|
const match = pointer ? /^gitdir:\s*(.+)$/u.exec(pointer) : null;
|
|
1142
1217
|
if (!match?.[1]) return null;
|
|
1143
|
-
const gitDir =
|
|
1144
|
-
const common = readSmallText(
|
|
1218
|
+
const gitDir = path18.resolve(current, match[1]);
|
|
1219
|
+
const common = readSmallText(path18.join(gitDir, "commondir"));
|
|
1145
1220
|
return {
|
|
1146
1221
|
gitDir,
|
|
1147
|
-
commonDir: common ?
|
|
1222
|
+
commonDir: common ? path18.resolve(gitDir, common) : gitDir
|
|
1148
1223
|
};
|
|
1149
1224
|
}
|
|
1150
|
-
const parent =
|
|
1225
|
+
const parent = path18.dirname(current);
|
|
1151
1226
|
if (parent === current) return null;
|
|
1152
1227
|
current = parent;
|
|
1153
1228
|
}
|
|
1154
1229
|
}
|
|
1155
1230
|
function checkoutSignature(layout, cwd) {
|
|
1156
|
-
const headPath =
|
|
1231
|
+
const headPath = path18.join(layout.gitDir, "HEAD");
|
|
1157
1232
|
const head = readSmallText(headPath);
|
|
1158
1233
|
const configIdentity = effectiveConfigIdentity(cwd);
|
|
1159
1234
|
if (head === null || configIdentity === null) {
|
|
@@ -1162,14 +1237,14 @@ function checkoutSignature(layout, cwd) {
|
|
|
1162
1237
|
const parts = [layout.gitDir, head, configIdentity];
|
|
1163
1238
|
const ref = /^ref:\s*(.+)$/u.exec(head)?.[1];
|
|
1164
1239
|
if (ref) {
|
|
1165
|
-
const looseRefPath =
|
|
1240
|
+
const looseRefPath = path18.join(layout.commonDir, ref);
|
|
1166
1241
|
if (/^ref:/u.test(readSmallText(looseRefPath) ?? "")) return null;
|
|
1167
1242
|
const looseRefIdentity = fileContentIdentity(looseRefPath);
|
|
1168
1243
|
const packedIdentity = packedRefsIdentity(
|
|
1169
|
-
|
|
1244
|
+
path18.join(layout.commonDir, "packed-refs")
|
|
1170
1245
|
);
|
|
1171
1246
|
const reftableIdentity = fileContentIdentity(
|
|
1172
|
-
|
|
1247
|
+
path18.join(layout.commonDir, "reftable", "tables.list")
|
|
1173
1248
|
);
|
|
1174
1249
|
if (!looseRefIdentity || !packedIdentity || !reftableIdentity || looseRefIdentity === "missing" && packedIdentity === "missing" && reftableIdentity === "missing") {
|
|
1175
1250
|
return null;
|
|
@@ -1180,7 +1255,7 @@ function checkoutSignature(layout, cwd) {
|
|
|
1180
1255
|
}
|
|
1181
1256
|
function readPersistentOriginCache(cacheFile) {
|
|
1182
1257
|
try {
|
|
1183
|
-
const parsed = JSON.parse(
|
|
1258
|
+
const parsed = JSON.parse(fs8.readFileSync(cacheFile, "utf8"));
|
|
1184
1259
|
if (parsed && typeof parsed === "object" && parsed.schemaVersion === PERSISTENT_ORIGIN_CACHE_SCHEMA_VERSION && parsed.entries && typeof parsed.entries === "object") {
|
|
1185
1260
|
return parsed;
|
|
1186
1261
|
}
|
|
@@ -1191,13 +1266,13 @@ function readPersistentOriginCache(cacheFile) {
|
|
|
1191
1266
|
function writePersistentOriginCache(cacheFile, cache) {
|
|
1192
1267
|
const temporary = `${cacheFile}.${process.pid}.tmp`;
|
|
1193
1268
|
try {
|
|
1194
|
-
|
|
1195
|
-
|
|
1269
|
+
fs8.mkdirSync(path18.dirname(cacheFile), { recursive: true, mode: 448 });
|
|
1270
|
+
fs8.writeFileSync(temporary, `${JSON.stringify(cache)}
|
|
1196
1271
|
`, { mode: 384 });
|
|
1197
|
-
|
|
1272
|
+
fs8.renameSync(temporary, cacheFile);
|
|
1198
1273
|
} catch {
|
|
1199
1274
|
try {
|
|
1200
|
-
|
|
1275
|
+
fs8.rmSync(temporary, { force: true });
|
|
1201
1276
|
} catch {
|
|
1202
1277
|
}
|
|
1203
1278
|
}
|
|
@@ -1285,20 +1360,20 @@ function isAbortError(error) {
|
|
|
1285
1360
|
}
|
|
1286
1361
|
function safeStat(filePath) {
|
|
1287
1362
|
try {
|
|
1288
|
-
return
|
|
1363
|
+
return fs9.statSync(filePath);
|
|
1289
1364
|
} catch {
|
|
1290
1365
|
return null;
|
|
1291
1366
|
}
|
|
1292
1367
|
}
|
|
1293
1368
|
function normalizeFilePath2(filePath) {
|
|
1294
|
-
return
|
|
1369
|
+
return path19.resolve(filePath);
|
|
1295
1370
|
}
|
|
1296
1371
|
function artifactReadPath(artifact) {
|
|
1297
1372
|
return normalizeFilePath2(artifact.readPath ?? artifact.sourcePath);
|
|
1298
1373
|
}
|
|
1299
1374
|
function statCandidateSource(sourcePath, transientStatErrors) {
|
|
1300
1375
|
try {
|
|
1301
|
-
return
|
|
1376
|
+
return fs9.statSync(sourcePath);
|
|
1302
1377
|
} catch (error) {
|
|
1303
1378
|
if (error.code === "ENOENT") return null;
|
|
1304
1379
|
if (transientStatErrors === "throw") throw error;
|
|
@@ -1306,7 +1381,7 @@ function statCandidateSource(sourcePath, transientStatErrors) {
|
|
|
1306
1381
|
}
|
|
1307
1382
|
}
|
|
1308
1383
|
function contentTypeForPath(filePath) {
|
|
1309
|
-
const ext =
|
|
1384
|
+
const ext = path19.extname(filePath).toLowerCase();
|
|
1310
1385
|
if (ext === ".json" || ext === ".jsonl") return "application/json";
|
|
1311
1386
|
if (ext === ".md") return "text/markdown";
|
|
1312
1387
|
if (ext === ".toml") return "application/toml";
|
|
@@ -1349,13 +1424,14 @@ function discoverArtifacts(options = {}) {
|
|
|
1349
1424
|
};
|
|
1350
1425
|
}
|
|
1351
1426
|
const homeDir = normalizeFilePath2(homeDirInput);
|
|
1427
|
+
const maxBytes = options.maxFileBytes ?? DEFAULT_MAX_ARTIFACT_BYTES;
|
|
1352
1428
|
const candidates = discoverTargetArtifactCandidates({
|
|
1353
1429
|
homeDir,
|
|
1354
1430
|
env,
|
|
1431
|
+
maxFileBytes: maxBytes,
|
|
1355
1432
|
resolveGitHubOrigin: repositoryResolution.resolve,
|
|
1356
1433
|
...options.materializeArtifact ? { materializeArtifact: options.materializeArtifact } : {}
|
|
1357
1434
|
});
|
|
1358
|
-
const maxBytes = options.maxFileBytes ?? DEFAULT_MAX_ARTIFACT_BYTES;
|
|
1359
1435
|
const byKey = /* @__PURE__ */ new Map();
|
|
1360
1436
|
const oversizedByKey = /* @__PURE__ */ new Map();
|
|
1361
1437
|
for (const candidate of candidates) {
|
|
@@ -1418,7 +1494,7 @@ function readUploadThrottles(value) {
|
|
|
1418
1494
|
}
|
|
1419
1495
|
function readArtifactQueue(queueFile) {
|
|
1420
1496
|
try {
|
|
1421
|
-
const parsed = JSON.parse(
|
|
1497
|
+
const parsed = JSON.parse(fs9.readFileSync(queueFile, "utf8"));
|
|
1422
1498
|
if (!parsed || typeof parsed !== "object") return emptyQueue();
|
|
1423
1499
|
const record = parsed;
|
|
1424
1500
|
if (record.schemaVersion !== RAW_ARTIFACT_SCHEMA_VERSION) {
|
|
@@ -1435,15 +1511,15 @@ function readArtifactQueue(queueFile) {
|
|
|
1435
1511
|
}
|
|
1436
1512
|
}
|
|
1437
1513
|
function writeArtifactQueue(queueFile, queue) {
|
|
1438
|
-
|
|
1514
|
+
fs9.mkdirSync(path19.dirname(queueFile), { recursive: true, mode: 448 });
|
|
1439
1515
|
const tempFile = `${queueFile}.${process.pid}.${Date.now()}.tmp`;
|
|
1440
|
-
|
|
1516
|
+
fs9.writeFileSync(tempFile, `${JSON.stringify(queue, null, 2)}
|
|
1441
1517
|
`, {
|
|
1442
1518
|
mode: 384
|
|
1443
1519
|
});
|
|
1444
|
-
|
|
1520
|
+
fs9.renameSync(tempFile, queueFile);
|
|
1445
1521
|
try {
|
|
1446
|
-
|
|
1522
|
+
fs9.chmodSync(queueFile, 384);
|
|
1447
1523
|
} catch {
|
|
1448
1524
|
}
|
|
1449
1525
|
}
|
|
@@ -1460,11 +1536,20 @@ function nextGenerationStartedAtMs(nowMs, existing) {
|
|
|
1460
1536
|
return existing ? Math.max(nowMs, existing.generationStartedAtMs + 1) : nowMs;
|
|
1461
1537
|
}
|
|
1462
1538
|
function shouldStartNewGeneration(input) {
|
|
1539
|
+
if (input.existing.source === "mini-swe-agent") {
|
|
1540
|
+
if (input.existing.contentSha256) {
|
|
1541
|
+
try {
|
|
1542
|
+
return createHash5("sha256").update(fs9.readFileSync(input.nextReadPath)).digest("hex") !== input.existing.contentSha256;
|
|
1543
|
+
} catch {
|
|
1544
|
+
}
|
|
1545
|
+
}
|
|
1546
|
+
return input.nextSizeBytes !== input.existing.sizeBytes || input.nextMtimeMs !== input.existing.mtimeMs;
|
|
1547
|
+
}
|
|
1463
1548
|
if (input.nextSizeBytes < input.existing.uploadedSizeBytes) return true;
|
|
1464
1549
|
if (input.nextSizeBytes < input.existing.sizeBytes) return true;
|
|
1465
1550
|
if ((input.nextReadPath !== artifactReadPath(input.existing) || input.existing.readPath !== void 0) && input.nextSizeBytes === input.existing.sizeBytes && input.existing.uploadedSizeBytes >= input.nextSizeBytes && input.existing.contentSha256) {
|
|
1466
1551
|
try {
|
|
1467
|
-
const contentSha256 = createHash5("sha256").update(
|
|
1552
|
+
const contentSha256 = createHash5("sha256").update(fs9.readFileSync(input.nextReadPath)).digest("hex");
|
|
1468
1553
|
if (contentSha256 === input.existing.contentSha256) return false;
|
|
1469
1554
|
} catch {
|
|
1470
1555
|
}
|
|
@@ -1583,7 +1668,7 @@ function metadataForGeneration(input) {
|
|
|
1583
1668
|
...repositoryContext ? { repositoryContext } : {}
|
|
1584
1669
|
};
|
|
1585
1670
|
}
|
|
1586
|
-
function
|
|
1671
|
+
function snapshotCandidate2(candidate, existing, nowMs, maxFileBytes, transientStatErrors = "ignore", observerIdentity) {
|
|
1587
1672
|
const sourcePath = normalizeFilePath2(candidate.sourcePath);
|
|
1588
1673
|
const readPath = artifactReadPath(candidate);
|
|
1589
1674
|
const stat = statCandidateSource(readPath, transientStatErrors);
|
|
@@ -1727,7 +1812,7 @@ function snapshotArtifactsLocked(options, lock) {
|
|
|
1727
1812
|
throw new Error("artifact queue lock ownership was lost");
|
|
1728
1813
|
}
|
|
1729
1814
|
const existing = (candidate.identityKey ? entriesByIdentityKey.get(candidate.identityKey) : void 0) ?? entriesByKey.get(buildArtifactKey(candidate));
|
|
1730
|
-
const snapshot =
|
|
1815
|
+
const snapshot = snapshotCandidate2(
|
|
1731
1816
|
candidate,
|
|
1732
1817
|
existing,
|
|
1733
1818
|
nowMs,
|
|
@@ -1798,7 +1883,7 @@ function sameSourceRevision(left, right) {
|
|
|
1798
1883
|
}
|
|
1799
1884
|
function safeSourceRevision(filePath) {
|
|
1800
1885
|
try {
|
|
1801
|
-
const stat =
|
|
1886
|
+
const stat = fs9.statSync(filePath, { bigint: true });
|
|
1802
1887
|
return stat.isFile() ? sourceRevisionFromStat(stat) : null;
|
|
1803
1888
|
} catch {
|
|
1804
1889
|
return null;
|
|
@@ -1810,7 +1895,7 @@ function readExactRange(fd, startByte, endByte) {
|
|
|
1810
1895
|
const buffer = Buffer.alloc(sizeBytes);
|
|
1811
1896
|
let offset = 0;
|
|
1812
1897
|
while (offset < sizeBytes) {
|
|
1813
|
-
const bytesRead =
|
|
1898
|
+
const bytesRead = fs9.readSync(
|
|
1814
1899
|
fd,
|
|
1815
1900
|
buffer,
|
|
1816
1901
|
offset,
|
|
@@ -1829,19 +1914,19 @@ function readFileRangeAtRevision(filePath, startByte, endByte, expectedRevision)
|
|
|
1829
1914
|
}
|
|
1830
1915
|
let fd;
|
|
1831
1916
|
try {
|
|
1832
|
-
fd =
|
|
1917
|
+
fd = fs9.openSync(filePath, "r");
|
|
1833
1918
|
} catch {
|
|
1834
1919
|
return null;
|
|
1835
1920
|
}
|
|
1836
1921
|
try {
|
|
1837
1922
|
const openedRevision = sourceRevisionFromStat(
|
|
1838
|
-
|
|
1923
|
+
fs9.fstatSync(fd, { bigint: true })
|
|
1839
1924
|
);
|
|
1840
1925
|
if (!sameSourceRevision(pathRevisionBefore, openedRevision)) return null;
|
|
1841
1926
|
const bytes = readExactRange(fd, startByte, endByte);
|
|
1842
1927
|
if (!bytes) return null;
|
|
1843
1928
|
const revisionAfterRead = sourceRevisionFromStat(
|
|
1844
|
-
|
|
1929
|
+
fs9.fstatSync(fd, { bigint: true })
|
|
1845
1930
|
);
|
|
1846
1931
|
const pathRevisionAfter = safeSourceRevision(filePath);
|
|
1847
1932
|
if (!sameSourceRevision(openedRevision, revisionAfterRead) || !pathRevisionAfter || !sameSourceRevision(openedRevision, pathRevisionAfter)) {
|
|
@@ -1851,7 +1936,7 @@ function readFileRangeAtRevision(filePath, startByte, endByte, expectedRevision)
|
|
|
1851
1936
|
} catch {
|
|
1852
1937
|
return null;
|
|
1853
1938
|
} finally {
|
|
1854
|
-
|
|
1939
|
+
fs9.closeSync(fd);
|
|
1855
1940
|
}
|
|
1856
1941
|
}
|
|
1857
1942
|
function uploadMetadata(input) {
|
|
@@ -1983,13 +2068,13 @@ function validateCheckpointPrefix(input) {
|
|
|
1983
2068
|
}
|
|
1984
2069
|
let fd;
|
|
1985
2070
|
try {
|
|
1986
|
-
fd =
|
|
2071
|
+
fd = fs9.openSync(input.sourcePath, "r");
|
|
1987
2072
|
} catch {
|
|
1988
2073
|
return { status: "changed" };
|
|
1989
2074
|
}
|
|
1990
2075
|
try {
|
|
1991
2076
|
const openedRevision = sourceRevisionFromStat(
|
|
1992
|
-
|
|
2077
|
+
fs9.fstatSync(fd, { bigint: true })
|
|
1993
2078
|
);
|
|
1994
2079
|
if (!sameSourceRevision(pathRevisionBefore, openedRevision)) {
|
|
1995
2080
|
return { status: "changed" };
|
|
@@ -2009,7 +2094,7 @@ function validateCheckpointPrefix(input) {
|
|
|
2009
2094
|
contentHash.update(chunk);
|
|
2010
2095
|
}
|
|
2011
2096
|
const revisionAfterRead = sourceRevisionFromStat(
|
|
2012
|
-
|
|
2097
|
+
fs9.fstatSync(fd, { bigint: true })
|
|
2013
2098
|
);
|
|
2014
2099
|
const pathRevisionAfter = safeSourceRevision(input.sourcePath);
|
|
2015
2100
|
if (!sameSourceRevision(openedRevision, revisionAfterRead) || !pathRevisionAfter || !sameSourceRevision(openedRevision, pathRevisionAfter)) {
|
|
@@ -2024,7 +2109,7 @@ function validateCheckpointPrefix(input) {
|
|
|
2024
2109
|
} catch {
|
|
2025
2110
|
return { status: "changed" };
|
|
2026
2111
|
} finally {
|
|
2027
|
-
|
|
2112
|
+
fs9.closeSync(fd);
|
|
2028
2113
|
}
|
|
2029
2114
|
}
|
|
2030
2115
|
function validatedPrefixStillApplies(prefix, entry, uploadDestinationId, revision) {
|
|
@@ -2158,14 +2243,14 @@ function defaultIsPidAlive(pid) {
|
|
|
2158
2243
|
}
|
|
2159
2244
|
function readQueueLockHolder(lockFile) {
|
|
2160
2245
|
try {
|
|
2161
|
-
const parsed = JSON.parse(
|
|
2246
|
+
const parsed = JSON.parse(fs9.readFileSync(lockFile, "utf8"));
|
|
2162
2247
|
if (!parsed || typeof parsed !== "object") return null;
|
|
2163
2248
|
const record = parsed;
|
|
2164
2249
|
if (typeof record.pid !== "number" || typeof record.timestampMs !== "number") {
|
|
2165
2250
|
return null;
|
|
2166
2251
|
}
|
|
2167
2252
|
const ownerToken = typeof record.ownerToken === "string" ? record.ownerToken : void 0;
|
|
2168
|
-
const timestampMs = ownerToken ? Math.max(record.timestampMs,
|
|
2253
|
+
const timestampMs = ownerToken ? Math.max(record.timestampMs, fs9.statSync(lockFile).mtimeMs) : record.timestampMs;
|
|
2169
2254
|
return { pid: record.pid, timestampMs, ownerToken };
|
|
2170
2255
|
} catch {
|
|
2171
2256
|
return null;
|
|
@@ -2173,8 +2258,8 @@ function readQueueLockHolder(lockFile) {
|
|
|
2173
2258
|
}
|
|
2174
2259
|
function queueLockFileMatchesOwner(lockFile, fd, ownerToken) {
|
|
2175
2260
|
try {
|
|
2176
|
-
const openStat =
|
|
2177
|
-
const pathStat =
|
|
2261
|
+
const openStat = fs9.fstatSync(fd);
|
|
2262
|
+
const pathStat = fs9.statSync(lockFile);
|
|
2178
2263
|
if (openStat.dev !== pathStat.dev || openStat.ino !== pathStat.ino) {
|
|
2179
2264
|
return false;
|
|
2180
2265
|
}
|
|
@@ -2185,14 +2270,14 @@ function queueLockFileMatchesOwner(lockFile, fd, ownerToken) {
|
|
|
2185
2270
|
}
|
|
2186
2271
|
function acquireQueueLock(queueFile, deps) {
|
|
2187
2272
|
const lockFile = queueLockFile(queueFile);
|
|
2188
|
-
|
|
2273
|
+
fs9.mkdirSync(path19.dirname(lockFile), { recursive: true, mode: 448 });
|
|
2189
2274
|
for (let attempt = 0; attempt < 2; attempt += 1) {
|
|
2190
2275
|
try {
|
|
2191
|
-
const fd =
|
|
2276
|
+
const fd = fs9.openSync(lockFile, "wx+", 384);
|
|
2192
2277
|
const ownerToken = randomUUID3();
|
|
2193
2278
|
let released = false;
|
|
2194
2279
|
try {
|
|
2195
|
-
|
|
2280
|
+
fs9.writeSync(
|
|
2196
2281
|
fd,
|
|
2197
2282
|
`${JSON.stringify({
|
|
2198
2283
|
pid: process.pid,
|
|
@@ -2202,11 +2287,11 @@ function acquireQueueLock(queueFile, deps) {
|
|
|
2202
2287
|
`
|
|
2203
2288
|
);
|
|
2204
2289
|
const heartbeatAt = new Date(deps.nowMs());
|
|
2205
|
-
|
|
2290
|
+
fs9.futimesSync(fd, heartbeatAt, heartbeatAt);
|
|
2206
2291
|
} catch (error) {
|
|
2207
|
-
|
|
2292
|
+
fs9.closeSync(fd);
|
|
2208
2293
|
try {
|
|
2209
|
-
|
|
2294
|
+
fs9.unlinkSync(lockFile);
|
|
2210
2295
|
} catch {
|
|
2211
2296
|
}
|
|
2212
2297
|
throw error;
|
|
@@ -2214,7 +2299,7 @@ function acquireQueueLock(queueFile, deps) {
|
|
|
2214
2299
|
const close = () => {
|
|
2215
2300
|
if (released) return;
|
|
2216
2301
|
released = true;
|
|
2217
|
-
|
|
2302
|
+
fs9.closeSync(fd);
|
|
2218
2303
|
};
|
|
2219
2304
|
return {
|
|
2220
2305
|
heartbeat() {
|
|
@@ -2223,7 +2308,7 @@ function acquireQueueLock(queueFile, deps) {
|
|
|
2223
2308
|
return false;
|
|
2224
2309
|
try {
|
|
2225
2310
|
const heartbeatAt = new Date(deps.nowMs());
|
|
2226
|
-
|
|
2311
|
+
fs9.futimesSync(fd, heartbeatAt, heartbeatAt);
|
|
2227
2312
|
return true;
|
|
2228
2313
|
} catch {
|
|
2229
2314
|
return false;
|
|
@@ -2233,7 +2318,7 @@ function acquireQueueLock(queueFile, deps) {
|
|
|
2233
2318
|
if (released) return;
|
|
2234
2319
|
if (queueLockFileMatchesOwner(lockFile, fd, ownerToken)) {
|
|
2235
2320
|
try {
|
|
2236
|
-
|
|
2321
|
+
fs9.unlinkSync(lockFile);
|
|
2237
2322
|
} catch {
|
|
2238
2323
|
}
|
|
2239
2324
|
}
|
|
@@ -2246,7 +2331,7 @@ function acquireQueueLock(queueFile, deps) {
|
|
|
2246
2331
|
const stale = !holder || !deps.isPidAlive(holder.pid) || deps.nowMs() - holder.timestampMs > QUEUE_LOCK_STALE_MS;
|
|
2247
2332
|
if (!stale) return null;
|
|
2248
2333
|
try {
|
|
2249
|
-
|
|
2334
|
+
fs9.unlinkSync(lockFile);
|
|
2250
2335
|
} catch {
|
|
2251
2336
|
}
|
|
2252
2337
|
}
|
|
@@ -2304,7 +2389,7 @@ async function postRawArtifact(url, metadata, content, headers, fetchImpl = fetc
|
|
|
2304
2389
|
form.append(
|
|
2305
2390
|
"file",
|
|
2306
2391
|
new Blob([new Uint8Array(content)], { type: metadata.contentType }),
|
|
2307
|
-
|
|
2392
|
+
path19.basename(metadata.sourcePath) || "raw-artifact"
|
|
2308
2393
|
);
|
|
2309
2394
|
const abort = new AbortController();
|
|
2310
2395
|
const timeout = setTimeout(() => abort.abort(), timeoutMs);
|
|
@@ -2663,7 +2748,7 @@ async function uploadPendingArtifactsLocked(options, run) {
|
|
|
2663
2748
|
let sourceRefreshesThisAttempt = 0;
|
|
2664
2749
|
let validatedPrefix;
|
|
2665
2750
|
const refreshSourceSnapshot = () => {
|
|
2666
|
-
const snapshot =
|
|
2751
|
+
const snapshot = snapshotCandidate2(
|
|
2667
2752
|
{
|
|
2668
2753
|
artifactType: current.artifactType,
|
|
2669
2754
|
source: current.source,
|
|
@@ -3193,11 +3278,11 @@ async function uploadPendingArtifactsLocked(options, run) {
|
|
|
3193
3278
|
}
|
|
3194
3279
|
|
|
3195
3280
|
// ../../packages/panopticon/src/raw-sync.ts
|
|
3196
|
-
import
|
|
3197
|
-
import
|
|
3281
|
+
import fs11 from "fs";
|
|
3282
|
+
import path20 from "path";
|
|
3198
3283
|
|
|
3199
3284
|
// ../../packages/panopticon/src/artifact-materializer.ts
|
|
3200
|
-
import
|
|
3285
|
+
import fs10 from "fs";
|
|
3201
3286
|
function entryNeedsBytes(entry, amendmentPending) {
|
|
3202
3287
|
if (entry.uploadedSizeBytes < entry.sizeBytes) return true;
|
|
3203
3288
|
return amendmentPending(entry);
|
|
@@ -3212,7 +3297,7 @@ function createArtifactMaterializer(input) {
|
|
|
3212
3297
|
const unsupportedReason = (input.supportsCompression ?? supportsCompressedArtifacts)() ? void 0 : `compressed artifacts need Node 22.15 or newer (running ${process.version})`;
|
|
3213
3298
|
const chargeExisting = (cachePath) => {
|
|
3214
3299
|
try {
|
|
3215
|
-
const stat =
|
|
3300
|
+
const stat = fs10.statSync(cachePath);
|
|
3216
3301
|
if (!stat.isFile()) return false;
|
|
3217
3302
|
if (!retained.has(cachePath)) {
|
|
3218
3303
|
retained.add(cachePath);
|
|
@@ -3260,20 +3345,20 @@ function getRawArtifactSyncPaths(stateDir) {
|
|
|
3260
3345
|
if (stateDir.length === 0) {
|
|
3261
3346
|
throw new Error("raw artifact sync state directory must not be empty");
|
|
3262
3347
|
}
|
|
3263
|
-
const root =
|
|
3348
|
+
const root = path20.resolve(stateDir);
|
|
3264
3349
|
const managed = getManagedClientPaths({ PANOPTICON_HOME: root });
|
|
3265
3350
|
return {
|
|
3266
3351
|
root,
|
|
3267
3352
|
settingsFile: managed.syncSettingsFile,
|
|
3268
3353
|
queueFile: managed.artifactQueue,
|
|
3269
3354
|
artifactCacheDir: managed.artifactCache,
|
|
3270
|
-
discoveryCacheFile:
|
|
3271
|
-
githubOriginCacheFile:
|
|
3355
|
+
discoveryCacheFile: path20.join(root, "discovery.cache.json"),
|
|
3356
|
+
githubOriginCacheFile: path20.join(root, "github-origins.cache.json")
|
|
3272
3357
|
};
|
|
3273
3358
|
}
|
|
3274
3359
|
function invalidateRawArtifactDiscoveryCache(stateDir) {
|
|
3275
3360
|
try {
|
|
3276
|
-
|
|
3361
|
+
fs11.rmSync(getRawArtifactSyncPaths(stateDir).discoveryCacheFile, {
|
|
3277
3362
|
force: true
|
|
3278
3363
|
});
|
|
3279
3364
|
} catch {
|
|
@@ -3382,7 +3467,7 @@ function createRawArtifactSync(options) {
|
|
|
3382
3467
|
if (reuseMs <= 0) return null;
|
|
3383
3468
|
try {
|
|
3384
3469
|
const parsed = JSON.parse(
|
|
3385
|
-
|
|
3470
|
+
fs11.readFileSync(paths.discoveryCacheFile, "utf8")
|
|
3386
3471
|
);
|
|
3387
3472
|
if (parsed.schemaVersion !== DISCOVERY_CACHE_SCHEMA_VERSION || typeof parsed.createdAtMs !== "number" || parsed.inputs !== discoveryInputs() || !parsed.discovery || typeof parsed.discovery !== "object") {
|
|
3388
3473
|
return null;
|
|
@@ -3398,11 +3483,11 @@ function createRawArtifactSync(options) {
|
|
|
3398
3483
|
if ((options.discoveryReuseMs ?? 0) <= 0) return;
|
|
3399
3484
|
const temporary = `${paths.discoveryCacheFile}.${process.pid}.tmp`;
|
|
3400
3485
|
try {
|
|
3401
|
-
|
|
3486
|
+
fs11.mkdirSync(path20.dirname(paths.discoveryCacheFile), {
|
|
3402
3487
|
recursive: true,
|
|
3403
3488
|
mode: 448
|
|
3404
3489
|
});
|
|
3405
|
-
|
|
3490
|
+
fs11.writeFileSync(
|
|
3406
3491
|
temporary,
|
|
3407
3492
|
`${JSON.stringify({
|
|
3408
3493
|
schemaVersion: DISCOVERY_CACHE_SCHEMA_VERSION,
|
|
@@ -3413,10 +3498,10 @@ function createRawArtifactSync(options) {
|
|
|
3413
3498
|
`,
|
|
3414
3499
|
{ mode: 384 }
|
|
3415
3500
|
);
|
|
3416
|
-
|
|
3501
|
+
fs11.renameSync(temporary, paths.discoveryCacheFile);
|
|
3417
3502
|
} catch {
|
|
3418
3503
|
try {
|
|
3419
|
-
|
|
3504
|
+
fs11.rmSync(temporary, { force: true });
|
|
3420
3505
|
} catch {
|
|
3421
3506
|
}
|
|
3422
3507
|
}
|