mirror of
https://github.com/openclaw/openclaw.git
synced 2026-07-21 02:06:43 +00:00
chore(tooling): typecheck scripts/** with a dedicated tsgo lane (#104348)
* feat(tooling): add tsgo typecheck lane for scripts/** * fix(scripts): burn down scripts type debt surfaced by the new lane Typing-only except bugs the lane surfaced: gh-read timeout race, Discord Headers spread dropping entries, undefined allowedHeadBranches match, plugin-boundary matchAll crash. Deletes retired config keys from fixtures/benches (prompt snapshots regenerated, config dump only) and the orphaned non-runnable sync-moonshot-docs script. Adds full-surface .d.mts declarations for existing .mjs boundaries.
This commit is contained in:
@@ -1348,6 +1348,7 @@ jobs:
|
||||
;;
|
||||
test-types)
|
||||
pnpm check:test-types
|
||||
pnpm tsgo:scripts
|
||||
;;
|
||||
*)
|
||||
echo "Unsupported check task: $TASK" >&2
|
||||
|
||||
@@ -1962,6 +1962,7 @@
|
||||
"tsgo:extensions:test": "node scripts/run-tsgo.mjs -p test/tsconfig/tsconfig.extensions.test.json --incremental --tsBuildInfoFile .artifacts/tsgo-cache/extensions-test.tsbuildinfo",
|
||||
"tsgo:prod": "pnpm tsgo:core && pnpm tsgo:extensions",
|
||||
"tsgo:profile": "node scripts/profile-tsgo.mjs",
|
||||
"tsgo:scripts": "node scripts/run-tsgo.mjs -p tsconfig.scripts.json --incremental --tsBuildInfoFile .artifacts/tsgo-cache/scripts.tsbuildinfo",
|
||||
"tsgo:test": "pnpm tsgo:core:test && pnpm tsgo:extensions:test",
|
||||
"tsgo:test:extensions": "pnpm tsgo:extensions:test",
|
||||
"tsgo:test:packages": "node scripts/run-tsgo.mjs -p test/tsconfig/tsconfig.test.packages.json --incremental --tsBuildInfoFile .artifacts/tsgo-cache/test-packages.tsbuildinfo",
|
||||
|
||||
@@ -65,7 +65,7 @@ export async function checkAndroidAppI18n() {
|
||||
]);
|
||||
const [base, ...translations] = localeStrings;
|
||||
const baseKeys = new Set(base.keys());
|
||||
const problems = translations.flatMap((strings, index) => {
|
||||
const problems: Array<readonly [string, string[]]> = translations.flatMap((strings, index) => {
|
||||
const locale = NATIVE_I18N_LOCALES[index];
|
||||
const keys = new Set(strings.keys());
|
||||
const placeholderMismatches = [...base].flatMap(([key, sourceValue]) => {
|
||||
|
||||
@@ -212,17 +212,16 @@ function listSetupTokenProfiles(
|
||||
store: { profiles: Record<string, AuthProfileCredential> },
|
||||
normalizeProviderId: (provider: string) => string,
|
||||
): Array<{ id: string; token: string }> {
|
||||
return Object.entries(store.profiles)
|
||||
.filter(([, cred]) => {
|
||||
if (cred.type !== "token") {
|
||||
return false;
|
||||
}
|
||||
if (normalizeProviderId(cred.provider) !== "anthropic") {
|
||||
return false;
|
||||
}
|
||||
return isSetupToken(cred.token ?? "");
|
||||
})
|
||||
.map(([id, cred]) => ({ id, token: cred.token ?? "" }));
|
||||
return Object.entries(store.profiles).flatMap(([id, cred]) => {
|
||||
if (
|
||||
cred.type !== "token" ||
|
||||
normalizeProviderId(cred.provider) !== "anthropic" ||
|
||||
!isSetupToken(cred.token ?? "")
|
||||
) {
|
||||
return [];
|
||||
}
|
||||
return [{ id, token: cred.token ?? "" }];
|
||||
});
|
||||
}
|
||||
|
||||
function pickSetupTokenProfile(candidates: Array<{ id: string; token: string }>): {
|
||||
@@ -390,15 +389,16 @@ async function startAnthropicProxy(params: { port: number; upstreamBaseUrl: stri
|
||||
}
|
||||
headers.set(key, Array.isArray(value) ? value.join(", ") : value);
|
||||
}
|
||||
const upstreamRes = await fetch(upstreamUrl, {
|
||||
const upstreamInit = {
|
||||
method,
|
||||
headers,
|
||||
body:
|
||||
method === "GET" || method === "HEAD" || requestBody.byteLength === 0
|
||||
? undefined
|
||||
: requestBody,
|
||||
: Uint8Array.from(requestBody),
|
||||
duplex: "half",
|
||||
});
|
||||
} as RequestInit & { duplex: "half" };
|
||||
const upstreamRes = await fetch(upstreamUrl, upstreamInit);
|
||||
const responseHeaders: Record<string, string> = {};
|
||||
for (const [key, value] of upstreamRes.headers.entries()) {
|
||||
const lower = key.toLowerCase();
|
||||
@@ -926,19 +926,21 @@ async function runGatewayPrompt(prompt: string): Promise<PromptResult> {
|
||||
mode: "cli",
|
||||
});
|
||||
const text = extractPayloadText(waitRes);
|
||||
const waitStatus = typeof waitRes.status === "string" ? waitRes.status : undefined;
|
||||
const waitError = typeof waitRes.error === "string" ? waitRes.error : undefined;
|
||||
const logTail = await readLogTail(logPath);
|
||||
const matched400 = matchesExtraUsage400(waitRes.error, logTail, JSON.stringify(waitRes));
|
||||
const matched400 = matchesExtraUsage400(waitError, logTail, JSON.stringify(waitRes));
|
||||
return {
|
||||
prompt,
|
||||
ok: waitRes.status === "ok" && !matched400,
|
||||
ok: waitStatus === "ok" && !matched400,
|
||||
transport: "gateway",
|
||||
promptMode: GATEWAY_PROMPT_MODE,
|
||||
status: waitRes.status,
|
||||
status: waitStatus,
|
||||
text: text || undefined,
|
||||
error:
|
||||
waitRes.status === "ok"
|
||||
waitStatus === "ok"
|
||||
? undefined
|
||||
: redactForDevToolLog(waitRes.error || logTail || "agent.wait failed"),
|
||||
: redactForDevToolLog(waitError || logTail || "agent.wait failed"),
|
||||
matchedExtraUsage400: matched400,
|
||||
capture: summarizeCapture(proxy?.getLastCapture(), prompt),
|
||||
...promptProbeTmpResult(tmpDir),
|
||||
|
||||
@@ -24,7 +24,12 @@ const LOCALIZED_WRAPPER_CONTRACTS: Record<string, string[]> = {
|
||||
],
|
||||
};
|
||||
|
||||
const CATALOGS = [
|
||||
type AppleCatalogSpec = {
|
||||
path: string;
|
||||
coverage: Record<string, readonly string[]>;
|
||||
};
|
||||
|
||||
const CATALOGS: readonly AppleCatalogSpec[] = [
|
||||
{
|
||||
path: "apps/ios/Resources/Localizable.xcstrings",
|
||||
coverage: {
|
||||
@@ -99,7 +104,7 @@ const CATALOGS = [
|
||||
"apps/macos/Sources/OpenClaw/CronSettings+Rows.swift": ["Run now"],
|
||||
},
|
||||
},
|
||||
] as const;
|
||||
];
|
||||
|
||||
type Catalog = {
|
||||
sourceLanguage?: string;
|
||||
|
||||
@@ -182,6 +182,7 @@ async function main(argv = process.argv.slice(2)): Promise<void> {
|
||||
name: "Claude Opus 4.6",
|
||||
api: "anthropic-messages",
|
||||
provider: "anthropic",
|
||||
baseUrl: "https://api.anthropic.com",
|
||||
reasoning: true,
|
||||
input: ["text", "image"],
|
||||
cost: { input: 15, output: 75, cacheRead: 1.5, cacheWrite: 18.75 },
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
import fs from "node:fs";
|
||||
import os from "node:os";
|
||||
import path from "node:path";
|
||||
import type { DatabaseSync } from "node:sqlite";
|
||||
import type { DatabaseSync, SQLInputValue } from "node:sqlite";
|
||||
import { pathToFileURL } from "node:url";
|
||||
import {
|
||||
openOpenClawAgentDatabase,
|
||||
@@ -465,7 +465,7 @@ function percentile(values: number[], pct: number): number {
|
||||
function runTimedQuery(
|
||||
db: DatabaseSync,
|
||||
query: string,
|
||||
params: unknown[],
|
||||
params: SQLInputValue[],
|
||||
runs: number,
|
||||
): TimedQuery {
|
||||
const statement = db.prepare(query);
|
||||
|
||||
@@ -114,13 +114,12 @@ const TEXT_BODY = "OpenClaw web_fetch direct text benchmark body.".repeat(160);
|
||||
const MARKDOWN_BODY = "# Web Fetch Benchmark\n\n" + "- markdown list item\n".repeat(220);
|
||||
const OFFLINE_PROVIDER_ENV_VARS = ["FIRECRAWL_API_KEY"] as const;
|
||||
|
||||
const lookupFn: LookupFn = async () => [{ address: "93.184.216.34", family: 4 }];
|
||||
const lookupFn = (async () => [{ address: "93.184.216.34", family: 4 }]) as unknown as LookupFn;
|
||||
const toolConfig: OpenClawConfig = {
|
||||
tools: {
|
||||
web: {
|
||||
fetch: {
|
||||
cacheTtlMinutes: 0,
|
||||
firecrawl: { enabled: false },
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -270,7 +269,7 @@ function installMockFetch(params: { body: string; contentType: string }) {
|
||||
headers: {
|
||||
"content-type": params.contentType,
|
||||
},
|
||||
})) as typeof globalThis.fetch & { mock: object };
|
||||
})) as unknown as typeof globalThis.fetch & { mock: object };
|
||||
// fetchWithSsrFGuard preserves dispatcher support unless global fetch is a
|
||||
// test double. The marker keeps this benchmark offline and deterministic.
|
||||
fetchImpl.mock = {};
|
||||
|
||||
@@ -13,6 +13,8 @@ const DOCS_PATH_RE = /^(?:docs\/|README\.md$|AGENTS\.md$|.*\.mdx?$)/u;
|
||||
const APP_PATH_RE = /^(?:apps\/|Swabble\/|appcast\.xml$)/u;
|
||||
const EXTENSION_PATH_RE = /^extensions\/[^/]+(?:\/|$)/u;
|
||||
const CORE_PATH_RE = /^(?:src\/|ui\/|packages\/)/u;
|
||||
const SCRIPTS_TYPECHECK_PATH_RE =
|
||||
/^(?:scripts\/.*\.(?:[cm]?ts|[cm]?tsx)|tsconfig\.scripts\.json)$/u;
|
||||
const TOOLING_PATH_RE =
|
||||
/^(?:scripts\/|test\/vitest\/|\.github\/|\.vscode\/|config\/|deploy\/|git-hooks\/|Dockerfile\.sandbox(?:-(?:browser|common))?$|Makefile$|docker-setup\.sh$|setup-podman\.sh$|openclaw\.podman\.env$|skills\/pyproject\.toml$|vitest(?:\..+)?\.config\.ts$|tsconfig.*\.json$|\.dockerignore$|\.gitignore$|\.jscpd\.json$|\.npmignore$|\.pre-commit-config\.yaml$|\.swiftformat$|\.swiftlint\.yml$|\.oxlint.*|\.oxfmt.*)/u;
|
||||
const ROOT_GLOBAL_PATH_RE =
|
||||
@@ -54,7 +56,7 @@ export const RELEASE_METADATA_PATHS = new Set([
|
||||
"package.json",
|
||||
]);
|
||||
|
||||
/** @typedef {"core" | "coreTests" | "extensions" | "extensionTests" | "apps" | "docs" | "tooling" | "liveDockerTooling" | "releaseMetadata" | "all"} ChangedLane */
|
||||
/** @typedef {"core" | "coreTests" | "extensions" | "extensionTests" | "scripts" | "apps" | "docs" | "tooling" | "liveDockerTooling" | "releaseMetadata" | "all"} ChangedLane */
|
||||
|
||||
/**
|
||||
* @typedef {{
|
||||
@@ -85,6 +87,7 @@ export function createEmptyChangedLanes() {
|
||||
coreTests: false,
|
||||
extensions: false,
|
||||
extensionTests: false,
|
||||
scripts: false,
|
||||
apps: false,
|
||||
docs: false,
|
||||
tooling: false,
|
||||
@@ -139,6 +142,10 @@ export function detectChangedLanes(changedPaths, options = {}) {
|
||||
}
|
||||
|
||||
for (const changedPath of paths) {
|
||||
if (SCRIPTS_TYPECHECK_PATH_RE.test(changedPath)) {
|
||||
lanes.scripts = true;
|
||||
}
|
||||
|
||||
if (DOCS_PATH_RE.test(changedPath)) {
|
||||
lanes.docs = true;
|
||||
continue;
|
||||
|
||||
@@ -391,6 +391,9 @@ export function createChangedCheckPlan(result, options = {}) {
|
||||
if (lanes.extensionTests) {
|
||||
addTypecheck("typecheck extension tests", ["tsgo:extensions:test"]);
|
||||
}
|
||||
if (lanes.scripts) {
|
||||
addTypecheck("typecheck scripts", ["tsgo:scripts"]);
|
||||
}
|
||||
|
||||
if (lanes.core || lanes.coreTests) {
|
||||
const coreLintCommand = createTargetedCoreLintCommand(result.paths, baseEnv);
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
import type fs from "node:fs";
|
||||
|
||||
type CliBootstrapCheckParams = {
|
||||
rootDir?: string;
|
||||
entrypoints?: string[];
|
||||
distDir?: string;
|
||||
gatewayRunChunkMaxBytes?: number;
|
||||
fs?: typeof fs;
|
||||
logger?: { error(message: string): void };
|
||||
};
|
||||
|
||||
export function listStaticImportSpecifiers(source: string): string[];
|
||||
export function collectCliBootstrapExternalImportErrors(params?: CliBootstrapCheckParams): string[];
|
||||
export function collectGatewayRunChunkBudgetErrors(params?: CliBootstrapCheckParams): string[];
|
||||
export function checkCliBootstrapExternalImports(params?: CliBootstrapCheckParams): void;
|
||||
+6
-6
@@ -114,12 +114,12 @@ export async function main(argv = process.argv.slice(2)) {
|
||||
{
|
||||
name: "typecheck",
|
||||
parallel: false,
|
||||
commands: [
|
||||
{
|
||||
name: args.includeTestTypes ? "typecheck all" : "typecheck prod",
|
||||
args: [args.includeTestTypes ? "tsgo:all" : "tsgo:prod"],
|
||||
},
|
||||
],
|
||||
commands: args.includeTestTypes
|
||||
? [{ name: "typecheck all", args: ["tsgo:all"] }]
|
||||
: [
|
||||
{ name: "typecheck prod", args: ["tsgo:prod"] },
|
||||
{ name: "typecheck scripts", args: ["tsgo:scripts"] },
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "lint",
|
||||
|
||||
@@ -324,8 +324,8 @@ async function main(): Promise<void> {
|
||||
},
|
||||
);
|
||||
|
||||
let childStdout = Buffer.alloc(0);
|
||||
let childStderr = Buffer.alloc(0);
|
||||
let childStdout: Buffer = Buffer.alloc(0);
|
||||
let childStderr: Buffer = Buffer.alloc(0);
|
||||
let restored = false;
|
||||
let mirrorOffset = 0;
|
||||
let mirrorFilterPending = "";
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
export function readPositiveIntEnv(name: string, fallback: number, env?: NodeJS.ProcessEnv): number;
|
||||
export function readTcpPortEnv(name: string, fallback: number, env?: NodeJS.ProcessEnv): number;
|
||||
@@ -0,0 +1,52 @@
|
||||
import type { spawnSync, SpawnSyncOptions } from "node:child_process";
|
||||
import type { existsSync } from "node:fs";
|
||||
import type { resolvePnpmRunner } from "./pnpm-runner.mjs";
|
||||
|
||||
type Getuid = typeof process.getuid;
|
||||
type ChromiumInstallOptions = {
|
||||
comSpec?: string;
|
||||
cwd?: string;
|
||||
env?: NodeJS.ProcessEnv;
|
||||
executablePath?: string;
|
||||
existsSync?: typeof existsSync;
|
||||
getuid?: Getuid;
|
||||
log?: (message: string) => void;
|
||||
platform?: NodeJS.Platform;
|
||||
spawnSync?: typeof spawnSync;
|
||||
stdio?: SpawnSyncOptions["stdio"];
|
||||
};
|
||||
|
||||
export const systemChromiumExecutableCandidates: readonly string[];
|
||||
export function canRunChromiumExecutable(
|
||||
executablePath: string,
|
||||
spawnSync?: typeof spawnSync,
|
||||
): boolean;
|
||||
export function resolveSystemChromiumExecutablePath(
|
||||
existsSync?: typeof existsSync,
|
||||
spawnSync?: typeof spawnSync,
|
||||
): string;
|
||||
export function resolvePlaywrightInstallRunner(options?: {
|
||||
comSpec?: string;
|
||||
env?: NodeJS.ProcessEnv;
|
||||
platform?: NodeJS.Platform;
|
||||
targets?: string[];
|
||||
withDeps?: boolean;
|
||||
}): ReturnType<typeof resolvePnpmRunner>;
|
||||
export function shouldInstallPlaywrightSystemDependencies(options?: {
|
||||
env?: NodeJS.ProcessEnv;
|
||||
getuid?: Getuid;
|
||||
platform?: NodeJS.Platform;
|
||||
}): boolean;
|
||||
export function installLinuxSystemChromiumPackage(options?: ChromiumInstallOptions): number;
|
||||
export function isDirectScriptExecution(
|
||||
argvEntry?: string,
|
||||
modulePath?: string,
|
||||
realpath?: (path: string) => string,
|
||||
): boolean;
|
||||
export function ensurePlaywrightChromium(
|
||||
options?: ChromiumInstallOptions & {
|
||||
ensureFfmpeg?: boolean;
|
||||
systemExecutablePath?: string;
|
||||
},
|
||||
): number;
|
||||
export function shouldEnsureFfmpegFromArgv(argv?: readonly string[]): boolean;
|
||||
+1
-1
@@ -191,7 +191,7 @@ async function withGitHubFetchTimeout<T>(
|
||||
}, timeoutMs);
|
||||
});
|
||||
try {
|
||||
return await Promise.race([run(controller.signal), timeoutPromise]);
|
||||
return await Promise.race([run(controller.signal, timeoutPromise), timeoutPromise]);
|
||||
} finally {
|
||||
if (timeout) {
|
||||
clearTimeout(timeout);
|
||||
|
||||
@@ -0,0 +1,94 @@
|
||||
export const ACTIONS_ARTIFACT_API_VERSION: "2026-03-10";
|
||||
export const DEFAULT_MAX_ACTIONS_ARTIFACT_BYTES: number;
|
||||
export const DEFAULT_MAX_ACTIONS_ARTIFACT_EXPANDED_BYTES: number;
|
||||
|
||||
export type ArtifactArchivePolicy = {
|
||||
expectedEntries?: readonly string[];
|
||||
minEntries?: number;
|
||||
maxEntries?: number;
|
||||
maxArchiveBytes?: number;
|
||||
maxExpandedBytes?: number;
|
||||
rejectCaseFoldAliases?: boolean;
|
||||
allowPath?: (name: string) => boolean;
|
||||
maxCompressedEntryBytes?: (name: string) => number;
|
||||
maxEntryBytes: (name: string) => number;
|
||||
};
|
||||
|
||||
export type ArtifactBinding = {
|
||||
artifactDigest: string;
|
||||
artifactId: number;
|
||||
artifactName: string;
|
||||
artifactSizeBytes: number;
|
||||
repository: string;
|
||||
runStatePolicy: "completed-success" | "same-run-producer-success";
|
||||
runAttempt: number;
|
||||
runId: number;
|
||||
workflowEvent: string;
|
||||
workflowHeadBranch: string;
|
||||
workflowPath: string;
|
||||
workflowSha: string;
|
||||
consumerRunAttempt?: number;
|
||||
producerJobName?: string;
|
||||
};
|
||||
|
||||
export type ArtifactFileDescription = {
|
||||
path: string;
|
||||
sha256: string;
|
||||
sizeBytes: number;
|
||||
};
|
||||
|
||||
type ArtifactDownloadParams = {
|
||||
expected: ArtifactBinding;
|
||||
fetchImpl?: typeof fetch;
|
||||
maxArchiveBytes?: number;
|
||||
retryAttempts?: number;
|
||||
retryDelayMs?: number;
|
||||
timeoutMs?: number;
|
||||
token: string;
|
||||
};
|
||||
|
||||
type ArtifactDownloadResult = {
|
||||
archiveBytes: Uint8Array;
|
||||
artifactMetadata: Record<string, unknown>;
|
||||
binding: ArtifactBinding;
|
||||
workflowJobs: Record<string, unknown> | undefined;
|
||||
workflowRun: Record<string, unknown>;
|
||||
};
|
||||
|
||||
export function sha256Digest(bytes: Uint8Array): string;
|
||||
export function describeActionsArtifactFiles(
|
||||
files: Map<string, Uint8Array>,
|
||||
): ArtifactFileDescription[];
|
||||
export function readBoundedRegularFile(
|
||||
path: string,
|
||||
params: { label: string; maxBytes: number },
|
||||
): Buffer;
|
||||
export function inspectActionsArtifactZipWithPolicy(
|
||||
inputBytes: Uint8Array,
|
||||
inputPolicy: ArtifactArchivePolicy,
|
||||
): Map<string, Buffer>;
|
||||
export function inspectActionsArtifactZip(
|
||||
bytes: Uint8Array,
|
||||
expectedEntries?: number | readonly string[],
|
||||
limits?: {
|
||||
maxArchiveBytes?: number;
|
||||
maxExpandedBytes?: number;
|
||||
maxCompressedEntryBytes?: number;
|
||||
maxEntryBytes?: number;
|
||||
},
|
||||
): Map<string, Buffer>;
|
||||
export function validateActionsArtifactBinding(params: {
|
||||
artifactMetadata: unknown;
|
||||
expected: ArtifactBinding;
|
||||
workflowRun: unknown;
|
||||
}): ArtifactBinding;
|
||||
export function validateActionsArtifactProducerJob(params: {
|
||||
expected: ArtifactBinding;
|
||||
workflowJobs: unknown;
|
||||
}): ArtifactBinding;
|
||||
export function downloadActionsArtifactArchive(
|
||||
params: ArtifactDownloadParams,
|
||||
): Promise<ArtifactDownloadResult>;
|
||||
export function readPublicationArtifactArchive(
|
||||
params: ArtifactDownloadParams & { archivePolicy: ArtifactArchivePolicy },
|
||||
): Promise<ArtifactDownloadResult & { files: Map<string, Buffer> }>;
|
||||
@@ -0,0 +1,51 @@
|
||||
type FlagArgs = Record<string, unknown>;
|
||||
type FlagSpec<T extends FlagArgs> = {
|
||||
consume(
|
||||
argv: readonly string[],
|
||||
index: number,
|
||||
args: T,
|
||||
): {
|
||||
flag: string;
|
||||
nextIndex: number;
|
||||
repeatable: boolean;
|
||||
apply(target: T): void;
|
||||
} | null;
|
||||
};
|
||||
|
||||
export function readFlagValue(args: readonly string[], name: string): string | undefined;
|
||||
export function stripLeadingPackageManagerSeparator(argv: string[]): string[];
|
||||
export function stringFlag<T extends FlagArgs>(
|
||||
flag: string,
|
||||
key: string,
|
||||
options?: { rejectShortOptions?: boolean },
|
||||
): FlagSpec<T>;
|
||||
export function stringListFlag<T extends FlagArgs>(
|
||||
flag: string,
|
||||
key: string,
|
||||
options?: { rejectShortOptions?: boolean },
|
||||
): FlagSpec<T>;
|
||||
export function intFlag<T extends FlagArgs>(
|
||||
flag: string,
|
||||
key: string,
|
||||
options?: { min?: number },
|
||||
): FlagSpec<T>;
|
||||
export function floatFlag<T extends FlagArgs>(
|
||||
flag: string,
|
||||
key: string,
|
||||
options?: { includeMin?: boolean; min?: number },
|
||||
): FlagSpec<T>;
|
||||
export function booleanFlag<T extends FlagArgs>(
|
||||
flag: string,
|
||||
key: string,
|
||||
value?: unknown,
|
||||
): FlagSpec<T>;
|
||||
export function parseFlagArgs<T extends FlagArgs>(
|
||||
argv: readonly string[],
|
||||
args: T,
|
||||
specs: readonly FlagSpec<T>[],
|
||||
options?: {
|
||||
allowUnknownOptions?: boolean;
|
||||
ignoreDoubleDash?: boolean;
|
||||
onUnhandledArg?: (arg: string, args: T) => "handled" | void;
|
||||
},
|
||||
): T;
|
||||
@@ -0,0 +1,11 @@
|
||||
export const BUNDLED_PLUGIN_ROOT_DIR: "extensions";
|
||||
export const BUNDLED_PLUGIN_PATH_PREFIX: "extensions/";
|
||||
export const BUNDLED_PLUGIN_TEST_GLOB: "extensions/**/*.test.ts";
|
||||
export const BUNDLED_PLUGIN_E2E_TEST_GLOB: "extensions/**/*.e2e.test.ts";
|
||||
export const BUNDLED_PLUGIN_LIVE_TEST_GLOB: "extensions/**/*.live.test.ts";
|
||||
|
||||
export function bundledPluginRoot(pluginId: string): string;
|
||||
export function bundledPluginFile(pluginId: string, relativePath: string): string;
|
||||
export function bundledDistPluginRoot(pluginId: string): string;
|
||||
export function bundledDistPluginFile(pluginId: string, relativePath: string): string;
|
||||
export function bundledPluginCallsite(pluginId: string, relativePath: string, line: number): string;
|
||||
@@ -0,0 +1,55 @@
|
||||
export type ParsedReleaseVersion = {
|
||||
version: string;
|
||||
baseVersion: string;
|
||||
channel: "stable" | "alpha" | "beta";
|
||||
year: number;
|
||||
month: number;
|
||||
patch: number;
|
||||
alphaNumber?: number;
|
||||
betaNumber?: number;
|
||||
correctionNumber?: number;
|
||||
};
|
||||
export type NpmPublishPlan = {
|
||||
channel: "stable" | "alpha" | "beta";
|
||||
publishTag: "latest" | "alpha" | "beta" | "extended-stable";
|
||||
mirrorDistTags: Array<"latest" | "alpha" | "beta">;
|
||||
};
|
||||
export type PublishedNpmVersionRoute = "npm-readback" | "npm-mirror" | "npm-tag-repair";
|
||||
export type NpmRegistryPackumentResult = {
|
||||
status: number;
|
||||
ok: boolean;
|
||||
packument: unknown;
|
||||
};
|
||||
export function fetchNpmRegistryPackumentWithRetry(params: {
|
||||
packageName: string;
|
||||
packageUrl: string;
|
||||
attempts?: number;
|
||||
timeoutMs?: number;
|
||||
fetchImpl?: (input: string, init: RequestInit) => Promise<Response>;
|
||||
sleep?: (delayMs: number) => Promise<void>;
|
||||
createSignal?: (timeoutMs: number) => AbortSignal;
|
||||
}): Promise<NpmRegistryPackumentResult>;
|
||||
export function parseReleaseVersion(version: string): ParsedReleaseVersion | null;
|
||||
export function collectReleaseVersionFloorErrors(
|
||||
version: string | ParsedReleaseVersion | null,
|
||||
): string[];
|
||||
export function compareReleaseVersions(left: string, right: string): number | null;
|
||||
export function resolveNpmPublishPlan(
|
||||
version: string,
|
||||
currentBetaVersion?: string | null,
|
||||
publishTagOverride?: string | null,
|
||||
): NpmPublishPlan;
|
||||
export function resolvePublishedNpmVersionRoute(params: {
|
||||
packageVersion: string;
|
||||
publishPlan: NpmPublishPlan;
|
||||
distTags: Record<string, unknown>;
|
||||
}): PublishedNpmVersionRoute;
|
||||
export function resolveNpmDistTagMirrorAuth(params?: {
|
||||
nodeAuthToken?: string | null;
|
||||
npmToken?: string | null;
|
||||
}): { hasAuth: boolean; source: "node-auth-token" | "npm-token" | "none" };
|
||||
export function shouldRequireNpmDistTagMirrorAuth(params: {
|
||||
mode: "--dry-run" | "--publish";
|
||||
mirrorDistTags: readonly string[];
|
||||
hasAuth: boolean;
|
||||
}): boolean;
|
||||
@@ -1,12 +1,16 @@
|
||||
// Npm Verify Exec script supports OpenClaw repository automation.
|
||||
import { execFileSync } from "node:child_process";
|
||||
import { execFileSync, type ExecFileSyncOptionsWithStringEncoding } from "node:child_process";
|
||||
|
||||
type NpmVerifyCommandInvocation = {
|
||||
export type NpmVerifyCommandInvocation = {
|
||||
command: string;
|
||||
args: string[];
|
||||
windowsVerbatimArguments?: boolean;
|
||||
};
|
||||
|
||||
type NpmVerifyExecOptions = ExecFileSyncOptionsWithStringEncoding & {
|
||||
windowsVerbatimArguments?: boolean;
|
||||
};
|
||||
|
||||
const DEFAULT_NPM_VERIFY_COMMAND_TIMEOUT_MS = 5 * 60 * 1000;
|
||||
const DEFAULT_NPM_VERIFY_COMMAND_MAX_BUFFER_BYTES = 16 * 1024 * 1024;
|
||||
|
||||
@@ -40,7 +44,7 @@ export function runNpmVerifyCommand(
|
||||
DEFAULT_NPM_VERIFY_COMMAND_MAX_BUFFER_BYTES,
|
||||
);
|
||||
|
||||
return execFileSync(invocation.command, invocation.args, {
|
||||
const execOptions: NpmVerifyExecOptions = {
|
||||
cwd,
|
||||
encoding: "utf8",
|
||||
killSignal: "SIGKILL",
|
||||
@@ -48,5 +52,6 @@ export function runNpmVerifyCommand(
|
||||
stdio: ["ignore", "pipe", "pipe"],
|
||||
timeout: timeoutMs,
|
||||
windowsVerbatimArguments: invocation.windowsVerbatimArguments,
|
||||
}).trim();
|
||||
};
|
||||
return execFileSync(invocation.command, invocation.args, execOptions).trim();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
export function parsePositiveInt(raw: string, label: string): number;
|
||||
export function parseNonNegativeInt(raw: string, label: string): number;
|
||||
export function parsePositiveNumber(raw: string, label: string): number;
|
||||
@@ -58,7 +58,7 @@ export type PublishablePluginPackage = {
|
||||
packageName: string;
|
||||
version: string;
|
||||
channel: "stable" | "alpha" | "beta";
|
||||
publishTag: "latest" | "alpha" | "beta";
|
||||
publishTag: "latest" | "alpha" | "beta" | "extended-stable";
|
||||
requiredLatestDependencies?: RequiredLatestDependency[];
|
||||
};
|
||||
|
||||
|
||||
@@ -40,6 +40,7 @@ export type PluginPackageJson = {
|
||||
pluginSdkVersion?: string;
|
||||
};
|
||||
release?: {
|
||||
publishToClawHub?: boolean;
|
||||
publishToNpm?: boolean;
|
||||
requireLatestDependencies?: unknown;
|
||||
};
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
export type RuntimeDependencyPackageJson = {
|
||||
dependencies?: Record<string, string>;
|
||||
optionalDependencies?: Record<string, string>;
|
||||
};
|
||||
export function collectRuntimeDependencySpecs(
|
||||
packageJson?: RuntimeDependencyPackageJson,
|
||||
): Map<string, string>;
|
||||
export function packageNameFromSpecifier(specifier: string): string | null;
|
||||
export function collectBundledPluginPackageDependencySpecs(
|
||||
bundledPluginsDir: string,
|
||||
): Map<
|
||||
string,
|
||||
{ conflicts: Array<{ pluginId: string; spec: string }>; pluginIds: string[]; spec: string }
|
||||
>;
|
||||
@@ -843,7 +843,12 @@ function validateBootstrapPackageEvidence(
|
||||
}
|
||||
const expectedSize = value.expectedSize;
|
||||
const registrySize = value.registrySize;
|
||||
if (!Number.isSafeInteger(expectedSize) || expectedSize <= 0 || registrySize !== expectedSize) {
|
||||
if (
|
||||
typeof expectedSize !== "number" ||
|
||||
!Number.isSafeInteger(expectedSize) ||
|
||||
expectedSize <= 0 ||
|
||||
registrySize !== expectedSize
|
||||
) {
|
||||
throw new Error(
|
||||
`${params.packageName} registry artifact size differs from the packed artifact.`,
|
||||
);
|
||||
@@ -1316,6 +1321,9 @@ export async function verifyBetaRelease(
|
||||
}
|
||||
|
||||
const workflowRuns: WorkflowRunSummary[] = [];
|
||||
const allowedReleaseWorkflowHeadBranches = args.workflowRef
|
||||
? ["main", args.workflowRef]
|
||||
: ["main"];
|
||||
if (args.workflowRuns.fullReleaseValidation !== undefined) {
|
||||
workflowRuns.push(
|
||||
verifyWorkflowRun({
|
||||
@@ -1323,7 +1331,7 @@ export async function verifyBetaRelease(
|
||||
label: "Full Release Validation",
|
||||
repo: args.repo,
|
||||
expectedWorkflowName: "Full Release Validation",
|
||||
allowedHeadBranches: ["main", args.workflowRef],
|
||||
allowedHeadBranches: allowedReleaseWorkflowHeadBranches,
|
||||
rerunFailed: false,
|
||||
}),
|
||||
);
|
||||
@@ -1383,7 +1391,7 @@ export async function verifyBetaRelease(
|
||||
label: "NPM Telegram Beta E2E",
|
||||
repo: args.repo,
|
||||
expectedWorkflowName: "NPM Telegram Beta E2E",
|
||||
allowedHeadBranches: ["main", args.workflowRef],
|
||||
allowedHeadBranches: allowedReleaseWorkflowHeadBranches,
|
||||
rerunFailed: false,
|
||||
}),
|
||||
);
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
export const WORKSPACE_TEMPLATE_PACK_PATHS: readonly string[];
|
||||
export function createWorkspaceBootstrapSmokeEnv(
|
||||
env: NodeJS.ProcessEnv,
|
||||
homeDir: string,
|
||||
overrides?: NodeJS.ProcessEnv,
|
||||
): NodeJS.ProcessEnv;
|
||||
export function runInstalledWorkspaceBootstrapSmoke(params: { packageRoot: string }): void;
|
||||
@@ -659,7 +659,7 @@ function extractCandidates(
|
||||
uiCallNames: ReadonlySet<string>,
|
||||
): Candidate[] {
|
||||
const entries: Candidate[] = [];
|
||||
const patterns =
|
||||
const patterns: Array<readonly [RegExp, string]> =
|
||||
surface === "apple"
|
||||
? [
|
||||
[APPLE_UI_MULTILINE_CALLS, "ui-call-multiline"],
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -328,7 +328,7 @@ export function runNpmReleaseCheckCommand(
|
||||
},
|
||||
): string {
|
||||
const env = options.env ?? process.env;
|
||||
const output = execFileSync(invocation.command, invocation.args, {
|
||||
const execOptions = {
|
||||
cwd: options.cwd,
|
||||
encoding: options.encoding,
|
||||
env,
|
||||
@@ -337,7 +337,11 @@ export function runNpmReleaseCheckCommand(
|
||||
stdio: options.stdio,
|
||||
timeout: options.timeoutMs ?? resolveNpmReleaseCheckCommandTimeoutMs(env),
|
||||
windowsVerbatimArguments: invocation.windowsVerbatimArguments,
|
||||
}) as Buffer | string | null;
|
||||
} as Parameters<typeof execFileSync>[2] & { windowsVerbatimArguments?: boolean };
|
||||
const output = execFileSync(invocation.command, invocation.args, execOptions) as
|
||||
| Buffer
|
||||
| string
|
||||
| null;
|
||||
if (output == null) {
|
||||
return "";
|
||||
}
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
type PackageChangelogOptions = { allowUnreleased?: boolean };
|
||||
|
||||
export function resolvePackageChangelogVersions(
|
||||
packageVersion: string,
|
||||
options?: PackageChangelogOptions,
|
||||
): string[];
|
||||
export function extractCurrentPackageChangelog(
|
||||
content: string,
|
||||
packageVersion: string,
|
||||
options?: PackageChangelogOptions,
|
||||
): string;
|
||||
export function restorePackageChangelog(cwd?: string): Promise<boolean>;
|
||||
export function preparePackageChangelog(
|
||||
cwd?: string,
|
||||
options?: PackageChangelogOptions,
|
||||
): Promise<boolean>;
|
||||
@@ -151,18 +151,6 @@ function buildConfig(options: Options, workspaceDir: string): OpenClawConfig {
|
||||
controlUi: { enabled: false },
|
||||
mode: "local",
|
||||
},
|
||||
memory: {
|
||||
active: {
|
||||
allowedChatTypes: ["direct"],
|
||||
agents: ["main"],
|
||||
logging: false,
|
||||
maxSummaryChars: 220,
|
||||
persistTranscripts: false,
|
||||
promptStyle: "balanced",
|
||||
queryMode: "recent",
|
||||
timeoutMs: 15_000,
|
||||
},
|
||||
},
|
||||
models: {
|
||||
mode: "replace",
|
||||
providers,
|
||||
|
||||
@@ -322,6 +322,9 @@ function extractCompatTokens(record: PluginCompatRecord): string[] {
|
||||
const tokens = new Set<string>();
|
||||
const values = [record.code, record.replacement, ...record.surfaces, ...record.diagnostics];
|
||||
for (const value of values) {
|
||||
if (value === undefined) {
|
||||
continue;
|
||||
}
|
||||
for (const match of value.matchAll(/`([^`]+)`/g)) {
|
||||
const token = match[1]?.trim();
|
||||
if (token && !token.includes(" ")) {
|
||||
@@ -523,7 +526,7 @@ function buildSummary(report: BoundaryReport, owner?: string): BoundaryReportSum
|
||||
};
|
||||
}
|
||||
|
||||
function buildReport(options: Pick<CliOptions, "owner" | "summary"> = {}): BoundaryReport {
|
||||
function buildReport(options: Partial<Pick<CliOptions, "owner" | "summary">> = {}): BoundaryReport {
|
||||
const files = options.summary
|
||||
? collectSummaryWorkspaceTextFileSources()
|
||||
: collectWorkspaceTextFileSources();
|
||||
|
||||
@@ -521,11 +521,9 @@ function emitDiscriminatedUnion(name: string, schema: JsonSchema): string | unde
|
||||
if (cases.some((entry) => !entry)) {
|
||||
continue;
|
||||
}
|
||||
const resolvedCases: Array<{
|
||||
branchName: string;
|
||||
caseName: string;
|
||||
literal: boolean | number | string | null;
|
||||
}> = cases;
|
||||
const resolvedCases = cases.filter(
|
||||
(entry): entry is NonNullable<typeof entry> => entry !== undefined,
|
||||
);
|
||||
const [firstCase] = resolvedCases;
|
||||
if (!firstCase) {
|
||||
continue;
|
||||
|
||||
@@ -703,7 +703,10 @@ async function runUxMatrixEvidenceProducer(options: ProducerOptions) {
|
||||
: []),
|
||||
],
|
||||
coverageIds: ["ui.control", "gateway.control-ui-hosting"],
|
||||
failureReason: matrixScreenshotResult.failureReason,
|
||||
failureReason:
|
||||
"failureReason" in matrixScreenshotResult
|
||||
? matrixScreenshotResult.failureReason
|
||||
: undefined,
|
||||
stage: "screenshot-artifact",
|
||||
status: matrixScreenshotResult.status,
|
||||
surface: "control-ui",
|
||||
@@ -781,7 +784,8 @@ async function runUxMatrixEvidenceProducer(options: ProducerOptions) {
|
||||
: []),
|
||||
],
|
||||
coverageIds: ["qa.artifact-safety", "tools.evidence", "workspace.artifacts"],
|
||||
failureReason: fixtureProofResult.failureReason,
|
||||
failureReason:
|
||||
"failureReason" in fixtureProofResult ? fixtureProofResult.failureReason : undefined,
|
||||
stage: "producer-artifact-fixture",
|
||||
status: fixtureProofResult.status,
|
||||
surface: "qa-lab",
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#!/usr/bin/env -S node --import tsx
|
||||
// Release Check script supports OpenClaw repository automation.
|
||||
|
||||
import { execFileSync } from "node:child_process";
|
||||
import { execFileSync, type ExecFileSyncOptions } from "node:child_process";
|
||||
import {
|
||||
copyFileSync,
|
||||
existsSync,
|
||||
@@ -56,6 +56,10 @@ import { listStaticExtensionAssetOutputs } from "./runtime-postbuild.mjs";
|
||||
import { sparkleBuildFloorsFromShortVersion, type SparkleBuildFloors } from "./sparkle-build.ts";
|
||||
import { buildCmdExeCommandLine, resolveWindowsCmdExePath } from "./windows-cmd-helpers.mjs";
|
||||
|
||||
type ReleaseCheckExecOptions = ExecFileSyncOptions & {
|
||||
windowsVerbatimArguments?: boolean;
|
||||
};
|
||||
|
||||
export { collectBundledExtensionManifestErrors } from "./lib/bundled-extension-manifest.ts";
|
||||
export { packageNameFromSpecifier } from "./lib/plugin-package-dependencies.mjs";
|
||||
|
||||
@@ -211,7 +215,7 @@ export function runReleaseCheckCommand(
|
||||
timeoutMs?: number;
|
||||
},
|
||||
): string {
|
||||
const output = execFileSync(invocation.command, invocation.args, {
|
||||
const execOptions: ReleaseCheckExecOptions = {
|
||||
cwd: options.cwd,
|
||||
encoding: options.encoding,
|
||||
env: invocation.env ?? options.env,
|
||||
@@ -231,7 +235,12 @@ export function runReleaseCheckCommand(
|
||||
DEFAULT_RELEASE_CHECK_COMMAND_TIMEOUT_MS,
|
||||
),
|
||||
windowsVerbatimArguments: invocation.windowsVerbatimArguments,
|
||||
}) as Buffer | string | null;
|
||||
};
|
||||
const output: Buffer | string | null = execFileSync(
|
||||
invocation.command,
|
||||
invocation.args,
|
||||
execOptions,
|
||||
);
|
||||
if (output == null) {
|
||||
return "";
|
||||
}
|
||||
|
||||
@@ -200,7 +200,7 @@ function stringParam(params: Record<string, unknown>, key: string): string {
|
||||
function makeTool(
|
||||
name: string,
|
||||
description: string,
|
||||
properties: Record<string, unknown>,
|
||||
properties: Parameters<typeof Type.Object>[0],
|
||||
execute: (params: Record<string, unknown>) => unknown,
|
||||
): AnyAgentTool {
|
||||
const tool = {
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
import type fs from "node:fs";
|
||||
|
||||
export type StaticExtensionAsset = {
|
||||
pluginDir?: string;
|
||||
src: string;
|
||||
dest: string;
|
||||
};
|
||||
|
||||
export type RuntimePostBuildParams = {
|
||||
rootDir?: string;
|
||||
repoRoot?: string;
|
||||
cwd?: string;
|
||||
env?: NodeJS.ProcessEnv;
|
||||
fs?: typeof fs;
|
||||
timings?: boolean | "verbose";
|
||||
warn?: (message: string) => void;
|
||||
};
|
||||
|
||||
type StaticExtensionAssetParams = Pick<RuntimePostBuildParams, "rootDir" | "fs" | "warn"> & {
|
||||
assets?: StaticExtensionAsset[];
|
||||
};
|
||||
|
||||
type LegacyCliExitCompatChunk = { dest: string; contents: string };
|
||||
|
||||
export function copyStaticExtensionAssets(params?: StaticExtensionAssetParams): void;
|
||||
export function listStaticExtensionAssetOutputs(params?: StaticExtensionAssetParams): string[];
|
||||
|
||||
export const LEGACY_CLI_EXIT_COMPAT_CHUNKS: LegacyCliExitCompatChunk[];
|
||||
export function listCoreRuntimePostBuildOutputs(
|
||||
params?: Pick<RuntimePostBuildParams, "rootDir" | "fs"> & {
|
||||
chunks?: LegacyCliExitCompatChunk[];
|
||||
},
|
||||
): string[];
|
||||
export function writeStableRootRuntimeAliases(
|
||||
params?: Pick<RuntimePostBuildParams, "rootDir" | "fs">,
|
||||
): void;
|
||||
export function rewriteRootRuntimeImportsToStableAliases(
|
||||
params?: Pick<RuntimePostBuildParams, "rootDir" | "fs">,
|
||||
): void;
|
||||
export function writeLegacyRootRuntimeCompatAliases(
|
||||
params?: Pick<RuntimePostBuildParams, "rootDir" | "fs">,
|
||||
): void;
|
||||
export function writeLegacyCliExitCompatChunks(params?: {
|
||||
rootDir?: string;
|
||||
chunks?: LegacyCliExitCompatChunk[];
|
||||
}): void;
|
||||
export function runRuntimePostBuild(params?: RuntimePostBuildParams): void;
|
||||
@@ -1,126 +0,0 @@
|
||||
// Sync Moonshot Docs script supports OpenClaw repository automation.
|
||||
import { readFile, writeFile } from "node:fs/promises";
|
||||
import path from "node:path";
|
||||
import { fileURLToPath } from "node:url";
|
||||
import {
|
||||
MOONSHOT_KIMI_K2_CONTEXT_WINDOW,
|
||||
MOONSHOT_KIMI_K2_COST,
|
||||
MOONSHOT_KIMI_K2_INPUT,
|
||||
MOONSHOT_KIMI_K2_MAX_TOKENS,
|
||||
MOONSHOT_KIMI_K2_MODELS,
|
||||
} from "../ui/src/ui/data/moonshot-kimi-k2";
|
||||
|
||||
const here = path.dirname(fileURLToPath(import.meta.url));
|
||||
const repoRoot = path.resolve(here, "..");
|
||||
|
||||
function replaceBlockLines(
|
||||
text: string,
|
||||
startMarker: string,
|
||||
endMarker: string,
|
||||
lines: string[],
|
||||
): string {
|
||||
const startIndex = text.indexOf(startMarker);
|
||||
if (startIndex === -1) {
|
||||
throw new Error(`Missing start marker: ${startMarker}`);
|
||||
}
|
||||
const endIndex = text.indexOf(endMarker, startIndex);
|
||||
if (endIndex === -1) {
|
||||
throw new Error(`Missing end marker: ${endMarker}`);
|
||||
}
|
||||
|
||||
const startLineStart = text.lastIndexOf("\n", startIndex);
|
||||
const startLineStartIndex = startLineStart === -1 ? 0 : startLineStart + 1;
|
||||
const indent = text.slice(startLineStartIndex, startIndex);
|
||||
|
||||
const endLineEnd = text.indexOf("\n", endIndex);
|
||||
const endLineEndIndex = endLineEnd === -1 ? text.length : endLineEnd + 1;
|
||||
|
||||
const before = text.slice(0, startLineStartIndex);
|
||||
const after = text.slice(endLineEndIndex);
|
||||
|
||||
const replacementLines = [
|
||||
`${indent}${startMarker}`,
|
||||
...lines.map((line) => `${indent}${line}`),
|
||||
`${indent}${endMarker}`,
|
||||
];
|
||||
|
||||
const replacement = replacementLines.join("\n");
|
||||
if (!after) {
|
||||
return `${before}${replacement}`;
|
||||
}
|
||||
return `${before}${replacement}\n${after}`;
|
||||
}
|
||||
|
||||
function renderKimiK2Ids(prefix: string) {
|
||||
return [...MOONSHOT_KIMI_K2_MODELS.map((model) => `- \`${prefix}${model.id}\``), ""];
|
||||
}
|
||||
|
||||
function renderMoonshotAliases() {
|
||||
return MOONSHOT_KIMI_K2_MODELS.map((model, index) => {
|
||||
const isLast = index === MOONSHOT_KIMI_K2_MODELS.length - 1;
|
||||
const suffix = isLast ? "" : ",";
|
||||
return `"moonshot/${model.id}": { alias: "${model.alias}" }${suffix}`;
|
||||
});
|
||||
}
|
||||
|
||||
function renderMoonshotModels() {
|
||||
const input = JSON.stringify([...MOONSHOT_KIMI_K2_INPUT]);
|
||||
const cost = `input: ${MOONSHOT_KIMI_K2_COST.input}, output: ${MOONSHOT_KIMI_K2_COST.output}, cacheRead: ${MOONSHOT_KIMI_K2_COST.cacheRead}, cacheWrite: ${MOONSHOT_KIMI_K2_COST.cacheWrite}`;
|
||||
|
||||
return MOONSHOT_KIMI_K2_MODELS.flatMap((model, index) => {
|
||||
const isLast = index === MOONSHOT_KIMI_K2_MODELS.length - 1;
|
||||
const closing = isLast ? "}" : "},";
|
||||
return [
|
||||
"{",
|
||||
` id: "${model.id}",`,
|
||||
` name: "${model.name}",`,
|
||||
` reasoning: ${model.reasoning},`,
|
||||
` input: ${input},`,
|
||||
` cost: { ${cost} },`,
|
||||
` contextWindow: ${MOONSHOT_KIMI_K2_CONTEXT_WINDOW},`,
|
||||
` maxTokens: ${MOONSHOT_KIMI_K2_MAX_TOKENS}`,
|
||||
closing,
|
||||
];
|
||||
});
|
||||
}
|
||||
|
||||
async function syncMoonshotDocs() {
|
||||
const moonshotDoc = path.join(repoRoot, "docs/providers/moonshot.md");
|
||||
const conceptsDoc = path.join(repoRoot, "docs/concepts/model-providers.md");
|
||||
|
||||
let moonshotText = await readFile(moonshotDoc, "utf8");
|
||||
moonshotText = replaceBlockLines(
|
||||
moonshotText,
|
||||
'[//]: # "moonshot-kimi-k2-ids:start"',
|
||||
'[//]: # "moonshot-kimi-k2-ids:end"',
|
||||
renderKimiK2Ids(""),
|
||||
);
|
||||
moonshotText = replaceBlockLines(
|
||||
moonshotText,
|
||||
"// moonshot-kimi-k2-aliases:start",
|
||||
"// moonshot-kimi-k2-aliases:end",
|
||||
renderMoonshotAliases(),
|
||||
);
|
||||
moonshotText = replaceBlockLines(
|
||||
moonshotText,
|
||||
"// moonshot-kimi-k2-models:start",
|
||||
"// moonshot-kimi-k2-models:end",
|
||||
renderMoonshotModels(),
|
||||
);
|
||||
|
||||
let conceptsText = await readFile(conceptsDoc, "utf8");
|
||||
conceptsText = replaceBlockLines(
|
||||
conceptsText,
|
||||
'[//]: # "moonshot-kimi-k2-model-refs:start"',
|
||||
'[//]: # "moonshot-kimi-k2-model-refs:end"',
|
||||
renderKimiK2Ids("moonshot/"),
|
||||
);
|
||||
|
||||
await writeFile(moonshotDoc, moonshotText);
|
||||
await writeFile(conceptsDoc, conceptsText);
|
||||
}
|
||||
|
||||
syncMoonshotDocs().catch((error: unknown) => {
|
||||
console.error(error);
|
||||
process.exitCode = 1;
|
||||
});
|
||||
@@ -165,7 +165,7 @@ function envKeysFromObjectLiteral(node: ts.Expression): string[] {
|
||||
}
|
||||
return node.properties
|
||||
.map((property) => (ts.isPropertyAssignment(property) ? propertyNameText(property.name) : null))
|
||||
.filter((key): key is string => Boolean(key) && TRACKED_ENV_KEYS.has(key));
|
||||
.filter((key): key is string => key !== null && TRACKED_ENV_KEYS.has(key));
|
||||
}
|
||||
|
||||
function isAssignmentOperator(kind: ts.SyntaxKind): boolean {
|
||||
|
||||
@@ -708,6 +708,10 @@ const TOOLING_SOURCE_TEST_TARGETS = new Map([
|
||||
],
|
||||
["scripts/clawtributors-map.json", ["test/scripts/update-clawtributors.test.ts"]],
|
||||
["scripts/tsconfig.json", ["test/scripts/oxlint-config.test.ts"]],
|
||||
[
|
||||
"tsconfig.scripts.json",
|
||||
["test/scripts/changed-lanes.test.ts", "test/scripts/test-projects.test.ts"],
|
||||
],
|
||||
["scripts/build-all.mjs", ["test/scripts/build-all.test.ts"]],
|
||||
["scripts/build-stamp.mjs", ["src/infra/build-stamp.test.ts"]],
|
||||
["scripts/crabbox-wrapper-providers.mjs", ["test/scripts/crabbox-wrapper.test.ts"]],
|
||||
|
||||
@@ -2,7 +2,9 @@
|
||||
import fs from "node:fs";
|
||||
import path from "node:path";
|
||||
import { fileURLToPath } from "node:url";
|
||||
import { TOOL_DISPLAY_CONFIG, type ToolDisplayConfig } from "../src/agents/tool-display-config.js";
|
||||
import { TOOL_DISPLAY_CONFIG } from "../src/agents/tool-display-config.js";
|
||||
|
||||
type ToolDisplayConfig = typeof TOOL_DISPLAY_CONFIG;
|
||||
|
||||
const scriptDir = path.dirname(fileURLToPath(import.meta.url));
|
||||
const repoRoot = path.resolve(scriptDir, "..");
|
||||
|
||||
@@ -343,9 +343,6 @@ function createIsolatedRootHelpRenderContext(
|
||||
workspace: workspaceDir,
|
||||
},
|
||||
},
|
||||
plugins: {
|
||||
loadPaths: [],
|
||||
},
|
||||
};
|
||||
return { config, env };
|
||||
}
|
||||
|
||||
Vendored
-18
@@ -41,7 +41,6 @@
|
||||
"agents": {
|
||||
"defaults": {
|
||||
"heartbeat": {
|
||||
"enabled": true,
|
||||
"every": "30m"
|
||||
}
|
||||
}
|
||||
@@ -50,23 +49,6 @@
|
||||
"groupChat": {
|
||||
"visibleReplies": "message_tool"
|
||||
}
|
||||
},
|
||||
"tools": {
|
||||
"profiles": {
|
||||
"coding": {
|
||||
"allow": [
|
||||
"message",
|
||||
"heartbeat_respond",
|
||||
"sessions_spawn",
|
||||
"sessions_list",
|
||||
"sessions_yield",
|
||||
"cron",
|
||||
"memory_search",
|
||||
"memory_get",
|
||||
"session_status"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
test/fixtures/agents/prompt-snapshots/codex-runtime-happy-path/telegram-direct-codex-message-tool.md
Vendored
-18
@@ -41,7 +41,6 @@
|
||||
"agents": {
|
||||
"defaults": {
|
||||
"heartbeat": {
|
||||
"enabled": true,
|
||||
"every": "30m"
|
||||
}
|
||||
}
|
||||
@@ -50,23 +49,6 @@
|
||||
"groupChat": {
|
||||
"visibleReplies": "message_tool"
|
||||
}
|
||||
},
|
||||
"tools": {
|
||||
"profiles": {
|
||||
"coding": {
|
||||
"allow": [
|
||||
"message",
|
||||
"heartbeat_respond",
|
||||
"sessions_spawn",
|
||||
"sessions_list",
|
||||
"sessions_yield",
|
||||
"cron",
|
||||
"memory_search",
|
||||
"memory_get",
|
||||
"session_status"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Vendored
-18
@@ -41,7 +41,6 @@
|
||||
"agents": {
|
||||
"defaults": {
|
||||
"heartbeat": {
|
||||
"enabled": true,
|
||||
"every": "30m"
|
||||
}
|
||||
}
|
||||
@@ -50,23 +49,6 @@
|
||||
"groupChat": {
|
||||
"visibleReplies": "message_tool"
|
||||
}
|
||||
},
|
||||
"tools": {
|
||||
"profiles": {
|
||||
"coding": {
|
||||
"allow": [
|
||||
"message",
|
||||
"heartbeat_respond",
|
||||
"sessions_spawn",
|
||||
"sessions_list",
|
||||
"sessions_yield",
|
||||
"cron",
|
||||
"memory_search",
|
||||
"memory_get",
|
||||
"session_status"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
@@ -107,7 +107,10 @@ type CodexPromptSnapshotApi = {
|
||||
developerInstructions: string;
|
||||
threadStartParams: Record<string, unknown>;
|
||||
threadResumeParams: Record<string, unknown>;
|
||||
turnStartParams: Record<string, unknown>;
|
||||
turnStartParams: Record<string, unknown> & {
|
||||
input?: unknown;
|
||||
collaborationMode?: { settings?: { developer_instructions?: string } };
|
||||
};
|
||||
};
|
||||
createCodexDynamicToolSpecsForPromptSnapshot: (params: {
|
||||
tools: AnyAgentTool[];
|
||||
@@ -249,28 +252,10 @@ const baseConfig: OpenClawConfig = {
|
||||
agents: {
|
||||
defaults: {
|
||||
heartbeat: {
|
||||
enabled: true,
|
||||
every: "30m",
|
||||
},
|
||||
},
|
||||
},
|
||||
tools: {
|
||||
profiles: {
|
||||
coding: {
|
||||
allow: [
|
||||
"message",
|
||||
"heartbeat_respond",
|
||||
"sessions_spawn",
|
||||
"sessions_list",
|
||||
"sessions_yield",
|
||||
"cron",
|
||||
"memory_search",
|
||||
"memory_get",
|
||||
"session_status",
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
const dynamicToolsConfig: OpenClawConfig = {
|
||||
|
||||
@@ -598,6 +598,19 @@ describe("scripts/changed-lanes", () => {
|
||||
});
|
||||
});
|
||||
|
||||
it.each([
|
||||
"scripts/control-ui-i18n.ts",
|
||||
"scripts/lib/example.ts",
|
||||
"scripts/lib/example.d.mts",
|
||||
"tsconfig.scripts.json",
|
||||
])("routes %s to the scripts typecheck lane", (changedPath) => {
|
||||
const result = detectChangedLanes([changedPath]);
|
||||
const plan = createChangedCheckPlan(result);
|
||||
|
||||
expect(result.lanes.scripts).toBe(true);
|
||||
expect(plan.commands.map((command) => command.args[0])).toContain("tsgo:scripts");
|
||||
});
|
||||
|
||||
it("falls back to full core lint for broad core diffs", () => {
|
||||
const targets = Array.from({ length: 9 }, (_, index) => `src/shared/file-${index}.ts`);
|
||||
const command = createTargetedCoreLintCommand(targets, { PATH: "/usr/bin" });
|
||||
@@ -1818,6 +1831,7 @@ describe("scripts/changed-lanes", () => {
|
||||
coreTests: false,
|
||||
extensions: false,
|
||||
extensionTests: false,
|
||||
scripts: false,
|
||||
apps: false,
|
||||
docs: false,
|
||||
tooling: false,
|
||||
|
||||
@@ -869,7 +869,9 @@ describe("scripts/openclaw-cross-os-release-checks", () => {
|
||||
const topLevelImports = source.slice(0, source.indexOf("const SCRIPT_PATH"));
|
||||
|
||||
expect(topLevelImports).not.toContain("package-dist-inventory");
|
||||
expect(source).toContain("function assertNoLegacyPluginDependencyStagingDebris(packageRoot)");
|
||||
expect(source).toMatch(
|
||||
/function assertNoLegacyPluginDependencyStagingDebris\(packageRoot: string\)/u,
|
||||
);
|
||||
});
|
||||
|
||||
it("filters the cross-OS runner matrix to a focused OS suite", () => {
|
||||
@@ -1724,11 +1726,10 @@ describe("scripts/openclaw-cross-os-release-checks", () => {
|
||||
expect(init).toMatchObject({
|
||||
method: "POST",
|
||||
body: "{}",
|
||||
headers: {
|
||||
Authorization: "Bot discord-token",
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
});
|
||||
const headers = new Headers(init.headers);
|
||||
expect(headers.get("Authorization")).toBe("Bot discord-token");
|
||||
expect(headers.get("Content-Type")).toBe("application/json");
|
||||
expect(init.signal).toBeInstanceOf(AbortSignal);
|
||||
});
|
||||
|
||||
|
||||
@@ -1197,6 +1197,13 @@ describe("scripts/test-projects changed-target routing", () => {
|
||||
});
|
||||
});
|
||||
|
||||
it("keeps the scripts typecheck project on its routing tests", () => {
|
||||
expect(resolveChangedTestTargetPlan(["tsconfig.scripts.json"])).toEqual({
|
||||
mode: "targets",
|
||||
targets: ["test/scripts/changed-lanes.test.ts", "test/scripts/test-projects.test.ts"],
|
||||
});
|
||||
});
|
||||
|
||||
it("keeps docs i18n behavior fixture edits on behavior baseline tests", () => {
|
||||
for (const fixturePath of [
|
||||
"scripts/docs-i18n/testdata/behavior/fenced-singleton-retry/case.json",
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
"files": [],
|
||||
"references": [
|
||||
{ "path": "./tsconfig.core.projects.json" },
|
||||
{ "path": "./tsconfig.extensions.projects.json" }
|
||||
{ "path": "./tsconfig.extensions.projects.json" },
|
||||
{ "path": "./tsconfig.scripts.json" }
|
||||
]
|
||||
}
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
{
|
||||
"extends": "./tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"noUnusedLocals": true,
|
||||
"noUnusedParameters": true,
|
||||
"tsBuildInfoFile": ".artifacts/tsgo-cache/scripts.tsbuildinfo"
|
||||
},
|
||||
"include": ["scripts/**/*", "src/**/*.d.ts", "packages/**/*.d.ts"],
|
||||
"exclude": [
|
||||
"node_modules",
|
||||
"dist",
|
||||
"**/dist/**",
|
||||
// E2E clients import built dist artifacts and are validated by Docker runs,
|
||||
// so they cannot join this source-only program.
|
||||
"scripts/e2e/**"
|
||||
]
|
||||
}
|
||||
Reference in New Issue
Block a user