@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/klaw.plugin.json CHANGED
@@ -3,214 +3,14 @@
3
3
  "activation": {
4
4
  "onStartup": false
5
5
  },
6
- "channels": [
7
- "tlon"
8
- ],
6
+ "channels": ["tlon"],
9
7
  "contracts": {
10
- "tools": [
11
- "tlon"
12
- ]
8
+ "tools": ["tlon"]
13
9
  },
14
- "skills": [
15
- "./bundled-skills/@tloncorp/tlon-skill"
16
- ],
10
+ "skills": ["node_modules/@tloncorp/tlon-skill"],
17
11
  "configSchema": {
18
12
  "type": "object",
19
13
  "additionalProperties": false,
20
14
  "properties": {}
21
- },
22
- "channelConfigs": {
23
- "tlon": {
24
- "schema": {
25
- "$schema": "http://json-schema.org/draft-07/schema#",
26
- "type": "object",
27
- "properties": {
28
- "name": {
29
- "type": "string"
30
- },
31
- "enabled": {
32
- "type": "boolean"
33
- },
34
- "ship": {
35
- "type": "string",
36
- "minLength": 1
37
- },
38
- "url": {
39
- "type": "string"
40
- },
41
- "code": {
42
- "type": "string"
43
- },
44
- "network": {
45
- "type": "object",
46
- "properties": {
47
- "dangerouslyAllowPrivateNetwork": {
48
- "type": "boolean"
49
- }
50
- },
51
- "additionalProperties": false
52
- },
53
- "groupChannels": {
54
- "type": "array",
55
- "items": {
56
- "type": "string",
57
- "minLength": 1
58
- }
59
- },
60
- "dmAllowlist": {
61
- "type": "array",
62
- "items": {
63
- "type": "string",
64
- "minLength": 1
65
- }
66
- },
67
- "groupInviteAllowlist": {
68
- "type": "array",
69
- "items": {
70
- "type": "string",
71
- "minLength": 1
72
- }
73
- },
74
- "autoDiscoverChannels": {
75
- "type": "boolean"
76
- },
77
- "showModelSignature": {
78
- "type": "boolean"
79
- },
80
- "responsePrefix": {
81
- "type": "string"
82
- },
83
- "autoAcceptDmInvites": {
84
- "type": "boolean"
85
- },
86
- "autoAcceptGroupInvites": {
87
- "type": "boolean"
88
- },
89
- "ownerShip": {
90
- "type": "string",
91
- "minLength": 1
92
- },
93
- "authorization": {
94
- "type": "object",
95
- "properties": {
96
- "channelRules": {
97
- "type": "object",
98
- "propertyNames": {
99
- "type": "string"
100
- },
101
- "additionalProperties": {
102
- "type": "object",
103
- "properties": {
104
- "mode": {
105
- "type": "string",
106
- "enum": [
107
- "restricted",
108
- "open"
109
- ]
110
- },
111
- "allowedShips": {
112
- "type": "array",
113
- "items": {
114
- "type": "string",
115
- "minLength": 1
116
- }
117
- }
118
- },
119
- "additionalProperties": false
120
- }
121
- }
122
- },
123
- "additionalProperties": false
124
- },
125
- "defaultAuthorizedShips": {
126
- "type": "array",
127
- "items": {
128
- "type": "string",
129
- "minLength": 1
130
- }
131
- },
132
- "accounts": {
133
- "type": "object",
134
- "propertyNames": {
135
- "type": "string"
136
- },
137
- "additionalProperties": {
138
- "type": "object",
139
- "properties": {
140
- "name": {
141
- "type": "string"
142
- },
143
- "enabled": {
144
- "type": "boolean"
145
- },
146
- "ship": {
147
- "type": "string",
148
- "minLength": 1
149
- },
150
- "url": {
151
- "type": "string"
152
- },
153
- "code": {
154
- "type": "string"
155
- },
156
- "network": {
157
- "type": "object",
158
- "properties": {
159
- "dangerouslyAllowPrivateNetwork": {
160
- "type": "boolean"
161
- }
162
- },
163
- "additionalProperties": false
164
- },
165
- "groupChannels": {
166
- "type": "array",
167
- "items": {
168
- "type": "string",
169
- "minLength": 1
170
- }
171
- },
172
- "dmAllowlist": {
173
- "type": "array",
174
- "items": {
175
- "type": "string",
176
- "minLength": 1
177
- }
178
- },
179
- "groupInviteAllowlist": {
180
- "type": "array",
181
- "items": {
182
- "type": "string",
183
- "minLength": 1
184
- }
185
- },
186
- "autoDiscoverChannels": {
187
- "type": "boolean"
188
- },
189
- "showModelSignature": {
190
- "type": "boolean"
191
- },
192
- "responsePrefix": {
193
- "type": "string"
194
- },
195
- "autoAcceptDmInvites": {
196
- "type": "boolean"
197
- },
198
- "autoAcceptGroupInvites": {
199
- "type": "boolean"
200
- },
201
- "ownerShip": {
202
- "type": "string",
203
- "minLength": 1
204
- }
205
- },
206
- "additionalProperties": false
207
- }
208
- }
209
- },
210
- "additionalProperties": false
211
- },
212
- "label": "Tlon",
213
- "description": "decentralized messaging on Urbit; install the plugin to enable."
214
- }
215
15
  }
216
16
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kodelyth/tlon",
3
- "version": "2026.5.39",
3
+ "version": "2026.5.42",
4
4
  "description": "Klaw Tlon/Urbit channel plugin",
5
5
  "repository": {
6
6
  "type": "git",
@@ -16,7 +16,7 @@
16
16
  },
17
17
  "devDependencies": {
18
18
  "@kodelyth/plugin-sdk": "1.0.1",
19
- "@kodelyth/klaw": "2026.5.41"
19
+ "@kodelyth/klaw": "2026.5.42"
20
20
  },
21
21
  "peerDependencies": {
22
22
  "@kodelyth/klaw": ">=2026.5.19"
@@ -28,9 +28,9 @@
28
28
  },
29
29
  "klaw": {
30
30
  "extensions": [
31
- "./index.js"
31
+ "./index.ts"
32
32
  ],
33
- "setupEntry": "./setup-entry.js",
33
+ "setupEntry": "./setup-entry.ts",
34
34
  "channel": {
35
35
  "id": "tlon",
36
36
  "label": "Tlon",
package/runtime-api.ts ADDED
@@ -0,0 +1,17 @@
1
+ // Private runtime barrel for the bundled Tlon extension.
2
+ // Keep this barrel thin and aligned with the local extension surface.
3
+
4
+ export type { ReplyPayload } from "klaw/plugin-sdk/reply-runtime";
5
+ export type { KlawConfig } from "klaw/plugin-sdk/config-contracts";
6
+ export type { RuntimeEnv } from "klaw/plugin-sdk/runtime";
7
+ export { createDedupeCache } from "klaw/plugin-sdk/core";
8
+ export { createLoggerBackedRuntime } from "./src/logger-runtime.js";
9
+ export {
10
+ fetchWithSsrFGuard,
11
+ isBlockedHostnameOrIp,
12
+ ssrfPolicyFromAllowPrivateNetwork,
13
+ ssrfPolicyFromDangerouslyAllowPrivateNetwork,
14
+ type LookupFn,
15
+ type SsrFPolicy,
16
+ } from "klaw/plugin-sdk/ssrf-runtime";
17
+ export { SsrFBlockedError } from "klaw/plugin-sdk/ssrf-runtime";
package/setup-api.ts ADDED
@@ -0,0 +1,2 @@
1
+ export { tlonSetupAdapter } from "./src/setup-core.js";
2
+ export { tlonSetupWizard } from "./src/setup-surface.js";
package/setup-entry.ts ADDED
@@ -0,0 +1,9 @@
1
+ import { defineBundledChannelSetupEntry } from "klaw/plugin-sdk/channel-entry-contract";
2
+
3
+ export default defineBundledChannelSetupEntry({
4
+ importMetaUrl: import.meta.url,
5
+ plugin: {
6
+ specifier: "./api.js",
7
+ exportName: "tlonPlugin",
8
+ },
9
+ });
@@ -0,0 +1,31 @@
1
+ export type TlonAccountFieldsInput = {
2
+ ship?: string;
3
+ url?: string;
4
+ code?: string;
5
+ dangerouslyAllowPrivateNetwork?: boolean;
6
+ groupChannels?: string[];
7
+ dmAllowlist?: string[];
8
+ autoDiscoverChannels?: boolean;
9
+ ownerShip?: string;
10
+ };
11
+
12
+ export function buildTlonAccountFields(input: TlonAccountFieldsInput) {
13
+ return {
14
+ ...(input.ship ? { ship: input.ship } : {}),
15
+ ...(input.url ? { url: input.url } : {}),
16
+ ...(input.code ? { code: input.code } : {}),
17
+ ...(typeof input.dangerouslyAllowPrivateNetwork === "boolean"
18
+ ? {
19
+ network: {
20
+ dangerouslyAllowPrivateNetwork: input.dangerouslyAllowPrivateNetwork,
21
+ },
22
+ }
23
+ : {}),
24
+ ...(input.groupChannels ? { groupChannels: input.groupChannels } : {}),
25
+ ...(input.dmAllowlist ? { dmAllowlist: input.dmAllowlist } : {}),
26
+ ...(typeof input.autoDiscoverChannels === "boolean"
27
+ ? { autoDiscoverChannels: input.autoDiscoverChannels }
28
+ : {}),
29
+ ...(input.ownerShip ? { ownerShip: input.ownerShip } : {}),
30
+ };
31
+ }
@@ -0,0 +1,145 @@
1
+ import { verifyChannelMessageAdapterCapabilityProofs } from "klaw/plugin-sdk/channel-message";
2
+ import { beforeEach, describe, expect, it, vi } from "vitest";
3
+ import type { KlawConfig } from "../runtime-api.js";
4
+
5
+ const mocks = vi.hoisted(() => ({
6
+ sendText: vi.fn(),
7
+ sendMedia: vi.fn(),
8
+ }));
9
+
10
+ vi.mock("./channel.runtime.js", () => ({
11
+ tlonRuntimeOutbound: {
12
+ sendText: mocks.sendText,
13
+ sendMedia: mocks.sendMedia,
14
+ },
15
+ }));
16
+
17
+ import { tlonPlugin } from "./channel.js";
18
+
19
+ const cfg = {
20
+ channels: {
21
+ tlon: {
22
+ ship: "~zod",
23
+ url: "https://zod.example",
24
+ code: "lidlut-tabwed-pillex-ridrup",
25
+ },
26
+ },
27
+ } as KlawConfig;
28
+
29
+ describe("tlon channel message adapter", () => {
30
+ beforeEach(() => {
31
+ mocks.sendText.mockReset();
32
+ mocks.sendMedia.mockReset();
33
+ mocks.sendText.mockResolvedValue({
34
+ channel: "tlon",
35
+ messageId: "~zod/1700000000000",
36
+ conversationId: "~nec/general",
37
+ });
38
+ mocks.sendMedia.mockResolvedValue({
39
+ channel: "tlon",
40
+ messageId: "~zod/1700000000001",
41
+ conversationId: "~nec/general",
42
+ });
43
+ });
44
+
45
+ it("backs declared durable-final capabilities with outbound send proofs", async () => {
46
+ const adapter = tlonPlugin.message;
47
+ if (!adapter?.send?.text || !adapter.send.media) {
48
+ throw new Error("expected tlon channel message adapter with text and media senders");
49
+ }
50
+ const sendText = adapter.send.text;
51
+ const sendMedia = adapter.send.media;
52
+
53
+ const proveText = async () => {
54
+ mocks.sendText.mockClear();
55
+ const result = await sendText({
56
+ cfg,
57
+ to: "chat/~nec/general",
58
+ text: "hello",
59
+ accountId: "default",
60
+ });
61
+ expect(mocks.sendText).toHaveBeenLastCalledWith({
62
+ cfg,
63
+ to: "chat/~nec/general",
64
+ text: "hello",
65
+ accountId: "default",
66
+ replyToId: undefined,
67
+ threadId: undefined,
68
+ });
69
+ expect(result.receipt.platformMessageIds).toEqual(["~zod/1700000000000"]);
70
+ expect(result.receipt.parts[0]?.kind).toBe("text");
71
+ };
72
+
73
+ const proveMedia = async () => {
74
+ mocks.sendMedia.mockClear();
75
+ const result = await sendMedia({
76
+ cfg,
77
+ to: "chat/~nec/general",
78
+ text: "image",
79
+ mediaUrl: "https://example.com/image.png",
80
+ accountId: "default",
81
+ });
82
+ expect(mocks.sendMedia).toHaveBeenLastCalledWith({
83
+ cfg,
84
+ to: "chat/~nec/general",
85
+ text: "image",
86
+ mediaUrl: "https://example.com/image.png",
87
+ accountId: "default",
88
+ replyToId: undefined,
89
+ threadId: undefined,
90
+ });
91
+ expect(result.receipt.platformMessageIds).toEqual(["~zod/1700000000001"]);
92
+ expect(result.receipt.parts[0]?.kind).toBe("media");
93
+ };
94
+
95
+ const proveReplyThread = async () => {
96
+ mocks.sendText.mockClear();
97
+ const result = await sendText({
98
+ cfg,
99
+ to: "chat/~nec/general",
100
+ text: "threaded",
101
+ accountId: "default",
102
+ replyToId: "1700000000000",
103
+ threadId: "1700000000000",
104
+ });
105
+ expect(mocks.sendText).toHaveBeenLastCalledWith({
106
+ cfg,
107
+ to: "chat/~nec/general",
108
+ text: "threaded",
109
+ accountId: "default",
110
+ replyToId: "1700000000000",
111
+ threadId: "1700000000000",
112
+ });
113
+ expect(result.receipt.replyToId).toBe("1700000000000");
114
+ expect(result.receipt.threadId).toBe("1700000000000");
115
+ };
116
+
117
+ const proofs = await verifyChannelMessageAdapterCapabilityProofs({
118
+ adapterName: "tlonMessageAdapter",
119
+ adapter,
120
+ proofs: {
121
+ text: proveText,
122
+ media: proveMedia,
123
+ replyTo: proveReplyThread,
124
+ thread: proveReplyThread,
125
+ messageSendingHooks: () => {
126
+ expect(sendText).toBeTypeOf("function");
127
+ },
128
+ },
129
+ });
130
+ expect(proofs).toStrictEqual([
131
+ { capability: "text", status: "verified" },
132
+ { capability: "media", status: "verified" },
133
+ { capability: "payload", status: "not_declared" },
134
+ { capability: "silent", status: "not_declared" },
135
+ { capability: "replyTo", status: "verified" },
136
+ { capability: "thread", status: "verified" },
137
+ { capability: "nativeQuote", status: "not_declared" },
138
+ { capability: "messageSendingHooks", status: "verified" },
139
+ { capability: "batch", status: "not_declared" },
140
+ { capability: "reconcileUnknownSend", status: "not_declared" },
141
+ { capability: "afterSendSuccess", status: "not_declared" },
142
+ { capability: "afterCommit", status: "not_declared" },
143
+ ]);
144
+ });
145
+ });