@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.
- package/README.md +174 -0
- package/dist/index.js +190 -0
- package/dist/index.js.map +1 -0
- package/dist/src/account-fields.js +17 -0
- package/dist/src/account-fields.js.map +1 -0
- package/dist/src/actions.js +164 -0
- package/dist/src/actions.js.map +1 -0
- package/dist/src/channel.js +400 -0
- package/dist/src/channel.js.map +1 -0
- package/dist/src/config-schema.js +55 -0
- package/dist/src/config-schema.js.map +1 -0
- package/dist/src/monitor/approval.js +194 -0
- package/dist/src/monitor/approval.js.map +1 -0
- package/dist/src/monitor/discovery.js +64 -0
- package/dist/src/monitor/discovery.js.map +1 -0
- package/dist/src/monitor/history.js +158 -0
- package/dist/src/monitor/history.js.map +1 -0
- package/dist/src/monitor/index.js +1940 -0
- package/dist/src/monitor/index.js.map +1 -0
- package/dist/src/monitor/media.js +128 -0
- package/dist/src/monitor/media.js.map +1 -0
- package/dist/src/monitor/processed-messages.js +38 -0
- package/dist/src/monitor/processed-messages.js.map +1 -0
- package/dist/src/monitor/utils.js +283 -0
- package/dist/src/monitor/utils.js.map +1 -0
- package/dist/src/onboarding.js +178 -0
- package/dist/src/onboarding.js.map +1 -0
- package/dist/src/runtime.js +11 -0
- package/dist/src/runtime.js.map +1 -0
- package/dist/src/settings.js +305 -0
- package/dist/src/settings.js.map +1 -0
- package/dist/src/targets.js +85 -0
- package/dist/src/targets.js.map +1 -0
- package/dist/src/types.js +79 -0
- package/dist/src/types.js.map +1 -0
- package/dist/src/urbit/api-client.js +104 -0
- package/dist/src/urbit/api-client.js.map +1 -0
- package/dist/src/urbit/auth.js +35 -0
- package/dist/src/urbit/auth.js.map +1 -0
- package/dist/src/urbit/base-url.js +45 -0
- package/dist/src/urbit/base-url.js.map +1 -0
- package/dist/src/urbit/channel-ops.js +136 -0
- package/dist/src/urbit/channel-ops.js.map +1 -0
- package/dist/src/urbit/context.js +42 -0
- package/dist/src/urbit/context.js.map +1 -0
- package/dist/src/urbit/errors.js +36 -0
- package/dist/src/urbit/errors.js.map +1 -0
- package/dist/src/urbit/fetch.js +23 -0
- package/dist/src/urbit/fetch.js.map +1 -0
- package/dist/src/urbit/foreigns.js +6 -0
- package/dist/src/urbit/foreigns.js.map +1 -0
- package/dist/src/urbit/http-poke.js +56 -0
- package/dist/src/urbit/http-poke.js.map +1 -0
- package/dist/src/urbit/send.js +208 -0
- package/dist/src/urbit/send.js.map +1 -0
- package/dist/src/urbit/sse-client.js +453 -0
- package/dist/src/urbit/sse-client.js.map +1 -0
- package/dist/src/urbit/story.js +286 -0
- package/dist/src/urbit/story.js.map +1 -0
- package/dist/src/urbit/upload.js +51 -0
- package/dist/src/urbit/upload.js.map +1 -0
- package/openclaw.plugin.json +10 -0
- 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 @@
|
|
|
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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"}
|