@trim21/personal-pi-extensions 0.0.343 → 0.0.346

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 CHANGED
@@ -321,7 +321,7 @@ sqlite 文件路径按优先级取第一个可用值:
321
321
  ```
322
322
  /talk-group-join # 无参:自动创建一个新 group(uuid 作为组名)并加入
323
323
  /talk-group-join <name> # 加入名为 name 的 group;不存在则创建(名字允许字母/数字/-/_)
324
- /talk-group-join-last # 加入最近创建的 group(方便新开 session 快速归队)
324
+ /talk-group-join-last # 加入最近创建的 group(方便新开 session 快速归队);支持 --name <alias> 设置显示名
325
325
  /talk-group-leave # 离开当前 group(组空了自动删除)
326
326
  /talk-group-list # 列出所有 group 及其成员,最新创建的在前
327
327
  /talk-group-del <name> # 删除指定 group(成员随之变为未入组)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@trim21/personal-pi-extensions",
3
- "version": "0.0.343",
3
+ "version": "0.0.346",
4
4
  "type": "module",
5
5
  "description": "Custom pi coding-agent extensions: bwrap sandbox, workspace guard, opencode edit, and more",
6
6
  "keywords": [
@@ -302,7 +302,6 @@ export function registerAstEditTool(pi: ExtensionAPI, ctx: AftToolContext): void
302
302
  input: params,
303
303
  output: text,
304
304
  }),
305
- expanded: true,
306
305
  } satisfies ToolPendant,
307
306
  },
308
307
  };
@@ -126,7 +126,6 @@ export function registerImportTool(pi: ExtensionAPI, ctx: AftToolContext): void
126
126
  input: params,
127
127
  output: text,
128
128
  }),
129
- expanded: true,
130
129
  } satisfies ToolPendant,
131
130
  },
132
131
  };
@@ -145,7 +145,6 @@ export function registerRefactorTool(pi: ExtensionAPI, ctx: AftToolContext): voi
145
145
  input: params,
146
146
  output: text,
147
147
  }),
148
- expanded: true,
149
148
  } satisfies ToolPendant,
150
149
  },
151
150
  };
package/src/aft/tools.ts CHANGED
@@ -427,7 +427,6 @@ export function registerSearchTool(pi: ExtensionAPI, ctx: AftToolContext): void
427
427
  output: text,
428
428
  truncated,
429
429
  }),
430
- expanded: true,
431
430
  } satisfies ToolPendant,
432
431
  },
433
432
  };
@@ -4,8 +4,6 @@
4
4
  * 工具 execute 返回的 details 里可携带一个可折叠的 markdown 面板,TUI 会把它
5
5
  * 与本次工具调用的消息一起渲染:
6
6
  * - `markdown`: 面板正文(完整 markdown),建议以 `## ` 标题开头、末尾 trim
7
- * - `expanded`: 面板是否默认展开;识别/结果这类需要立即看到的内容用 true,
8
- * 列表等常驻信息用 false
9
7
  */
10
8
  export interface ToolPendant {
11
9
  /**
@@ -20,8 +18,4 @@ export interface ToolPendant {
20
18
  * 面板正文(完整 markdown),建议以 `## ` 标题开头、末尾 trim
21
19
  */
22
20
  markdown?: string;
23
- /**
24
- * @default false
25
- */
26
- expanded?: boolean;
27
21
  }
@@ -173,7 +173,6 @@ export default function todowrite(pi: ExtensionAPI) {
173
173
  todos,
174
174
  pendant: {
175
175
  markdown: buildTodoMarkdown(todos),
176
- expanded: false,
177
176
  },
178
177
  },
179
178
  });
@@ -711,7 +711,6 @@ export default function spawnAgent(pi: ExtensionAPI) {
711
711
  ...result,
712
712
  pendant: {
713
713
  markdown: formatPendantMarkdown(params.task, message),
714
- expanded: true,
715
714
  } satisfies ToolPendant,
716
715
  },
717
716
  isError: true,
@@ -729,7 +728,6 @@ export default function spawnAgent(pi: ExtensionAPI) {
729
728
  ...result,
730
729
  pendant: {
731
730
  markdown: formatPendantMarkdown(params.task, text),
732
- expanded: false,
733
731
  } satisfies ToolPendant,
734
732
  },
735
733
  };
package/src/talk/core.ts CHANGED
@@ -530,7 +530,7 @@ export class TalkCore {
530
530
  return `Invalid group name '${name}'. Allowed: letters, digits, '-' and '_' (max 64 chars).`;
531
531
  }
532
532
  if (agentName !== undefined) {
533
- await this.writeSelf({ name: agentName });
533
+ await this.writeSelf({ name: agentName, alias: agentName });
534
534
  }
535
535
  const nameNote = agentName === undefined ? "" : ` You are visible as "${agentName}".`;
536
536
  const existing = await readGroup(this.storage, name);
@@ -556,12 +556,15 @@ export class TalkCore {
556
556
  return `Created group ${name}.${nameNote} Other agents join it with /talk-group-join ${name}.`;
557
557
  }
558
558
 
559
- /** Join the most recently created group; no-op when already in it. */
560
- async groupJoinLast(): Promise<string> {
559
+ /**
560
+ * Join the most recently created group; no-op when already in it. When
561
+ * `agentName` is given, the agent's display name is set to it.
562
+ */
563
+ async groupJoinLast(agentName?: string): Promise<string> {
561
564
  const groups = await listGroups(this.storage);
562
565
  if (groups.length === 0) return "No groups. Create one with /talk-group-join.";
563
566
  const latest = groups.reduce((a, b) => (b.createdAt > a.createdAt ? b : a));
564
- return this.groupJoin(latest.id);
567
+ return this.groupJoin(latest.id, agentName);
565
568
  }
566
569
 
567
570
  /** Leave the current group; an emptied group is deleted. */
@@ -618,6 +621,18 @@ export class TalkCore {
618
621
  return `Groups (${groups.length}):\n${lines.join("\n")}`;
619
622
  }
620
623
 
624
+ /**
625
+ * Status-bar text for the caller: "alias@group" when an explicit alias was
626
+ * set via `talk-group-join --name`, "@group" otherwise; undefined when the
627
+ * caller is in no group (the adapter clears its status bar).
628
+ */
629
+ async groupStatus(): Promise<string | undefined> {
630
+ const self = this.requireSelf();
631
+ const group = await groupForAgent(this.storage, self.agentId);
632
+ if (!group) return undefined;
633
+ return self.alias ? `${self.alias}@${group.id}` : `@${group.id}`;
634
+ }
635
+
621
636
  async send(to: string, body: string): Promise<string> {
622
637
  if (!to) return 'send requires "to".';
623
638
  if (!body) return 'send requires "message".';
package/src/talk/index.ts CHANGED
@@ -14,7 +14,9 @@ import * as path from "node:path";
14
14
 
15
15
  import {
16
16
  type ExtensionAPI,
17
+ type ExtensionCommandContext,
17
18
  type ExtensionContext,
19
+ type ExtensionUIContext,
18
20
  getAgentDir,
19
21
  truncateToVisualLines,
20
22
  } from "@earendil-works/pi-coding-agent";
@@ -161,6 +163,19 @@ export default function talk(pi: ExtensionAPI) {
161
163
  return undefined;
162
164
  }
163
165
 
166
+ /** Refresh the talk footer/status-bar text: "alias@group", or "@group" with no explicit alias. */
167
+ function refreshGroupStatus(ui: ExtensionUIContext): void {
168
+ void (async () => {
169
+ if (!self) return;
170
+ try {
171
+ const text = await core.groupStatus();
172
+ ui.setStatus("talk", text && ui.theme.fg("accent", text));
173
+ } catch {
174
+ // status bar is best-effort; never break the agent
175
+ }
176
+ })();
177
+ }
178
+
164
179
  // ── Lifecycle ──────────────────────────────────────────────────────────
165
180
 
166
181
  pi.on("session_start", (_event, ctx: ExtensionContext) => {
@@ -177,7 +192,7 @@ export default function talk(pi: ExtensionAPI) {
177
192
  lastSeenAt: now,
178
193
  status: "idle",
179
194
  };
180
- void core.start(self);
195
+ void core.start(self).then(() => refreshGroupStatus(ctx.ui));
181
196
  });
182
197
 
183
198
  pi.on("agent_start", () => core.setWorking());
@@ -278,6 +293,7 @@ export default function talk(pi: ExtensionAPI) {
278
293
  function handleCommand<TFlags extends TObject>(
279
294
  spec: CommandSpec<TFlags>,
280
295
  args: string,
296
+ ctx: ExtensionCommandContext,
281
297
  run: (parsed: OkResult<TFlags>) => Promise<string> | string,
282
298
  ): Promise<void> {
283
299
  const parsed = parseCommand(spec, args);
@@ -289,6 +305,9 @@ export default function talk(pi: ExtensionAPI) {
289
305
  const initError = requireInit();
290
306
  const text = initError ?? (await run(parsed));
291
307
  pi.sendMessage({ customType: LIST_TYPE, content: text, display: true });
308
+ // Group membership can change under any of these commands; keep the
309
+ // footer/status-bar text in sync.
310
+ refreshGroupStatus(ctx.ui);
292
311
  })();
293
312
  }
294
313
 
@@ -327,9 +346,13 @@ export default function talk(pi: ExtensionAPI) {
327
346
 
328
347
  const TALK_GROUP_JOIN_LAST_SPEC = {
329
348
  name: "talk-group-join-last",
330
- usage: "",
331
- description: "Join the most recently created agent group (no-op when already in it).",
332
- flags: Type.Object({}),
349
+ usage: "[options]",
350
+ description:
351
+ "Join the most recently created agent group (no-op when already in it); --name <alias> additionally sets this agent's display name",
352
+ flags: Type.Object({
353
+ name: Type.Optional(Type.String({ description: "Set this agent's display name" })),
354
+ }),
355
+ flagMeta: { name: { short: "n", valuePlaceholder: "<alias>" } },
333
356
  arity: { max: 0 },
334
357
  };
335
358
 
@@ -368,13 +391,13 @@ export default function talk(pi: ExtensionAPI) {
368
391
 
369
392
  pi.registerCommand("talk", {
370
393
  description: TALK_SPEC.description,
371
- handler: (args) => handleCommand(TALK_SPEC, args, async () => core.list()),
394
+ handler: (args, ctx) => handleCommand(TALK_SPEC, args, ctx, async () => core.list()),
372
395
  });
373
396
 
374
397
  pi.registerCommand("talk-dead", {
375
398
  description: TALK_DEAD_SPEC.description,
376
- handler: (args) =>
377
- handleCommand(TALK_DEAD_SPEC, args, async (parsed) => {
399
+ handler: (args, ctx) =>
400
+ handleCommand(TALK_DEAD_SPEC, args, ctx, async (parsed) => {
378
401
  if (parsed.flags.all && parsed.args.length > 0) {
379
402
  return "--all cannot be combined with an agent id.\nTry '/talk-dead --help' for usage.";
380
403
  }
@@ -388,8 +411,8 @@ export default function talk(pi: ExtensionAPI) {
388
411
 
389
412
  pi.registerCommand("talk-group-join", {
390
413
  description: TALK_GROUP_JOIN_SPEC.description,
391
- handler: (args) =>
392
- handleCommand(TALK_GROUP_JOIN_SPEC, args, async (parsed) => {
414
+ handler: (args, ctx) =>
415
+ handleCommand(TALK_GROUP_JOIN_SPEC, args, ctx, async (parsed) => {
393
416
  const agentName = parsed.flags.name?.trim() || undefined;
394
417
  if (agentName !== undefined) explicitName = agentName;
395
418
  return core.groupJoin(parsed.args[0], agentName);
@@ -398,29 +421,38 @@ export default function talk(pi: ExtensionAPI) {
398
421
 
399
422
  pi.registerCommand("talk-group-join-last", {
400
423
  description: TALK_GROUP_JOIN_LAST_SPEC.description,
401
- handler: (args) =>
402
- handleCommand(TALK_GROUP_JOIN_LAST_SPEC, args, async () => core.groupJoinLast()),
424
+ handler: (args, ctx) =>
425
+ handleCommand(TALK_GROUP_JOIN_LAST_SPEC, args, ctx, async (parsed) => {
426
+ const agentName = parsed.flags.name?.trim() || undefined;
427
+ if (agentName !== undefined) explicitName = agentName;
428
+ return core.groupJoinLast(agentName);
429
+ }),
403
430
  });
404
431
 
405
432
  pi.registerCommand("talk-group-leave", {
406
433
  description: TALK_GROUP_LEAVE_SPEC.description,
407
- handler: (args) => handleCommand(TALK_GROUP_LEAVE_SPEC, args, async () => core.groupLeave()),
434
+ handler: (args, ctx) =>
435
+ handleCommand(TALK_GROUP_LEAVE_SPEC, args, ctx, async () => core.groupLeave()),
408
436
  });
409
437
 
410
438
  pi.registerCommand("talk-group-list", {
411
439
  description: TALK_GROUP_LIST_SPEC.description,
412
- handler: (args) => handleCommand(TALK_GROUP_LIST_SPEC, args, async () => core.groupList()),
440
+ handler: (args, ctx) =>
441
+ handleCommand(TALK_GROUP_LIST_SPEC, args, ctx, async () => core.groupList()),
413
442
  });
414
443
 
415
444
  pi.registerCommand("talk-group-del", {
416
445
  description: TALK_GROUP_DEL_SPEC.description,
417
- handler: (args) =>
418
- handleCommand(TALK_GROUP_DEL_SPEC, args, async (parsed) => core.groupDelete(parsed.args[0])),
446
+ handler: (args, ctx) =>
447
+ handleCommand(TALK_GROUP_DEL_SPEC, args, ctx, async (parsed) =>
448
+ core.groupDelete(parsed.args[0]),
449
+ ),
419
450
  });
420
451
 
421
452
  pi.registerCommand("talk-group-clear", {
422
453
  description: TALK_GROUP_CLEAR_SPEC.description,
423
- handler: (args) => handleCommand(TALK_GROUP_CLEAR_SPEC, args, async () => core.groupClear()),
454
+ handler: (args, ctx) =>
455
+ handleCommand(TALK_GROUP_CLEAR_SPEC, args, ctx, async () => core.groupClear()),
424
456
  });
425
457
 
426
458
  // ── Delivery card ──────────────────────────────────────────────────────
@@ -36,6 +36,8 @@ export const AgentRecordSchema = Type.Object({
36
36
  addr: Type.String(),
37
37
  agentId: Type.String(),
38
38
  name: Type.String(),
39
+ /** Display name explicitly set via `talk-group-join --name`, distinct from the session name. */
40
+ alias: Type.Optional(Type.String()),
39
41
  cwd: Type.String(),
40
42
  pid: Type.Number(),
41
43
  pidStart: Type.Optional(Type.Number()),
@@ -445,7 +445,6 @@ export default function visionAgent(pi: ExtensionAPI) {
445
445
  count: paths.length,
446
446
  pendant: {
447
447
  markdown,
448
- expanded: true,
449
448
  } satisfies ToolPendant,
450
449
  },
451
450
  };
@@ -465,7 +464,6 @@ export default function visionAgent(pi: ExtensionAPI) {
465
464
  error: message,
466
465
  pendant: {
467
466
  markdown: `## 图片识别失败\n\n${message}`,
468
- expanded: true,
469
467
  } satisfies ToolPendant,
470
468
  },
471
469
  };