mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-06 05:30:42 +00:00
refactor: remove dead private helpers
This commit is contained in:
@@ -1,4 +1,3 @@
|
||||
import type { KilocodeModelCatalogEntry } from "openclaw/plugin-sdk/provider-model-shared";
|
||||
import type { ModelDefinitionConfig } from "openclaw/plugin-sdk/provider-model-shared";
|
||||
import { createSubsystemLogger } from "openclaw/plugin-sdk/runtime-env";
|
||||
import { normalizeLowercaseStringOrEmpty } from "openclaw/plugin-sdk/text-runtime";
|
||||
@@ -10,6 +9,15 @@ export const KILOCODE_DEFAULT_MODEL_ID = "kilo/auto";
|
||||
export const KILOCODE_DEFAULT_MODEL_REF = `kilocode/${KILOCODE_DEFAULT_MODEL_ID}`;
|
||||
export const KILOCODE_DEFAULT_MODEL_NAME = "Kilo Auto";
|
||||
|
||||
export type KilocodeModelCatalogEntry = {
|
||||
id: string;
|
||||
name: string;
|
||||
reasoning: boolean;
|
||||
input: Array<"text" | "image">;
|
||||
contextWindow?: number;
|
||||
maxTokens?: number;
|
||||
};
|
||||
|
||||
export const KILOCODE_MODEL_CATALOG: KilocodeModelCatalogEntry[] = [
|
||||
{
|
||||
id: KILOCODE_DEFAULT_MODEL_ID,
|
||||
|
||||
@@ -9,4 +9,4 @@ export {
|
||||
KILOCODE_MODEL_CATALOG,
|
||||
} from "./provider-models.js";
|
||||
|
||||
export type { KilocodeModelCatalogEntry } from "openclaw/plugin-sdk/provider-model-shared";
|
||||
export type { KilocodeModelCatalogEntry } from "./provider-models.js";
|
||||
|
||||
@@ -134,23 +134,6 @@ export function resolveChannelMessageToolHints(params: {
|
||||
.filter(Boolean);
|
||||
}
|
||||
|
||||
export function resolveChannelMessageToolCapabilities(params: {
|
||||
cfg?: OpenClawConfig;
|
||||
channel?: string | null;
|
||||
accountId?: string | null;
|
||||
}): string[] {
|
||||
const channelId = normalizeAnyChannelId(params.channel);
|
||||
if (!channelId) {
|
||||
return [];
|
||||
}
|
||||
const resolve = getChannelPlugin(channelId)?.agentPrompt?.messageToolCapabilities;
|
||||
if (!resolve) {
|
||||
return [];
|
||||
}
|
||||
const cfg = params.cfg ?? ({} as OpenClawConfig);
|
||||
return normalizePromptCapabilities(resolve({ cfg, accountId: params.accountId }));
|
||||
}
|
||||
|
||||
export function resolveChannelPromptCapabilities(params: {
|
||||
cfg?: OpenClawConfig;
|
||||
channel?: string | null;
|
||||
|
||||
@@ -1,13 +1,7 @@
|
||||
import type { Context } from "@mariozechner/pi-ai";
|
||||
import { buildCopilotIdeHeaders } from "../plugin-sdk/provider-auth.js";
|
||||
|
||||
export {
|
||||
buildCopilotIdeHeaders,
|
||||
COPILOT_EDITOR_PLUGIN_VERSION,
|
||||
COPILOT_EDITOR_VERSION,
|
||||
COPILOT_GITHUB_API_VERSION,
|
||||
COPILOT_USER_AGENT,
|
||||
} from "../plugin-sdk/provider-auth.js";
|
||||
export { buildCopilotIdeHeaders } from "../plugin-sdk/provider-auth.js";
|
||||
|
||||
function inferCopilotInitiator(messages: Context["messages"]): "agent" | "user" {
|
||||
const last = messages[messages.length - 1];
|
||||
|
||||
@@ -2,6 +2,7 @@ import { beforeEach, describe, expect, it, vi } from "vitest";
|
||||
|
||||
const mocks = vi.hoisted(() => ({
|
||||
ensureAuthProfileStore: vi.fn(),
|
||||
externalCliDiscoveryForProviderAuth: vi.fn(() => undefined),
|
||||
loadAuthProfileStoreWithoutExternalProfiles: vi.fn(),
|
||||
resolveAuthProfileOrder: vi.fn(),
|
||||
resolveAuthProfileDisplayLabel: vi.fn(),
|
||||
@@ -12,6 +13,7 @@ const mocks = vi.hoisted(() => ({
|
||||
|
||||
vi.mock("./auth-profiles.js", () => ({
|
||||
ensureAuthProfileStore: mocks.ensureAuthProfileStore,
|
||||
externalCliDiscoveryForProviderAuth: mocks.externalCliDiscoveryForProviderAuth,
|
||||
loadAuthProfileStoreWithoutExternalProfiles: mocks.loadAuthProfileStoreWithoutExternalProfiles,
|
||||
resolveAuthProfileOrder: mocks.resolveAuthProfileOrder,
|
||||
resolveAuthProfileDisplayLabel: mocks.resolveAuthProfileDisplayLabel,
|
||||
@@ -35,6 +37,8 @@ describe("resolveModelAuthLabel", () => {
|
||||
({ resolveModelAuthLabel } = await import("./model-auth-label.js"));
|
||||
}
|
||||
mocks.ensureAuthProfileStore.mockReset();
|
||||
mocks.externalCliDiscoveryForProviderAuth.mockReset();
|
||||
mocks.externalCliDiscoveryForProviderAuth.mockReturnValue(undefined);
|
||||
mocks.loadAuthProfileStoreWithoutExternalProfiles.mockReset();
|
||||
mocks.resolveAuthProfileOrder.mockReset();
|
||||
mocks.resolveAuthProfileDisplayLabel.mockReset();
|
||||
|
||||
@@ -1,8 +1,5 @@
|
||||
import { normalizeToolParameterSchema } from "./pi-tools-parameter-schema.js";
|
||||
export {
|
||||
resolveOpenAIStrictToolSetting,
|
||||
resolvesToNativeOpenAIStrictTools,
|
||||
} from "./openai-strict-tool-setting.js";
|
||||
export { resolveOpenAIStrictToolSetting } from "./openai-strict-tool-setting.js";
|
||||
|
||||
type ToolWithParameters = {
|
||||
name?: unknown;
|
||||
|
||||
@@ -106,17 +106,3 @@ export function readLastCacheTtlTimestamp(
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
export function appendCacheTtlTimestamp(sessionManager: unknown, data: CacheTtlEntryData): void {
|
||||
const sm = sessionManager as {
|
||||
appendCustomEntry?: (customType: string, data: unknown) => void;
|
||||
};
|
||||
if (!sm?.appendCustomEntry) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
sm.appendCustomEntry(CACHE_TTL_CUSTOM_TYPE, data);
|
||||
} catch {
|
||||
// ignore persistence failures
|
||||
}
|
||||
}
|
||||
|
||||
@@ -464,15 +464,6 @@ export function createCodexNativeWebSearchWrapper(
|
||||
});
|
||||
};
|
||||
}
|
||||
export function createCodexDefaultTransportWrapper(baseStreamFn: StreamFn | undefined): StreamFn {
|
||||
const underlying = baseStreamFn ?? streamSimple;
|
||||
return (model, context, options) =>
|
||||
underlying(model, context, {
|
||||
...options,
|
||||
transport: options?.transport ?? "auto",
|
||||
});
|
||||
}
|
||||
|
||||
export function createOpenAIDefaultTransportWrapper(baseStreamFn: StreamFn | undefined): StreamFn {
|
||||
const underlying = baseStreamFn ?? streamSimple;
|
||||
return (model, context, options) => {
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import type { StreamFn } from "@mariozechner/pi-agent-core";
|
||||
import { streamSimple } from "@mariozechner/pi-ai";
|
||||
import type { ThinkLevel } from "../../auto-reply/thinking.js";
|
||||
import { isProxyReasoningUnsupportedModelHint } from "../../plugin-sdk/provider-model-shared.js";
|
||||
import { normalizeOptionalLowercaseString, readStringValue } from "../../shared/string-coerce.js";
|
||||
import { resolveProviderRequestPolicy } from "../provider-attribution.js";
|
||||
import { resolveProviderRequestPolicyConfig } from "../provider-request-config.js";
|
||||
@@ -108,7 +107,9 @@ export function createOpenRouterWrapper(
|
||||
}
|
||||
|
||||
export function isProxyReasoningUnsupported(modelId: string): boolean {
|
||||
return isProxyReasoningUnsupportedModelHint(modelId);
|
||||
const trimmed = normalizeOptionalLowercaseString(modelId);
|
||||
const slashIndex = trimmed?.indexOf("/") ?? -1;
|
||||
return slashIndex > 0 && trimmed?.slice(0, slashIndex) === "x-ai";
|
||||
}
|
||||
|
||||
export function createKilocodeWrapper(
|
||||
|
||||
@@ -353,7 +353,6 @@ export {
|
||||
shouldInjectHeartbeatPrompt,
|
||||
} from "./attempt.prompt-helpers.js";
|
||||
export {
|
||||
buildSessionsYieldContextMessage,
|
||||
persistSessionsYieldContextMessage,
|
||||
queueSessionsYieldInterruptMessage,
|
||||
stripSessionsYieldArtifacts,
|
||||
|
||||
@@ -1,12 +1,5 @@
|
||||
import type { FailoverReason } from "../../pi-embedded-helpers.js";
|
||||
|
||||
export type RunFailoverDecisionAction =
|
||||
| "continue_normal"
|
||||
| "rotate_profile"
|
||||
| "fallback_model"
|
||||
| "surface_error"
|
||||
| "return_error_payload";
|
||||
|
||||
export type RunFailoverDecision =
|
||||
| {
|
||||
action: "continue_normal";
|
||||
|
||||
@@ -8,11 +8,6 @@
|
||||
export { default } from "./context-pruning/extension.js";
|
||||
|
||||
export { pruneContextMessages } from "./context-pruning/pruner.js";
|
||||
export type {
|
||||
ContextPruningConfig,
|
||||
ContextPruningToolMatch,
|
||||
EffectiveContextPruningSettings,
|
||||
} from "./context-pruning/settings.js";
|
||||
export {
|
||||
computeEffectiveSettings,
|
||||
DEFAULT_CONTEXT_PRUNING_SETTINGS,
|
||||
|
||||
@@ -20,7 +20,6 @@ export type {
|
||||
SandboxBackendCommandResult,
|
||||
SandboxBackendExecSpec,
|
||||
SandboxBackendHandle,
|
||||
SandboxFsBridgeContext,
|
||||
} from "./backend-handle.types.js";
|
||||
|
||||
const SANDBOX_BACKEND_FACTORIES = new Map<SandboxBackendId, RegisteredSandboxBackend>();
|
||||
|
||||
@@ -100,11 +100,3 @@ export function sanitizeEnvVars(
|
||||
|
||||
return { allowed, blocked, warnings };
|
||||
}
|
||||
|
||||
export function getBlockedPatterns(): string[] {
|
||||
return BLOCKED_ENV_VAR_PATTERNS.map((pattern) => pattern.source);
|
||||
}
|
||||
|
||||
export function getAllowedPatterns(): string[] {
|
||||
return ALLOWED_ENV_VAR_PATTERNS.map((pattern) => pattern.source);
|
||||
}
|
||||
|
||||
@@ -6,23 +6,6 @@ function resolveControllerSessionKey(entry: SubagentRunRecord): string {
|
||||
return entry.controllerSessionKey?.trim() || entry.requesterSessionKey;
|
||||
}
|
||||
|
||||
export function findRunIdsByChildSessionKeyFromRuns(
|
||||
runs: Map<string, SubagentRunRecord>,
|
||||
childSessionKey: string,
|
||||
): string[] {
|
||||
const key = childSessionKey.trim();
|
||||
if (!key) {
|
||||
return [];
|
||||
}
|
||||
const runIds: string[] = [];
|
||||
for (const [runId, entry] of runs.entries()) {
|
||||
if (entry.childSessionKey === key) {
|
||||
runIds.push(runId);
|
||||
}
|
||||
}
|
||||
return runIds;
|
||||
}
|
||||
|
||||
export function listRunsForRequesterFromRuns(
|
||||
runs: Map<string, SubagentRunRecord>,
|
||||
requesterSessionKey: string,
|
||||
|
||||
@@ -7,8 +7,6 @@ import { readStringValue } from "../shared/string-coerce.js";
|
||||
import { normalizeDeliveryContext } from "../utils/delivery-context.shared.js";
|
||||
import type { SubagentRunRecord } from "./subagent-registry.types.js";
|
||||
|
||||
export type PersistedSubagentRegistryVersion = 1 | 2;
|
||||
|
||||
type PersistedSubagentRegistryV1 = {
|
||||
version: 1;
|
||||
runs: Record<string, LegacySubagentRunRecord>;
|
||||
|
||||
@@ -20,24 +20,6 @@ export function sanitizeTextContent(text: string): string {
|
||||
return sanitizeAssistantVisibleTextWithProfile(text, "history");
|
||||
}
|
||||
|
||||
export function hasAssistantPhaseMetadata(message: unknown): boolean {
|
||||
if (!message || typeof message !== "object") {
|
||||
return false;
|
||||
}
|
||||
if ((message as { role?: unknown }).role !== "assistant") {
|
||||
return false;
|
||||
}
|
||||
const content = (message as { content?: unknown }).content;
|
||||
if (!Array.isArray(content)) {
|
||||
return false;
|
||||
}
|
||||
return content.some(
|
||||
(block) =>
|
||||
block &&
|
||||
typeof block === "object" &&
|
||||
typeof (block as { textSignature?: unknown }).textSignature === "string",
|
||||
);
|
||||
}
|
||||
export function extractAssistantText(message: unknown): string | undefined {
|
||||
if (!message || typeof message !== "object") {
|
||||
return undefined;
|
||||
|
||||
@@ -1,5 +1 @@
|
||||
export {
|
||||
extractAssistantText,
|
||||
sanitizeTextContent,
|
||||
stripToolMessages,
|
||||
} from "./chat-history-text.js";
|
||||
export { extractAssistantText, sanitizeTextContent } from "./chat-history-text.js";
|
||||
|
||||
@@ -5,9 +5,9 @@ import {
|
||||
createSessionVisibilityGuard,
|
||||
resolveEffectiveSessionToolsVisibility,
|
||||
resolveSandboxSessionToolsVisibility,
|
||||
resolveSandboxedSessionToolContext,
|
||||
resolveSessionToolsVisibility,
|
||||
} from "./sessions-access.js";
|
||||
} from "../../plugin-sdk/session-visibility.js";
|
||||
import { resolveSandboxedSessionToolContext } from "./sessions-access.js";
|
||||
import { __testing as sessionsResolutionTesting } from "./sessions-resolution.js";
|
||||
|
||||
describe("resolveSessionToolsVisibility", () => {
|
||||
|
||||
@@ -6,27 +6,17 @@ import {
|
||||
listSpawnedSessionKeys,
|
||||
resolveEffectiveSessionToolsVisibility,
|
||||
resolveSandboxSessionToolsVisibility,
|
||||
resolveSessionToolsVisibility,
|
||||
} from "../../plugin-sdk/session-visibility.js";
|
||||
import { isSubagentSessionKey } from "../../routing/session-key.js";
|
||||
import { normalizeOptionalString } from "../../shared/string-coerce.js";
|
||||
import { resolveInternalSessionKey, resolveMainSessionAlias } from "./sessions-resolution.js";
|
||||
|
||||
export type {
|
||||
AgentToAgentPolicy,
|
||||
SessionAccessAction,
|
||||
SessionAccessResult,
|
||||
SessionToolsVisibility,
|
||||
} from "../../plugin-sdk/session-visibility.js";
|
||||
|
||||
export {
|
||||
createAgentToAgentPolicy,
|
||||
createSessionVisibilityChecker,
|
||||
createSessionVisibilityGuard,
|
||||
listSpawnedSessionKeys,
|
||||
resolveEffectiveSessionToolsVisibility,
|
||||
resolveSandboxSessionToolsVisibility,
|
||||
resolveSessionToolsVisibility,
|
||||
} from "../../plugin-sdk/session-visibility.js";
|
||||
|
||||
export function resolveSandboxedSessionToolContext(params: {
|
||||
|
||||
@@ -1,25 +1,11 @@
|
||||
export type {
|
||||
AgentToAgentPolicy,
|
||||
SessionAccessAction,
|
||||
SessionAccessResult,
|
||||
SessionToolsVisibility,
|
||||
} from "./sessions-access.js";
|
||||
export {
|
||||
createAgentToAgentPolicy,
|
||||
createSessionVisibilityGuard,
|
||||
resolveEffectiveSessionToolsVisibility,
|
||||
resolveSandboxSessionToolsVisibility,
|
||||
resolveSandboxedSessionToolContext,
|
||||
resolveSessionToolsVisibility,
|
||||
} from "./sessions-access.js";
|
||||
import { resolveSandboxedSessionToolContext } from "./sessions-access.js";
|
||||
export type { SessionReferenceResolution } from "./sessions-resolution.js";
|
||||
export {
|
||||
isRequesterSpawnedSessionVisible,
|
||||
isResolvedSessionVisibleToRequester,
|
||||
listSpawnedSessionKeys,
|
||||
looksLikeSessionId,
|
||||
looksLikeSessionKey,
|
||||
resolveCurrentSessionClientAlias,
|
||||
resolveDisplaySessionKey,
|
||||
resolveInternalSessionKey,
|
||||
@@ -27,7 +13,6 @@ export {
|
||||
resolveSessionReference,
|
||||
resolveVisibleSessionReference,
|
||||
shouldResolveSessionIdInput,
|
||||
shouldVerifyRequesterSpawnedSessionVisibility,
|
||||
} from "./sessions-resolution.js";
|
||||
export {
|
||||
extractAssistantText,
|
||||
|
||||
@@ -1,41 +1,6 @@
|
||||
import { resolvePluginWebSearchConfig } from "../../config/plugin-web-search-config.js";
|
||||
import type { OpenClawConfig } from "../../config/types.openclaw.js";
|
||||
|
||||
type ConfiguredWebSearchProvider = NonNullable<
|
||||
NonNullable<NonNullable<OpenClawConfig["tools"]>["web"]>["search"]
|
||||
>["provider"];
|
||||
|
||||
export type WebSearchConfig = NonNullable<OpenClawConfig["tools"]>["web"] extends infer Web
|
||||
? Web extends { search?: infer Search }
|
||||
? Search
|
||||
: undefined
|
||||
: undefined;
|
||||
|
||||
function cloneWithDescriptors<T extends object>(value: T | undefined): T {
|
||||
const next = Object.create(Object.getPrototypeOf(value ?? {})) as T;
|
||||
if (value) {
|
||||
Object.defineProperties(next, Object.getOwnPropertyDescriptors(value));
|
||||
}
|
||||
return next;
|
||||
}
|
||||
|
||||
export function withForcedProvider(
|
||||
config: OpenClawConfig | undefined,
|
||||
provider: ConfiguredWebSearchProvider,
|
||||
): OpenClawConfig {
|
||||
const next = cloneWithDescriptors(config ?? {});
|
||||
const tools = cloneWithDescriptors(next.tools ?? {});
|
||||
const web = cloneWithDescriptors(tools.web ?? {});
|
||||
const search = cloneWithDescriptors(web.search ?? {});
|
||||
|
||||
search.provider = provider;
|
||||
web.search = search;
|
||||
tools.web = web;
|
||||
next.tools = tools;
|
||||
|
||||
return next;
|
||||
}
|
||||
|
||||
export function getTopLevelCredentialValue(searchConfig?: Record<string, unknown>): unknown {
|
||||
return searchConfig?.apiKey;
|
||||
}
|
||||
@@ -102,14 +67,6 @@ export function mergeScopedSearchConfig(
|
||||
return next;
|
||||
}
|
||||
|
||||
export function resolveSearchConfig(cfg?: OpenClawConfig): WebSearchConfig {
|
||||
const search = cfg?.tools?.web?.search;
|
||||
if (!search || typeof search !== "object") {
|
||||
return undefined;
|
||||
}
|
||||
return search as WebSearchConfig;
|
||||
}
|
||||
|
||||
export function resolveProviderWebSearchPluginConfig(
|
||||
config: OpenClawConfig | undefined,
|
||||
pluginId: string,
|
||||
@@ -143,16 +100,3 @@ export function setProviderWebSearchPluginConfigValue(
|
||||
const webSearch = ensureObject(config, "webSearch");
|
||||
webSearch[key] = value;
|
||||
}
|
||||
|
||||
export function resolveSearchEnabled(params: {
|
||||
search?: WebSearchConfig;
|
||||
sandboxed?: boolean;
|
||||
}): boolean {
|
||||
if (typeof params.search?.enabled === "boolean") {
|
||||
return params.search.enabled;
|
||||
}
|
||||
if (params.sandboxed) {
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
export { createWebFetchTool, extractReadableContent } from "./web-fetch.js";
|
||||
export { createWebFetchTool } from "./web-fetch.js";
|
||||
export { createWebSearchTool } from "./web-search.js";
|
||||
|
||||
@@ -368,23 +368,6 @@ function estimatePromptTokensFromSessionTranscript(params: {
|
||||
}
|
||||
}
|
||||
|
||||
export async function readPromptTokensFromSessionLog(
|
||||
sessionId?: string,
|
||||
sessionEntry?: SessionEntry,
|
||||
sessionKey?: string,
|
||||
opts?: { storePath?: string },
|
||||
): Promise<SessionTranscriptUsageSnapshot | undefined> {
|
||||
const snapshot = await readSessionLogSnapshot({
|
||||
sessionId,
|
||||
sessionEntry,
|
||||
sessionKey,
|
||||
opts,
|
||||
includeByteSize: false,
|
||||
includeUsage: true,
|
||||
});
|
||||
return snapshot.usage;
|
||||
}
|
||||
|
||||
export async function runPreflightCompactionIfNeeded(params: {
|
||||
cfg: OpenClawConfig;
|
||||
followupRun: FollowupRun;
|
||||
|
||||
@@ -2,19 +2,13 @@ import type { SubagentRunRecord } from "../../agents/subagent-registry.types.js"
|
||||
import type { HandleCommandsParams } from "./commands-types.js";
|
||||
|
||||
export {
|
||||
ACTIONS,
|
||||
COMMAND,
|
||||
COMMAND_AGENTS,
|
||||
COMMAND_FOCUS,
|
||||
COMMAND_KILL,
|
||||
COMMAND_STEER,
|
||||
COMMAND_TELL,
|
||||
COMMAND_UNFOCUS,
|
||||
resolveHandledPrefix,
|
||||
resolveRequesterSessionKey,
|
||||
resolveSubagentsAction,
|
||||
stopWithText,
|
||||
type SubagentsAction,
|
||||
} from "./commands-subagents/shared.js";
|
||||
|
||||
export type SubagentsCommandContext = {
|
||||
|
||||
@@ -8,8 +8,6 @@ import {
|
||||
} from "./commands-subagents-dispatch.js";
|
||||
import type { CommandHandler } from "./commands-types.js";
|
||||
|
||||
export { extractMessageText } from "./commands-subagents-text.js";
|
||||
|
||||
let actionAgentsPromise: Promise<typeof import("./commands-subagents/action-agents.js")> | null =
|
||||
null;
|
||||
let actionFocusPromise: Promise<typeof import("./commands-subagents/action-focus.js")> | null =
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import { resolveModelDisplayName } from "../../../agents/model-selection-display.js";
|
||||
import { resolveStoredSubagentCapabilities } from "../../../agents/subagent-capabilities.js";
|
||||
import type { ResolvedSubagentController } from "../../../agents/subagent-control.js";
|
||||
import { subagentRuns } from "../../../agents/subagent-registry-memory.js";
|
||||
@@ -11,11 +10,7 @@ import {
|
||||
resolveMainSessionAlias,
|
||||
stripToolMessages,
|
||||
} from "../../../agents/tools/sessions-helpers.js";
|
||||
import type { resolveStorePath as resolveStorePathFn } from "../../../config/sessions/paths.js";
|
||||
import type { loadSessionStore as loadSessionStoreFn } from "../../../config/sessions/store-load.js";
|
||||
import type { SessionEntry } from "../../../config/sessions/types.js";
|
||||
import { callGateway } from "../../../gateway/call.js";
|
||||
import { formatTimeAgo } from "../../../infra/format-time/format-relative.ts";
|
||||
import { parseAgentSessionKey } from "../../../routing/session-key.js";
|
||||
import { isSubagentSessionKey } from "../../../routing/session-key.js";
|
||||
import { looksLikeSessionId } from "../../../sessions/session-id.js";
|
||||
@@ -23,17 +18,11 @@ import {
|
||||
normalizeLowercaseStringOrEmpty,
|
||||
normalizeOptionalString,
|
||||
} from "../../../shared/string-coerce.js";
|
||||
import {
|
||||
formatDurationCompact,
|
||||
formatTokenUsageDisplay,
|
||||
truncateLine,
|
||||
} from "../../../shared/subagents-format.js";
|
||||
import { resolveCommandSurfaceChannel, resolveChannelAccountId } from "../channel-context.js";
|
||||
import { extractMessageText, type ChatMessage } from "../commands-subagents-text.js";
|
||||
import type { CommandHandler, CommandHandlerResult } from "../commands-types.js";
|
||||
import {
|
||||
formatRunLabel,
|
||||
formatRunStatus,
|
||||
resolveSubagentTargetFromRuns,
|
||||
type SubagentTargetResolution,
|
||||
} from "../subagents-utils.js";
|
||||
@@ -45,11 +34,11 @@ export type { ChatMessage } from "../commands-subagents-text.js";
|
||||
export const COMMAND = "/subagents";
|
||||
export const COMMAND_KILL = "/kill";
|
||||
export const COMMAND_STEER = "/steer";
|
||||
export const COMMAND_TELL = "/tell";
|
||||
export const COMMAND_FOCUS = "/focus";
|
||||
export const COMMAND_UNFOCUS = "/unfocus";
|
||||
export const COMMAND_AGENTS = "/agents";
|
||||
export const ACTIONS = new Set([
|
||||
const COMMAND_TELL = "/tell";
|
||||
const COMMAND_FOCUS = "/focus";
|
||||
const COMMAND_UNFOCUS = "/unfocus";
|
||||
const COMMAND_AGENTS = "/agents";
|
||||
const ACTIONS = new Set([
|
||||
"list",
|
||||
"kill",
|
||||
"log",
|
||||
@@ -64,81 +53,8 @@ export const ACTIONS = new Set([
|
||||
]);
|
||||
|
||||
export const RECENT_WINDOW_MINUTES = 30;
|
||||
const SUBAGENT_TASK_PREVIEW_MAX = 110;
|
||||
export const STEER_ABORT_SETTLE_TIMEOUT_MS = 5_000;
|
||||
|
||||
function compactLine(value: string) {
|
||||
return value.replace(/\s+/g, " ").trim();
|
||||
}
|
||||
|
||||
function formatTaskPreview(value: string) {
|
||||
return truncateLine(compactLine(value), SUBAGENT_TASK_PREVIEW_MAX);
|
||||
}
|
||||
|
||||
export function resolveDisplayStatus(
|
||||
entry: SubagentRunRecord,
|
||||
options?: { pendingDescendants?: number },
|
||||
) {
|
||||
const pendingDescendants = Math.max(0, options?.pendingDescendants ?? 0);
|
||||
if (pendingDescendants > 0) {
|
||||
const childLabel = pendingDescendants === 1 ? "child" : "children";
|
||||
return `active (waiting on ${pendingDescendants} ${childLabel})`;
|
||||
}
|
||||
const status = formatRunStatus(entry);
|
||||
return status === "error" ? "failed" : status;
|
||||
}
|
||||
|
||||
export function formatSubagentListLine(params: {
|
||||
entry: SubagentRunRecord;
|
||||
index: number;
|
||||
runtimeMs: number;
|
||||
sessionEntry?: SessionEntry;
|
||||
pendingDescendants?: number;
|
||||
}) {
|
||||
const usageText = formatTokenUsageDisplay(params.sessionEntry);
|
||||
const label = truncateLine(formatRunLabel(params.entry, { maxLength: 48 }), 48);
|
||||
const task = formatTaskPreview(params.entry.task);
|
||||
const runtime = formatDurationCompact(params.runtimeMs) ?? "n/a";
|
||||
const status = resolveDisplayStatus(params.entry, {
|
||||
pendingDescendants: params.pendingDescendants,
|
||||
});
|
||||
return `${params.index}. ${label} (${resolveModelDisplayName({
|
||||
runtimeProvider:
|
||||
typeof params.sessionEntry?.modelProvider === "string"
|
||||
? params.sessionEntry.modelProvider
|
||||
: null,
|
||||
runtimeModel: typeof params.sessionEntry?.model === "string" ? params.sessionEntry.model : null,
|
||||
overrideProvider:
|
||||
typeof params.sessionEntry?.providerOverride === "string"
|
||||
? params.sessionEntry.providerOverride
|
||||
: null,
|
||||
overrideModel:
|
||||
typeof params.sessionEntry?.modelOverride === "string"
|
||||
? params.sessionEntry.modelOverride
|
||||
: null,
|
||||
fallbackModel: params.entry.model,
|
||||
})}, ${runtime}${usageText ? `, ${usageText}` : ""}) ${status}${
|
||||
normalizeLowercaseStringOrEmpty(task) !== normalizeLowercaseStringOrEmpty(label)
|
||||
? ` - ${task}`
|
||||
: ""
|
||||
}`;
|
||||
}
|
||||
|
||||
function formatTimestamp(valueMs?: number) {
|
||||
if (!valueMs || !Number.isFinite(valueMs) || valueMs <= 0) {
|
||||
return "n/a";
|
||||
}
|
||||
return new Date(valueMs).toISOString();
|
||||
}
|
||||
|
||||
export function formatTimestampWithAge(valueMs?: number) {
|
||||
if (!valueMs || !Number.isFinite(valueMs) || valueMs <= 0) {
|
||||
return "n/a";
|
||||
}
|
||||
return `${formatTimestamp(valueMs)} (${formatTimeAgo(Date.now() - valueMs, { fallback: "n/a" })})`;
|
||||
}
|
||||
|
||||
export type SubagentsAction =
|
||||
type SubagentsAction =
|
||||
| "list"
|
||||
| "kill"
|
||||
| "log"
|
||||
@@ -395,26 +311,3 @@ export function formatLogLines(messages: ChatMessage[]) {
|
||||
}
|
||||
return lines;
|
||||
}
|
||||
|
||||
export type SessionStoreCache = Map<string, Record<string, SessionEntry>>;
|
||||
|
||||
export function loadSubagentSessionEntry(
|
||||
params: SubagentsCommandParams,
|
||||
childKey: string,
|
||||
loaders: {
|
||||
loadSessionStore: typeof loadSessionStoreFn;
|
||||
resolveStorePath: typeof resolveStorePathFn;
|
||||
},
|
||||
storeCache?: SessionStoreCache,
|
||||
) {
|
||||
const parsed = parseAgentSessionKey(childKey);
|
||||
const storePath = loaders.resolveStorePath(params.cfg.session?.store, {
|
||||
agentId: parsed?.agentId,
|
||||
});
|
||||
let store = storeCache?.get(storePath);
|
||||
if (!store) {
|
||||
store = loaders.loadSessionStore(storePath);
|
||||
storeCache?.set(storePath, store);
|
||||
}
|
||||
return { storePath, store, entry: store[childKey] };
|
||||
}
|
||||
|
||||
@@ -1,8 +1,3 @@
|
||||
export { buildCommandContext } from "./commands-context.js";
|
||||
export { handleCommands } from "./commands-core.js";
|
||||
export { buildStatusReply } from "./commands-status.js";
|
||||
export type {
|
||||
CommandContext,
|
||||
CommandHandlerResult,
|
||||
HandleCommandsParams,
|
||||
} from "./commands-types.js";
|
||||
|
||||
@@ -1,8 +1 @@
|
||||
export { applyInlineDirectivesFastLane } from "./directive-handling.fast-lane.js";
|
||||
export * from "./directive-handling.impl.js";
|
||||
export type { InlineDirectives } from "./directive-handling.parse.js";
|
||||
export { isDirectiveOnly } from "./directive-handling.directive-only.js";
|
||||
export { parseInlineDirectives } from "./directive-handling.parse.js";
|
||||
export { persistInlineDirectives } from "./directive-handling.persist.js";
|
||||
export { resolveDefaultModel } from "./directive-handling.defaults.js";
|
||||
export { formatDirectiveAck } from "./directive-handling.shared.js";
|
||||
|
||||
@@ -4,7 +4,6 @@ import {
|
||||
type ElevatedLevel,
|
||||
normalizeFastMode,
|
||||
normalizeElevatedLevel,
|
||||
normalizeNoticeLevel,
|
||||
normalizeReasoningLevel,
|
||||
normalizeTraceLevel,
|
||||
normalizeThinkLevel,
|
||||
@@ -162,24 +161,6 @@ export function extractFastDirective(body?: string): {
|
||||
};
|
||||
}
|
||||
|
||||
export function extractNoticeDirective(body?: string): {
|
||||
cleaned: string;
|
||||
noticeLevel?: NoticeLevel;
|
||||
rawLevel?: string;
|
||||
hasDirective: boolean;
|
||||
} {
|
||||
if (!body) {
|
||||
return { cleaned: "", hasDirective: false };
|
||||
}
|
||||
const extracted = extractLevelDirective(body, ["notice", "notices"], normalizeNoticeLevel);
|
||||
return {
|
||||
cleaned: extracted.cleaned,
|
||||
noticeLevel: extracted.level,
|
||||
rawLevel: extracted.rawLevel,
|
||||
hasDirective: extracted.hasDirective,
|
||||
};
|
||||
}
|
||||
|
||||
export function extractElevatedDirective(body?: string): {
|
||||
cleaned: string;
|
||||
elevatedLevel?: ElevatedLevel;
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import crypto from "node:crypto";
|
||||
import { resolveContextTokensForModel } from "../../agents/context.js";
|
||||
import { DEFAULT_CONTEXT_TOKENS } from "../../agents/defaults.js";
|
||||
import { parseNonNegativeByteSize } from "../../config/byte-size.js";
|
||||
@@ -122,20 +121,3 @@ export function hasAlreadyFlushedForCurrentCompaction(
|
||||
const lastFlushAt = entry.memoryFlushCompactionCount;
|
||||
return typeof lastFlushAt === "number" && lastFlushAt === compactionCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compute a lightweight content hash from the tail of a session transcript.
|
||||
* Used for state-based flush deduplication — if the hash hasn't changed since
|
||||
* the last flush, the context is effectively the same and flushing again would
|
||||
* produce duplicate memory entries.
|
||||
*
|
||||
* Hash input: `messages.length` + content of the last 3 user/assistant messages.
|
||||
* Algorithm: SHA-256 truncated to 16 hex chars (collision-resistant enough for dedup).
|
||||
*/
|
||||
export function computeContextHash(messages: Array<{ role?: string; content?: unknown }>): string {
|
||||
const userAssistant = messages.filter((m) => m.role === "user" || m.role === "assistant");
|
||||
const tail = userAssistant.slice(-3);
|
||||
const payload = `${messages.length}:${tail.map((m, i) => `[${i}:${m.role ?? ""}]${typeof m.content === "string" ? m.content : JSON.stringify(m.content ?? "")}`).join("\x00")}`;
|
||||
const hash = crypto.createHash("sha256").update(payload).digest("hex");
|
||||
return hash.slice(0, 16);
|
||||
}
|
||||
|
||||
@@ -14,12 +14,7 @@ import {
|
||||
import { escapeRegExp } from "../../utils.js";
|
||||
import type { MsgContext } from "../templating.js";
|
||||
import type { ExplicitMentionSignal } from "./mentions.types.js";
|
||||
export type {
|
||||
BuildMentionRegexes,
|
||||
ExplicitMentionSignal,
|
||||
MatchesMentionPatterns,
|
||||
MatchesMentionWithExplicit,
|
||||
} from "./mentions.types.js";
|
||||
export type { ExplicitMentionSignal } from "./mentions.types.js";
|
||||
|
||||
function deriveMentionPatterns(identity?: { name?: string; emoji?: string }) {
|
||||
const patterns: string[] = [];
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
export type { AllowlistMatch, AllowlistMatchSource } from "../allowlist-match.js";
|
||||
export { formatAllowlistMatchMeta, resolveAllowlistMatchSimple } from "../allowlist-match.js";
|
||||
export { formatAllowlistMatchMeta } from "../allowlist-match.js";
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import { getChannelPlugin, normalizeChannelId } from "./registry.js";
|
||||
import type { ChannelConfiguredBindingProvider } from "./types.adapters.js";
|
||||
import type { ChannelPlugin } from "./types.plugin.js";
|
||||
|
||||
@@ -13,13 +12,3 @@ export function resolveChannelConfiguredBindingProvider(
|
||||
): ChannelConfiguredBindingProvider | undefined {
|
||||
return plugin?.bindings;
|
||||
}
|
||||
|
||||
export function resolveChannelConfiguredBindingProviderByChannel(
|
||||
channel: string,
|
||||
): ChannelConfiguredBindingProvider | undefined {
|
||||
const normalizedChannel = normalizeChannelId(channel);
|
||||
if (!normalizedChannel) {
|
||||
return undefined;
|
||||
}
|
||||
return resolveChannelConfiguredBindingProvider(getChannelPlugin(normalizedChannel));
|
||||
}
|
||||
|
||||
@@ -20,15 +20,6 @@ export const BLUEBUBBLES_ACTIONS = {
|
||||
sendAttachment: { gate: "sendAttachment" },
|
||||
} as const satisfies Partial<Record<ChannelMessageActionName, BlueBubblesActionSpec>>;
|
||||
|
||||
const BLUEBUBBLES_ACTION_SPECS = BLUEBUBBLES_ACTIONS as Record<
|
||||
keyof typeof BLUEBUBBLES_ACTIONS,
|
||||
BlueBubblesActionSpec
|
||||
>;
|
||||
|
||||
export const BLUEBUBBLES_ACTION_NAMES = Object.keys(
|
||||
BLUEBUBBLES_ACTIONS,
|
||||
) as (keyof typeof BLUEBUBBLES_ACTIONS)[];
|
||||
|
||||
export const BLUEBUBBLES_GROUP_ACTIONS = new Set<ChannelMessageActionName>(
|
||||
BLUEBUBBLES_ACTION_NAMES.filter((action) => BLUEBUBBLES_ACTION_SPECS[action]?.groupOnly),
|
||||
);
|
||||
|
||||
@@ -73,10 +73,6 @@ export function* iterateBootstrapChannelPlugins(): IterableIterator<ChannelPlugi
|
||||
}
|
||||
}
|
||||
|
||||
export function listBootstrapChannelPlugins(): readonly ChannelPlugin[] {
|
||||
return [...iterateBootstrapChannelPlugins()];
|
||||
}
|
||||
|
||||
export function getBootstrapChannelPlugin(id: ChannelId): ChannelPlugin | undefined {
|
||||
const resolvedId = resolveBootstrapChannelId(id);
|
||||
if (!resolvedId) {
|
||||
|
||||
@@ -21,9 +21,3 @@ export function isChannelVisibleInSetup(
|
||||
): boolean {
|
||||
return resolveChannelExposure(meta).setup;
|
||||
}
|
||||
|
||||
export function isChannelVisibleInDocs(
|
||||
meta: Pick<ChannelMeta, "exposure" | "showConfigured" | "showInSetup">,
|
||||
): boolean {
|
||||
return resolveChannelExposure(meta).docs;
|
||||
}
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
import type { OpenClawConfig } from "../../config/types.openclaw.js";
|
||||
import type { RuntimeEnv } from "../../runtime.js";
|
||||
import { normalizeLowercaseStringOrEmpty } from "../../shared/string-coerce.js";
|
||||
import type { ChannelId } from "./channel-id.types.js";
|
||||
import type { ChannelPairingAdapter } from "./pairing.types.js";
|
||||
import { getChannelPlugin, listChannelPlugins, normalizeChannelId } from "./registry.js";
|
||||
import { getChannelPlugin, listChannelPlugins } from "./registry.js";
|
||||
|
||||
export function listPairingChannels(): ChannelId[] {
|
||||
// Channel docking: pairing support is declared via plugin.pairing.
|
||||
@@ -25,24 +24,6 @@ export function requirePairingAdapter(channelId: ChannelId): ChannelPairingAdapt
|
||||
return adapter;
|
||||
}
|
||||
|
||||
export function resolvePairingChannel(raw: unknown): ChannelId {
|
||||
const value =
|
||||
typeof raw === "string"
|
||||
? raw
|
||||
: typeof raw === "number" || typeof raw === "boolean"
|
||||
? String(raw)
|
||||
: "";
|
||||
const normalizedValue = normalizeLowercaseStringOrEmpty(value);
|
||||
const normalized = normalizeChannelId(normalizedValue);
|
||||
const channels = listPairingChannels();
|
||||
if (!normalized || !channels.includes(normalized)) {
|
||||
throw new Error(
|
||||
`Invalid channel: ${normalizedValue || "(empty)"} (expected one of: ${channels.join(", ")})`,
|
||||
);
|
||||
}
|
||||
return normalized;
|
||||
}
|
||||
|
||||
export async function notifyPairingApproved(params: {
|
||||
channelId: ChannelId;
|
||||
id: string;
|
||||
|
||||
@@ -317,7 +317,9 @@ describe("gateway run option collisions", () => {
|
||||
});
|
||||
startGatewayServer.mockRejectedValueOnce(err);
|
||||
|
||||
await runGatewayCli(["gateway", "run", "--allow-unconfigured"]);
|
||||
await expect(runGatewayCli(["gateway", "run", "--allow-unconfigured"])).rejects.toThrow(
|
||||
"__exit__:0",
|
||||
);
|
||||
|
||||
expect(writeDiagnosticStabilityBundleForFailureSync).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
@@ -77,5 +77,3 @@ export function registerMessageThreadCommands(message: Command, helpers: Message
|
||||
await helpers.runMessageAction("thread-reply", opts);
|
||||
});
|
||||
}
|
||||
|
||||
export const __test__ = { resolveThreadCreateRequest };
|
||||
|
||||
@@ -1 +1,4 @@
|
||||
export * from "../../agents/command/session.js";
|
||||
export {
|
||||
buildExplicitSessionIdSessionKey,
|
||||
resolveSessionKeyForRequest,
|
||||
} from "../../agents/command/session.js";
|
||||
|
||||
@@ -1,99 +1,4 @@
|
||||
import type { ApplyAuthChoiceParams } from "./auth-choice.apply.types.js";
|
||||
import { applyDefaultModelChoice } from "./auth-choice.default-model.js";
|
||||
|
||||
export type {
|
||||
SecretInputModePromptCopy,
|
||||
SecretRefSetupPromptCopy,
|
||||
} from "../plugins/provider-auth-input.js";
|
||||
export {
|
||||
ensureApiKeyFromEnvOrPrompt,
|
||||
ensureApiKeyFromOptionEnvOrPrompt,
|
||||
maybeApplyApiKeyFromOption,
|
||||
normalizeSecretInputModeInput,
|
||||
normalizeTokenProviderInput,
|
||||
promptSecretRefForSetup,
|
||||
resolveSecretInputModeForEnvSelection,
|
||||
} from "../plugins/provider-auth-input.js";
|
||||
|
||||
export function createAuthChoiceAgentModelNoter(
|
||||
params: ApplyAuthChoiceParams,
|
||||
): (model: string) => Promise<void> {
|
||||
return async (model: string) => {
|
||||
if (!params.agentId) {
|
||||
return;
|
||||
}
|
||||
await params.prompter.note(
|
||||
`Default model set to ${model} for agent "${params.agentId}".`,
|
||||
"Model configured",
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
export interface ApplyAuthChoiceModelState {
|
||||
config: ApplyAuthChoiceParams["config"];
|
||||
agentModelOverride: string | undefined;
|
||||
}
|
||||
|
||||
export function createAuthChoiceModelStateBridge(bindings: {
|
||||
getConfig: () => ApplyAuthChoiceParams["config"];
|
||||
setConfig: (config: ApplyAuthChoiceParams["config"]) => void;
|
||||
getAgentModelOverride: () => string | undefined;
|
||||
setAgentModelOverride: (model: string | undefined) => void;
|
||||
}): ApplyAuthChoiceModelState {
|
||||
return {
|
||||
get config() {
|
||||
return bindings.getConfig();
|
||||
},
|
||||
set config(config) {
|
||||
bindings.setConfig(config);
|
||||
},
|
||||
get agentModelOverride() {
|
||||
return bindings.getAgentModelOverride();
|
||||
},
|
||||
set agentModelOverride(model) {
|
||||
bindings.setAgentModelOverride(model);
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
export function createAuthChoiceDefaultModelApplier(
|
||||
params: ApplyAuthChoiceParams,
|
||||
state: ApplyAuthChoiceModelState,
|
||||
): (
|
||||
options: Omit<
|
||||
Parameters<typeof applyDefaultModelChoice>[0],
|
||||
"config" | "setDefaultModel" | "noteAgentModel" | "prompter"
|
||||
>,
|
||||
) => Promise<void> {
|
||||
const noteAgentModel = createAuthChoiceAgentModelNoter(params);
|
||||
|
||||
return async (options) => {
|
||||
const applied = await applyDefaultModelChoice({
|
||||
config: state.config,
|
||||
setDefaultModel: params.setDefaultModel,
|
||||
noteAgentModel,
|
||||
prompter: params.prompter,
|
||||
...options,
|
||||
});
|
||||
state.config = applied.config;
|
||||
state.agentModelOverride = applied.agentModelOverride ?? state.agentModelOverride;
|
||||
};
|
||||
}
|
||||
|
||||
export function createAuthChoiceDefaultModelApplierForMutableState(
|
||||
params: ApplyAuthChoiceParams,
|
||||
getConfig: () => ApplyAuthChoiceParams["config"],
|
||||
setConfig: (config: ApplyAuthChoiceParams["config"]) => void,
|
||||
getAgentModelOverride: () => string | undefined,
|
||||
setAgentModelOverride: (model: string | undefined) => void,
|
||||
): ReturnType<typeof createAuthChoiceDefaultModelApplier> {
|
||||
return createAuthChoiceDefaultModelApplier(
|
||||
params,
|
||||
createAuthChoiceModelStateBridge({
|
||||
getConfig,
|
||||
setConfig,
|
||||
getAgentModelOverride,
|
||||
setAgentModelOverride,
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import { mergeMissing } from "../../../config/legacy.shared.js";
|
||||
import type { OpenClawConfig } from "../../../config/types.openclaw.js";
|
||||
import {
|
||||
cloneRecord,
|
||||
ensureRecord,
|
||||
@@ -85,19 +84,6 @@ export function listLegacyWebFetchConfigPaths(raw: unknown): string[] {
|
||||
return Object.keys(firecrawl).map((key) => `tools.web.fetch.firecrawl.${key}`);
|
||||
}
|
||||
|
||||
export function normalizeLegacyWebFetchConfig<T>(raw: T): T {
|
||||
if (!isRecord(raw)) {
|
||||
return raw;
|
||||
}
|
||||
|
||||
const fetch = resolveLegacyFetchConfig(raw);
|
||||
if (!fetch) {
|
||||
return raw;
|
||||
}
|
||||
|
||||
return normalizeLegacyWebFetchConfigRecord(raw).config;
|
||||
}
|
||||
|
||||
export function migrateLegacyWebFetchConfig<T>(raw: T): { config: T; changes: string[] } {
|
||||
if (!isRecord(raw) || !hasMappedLegacyWebFetchConfig(raw)) {
|
||||
return { config: raw, changes: [] };
|
||||
@@ -145,14 +131,3 @@ function normalizeLegacyWebFetchConfigRecord<T extends JsonRecord>(
|
||||
|
||||
return { config: nextRoot, changes };
|
||||
}
|
||||
|
||||
export function resolvePluginWebFetchConfig(
|
||||
config: OpenClawConfig | undefined,
|
||||
pluginId: string,
|
||||
): Record<string, unknown> | undefined {
|
||||
const pluginConfig = config?.plugins?.entries?.[pluginId]?.config;
|
||||
if (!isRecord(pluginConfig)) {
|
||||
return undefined;
|
||||
}
|
||||
return isRecord(pluginConfig.webFetch) ? pluginConfig.webFetch : undefined;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import { mergeMissing } from "../../../config/legacy.shared.js";
|
||||
import type { OpenClawConfig } from "../../../config/types.openclaw.js";
|
||||
import {
|
||||
loadPluginManifestRegistryForPluginRegistry,
|
||||
resolveManifestContractOwnerPluginId,
|
||||
@@ -155,19 +154,6 @@ export function listLegacyWebSearchConfigPaths(raw: unknown): string[] {
|
||||
return paths;
|
||||
}
|
||||
|
||||
export function normalizeLegacyWebSearchConfig<T>(raw: T): T {
|
||||
if (!isRecord(raw)) {
|
||||
return raw;
|
||||
}
|
||||
|
||||
const search = resolveLegacySearchConfig(raw);
|
||||
if (!search) {
|
||||
return raw;
|
||||
}
|
||||
|
||||
return normalizeLegacyWebSearchConfigRecord(raw).config;
|
||||
}
|
||||
|
||||
export function migrateLegacyWebSearchConfig<T>(raw: T): { config: T; changes: string[] } {
|
||||
if (!isRecord(raw)) {
|
||||
return { config: raw, changes: [] };
|
||||
@@ -249,15 +235,3 @@ function normalizeLegacyWebSearchConfigRecord<T extends JsonRecord>(
|
||||
|
||||
return { config: nextRoot, changes };
|
||||
}
|
||||
|
||||
export function resolvePluginWebSearchConfig(
|
||||
config: OpenClawConfig | undefined,
|
||||
pluginId: string,
|
||||
): Record<string, unknown> | undefined {
|
||||
const pluginConfig = config?.plugins?.entries?.[pluginId]?.config;
|
||||
if (!isRecord(pluginConfig)) {
|
||||
return undefined;
|
||||
}
|
||||
const webSearch = pluginConfig.webSearch;
|
||||
return isRecord(webSearch) ? webSearch : undefined;
|
||||
}
|
||||
|
||||
@@ -117,7 +117,7 @@ vi.mock("../oauth-env.js", () => ({
|
||||
isRemoteEnvironment: mocks.isRemoteEnvironment,
|
||||
}));
|
||||
|
||||
vi.mock("../oauth-flow.js", () => ({
|
||||
vi.mock("../../plugins/provider-oauth-flow.js", () => ({
|
||||
createVpsAwareOAuthHandlers: vi.fn(() => ({
|
||||
onAuth: vi.fn(),
|
||||
onPrompt: vi.fn(),
|
||||
@@ -128,7 +128,7 @@ vi.mock("../auth-token.js", () => ({
|
||||
validateAnthropicSetupToken: vi.fn(() => undefined),
|
||||
}));
|
||||
|
||||
vi.mock("../provider-auth-helpers.js", () => {
|
||||
vi.mock("../../plugins/provider-auth-choice-helpers.js", () => {
|
||||
const normalize = (value: string | undefined) => value?.trim().toLowerCase() ?? "";
|
||||
const isRecord = (value: unknown): value is Record<string, unknown> =>
|
||||
Boolean(value && typeof value === "object" && !Array.isArray(value));
|
||||
|
||||
@@ -21,7 +21,14 @@ import { formatCliCommand } from "../../cli/command-format.js";
|
||||
import { parseDurationMs } from "../../cli/parse-duration.js";
|
||||
import { logConfigUpdated } from "../../config/logging.js";
|
||||
import type { OpenClawConfig } from "../../config/types.openclaw.js";
|
||||
import {
|
||||
applyProviderAuthConfigPatch,
|
||||
applyDefaultModel,
|
||||
pickAuthMethod,
|
||||
resolveProviderMatch,
|
||||
} from "../../plugins/provider-auth-choice-helpers.js";
|
||||
import { applyAuthProfileConfig } from "../../plugins/provider-auth-helpers.js";
|
||||
import { createVpsAwareOAuthHandlers } from "../../plugins/provider-oauth-flow.js";
|
||||
import { resolvePluginProviders } from "../../plugins/providers.runtime.js";
|
||||
import type {
|
||||
ProviderAuthMethod,
|
||||
@@ -37,13 +44,6 @@ import { stylePromptHint, stylePromptMessage } from "../../terminal/prompt-style
|
||||
import { createClackPrompter } from "../../wizard/clack-prompter.js";
|
||||
import { validateAnthropicSetupToken } from "../auth-token.js";
|
||||
import { isRemoteEnvironment } from "../oauth-env.js";
|
||||
import { createVpsAwareOAuthHandlers } from "../oauth-flow.js";
|
||||
import {
|
||||
applyProviderAuthConfigPatch,
|
||||
applyDefaultModel,
|
||||
pickAuthMethod,
|
||||
resolveProviderMatch,
|
||||
} from "../provider-auth-helpers.js";
|
||||
import { loadValidConfigOrThrow, resolveKnownAgentId, updateConfig } from "./shared.js";
|
||||
|
||||
function guardCancel<T>(value: T | symbol): T {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { colorize, isRich as isRichTerminal, theme } from "../../terminal/theme.js";
|
||||
import { isRich as isRichTerminal, theme } from "../../terminal/theme.js";
|
||||
export { maskApiKey } from "../../utils/mask-api-key.js";
|
||||
|
||||
export const isRich = (opts?: { json?: boolean; plain?: boolean }) =>
|
||||
@@ -6,19 +6,6 @@ export const isRich = (opts?: { json?: boolean; plain?: boolean }) =>
|
||||
|
||||
export const pad = (value: string, size: number) => value.padEnd(size);
|
||||
|
||||
export const formatKey = (key: string, rich: boolean) => colorize(rich, theme.warn, key);
|
||||
|
||||
export const formatValue = (value: string, rich: boolean) => colorize(rich, theme.info, value);
|
||||
|
||||
export const formatKeyValue = (
|
||||
key: string,
|
||||
value: string,
|
||||
rich: boolean,
|
||||
valueColor: (value: string) => string = theme.info,
|
||||
) => `${formatKey(key, rich)}=${colorize(rich, valueColor, value)}`;
|
||||
|
||||
export const formatSeparator = (rich: boolean) => colorize(rich, theme.muted, " | ");
|
||||
|
||||
export const formatTag = (tag: string, rich: boolean) => {
|
||||
if (!rich) {
|
||||
return tag;
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import {
|
||||
DEFAULT_GATEWAY_DAEMON_RUNTIME,
|
||||
GATEWAY_DAEMON_RUNTIME_OPTIONS,
|
||||
isGatewayDaemonRuntime,
|
||||
type GatewayDaemonRuntime,
|
||||
} from "./daemon-runtime.js";
|
||||
@@ -9,8 +8,6 @@ export type NodeDaemonRuntime = GatewayDaemonRuntime;
|
||||
|
||||
export const DEFAULT_NODE_DAEMON_RUNTIME = DEFAULT_GATEWAY_DAEMON_RUNTIME;
|
||||
|
||||
export const NODE_DAEMON_RUNTIME_OPTIONS = GATEWAY_DAEMON_RUNTIME_OPTIONS;
|
||||
|
||||
export function isNodeDaemonRuntime(value: string | undefined): value is NodeDaemonRuntime {
|
||||
return isGatewayDaemonRuntime(value);
|
||||
}
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
export * from "../plugins/provider-oauth-flow.js";
|
||||
@@ -2,8 +2,6 @@ import { afterEach, describe, expect, it, vi } from "vitest";
|
||||
import type { ensureApiKeyFromEnvOrPrompt } from "../plugins/provider-auth-input.js";
|
||||
import { promptCustomApiConfig } from "./onboard-custom.js";
|
||||
|
||||
const OLLAMA_DEFAULT_BASE_URL_FOR_TEST = "http://127.0.0.1:11434";
|
||||
|
||||
vi.mock("../plugins/provider-auth-input.js", () => ({
|
||||
ensureApiKeyFromEnvOrPrompt: vi.fn(
|
||||
async (params: Parameters<typeof ensureApiKeyFromEnvOrPrompt>[0]) => {
|
||||
@@ -138,7 +136,7 @@ describe("promptCustomApiConfig", () => {
|
||||
});
|
||||
});
|
||||
|
||||
it("defaults custom setup to the native Ollama base URL", async () => {
|
||||
it("does not seed custom setup with a provider-specific base URL", async () => {
|
||||
const prompter = createTestPrompter({
|
||||
text: ["http://localhost:11434", "", "llama3", "custom", ""],
|
||||
select: ["plaintext", "openai"],
|
||||
@@ -150,7 +148,7 @@ describe("promptCustomApiConfig", () => {
|
||||
expect(prompter.text).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
message: "API Base URL",
|
||||
initialValue: OLLAMA_DEFAULT_BASE_URL_FOR_TEST,
|
||||
initialValue: undefined,
|
||||
}),
|
||||
);
|
||||
});
|
||||
|
||||
@@ -2,7 +2,6 @@ import { modelKey } from "../agents/model-selection.js";
|
||||
import type { OpenClawConfig } from "../config/types.openclaw.js";
|
||||
import type { SecretInput } from "../config/types.secrets.js";
|
||||
import { ensureApiKeyFromEnvOrPrompt } from "../plugins/provider-auth-input.js";
|
||||
import { OLLAMA_DEFAULT_BASE_URL } from "../plugins/provider-model-defaults.js";
|
||||
import type { RuntimeEnv } from "../runtime.js";
|
||||
import { fetchWithTimeout } from "../utils/fetch-timeout.js";
|
||||
import { normalizeSecretInput } from "../utils/normalize-secret-input.js";
|
||||
@@ -137,7 +136,7 @@ async function promptBaseUrlAndKey(params: {
|
||||
}): Promise<{ baseUrl: string; apiKey?: SecretInput; resolvedApiKey: string }> {
|
||||
const baseUrlInput = await params.prompter.text({
|
||||
message: "API Base URL",
|
||||
initialValue: params.initialBaseUrl ?? OLLAMA_DEFAULT_BASE_URL,
|
||||
initialValue: params.initialBaseUrl,
|
||||
placeholder: "https://api.example.com/v1",
|
||||
validate: (val) => {
|
||||
return URL.canParse(val) ? undefined : "Please enter a valid URL (e.g. http://...)";
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
export * from "../plugins/provider-auth-choice-helpers.js";
|
||||
@@ -14,20 +14,6 @@ export function formatImageMatch(matches: boolean): string {
|
||||
return matches ? "✓" : "⚠️ mismatch";
|
||||
}
|
||||
|
||||
/**
|
||||
* Type guard and counter utilities
|
||||
*/
|
||||
|
||||
export type ContainerItem = {
|
||||
running: boolean;
|
||||
imageMatch: boolean;
|
||||
containerName: string;
|
||||
sessionKey: string;
|
||||
image: string;
|
||||
createdAtMs: number;
|
||||
lastUsedAtMs: number;
|
||||
};
|
||||
|
||||
export function countRunning(items: readonly { running: boolean }[]): number {
|
||||
return items.filter((item) => item.running).length;
|
||||
}
|
||||
|
||||
@@ -178,5 +178,3 @@ export function summarizeLogTail(rawLines: string[], opts?: { maxLines?: number
|
||||
];
|
||||
return kept;
|
||||
}
|
||||
|
||||
export { pickGatewaySelfPresence } from "../gateway-presence.js";
|
||||
|
||||
@@ -71,15 +71,6 @@ type StatusScanCoreBootstrapParams<TAgentStatus> = {
|
||||
getAgentLocalStatuses: (cfg: OpenClawConfig) => Promise<TAgentStatus>;
|
||||
};
|
||||
|
||||
type StatusScanBootstrapParams<TAgentStatus, TSummary> =
|
||||
StatusScanCoreBootstrapParams<TAgentStatus> & {
|
||||
sourceConfig: OpenClawConfig;
|
||||
getStatusSummary: (params: {
|
||||
config: OpenClawConfig;
|
||||
sourceConfig: OpenClawConfig;
|
||||
}) => Promise<TSummary>;
|
||||
};
|
||||
|
||||
export async function createStatusScanCoreBootstrap<TAgentStatus>(
|
||||
params: StatusScanCoreBootstrapParams<TAgentStatus>,
|
||||
) {
|
||||
@@ -131,27 +122,3 @@ export async function createStatusScanCoreBootstrap<TAgentStatus>(
|
||||
}),
|
||||
};
|
||||
}
|
||||
|
||||
export async function createStatusScanBootstrap<TAgentStatus, TSummary>(
|
||||
params: StatusScanBootstrapParams<TAgentStatus, TSummary>,
|
||||
) {
|
||||
const core = await createStatusScanCoreBootstrap<TAgentStatus>({
|
||||
coldStart: params.coldStart,
|
||||
cfg: params.cfg,
|
||||
hasConfiguredChannels: params.hasConfiguredChannels,
|
||||
opts: params.opts,
|
||||
getTailnetHostname: params.getTailnetHostname,
|
||||
getUpdateCheckResult: params.getUpdateCheckResult,
|
||||
getAgentLocalStatuses: params.getAgentLocalStatuses,
|
||||
});
|
||||
const summaryPromise = core.skipColdStartNetworkChecks
|
||||
? Promise.resolve(buildColdStartStatusSummary() as TSummary)
|
||||
: params.getStatusSummary({
|
||||
config: params.cfg,
|
||||
sourceConfig: params.sourceConfig,
|
||||
});
|
||||
return {
|
||||
...core,
|
||||
summaryPromise,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -6,10 +6,4 @@ export const MANIFEST_KEY = PROJECT_NAME;
|
||||
|
||||
export const LEGACY_MANIFEST_KEYS = LEGACY_PROJECT_NAMES;
|
||||
|
||||
export const LEGACY_PLUGIN_MANIFEST_FILENAMES = [] as const;
|
||||
|
||||
export const LEGACY_CANVAS_HANDLER_NAMES = [] as const;
|
||||
|
||||
export const MACOS_APP_SOURCES_DIR = "apps/macos/Sources/OpenClaw" as const;
|
||||
|
||||
export const LEGACY_MACOS_APP_SOURCES_DIRS = [] as const;
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
import type { AgentAcpBinding, AgentBinding, AgentRouteBinding } from "./types.agents.js";
|
||||
import type { OpenClawConfig } from "./types.openclaw.js";
|
||||
|
||||
export type ConfiguredBindingRule = AgentBinding;
|
||||
|
||||
function normalizeBindingType(binding: AgentBinding): "route" | "acp" {
|
||||
return binding.type === "acp" ? "acp" : "route";
|
||||
}
|
||||
|
||||
@@ -405,7 +405,3 @@ export function applyCompactionDefaults(cfg: OpenClawConfig): OpenClawConfig {
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
export function resetSessionDefaultsWarningForTests() {
|
||||
defaultWarnState = { warned: false };
|
||||
}
|
||||
|
||||
@@ -18,7 +18,6 @@ export type LegacyConfigMigrationSpec = LegacyConfigMigration & {
|
||||
};
|
||||
|
||||
import { isSafeExecutableValue } from "../infra/exec-safety.js";
|
||||
import { normalizeOptionalString } from "../shared/string-coerce.js";
|
||||
import { isRecord } from "../utils.js";
|
||||
import { isBlockedObjectKey } from "./prototype-keys.js";
|
||||
export { isRecord };
|
||||
@@ -89,53 +88,6 @@ export const mapLegacyAudioTranscription = (value: unknown): Record<string, unkn
|
||||
return result;
|
||||
};
|
||||
|
||||
export const getAgentsList = (agents: Record<string, unknown> | null) => {
|
||||
const list = agents?.list;
|
||||
return Array.isArray(list) ? list : [];
|
||||
};
|
||||
|
||||
export const resolveDefaultAgentIdFromRaw = (raw: Record<string, unknown>) => {
|
||||
const agents = getRecord(raw.agents);
|
||||
const list = getAgentsList(agents);
|
||||
const defaultEntry = list.find(
|
||||
(entry): entry is { id: string } =>
|
||||
isRecord(entry) &&
|
||||
entry.default === true &&
|
||||
typeof entry.id === "string" &&
|
||||
normalizeOptionalString(entry.id) !== undefined,
|
||||
);
|
||||
if (defaultEntry) {
|
||||
return normalizeOptionalString(defaultEntry.id) ?? "main";
|
||||
}
|
||||
const routing = getRecord(raw.routing);
|
||||
const routingDefault = normalizeOptionalString(routing?.defaultAgentId) ?? "";
|
||||
if (routingDefault) {
|
||||
return routingDefault;
|
||||
}
|
||||
const firstEntry = list.find(
|
||||
(entry): entry is { id: string } =>
|
||||
isRecord(entry) && normalizeOptionalString(entry.id) !== undefined,
|
||||
);
|
||||
if (firstEntry) {
|
||||
return normalizeOptionalString(firstEntry.id) ?? "main";
|
||||
}
|
||||
return "main";
|
||||
};
|
||||
|
||||
export const ensureAgentEntry = (list: unknown[], id: string): Record<string, unknown> => {
|
||||
const normalized = id.trim();
|
||||
const existing = list.find(
|
||||
(entry): entry is Record<string, unknown> =>
|
||||
isRecord(entry) && typeof entry.id === "string" && entry.id.trim() === normalized,
|
||||
);
|
||||
if (existing) {
|
||||
return existing;
|
||||
}
|
||||
const created: Record<string, unknown> = { id: normalized };
|
||||
list.push(created);
|
||||
return created;
|
||||
};
|
||||
|
||||
export const defineLegacyConfigMigration = (
|
||||
migration: LegacyConfigMigrationSpec,
|
||||
): LegacyConfigMigrationSpec => migration;
|
||||
|
||||
@@ -36,13 +36,3 @@ export function stripShippedPluginInstallConfigRecords(config: unknown): unknown
|
||||
const { plugins: _plugins, ...rest } = config;
|
||||
return plugins === undefined ? rest : { ...rest, plugins };
|
||||
}
|
||||
|
||||
export function prepareShippedPluginInstallConfigMigration(config: unknown): {
|
||||
config: unknown;
|
||||
installRecords: Record<string, PluginInstallRecord>;
|
||||
} {
|
||||
return {
|
||||
config: stripShippedPluginInstallConfigRecords(config),
|
||||
installRecords: extractShippedPluginInstallConfigRecords(config),
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
export type PortRange = { start: number; end: number };
|
||||
type PortRange = { start: number; end: number };
|
||||
|
||||
function isValidPort(port: number): boolean {
|
||||
return Number.isFinite(port) && port > 0 && port <= 65535;
|
||||
@@ -12,26 +12,11 @@ function derivePort(base: number, offset: number, fallback: number): number {
|
||||
return clampPort(base + offset, fallback);
|
||||
}
|
||||
|
||||
export const DEFAULT_BRIDGE_PORT = 18790;
|
||||
export const DEFAULT_BROWSER_CONTROL_PORT = 18791;
|
||||
export const DEFAULT_CANVAS_HOST_PORT = 18793;
|
||||
export const DEFAULT_BROWSER_CDP_PORT_RANGE_START = 18800;
|
||||
export const DEFAULT_BROWSER_CDP_PORT_RANGE_END = 18899;
|
||||
const DEFAULT_BROWSER_CDP_PORT_RANGE_SPAN =
|
||||
DEFAULT_BROWSER_CDP_PORT_RANGE_END - DEFAULT_BROWSER_CDP_PORT_RANGE_START;
|
||||
|
||||
export function deriveDefaultBridgePort(gatewayPort: number): number {
|
||||
return derivePort(gatewayPort, 1, DEFAULT_BRIDGE_PORT);
|
||||
}
|
||||
|
||||
export function deriveDefaultBrowserControlPort(gatewayPort: number): number {
|
||||
return derivePort(gatewayPort, 2, DEFAULT_BROWSER_CONTROL_PORT);
|
||||
}
|
||||
|
||||
export function deriveDefaultCanvasHostPort(gatewayPort: number): number {
|
||||
return derivePort(gatewayPort, 4, DEFAULT_CANVAS_HOST_PORT);
|
||||
}
|
||||
|
||||
export function deriveDefaultBrowserCdpPortRange(browserControlPort: number): PortRange {
|
||||
const start = derivePort(browserControlPort, 9, DEFAULT_BROWSER_CDP_PORT_RANGE_START);
|
||||
const end = start + DEFAULT_BROWSER_CDP_PORT_RANGE_SPAN;
|
||||
|
||||
@@ -1291,17 +1291,6 @@ async function applyStartupCatchupOutcomes(
|
||||
});
|
||||
}
|
||||
|
||||
export async function runDueJobs(state: CronServiceState) {
|
||||
if (!state.store) {
|
||||
return;
|
||||
}
|
||||
const now = state.deps.nowMs();
|
||||
const due = collectRunnableJobs(state, now);
|
||||
for (const job of due) {
|
||||
await executeJob(state, job, now, { forced: false });
|
||||
}
|
||||
}
|
||||
|
||||
export async function executeJobCore(
|
||||
state: CronServiceState,
|
||||
job: CronJob,
|
||||
|
||||
@@ -13,8 +13,6 @@ export type ProviderSetupFlowOption = FlowOption & {
|
||||
onboardingScopes?: ProviderFlowScope[];
|
||||
};
|
||||
|
||||
export type ProviderModelPickerFlowEntry = FlowOption;
|
||||
|
||||
export type ProviderSetupFlowContribution = FlowContribution & {
|
||||
kind: "provider";
|
||||
surface: "setup";
|
||||
|
||||
@@ -304,29 +304,6 @@ export async function createCanvasDocument(
|
||||
return manifest;
|
||||
}
|
||||
|
||||
export async function loadCanvasDocumentManifest(
|
||||
documentId: string,
|
||||
options?: { stateDir?: string; canvasRootDir?: string },
|
||||
): Promise<CanvasDocumentManifest | null> {
|
||||
const id = normalizeCanvasDocumentId(documentId);
|
||||
const manifestPath = path.join(
|
||||
resolveCanvasDocumentDir(id, {
|
||||
stateDir: options?.stateDir,
|
||||
rootDir: options?.canvasRootDir,
|
||||
}),
|
||||
"manifest.json",
|
||||
);
|
||||
try {
|
||||
const raw = await fs.readFile(manifestPath, "utf8");
|
||||
const parsed = JSON.parse(raw);
|
||||
return parsed && typeof parsed === "object" && !Array.isArray(parsed)
|
||||
? (parsed as CanvasDocumentManifest)
|
||||
: null;
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
export function resolveCanvasDocumentAssets(
|
||||
manifest: CanvasDocumentManifest,
|
||||
options?: { baseUrl?: string; stateDir?: string; canvasRootDir?: string },
|
||||
|
||||
@@ -197,24 +197,3 @@ export function abortChatRunById(
|
||||
}
|
||||
return { aborted: true };
|
||||
}
|
||||
|
||||
export function abortChatRunsForSessionKey(
|
||||
ops: ChatAbortOps,
|
||||
params: {
|
||||
sessionKey: string;
|
||||
stopReason?: string;
|
||||
},
|
||||
): { aborted: boolean; runIds: string[] } {
|
||||
const { sessionKey, stopReason } = params;
|
||||
const runIds: string[] = [];
|
||||
for (const [runId, active] of ops.chatAbortControllers) {
|
||||
if (active.sessionKey !== sessionKey) {
|
||||
continue;
|
||||
}
|
||||
const res = abortChatRunById(ops, { runId, sessionKey, stopReason });
|
||||
if (res.aborted) {
|
||||
runIds.push(runId);
|
||||
}
|
||||
}
|
||||
return { aborted: runIds.length > 0, runIds };
|
||||
}
|
||||
|
||||
@@ -323,14 +323,3 @@ export function resolveGatewayProbeCredentialsFromConfig(params: {
|
||||
remoteTokenFallback: "remote-only",
|
||||
});
|
||||
}
|
||||
|
||||
export function resolveGatewayDriftCheckCredentialsFromConfig(params: {
|
||||
cfg: OpenClawConfig;
|
||||
}): ResolvedGatewayCredentials {
|
||||
return resolveGatewayCredentialsFromConfig({
|
||||
cfg: params.cfg,
|
||||
env: {} as NodeJS.ProcessEnv,
|
||||
modeOverride: "local",
|
||||
localTokenPrecedence: "config-first",
|
||||
});
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@ import {
|
||||
pickMatchingExternalInterfaceAddress,
|
||||
readNetworkInterfaces,
|
||||
} from "../infra/network-interfaces.js";
|
||||
import { pickPrimaryTailnetIPv4, pickPrimaryTailnetIPv6 } from "../infra/tailnet.js";
|
||||
import { pickPrimaryTailnetIPv4 } from "../infra/tailnet.js";
|
||||
import {
|
||||
isCanonicalDottedDecimalIPv4,
|
||||
isIpInCidr,
|
||||
@@ -206,31 +206,6 @@ export function resolveRequestClientIp(
|
||||
});
|
||||
}
|
||||
|
||||
export function isLocalGatewayAddress(ip: string | undefined): boolean {
|
||||
if (isLoopbackAddress(ip)) {
|
||||
return true;
|
||||
}
|
||||
if (!ip) {
|
||||
return false;
|
||||
}
|
||||
const normalized = normalizeIp(ip);
|
||||
if (!normalized) {
|
||||
return false;
|
||||
}
|
||||
const tailnetIPv4 = pickPrimaryTailnetIPv4();
|
||||
if (tailnetIPv4 && normalized === normalizeLowercaseStringOrEmpty(tailnetIPv4)) {
|
||||
return true;
|
||||
}
|
||||
const tailnetIPv6 = pickPrimaryTailnetIPv6();
|
||||
if (
|
||||
tailnetIPv6 &&
|
||||
normalizeLowercaseStringOrEmpty(ip) === normalizeLowercaseStringOrEmpty(tailnetIPv6)
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
export {
|
||||
isContainerEnvironment,
|
||||
__resetContainerEnvironmentCacheForTest as __resetContainerCacheForTest,
|
||||
|
||||
@@ -121,11 +121,6 @@ export function canonicalizePathForSecurity(pathname: string): SecurityPathCanon
|
||||
};
|
||||
}
|
||||
|
||||
export function hasSecurityPathCanonicalizationAnomaly(pathname: string): boolean {
|
||||
const canonical = canonicalizePathForSecurity(pathname);
|
||||
return canonical.malformedEncoding || canonical.decodePassLimitReached;
|
||||
}
|
||||
|
||||
const normalizedPrefixesCache = new WeakMap<readonly string[], readonly string[]>();
|
||||
|
||||
function getNormalizedPrefixes(prefixes: readonly string[]): readonly string[] {
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
export {
|
||||
dedupeDreamDiaryEntries,
|
||||
filterRecallEntriesWithinLookback,
|
||||
previewGroundedRemMarkdown,
|
||||
previewRemHarness,
|
||||
removeBackfillDiaryEntries,
|
||||
|
||||
@@ -227,10 +227,6 @@ export type DoctorMemoryRemHarnessErrorPayload = {
|
||||
error: string;
|
||||
};
|
||||
|
||||
export type DoctorMemoryRemHarnessPayload =
|
||||
| DoctorMemoryRemHarnessSuccessPayload
|
||||
| DoctorMemoryRemHarnessErrorPayload;
|
||||
|
||||
function extractIsoDayFromPath(filePath: string): string | null {
|
||||
const match = filePath.replaceAll("\\", "/").match(/(\d{4}-\d{2}-\d{2})\.md$/i);
|
||||
return match?.[1] ?? null;
|
||||
|
||||
@@ -24,9 +24,6 @@ import type { GatewayRequestHandlers } from "./types.js";
|
||||
|
||||
const log = createSubsystemLogger("models-auth-status");
|
||||
|
||||
/** The `ts` sentinel the UI uses to distinguish "never loaded" from "load failed". */
|
||||
export const MODEL_AUTH_STATUS_NEVER_LOADED = 0;
|
||||
|
||||
/**
|
||||
* Models-auth status wire types. Mirrored in ui/src/ui/types.ts via an
|
||||
* `import(...)` re-export — edit here and the UI picks up the change.
|
||||
|
||||
@@ -32,13 +32,6 @@ export async function respondUnavailableOnThrow(respond: RespondFn, fn: () => Pr
|
||||
}
|
||||
}
|
||||
|
||||
export function uniqueSortedStrings(values: unknown[]) {
|
||||
return [...new Set(values.filter((v) => typeof v === "string"))]
|
||||
.map((v) => v.trim())
|
||||
.filter(Boolean)
|
||||
.toSorted();
|
||||
}
|
||||
|
||||
export function respondUnavailableOnNodeInvokeError<T extends { ok: boolean; error?: unknown }>(
|
||||
respond: RespondFn,
|
||||
res: T,
|
||||
|
||||
@@ -7,7 +7,6 @@ import { createSubsystemLogger } from "../logging/subsystem.js";
|
||||
import { isPathInsideWithRealpath } from "../security/scan-paths.js";
|
||||
import { CONFIG_DIR, resolveUserPath } from "../utils.js";
|
||||
import { resolveBundledHooksDir } from "./bundled-dir.js";
|
||||
import { shouldIncludeHook } from "./config.js";
|
||||
import {
|
||||
parseFrontmatter,
|
||||
resolveHookInvocationPolicy,
|
||||
@@ -15,14 +14,7 @@ import {
|
||||
} from "./frontmatter.js";
|
||||
import { resolvePluginHookDirs } from "./plugin-hooks.js";
|
||||
import { resolveHookEntries } from "./policy.js";
|
||||
import type {
|
||||
Hook,
|
||||
HookEligibilityContext,
|
||||
HookEntry,
|
||||
HookSnapshot,
|
||||
HookSource,
|
||||
ParsedHookFrontmatter,
|
||||
} from "./types.js";
|
||||
import type { Hook, HookEntry, HookSource, ParsedHookFrontmatter } from "./types.js";
|
||||
|
||||
type HookPackageManifest = {
|
||||
name?: string;
|
||||
@@ -34,14 +26,6 @@ type LoadedHook = {
|
||||
frontmatter: ParsedHookFrontmatter;
|
||||
};
|
||||
|
||||
function filterHookEntries(
|
||||
entries: HookEntry[],
|
||||
config?: OpenClawConfig,
|
||||
eligibility?: HookEligibilityContext,
|
||||
): HookEntry[] {
|
||||
return entries.filter((entry) => shouldIncludeHook({ entry, config, eligibility }));
|
||||
}
|
||||
|
||||
function readHookPackageManifest(dir: string): HookPackageManifest | null {
|
||||
const manifestPath = path.join(dir, "package.json");
|
||||
const raw = readBoundaryFileUtf8({
|
||||
@@ -291,30 +275,6 @@ export function discoverWorkspaceHookEntries(
|
||||
return [...extraHooks, ...bundledHooks, ...pluginHooks, ...managedHooks, ...workspaceHooks];
|
||||
}
|
||||
|
||||
export function buildWorkspaceHookSnapshot(
|
||||
workspaceDir: string,
|
||||
opts?: {
|
||||
config?: OpenClawConfig;
|
||||
managedHooksDir?: string;
|
||||
bundledHooksDir?: string;
|
||||
entries?: HookEntry[];
|
||||
eligibility?: HookEligibilityContext;
|
||||
snapshotVersion?: number;
|
||||
},
|
||||
): HookSnapshot {
|
||||
const hookEntries = opts?.entries ?? loadWorkspaceHookEntries(workspaceDir, opts);
|
||||
const eligible = filterHookEntries(hookEntries, opts?.config, opts?.eligibility);
|
||||
|
||||
return {
|
||||
hooks: eligible.map((entry) => ({
|
||||
name: entry.hook.name,
|
||||
events: entry.metadata?.events ?? [],
|
||||
})),
|
||||
resolvedHooks: eligible.map((entry) => entry.hook),
|
||||
version: opts?.snapshotVersion,
|
||||
};
|
||||
}
|
||||
|
||||
export function loadWorkspaceHookEntries(
|
||||
workspaceDir: string,
|
||||
opts?: {
|
||||
|
||||
@@ -230,13 +230,6 @@ export function runWithDiagnosticTraceContext<T>(
|
||||
return getDiagnosticTraceScopeState().storage.run(freezeDiagnosticTraceContext(trace), callback);
|
||||
}
|
||||
|
||||
export function runWithNewDiagnosticTraceContext<T>(
|
||||
input: DiagnosticTraceContextInput,
|
||||
callback: () => T,
|
||||
): T {
|
||||
return runWithDiagnosticTraceContext(createDiagnosticTraceContext(input), callback);
|
||||
}
|
||||
|
||||
export function resetDiagnosticTraceContextForTest(): void {
|
||||
getDiagnosticTraceScopeState().storage.disable();
|
||||
}
|
||||
|
||||
@@ -167,23 +167,6 @@ function readDotEnvFile(params: {
|
||||
return { filePath: params.filePath, entries };
|
||||
}
|
||||
|
||||
export function loadRuntimeDotEnvFile(filePath: string, opts?: { quiet?: boolean }) {
|
||||
const parsed = readDotEnvFile({
|
||||
filePath,
|
||||
shouldBlockKey: shouldBlockRuntimeDotEnvKey,
|
||||
quiet: opts?.quiet ?? true,
|
||||
});
|
||||
if (!parsed) {
|
||||
return;
|
||||
}
|
||||
for (const { key, value } of parsed.entries) {
|
||||
if (process.env[key] !== undefined) {
|
||||
continue;
|
||||
}
|
||||
process.env[key] = value;
|
||||
}
|
||||
}
|
||||
|
||||
export function loadWorkspaceDotEnvFile(filePath: string, opts?: { quiet?: boolean }) {
|
||||
const parsed = readDotEnvFile({
|
||||
filePath,
|
||||
|
||||
@@ -791,13 +791,3 @@ export function createExecApprovalForwarder(
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
export function shouldForwardExecApproval(params: {
|
||||
config?: ExecApprovalForwardingConfig;
|
||||
request: ExecApprovalRequest;
|
||||
}): boolean {
|
||||
return shouldForwardRoute({
|
||||
config: params.config,
|
||||
routeRequest: execApprovalStrategy.getRouteRequestFromRequest(params.request),
|
||||
});
|
||||
}
|
||||
|
||||
@@ -179,18 +179,6 @@ export async function getTailscaleBinary(): Promise<string> {
|
||||
return cachedTailscaleBinary ?? "tailscale";
|
||||
}
|
||||
|
||||
export async function readTailscaleStatusJson(
|
||||
exec: typeof runExec = runExec,
|
||||
opts?: { timeoutMs?: number },
|
||||
): Promise<Record<string, unknown>> {
|
||||
const tailscaleBin = await getTailscaleBinary();
|
||||
const { stdout } = await exec(tailscaleBin, ["status", "--json"], {
|
||||
timeoutMs: opts?.timeoutMs ?? 5000,
|
||||
maxBuffer: 400_000,
|
||||
});
|
||||
return stdout ? parsePossiblyNoisyJsonObject(stdout) : {};
|
||||
}
|
||||
|
||||
export async function ensureGoInstalled(
|
||||
exec: typeof runExec = runExec,
|
||||
prompt: typeof promptYesNo = promptYesNo,
|
||||
|
||||
@@ -103,12 +103,6 @@ export type DiagnosticStabilitySnapshot = {
|
||||
};
|
||||
};
|
||||
|
||||
export type DiagnosticStabilityQuery = {
|
||||
limit?: number;
|
||||
type?: string;
|
||||
sinceSeq?: number;
|
||||
};
|
||||
|
||||
export type DiagnosticStabilityQueryInput = {
|
||||
limit?: unknown;
|
||||
type?: unknown;
|
||||
|
||||
@@ -98,23 +98,6 @@ export function writeSupportBundleFile(outputDir: string, file: DiagnosticSuppor
|
||||
});
|
||||
}
|
||||
|
||||
export function copySupportBundleFile(params: {
|
||||
outputDir: string;
|
||||
sourceFile: string;
|
||||
path: string;
|
||||
}): DiagnosticSupportBundleContent {
|
||||
const outputPath = resolveSupportBundleFilePath(params.outputDir, params.path);
|
||||
fs.mkdirSync(path.dirname(outputPath), { recursive: true, mode: 0o700 });
|
||||
fs.copyFileSync(params.sourceFile, outputPath, fs.constants.COPYFILE_EXCL);
|
||||
fs.chmodSync(outputPath, 0o600);
|
||||
const stat = fs.statSync(outputPath);
|
||||
return {
|
||||
path: assertSafeBundleRelativePath(params.path),
|
||||
mediaType: "application/x-ndjson",
|
||||
bytes: stat.size,
|
||||
};
|
||||
}
|
||||
|
||||
export function writeSupportBundleDirectory(params: {
|
||||
outputDir: string;
|
||||
files: readonly DiagnosticSupportBundleFile[];
|
||||
|
||||
@@ -65,13 +65,6 @@ export function resolveMaxBytes(params: {
|
||||
return DEFAULT_MAX_BYTES[params.capability];
|
||||
}
|
||||
|
||||
export function resolveCapabilityConfig(
|
||||
cfg: OpenClawConfig,
|
||||
capability: MediaUnderstandingCapability,
|
||||
): MediaUnderstandingConfig | undefined {
|
||||
return cfg.tools?.media?.[capability];
|
||||
}
|
||||
|
||||
export function resolveScopeDecision(params: {
|
||||
scope?: MediaUnderstandingScopeConfig;
|
||||
ctx: MsgContext;
|
||||
|
||||
@@ -47,8 +47,6 @@ export type MediaUnderstandingModelDecision = {
|
||||
reason?: string;
|
||||
};
|
||||
|
||||
export type MediaUnderstandingAttemptOutcome = MediaUnderstandingModelDecision["outcome"];
|
||||
|
||||
export type MediaUnderstandingAttachmentDecision = {
|
||||
attachmentIndex: number;
|
||||
attempts: MediaUnderstandingModelDecision[];
|
||||
|
||||
@@ -248,7 +248,6 @@ async function sendSystemRunCompleted(
|
||||
});
|
||||
}
|
||||
|
||||
export { formatSystemRunAllowlistMissMessage } from "./exec-policy.js";
|
||||
export { buildSystemRunApprovalPlan } from "./invoke-system-run-plan.js";
|
||||
|
||||
async function parseSystemRunPhase(
|
||||
|
||||
@@ -3,7 +3,6 @@ import {
|
||||
clearAllowFromFileReadCacheForNamespace,
|
||||
dedupePreserveOrder,
|
||||
readAllowFromFileSyncWithExists,
|
||||
readAllowFromFileWithExists,
|
||||
resolveAllowFromAccountId,
|
||||
resolveAllowFromFilePath,
|
||||
shouldIncludeLegacyAllowFromEntries,
|
||||
@@ -20,16 +19,6 @@ function normalizeRawAllowFromList(store: AllowFromStore): string[] {
|
||||
);
|
||||
}
|
||||
|
||||
async function readAllowFromEntriesForPathWithExists(
|
||||
filePath: string,
|
||||
): Promise<{ entries: string[]; exists: boolean }> {
|
||||
return await readAllowFromFileWithExists({
|
||||
cacheNamespace: ALLOW_FROM_STORE_READ_CACHE_NAMESPACE,
|
||||
filePath,
|
||||
normalizeStore: normalizeRawAllowFromList,
|
||||
});
|
||||
}
|
||||
|
||||
function readAllowFromEntriesForPathSyncWithExists(filePath: string): {
|
||||
entries: string[];
|
||||
exists: boolean;
|
||||
@@ -49,45 +38,6 @@ export function resolveChannelAllowFromPath(
|
||||
return resolveAllowFromFilePath(channel, env, accountId);
|
||||
}
|
||||
|
||||
export async function readLegacyChannelAllowFromStoreEntries(
|
||||
channel: PairingChannel,
|
||||
env: NodeJS.ProcessEnv = process.env,
|
||||
): Promise<string[]> {
|
||||
const filePath = resolveAllowFromFilePath(channel, env);
|
||||
return (await readAllowFromEntriesForPathWithExists(filePath)).entries;
|
||||
}
|
||||
|
||||
export async function readChannelAllowFromStoreEntries(
|
||||
channel: PairingChannel,
|
||||
env: NodeJS.ProcessEnv = process.env,
|
||||
accountId?: string,
|
||||
): Promise<string[]> {
|
||||
const resolvedAccountId = resolveAllowFromAccountId(accountId);
|
||||
if (!shouldIncludeLegacyAllowFromEntries(resolvedAccountId)) {
|
||||
return (
|
||||
await readAllowFromEntriesForPathWithExists(
|
||||
resolveAllowFromFilePath(channel, env, resolvedAccountId),
|
||||
)
|
||||
).entries;
|
||||
}
|
||||
const scopedEntries = (
|
||||
await readAllowFromEntriesForPathWithExists(
|
||||
resolveAllowFromFilePath(channel, env, resolvedAccountId),
|
||||
)
|
||||
).entries;
|
||||
const legacyEntries = (
|
||||
await readAllowFromEntriesForPathWithExists(resolveAllowFromFilePath(channel, env))
|
||||
).entries;
|
||||
return dedupePreserveOrder([...scopedEntries, ...legacyEntries]);
|
||||
}
|
||||
|
||||
export function readLegacyChannelAllowFromStoreEntriesSync(
|
||||
channel: PairingChannel,
|
||||
env: NodeJS.ProcessEnv = process.env,
|
||||
): string[] {
|
||||
return readAllowFromEntriesForPathSyncWithExists(resolveAllowFromFilePath(channel, env)).entries;
|
||||
}
|
||||
|
||||
export function readChannelAllowFromStoreEntriesSync(
|
||||
channel: PairingChannel,
|
||||
env: NodeJS.ProcessEnv = process.env,
|
||||
|
||||
@@ -33,7 +33,7 @@ export { parseImageGenerationModelRef } from "../image-generation/model-ref.js";
|
||||
export { createSubsystemLogger } from "../logging/subsystem.js";
|
||||
export { normalizeGooglePreviewModelId as normalizeGoogleModelId } from "./provider-model-shared.js";
|
||||
export { getProviderEnvVars } from "../secrets/provider-env-vars.js";
|
||||
export { OPENAI_DEFAULT_IMAGE_MODEL } from "../plugins/provider-model-defaults.js";
|
||||
export const OPENAI_DEFAULT_IMAGE_MODEL = "gpt-image-2";
|
||||
|
||||
type ImageGenerationCoreAuthRuntimeModule =
|
||||
typeof import("./image-generation-core.auth.runtime.js");
|
||||
|
||||
@@ -39,7 +39,6 @@ export type {
|
||||
ProviderEndpointResolution,
|
||||
} from "../agents/provider-attribution.js";
|
||||
export type { ProviderPlugin } from "../plugins/types.js";
|
||||
export type { KilocodeModelCatalogEntry } from "../plugins/provider-model-kilocode.js";
|
||||
|
||||
export { DEFAULT_CONTEXT_TOKENS } from "../agents/defaults.js";
|
||||
export {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
export type BundledRuntimeDepsInstallActivity = {
|
||||
type BundledRuntimeDepsInstallActivity = {
|
||||
id: number;
|
||||
installRoot: string;
|
||||
missingSpecs: string[];
|
||||
@@ -54,10 +54,6 @@ export function getActiveBundledRuntimeDepsInstallCount(): number {
|
||||
return activeInstalls.size;
|
||||
}
|
||||
|
||||
export function listActiveBundledRuntimeDepsInstalls(): BundledRuntimeDepsInstallActivity[] {
|
||||
return [...activeInstalls.values()].toSorted((left, right) => left.id - right.id);
|
||||
}
|
||||
|
||||
export async function waitForBundledRuntimeDepsInstallIdle(
|
||||
timeoutMs?: number,
|
||||
): Promise<{ drained: boolean; active: number }> {
|
||||
|
||||
@@ -3,13 +3,6 @@ type EnableStateLike = {
|
||||
reason?: string;
|
||||
};
|
||||
|
||||
type EnableStateParamsLike = {
|
||||
id: string;
|
||||
origin: string;
|
||||
config: unknown;
|
||||
enabledByDefault?: boolean;
|
||||
};
|
||||
|
||||
type PluginKindLike = string | readonly string[] | undefined;
|
||||
|
||||
export type PluginActivationSource = "disabled" | "explicit" | "auto" | "default";
|
||||
@@ -315,13 +308,6 @@ export function resolveEnableStateResult<TParams>(
|
||||
return toEnableStateResult(resolveState(params));
|
||||
}
|
||||
|
||||
export function resolveEnableStateShared<TParams extends EnableStateParamsLike>(
|
||||
params: TParams,
|
||||
resolveState: (params: TParams) => EnableStateLike,
|
||||
): { enabled: boolean; reason?: string } {
|
||||
return resolveEnableStateResult(params, resolveState);
|
||||
}
|
||||
|
||||
export function createPluginEnableStateResolver<TConfig, TOrigin extends string>(
|
||||
resolveState: (params: {
|
||||
id: string;
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
import type { OpenClawConfig } from "../config/types.openclaw.js";
|
||||
import {
|
||||
createEffectiveEnableStateResolver,
|
||||
createPluginEnableStateResolver,
|
||||
resolveMemorySlotDecisionShared,
|
||||
resolvePluginActivationDecisionShared,
|
||||
toPluginActivationState,
|
||||
@@ -54,11 +52,6 @@ export function resolvePluginActivationState(params: {
|
||||
}
|
||||
export const hasExplicitPluginConfig = hasExplicitPluginConfigShared;
|
||||
|
||||
export const resolveEnableState = createPluginEnableStateResolver<
|
||||
NormalizedPluginsConfig,
|
||||
PluginOrigin
|
||||
>(resolvePluginActivationState);
|
||||
|
||||
export const isBundledChannelEnabledByChannelConfig = isBundledChannelEnabledByChannelConfigShared;
|
||||
|
||||
type PolicyEffectiveActivationParams = {
|
||||
@@ -72,11 +65,6 @@ type PolicyEffectiveActivationParams = {
|
||||
autoEnabledReason?: string;
|
||||
};
|
||||
|
||||
export const resolveEffectiveEnableState =
|
||||
createEffectiveEnableStateResolver<PolicyEffectiveActivationParams>(
|
||||
resolveEffectivePluginActivationState,
|
||||
);
|
||||
|
||||
export function resolveEffectivePluginActivationState(
|
||||
params: PolicyEffectiveActivationParams,
|
||||
): PluginActivationState {
|
||||
|
||||
@@ -2,10 +2,7 @@ import type {
|
||||
DocumentExtractorPlugin,
|
||||
PluginDocumentExtractorEntry,
|
||||
} from "./document-extractor-types.js";
|
||||
import {
|
||||
loadBundledPluginPublicArtifactModuleSync,
|
||||
resolveBundledPluginPublicArtifactPath,
|
||||
} from "./public-surface-loader.js";
|
||||
import { loadBundledPluginPublicArtifactModuleSync } from "./public-surface-loader.js";
|
||||
|
||||
const DOCUMENT_EXTRACTOR_ARTIFACT_CANDIDATES = [
|
||||
"document-extractor.js",
|
||||
@@ -100,9 +97,3 @@ export function loadBundledDocumentExtractorEntriesFromDir(params: {
|
||||
}
|
||||
return extractors.map((extractor) => Object.assign({}, extractor, { pluginId: params.pluginId }));
|
||||
}
|
||||
|
||||
export function hasBundledDocumentExtractorPublicArtifact(pluginId: string): boolean {
|
||||
return DOCUMENT_EXTRACTOR_ARTIFACT_CANDIDATES.some((artifactBasename) =>
|
||||
Boolean(resolveBundledPluginPublicArtifactPath({ dirName: pluginId, artifactBasename })),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -23,7 +23,6 @@ import {
|
||||
type RefreshInstalledPluginIndexParams,
|
||||
} from "./installed-plugin-index.js";
|
||||
export {
|
||||
INSTALLED_PLUGIN_INDEX_STORE_PATH,
|
||||
resolveInstalledPluginIndexStorePath,
|
||||
type InstalledPluginIndexStoreOptions,
|
||||
} from "./installed-plugin-index-store-path.js";
|
||||
|
||||
@@ -1,75 +0,0 @@
|
||||
import type { OpenClawConfig } from "../config/types.openclaw.js";
|
||||
export {
|
||||
applyOpencodeZenModelDefault,
|
||||
OPENCODE_ZEN_DEFAULT_MODEL,
|
||||
} from "../plugin-sdk/opencode.js";
|
||||
import { ensureModelAllowlistEntry } from "./provider-model-allowlist.js";
|
||||
import { applyAgentDefaultPrimaryModel } from "./provider-model-primary.js";
|
||||
|
||||
export const OPENAI_DEFAULT_MODEL = "openai/gpt-5.5";
|
||||
export const OPENAI_CODEX_DEFAULT_MODEL = "openai-codex/gpt-5.5";
|
||||
export const OPENAI_DEFAULT_IMAGE_MODEL = "gpt-image-2";
|
||||
export const OPENAI_DEFAULT_TTS_MODEL = "gpt-4o-mini-tts";
|
||||
export const OPENAI_DEFAULT_TTS_VOICE = "alloy";
|
||||
export const OPENAI_DEFAULT_AUDIO_TRANSCRIPTION_MODEL = "gpt-4o-transcribe";
|
||||
export const OPENAI_DEFAULT_EMBEDDING_MODEL = "text-embedding-3-small";
|
||||
export const GOOGLE_GEMINI_DEFAULT_MODEL = "google/gemini-3.1-pro-preview";
|
||||
export const OLLAMA_DEFAULT_BASE_URL = "http://127.0.0.1:11434";
|
||||
export const OPENCODE_GO_DEFAULT_MODEL_REF = "opencode-go/kimi-k2.6";
|
||||
|
||||
export function applyGoogleGeminiModelDefault(cfg: OpenClawConfig): {
|
||||
next: OpenClawConfig;
|
||||
changed: boolean;
|
||||
} {
|
||||
return applyAgentDefaultPrimaryModel({ cfg, model: GOOGLE_GEMINI_DEFAULT_MODEL });
|
||||
}
|
||||
|
||||
export function applyOpenAIProviderConfig(cfg: OpenClawConfig): OpenClawConfig {
|
||||
const next = ensureModelAllowlistEntry({
|
||||
cfg,
|
||||
modelRef: OPENAI_DEFAULT_MODEL,
|
||||
});
|
||||
const models = { ...next.agents?.defaults?.models };
|
||||
models[OPENAI_DEFAULT_MODEL] = {
|
||||
...models[OPENAI_DEFAULT_MODEL],
|
||||
alias: models[OPENAI_DEFAULT_MODEL]?.alias ?? "GPT",
|
||||
};
|
||||
|
||||
return {
|
||||
...next,
|
||||
agents: {
|
||||
...next.agents,
|
||||
defaults: {
|
||||
...next.agents?.defaults,
|
||||
models,
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
export function applyOpenAIConfig(cfg: OpenClawConfig): OpenClawConfig {
|
||||
const next = applyOpenAIProviderConfig(cfg);
|
||||
return {
|
||||
...next,
|
||||
agents: {
|
||||
...next.agents,
|
||||
defaults: {
|
||||
...next.agents?.defaults,
|
||||
model:
|
||||
next.agents?.defaults?.model && typeof next.agents.defaults.model === "object"
|
||||
? {
|
||||
...next.agents.defaults.model,
|
||||
primary: OPENAI_DEFAULT_MODEL,
|
||||
}
|
||||
: { primary: OPENAI_DEFAULT_MODEL },
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
export function applyOpencodeGoModelDefault(cfg: OpenClawConfig): {
|
||||
next: OpenClawConfig;
|
||||
changed: boolean;
|
||||
} {
|
||||
return applyAgentDefaultPrimaryModel({ cfg, model: OPENCODE_GO_DEFAULT_MODEL_REF });
|
||||
}
|
||||
@@ -1,37 +0,0 @@
|
||||
export const KILOCODE_BASE_URL = "https://api.kilo.ai/api/gateway/";
|
||||
export const KILOCODE_DEFAULT_MODEL_ID = "kilo/auto";
|
||||
export const KILOCODE_DEFAULT_MODEL_REF = `kilocode/${KILOCODE_DEFAULT_MODEL_ID}`;
|
||||
export const KILOCODE_DEFAULT_MODEL_NAME = "Kilo Auto";
|
||||
|
||||
export type KilocodeModelCatalogEntry = {
|
||||
id: string;
|
||||
name: string;
|
||||
reasoning: boolean;
|
||||
input: Array<"text" | "image">;
|
||||
contextWindow?: number;
|
||||
maxTokens?: number;
|
||||
};
|
||||
|
||||
/**
|
||||
* Static fallback catalog used by synchronous config surfaces and as the
|
||||
* discovery fallback when the gateway model endpoint is unavailable.
|
||||
*/
|
||||
export const KILOCODE_MODEL_CATALOG: KilocodeModelCatalogEntry[] = [
|
||||
{
|
||||
id: KILOCODE_DEFAULT_MODEL_ID,
|
||||
name: KILOCODE_DEFAULT_MODEL_NAME,
|
||||
reasoning: true,
|
||||
input: ["text", "image"],
|
||||
contextWindow: 1000000,
|
||||
maxTokens: 128000,
|
||||
},
|
||||
];
|
||||
|
||||
export const KILOCODE_DEFAULT_CONTEXT_WINDOW = 1000000;
|
||||
export const KILOCODE_DEFAULT_MAX_TOKENS = 128000;
|
||||
export const KILOCODE_DEFAULT_COST = {
|
||||
input: 0,
|
||||
output: 0,
|
||||
cacheRead: 0,
|
||||
cacheWrite: 0,
|
||||
} as const;
|
||||
@@ -11,13 +11,6 @@ type PluginRuntimeRecord = {
|
||||
source: string;
|
||||
};
|
||||
|
||||
type CachedPluginBoundaryLoaderParams = {
|
||||
pluginId: string;
|
||||
entryBaseName: string;
|
||||
required?: boolean;
|
||||
missingLabel?: string;
|
||||
};
|
||||
|
||||
export function readPluginBoundaryConfigSafely() {
|
||||
try {
|
||||
return getRuntimeConfig();
|
||||
@@ -130,48 +123,3 @@ export function loadPluginBoundaryModuleWithJiti<TModule>(
|
||||
): TModule {
|
||||
return getPluginBoundaryJiti(modulePath, loaders)(modulePath) as TModule;
|
||||
}
|
||||
|
||||
// oxlint-disable-next-line typescript/no-unnecessary-type-parameters -- Dynamic plugin boundary loaders use caller-supplied module types.
|
||||
export function createCachedPluginBoundaryModuleLoader<TModule>(
|
||||
params: CachedPluginBoundaryLoaderParams,
|
||||
): () => TModule | null {
|
||||
let cachedModulePath: string | null = null;
|
||||
let cachedModule: TModule | null = null;
|
||||
const loaders: PluginJitiLoaderCache = new Map();
|
||||
|
||||
return () => {
|
||||
const missingLabel = params.missingLabel ?? `${params.pluginId} plugin runtime`;
|
||||
const record = resolvePluginRuntimeRecord(
|
||||
params.pluginId,
|
||||
params.required
|
||||
? () => {
|
||||
throw new Error(`${missingLabel} is unavailable: missing plugin '${params.pluginId}'`);
|
||||
}
|
||||
: undefined,
|
||||
);
|
||||
if (!record) {
|
||||
return null;
|
||||
}
|
||||
const modulePath = resolvePluginRuntimeModulePath(
|
||||
record,
|
||||
params.entryBaseName,
|
||||
params.required
|
||||
? () => {
|
||||
throw new Error(
|
||||
`${missingLabel} is unavailable: missing ${params.entryBaseName} for plugin '${params.pluginId}'`,
|
||||
);
|
||||
}
|
||||
: undefined,
|
||||
);
|
||||
if (!modulePath) {
|
||||
return null;
|
||||
}
|
||||
if (cachedModule && cachedModulePath === modulePath) {
|
||||
return cachedModule;
|
||||
}
|
||||
const loaded = loadPluginBoundaryModuleWithJiti<TModule>(modulePath, loaders);
|
||||
cachedModulePath = modulePath;
|
||||
cachedModule = loaded;
|
||||
return loaded;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,6 +1,2 @@
|
||||
export {
|
||||
openUrl,
|
||||
resolveBrowserOpenCommand,
|
||||
type BrowserOpenCommand,
|
||||
} from "../infra/browser-open.js";
|
||||
export { openUrl } from "../infra/browser-open.js";
|
||||
export { isRemoteEnvironment } from "../infra/remote-env.js";
|
||||
|
||||
@@ -35,17 +35,6 @@ export function hasKind(kind: PluginKind | PluginKind[] | undefined, target: Plu
|
||||
return Array.isArray(kind) ? kind.includes(target) : kind === target;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the slot key for a single-kind plugin.
|
||||
* For multi-kind plugins use `slotKeysForPluginKind` instead.
|
||||
*/
|
||||
export function slotKeyForPluginKind(kind?: PluginKind): PluginSlotKey | null {
|
||||
if (!kind) {
|
||||
return null;
|
||||
}
|
||||
return SLOT_BY_KIND[kind] ?? null;
|
||||
}
|
||||
|
||||
/** Order-insensitive equality check for two kind values (string or array). */
|
||||
export function kindsEqual(
|
||||
a: PluginKind | PluginKind[] | undefined,
|
||||
|
||||
@@ -1,7 +1,4 @@
|
||||
import {
|
||||
loadBundledPluginPublicArtifactModuleSync,
|
||||
resolveBundledPluginPublicArtifactPath,
|
||||
} from "./public-surface-loader.js";
|
||||
import { loadBundledPluginPublicArtifactModuleSync } from "./public-surface-loader.js";
|
||||
import type {
|
||||
PluginWebContentExtractorEntry,
|
||||
WebContentExtractorPlugin,
|
||||
@@ -83,9 +80,3 @@ export function loadBundledWebContentExtractorEntriesFromDir(params: {
|
||||
}
|
||||
return extractors.map((extractor) => Object.assign({}, extractor, { pluginId: params.pluginId }));
|
||||
}
|
||||
|
||||
export function hasBundledWebContentExtractorPublicArtifact(pluginId: string): boolean {
|
||||
return WEB_CONTENT_EXTRACTOR_ARTIFACT_CANDIDATES.some((artifactBasename) =>
|
||||
Boolean(resolveBundledPluginPublicArtifactPath({ dirName: pluginId, artifactBasename })),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -31,28 +31,6 @@ export function resolveCommandStdio(params: {
|
||||
return [stdin, "pipe", "pipe"];
|
||||
}
|
||||
|
||||
export function formatSpawnError(err: unknown): string {
|
||||
if (!(err instanceof Error)) {
|
||||
return String(err);
|
||||
}
|
||||
const details = err as NodeJS.ErrnoException;
|
||||
const parts: string[] = [];
|
||||
const message = err.message?.trim();
|
||||
if (message) {
|
||||
parts.push(message);
|
||||
}
|
||||
if (details.code && !message?.includes(details.code)) {
|
||||
parts.push(details.code);
|
||||
}
|
||||
if (details.syscall) {
|
||||
parts.push(`syscall=${details.syscall}`);
|
||||
}
|
||||
if (typeof details.errno === "number") {
|
||||
parts.push(`errno=${details.errno}`);
|
||||
}
|
||||
return parts.join(" ");
|
||||
}
|
||||
|
||||
function shouldRetry(err: unknown, codes: string[]): boolean {
|
||||
const code =
|
||||
err && typeof err === "object" && "code" in err ? String((err as { code?: unknown }).code) : "";
|
||||
|
||||
@@ -66,7 +66,7 @@ export type ResolvedAgentRoute = {
|
||||
| "default";
|
||||
};
|
||||
|
||||
export { DEFAULT_ACCOUNT_ID, DEFAULT_AGENT_ID } from "./session-key.js";
|
||||
export { DEFAULT_ACCOUNT_ID } from "./session-key.js";
|
||||
|
||||
export function deriveLastRoutePolicy(params: {
|
||||
sessionKey: string;
|
||||
|
||||
@@ -34,7 +34,3 @@ export function listAuthProfileStorePaths(config: OpenClawConfig, stateDir: stri
|
||||
|
||||
return [...paths];
|
||||
}
|
||||
|
||||
export function collectAuthStorePaths(config: OpenClawConfig, stateDir: string): string[] {
|
||||
return listAuthProfileStorePaths(config, stateDir);
|
||||
}
|
||||
|
||||
@@ -65,34 +65,3 @@ export function readJsonPointer(
|
||||
}
|
||||
return current;
|
||||
}
|
||||
|
||||
export function setJsonPointer(
|
||||
root: Record<string, unknown>,
|
||||
pointer: string,
|
||||
value: unknown,
|
||||
): void {
|
||||
if (!pointer.startsWith("/")) {
|
||||
throw new Error(`Invalid JSON pointer "${pointer}".`);
|
||||
}
|
||||
|
||||
const tokens = pointer
|
||||
.slice(1)
|
||||
.split("/")
|
||||
.map((token) => decodeJsonPointerToken(token));
|
||||
|
||||
let current: Record<string, unknown> = root;
|
||||
for (let index = 0; index < tokens.length; index += 1) {
|
||||
const token = tokens[index];
|
||||
const isLast = index === tokens.length - 1;
|
||||
if (isLast) {
|
||||
current[token] = value;
|
||||
return;
|
||||
}
|
||||
const child = current[token];
|
||||
const next: Record<string, unknown> = isJsonObject(child) ? child : {};
|
||||
if (next !== child) {
|
||||
current[token] = next;
|
||||
}
|
||||
current = next;
|
||||
}
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user