@hasna/instructions 0.5.3 → 0.5.5
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/README.md +8 -3
- package/dist/cli/index.js +540 -340
- package/dist/index.js +365 -266
- package/dist/lib/app-home.d.ts +54 -0
- package/dist/lib/app-home.d.ts.map +1 -0
- package/dist/lib/app-home.test.d.ts +2 -0
- package/dist/lib/app-home.test.d.ts.map +1 -0
- package/dist/lib/raw-store-root.d.ts +12 -8
- package/dist/lib/raw-store-root.d.ts.map +1 -1
- package/dist/lib/station-profile.d.ts.map +1 -1
- package/dist/mcp/index.js +187 -73
- package/dist/mcp/server.d.ts.map +1 -1
- package/dist/server/index.js +1 -1
- package/package.json +5 -4
package/dist/cli/index.js
CHANGED
|
@@ -1290,8 +1290,8 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
1290
1290
|
args = args.slice();
|
|
1291
1291
|
let launchWithNode = false;
|
|
1292
1292
|
const sourceExt = [".js", ".ts", ".tsx", ".mjs", ".cjs"];
|
|
1293
|
-
function findFile(
|
|
1294
|
-
const localBin = path.resolve(
|
|
1293
|
+
function findFile(baseDir2, baseName) {
|
|
1294
|
+
const localBin = path.resolve(baseDir2, baseName);
|
|
1295
1295
|
if (fs.existsSync(localBin))
|
|
1296
1296
|
return localBin;
|
|
1297
1297
|
if (sourceExt.includes(path.extname(baseName)))
|
|
@@ -2160,19 +2160,122 @@ var init_retired_storage_mode = __esm(() => {
|
|
|
2160
2160
|
];
|
|
2161
2161
|
});
|
|
2162
2162
|
|
|
2163
|
+
// ../../node_modules/.bun/@hasna+paths@0.1.0/node_modules/@hasna/paths/dist/index.js
|
|
2164
|
+
import { homedir as homedir3 } from "os";
|
|
2165
|
+
import { join as join4 } from "path";
|
|
2166
|
+
function assertApp2(app) {
|
|
2167
|
+
if (typeof app !== "string" || app.length === 0) {
|
|
2168
|
+
throw new TypeError("paths: app must be a non-empty string");
|
|
2169
|
+
}
|
|
2170
|
+
if (!APP_SLUG_RE2.test(app)) {
|
|
2171
|
+
throw new TypeError(`paths: invalid app slug "${app}" \u2014 expected lowercase kebab-case ([a-z0-9]+(-[a-z0-9]+)*)`);
|
|
2172
|
+
}
|
|
2173
|
+
}
|
|
2174
|
+
function envOf2(options) {
|
|
2175
|
+
return options.env ?? process.env;
|
|
2176
|
+
}
|
|
2177
|
+
function envValue2(options, kind) {
|
|
2178
|
+
const value = envOf2(options)[KIND_ENV2[kind]];
|
|
2179
|
+
return typeof value === "string" && value.length > 0 ? value : undefined;
|
|
2180
|
+
}
|
|
2181
|
+
function isMacOS2(platform) {
|
|
2182
|
+
return platform === "darwin";
|
|
2183
|
+
}
|
|
2184
|
+
function baseDir2(kind, options) {
|
|
2185
|
+
const override = envValue2(options, kind);
|
|
2186
|
+
if (override)
|
|
2187
|
+
return override;
|
|
2188
|
+
const home = options.home ?? homedir3();
|
|
2189
|
+
const platform = options.platform ?? process.platform;
|
|
2190
|
+
if (isMacOS2(platform)) {
|
|
2191
|
+
switch (kind) {
|
|
2192
|
+
case "config":
|
|
2193
|
+
case "data":
|
|
2194
|
+
return join4(home, "Library", "Application Support", "Hasna");
|
|
2195
|
+
case "cache":
|
|
2196
|
+
return join4(home, "Library", "Caches", "Hasna");
|
|
2197
|
+
case "state":
|
|
2198
|
+
return join4(home, "Library", "Logs", "Hasna");
|
|
2199
|
+
}
|
|
2200
|
+
}
|
|
2201
|
+
switch (kind) {
|
|
2202
|
+
case "config":
|
|
2203
|
+
return join4(home, ".config", "hasna");
|
|
2204
|
+
case "data":
|
|
2205
|
+
return join4(home, ".local", "share", "hasna");
|
|
2206
|
+
case "state":
|
|
2207
|
+
return join4(home, ".local", "state", "hasna");
|
|
2208
|
+
case "cache":
|
|
2209
|
+
return join4(home, ".cache", "hasna");
|
|
2210
|
+
}
|
|
2211
|
+
}
|
|
2212
|
+
function resolvePath2(kind, options) {
|
|
2213
|
+
assertApp2(options.app);
|
|
2214
|
+
const appSegment = options.internal === true ? join4("internal", options.app) : options.app;
|
|
2215
|
+
return join4(baseDir2(kind, options), appSegment);
|
|
2216
|
+
}
|
|
2217
|
+
function configDir(options) {
|
|
2218
|
+
return resolvePath2("config", options);
|
|
2219
|
+
}
|
|
2220
|
+
var KIND_ENV2, APP_SLUG_RE2;
|
|
2221
|
+
var init_dist = __esm(() => {
|
|
2222
|
+
KIND_ENV2 = {
|
|
2223
|
+
config: "HASNA_CONFIG_HOME",
|
|
2224
|
+
data: "HASNA_DATA_HOME",
|
|
2225
|
+
state: "HASNA_STATE_HOME",
|
|
2226
|
+
cache: "HASNA_CACHE_HOME"
|
|
2227
|
+
};
|
|
2228
|
+
APP_SLUG_RE2 = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;
|
|
2229
|
+
});
|
|
2230
|
+
|
|
2231
|
+
// src/lib/app-home.ts
|
|
2232
|
+
import { existsSync as existsSync3 } from "fs";
|
|
2233
|
+
import { homedir as homedir5 } from "os";
|
|
2234
|
+
import { join as join6, resolve as resolve2 } from "path";
|
|
2235
|
+
function homeDir(env = process.env) {
|
|
2236
|
+
return env["HOME"] || env["USERPROFILE"] || homedir5();
|
|
2237
|
+
}
|
|
2238
|
+
function legacyStoreHome(env = process.env) {
|
|
2239
|
+
return resolve2(join6(homeDir(env), ".hasna", "instructions"));
|
|
2240
|
+
}
|
|
2241
|
+
function resolverStoreHome(env = process.env) {
|
|
2242
|
+
return configDir({ app: "configs", env, home: env.HOME || env.USERPROFILE || homedir5() });
|
|
2243
|
+
}
|
|
2244
|
+
function adoptResolverStoreHome(resolved, env = process.env) {
|
|
2245
|
+
const override = env.HASNA_CONFIG_HOME;
|
|
2246
|
+
if (typeof override === "string" && override.trim().length > 0)
|
|
2247
|
+
return true;
|
|
2248
|
+
return existsSync3(join6(resolved, "instructions.db"));
|
|
2249
|
+
}
|
|
2250
|
+
function exactStoreHome(env = process.env) {
|
|
2251
|
+
const v = env[HASNA_CONFIGS_HOME_ENV];
|
|
2252
|
+
return v && v.trim() ? v.trim() : undefined;
|
|
2253
|
+
}
|
|
2254
|
+
function getConfigsStoreHome(env = process.env) {
|
|
2255
|
+
const exact = exactStoreHome(env);
|
|
2256
|
+
if (exact)
|
|
2257
|
+
return resolve2(exact);
|
|
2258
|
+
const resolved = resolverStoreHome(env);
|
|
2259
|
+
return adoptResolverStoreHome(resolved, env) ? resolve2(resolved) : legacyStoreHome(env);
|
|
2260
|
+
}
|
|
2261
|
+
var HASNA_CONFIGS_HOME_ENV = "HASNA_CONFIGS_HOME";
|
|
2262
|
+
var init_app_home = __esm(() => {
|
|
2263
|
+
init_dist();
|
|
2264
|
+
});
|
|
2265
|
+
|
|
2163
2266
|
// src/lib/raw-store-root.ts
|
|
2164
|
-
import {
|
|
2165
|
-
|
|
2166
|
-
|
|
2167
|
-
return resolve(process.env[RAW_STORE_ROOT_ENV] || join2(process.env["HOME"] || homedir2(), ".hasna", "instructions"));
|
|
2267
|
+
import { resolve as resolve3 } from "path";
|
|
2268
|
+
function getRawStoreRoot(env = process.env) {
|
|
2269
|
+
return resolve3(getConfigsStoreHome(env));
|
|
2168
2270
|
}
|
|
2169
|
-
var
|
|
2170
|
-
|
|
2271
|
+
var init_raw_store_root = __esm(() => {
|
|
2272
|
+
init_app_home();
|
|
2273
|
+
});
|
|
2171
2274
|
|
|
2172
2275
|
// src/db/database.ts
|
|
2173
2276
|
import { Database } from "bun:sqlite";
|
|
2174
|
-
import { existsSync as
|
|
2175
|
-
import { join as
|
|
2277
|
+
import { existsSync as existsSync5, mkdirSync, rmSync } from "fs";
|
|
2278
|
+
import { join as join7 } from "path";
|
|
2176
2279
|
import { randomUUID as randomUUID3 } from "crypto";
|
|
2177
2280
|
function getDbPath() {
|
|
2178
2281
|
if (process.env["HASNA_INSTRUCTIONS_DB_PATH"]) {
|
|
@@ -2180,7 +2283,7 @@ function getDbPath() {
|
|
|
2180
2283
|
}
|
|
2181
2284
|
const dir = getRawStoreRoot();
|
|
2182
2285
|
mkdirSync(dir, { recursive: true });
|
|
2183
|
-
return
|
|
2286
|
+
return join7(dir, "instructions.db");
|
|
2184
2287
|
}
|
|
2185
2288
|
function uuid() {
|
|
2186
2289
|
return randomUUID3();
|
|
@@ -2221,7 +2324,7 @@ function resetLocalDatabase() {
|
|
|
2221
2324
|
if (dbPath === ":memory:")
|
|
2222
2325
|
return;
|
|
2223
2326
|
for (const p of [dbPath, `${dbPath}-wal`, `${dbPath}-shm`]) {
|
|
2224
|
-
if (
|
|
2327
|
+
if (existsSync5(p))
|
|
2225
2328
|
rmSync(p);
|
|
2226
2329
|
}
|
|
2227
2330
|
}
|
|
@@ -2658,9 +2761,9 @@ var init_template = __esm(() => {
|
|
|
2658
2761
|
});
|
|
2659
2762
|
|
|
2660
2763
|
// src/lib/machine.ts
|
|
2661
|
-
import { arch as currentArch, homedir as
|
|
2662
|
-
import { existsSync as
|
|
2663
|
-
import { join as
|
|
2764
|
+
import { arch as currentArch, homedir as homedir6, hostname as currentHostname, type as currentOsType } from "os";
|
|
2765
|
+
import { existsSync as existsSync6 } from "fs";
|
|
2766
|
+
import { join as join8 } from "path";
|
|
2664
2767
|
function normalizeOsFamily(os) {
|
|
2665
2768
|
const value = (os ?? "").trim().toLowerCase();
|
|
2666
2769
|
if (value === "darwin" || value === "macos" || value === "mac" || value === "osx")
|
|
@@ -2672,11 +2775,11 @@ function normalizeOsFamily(os) {
|
|
|
2672
2775
|
return value || "unknown";
|
|
2673
2776
|
}
|
|
2674
2777
|
function detectMachineContext(overrides = {}) {
|
|
2675
|
-
const
|
|
2778
|
+
const homeDir2 = overrides.home_dir ?? process.env["CONFIGS_HOME"] ?? process.env["HOME"] ?? homedir6();
|
|
2676
2779
|
const os = overrides.os ?? currentOsType();
|
|
2677
2780
|
const osFamily = normalizeOsFamily(os);
|
|
2678
|
-
const bunBinDir = overrides.bun_bin_dir ??
|
|
2679
|
-
const defaultBunPath = osFamily === "macos" &&
|
|
2781
|
+
const bunBinDir = overrides.bun_bin_dir ?? join8(homeDir2, ".bun", "bin");
|
|
2782
|
+
const defaultBunPath = osFamily === "macos" && existsSync6(BREW_BUN_PATH) ? BREW_BUN_PATH : join8(bunBinDir, "bun");
|
|
2680
2783
|
return {
|
|
2681
2784
|
id: "current-machine",
|
|
2682
2785
|
hostname: overrides.hostname ?? currentHostname(),
|
|
@@ -2685,11 +2788,11 @@ function detectMachineContext(overrides = {}) {
|
|
|
2685
2788
|
last_applied_at: null,
|
|
2686
2789
|
created_at: "",
|
|
2687
2790
|
os_family: osFamily,
|
|
2688
|
-
home_dir:
|
|
2689
|
-
workspace_root: overrides.workspace_root ??
|
|
2791
|
+
home_dir: homeDir2,
|
|
2792
|
+
workspace_root: overrides.workspace_root ?? join8(homeDir2, osFamily === "macos" ? "Workspace" : "workspace"),
|
|
2690
2793
|
bun_bin_dir: bunBinDir,
|
|
2691
2794
|
bun_path: overrides.bun_path ?? defaultBunPath,
|
|
2692
|
-
path_prefix: overrides.path_prefix ?? (osFamily === "macos" ? `${
|
|
2795
|
+
path_prefix: overrides.path_prefix ?? (osFamily === "macos" ? `${join8("/opt", "homebrew", "bin")}:${bunBinDir}` : bunBinDir)
|
|
2693
2796
|
};
|
|
2694
2797
|
}
|
|
2695
2798
|
function machineContextToVariables(machine) {
|
|
@@ -7324,7 +7427,7 @@ import { dlopen, FFIType } from "bun:ffi";
|
|
|
7324
7427
|
import {
|
|
7325
7428
|
closeSync,
|
|
7326
7429
|
constants,
|
|
7327
|
-
existsSync as
|
|
7430
|
+
existsSync as existsSync7,
|
|
7328
7431
|
fstatSync,
|
|
7329
7432
|
fsyncSync,
|
|
7330
7433
|
lstatSync,
|
|
@@ -7337,7 +7440,7 @@ import {
|
|
|
7337
7440
|
statSync,
|
|
7338
7441
|
writeFileSync
|
|
7339
7442
|
} from "fs";
|
|
7340
|
-
import { basename, dirname, isAbsolute, join as
|
|
7443
|
+
import { basename, dirname, isAbsolute, join as join9, parse, relative, resolve as resolve4 } from "path";
|
|
7341
7444
|
function managedObservationMaxBytes(relativePath) {
|
|
7342
7445
|
return SESSION_MANAGED_OUTPUT_PATHS.includes(relativePath) ? SESSION_MANAGED_OUTPUT_MAX_BYTES : FOREIGN_INPUT_MAX_BYTES;
|
|
7343
7446
|
}
|
|
@@ -7417,7 +7520,7 @@ function planProjectContext(input) {
|
|
|
7417
7520
|
const inlineMarkerOverhead = nativeImports ? 0 : Buffer.byteLength(buildManagedBlock(bundle, "", `
|
|
7418
7521
|
`), "utf8");
|
|
7419
7522
|
const generated = buildCanonicalFragment(bundle, status, ageSeconds, PROJECT_CONTEXT_MAX_RENDERED_BYTES - Math.max(320, inlineMarkerOverhead), PROJECT_CONTEXT_MAX_APPROX_TOKENS - Math.max(80, Math.ceil(inlineMarkerOverhead / 4)));
|
|
7420
|
-
const previousTargetContent =
|
|
7523
|
+
const previousTargetContent = existsSync7(paths.target) ? readUtf8RegularFile(paths.target, workspaceRoot, managedObservationMaxBytes(relativePosix(workspaceRoot, paths.target))) : null;
|
|
7421
7524
|
const markerParse = parseManagedBlock(previousTargetContent ?? "", input.force === true);
|
|
7422
7525
|
if (markerParse.block && markerParse.block.id !== bundle.project.id) {
|
|
7423
7526
|
throw new ProjectContextError("MANAGED_BLOCK_CONFLICT", "managed block belongs to a different project");
|
|
@@ -7468,7 +7571,7 @@ function composeProjectContextSessionRender(input) {
|
|
|
7468
7571
|
return null;
|
|
7469
7572
|
const { runtime, workspace_root: workspaceRoot, observed_hashes: observedHashes } = guard;
|
|
7470
7573
|
const paths = runtimePaths(workspaceRoot, runtime);
|
|
7471
|
-
if (!
|
|
7574
|
+
if (!existsSync7(paths.manifest))
|
|
7472
7575
|
return null;
|
|
7473
7576
|
assertCodewithTargetIsConsumed(workspaceRoot, runtime);
|
|
7474
7577
|
const manifest = readProjectContextManifest(paths.manifest, workspaceRoot);
|
|
@@ -7497,7 +7600,7 @@ function composeProjectContextSessionRender(input) {
|
|
|
7497
7600
|
}
|
|
7498
7601
|
const fragment = readUtf8RegularFile(paths.fragment, workspaceRoot, PROJECT_CONTEXT_MAX_RENDERED_BYTES);
|
|
7499
7602
|
scanGeneratedContent(fragment);
|
|
7500
|
-
if (!
|
|
7603
|
+
if (!existsSync7(paths.target)) {
|
|
7501
7604
|
throw new ProjectContextError("MANAGED_BLOCK_CONFLICT", "project-context provider target is missing while durable context is active");
|
|
7502
7605
|
}
|
|
7503
7606
|
const currentTarget = readUtf8RegularFile(paths.target, workspaceRoot, managedObservationMaxBytes(relativePosix(workspaceRoot, paths.target)));
|
|
@@ -7508,7 +7611,7 @@ function composeProjectContextSessionRender(input) {
|
|
|
7508
7611
|
if (currentMarkers.block.id !== cache.project_id || currentMarkers.block.revision !== cache.revision || currentMarkers.block.hash !== cache.hash) {
|
|
7509
7612
|
throw new ProjectContextError("MANAGED_BLOCK_CONFLICT", "project-context provider markers differ from the durable cache");
|
|
7510
7613
|
}
|
|
7511
|
-
const plannedIndexes = input.files.filter((file) => file.role === "index" &&
|
|
7614
|
+
const plannedIndexes = input.files.filter((file) => file.role === "index" && resolve4(file.path) === paths.target);
|
|
7512
7615
|
if (plannedIndexes.length !== 1) {
|
|
7513
7616
|
throw new ProjectContextError("PROJECT_CONTEXT_MANIFEST_INVALID", "session renderer does not own the selected project-context provider target");
|
|
7514
7617
|
}
|
|
@@ -7566,7 +7669,7 @@ function withProjectContextSessionGuard(guard, action, options = {}) {
|
|
|
7566
7669
|
verify();
|
|
7567
7670
|
return action(null);
|
|
7568
7671
|
}
|
|
7569
|
-
const lockPath =
|
|
7672
|
+
const lockPath = resolve4(validated.workspace_root, ...PROJECT_CONTEXT_LOCK_PATH.split("/"));
|
|
7570
7673
|
const lock = acquireWorkspaceLock(validated.workspace_root, lockPath);
|
|
7571
7674
|
try {
|
|
7572
7675
|
verify();
|
|
@@ -7592,7 +7695,7 @@ function validateProjectContextSessionGuard(guard) {
|
|
|
7592
7695
|
if (!isRecord(observed) || typeof observed.path !== "string") {
|
|
7593
7696
|
throw new ProjectContextError("PROJECT_CONTEXT_SESSION_STALE", "session project-context guard contains malformed hash metadata");
|
|
7594
7697
|
}
|
|
7595
|
-
const path =
|
|
7698
|
+
const path = resolve4(observed.path);
|
|
7596
7699
|
if (!allowedPaths.has(path) || observedPaths.has(path)) {
|
|
7597
7700
|
throw new ProjectContextError("PROJECT_CONTEXT_SESSION_STALE", "session project-context guard contains an unexpected or duplicate path");
|
|
7598
7701
|
}
|
|
@@ -7614,7 +7717,7 @@ function validateProjectContextSessionGuard(guard) {
|
|
|
7614
7717
|
function applyProjectContext(options) {
|
|
7615
7718
|
const workspaceRoot = assertSafeWorkspaceRoot(options.workspace_root);
|
|
7616
7719
|
const now3 = options.now ?? new Date;
|
|
7617
|
-
const lockPath =
|
|
7720
|
+
const lockPath = resolve4(workspaceRoot, ...PROJECT_CONTEXT_LOCK_PATH.split("/"));
|
|
7618
7721
|
const lock = options.dry_run ? null : acquireWorkspaceLock(workspaceRoot, lockPath, options.test_hooks?.after_lock_open, options.test_hooks?.before_stale_lock_remove, options.test_hooks?.process_start_identity);
|
|
7619
7722
|
try {
|
|
7620
7723
|
const resolved = resolveBundleForApply(options, workspaceRoot, now3);
|
|
@@ -7761,7 +7864,7 @@ function resolveBundleForApply(options, workspaceRoot, now3) {
|
|
|
7761
7864
|
if (!options.expected_project_id) {
|
|
7762
7865
|
throw new ProjectContextError("PROJECT_CONTEXT_CACHE_ID_REQUIRED", "expected_project_id is required for stale-cache fallback");
|
|
7763
7866
|
}
|
|
7764
|
-
const cachePath =
|
|
7867
|
+
const cachePath = resolve4(workspaceRoot, ...PROJECT_CONTEXT_CACHE_PATH.split("/"));
|
|
7765
7868
|
const cache = readProjectContextCache(cachePath, workspaceRoot);
|
|
7766
7869
|
if (!cache)
|
|
7767
7870
|
throw new ProjectContextError("PROJECT_CONTEXT_CACHE_MISSING", "no last-known-good project context cache exists");
|
|
@@ -7963,7 +8066,7 @@ function findLegacyCodewithWorkspaceSection(workspaceRoot, runtime, content, bun
|
|
|
7963
8066
|
if (runtime !== "codewith" || !content)
|
|
7964
8067
|
return null;
|
|
7965
8068
|
const sessionManifestPath = runtimePaths(workspaceRoot, runtime).sessionManifest;
|
|
7966
|
-
if (!
|
|
8069
|
+
if (!existsSync7(sessionManifestPath))
|
|
7967
8070
|
return null;
|
|
7968
8071
|
const manifest = readSessionManifestRecord(sessionManifestPath, workspaceRoot);
|
|
7969
8072
|
if (!manifest || manifest["schema"] !== SESSION_RENDER_SCHEMA) {
|
|
@@ -8014,7 +8117,7 @@ function assertRevisionOrdering(plan, force) {
|
|
|
8014
8117
|
const manifest = readProjectContextManifest(plan.manifest_path, plan.workspace_root);
|
|
8015
8118
|
if (manifest) {
|
|
8016
8119
|
const manifestHashHasRecoveryProof = manifest.projectContext.hash === plan.bundle.hash || metadataSnapshotMatchesManifest(plan, manifest);
|
|
8017
|
-
const canonicalStateAlreadyInstalled = cache !== null && canonicalCacheHash === plan.bundle.hash && cache.project_id === plan.bundle.project.id && cache.revision === plan.bundle.revision && plan.marker !== null && plan.marker.id === plan.bundle.project.id && plan.marker.revision === plan.bundle.revision && plan.marker.hash === plan.bundle.hash &&
|
|
8120
|
+
const canonicalStateAlreadyInstalled = cache !== null && canonicalCacheHash === plan.bundle.hash && cache.project_id === plan.bundle.project.id && cache.revision === plan.bundle.revision && plan.marker !== null && plan.marker.id === plan.bundle.project.id && plan.marker.revision === plan.bundle.revision && plan.marker.hash === plan.bundle.hash && existsSync7(plan.fragment_path) && fragmentMatchesBundle(plan.fragment_path, plan.bundle, plan.workspace_root) && manifestHashHasRecoveryProof;
|
|
8018
8121
|
observations.push({
|
|
8019
8122
|
source: "manifest",
|
|
8020
8123
|
id: manifest.projectContext.projectId,
|
|
@@ -8022,7 +8125,7 @@ function assertRevisionOrdering(plan, force) {
|
|
|
8022
8125
|
hash: canonicalStateAlreadyInstalled && manifest.projectContext.projectId === plan.bundle.project.id && manifest.projectContext.revision === plan.bundle.revision ? plan.bundle.hash : normalizePersistedHash(manifest.projectContext.revision, manifest.projectContext.hash)
|
|
8023
8126
|
});
|
|
8024
8127
|
const fragmentEntry = manifest.files.find((file) => file.relativePath === PROJECT_CONTEXT_FRAGMENT_PATH);
|
|
8025
|
-
if (fragmentEntry &&
|
|
8128
|
+
if (fragmentEntry && existsSync7(plan.fragment_path)) {
|
|
8026
8129
|
const actual = currentFileHash(plan.fragment_path, plan.workspace_root);
|
|
8027
8130
|
if (actual !== fragmentEntry.sha256 && !fragmentMatchesBundle(plan.fragment_path, plan.bundle, plan.workspace_root) && !force) {
|
|
8028
8131
|
throw new ProjectContextError("MANAGED_BLOCK_CONFLICT", "canonical project-context fragment changed outside Instructions");
|
|
@@ -8117,9 +8220,9 @@ function buildManifest(plan, now3) {
|
|
|
8117
8220
|
function buildSessionCompatibilityManifest(plan, now3) {
|
|
8118
8221
|
const paths = runtimePaths(plan.workspace_root, plan.runtime);
|
|
8119
8222
|
const tool = manifestTool(plan.runtime);
|
|
8120
|
-
const targetHome = plan.runtime === "codewith" ?
|
|
8223
|
+
const targetHome = plan.runtime === "codewith" ? resolve4(plan.workspace_root, ".codewith") : plan.workspace_root;
|
|
8121
8224
|
const targetRelativePath = sessionTargetRelativePath(plan.runtime);
|
|
8122
|
-
const existing =
|
|
8225
|
+
const existing = existsSync7(paths.sessionManifest) ? readSessionManifestRecord(paths.sessionManifest, plan.workspace_root) : {
|
|
8123
8226
|
schema: SESSION_RENDER_SCHEMA,
|
|
8124
8227
|
tool,
|
|
8125
8228
|
adapterMode: plan.native_imports ? "native-imports" : "flattened-markdown",
|
|
@@ -8139,7 +8242,7 @@ function buildSessionCompatibilityManifest(plan, now3) {
|
|
|
8139
8242
|
throw new ProjectContextError("PROJECT_CONTEXT_MANIFEST_INVALID", "provider session manifest is malformed or incompatible");
|
|
8140
8243
|
}
|
|
8141
8244
|
const existingTargetHome = safeLegacyMetadataString(existing["targetHome"], null);
|
|
8142
|
-
if (existingTargetHome !== null &&
|
|
8245
|
+
if (existingTargetHome !== null && resolve4(existingTargetHome) !== targetHome) {
|
|
8143
8246
|
throw new ProjectContextError("PROJECT_CONTEXT_MANIFEST_INVALID", "provider session manifest targets a different workspace");
|
|
8144
8247
|
}
|
|
8145
8248
|
const sources = sanitizeLegacySources(existing["sources"]).filter((source) => source["id"] !== "project-context-bundle");
|
|
@@ -8425,9 +8528,9 @@ function writeMetadataSnapshot(plan, now3) {
|
|
|
8425
8528
|
const previous = readProjectContextManifest(plan.manifest_path, plan.workspace_root);
|
|
8426
8529
|
if (!previous || previous.projectContext.revision === plan.bundle.revision && previous.projectContext.hash === plan.bundle.hash)
|
|
8427
8530
|
return null;
|
|
8428
|
-
const snapshotDir =
|
|
8531
|
+
const snapshotDir = resolve4(plan.workspace_root, ...PROJECT_CONTEXT_SNAPSHOT_DIR.split("/"));
|
|
8429
8532
|
ensureSafeDirectory(snapshotDir, plan.workspace_root, 448);
|
|
8430
|
-
const snapshotPath =
|
|
8533
|
+
const snapshotPath = resolve4(snapshotDir, `${safeFilename(previous.projectContext.revision)}-${previous.projectContext.hash.slice(-12)}.json`);
|
|
8431
8534
|
const snapshot = {
|
|
8432
8535
|
schema: "hasna.configs.session-render-snapshot/v1",
|
|
8433
8536
|
kind: "project-context-metadata",
|
|
@@ -8443,9 +8546,9 @@ function writeMetadataSnapshot(plan, now3) {
|
|
|
8443
8546
|
return snapshotPath;
|
|
8444
8547
|
}
|
|
8445
8548
|
function metadataSnapshotMatchesManifest(plan, manifest) {
|
|
8446
|
-
const snapshotDir =
|
|
8447
|
-
const snapshotPath =
|
|
8448
|
-
if (!
|
|
8549
|
+
const snapshotDir = resolve4(plan.workspace_root, ...PROJECT_CONTEXT_SNAPSHOT_DIR.split("/"));
|
|
8550
|
+
const snapshotPath = resolve4(snapshotDir, `${safeFilename(manifest.projectContext.revision)}-${manifest.projectContext.hash.slice(-12)}.json`);
|
|
8551
|
+
if (!existsSync7(snapshotPath))
|
|
8449
8552
|
return false;
|
|
8450
8553
|
const record = readJsonRecord(snapshotPath, plan.workspace_root);
|
|
8451
8554
|
const result = projectContextMetadataSnapshotSchema.safeParse(record);
|
|
@@ -8493,10 +8596,10 @@ function writeProjectContextRollbackSnapshot(plan, now3, outputs) {
|
|
|
8493
8596
|
sha256: nextHash
|
|
8494
8597
|
};
|
|
8495
8598
|
});
|
|
8496
|
-
const snapshotDir =
|
|
8599
|
+
const snapshotDir = resolve4(plan.workspace_root, ...SESSION_RENDER_SNAPSHOT_RELATIVE_DIR.split("/"));
|
|
8497
8600
|
ensureSafeDirectory(snapshotDir, plan.workspace_root, 448);
|
|
8498
8601
|
const timestamp = now3.toISOString().replace(/[:.]/g, "-");
|
|
8499
|
-
const snapshotPath =
|
|
8602
|
+
const snapshotPath = resolve4(snapshotDir, `${timestamp}-${randomUUID5()}.json`);
|
|
8500
8603
|
const snapshot = {
|
|
8501
8604
|
schema: "hasna.configs.session-render-snapshot/v2",
|
|
8502
8605
|
createdAt: now3.toISOString(),
|
|
@@ -8514,7 +8617,7 @@ function writeProjectContextRollbackSnapshot(plan, now3, outputs) {
|
|
|
8514
8617
|
return snapshotPath;
|
|
8515
8618
|
}
|
|
8516
8619
|
function readProjectContextManifest(path, workspaceRoot) {
|
|
8517
|
-
if (!
|
|
8620
|
+
if (!existsSync7(path))
|
|
8518
8621
|
return null;
|
|
8519
8622
|
const record = readJsonRecord(path, workspaceRoot);
|
|
8520
8623
|
const result = storedManifestObservationSchema.safeParse(record);
|
|
@@ -8529,7 +8632,7 @@ function readProjectContextManifest(path, workspaceRoot) {
|
|
|
8529
8632
|
};
|
|
8530
8633
|
}
|
|
8531
8634
|
function readProjectContextCache(path, workspaceRoot) {
|
|
8532
|
-
if (!
|
|
8635
|
+
if (!existsSync7(path))
|
|
8533
8636
|
return null;
|
|
8534
8637
|
const record = readJsonRecord(path, workspaceRoot);
|
|
8535
8638
|
const result = projectContextCacheSchema.safeParse(record);
|
|
@@ -8561,7 +8664,7 @@ function readSessionManifestRecord(path, workspaceRoot) {
|
|
|
8561
8664
|
}
|
|
8562
8665
|
}
|
|
8563
8666
|
function atomicWriteFile(path, content, workspaceRoot, defaultMode, expectedHash, afterExchange, atomicExchangeUnavailable = false, beforeInstall, portableCreateOnly = false, maxObservedBytes, allowPortableReplacement = false) {
|
|
8564
|
-
const dir =
|
|
8667
|
+
const dir = resolve4(path, "..");
|
|
8565
8668
|
ensureSafeDirectory(dir, workspaceRoot, 448);
|
|
8566
8669
|
assertNoSymlinkSegments(workspaceRoot, path);
|
|
8567
8670
|
const anchoredOps = portableCreateOnly ? null : resolveAnchoredFsOps();
|
|
@@ -8578,7 +8681,7 @@ function atomicWriteFile(path, content, workspaceRoot, defaultMode, expectedHash
|
|
|
8578
8681
|
const previous = anchoredFileObservation(directory, targetName);
|
|
8579
8682
|
const previousMode = previous?.mode ?? defaultMode;
|
|
8580
8683
|
const tempName = `.project-context-${randomUUID5()}.tmp`;
|
|
8581
|
-
const tempPath =
|
|
8684
|
+
const tempPath = join9(dir, tempName);
|
|
8582
8685
|
let fd = null;
|
|
8583
8686
|
let preserveTemp = false;
|
|
8584
8687
|
let directoryChanged = false;
|
|
@@ -8709,7 +8812,7 @@ function atomicWritePortable(path, content, workspaceRoot, defaultMode, expected
|
|
|
8709
8812
|
}
|
|
8710
8813
|
const dir = dirname(path);
|
|
8711
8814
|
const directoryIdentity = captureManagedDirectoryIdentity(dir, workspaceRoot);
|
|
8712
|
-
const tempPath =
|
|
8815
|
+
const tempPath = join9(dir, `.project-context-${randomUUID5()}.tmp`);
|
|
8713
8816
|
let fd = null;
|
|
8714
8817
|
let tempIdentity = null;
|
|
8715
8818
|
try {
|
|
@@ -8766,7 +8869,7 @@ function atomicWritePortableReplacement(path, content, workspaceRoot, expectedHa
|
|
|
8766
8869
|
}
|
|
8767
8870
|
const dir = dirname(path);
|
|
8768
8871
|
const directoryIdentity = captureManagedDirectoryIdentity(dir, workspaceRoot);
|
|
8769
|
-
const tempPath =
|
|
8872
|
+
const tempPath = join9(dir, `.project-context-${randomUUID5()}.tmp`);
|
|
8770
8873
|
const desiredHash = sha2562(content);
|
|
8771
8874
|
let fd = null;
|
|
8772
8875
|
let tempIdentity = null;
|
|
@@ -8823,7 +8926,7 @@ function portablePreparedHash(tempPath, path, workspaceRoot, maxObservedBytes, s
|
|
|
8823
8926
|
function portableFileHash(path, workspaceRoot, maxObservedBytes) {
|
|
8824
8927
|
if (maxObservedBytes === undefined)
|
|
8825
8928
|
return currentFileHash(path, workspaceRoot);
|
|
8826
|
-
if (!
|
|
8929
|
+
if (!existsSync7(path))
|
|
8827
8930
|
return null;
|
|
8828
8931
|
assertNoSymlinkSegments(workspaceRoot, path);
|
|
8829
8932
|
const stat = lstatSync(path);
|
|
@@ -8835,11 +8938,11 @@ function portableFileHash(path, workspaceRoot, maxObservedBytes) {
|
|
|
8835
8938
|
return createHash2("sha256").update(readFileSync(path)).digest("hex");
|
|
8836
8939
|
}
|
|
8837
8940
|
function writeProjectContextCoordinatedFile(input) {
|
|
8838
|
-
atomicWriteFile(
|
|
8941
|
+
atomicWriteFile(resolve4(input.path), input.content, assertSafeWorkspaceRoot(input.workspace_root), input.default_mode ?? 420, input.expected_hash, undefined, false, input.test_hooks?.before_install, input.force_portable_file_ops ?? false, input.max_observed_bytes, input.allow_portable_replacement ?? false);
|
|
8839
8942
|
}
|
|
8840
8943
|
function removeProjectContextCoordinatedFile(input) {
|
|
8841
8944
|
const workspaceRoot = assertSafeWorkspaceRoot(input.workspace_root);
|
|
8842
|
-
const path =
|
|
8945
|
+
const path = resolve4(input.path);
|
|
8843
8946
|
assertNoSymlinkSegments(workspaceRoot, path);
|
|
8844
8947
|
const dir = dirname(path);
|
|
8845
8948
|
const anchoredOps = input.force_portable_file_ops ? null : resolveAnchoredFsOps();
|
|
@@ -8865,7 +8968,7 @@ function removeProjectContextCoordinatedFile(input) {
|
|
|
8865
8968
|
throw new ProjectContextHashRace(`managed path changed during deletion: ${relativePosix(workspaceRoot, path)}`);
|
|
8866
8969
|
}
|
|
8867
8970
|
displaced = true;
|
|
8868
|
-
input.test_hooks?.after_displace?.(
|
|
8971
|
+
input.test_hooks?.after_displace?.(join9(dir, displacedName));
|
|
8869
8972
|
const moved = anchoredFileObservation(directory, displacedName);
|
|
8870
8973
|
if (!moved || moved.dev !== observed.dev || moved.ino !== observed.ino || moved.hash !== input.expected_hash || anchoredFileObservation(directory, targetName) !== null) {
|
|
8871
8974
|
throw new ProjectContextHashRace(`managed path changed during deletion validation: ${relativePosix(workspaceRoot, path)}`);
|
|
@@ -8911,7 +9014,7 @@ function removePortableCoordinatedFile(path, workspaceRoot, expectedHash, maxObs
|
|
|
8911
9014
|
}
|
|
8912
9015
|
const dir = dirname(path);
|
|
8913
9016
|
const directoryIdentity = captureManagedDirectoryIdentity(dir, workspaceRoot);
|
|
8914
|
-
const displacedPath =
|
|
9017
|
+
const displacedPath = join9(dir, `.project-context-delete-${randomUUID5()}.tmp`);
|
|
8915
9018
|
let displaced = false;
|
|
8916
9019
|
try {
|
|
8917
9020
|
assertManagedDirectoryStable(dir, workspaceRoot, directoryIdentity);
|
|
@@ -8922,7 +9025,7 @@ function removePortableCoordinatedFile(path, workspaceRoot, expectedHash, maxObs
|
|
|
8922
9025
|
displaced = true;
|
|
8923
9026
|
afterDisplace?.(displacedPath);
|
|
8924
9027
|
const moved = lstatSync(displacedPath);
|
|
8925
|
-
if (moved.isSymbolicLink() || !moved.isFile() || moved.dev !== observed.dev || moved.ino !== observed.ino || portableFileHash(displacedPath, workspaceRoot, maxObservedBytes) !== expectedHash ||
|
|
9028
|
+
if (moved.isSymbolicLink() || !moved.isFile() || moved.dev !== observed.dev || moved.ino !== observed.ino || portableFileHash(displacedPath, workspaceRoot, maxObservedBytes) !== expectedHash || existsSync7(path)) {
|
|
8926
9029
|
throw new ProjectContextHashRace(`managed path changed during portable deletion: ${relativePosix(workspaceRoot, path)}`);
|
|
8927
9030
|
}
|
|
8928
9031
|
rmSync2(displacedPath);
|
|
@@ -8982,7 +9085,7 @@ function anchoredOpenExclusive(directory, name, mode) {
|
|
|
8982
9085
|
const requestedMode = mode & 4095;
|
|
8983
9086
|
let fd;
|
|
8984
9087
|
try {
|
|
8985
|
-
fd = openSync(
|
|
9088
|
+
fd = openSync(join9(directory.path, name), constants.O_WRONLY | constants.O_CREAT | constants.O_EXCL | constants.O_NOFOLLOW, requestedMode);
|
|
8986
9089
|
} catch {
|
|
8987
9090
|
throw new ProjectContextHashRace(`could not create prepared managed file in ${relativePosix(directory.workspaceRoot, directory.path)}`);
|
|
8988
9091
|
}
|
|
@@ -9025,7 +9128,7 @@ function anchoredFileObservation(directory, name) {
|
|
|
9025
9128
|
const stat = fstatSync(fd);
|
|
9026
9129
|
if (!stat.isFile())
|
|
9027
9130
|
throw new ProjectContextHashRace("managed output is not a regular file");
|
|
9028
|
-
const relativePath = relativePosix(directory.workspaceRoot,
|
|
9131
|
+
const relativePath = relativePosix(directory.workspaceRoot, join9(directory.path, name));
|
|
9029
9132
|
const maxBytes = directory.maxObservedBytes === undefined ? managedObservationMaxBytes(relativePath) : directory.maxObservedBytes;
|
|
9030
9133
|
if (maxBytes !== null && stat.size > maxBytes) {
|
|
9031
9134
|
throw new ProjectContextHashRace(`managed output exceeds the safe read limit: ${relativePath}`);
|
|
@@ -9051,7 +9154,7 @@ function anchoredPreparedObservation(directory, name, path, stage) {
|
|
|
9051
9154
|
return observed;
|
|
9052
9155
|
}
|
|
9053
9156
|
function captureManagedDirectoryIdentity(path, workspaceRoot) {
|
|
9054
|
-
assertNoSymlinkSegments(workspaceRoot,
|
|
9157
|
+
assertNoSymlinkSegments(workspaceRoot, join9(path, ".project-context-directory-guard"));
|
|
9055
9158
|
let stat;
|
|
9056
9159
|
try {
|
|
9057
9160
|
stat = lstatSync(path);
|
|
@@ -9064,7 +9167,7 @@ function captureManagedDirectoryIdentity(path, workspaceRoot) {
|
|
|
9064
9167
|
return { dev: stat.dev, ino: stat.ino };
|
|
9065
9168
|
}
|
|
9066
9169
|
function assertManagedDirectoryStable(path, workspaceRoot, expected) {
|
|
9067
|
-
assertNoSymlinkSegments(workspaceRoot,
|
|
9170
|
+
assertNoSymlinkSegments(workspaceRoot, join9(path, ".project-context-directory-guard"));
|
|
9068
9171
|
let current;
|
|
9069
9172
|
try {
|
|
9070
9173
|
current = lstatSync(path);
|
|
@@ -9197,10 +9300,10 @@ function resolveAnchoredFsOps() {
|
|
|
9197
9300
|
return null;
|
|
9198
9301
|
}
|
|
9199
9302
|
function acquireWorkspaceLock(workspaceRoot, lockPath, afterOpen, beforeStaleRemove, processStartIdentityLookup = processStartIdentity) {
|
|
9200
|
-
const lockDirectory =
|
|
9303
|
+
const lockDirectory = resolve4(lockPath, "..");
|
|
9201
9304
|
ensureSafeDirectory(lockDirectory, workspaceRoot, 448);
|
|
9202
9305
|
assertNoSymlinkSegments(workspaceRoot, lockPath);
|
|
9203
|
-
const tempPath =
|
|
9306
|
+
const tempPath = join9(lockDirectory, `.project-context-lock-${randomUUID5()}.tmp`);
|
|
9204
9307
|
let fd = null;
|
|
9205
9308
|
let openedIdentity = null;
|
|
9206
9309
|
let openedContentHash = null;
|
|
@@ -9234,7 +9337,7 @@ function acquireWorkspaceLock(workspaceRoot, lockPath, afterOpen, beforeStaleRem
|
|
|
9234
9337
|
linked = true;
|
|
9235
9338
|
}
|
|
9236
9339
|
fsyncDirectory(lockDirectory);
|
|
9237
|
-
if (
|
|
9340
|
+
if (existsSync7(tempPath)) {
|
|
9238
9341
|
rmSync2(tempPath);
|
|
9239
9342
|
fsyncDirectory(lockDirectory);
|
|
9240
9343
|
}
|
|
@@ -9249,7 +9352,7 @@ function acquireWorkspaceLock(workspaceRoot, lockPath, afterOpen, beforeStaleRem
|
|
|
9249
9352
|
if (linked && openedIdentity && openedContentHash) {
|
|
9250
9353
|
removeOwnedLockByInode(lockPath, openedIdentity, openedContentHash);
|
|
9251
9354
|
}
|
|
9252
|
-
if (!preserveTemp &&
|
|
9355
|
+
if (!preserveTemp && existsSync7(tempPath)) {
|
|
9253
9356
|
try {
|
|
9254
9357
|
rmSync2(tempPath);
|
|
9255
9358
|
} catch {}
|
|
@@ -9264,7 +9367,7 @@ function acquireWorkspaceLock(workspaceRoot, lockPath, afterOpen, beforeStaleRem
|
|
|
9264
9367
|
}
|
|
9265
9368
|
function removeOwnedLockByInode(lockPath, identity, expectedHash) {
|
|
9266
9369
|
try {
|
|
9267
|
-
if (!
|
|
9370
|
+
if (!existsSync7(lockPath))
|
|
9268
9371
|
return;
|
|
9269
9372
|
const current = lstatSync(lockPath);
|
|
9270
9373
|
if (current.isSymbolicLink() || current.dev !== identity.dev || current.ino !== identity.ino)
|
|
@@ -9272,7 +9375,7 @@ function removeOwnedLockByInode(lockPath, identity, expectedHash) {
|
|
|
9272
9375
|
if (expectedHash !== undefined && sha2562(readFileSync(lockPath, "utf8")) !== expectedHash)
|
|
9273
9376
|
return;
|
|
9274
9377
|
rmSync2(lockPath);
|
|
9275
|
-
fsyncDirectory(
|
|
9378
|
+
fsyncDirectory(resolve4(lockPath, ".."));
|
|
9276
9379
|
} catch {}
|
|
9277
9380
|
}
|
|
9278
9381
|
function observeStaleWorkspaceLock(lockPath, workspaceRoot, processStartIdentityLookup = processStartIdentity) {
|
|
@@ -9343,7 +9446,7 @@ function tryTakeoverStaleWorkspaceLock(candidatePath, lockPath, workspaceRoot, c
|
|
|
9343
9446
|
const candidateInstalled = !current.isSymbolicLink() && current.dev === candidateIdentity.dev && current.ino === candidateIdentity.ino && currentFileHash(lockPath, workspaceRoot) === candidateHash;
|
|
9344
9447
|
const staleDisplaced = !displaced.isSymbolicLink() && displaced.dev === stale.identity.dev && displaced.ino === stale.identity.ino && currentFileHash(candidatePath, workspaceRoot) === stale.contentHash;
|
|
9345
9448
|
if (!candidateInstalled || !staleDisplaced) {
|
|
9346
|
-
if (candidateInstalled &&
|
|
9449
|
+
if (candidateInstalled && existsSync7(candidatePath)) {
|
|
9347
9450
|
atomicExchangePaths(candidatePath, lockPath);
|
|
9348
9451
|
exchanged = false;
|
|
9349
9452
|
return false;
|
|
@@ -9351,13 +9454,13 @@ function tryTakeoverStaleWorkspaceLock(candidatePath, lockPath, workspaceRoot, c
|
|
|
9351
9454
|
throw new ProjectContextError("PROJECT_CONTEXT_LOCK_LOST", "workspace lock changed during stale-lock takeover and could not be restored safely");
|
|
9352
9455
|
}
|
|
9353
9456
|
rmSync2(candidatePath);
|
|
9354
|
-
fsyncDirectory(
|
|
9457
|
+
fsyncDirectory(resolve4(lockPath, ".."));
|
|
9355
9458
|
exchanged = false;
|
|
9356
9459
|
return true;
|
|
9357
9460
|
} catch (error) {
|
|
9358
9461
|
if (exchanged) {
|
|
9359
9462
|
try {
|
|
9360
|
-
if (currentFileHash(lockPath, workspaceRoot) === candidateHash &&
|
|
9463
|
+
if (currentFileHash(lockPath, workspaceRoot) === candidateHash && existsSync7(candidatePath)) {
|
|
9361
9464
|
atomicExchangePaths(candidatePath, lockPath);
|
|
9362
9465
|
exchanged = false;
|
|
9363
9466
|
}
|
|
@@ -9370,7 +9473,7 @@ function tryTakeoverStaleWorkspaceLock(candidatePath, lockPath, workspaceRoot, c
|
|
|
9370
9473
|
}
|
|
9371
9474
|
}
|
|
9372
9475
|
function assertWorkspaceLockHeld(lockPath, lock, workspaceRoot) {
|
|
9373
|
-
if (!
|
|
9476
|
+
if (!existsSync7(lockPath)) {
|
|
9374
9477
|
throw new ProjectContextError("PROJECT_CONTEXT_LOCK_LOST", "workspace project-context lock changed during render");
|
|
9375
9478
|
}
|
|
9376
9479
|
const current = lstatSync(lockPath);
|
|
@@ -9430,8 +9533,8 @@ function releaseWorkspaceLock(lockPath, lock, workspaceRoot) {
|
|
|
9430
9533
|
}
|
|
9431
9534
|
return;
|
|
9432
9535
|
}
|
|
9433
|
-
const lockDirectory =
|
|
9434
|
-
const releasePath =
|
|
9536
|
+
const lockDirectory = resolve4(lockPath, "..");
|
|
9537
|
+
const releasePath = join9(lockDirectory, `.project-context-release-${randomUUID5()}.tmp`);
|
|
9435
9538
|
let releaseFd = null;
|
|
9436
9539
|
let releaseIdentity = null;
|
|
9437
9540
|
let releaseHash = null;
|
|
@@ -9460,7 +9563,7 @@ function releaseWorkspaceLock(lockPath, lock, workspaceRoot) {
|
|
|
9460
9563
|
const releaseInstalled = !installed.isSymbolicLink() && installed.dev === releaseIdentity.dev && installed.ino === releaseIdentity.ino && currentFileHash(lockPath, workspaceRoot) === releaseHash;
|
|
9461
9564
|
const ownedDisplaced = !displaced.isSymbolicLink() && displaced.dev === lock.identity.dev && displaced.ino === lock.identity.ino && currentFileHash(releasePath, workspaceRoot) === lock.contentHash;
|
|
9462
9565
|
if (!releaseInstalled || !ownedDisplaced) {
|
|
9463
|
-
if (releaseInstalled &&
|
|
9566
|
+
if (releaseInstalled && existsSync7(releasePath)) {
|
|
9464
9567
|
atomicExchangePaths(releasePath, lockPath);
|
|
9465
9568
|
exchanged = false;
|
|
9466
9569
|
}
|
|
@@ -9473,7 +9576,7 @@ function releaseWorkspaceLock(lockPath, lock, workspaceRoot) {
|
|
|
9473
9576
|
} catch {
|
|
9474
9577
|
if (exchanged) {
|
|
9475
9578
|
try {
|
|
9476
|
-
if (releaseHash && currentFileHash(lockPath, workspaceRoot) === releaseHash &&
|
|
9579
|
+
if (releaseHash && currentFileHash(lockPath, workspaceRoot) === releaseHash && existsSync7(releasePath)) {
|
|
9477
9580
|
atomicExchangePaths(releasePath, lockPath);
|
|
9478
9581
|
exchanged = false;
|
|
9479
9582
|
}
|
|
@@ -9485,7 +9588,7 @@ function releaseWorkspaceLock(lockPath, lock, workspaceRoot) {
|
|
|
9485
9588
|
closeSync(releaseFd);
|
|
9486
9589
|
} catch {}
|
|
9487
9590
|
}
|
|
9488
|
-
if (!exchanged &&
|
|
9591
|
+
if (!exchanged && existsSync7(releasePath)) {
|
|
9489
9592
|
try {
|
|
9490
9593
|
rmSync2(releasePath);
|
|
9491
9594
|
} catch {}
|
|
@@ -9511,15 +9614,15 @@ function ensureSafeDirectory(path, workspaceRoot, mode) {
|
|
|
9511
9614
|
const segments = rel.split(/[\\/]+/).filter(Boolean);
|
|
9512
9615
|
let current = workspaceRoot;
|
|
9513
9616
|
for (const segment of segments) {
|
|
9514
|
-
current =
|
|
9515
|
-
if (
|
|
9617
|
+
current = join9(current, segment);
|
|
9618
|
+
if (existsSync7(current)) {
|
|
9516
9619
|
if (lstatSync(current).isSymbolicLink())
|
|
9517
9620
|
throw new ProjectContextError("PROJECT_CONTEXT_SYMLINK_REJECTED", `managed path uses a symlink: ${current}`);
|
|
9518
9621
|
if (!statSync(current).isDirectory())
|
|
9519
9622
|
throw new ProjectContextError("PROJECT_CONTEXT_PATH_INVALID", `managed path is not a directory: ${current}`);
|
|
9520
9623
|
} else {
|
|
9521
9624
|
mkdirSync2(current, { mode });
|
|
9522
|
-
fsyncDirectory(
|
|
9625
|
+
fsyncDirectory(resolve4(current, ".."));
|
|
9523
9626
|
}
|
|
9524
9627
|
}
|
|
9525
9628
|
}
|
|
@@ -9575,11 +9678,11 @@ function scanGeneratedContent(content) {
|
|
|
9575
9678
|
function runtimePaths(workspaceRoot, runtime) {
|
|
9576
9679
|
const relativeTarget = runtime === "claude" ? "CLAUDE.md" : runtime === "codewith" ? ".codewith/CODEWITH.md" : "AGENTS.md";
|
|
9577
9680
|
return {
|
|
9578
|
-
target:
|
|
9579
|
-
fragment:
|
|
9580
|
-
manifest:
|
|
9581
|
-
cache:
|
|
9582
|
-
sessionManifest: runtime === "codewith" ?
|
|
9681
|
+
target: resolve4(workspaceRoot, ...relativeTarget.split("/")),
|
|
9682
|
+
fragment: resolve4(workspaceRoot, ...PROJECT_CONTEXT_FRAGMENT_PATH.split("/")),
|
|
9683
|
+
manifest: resolve4(workspaceRoot, ...PROJECT_CONTEXT_MANIFEST_PATH.split("/")),
|
|
9684
|
+
cache: resolve4(workspaceRoot, ...PROJECT_CONTEXT_CACHE_PATH.split("/")),
|
|
9685
|
+
sessionManifest: runtime === "codewith" ? resolve4(workspaceRoot, ".codewith", ".hasna", "session-render-manifest.json") : resolve4(workspaceRoot, ".hasna", "session-render-manifest.json")
|
|
9583
9686
|
};
|
|
9584
9687
|
}
|
|
9585
9688
|
function projectContextSessionGuardPaths(paths, runtime) {
|
|
@@ -9589,7 +9692,7 @@ function projectContextSessionGuardPaths(paths, runtime) {
|
|
|
9589
9692
|
paths.fragment,
|
|
9590
9693
|
paths.target,
|
|
9591
9694
|
paths.sessionManifest,
|
|
9592
|
-
...runtime === "codewith" ? [
|
|
9695
|
+
...runtime === "codewith" ? [resolve4(paths.target, "..", "CODEWITH.override.md")] : []
|
|
9593
9696
|
];
|
|
9594
9697
|
}
|
|
9595
9698
|
function sessionTargetRelativePath(runtime) {
|
|
@@ -9609,27 +9712,27 @@ function projectContextRuntimeForSessionTool(tool) {
|
|
|
9609
9712
|
return null;
|
|
9610
9713
|
}
|
|
9611
9714
|
function projectContextWorkspaceForSession(input, runtime) {
|
|
9612
|
-
const targetHome =
|
|
9715
|
+
const targetHome = resolve4(input.target_home);
|
|
9613
9716
|
if (runtime === "codewith") {
|
|
9614
9717
|
const workspaceRoot = basename(targetHome) === ".codewith" ? dirname(targetHome) : null;
|
|
9615
9718
|
if (!workspaceRoot)
|
|
9616
9719
|
return null;
|
|
9617
|
-
if (input.project_root &&
|
|
9720
|
+
if (input.project_root && resolve4(input.project_root) !== workspaceRoot) {
|
|
9618
9721
|
throw new ProjectContextError("PROJECT_CONTEXT_PATH_INVALID", "Codewith project_root must be the parent workspace of target_home");
|
|
9619
9722
|
}
|
|
9620
|
-
if (!
|
|
9723
|
+
if (!existsSync7(workspaceRoot) || !lstatSync(workspaceRoot).isDirectory())
|
|
9621
9724
|
return null;
|
|
9622
9725
|
return assertSafeWorkspaceRoot(workspaceRoot);
|
|
9623
9726
|
}
|
|
9624
|
-
if (!
|
|
9727
|
+
if (!existsSync7(targetHome) || !lstatSync(targetHome).isDirectory())
|
|
9625
9728
|
return null;
|
|
9626
9729
|
return assertSafeWorkspaceRoot(targetHome);
|
|
9627
9730
|
}
|
|
9628
9731
|
function assertCodewithTargetIsConsumed(workspaceRoot, runtime) {
|
|
9629
9732
|
if (runtime !== "codewith")
|
|
9630
9733
|
return;
|
|
9631
|
-
const override =
|
|
9632
|
-
if (!
|
|
9734
|
+
const override = resolve4(workspaceRoot, ".codewith", "CODEWITH.override.md");
|
|
9735
|
+
if (!existsSync7(override))
|
|
9633
9736
|
return;
|
|
9634
9737
|
assertNoSymlinkSegments(workspaceRoot, override);
|
|
9635
9738
|
if (!lstatSync(override).isFile())
|
|
@@ -9639,10 +9742,10 @@ function assertCodewithTargetIsConsumed(workspaceRoot, runtime) {
|
|
|
9639
9742
|
function assertSafeWorkspaceRoot(path) {
|
|
9640
9743
|
if (!isAbsolute(path))
|
|
9641
9744
|
throw new ProjectContextError("PROJECT_CONTEXT_PATH_INVALID", "workspace root must be absolute");
|
|
9642
|
-
const normalized =
|
|
9745
|
+
const normalized = resolve4(path);
|
|
9643
9746
|
if (normalized === parse(normalized).root)
|
|
9644
9747
|
throw new ProjectContextError("PROJECT_CONTEXT_PATH_INVALID", "workspace root cannot be the filesystem root");
|
|
9645
|
-
if (!
|
|
9748
|
+
if (!existsSync7(normalized) || !lstatSync(normalized).isDirectory())
|
|
9646
9749
|
throw new ProjectContextError("PROJECT_CONTEXT_PATH_INVALID", "workspace root must be an existing directory");
|
|
9647
9750
|
assertNoSymlinkAncestors(normalized);
|
|
9648
9751
|
if (lstatSync(normalized).isSymbolicLink())
|
|
@@ -9656,18 +9759,18 @@ function assertNoSymlinkSegments(root, target) {
|
|
|
9656
9759
|
}
|
|
9657
9760
|
let current = root;
|
|
9658
9761
|
for (const segment of rel.split(/[\\/]+/).filter(Boolean)) {
|
|
9659
|
-
current =
|
|
9660
|
-
if (
|
|
9762
|
+
current = join9(current, segment);
|
|
9763
|
+
if (existsSync7(current) && lstatSync(current).isSymbolicLink()) {
|
|
9661
9764
|
throw new ProjectContextError("PROJECT_CONTEXT_SYMLINK_REJECTED", `managed path uses a symlink: ${current}`);
|
|
9662
9765
|
}
|
|
9663
9766
|
}
|
|
9664
9767
|
}
|
|
9665
9768
|
function assertNoSymlinkAncestors(path) {
|
|
9666
|
-
const normalized =
|
|
9769
|
+
const normalized = resolve4(path);
|
|
9667
9770
|
let current = parse(normalized).root;
|
|
9668
9771
|
for (const segment of relative(current, normalized).split(/[\\/]+/).filter(Boolean)) {
|
|
9669
|
-
current =
|
|
9670
|
-
if (!
|
|
9772
|
+
current = join9(current, segment);
|
|
9773
|
+
if (!existsSync7(current))
|
|
9671
9774
|
return;
|
|
9672
9775
|
if (lstatSync(current).isSymbolicLink())
|
|
9673
9776
|
throw new ProjectContextError("PROJECT_CONTEXT_SYMLINK_REJECTED", `workspace ancestor is a symlink: ${current}`);
|
|
@@ -9683,7 +9786,7 @@ function readUtf8RegularFile(path, workspaceRoot, maxBytes = FOREIGN_INPUT_MAX_B
|
|
|
9683
9786
|
return readFileSync(path, "utf8");
|
|
9684
9787
|
}
|
|
9685
9788
|
function currentFileHash(path, workspaceRoot) {
|
|
9686
|
-
if (!
|
|
9789
|
+
if (!existsSync7(path))
|
|
9687
9790
|
return null;
|
|
9688
9791
|
const relativePath = relativePosix(workspaceRoot, path);
|
|
9689
9792
|
return sha2562(readUtf8RegularFile(path, workspaceRoot, managedObservationMaxBytes(relativePath)));
|
|
@@ -9702,10 +9805,10 @@ function fragmentMatchesBundle(path, bundle, workspaceRoot) {
|
|
|
9702
9805
|
}
|
|
9703
9806
|
function durableSourcePath(path, workspaceRoot) {
|
|
9704
9807
|
if (!path || path.startsWith("/dev/fd/"))
|
|
9705
|
-
return
|
|
9706
|
-
const normalized = isAbsolute(path) ?
|
|
9808
|
+
return resolve4(workspaceRoot, ...PROJECT_CONTEXT_CACHE_PATH.split("/"));
|
|
9809
|
+
const normalized = isAbsolute(path) ? resolve4(path) : resolve4(workspaceRoot, path);
|
|
9707
9810
|
if (normalized.startsWith("/dev/fd/"))
|
|
9708
|
-
return
|
|
9811
|
+
return resolve4(workspaceRoot, ...PROJECT_CONTEXT_CACHE_PATH.split("/"));
|
|
9709
9812
|
return normalized;
|
|
9710
9813
|
}
|
|
9711
9814
|
function compareRevisions(incoming, previous) {
|
|
@@ -10265,7 +10368,7 @@ function compareProviderVersions(left, right) {
|
|
|
10265
10368
|
|
|
10266
10369
|
// src/lib/asset-plan.ts
|
|
10267
10370
|
import { createHash as createHash3 } from "crypto";
|
|
10268
|
-
import { isAbsolute as isAbsolute2, posix, resolve as
|
|
10371
|
+
import { isAbsolute as isAbsolute2, posix, resolve as resolve5 } from "path";
|
|
10269
10372
|
function assetCapability(provider, surface, kind, support, strategies, note, providerVersionRange = "*") {
|
|
10270
10373
|
return Object.freeze({
|
|
10271
10374
|
schema: ASSET_CAPABILITY_SCHEMA,
|
|
@@ -10472,8 +10575,8 @@ function resolveAssetDestination(item, roots) {
|
|
|
10472
10575
|
if (!isAbsolute2(root))
|
|
10473
10576
|
throw new Error(`Asset ${item.assetKey} destination root must be absolute.`);
|
|
10474
10577
|
const relativePath = safeRelativePath(item.destination.relativePath);
|
|
10475
|
-
const target =
|
|
10476
|
-
const normalizedRoot =
|
|
10578
|
+
const target = resolve5(root, ...relativePath.split("/"));
|
|
10579
|
+
const normalizedRoot = resolve5(root);
|
|
10477
10580
|
if (target === normalizedRoot)
|
|
10478
10581
|
throw new Error(`Asset ${item.assetKey} destination cannot replace its root.`);
|
|
10479
10582
|
if (!target.startsWith(`${normalizedRoot}/`))
|
|
@@ -10653,13 +10756,13 @@ var init_asset_plan = __esm(() => {
|
|
|
10653
10756
|
// src/lib/cursor-authority.ts
|
|
10654
10757
|
import { createHash as createHash4 } from "crypto";
|
|
10655
10758
|
import { lstatSync as lstatSync2, readFileSync as readFileSync2 } from "fs";
|
|
10656
|
-
import { homedir as
|
|
10657
|
-
import { join as
|
|
10759
|
+
import { homedir as homedir7 } from "os";
|
|
10760
|
+
import { join as join10, resolve as resolve6 } from "path";
|
|
10658
10761
|
function sha2564(content) {
|
|
10659
10762
|
return createHash4("sha256").update(content).digest("hex");
|
|
10660
10763
|
}
|
|
10661
|
-
function
|
|
10662
|
-
return process.env["HOME"] ||
|
|
10764
|
+
function homeDir2() {
|
|
10765
|
+
return process.env["HOME"] || homedir7();
|
|
10663
10766
|
}
|
|
10664
10767
|
function markerPayload(content, markerLine, markerIndex) {
|
|
10665
10768
|
const index = markerIndex ?? content.indexOf(markerLine);
|
|
@@ -10675,12 +10778,12 @@ function baseObservation(path) {
|
|
|
10675
10778
|
};
|
|
10676
10779
|
}
|
|
10677
10780
|
function observeCursorGlobalAuthority(options = {}) {
|
|
10678
|
-
const authorityPath =
|
|
10781
|
+
const authorityPath = resolve6(join10(options.home ?? homeDir2(), CURSOR_GLOBAL_AUTHORITY_RELATIVE_PATH));
|
|
10679
10782
|
const readFile2 = options.readFile ?? ((path) => readFileSync2(path, "utf8"));
|
|
10680
10783
|
return observeCursorGlobalAuthorityPath(authorityPath, readFile2);
|
|
10681
10784
|
}
|
|
10682
10785
|
function observeCursorGlobalAuthorityAtPath(authorityPath) {
|
|
10683
|
-
return observeCursorGlobalAuthorityPath(
|
|
10786
|
+
return observeCursorGlobalAuthorityPath(resolve6(authorityPath), (path) => readFileSync2(path, "utf8"));
|
|
10684
10787
|
}
|
|
10685
10788
|
function observeCursorGlobalAuthorityPath(authorityPath, readFile2) {
|
|
10686
10789
|
const base = baseObservation(authorityPath);
|
|
@@ -10825,7 +10928,7 @@ function observeCursorGlobalAuthorityPath(authorityPath, readFile2) {
|
|
|
10825
10928
|
};
|
|
10826
10929
|
}
|
|
10827
10930
|
function isCursorGlobalAuthorityPath(path) {
|
|
10828
|
-
return
|
|
10931
|
+
return resolve6(path) === resolve6(join10(homeDir2(), CURSOR_GLOBAL_AUTHORITY_RELATIVE_PATH));
|
|
10829
10932
|
}
|
|
10830
10933
|
function stampCursorGlobalAuthorityMarker(content) {
|
|
10831
10934
|
const existing = content.match(CURSOR_GLOBAL_AUTHORITY_MARKER_PATTERN);
|
|
@@ -10881,16 +10984,16 @@ var init_cursor_authority = __esm(() => {
|
|
|
10881
10984
|
// src/lib/session-authority.ts
|
|
10882
10985
|
import { createHash as createHash5 } from "crypto";
|
|
10883
10986
|
import { lstatSync as lstatSync3, readFileSync as readFileSync3, realpathSync, statSync as statSync2 } from "fs";
|
|
10884
|
-
import { homedir as
|
|
10885
|
-
import { join as
|
|
10987
|
+
import { homedir as homedir8 } from "os";
|
|
10988
|
+
import { join as join11, resolve as resolve7 } from "path";
|
|
10886
10989
|
function sha2565(content) {
|
|
10887
10990
|
return createHash5("sha256").update(content).digest("hex");
|
|
10888
10991
|
}
|
|
10889
10992
|
function configHomeDir() {
|
|
10890
|
-
return process.env["CONFIGS_HOME"] || process.env["HOME"] ||
|
|
10993
|
+
return process.env["CONFIGS_HOME"] || process.env["HOME"] || homedir8();
|
|
10891
10994
|
}
|
|
10892
10995
|
function normalizeOwnedTargetPath(p) {
|
|
10893
|
-
const expanded = p.startsWith("~/") ?
|
|
10996
|
+
const expanded = p.startsWith("~/") ? resolve7(configHomeDir(), p.slice(2)) : resolve7(p);
|
|
10894
10997
|
try {
|
|
10895
10998
|
return realpathSync(expanded);
|
|
10896
10999
|
} catch {
|
|
@@ -10898,7 +11001,7 @@ function normalizeOwnedTargetPath(p) {
|
|
|
10898
11001
|
}
|
|
10899
11002
|
}
|
|
10900
11003
|
function detectClaudeAuthorityConflicts(targetHome, ownedAuthorities = []) {
|
|
10901
|
-
const authorityPath =
|
|
11004
|
+
const authorityPath = resolve7(join11(targetHome, CLAUDE_LEGACY_AUTHORITY_RELATIVE_PATH));
|
|
10902
11005
|
let stat;
|
|
10903
11006
|
try {
|
|
10904
11007
|
stat = lstatSync3(authorityPath);
|
|
@@ -10987,9 +11090,9 @@ var init_session_authority = __esm(() => {
|
|
|
10987
11090
|
|
|
10988
11091
|
// src/lib/session-render.ts
|
|
10989
11092
|
import { createHash as createHash6 } from "crypto";
|
|
10990
|
-
import { existsSync as
|
|
10991
|
-
import { homedir as
|
|
10992
|
-
import { basename as basename4, dirname as dirname3, extname as extname2, isAbsolute as isAbsolute3, join as
|
|
11093
|
+
import { existsSync as existsSync9, readFileSync as readFileSync4, realpathSync as realpathSync2, statSync as statSync3 } from "fs";
|
|
11094
|
+
import { homedir as homedir9 } from "os";
|
|
11095
|
+
import { basename as basename4, dirname as dirname3, extname as extname2, isAbsolute as isAbsolute3, join as join12, parse as parse2, posix as posix2, relative as relative2, resolve as resolve8 } from "path";
|
|
10993
11096
|
function normalizeSessionInstructionLayer(value) {
|
|
10994
11097
|
if (value === "provider")
|
|
10995
11098
|
return "tool";
|
|
@@ -11075,13 +11178,13 @@ function yamlQuote2(value) {
|
|
|
11075
11178
|
return `"${value.replace(/\\/g, "\\\\").replace(/"/g, "\\\"")}"`;
|
|
11076
11179
|
}
|
|
11077
11180
|
function defaultTargetHome(tool, profile, sessionId) {
|
|
11078
|
-
const home = process.env["HOME"] ||
|
|
11079
|
-
return
|
|
11181
|
+
const home = process.env["HOME"] || homedir9();
|
|
11182
|
+
return join12(home, ".hasna", "accounts", "profiles", tool, slug(profile));
|
|
11080
11183
|
}
|
|
11081
11184
|
function joinTarget(targetHome, relativePath) {
|
|
11082
11185
|
const safeTargetHome = assertSafeTargetRoot(targetHome);
|
|
11083
11186
|
const safeRelativePath2 = assertSafeRelativePath(relativePath);
|
|
11084
|
-
return
|
|
11187
|
+
return join12(safeTargetHome, ...safeRelativePath2.split("/"));
|
|
11085
11188
|
}
|
|
11086
11189
|
function makeFile(targetHome, relativePath, role, content, sourceIds) {
|
|
11087
11190
|
const safeTargetHome = assertSafeTargetRoot(targetHome);
|
|
@@ -11650,7 +11753,7 @@ function buildOpenCodeFiles(targetHome, adapter, profile, sources, providerConfi
|
|
|
11650
11753
|
...sources.flatMap((source) => source.resolvedRules.map((rule) => rule.id))
|
|
11651
11754
|
]);
|
|
11652
11755
|
const existingConfigPath = joinTarget(targetHome, adapter.configFile);
|
|
11653
|
-
const selectedConfig =
|
|
11756
|
+
const selectedConfig = existsSync9(existingConfigPath) ? readOpenCodeConfig(readFileSync4(existingConfigPath, "utf8"), existingConfigPath) : providerConfig ? readOpenCodeConfig(providerConfig.content, providerConfig.sourceId) : {};
|
|
11654
11757
|
const preservedInstructions = normalizeOpenCodeInstructions(selectedConfig["instructions"]).filter((path) => !pathIsManagedOpenCodeInstruction(path, adapter.managedDir));
|
|
11655
11758
|
const config = {
|
|
11656
11759
|
...selectedConfig,
|
|
@@ -11839,7 +11942,7 @@ function adapterFor(input) {
|
|
|
11839
11942
|
return gatedNativeImports ? CODEWITH_NATIVE_ADAPTER : CODEWITH_FLATTENED_ADAPTER;
|
|
11840
11943
|
}
|
|
11841
11944
|
function getHomeDir() {
|
|
11842
|
-
return process.env["CONFIGS_HOME"] || process.env["HOME"] ||
|
|
11945
|
+
return process.env["CONFIGS_HOME"] || process.env["HOME"] || homedir9();
|
|
11843
11946
|
}
|
|
11844
11947
|
function cleanSessionPathInput(path) {
|
|
11845
11948
|
const trimmed = path.trim();
|
|
@@ -11854,16 +11957,16 @@ function resolveSessionPath(path) {
|
|
|
11854
11957
|
throw new Error("Session render path cannot be empty.");
|
|
11855
11958
|
const home = getHomeDir();
|
|
11856
11959
|
if (cleaned === "~")
|
|
11857
|
-
return
|
|
11960
|
+
return resolve8(home);
|
|
11858
11961
|
if (cleaned.startsWith("~/"))
|
|
11859
|
-
return
|
|
11962
|
+
return resolve8(home, cleaned.slice(2));
|
|
11860
11963
|
if (cleaned === "{{HOME}}" || cleaned === "${HOME}")
|
|
11861
|
-
return
|
|
11964
|
+
return resolve8(home);
|
|
11862
11965
|
if (cleaned.startsWith("{{HOME}}/"))
|
|
11863
|
-
return
|
|
11966
|
+
return resolve8(home, cleaned.slice("{{HOME}}/".length));
|
|
11864
11967
|
if (cleaned.startsWith("${HOME}/"))
|
|
11865
|
-
return
|
|
11866
|
-
return
|
|
11968
|
+
return resolve8(home, cleaned.slice("${HOME}/".length));
|
|
11969
|
+
return resolve8(cleaned);
|
|
11867
11970
|
}
|
|
11868
11971
|
function assertSafeRelativePath(relativePath) {
|
|
11869
11972
|
if (!relativePath.trim())
|
|
@@ -11879,7 +11982,7 @@ function assertSafeRelativePath(relativePath) {
|
|
|
11879
11982
|
function assertSafeTargetRoot(targetHome) {
|
|
11880
11983
|
if (!isAbsolute3(targetHome))
|
|
11881
11984
|
throw new Error(`Session render target must be an absolute path: ${targetHome}`);
|
|
11882
|
-
const normalized =
|
|
11985
|
+
const normalized = resolve8(targetHome);
|
|
11883
11986
|
if (normalized === parse2(normalized).root) {
|
|
11884
11987
|
throw new Error(`Session render target cannot be the filesystem root: ${targetHome}`);
|
|
11885
11988
|
}
|
|
@@ -12115,7 +12218,7 @@ function planSessionRender(input) {
|
|
|
12115
12218
|
sourceId: input.providerConfig.sourceId,
|
|
12116
12219
|
selectedPayloadSha256: sha2566(input.providerConfig.content),
|
|
12117
12220
|
renderedPayloadSha256: files.find((file) => file.relativePath === adapter.configFile)?.sha256 ?? sha2566(input.providerConfig.content),
|
|
12118
|
-
selected: !
|
|
12221
|
+
selected: !existsSync9(joinTarget(targetHome, adapter.configFile))
|
|
12119
12222
|
}
|
|
12120
12223
|
} : {},
|
|
12121
12224
|
...projectContext ? {
|
|
@@ -12376,10 +12479,10 @@ function layerFromIdentityKind(kind, exportShape) {
|
|
|
12376
12479
|
function contentFromIdentitySourcePaths(sourcePaths, exportPath, sourceId) {
|
|
12377
12480
|
if (sourcePaths.length === 0 || !exportPath)
|
|
12378
12481
|
return;
|
|
12379
|
-
const
|
|
12482
|
+
const baseDir3 = dirname3(resolveSessionPath(exportPath));
|
|
12380
12483
|
const contents = [];
|
|
12381
12484
|
for (const sourcePath of sourcePaths) {
|
|
12382
|
-
const content = readIdentitySourcePath(sourcePath,
|
|
12485
|
+
const content = readIdentitySourcePath(sourcePath, baseDir3, sourceId);
|
|
12383
12486
|
if (content !== undefined)
|
|
12384
12487
|
contents.push({ path: sourcePath.path, content });
|
|
12385
12488
|
}
|
|
@@ -12392,9 +12495,9 @@ ${item.content.trimEnd()}`).join(`
|
|
|
12392
12495
|
|
|
12393
12496
|
`));
|
|
12394
12497
|
}
|
|
12395
|
-
function readIdentitySourcePath(sourcePath,
|
|
12396
|
-
const resolvedPath = resolveIdentitySourcePath(sourcePath.path,
|
|
12397
|
-
if (!
|
|
12498
|
+
function readIdentitySourcePath(sourcePath, baseDir3, sourceId) {
|
|
12499
|
+
const resolvedPath = resolveIdentitySourcePath(sourcePath.path, baseDir3, sourceId);
|
|
12500
|
+
if (!existsSync9(resolvedPath)) {
|
|
12398
12501
|
if (sourcePath.required) {
|
|
12399
12502
|
throw new Error(`Required identity instruction source path not found for ${sourceId}: ${sourcePath.path}`);
|
|
12400
12503
|
}
|
|
@@ -12404,27 +12507,27 @@ function readIdentitySourcePath(sourcePath, baseDir, sourceId) {
|
|
|
12404
12507
|
if (!stat.isFile()) {
|
|
12405
12508
|
throw new Error(`Identity instruction source path is not a file for ${sourceId}: ${sourcePath.path}`);
|
|
12406
12509
|
}
|
|
12407
|
-
const realBase = realpathSync2(
|
|
12510
|
+
const realBase = realpathSync2(baseDir3);
|
|
12408
12511
|
const realPath = realpathSync2(resolvedPath);
|
|
12409
12512
|
if (!pathIsInside(realPath, realBase)) {
|
|
12410
12513
|
throw new Error(`Identity instruction source path escapes export directory for ${sourceId}: ${sourcePath.path}`);
|
|
12411
12514
|
}
|
|
12412
12515
|
return readFileSync4(realPath, "utf-8");
|
|
12413
12516
|
}
|
|
12414
|
-
function resolveIdentitySourcePath(path,
|
|
12517
|
+
function resolveIdentitySourcePath(path, baseDir3, sourceId) {
|
|
12415
12518
|
const cleaned = cleanSessionPathInput(path);
|
|
12416
12519
|
if (!cleaned)
|
|
12417
12520
|
throw new Error(`Identity instruction source path cannot be empty for ${sourceId}.`);
|
|
12418
12521
|
if (cleaned.includes("\\"))
|
|
12419
12522
|
throw new Error(`Identity instruction source path must use POSIX separators for ${sourceId}: ${path}`);
|
|
12420
|
-
const resolvedPath = isAbsolute3(cleaned) ?
|
|
12421
|
-
if (!pathIsInside(resolvedPath,
|
|
12523
|
+
const resolvedPath = isAbsolute3(cleaned) ? resolve8(cleaned) : resolve8(baseDir3, cleaned);
|
|
12524
|
+
if (!pathIsInside(resolvedPath, resolve8(baseDir3))) {
|
|
12422
12525
|
throw new Error(`Identity instruction source path escapes export directory for ${sourceId}: ${path}`);
|
|
12423
12526
|
}
|
|
12424
12527
|
return resolvedPath;
|
|
12425
12528
|
}
|
|
12426
|
-
function pathIsInside(path,
|
|
12427
|
-
const rel = relative2(
|
|
12529
|
+
function pathIsInside(path, baseDir3) {
|
|
12530
|
+
const rel = relative2(baseDir3, path);
|
|
12428
12531
|
return rel === "" || !rel.startsWith("..") && !isAbsolute3(rel);
|
|
12429
12532
|
}
|
|
12430
12533
|
function providerTargetsTool(targets, tool) {
|
|
@@ -14084,8 +14187,8 @@ var init_config_store = __esm(() => {
|
|
|
14084
14187
|
});
|
|
14085
14188
|
|
|
14086
14189
|
// src/lib/session-render-ownership.ts
|
|
14087
|
-
import { existsSync as
|
|
14088
|
-
import { dirname as dirname4, join as
|
|
14190
|
+
import { existsSync as existsSync10, readFileSync as readFileSync5, statSync as statSync4 } from "fs";
|
|
14191
|
+
import { dirname as dirname4, join as join13, parse as parse3, relative as relative3, sep } from "path";
|
|
14089
14192
|
function toSegments(absolutePath2) {
|
|
14090
14193
|
return absolutePath2.replaceAll("\\", "/").split("/").filter(Boolean);
|
|
14091
14194
|
}
|
|
@@ -14104,7 +14207,7 @@ function pathIsSessionRenderManagedDir(absolutePath2) {
|
|
|
14104
14207
|
function readManifestRelativePaths(manifestPath) {
|
|
14105
14208
|
let stats;
|
|
14106
14209
|
try {
|
|
14107
|
-
if (!
|
|
14210
|
+
if (!existsSync10(manifestPath))
|
|
14108
14211
|
return null;
|
|
14109
14212
|
stats = statSync4(manifestPath);
|
|
14110
14213
|
} catch {
|
|
@@ -14133,7 +14236,7 @@ function sessionRenderManifestClaimsPath(absolutePath2) {
|
|
|
14133
14236
|
const root = parse3(absolutePath2).root;
|
|
14134
14237
|
let home = dirname4(absolutePath2);
|
|
14135
14238
|
for (let depth = 0;depth < MANIFEST_ANCESTOR_LIMIT; depth += 1) {
|
|
14136
|
-
const manifestPath =
|
|
14239
|
+
const manifestPath = join13(home, ...SESSION_RENDER_MANIFEST_RELATIVE_PATH.split("/"));
|
|
14137
14240
|
const relativePaths = readManifestRelativePaths(manifestPath);
|
|
14138
14241
|
if (relativePaths) {
|
|
14139
14242
|
const claimed = relative3(home, absolutePath2).split(sep).join("/");
|
|
@@ -14168,17 +14271,17 @@ __export(exports_apply, {
|
|
|
14168
14271
|
applyConfigs: () => applyConfigs,
|
|
14169
14272
|
applyConfig: () => applyConfig
|
|
14170
14273
|
});
|
|
14171
|
-
import { existsSync as
|
|
14172
|
-
import { basename as basename5, dirname as dirname5, join as
|
|
14173
|
-
import { homedir as
|
|
14274
|
+
import { existsSync as existsSync11, mkdirSync as mkdirSync3, readFileSync as readFileSync6, realpathSync as realpathSync3, writeFileSync as writeFileSync2 } from "fs";
|
|
14275
|
+
import { basename as basename5, dirname as dirname5, join as join14, resolve as resolve9 } from "path";
|
|
14276
|
+
import { homedir as homedir10 } from "os";
|
|
14174
14277
|
function getConfigHome() {
|
|
14175
|
-
return process.env["CONFIGS_HOME"] || process.env["HOME"] ||
|
|
14278
|
+
return process.env["CONFIGS_HOME"] || process.env["HOME"] || homedir10();
|
|
14176
14279
|
}
|
|
14177
14280
|
function expandPath(p) {
|
|
14178
14281
|
if (p.startsWith("~/")) {
|
|
14179
|
-
return
|
|
14282
|
+
return resolve9(getConfigHome(), p.slice(2));
|
|
14180
14283
|
}
|
|
14181
|
-
return
|
|
14284
|
+
return resolve9(p);
|
|
14182
14285
|
}
|
|
14183
14286
|
function normalizeTargetPath(p) {
|
|
14184
14287
|
const expanded = expandPath(p);
|
|
@@ -14188,9 +14291,9 @@ function normalizeTargetPath(p) {
|
|
|
14188
14291
|
let current = expanded;
|
|
14189
14292
|
const missingSegments = [];
|
|
14190
14293
|
while (true) {
|
|
14191
|
-
if (
|
|
14294
|
+
if (existsSync11(current)) {
|
|
14192
14295
|
try {
|
|
14193
|
-
return
|
|
14296
|
+
return resolve9(realpathSync3(current), ...missingSegments);
|
|
14194
14297
|
} catch {
|
|
14195
14298
|
return expanded;
|
|
14196
14299
|
}
|
|
@@ -14219,11 +14322,11 @@ async function writeConfigResult(config, targetPath, content, opts, meta = {}) {
|
|
|
14219
14322
|
}
|
|
14220
14323
|
const path = expandPath(renderedTargetPath);
|
|
14221
14324
|
const renderedForTarget = isCursorGlobalAuthorityPath(path) ? stampCursorGlobalAuthorityMarker(renderedContent) : renderedContent;
|
|
14222
|
-
const previousContent =
|
|
14325
|
+
const previousContent = existsSync11(path) ? readFileSync6(path, "utf-8") : null;
|
|
14223
14326
|
const changed = previousContent !== renderedForTarget;
|
|
14224
14327
|
if (!opts.dryRun) {
|
|
14225
14328
|
const dir = dirname5(path);
|
|
14226
|
-
if (!
|
|
14329
|
+
if (!existsSync11(dir)) {
|
|
14227
14330
|
mkdirSync3(dir, { recursive: true });
|
|
14228
14331
|
}
|
|
14229
14332
|
if (previousContent !== null && changed) {
|
|
@@ -14257,7 +14360,7 @@ function wouldDestroyACredential(targetPath, renderedContent, format) {
|
|
|
14257
14360
|
let current;
|
|
14258
14361
|
try {
|
|
14259
14362
|
const path = expandPath(targetPath);
|
|
14260
|
-
if (!
|
|
14363
|
+
if (!existsSync11(path))
|
|
14261
14364
|
return [];
|
|
14262
14365
|
current = readFileSync6(path, "utf-8");
|
|
14263
14366
|
} catch {
|
|
@@ -14583,7 +14686,7 @@ function sessionRendererOwnsCanonicalTarget(normalized, opts) {
|
|
|
14583
14686
|
getConfigHome(),
|
|
14584
14687
|
opts.vars?.["HOME_DIR"]
|
|
14585
14688
|
].filter((home) => typeof home === "string" && home.length > 0));
|
|
14586
|
-
if ([...homes].some((home) => SESSION_RENDER_OWNED_CONFIG_TARGETS.some((relativePath) => normalized === normalizeTargetPath(
|
|
14689
|
+
if ([...homes].some((home) => SESSION_RENDER_OWNED_CONFIG_TARGETS.some((relativePath) => normalized === normalizeTargetPath(join14(home, ...relativePath.split("/"))))))
|
|
14587
14690
|
return true;
|
|
14588
14691
|
return sessionRenderOwnsPath(normalized);
|
|
14589
14692
|
}
|
|
@@ -14601,20 +14704,20 @@ var init_apply = __esm(() => {
|
|
|
14601
14704
|
});
|
|
14602
14705
|
|
|
14603
14706
|
// src/lib/sync-dir.ts
|
|
14604
|
-
import { existsSync as
|
|
14605
|
-
import { join as
|
|
14606
|
-
import { homedir as
|
|
14707
|
+
import { existsSync as existsSync12, readdirSync, readFileSync as readFileSync7, statSync as statSync5 } from "fs";
|
|
14708
|
+
import { join as join15, relative as relative4 } from "path";
|
|
14709
|
+
import { homedir as homedir11 } from "os";
|
|
14607
14710
|
function shouldSkip(p) {
|
|
14608
14711
|
return SKIP.some((s) => p.includes(s));
|
|
14609
14712
|
}
|
|
14610
14713
|
async function syncFromDir(dir, opts = {}) {
|
|
14611
14714
|
const store = opts.store ?? resolveConfigStore();
|
|
14612
14715
|
const absDir = expandPath(dir);
|
|
14613
|
-
if (!
|
|
14716
|
+
if (!existsSync12(absDir))
|
|
14614
14717
|
return { added: 0, updated: 0, unchanged: 0, skipped: [`Not found: ${absDir}`] };
|
|
14615
|
-
const files = opts.recursive !== false ? walkDir(absDir) : readdirSync(absDir).map((f) =>
|
|
14718
|
+
const files = opts.recursive !== false ? walkDir(absDir) : readdirSync(absDir).map((f) => join15(absDir, f)).filter((f) => statSync5(f).isFile());
|
|
14616
14719
|
const result = { added: 0, updated: 0, unchanged: 0, skipped: [] };
|
|
14617
|
-
const home =
|
|
14720
|
+
const home = homedir11();
|
|
14618
14721
|
const allConfigs = await store.listConfigs();
|
|
14619
14722
|
for (const file of files) {
|
|
14620
14723
|
if (shouldSkip(file)) {
|
|
@@ -14649,7 +14752,7 @@ async function syncFromDir(dir, opts = {}) {
|
|
|
14649
14752
|
}
|
|
14650
14753
|
async function syncToDir(dir, opts = {}) {
|
|
14651
14754
|
const store = opts.store ?? resolveConfigStore();
|
|
14652
|
-
const home =
|
|
14755
|
+
const home = homedir11();
|
|
14653
14756
|
const absDir = expandPath(dir);
|
|
14654
14757
|
const normalized = dir.startsWith("~/") ? dir : absDir.replace(home, "~");
|
|
14655
14758
|
const configs = (await store.listConfigs()).filter((c) => c.target_path && (c.target_path.startsWith(normalized) || c.target_path.startsWith(absDir)));
|
|
@@ -14673,7 +14776,7 @@ async function syncToDir(dir, opts = {}) {
|
|
|
14673
14776
|
}
|
|
14674
14777
|
function walkDir(dir, files = []) {
|
|
14675
14778
|
for (const entry of readdirSync(dir, { withFileTypes: true })) {
|
|
14676
|
-
const full =
|
|
14779
|
+
const full = join15(dir, entry.name);
|
|
14677
14780
|
if (shouldSkip(full))
|
|
14678
14781
|
continue;
|
|
14679
14782
|
if (entry.isDirectory())
|
|
@@ -14708,8 +14811,8 @@ __export(exports_sync, {
|
|
|
14708
14811
|
KNOWN_CONFIGS: () => KNOWN_CONFIGS,
|
|
14709
14812
|
CLAUDE_PROMPT_OUTPUTS: () => CLAUDE_PROMPT_OUTPUTS
|
|
14710
14813
|
});
|
|
14711
|
-
import { existsSync as
|
|
14712
|
-
import { basename as basename6, extname as extname3, join as
|
|
14814
|
+
import { existsSync as existsSync13, readdirSync as readdirSync2, readFileSync as readFileSync8 } from "fs";
|
|
14815
|
+
import { basename as basename6, extname as extname3, join as join16 } from "path";
|
|
14713
14816
|
function claudeRuleOutputs(fileName) {
|
|
14714
14817
|
const stem = basename6(fileName, extname3(fileName));
|
|
14715
14818
|
return [
|
|
@@ -14748,7 +14851,7 @@ function isGeneratedOutputTarget2(config, owners) {
|
|
|
14748
14851
|
return !!ownerIds && !ownerIds.has(config.id);
|
|
14749
14852
|
}
|
|
14750
14853
|
function hasClaudePromptSource() {
|
|
14751
|
-
return
|
|
14854
|
+
return existsSync13(expandPath("~/.claude/CLAUDE.md"));
|
|
14752
14855
|
}
|
|
14753
14856
|
function hasClaudeRuleSourceForCursorTarget(targetPath) {
|
|
14754
14857
|
const absoluteTargetPath = expandPath(targetPath);
|
|
@@ -14756,7 +14859,7 @@ function hasClaudeRuleSourceForCursorTarget(targetPath) {
|
|
|
14756
14859
|
if (!absoluteTargetPath.startsWith(`${absolutePrefix}/`) || !absoluteTargetPath.endsWith(".mdc"))
|
|
14757
14860
|
return false;
|
|
14758
14861
|
const stem = basename6(absoluteTargetPath, ".mdc");
|
|
14759
|
-
return
|
|
14862
|
+
return existsSync13(expandPath(`~/.claude/rules/${stem}.md`)) || existsSync13(expandPath(`~/.claude/rules/${stem}.mdc`));
|
|
14760
14863
|
}
|
|
14761
14864
|
function isKnownGeneratedTargetPath(targetPath) {
|
|
14762
14865
|
const normalizedTargetPath = normalizeTargetPath(targetPath);
|
|
@@ -14773,8 +14876,8 @@ async function syncProject(opts) {
|
|
|
14773
14876
|
const allConfigs = await store.listConfigs();
|
|
14774
14877
|
const machine = detectMachineContext();
|
|
14775
14878
|
for (const pf of PROJECT_CONFIG_FILES) {
|
|
14776
|
-
const abs =
|
|
14777
|
-
if (!
|
|
14879
|
+
const abs = join16(absDir, pf.file);
|
|
14880
|
+
if (!existsSync13(abs))
|
|
14778
14881
|
continue;
|
|
14779
14882
|
try {
|
|
14780
14883
|
const rawContent = readFileSync8(abs, "utf-8");
|
|
@@ -14806,19 +14909,19 @@ async function syncProject(opts) {
|
|
|
14806
14909
|
}
|
|
14807
14910
|
}
|
|
14808
14911
|
for (const ruleDir of [
|
|
14809
|
-
{ dir:
|
|
14810
|
-
{ dir:
|
|
14811
|
-
{ dir:
|
|
14812
|
-
{ dir:
|
|
14813
|
-
{ dir:
|
|
14814
|
-
{ dir:
|
|
14815
|
-
{ dir:
|
|
14912
|
+
{ dir: join16(absDir, ".claude", "rules"), agent: "claude", namePrefix: "rules" },
|
|
14913
|
+
{ dir: join16(absDir, ".agents", "rules"), agent: "antigravity", namePrefix: "antigravity-rules" },
|
|
14914
|
+
{ dir: join16(absDir, ".cursor", "rules"), agent: "cursor", namePrefix: "cursor-rules" },
|
|
14915
|
+
{ dir: join16(absDir, ".github", "instructions"), agent: "copilot", namePrefix: "copilot-instructions" },
|
|
14916
|
+
{ dir: join16(absDir, ".devin", "rules"), agent: "devin", namePrefix: "devin-rules" },
|
|
14917
|
+
{ dir: join16(absDir, ".windsurf", "rules"), agent: "windsurf-legacy", namePrefix: "windsurf-rules" },
|
|
14918
|
+
{ dir: join16(absDir, ".clinerules"), agent: "cline", namePrefix: "cline-rules" }
|
|
14816
14919
|
]) {
|
|
14817
|
-
if (!
|
|
14920
|
+
if (!existsSync13(ruleDir.dir))
|
|
14818
14921
|
continue;
|
|
14819
14922
|
const mdFiles = readdirSync2(ruleDir.dir).filter((f) => f.endsWith(".md") || f.endsWith(".mdc"));
|
|
14820
14923
|
for (const f of mdFiles) {
|
|
14821
|
-
const abs =
|
|
14924
|
+
const abs = join16(ruleDir.dir, f);
|
|
14822
14925
|
const raw = readFileSync8(abs, "utf-8");
|
|
14823
14926
|
const redacted = redactContent(raw, "markdown");
|
|
14824
14927
|
const machineAware = templateizeMachineContent(redacted.content, machine);
|
|
@@ -14858,14 +14961,14 @@ async function syncKnown(opts = {}) {
|
|
|
14858
14961
|
for (const known of targets) {
|
|
14859
14962
|
if (known.rulesDir) {
|
|
14860
14963
|
const absDir = expandPath(known.rulesDir);
|
|
14861
|
-
if (!
|
|
14964
|
+
if (!existsSync13(absDir)) {
|
|
14862
14965
|
result.skipped.push(known.rulesDir);
|
|
14863
14966
|
continue;
|
|
14864
14967
|
}
|
|
14865
14968
|
const extensions = known.rulesExtensions ?? [".md", ".mdc"];
|
|
14866
14969
|
const ruleFiles = readdirSync2(absDir).filter((f) => extensions.some((ext) => f.endsWith(ext)));
|
|
14867
14970
|
for (const f of ruleFiles) {
|
|
14868
|
-
const abs2 =
|
|
14971
|
+
const abs2 = join16(absDir, f);
|
|
14869
14972
|
const targetPath = abs2.replace(home, "~");
|
|
14870
14973
|
if (existingOutputOwners.has(normalizeTargetPath(targetPath)) || isKnownGeneratedTargetPath(targetPath)) {
|
|
14871
14974
|
result.skipped.push(`${targetPath} (generated output)`);
|
|
@@ -14899,7 +15002,7 @@ async function syncKnown(opts = {}) {
|
|
|
14899
15002
|
continue;
|
|
14900
15003
|
}
|
|
14901
15004
|
const abs = expandPath(known.path);
|
|
14902
|
-
if (!
|
|
15005
|
+
if (!existsSync13(abs)) {
|
|
14903
15006
|
result.skipped.push(known.path);
|
|
14904
15007
|
continue;
|
|
14905
15008
|
}
|
|
@@ -15005,7 +15108,7 @@ function storedPlaceholderIsLiteralOnDisk(storedLine, diskLine) {
|
|
|
15005
15108
|
}
|
|
15006
15109
|
function buildDiff(expectedContent, targetPath, storedFormat, showSecrets) {
|
|
15007
15110
|
const path = expandPath(targetPath);
|
|
15008
|
-
if (!
|
|
15111
|
+
if (!existsSync13(path))
|
|
15009
15112
|
return `(file not found on disk: ${path})`;
|
|
15010
15113
|
const diskContent = readFileSync8(path, "utf-8");
|
|
15011
15114
|
if (diskContent === expectedContent)
|
|
@@ -15240,16 +15343,16 @@ __export(exports_package_manager_guard, {
|
|
|
15240
15343
|
scanPackageManagerSecrets: () => scanPackageManagerSecrets
|
|
15241
15344
|
});
|
|
15242
15345
|
import { execFileSync as execFileSync2 } from "child_process";
|
|
15243
|
-
import { existsSync as
|
|
15244
|
-
import { homedir as
|
|
15245
|
-
import { basename as basename7, dirname as dirname10, isAbsolute as isAbsolute5, join as
|
|
15346
|
+
import { existsSync as existsSync22, lstatSync as lstatSync7, readdirSync as readdirSync5, readFileSync as readFileSync16 } from "fs";
|
|
15347
|
+
import { homedir as homedir14 } from "os";
|
|
15348
|
+
import { basename as basename7, dirname as dirname10, isAbsolute as isAbsolute5, join as join24, relative as relative7, resolve as resolve14 } from "path";
|
|
15246
15349
|
function scanPackageManagerSecrets(options = {}) {
|
|
15247
|
-
const cwd = options.cwd ?
|
|
15248
|
-
const roots = (options.roots && options.roots.length > 0 ? options.roots : [cwd]).map((root) =>
|
|
15350
|
+
const cwd = options.cwd ? resolve14(options.cwd) : process.cwd();
|
|
15351
|
+
const roots = (options.roots && options.roots.length > 0 ? options.roots : [cwd]).map((root) => resolve14(cwd, root));
|
|
15249
15352
|
const findings = [];
|
|
15250
15353
|
let scannedFiles = 0;
|
|
15251
15354
|
for (const root of roots) {
|
|
15252
|
-
if (!
|
|
15355
|
+
if (!existsSync22(root))
|
|
15253
15356
|
continue;
|
|
15254
15357
|
const stat = lstatSync7(root);
|
|
15255
15358
|
if (stat.isFile()) {
|
|
@@ -15276,10 +15379,10 @@ function scanPackageManagerSecrets(options = {}) {
|
|
|
15276
15379
|
}
|
|
15277
15380
|
}
|
|
15278
15381
|
if (options.includeHome) {
|
|
15279
|
-
const home =
|
|
15382
|
+
const home = homedir14();
|
|
15280
15383
|
for (const name of HOME_FILES) {
|
|
15281
|
-
const file =
|
|
15282
|
-
if (!
|
|
15384
|
+
const file = join24(home, name);
|
|
15385
|
+
if (!existsSync22(file))
|
|
15283
15386
|
continue;
|
|
15284
15387
|
const text = readTextFile(file);
|
|
15285
15388
|
if (text === null)
|
|
@@ -15303,12 +15406,12 @@ function collectRepoFiles(root) {
|
|
|
15303
15406
|
if (entry.isDirectory()) {
|
|
15304
15407
|
if (SKIP_DIRS.has(entry.name))
|
|
15305
15408
|
continue;
|
|
15306
|
-
visit(
|
|
15409
|
+
visit(join24(dir, entry.name));
|
|
15307
15410
|
continue;
|
|
15308
15411
|
}
|
|
15309
15412
|
if (!entry.isFile())
|
|
15310
15413
|
continue;
|
|
15311
|
-
const file =
|
|
15414
|
+
const file = join24(dir, entry.name);
|
|
15312
15415
|
if (shouldScanRepoFile(file))
|
|
15313
15416
|
out.push(file);
|
|
15314
15417
|
}
|
|
@@ -15576,7 +15679,7 @@ function stripInlineComment(value) {
|
|
|
15576
15679
|
return value.replace(/\s[#;].*$/, "").trim();
|
|
15577
15680
|
}
|
|
15578
15681
|
function displayPath(file, root) {
|
|
15579
|
-
const home =
|
|
15682
|
+
const home = homedir14();
|
|
15580
15683
|
if (root === home && (file === home || file.startsWith(home + "/")))
|
|
15581
15684
|
return "~/" + toPosix(relative7(home, file));
|
|
15582
15685
|
if (isAbsolute5(root) && file.startsWith(root + "/"))
|
|
@@ -15630,7 +15733,11 @@ var init_package_manager_guard = __esm(() => {
|
|
|
15630
15733
|
// ../events/dist/commander.js
|
|
15631
15734
|
import { chmod, mkdir, readFile, rename, writeFile } from "fs/promises";
|
|
15632
15735
|
import { Buffer as Buffer2 } from "buffer";
|
|
15736
|
+
import { existsSync as existsSync2 } from "fs";
|
|
15737
|
+
import { join as join3 } from "path";
|
|
15633
15738
|
import { existsSync } from "fs";
|
|
15739
|
+
import { homedir as homedir2 } from "os";
|
|
15740
|
+
import { join as join2, resolve } from "path";
|
|
15634
15741
|
import { homedir } from "os";
|
|
15635
15742
|
import { join } from "path";
|
|
15636
15743
|
import { createHmac, timingSafeEqual } from "crypto";
|
|
@@ -15736,13 +15843,106 @@ function channelMatchesEvent(channel, event) {
|
|
|
15736
15843
|
return true;
|
|
15737
15844
|
return channel.filters.some((filter) => eventMatchesFilter(event, filter));
|
|
15738
15845
|
}
|
|
15846
|
+
var KIND_ENV = {
|
|
15847
|
+
config: "HASNA_CONFIG_HOME",
|
|
15848
|
+
data: "HASNA_DATA_HOME",
|
|
15849
|
+
state: "HASNA_STATE_HOME",
|
|
15850
|
+
cache: "HASNA_CACHE_HOME"
|
|
15851
|
+
};
|
|
15852
|
+
var APP_SLUG_RE = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;
|
|
15853
|
+
function assertApp(app) {
|
|
15854
|
+
if (typeof app !== "string" || app.length === 0) {
|
|
15855
|
+
throw new TypeError("paths: app must be a non-empty string");
|
|
15856
|
+
}
|
|
15857
|
+
if (!APP_SLUG_RE.test(app)) {
|
|
15858
|
+
throw new TypeError(`paths: invalid app slug "${app}" \u2014 expected lowercase kebab-case ([a-z0-9]+(-[a-z0-9]+)*)`);
|
|
15859
|
+
}
|
|
15860
|
+
}
|
|
15861
|
+
function envOf(options) {
|
|
15862
|
+
return options.env ?? process.env;
|
|
15863
|
+
}
|
|
15864
|
+
function envValue(options, kind) {
|
|
15865
|
+
const value = envOf(options)[KIND_ENV[kind]];
|
|
15866
|
+
return typeof value === "string" && value.length > 0 ? value : undefined;
|
|
15867
|
+
}
|
|
15868
|
+
function isMacOS(platform) {
|
|
15869
|
+
return platform === "darwin";
|
|
15870
|
+
}
|
|
15871
|
+
function baseDir(kind, options) {
|
|
15872
|
+
const override = envValue(options, kind);
|
|
15873
|
+
if (override)
|
|
15874
|
+
return override;
|
|
15875
|
+
const home = options.home ?? homedir();
|
|
15876
|
+
const platform = options.platform ?? process.platform;
|
|
15877
|
+
if (isMacOS(platform)) {
|
|
15878
|
+
switch (kind) {
|
|
15879
|
+
case "config":
|
|
15880
|
+
case "data":
|
|
15881
|
+
return join(home, "Library", "Application Support", "Hasna");
|
|
15882
|
+
case "cache":
|
|
15883
|
+
return join(home, "Library", "Caches", "Hasna");
|
|
15884
|
+
case "state":
|
|
15885
|
+
return join(home, "Library", "Logs", "Hasna");
|
|
15886
|
+
}
|
|
15887
|
+
}
|
|
15888
|
+
switch (kind) {
|
|
15889
|
+
case "config":
|
|
15890
|
+
return join(home, ".config", "hasna");
|
|
15891
|
+
case "data":
|
|
15892
|
+
return join(home, ".local", "share", "hasna");
|
|
15893
|
+
case "state":
|
|
15894
|
+
return join(home, ".local", "state", "hasna");
|
|
15895
|
+
case "cache":
|
|
15896
|
+
return join(home, ".cache", "hasna");
|
|
15897
|
+
}
|
|
15898
|
+
}
|
|
15899
|
+
function resolvePath(kind, options) {
|
|
15900
|
+
assertApp(options.app);
|
|
15901
|
+
const appSegment = options.internal === true ? join("internal", options.app) : options.app;
|
|
15902
|
+
return join(baseDir(kind, options), appSegment);
|
|
15903
|
+
}
|
|
15904
|
+
function dataDir(options) {
|
|
15905
|
+
return resolvePath("data", options);
|
|
15906
|
+
}
|
|
15739
15907
|
var HASNA_EVENTS_DIR_ENV = "HASNA_EVENTS_DIR";
|
|
15740
15908
|
var HASNA_EVENTS_HOME_ENV = "HASNA_EVENTS_HOME";
|
|
15909
|
+
var EVENTS_STORE_SENTINEL_FILE = "events.json";
|
|
15910
|
+
function effectiveHome() {
|
|
15911
|
+
return process.env["HOME"] || process.env["USERPROFILE"] || homedir2();
|
|
15912
|
+
}
|
|
15913
|
+
function legacyHomeDir() {
|
|
15914
|
+
return join2(effectiveHome(), ".hasna", "events");
|
|
15915
|
+
}
|
|
15916
|
+
function resolverHome() {
|
|
15917
|
+
return dataDir({ app: "events", home: effectiveHome() || undefined });
|
|
15918
|
+
}
|
|
15919
|
+
function adoptResolverHome(resolved, env = process.env) {
|
|
15920
|
+
const dataOverride = env.HASNA_DATA_HOME;
|
|
15921
|
+
if (typeof dataOverride === "string" && dataOverride.trim().length > 0)
|
|
15922
|
+
return true;
|
|
15923
|
+
return existsSync(join2(resolved, EVENTS_STORE_SENTINEL_FILE));
|
|
15924
|
+
}
|
|
15925
|
+
function exactEventsHome() {
|
|
15926
|
+
const dir = process.env[HASNA_EVENTS_DIR_ENV];
|
|
15927
|
+
if (dir && dir.trim())
|
|
15928
|
+
return dir.trim();
|
|
15929
|
+
const home = process.env[HASNA_EVENTS_HOME_ENV];
|
|
15930
|
+
if (home && home.trim())
|
|
15931
|
+
return home.trim();
|
|
15932
|
+
return;
|
|
15933
|
+
}
|
|
15934
|
+
function getEventsHome() {
|
|
15935
|
+
const exact = exactEventsHome();
|
|
15936
|
+
if (exact)
|
|
15937
|
+
return resolve(exact);
|
|
15938
|
+
const resolved = resolverHome();
|
|
15939
|
+
return adoptResolverHome(resolved) ? resolve(resolved) : resolve(legacyHomeDir());
|
|
15940
|
+
}
|
|
15741
15941
|
var LOCAL_JSON_EVENT_CURSOR_PREFIX = "local-json-v1:";
|
|
15742
15942
|
var DEFAULT_EVENT_PAGE_LIMIT = 100;
|
|
15743
15943
|
var MAX_EVENT_PAGE_LIMIT = 1000;
|
|
15744
15944
|
function getEventsDataDir(override) {
|
|
15745
|
-
return override ||
|
|
15945
|
+
return override || getEventsHome();
|
|
15746
15946
|
}
|
|
15747
15947
|
function getActiveEventsDirEnv() {
|
|
15748
15948
|
if (process.env[HASNA_EVENTS_DIR_ENV])
|
|
@@ -15758,12 +15958,12 @@ class JsonEventsStore {
|
|
|
15758
15958
|
channelsPath;
|
|
15759
15959
|
eventsPath;
|
|
15760
15960
|
deliveriesPath;
|
|
15761
|
-
constructor(
|
|
15762
|
-
this.dataDir =
|
|
15763
|
-
this.runtime = localJsonRuntime(
|
|
15764
|
-
this.channelsPath =
|
|
15765
|
-
this.eventsPath =
|
|
15766
|
-
this.deliveriesPath =
|
|
15961
|
+
constructor(dataDir2 = getEventsDataDir()) {
|
|
15962
|
+
this.dataDir = dataDir2;
|
|
15963
|
+
this.runtime = localJsonRuntime(dataDir2);
|
|
15964
|
+
this.channelsPath = join3(dataDir2, "channels.json");
|
|
15965
|
+
this.eventsPath = join3(dataDir2, "events.json");
|
|
15966
|
+
this.deliveriesPath = join3(dataDir2, "deliveries.json");
|
|
15767
15967
|
}
|
|
15768
15968
|
async init() {
|
|
15769
15969
|
await mkdir(this.dataDir, { recursive: true, mode: 448 });
|
|
@@ -15880,7 +16080,7 @@ class JsonEventsStore {
|
|
|
15880
16080
|
};
|
|
15881
16081
|
}
|
|
15882
16082
|
async ensureArrayFile(path) {
|
|
15883
|
-
if (!
|
|
16083
|
+
if (!existsSync2(path)) {
|
|
15884
16084
|
await writeFile(path, `[]
|
|
15885
16085
|
`, { encoding: "utf-8", mode: 384 });
|
|
15886
16086
|
}
|
|
@@ -15910,7 +16110,7 @@ class JsonEventsStore {
|
|
|
15910
16110
|
});
|
|
15911
16111
|
}
|
|
15912
16112
|
}
|
|
15913
|
-
function localJsonRuntime(
|
|
16113
|
+
function localJsonRuntime(dataDir2 = getEventsDataDir()) {
|
|
15914
16114
|
return {
|
|
15915
16115
|
mode: "local-files",
|
|
15916
16116
|
name: "json-events-store",
|
|
@@ -15923,7 +16123,7 @@ function localJsonRuntime(dataDir = getEventsDataDir()) {
|
|
|
15923
16123
|
durable: true,
|
|
15924
16124
|
idempotency: "best-effort-local",
|
|
15925
16125
|
replayCursors: true,
|
|
15926
|
-
description: `Local JSON files in ${
|
|
16126
|
+
description: `Local JSON files in ${dataDir2}; no SQLite, Postgres, S3, or AWS runtime is configured by this store.`
|
|
15927
16127
|
};
|
|
15928
16128
|
}
|
|
15929
16129
|
function encodeLocalJsonEventCursor(offset, options = {}) {
|
|
@@ -15987,8 +16187,8 @@ function assertCursorFilter(name, cursorValue, optionValue) {
|
|
|
15987
16187
|
function findEventByIdentity(events, identity) {
|
|
15988
16188
|
return events.find((event) => identity.id !== undefined && event.id === identity.id || identity.dedupeKey !== undefined && event.dedupeKey === identity.dedupeKey);
|
|
15989
16189
|
}
|
|
15990
|
-
async function getEventsStatus(
|
|
15991
|
-
const store = new JsonEventsStore(
|
|
16190
|
+
async function getEventsStatus(dataDir2) {
|
|
16191
|
+
const store = new JsonEventsStore(dataDir2);
|
|
15992
16192
|
await store.init();
|
|
15993
16193
|
const [channels, events, deliveries] = await Promise.all([
|
|
15994
16194
|
store.listChannels(),
|
|
@@ -16030,9 +16230,9 @@ async function getEventsStatus(dataDir) {
|
|
|
16030
16230
|
}
|
|
16031
16231
|
};
|
|
16032
16232
|
}
|
|
16033
|
-
function statusFile(
|
|
16034
|
-
const path =
|
|
16035
|
-
return { path, exists:
|
|
16233
|
+
function statusFile(dataDir2, fileName, records) {
|
|
16234
|
+
const path = join3(dataDir2, fileName);
|
|
16235
|
+
return { path, exists: existsSync2(path), records };
|
|
16036
16236
|
}
|
|
16037
16237
|
var DEFAULT_SIGNATURE_TOLERANCE_MS = 5 * 60 * 1000;
|
|
16038
16238
|
function buildSignatureBase(timestamp, body) {
|
|
@@ -16371,7 +16571,7 @@ async function pinnedNativeRequest(target, addresses, method, headers, body, sig
|
|
|
16371
16571
|
callback(null, entries);
|
|
16372
16572
|
}
|
|
16373
16573
|
};
|
|
16374
|
-
return new Promise((
|
|
16574
|
+
return new Promise((resolve2, reject) => {
|
|
16375
16575
|
const request = isHttps ? nodeHttpsRequest(requestOptions, onResponse) : nodeHttpRequest(requestOptions, onResponse);
|
|
16376
16576
|
const onAbort = () => {
|
|
16377
16577
|
const error = new Error("The operation was aborted.");
|
|
@@ -16398,7 +16598,7 @@ async function pinnedNativeRequest(target, addresses, method, headers, body, sig
|
|
|
16398
16598
|
else if (Array.isArray(value))
|
|
16399
16599
|
headersRecord[name] = value.join(", ");
|
|
16400
16600
|
}
|
|
16401
|
-
|
|
16601
|
+
resolve2(new Response(Buffer.concat(chunks), { status: response.statusCode ?? 200, headers: headersRecord }));
|
|
16402
16602
|
});
|
|
16403
16603
|
}
|
|
16404
16604
|
});
|
|
@@ -16495,7 +16695,7 @@ async function dispatchCommand(event, channel) {
|
|
|
16495
16695
|
HASNA_EVENT_SCHEMA_VERSION: event.schemaVersion,
|
|
16496
16696
|
HASNA_EVENT_JSON: eventJson
|
|
16497
16697
|
};
|
|
16498
|
-
return new Promise((
|
|
16698
|
+
return new Promise((resolve2) => {
|
|
16499
16699
|
const child = spawn(channel.command.command, channel.command.args ?? [], {
|
|
16500
16700
|
cwd: channel.command.cwd,
|
|
16501
16701
|
env,
|
|
@@ -16513,7 +16713,7 @@ async function dispatchCommand(event, channel) {
|
|
|
16513
16713
|
});
|
|
16514
16714
|
child.on("error", (error) => {
|
|
16515
16715
|
clearTimeout(timeout);
|
|
16516
|
-
|
|
16716
|
+
resolve2({
|
|
16517
16717
|
attempt: 1,
|
|
16518
16718
|
status: "failed",
|
|
16519
16719
|
startedAt,
|
|
@@ -16526,7 +16726,7 @@ async function dispatchCommand(event, channel) {
|
|
|
16526
16726
|
child.on("close", (code, signal) => {
|
|
16527
16727
|
clearTimeout(timeout);
|
|
16528
16728
|
const success = code === 0;
|
|
16529
|
-
|
|
16729
|
+
resolve2({
|
|
16530
16730
|
attempt: 1,
|
|
16531
16731
|
status: success ? "success" : "failed",
|
|
16532
16732
|
startedAt,
|
|
@@ -17179,9 +17379,9 @@ var {
|
|
|
17179
17379
|
// src/cli/index.tsx
|
|
17180
17380
|
init_apply();
|
|
17181
17381
|
import chalk from "chalk";
|
|
17182
|
-
import { existsSync as
|
|
17183
|
-
import { homedir as
|
|
17184
|
-
import { basename as basename8, join as
|
|
17382
|
+
import { existsSync as existsSync23, lstatSync as lstatSync8, readFileSync as readFileSync17, readSync, writeSync } from "fs";
|
|
17383
|
+
import { homedir as homedir15 } from "os";
|
|
17384
|
+
import { basename as basename8, join as join25, resolve as resolve15 } from "path";
|
|
17185
17385
|
|
|
17186
17386
|
// src/lib/config-target-identity.ts
|
|
17187
17387
|
init_apply();
|
|
@@ -17227,15 +17427,15 @@ init_redact();
|
|
|
17227
17427
|
|
|
17228
17428
|
// src/lib/export.ts
|
|
17229
17429
|
init_config_store();
|
|
17230
|
-
import { existsSync as
|
|
17231
|
-
import { join as
|
|
17430
|
+
import { existsSync as existsSync14, mkdirSync as mkdirSync4, rmSync as rmSync3, writeFileSync as writeFileSync3 } from "fs";
|
|
17431
|
+
import { join as join17, resolve as resolve10 } from "path";
|
|
17232
17432
|
import { tmpdir } from "os";
|
|
17233
17433
|
async function exportConfigs(outputPath, opts = {}) {
|
|
17234
17434
|
const store = opts.store ?? resolveConfigStore();
|
|
17235
17435
|
const configs = await store.listConfigs(opts.filter);
|
|
17236
|
-
const absOutput =
|
|
17237
|
-
const tmpDir =
|
|
17238
|
-
const contentsDir =
|
|
17436
|
+
const absOutput = resolve10(outputPath);
|
|
17437
|
+
const tmpDir = join17(tmpdir(), `configs-export-${Date.now()}`);
|
|
17438
|
+
const contentsDir = join17(tmpDir, "contents");
|
|
17239
17439
|
try {
|
|
17240
17440
|
mkdirSync4(contentsDir, { recursive: true });
|
|
17241
17441
|
const manifest = {
|
|
@@ -17243,10 +17443,10 @@ async function exportConfigs(outputPath, opts = {}) {
|
|
|
17243
17443
|
exported_at: new Date().toISOString(),
|
|
17244
17444
|
configs: configs.map(({ content: _content, ...meta }) => meta)
|
|
17245
17445
|
};
|
|
17246
|
-
writeFileSync3(
|
|
17446
|
+
writeFileSync3(join17(tmpDir, "manifest.json"), JSON.stringify(manifest, null, 2), "utf-8");
|
|
17247
17447
|
for (const config of configs) {
|
|
17248
17448
|
const fileName = `${config.slug}.${config.format === "text" ? "txt" : config.format}`;
|
|
17249
|
-
writeFileSync3(
|
|
17449
|
+
writeFileSync3(join17(contentsDir, fileName), config.content, "utf-8");
|
|
17250
17450
|
}
|
|
17251
17451
|
const proc = Bun.spawn(["tar", "czf", absOutput, "-C", tmpDir, "."], {
|
|
17252
17452
|
stdout: "pipe",
|
|
@@ -17259,7 +17459,7 @@ async function exportConfigs(outputPath, opts = {}) {
|
|
|
17259
17459
|
}
|
|
17260
17460
|
return { path: absOutput, count: configs.length };
|
|
17261
17461
|
} finally {
|
|
17262
|
-
if (
|
|
17462
|
+
if (existsSync14(tmpDir)) {
|
|
17263
17463
|
rmSync3(tmpDir, { recursive: true, force: true });
|
|
17264
17464
|
}
|
|
17265
17465
|
}
|
|
@@ -17267,14 +17467,14 @@ async function exportConfigs(outputPath, opts = {}) {
|
|
|
17267
17467
|
|
|
17268
17468
|
// src/lib/import.ts
|
|
17269
17469
|
init_config_store();
|
|
17270
|
-
import { existsSync as
|
|
17271
|
-
import { join as
|
|
17470
|
+
import { existsSync as existsSync15, mkdirSync as mkdirSync5, readFileSync as readFileSync9, rmSync as rmSync4 } from "fs";
|
|
17471
|
+
import { join as join18, resolve as resolve11 } from "path";
|
|
17272
17472
|
import { tmpdir as tmpdir2 } from "os";
|
|
17273
17473
|
async function importConfigs(bundlePath, opts = {}) {
|
|
17274
17474
|
const store = opts.store ?? resolveConfigStore();
|
|
17275
17475
|
const conflict = opts.conflict ?? "skip";
|
|
17276
|
-
const absPath =
|
|
17277
|
-
const tmpDir =
|
|
17476
|
+
const absPath = resolve11(bundlePath);
|
|
17477
|
+
const tmpDir = join18(tmpdir2(), `configs-import-${Date.now()}`);
|
|
17278
17478
|
const result = { created: 0, updated: 0, skipped: 0, errors: [] };
|
|
17279
17479
|
try {
|
|
17280
17480
|
mkdirSync5(tmpDir, { recursive: true });
|
|
@@ -17287,15 +17487,15 @@ async function importConfigs(bundlePath, opts = {}) {
|
|
|
17287
17487
|
const stderr = await new Response(proc.stderr).text();
|
|
17288
17488
|
throw new Error(`tar extraction failed: ${stderr}`);
|
|
17289
17489
|
}
|
|
17290
|
-
const manifestPath =
|
|
17291
|
-
if (!
|
|
17490
|
+
const manifestPath = join18(tmpDir, "manifest.json");
|
|
17491
|
+
if (!existsSync15(manifestPath))
|
|
17292
17492
|
throw new Error("Invalid bundle: missing manifest.json");
|
|
17293
17493
|
const manifest = JSON.parse(readFileSync9(manifestPath, "utf-8"));
|
|
17294
17494
|
for (const meta of manifest.configs) {
|
|
17295
17495
|
try {
|
|
17296
17496
|
const ext = meta.format === "text" ? "txt" : meta.format;
|
|
17297
|
-
const contentFile =
|
|
17298
|
-
const content =
|
|
17497
|
+
const contentFile = join18(tmpDir, "contents", `${meta.slug}.${ext}`);
|
|
17498
|
+
const content = existsSync15(contentFile) ? readFileSync9(contentFile, "utf-8") : "";
|
|
17299
17499
|
let existing = null;
|
|
17300
17500
|
try {
|
|
17301
17501
|
existing = await store.getConfig(meta.slug);
|
|
@@ -17329,7 +17529,7 @@ async function importConfigs(bundlePath, opts = {}) {
|
|
|
17329
17529
|
}
|
|
17330
17530
|
return result;
|
|
17331
17531
|
} finally {
|
|
17332
|
-
if (
|
|
17532
|
+
if (existsSync15(tmpDir)) {
|
|
17333
17533
|
rmSync4(tmpDir, { recursive: true, force: true });
|
|
17334
17534
|
}
|
|
17335
17535
|
}
|
|
@@ -17346,14 +17546,14 @@ init_cursor_authority();
|
|
|
17346
17546
|
init_session_authority();
|
|
17347
17547
|
import { createHash as createHash8, randomUUID as randomUUID7 } from "crypto";
|
|
17348
17548
|
import {
|
|
17349
|
-
existsSync as
|
|
17549
|
+
existsSync as existsSync16,
|
|
17350
17550
|
lstatSync as lstatSync4,
|
|
17351
17551
|
mkdirSync as mkdirSync6,
|
|
17352
17552
|
readFileSync as readFileSync10,
|
|
17353
17553
|
readdirSync as readdirSync3,
|
|
17354
17554
|
statSync as statSync6
|
|
17355
17555
|
} from "fs";
|
|
17356
|
-
import { dirname as dirname6, isAbsolute as isAbsolute4, join as
|
|
17556
|
+
import { dirname as dirname6, isAbsolute as isAbsolute4, join as join19, parse as parse4, relative as relative5, resolve as resolve12 } from "path";
|
|
17357
17557
|
|
|
17358
17558
|
class SessionApplyError extends Error {
|
|
17359
17559
|
constructor(message) {
|
|
@@ -17485,13 +17685,13 @@ function assertClaudeAuthorityStillClear(plan, targetHome, ownedClaudeAuthoritie
|
|
|
17485
17685
|
throw new SessionApplyError(`Claude authority changed after planning; refusing to apply: ${summary}`);
|
|
17486
17686
|
}
|
|
17487
17687
|
function ensureSessionTargetHome(targetHome) {
|
|
17488
|
-
if (!
|
|
17688
|
+
if (!existsSync16(targetHome))
|
|
17489
17689
|
mkdirSync6(targetHome, { recursive: true, mode: 448 });
|
|
17490
17690
|
assertSafeTargetHome(targetHome);
|
|
17491
17691
|
}
|
|
17492
17692
|
function checkSessionRenderDrift(targetHome, manifestPath) {
|
|
17493
17693
|
const safeTargetHome = assertSafeTargetHome(targetHome);
|
|
17494
|
-
const resolvedManifestPath = manifestPath ? resolveManifestRelativePath(relative5(safeTargetHome,
|
|
17694
|
+
const resolvedManifestPath = manifestPath ? resolveManifestRelativePath(relative5(safeTargetHome, resolve12(manifestPath)), safeTargetHome) : resolve12(safeTargetHome, ".hasna", "session-render-manifest.json");
|
|
17495
17695
|
const checkedAt = new Date().toISOString();
|
|
17496
17696
|
const previousManifest = readPreviousManifest(resolvedManifestPath);
|
|
17497
17697
|
if (!previousManifest) {
|
|
@@ -17508,7 +17708,7 @@ function checkSessionRenderDrift(targetHome, manifestPath) {
|
|
|
17508
17708
|
const drifted = [];
|
|
17509
17709
|
for (const file of previousManifest.files) {
|
|
17510
17710
|
const target = resolveManifestRelativePath(file.relativePath, safeTargetHome);
|
|
17511
|
-
if (!
|
|
17711
|
+
if (!existsSync16(target)) {
|
|
17512
17712
|
missing.push({
|
|
17513
17713
|
path: target,
|
|
17514
17714
|
relativePath: file.relativePath,
|
|
@@ -17541,7 +17741,7 @@ function checkSessionRenderDrift(targetHome, manifestPath) {
|
|
|
17541
17741
|
function restoreSessionRenderSnapshot(snapshotPath, options = {}) {
|
|
17542
17742
|
const snapshot = readSessionRenderSnapshot(snapshotPath);
|
|
17543
17743
|
const targetHome = assertSafeTargetHome(snapshot.targetHome);
|
|
17544
|
-
const resolvedSnapshotPath =
|
|
17744
|
+
const resolvedSnapshotPath = resolve12(snapshotPath);
|
|
17545
17745
|
const snapshotRelativePath = relative5(targetHome, resolvedSnapshotPath);
|
|
17546
17746
|
if (snapshotRelativePath === "" || snapshotRelativePath === ".." || snapshotRelativePath.startsWith("../") || isAbsolute4(snapshotRelativePath)) {
|
|
17547
17747
|
throw new SessionApplyError("Session snapshot must be stored inside its target home.");
|
|
@@ -17659,8 +17859,8 @@ function requiredRestoreHash(file) {
|
|
|
17659
17859
|
return file.previousSha256;
|
|
17660
17860
|
}
|
|
17661
17861
|
function readSessionRenderSnapshot(snapshotPath) {
|
|
17662
|
-
const resolved =
|
|
17663
|
-
if (!
|
|
17862
|
+
const resolved = resolve12(snapshotPath);
|
|
17863
|
+
if (!existsSync16(resolved))
|
|
17664
17864
|
throw new SessionApplyError(`Session snapshot not found: ${snapshotPath}`);
|
|
17665
17865
|
const stat = lstatSync4(resolved);
|
|
17666
17866
|
if (stat.isSymbolicLink() || !stat.isFile()) {
|
|
@@ -17740,7 +17940,7 @@ function readSessionRenderSnapshot(snapshotPath) {
|
|
|
17740
17940
|
}
|
|
17741
17941
|
function reconstructPreRollbackLegacyV1Snapshot(snapshot, previousFiles, previousManifestFiles, targetHome, snapshotPath) {
|
|
17742
17942
|
assertNoNewerSessionSnapshot(snapshotPath, snapshot.createdAt, targetHome);
|
|
17743
|
-
const manifestPath =
|
|
17943
|
+
const manifestPath = resolve12(snapshot.manifestPath);
|
|
17744
17944
|
const manifestRelativePath = relative5(targetHome, manifestPath).replaceAll("\\", "/");
|
|
17745
17945
|
resolveSnapshotFilePath(manifestRelativePath, snapshot.manifestPath, targetHome);
|
|
17746
17946
|
const manifestSha256 = currentSessionFileHash(manifestPath, targetHome);
|
|
@@ -17757,7 +17957,7 @@ function reconstructPreRollbackLegacyV1Snapshot(snapshot, previousFiles, previou
|
|
|
17757
17957
|
throw new SessionApplyError(`Pre-rollback legacy v1 applied manifest is invalid: ${snapshotPath}`);
|
|
17758
17958
|
}
|
|
17759
17959
|
const appliedManifest = parsedManifest;
|
|
17760
|
-
if (appliedManifest.schema !== SESSION_RENDER_SCHEMA || appliedManifest.tool !== snapshot.tool || appliedManifest.profile !== snapshot.profile || typeof appliedManifest.targetHome !== "string" ||
|
|
17960
|
+
if (appliedManifest.schema !== SESSION_RENDER_SCHEMA || appliedManifest.tool !== snapshot.tool || appliedManifest.profile !== snapshot.profile || typeof appliedManifest.targetHome !== "string" || resolve12(appliedManifest.targetHome) !== targetHome || appliedManifest.targetKind !== "session-home" && appliedManifest.targetKind !== "project-root" || !Array.isArray(appliedManifest.files)) {
|
|
17761
17961
|
throw new SessionApplyError(`Pre-rollback legacy v1 applied manifest does not match its snapshot: ${snapshotPath}`);
|
|
17762
17962
|
}
|
|
17763
17963
|
const afterFiles = [];
|
|
@@ -17842,8 +18042,8 @@ function assertNoNewerSessionSnapshot(snapshotPath, createdAt, targetHome) {
|
|
|
17842
18042
|
throw new SessionApplyError(`Pre-rollback legacy v1 snapshot has an invalid creation time: ${snapshotPath}`);
|
|
17843
18043
|
}
|
|
17844
18044
|
for (const entry of readdirSync3(dirname6(snapshotPath))) {
|
|
17845
|
-
const candidatePath =
|
|
17846
|
-
if (candidatePath ===
|
|
18045
|
+
const candidatePath = resolve12(dirname6(snapshotPath), entry);
|
|
18046
|
+
if (candidatePath === resolve12(snapshotPath) || !entry.endsWith(".json"))
|
|
17847
18047
|
continue;
|
|
17848
18048
|
const candidateStat = lstatSync4(candidatePath);
|
|
17849
18049
|
if (candidateStat.isSymbolicLink() || !candidateStat.isFile() || candidateStat.size > 32 * 1024 * 1024)
|
|
@@ -17851,7 +18051,7 @@ function assertNoNewerSessionSnapshot(snapshotPath, createdAt, targetHome) {
|
|
|
17851
18051
|
try {
|
|
17852
18052
|
const candidate = JSON.parse(readFileSync10(candidatePath, "utf8"));
|
|
17853
18053
|
const candidateCreatedAtMs = typeof candidate.createdAt === "string" ? Date.parse(candidate.createdAt) : Number.NaN;
|
|
17854
|
-
if ((candidate.schema === "hasna.configs.session-render-snapshot/v1" || candidate.schema === "hasna.configs.session-render-snapshot/v2") && typeof candidate.targetHome === "string" &&
|
|
18054
|
+
if ((candidate.schema === "hasna.configs.session-render-snapshot/v1" || candidate.schema === "hasna.configs.session-render-snapshot/v2") && typeof candidate.targetHome === "string" && resolve12(candidate.targetHome) === targetHome && Number.isFinite(candidateCreatedAtMs) && candidateCreatedAtMs >= createdAtMs) {
|
|
17855
18055
|
throw new SessionApplyError(`Cannot restore pre-rollback legacy v1 snapshot after a newer session snapshot exists: ${candidatePath}`);
|
|
17856
18056
|
}
|
|
17857
18057
|
} catch (error) {
|
|
@@ -17920,14 +18120,14 @@ function inferLegacySnapshotAction(file, previousFiles, previousManifestFiles, p
|
|
|
17920
18120
|
}
|
|
17921
18121
|
function resolveSnapshotFilePath(relativePath, recordedPath, targetHome) {
|
|
17922
18122
|
const path = resolveManifestRelativePath(relativePath, targetHome);
|
|
17923
|
-
if (
|
|
18123
|
+
if (resolve12(recordedPath) !== path) {
|
|
17924
18124
|
throw new SessionApplyError(`Session snapshot file path mismatch for ${relativePath}`);
|
|
17925
18125
|
}
|
|
17926
18126
|
return path;
|
|
17927
18127
|
}
|
|
17928
18128
|
function planFileResult(plan, file, targetHome, previousHashes, previousManifest, options) {
|
|
17929
18129
|
const target = resolvePlannedFilePath(plan, file, targetHome);
|
|
17930
|
-
const previousContent =
|
|
18130
|
+
const previousContent = existsSync16(target) ? readFileSync10(target, "utf-8") : null;
|
|
17931
18131
|
const previousSha256 = previousContent === null ? null : sha2568(previousContent);
|
|
17932
18132
|
const previouslyManaged = isPreviouslyManaged(file, previousSha256, previousHashes, previousManifest);
|
|
17933
18133
|
const changed = previousContent !== file.content;
|
|
@@ -18026,7 +18226,7 @@ function planStaleFileResults(plan, targetHome, previousManifest, currentRelativ
|
|
|
18026
18226
|
}
|
|
18027
18227
|
function planStaleFileResult(file, targetHome, options) {
|
|
18028
18228
|
const target = resolveManifestRelativePath(file.relativePath, targetHome);
|
|
18029
|
-
if (!
|
|
18229
|
+
if (!existsSync16(target))
|
|
18030
18230
|
return null;
|
|
18031
18231
|
const previousContent = readFileSync10(target, "utf-8");
|
|
18032
18232
|
const previousSha256 = sha2568(previousContent);
|
|
@@ -18073,19 +18273,19 @@ function isPreviouslyManaged(file, previousSha256, previousHashes, previousManif
|
|
|
18073
18273
|
return previousHashes.get(file.relativePath) === previousSha256;
|
|
18074
18274
|
}
|
|
18075
18275
|
function resolvePlannedFilePath(plan, file, targetHome) {
|
|
18076
|
-
const target =
|
|
18276
|
+
const target = resolve12(targetHome, ...file.relativePath.split("/"));
|
|
18077
18277
|
const rel = relative5(targetHome, target);
|
|
18078
18278
|
if (rel === "" || rel === ".." || rel.startsWith("../") || isAbsolute4(rel)) {
|
|
18079
18279
|
throw new SessionApplyError(`Session file escapes target home: ${file.relativePath}`);
|
|
18080
18280
|
}
|
|
18081
|
-
if (
|
|
18281
|
+
if (resolve12(file.path) !== target) {
|
|
18082
18282
|
throw new SessionApplyError(`Session file path mismatch for ${file.relativePath}: ${file.path}`);
|
|
18083
18283
|
}
|
|
18084
18284
|
assertNoSymlinkSegments2(targetHome, target);
|
|
18085
18285
|
return target;
|
|
18086
18286
|
}
|
|
18087
18287
|
function resolveManifestRelativePath(relativePath, targetHome) {
|
|
18088
|
-
const target =
|
|
18288
|
+
const target = resolve12(targetHome, ...relativePath.split(/[\\/]+/));
|
|
18089
18289
|
const rel = relative5(targetHome, target);
|
|
18090
18290
|
if (rel === "" || rel === ".." || rel.startsWith("../") || isAbsolute4(rel)) {
|
|
18091
18291
|
throw new SessionApplyError(`Session manifest file escapes target home: ${relativePath}`);
|
|
@@ -18094,7 +18294,7 @@ function resolveManifestRelativePath(relativePath, targetHome) {
|
|
|
18094
18294
|
return target;
|
|
18095
18295
|
}
|
|
18096
18296
|
function readPreviousManifest(path) {
|
|
18097
|
-
if (!
|
|
18297
|
+
if (!existsSync16(path))
|
|
18098
18298
|
return null;
|
|
18099
18299
|
try {
|
|
18100
18300
|
const parsed = JSON.parse(readFileSync10(path, "utf-8"));
|
|
@@ -18136,7 +18336,7 @@ function assertExpectedSessionFileHash(path, targetHome, expectedHash) {
|
|
|
18136
18336
|
}
|
|
18137
18337
|
function currentSessionFileHash(path, targetHome) {
|
|
18138
18338
|
assertNoSymlinkSegments2(targetHome, path);
|
|
18139
|
-
if (!
|
|
18339
|
+
if (!existsSync16(path))
|
|
18140
18340
|
return null;
|
|
18141
18341
|
const stat = lstatSync4(path);
|
|
18142
18342
|
if (stat.isSymbolicLink() || !stat.isFile()) {
|
|
@@ -18151,7 +18351,7 @@ function requiredPreviousHash(result) {
|
|
|
18151
18351
|
return result.previousSha256;
|
|
18152
18352
|
}
|
|
18153
18353
|
function writeSessionSnapshot(plan, targetHome, manifestPath, results, previousManifest, coordination, allowPortableFallback, forcePortableFileOps) {
|
|
18154
|
-
const existingFiles = results.filter((result) => result.action === "update" || result.action === "delete").filter((result) =>
|
|
18354
|
+
const existingFiles = results.filter((result) => result.action === "update" || result.action === "delete").filter((result) => existsSync16(result.path)).map((result) => {
|
|
18155
18355
|
const content = readFileSync10(result.path, "utf-8");
|
|
18156
18356
|
return {
|
|
18157
18357
|
path: result.path,
|
|
@@ -18170,7 +18370,7 @@ function writeSessionSnapshot(plan, targetHome, manifestPath, results, previousM
|
|
|
18170
18370
|
};
|
|
18171
18371
|
}
|
|
18172
18372
|
const timestamp = new Date().toISOString().replace(/[:.]/g, "-");
|
|
18173
|
-
const snapshotPath =
|
|
18373
|
+
const snapshotPath = resolve12(targetHome, ".hasna", "session-render-snapshots", `${timestamp}-${randomUUID7()}.json`);
|
|
18174
18374
|
const afterFiles = results.map((result) => {
|
|
18175
18375
|
if (result.action === "conflict") {
|
|
18176
18376
|
throw new SessionApplyError(`Cannot snapshot unresolved conflict: ${result.relativePath}`);
|
|
@@ -18218,12 +18418,12 @@ function writeSessionSnapshot(plan, targetHome, manifestPath, results, previousM
|
|
|
18218
18418
|
function assertSafeTargetHome(targetHome) {
|
|
18219
18419
|
if (!isAbsolute4(targetHome))
|
|
18220
18420
|
throw new SessionApplyError(`Session target home must be absolute: ${targetHome}`);
|
|
18221
|
-
const normalized =
|
|
18421
|
+
const normalized = resolve12(targetHome);
|
|
18222
18422
|
if (normalized === parse4(normalized).root) {
|
|
18223
18423
|
throw new SessionApplyError(`Session target home cannot be the filesystem root: ${targetHome}`);
|
|
18224
18424
|
}
|
|
18225
18425
|
assertNoSymlinkAncestors2(normalized);
|
|
18226
|
-
if (
|
|
18426
|
+
if (existsSync16(normalized) && lstatSync4(normalized).isSymbolicLink()) {
|
|
18227
18427
|
throw new SessionApplyError(`Session target home cannot be a symlink: ${normalized}`);
|
|
18228
18428
|
}
|
|
18229
18429
|
return normalized;
|
|
@@ -18233,20 +18433,20 @@ function assertNoSymlinkSegments2(root, target) {
|
|
|
18233
18433
|
const rel = relative5(root, target);
|
|
18234
18434
|
let current = root;
|
|
18235
18435
|
for (const segment of rel.split(/[\\/]+/).filter(Boolean)) {
|
|
18236
|
-
current =
|
|
18237
|
-
if (
|
|
18436
|
+
current = join19(current, segment);
|
|
18437
|
+
if (existsSync16(current) && lstatSync4(current).isSymbolicLink()) {
|
|
18238
18438
|
throw new SessionApplyError(`Session apply path uses a symlink: ${current}`);
|
|
18239
18439
|
}
|
|
18240
18440
|
}
|
|
18241
18441
|
}
|
|
18242
18442
|
function assertNoSymlinkAncestors2(path) {
|
|
18243
|
-
const normalized =
|
|
18443
|
+
const normalized = resolve12(path);
|
|
18244
18444
|
const parsed = parse4(normalized);
|
|
18245
18445
|
let current = parsed.root;
|
|
18246
18446
|
const rel = relative5(parsed.root, normalized);
|
|
18247
18447
|
for (const segment of rel.split(/[\\/]+/).filter(Boolean)) {
|
|
18248
|
-
current =
|
|
18249
|
-
if (!
|
|
18448
|
+
current = join19(current, segment);
|
|
18449
|
+
if (!existsSync16(current))
|
|
18250
18450
|
return;
|
|
18251
18451
|
if (lstatSync4(current).isSymbolicLink()) {
|
|
18252
18452
|
throw new SessionApplyError(`Session apply path uses a symlink ancestor: ${current}`);
|
|
@@ -18295,10 +18495,11 @@ function formatGlobalSourceCoverageWarnings(result) {
|
|
|
18295
18495
|
}
|
|
18296
18496
|
|
|
18297
18497
|
// src/lib/station-profile.ts
|
|
18498
|
+
init_raw_store_root();
|
|
18298
18499
|
import { spawnSync } from "child_process";
|
|
18299
|
-
import { existsSync as
|
|
18300
|
-
import { arch as osArch, homedir as
|
|
18301
|
-
import { dirname as dirname7, join as
|
|
18500
|
+
import { existsSync as existsSync17, lstatSync as lstatSync5, mkdirSync as mkdirSync7, readFileSync as readFileSync11, readdirSync as readdirSync4, writeFileSync as writeFileSync4 } from "fs";
|
|
18501
|
+
import { arch as osArch, homedir as homedir12, hostname as osHostname, platform as osPlatform, userInfo as osUserInfo } from "os";
|
|
18502
|
+
import { dirname as dirname7, join as join20 } from "path";
|
|
18302
18503
|
var STATION_PROFILE_CACHE_FILENAME = "station-profile.md";
|
|
18303
18504
|
var STATION_PROFILE_SOURCE_ID = "station-profile";
|
|
18304
18505
|
var STATION_PROFILE_LAYER = "machine";
|
|
@@ -18308,22 +18509,21 @@ var STATION_PROFILE_FULL_NAMES_MAX = 6;
|
|
|
18308
18509
|
var STATION_PROFILE_PRIMARY_SCOPE = "@hasna";
|
|
18309
18510
|
var MACHINES_MANIFEST_PATH_ENV = "HASNA_MACHINES_MANIFEST_PATH";
|
|
18310
18511
|
var BUN_INSTALL_ENV = "BUN_INSTALL";
|
|
18311
|
-
function
|
|
18312
|
-
return env["HOME"] || env["USERPROFILE"] ||
|
|
18512
|
+
function homeDir3(env = process.env) {
|
|
18513
|
+
return env["HOME"] || env["USERPROFILE"] || homedir12();
|
|
18313
18514
|
}
|
|
18314
18515
|
function getStationProfileCachePath(env = process.env) {
|
|
18315
|
-
|
|
18316
|
-
return join16(resolve11(root), STATION_PROFILE_CACHE_FILENAME);
|
|
18516
|
+
return join20(getRawStoreRoot(env), STATION_PROFILE_CACHE_FILENAME);
|
|
18317
18517
|
}
|
|
18318
18518
|
function getMachinesManifestPath(env = process.env) {
|
|
18319
|
-
return env[MACHINES_MANIFEST_PATH_ENV] ||
|
|
18519
|
+
return env[MACHINES_MANIFEST_PATH_ENV] || join20(homeDir3(env), ".hasna", "machines", "machines.json");
|
|
18320
18520
|
}
|
|
18321
18521
|
function getBunGlobalModulesDir(env = process.env) {
|
|
18322
|
-
return
|
|
18522
|
+
return join20(env[BUN_INSTALL_ENV] || join20(homeDir3(env), ".bun"), "install", "global", "node_modules");
|
|
18323
18523
|
}
|
|
18324
18524
|
function readMachinesManifest(path) {
|
|
18325
18525
|
try {
|
|
18326
|
-
if (!
|
|
18526
|
+
if (!existsSync17(path))
|
|
18327
18527
|
return null;
|
|
18328
18528
|
const parsed = JSON.parse(readFileSync11(path, "utf8"));
|
|
18329
18529
|
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed))
|
|
@@ -18379,9 +18579,9 @@ function probeMachineStatus(machineId) {
|
|
|
18379
18579
|
function resolveStationProfileMachine(env = process.env, options = {}) {
|
|
18380
18580
|
const hostname2 = osHostname();
|
|
18381
18581
|
const record = findLocalManifestMachine(readMachinesManifest(getMachinesManifestPath(env)), hostname2);
|
|
18382
|
-
const home =
|
|
18582
|
+
const home = homeDir3(env);
|
|
18383
18583
|
const platform = stringField(record, "platform") ?? osPlatform();
|
|
18384
|
-
const workspacePath = stringField(record, "workspacePath") ??
|
|
18584
|
+
const workspacePath = stringField(record, "workspacePath") ?? join20(home, platform === "darwin" ? "Workspace" : "workspace");
|
|
18385
18585
|
const machine = {
|
|
18386
18586
|
id: stringField(record, "id") ?? hostname2,
|
|
18387
18587
|
hostname: stringField(record, "hostname") ?? hostname2,
|
|
@@ -18398,9 +18598,9 @@ function resolveStationProfileMachine(env = process.env, options = {}) {
|
|
|
18398
18598
|
return machine;
|
|
18399
18599
|
}
|
|
18400
18600
|
function scopedPackageNames(modulesDir, scope) {
|
|
18401
|
-
const scopeDir =
|
|
18601
|
+
const scopeDir = join20(modulesDir, scope);
|
|
18402
18602
|
try {
|
|
18403
|
-
if (!
|
|
18603
|
+
if (!existsSync17(scopeDir))
|
|
18404
18604
|
return null;
|
|
18405
18605
|
return readdirNames(scopeDir).sort();
|
|
18406
18606
|
} catch {
|
|
@@ -18410,7 +18610,7 @@ function scopedPackageNames(modulesDir, scope) {
|
|
|
18410
18610
|
function readdirNames(dir) {
|
|
18411
18611
|
return readdirSync4(dir).filter((name) => {
|
|
18412
18612
|
try {
|
|
18413
|
-
return lstatSync5(
|
|
18613
|
+
return lstatSync5(join20(dir, name)).isDirectory();
|
|
18414
18614
|
} catch {
|
|
18415
18615
|
return false;
|
|
18416
18616
|
}
|
|
@@ -18420,7 +18620,7 @@ function resolveStationProfilePackages(env = process.env) {
|
|
|
18420
18620
|
const modulesDir = getBunGlobalModulesDir(env);
|
|
18421
18621
|
let scopeDirs;
|
|
18422
18622
|
try {
|
|
18423
|
-
if (!
|
|
18623
|
+
if (!existsSync17(modulesDir))
|
|
18424
18624
|
return null;
|
|
18425
18625
|
scopeDirs = readdirNames(modulesDir).filter((name) => name.startsWith("@") && name.toLowerCase().includes("hasna"));
|
|
18426
18626
|
} catch {
|
|
@@ -18495,7 +18695,7 @@ function refreshStationProfile(options = {}) {
|
|
|
18495
18695
|
const path = getStationProfileCachePath(env);
|
|
18496
18696
|
const generatedAt = new Date().toISOString();
|
|
18497
18697
|
if (!options.dryRun) {
|
|
18498
|
-
const existing =
|
|
18698
|
+
const existing = existsSync17(path) ? readFileSync11(path, "utf8") : null;
|
|
18499
18699
|
if (existing !== content) {
|
|
18500
18700
|
mkdirSync7(dirname7(path), { recursive: true });
|
|
18501
18701
|
writeFileSync4(path, content, "utf8");
|
|
@@ -18514,7 +18714,7 @@ function refreshStationProfile(options = {}) {
|
|
|
18514
18714
|
function readStationProfile(env = process.env) {
|
|
18515
18715
|
const path = getStationProfileCachePath(env);
|
|
18516
18716
|
try {
|
|
18517
|
-
if (!
|
|
18717
|
+
if (!existsSync17(path))
|
|
18518
18718
|
return null;
|
|
18519
18719
|
return readFileSync11(path, "utf8");
|
|
18520
18720
|
} catch {
|
|
@@ -18853,7 +19053,7 @@ init_codewith_shared_todos_storage_standard();
|
|
|
18853
19053
|
import { createHash as createHash9 } from "crypto";
|
|
18854
19054
|
import { spawnSync as spawnSync2 } from "child_process";
|
|
18855
19055
|
import {
|
|
18856
|
-
existsSync as
|
|
19056
|
+
existsSync as existsSync18,
|
|
18857
19057
|
lstatSync as lstatSync6,
|
|
18858
19058
|
mkdirSync as mkdirSync8,
|
|
18859
19059
|
readFileSync as readFileSync12,
|
|
@@ -18861,8 +19061,8 @@ import {
|
|
|
18861
19061
|
rmSync as rmSync5,
|
|
18862
19062
|
writeFileSync as writeFileSync5
|
|
18863
19063
|
} from "fs";
|
|
18864
|
-
import { homedir as
|
|
18865
|
-
import { dirname as dirname8, join as
|
|
19064
|
+
import { homedir as homedir13 } from "os";
|
|
19065
|
+
import { dirname as dirname8, join as join21, parse as parse5, relative as relative6, resolve as resolve13 } from "path";
|
|
18866
19066
|
var INBOX_CONVERSATIONS_MINIMUM_VERSION = "0.5.28";
|
|
18867
19067
|
var INBOX_SKILL_MARKERS = [
|
|
18868
19068
|
[".claude", "skills", "inbox", "SKILL.md"],
|
|
@@ -18883,13 +19083,13 @@ function lstatOrNull(path) {
|
|
|
18883
19083
|
}
|
|
18884
19084
|
}
|
|
18885
19085
|
function findSymlinkedAncestor(path) {
|
|
18886
|
-
const normalized =
|
|
19086
|
+
const normalized = resolve13(path);
|
|
18887
19087
|
const parsed = parse5(normalized);
|
|
18888
19088
|
let current = parsed.root;
|
|
18889
19089
|
const rel = relative6(parsed.root, normalized);
|
|
18890
19090
|
for (const segment of rel.split(/[\\/]+/).filter(Boolean)) {
|
|
18891
|
-
current =
|
|
18892
|
-
if (!
|
|
19091
|
+
current = join21(current, segment);
|
|
19092
|
+
if (!existsSync18(current))
|
|
18893
19093
|
return null;
|
|
18894
19094
|
if (lstatSync6(current).isSymbolicLink())
|
|
18895
19095
|
return current;
|
|
@@ -18906,11 +19106,11 @@ function packagedInboxSkillPath(explicitPath) {
|
|
|
18906
19106
|
if (explicitPath)
|
|
18907
19107
|
return explicitPath;
|
|
18908
19108
|
const candidates = [
|
|
18909
|
-
|
|
18910
|
-
|
|
18911
|
-
|
|
19109
|
+
join21(import.meta.dir, "..", "..", "assets", "skills", "inbox", "SKILL.md"),
|
|
19110
|
+
join21(import.meta.dir, "..", "assets", "skills", "inbox", "SKILL.md"),
|
|
19111
|
+
join21(process.cwd(), "assets", "skills", "inbox", "SKILL.md")
|
|
18912
19112
|
];
|
|
18913
|
-
const found = candidates.find((candidate) =>
|
|
19113
|
+
const found = candidates.find((candidate) => existsSync18(candidate));
|
|
18914
19114
|
if (!found) {
|
|
18915
19115
|
throw new Error(`packaged inbox skill contract is missing (checked ${candidates.length} package-relative locations)`);
|
|
18916
19116
|
}
|
|
@@ -18959,8 +19159,8 @@ function compareVersions(left, right) {
|
|
|
18959
19159
|
}
|
|
18960
19160
|
return 0;
|
|
18961
19161
|
}
|
|
18962
|
-
function inspectSkillMarkers(
|
|
18963
|
-
return INBOX_SKILL_MARKERS.map((parts) =>
|
|
19162
|
+
function inspectSkillMarkers(homeDir4) {
|
|
19163
|
+
return INBOX_SKILL_MARKERS.map((parts) => join21(homeDir4, ...parts)).map((path) => {
|
|
18964
19164
|
const stat = lstatOrNull(path);
|
|
18965
19165
|
if (!stat)
|
|
18966
19166
|
return null;
|
|
@@ -18976,9 +19176,9 @@ function inspectSkillMarkers(homeDir3) {
|
|
|
18976
19176
|
}).filter((snapshot) => snapshot !== null);
|
|
18977
19177
|
}
|
|
18978
19178
|
function inspectInbox(options) {
|
|
18979
|
-
const
|
|
19179
|
+
const homeDir4 = options.homeDir ?? homedir13();
|
|
18980
19180
|
const runtimeCommand = options.conversationsCommand ?? "conversations";
|
|
18981
|
-
const snapshots = inspectSkillMarkers(
|
|
19181
|
+
const snapshots = inspectSkillMarkers(homeDir4);
|
|
18982
19182
|
const skillPresent = snapshots.length > 0;
|
|
18983
19183
|
let canonicalContent = null;
|
|
18984
19184
|
let canonicalSha256 = null;
|
|
@@ -19253,11 +19453,11 @@ init_project_context();
|
|
|
19253
19453
|
init_config_store();
|
|
19254
19454
|
init_apply();
|
|
19255
19455
|
init_config_agents();
|
|
19256
|
-
import { existsSync as
|
|
19456
|
+
import { existsSync as existsSync20, readFileSync as readFileSync14 } from "fs";
|
|
19257
19457
|
|
|
19258
19458
|
// src/lib/package-version.ts
|
|
19259
|
-
import { existsSync as
|
|
19260
|
-
import { dirname as dirname9, join as
|
|
19459
|
+
import { existsSync as existsSync19, readFileSync as readFileSync13 } from "fs";
|
|
19460
|
+
import { dirname as dirname9, join as join22 } from "path";
|
|
19261
19461
|
import { fileURLToPath } from "url";
|
|
19262
19462
|
var cached = null;
|
|
19263
19463
|
function getPackageVersion() {
|
|
@@ -19266,8 +19466,8 @@ function getPackageVersion() {
|
|
|
19266
19466
|
try {
|
|
19267
19467
|
let dir = dirname9(fileURLToPath(import.meta.url));
|
|
19268
19468
|
for (let i = 0;i < 8; i++) {
|
|
19269
|
-
const pkgPath =
|
|
19270
|
-
if (
|
|
19469
|
+
const pkgPath = join22(dir, "package.json");
|
|
19470
|
+
if (existsSync19(pkgPath)) {
|
|
19271
19471
|
const pkg = JSON.parse(readFileSync13(pkgPath, "utf8"));
|
|
19272
19472
|
if (pkg.name === "@hasna/instructions" && pkg.version) {
|
|
19273
19473
|
cached = pkg.version;
|
|
@@ -19331,7 +19531,7 @@ async function getConfigsStatus(store = resolveConfigStore(), options = {}) {
|
|
|
19331
19531
|
continue;
|
|
19332
19532
|
knownTargets += 1;
|
|
19333
19533
|
const targetPath = expandPath(config.target_path);
|
|
19334
|
-
if (!
|
|
19534
|
+
if (!existsSync20(targetPath)) {
|
|
19335
19535
|
missingTargets += 1;
|
|
19336
19536
|
continue;
|
|
19337
19537
|
}
|
|
@@ -19431,8 +19631,8 @@ init_config_store();
|
|
|
19431
19631
|
|
|
19432
19632
|
// src/lib/provider-context.ts
|
|
19433
19633
|
import { createHash as createHash10 } from "crypto";
|
|
19434
|
-
import { existsSync as
|
|
19435
|
-
import { join as
|
|
19634
|
+
import { existsSync as existsSync21, mkdirSync as mkdirSync9, readFileSync as readFileSync15, writeFileSync as writeFileSync6 } from "fs";
|
|
19635
|
+
import { join as join23 } from "path";
|
|
19436
19636
|
var PROVIDER_CONTEXT_DIR = ".hasna/provider-context";
|
|
19437
19637
|
var PROVIDER_CONTEXT_MANIFEST = "manifest.json";
|
|
19438
19638
|
var PROVIDER_CONTEXT_SCHEMA = "hasna.instructions.provider-context/v1";
|
|
@@ -19577,17 +19777,17 @@ function resolveAndRenderProviderContext(opts) {
|
|
|
19577
19777
|
const recordedEndpoint = originAccepted ? `${opts.origin.host}${opts.origin.pathPrefix || ""}` : null;
|
|
19578
19778
|
const reason = entry === null && opts.rawEndpoint ? originAccepted ? `endpoint "${recordedEndpoint}" is not in the provider-context registry; using the invariant fragment` : "endpoint rejected (embedded credentials or unparseable); using the invariant fragment" : null;
|
|
19579
19779
|
const content = renderProviderFragment(entry);
|
|
19580
|
-
const dir =
|
|
19581
|
-
if (!
|
|
19780
|
+
const dir = join23(opts.homeDir, PROVIDER_CONTEXT_DIR);
|
|
19781
|
+
if (!existsSync21(dir))
|
|
19582
19782
|
mkdirSync9(dir, { recursive: true });
|
|
19583
19783
|
const filename = `${entry ? entry.key : "invariant"}.md`;
|
|
19584
|
-
const fragmentPath2 =
|
|
19784
|
+
const fragmentPath2 = join23(dir, filename);
|
|
19585
19785
|
const fragmentSha256 = sha25610(content);
|
|
19586
19786
|
writeFileSync6(fragmentPath2, content, "utf8");
|
|
19587
|
-
const manifestPath =
|
|
19787
|
+
const manifestPath = join23(dir, PROVIDER_CONTEXT_MANIFEST);
|
|
19588
19788
|
let manifest = { schema: PROVIDER_CONTEXT_SCHEMA, fragments: {} };
|
|
19589
19789
|
try {
|
|
19590
|
-
if (
|
|
19790
|
+
if (existsSync21(manifestPath)) {
|
|
19591
19791
|
const parsed = JSON.parse(readFileSync15(manifestPath, "utf8"));
|
|
19592
19792
|
if (parsed && typeof parsed === "object")
|
|
19593
19793
|
manifest = parsed;
|
|
@@ -19731,7 +19931,7 @@ function parseSessionSource(value, order) {
|
|
|
19731
19931
|
if (!path)
|
|
19732
19932
|
throw new Error(`Invalid --source "${value}" (expected path or id=path)`);
|
|
19733
19933
|
const absPath = resolveSessionPath(path);
|
|
19734
|
-
if (!
|
|
19934
|
+
if (!existsSync23(absPath))
|
|
19735
19935
|
throw new Error(`Instruction source file not found: ${absPath}`);
|
|
19736
19936
|
const content = readSessionInstructionSourceFile(absPath);
|
|
19737
19937
|
const source = sourceFromFilePath(absPath, content, order);
|
|
@@ -19812,7 +20012,7 @@ async function collectSessionSources(opts, tool, store) {
|
|
|
19812
20012
|
}
|
|
19813
20013
|
for (const value of opts.identityExport ?? []) {
|
|
19814
20014
|
const path = resolveSessionPath(value);
|
|
19815
|
-
if (!
|
|
20015
|
+
if (!existsSync23(path))
|
|
19816
20016
|
throw new Error(`Identity instruction export not found: ${path}`);
|
|
19817
20017
|
const parsed = JSON.parse(readFileSync17(path, "utf-8"));
|
|
19818
20018
|
sources.push(...sourcesFromIdentityExport(parsed, { path, tool, orderOffset: sources.length }));
|
|
@@ -19946,7 +20146,7 @@ function readProjectContextBundleOption(value, allowMissing = false) {
|
|
|
19946
20146
|
if (value === "-")
|
|
19947
20147
|
return { json: readBoundedProjectContextStdin() };
|
|
19948
20148
|
const path = resolveSessionPath(value);
|
|
19949
|
-
if (!
|
|
20149
|
+
if (!existsSync23(path)) {
|
|
19950
20150
|
if (allowMissing)
|
|
19951
20151
|
return {};
|
|
19952
20152
|
throw new ProjectContextError("PROJECT_CONTEXT_INPUT_MISSING", `bundle file not found: ${path}`);
|
|
@@ -20117,8 +20317,8 @@ program.command("tag <id>").description("Add or remove tags on a stored config (
|
|
|
20117
20317
|
console.log(chalk.green("\u2713") + ` Tags on ${chalk.bold(updated.name)} ${chalk.dim(`(${updated.slug})`)}: ${nextTags.join(", ") || chalk.dim("(none)")}`);
|
|
20118
20318
|
});
|
|
20119
20319
|
program.command("add <path>").description("Ingest a file into the config DB").option("-n, --name <name>", "config name (defaults to filename)").option("-c, --category <cat>", "category override").option("-a, --agent <agent>", "agent override").option("-k, --kind <kind>", "kind: file|reference", "file").option("--template", "mark as template (has {{VAR}} placeholders)").option("--update", "if a config already owns this path, update that row in place instead of refusing").action(async (filePath, opts) => {
|
|
20120
|
-
const abs =
|
|
20121
|
-
if (!
|
|
20320
|
+
const abs = resolve15(filePath);
|
|
20321
|
+
if (!existsSync23(abs)) {
|
|
20122
20322
|
console.error(chalk.red(`File not found: ${abs}`));
|
|
20123
20323
|
process.exit(1);
|
|
20124
20324
|
}
|
|
@@ -20126,7 +20326,7 @@ program.command("add <path>").description("Ingest a file into the config DB").op
|
|
|
20126
20326
|
const storedFmt = detectFormat(abs);
|
|
20127
20327
|
const fmt = redactFormatForTarget(abs, storedFmt);
|
|
20128
20328
|
const { content, redacted, isTemplate: isTemplate2 } = redactContent(rawContent, fmt);
|
|
20129
|
-
const targetPath = abs.startsWith(
|
|
20329
|
+
const targetPath = abs.startsWith(homedir15()) ? abs.replace(homedir15(), "~") : abs;
|
|
20130
20330
|
const name = opts.name || filePath.split("/").pop();
|
|
20131
20331
|
const store = resolveConfigStore();
|
|
20132
20332
|
const allConfigs = await store.listConfigs();
|
|
@@ -20301,7 +20501,7 @@ program.command("sync").description("Sync known AI coding configs from disk into
|
|
|
20301
20501
|
for (const entry of entries) {
|
|
20302
20502
|
if (!entry.isDirectory())
|
|
20303
20503
|
continue;
|
|
20304
|
-
const projDir =
|
|
20504
|
+
const projDir = join25(absDir, entry.name);
|
|
20305
20505
|
const hasAgentConfig = [
|
|
20306
20506
|
"CLAUDE.md",
|
|
20307
20507
|
".mcp.json",
|
|
@@ -20314,7 +20514,7 @@ program.command("sync").description("Sync known AI coding configs from disk into
|
|
|
20314
20514
|
".aicopilot",
|
|
20315
20515
|
".cursor",
|
|
20316
20516
|
".agents"
|
|
20317
|
-
].some((marker) =>
|
|
20517
|
+
].some((marker) => existsSync23(join25(projDir, marker)));
|
|
20318
20518
|
if (!hasAgentConfig)
|
|
20319
20519
|
continue;
|
|
20320
20520
|
const result2 = await syncProject({ projectDir: projDir, dryRun: opts.dryRun, store });
|
|
@@ -20365,7 +20565,7 @@ program.command("import <file>").description("Import configs from a tar.gz bundl
|
|
|
20365
20565
|
});
|
|
20366
20566
|
program.command("whoami").description("Show setup summary").action(async () => {
|
|
20367
20567
|
const store = resolveConfigStore();
|
|
20368
|
-
const dbPath = isApiTransport() ? `${process.env["HASNA_INSTRUCTIONS_API_URL"]}/v1` : process.env["HASNA_INSTRUCTIONS_DB_PATH"] ||
|
|
20568
|
+
const dbPath = isApiTransport() ? `${process.env["HASNA_INSTRUCTIONS_API_URL"]}/v1` : process.env["HASNA_INSTRUCTIONS_DB_PATH"] || join25(getRawStoreRoot(), "instructions.db");
|
|
20369
20569
|
const stats = await store.getConfigStats();
|
|
20370
20570
|
console.log(chalk.bold("@hasna/instructions") + chalk.dim(" v" + pkg.version));
|
|
20371
20571
|
console.log(chalk.cyan(isApiTransport() ? "API:" : "DB:") + " " + dbPath);
|
|
@@ -21244,7 +21444,7 @@ mcpCmd.command("install").alias("add").description("Install configs MCP server i
|
|
|
21244
21444
|
} else if (target === "codex") {
|
|
21245
21445
|
const { appendFileSync, existsSync: ex } = await import("fs");
|
|
21246
21446
|
const { join: j } = await import("path");
|
|
21247
|
-
const configPath = j(
|
|
21447
|
+
const configPath = j(homedir15(), ".codex", "config.toml");
|
|
21248
21448
|
const block = `
|
|
21249
21449
|
[mcp_servers.configs]
|
|
21250
21450
|
command = "${mcpBinary}"
|
|
@@ -21262,7 +21462,7 @@ args = []
|
|
|
21262
21462
|
} else if (target === "antigravity") {
|
|
21263
21463
|
const { mkdirSync: md, readFileSync: rf, writeFileSync: wf, existsSync: ex } = await import("fs");
|
|
21264
21464
|
const { dirname: dn, join: j } = await import("path");
|
|
21265
|
-
const configPath = j(
|
|
21465
|
+
const configPath = j(homedir15(), ".gemini", "config", "mcp_config.json");
|
|
21266
21466
|
let settings = {};
|
|
21267
21467
|
if (ex(configPath)) {
|
|
21268
21468
|
try {
|
|
@@ -21346,7 +21546,7 @@ DB stats:`));
|
|
|
21346
21546
|
if (count > 0)
|
|
21347
21547
|
console.log(` ${key.padEnd(18)} ${count}`);
|
|
21348
21548
|
}
|
|
21349
|
-
const location = isApiTransport() ? `${process.env["HASNA_INSTRUCTIONS_API_URL"]}/v1` : process.env["HASNA_INSTRUCTIONS_DB_PATH"] ||
|
|
21549
|
+
const location = isApiTransport() ? `${process.env["HASNA_INSTRUCTIONS_API_URL"]}/v1` : process.env["HASNA_INSTRUCTIONS_DB_PATH"] || join25(getRawStoreRoot(), "instructions.db");
|
|
21350
21550
|
console.log(chalk.dim(`
|
|
21351
21551
|
${isApiTransport() ? "API" : "DB"}: ${location}`));
|
|
21352
21552
|
});
|
|
@@ -21407,10 +21607,10 @@ managedSkillsCmd.command("apply").option("--dry-run", "preview without writing")
|
|
|
21407
21607
|
});
|
|
21408
21608
|
program.command("backup").description("Export configs to a timestamped backup file").action(async () => {
|
|
21409
21609
|
const { mkdirSync: mk } = await import("fs");
|
|
21410
|
-
const backupDir =
|
|
21610
|
+
const backupDir = join25(getRawStoreRoot(), "backups");
|
|
21411
21611
|
mk(backupDir, { recursive: true });
|
|
21412
21612
|
const ts = new Date().toISOString().replace(/[:.]/g, "-").replace("T", "-").slice(0, 19);
|
|
21413
|
-
const outPath =
|
|
21613
|
+
const outPath = join25(backupDir, `configs-${ts}.tar.gz`);
|
|
21414
21614
|
const result = await exportConfigs(outPath, { store: resolveConfigStore() });
|
|
21415
21615
|
const { statSync: st } = await import("fs");
|
|
21416
21616
|
const size = st(outPath).size;
|
|
@@ -21438,9 +21638,9 @@ program.command("doctor").description("Validate configs: syntax, permissions, mi
|
|
|
21438
21638
|
console.log(chalk.cyan("Known files on disk:"));
|
|
21439
21639
|
for (const k of KNOWN_CONFIGS) {
|
|
21440
21640
|
if (k.rulesDir) {
|
|
21441
|
-
|
|
21641
|
+
existsSync23(expandPath(k.rulesDir)) ? pass(`${k.rulesDir}/ exists`) : k.optional ? skip(`${k.rulesDir}/ (optional)`) : fail2(`${k.rulesDir}/ not found`);
|
|
21442
21642
|
} else {
|
|
21443
|
-
|
|
21643
|
+
existsSync23(expandPath(k.path)) ? pass(k.path) : k.optional ? skip(`${k.path} (optional)`) : fail2(`${k.path} not found`);
|
|
21444
21644
|
}
|
|
21445
21645
|
}
|
|
21446
21646
|
const allConfigs = await store.listConfigs();
|
|
@@ -21594,16 +21794,16 @@ program.command("watch").description("Watch known config files for changes and a
|
|
|
21594
21794
|
for (const k of KNOWN_CONFIGS) {
|
|
21595
21795
|
if (k.rulesDir) {
|
|
21596
21796
|
const absDir = expandPath2(k.rulesDir);
|
|
21597
|
-
if (!
|
|
21797
|
+
if (!existsSync23(absDir))
|
|
21598
21798
|
continue;
|
|
21599
21799
|
const { readdirSync: readdirSync6 } = await import("fs");
|
|
21600
21800
|
for (const f of readdirSync6(absDir).filter((f2) => f2.endsWith(".md"))) {
|
|
21601
|
-
const abs =
|
|
21801
|
+
const abs = join25(absDir, f);
|
|
21602
21802
|
mtimes.set(abs, st(abs).mtimeMs);
|
|
21603
21803
|
}
|
|
21604
21804
|
} else {
|
|
21605
21805
|
const abs = expandPath2(k.path);
|
|
21606
|
-
if (
|
|
21806
|
+
if (existsSync23(abs))
|
|
21607
21807
|
mtimes.set(abs, st(abs).mtimeMs);
|
|
21608
21808
|
}
|
|
21609
21809
|
}
|
|
@@ -21611,7 +21811,7 @@ program.command("watch").description("Watch known config files for changes and a
|
|
|
21611
21811
|
const tick = async () => {
|
|
21612
21812
|
let changed = 0;
|
|
21613
21813
|
for (const [abs, oldMtime] of mtimes) {
|
|
21614
|
-
if (!
|
|
21814
|
+
if (!existsSync23(abs))
|
|
21615
21815
|
continue;
|
|
21616
21816
|
const newMtime = st(abs).mtimeMs;
|
|
21617
21817
|
if (newMtime !== oldMtime) {
|
|
@@ -21623,10 +21823,10 @@ program.command("watch").description("Watch known config files for changes and a
|
|
|
21623
21823
|
for (const k of KNOWN_CONFIGS) {
|
|
21624
21824
|
if (k.rulesDir) {
|
|
21625
21825
|
const absDir = expandPath2(k.rulesDir);
|
|
21626
|
-
if (!
|
|
21826
|
+
if (!existsSync23(absDir))
|
|
21627
21827
|
continue;
|
|
21628
21828
|
for (const f of rd(absDir).filter((f2) => f2.endsWith(".md"))) {
|
|
21629
|
-
const abs =
|
|
21829
|
+
const abs = join25(absDir, f);
|
|
21630
21830
|
if (!mtimes.has(abs)) {
|
|
21631
21831
|
mtimes.set(abs, st(abs).mtimeMs);
|
|
21632
21832
|
changed++;
|
|
@@ -21634,7 +21834,7 @@ program.command("watch").description("Watch known config files for changes and a
|
|
|
21634
21834
|
}
|
|
21635
21835
|
} else {
|
|
21636
21836
|
const abs = expandPath2(k.path);
|
|
21637
|
-
if (
|
|
21837
|
+
if (existsSync23(abs) && !mtimes.has(abs)) {
|
|
21638
21838
|
mtimes.set(abs, st(abs).mtimeMs);
|
|
21639
21839
|
changed++;
|
|
21640
21840
|
}
|
|
@@ -21662,7 +21862,7 @@ program.command("report").description("Summary of stored configs, drift, and eco
|
|
|
21662
21862
|
if (!c.target_path)
|
|
21663
21863
|
continue;
|
|
21664
21864
|
const abs = expandPath(c.target_path);
|
|
21665
|
-
if (!
|
|
21865
|
+
if (!existsSync23(abs)) {
|
|
21666
21866
|
missing++;
|
|
21667
21867
|
continue;
|
|
21668
21868
|
}
|
|
@@ -21733,7 +21933,7 @@ program.command("clean").description("Remove configs from DB whose target files
|
|
|
21733
21933
|
if (!c.target_path)
|
|
21734
21934
|
continue;
|
|
21735
21935
|
const abs = expandPath(c.target_path);
|
|
21736
|
-
if (!
|
|
21936
|
+
if (!existsSync23(abs)) {
|
|
21737
21937
|
if (printed < maxPrinted) {
|
|
21738
21938
|
if (opts.dryRun) {
|
|
21739
21939
|
console.log(chalk.yellow(" would remove:") + ` ${c.slug} ${chalk.dim(`(${truncateMiddle(c.target_path, 88)})`)}`);
|
|
@@ -21879,13 +22079,13 @@ providerContextCmd.command("resolve").description("Resolve the endpoint to a pro
|
|
|
21879
22079
|
try {
|
|
21880
22080
|
const rawEndpoint = opts.endpoint ?? process.env["ANTHROPIC_BASE_URL"] ?? "";
|
|
21881
22081
|
const rawModel = opts.model ?? process.env["ANTHROPIC_MODEL"] ?? "";
|
|
21882
|
-
const
|
|
22082
|
+
const homeDir4 = opts.home ?? homedir15();
|
|
21883
22083
|
const origin = normalizeEndpointOrigin(rawEndpoint);
|
|
21884
22084
|
const resolution = resolveAndRenderProviderContext({
|
|
21885
22085
|
origin,
|
|
21886
22086
|
rawEndpoint,
|
|
21887
22087
|
rawModel,
|
|
21888
|
-
homeDir:
|
|
22088
|
+
homeDir: homeDir4
|
|
21889
22089
|
});
|
|
21890
22090
|
if (opts.json) {
|
|
21891
22091
|
printJson({
|