mirror of
https://github.com/openclaw/openclaw.git
synced 2026-04-17 12:11:20 +00:00
refactor: dedupe telemetry string readers
This commit is contained in:
@@ -11,6 +11,7 @@ import {
|
||||
parseAgentSessionKey,
|
||||
resolveAgentIdFromSessionKey,
|
||||
} from "../routing/session-key.js";
|
||||
import { readStringValue } from "../shared/string-coerce.js";
|
||||
import { resolveUserPath } from "../utils.js";
|
||||
import { resolveEffectiveAgentSkillFilter } from "./skills/agent-filter.js";
|
||||
import { resolveDefaultAgentWorkspaceDir } from "./workspace.js";
|
||||
@@ -137,9 +138,9 @@ export function resolveAgentConfig(
|
||||
}
|
||||
const agentDefaults = cfg.agents?.defaults;
|
||||
return {
|
||||
name: typeof entry.name === "string" ? entry.name : undefined,
|
||||
workspace: typeof entry.workspace === "string" ? entry.workspace : undefined,
|
||||
agentDir: typeof entry.agentDir === "string" ? entry.agentDir : undefined,
|
||||
name: readStringValue(entry.name),
|
||||
workspace: readStringValue(entry.workspace),
|
||||
agentDir: readStringValue(entry.agentDir),
|
||||
model:
|
||||
typeof entry.model === "string" || (entry.model && typeof entry.model === "object")
|
||||
? entry.model
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import type { AgentMessage } from "@mariozechner/pi-agent-core";
|
||||
import { readStringValue } from "../shared/string-coerce.js";
|
||||
import { extractToolCallsFromAssistant, extractToolResultId } from "./tool-call-id.js";
|
||||
|
||||
const TOOL_CALL_NAME_MAX_CHARS = 64;
|
||||
@@ -96,7 +97,7 @@ function redactSessionsSpawnAttachmentsArgs(value: unknown): unknown {
|
||||
}
|
||||
|
||||
function sanitizeToolCallBlock(block: RawToolCallBlock): RawToolCallBlock {
|
||||
const rawName = typeof block.name === "string" ? block.name : undefined;
|
||||
const rawName = readStringValue(block.name);
|
||||
const trimmedName = rawName?.trim();
|
||||
const hasTrimmedName = typeof trimmedName === "string" && trimmedName.length > 0;
|
||||
const normalizedName = hasTrimmedName ? trimmedName : undefined;
|
||||
|
||||
@@ -2,6 +2,7 @@ import os from "node:os";
|
||||
import path from "node:path";
|
||||
import { resolveStateDir } from "../config/paths.js";
|
||||
import { loadJsonFile, saveJsonFile } from "../infra/json-file.js";
|
||||
import { readStringValue } from "../shared/string-coerce.js";
|
||||
import { normalizeDeliveryContext } from "../utils/delivery-context.js";
|
||||
import type { SubagentRunRecord } from "./subagent-registry.types.js";
|
||||
|
||||
@@ -84,9 +85,8 @@ export function loadSubagentRegistryFromDisk(): Map<string, SubagentRunRecord> {
|
||||
: undefined;
|
||||
const requesterOrigin = normalizeDeliveryContext(
|
||||
typed.requesterOrigin ?? {
|
||||
channel: typeof typed.requesterChannel === "string" ? typed.requesterChannel : undefined,
|
||||
accountId:
|
||||
typeof typed.requesterAccountId === "string" ? typed.requesterAccountId : undefined,
|
||||
channel: readStringValue(typed.requesterChannel),
|
||||
accountId: readStringValue(typed.requesterAccountId),
|
||||
},
|
||||
);
|
||||
const {
|
||||
|
||||
@@ -11,6 +11,7 @@ import {
|
||||
} from "../../infra/restart-sentinel.js";
|
||||
import { scheduleGatewaySigusr1Restart } from "../../infra/restart.js";
|
||||
import { createSubsystemLogger } from "../../logging/subsystem.js";
|
||||
import { readStringValue } from "../../shared/string-coerce.js";
|
||||
import { stringEnum } from "../schema/typebox.js";
|
||||
import { type AnyAgentTool, jsonResult, readStringParam } from "./common.js";
|
||||
import { callGatewayTool, readGatewayCallOptions } from "./gateway.js";
|
||||
@@ -27,8 +28,8 @@ function resolveBaseHashFromSnapshot(snapshot: unknown): string | undefined {
|
||||
const hashValue = (snapshot as { hash?: unknown }).hash;
|
||||
const rawValue = (snapshot as { raw?: unknown }).raw;
|
||||
const hash = resolveConfigSnapshotHash({
|
||||
hash: typeof hashValue === "string" ? hashValue : undefined,
|
||||
raw: typeof rawValue === "string" ? rawValue : undefined,
|
||||
hash: readStringValue(hashValue),
|
||||
raw: readStringValue(rawValue),
|
||||
});
|
||||
return hash ?? undefined;
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ import { callGateway } from "../../gateway/call.js";
|
||||
import { capArrayByJsonBytes } from "../../gateway/session-utils.fs.js";
|
||||
import { jsonUtf8Bytes } from "../../infra/json-utf8-bytes.js";
|
||||
import { redactSensitiveText } from "../../logging/redact.js";
|
||||
import { readStringValue } from "../../shared/string-coerce.js";
|
||||
import { truncateUtf16Safe } from "../../utils.js";
|
||||
import {
|
||||
describeSessionsHistoryTool,
|
||||
@@ -87,7 +88,7 @@ function sanitizeHistoryContentBlock(block: unknown): {
|
||||
redacted ||= res.redacted;
|
||||
}
|
||||
if (type === "image") {
|
||||
const data = typeof entry.data === "string" ? entry.data : undefined;
|
||||
const data = readStringValue(entry.data);
|
||||
const bytes = data ? data.length : undefined;
|
||||
if ("data" in entry) {
|
||||
delete entry.data;
|
||||
|
||||
@@ -8,6 +8,7 @@ import {
|
||||
} from "../../config/sessions.js";
|
||||
import { callGateway } from "../../gateway/call.js";
|
||||
import { resolveAgentIdFromSessionKey } from "../../routing/session-key.js";
|
||||
import { readStringValue } from "../../shared/string-coerce.js";
|
||||
import {
|
||||
describeSessionsListTool,
|
||||
SESSIONS_LIST_TOOL_DISPLAY_SUMMARY,
|
||||
@@ -152,23 +153,17 @@ export function createSessionsListTool(opts?: {
|
||||
entry.deliveryContext && typeof entry.deliveryContext === "object"
|
||||
? (entry.deliveryContext as Record<string, unknown>)
|
||||
: undefined;
|
||||
const deliveryChannel =
|
||||
typeof deliveryContext?.channel === "string" ? deliveryContext.channel : undefined;
|
||||
const deliveryTo = typeof deliveryContext?.to === "string" ? deliveryContext.to : undefined;
|
||||
const deliveryAccountId =
|
||||
typeof deliveryContext?.accountId === "string" ? deliveryContext.accountId : undefined;
|
||||
const deliveryChannel = readStringValue(deliveryContext?.channel);
|
||||
const deliveryTo = readStringValue(deliveryContext?.to);
|
||||
const deliveryAccountId = readStringValue(deliveryContext?.accountId);
|
||||
const deliveryThreadId =
|
||||
typeof deliveryContext?.threadId === "string" ||
|
||||
(typeof deliveryContext?.threadId === "number" &&
|
||||
Number.isFinite(deliveryContext.threadId))
|
||||
? deliveryContext.threadId
|
||||
: undefined;
|
||||
const lastChannel =
|
||||
deliveryChannel ??
|
||||
(typeof entry.lastChannel === "string" ? entry.lastChannel : undefined);
|
||||
const lastAccountId =
|
||||
deliveryAccountId ??
|
||||
(typeof entry.lastAccountId === "string" ? entry.lastAccountId : undefined);
|
||||
const lastChannel = deliveryChannel ?? readStringValue(entry.lastChannel);
|
||||
const lastAccountId = deliveryAccountId ?? readStringValue(entry.lastAccountId);
|
||||
const derivedChannel = deriveChannel({
|
||||
key,
|
||||
kind,
|
||||
@@ -176,9 +171,9 @@ export function createSessionsListTool(opts?: {
|
||||
lastChannel,
|
||||
});
|
||||
|
||||
const sessionId = typeof entry.sessionId === "string" ? entry.sessionId : undefined;
|
||||
const sessionId = readStringValue(entry.sessionId);
|
||||
const sessionFileRaw = (entry as { sessionFile?: unknown }).sessionFile;
|
||||
const sessionFile = typeof sessionFileRaw === "string" ? sessionFileRaw : undefined;
|
||||
const sessionFile = readStringValue(sessionFileRaw);
|
||||
let transcriptPath: string | undefined;
|
||||
if (sessionId) {
|
||||
try {
|
||||
@@ -215,8 +210,7 @@ export function createSessionsListTool(opts?: {
|
||||
(typeof entryOrigin?.accountId === "string" ? entryOrigin.accountId : undefined)
|
||||
? {
|
||||
provider: originChannel,
|
||||
accountId:
|
||||
typeof entryOrigin?.accountId === "string" ? entryOrigin.accountId : undefined,
|
||||
accountId: readStringValue(entryOrigin?.accountId),
|
||||
}
|
||||
: undefined,
|
||||
spawnedBy:
|
||||
@@ -227,8 +221,8 @@ export function createSessionsListTool(opts?: {
|
||||
mainKey,
|
||||
})
|
||||
: undefined,
|
||||
label: typeof entry.label === "string" ? entry.label : undefined,
|
||||
displayName: typeof entry.displayName === "string" ? entry.displayName : undefined,
|
||||
label: readStringValue(entry.label),
|
||||
displayName: readStringValue(entry.displayName),
|
||||
parentSessionKey:
|
||||
typeof entry.parentSessionKey === "string"
|
||||
? resolveDisplaySessionKey({
|
||||
@@ -248,12 +242,12 @@ export function createSessionsListTool(opts?: {
|
||||
: undefined,
|
||||
updatedAt: typeof entry.updatedAt === "number" ? entry.updatedAt : undefined,
|
||||
sessionId,
|
||||
model: typeof entry.model === "string" ? entry.model : undefined,
|
||||
model: readStringValue(entry.model),
|
||||
contextTokens: typeof entry.contextTokens === "number" ? entry.contextTokens : undefined,
|
||||
totalTokens: typeof entry.totalTokens === "number" ? entry.totalTokens : undefined,
|
||||
estimatedCostUsd:
|
||||
typeof entry.estimatedCostUsd === "number" ? entry.estimatedCostUsd : undefined,
|
||||
status: typeof entry.status === "string" ? entry.status : undefined,
|
||||
status: readStringValue(entry.status),
|
||||
startedAt: typeof entry.startedAt === "number" ? entry.startedAt : undefined,
|
||||
endedAt: typeof entry.endedAt === "number" ? entry.endedAt : undefined,
|
||||
runtimeMs: typeof entry.runtimeMs === "number" ? entry.runtimeMs : undefined,
|
||||
@@ -268,19 +262,18 @@ export function createSessionsListTool(opts?: {
|
||||
}),
|
||||
)
|
||||
: undefined,
|
||||
thinkingLevel: typeof entry.thinkingLevel === "string" ? entry.thinkingLevel : undefined,
|
||||
thinkingLevel: readStringValue(entry.thinkingLevel),
|
||||
fastMode: typeof entry.fastMode === "boolean" ? entry.fastMode : undefined,
|
||||
verboseLevel: typeof entry.verboseLevel === "string" ? entry.verboseLevel : undefined,
|
||||
reasoningLevel:
|
||||
typeof entry.reasoningLevel === "string" ? entry.reasoningLevel : undefined,
|
||||
elevatedLevel: typeof entry.elevatedLevel === "string" ? entry.elevatedLevel : undefined,
|
||||
responseUsage: typeof entry.responseUsage === "string" ? entry.responseUsage : undefined,
|
||||
verboseLevel: readStringValue(entry.verboseLevel),
|
||||
reasoningLevel: readStringValue(entry.reasoningLevel),
|
||||
elevatedLevel: readStringValue(entry.elevatedLevel),
|
||||
responseUsage: readStringValue(entry.responseUsage),
|
||||
systemSent: typeof entry.systemSent === "boolean" ? entry.systemSent : undefined,
|
||||
abortedLastRun:
|
||||
typeof entry.abortedLastRun === "boolean" ? entry.abortedLastRun : undefined,
|
||||
sendPolicy: typeof entry.sendPolicy === "string" ? entry.sendPolicy : undefined,
|
||||
sendPolicy: readStringValue(entry.sendPolicy),
|
||||
lastChannel,
|
||||
lastTo: deliveryTo ?? (typeof entry.lastTo === "string" ? entry.lastTo : undefined),
|
||||
lastTo: deliveryTo ?? readStringValue(entry.lastTo),
|
||||
lastAccountId,
|
||||
transcriptPath,
|
||||
};
|
||||
|
||||
@@ -6,6 +6,7 @@ import { openBoundaryFile } from "../infra/boundary-file-read.js";
|
||||
import { resolveRequiredHomeDir } from "../infra/home-dir.js";
|
||||
import { runCommandWithTimeout } from "../process/exec.js";
|
||||
import { isCronSessionKey, isSubagentSessionKey } from "../routing/session-key.js";
|
||||
import { readStringValue } from "../shared/string-coerce.js";
|
||||
import { resolveUserPath } from "../utils.js";
|
||||
import { resolveWorkspaceTemplateDir } from "./workspace-templates.js";
|
||||
|
||||
@@ -217,14 +218,11 @@ function parseWorkspaceSetupState(raw: string): WorkspaceSetupState | null {
|
||||
if (!parsed || typeof parsed !== "object") {
|
||||
return null;
|
||||
}
|
||||
const legacyCompletedAt =
|
||||
typeof parsed.onboardingCompletedAt === "string" ? parsed.onboardingCompletedAt : undefined;
|
||||
const legacyCompletedAt = readStringValue(parsed.onboardingCompletedAt);
|
||||
return {
|
||||
version: WORKSPACE_STATE_VERSION,
|
||||
bootstrapSeededAt:
|
||||
typeof parsed.bootstrapSeededAt === "string" ? parsed.bootstrapSeededAt : undefined,
|
||||
setupCompletedAt:
|
||||
typeof parsed.setupCompletedAt === "string" ? parsed.setupCompletedAt : legacyCompletedAt,
|
||||
bootstrapSeededAt: readStringValue(parsed.bootstrapSeededAt),
|
||||
setupCompletedAt: readStringValue(parsed.setupCompletedAt) ?? legacyCompletedAt,
|
||||
};
|
||||
} catch {
|
||||
return null;
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import path from "node:path";
|
||||
import * as tar from "tar";
|
||||
import { type RuntimeEnv, writeRuntimeJson } from "../runtime.js";
|
||||
import { readStringValue } from "../shared/string-coerce.js";
|
||||
import { isRecord, resolveUserPath } from "../utils.js";
|
||||
|
||||
const WINDOWS_ABSOLUTE_ARCHIVE_PATH_RE = /^[A-Za-z]:[\\/]/;
|
||||
@@ -150,10 +151,9 @@ function parseManifest(raw: string): BackupManifest {
|
||||
: undefined,
|
||||
paths: isRecord(parsed.paths)
|
||||
? {
|
||||
stateDir: typeof parsed.paths.stateDir === "string" ? parsed.paths.stateDir : undefined,
|
||||
configPath:
|
||||
typeof parsed.paths.configPath === "string" ? parsed.paths.configPath : undefined,
|
||||
oauthDir: typeof parsed.paths.oauthDir === "string" ? parsed.paths.oauthDir : undefined,
|
||||
stateDir: readStringValue(parsed.paths.stateDir),
|
||||
configPath: readStringValue(parsed.paths.configPath),
|
||||
oauthDir: readStringValue(parsed.paths.oauthDir),
|
||||
workspaceDirs: Array.isArray(parsed.paths.workspaceDirs)
|
||||
? parsed.paths.workspaceDirs.filter(
|
||||
(entry): entry is string => typeof entry === "string",
|
||||
|
||||
@@ -11,6 +11,7 @@ import { findTailscaleBinary } from "../infra/tailscale.js";
|
||||
import type { RuntimeEnv } from "../runtime.js";
|
||||
import { resolveDefaultSecretProviderAlias } from "../secrets/ref-contract.js";
|
||||
import { validateIPv4AddressInput } from "../shared/net/ipv4.js";
|
||||
import { readStringValue } from "../shared/string-coerce.js";
|
||||
import { note } from "../terminal/note.js";
|
||||
import { buildGatewayAuthConfig } from "./configure.gateway-auth.js";
|
||||
import { confirm, select, text } from "./configure.shared.js";
|
||||
@@ -86,7 +87,7 @@ export async function promptGatewayConfig(
|
||||
}),
|
||||
runtime,
|
||||
);
|
||||
customBindHost = typeof input === "string" ? input : undefined;
|
||||
customBindHost = readStringValue(input);
|
||||
}
|
||||
|
||||
let authMode = guardCancel(
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import { readStringValue } from "../shared/string-coerce.js";
|
||||
|
||||
export type GatewaySelfPresence = {
|
||||
host?: string;
|
||||
ip?: string;
|
||||
@@ -19,9 +21,9 @@ export function pickGatewaySelfPresence(presence: unknown): GatewaySelfPresence
|
||||
return null;
|
||||
}
|
||||
return {
|
||||
host: typeof self.host === "string" ? self.host : undefined,
|
||||
ip: typeof self.ip === "string" ? self.ip : undefined,
|
||||
version: typeof self.version === "string" ? self.version : undefined,
|
||||
platform: typeof self.platform === "string" ? self.platform : undefined,
|
||||
host: readStringValue(self.host),
|
||||
ip: readStringValue(self.ip),
|
||||
version: readStringValue(self.version),
|
||||
platform: readStringValue(self.platform),
|
||||
};
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ import {
|
||||
type GatewayBonjourBeacon,
|
||||
} from "../../infra/bonjour-discovery.js";
|
||||
import { formatErrorMessage } from "../../infra/errors.js";
|
||||
import { readStringValue } from "../../shared/string-coerce.js";
|
||||
import { pickAutoSshTargetFromDiscovery } from "./discovery.js";
|
||||
import {
|
||||
extractConfigSummary,
|
||||
@@ -117,8 +118,8 @@ export async function runGatewayStatusProbePass(params: {
|
||||
const probed = await Promise.all(
|
||||
targets.map(async (target) => {
|
||||
const authResolution = await resolveAuthForTarget(params.cfg, target, {
|
||||
token: typeof params.opts.token === "string" ? params.opts.token : undefined,
|
||||
password: typeof params.opts.password === "string" ? params.opts.password : undefined,
|
||||
token: readStringValue(params.opts.token),
|
||||
password: readStringValue(params.opts.password),
|
||||
});
|
||||
const probe = await probeGateway({
|
||||
url: target.url,
|
||||
|
||||
@@ -2,6 +2,7 @@ import fs from "node:fs";
|
||||
import path from "node:path";
|
||||
import { CONFIG_PATH, type HookMappingConfig, type HooksConfig } from "../config/config.js";
|
||||
import { importFileModule, resolveFunctionModuleExport } from "../hooks/module-loader.js";
|
||||
import { readStringValue } from "../shared/string-coerce.js";
|
||||
import type { HookMessageChannel } from "./hooks.js";
|
||||
|
||||
export type HookMappingResolved = {
|
||||
@@ -228,7 +229,7 @@ function mappingMatches(mapping: HookMappingResolved, ctx: HookMappingContext) {
|
||||
}
|
||||
}
|
||||
if (mapping.matchSource) {
|
||||
const source = typeof ctx.payload.source === "string" ? ctx.payload.source : undefined;
|
||||
const source = readStringValue(ctx.payload.source);
|
||||
if (!source || source !== mapping.matchSource) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -33,7 +33,7 @@ import {
|
||||
resolveAgentIdFromSessionKey,
|
||||
toAgentStoreSessionKey,
|
||||
} from "../../routing/session-key.js";
|
||||
import { normalizeOptionalString } from "../../shared/string-coerce.js";
|
||||
import { normalizeOptionalString, readStringValue } from "../../shared/string-coerce.js";
|
||||
import { GATEWAY_CLIENT_IDS } from "../protocol/client-info.js";
|
||||
import {
|
||||
ErrorCodes,
|
||||
@@ -1206,14 +1206,14 @@ export const sessionsHandlers: GatewayRequestHandlers = {
|
||||
context,
|
||||
requestedKey: key,
|
||||
canonicalKey,
|
||||
runId: typeof p.runId === "string" ? p.runId : undefined,
|
||||
runId: readStringValue(p.runId),
|
||||
});
|
||||
let abortedRunId: string | null = null;
|
||||
await chatHandlers["chat.abort"]({
|
||||
req,
|
||||
params: {
|
||||
sessionKey: abortSessionKey,
|
||||
runId: typeof p.runId === "string" ? p.runId : undefined,
|
||||
runId: readStringValue(p.runId),
|
||||
},
|
||||
respond: (ok, payload, error, meta) => {
|
||||
if (!ok) {
|
||||
|
||||
@@ -5,6 +5,7 @@ import { shouldLogSubsystemToConsole } from "../logging/console.js";
|
||||
import { getDefaultRedactPatterns, redactSensitiveText } from "../logging/redact.js";
|
||||
import { createSubsystemLogger } from "../logging/subsystem.js";
|
||||
import { parseAgentSessionKey } from "../routing/session-key.js";
|
||||
import { readStringValue } from "../shared/string-coerce.js";
|
||||
import { DEFAULT_WS_SLOW_MS, getGatewayWsLogStyle } from "./ws-logging.js";
|
||||
|
||||
const LOG_VALUE_LIMIT = 240;
|
||||
@@ -169,10 +170,10 @@ export function summarizeAgentEventForWsLog(payload: unknown): Record<string, un
|
||||
return {};
|
||||
}
|
||||
const rec = payload as Record<string, unknown>;
|
||||
const runId = typeof rec.runId === "string" ? rec.runId : undefined;
|
||||
const stream = typeof rec.stream === "string" ? rec.stream : undefined;
|
||||
const runId = readStringValue(rec.runId);
|
||||
const stream = readStringValue(rec.stream);
|
||||
const seq = typeof rec.seq === "number" ? rec.seq : undefined;
|
||||
const sessionKey = typeof rec.sessionKey === "string" ? rec.sessionKey : undefined;
|
||||
const sessionKey = readStringValue(rec.sessionKey);
|
||||
const data =
|
||||
rec.data && typeof rec.data === "object" ? (rec.data as Record<string, unknown>) : undefined;
|
||||
|
||||
@@ -201,7 +202,7 @@ export function summarizeAgentEventForWsLog(payload: unknown): Record<string, un
|
||||
}
|
||||
|
||||
if (stream === "assistant") {
|
||||
const text = typeof data.text === "string" ? data.text : undefined;
|
||||
const text = readStringValue(data.text);
|
||||
if (text?.trim()) {
|
||||
extra.text = compactPreview(text);
|
||||
}
|
||||
@@ -215,16 +216,16 @@ export function summarizeAgentEventForWsLog(payload: unknown): Record<string, un
|
||||
}
|
||||
|
||||
if (stream === "tool") {
|
||||
const phase = typeof data.phase === "string" ? data.phase : undefined;
|
||||
const name = typeof data.name === "string" ? data.name : undefined;
|
||||
const phase = readStringValue(data.phase);
|
||||
const name = readStringValue(data.name);
|
||||
if (phase || name) {
|
||||
extra.tool = `${phase ?? "?"}:${name ?? "?"}`;
|
||||
}
|
||||
const toolCallId = typeof data.toolCallId === "string" ? data.toolCallId : undefined;
|
||||
const toolCallId = readStringValue(data.toolCallId);
|
||||
if (toolCallId) {
|
||||
extra.call = shortId(toolCallId);
|
||||
}
|
||||
const meta = typeof data.meta === "string" ? data.meta : undefined;
|
||||
const meta = readStringValue(data.meta);
|
||||
if (meta?.trim()) {
|
||||
extra.meta = meta;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user