@tloncorp/openclaw 0.1.0

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 (63) hide show
  1. package/README.md +174 -0
  2. package/dist/index.js +190 -0
  3. package/dist/index.js.map +1 -0
  4. package/dist/src/account-fields.js +17 -0
  5. package/dist/src/account-fields.js.map +1 -0
  6. package/dist/src/actions.js +164 -0
  7. package/dist/src/actions.js.map +1 -0
  8. package/dist/src/channel.js +400 -0
  9. package/dist/src/channel.js.map +1 -0
  10. package/dist/src/config-schema.js +55 -0
  11. package/dist/src/config-schema.js.map +1 -0
  12. package/dist/src/monitor/approval.js +194 -0
  13. package/dist/src/monitor/approval.js.map +1 -0
  14. package/dist/src/monitor/discovery.js +64 -0
  15. package/dist/src/monitor/discovery.js.map +1 -0
  16. package/dist/src/monitor/history.js +158 -0
  17. package/dist/src/monitor/history.js.map +1 -0
  18. package/dist/src/monitor/index.js +1940 -0
  19. package/dist/src/monitor/index.js.map +1 -0
  20. package/dist/src/monitor/media.js +128 -0
  21. package/dist/src/monitor/media.js.map +1 -0
  22. package/dist/src/monitor/processed-messages.js +38 -0
  23. package/dist/src/monitor/processed-messages.js.map +1 -0
  24. package/dist/src/monitor/utils.js +283 -0
  25. package/dist/src/monitor/utils.js.map +1 -0
  26. package/dist/src/onboarding.js +178 -0
  27. package/dist/src/onboarding.js.map +1 -0
  28. package/dist/src/runtime.js +11 -0
  29. package/dist/src/runtime.js.map +1 -0
  30. package/dist/src/settings.js +305 -0
  31. package/dist/src/settings.js.map +1 -0
  32. package/dist/src/targets.js +85 -0
  33. package/dist/src/targets.js.map +1 -0
  34. package/dist/src/types.js +79 -0
  35. package/dist/src/types.js.map +1 -0
  36. package/dist/src/urbit/api-client.js +104 -0
  37. package/dist/src/urbit/api-client.js.map +1 -0
  38. package/dist/src/urbit/auth.js +35 -0
  39. package/dist/src/urbit/auth.js.map +1 -0
  40. package/dist/src/urbit/base-url.js +45 -0
  41. package/dist/src/urbit/base-url.js.map +1 -0
  42. package/dist/src/urbit/channel-ops.js +136 -0
  43. package/dist/src/urbit/channel-ops.js.map +1 -0
  44. package/dist/src/urbit/context.js +42 -0
  45. package/dist/src/urbit/context.js.map +1 -0
  46. package/dist/src/urbit/errors.js +36 -0
  47. package/dist/src/urbit/errors.js.map +1 -0
  48. package/dist/src/urbit/fetch.js +23 -0
  49. package/dist/src/urbit/fetch.js.map +1 -0
  50. package/dist/src/urbit/foreigns.js +6 -0
  51. package/dist/src/urbit/foreigns.js.map +1 -0
  52. package/dist/src/urbit/http-poke.js +56 -0
  53. package/dist/src/urbit/http-poke.js.map +1 -0
  54. package/dist/src/urbit/send.js +208 -0
  55. package/dist/src/urbit/send.js.map +1 -0
  56. package/dist/src/urbit/sse-client.js +453 -0
  57. package/dist/src/urbit/sse-client.js.map +1 -0
  58. package/dist/src/urbit/story.js +286 -0
  59. package/dist/src/urbit/story.js.map +1 -0
  60. package/dist/src/urbit/upload.js +51 -0
  61. package/dist/src/urbit/upload.js.map +1 -0
  62. package/openclaw.plugin.json +10 -0
  63. package/package.json +84 -0
@@ -0,0 +1,178 @@
1
+ import { formatDocsLink, promptAccountId, DEFAULT_ACCOUNT_ID, normalizeAccountId, } from "openclaw/plugin-sdk";
2
+ import { buildTlonAccountFields } from "./account-fields.js";
3
+ import { listTlonAccountIds, resolveTlonAccount } from "./types.js";
4
+ import { isBlockedUrbitHostname, validateUrbitBaseUrl } from "./urbit/base-url.js";
5
+ const channel = "tlon";
6
+ function isConfigured(account) {
7
+ return Boolean(account.ship && account.url && account.code);
8
+ }
9
+ function applyAccountConfig(params) {
10
+ const { cfg, accountId, input } = params;
11
+ const useDefault = accountId === DEFAULT_ACCOUNT_ID;
12
+ const base = cfg.channels?.tlon ?? {};
13
+ const nextValues = {
14
+ enabled: true,
15
+ ...(input.name ? { name: input.name } : {}),
16
+ ...buildTlonAccountFields(input),
17
+ };
18
+ if (useDefault) {
19
+ return {
20
+ ...cfg,
21
+ channels: {
22
+ ...cfg.channels,
23
+ tlon: {
24
+ ...base,
25
+ ...nextValues,
26
+ },
27
+ },
28
+ };
29
+ }
30
+ return {
31
+ ...cfg,
32
+ channels: {
33
+ ...cfg.channels,
34
+ tlon: {
35
+ ...base,
36
+ enabled: base.enabled ?? true,
37
+ accounts: {
38
+ ...base.accounts,
39
+ [accountId]: {
40
+ ...base.accounts?.[accountId],
41
+ ...nextValues,
42
+ },
43
+ },
44
+ },
45
+ },
46
+ };
47
+ }
48
+ async function noteTlonHelp(prompter) {
49
+ await prompter.note([
50
+ "You need your Urbit ship URL and login code.",
51
+ "Example URL: https://your-ship-host",
52
+ "Example ship: ~sampel-palnet",
53
+ "If your ship URL is on a private network (LAN/localhost), you must explicitly allow it during setup.",
54
+ `Docs: ${formatDocsLink("/channels/tlon", "channels/tlon")}`,
55
+ ].join("\n"), "Tlon setup");
56
+ }
57
+ function parseList(value) {
58
+ return value
59
+ .split(/[\n,;]+/g)
60
+ .map((entry) => entry.trim())
61
+ .filter(Boolean);
62
+ }
63
+ export const tlonOnboardingAdapter = {
64
+ channel,
65
+ getStatus: async ({ cfg }) => {
66
+ const accountIds = listTlonAccountIds(cfg);
67
+ const configured = accountIds.length > 0
68
+ ? accountIds.some((accountId) => isConfigured(resolveTlonAccount(cfg, accountId)))
69
+ : isConfigured(resolveTlonAccount(cfg, DEFAULT_ACCOUNT_ID));
70
+ return {
71
+ channel,
72
+ configured,
73
+ statusLines: [`Tlon: ${configured ? "configured" : "needs setup"}`],
74
+ selectionHint: configured ? "configured" : "urbit messenger",
75
+ quickstartScore: configured ? 1 : 4,
76
+ };
77
+ },
78
+ configure: async ({ cfg, prompter, accountOverrides, shouldPromptAccountIds }) => {
79
+ const override = accountOverrides[channel]?.trim();
80
+ const defaultAccountId = DEFAULT_ACCOUNT_ID;
81
+ let accountId = override ? normalizeAccountId(override) : defaultAccountId;
82
+ if (shouldPromptAccountIds && !override) {
83
+ accountId = await promptAccountId({
84
+ cfg,
85
+ prompter,
86
+ label: "Tlon",
87
+ currentId: accountId,
88
+ listAccountIds: listTlonAccountIds,
89
+ defaultAccountId,
90
+ });
91
+ }
92
+ const resolved = resolveTlonAccount(cfg, accountId);
93
+ await noteTlonHelp(prompter);
94
+ const ship = await prompter.text({
95
+ message: "Ship name",
96
+ placeholder: "~sampel-palnet",
97
+ initialValue: resolved.ship ?? undefined,
98
+ validate: (value) => (String(value ?? "").trim() ? undefined : "Required"),
99
+ });
100
+ const url = await prompter.text({
101
+ message: "Ship URL",
102
+ placeholder: "https://your-ship-host",
103
+ initialValue: resolved.url ?? undefined,
104
+ validate: (value) => {
105
+ const next = validateUrbitBaseUrl(String(value ?? ""));
106
+ if (!next.ok) {
107
+ return next.error;
108
+ }
109
+ return undefined;
110
+ },
111
+ });
112
+ const validatedUrl = validateUrbitBaseUrl(String(url).trim());
113
+ if (!validatedUrl.ok) {
114
+ throw new Error(`Invalid URL: ${validatedUrl.error}`);
115
+ }
116
+ let allowPrivateNetwork = resolved.allowPrivateNetwork ?? false;
117
+ if (isBlockedUrbitHostname(validatedUrl.hostname)) {
118
+ allowPrivateNetwork = await prompter.confirm({
119
+ message: "Ship URL looks like a private/internal host. Allow private network access? (SSRF risk)",
120
+ initialValue: allowPrivateNetwork,
121
+ });
122
+ if (!allowPrivateNetwork) {
123
+ throw new Error("Refusing private/internal Ship URL without explicit approval");
124
+ }
125
+ }
126
+ const code = await prompter.text({
127
+ message: "Login code",
128
+ placeholder: "lidlut-tabwed-pillex-ridrup",
129
+ initialValue: resolved.code ?? undefined,
130
+ validate: (value) => (String(value ?? "").trim() ? undefined : "Required"),
131
+ });
132
+ const wantsGroupChannels = await prompter.confirm({
133
+ message: "Add group channels manually? (optional)",
134
+ initialValue: false,
135
+ });
136
+ let groupChannels;
137
+ if (wantsGroupChannels) {
138
+ const entry = await prompter.text({
139
+ message: "Group channels (comma-separated)",
140
+ placeholder: "chat/~host-ship/general, chat/~host-ship/support",
141
+ });
142
+ const parsed = parseList(String(entry ?? ""));
143
+ groupChannels = parsed.length > 0 ? parsed : undefined;
144
+ }
145
+ const wantsAllowlist = await prompter.confirm({
146
+ message: "Restrict DMs with an allowlist?",
147
+ initialValue: false,
148
+ });
149
+ let dmAllowlist;
150
+ if (wantsAllowlist) {
151
+ const entry = await prompter.text({
152
+ message: "DM allowlist (comma-separated ship names)",
153
+ placeholder: "~zod, ~nec",
154
+ });
155
+ const parsed = parseList(String(entry ?? ""));
156
+ dmAllowlist = parsed.length > 0 ? parsed : undefined;
157
+ }
158
+ const autoDiscoverChannels = await prompter.confirm({
159
+ message: "Enable auto-discovery of group channels?",
160
+ initialValue: resolved.autoDiscoverChannels ?? true,
161
+ });
162
+ const next = applyAccountConfig({
163
+ cfg,
164
+ accountId,
165
+ input: {
166
+ ship: String(ship).trim(),
167
+ url: String(url).trim(),
168
+ code: String(code).trim(),
169
+ allowPrivateNetwork,
170
+ groupChannels,
171
+ dmAllowlist,
172
+ autoDiscoverChannels,
173
+ },
174
+ });
175
+ return { cfg: next, accountId };
176
+ },
177
+ };
178
+ //# sourceMappingURL=onboarding.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"onboarding.js","sourceRoot":"","sources":["../../src/onboarding.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ let runtime = null;
2
+ export function setTlonRuntime(next) {
3
+ runtime = next;
4
+ }
5
+ export function getTlonRuntime() {
6
+ if (!runtime) {
7
+ throw new Error("Tlon runtime not initialized");
8
+ }
9
+ return runtime;
10
+ }
11
+ //# sourceMappingURL=runtime.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runtime.js","sourceRoot":"","sources":["../../src/runtime.ts"],"names":[],"mappings":"AAEA,IAAI,OAAO,GAAyB,IAAI,CAAC;AAEzC,MAAM,UAAU,cAAc,CAAC,IAAmB;IAChD,OAAO,GAAG,IAAI,CAAC;AACjB,CAAC;AAED,MAAM,UAAU,cAAc;IAC5B,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,MAAM,IAAI,KAAK,CAAC,8BAA8B,CAAC,CAAC;IAClD,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC"}
@@ -0,0 +1,305 @@
1
+ /**
2
+ * Settings Store integration for hot-reloading Tlon plugin config.
3
+ *
4
+ * Settings are stored in Urbit's %settings agent under:
5
+ * desk: "moltbot"
6
+ * bucket: "tlon"
7
+ *
8
+ * This allows config changes via poke from any Landscape client
9
+ * without requiring a gateway restart.
10
+ */
11
+ const SETTINGS_DESK = "moltbot";
12
+ const SETTINGS_BUCKET = "tlon";
13
+ /**
14
+ * Parse channelRules - handles both JSON string and object formats.
15
+ * Settings-store doesn't support nested objects, so we store as JSON string.
16
+ */
17
+ function parseChannelRules(value) {
18
+ if (!value) {
19
+ return undefined;
20
+ }
21
+ // If it's a string, try to parse as JSON
22
+ if (typeof value === "string") {
23
+ try {
24
+ const parsed = JSON.parse(value);
25
+ if (isChannelRulesObject(parsed)) {
26
+ return parsed;
27
+ }
28
+ }
29
+ catch {
30
+ return undefined;
31
+ }
32
+ }
33
+ // If it's already an object, use directly
34
+ if (isChannelRulesObject(value)) {
35
+ return value;
36
+ }
37
+ return undefined;
38
+ }
39
+ /**
40
+ * Parse settings from the raw Urbit settings-store response.
41
+ * The response shape is: { [bucket]: { [key]: value } }
42
+ */
43
+ export function parseSettingsResponse(raw) {
44
+ if (!raw || typeof raw !== "object") {
45
+ return {};
46
+ }
47
+ const desk = raw;
48
+ const bucket = desk[SETTINGS_BUCKET];
49
+ if (!bucket || typeof bucket !== "object") {
50
+ return {};
51
+ }
52
+ const settings = bucket;
53
+ return {
54
+ groupChannels: Array.isArray(settings.groupChannels)
55
+ ? settings.groupChannels.filter((x) => typeof x === "string")
56
+ : undefined,
57
+ dmAllowlist: Array.isArray(settings.dmAllowlist)
58
+ ? settings.dmAllowlist.filter((x) => typeof x === "string")
59
+ : undefined,
60
+ autoDiscover: typeof settings.autoDiscover === "boolean" ? settings.autoDiscover : undefined,
61
+ showModelSig: typeof settings.showModelSig === "boolean" ? settings.showModelSig : undefined,
62
+ autoAcceptDmInvites: typeof settings.autoAcceptDmInvites === "boolean" ? settings.autoAcceptDmInvites : undefined,
63
+ autoAcceptGroupInvites: typeof settings.autoAcceptGroupInvites === "boolean"
64
+ ? settings.autoAcceptGroupInvites
65
+ : undefined,
66
+ groupInviteAllowlist: Array.isArray(settings.groupInviteAllowlist)
67
+ ? settings.groupInviteAllowlist.filter((x) => typeof x === "string")
68
+ : undefined,
69
+ channelRules: parseChannelRules(settings.channelRules),
70
+ defaultAuthorizedShips: Array.isArray(settings.defaultAuthorizedShips)
71
+ ? settings.defaultAuthorizedShips.filter((x) => typeof x === "string")
72
+ : undefined,
73
+ ownerShip: typeof settings.ownerShip === "string" ? settings.ownerShip : undefined,
74
+ pendingApprovals: parsePendingApprovals(settings.pendingApprovals),
75
+ lastOwnerMessageAt: typeof settings.lastOwnerMessageAt === "number" ? settings.lastOwnerMessageAt : undefined,
76
+ lastOwnerMessageDate: typeof settings.lastOwnerMessageDate === "string" ? settings.lastOwnerMessageDate : undefined,
77
+ };
78
+ }
79
+ function isChannelRulesObject(val) {
80
+ if (!val || typeof val !== "object" || Array.isArray(val)) {
81
+ return false;
82
+ }
83
+ for (const [, rule] of Object.entries(val)) {
84
+ if (!rule || typeof rule !== "object") {
85
+ return false;
86
+ }
87
+ }
88
+ return true;
89
+ }
90
+ /**
91
+ * Parse pendingApprovals - handles both JSON string and array formats.
92
+ * Settings-store stores complex objects as JSON strings.
93
+ */
94
+ function parsePendingApprovals(value) {
95
+ if (!value) {
96
+ return undefined;
97
+ }
98
+ // If it's a string, try to parse as JSON
99
+ let parsed = value;
100
+ if (typeof value === "string") {
101
+ try {
102
+ parsed = JSON.parse(value);
103
+ }
104
+ catch {
105
+ return undefined;
106
+ }
107
+ }
108
+ // Validate it's an array
109
+ if (!Array.isArray(parsed)) {
110
+ return undefined;
111
+ }
112
+ // Filter to valid PendingApproval objects
113
+ return parsed.filter((item) => {
114
+ if (!item || typeof item !== "object") {
115
+ return false;
116
+ }
117
+ const obj = item;
118
+ return (typeof obj.id === "string" &&
119
+ (obj.type === "dm" || obj.type === "channel" || obj.type === "group") &&
120
+ typeof obj.requestingShip === "string" &&
121
+ typeof obj.timestamp === "number");
122
+ });
123
+ }
124
+ /**
125
+ * Parse a single settings entry update event.
126
+ */
127
+ function parseSettingsEvent(event) {
128
+ if (!event || typeof event !== "object") {
129
+ return null;
130
+ }
131
+ const evt = event;
132
+ // Handle put-entry events
133
+ if (evt["put-entry"]) {
134
+ const put = evt["put-entry"];
135
+ if (put.desk !== SETTINGS_DESK || put["bucket-key"] !== SETTINGS_BUCKET) {
136
+ return null;
137
+ }
138
+ return {
139
+ key: String(put["entry-key"] ?? ""),
140
+ value: put.value,
141
+ };
142
+ }
143
+ // Handle del-entry events
144
+ if (evt["del-entry"]) {
145
+ const del = evt["del-entry"];
146
+ if (del.desk !== SETTINGS_DESK || del["bucket-key"] !== SETTINGS_BUCKET) {
147
+ return null;
148
+ }
149
+ return {
150
+ key: String(del["entry-key"] ?? ""),
151
+ value: undefined,
152
+ };
153
+ }
154
+ return null;
155
+ }
156
+ /**
157
+ * Apply a single settings update to the current state.
158
+ */
159
+ export function applySettingsUpdate(current, key, value) {
160
+ const next = { ...current };
161
+ switch (key) {
162
+ case "groupChannels":
163
+ next.groupChannels = Array.isArray(value)
164
+ ? value.filter((x) => typeof x === "string")
165
+ : undefined;
166
+ break;
167
+ case "dmAllowlist":
168
+ next.dmAllowlist = Array.isArray(value)
169
+ ? value.filter((x) => typeof x === "string")
170
+ : undefined;
171
+ break;
172
+ case "autoDiscover":
173
+ next.autoDiscover = typeof value === "boolean" ? value : undefined;
174
+ break;
175
+ case "showModelSig":
176
+ next.showModelSig = typeof value === "boolean" ? value : undefined;
177
+ break;
178
+ case "autoAcceptDmInvites":
179
+ next.autoAcceptDmInvites = typeof value === "boolean" ? value : undefined;
180
+ break;
181
+ case "autoAcceptGroupInvites":
182
+ next.autoAcceptGroupInvites = typeof value === "boolean" ? value : undefined;
183
+ break;
184
+ case "groupInviteAllowlist":
185
+ next.groupInviteAllowlist = Array.isArray(value)
186
+ ? value.filter((x) => typeof x === "string")
187
+ : undefined;
188
+ break;
189
+ case "channelRules":
190
+ next.channelRules = parseChannelRules(value);
191
+ break;
192
+ case "defaultAuthorizedShips":
193
+ next.defaultAuthorizedShips = Array.isArray(value)
194
+ ? value.filter((x) => typeof x === "string")
195
+ : undefined;
196
+ break;
197
+ case "ownerShip":
198
+ next.ownerShip = typeof value === "string" ? value : undefined;
199
+ break;
200
+ case "pendingApprovals":
201
+ next.pendingApprovals = parsePendingApprovals(value);
202
+ break;
203
+ case "lastOwnerMessageAt":
204
+ next.lastOwnerMessageAt = typeof value === "number" ? value : undefined;
205
+ break;
206
+ case "lastOwnerMessageDate":
207
+ next.lastOwnerMessageDate = typeof value === "string" ? value : undefined;
208
+ break;
209
+ }
210
+ return next;
211
+ }
212
+ /**
213
+ * Create a settings store subscription manager.
214
+ *
215
+ * Usage:
216
+ * const settings = createSettingsManager(api, logger);
217
+ * await settings.load();
218
+ * settings.subscribe((newSettings) => { ... });
219
+ */
220
+ export function createSettingsManager(api, logger) {
221
+ let state = {
222
+ current: {},
223
+ loaded: false,
224
+ };
225
+ const listeners = new Set();
226
+ const notify = () => {
227
+ for (const listener of listeners) {
228
+ try {
229
+ listener(state.current);
230
+ }
231
+ catch (err) {
232
+ logger?.error?.(`[settings] Listener error: ${String(err)}`);
233
+ }
234
+ }
235
+ };
236
+ return {
237
+ /**
238
+ * Get current settings (may be empty if not loaded yet).
239
+ */
240
+ get current() {
241
+ return state.current;
242
+ },
243
+ /**
244
+ * Whether initial settings have been loaded.
245
+ */
246
+ get loaded() {
247
+ return state.loaded;
248
+ },
249
+ /**
250
+ * Load initial settings via scry.
251
+ */
252
+ async load() {
253
+ try {
254
+ const raw = await api.scry("/settings/all.json");
255
+ // Response shape: { all: { [desk]: { [bucket]: { [key]: value } } } }
256
+ const allData = raw;
257
+ const deskData = allData?.all?.[SETTINGS_DESK];
258
+ state.current = parseSettingsResponse(deskData ?? {});
259
+ state.loaded = true;
260
+ logger?.log?.(`[settings] Loaded: ${JSON.stringify(state.current)}`);
261
+ return state.current;
262
+ }
263
+ catch (err) {
264
+ // Settings desk may not exist yet - that's fine, use defaults
265
+ logger?.log?.(`[settings] No settings found (using defaults): ${String(err)}`);
266
+ state.current = {};
267
+ state.loaded = true;
268
+ return state.current;
269
+ }
270
+ },
271
+ /**
272
+ * Subscribe to settings changes.
273
+ */
274
+ async startSubscription() {
275
+ await api.subscribe({
276
+ app: "settings",
277
+ path: "/desk/" + SETTINGS_DESK,
278
+ event: (event) => {
279
+ const update = parseSettingsEvent(event);
280
+ if (!update) {
281
+ return;
282
+ }
283
+ logger?.log?.(`[settings] Update: ${update.key} = ${JSON.stringify(update.value)}`);
284
+ state.current = applySettingsUpdate(state.current, update.key, update.value);
285
+ notify();
286
+ },
287
+ err: (error) => {
288
+ logger?.error?.(`[settings] Subscription error: ${String(error)}`);
289
+ },
290
+ quit: () => {
291
+ logger?.log?.("[settings] Subscription ended");
292
+ },
293
+ });
294
+ logger?.log?.("[settings] Subscribed to settings updates");
295
+ },
296
+ /**
297
+ * Register a listener for settings changes.
298
+ */
299
+ onChange(listener) {
300
+ listeners.add(listener);
301
+ return () => listeners.delete(listener);
302
+ },
303
+ };
304
+ }
305
+ //# sourceMappingURL=settings.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"settings.js","sourceRoot":"","sources":["../../src/settings.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,85 @@
1
+ const SHIP_RE = /^~?[a-z-]+$/i;
2
+ const NEST_RE = /^(chat|heap|diary)\/([^/]+)\/([^/]+)$/i;
3
+ export function normalizeShip(raw) {
4
+ const trimmed = raw.trim();
5
+ if (!trimmed) {
6
+ return trimmed;
7
+ }
8
+ return trimmed.startsWith("~") ? trimmed : `~${trimmed}`;
9
+ }
10
+ export function parseNest(raw) {
11
+ const match = NEST_RE.exec(raw.trim());
12
+ if (!match) {
13
+ return null;
14
+ }
15
+ return {
16
+ nestPrefix: match[1].toLowerCase(),
17
+ hostShip: normalizeShip(match[2]),
18
+ channelName: match[3],
19
+ };
20
+ }
21
+ export function parseChannelNest(raw) {
22
+ const result = parseNest(raw);
23
+ if (!result) {
24
+ return null;
25
+ }
26
+ return { hostShip: result.hostShip, channelName: result.channelName };
27
+ }
28
+ export function parseTlonTarget(raw) {
29
+ const trimmed = raw?.trim();
30
+ if (!trimmed) {
31
+ return null;
32
+ }
33
+ const withoutPrefix = trimmed.replace(/^tlon:/i, "");
34
+ // DM targets: dm/~ship or dm:~ship
35
+ const dmPrefix = withoutPrefix.match(/^dm[/:](.+)$/i);
36
+ if (dmPrefix) {
37
+ return { kind: "dm", ship: normalizeShip(dmPrefix[1]) };
38
+ }
39
+ // Group/room prefix: group:chat/~host/channel or room:~host/channel
40
+ const groupPrefix = withoutPrefix.match(/^(group|room)[/:](.+)$/i);
41
+ if (groupPrefix) {
42
+ const groupTarget = groupPrefix[2].trim();
43
+ const parsedNest = parseNest(groupTarget);
44
+ if (parsedNest) {
45
+ return {
46
+ kind: "channel",
47
+ nest: `${parsedNest.nestPrefix}/${parsedNest.hostShip}/${parsedNest.channelName}`,
48
+ hostShip: parsedNest.hostShip,
49
+ channelName: parsedNest.channelName,
50
+ };
51
+ }
52
+ // Legacy format: group:~host/channel (defaults to chat)
53
+ const parts = groupTarget.split("/");
54
+ if (parts.length === 2) {
55
+ const hostShip = normalizeShip(parts[0]);
56
+ const channelName = parts[1];
57
+ return {
58
+ kind: "channel",
59
+ nest: `chat/${hostShip}/${channelName}`,
60
+ hostShip,
61
+ channelName,
62
+ };
63
+ }
64
+ return null;
65
+ }
66
+ // Direct nest format: chat/~host/channel, heap/~host/channel, diary/~host/channel
67
+ const parsedNest = parseNest(withoutPrefix);
68
+ if (parsedNest) {
69
+ return {
70
+ kind: "channel",
71
+ nest: `${parsedNest.nestPrefix}/${parsedNest.hostShip}/${parsedNest.channelName}`,
72
+ hostShip: parsedNest.hostShip,
73
+ channelName: parsedNest.channelName,
74
+ };
75
+ }
76
+ // Bare ship name: treat as DM
77
+ if (SHIP_RE.test(withoutPrefix)) {
78
+ return { kind: "dm", ship: normalizeShip(withoutPrefix) };
79
+ }
80
+ return null;
81
+ }
82
+ export function formatTargetHint() {
83
+ return "dm/~ship | ~ship | chat/~host/channel | heap/~host/channel | diary/~host/channel";
84
+ }
85
+ //# sourceMappingURL=targets.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"targets.js","sourceRoot":"","sources":["../../src/targets.ts"],"names":[],"mappings":"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"}