From c89527f38950a8bceddd0c6f779dbacfe5251ae0 Mon Sep 17 00:00:00 2001 From: Vincent Koc Date: Sun, 15 Mar 2026 19:19:22 -0700 Subject: [PATCH] Tlon: split setup adapter helpers --- extensions/tlon/src/channel.ts | 3 +- extensions/tlon/src/setup-core.ts | 101 +++++++++++++++++++++++++++ extensions/tlon/src/setup-surface.ts | 100 +------------------------- src/plugin-sdk/tlon.ts | 3 +- 4 files changed, 108 insertions(+), 99 deletions(-) create mode 100644 extensions/tlon/src/setup-core.ts diff --git a/extensions/tlon/src/channel.ts b/extensions/tlon/src/channel.ts index 7a460a6adb8..9282fcf92f9 100644 --- a/extensions/tlon/src/channel.ts +++ b/extensions/tlon/src/channel.ts @@ -7,7 +7,8 @@ import type { } from "openclaw/plugin-sdk/tlon"; import { tlonChannelConfigSchema } from "./config-schema.js"; import { monitorTlonProvider } from "./monitor/index.js"; -import { tlonSetupAdapter, tlonSetupWizard } from "./setup-surface.js"; +import { tlonSetupAdapter } from "./setup-core.js"; +import { tlonSetupWizard } from "./setup-surface.js"; import { formatTargetHint, normalizeShip, parseTlonTarget } from "./targets.js"; import { resolveTlonAccount, listTlonAccountIds } from "./types.js"; import { authenticate } from "./urbit/auth.js"; diff --git a/extensions/tlon/src/setup-core.ts b/extensions/tlon/src/setup-core.ts new file mode 100644 index 00000000000..a237a813edf --- /dev/null +++ b/extensions/tlon/src/setup-core.ts @@ -0,0 +1,101 @@ +import { + applyAccountNameToChannelSection, + patchScopedAccountConfig, +} from "../../../src/channels/plugins/setup-helpers.js"; +import type { ChannelSetupAdapter } from "../../../src/channels/plugins/types.adapters.js"; +import type { ChannelSetupInput } from "../../../src/channels/plugins/types.core.js"; +import type { OpenClawConfig } from "../../../src/config/config.js"; +import { DEFAULT_ACCOUNT_ID, normalizeAccountId } from "../../../src/routing/session-key.js"; +import { buildTlonAccountFields } from "./account-fields.js"; +import { resolveTlonAccount } from "./types.js"; + +const channel = "tlon" as const; + +export type TlonSetupInput = ChannelSetupInput & { + ship?: string; + url?: string; + code?: string; + allowPrivateNetwork?: boolean; + groupChannels?: string[]; + dmAllowlist?: string[]; + autoDiscoverChannels?: boolean; + ownerShip?: string; +}; + +export function applyTlonSetupConfig(params: { + cfg: OpenClawConfig; + accountId: string; + input: TlonSetupInput; +}): OpenClawConfig { + const { cfg, accountId, input } = params; + const useDefault = accountId === DEFAULT_ACCOUNT_ID; + const namedConfig = applyAccountNameToChannelSection({ + cfg, + channelKey: channel, + accountId, + name: input.name, + }); + const base = namedConfig.channels?.tlon ?? {}; + const payload = buildTlonAccountFields(input); + + if (useDefault) { + return { + ...namedConfig, + channels: { + ...namedConfig.channels, + tlon: { + ...base, + enabled: true, + ...payload, + }, + }, + }; + } + + return patchScopedAccountConfig({ + cfg: namedConfig, + channelKey: channel, + accountId, + patch: { enabled: base.enabled ?? true }, + accountPatch: { + enabled: true, + ...payload, + }, + ensureChannelEnabled: false, + ensureAccountEnabled: false, + }); +} + +export const tlonSetupAdapter: ChannelSetupAdapter = { + resolveAccountId: ({ accountId }) => normalizeAccountId(accountId), + applyAccountName: ({ cfg, accountId, name }) => + applyAccountNameToChannelSection({ + cfg, + channelKey: channel, + accountId, + name, + }), + validateInput: ({ cfg, accountId, input }) => { + const setupInput = input as TlonSetupInput; + const resolved = resolveTlonAccount(cfg, accountId ?? undefined); + const ship = setupInput.ship?.trim() || resolved.ship; + const url = setupInput.url?.trim() || resolved.url; + const code = setupInput.code?.trim() || resolved.code; + if (!ship) { + return "Tlon requires --ship."; + } + if (!url) { + return "Tlon requires --url."; + } + if (!code) { + return "Tlon requires --code."; + } + return null; + }, + applyAccountConfig: ({ cfg, accountId, input }) => + applyTlonSetupConfig({ + cfg, + accountId, + input: input as TlonSetupInput, + }), +}; diff --git a/extensions/tlon/src/setup-surface.ts b/extensions/tlon/src/setup-surface.ts index 4cf0d006ebd..ec6258277bd 100644 --- a/extensions/tlon/src/setup-surface.ts +++ b/extensions/tlon/src/setup-surface.ts @@ -1,31 +1,13 @@ -import { - applyAccountNameToChannelSection, - patchScopedAccountConfig, -} from "../../../src/channels/plugins/setup-helpers.js"; import type { ChannelSetupWizard } from "../../../src/channels/plugins/setup-wizard.js"; -import type { ChannelSetupAdapter } from "../../../src/channels/plugins/types.adapters.js"; -import type { ChannelSetupInput } from "../../../src/channels/plugins/types.core.js"; -import type { OpenClawConfig } from "../../../src/config/config.js"; -import { DEFAULT_ACCOUNT_ID, normalizeAccountId } from "../../../src/routing/session-key.js"; +import { DEFAULT_ACCOUNT_ID } from "../../../src/routing/session-key.js"; import { formatDocsLink } from "../../../src/terminal/links.js"; -import { buildTlonAccountFields } from "./account-fields.js"; +import { applyTlonSetupConfig, type TlonSetupInput, tlonSetupAdapter } from "./setup-core.js"; import { normalizeShip } from "./targets.js"; import { listTlonAccountIds, resolveTlonAccount, type TlonResolvedAccount } from "./types.js"; import { isBlockedUrbitHostname, validateUrbitBaseUrl } from "./urbit/base-url.js"; const channel = "tlon" as const; -type TlonSetupInput = ChannelSetupInput & { - ship?: string; - url?: string; - code?: string; - allowPrivateNetwork?: boolean; - groupChannels?: string[]; - dmAllowlist?: string[]; - autoDiscoverChannels?: boolean; - ownerShip?: string; -}; - function isConfigured(account: TlonResolvedAccount): boolean { return Boolean(account.ship && account.url && account.code); } @@ -37,83 +19,7 @@ function parseList(value: string): string[] { .filter(Boolean); } -function applyTlonSetupConfig(params: { - cfg: OpenClawConfig; - accountId: string; - input: TlonSetupInput; -}): OpenClawConfig { - const { cfg, accountId, input } = params; - const useDefault = accountId === DEFAULT_ACCOUNT_ID; - const namedConfig = applyAccountNameToChannelSection({ - cfg, - channelKey: channel, - accountId, - name: input.name, - }); - const base = namedConfig.channels?.tlon ?? {}; - const payload = buildTlonAccountFields(input); - - if (useDefault) { - return { - ...namedConfig, - channels: { - ...namedConfig.channels, - tlon: { - ...base, - enabled: true, - ...payload, - }, - }, - }; - } - - return patchScopedAccountConfig({ - cfg: namedConfig, - channelKey: channel, - accountId, - patch: { enabled: base.enabled ?? true }, - accountPatch: { - enabled: true, - ...payload, - }, - ensureChannelEnabled: false, - ensureAccountEnabled: false, - }); -} - -export const tlonSetupAdapter: ChannelSetupAdapter = { - resolveAccountId: ({ accountId }) => normalizeAccountId(accountId), - applyAccountName: ({ cfg, accountId, name }) => - applyAccountNameToChannelSection({ - cfg, - channelKey: channel, - accountId, - name, - }), - validateInput: ({ cfg, accountId, input }) => { - const setupInput = input as TlonSetupInput; - const resolved = resolveTlonAccount(cfg, accountId ?? undefined); - const ship = setupInput.ship?.trim() || resolved.ship; - const url = setupInput.url?.trim() || resolved.url; - const code = setupInput.code?.trim() || resolved.code; - if (!ship) { - return "Tlon requires --ship."; - } - if (!url) { - return "Tlon requires --url."; - } - if (!code) { - return "Tlon requires --code."; - } - return null; - }, - applyAccountConfig: ({ cfg, accountId, input }) => - applyTlonSetupConfig({ - cfg, - accountId, - input: input as TlonSetupInput, - }), -}; +export { tlonSetupAdapter } from "./setup-core.js"; export const tlonSetupWizard: ChannelSetupWizard = { channel, diff --git a/src/plugin-sdk/tlon.ts b/src/plugin-sdk/tlon.ts index 9a39493cac2..f1415103398 100644 --- a/src/plugin-sdk/tlon.ts +++ b/src/plugin-sdk/tlon.ts @@ -28,4 +28,5 @@ export type { RuntimeEnv } from "../runtime.js"; export { formatDocsLink } from "../terminal/links.js"; export type { WizardPrompter } from "../wizard/prompts.js"; export { createLoggerBackedRuntime } from "./runtime.js"; -export { tlonSetupAdapter, tlonSetupWizard } from "../../extensions/tlon/src/setup-surface.js"; +export { tlonSetupAdapter } from "../../extensions/tlon/src/setup-core.js"; +export { tlonSetupWizard } from "../../extensions/tlon/src/setup-surface.js";