@xmoxmo/bncr 0.5.2 → 0.5.3

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xmoxmo/bncr",
3
- "version": "0.5.2",
3
+ "version": "0.5.3",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -187,6 +187,7 @@ export function buildBncrPromptVisibleContextFacts(
187
187
  facts: ReturnType<typeof buildBncrStructuredContextFacts>,
188
188
  ) {
189
189
  const result: {
190
+ platform?: string;
190
191
  trigger?: {
191
192
  botName?: string;
192
193
  };
@@ -220,6 +221,10 @@ export function buildBncrPromptVisibleContextFacts(
220
221
  }>;
221
222
  } = {};
222
223
 
224
+ if (facts.platform) {
225
+ result.platform = `${facts.channel.id}/${facts.platform}`;
226
+ }
227
+
223
228
  if (
224
229
  facts.sender.isAdmin === true ||
225
230
  facts.sender.isOwner === true ||
@@ -52,8 +52,8 @@ const BNCR_HELP_TEXT = [
52
52
  ' • /bncr mode help',
53
53
  ' • /bncr mode <admin|mention|hybrid|all> [<SceneId>]',
54
54
  ' • /bncr revoke [<SceneId>]',
55
- ' • /bncr list pending',
56
- ' • /bncr list scenes',
55
+ ' • /bncr list pending [filters...]',
56
+ ' • /bncr list scenes [filters...]',
57
57
  '',
58
58
  '📋 Group history',
59
59
  ' • /bncr history-help',
@@ -14,7 +14,7 @@ export type BncrSceneAdminCommand =
14
14
  | { kind: 'mode-help' }
15
15
  | { kind: 'mode-get'; sceneKey?: string }
16
16
  | { kind: 'mode'; sceneKey: string; mode: BncrGroupReplyMode }
17
- | { kind: 'list'; scope: 'pending' | 'scenes' }
17
+ | { kind: 'list'; scope: 'pending' | 'scenes'; filters?: string[] }
18
18
  | { kind: 'history-limit-get'; sceneKey?: string }
19
19
  | { kind: 'history-limit-set'; sceneKey: string; limit: number }
20
20
  | { kind: 'history-force-get'; sceneKey?: string }
@@ -69,6 +69,11 @@ function splitArgs(raw: string): string[] {
69
69
  .filter(Boolean);
70
70
  }
71
71
 
72
+ function normalizeFilters(args: string[]): string[] | undefined {
73
+ const filters = args.map((part) => normalizeToken(part).toLowerCase()).filter(Boolean);
74
+ return filters.length > 0 ? filters : undefined;
75
+ }
76
+
72
77
  function resolveCurrentGroupSceneKey(parsed: ParsedInbound): string | null {
73
78
  if (parsed.peer.kind !== 'group') return null;
74
79
  const platform = normalizeToken(parsed.platform);
@@ -151,12 +156,26 @@ export function parseSceneAdminCommand(command: NativeCommand): ParsedSceneAdmin
151
156
  };
152
157
  case 'list':
153
158
  if (args[0] === 'pending') {
154
- return { matched: true, valid: true, command: { kind: 'list', scope: 'pending' } };
159
+ const filters = normalizeFilters(args.slice(1));
160
+ return {
161
+ matched: true,
162
+ valid: true,
163
+ command: { kind: 'list', scope: 'pending', ...(filters ? { filters } : {}) },
164
+ };
155
165
  }
156
166
  if (args[0] === 'scenes') {
157
- return { matched: true, valid: true, command: { kind: 'list', scope: 'scenes' } };
167
+ const filters = normalizeFilters(args.slice(1));
168
+ return {
169
+ matched: true,
170
+ valid: true,
171
+ command: { kind: 'list', scope: 'scenes', ...(filters ? { filters } : {}) },
172
+ };
158
173
  }
159
- return { matched: true, valid: false, text: 'Usage: /bncr list <pending|scenes>' };
174
+ return {
175
+ matched: true,
176
+ valid: false,
177
+ text: 'Usage: /bncr list <pending|scenes> [filters...]',
178
+ };
160
179
  case 'history-limit':
161
180
  if (args.length === 0) {
162
181
  return { matched: true, valid: true, command: { kind: 'history-limit-get' } };
@@ -271,6 +290,30 @@ function formatSceneGroups(scenes: BncrSceneRecord[]): string {
271
290
  .join('\n\n');
272
291
  }
273
292
 
293
+ function buildSceneSearchHaystack(scene: BncrSceneRecord): string[] {
294
+ const parts: string[] = [
295
+ normalizeToken(scene.sceneKey),
296
+ normalizeToken(scene.platform),
297
+ normalizeToken(scene.status),
298
+ normalizeToken(scene.agentId ?? ''),
299
+ normalizeToken(scene.kind),
300
+ normalizeToken(scene.userId ?? ''),
301
+ normalizeToken(scene.userName ?? ''),
302
+ normalizeToken(scene.groupId ?? ''),
303
+ normalizeToken(scene.groupName ?? ''),
304
+ ];
305
+ if (scene.kind === 'group') {
306
+ parts.push(scene.groupReplyMode || 'admin');
307
+ }
308
+ return parts.map((part) => part.toLowerCase()).filter(Boolean);
309
+ }
310
+
311
+ function matchesSceneFilters(scene: BncrSceneRecord, filters: string[] | undefined): boolean {
312
+ if (!filters?.length) return true;
313
+ const haystack = buildSceneSearchHaystack(scene);
314
+ return filters.every((filter) => haystack.some((part) => part.includes(filter)));
315
+ }
316
+
274
317
  function applySceneStatus(scene: BncrSceneRecord, status: BncrSceneStatus): BncrSceneRecord {
275
318
  return {
276
319
  ...scene,
@@ -299,11 +342,19 @@ export function executeSceneAdminCommand(args: {
299
342
  if (command.kind === 'list') {
300
343
  const scenes = Array.from(sceneRegistry.values())
301
344
  .filter((scene) => (command.scope === 'pending' ? scene.status === 'pending' : true))
345
+ .filter((scene) => matchesSceneFilters(scene, command.filters))
302
346
  .sort((a, b) => a.lastSeenAt - b.lastSeenAt);
303
347
  if (scenes.length === 0) {
304
348
  return {
305
349
  ok: true,
306
- text: command.scope === 'pending' ? 'No pending scenes.' : 'No scenes recorded.',
350
+ text:
351
+ command.scope === 'pending'
352
+ ? command.filters?.length
353
+ ? `No pending scenes matched: ${command.filters.join(' ')}`
354
+ : 'No pending scenes.'
355
+ : command.filters?.length
356
+ ? `No scenes matched: ${command.filters.join(' ')}`
357
+ : 'No scenes recorded.',
307
358
  };
308
359
  }
309
360
  return { ok: true, text: formatSceneGroups(scenes) };
@@ -265,6 +265,7 @@ export function buildBncrInboundTurnContext(args: {
265
265
  },
266
266
  extra: {
267
267
  OriginatingChannel: channelId,
268
+ ...(parsed.isGroup === true && parsed.groupName ? { GroupSubject: parsed.groupName } : {}),
268
269
  ...(ownerAllowFrom?.length ? { OwnerAllowFrom: ownerAllowFrom } : {}),
269
270
  BncrStructuredContextFacts: structuredContextFacts,
270
271
  StructuredContextFacts: structuredContextFacts,