From 9cf27393bf5548ac5aa538691f4ef59124d5a50f Mon Sep 17 00:00:00 2001 From: Hunter Miller Date: Thu, 29 Jan 2026 20:26:08 -0600 Subject: [PATCH] Tlon plugin: handle channelRules as JSON string Settings-store doesn't support nested objects as values, so channelRules is stored as a JSON string and parsed on read. --- extensions/tlon/src/settings.ts | 31 +++++++++++++++++++++++++++---- src/canvas-host/a2ui/.bundle.hash | 2 +- 2 files changed, 28 insertions(+), 5 deletions(-) diff --git a/extensions/tlon/src/settings.ts b/extensions/tlon/src/settings.ts index 78c8230cf..1dfd8a576 100644 --- a/extensions/tlon/src/settings.ts +++ b/extensions/tlon/src/settings.ts @@ -31,6 +31,31 @@ export type TlonSettingsState = { const SETTINGS_DESK = "moltbot"; const SETTINGS_BUCKET = "tlon"; +/** + * Parse channelRules - handles both JSON string and object formats. + * Settings-store doesn't support nested objects, so we store as JSON string. + */ +function parseChannelRules( + value: unknown +): Record | undefined { + if (!value) return undefined; + + // If it's a string, try to parse as JSON + if (typeof value === "string") { + try { + const parsed = JSON.parse(value); + if (isChannelRulesObject(parsed)) return parsed; + } catch { + return undefined; + } + } + + // If it's already an object, use directly + if (isChannelRulesObject(value)) return value; + + return undefined; +} + /** * Parse settings from the raw Urbit settings-store response. * The response shape is: { [bucket]: { [key]: value } } @@ -57,9 +82,7 @@ function parseSettingsResponse(raw: unknown): TlonSettingsStore { showModelSig: typeof settings.showModelSig === "boolean" ? settings.showModelSig : undefined, - channelRules: isChannelRulesObject(settings.channelRules) - ? settings.channelRules - : undefined, + channelRules: parseChannelRules(settings.channelRules), defaultAuthorizedShips: Array.isArray(settings.defaultAuthorizedShips) ? settings.defaultAuthorizedShips.filter((x): x is string => typeof x === "string") : undefined, @@ -139,7 +162,7 @@ function applySettingsUpdate( next.showModelSig = typeof value === "boolean" ? value : undefined; break; case "channelRules": - next.channelRules = isChannelRulesObject(value) ? value : undefined; + next.channelRules = parseChannelRules(value); break; case "defaultAuthorizedShips": next.defaultAuthorizedShips = Array.isArray(value) diff --git a/src/canvas-host/a2ui/.bundle.hash b/src/canvas-host/a2ui/.bundle.hash index 6c9cb0299..dd57697ae 100644 --- a/src/canvas-host/a2ui/.bundle.hash +++ b/src/canvas-host/a2ui/.bundle.hash @@ -1 +1 @@ -b6d3dea7c656c8a480059c32e954c4d39053ff79c4e9c69b38f4c04e3f0280d4 +bd5789522e6bde45274e15fdd45b10c9a41da378b190d6f42cef5ef2a69d72a7