chore: Enable linting in `scripts`.
parent
0ffc251704
commit
1838ab019b
|
|
@ -32,7 +32,6 @@
|
||||||
"Swabble/",
|
"Swabble/",
|
||||||
"vendor/",
|
"vendor/",
|
||||||
"extensions/",
|
"extensions/",
|
||||||
"scripts/",
|
|
||||||
"ui/"
|
"ui/"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -18,20 +18,28 @@ const DEFAULT_RUNS = 10;
|
||||||
|
|
||||||
function parseArg(flag: string): string | undefined {
|
function parseArg(flag: string): string | undefined {
|
||||||
const idx = process.argv.indexOf(flag);
|
const idx = process.argv.indexOf(flag);
|
||||||
if (idx === -1) return undefined;
|
if (idx === -1) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
return process.argv[idx + 1];
|
return process.argv[idx + 1];
|
||||||
}
|
}
|
||||||
|
|
||||||
function parseRuns(raw: string | undefined): number {
|
function parseRuns(raw: string | undefined): number {
|
||||||
if (!raw) return DEFAULT_RUNS;
|
if (!raw) {
|
||||||
|
return DEFAULT_RUNS;
|
||||||
|
}
|
||||||
const parsed = Number(raw);
|
const parsed = Number(raw);
|
||||||
if (!Number.isFinite(parsed) || parsed <= 0) return DEFAULT_RUNS;
|
if (!Number.isFinite(parsed) || parsed <= 0) {
|
||||||
|
return DEFAULT_RUNS;
|
||||||
|
}
|
||||||
return Math.floor(parsed);
|
return Math.floor(parsed);
|
||||||
}
|
}
|
||||||
|
|
||||||
function median(values: number[]): number {
|
function median(values: number[]): number {
|
||||||
if (values.length === 0) return 0;
|
if (values.length === 0) {
|
||||||
const sorted = [...values].sort((a, b) => a - b);
|
return 0;
|
||||||
|
}
|
||||||
|
const sorted = [...values].toSorted((a, b) => a - b);
|
||||||
const mid = Math.floor(sorted.length / 2);
|
const mid = Math.floor(sorted.length / 2);
|
||||||
if (sorted.length % 2 === 0) {
|
if (sorted.length % 2 === 0) {
|
||||||
return Math.round((sorted[mid - 1] + sorted[mid]) / 2);
|
return Math.round((sorted[mid - 1] + sorted[mid]) / 2);
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,6 @@ import { fileURLToPath } from "node:url";
|
||||||
|
|
||||||
const root = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..");
|
const root = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..");
|
||||||
const binDir = path.join(root, "bin");
|
const binDir = path.join(root, "bin");
|
||||||
const scriptPath = path.join(root, "scripts", "docs-list.js");
|
|
||||||
const binPath = path.join(binDir, "docs-list");
|
const binPath = path.join(binDir, "docs-list");
|
||||||
|
|
||||||
fs.mkdirSync(binDir, { recursive: true });
|
fs.mkdirSync(binDir, { recursive: true });
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,9 @@ function parseArgs(argv: string[]): ParsedArgs {
|
||||||
const arg = argv[index];
|
const arg = argv[index];
|
||||||
if (arg === "--max") {
|
if (arg === "--max") {
|
||||||
const next = argv[index + 1];
|
const next = argv[index + 1];
|
||||||
if (!next || Number.isNaN(Number(next))) throw new Error("Missing/invalid --max value");
|
if (!next || Number.isNaN(Number(next))) {
|
||||||
|
throw new Error("Missing/invalid --max value");
|
||||||
|
}
|
||||||
maxLines = Number(next);
|
maxLines = Number(next);
|
||||||
index++;
|
index++;
|
||||||
continue;
|
continue;
|
||||||
|
|
@ -43,7 +45,9 @@ async function countLines(filePath: string): Promise<number> {
|
||||||
async function main() {
|
async function main() {
|
||||||
// Makes `... | head` safe.
|
// Makes `... | head` safe.
|
||||||
process.stdout.on("error", (error: NodeJS.ErrnoException) => {
|
process.stdout.on("error", (error: NodeJS.ErrnoException) => {
|
||||||
if (error.code === "EPIPE") process.exit(0);
|
if (error.code === "EPIPE") {
|
||||||
|
process.exit(0);
|
||||||
|
}
|
||||||
throw error;
|
throw error;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -58,9 +62,11 @@ async function main() {
|
||||||
|
|
||||||
const offenders = results
|
const offenders = results
|
||||||
.filter((result) => result.lines > maxLines)
|
.filter((result) => result.lines > maxLines)
|
||||||
.sort((a, b) => b.lines - a.lines);
|
.toSorted((a, b) => b.lines - a.lines);
|
||||||
|
|
||||||
if (!offenders.length) return;
|
if (!offenders.length) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Minimal, grep-friendly output.
|
// Minimal, grep-friendly output.
|
||||||
for (const offender of offenders) {
|
for (const offender of offenders) {
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,9 @@ function copyHookMetadata() {
|
||||||
const entries = fs.readdirSync(srcBundled, { withFileTypes: true });
|
const entries = fs.readdirSync(srcBundled, { withFileTypes: true });
|
||||||
|
|
||||||
for (const entry of entries) {
|
for (const entry of entries) {
|
||||||
if (!entry.isDirectory()) continue;
|
if (!entry.isDirectory()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
const hookName = entry.name;
|
const hookName = entry.name;
|
||||||
const srcHookDir = path.join(srcBundled, hookName);
|
const srcHookDir = path.join(srcBundled, hookName);
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,9 @@ type Args = {
|
||||||
|
|
||||||
const mask = (value: string) => {
|
const mask = (value: string) => {
|
||||||
const compact = value.trim();
|
const compact = value.trim();
|
||||||
if (!compact) return "missing";
|
if (!compact) {
|
||||||
|
return "missing";
|
||||||
|
}
|
||||||
const edge = compact.length >= 12 ? 6 : 4;
|
const edge = compact.length >= 12 ? 6 : 4;
|
||||||
return `${compact.slice(0, edge)}…${compact.slice(-edge)}`;
|
return `${compact.slice(0, edge)}…${compact.slice(-edge)}`;
|
||||||
};
|
};
|
||||||
|
|
@ -48,7 +50,9 @@ const loadAuthProfiles = (agentId: string) => {
|
||||||
process.env.CLAWDBOT_STATE_DIR?.trim() ||
|
process.env.CLAWDBOT_STATE_DIR?.trim() ||
|
||||||
path.join(os.homedir(), ".openclaw");
|
path.join(os.homedir(), ".openclaw");
|
||||||
const authPath = path.join(stateRoot, "agents", agentId, "agent", "auth-profiles.json");
|
const authPath = path.join(stateRoot, "agents", agentId, "agent", "auth-profiles.json");
|
||||||
if (!fs.existsSync(authPath)) throw new Error(`Missing: ${authPath}`);
|
if (!fs.existsSync(authPath)) {
|
||||||
|
throw new Error(`Missing: ${authPath}`);
|
||||||
|
}
|
||||||
const store = JSON.parse(fs.readFileSync(authPath, "utf8")) as {
|
const store = JSON.parse(fs.readFileSync(authPath, "utf8")) as {
|
||||||
profiles?: Record<string, { provider?: string; type?: string; token?: string; key?: string }>;
|
profiles?: Record<string, { provider?: string; type?: string; token?: string; key?: string }>;
|
||||||
};
|
};
|
||||||
|
|
@ -61,9 +65,13 @@ const pickAnthropicTokens = (store: {
|
||||||
const profiles = store.profiles ?? {};
|
const profiles = store.profiles ?? {};
|
||||||
const found: Array<{ profileId: string; token: string }> = [];
|
const found: Array<{ profileId: string; token: string }> = [];
|
||||||
for (const [id, cred] of Object.entries(profiles)) {
|
for (const [id, cred] of Object.entries(profiles)) {
|
||||||
if (cred?.provider !== "anthropic") continue;
|
if (cred?.provider !== "anthropic") {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
const token = cred.type === "token" ? cred.token?.trim() : undefined;
|
const token = cred.type === "token" ? cred.token?.trim() : undefined;
|
||||||
if (token) found.push({ profileId: id, token });
|
if (token) {
|
||||||
|
found.push({ profileId: id, token });
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return found;
|
return found;
|
||||||
};
|
};
|
||||||
|
|
@ -87,7 +95,9 @@ const readClaudeCliKeychain = (): {
|
||||||
expiresAt?: number;
|
expiresAt?: number;
|
||||||
scopes?: string[];
|
scopes?: string[];
|
||||||
} | null => {
|
} | null => {
|
||||||
if (process.platform !== "darwin") return null;
|
if (process.platform !== "darwin") {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
try {
|
try {
|
||||||
const raw = execFileSync(
|
const raw = execFileSync(
|
||||||
"security",
|
"security",
|
||||||
|
|
@ -96,9 +106,13 @@ const readClaudeCliKeychain = (): {
|
||||||
);
|
);
|
||||||
const parsed = JSON.parse(raw.trim()) as Record<string, unknown>;
|
const parsed = JSON.parse(raw.trim()) as Record<string, unknown>;
|
||||||
const oauth = parsed?.claudeAiOauth as Record<string, unknown> | undefined;
|
const oauth = parsed?.claudeAiOauth as Record<string, unknown> | undefined;
|
||||||
if (!oauth || typeof oauth !== "object") return null;
|
if (!oauth || typeof oauth !== "object") {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
const accessToken = oauth.accessToken;
|
const accessToken = oauth.accessToken;
|
||||||
if (typeof accessToken !== "string" || !accessToken.trim()) return null;
|
if (typeof accessToken !== "string" || !accessToken.trim()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
const expiresAt = typeof oauth.expiresAt === "number" ? oauth.expiresAt : undefined;
|
const expiresAt = typeof oauth.expiresAt === "number" ? oauth.expiresAt : undefined;
|
||||||
const scopes = Array.isArray(oauth.scopes)
|
const scopes = Array.isArray(oauth.scopes)
|
||||||
? oauth.scopes.filter((v): v is string => typeof v === "string")
|
? oauth.scopes.filter((v): v is string => typeof v === "string")
|
||||||
|
|
@ -110,10 +124,18 @@ const readClaudeCliKeychain = (): {
|
||||||
};
|
};
|
||||||
|
|
||||||
const chromeServiceNameForPath = (cookiePath: string): string => {
|
const chromeServiceNameForPath = (cookiePath: string): string => {
|
||||||
if (cookiePath.includes("/Arc/")) return "Arc Safe Storage";
|
if (cookiePath.includes("/Arc/")) {
|
||||||
if (cookiePath.includes("/BraveSoftware/")) return "Brave Safe Storage";
|
return "Arc Safe Storage";
|
||||||
if (cookiePath.includes("/Microsoft Edge/")) return "Microsoft Edge Safe Storage";
|
}
|
||||||
if (cookiePath.includes("/Chromium/")) return "Chromium Safe Storage";
|
if (cookiePath.includes("/BraveSoftware/")) {
|
||||||
|
return "Brave Safe Storage";
|
||||||
|
}
|
||||||
|
if (cookiePath.includes("/Microsoft Edge/")) {
|
||||||
|
return "Microsoft Edge Safe Storage";
|
||||||
|
}
|
||||||
|
if (cookiePath.includes("/Chromium/")) {
|
||||||
|
return "Chromium Safe Storage";
|
||||||
|
}
|
||||||
return "Chrome Safe Storage";
|
return "Chrome Safe Storage";
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -132,12 +154,18 @@ const readKeychainPassword = (service: string): string | null => {
|
||||||
};
|
};
|
||||||
|
|
||||||
const decryptChromeCookieValue = (encrypted: Buffer, service: string): string | null => {
|
const decryptChromeCookieValue = (encrypted: Buffer, service: string): string | null => {
|
||||||
if (encrypted.length < 4) return null;
|
if (encrypted.length < 4) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
const prefix = encrypted.subarray(0, 3).toString("utf8");
|
const prefix = encrypted.subarray(0, 3).toString("utf8");
|
||||||
if (prefix !== "v10" && prefix !== "v11") return null;
|
if (prefix !== "v10" && prefix !== "v11") {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
const password = readKeychainPassword(service);
|
const password = readKeychainPassword(service);
|
||||||
if (!password) return null;
|
if (!password) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
const key = crypto.pbkdf2Sync(password, "saltysalt", 1003, 16, "sha1");
|
const key = crypto.pbkdf2Sync(password, "saltysalt", 1003, 16, "sha1");
|
||||||
const iv = Buffer.alloc(16, 0x20);
|
const iv = Buffer.alloc(16, 0x20);
|
||||||
|
|
@ -172,10 +200,16 @@ const queryChromeCookieDb = (cookieDb: string): string | null => {
|
||||||
],
|
],
|
||||||
{ encoding: "utf8", stdio: ["ignore", "pipe", "ignore"], timeout: 5000 },
|
{ encoding: "utf8", stdio: ["ignore", "pipe", "ignore"], timeout: 5000 },
|
||||||
).trim();
|
).trim();
|
||||||
if (!out) return null;
|
if (!out) {
|
||||||
if (out.startsWith("sk-ant-")) return out;
|
return null;
|
||||||
|
}
|
||||||
|
if (out.startsWith("sk-ant-")) {
|
||||||
|
return out;
|
||||||
|
}
|
||||||
const hex = out.replace(/[^0-9A-Fa-f]/g, "");
|
const hex = out.replace(/[^0-9A-Fa-f]/g, "");
|
||||||
if (!hex) return null;
|
if (!hex) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
const buf = Buffer.from(hex, "hex");
|
const buf = Buffer.from(hex, "hex");
|
||||||
const service = chromeServiceNameForPath(cookieDb);
|
const service = chromeServiceNameForPath(cookieDb);
|
||||||
const decrypted = decryptChromeCookieValue(buf, service);
|
const decrypted = decryptChromeCookieValue(buf, service);
|
||||||
|
|
@ -209,7 +243,9 @@ const queryFirefoxCookieDb = (cookieDb: string): string | null => {
|
||||||
};
|
};
|
||||||
|
|
||||||
const findClaudeSessionKey = (): { sessionKey: string; source: string } | null => {
|
const findClaudeSessionKey = (): { sessionKey: string; source: string } | null => {
|
||||||
if (process.platform !== "darwin") return null;
|
if (process.platform !== "darwin") {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
const firefoxRoot = path.join(
|
const firefoxRoot = path.join(
|
||||||
os.homedir(),
|
os.homedir(),
|
||||||
|
|
@ -221,9 +257,13 @@ const findClaudeSessionKey = (): { sessionKey: string; source: string } | null =
|
||||||
if (fs.existsSync(firefoxRoot)) {
|
if (fs.existsSync(firefoxRoot)) {
|
||||||
for (const entry of fs.readdirSync(firefoxRoot)) {
|
for (const entry of fs.readdirSync(firefoxRoot)) {
|
||||||
const db = path.join(firefoxRoot, entry, "cookies.sqlite");
|
const db = path.join(firefoxRoot, entry, "cookies.sqlite");
|
||||||
if (!fs.existsSync(db)) continue;
|
if (!fs.existsSync(db)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
const value = queryFirefoxCookieDb(db);
|
const value = queryFirefoxCookieDb(db);
|
||||||
if (value) return { sessionKey: value, source: `firefox:${db}` };
|
if (value) {
|
||||||
|
return { sessionKey: value, source: `firefox:${db}` };
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -236,15 +276,21 @@ const findClaudeSessionKey = (): { sessionKey: string; source: string } | null =
|
||||||
];
|
];
|
||||||
|
|
||||||
for (const root of chromeCandidates) {
|
for (const root of chromeCandidates) {
|
||||||
if (!fs.existsSync(root)) continue;
|
if (!fs.existsSync(root)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
const profiles = fs
|
const profiles = fs
|
||||||
.readdirSync(root)
|
.readdirSync(root)
|
||||||
.filter((name) => name === "Default" || name.startsWith("Profile "));
|
.filter((name) => name === "Default" || name.startsWith("Profile "));
|
||||||
for (const profile of profiles) {
|
for (const profile of profiles) {
|
||||||
const db = path.join(root, profile, "Cookies");
|
const db = path.join(root, profile, "Cookies");
|
||||||
if (!fs.existsSync(db)) continue;
|
if (!fs.existsSync(db)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
const value = queryChromeCookieDb(db);
|
const value = queryChromeCookieDb(db);
|
||||||
if (value) return { sessionKey: value, source: `chromium:${db}` };
|
if (value) {
|
||||||
|
return { sessionKey: value, source: `chromium:${db}` };
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -32,8 +32,14 @@ function compactStrings(values) {
|
||||||
if (value === null || value === undefined) {
|
if (value === null || value === undefined) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
const normalized = String(value).trim();
|
const normalized =
|
||||||
if (normalized.length > 0) {
|
typeof value === "string"
|
||||||
|
? value.trim()
|
||||||
|
: typeof value === "number" || typeof value === "boolean"
|
||||||
|
? String(value).trim()
|
||||||
|
: null;
|
||||||
|
|
||||||
|
if (normalized?.length > 0) {
|
||||||
result.push(normalized);
|
result.push(normalized);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -62,7 +68,7 @@ function walkMarkdownFiles(dir, base = dir) {
|
||||||
files.push(relative(base, fullPath));
|
files.push(relative(base, fullPath));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return files.sort((a, b) => a.localeCompare(b));
|
return files.toSorted((a, b) => a.localeCompare(b));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,9 @@ const userAgent =
|
||||||
const timeoutMs = 30_000;
|
const timeoutMs = 30_000;
|
||||||
|
|
||||||
function truncate(value: string, max = 180): string {
|
function truncate(value: string, max = 180): string {
|
||||||
if (!value) return "";
|
if (!value) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
return value.length > max ? `${value.slice(0, max)}…` : value;
|
return value.length > max ? `${value.slice(0, max)}…` : value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -89,8 +91,12 @@ async function run() {
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log(`local: ${localStatus} len=${localText.length} title=${truncate(localTitle, 80)}`);
|
console.log(`local: ${localStatus} len=${localText.length} title=${truncate(localTitle, 80)}`);
|
||||||
if (localError) console.log(`local error: ${localError}`);
|
if (localError) {
|
||||||
if (localText) console.log(`local sample: ${truncate(localText)}`);
|
console.log(`local error: ${localError}`);
|
||||||
|
}
|
||||||
|
if (localText) {
|
||||||
|
console.log(`local sample: ${truncate(localText)}`);
|
||||||
|
}
|
||||||
|
|
||||||
if (apiKey) {
|
if (apiKey) {
|
||||||
try {
|
try {
|
||||||
|
|
@ -111,8 +117,12 @@ async function run() {
|
||||||
80,
|
80,
|
||||||
)} status=${firecrawl.status ?? "n/a"}`,
|
)} status=${firecrawl.status ?? "n/a"}`,
|
||||||
);
|
);
|
||||||
if (firecrawl.warning) console.log(`firecrawl warning: ${firecrawl.warning}`);
|
if (firecrawl.warning) {
|
||||||
if (firecrawl.text) console.log(`firecrawl sample: ${truncate(firecrawl.text)}`);
|
console.log(`firecrawl warning: ${firecrawl.warning}`);
|
||||||
|
}
|
||||||
|
if (firecrawl.text) {
|
||||||
|
console.log(`firecrawl sample: ${truncate(firecrawl.text)}`);
|
||||||
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
const message = error instanceof Error ? error.message : String(error);
|
const message = error instanceof Error ? error.message : String(error);
|
||||||
console.log(`firecrawl: error ${message}`);
|
console.log(`firecrawl: error ${message}`);
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,9 @@ function runGitCommand(args, options = {}) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function splitNullDelimited(value) {
|
function splitNullDelimited(value) {
|
||||||
if (!value) return [];
|
if (!value) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
const text = String(value);
|
const text = String(value);
|
||||||
return text.split("\0").filter(Boolean);
|
return text.split("\0").filter(Boolean);
|
||||||
}
|
}
|
||||||
|
|
@ -44,7 +46,9 @@ function findPartiallyStagedFiles(stagedFiles, unstagedFiles) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function filterOutPartialTargets(targets, partialTargets) {
|
function filterOutPartialTargets(targets, partialTargets) {
|
||||||
if (partialTargets.length === 0) return targets;
|
if (partialTargets.length === 0) {
|
||||||
|
return targets;
|
||||||
|
}
|
||||||
const partial = new Set(partialTargets.map(normalizeGitPath));
|
const partial = new Set(partialTargets.map(normalizeGitPath));
|
||||||
return targets.filter((filePath) => !partial.has(normalizeGitPath(filePath)));
|
return targets.filter((filePath) => !partial.has(normalizeGitPath(filePath)));
|
||||||
}
|
}
|
||||||
|
|
@ -66,7 +70,9 @@ function resolveOxfmtCommand(repoRoot) {
|
||||||
|
|
||||||
function getGitPaths(args, repoRoot) {
|
function getGitPaths(args, repoRoot) {
|
||||||
const result = runGitCommand(args, { cwd: repoRoot });
|
const result = runGitCommand(args, { cwd: repoRoot });
|
||||||
if (result.status !== 0) return [];
|
if (result.status !== 0) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
return splitNullDelimited(result.stdout ?? "");
|
return splitNullDelimited(result.stdout ?? "");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -79,7 +85,9 @@ function formatFiles(repoRoot, oxfmt, files) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function stageFiles(repoRoot, files) {
|
function stageFiles(repoRoot, files) {
|
||||||
if (files.length === 0) return true;
|
if (files.length === 0) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
const result = runGitCommand(["add", "--", ...files], { cwd: repoRoot, stdio: "inherit" });
|
const result = runGitCommand(["add", "--", ...files], { cwd: repoRoot, stdio: "inherit" });
|
||||||
return result.status === 0;
|
return result.status === 0;
|
||||||
}
|
}
|
||||||
|
|
@ -91,7 +99,9 @@ function main() {
|
||||||
repoRoot,
|
repoRoot,
|
||||||
);
|
);
|
||||||
const targets = filterOxfmtTargets(staged);
|
const targets = filterOxfmtTargets(staged);
|
||||||
if (targets.length === 0) return;
|
if (targets.length === 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const unstaged = getGitPaths(["diff", "--name-only", "-z"], repoRoot);
|
const unstaged = getGitPaths(["diff", "--name-only", "-z"], repoRoot);
|
||||||
const partial = findPartiallyStagedFiles(targets, unstaged);
|
const partial = findPartiallyStagedFiles(targets, unstaged);
|
||||||
|
|
@ -104,7 +114,9 @@ function main() {
|
||||||
}
|
}
|
||||||
|
|
||||||
const filteredTargets = filterOutPartialTargets(targets, partial);
|
const filteredTargets = filterOutPartialTargets(targets, partial);
|
||||||
if (filteredTargets.length === 0) return;
|
if (filteredTargets.length === 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const oxfmt = resolveOxfmtCommand(repoRoot);
|
const oxfmt = resolveOxfmtCommand(repoRoot);
|
||||||
if (!oxfmt) {
|
if (!oxfmt) {
|
||||||
|
|
|
||||||
|
|
@ -10,10 +10,18 @@ function detectPackageManager(ua = process.env.npm_config_user_agent ?? "") {
|
||||||
// - "npm/10.9.4 node/v22.12.0 linux x64"
|
// - "npm/10.9.4 node/v22.12.0 linux x64"
|
||||||
// - "bun/1.2.2"
|
// - "bun/1.2.2"
|
||||||
const normalized = String(ua).trim();
|
const normalized = String(ua).trim();
|
||||||
if (normalized.startsWith("pnpm/")) return "pnpm";
|
if (normalized.startsWith("pnpm/")) {
|
||||||
if (normalized.startsWith("bun/")) return "bun";
|
return "pnpm";
|
||||||
if (normalized.startsWith("npm/")) return "npm";
|
}
|
||||||
if (normalized.startsWith("yarn/")) return "yarn";
|
if (normalized.startsWith("bun/")) {
|
||||||
|
return "bun";
|
||||||
|
}
|
||||||
|
if (normalized.startsWith("npm/")) {
|
||||||
|
return "npm";
|
||||||
|
}
|
||||||
|
if (normalized.startsWith("yarn/")) {
|
||||||
|
return "yarn";
|
||||||
|
}
|
||||||
return "unknown";
|
return "unknown";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -28,38 +36,42 @@ function getRepoRoot() {
|
||||||
}
|
}
|
||||||
|
|
||||||
function ensureExecutable(targetPath) {
|
function ensureExecutable(targetPath) {
|
||||||
if (process.platform === "win32") return;
|
if (process.platform === "win32") {
|
||||||
if (!fs.existsSync(targetPath)) return;
|
return;
|
||||||
|
}
|
||||||
|
if (!fs.existsSync(targetPath)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
try {
|
try {
|
||||||
const mode = fs.statSync(targetPath).mode & 0o777;
|
const mode = fs.statSync(targetPath).mode & 0o777;
|
||||||
if (mode & 0o100) return;
|
if (mode & 0o100) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
fs.chmodSync(targetPath, 0o755);
|
fs.chmodSync(targetPath, 0o755);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.warn(`[postinstall] chmod failed: ${err}`);
|
console.warn(`[postinstall] chmod failed: ${err}`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function hasGit(repoRoot) {
|
|
||||||
const result = spawnSync("git", ["--version"], {
|
|
||||||
cwd: repoRoot,
|
|
||||||
stdio: "ignore",
|
|
||||||
});
|
|
||||||
return result.status === 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
function extractPackageName(key) {
|
function extractPackageName(key) {
|
||||||
if (key.startsWith("@")) {
|
if (key.startsWith("@")) {
|
||||||
const idx = key.indexOf("@", 1);
|
const idx = key.indexOf("@", 1);
|
||||||
if (idx === -1) return key;
|
if (idx === -1) {
|
||||||
|
return key;
|
||||||
|
}
|
||||||
return key.slice(0, idx);
|
return key.slice(0, idx);
|
||||||
}
|
}
|
||||||
const idx = key.lastIndexOf("@");
|
const idx = key.lastIndexOf("@");
|
||||||
if (idx <= 0) return key;
|
if (idx <= 0) {
|
||||||
|
return key;
|
||||||
|
}
|
||||||
return key.slice(0, idx);
|
return key.slice(0, idx);
|
||||||
}
|
}
|
||||||
|
|
||||||
function stripPrefix(p) {
|
function stripPrefix(p) {
|
||||||
if (p.startsWith("a/") || p.startsWith("b/")) return p.slice(2);
|
if (p.startsWith("a/") || p.startsWith("b/")) {
|
||||||
|
return p.slice(2);
|
||||||
|
}
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -89,7 +101,9 @@ function parsePatch(patchText) {
|
||||||
i += 1;
|
i += 1;
|
||||||
|
|
||||||
// Skip index line(s)
|
// Skip index line(s)
|
||||||
while (i < lines.length && lines[i].startsWith("index ")) i += 1;
|
while (i < lines.length && lines[i].startsWith("index ")) {
|
||||||
|
i += 1;
|
||||||
|
}
|
||||||
|
|
||||||
if (i < lines.length && lines[i].startsWith("--- ")) {
|
if (i < lines.length && lines[i].startsWith("--- ")) {
|
||||||
file.oldPath = stripPrefix(lines[i].slice(4).trim());
|
file.oldPath = stripPrefix(lines[i].slice(4).trim());
|
||||||
|
|
@ -103,7 +117,9 @@ function parsePatch(patchText) {
|
||||||
while (i < lines.length && lines[i].startsWith("@@")) {
|
while (i < lines.length && lines[i].startsWith("@@")) {
|
||||||
const header = lines[i];
|
const header = lines[i];
|
||||||
const match = /^@@\s+(-\d+(?:,\d+)?)\s+(\+\d+(?:,\d+)?)\s+@@/.exec(header);
|
const match = /^@@\s+(-\d+(?:,\d+)?)\s+(\+\d+(?:,\d+)?)\s+@@/.exec(header);
|
||||||
if (!match) throw new Error(`invalid hunk header: ${header}`);
|
if (!match) {
|
||||||
|
throw new Error(`invalid hunk header: ${header}`);
|
||||||
|
}
|
||||||
const oldRange = parseRange(match[1]);
|
const oldRange = parseRange(match[1]);
|
||||||
const newRange = parseRange(match[2]);
|
const newRange = parseRange(match[2]);
|
||||||
i += 1;
|
i += 1;
|
||||||
|
|
@ -111,7 +127,9 @@ function parsePatch(patchText) {
|
||||||
const hunkLines = [];
|
const hunkLines = [];
|
||||||
while (i < lines.length) {
|
while (i < lines.length) {
|
||||||
const line = lines[i];
|
const line = lines[i];
|
||||||
if (line.startsWith("@@") || line.startsWith("diff --git ")) break;
|
if (line.startsWith("@@") || line.startsWith("diff --git ")) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
if (line === "") {
|
if (line === "") {
|
||||||
i += 1;
|
i += 1;
|
||||||
continue;
|
continue;
|
||||||
|
|
@ -148,7 +166,9 @@ function readFileLines(targetPath) {
|
||||||
const raw = fs.readFileSync(targetPath, "utf-8");
|
const raw = fs.readFileSync(targetPath, "utf-8");
|
||||||
const hasTrailingNewline = raw.endsWith("\n");
|
const hasTrailingNewline = raw.endsWith("\n");
|
||||||
const parts = raw.split("\n");
|
const parts = raw.split("\n");
|
||||||
if (hasTrailingNewline) parts.pop();
|
if (hasTrailingNewline) {
|
||||||
|
parts.pop();
|
||||||
|
}
|
||||||
return { lines: parts, hasTrailingNewline };
|
return { lines: parts, hasTrailingNewline };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -235,7 +255,9 @@ function applyPatchSet({ patchText, targetDir }) {
|
||||||
resolvedTarget = fs.realpathSync(resolvedTarget);
|
resolvedTarget = fs.realpathSync(resolvedTarget);
|
||||||
|
|
||||||
const files = parsePatch(patchText);
|
const files = parsePatch(patchText);
|
||||||
if (files.length === 0) return;
|
if (files.length === 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
for (const filePatch of files) {
|
for (const filePatch of files) {
|
||||||
applyPatchToFile(resolvedTarget, filePatch);
|
applyPatchToFile(resolvedTarget, filePatch);
|
||||||
|
|
@ -253,14 +275,20 @@ function applyPatchFile({ patchPath, targetDir }) {
|
||||||
|
|
||||||
function trySetupCompletion(repoRoot) {
|
function trySetupCompletion(repoRoot) {
|
||||||
// Skip in CI or if explicitly disabled
|
// Skip in CI or if explicitly disabled
|
||||||
if (process.env.CI || process.env.OPENCLAW_SKIP_COMPLETION_SETUP) return;
|
if (process.env.CI || process.env.OPENCLAW_SKIP_COMPLETION_SETUP) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const binPath = path.join(repoRoot, "openclaw.mjs");
|
const binPath = path.join(repoRoot, "openclaw.mjs");
|
||||||
if (!fs.existsSync(binPath)) return;
|
if (!fs.existsSync(binPath)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// In development, dist might not exist yet during postinstall
|
// In development, dist might not exist yet during postinstall
|
||||||
const distEntry = path.join(repoRoot, "dist", "index.js");
|
const distEntry = path.join(repoRoot, "dist", "index.js");
|
||||||
if (!fs.existsSync(distEntry)) return;
|
if (!fs.existsSync(distEntry)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Run with OPENCLAW_SKIP_POSTINSTALL to avoid any weird recursion,
|
// Run with OPENCLAW_SKIP_POSTINSTALL to avoid any weird recursion,
|
||||||
|
|
@ -270,7 +298,7 @@ function trySetupCompletion(repoRoot) {
|
||||||
stdio: "inherit",
|
stdio: "inherit",
|
||||||
env: { ...process.env, OPENCLAW_SKIP_POSTINSTALL: "1" },
|
env: { ...process.env, OPENCLAW_SKIP_POSTINSTALL: "1" },
|
||||||
});
|
});
|
||||||
} catch (err) {
|
} catch {
|
||||||
// Ignore errors to not break install
|
// Ignore errors to not break install
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -294,9 +322,13 @@ function main() {
|
||||||
// Bun does not support pnpm.patchedDependencies. Apply these patch files to
|
// Bun does not support pnpm.patchedDependencies. Apply these patch files to
|
||||||
// node_modules packages as a best-effort compatibility layer.
|
// node_modules packages as a best-effort compatibility layer.
|
||||||
for (const [key, relPatchPath] of Object.entries(patched)) {
|
for (const [key, relPatchPath] of Object.entries(patched)) {
|
||||||
if (typeof relPatchPath !== "string" || !relPatchPath.trim()) continue;
|
if (typeof relPatchPath !== "string" || !relPatchPath.trim()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
const pkgName = extractPackageName(String(key));
|
const pkgName = extractPackageName(String(key));
|
||||||
if (!pkgName) continue;
|
if (!pkgName) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
applyPatchFile({
|
applyPatchFile({
|
||||||
targetDir: path.join("node_modules", ...pkgName.split("/")),
|
targetDir: path.join("node_modules", ...pkgName.split("/")),
|
||||||
patchPath: relPatchPath,
|
patchPath: relPatchPath,
|
||||||
|
|
|
||||||
|
|
@ -72,7 +72,9 @@ function camelCase(input: string) {
|
||||||
|
|
||||||
function safeName(name: string) {
|
function safeName(name: string) {
|
||||||
const cc = camelCase(name.replace(/-/g, "_"));
|
const cc = camelCase(name.replace(/-/g, "_"));
|
||||||
if (reserved.has(cc)) return `_${cc}`;
|
if (reserved.has(cc)) {
|
||||||
|
return `_${cc}`;
|
||||||
|
}
|
||||||
return cc;
|
return cc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -86,11 +88,15 @@ function swiftType(schema: JsonSchema, required: boolean): string {
|
||||||
const named = schemaNameByObject.get(schema as object);
|
const named = schemaNameByObject.get(schema as object);
|
||||||
if (named) {
|
if (named) {
|
||||||
base = named;
|
base = named;
|
||||||
} else if (t === "string") base = "String";
|
} else if (t === "string") {
|
||||||
else if (t === "integer") base = "Int";
|
base = "String";
|
||||||
else if (t === "number") base = "Double";
|
} else if (t === "integer") {
|
||||||
else if (t === "boolean") base = "Bool";
|
base = "Int";
|
||||||
else if (t === "array") {
|
} else if (t === "number") {
|
||||||
|
base = "Double";
|
||||||
|
} else if (t === "boolean") {
|
||||||
|
base = "Bool";
|
||||||
|
} else if (t === "array") {
|
||||||
base = `[${swiftType(schema.items ?? { type: "Any" }, true)}]`;
|
base = `[${swiftType(schema.items ?? { type: "Any" }, true)}]`;
|
||||||
} else if (schema.enum) {
|
} else if (schema.enum) {
|
||||||
base = "String";
|
base = "String";
|
||||||
|
|
@ -213,7 +219,9 @@ async function generate() {
|
||||||
|
|
||||||
// Value structs
|
// Value structs
|
||||||
for (const [name, schema] of definitions) {
|
for (const [name, schema] of definitions) {
|
||||||
if (name === "GatewayFrame") continue;
|
if (name === "GatewayFrame") {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
if (schema.type === "object") {
|
if (schema.type === "object") {
|
||||||
parts.push(emitStruct(name, schema));
|
parts.push(emitStruct(name, schema));
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,9 @@ async function runFetch(url: string, readability: boolean) {
|
||||||
},
|
},
|
||||||
sandboxed: false,
|
sandboxed: false,
|
||||||
});
|
});
|
||||||
if (!tool) throw new Error("web_fetch tool is disabled");
|
if (!tool) {
|
||||||
|
throw new Error("web_fetch tool is disabled");
|
||||||
|
}
|
||||||
const result = await tool.execute("test", { url, extractMode: "markdown" });
|
const result = await tool.execute("test", { url, extractMode: "markdown" });
|
||||||
return result.details as {
|
return result.details as {
|
||||||
text?: string;
|
text?: string;
|
||||||
|
|
@ -35,7 +37,9 @@ async function runFetch(url: string, readability: boolean) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function truncate(value: string, max = 160): string {
|
function truncate(value: string, max = 160): string {
|
||||||
if (!value) return "";
|
if (!value) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
return value.length > max ? `${value.slice(0, max)}…` : value;
|
return value.length > max ? `${value.slice(0, max)}…` : value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -50,7 +54,9 @@ async function run() {
|
||||||
80,
|
80,
|
||||||
)}`,
|
)}`,
|
||||||
);
|
);
|
||||||
if (readable.text) console.log(`readability sample: ${truncate(readable.text)}`);
|
if (readable.text) {
|
||||||
|
console.log(`readability sample: ${truncate(readable.text)}`);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,9 @@ const statMtime = (filePath) => {
|
||||||
|
|
||||||
const isExcludedSource = (filePath) => {
|
const isExcludedSource = (filePath) => {
|
||||||
const relativePath = path.relative(srcRoot, filePath);
|
const relativePath = path.relative(srcRoot, filePath);
|
||||||
if (relativePath.startsWith("..")) return false;
|
if (relativePath.startsWith("..")) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
return (
|
return (
|
||||||
relativePath.endsWith(".test.ts") ||
|
relativePath.endsWith(".test.ts") ||
|
||||||
relativePath.endsWith(".test.tsx") ||
|
relativePath.endsWith(".test.tsx") ||
|
||||||
|
|
@ -40,7 +42,9 @@ const findLatestMtime = (dirPath, shouldSkip) => {
|
||||||
const queue = [dirPath];
|
const queue = [dirPath];
|
||||||
while (queue.length > 0) {
|
while (queue.length > 0) {
|
||||||
const current = queue.pop();
|
const current = queue.pop();
|
||||||
if (!current) continue;
|
if (!current) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
let entries = [];
|
let entries = [];
|
||||||
try {
|
try {
|
||||||
entries = fs.readdirSync(current, { withFileTypes: true });
|
entries = fs.readdirSync(current, { withFileTypes: true });
|
||||||
|
|
@ -53,10 +57,16 @@ const findLatestMtime = (dirPath, shouldSkip) => {
|
||||||
queue.push(fullPath);
|
queue.push(fullPath);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (!entry.isFile()) continue;
|
if (!entry.isFile()) {
|
||||||
if (shouldSkip?.(fullPath)) continue;
|
continue;
|
||||||
|
}
|
||||||
|
if (shouldSkip?.(fullPath)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
const mtime = statMtime(fullPath);
|
const mtime = statMtime(fullPath);
|
||||||
if (mtime == null) continue;
|
if (mtime == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
if (latest == null || mtime > latest) {
|
if (latest == null || mtime > latest) {
|
||||||
latest = mtime;
|
latest = mtime;
|
||||||
}
|
}
|
||||||
|
|
@ -66,23 +76,35 @@ const findLatestMtime = (dirPath, shouldSkip) => {
|
||||||
};
|
};
|
||||||
|
|
||||||
const shouldBuild = () => {
|
const shouldBuild = () => {
|
||||||
if (env.OPENCLAW_FORCE_BUILD === "1") return true;
|
if (env.OPENCLAW_FORCE_BUILD === "1") {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
const stampMtime = statMtime(buildStampPath);
|
const stampMtime = statMtime(buildStampPath);
|
||||||
if (stampMtime == null) return true;
|
if (stampMtime == null) {
|
||||||
if (statMtime(distEntry) == null) return true;
|
return true;
|
||||||
|
}
|
||||||
|
if (statMtime(distEntry) == null) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
for (const filePath of configFiles) {
|
for (const filePath of configFiles) {
|
||||||
const mtime = statMtime(filePath);
|
const mtime = statMtime(filePath);
|
||||||
if (mtime != null && mtime > stampMtime) return true;
|
if (mtime != null && mtime > stampMtime) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const srcMtime = findLatestMtime(srcRoot, isExcludedSource);
|
const srcMtime = findLatestMtime(srcRoot, isExcludedSource);
|
||||||
if (srcMtime != null && srcMtime > stampMtime) return true;
|
if (srcMtime != null && srcMtime > stampMtime) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
|
|
||||||
const logRunner = (message) => {
|
const logRunner = (message) => {
|
||||||
if (env.OPENCLAW_RUNNER_LOG === "0") return;
|
if (env.OPENCLAW_RUNNER_LOG === "0") {
|
||||||
|
return;
|
||||||
|
}
|
||||||
process.stderr.write(`[openclaw] ${message}\n`);
|
process.stderr.write(`[openclaw] ${message}\n`);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -20,11 +20,17 @@ function runGitCommand(args, options = {}) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function ensureExecutable(targetPath) {
|
function ensureExecutable(targetPath) {
|
||||||
if (process.platform === "win32") return;
|
if (process.platform === "win32") {
|
||||||
if (!fs.existsSync(targetPath)) return;
|
return;
|
||||||
|
}
|
||||||
|
if (!fs.existsSync(targetPath)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
try {
|
try {
|
||||||
const mode = fs.statSync(targetPath).mode & 0o777;
|
const mode = fs.statSync(targetPath).mode & 0o777;
|
||||||
if (mode & 0o100) return;
|
if (mode & 0o100) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
fs.chmodSync(targetPath, 0o755);
|
fs.chmodSync(targetPath, 0o755);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.warn(`[setup-git-hooks] chmod failed: ${err}`);
|
console.warn(`[setup-git-hooks] chmod failed: ${err}`);
|
||||||
|
|
@ -41,7 +47,9 @@ function isGitRepo({ repoRoot = getRepoRoot(), runGit = runGitCommand } = {}) {
|
||||||
cwd: repoRoot,
|
cwd: repoRoot,
|
||||||
stdio: "pipe",
|
stdio: "pipe",
|
||||||
});
|
});
|
||||||
if (result.status !== 0) return false;
|
if (result.status !== 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
return String(result.stdout ?? "").trim() === "true";
|
return String(result.stdout ?? "").trim() === "true";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -44,7 +44,9 @@ function replaceBlockLines(
|
||||||
];
|
];
|
||||||
|
|
||||||
const replacement = replacementLines.join("\n");
|
const replacement = replacementLines.join("\n");
|
||||||
if (!after) return `${before}${replacement}`;
|
if (!after) {
|
||||||
|
return `${before}${replacement}`;
|
||||||
|
}
|
||||||
return `${before}${replacement}\n${after}`;
|
return `${before}${replacement}\n${after}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,6 @@ type PackageJson = {
|
||||||
version?: string;
|
version?: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
const root = resolve(".");
|
|
||||||
const rootPackagePath = resolve("package.json");
|
const rootPackagePath = resolve("package.json");
|
||||||
const rootPackage = JSON.parse(readFileSync(rootPackagePath, "utf8")) as PackageJson;
|
const rootPackage = JSON.parse(readFileSync(rootPackagePath, "utf8")) as PackageJson;
|
||||||
const targetVersion = rootPackage.version;
|
const targetVersion = rootPackage.version;
|
||||||
|
|
@ -25,9 +24,13 @@ const changelogged: string[] = [];
|
||||||
const skipped: string[] = [];
|
const skipped: string[] = [];
|
||||||
|
|
||||||
function ensureChangelogEntry(changelogPath: string, version: string): boolean {
|
function ensureChangelogEntry(changelogPath: string, version: string): boolean {
|
||||||
if (!existsSync(changelogPath)) return false;
|
if (!existsSync(changelogPath)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
const content = readFileSync(changelogPath, "utf8");
|
const content = readFileSync(changelogPath, "utf8");
|
||||||
if (content.includes(`## ${version}`)) return false;
|
if (content.includes(`## ${version}`)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
const entry = `## ${version}\n\n### Changes\n- Version alignment with core OpenClaw release numbers.\n\n`;
|
const entry = `## ${version}\n\n### Changes\n- Version alignment with core OpenClaw release numbers.\n\n`;
|
||||||
if (content.startsWith("# Changelog\n\n")) {
|
if (content.startsWith("# Changelog\n\n")) {
|
||||||
const next = content.replace("# Changelog\n\n", `# Changelog\n\n${entry}`);
|
const next = content.replace("# Changelog\n\n", `# Changelog\n\n${entry}`);
|
||||||
|
|
|
||||||
|
|
@ -74,11 +74,15 @@ const runOnce = (entry, extraArgs = []) =>
|
||||||
});
|
});
|
||||||
|
|
||||||
const run = async (entry) => {
|
const run = async (entry) => {
|
||||||
if (shardCount <= 1) return runOnce(entry);
|
if (shardCount <= 1) {
|
||||||
|
return runOnce(entry);
|
||||||
|
}
|
||||||
for (let shardIndex = 1; shardIndex <= shardCount; shardIndex += 1) {
|
for (let shardIndex = 1; shardIndex <= shardCount; shardIndex += 1) {
|
||||||
// eslint-disable-next-line no-await-in-loop
|
// eslint-disable-next-line no-await-in-loop
|
||||||
const code = await runOnce(entry, ["--shard", `${shardIndex}/${shardCount}`]);
|
const code = await runOnce(entry, ["--shard", `${shardIndex}/${shardCount}`]);
|
||||||
if (code !== 0) return code;
|
if (code !== 0) {
|
||||||
|
return code;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,9 @@ function which(cmd) {
|
||||||
for (const ext of extensions) {
|
for (const ext of extensions) {
|
||||||
const candidate = path.join(entry, process.platform === "win32" ? `${cmd}${ext}` : cmd);
|
const candidate = path.join(entry, process.platform === "win32" ? `${cmd}${ext}` : cmd);
|
||||||
try {
|
try {
|
||||||
if (fs.existsSync(candidate)) return candidate;
|
if (fs.existsSync(candidate)) {
|
||||||
|
return candidate;
|
||||||
|
}
|
||||||
} catch {
|
} catch {
|
||||||
// ignore
|
// ignore
|
||||||
}
|
}
|
||||||
|
|
@ -42,7 +44,9 @@ function which(cmd) {
|
||||||
|
|
||||||
function resolveRunner() {
|
function resolveRunner() {
|
||||||
const pnpm = which("pnpm");
|
const pnpm = which("pnpm");
|
||||||
if (pnpm) return { cmd: pnpm, kind: "pnpm" };
|
if (pnpm) {
|
||||||
|
return { cmd: pnpm, kind: "pnpm" };
|
||||||
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -54,7 +58,9 @@ function run(cmd, args) {
|
||||||
shell: process.platform === "win32",
|
shell: process.platform === "win32",
|
||||||
});
|
});
|
||||||
child.on("exit", (code, signal) => {
|
child.on("exit", (code, signal) => {
|
||||||
if (signal) process.exit(1);
|
if (signal) {
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
process.exit(code ?? 1);
|
process.exit(code ?? 1);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
@ -66,8 +72,12 @@ function runSync(cmd, args, envOverride) {
|
||||||
env: envOverride ?? process.env,
|
env: envOverride ?? process.env,
|
||||||
shell: process.platform === "win32",
|
shell: process.platform === "win32",
|
||||||
});
|
});
|
||||||
if (result.signal) process.exit(1);
|
if (result.signal) {
|
||||||
if ((result.status ?? 1) !== 0) process.exit(result.status ?? 1);
|
process.exit(1);
|
||||||
|
}
|
||||||
|
if ((result.status ?? 1) !== 0) {
|
||||||
|
process.exit(result.status ?? 1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function depsInstalled(kind) {
|
function depsInstalled(kind) {
|
||||||
|
|
@ -114,8 +124,9 @@ if (action !== "install" && !script) {
|
||||||
process.exit(2);
|
process.exit(2);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (action === "install") run(runner.cmd, ["install", ...rest]);
|
if (action === "install") {
|
||||||
else {
|
run(runner.cmd, ["install", ...rest]);
|
||||||
|
} else {
|
||||||
if (!depsInstalled(action === "test" ? "test" : "build")) {
|
if (!depsInstalled(action === "test" ? "test" : "build")) {
|
||||||
const installEnv =
|
const installEnv =
|
||||||
action === "build" ? { ...process.env, NODE_ENV: "production" } : process.env;
|
action === "build" ? { ...process.env, NODE_ENV: "production" } : process.env;
|
||||||
|
|
|
||||||
|
|
@ -229,7 +229,7 @@ const lines: string[] = [];
|
||||||
for (let i = 0; i < entries.length; i += PER_LINE) {
|
for (let i = 0; i < entries.length; i += PER_LINE) {
|
||||||
const chunk = entries.slice(i, i + PER_LINE);
|
const chunk = entries.slice(i, i + PER_LINE);
|
||||||
const parts = chunk.map((entry) => {
|
const parts = chunk.map((entry) => {
|
||||||
return `<a href=\"${entry.html_url}\"><img src=\"${entry.avatar_url}\" width=\"48\" height=\"48\" alt=\"${entry.display}\" title=\"${entry.display}\"/></a>`;
|
return `<a href="${entry.html_url}"><img src="${entry.avatar_url}" width="48" height="48" alt="${entry.display}" title="${entry.display}"/></a>`;
|
||||||
});
|
});
|
||||||
lines.push(` ${parts.join(" ")}`);
|
lines.push(` ${parts.join(" ")}`);
|
||||||
}
|
}
|
||||||
|
|
@ -243,7 +243,7 @@ if (start === -1 || end === -1) {
|
||||||
throw new Error("README.md missing clawtributors block");
|
throw new Error("README.md missing clawtributors block");
|
||||||
}
|
}
|
||||||
|
|
||||||
const next = `${readme.slice(0, start)}<p align=\"left\">\n${block}${readme.slice(end)}`;
|
const next = `${readme.slice(0, start)}<p align="left">\n${block}${readme.slice(end)}`;
|
||||||
writeFileSync(readmePath, next);
|
writeFileSync(readmePath, next);
|
||||||
|
|
||||||
console.log(`Updated README clawtributors: ${entries.length} entries`);
|
console.log(`Updated README clawtributors: ${entries.length} entries`);
|
||||||
|
|
@ -419,7 +419,7 @@ function parseReadmeEntries(
|
||||||
}
|
}
|
||||||
const block = content.slice(start, end);
|
const block = content.slice(start, end);
|
||||||
const entries: Array<{ display: string; html_url: string; avatar_url: string }> = [];
|
const entries: Array<{ display: string; html_url: string; avatar_url: string }> = [];
|
||||||
const linked = /<a href=\"([^\"]+)\"><img src=\"([^\"]+)\"[^>]*alt=\"([^\"]+)\"[^>]*>/g;
|
const linked = /<a href="([^"]+)"><img src="([^"]+)"[^>]*alt="([^"]+)"[^>]*>/g;
|
||||||
for (const match of block.matchAll(linked)) {
|
for (const match of block.matchAll(linked)) {
|
||||||
const [, href, src, alt] = match;
|
const [, href, src, alt] = match;
|
||||||
if (!href || !src || !alt) {
|
if (!href || !src || !alt) {
|
||||||
|
|
@ -427,7 +427,7 @@ function parseReadmeEntries(
|
||||||
}
|
}
|
||||||
entries.push({ html_url: href, avatar_url: src, display: alt });
|
entries.push({ html_url: href, avatar_url: src, display: alt });
|
||||||
}
|
}
|
||||||
const standalone = /<img src=\"([^\"]+)\"[^>]*alt=\"([^\"]+)\"[^>]*>/g;
|
const standalone = /<img src="([^"]+)"[^>]*alt="([^"]+)"[^>]*>/g;
|
||||||
for (const match of block.matchAll(standalone)) {
|
for (const match of block.matchAll(standalone)) {
|
||||||
const [, src, alt] = match;
|
const [, src, alt] = match;
|
||||||
if (!src || !alt) {
|
if (!src || !alt) {
|
||||||
|
|
@ -442,7 +442,7 @@ function parseReadmeEntries(
|
||||||
}
|
}
|
||||||
|
|
||||||
function loginFromUrl(url: string): string | null {
|
function loginFromUrl(url: string): string | null {
|
||||||
const match = /^https?:\/\/github\.com\/([^\/?#]+)/i.exec(url);
|
const match = /^https?:\/\/github\.com\/([^/?#]+)/i.exec(url);
|
||||||
if (!match) {
|
if (!match) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,9 @@ const readPackageVersion = () => {
|
||||||
|
|
||||||
const resolveCommit = () => {
|
const resolveCommit = () => {
|
||||||
const envCommit = process.env.GIT_COMMIT?.trim() || process.env.GIT_SHA?.trim();
|
const envCommit = process.env.GIT_COMMIT?.trim() || process.env.GIT_SHA?.trim();
|
||||||
if (envCommit) return envCommit;
|
if (envCommit) {
|
||||||
|
return envCommit;
|
||||||
|
}
|
||||||
try {
|
try {
|
||||||
return execSync("git rev-parse HEAD", {
|
return execSync("git rev-parse HEAD", {
|
||||||
cwd: rootDir,
|
cwd: rootDir,
|
||||||
|
|
|
||||||
|
|
@ -13,9 +13,13 @@ type RunResult = {
|
||||||
|
|
||||||
function pickAnthropicEnv(): { type: "oauth" | "api"; value: string } | null {
|
function pickAnthropicEnv(): { type: "oauth" | "api"; value: string } | null {
|
||||||
const oauth = process.env.ANTHROPIC_OAUTH_TOKEN?.trim();
|
const oauth = process.env.ANTHROPIC_OAUTH_TOKEN?.trim();
|
||||||
if (oauth) return { type: "oauth", value: oauth };
|
if (oauth) {
|
||||||
|
return { type: "oauth", value: oauth };
|
||||||
|
}
|
||||||
const api = process.env.ANTHROPIC_API_KEY?.trim();
|
const api = process.env.ANTHROPIC_API_KEY?.trim();
|
||||||
if (api) return { type: "api", value: api };
|
if (api) {
|
||||||
|
return { type: "api", value: api };
|
||||||
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue