@shadowob/shared 1.1.7 → 1.1.9
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/dist/{chunk-EXZEQO5X.js → chunk-KKRZTKE6.js} +12 -59
- package/dist/chunk-X6FS22AL.js +175 -0
- package/dist/index.cjs +198 -60
- package/dist/index.d.cts +3 -3
- package/dist/index.d.ts +3 -3
- package/dist/index.js +29 -4
- package/dist/{message.types-TGJmaffM.d.cts → message.types-D5IHsEOR.d.cts} +122 -1
- package/dist/{message.types-TGJmaffM.d.ts → message.types-D5IHsEOR.d.ts} +122 -1
- package/dist/play-catalog/index.cjs +12 -60
- package/dist/play-catalog/index.d.cts +1 -13
- package/dist/play-catalog/index.d.ts +1 -13
- package/dist/play-catalog/index.js +1 -3
- package/dist/types/index.cjs +195 -0
- package/dist/types/index.d.cts +66 -2
- package/dist/types/index.d.ts +66 -2
- package/dist/types/index.js +30 -1
- package/dist/utils/index.d.cts +1 -1
- package/dist/utils/index.d.ts +1 -1
- package/package.json +1 -1
- package/dist/chunk-6H4LIJZC.js +0 -0
|
@@ -8,24 +8,21 @@ var playTemplate = (id) => ({
|
|
|
8
8
|
},
|
|
9
9
|
materials: { cover: playCover(id) }
|
|
10
10
|
});
|
|
11
|
-
var communityAction = (channelName
|
|
11
|
+
var communityAction = (channelName) => ({
|
|
12
12
|
kind: "public_channel",
|
|
13
13
|
channelName,
|
|
14
|
-
buddyTemplateSlug: channelName
|
|
15
|
-
...greeting ? { greeting } : {}
|
|
14
|
+
buddyTemplateSlug: channelName
|
|
16
15
|
});
|
|
17
|
-
var roomAction = (namePrefix
|
|
16
|
+
var roomAction = (namePrefix) => ({
|
|
18
17
|
kind: "private_room",
|
|
19
18
|
namePrefix,
|
|
20
|
-
buddyTemplateSlug: namePrefix
|
|
21
|
-
...greeting ? { greeting } : {}
|
|
19
|
+
buddyTemplateSlug: namePrefix
|
|
22
20
|
});
|
|
23
|
-
var cloudAction = (templateSlug, resourceTier = "lightweight"
|
|
21
|
+
var cloudAction = (templateSlug, resourceTier = "lightweight") => ({
|
|
24
22
|
kind: "cloud_deploy",
|
|
25
23
|
templateSlug,
|
|
26
24
|
buddyTemplateSlug: templateSlug,
|
|
27
|
-
resourceTier
|
|
28
|
-
...defaultChannelName ? { defaultChannelName } : {}
|
|
25
|
+
resourceTier
|
|
29
26
|
});
|
|
30
27
|
function getPlayBuddyUsername(templateSlug) {
|
|
31
28
|
const normalized = templateSlug.trim().toLowerCase().replace(/[^a-z0-9]+/g, "_").replace(/^_+|_+$/g, "").slice(0, 27) || "play";
|
|
@@ -34,55 +31,15 @@ function getPlayBuddyUsername(templateSlug) {
|
|
|
34
31
|
function getPlayBuddyEmail(templateSlug) {
|
|
35
32
|
return `${getPlayBuddyUsername(templateSlug)}@shadowob.bot`;
|
|
36
33
|
}
|
|
37
|
-
var SHADOW_PLAY_SERVER_TEMPLATE = {
|
|
38
|
-
slug: "shadow-plays",
|
|
39
|
-
name: "Shadow Plays",
|
|
40
|
-
description: "Default public community space for launchable homepage plays.",
|
|
41
|
-
channels: [
|
|
42
|
-
{
|
|
43
|
-
name: "general",
|
|
44
|
-
topic: "General discussion for new players and Shadow community members."
|
|
45
|
-
},
|
|
46
|
-
{
|
|
47
|
-
name: "world-pulse",
|
|
48
|
-
topic: "A public room for real-time global events and daily signal."
|
|
49
|
-
},
|
|
50
|
-
{
|
|
51
|
-
name: "financial-freedom",
|
|
52
|
-
topic: "A public room for lightweight financial freedom simulations and planning prompts."
|
|
53
|
-
},
|
|
54
|
-
{
|
|
55
|
-
name: "ai-werewolf",
|
|
56
|
-
topic: "A public room for AI-hosted social deduction sessions."
|
|
57
|
-
},
|
|
58
|
-
{
|
|
59
|
-
name: "code-arena",
|
|
60
|
-
topic: "A public room for coding challenges and real-time battles."
|
|
61
|
-
},
|
|
62
|
-
{
|
|
63
|
-
name: "brain-fix",
|
|
64
|
-
topic: "A calm public room for one-minute focus resets and reflection."
|
|
65
|
-
},
|
|
66
|
-
{
|
|
67
|
-
name: "gitstory",
|
|
68
|
-
topic: "A public room for turning software history into stories and retrospectives."
|
|
69
|
-
},
|
|
70
|
-
{
|
|
71
|
-
name: "gstack",
|
|
72
|
-
topic: "A public room for founder strategy, product stress tests, and launch planning."
|
|
73
|
-
}
|
|
74
|
-
]
|
|
75
|
-
};
|
|
76
34
|
function cloudPlay(id, input) {
|
|
77
|
-
const { defaultChannelName, ...content } = input;
|
|
78
35
|
return {
|
|
79
36
|
id,
|
|
80
37
|
image: playCover(id),
|
|
81
38
|
status: "gated",
|
|
82
|
-
action: cloudAction(id, "lightweight"
|
|
39
|
+
action: cloudAction(id, "lightweight"),
|
|
83
40
|
gates: { auth: "required", membership: "required", profile: "optional" },
|
|
84
41
|
...playTemplate(id),
|
|
85
|
-
...
|
|
42
|
+
...input
|
|
86
43
|
};
|
|
87
44
|
}
|
|
88
45
|
var DEFAULT_HOMEPLAY_CATALOG = [
|
|
@@ -246,7 +203,7 @@ var DEFAULT_HOMEPLAY_CATALOG = [
|
|
|
246
203
|
accentColor: "#f59e0b",
|
|
247
204
|
hot: true,
|
|
248
205
|
status: "gated",
|
|
249
|
-
action: cloudAction("little-match-girl", "lightweight"
|
|
206
|
+
action: cloudAction("little-match-girl", "lightweight"),
|
|
250
207
|
gates: { auth: "required", membership: "required", profile: "optional" },
|
|
251
208
|
...playTemplate("little-match-girl"),
|
|
252
209
|
materials: { cover: "/home-assets/topics/night-radio.jpg" }
|
|
@@ -260,8 +217,7 @@ var DEFAULT_HOMEPLAY_CATALOG = [
|
|
|
260
217
|
categoryEn: "Buddy Teams",
|
|
261
218
|
starts: "16.4k",
|
|
262
219
|
accentColor: "#22d3ee",
|
|
263
|
-
hot: true
|
|
264
|
-
defaultChannelName: "choose"
|
|
220
|
+
hot: true
|
|
265
221
|
}),
|
|
266
222
|
cloudPlay("bmad-method-buddy", {
|
|
267
223
|
title: "BMAD \u65B9\u6CD5 Buddy",
|
|
@@ -271,8 +227,7 @@ var DEFAULT_HOMEPLAY_CATALOG = [
|
|
|
271
227
|
category: "Buddy \u56E2\u961F",
|
|
272
228
|
categoryEn: "Buddy Teams",
|
|
273
229
|
starts: "13.7k",
|
|
274
|
-
accentColor: "#60a5fa"
|
|
275
|
-
defaultChannelName: "delivery"
|
|
230
|
+
accentColor: "#60a5fa"
|
|
276
231
|
}),
|
|
277
232
|
cloudPlay("claude-ads-buddy", {
|
|
278
233
|
title: "Claude Ads Buddy",
|
|
@@ -335,8 +290,7 @@ var DEFAULT_HOMEPLAY_CATALOG = [
|
|
|
335
290
|
categoryEn: "Hacker & Painter",
|
|
336
291
|
starts: "15.1k",
|
|
337
292
|
accentColor: "#fb923c",
|
|
338
|
-
hot: true
|
|
339
|
-
defaultChannelName: "office-hours"
|
|
293
|
+
hot: true
|
|
340
294
|
}),
|
|
341
295
|
cloudPlay("marketingskills-buddy", {
|
|
342
296
|
title: "\u8425\u9500\u6280\u80FD Buddy",
|
|
@@ -423,7 +377,6 @@ function getDefaultHomePlay(playId) {
|
|
|
423
377
|
export {
|
|
424
378
|
getPlayBuddyUsername,
|
|
425
379
|
getPlayBuddyEmail,
|
|
426
|
-
SHADOW_PLAY_SERVER_TEMPLATE,
|
|
427
380
|
DEFAULT_HOMEPLAY_CATALOG,
|
|
428
381
|
getDefaultHomePlay
|
|
429
382
|
};
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
// src/types/inbox.types.ts
|
|
2
|
+
var BUDDY_INBOX_TOPIC_PREFIX = "shadow:buddy-inbox:";
|
|
3
|
+
function buddyInboxTopic(agentId) {
|
|
4
|
+
return `${BUDDY_INBOX_TOPIC_PREFIX}${agentId}`;
|
|
5
|
+
}
|
|
6
|
+
function parseBuddyInboxAgentId(topic) {
|
|
7
|
+
if (!topic?.startsWith(BUDDY_INBOX_TOPIC_PREFIX)) return null;
|
|
8
|
+
const agentId = topic.slice(BUDDY_INBOX_TOPIC_PREFIX.length).trim();
|
|
9
|
+
return agentId || null;
|
|
10
|
+
}
|
|
11
|
+
function isBuddyInboxTopic(topic) {
|
|
12
|
+
return parseBuddyInboxAgentId(topic) !== null;
|
|
13
|
+
}
|
|
14
|
+
var TASK_MESSAGE_CARD_STATUSES = [
|
|
15
|
+
"queued",
|
|
16
|
+
"claimed",
|
|
17
|
+
"running",
|
|
18
|
+
"completed",
|
|
19
|
+
"failed",
|
|
20
|
+
"canceled",
|
|
21
|
+
"transferred"
|
|
22
|
+
];
|
|
23
|
+
var TERMINAL_TASK_MESSAGE_CARD_STATUSES = [
|
|
24
|
+
"completed",
|
|
25
|
+
"failed",
|
|
26
|
+
"canceled",
|
|
27
|
+
"transferred"
|
|
28
|
+
];
|
|
29
|
+
var TASK_MESSAGE_CARD_STATUS_TRANSITIONS = {
|
|
30
|
+
queued: ["queued", "claimed", "running", "completed", "failed", "canceled"],
|
|
31
|
+
claimed: ["claimed", "running", "completed", "failed", "canceled"],
|
|
32
|
+
running: ["running", "completed", "failed", "canceled"],
|
|
33
|
+
completed: ["completed"],
|
|
34
|
+
failed: ["failed", "transferred"],
|
|
35
|
+
canceled: ["canceled"],
|
|
36
|
+
transferred: ["transferred"]
|
|
37
|
+
};
|
|
38
|
+
function isTerminalTaskMessageCardStatus(status) {
|
|
39
|
+
return TERMINAL_TASK_MESSAGE_CARD_STATUSES.includes(
|
|
40
|
+
status
|
|
41
|
+
);
|
|
42
|
+
}
|
|
43
|
+
function canTransitionTaskMessageCardStatus(from, to) {
|
|
44
|
+
const allowed = TASK_MESSAGE_CARD_STATUS_TRANSITIONS[from];
|
|
45
|
+
return allowed.includes(to);
|
|
46
|
+
}
|
|
47
|
+
var DEFAULT_BUDDY_INBOX_ADMISSION_POLICY = {
|
|
48
|
+
defaultMode: "allow",
|
|
49
|
+
rules: []
|
|
50
|
+
};
|
|
51
|
+
function isRecord(value) {
|
|
52
|
+
return !!value && typeof value === "object" && !Array.isArray(value);
|
|
53
|
+
}
|
|
54
|
+
function parseAdmissionMode(value, fallback) {
|
|
55
|
+
if (value === "allow" || value === "deny" || value === "first_time" || value === "every_time") {
|
|
56
|
+
return value;
|
|
57
|
+
}
|
|
58
|
+
if (value === void 0 || value === null) return fallback;
|
|
59
|
+
throw new Error("Invalid Buddy Inbox admission mode");
|
|
60
|
+
}
|
|
61
|
+
function parseSubjectKind(value) {
|
|
62
|
+
if (value === "user" || value === "agent" || value === "server_app" || value === "system") {
|
|
63
|
+
return value;
|
|
64
|
+
}
|
|
65
|
+
throw new Error("Invalid Buddy Inbox admission subject kind");
|
|
66
|
+
}
|
|
67
|
+
function parseOptionalString(value, field, maxLength) {
|
|
68
|
+
if (value === void 0 || value === null || value === "") return void 0;
|
|
69
|
+
if (typeof value !== "string" || value.length > maxLength) {
|
|
70
|
+
throw new Error(`Invalid Buddy Inbox admission ${field}`);
|
|
71
|
+
}
|
|
72
|
+
return value;
|
|
73
|
+
}
|
|
74
|
+
function normalizeBuddyInboxAdmissionPolicy(value) {
|
|
75
|
+
if (value === void 0 || value === null) return { ...DEFAULT_BUDDY_INBOX_ADMISSION_POLICY };
|
|
76
|
+
if (!isRecord(value)) throw new Error("Invalid Buddy Inbox admission policy");
|
|
77
|
+
const defaultMode = parseAdmissionMode(value.defaultMode, "allow");
|
|
78
|
+
const rawRules = value.rules;
|
|
79
|
+
if (rawRules !== void 0 && !Array.isArray(rawRules)) {
|
|
80
|
+
throw new Error("Invalid Buddy Inbox admission rules");
|
|
81
|
+
}
|
|
82
|
+
const rules = (rawRules ?? []).slice(0, 100).map((entry) => {
|
|
83
|
+
if (!isRecord(entry)) throw new Error("Invalid Buddy Inbox admission rule");
|
|
84
|
+
return {
|
|
85
|
+
subjectKind: parseSubjectKind(entry.subjectKind),
|
|
86
|
+
subjectId: parseOptionalString(entry.subjectId, "subjectId", 160),
|
|
87
|
+
appKey: parseOptionalString(entry.appKey, "appKey", 120),
|
|
88
|
+
mode: parseAdmissionMode(entry.mode, defaultMode),
|
|
89
|
+
...entry.approved === true ? { approved: true } : {},
|
|
90
|
+
note: parseOptionalString(entry.note, "note", 500),
|
|
91
|
+
createdAt: parseOptionalString(entry.createdAt, "createdAt", 64),
|
|
92
|
+
updatedAt: parseOptionalString(entry.updatedAt, "updatedAt", 64)
|
|
93
|
+
};
|
|
94
|
+
});
|
|
95
|
+
return { defaultMode, rules };
|
|
96
|
+
}
|
|
97
|
+
function buddyInboxAdmissionRuleKey(rule) {
|
|
98
|
+
return [rule.subjectKind, rule.subjectId ?? "", rule.appKey ?? ""].join(":");
|
|
99
|
+
}
|
|
100
|
+
function parsePendingTask(value) {
|
|
101
|
+
if (!isRecord(value)) throw new Error("Invalid Buddy Inbox pending task");
|
|
102
|
+
const title = parseOptionalString(value.title, "task.title", 180);
|
|
103
|
+
if (!title) throw new Error("Invalid Buddy Inbox pending task title");
|
|
104
|
+
const body = parseOptionalString(value.body, "task.body", 8e3);
|
|
105
|
+
const priority = value.priority;
|
|
106
|
+
if (priority !== void 0 && priority !== "low" && priority !== "normal" && priority !== "high" && priority !== "urgent") {
|
|
107
|
+
throw new Error("Invalid Buddy Inbox pending task priority");
|
|
108
|
+
}
|
|
109
|
+
const idempotencyKey = parseOptionalString(value.idempotencyKey, "task.idempotencyKey", 240);
|
|
110
|
+
const source = isRecord(value.source) ? value.source : void 0;
|
|
111
|
+
const data = isRecord(value.data) ? value.data : void 0;
|
|
112
|
+
return {
|
|
113
|
+
title,
|
|
114
|
+
...body ? { body } : {},
|
|
115
|
+
...priority ? { priority } : {},
|
|
116
|
+
...idempotencyKey ? { idempotencyKey } : {},
|
|
117
|
+
...source ? { source } : {},
|
|
118
|
+
...data ? { data } : {}
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
function normalizeBuddyInboxAdmissionPendingDeliveries(value) {
|
|
122
|
+
if (value === void 0 || value === null) return [];
|
|
123
|
+
if (!Array.isArray(value)) throw new Error("Invalid Buddy Inbox pending deliveries");
|
|
124
|
+
return value.slice(0, 100).map((entry) => {
|
|
125
|
+
if (!isRecord(entry)) throw new Error("Invalid Buddy Inbox pending delivery");
|
|
126
|
+
const id = parseOptionalString(entry.id, "pending.id", 80);
|
|
127
|
+
const serverId = parseOptionalString(entry.serverId, "pending.serverId", 160);
|
|
128
|
+
const channelId = parseOptionalString(entry.channelId, "pending.channelId", 160);
|
|
129
|
+
const agentId = parseOptionalString(entry.agentId, "pending.agentId", 160);
|
|
130
|
+
const mode = parseAdmissionMode(entry.mode, "first_time");
|
|
131
|
+
if (mode !== "first_time" && mode !== "every_time") {
|
|
132
|
+
throw new Error("Invalid Buddy Inbox pending mode");
|
|
133
|
+
}
|
|
134
|
+
if (!isRecord(entry.subject)) throw new Error("Invalid Buddy Inbox pending subject");
|
|
135
|
+
if (!isRecord(entry.requestedBy)) throw new Error("Invalid Buddy Inbox pending requester");
|
|
136
|
+
if (!id || !serverId || !channelId || !agentId) {
|
|
137
|
+
throw new Error("Invalid Buddy Inbox pending delivery identifiers");
|
|
138
|
+
}
|
|
139
|
+
const requestedAt = parseOptionalString(entry.requestedAt, "pending.requestedAt", 64);
|
|
140
|
+
if (!requestedAt) throw new Error("Invalid Buddy Inbox pending requestedAt");
|
|
141
|
+
return {
|
|
142
|
+
id,
|
|
143
|
+
serverId,
|
|
144
|
+
channelId,
|
|
145
|
+
agentId,
|
|
146
|
+
mode,
|
|
147
|
+
subject: {
|
|
148
|
+
kind: parseSubjectKind(entry.subject.kind),
|
|
149
|
+
id: parseOptionalString(entry.subject.id, "subject.id", 160),
|
|
150
|
+
appKey: parseOptionalString(entry.subject.appKey, "subject.appKey", 120),
|
|
151
|
+
label: parseOptionalString(entry.subject.label, "subject.label", 160)
|
|
152
|
+
},
|
|
153
|
+
task: parsePendingTask(entry.task),
|
|
154
|
+
requestedBy: entry.requestedBy,
|
|
155
|
+
requestedAt,
|
|
156
|
+
updatedAt: parseOptionalString(entry.updatedAt, "pending.updatedAt", 64)
|
|
157
|
+
};
|
|
158
|
+
});
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
export {
|
|
162
|
+
BUDDY_INBOX_TOPIC_PREFIX,
|
|
163
|
+
buddyInboxTopic,
|
|
164
|
+
parseBuddyInboxAgentId,
|
|
165
|
+
isBuddyInboxTopic,
|
|
166
|
+
TASK_MESSAGE_CARD_STATUSES,
|
|
167
|
+
TERMINAL_TASK_MESSAGE_CARD_STATUSES,
|
|
168
|
+
TASK_MESSAGE_CARD_STATUS_TRANSITIONS,
|
|
169
|
+
isTerminalTaskMessageCardStatus,
|
|
170
|
+
canTransitionTaskMessageCardStatus,
|
|
171
|
+
DEFAULT_BUDDY_INBOX_ADMISSION_POLICY,
|
|
172
|
+
normalizeBuddyInboxAdmissionPolicy,
|
|
173
|
+
buddyInboxAdmissionRuleKey,
|
|
174
|
+
normalizeBuddyInboxAdmissionPendingDeliveries
|
|
175
|
+
};
|
package/dist/index.cjs
CHANGED
|
@@ -20,14 +20,21 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
20
20
|
// src/index.ts
|
|
21
21
|
var index_exports = {};
|
|
22
22
|
__export(index_exports, {
|
|
23
|
+
BUDDY_INBOX_TOPIC_PREFIX: () => BUDDY_INBOX_TOPIC_PREFIX,
|
|
23
24
|
CAT_AVATAR_COUNT: () => CAT_AVATAR_COUNT,
|
|
24
25
|
CLIENT_EVENTS: () => CLIENT_EVENTS,
|
|
26
|
+
DEFAULT_BUDDY_INBOX_ADMISSION_POLICY: () => DEFAULT_BUDDY_INBOX_ADMISSION_POLICY,
|
|
25
27
|
DEFAULT_HOMEPLAY_CATALOG: () => DEFAULT_HOMEPLAY_CATALOG,
|
|
26
28
|
LIMITS: () => LIMITS,
|
|
27
29
|
SERVER_EVENTS: () => SERVER_EVENTS,
|
|
28
|
-
|
|
30
|
+
TASK_MESSAGE_CARD_STATUSES: () => TASK_MESSAGE_CARD_STATUSES,
|
|
31
|
+
TASK_MESSAGE_CARD_STATUS_TRANSITIONS: () => TASK_MESSAGE_CARD_STATUS_TRANSITIONS,
|
|
32
|
+
TERMINAL_TASK_MESSAGE_CARD_STATUSES: () => TERMINAL_TASK_MESSAGE_CARD_STATUSES,
|
|
29
33
|
assignMentionRanges: () => assignMentionRanges,
|
|
34
|
+
buddyInboxAdmissionRuleKey: () => buddyInboxAdmissionRuleKey,
|
|
35
|
+
buddyInboxTopic: () => buddyInboxTopic,
|
|
30
36
|
buildMentionMarkdownLinks: () => buildMentionMarkdownLinks,
|
|
37
|
+
canTransitionTaskMessageCardStatus: () => canTransitionTaskMessageCardStatus,
|
|
31
38
|
canonicalMentionToken: () => canonicalMentionToken,
|
|
32
39
|
canonicalizeMentionContent: () => canonicalizeMentionContent,
|
|
33
40
|
escapeMarkdownLinkLabel: () => escapeMarkdownLinkLabel,
|
|
@@ -41,9 +48,14 @@ __export(index_exports, {
|
|
|
41
48
|
getDefaultHomePlay: () => getDefaultHomePlay,
|
|
42
49
|
getPlayBuddyEmail: () => getPlayBuddyEmail,
|
|
43
50
|
getPlayBuddyUsername: () => getPlayBuddyUsername,
|
|
51
|
+
isBuddyInboxTopic: () => isBuddyInboxTopic,
|
|
44
52
|
isCanonicalMentionToken: () => isCanonicalMentionToken,
|
|
53
|
+
isTerminalTaskMessageCardStatus: () => isTerminalTaskMessageCardStatus,
|
|
45
54
|
isValidEmail: () => isValidEmail,
|
|
46
55
|
mentionDisplayText: () => mentionDisplayText,
|
|
56
|
+
normalizeBuddyInboxAdmissionPendingDeliveries: () => normalizeBuddyInboxAdmissionPendingDeliveries,
|
|
57
|
+
normalizeBuddyInboxAdmissionPolicy: () => normalizeBuddyInboxAdmissionPolicy,
|
|
58
|
+
parseBuddyInboxAgentId: () => parseBuddyInboxAgentId,
|
|
47
59
|
parseCanonicalMentionToken: () => parseCanonicalMentionToken,
|
|
48
60
|
renderCatSvg: () => renderCatSvg,
|
|
49
61
|
segmentTextByMentions: () => segmentTextByMentions,
|
|
@@ -124,24 +136,21 @@ var playTemplate = (id) => ({
|
|
|
124
136
|
},
|
|
125
137
|
materials: { cover: playCover(id) }
|
|
126
138
|
});
|
|
127
|
-
var communityAction = (channelName
|
|
139
|
+
var communityAction = (channelName) => ({
|
|
128
140
|
kind: "public_channel",
|
|
129
141
|
channelName,
|
|
130
|
-
buddyTemplateSlug: channelName
|
|
131
|
-
...greeting ? { greeting } : {}
|
|
142
|
+
buddyTemplateSlug: channelName
|
|
132
143
|
});
|
|
133
|
-
var roomAction = (namePrefix
|
|
144
|
+
var roomAction = (namePrefix) => ({
|
|
134
145
|
kind: "private_room",
|
|
135
146
|
namePrefix,
|
|
136
|
-
buddyTemplateSlug: namePrefix
|
|
137
|
-
...greeting ? { greeting } : {}
|
|
147
|
+
buddyTemplateSlug: namePrefix
|
|
138
148
|
});
|
|
139
|
-
var cloudAction = (templateSlug, resourceTier = "lightweight"
|
|
149
|
+
var cloudAction = (templateSlug, resourceTier = "lightweight") => ({
|
|
140
150
|
kind: "cloud_deploy",
|
|
141
151
|
templateSlug,
|
|
142
152
|
buddyTemplateSlug: templateSlug,
|
|
143
|
-
resourceTier
|
|
144
|
-
...defaultChannelName ? { defaultChannelName } : {}
|
|
153
|
+
resourceTier
|
|
145
154
|
});
|
|
146
155
|
function getPlayBuddyUsername(templateSlug) {
|
|
147
156
|
const normalized = templateSlug.trim().toLowerCase().replace(/[^a-z0-9]+/g, "_").replace(/^_+|_+$/g, "").slice(0, 27) || "play";
|
|
@@ -150,55 +159,15 @@ function getPlayBuddyUsername(templateSlug) {
|
|
|
150
159
|
function getPlayBuddyEmail(templateSlug) {
|
|
151
160
|
return `${getPlayBuddyUsername(templateSlug)}@shadowob.bot`;
|
|
152
161
|
}
|
|
153
|
-
var SHADOW_PLAY_SERVER_TEMPLATE = {
|
|
154
|
-
slug: "shadow-plays",
|
|
155
|
-
name: "Shadow Plays",
|
|
156
|
-
description: "Default public community space for launchable homepage plays.",
|
|
157
|
-
channels: [
|
|
158
|
-
{
|
|
159
|
-
name: "general",
|
|
160
|
-
topic: "General discussion for new players and Shadow community members."
|
|
161
|
-
},
|
|
162
|
-
{
|
|
163
|
-
name: "world-pulse",
|
|
164
|
-
topic: "A public room for real-time global events and daily signal."
|
|
165
|
-
},
|
|
166
|
-
{
|
|
167
|
-
name: "financial-freedom",
|
|
168
|
-
topic: "A public room for lightweight financial freedom simulations and planning prompts."
|
|
169
|
-
},
|
|
170
|
-
{
|
|
171
|
-
name: "ai-werewolf",
|
|
172
|
-
topic: "A public room for AI-hosted social deduction sessions."
|
|
173
|
-
},
|
|
174
|
-
{
|
|
175
|
-
name: "code-arena",
|
|
176
|
-
topic: "A public room for coding challenges and real-time battles."
|
|
177
|
-
},
|
|
178
|
-
{
|
|
179
|
-
name: "brain-fix",
|
|
180
|
-
topic: "A calm public room for one-minute focus resets and reflection."
|
|
181
|
-
},
|
|
182
|
-
{
|
|
183
|
-
name: "gitstory",
|
|
184
|
-
topic: "A public room for turning software history into stories and retrospectives."
|
|
185
|
-
},
|
|
186
|
-
{
|
|
187
|
-
name: "gstack",
|
|
188
|
-
topic: "A public room for founder strategy, product stress tests, and launch planning."
|
|
189
|
-
}
|
|
190
|
-
]
|
|
191
|
-
};
|
|
192
162
|
function cloudPlay(id, input) {
|
|
193
|
-
const { defaultChannelName, ...content } = input;
|
|
194
163
|
return {
|
|
195
164
|
id,
|
|
196
165
|
image: playCover(id),
|
|
197
166
|
status: "gated",
|
|
198
|
-
action: cloudAction(id, "lightweight"
|
|
167
|
+
action: cloudAction(id, "lightweight"),
|
|
199
168
|
gates: { auth: "required", membership: "required", profile: "optional" },
|
|
200
169
|
...playTemplate(id),
|
|
201
|
-
...
|
|
170
|
+
...input
|
|
202
171
|
};
|
|
203
172
|
}
|
|
204
173
|
var DEFAULT_HOMEPLAY_CATALOG = [
|
|
@@ -362,7 +331,7 @@ var DEFAULT_HOMEPLAY_CATALOG = [
|
|
|
362
331
|
accentColor: "#f59e0b",
|
|
363
332
|
hot: true,
|
|
364
333
|
status: "gated",
|
|
365
|
-
action: cloudAction("little-match-girl", "lightweight"
|
|
334
|
+
action: cloudAction("little-match-girl", "lightweight"),
|
|
366
335
|
gates: { auth: "required", membership: "required", profile: "optional" },
|
|
367
336
|
...playTemplate("little-match-girl"),
|
|
368
337
|
materials: { cover: "/home-assets/topics/night-radio.jpg" }
|
|
@@ -376,8 +345,7 @@ var DEFAULT_HOMEPLAY_CATALOG = [
|
|
|
376
345
|
categoryEn: "Buddy Teams",
|
|
377
346
|
starts: "16.4k",
|
|
378
347
|
accentColor: "#22d3ee",
|
|
379
|
-
hot: true
|
|
380
|
-
defaultChannelName: "choose"
|
|
348
|
+
hot: true
|
|
381
349
|
}),
|
|
382
350
|
cloudPlay("bmad-method-buddy", {
|
|
383
351
|
title: "BMAD \u65B9\u6CD5 Buddy",
|
|
@@ -387,8 +355,7 @@ var DEFAULT_HOMEPLAY_CATALOG = [
|
|
|
387
355
|
category: "Buddy \u56E2\u961F",
|
|
388
356
|
categoryEn: "Buddy Teams",
|
|
389
357
|
starts: "13.7k",
|
|
390
|
-
accentColor: "#60a5fa"
|
|
391
|
-
defaultChannelName: "delivery"
|
|
358
|
+
accentColor: "#60a5fa"
|
|
392
359
|
}),
|
|
393
360
|
cloudPlay("claude-ads-buddy", {
|
|
394
361
|
title: "Claude Ads Buddy",
|
|
@@ -451,8 +418,7 @@ var DEFAULT_HOMEPLAY_CATALOG = [
|
|
|
451
418
|
categoryEn: "Hacker & Painter",
|
|
452
419
|
starts: "15.1k",
|
|
453
420
|
accentColor: "#fb923c",
|
|
454
|
-
hot: true
|
|
455
|
-
defaultChannelName: "office-hours"
|
|
421
|
+
hot: true
|
|
456
422
|
}),
|
|
457
423
|
cloudPlay("marketingskills-buddy", {
|
|
458
424
|
title: "\u8425\u9500\u6280\u80FD Buddy",
|
|
@@ -536,6 +502,166 @@ function getDefaultHomePlay(playId) {
|
|
|
536
502
|
return DEFAULT_HOMEPLAY_CATALOG.find((play) => play.id === playId) ?? null;
|
|
537
503
|
}
|
|
538
504
|
|
|
505
|
+
// src/types/inbox.types.ts
|
|
506
|
+
var BUDDY_INBOX_TOPIC_PREFIX = "shadow:buddy-inbox:";
|
|
507
|
+
function buddyInboxTopic(agentId) {
|
|
508
|
+
return `${BUDDY_INBOX_TOPIC_PREFIX}${agentId}`;
|
|
509
|
+
}
|
|
510
|
+
function parseBuddyInboxAgentId(topic) {
|
|
511
|
+
if (!topic?.startsWith(BUDDY_INBOX_TOPIC_PREFIX)) return null;
|
|
512
|
+
const agentId = topic.slice(BUDDY_INBOX_TOPIC_PREFIX.length).trim();
|
|
513
|
+
return agentId || null;
|
|
514
|
+
}
|
|
515
|
+
function isBuddyInboxTopic(topic) {
|
|
516
|
+
return parseBuddyInboxAgentId(topic) !== null;
|
|
517
|
+
}
|
|
518
|
+
var TASK_MESSAGE_CARD_STATUSES = [
|
|
519
|
+
"queued",
|
|
520
|
+
"claimed",
|
|
521
|
+
"running",
|
|
522
|
+
"completed",
|
|
523
|
+
"failed",
|
|
524
|
+
"canceled",
|
|
525
|
+
"transferred"
|
|
526
|
+
];
|
|
527
|
+
var TERMINAL_TASK_MESSAGE_CARD_STATUSES = [
|
|
528
|
+
"completed",
|
|
529
|
+
"failed",
|
|
530
|
+
"canceled",
|
|
531
|
+
"transferred"
|
|
532
|
+
];
|
|
533
|
+
var TASK_MESSAGE_CARD_STATUS_TRANSITIONS = {
|
|
534
|
+
queued: ["queued", "claimed", "running", "completed", "failed", "canceled"],
|
|
535
|
+
claimed: ["claimed", "running", "completed", "failed", "canceled"],
|
|
536
|
+
running: ["running", "completed", "failed", "canceled"],
|
|
537
|
+
completed: ["completed"],
|
|
538
|
+
failed: ["failed", "transferred"],
|
|
539
|
+
canceled: ["canceled"],
|
|
540
|
+
transferred: ["transferred"]
|
|
541
|
+
};
|
|
542
|
+
function isTerminalTaskMessageCardStatus(status) {
|
|
543
|
+
return TERMINAL_TASK_MESSAGE_CARD_STATUSES.includes(
|
|
544
|
+
status
|
|
545
|
+
);
|
|
546
|
+
}
|
|
547
|
+
function canTransitionTaskMessageCardStatus(from, to) {
|
|
548
|
+
const allowed = TASK_MESSAGE_CARD_STATUS_TRANSITIONS[from];
|
|
549
|
+
return allowed.includes(to);
|
|
550
|
+
}
|
|
551
|
+
var DEFAULT_BUDDY_INBOX_ADMISSION_POLICY = {
|
|
552
|
+
defaultMode: "allow",
|
|
553
|
+
rules: []
|
|
554
|
+
};
|
|
555
|
+
function isRecord(value) {
|
|
556
|
+
return !!value && typeof value === "object" && !Array.isArray(value);
|
|
557
|
+
}
|
|
558
|
+
function parseAdmissionMode(value, fallback) {
|
|
559
|
+
if (value === "allow" || value === "deny" || value === "first_time" || value === "every_time") {
|
|
560
|
+
return value;
|
|
561
|
+
}
|
|
562
|
+
if (value === void 0 || value === null) return fallback;
|
|
563
|
+
throw new Error("Invalid Buddy Inbox admission mode");
|
|
564
|
+
}
|
|
565
|
+
function parseSubjectKind(value) {
|
|
566
|
+
if (value === "user" || value === "agent" || value === "server_app" || value === "system") {
|
|
567
|
+
return value;
|
|
568
|
+
}
|
|
569
|
+
throw new Error("Invalid Buddy Inbox admission subject kind");
|
|
570
|
+
}
|
|
571
|
+
function parseOptionalString(value, field, maxLength) {
|
|
572
|
+
if (value === void 0 || value === null || value === "") return void 0;
|
|
573
|
+
if (typeof value !== "string" || value.length > maxLength) {
|
|
574
|
+
throw new Error(`Invalid Buddy Inbox admission ${field}`);
|
|
575
|
+
}
|
|
576
|
+
return value;
|
|
577
|
+
}
|
|
578
|
+
function normalizeBuddyInboxAdmissionPolicy(value) {
|
|
579
|
+
if (value === void 0 || value === null) return { ...DEFAULT_BUDDY_INBOX_ADMISSION_POLICY };
|
|
580
|
+
if (!isRecord(value)) throw new Error("Invalid Buddy Inbox admission policy");
|
|
581
|
+
const defaultMode = parseAdmissionMode(value.defaultMode, "allow");
|
|
582
|
+
const rawRules = value.rules;
|
|
583
|
+
if (rawRules !== void 0 && !Array.isArray(rawRules)) {
|
|
584
|
+
throw new Error("Invalid Buddy Inbox admission rules");
|
|
585
|
+
}
|
|
586
|
+
const rules = (rawRules ?? []).slice(0, 100).map((entry) => {
|
|
587
|
+
if (!isRecord(entry)) throw new Error("Invalid Buddy Inbox admission rule");
|
|
588
|
+
return {
|
|
589
|
+
subjectKind: parseSubjectKind(entry.subjectKind),
|
|
590
|
+
subjectId: parseOptionalString(entry.subjectId, "subjectId", 160),
|
|
591
|
+
appKey: parseOptionalString(entry.appKey, "appKey", 120),
|
|
592
|
+
mode: parseAdmissionMode(entry.mode, defaultMode),
|
|
593
|
+
...entry.approved === true ? { approved: true } : {},
|
|
594
|
+
note: parseOptionalString(entry.note, "note", 500),
|
|
595
|
+
createdAt: parseOptionalString(entry.createdAt, "createdAt", 64),
|
|
596
|
+
updatedAt: parseOptionalString(entry.updatedAt, "updatedAt", 64)
|
|
597
|
+
};
|
|
598
|
+
});
|
|
599
|
+
return { defaultMode, rules };
|
|
600
|
+
}
|
|
601
|
+
function buddyInboxAdmissionRuleKey(rule) {
|
|
602
|
+
return [rule.subjectKind, rule.subjectId ?? "", rule.appKey ?? ""].join(":");
|
|
603
|
+
}
|
|
604
|
+
function parsePendingTask(value) {
|
|
605
|
+
if (!isRecord(value)) throw new Error("Invalid Buddy Inbox pending task");
|
|
606
|
+
const title = parseOptionalString(value.title, "task.title", 180);
|
|
607
|
+
if (!title) throw new Error("Invalid Buddy Inbox pending task title");
|
|
608
|
+
const body = parseOptionalString(value.body, "task.body", 8e3);
|
|
609
|
+
const priority = value.priority;
|
|
610
|
+
if (priority !== void 0 && priority !== "low" && priority !== "normal" && priority !== "high" && priority !== "urgent") {
|
|
611
|
+
throw new Error("Invalid Buddy Inbox pending task priority");
|
|
612
|
+
}
|
|
613
|
+
const idempotencyKey = parseOptionalString(value.idempotencyKey, "task.idempotencyKey", 240);
|
|
614
|
+
const source = isRecord(value.source) ? value.source : void 0;
|
|
615
|
+
const data = isRecord(value.data) ? value.data : void 0;
|
|
616
|
+
return {
|
|
617
|
+
title,
|
|
618
|
+
...body ? { body } : {},
|
|
619
|
+
...priority ? { priority } : {},
|
|
620
|
+
...idempotencyKey ? { idempotencyKey } : {},
|
|
621
|
+
...source ? { source } : {},
|
|
622
|
+
...data ? { data } : {}
|
|
623
|
+
};
|
|
624
|
+
}
|
|
625
|
+
function normalizeBuddyInboxAdmissionPendingDeliveries(value) {
|
|
626
|
+
if (value === void 0 || value === null) return [];
|
|
627
|
+
if (!Array.isArray(value)) throw new Error("Invalid Buddy Inbox pending deliveries");
|
|
628
|
+
return value.slice(0, 100).map((entry) => {
|
|
629
|
+
if (!isRecord(entry)) throw new Error("Invalid Buddy Inbox pending delivery");
|
|
630
|
+
const id = parseOptionalString(entry.id, "pending.id", 80);
|
|
631
|
+
const serverId = parseOptionalString(entry.serverId, "pending.serverId", 160);
|
|
632
|
+
const channelId = parseOptionalString(entry.channelId, "pending.channelId", 160);
|
|
633
|
+
const agentId = parseOptionalString(entry.agentId, "pending.agentId", 160);
|
|
634
|
+
const mode = parseAdmissionMode(entry.mode, "first_time");
|
|
635
|
+
if (mode !== "first_time" && mode !== "every_time") {
|
|
636
|
+
throw new Error("Invalid Buddy Inbox pending mode");
|
|
637
|
+
}
|
|
638
|
+
if (!isRecord(entry.subject)) throw new Error("Invalid Buddy Inbox pending subject");
|
|
639
|
+
if (!isRecord(entry.requestedBy)) throw new Error("Invalid Buddy Inbox pending requester");
|
|
640
|
+
if (!id || !serverId || !channelId || !agentId) {
|
|
641
|
+
throw new Error("Invalid Buddy Inbox pending delivery identifiers");
|
|
642
|
+
}
|
|
643
|
+
const requestedAt = parseOptionalString(entry.requestedAt, "pending.requestedAt", 64);
|
|
644
|
+
if (!requestedAt) throw new Error("Invalid Buddy Inbox pending requestedAt");
|
|
645
|
+
return {
|
|
646
|
+
id,
|
|
647
|
+
serverId,
|
|
648
|
+
channelId,
|
|
649
|
+
agentId,
|
|
650
|
+
mode,
|
|
651
|
+
subject: {
|
|
652
|
+
kind: parseSubjectKind(entry.subject.kind),
|
|
653
|
+
id: parseOptionalString(entry.subject.id, "subject.id", 160),
|
|
654
|
+
appKey: parseOptionalString(entry.subject.appKey, "subject.appKey", 120),
|
|
655
|
+
label: parseOptionalString(entry.subject.label, "subject.label", 160)
|
|
656
|
+
},
|
|
657
|
+
task: parsePendingTask(entry.task),
|
|
658
|
+
requestedBy: entry.requestedBy,
|
|
659
|
+
requestedAt,
|
|
660
|
+
updatedAt: parseOptionalString(entry.updatedAt, "pending.updatedAt", 64)
|
|
661
|
+
};
|
|
662
|
+
});
|
|
663
|
+
}
|
|
664
|
+
|
|
539
665
|
// src/utils/index.ts
|
|
540
666
|
var import_nanoid = require("nanoid");
|
|
541
667
|
|
|
@@ -1039,14 +1165,21 @@ function slugify(text) {
|
|
|
1039
1165
|
}
|
|
1040
1166
|
// Annotate the CommonJS export names for ESM import in node:
|
|
1041
1167
|
0 && (module.exports = {
|
|
1168
|
+
BUDDY_INBOX_TOPIC_PREFIX,
|
|
1042
1169
|
CAT_AVATAR_COUNT,
|
|
1043
1170
|
CLIENT_EVENTS,
|
|
1171
|
+
DEFAULT_BUDDY_INBOX_ADMISSION_POLICY,
|
|
1044
1172
|
DEFAULT_HOMEPLAY_CATALOG,
|
|
1045
1173
|
LIMITS,
|
|
1046
1174
|
SERVER_EVENTS,
|
|
1047
|
-
|
|
1175
|
+
TASK_MESSAGE_CARD_STATUSES,
|
|
1176
|
+
TASK_MESSAGE_CARD_STATUS_TRANSITIONS,
|
|
1177
|
+
TERMINAL_TASK_MESSAGE_CARD_STATUSES,
|
|
1048
1178
|
assignMentionRanges,
|
|
1179
|
+
buddyInboxAdmissionRuleKey,
|
|
1180
|
+
buddyInboxTopic,
|
|
1049
1181
|
buildMentionMarkdownLinks,
|
|
1182
|
+
canTransitionTaskMessageCardStatus,
|
|
1050
1183
|
canonicalMentionToken,
|
|
1051
1184
|
canonicalizeMentionContent,
|
|
1052
1185
|
escapeMarkdownLinkLabel,
|
|
@@ -1060,9 +1193,14 @@ function slugify(text) {
|
|
|
1060
1193
|
getDefaultHomePlay,
|
|
1061
1194
|
getPlayBuddyEmail,
|
|
1062
1195
|
getPlayBuddyUsername,
|
|
1196
|
+
isBuddyInboxTopic,
|
|
1063
1197
|
isCanonicalMentionToken,
|
|
1198
|
+
isTerminalTaskMessageCardStatus,
|
|
1064
1199
|
isValidEmail,
|
|
1065
1200
|
mentionDisplayText,
|
|
1201
|
+
normalizeBuddyInboxAdmissionPendingDeliveries,
|
|
1202
|
+
normalizeBuddyInboxAdmissionPolicy,
|
|
1203
|
+
parseBuddyInboxAgentId,
|
|
1066
1204
|
parseCanonicalMentionToken,
|
|
1067
1205
|
renderCatSvg,
|
|
1068
1206
|
segmentTextByMentions,
|