diff --git a/CHANGELOG.md b/CHANGELOG.md index 124bd7617..9c0e8edf2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,7 @@ Docs: https://docs.clawd.bot - Web UI: hide internal `message_id` hints in chat bubbles. - Heartbeat: normalize target identifiers for consistent routing. - Gateway: reduce log noise for late invokes + remote node probes; debounce skills refresh. (#1607) Thanks @petter-b. +- Tlon: fix Zod v4 record keys + aura v3 DM ids. (#1631) Thanks @arthyn. ## 2026.1.23-1 diff --git a/extensions/tlon/src/config-schema.test.ts b/extensions/tlon/src/config-schema.test.ts new file mode 100644 index 000000000..6a5b52439 --- /dev/null +++ b/extensions/tlon/src/config-schema.test.ts @@ -0,0 +1,32 @@ +import { describe, expect, it } from "vitest"; + +import { TlonAuthorizationSchema, TlonConfigSchema } from "./config-schema.js"; + +describe("Tlon config schema", () => { + it("accepts channelRules with string keys", () => { + const parsed = TlonAuthorizationSchema.parse({ + channelRules: { + "chat/~zod/test": { + mode: "open", + allowedShips: ["~zod"], + }, + }, + }); + + expect(parsed.channelRules?.["chat/~zod/test"]?.mode).toBe("open"); + }); + + it("accepts accounts with string keys", () => { + const parsed = TlonConfigSchema.parse({ + accounts: { + primary: { + ship: "~zod", + url: "https://example.com", + code: "code-123", + }, + }, + }); + + expect(parsed.accounts?.primary?.ship).toBe("~zod"); + }); +}); diff --git a/extensions/tlon/src/config-schema.ts b/extensions/tlon/src/config-schema.ts index 13c7cd7c0..20b5eb4dd 100644 --- a/extensions/tlon/src/config-schema.ts +++ b/extensions/tlon/src/config-schema.ts @@ -10,7 +10,7 @@ export const TlonChannelRuleSchema = z.object({ }); export const TlonAuthorizationSchema = z.object({ - channelRules: z.record(TlonChannelRuleSchema).optional(), + channelRules: z.record(z.string(), TlonChannelRuleSchema).optional(), }); export const TlonAccountSchema = z.object({ @@ -37,7 +37,7 @@ export const TlonConfigSchema = z.object({ showModelSignature: z.boolean().optional(), authorization: TlonAuthorizationSchema.optional(), defaultAuthorizedShips: z.array(ShipSchema).optional(), - accounts: z.record(TlonAccountSchema).optional(), + accounts: z.record(z.string(), TlonAccountSchema).optional(), }); export const tlonChannelConfigSchema = buildChannelConfigSchema(TlonConfigSchema); diff --git a/extensions/tlon/src/urbit/send.test.ts b/extensions/tlon/src/urbit/send.test.ts new file mode 100644 index 000000000..aad3a674e --- /dev/null +++ b/extensions/tlon/src/urbit/send.test.ts @@ -0,0 +1,38 @@ +import { afterEach, describe, expect, it, vi } from "vitest"; + +vi.mock("@urbit/aura", () => ({ + scot: vi.fn(() => "mocked-ud"), + da: { + fromUnix: vi.fn(() => 123n), + }, +})); + +describe("sendDm", () => { + afterEach(() => { + vi.restoreAllMocks(); + }); + + it("uses aura v3 helpers for the DM id", async () => { + const { sendDm } = await import("./send.js"); + const aura = await import("@urbit/aura"); + const scot = vi.mocked(aura.scot); + const fromUnix = vi.mocked(aura.da.fromUnix); + + const sentAt = 1_700_000_000_000; + vi.spyOn(Date, "now").mockReturnValue(sentAt); + + const poke = vi.fn(async () => ({})); + + const result = await sendDm({ + api: { poke }, + fromShip: "~zod", + toShip: "~nec", + text: "hi", + }); + + expect(fromUnix).toHaveBeenCalledWith(sentAt); + expect(scot).toHaveBeenCalledWith("ud", 123n); + expect(poke).toHaveBeenCalledTimes(1); + expect(result.messageId).toBe("~zod/mocked-ud"); + }); +}); diff --git a/extensions/tlon/src/urbit/send.ts b/extensions/tlon/src/urbit/send.ts index 6a90fcbf9..35f7f2d74 100644 --- a/extensions/tlon/src/urbit/send.ts +++ b/extensions/tlon/src/urbit/send.ts @@ -1,4 +1,4 @@ -import { unixToDa, formatUd } from "@urbit/aura"; +import { scot, da } from "@urbit/aura"; export type TlonPokeApi = { poke: (params: { app: string; mark: string; json: unknown }) => Promise; @@ -14,7 +14,7 @@ type SendTextParams = { export async function sendDm({ api, fromShip, toShip, text }: SendTextParams) { const story = [{ inline: [text] }]; const sentAt = Date.now(); - const idUd = formatUd(unixToDa(sentAt)); + const idUd = scot('ud', da.fromUnix(sentAt)); const id = `${fromShip}/${idUd}`; const delta = {