@hasna/skills 0.10.1 → 0.10.2
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 +32 -0
- package/bin/index.js +352 -119
- package/bin/mcp.js +229 -42
- package/bin/migrate.js +2 -6
- package/bin/server.js +5 -6
- package/bin/worker.js +2 -6
- package/dist/index.js +239 -60
- package/dist/lib/selection-cache.d.ts +12 -0
- package/dist/sdk/index.js +312 -134
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -6988,7 +6988,7 @@ var require_public_api = __commonJS((exports) => {
|
|
|
6988
6988
|
});
|
|
6989
6989
|
|
|
6990
6990
|
// src/lib/registry.ts
|
|
6991
|
-
import { existsSync as existsSync14, readFileSync as
|
|
6991
|
+
import { existsSync as existsSync14, readFileSync as readFileSync18, readdirSync as readdirSync11 } from "fs";
|
|
6992
6992
|
import { join as join29 } from "path";
|
|
6993
6993
|
|
|
6994
6994
|
// src/lib/config.ts
|
|
@@ -9091,7 +9091,7 @@ function assertAgentPolicyCollections(policy) {
|
|
|
9091
9091
|
|
|
9092
9092
|
// src/lib/agent-discovery.ts
|
|
9093
9093
|
import { createHash as createHash16 } from "crypto";
|
|
9094
|
-
import { lstatSync as lstatSync20, readFileSync as
|
|
9094
|
+
import { lstatSync as lstatSync20, readFileSync as readFileSync17, readdirSync as readdirSync9, realpathSync as realpathSync4 } from "fs";
|
|
9095
9095
|
import { basename as basename8, dirname as dirname16, isAbsolute as isAbsolute14, join as join26, resolve as resolve14, sep as sep5 } from "path";
|
|
9096
9096
|
import { isDeepStrictEqual as isDeepStrictEqual3 } from "util";
|
|
9097
9097
|
|
|
@@ -9611,7 +9611,7 @@ import { isAbsolute as isAbsolute11, join as join23, resolve as resolve11 } from
|
|
|
9611
9611
|
// package.json
|
|
9612
9612
|
var package_default = {
|
|
9613
9613
|
name: "@hasna/skills",
|
|
9614
|
-
version: "0.10.
|
|
9614
|
+
version: "0.10.2",
|
|
9615
9615
|
description: "Skills library for AI coding agents",
|
|
9616
9616
|
type: "module",
|
|
9617
9617
|
bin: {
|
|
@@ -11823,7 +11823,9 @@ function tarOctal(field) {
|
|
|
11823
11823
|
|
|
11824
11824
|
// src/lib/selection-cache.ts
|
|
11825
11825
|
import { createHash as createHash7, randomUUID } from "crypto";
|
|
11826
|
-
import {
|
|
11826
|
+
import { spawnSync as spawnSync2 } from "child_process";
|
|
11827
|
+
import { closeSync as closeSync6, constants as constants3, fstatSync as fstatSync6, fsyncSync, lstatSync as lstatSync9, mkdirSync as mkdirSync3, openSync as openSync6, readFileSync as readFileSync9, readlinkSync as readlinkSync2, readSync as readSync3, renameSync, unlinkSync, writeFileSync as writeFileSync3 } from "fs";
|
|
11828
|
+
import { hostname } from "os";
|
|
11827
11829
|
import { dirname as dirname8, join as join12, parse as parse2, resolve as resolve7 } from "path";
|
|
11828
11830
|
import { isDeepStrictEqual } from "util";
|
|
11829
11831
|
|
|
@@ -12124,6 +12126,166 @@ function readSkillSessionSnapshot(sessionId, options = {}) {
|
|
|
12124
12126
|
function skillSessionSnapshotBinding(snapshot) {
|
|
12125
12127
|
return { sessionId: snapshot.sessionId, generation: snapshot.generation, receiptSha256: snapshot.receiptSha256 };
|
|
12126
12128
|
}
|
|
12129
|
+
var SESSION_LOCK_MAX_BYTES = 4096;
|
|
12130
|
+
var SESSION_LOCK_MIN_AGE_MS = 30000;
|
|
12131
|
+
function localBootId() {
|
|
12132
|
+
try {
|
|
12133
|
+
if (process.platform === "linux") {
|
|
12134
|
+
const value = readFileSync9("/proc/sys/kernel/random/boot_id", "utf8").trim();
|
|
12135
|
+
return /^[a-f0-9-]{36}$/i.test(value) ? value : null;
|
|
12136
|
+
}
|
|
12137
|
+
if (process.platform === "darwin") {
|
|
12138
|
+
const result = spawnSync2("/usr/sbin/sysctl", ["-n", "kern.boottime"], { encoding: "utf8", timeout: 3000, env: { LC_ALL: "C" } });
|
|
12139
|
+
if (result.status !== 0 || result.error)
|
|
12140
|
+
return null;
|
|
12141
|
+
const seconds = /\bsec\s*=\s*(\d+)\b/.exec(result.stdout)?.[1];
|
|
12142
|
+
return seconds ? `darwin:${seconds}` : null;
|
|
12143
|
+
}
|
|
12144
|
+
} catch {}
|
|
12145
|
+
return null;
|
|
12146
|
+
}
|
|
12147
|
+
function processStart(pid) {
|
|
12148
|
+
if (!Number.isSafeInteger(pid) || pid <= 0)
|
|
12149
|
+
return { state: "unknown" };
|
|
12150
|
+
if (process.platform === "linux") {
|
|
12151
|
+
try {
|
|
12152
|
+
const stat = readFileSync9(`/proc/${pid}/stat`, "utf8");
|
|
12153
|
+
const close = stat.lastIndexOf(")");
|
|
12154
|
+
const start = close < 0 ? undefined : stat.slice(close + 2).trim().split(/\s+/)[19];
|
|
12155
|
+
return start && /^\d+$/.test(start) ? { state: "alive", start: `linux:${start}` } : { state: "unknown" };
|
|
12156
|
+
} catch (error) {
|
|
12157
|
+
return { state: error.code === "ENOENT" ? "absent" : "unknown" };
|
|
12158
|
+
}
|
|
12159
|
+
}
|
|
12160
|
+
if (process.platform === "darwin") {
|
|
12161
|
+
const result = spawnSync2("/bin/ps", ["-p", String(pid), "-o", "lstart="], { encoding: "utf8", timeout: 3000, env: { LC_ALL: "C" } });
|
|
12162
|
+
if (result.error || result.signal)
|
|
12163
|
+
return { state: "unknown" };
|
|
12164
|
+
const start = result.stdout.trim();
|
|
12165
|
+
if (result.status === 1 && !start && !result.stderr.trim())
|
|
12166
|
+
return { state: "absent" };
|
|
12167
|
+
return result.status === 0 && start ? { state: "alive", start: `darwin:${start}` } : { state: "unknown" };
|
|
12168
|
+
}
|
|
12169
|
+
return { state: "unknown" };
|
|
12170
|
+
}
|
|
12171
|
+
function localLockIdentity() {
|
|
12172
|
+
const bootId = localBootId(), owner = processStart(process.pid);
|
|
12173
|
+
if (!bootId || owner.state !== "alive")
|
|
12174
|
+
return null;
|
|
12175
|
+
let pidNamespace;
|
|
12176
|
+
if (process.platform === "linux") {
|
|
12177
|
+
try {
|
|
12178
|
+
pidNamespace = readlinkSync2("/proc/self/ns/pid");
|
|
12179
|
+
} catch {
|
|
12180
|
+
return null;
|
|
12181
|
+
}
|
|
12182
|
+
if (!/^pid:\[\d+\]$/.test(pidNamespace))
|
|
12183
|
+
return null;
|
|
12184
|
+
}
|
|
12185
|
+
return { host: hostname(), bootId, pidNamespace, processStart: owner.start };
|
|
12186
|
+
}
|
|
12187
|
+
function readSessionLock(sessionId, options) {
|
|
12188
|
+
const path = `${sessionReceiptPath(sessionId, options)}.write-lock`;
|
|
12189
|
+
const before = lstatSync9(path, { throwIfNoEntry: false });
|
|
12190
|
+
if (!before)
|
|
12191
|
+
return null;
|
|
12192
|
+
if (!before.isFile() || before.nlink !== 1 || process.getuid && before.uid !== process.getuid()) {
|
|
12193
|
+
throw new SkillSelectionError("SESSION_WRITE_LOCKED", "The session lock is not a private regular file; recovery requires review.");
|
|
12194
|
+
}
|
|
12195
|
+
const bytes = readRegularFile(path, SESSION_LOCK_MAX_BYTES);
|
|
12196
|
+
const after = lstatSync9(path, { throwIfNoEntry: false });
|
|
12197
|
+
if (!bytes || !after?.isFile() || before.dev !== after.dev || before.ino !== after.ino || before.mtimeMs !== after.mtimeMs) {
|
|
12198
|
+
throw new SkillSelectionError("SESSION_WRITE_LOCKED", "The session lock changed during inspection; recovery requires review.");
|
|
12199
|
+
}
|
|
12200
|
+
let marker;
|
|
12201
|
+
try {
|
|
12202
|
+
marker = JSON.parse(new TextDecoder("utf-8", { fatal: true }).decode(bytes));
|
|
12203
|
+
} catch {
|
|
12204
|
+
throw new SkillSelectionError("SESSION_WRITE_LOCKED", "The session lock is unreadable; recovery requires review.");
|
|
12205
|
+
}
|
|
12206
|
+
if (!marker || ![1, 2].includes(marker.schemaVersion) || marker.sessionId !== sessionId || !/^[a-f0-9-]{36}$/i.test(marker.operationId) || !Number.isSafeInteger(marker.pid) || marker.pid <= 0 || marker.schemaVersion === 2 && (!marker.host || !marker.bootId || !marker.processStart || process.platform === "linux" && !marker.pidNamespace)) {
|
|
12207
|
+
throw new SkillSelectionError("SESSION_WRITE_LOCKED", "The session lock has invalid ownership metadata; recovery requires review.");
|
|
12208
|
+
}
|
|
12209
|
+
return { path, bytes, marker, sha256: sha256Hex(bytes), dev: after.dev, ino: after.ino, mtimeMs: after.mtimeMs };
|
|
12210
|
+
}
|
|
12211
|
+
function writerIsGone(lock, explicitLocalHost) {
|
|
12212
|
+
if (Date.now() - lock.mtimeMs < SESSION_LOCK_MIN_AGE_MS)
|
|
12213
|
+
return false;
|
|
12214
|
+
const owner = processStart(lock.marker.pid);
|
|
12215
|
+
if (owner.state === "unknown")
|
|
12216
|
+
return false;
|
|
12217
|
+
if (lock.marker.schemaVersion === 1)
|
|
12218
|
+
return explicitLocalHost && owner.state === "absent";
|
|
12219
|
+
const local = localLockIdentity();
|
|
12220
|
+
if (!local || lock.marker.host !== local.host || lock.marker.bootId !== local.bootId || lock.marker.pidNamespace !== local.pidNamespace)
|
|
12221
|
+
return false;
|
|
12222
|
+
return owner.state === "absent" || owner.state === "alive" && owner.start !== lock.marker.processStart;
|
|
12223
|
+
}
|
|
12224
|
+
function archiveSessionLock(lock, receipt, explicitLocalHost) {
|
|
12225
|
+
const guardPath = `${lock.path}.recovery-guard`;
|
|
12226
|
+
let guardFd;
|
|
12227
|
+
try {
|
|
12228
|
+
guardFd = openSync6(guardPath, constants3.O_WRONLY | constants3.O_CREAT | constants3.O_EXCL | constants3.O_NOFOLLOW, 384);
|
|
12229
|
+
} catch (error) {
|
|
12230
|
+
if (error.code === "EEXIST")
|
|
12231
|
+
return null;
|
|
12232
|
+
throw error;
|
|
12233
|
+
}
|
|
12234
|
+
const guardStat = fstatSync6(guardFd);
|
|
12235
|
+
try {
|
|
12236
|
+
writeFileSync3(guardFd, `${JSON.stringify({ schemaVersion: 1, pid: process.pid, operationId: randomUUID() })}
|
|
12237
|
+
`);
|
|
12238
|
+
fsyncSync(guardFd);
|
|
12239
|
+
const cacheOptions = { cacheDir: dirname8(dirname8(lock.path)) };
|
|
12240
|
+
const current = readSessionLock(lock.marker.sessionId, cacheOptions);
|
|
12241
|
+
if (!current || current.dev !== lock.dev || current.ino !== lock.ino || current.sha256 !== lock.sha256 || current.mtimeMs !== lock.mtimeMs || !writerIsGone(current, explicitLocalHost))
|
|
12242
|
+
return null;
|
|
12243
|
+
const currentReceipt = readSkillSessionSnapshotIfExists(lock.marker.sessionId, cacheOptions);
|
|
12244
|
+
if (currentReceipt?.sha256 !== receipt?.sha256 || currentReceipt?.generation !== receipt?.generation)
|
|
12245
|
+
return null;
|
|
12246
|
+
const directory = join12(dirname8(dirname8(lock.path)), "session-lock-recoveries", randomUUID());
|
|
12247
|
+
const archivePath = join12(directory, "original.write-lock");
|
|
12248
|
+
const recordPath = join12(directory, "recovery.json");
|
|
12249
|
+
assertRegularPath(archivePath, true);
|
|
12250
|
+
archiveBytes(recordPath, Buffer.from(`${JSON.stringify({
|
|
12251
|
+
schemaVersion: 1,
|
|
12252
|
+
sessionId: lock.marker.sessionId,
|
|
12253
|
+
originalPath: lock.path,
|
|
12254
|
+
lockSha256: lock.sha256,
|
|
12255
|
+
lockMtime: new Date(lock.mtimeMs).toISOString(),
|
|
12256
|
+
lockPid: lock.marker.pid,
|
|
12257
|
+
receiptSha256: receipt?.sha256 ?? null,
|
|
12258
|
+
receiptGeneration: receipt?.generation ?? null,
|
|
12259
|
+
status: "prepared"
|
|
12260
|
+
})}
|
|
12261
|
+
`));
|
|
12262
|
+
syncDirectory(directory);
|
|
12263
|
+
syncDirectory(dirname8(directory));
|
|
12264
|
+
const finalLock = readSessionLock(lock.marker.sessionId, cacheOptions);
|
|
12265
|
+
if (!finalLock || finalLock.dev !== lock.dev || finalLock.ino !== lock.ino || finalLock.sha256 !== lock.sha256 || readSkillSessionSnapshotIfExists(lock.marker.sessionId, cacheOptions)?.sha256 !== receipt?.sha256)
|
|
12266
|
+
return null;
|
|
12267
|
+
let moved = false;
|
|
12268
|
+
try {
|
|
12269
|
+
renameSync(lock.path, archivePath);
|
|
12270
|
+
moved = true;
|
|
12271
|
+
syncDirectory(directory);
|
|
12272
|
+
syncDirectory(dirname8(lock.path));
|
|
12273
|
+
if (sha256Hex(readRegularFile(archivePath, SESSION_LOCK_MAX_BYTES)) !== lock.sha256) {
|
|
12274
|
+
throw new Error("Archived lock bytes changed");
|
|
12275
|
+
}
|
|
12276
|
+
} catch (error) {
|
|
12277
|
+
if (moved)
|
|
12278
|
+
throw new SkillSelectionError("SESSION_LOCK_RECOVERY_INCOMPLETE", "The lock moved, but durable recovery could not be confirmed; inspect the preserved recovery directory and session receipt.");
|
|
12279
|
+
throw error;
|
|
12280
|
+
}
|
|
12281
|
+
return archivePath;
|
|
12282
|
+
} finally {
|
|
12283
|
+
closeSync6(guardFd);
|
|
12284
|
+
const current = lstatSync9(guardPath, { throwIfNoEntry: false });
|
|
12285
|
+
if (current?.isFile() && current.dev === guardStat.dev && current.ino === guardStat.ino)
|
|
12286
|
+
unlinkSync(guardPath);
|
|
12287
|
+
}
|
|
12288
|
+
}
|
|
12127
12289
|
function withSessionWriteLocks(sessionIds, options, action) {
|
|
12128
12290
|
const operationId = randomUUID();
|
|
12129
12291
|
const locks = [...new Set(sessionIds)].map((sessionId) => ({ sessionId, path: `${sessionReceiptPath(sessionId, options)}.write-lock` })).sort((a, b) => a.path < b.path ? -1 : a.path > b.path ? 1 : 0);
|
|
@@ -12143,13 +12305,30 @@ function withSessionWriteLocks(sessionIds, options, action) {
|
|
|
12143
12305
|
try {
|
|
12144
12306
|
fd = openSync6(lock.path, constants3.O_WRONLY | constants3.O_CREAT | constants3.O_EXCL | constants3.O_NOFOLLOW, 384);
|
|
12145
12307
|
} catch (error) {
|
|
12146
|
-
if (error.code
|
|
12147
|
-
throw
|
|
12148
|
-
|
|
12308
|
+
if (error.code !== "EEXIST")
|
|
12309
|
+
throw error;
|
|
12310
|
+
try {
|
|
12311
|
+
const stale = readSessionLock(lock.sessionId, options);
|
|
12312
|
+
const receipt = stale && readSkillSessionSnapshotIfExists(lock.sessionId, options);
|
|
12313
|
+
if (stale?.marker.schemaVersion === 2 && writerIsGone(stale, false)) {
|
|
12314
|
+
archiveSessionLock(stale, receipt, false);
|
|
12315
|
+
}
|
|
12316
|
+
} catch (recoveryError) {
|
|
12317
|
+
if (recoveryError instanceof SkillSelectionError && recoveryError.code === "SESSION_LOCK_RECOVERY_INCOMPLETE")
|
|
12318
|
+
throw recoveryError;
|
|
12319
|
+
}
|
|
12320
|
+
try {
|
|
12321
|
+
fd = openSync6(lock.path, constants3.O_WRONLY | constants3.O_CREAT | constants3.O_EXCL | constants3.O_NOFOLLOW, 384);
|
|
12322
|
+
} catch (retryError) {
|
|
12323
|
+
if (retryError.code === "EEXIST")
|
|
12324
|
+
throw new SkillSelectionError("SESSION_WRITE_LOCKED", "Another Skills process owns a required session write lock; retry after it completes. A surviving legacy lock requires explicit recovery review.");
|
|
12325
|
+
throw retryError;
|
|
12326
|
+
}
|
|
12149
12327
|
}
|
|
12150
12328
|
const stat = fstatSync6(fd);
|
|
12151
12329
|
owned.push({ path: lock.path, fd, dev: stat.dev, ino: stat.ino });
|
|
12152
|
-
|
|
12330
|
+
const identity3 = localLockIdentity();
|
|
12331
|
+
writeFileSync3(fd, `${JSON.stringify({ schemaVersion: identity3 ? 2 : 1, operationId, sessionId: lock.sessionId, pid: process.pid, ...identity3 })}
|
|
12153
12332
|
`);
|
|
12154
12333
|
}
|
|
12155
12334
|
return action(assertOwned);
|
|
@@ -12268,7 +12447,7 @@ function replaceSkillSession(expected, replacement, plan, options = {}, beforeCo
|
|
|
12268
12447
|
}
|
|
12269
12448
|
|
|
12270
12449
|
// src/lib/dependency-preparation.ts
|
|
12271
|
-
import { constants as constants4, closeSync as closeSync7, fstatSync as fstatSync7, lstatSync as lstatSync10, mkdirSync as mkdirSync4, openSync as openSync7, readFileSync as
|
|
12450
|
+
import { constants as constants4, closeSync as closeSync7, fstatSync as fstatSync7, lstatSync as lstatSync10, mkdirSync as mkdirSync4, openSync as openSync7, readFileSync as readFileSync10, readdirSync as readdirSync5, rmdirSync, unlinkSync as unlinkSync2, ftruncateSync, writeSync } from "fs";
|
|
12272
12451
|
import { join as join13 } from "path";
|
|
12273
12452
|
|
|
12274
12453
|
// src/lib/preparation-process.ts
|
|
@@ -12342,7 +12521,7 @@ function claimPreparation(skillPath) {
|
|
|
12342
12521
|
return;
|
|
12343
12522
|
if (!lstatSync10(state).isFile() || lstatSync10(state).isSymbolicLink() || lstatSync10(state).size > 1024)
|
|
12344
12523
|
return;
|
|
12345
|
-
const previous = JSON.parse(
|
|
12524
|
+
const previous = JSON.parse(readFileSync10(state, "utf8"));
|
|
12346
12525
|
if (previous.version !== 1 || previous.status !== "failed" || Object.keys(previous).length !== 2)
|
|
12347
12526
|
return;
|
|
12348
12527
|
}
|
|
@@ -12475,11 +12654,11 @@ async function prepareSkillDependencies(skillPath, env, timeoutMs = DEFAULT_PREP
|
|
|
12475
12654
|
}
|
|
12476
12655
|
|
|
12477
12656
|
// src/lib/skillinfo.ts
|
|
12478
|
-
import { existsSync as existsSync12, readFileSync as
|
|
12657
|
+
import { existsSync as existsSync12, readFileSync as readFileSync16 } from "fs";
|
|
12479
12658
|
import { join as join20 } from "path";
|
|
12480
12659
|
|
|
12481
12660
|
// src/lib/installer.ts
|
|
12482
|
-
import { existsSync as existsSync11, readFileSync as
|
|
12661
|
+
import { existsSync as existsSync11, readFileSync as readFileSync15, rmSync as rmSync2 } from "fs";
|
|
12483
12662
|
import { join as join19 } from "path";
|
|
12484
12663
|
import { homedir as homedir4 } from "os";
|
|
12485
12664
|
|
|
@@ -12490,7 +12669,7 @@ import {
|
|
|
12490
12669
|
lstatSync as lstatSync15,
|
|
12491
12670
|
mkdirSync as mkdirSync6,
|
|
12492
12671
|
mkdtempSync,
|
|
12493
|
-
readFileSync as
|
|
12672
|
+
readFileSync as readFileSync13,
|
|
12494
12673
|
readdirSync as readdirSync8,
|
|
12495
12674
|
renameSync as renameSync3,
|
|
12496
12675
|
rmSync,
|
|
@@ -12502,7 +12681,7 @@ import { basename as basename5, dirname as dirname11, join as join17 } from "pat
|
|
|
12502
12681
|
|
|
12503
12682
|
// src/lib/agent-integration.ts
|
|
12504
12683
|
import { createHash as createHash10, randomUUID as randomUUID2 } from "crypto";
|
|
12505
|
-
import { existsSync as existsSync8, lstatSync as lstatSync14, statSync as statSync7, mkdirSync as mkdirSync5, readFileSync as
|
|
12684
|
+
import { existsSync as existsSync8, lstatSync as lstatSync14, statSync as statSync7, mkdirSync as mkdirSync5, readFileSync as readFileSync12, readdirSync as readdirSync7, opendirSync as opendirSync3, readlinkSync as readlinkSync3, realpathSync as realpathSync3, renameSync as renameSync2, rmdirSync as rmdirSync2, writeFileSync as writeFileSync4, unlinkSync as unlinkSync3, chmodSync, openSync as openSync10, closeSync as closeSync10, fsyncSync as fsyncSync2, fstatSync as fstatSync10, readSync as readSync6, constants as constants7, linkSync } from "fs";
|
|
12506
12685
|
import { dirname as dirname10, join as join16, resolve as resolve9, relative as relative4, isAbsolute as isAbsolute9, sep as sep4 } from "path";
|
|
12507
12686
|
import { homedir as homedir2 } from "os";
|
|
12508
12687
|
|
|
@@ -12588,7 +12767,7 @@ function requiresCliSkillLoading(dataDir2 = getDataDirReadOnly()) {
|
|
|
12588
12767
|
|
|
12589
12768
|
// src/lib/agent-bridge.ts
|
|
12590
12769
|
import { createHash as createHash8 } from "crypto";
|
|
12591
|
-
import { lstatSync as lstatSync12, readFileSync as
|
|
12770
|
+
import { lstatSync as lstatSync12, readFileSync as readFileSync11, readdirSync as readdirSync6 } from "fs";
|
|
12592
12771
|
import { join as join15 } from "path";
|
|
12593
12772
|
var CLI_BRIDGE_NAME = "skills-cli";
|
|
12594
12773
|
var CLI_BRIDGE_VERSION = 1;
|
|
@@ -12622,7 +12801,7 @@ function isOwnedCliBridge(path, expectedPaths) {
|
|
|
12622
12801
|
return false;
|
|
12623
12802
|
return Object.entries(CLI_BRIDGE_FILES).every(([name, content]) => {
|
|
12624
12803
|
const file = join15(path, name), stat = lstatSync12(file);
|
|
12625
|
-
return stat.isFile() && !stat.isSymbolicLink() && stat.size === Buffer.byteLength(content) &&
|
|
12804
|
+
return stat.isFile() && !stat.isSymbolicLink() && stat.size === Buffer.byteLength(content) && readFileSync11(file, "utf8") === content;
|
|
12626
12805
|
});
|
|
12627
12806
|
} catch {
|
|
12628
12807
|
return false;
|
|
@@ -13022,7 +13201,7 @@ function readRootAlias(home, agent) {
|
|
|
13022
13201
|
const stat = lstatSync14(alias, { throwIfNoEntry: false, bigint: true });
|
|
13023
13202
|
if (!stat?.isSymbolicLink())
|
|
13024
13203
|
throw new Error(`Agent root alias changed after planning: ${alias}`);
|
|
13025
|
-
const link =
|
|
13204
|
+
const link = readlinkSync3(alias), targetPath = resolve9(dirname10(alias), link);
|
|
13026
13205
|
assertSafePath(targetPath);
|
|
13027
13206
|
const targetStat = lstatSync14(targetPath, { throwIfNoEntry: false });
|
|
13028
13207
|
if (!targetStat?.isDirectory())
|
|
@@ -13175,7 +13354,7 @@ function inventoryNativeSkills(home = homedir2(), options = {}) {
|
|
|
13175
13354
|
throw new Error("Native skill discovery metadata limit exceeded");
|
|
13176
13355
|
}
|
|
13177
13356
|
function emptySiblingCacheAlias(path, parent) {
|
|
13178
|
-
const link =
|
|
13357
|
+
const link = readlinkSync3(path), target = resolve9(parent, link);
|
|
13179
13358
|
if (dirname10(target) !== parent || (isAbsolute9(link) ? link !== target : dirname10(link) !== "."))
|
|
13180
13359
|
return false;
|
|
13181
13360
|
if (!lstatSync14(target, { throwIfNoEntry: false })?.isDirectory())
|
|
@@ -13204,7 +13383,7 @@ function inventoryNativeSkills(home = homedir2(), options = {}) {
|
|
|
13204
13383
|
const marker = join16(path, ".hasna-skills.json");
|
|
13205
13384
|
if (existsSync8(marker)) {
|
|
13206
13385
|
try {
|
|
13207
|
-
managed = JSON.parse(
|
|
13386
|
+
managed = JSON.parse(readFileSync12(marker, "utf8")).managedBy === "@hasna/skills";
|
|
13208
13387
|
} catch {}
|
|
13209
13388
|
}
|
|
13210
13389
|
const bridge = !vendor && isOwnedCliBridge(path, bridgePaths);
|
|
@@ -13277,7 +13456,7 @@ function inventoryNativeSkills(home = homedir2(), options = {}) {
|
|
|
13277
13456
|
}
|
|
13278
13457
|
function readOptional(path) {
|
|
13279
13458
|
assertSafePath(path);
|
|
13280
|
-
return existsSync8(path) ?
|
|
13459
|
+
return existsSync8(path) ? readFileSync12(path, "utf8") : null;
|
|
13281
13460
|
}
|
|
13282
13461
|
function jsonObject(text2, path) {
|
|
13283
13462
|
if (text2 === null)
|
|
@@ -13989,7 +14168,7 @@ function hasSkillsOwnershipMarker(dir) {
|
|
|
13989
14168
|
try {
|
|
13990
14169
|
if (!lstatSync15(path).isFile())
|
|
13991
14170
|
return false;
|
|
13992
|
-
const marker = JSON.parse(
|
|
14171
|
+
const marker = JSON.parse(readFileSync13(path, "utf8"));
|
|
13993
14172
|
return isSkillsOwnershipMarker(marker);
|
|
13994
14173
|
} catch {
|
|
13995
14174
|
return false;
|
|
@@ -14198,7 +14377,7 @@ function writeManagedSkillDir(dir, skillMd, options) {
|
|
|
14198
14377
|
if (dirExists && managed && hasSkillMd && !options.force && isPointerSkillMd(skillMd)) {
|
|
14199
14378
|
let existingIsStub = false;
|
|
14200
14379
|
try {
|
|
14201
|
-
existingIsStub = isPointerSkillMd(
|
|
14380
|
+
existingIsStub = isPointerSkillMd(readFileSync13(skillMdPath, "utf-8"));
|
|
14202
14381
|
} catch {
|
|
14203
14382
|
existingIsStub = false;
|
|
14204
14383
|
}
|
|
@@ -14278,7 +14457,7 @@ function sourceSkillMd(skillPath, name, description, kind, preferBundledDocs = f
|
|
|
14278
14457
|
if (kind === undefined || kind === "instruction" || preferBundledDocs) {
|
|
14279
14458
|
const skillMdPath = join17(skillPath, "SKILL.md");
|
|
14280
14459
|
if (existsSync9(skillMdPath))
|
|
14281
|
-
return
|
|
14460
|
+
return readFileSync13(skillMdPath, "utf-8");
|
|
14282
14461
|
}
|
|
14283
14462
|
return pointerSkillMd(name, description);
|
|
14284
14463
|
}
|
|
@@ -14318,7 +14497,7 @@ function resolveSkillAlias(name) {
|
|
|
14318
14497
|
}
|
|
14319
14498
|
|
|
14320
14499
|
// src/lib/project-state.ts
|
|
14321
|
-
import { existsSync as existsSync10, mkdirSync as mkdirSync7, readFileSync as
|
|
14500
|
+
import { existsSync as existsSync10, mkdirSync as mkdirSync7, readFileSync as readFileSync14, writeFileSync as writeFileSync6 } from "fs";
|
|
14322
14501
|
import { join as join18 } from "path";
|
|
14323
14502
|
var VALID_PIN_SOURCES = [
|
|
14324
14503
|
"official",
|
|
@@ -14344,7 +14523,7 @@ function loadProjectConfig(targetDir = process.cwd()) {
|
|
|
14344
14523
|
if (!existsSync10(path))
|
|
14345
14524
|
return null;
|
|
14346
14525
|
try {
|
|
14347
|
-
return normalizeProjectConfig(JSON.parse(
|
|
14526
|
+
return normalizeProjectConfig(JSON.parse(readFileSync14(path, "utf-8")));
|
|
14348
14527
|
} catch {
|
|
14349
14528
|
return null;
|
|
14350
14529
|
}
|
|
@@ -14531,7 +14710,7 @@ function createLocalSkillManifest(name, generateSkillMd) {
|
|
|
14531
14710
|
let skillMd = "";
|
|
14532
14711
|
const skillMdPath = join19(sourcePath, "SKILL.md");
|
|
14533
14712
|
if (existsSync11(skillMdPath)) {
|
|
14534
|
-
skillMd =
|
|
14713
|
+
skillMd = readFileSync15(skillMdPath, "utf-8");
|
|
14535
14714
|
} else if (generateSkillMd) {
|
|
14536
14715
|
skillMd = generateSkillMd(name) ?? "";
|
|
14537
14716
|
} else {
|
|
@@ -14650,7 +14829,7 @@ function resolveAgentSkillMd(name, generateSkillMd) {
|
|
|
14650
14829
|
const sourcePath = getSkillPath(name);
|
|
14651
14830
|
const skillMdPath = join19(sourcePath, "SKILL.md");
|
|
14652
14831
|
if (existsSync11(skillMdPath))
|
|
14653
|
-
return
|
|
14832
|
+
return readFileSync15(skillMdPath, "utf-8");
|
|
14654
14833
|
if (generateSkillMd)
|
|
14655
14834
|
return generateSkillMd(name);
|
|
14656
14835
|
return generateMinimalSkillMd(name);
|
|
@@ -14706,14 +14885,14 @@ function readBundledSkillVersion(name) {
|
|
|
14706
14885
|
if (!existsSync11(pkgPath))
|
|
14707
14886
|
return "unknown";
|
|
14708
14887
|
try {
|
|
14709
|
-
const pkg = JSON.parse(
|
|
14888
|
+
const pkg = JSON.parse(readFileSync15(pkgPath, "utf-8"));
|
|
14710
14889
|
return pkg.version || "unknown";
|
|
14711
14890
|
} catch {
|
|
14712
14891
|
return "unknown";
|
|
14713
14892
|
}
|
|
14714
14893
|
}
|
|
14715
14894
|
function readFileIfExists(path) {
|
|
14716
|
-
return existsSync11(path) ?
|
|
14895
|
+
return existsSync11(path) ? readFileSync15(path, "utf-8") : null;
|
|
14717
14896
|
}
|
|
14718
14897
|
function loadProjectConfigCompat(targetDir) {
|
|
14719
14898
|
return loadProjectConfig(targetDir);
|
|
@@ -14761,7 +14940,7 @@ function isInstructionSkillDir(skillPath, meta) {
|
|
|
14761
14940
|
if (!existsSync12(skillMdPath))
|
|
14762
14941
|
return false;
|
|
14763
14942
|
try {
|
|
14764
|
-
return parseSkillFrontmatter(
|
|
14943
|
+
return parseSkillFrontmatter(readFileSync16(skillMdPath, "utf-8"))?.kind === "instruction";
|
|
14765
14944
|
} catch {
|
|
14766
14945
|
return false;
|
|
14767
14946
|
}
|
|
@@ -14812,7 +14991,7 @@ function getSkillRequirements(name) {
|
|
|
14812
14991
|
const meta = getSkill(name);
|
|
14813
14992
|
let dependencies = {};
|
|
14814
14993
|
try {
|
|
14815
|
-
dependencies = JSON.parse(
|
|
14994
|
+
dependencies = JSON.parse(readFileSync16(join20(skillPath, "package.json"), "utf8")).dependencies || {};
|
|
14816
14995
|
} catch {}
|
|
14817
14996
|
return getSkillRequirementsFromContent(name, texts, dependencies, meta);
|
|
14818
14997
|
}
|
|
@@ -14880,7 +15059,7 @@ async function runSkill(name, args, options = {}) {
|
|
|
14880
15059
|
}
|
|
14881
15060
|
let entryPoint2;
|
|
14882
15061
|
try {
|
|
14883
|
-
const pkg = JSON.parse(
|
|
15062
|
+
const pkg = JSON.parse(readFileSync16(pkgPath, "utf-8"));
|
|
14884
15063
|
if (pkg.bin) {
|
|
14885
15064
|
const binValues = Object.values(pkg.bin);
|
|
14886
15065
|
entryPoint2 = binValues[0];
|
|
@@ -14983,7 +15162,7 @@ function generateSkillMd(name) {
|
|
|
14983
15162
|
const pkgPath = join20(skillPath, "package.json");
|
|
14984
15163
|
if (existsSync12(pkgPath)) {
|
|
14985
15164
|
try {
|
|
14986
|
-
const pkg = JSON.parse(
|
|
15165
|
+
const pkg = JSON.parse(readFileSync16(pkgPath, "utf-8"));
|
|
14987
15166
|
if (pkg.bin) {
|
|
14988
15167
|
const binKeys = Object.keys(pkg.bin);
|
|
14989
15168
|
if (binKeys.length > 0)
|
|
@@ -15059,7 +15238,7 @@ function extractEnvVars(text2) {
|
|
|
15059
15238
|
function readIfExists(path) {
|
|
15060
15239
|
try {
|
|
15061
15240
|
if (existsSync12(path)) {
|
|
15062
|
-
return
|
|
15241
|
+
return readFileSync16(path, "utf-8");
|
|
15063
15242
|
}
|
|
15064
15243
|
} catch {}
|
|
15065
15244
|
return null;
|
|
@@ -16569,7 +16748,7 @@ function read2(path, changes) {
|
|
|
16569
16748
|
return null;
|
|
16570
16749
|
if (!stat2.isFile() || stat2.size > 16 * 1024 * 1024)
|
|
16571
16750
|
throw new Error(`Unsupported or oversized native discovery input: ${path}`);
|
|
16572
|
-
return
|
|
16751
|
+
return readFileSync17(path, "utf8");
|
|
16573
16752
|
}
|
|
16574
16753
|
function projected(source, changes, budget = discoveryByteBudget()) {
|
|
16575
16754
|
if (source.hashMode === "claude-settings-v1" || source.hashMode === "claude-settings-v2" || source.hashMode === "claude-settings-v3") {
|
|
@@ -17660,7 +17839,7 @@ function discoverSkillsInDir(dir, source = "custom") {
|
|
|
17660
17839
|
continue;
|
|
17661
17840
|
let content;
|
|
17662
17841
|
try {
|
|
17663
|
-
content =
|
|
17842
|
+
content = readFileSync18(skillMdPath, "utf-8");
|
|
17664
17843
|
} catch {
|
|
17665
17844
|
continue;
|
|
17666
17845
|
}
|
|
@@ -17697,7 +17876,7 @@ function findExtensionSkillPath(name) {
|
|
|
17697
17876
|
continue;
|
|
17698
17877
|
let content;
|
|
17699
17878
|
try {
|
|
17700
|
-
content =
|
|
17879
|
+
content = readFileSync18(skillMdPath, "utf-8");
|
|
17701
17880
|
} catch {
|
|
17702
17881
|
continue;
|
|
17703
17882
|
}
|
|
@@ -17762,7 +17941,7 @@ function getAllTags() {
|
|
|
17762
17941
|
}
|
|
17763
17942
|
// src/lib/run-state.ts
|
|
17764
17943
|
import { createHash as createHash17, randomBytes } from "crypto";
|
|
17765
|
-
import { existsSync as existsSync15, mkdirSync as mkdirSync10, readFileSync as
|
|
17944
|
+
import { existsSync as existsSync15, mkdirSync as mkdirSync10, readFileSync as readFileSync19, readdirSync as readdirSync12, statSync as statSync10, writeFileSync as writeFileSync9 } from "fs";
|
|
17766
17945
|
import { extname, join as join30, relative as relative6 } from "path";
|
|
17767
17946
|
function createSkillRun(params, targetDir = process.cwd()) {
|
|
17768
17947
|
const now = new Date;
|
|
@@ -17834,7 +18013,7 @@ function appendRunEvent(context, event, data = {}) {
|
|
|
17834
18013
|
const line = JSON.stringify({ ts: new Date().toISOString(), event, ...data }) + `
|
|
17835
18014
|
`;
|
|
17836
18015
|
const path = join30(context.runDir, "events.ndjson");
|
|
17837
|
-
const previous = existsSync15(path) ?
|
|
18016
|
+
const previous = existsSync15(path) ? readFileSync19(path, "utf-8") : "";
|
|
17838
18017
|
writeFileSync9(path, previous + line);
|
|
17839
18018
|
}
|
|
17840
18019
|
function listSkillRuns(targetDir = process.cwd(), limit = 50) {
|
|
@@ -17884,7 +18063,7 @@ function collectRunArtifacts(context) {
|
|
|
17884
18063
|
const artifacts = [];
|
|
17885
18064
|
for (const path of walkFiles(context.exportDir)) {
|
|
17886
18065
|
const stat2 = statSync10(path);
|
|
17887
|
-
const bytes =
|
|
18066
|
+
const bytes = readFileSync19(path);
|
|
17888
18067
|
artifacts.push({
|
|
17889
18068
|
path: toProjectRelative(context.targetDir, path),
|
|
17890
18069
|
mime: mimeForPath(path),
|
|
@@ -17899,7 +18078,7 @@ function readRunRecord(runDir) {
|
|
|
17899
18078
|
if (!existsSync15(path))
|
|
17900
18079
|
return null;
|
|
17901
18080
|
try {
|
|
17902
|
-
return JSON.parse(
|
|
18081
|
+
return JSON.parse(readFileSync19(path, "utf-8"));
|
|
17903
18082
|
} catch {
|
|
17904
18083
|
return null;
|
|
17905
18084
|
}
|
|
@@ -18069,7 +18248,7 @@ __export(exports_external, {
|
|
|
18069
18248
|
input: () => input,
|
|
18070
18249
|
includes: () => _includes,
|
|
18071
18250
|
httpUrl: () => httpUrl,
|
|
18072
|
-
hostname: () =>
|
|
18251
|
+
hostname: () => hostname3,
|
|
18073
18252
|
hex: () => hex2,
|
|
18074
18253
|
hash: () => hash2,
|
|
18075
18254
|
guid: () => guid2,
|
|
@@ -19855,7 +20034,7 @@ __export(exports_regexes, {
|
|
|
19855
20034
|
idnEmail: () => idnEmail,
|
|
19856
20035
|
httpProtocol: () => httpProtocol,
|
|
19857
20036
|
html5Email: () => html5Email,
|
|
19858
|
-
hostname: () =>
|
|
20037
|
+
hostname: () => hostname2,
|
|
19859
20038
|
hex: () => hex,
|
|
19860
20039
|
guid: () => guid,
|
|
19861
20040
|
extendedDuration: () => extendedDuration,
|
|
@@ -19917,7 +20096,7 @@ var cidrv4 = /^((25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\.){3}(25[0-5]
|
|
|
19917
20096
|
var cidrv6 = /^(([0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:))\/(12[0-8]|1[01][0-9]|[1-9]?[0-9])$/;
|
|
19918
20097
|
var base64 = /^$|^(?:[0-9a-zA-Z+/]{4})*(?:(?:[0-9a-zA-Z+/]{2}==)|(?:[0-9a-zA-Z+/]{3}=))?$/;
|
|
19919
20098
|
var base64url = /^[A-Za-z0-9_-]*$/;
|
|
19920
|
-
var
|
|
20099
|
+
var hostname2 = /^(?=.{1,253}\.?$)[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[-0-9a-zA-Z]{0,61}[0-9a-zA-Z])?)*\.?$/;
|
|
19921
20100
|
var domain = /^(?=.{1,253}$)([a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?\.)+[a-zA-Z]{2,63}$/;
|
|
19922
20101
|
var httpProtocol = /^https?$/;
|
|
19923
20102
|
var e164 = /^\+[1-9]\d{6,14}$/;
|
|
@@ -20754,9 +20933,9 @@ var asciiTabOrNewline = /[\t\n\r]/g;
|
|
|
20754
20933
|
function stripTabAndNewline(value) {
|
|
20755
20934
|
return value.replace(asciiTabOrNewline, "");
|
|
20756
20935
|
}
|
|
20757
|
-
function urlHostnameOk(url,
|
|
20758
|
-
|
|
20759
|
-
return
|
|
20936
|
+
function urlHostnameOk(url, hostname3) {
|
|
20937
|
+
hostname3.lastIndex = 0;
|
|
20938
|
+
return hostname3.test(url.hostname);
|
|
20760
20939
|
}
|
|
20761
20940
|
function urlProtocolOk(url, protocol) {
|
|
20762
20941
|
protocol.lastIndex = 0;
|
|
@@ -34144,7 +34323,7 @@ __export(exports_schemas2, {
|
|
|
34144
34323
|
int: () => int,
|
|
34145
34324
|
instanceof: () => _instanceof,
|
|
34146
34325
|
httpUrl: () => httpUrl,
|
|
34147
|
-
hostname: () =>
|
|
34326
|
+
hostname: () => hostname3,
|
|
34148
34327
|
hex: () => hex2,
|
|
34149
34328
|
hash: () => hash2,
|
|
34150
34329
|
guid: () => guid2,
|
|
@@ -34854,7 +35033,7 @@ var ZodCustomStringFormat = /* @__PURE__ */ $constructor("ZodCustomStringFormat"
|
|
|
34854
35033
|
function stringFormat(format, fnOrRegex, _params = {}) {
|
|
34855
35034
|
return _stringFormat(ZodCustomStringFormat, format, fnOrRegex, _params);
|
|
34856
35035
|
}
|
|
34857
|
-
function
|
|
35036
|
+
function hostname3(_params) {
|
|
34858
35037
|
return _stringFormat(ZodCustomStringFormat, "hostname", exports_regexes.hostname, _params);
|
|
34859
35038
|
}
|
|
34860
35039
|
function hex2(_params) {
|
|
@@ -39414,7 +39593,7 @@ async function createRemoteSkillsClient(env = process.env) {
|
|
|
39414
39593
|
return connection ? new RemoteSkillsClient(connection.apiKey, connection.apiOrigin) : null;
|
|
39415
39594
|
}
|
|
39416
39595
|
// src/lib/scheduler.ts
|
|
39417
|
-
import { existsSync as existsSync16, readFileSync as
|
|
39596
|
+
import { existsSync as existsSync16, readFileSync as readFileSync20, writeFileSync as writeFileSync10, mkdirSync as mkdirSync11 } from "fs";
|
|
39418
39597
|
import { join as join31 } from "path";
|
|
39419
39598
|
function getSchedulesPath(targetDir = process.cwd()) {
|
|
39420
39599
|
return join31(targetDir, ".skills", "schedules.json");
|
|
@@ -39423,7 +39602,7 @@ function loadSchedules(targetDir = process.cwd()) {
|
|
|
39423
39602
|
const path = getSchedulesPath(targetDir);
|
|
39424
39603
|
if (existsSync16(path)) {
|
|
39425
39604
|
try {
|
|
39426
|
-
return JSON.parse(
|
|
39605
|
+
return JSON.parse(readFileSync20(path, "utf-8"));
|
|
39427
39606
|
} catch {}
|
|
39428
39607
|
}
|
|
39429
39608
|
return { version: 1, schedules: [] };
|
|
@@ -39646,7 +39825,7 @@ function revisionIdOfRecord(record7) {
|
|
|
39646
39825
|
return revisionIdOf(record7);
|
|
39647
39826
|
}
|
|
39648
39827
|
// src/lib/pull.ts
|
|
39649
|
-
import { existsSync as existsSync17, mkdirSync as mkdirSync12, mkdtempSync as mkdtempSync3, readFileSync as
|
|
39828
|
+
import { existsSync as existsSync17, mkdirSync as mkdirSync12, mkdtempSync as mkdtempSync3, readFileSync as readFileSync21, renameSync as renameSync6, rmSync as rmSync5, writeFileSync as writeFileSync11 } from "fs";
|
|
39650
39829
|
import { dirname as dirname19, join as join32 } from "path";
|
|
39651
39830
|
|
|
39652
39831
|
// src/lib/skill-bundles.ts
|
|
@@ -39846,7 +40025,7 @@ function reconcileTombstone(slug2, corpusOptions) {
|
|
|
39846
40025
|
}
|
|
39847
40026
|
function readPullMarker(dir) {
|
|
39848
40027
|
try {
|
|
39849
|
-
return JSON.parse(
|
|
40028
|
+
return JSON.parse(readFileSync21(join32(dir, PULL_MARKER_FILE), "utf-8"));
|
|
39850
40029
|
} catch {
|
|
39851
40030
|
return null;
|
|
39852
40031
|
}
|
|
@@ -42098,7 +42277,7 @@ import { createHash as createHash21, createHmac as createHmac2 } from "crypto";
|
|
|
42098
42277
|
import {
|
|
42099
42278
|
existsSync as existsSync19,
|
|
42100
42279
|
mkdirSync as mkdirSync15,
|
|
42101
|
-
readFileSync as
|
|
42280
|
+
readFileSync as readFileSync23,
|
|
42102
42281
|
readdirSync as readdirSync13,
|
|
42103
42282
|
statSync as statSync11,
|
|
42104
42283
|
writeFileSync as writeFileSync13
|
|
@@ -42265,7 +42444,7 @@ function exportSkillsLocalSnapshot(targetDir = process.cwd(), options = {}) {
|
|
|
42265
42444
|
const files = [];
|
|
42266
42445
|
if (existsSync19(projectStateDir)) {
|
|
42267
42446
|
for (const filePath of walkFiles2(projectStateDir)) {
|
|
42268
|
-
const bytes =
|
|
42447
|
+
const bytes = readFileSync23(filePath);
|
|
42269
42448
|
const relativePath = toPosix(relative8(targetDir, filePath));
|
|
42270
42449
|
files.push({
|
|
42271
42450
|
path: relativePath,
|
|
@@ -42683,7 +42862,7 @@ import { createHash as createHash22 } from "crypto";
|
|
|
42683
42862
|
import {
|
|
42684
42863
|
copyFileSync,
|
|
42685
42864
|
mkdirSync as mkdirSync16,
|
|
42686
|
-
readFileSync as
|
|
42865
|
+
readFileSync as readFileSync25,
|
|
42687
42866
|
statSync as statSync13,
|
|
42688
42867
|
writeFileSync as writeFileSync14
|
|
42689
42868
|
} from "fs";
|
|
@@ -42854,7 +43033,7 @@ function validateStationId(stationId) {
|
|
|
42854
43033
|
}
|
|
42855
43034
|
}
|
|
42856
43035
|
function sha256File(filePath) {
|
|
42857
|
-
return createHash22("sha256").update(
|
|
43036
|
+
return createHash22("sha256").update(readFileSync25(filePath)).digest("hex");
|
|
42858
43037
|
}
|
|
42859
43038
|
function scanHome(definition, homesRoot) {
|
|
42860
43039
|
const homePath = homePathFor(definition, homesRoot);
|
|
@@ -43010,7 +43189,7 @@ import {
|
|
|
43010
43189
|
copyFileSync as copyFileSync2,
|
|
43011
43190
|
mkdirSync as mkdirSync17,
|
|
43012
43191
|
readdirSync as readdirSync15,
|
|
43013
|
-
readFileSync as
|
|
43192
|
+
readFileSync as readFileSync26,
|
|
43014
43193
|
statSync as statSync14,
|
|
43015
43194
|
writeFileSync as writeFileSync15
|
|
43016
43195
|
} from "fs";
|
|
@@ -43029,7 +43208,7 @@ function readSnapshotManifest(repoRoot, stationId) {
|
|
|
43029
43208
|
const manifestPath = join36(snapshotRoot, "sync-manifest.json");
|
|
43030
43209
|
let manifest;
|
|
43031
43210
|
try {
|
|
43032
|
-
manifest = JSON.parse(
|
|
43211
|
+
manifest = JSON.parse(readFileSync26(manifestPath, "utf8"));
|
|
43033
43212
|
} catch (error61) {
|
|
43034
43213
|
fail("MANIFEST_UNREADABLE", `cannot read snapshot manifest: ${manifestPath}: ${error61.message}`);
|
|
43035
43214
|
}
|
|
@@ -43165,7 +43344,7 @@ function planStationHydration(stationId, repoRoot) {
|
|
|
43165
43344
|
for (const copy of copies) {
|
|
43166
43345
|
let isStub = false;
|
|
43167
43346
|
try {
|
|
43168
|
-
isStub = isPointerSkillMd(
|
|
43347
|
+
isStub = isPointerSkillMd(readFileSync26(copy.fullPath, "utf8"));
|
|
43169
43348
|
} catch {
|
|
43170
43349
|
isStub = false;
|
|
43171
43350
|
}
|