Refactor: trim duplicate gateway/onboarding helpers and dead utils (#43871)

* Gateway: share input provenance schema

* Onboarding: dedupe top-level channel patching

* Utils: remove unused path helpers

* Protocol: refresh generated gateway models
This commit is contained in:
Vincent Koc
2026-03-12 05:04:31 -04:00
committed by GitHub
parent cb7b38105f
commit 7c889e7113
8 changed files with 55 additions and 105 deletions

View File

@@ -538,8 +538,6 @@ public struct AgentParams: Codable, Sendable {
public let inputprovenance: [String: AnyCodable]?
public let idempotencykey: String
public let label: String?
public let spawnedby: String?
public let workspacedir: String?
public init(
message: String,
@@ -566,9 +564,7 @@ public struct AgentParams: Codable, Sendable {
internalevents: [[String: AnyCodable]]?,
inputprovenance: [String: AnyCodable]?,
idempotencykey: String,
label: String?,
spawnedby: String?,
workspacedir: String?)
label: String?)
{
self.message = message
self.agentid = agentid
@@ -595,8 +591,6 @@ public struct AgentParams: Codable, Sendable {
self.inputprovenance = inputprovenance
self.idempotencykey = idempotencykey
self.label = label
self.spawnedby = spawnedby
self.workspacedir = workspacedir
}
private enum CodingKeys: String, CodingKey {
@@ -625,8 +619,6 @@ public struct AgentParams: Codable, Sendable {
case inputprovenance = "inputProvenance"
case idempotencykey = "idempotencyKey"
case label
case spawnedby = "spawnedBy"
case workspacedir = "workspaceDir"
}
}
@@ -1336,6 +1328,7 @@ public struct SessionsPatchParams: Codable, Sendable {
public let execnode: AnyCodable?
public let model: AnyCodable?
public let spawnedby: AnyCodable?
public let spawnedworkspacedir: AnyCodable?
public let spawndepth: AnyCodable?
public let subagentrole: AnyCodable?
public let subagentcontrolscope: AnyCodable?
@@ -1356,6 +1349,7 @@ public struct SessionsPatchParams: Codable, Sendable {
execnode: AnyCodable?,
model: AnyCodable?,
spawnedby: AnyCodable?,
spawnedworkspacedir: AnyCodable?,
spawndepth: AnyCodable?,
subagentrole: AnyCodable?,
subagentcontrolscope: AnyCodable?,
@@ -1375,6 +1369,7 @@ public struct SessionsPatchParams: Codable, Sendable {
self.execnode = execnode
self.model = model
self.spawnedby = spawnedby
self.spawnedworkspacedir = spawnedworkspacedir
self.spawndepth = spawndepth
self.subagentrole = subagentrole
self.subagentcontrolscope = subagentcontrolscope
@@ -1396,6 +1391,7 @@ public struct SessionsPatchParams: Codable, Sendable {
case execnode = "execNode"
case model
case spawnedby = "spawnedBy"
case spawnedworkspacedir = "spawnedWorkspaceDir"
case spawndepth = "spawnDepth"
case subagentrole = "subagentRole"
case subagentcontrolscope = "subagentControlScope"

View File

@@ -538,8 +538,6 @@ public struct AgentParams: Codable, Sendable {
public let inputprovenance: [String: AnyCodable]?
public let idempotencykey: String
public let label: String?
public let spawnedby: String?
public let workspacedir: String?
public init(
message: String,
@@ -566,9 +564,7 @@ public struct AgentParams: Codable, Sendable {
internalevents: [[String: AnyCodable]]?,
inputprovenance: [String: AnyCodable]?,
idempotencykey: String,
label: String?,
spawnedby: String?,
workspacedir: String?)
label: String?)
{
self.message = message
self.agentid = agentid
@@ -595,8 +591,6 @@ public struct AgentParams: Codable, Sendable {
self.inputprovenance = inputprovenance
self.idempotencykey = idempotencykey
self.label = label
self.spawnedby = spawnedby
self.workspacedir = workspacedir
}
private enum CodingKeys: String, CodingKey {
@@ -625,8 +619,6 @@ public struct AgentParams: Codable, Sendable {
case inputprovenance = "inputProvenance"
case idempotencykey = "idempotencyKey"
case label
case spawnedby = "spawnedBy"
case workspacedir = "workspaceDir"
}
}
@@ -1336,6 +1328,7 @@ public struct SessionsPatchParams: Codable, Sendable {
public let execnode: AnyCodable?
public let model: AnyCodable?
public let spawnedby: AnyCodable?
public let spawnedworkspacedir: AnyCodable?
public let spawndepth: AnyCodable?
public let subagentrole: AnyCodable?
public let subagentcontrolscope: AnyCodable?
@@ -1356,6 +1349,7 @@ public struct SessionsPatchParams: Codable, Sendable {
execnode: AnyCodable?,
model: AnyCodable?,
spawnedby: AnyCodable?,
spawnedworkspacedir: AnyCodable?,
spawndepth: AnyCodable?,
subagentrole: AnyCodable?,
subagentcontrolscope: AnyCodable?,
@@ -1375,6 +1369,7 @@ public struct SessionsPatchParams: Codable, Sendable {
self.execnode = execnode
self.model = model
self.spawnedby = spawnedby
self.spawnedworkspacedir = spawnedworkspacedir
self.spawndepth = spawndepth
self.subagentrole = subagentrole
self.subagentcontrolscope = subagentcontrolscope
@@ -1396,6 +1391,7 @@ public struct SessionsPatchParams: Codable, Sendable {
case execnode = "execNode"
case model
case spawnedby = "spawnedBy"
case spawnedworkspacedir = "spawnedWorkspaceDir"
case spawndepth = "spawnDepth"
case subagentrole = "subagentRole"
case subagentcontrolscope = "subagentControlScope"

View File

@@ -164,11 +164,11 @@ export function setAccountAllowFromForChannel(params: {
});
}
export function setTopLevelChannelAllowFrom(params: {
function patchTopLevelChannelConfig(params: {
cfg: OpenClawConfig;
channel: string;
allowFrom: string[];
enabled?: boolean;
patch: Record<string, unknown>;
}): OpenClawConfig {
const channelConfig =
(params.cfg.channels?.[params.channel] as Record<string, unknown> | undefined) ?? {};
@@ -179,12 +179,26 @@ export function setTopLevelChannelAllowFrom(params: {
[params.channel]: {
...channelConfig,
...(params.enabled ? { enabled: true } : {}),
allowFrom: params.allowFrom,
...params.patch,
},
},
};
}
export function setTopLevelChannelAllowFrom(params: {
cfg: OpenClawConfig;
channel: string;
allowFrom: string[];
enabled?: boolean;
}): OpenClawConfig {
return patchTopLevelChannelConfig({
cfg: params.cfg,
channel: params.channel,
enabled: params.enabled,
patch: { allowFrom: params.allowFrom },
});
}
export function setTopLevelChannelDmPolicyWithAllowFrom(params: {
cfg: OpenClawConfig;
channel: string;
@@ -199,17 +213,14 @@ export function setTopLevelChannelDmPolicyWithAllowFrom(params: {
undefined;
const allowFrom =
params.dmPolicy === "open" ? addWildcardAllowFrom(existingAllowFrom) : undefined;
return {
...params.cfg,
channels: {
...params.cfg.channels,
[params.channel]: {
...channelConfig,
dmPolicy: params.dmPolicy,
...(allowFrom ? { allowFrom } : {}),
},
return patchTopLevelChannelConfig({
cfg: params.cfg,
channel: params.channel,
patch: {
dmPolicy: params.dmPolicy,
...(allowFrom ? { allowFrom } : {}),
},
};
});
}
export function setTopLevelChannelGroupPolicy(params: {
@@ -218,19 +229,12 @@ export function setTopLevelChannelGroupPolicy(params: {
groupPolicy: GroupPolicy;
enabled?: boolean;
}): OpenClawConfig {
const channelConfig =
(params.cfg.channels?.[params.channel] as Record<string, unknown> | undefined) ?? {};
return {
...params.cfg,
channels: {
...params.cfg.channels,
[params.channel]: {
...channelConfig,
...(params.enabled ? { enabled: true } : {}),
groupPolicy: params.groupPolicy,
},
},
};
return patchTopLevelChannelConfig({
cfg: params.cfg,
channel: params.channel,
enabled: params.enabled,
patch: { groupPolicy: params.groupPolicy },
});
}
export function setChannelDmPolicyWithAllowFrom(params: {

View File

@@ -1,6 +1,5 @@
import { Type } from "@sinclair/typebox";
import { INPUT_PROVENANCE_KIND_VALUES } from "../../../sessions/input-provenance.js";
import { NonEmptyString, SessionLabelString } from "./primitives.js";
import { InputProvenanceSchema, NonEmptyString, SessionLabelString } from "./primitives.js";
export const AgentInternalEventSchema = Type.Object(
{
@@ -96,18 +95,7 @@ export const AgentParamsSchema = Type.Object(
lane: Type.Optional(Type.String()),
extraSystemPrompt: Type.Optional(Type.String()),
internalEvents: Type.Optional(Type.Array(AgentInternalEventSchema)),
inputProvenance: Type.Optional(
Type.Object(
{
kind: Type.String({ enum: [...INPUT_PROVENANCE_KIND_VALUES] }),
originSessionId: Type.Optional(Type.String()),
sourceSessionKey: Type.Optional(Type.String()),
sourceChannel: Type.Optional(Type.String()),
sourceTool: Type.Optional(Type.String()),
},
{ additionalProperties: false },
),
),
inputProvenance: Type.Optional(InputProvenanceSchema),
idempotencyKey: NonEmptyString,
label: Type.Optional(SessionLabelString),
},

View File

@@ -1,6 +1,5 @@
import { Type } from "@sinclair/typebox";
import { INPUT_PROVENANCE_KIND_VALUES } from "../../../sessions/input-provenance.js";
import { ChatSendSessionKeyString, NonEmptyString } from "./primitives.js";
import { ChatSendSessionKeyString, InputProvenanceSchema, NonEmptyString } from "./primitives.js";
export const LogsTailParamsSchema = Type.Object(
{
@@ -40,18 +39,7 @@ export const ChatSendParamsSchema = Type.Object(
deliver: Type.Optional(Type.Boolean()),
attachments: Type.Optional(Type.Array(Type.Unknown())),
timeoutMs: Type.Optional(Type.Integer({ minimum: 0 })),
systemInputProvenance: Type.Optional(
Type.Object(
{
kind: Type.String({ enum: [...INPUT_PROVENANCE_KIND_VALUES] }),
originSessionId: Type.Optional(Type.String()),
sourceSessionKey: Type.Optional(Type.String()),
sourceChannel: Type.Optional(Type.String()),
sourceTool: Type.Optional(Type.String()),
},
{ additionalProperties: false },
),
),
systemInputProvenance: Type.Optional(InputProvenanceSchema),
systemProvenanceReceipt: Type.Optional(Type.String()),
idempotencyKey: NonEmptyString,
},

View File

@@ -5,6 +5,7 @@ import {
FILE_SECRET_REF_ID_PATTERN,
SECRET_PROVIDER_ALIAS_PATTERN,
} from "../../../secrets/ref-contract.js";
import { INPUT_PROVENANCE_KIND_VALUES } from "../../../sessions/input-provenance.js";
import { SESSION_LABEL_MAX_LENGTH } from "../../../sessions/session-label.js";
import { GATEWAY_CLIENT_IDS, GATEWAY_CLIENT_MODES } from "../client-info.js";
@@ -18,6 +19,16 @@ export const SessionLabelString = Type.String({
minLength: 1,
maxLength: SESSION_LABEL_MAX_LENGTH,
});
export const InputProvenanceSchema = Type.Object(
{
kind: Type.String({ enum: [...INPUT_PROVENANCE_KIND_VALUES] }),
originSessionId: Type.Optional(Type.String()),
sourceSessionKey: Type.Optional(Type.String()),
sourceChannel: Type.Optional(Type.String()),
sourceTool: Type.Optional(Type.String()),
},
{ additionalProperties: false },
);
export const GatewayClientIdSchema = Type.Union(
Object.values(GATEWAY_CLIENT_IDS).map((value) => Type.Literal(value)),

View File

@@ -8,7 +8,6 @@ import {
ensureDir,
jidToE164,
normalizeE164,
normalizePath,
resolveConfigDir,
resolveHomeDir,
resolveJidToE164,
@@ -17,7 +16,6 @@ import {
shortenHomePath,
sleep,
toWhatsappJid,
withWhatsAppPrefix,
} from "./utils.js";
function withTempDirSync<T>(prefix: string, run: (dir: string) => T): T {
@@ -29,26 +27,6 @@ function withTempDirSync<T>(prefix: string, run: (dir: string) => T): T {
}
}
describe("normalizePath", () => {
it("adds leading slash when missing", () => {
expect(normalizePath("foo")).toBe("/foo");
});
it("keeps existing slash", () => {
expect(normalizePath("/bar")).toBe("/bar");
});
});
describe("withWhatsAppPrefix", () => {
it("adds whatsapp prefix", () => {
expect(withWhatsAppPrefix("+1555")).toBe("whatsapp:+1555");
});
it("leaves prefixed intact", () => {
expect(withWhatsAppPrefix("whatsapp:+1555")).toBe("whatsapp:+1555");
});
});
describe("ensureDir", () => {
it("creates nested directory", async () => {
await withTempDirSync("openclaw-test-", async (tmp) => {

View File

@@ -73,17 +73,6 @@ export function assertWebChannel(input: string): asserts input is WebChannel {
}
}
export function normalizePath(p: string): string {
if (!p.startsWith("/")) {
return `/${p}`;
}
return p;
}
export function withWhatsAppPrefix(number: string): string {
return number.startsWith("whatsapp:") ? number : `whatsapp:${number}`;
}
export function normalizeE164(number: string): string {
const withoutPrefix = number.replace(/^whatsapp:/, "").trim();
const digits = withoutPrefix.replace(/[^\d+]/g, "");