@kodelyth/tlon 2026.5.39 → 2026.5.42

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (91) hide show
  1. package/README.md +5 -0
  2. package/api.ts +16 -0
  3. package/channel-plugin-api.ts +1 -0
  4. package/dist/api.js +4 -0
  5. package/dist/channel-Bvzym9ez.js +236 -0
  6. package/dist/channel-plugin-api.js +2 -0
  7. package/dist/channel.runtime-CDY2BdfM.js +3626 -0
  8. package/dist/doctor-contract-Ip6FcHDH.js +7 -0
  9. package/dist/doctor-contract-api.js +2 -0
  10. package/dist/index.js +18 -0
  11. package/dist/runtime-BmSb9A-q.js +8 -0
  12. package/dist/runtime-api-Dq8wkBC_.js +4 -0
  13. package/dist/runtime-api.js +2 -0
  14. package/dist/setup-api.js +3 -0
  15. package/dist/setup-core-CF3ryHqs.js +387 -0
  16. package/dist/setup-entry.js +11 -0
  17. package/dist/setup-surface-BM5_V_XL.js +74 -0
  18. package/dist/test-api.js +2 -0
  19. package/doctor-contract-api.ts +1 -0
  20. package/index.ts +16 -0
  21. package/klaw.plugin.json +3 -203
  22. package/package.json +4 -4
  23. package/runtime-api.ts +17 -0
  24. package/setup-api.ts +2 -0
  25. package/setup-entry.ts +9 -0
  26. package/src/account-fields.ts +31 -0
  27. package/src/channel.message-adapter.test.ts +145 -0
  28. package/src/channel.runtime.ts +259 -0
  29. package/src/channel.ts +192 -0
  30. package/src/config-schema.ts +54 -0
  31. package/src/core.test.ts +298 -0
  32. package/src/doctor-contract.ts +9 -0
  33. package/src/doctor.test.ts +46 -0
  34. package/src/doctor.ts +10 -0
  35. package/src/logger-runtime.ts +1 -0
  36. package/src/monitor/approval-runtime.ts +363 -0
  37. package/src/monitor/approval.test.ts +33 -0
  38. package/src/monitor/approval.ts +283 -0
  39. package/src/monitor/authorization.ts +30 -0
  40. package/src/monitor/cites.ts +54 -0
  41. package/src/monitor/discovery.ts +68 -0
  42. package/src/monitor/history.ts +226 -0
  43. package/src/monitor/index.ts +1523 -0
  44. package/src/monitor/media.test.ts +80 -0
  45. package/src/monitor/media.ts +156 -0
  46. package/src/monitor/processed-messages.test.ts +58 -0
  47. package/src/monitor/processed-messages.ts +89 -0
  48. package/src/monitor/settings-helpers.test.ts +113 -0
  49. package/src/monitor/settings-helpers.ts +158 -0
  50. package/src/monitor/utils.ts +402 -0
  51. package/src/runtime.ts +9 -0
  52. package/src/security.test.ts +658 -0
  53. package/src/session-route.ts +40 -0
  54. package/src/settings.ts +391 -0
  55. package/src/setup-core.ts +231 -0
  56. package/src/setup-surface.ts +99 -0
  57. package/src/targets.ts +102 -0
  58. package/src/tlon-api.test.ts +572 -0
  59. package/src/tlon-api.ts +389 -0
  60. package/src/types.ts +160 -0
  61. package/src/urbit/auth.ssrf.test.ts +45 -0
  62. package/src/urbit/auth.ts +48 -0
  63. package/src/urbit/base-url.test.ts +48 -0
  64. package/src/urbit/base-url.ts +61 -0
  65. package/src/urbit/channel-ops.test.ts +36 -0
  66. package/src/urbit/channel-ops.ts +149 -0
  67. package/src/urbit/context.ts +50 -0
  68. package/src/urbit/errors.ts +51 -0
  69. package/src/urbit/fetch.ts +38 -0
  70. package/src/urbit/foreigns.ts +49 -0
  71. package/src/urbit/send.test.ts +83 -0
  72. package/src/urbit/send.ts +228 -0
  73. package/src/urbit/sse-client.test.ts +234 -0
  74. package/src/urbit/sse-client.ts +492 -0
  75. package/src/urbit/story.ts +332 -0
  76. package/src/urbit/upload.test.ts +155 -0
  77. package/src/urbit/upload.ts +60 -0
  78. package/test-api.ts +1 -0
  79. package/tsconfig.json +16 -0
  80. package/api.js +0 -7
  81. package/bundled-skills/@tloncorp/tlon-skill/SKILL.md +0 -501
  82. package/bundled-skills/@tloncorp/tlon-skill/bin/tlon.js +0 -7
  83. package/bundled-skills/@tloncorp/tlon-skill/package.json +0 -40
  84. package/bundled-skills/@tloncorp/tlon-skill/scripts/postinstall.js +0 -7
  85. package/channel-plugin-api.js +0 -7
  86. package/doctor-contract-api.js +0 -7
  87. package/index.js +0 -7
  88. package/runtime-api.js +0 -7
  89. package/setup-api.js +0 -7
  90. package/setup-entry.js +0 -7
  91. package/test-api.js +0 -7
package/README.md ADDED
@@ -0,0 +1,5 @@
1
+ # Tlon (Klaw plugin)
2
+
3
+ Tlon/Urbit channel plugin for Klaw. Supports DMs, group mentions, and thread replies.
4
+
5
+ Docs: https://klaw.kodelyth.com/channels/tlon
package/api.ts ADDED
@@ -0,0 +1,16 @@
1
+ export {
2
+ createDedupeCache,
3
+ createLoggerBackedRuntime,
4
+ fetchWithSsrFGuard,
5
+ isBlockedHostnameOrIp,
6
+ type LookupFn,
7
+ type KlawConfig,
8
+ type ReplyPayload,
9
+ type RuntimeEnv,
10
+ SsrFBlockedError,
11
+ type SsrFPolicy,
12
+ ssrfPolicyFromAllowPrivateNetwork,
13
+ ssrfPolicyFromDangerouslyAllowPrivateNetwork,
14
+ } from "./runtime-api.js";
15
+ export { tlonPlugin } from "./src/channel.js";
16
+ export { setTlonRuntime } from "./src/runtime.js";
@@ -0,0 +1 @@
1
+ export { tlonPlugin } from "./src/channel.js";
package/dist/api.js ADDED
@@ -0,0 +1,4 @@
1
+ import { a as ssrfPolicyFromAllowPrivateNetwork, i as isBlockedHostnameOrIp, n as createDedupeCache, o as ssrfPolicyFromDangerouslyAllowPrivateNetwork, r as fetchWithSsrFGuard, s as createLoggerBackedRuntime, t as SsrFBlockedError } from "./runtime-api-Dq8wkBC_.js";
2
+ import { t as tlonPlugin } from "./channel-Bvzym9ez.js";
3
+ import { n as setTlonRuntime } from "./runtime-BmSb9A-q.js";
4
+ export { SsrFBlockedError, createDedupeCache, createLoggerBackedRuntime, fetchWithSsrFGuard, isBlockedHostnameOrIp, setTlonRuntime, ssrfPolicyFromAllowPrivateNetwork, ssrfPolicyFromDangerouslyAllowPrivateNetwork, tlonPlugin };
@@ -0,0 +1,236 @@
1
+ import { n as normalizeCompatibilityConfig, t as legacyConfigRules } from "./doctor-contract-Ip6FcHDH.js";
2
+ import { a as tlonSetupAdapter, d as formatTargetHint, f as normalizeShip, h as resolveTlonOutboundTarget, l as listTlonAccountIds, m as parseTlonTarget, n as createTlonSetupWizardBase, u as resolveTlonAccount } from "./setup-core-CF3ryHqs.js";
3
+ import { buildChannelOutboundSessionRoute } from "klaw/plugin-sdk/core";
4
+ import { describeAccountSnapshot } from "klaw/plugin-sdk/account-helpers";
5
+ import { DEFAULT_ACCOUNT_ID } from "klaw/plugin-sdk/account-id";
6
+ import { createHybridChannelConfigAdapter } from "klaw/plugin-sdk/channel-config-helpers";
7
+ import { createChatChannelPlugin } from "klaw/plugin-sdk/channel-core";
8
+ import { createChannelMessageAdapterFromOutbound } from "klaw/plugin-sdk/channel-message";
9
+ import { createLazyRuntimeModule } from "klaw/plugin-sdk/lazy-runtime";
10
+ import { createRuntimeOutboundDelegates } from "klaw/plugin-sdk/outbound-runtime";
11
+ import { createComputedAccountStatusAdapter, createDefaultChannelRuntimeState } from "klaw/plugin-sdk/status-helpers";
12
+ import { buildChannelConfigSchema } from "klaw/plugin-sdk/channel-config-schema";
13
+ import { z } from "zod";
14
+ //#region extensions/tlon/src/config-schema.ts
15
+ const ShipSchema = z.string().min(1);
16
+ const ChannelNestSchema = z.string().min(1);
17
+ const TlonChannelRuleSchema = z.object({
18
+ mode: z.enum(["restricted", "open"]).optional(),
19
+ allowedShips: z.array(ShipSchema).optional()
20
+ });
21
+ const TlonAuthorizationSchema = z.object({ channelRules: z.record(z.string(), TlonChannelRuleSchema).optional() });
22
+ const TlonNetworkSchema = z.object({ dangerouslyAllowPrivateNetwork: z.boolean().optional() }).strict().optional();
23
+ const tlonCommonConfigFields = {
24
+ name: z.string().optional(),
25
+ enabled: z.boolean().optional(),
26
+ ship: ShipSchema.optional(),
27
+ url: z.string().optional(),
28
+ code: z.string().optional(),
29
+ network: TlonNetworkSchema,
30
+ groupChannels: z.array(ChannelNestSchema).optional(),
31
+ dmAllowlist: z.array(ShipSchema).optional(),
32
+ groupInviteAllowlist: z.array(ShipSchema).optional(),
33
+ autoDiscoverChannels: z.boolean().optional(),
34
+ showModelSignature: z.boolean().optional(),
35
+ responsePrefix: z.string().optional(),
36
+ autoAcceptDmInvites: z.boolean().optional(),
37
+ autoAcceptGroupInvites: z.boolean().optional(),
38
+ ownerShip: ShipSchema.optional()
39
+ };
40
+ const TlonAccountSchema = z.object({ ...tlonCommonConfigFields });
41
+ const tlonChannelConfigSchema = buildChannelConfigSchema(z.object({
42
+ ...tlonCommonConfigFields,
43
+ authorization: TlonAuthorizationSchema.optional(),
44
+ defaultAuthorizedShips: z.array(ShipSchema).optional(),
45
+ accounts: z.record(z.string(), TlonAccountSchema).optional()
46
+ }));
47
+ //#endregion
48
+ //#region extensions/tlon/src/doctor.ts
49
+ const tlonDoctor = {
50
+ legacyConfigRules,
51
+ normalizeCompatibilityConfig
52
+ };
53
+ //#endregion
54
+ //#region extensions/tlon/src/session-route.ts
55
+ function resolveTlonOutboundSessionRoute(params) {
56
+ const parsed = parseTlonTarget(params.target);
57
+ if (!parsed) return null;
58
+ if (parsed.kind === "group") return buildChannelOutboundSessionRoute({
59
+ cfg: params.cfg,
60
+ agentId: params.agentId,
61
+ channel: "tlon",
62
+ accountId: params.accountId,
63
+ peer: {
64
+ kind: "group",
65
+ id: parsed.nest
66
+ },
67
+ chatType: "group",
68
+ from: `tlon:group:${parsed.nest}`,
69
+ to: `tlon:${parsed.nest}`
70
+ });
71
+ return buildChannelOutboundSessionRoute({
72
+ cfg: params.cfg,
73
+ agentId: params.agentId,
74
+ channel: "tlon",
75
+ accountId: params.accountId,
76
+ peer: {
77
+ kind: "direct",
78
+ id: parsed.ship
79
+ },
80
+ chatType: "direct",
81
+ from: `tlon:${parsed.ship}`,
82
+ to: `tlon:${parsed.ship}`
83
+ });
84
+ }
85
+ //#endregion
86
+ //#region extensions/tlon/src/channel.ts
87
+ const TLON_CHANNEL_ID = "tlon";
88
+ const loadTlonChannelRuntime = createLazyRuntimeModule(() => import("./channel.runtime-CDY2BdfM.js"));
89
+ const tlonSetupWizardProxy = createTlonSetupWizardBase({
90
+ resolveConfigured: async ({ cfg, accountId }) => await (await loadTlonChannelRuntime()).tlonSetupWizard.status.resolveConfigured({
91
+ cfg,
92
+ accountId
93
+ }),
94
+ resolveStatusLines: async ({ cfg, accountId, configured }) => await (await loadTlonChannelRuntime()).tlonSetupWizard.status.resolveStatusLines?.({
95
+ cfg,
96
+ accountId,
97
+ configured
98
+ }) ?? [],
99
+ finalize: async (params) => await (await loadTlonChannelRuntime()).tlonSetupWizard.finalize(params)
100
+ });
101
+ const tlonConfigAdapter = createHybridChannelConfigAdapter({
102
+ sectionKey: TLON_CHANNEL_ID,
103
+ listAccountIds: listTlonAccountIds,
104
+ resolveAccount: resolveTlonAccount,
105
+ defaultAccountId: () => DEFAULT_ACCOUNT_ID,
106
+ clearBaseFields: [
107
+ "ship",
108
+ "code",
109
+ "url",
110
+ "name"
111
+ ],
112
+ preserveSectionOnDefaultDelete: true,
113
+ resolveAllowFrom: (account) => account.dmAllowlist,
114
+ formatAllowFrom: (allowFrom) => allowFrom.map((entry) => normalizeShip(String(entry))).filter(Boolean)
115
+ });
116
+ const tlonChannelOutbound = {
117
+ deliveryMode: "direct",
118
+ textChunkLimit: 1e4,
119
+ resolveTarget: ({ to }) => resolveTlonOutboundTarget(to),
120
+ deliveryCapabilities: { durableFinal: {
121
+ text: true,
122
+ media: true,
123
+ replyTo: true,
124
+ thread: true,
125
+ messageSendingHooks: true
126
+ } },
127
+ ...createRuntimeOutboundDelegates({
128
+ getRuntime: loadTlonChannelRuntime,
129
+ sendText: { resolve: (runtime) => runtime.tlonRuntimeOutbound.sendText },
130
+ sendMedia: { resolve: (runtime) => runtime.tlonRuntimeOutbound.sendMedia }
131
+ })
132
+ };
133
+ const tlonMessageAdapter = createChannelMessageAdapterFromOutbound({
134
+ id: TLON_CHANNEL_ID,
135
+ outbound: tlonChannelOutbound
136
+ });
137
+ const tlonPlugin = createChatChannelPlugin({
138
+ base: {
139
+ id: TLON_CHANNEL_ID,
140
+ meta: {
141
+ id: TLON_CHANNEL_ID,
142
+ label: "Tlon",
143
+ selectionLabel: "Tlon (Urbit)",
144
+ docsPath: "/channels/tlon",
145
+ docsLabel: "tlon",
146
+ blurb: "Decentralized messaging on Urbit",
147
+ aliases: ["urbit"],
148
+ order: 90
149
+ },
150
+ capabilities: {
151
+ chatTypes: [
152
+ "direct",
153
+ "group",
154
+ "thread"
155
+ ],
156
+ media: true,
157
+ reply: true,
158
+ threads: true
159
+ },
160
+ setup: tlonSetupAdapter,
161
+ setupWizard: tlonSetupWizardProxy,
162
+ reload: { configPrefixes: ["channels.tlon"] },
163
+ configSchema: tlonChannelConfigSchema,
164
+ config: {
165
+ ...tlonConfigAdapter,
166
+ isConfigured: (account) => account.configured,
167
+ describeAccount: (account) => describeAccountSnapshot({
168
+ account,
169
+ configured: account.configured,
170
+ extra: {
171
+ ship: account.ship,
172
+ url: account.url
173
+ }
174
+ })
175
+ },
176
+ doctor: tlonDoctor,
177
+ messaging: {
178
+ targetPrefixes: ["tlon"],
179
+ normalizeTarget: (target) => {
180
+ const parsed = parseTlonTarget(target);
181
+ if (!parsed) return target.trim();
182
+ if (parsed.kind === "dm") return parsed.ship;
183
+ return parsed.nest;
184
+ },
185
+ targetResolver: {
186
+ looksLikeId: (target) => Boolean(parseTlonTarget(target)),
187
+ hint: formatTargetHint()
188
+ },
189
+ resolveOutboundSessionRoute: (params) => resolveTlonOutboundSessionRoute(params)
190
+ },
191
+ message: tlonMessageAdapter,
192
+ status: createComputedAccountStatusAdapter({
193
+ defaultRuntime: createDefaultChannelRuntimeState(DEFAULT_ACCOUNT_ID),
194
+ collectStatusIssues: (accounts) => {
195
+ return accounts.flatMap((account) => {
196
+ if (!account.configured) return [{
197
+ channel: TLON_CHANNEL_ID,
198
+ accountId: account.accountId,
199
+ kind: "config",
200
+ message: "Account not configured (missing ship, code, or url)"
201
+ }];
202
+ return [];
203
+ });
204
+ },
205
+ buildChannelSummary: ({ snapshot }) => {
206
+ const s = snapshot;
207
+ return {
208
+ configured: s.configured ?? false,
209
+ ship: s.ship ?? null,
210
+ url: s.url ?? null
211
+ };
212
+ },
213
+ probeAccount: async ({ account }) => {
214
+ if (!account.configured || !account.ship || !account.url || !account.code) return {
215
+ ok: false,
216
+ error: "Not configured"
217
+ };
218
+ return await (await loadTlonChannelRuntime()).probeTlonAccount(account);
219
+ },
220
+ resolveAccountSnapshot: ({ account }) => ({
221
+ accountId: account.accountId,
222
+ name: account.name ?? void 0,
223
+ enabled: account.enabled,
224
+ configured: account.configured,
225
+ extra: {
226
+ ship: account.ship,
227
+ url: account.url
228
+ }
229
+ })
230
+ }),
231
+ gateway: { startAccount: async (ctx) => await (await loadTlonChannelRuntime()).startTlonGatewayAccount(ctx) }
232
+ },
233
+ outbound: tlonChannelOutbound
234
+ });
235
+ //#endregion
236
+ export { tlonPlugin as t };
@@ -0,0 +1,2 @@
1
+ import { t as tlonPlugin } from "./channel-Bvzym9ez.js";
2
+ export { tlonPlugin };