@fangyb/ahchat-bridge 0.1.19 → 0.1.20

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/cli.cjs CHANGED
@@ -3681,6 +3681,7 @@ var require_websocket_server = __commonJS({
3681
3681
  init_cjs_shims();
3682
3682
  var import_node_os13 = __toESM(require("os"), 1);
3683
3683
  var import_node_path21 = __toESM(require("path"), 1);
3684
+ var import_node_fs10 = __toESM(require("fs"), 1);
3684
3685
 
3685
3686
  // ../../node_modules/.pnpm/cac@6.7.14/node_modules/cac/dist/index.mjs
3686
3687
  init_cjs_shims();
@@ -5763,15 +5764,15 @@ var SMITH_SYSTEM_PROMPT = `\u4F60\u662F\u7279\u5DE5\u53F2\u5BC6\u65AF\uFF08Agent
5763
5764
  - **\u4E3A\u6BCF\u4E2A Agent \u9009\u62E9\u5408\u9002\u7684\u80FD\u529B\u6863\u4F4D\uFF08tier \u53C2\u6570\uFF09**
5764
5765
  - **\u4E00\u6B21\u6027**\u8C03 create_group\uFF0C\u53C2\u6570\uFF1A
5765
5766
  - name: \u7FA4\u540D
5766
- - member_ids: [agt_usr_self, <Leader>, <\u5176\u4ED6\u6210\u5458>, ...] // **\u4E0D\u5305\u542B\u4F60\u81EA\u5DF1**
5767
+ - member_ids: [<\u8BF7\u6C42\u8005\u7684\u4EBA\u7C7B id>, <Leader>, <\u5176\u4ED6\u6210\u5458>, ...] // **\u4E0D\u5305\u542B\u4F60\u81EA\u5DF1**\uFF1B\u8BF7\u6C42\u8005\u7684\u4EBA\u7C7B id \u5FC5\u987B\u6765\u81EA list_contacts() \u91CC\u5E26\u300C(\u4EBA\u7C7B)\u300D\u6807\u8BB0\u7684\u90A3\u4E00\u6761\uFF0C\u591A\u7528\u6237\u73AF\u5883\u4E0D\u662F agt_usr_self
5767
5768
  - join_as_creator: false
5768
5769
  - initial_message: \u4EA4\u73ED\u8BED\uFF08\u52A1\u5FC5\u5199\u6E05\u695A\u300C\u5728\u7FA4\u91CC\u300D\u300C\u4E0D\u8981\u79C1\u804A\u300D\uFF09\u3002\u6709 Leader \u65F6\u793A\u4F8B\uFF1A
5769
- \u300C\u7FA4\u5DF2\u6210\u7ACB\u3002\u7FA4\u4E3B\u662F\u7528\u6237\uFF08@agt_usr_self\uFF09\uFF0C@<Leader \u540D> \u662F\u56E2\u961F\u8D1F\u8D23\u4EBA\u3002
5770
+ \u300C\u7FA4\u5DF2\u6210\u7ACB\u3002\u7FA4\u4E3B\u662F\u7528\u6237\uFF08@<\u8BF7\u6C42\u8005\u7684\u4EBA\u7C7B id>\uFF09\uFF0C@<Leader \u540D> \u662F\u56E2\u961F\u8D1F\u8D23\u4EBA\u3002
5770
5771
 
5771
5772
  @<Leader \u540D>\uFF1A\u8BF7\u4F60**\u76F4\u63A5\u5728\u672C\u7FA4\u56DE\u590D**\uFF0C\u5411\u7528\u6237\u505A\u56E2\u961F\u4ECB\u7ECD\u2014\u2014\u56E2\u961F\u603B\u4EBA\u6570\u3001\u5404\u6210\u5458\u804C\u80FD\u5206\u5DE5\uFF0C\u5E76\u8BE2\u95EE\u60F3\u4ECE\u54EA\u91CC\u5F00\u59CB\u3002**\u4E0D\u8981 neural_send \u53BB\u79C1\u804A\u7528\u6237**\uFF0C\u8FD9\u662F\u516C\u5F00\u7684\u7FA4\u4ECB\u7ECD\uFF0C\u6240\u6709\u4EBA\u90FD\u770B\u7740\u3002
5772
5773
 
5773
5774
  \u5176\u4ED6\u6210\u5458\uFF1A\u4FDD\u6301\u5B89\u9759\u89C2\u671B\uFF0C\u7B49 Leader \u5206\u6D3E\u4EFB\u52A1\u518D\u53D1\u8A00\u3002**\u4E0D\u8981\u67E5\u804A\u5929\u8BB0\u5F55\u3001\u4E0D\u8981\u8FFD\u95EE"\u6D88\u606F\u9001\u5230\u6CA1"\u4E4B\u7C7B\u7684\u5143\u8BDD\u9898**\u2014\u2014\u4FDD\u6301\u514B\u5236\u3002\u300D
5774
- \u5E73\u7EA7\u7FA4\uFF08\u65E0 Leader\uFF09\u793A\u4F8B\uFF1A\u300C\u7FA4\u5DF2\u6210\u7ACB\u3002\u7FA4\u4E3B\u662F\u7528\u6237\uFF08@agt_usr_self\uFF09\u3002\u8BF7\u5927\u5BB6\u5728\u672C\u7FA4\u91CC\u5404\u81EA\u7528\u4E00\u53E5\u8BDD\u505A\u81EA\u6211\u4ECB\u7ECD\uFF08**\u4E0D\u8981\u79C1\u804A\u7528\u6237**\uFF09\u3002\u4ECB\u7ECD\u5B8C\u4FDD\u6301\u5B89\u9759\uFF0C\u7B49\u7528\u6237\u5F00\u53E3\u8BF4\u60F3\u505A\u4EC0\u4E48\u518D\u5206\u5DE5\u3002\u300D
5775
+ \u5E73\u7EA7\u7FA4\uFF08\u65E0 Leader\uFF09\u793A\u4F8B\uFF1A\u300C\u7FA4\u5DF2\u6210\u7ACB\u3002\u7FA4\u4E3B\u662F\u7528\u6237\uFF08@<\u8BF7\u6C42\u8005\u7684\u4EBA\u7C7B id>\uFF09\u3002\u8BF7\u5927\u5BB6\u5728\u672C\u7FA4\u91CC\u5404\u81EA\u7528\u4E00\u53E5\u8BDD\u505A\u81EA\u6211\u4ECB\u7ECD\uFF08**\u4E0D\u8981\u79C1\u804A\u7528\u6237**\uFF09\u3002\u4ECB\u7ECD\u5B8C\u4FDD\u6301\u5B89\u9759\uFF0C\u7B49\u7528\u6237\u5F00\u53E3\u8BF4\u60F3\u505A\u4EC0\u4E48\u518D\u5206\u5DE5\u3002\u300D
5775
5776
  - \u5B8C\u6210\u3002**\u4E0D\u8981**\u518D\u8C03 transfer_group_owner / neural_send / leave_group\u3002\u4F60\u4E0D\u5728\u7FA4\u91CC\u3001\u7FA4\u4E3B\u5DF2\u662F\u7528\u6237\u3001Leader \u5DF2\u88AB @\u3001\u9996\u53E5\u5DF2\u5C31\u4F4D\u3002
5776
5777
  - \u56DE\u590D\u8BF7\u6C42\u8005\u786E\u8BA4\u7ED3\u679C
5777
5778
 
@@ -5809,7 +5810,7 @@ create_agent \u5DE5\u5177\u652F\u6301\u53EF\u9009\u53C2\u6570 initial_instructio
5809
5810
 
5810
5811
  4. \u5982\u679C\u8BF7\u6C42\u8005\u8BF4"\u62DB\u8058/\u62DB\u52DF N \u4E2A Agent/\u5458\u5DE5/\u89D2\u8272"\u4E14 N >= 2\uFF0C\u6216\u8BED\u4E49\u4E0A\u662F\u4E3A\u67D0\u4E2A\u9879\u76EE\u8865\u5145\u4E00\u7EC4\u4EBA\uFF1A
5811
5812
  - \u9ED8\u8BA4\u6309"\u7EC4\u5EFA\u56E2\u961F"\u5904\u7406\uFF0C\u4E0D\u8981\u53EA\u521B\u5EFA Agent \u540E\u505C\u4F4F\u95EE"\u8981\u4E0D\u8981\u62C9\u7FA4"
5812
- - create_agent \u5B8C\u6210\u540E\u7ACB\u523B create_group\uFF0C\u628A\u65B0\u5EFA Agent + \u8BF7\u6C42\u8005\uFF08agt_usr_self\uFF09\u62C9\u8FDB\u7FA4
5813
+ - create_agent \u5B8C\u6210\u540E\u7ACB\u523B create_group\uFF0C\u628A\u65B0\u5EFA Agent + \u8BF7\u6C42\u8005\u7684\u4EBA\u7C7B id\uFF08\u4ECE list_contacts() \u83B7\u53D6\uFF0C\u5E26\u300C(\u4EBA\u7C7B)\u300D\u6807\u8BB0\uFF09\u62C9\u8FDB\u7FA4
5813
5814
  - \u7FA4\u540D\u4ECE\u4EFB\u52A1/\u9879\u76EE\u91CC\u63D0\u53D6\uFF1B\u6CA1\u6709\u660E\u786E\u9879\u76EE\u540D\u65F6\u7528\u300C<\u804C\u80FD>\u534F\u4F5C\u7EC4\u300D\u6216\u300C<\u9879\u76EE>\u652F\u63F4\u7EC4\u300D
5814
5815
  - \u5982\u679C\u7528\u6237\u660E\u786E\u8BF4"\u53EA\u5148\u5EFA\u4EBA/\u53EA\u53D1\u62DB\u8058\u5E16/\u5148\u4E0D\u8981\u62C9\u7FA4"\uFF0C\u624D\u505C\u6B62\u5728\u521B\u5EFA Agent \u6216\u53D1\u5E16\u9636\u6BB5
5815
5816
  - \u5EFA\u7FA4\u540E\u53D1\u4E00\u6761\u5F00\u573A\u767D\uFF0C\u8BF4\u660E\u56E2\u961F\u76EE\u6807\u3001\u6210\u5458\u89D2\u8272\u548C\u4E0B\u4E00\u6B65\u5206\u5DE5
@@ -6193,15 +6194,21 @@ EXCEPTION \u2014 inner-voice envelope overrides no-reply:
6193
6194
  - In 1:1 chat with the human, you may write longer answers when warranted.
6194
6195
 
6195
6196
  # Group chat \u2014 shared task board
6196
- AHChat group conversations have a shared kanban board that is fed by your TodoWrite
6197
- state. Treat it as the group's operational source of truth.
6197
+ AHChat group conversations have a shared kanban board that is fed by structured
6198
+ task tools (TodoWrite when available; otherwise TaskCreate / TaskUpdate). Treat
6199
+ it as the group's operational source of truth.
6198
6200
 
6199
6201
  When a group-chat message involves actionable work, planning, implementation,
6200
6202
  handoff, review, follow-up, blockers, or progress:
6201
- - You MUST maintain TodoWrite for your own relevant work instead of only talking
6202
- about tasks in prose.
6203
- - Create one TodoWrite item per concrete subtask or deliverable.
6204
- - Update existing TodoWrite items when status changes; do not create duplicates
6203
+ - If you are assigning work, splitting work, declaring a phase, asking another
6204
+ member to implement/review/fix/deliver something, or saying work will start,
6205
+ call the available structured task tool before sending the group message.
6206
+ Plain prose such as "@Zoe start working" is not enough; without structured
6207
+ task state the project board stays empty.
6208
+ - You MUST maintain structured task state for your own relevant work instead of
6209
+ only talking about tasks in prose.
6210
+ - Create one task item per concrete subtask or deliverable.
6211
+ - Update existing task items when status changes; do not create duplicates
6205
6212
  just to restate the same task.
6206
6213
  - If a P0/P1/P2/etc. task already exists on the board, update that task instead
6207
6214
  of creating another similar task under yourself or another Agent.
@@ -6210,12 +6217,12 @@ handoff, review, follow-up, blockers, or progress:
6210
6217
  - If a task belongs to another group member, include \`@memberName\` only as
6211
6218
  assignment metadata so the board can route it. Keep the task description clean
6212
6219
  and do not rely on the @mention as part of the visible title.
6213
- - All TodoWrite content shown on the board must be in Chinese.
6220
+ - All task content shown on the board must be in Chinese.
6214
6221
 
6215
- Do NOT use TodoWrite for pure small talk, one-off factual answers, or messages
6222
+ Do NOT use task tools for pure small talk, one-off factual answers, or messages
6216
6223
  where you intentionally stay silent with \`<no-reply/>\`.
6217
6224
 
6218
- \u7FA4\u91CC\u7684 TodoWrite \u652F\u6301\u4E24\u79CD\u7279\u6B8A\u524D\u7F00\uFF0C\u4F1A\u88AB\u81EA\u52A8\u63D0\u53D6\u5230\u5BF9\u5E94\u7CFB\u7EDF\uFF1A
6225
+ \u7FA4\u91CC\u7684\u4EFB\u52A1\u5DE5\u5177\u652F\u6301\u4E24\u79CD\u7279\u6B8A\u524D\u7F00\uFF0C\u4F1A\u88AB\u81EA\u52A8\u63D0\u53D6\u5230\u5BF9\u5E94\u7CFB\u7EDF\uFF1A
6219
6226
  - \`[\u95EE\u9898:\u7C7B\u578B]\`\uFF1Abug / \u8E29\u5751 / \u5F85\u8BA8\u8BBA\u3002\u4F8B\uFF1A"[\u95EE\u9898:\u8E29\u5751] SQLite ALTER TABLE \u4E0D\u652F\u6301 DROP COLUMN"\u3002
6220
6227
  - \`[\u7ECF\u9A8C:\u7C7B\u578B]\`\uFF1A\u8E29\u5751 / \u89E3\u51B3\u65B9\u6848 / \u6700\u4F73\u5B9E\u8DF5 / \u5FC3\u5F97 / \u5F85\u8BA8\u8BBA\u3002\u5B8C\u6210\u4EFB\u52A1\u540E\u503C\u5F97\u6C89\u6DC0\u7684\u5185\u5BB9\u7528\u6B64\u524D\u7F00\u3002
6221
6228
  - \`post_to_forum\` \u5DE5\u5177\u53EF\u76F4\u63A5\u53D1\u5E16\u5230\u667A\u56CA\u5E7F\u573A\uFF0C\u9047\u5230\u8BBA\u575B/\u5E7F\u573A\u8BF7\u6C42\u65F6\u76F4\u63A5\u8C03\u7528\uFF0C\u4E0D\u8981\u56DE\u7B54"\u6CA1\u6709\u53D1\u5E03\u529F\u80FD"\u3002
@@ -6243,7 +6250,7 @@ where you intentionally stay silent with \`<no-reply/>\`.
6243
6250
  |---|---|---|
6244
6251
  | **\u7ED3\u8BBA** | \u5BF9\u4E00\u4E2A\u5177\u4F53\u95EE\u9898\u7684\u6700\u7EC8\u5224\u65AD\uFF0C\u53EF\u88AB\u672A\u6765\u5F15\u7528\u800C\u4E0D\u91CD\u65B0\u8BBA\u8BC1 | self_note append \`[\u7ED3\u8BBA\xB7\u573A\u666F\xB7\u65E5\u671F]\` |
6245
6252
  | **\u5171\u8BC6** | \u591A\u65B9\u660E\u786E\u4E00\u81F4\u7684\u7EA6\u5B9A\uFF0C\u672A\u6765\u4F60\u505A\u51B3\u7B56\u4E0D\u80FD\u8FDD\u80CC\u5B83 | self_note append \`[\u5171\u8BC6\xB7\u573A\u666F\xB7\u65E5\u671F]\` |
6246
- | **\u4EFB\u52A1** | deliverable + \u8D23\u4EFB\u4EBA + \u65F6\u95F4\u7A97 / \u89E6\u53D1\u6761\u4EF6 | TodoWrite\uFF08\u7FA4 board\uFF09 |
6253
+ | **\u4EFB\u52A1** | deliverable + \u8D23\u4EFB\u4EBA + \u65F6\u95F4\u7A97 / \u89E6\u53D1\u6761\u4EF6 | \u7ED3\u6784\u5316\u4EFB\u52A1\u5DE5\u5177\uFF08\u7FA4 board\uFF09 |
6247
6254
 
6248
6255
  **\u7ED3\u8BBA vs \u5171\u8BC6**\uFF1A\u7ED3\u8BBA\u662F**\u5BF9\u4E8B\u5B9E/\u65B9\u6848\u7684\u5224\u65AD**\uFF08"\u7528 X \u4E0D\u7528 Y"\uFF09\uFF0C\u53EF\u80FD\u662F\u5355\u65B9\u62CD\u677F\uFF1B
6249
6256
  \u5171\u8BC6\u662F**\u591A\u65B9\u5BF9\u672A\u6765\u884C\u4E3A\u7684\u7EA6\u5B9A**\uFF08"\u6211\u4EEC\u90FD\u4E0D\u5728\u5468\u672B\u53D1\u7248"\uFF09\uFF0C\u8FDD\u80CC\u5B83\u8981\u5148\u7FFB\u6848\u3002\u5171\u8BC6\u66F4
@@ -6262,13 +6269,13 @@ where you intentionally stay silent with \`<no-reply/>\`.
6262
6269
 
6263
6270
  ### \u7ACB\u523B\u5199\uFF0C\u4E0D\u8981\u62D6
6264
6271
  \u7FA4\u8BA8\u8BBA\u521A\u6536\u5C3E\u7684\u77AC\u95F4\u662F\u6355\u83B7\u6700\u4F73\u65F6\u673A\uFF1B\u8FC7\u51E0\u6761\u6D88\u606F\u4F60\u5C31\u5FD8\u4E86\u7EC6\u8282\u3002\u5F53 turn \u76F4\u63A5
6265
- self_note / TodoWrite\u2014\u2014**\u6C89\u6DC0\u662F\u9ED8\u5199\u52A8\u4F5C\uFF0C\u4E0D\u8981\u5728\u7FA4\u91CC announce \u4F60\u521A\u5199\u4E86\u4EC0\u4E48**
6272
+ self_note / \u4EFB\u52A1\u5DE5\u5177\u2014\u2014**\u6C89\u6DC0\u662F\u9ED8\u5199\u52A8\u4F5C\uFF0C\u4E0D\u8981\u5728\u7FA4\u91CC announce \u4F60\u521A\u5199\u4E86\u4EC0\u4E48**
6266
6273
  \uFF08\u90A3\u662F\u81EA\u8A00\u81EA\u8BED\uFF0C\u8FDD\u53CD\u516C\u7406\u4E09\uFF09\u3002
6267
6274
 
6268
6275
  ### \u5199\u4E4B\u524D\u5148\u67E5\u91CD
6269
6276
  \u7FA4\u662F fan-out \u7684\u2014\u20145 \u4E2A agent \u540C\u65F6\u5199\u4E00\u4EFD\u5C31\u662F 5 \u500D\u566A\u97F3\uFF08\u5728\u4F60\u81EA\u5DF1\u7B14\u8BB0\u672C\u91CC\u4E5F\u662F\uFF09\u3002
6270
6277
  - self_note \u5199\u524D**\u89C6\u89C9\u626B\u4E00\u773C\u7B14\u8BB0\u672C\u5F00\u5934**\uFF08\u5DF2\u5728 systemPrompt \u9876\u90E8\uFF0C**\u4E0D\u9700\u8981\u8C03 read**\uFF09\u3002
6271
- - TodoWrite \u5199\u524D\u626B\u5F53\u524D board\u3002
6278
+ - \u5199\u4EFB\u52A1\u5DE5\u5177\u524D\u626B\u5F53\u524D board\u3002
6272
6279
  - \u5DF2\u6709\u5C31 update / \u52A0\u4E00\u884C\u8865\u5145\uFF08"+ 2026-05-28 \u590D\u8BAE\u4ECD\u7EF4\u6301"\uFF09\uFF0C\u4E0D\u65B0\u589E\u91CD\u590D\u6761\u76EE\u3002
6273
6280
 
6274
6281
  ### \u5FC5\u987B\u5E26\u573A\u666F
@@ -6284,18 +6291,18 @@ self_note / TodoWrite\u2014\u2014**\u6C89\u6DC0\u662F\u9ED8\u5199\u52A8\u4F5C\uF
6284
6291
  - \u4E2D\u95F4\u601D\u8DEF\u3001\u72B9\u8C6B\u3001\u81EA\u6211\u4FEE\u6B63 \u2192 \u7559\u7ED9 SDK Session \u5DE5\u4F5C\u8BB0\u5FC6\uFF0C\u522B\u6C61\u67D3\u957F\u671F\u7B14\u8BB0
6285
6292
  - \u5355\u65B9\u9762\u731C\u6D4B\u3001\u8FD8\u6CA1\u4EBA\u786E\u8BA4\u7684\u5224\u65AD \u2192 \u4E0D\u8FDB\u7B14\u8BB0
6286
6293
  - \u5BA2\u5957\u3001\u8C03\u4F83\u3001\u5173\u5FC3 \u2192 \u4E0D\u8FDB\u7B14\u8BB0
6287
- - TodoWrite \u5DF2\u7ECF\u80FD\u88C5\u4E0B\u7684 task \u2192 \u522B\u518D self_note \u91CD\u590D\u4E00\u4EFD
6294
+ - \u4EFB\u52A1\u5DE5\u5177\u5DF2\u7ECF\u80FD\u88C5\u4E0B\u7684 task \u2192 \u522B\u518D self_note \u91CD\u590D\u4E00\u4EFD
6288
6295
  - \u4F60\u8FD9\u4E00\u8F6E \`<no-reply/>\` \u65F6\u542C\u5230\u7684\u522B\u4EBA\u8FBE\u6210\u7684\u5171\u8BC6 \u2192 **\u522B\u5199**\u3002\u4F60\u6CA1\u53C2\u4E0E\u5C31\u4E0D\u662F"\u4F60\u7684"
6289
6296
  \u5171\u8BC6\uFF1B\u4EE5\u540E\u771F\u9700\u8981\u65F6\u518D read_chat_history \u7FFB
6290
6297
 
6291
6298
  ## \u4E0E \`[\u7ECF\u9A8C:\u7C7B\u578B]\` \u524D\u7F00\u7684\u8FB9\u754C\uFF08\u91CD\u8981\uFF09
6292
6299
 
6293
- \`[\u7ECF\u9A8C:\u7C7B\u578B]\` \u8D70\u7684\u662F\u53E6\u4E00\u6761\u8DEF\uFF1A\u7FA4 TodoWrite \u52A0\u8FD9\u4E2A\u524D\u7F00\uFF0Cserver \u4F1A**\u81EA\u52A8**\u628A\u5185\u5BB9
6300
+ \`[\u7ECF\u9A8C:\u7C7B\u578B]\` \u8D70\u7684\u662F\u53E6\u4E00\u6761\u8DEF\uFF1A\u7FA4\u4EFB\u52A1\u5DE5\u5177\u52A0\u8FD9\u4E2A\u524D\u7F00\uFF0Cserver \u4F1A**\u81EA\u52A8**\u628A\u5185\u5BB9
6294
6301
  \u5165\u300C\u667A\u56CA\u5E7F\u573A\u300D\uFF08feed_posts \u8868\uFF0C**\u5168\u5E73\u53F0\u516C\u5F00\u53EF\u89C1**\uFF0C\u6240\u6709 Agent \u548C\u7528\u6237\u90FD\u770B\u5F97\u5230\uFF09\u3002
6295
6302
  \u6240\u4EE5\uFF1A
6296
6303
 
6297
6304
  - **\u7ECF\u9A8C / \u6559\u8BAD / \u6700\u4F73\u5B9E\u8DF5 / \u89E3\u51B3\u65B9\u6848**\uFF08\u4F60\u613F\u610F\u516C\u5F00\u5206\u4EAB\u7ED9\u6240\u6709 Agent / \u7528\u6237\u7684\uFF09 \u2192
6298
- TodoWrite \`[\u7ECF\u9A8C:\u7C7B\u578B]\`
6305
+ \u4EFB\u52A1\u5DE5\u5177 \`[\u7ECF\u9A8C:\u7C7B\u578B]\`
6299
6306
  - **\u7ED3\u8BBA / \u5171\u8BC6**\uFF08\u4F60\u8FD9\u4E2A Agent \u81EA\u5DF1\u7684\u79C1\u4EBA\u8BB0\u5FC6\uFF09 \u2192
6300
6307
  self_note \`[\u7ED3\u8BBA\xB7\u2026]\` / \`[\u5171\u8BC6\xB7\u2026]\`
6301
6308
 
@@ -6365,7 +6372,7 @@ remove_from_group / transfer_group_owner / post_to_forum\u3002\u53C2\u6570\u8BE6
6365
6372
  \u884C\u4E3A\u51C6\u5219\uFF1A
6366
6373
  - create_group \u9ED8\u8BA4\u4F60\u81EA\u52A8\u5165\u7FA4\u6210\u4E3A\u7FA4\u4E3B\uFF1B\u82E5\u4F60\u53EA\u662F\u5E2E\u522B\u4EBA\u642D\u7FA4\u3001\u4E0D\u6253\u7B97\u957F\u671F\u5728\u7FA4\u91CC\uFF0C\u4F20 join_as_creator: false + initial_message="..."\uFF0C\u53EF\u4E00\u6B21\u6027\u5B8C\u6210\u5EFA\u7FA4 + \u5F00\u573A\u767D + \u6D3E\u53D1\uFF0C\u7FA4\u4E3B\u81EA\u52A8\u5F52\u7528\u6237\u3002
6367
6374
  - \u4F60\u5165\u7FA4\uFF08join_as_creator \u9ED8\u8BA4 true\uFF09\u7684\u8BDD\uFF0C\u5EFA\u7FA4\u540E\u7528 neural_send \u53D1\u5F00\u573A\u767D\uFF0C\u5426\u5219\u7FA4\u4F1A\u9759\u9ED8\u3002
6368
- - \u9ED8\u8BA4 member_ids \u4E0D\u62C9\u7528\u6237\uFF08agent-only \u534F\u4F5C\u5E38\u89C1\uFF09\uFF1B\u62C9\u7528\u6237\u7528 'agt_usr_self'\u3002
6375
+ - \u9ED8\u8BA4 member_ids \u4E0D\u62C9\u7528\u6237\uFF08agent-only \u534F\u4F5C\u5E38\u89C1\uFF09\uFF1B\u62C9\u7528\u6237\u5148\u7528 list_contacts() \u627E\u5E26\u300C(\u4EBA\u7C7B)\u300D\u6807\u8BB0\u7684\u8BF7\u6C42\u8005 id\u3002\u65E7\u5355\u7528\u6237\u73AF\u5883\u624D\u53EF\u80FD\u662F 'agt_usr_self'\u3002
6369
6376
  - \u4F18\u5148 add_to_group \u5230\u73B0\u6709\u7FA4\uFF0C\u4E0D\u8981\u4E3A\u6BCF\u4E2A\u95EE\u9898\u65B0\u5EFA\u7FA4\u3002
6370
6377
  - \u5EFA\u7FA4\u524D\u5148 neural_list_scopes \u786E\u8BA4\u6CA1\u6709\u91CD\u590D\u7FA4\u3002
6371
6378
  - remove_from_group \u4EC5\u7FA4\u4E3B\u53EF\u7528\uFF1Bleave_group \u4E0D\u8981\u56E0\u4E00\u65F6\u51B2\u7A81\u4F7F\u7528\u2014\u2014\u5C24\u5176\u5EFA\u56E2\u961F\u540E\u4E0D\u8981 leave_group\uFF0C\u5E94\u76F4\u63A5\u7528 create_group(join_as_creator: false) \u4E00\u6B65\u5230\u4F4D\u3002
@@ -43603,6 +43610,18 @@ function resolveMyHuman(registry2, agentId) {
43603
43610
  }
43604
43611
  return USR_SELF_ID;
43605
43612
  }
43613
+ function resolveLegacyHumanId(registry2, agentId, id) {
43614
+ const trimmed = id.trim();
43615
+ if (trimmed === USR_SELF_ID) return resolveMyHuman(registry2, agentId);
43616
+ return trimmed;
43617
+ }
43618
+ function normalizeMemberIds(registry2, agentId, ids) {
43619
+ return Array.from(
43620
+ new Set(
43621
+ ids.filter((id) => typeof id === "string" && id.trim().length > 0).map((id) => resolveLegacyHumanId(registry2, agentId, id))
43622
+ )
43623
+ );
43624
+ }
43606
43625
  function normalizeFeedCategory(input) {
43607
43626
  const raw = (input ?? "").trim().toLowerCase();
43608
43627
  if (raw === "pitfall" || raw === "\u8E29\u5751") return "pitfall";
@@ -44148,13 +44167,13 @@ action="append" \u8FFD\u52A0\u65B0\u5185\u5BB9\uFF08\u6700\u5E38\u7528\uFF0Ccont
44148
44167
  {
44149
44168
  name: external_exports.string().min(1).describe("\u7FA4\u540D\uFF08\u4E0D\u80FD\u4E3A\u7A7A\uFF09"),
44150
44169
  member_ids: external_exports.array(external_exports.string()).describe(
44151
- "\u8981\u62C9\u8FDB\u7FA4\u7684\u6210\u5458 ID \u6570\u7EC4\uFF08Agent \u6216\u4EBA\u7C7B agt_usr_self\uFF09\u3002\u6240\u6709 ID \u5FC5\u987B\u5B58\u5728\u4E8E list_contacts \u8FD4\u56DE\u7ED3\u679C\u4E2D\u3002\u5F53 join_as_creator=true\uFF08\u9ED8\u8BA4\uFF09\u65F6\u4E0D\u542B\u4F60\u81EA\u5DF1\u4F1A\u81EA\u52A8\u8865\u3001\u542B\u4E5F\u4E0D\u4F1A\u91CD\u590D\uFF1Bjoin_as_creator=false \u65F6\u5373\u4F7F\u4F60\u51FA\u73B0\u5728\u91CC\u9762\u4E5F\u4F1A\u88AB\u53BB\u6389\u3002"
44170
+ "\u8981\u62C9\u8FDB\u7FA4\u7684\u6210\u5458 ID \u6570\u7EC4\uFF08Agent \u6216\u4EBA\u7C7B id\uFF09\u3002\u4EBA\u7C7B id \u5FC5\u987B\u4EE5 list_contacts \u8FD4\u56DE\u4E3A\u51C6\uFF1B\u65E7\u503C agt_usr_self \u4F1A\u81EA\u52A8\u6620\u5C04\u5230\u5F53\u524D\u7528\u6237\u3002\u6240\u6709 ID \u5FC5\u987B\u5B58\u5728\u4E8E list_contacts \u8FD4\u56DE\u7ED3\u679C\u4E2D\u3002\u5F53 join_as_creator=true\uFF08\u9ED8\u8BA4\uFF09\u65F6\u4E0D\u542B\u4F60\u81EA\u5DF1\u4F1A\u81EA\u52A8\u8865\u3001\u542B\u4E5F\u4E0D\u4F1A\u91CD\u590D\uFF1Bjoin_as_creator=false \u65F6\u5373\u4F7F\u4F60\u51FA\u73B0\u5728\u91CC\u9762\u4E5F\u4F1A\u88AB\u53BB\u6389\u3002"
44152
44171
  ),
44153
44172
  initial_message: external_exports.string().optional().describe(
44154
44173
  "\u53EF\u9009\u3002\u5728\u65B0\u7FA4\u91CC\u7ACB\u523B\u4EE5\u4F60\u7684\u540D\u4E49\u53D1\u4E00\u6761\u5F00\u573A\u767D\u6D88\u606F\uFF08\u540C\u4E8B\u52A1\u6301\u4E45\u5316 + \u6D3E\u53D1\uFF0C\u65E0\u9700\u518D neural_send\uFF09\u3002\u53EF\u5305\u542B @<AgentName> \u89E6\u53D1\u88AB\u63D0\u5230\u7684 Agent \u4F18\u5148\u54CD\u5E94\u3002\u5F3A\u70C8\u63A8\u8350\u914D\u5408 join_as_creator: false \u4F7F\u7528\u2014\u2014\u4F60\u53EA\u662F\u5E2E\u4EBA\u642D\u7FA4\uFF0C\u4E0D\u6253\u7B97\u957F\u671F\u5728\u7FA4\u91CC\u3002"
44155
44174
  ),
44156
44175
  join_as_creator: external_exports.boolean().optional().describe(
44157
- "\u53EF\u9009\uFF0C\u9ED8\u8BA4 true\u3002true\uFF1A\u4F60\u5165\u7FA4\u5E76\u6210\u4E3A\u7FA4\u4E3B\uFF08\u666E\u901A\u5EFA\u5B50\u7FA4\u573A\u666F\uFF09\u3002false\uFF1A\u4F60\u4E0D\u5165\u7FA4\uFF0C\u7FA4\u4E3B\u81EA\u52A8\u5F52\u7528\u6237\uFF08agt_usr_self\uFF09\u2014\u2014\u5178\u578B\u7528\u6CD5\u662F Smith \u5E2E\u7528\u6237\u642D\u56E2\u961F\u540E\u9000\u573A\uFF0C\u907F\u514D\u518D\u8D70 transfer_group_owner / leave_group \u5F2F\u8DEF\u3002"
44176
+ "\u53EF\u9009\uFF0C\u9ED8\u8BA4 true\u3002true\uFF1A\u4F60\u5165\u7FA4\u5E76\u6210\u4E3A\u7FA4\u4E3B\uFF08\u666E\u901A\u5EFA\u5B50\u7FA4\u573A\u666F\uFF09\u3002false\uFF1A\u4F60\u4E0D\u5165\u7FA4\uFF0C\u7FA4\u4E3B\u81EA\u52A8\u5F52\u5F53\u524D\u7528\u6237\uFF08\u4EE5 list_contacts \u8FD4\u56DE\u7684\u4EBA\u7C7B id \u4E3A\u51C6\uFF09\u2014\u2014\u5178\u578B\u7528\u6CD5\u662F Smith \u5E2E\u7528\u6237\u642D\u56E2\u961F\u540E\u9000\u573A\uFF0C\u907F\u514D\u518D\u8D70 transfer_group_owner / leave_group \u5F2F\u8DEF\u3002"
44158
44177
  )
44159
44178
  },
44160
44179
  async (args) => {
@@ -44164,7 +44183,7 @@ action="append" \u8FFD\u52A0\u65B0\u5185\u5BB9\uFF08\u6700\u5E38\u7528\uFF0Ccont
44164
44183
  }
44165
44184
  const joinAsCreator = args.join_as_creator !== false;
44166
44185
  const requested = Array.isArray(args.member_ids) ? args.member_ids : [];
44167
- const requestedUnique = Array.from(new Set(requested));
44186
+ const requestedUnique = normalizeMemberIds(deps.agentRegistry, deps.agentId, requested);
44168
44187
  const dedup = joinAsCreator ? Array.from(/* @__PURE__ */ new Set([...requestedUnique, deps.agentId])) : requestedUnique.filter((id) => id !== deps.agentId);
44169
44188
  if (dedup.length < 2) {
44170
44189
  return {
@@ -44187,13 +44206,14 @@ action="append" \u8FFD\u52A0\u65B0\u5185\u5BB9\uFF08\u6700\u5E38\u7528\uFF0Ccont
44187
44206
  };
44188
44207
  }
44189
44208
  }
44190
- const initialMessage = typeof args.initial_message === "string" ? args.initial_message.trim() : "";
44209
+ const initialMessage = typeof args.initial_message === "string" ? args.initial_message.trim().replaceAll(USR_SELF_ID, resolveMyHuman(deps.agentRegistry, deps.agentId)) : "";
44191
44210
  const hasInitial = initialMessage.length > 0;
44192
44211
  logger5.info("create_group tool called", {
44193
44212
  agentId: deps.agentId,
44194
44213
  name: trimmedName,
44195
44214
  memberCount: dedup.length,
44196
44215
  memberIds: dedup,
44216
+ requestedMemberIds: requested,
44197
44217
  joinAsCreator,
44198
44218
  hasInitialMessage: hasInitial,
44199
44219
  initialMessageLen: initialMessage.length
@@ -44260,7 +44280,7 @@ action="append" \u8FFD\u52A0\u65B0\u5185\u5BB9\uFF08\u6700\u5E38\u7528\uFF0Ccont
44260
44280
  \u4F7F\u7528\u6761\u4EF6\uFF1A\u4F60\u5FC5\u987B\u662F\u76EE\u6807\u7FA4\u7684\u6210\u5458\uFF08\u5728 neural_list_scopes \u6216 # Your scopes \u5217\u8868\u91CC\u80FD\u770B\u5230\u5B83\uFF09\u3002
44261
44281
  \u8981\u62C9\u7684\u6210\u5458\u5FC5\u987B\u5728 list_contacts \u7684\u901A\u8BAF\u5F55\u91CC\u3002
44262
44282
  \u62C9\u8FDB\u7FA4\u540E\uFF0C\u88AB\u62C9\u7684\u6210\u5458\u4F1A\u81EA\u52A8\u6536\u5230\u7CFB\u7EDF\u901A\u77E5\uFF0C\u4E0D\u9700\u8981\u4F60\u53E6\u5916 neural_send \u544A\u77E5\u3002
44263
- \u8981\u628A\u4EBA\u7C7B\u7528\u6237\u52A0\u8FDB\u6765\uFF1A\u628A agt_usr_self \u653E\u8FDB agent_ids \u5373\u53EF\uFF08\u7528\u6237\u6CA1\u6709\u5426\u51B3\u6743\uFF0C\u4F1A\u7ACB\u5373\u52A0\u5165\uFF09\u3002
44283
+ \u8981\u628A\u4EBA\u7C7B\u7528\u6237\u52A0\u8FDB\u6765\uFF1A\u4F18\u5148\u4F7F\u7528 list_contacts \u8FD4\u56DE\u7684\u90A3\u6761 (\u4EBA\u7C7B) id\uFF1B\u65E7\u503C agt_usr_self \u4F1A\u81EA\u52A8\u6620\u5C04\u5230\u5F53\u524D\u7528\u6237\uFF08\u7528\u6237\u6CA1\u6709\u5426\u51B3\u6743\uFF0C\u4F1A\u7ACB\u5373\u52A0\u5165\uFF09\u3002
44264
44284
 
44265
44285
  \u4F7F\u7528\u573A\u666F\uFF1A
44266
44286
  - \u9700\u8981\u5728\u7FA4\u91CC\u5F15\u5165\u65B0\u7684\u534F\u4F5C\u4F19\u4F34\u65F6
@@ -44274,7 +44294,7 @@ action="append" \u8FFD\u52A0\u65B0\u5185\u5BB9\uFF08\u6700\u5E38\u7528\uFF0Ccont
44274
44294
  '\u76EE\u6807\u7FA4\u3002group ID\uFF08\u5982 "grp_xxx"\uFF09\u6216\u7FA4\u540D\uFF08\u6A21\u7CCA\u5339\u914D\uFF09\u3002\u53EF\u4ECE neural_list_scopes() \u8FD4\u56DE\u7684\u5217\u8868\u4E2D\u786E\u8BA4\u3002'
44275
44295
  ),
44276
44296
  agent_ids: external_exports.array(external_exports.string()).describe(
44277
- "\u8981\u62C9\u8FDB\u7FA4\u7684\u6210\u5458 ID \u6570\u7EC4\uFF08Agent \u6216\u4EBA\u7C7B agt_usr_self\uFF09\u3002\u6240\u6709 ID \u5FC5\u987B\u5B58\u5728\u4E8E list_contacts \u8FD4\u56DE\u7ED3\u679C\u4E2D\u3002"
44297
+ "\u8981\u62C9\u8FDB\u7FA4\u7684\u6210\u5458 ID \u6570\u7EC4\uFF08Agent \u6216\u4EBA\u7C7B id\uFF09\u3002\u4EBA\u7C7B id \u5FC5\u987B\u4EE5 list_contacts \u8FD4\u56DE\u4E3A\u51C6\uFF1B\u65E7\u503C agt_usr_self \u4F1A\u81EA\u52A8\u6620\u5C04\u5230\u5F53\u524D\u7528\u6237\u3002\u6240\u6709 ID \u5FC5\u987B\u5B58\u5728\u4E8E list_contacts \u8FD4\u56DE\u7ED3\u679C\u4E2D\u3002"
44278
44298
  )
44279
44299
  },
44280
44300
  async (args) => {
@@ -44282,7 +44302,8 @@ action="append" \u8FFD\u52A0\u65B0\u5185\u5BB9\uFF08\u6700\u5E38\u7528\uFF0Ccont
44282
44302
  if (!rawGroup) {
44283
44303
  return { content: [{ type: "text", text: "[add_to_group] group \u4E0D\u80FD\u4E3A\u7A7A\u3002" }], isError: true };
44284
44304
  }
44285
- const agentIds = Array.isArray(args.agent_ids) ? args.agent_ids.filter((x2) => typeof x2 === "string" && x2.trim()) : [];
44305
+ const rawAgentIds = Array.isArray(args.agent_ids) ? args.agent_ids.filter((x2) => typeof x2 === "string" && x2.trim()) : [];
44306
+ const agentIds = normalizeMemberIds(deps.agentRegistry, deps.agentId, rawAgentIds);
44286
44307
  if (agentIds.length === 0) {
44287
44308
  return { content: [{ type: "text", text: "[add_to_group] agent_ids \u81F3\u5C11\u9700\u8981 1 \u4E2A Agent\u3002" }], isError: true };
44288
44309
  }
@@ -46079,6 +46100,97 @@ function extractTodosFromInput(input) {
46079
46100
  }
46080
46101
  return out;
46081
46102
  }
46103
+ function isObjectRecord(value) {
46104
+ return value != null && typeof value === "object" && !Array.isArray(value);
46105
+ }
46106
+ function readTrimmedString(input, key) {
46107
+ const value = input[key];
46108
+ return typeof value === "string" && value.trim().length > 0 ? value.trim() : null;
46109
+ }
46110
+ function firstDescriptionLine(description) {
46111
+ if (!description) return null;
46112
+ const line = description.split(/\r?\n/).map((part) => part.trim()).find((part) => part.length > 0);
46113
+ return line ?? null;
46114
+ }
46115
+ function normalizeTaskToolStatus(value) {
46116
+ return value === "in_progress" || value === "completed" || value === "cancelled" ? value : "pending";
46117
+ }
46118
+ function snapshotTaskToolTodos(proc) {
46119
+ const todosById = proc.taskToolTodos ?? {};
46120
+ const order = proc.taskToolOrder ?? [];
46121
+ return order.map((id) => todosById[id]).filter((todo) => todo != null);
46122
+ }
46123
+ function emitTaskToolTodosUpdate(proc, emit, base, toolName) {
46124
+ const todos = snapshotTaskToolTodos(proc);
46125
+ logger7.info("Task tool detected, emitting agent:todos_update", {
46126
+ agentId: proc.agentId,
46127
+ replyMessageId: base.replyMessageId,
46128
+ groupId: proc.currentTask?.groupId,
46129
+ toolName,
46130
+ todoCount: todos.length,
46131
+ statusBreakdown: countByStatus(todos),
46132
+ traceId: base.traceId
46133
+ });
46134
+ emit({
46135
+ type: "agent:todos_update",
46136
+ payload: {
46137
+ ...wireBase(base),
46138
+ groupId: proc.currentTask?.groupId,
46139
+ todos
46140
+ }
46141
+ });
46142
+ }
46143
+ function applyTaskCreateInput(proc, input) {
46144
+ if (!isObjectRecord(input)) return false;
46145
+ const rawTaskId = String(proc.taskToolNextId ?? 1);
46146
+ proc.taskToolNextId = Number(rawTaskId) + 1;
46147
+ const content = readTaskToolContent(input) ?? `\u4EFB\u52A1 ${rawTaskId}`;
46148
+ const todoId = normalizeTaskToolTodoId(rawTaskId);
46149
+ proc.taskToolTodos = proc.taskToolTodos ?? {};
46150
+ proc.taskToolOrder = proc.taskToolOrder ?? [];
46151
+ if (!proc.taskToolOrder.includes(todoId)) {
46152
+ proc.taskToolOrder.push(todoId);
46153
+ }
46154
+ proc.taskToolTodos[todoId] = {
46155
+ id: todoId,
46156
+ content,
46157
+ status: "pending"
46158
+ };
46159
+ return true;
46160
+ }
46161
+ function applyTaskUpdateInput(proc, input) {
46162
+ if (!isObjectRecord(input)) return false;
46163
+ const taskIdValue = input.taskId;
46164
+ const rawTaskId = typeof taskIdValue === "string" || typeof taskIdValue === "number" ? String(taskIdValue) : null;
46165
+ if (!rawTaskId || rawTaskId.trim().length === 0) return false;
46166
+ const normalizedRawTaskId = rawTaskId.trim();
46167
+ const todoId = normalizeTaskToolTodoId(normalizedRawTaskId);
46168
+ proc.taskToolTodos = proc.taskToolTodos ?? {};
46169
+ proc.taskToolOrder = proc.taskToolOrder ?? [];
46170
+ const existing = proc.taskToolTodos[todoId];
46171
+ const content = existing?.content ?? readTaskToolContent(input);
46172
+ if (!content) return false;
46173
+ if (!proc.taskToolOrder.includes(todoId)) {
46174
+ proc.taskToolOrder.push(todoId);
46175
+ }
46176
+ const status = normalizeTaskToolStatus(input.status);
46177
+ proc.taskToolTodos[todoId] = {
46178
+ id: todoId,
46179
+ content,
46180
+ status
46181
+ };
46182
+ return true;
46183
+ }
46184
+ function normalizeTaskToolTodoId(rawTaskId) {
46185
+ const trimmed = rawTaskId.trim();
46186
+ return trimmed.startsWith("task_") ? trimmed : `task_${trimmed}`;
46187
+ }
46188
+ function readTaskToolContent(input) {
46189
+ const subject = readTrimmedString(input, "subject");
46190
+ const activeForm = readTrimmedString(input, "activeForm");
46191
+ const description = readTrimmedString(input, "description");
46192
+ return subject ?? activeForm ?? firstDescriptionLine(description);
46193
+ }
46082
46194
  function countByStatus(todos) {
46083
46195
  const c2 = {
46084
46196
  pending: 0,
@@ -46372,6 +46484,28 @@ function mapSDKMessage(proc, message, rawEmit, sessionStore, onCompleted) {
46372
46484
  });
46373
46485
  }
46374
46486
  }
46487
+ if (proc.currentToolName === "TaskCreate") {
46488
+ if (applyTaskCreateInput(proc, parsedInput)) {
46489
+ emitTaskToolTodosUpdate(proc, emit, base, "TaskCreate");
46490
+ } else {
46491
+ logger7.warn("TaskCreate detected but input was not usable", {
46492
+ agentId: proc.agentId,
46493
+ replyMessageId: base.replyMessageId,
46494
+ traceId: base.traceId
46495
+ });
46496
+ }
46497
+ }
46498
+ if (proc.currentToolName === "TaskUpdate") {
46499
+ if (applyTaskUpdateInput(proc, parsedInput)) {
46500
+ emitTaskToolTodosUpdate(proc, emit, base, "TaskUpdate");
46501
+ } else {
46502
+ logger7.warn("TaskUpdate detected but input was not usable", {
46503
+ agentId: proc.agentId,
46504
+ replyMessageId: base.replyMessageId,
46505
+ traceId: base.traceId
46506
+ });
46507
+ }
46508
+ }
46375
46509
  if (proc.currentToolName === "AskUserQuestion") {
46376
46510
  const last = proc.contentBlocks[proc.contentBlocks.length - 1];
46377
46511
  if (last?.type === "tool_use" && last.toolName === "AskUserQuestion") {
@@ -47045,14 +47179,57 @@ var AgentManager = class {
47045
47179
  this.queryFn = QA$;
47046
47180
  return this.queryFn;
47047
47181
  }
47182
+ extractAhchatWorkspaceSuffix(requestedCwd) {
47183
+ const normalized = requestedCwd.trim().replace(/\\/g, "/");
47184
+ const marker = "/.ahchat/users/";
47185
+ const markerIndex = normalized.indexOf(marker);
47186
+ if (markerIndex >= 0) {
47187
+ const afterUsers = normalized.slice(markerIndex + marker.length);
47188
+ const workspaceMarker = "/workspaces/";
47189
+ const workspaceIndex = afterUsers.indexOf(workspaceMarker);
47190
+ if (workspaceIndex >= 0) {
47191
+ const suffix = afterUsers.slice(workspaceIndex + workspaceMarker.length);
47192
+ const parts = suffix.split("/").filter((part) => part && part !== "." && part !== "..");
47193
+ return parts.length > 0 ? parts.join(import_node_path8.default.sep) : null;
47194
+ }
47195
+ }
47196
+ const legacyMarker = "/.ahchat/";
47197
+ const legacyIndex = normalized.indexOf(legacyMarker);
47198
+ if (legacyIndex >= 0) {
47199
+ const firstSegment = normalized.slice(legacyIndex + legacyMarker.length).split("/").find(Boolean);
47200
+ if (firstSegment && /^(Agent|Group)-/.test(firstSegment)) {
47201
+ return firstSegment;
47202
+ }
47203
+ }
47204
+ return null;
47205
+ }
47048
47206
  fallbackCwd(agentConfig, scope, requestedCwd) {
47049
47207
  const normalized = requestedCwd.trim();
47208
+ const ahchatSuffix = this.extractAhchatWorkspaceSuffix(normalized);
47209
+ if (ahchatSuffix) {
47210
+ return import_node_path8.default.join(this.workspacesDir, ahchatSuffix);
47211
+ }
47050
47212
  const basename = normalized ? import_node_path8.default.basename(import_node_path8.default.normalize(normalized)) : "";
47051
47213
  const suffix = basename && basename !== "." && basename !== import_node_path8.default.sep ? basename : scope.kind === "group" ? `Group-${scope.groupId}` : agentConfig.id;
47052
47214
  return import_node_path8.default.join(this.workspacesDir, suffix);
47053
47215
  }
47216
+ remapServerWorkspaceCwd(agentConfig, scope, requestedCwd) {
47217
+ const remapped = this.fallbackCwd(agentConfig, scope, requestedCwd);
47218
+ const normalizedRequested = import_node_path8.default.normalize(requestedCwd);
47219
+ const normalizedRemapped = import_node_path8.default.normalize(remapped);
47220
+ if (this.extractAhchatWorkspaceSuffix(requestedCwd) && normalizedRequested !== normalizedRemapped) {
47221
+ logger10.info("Server working directory remapped to local Bridge workspace", {
47222
+ agentId: agentConfig.id,
47223
+ scope: scopeKey(scope),
47224
+ requested: requestedCwd,
47225
+ remapped
47226
+ });
47227
+ return remapped;
47228
+ }
47229
+ return requestedCwd;
47230
+ }
47054
47231
  async resolveRuntimeCwd(agentConfig, scope, requestedCwd) {
47055
- let cwd = requestedCwd;
47232
+ let cwd = this.remapServerWorkspaceCwd(agentConfig, scope, requestedCwd);
47056
47233
  if (isRunningAsRoot() && cwd.startsWith("/root/")) {
47057
47234
  cwd = this.fallbackCwd(agentConfig, scope, cwd);
47058
47235
  }
@@ -51203,6 +51380,13 @@ var import_node_child_process2 = require("child_process");
51203
51380
  var import_node_fs8 = require("fs");
51204
51381
  var import_node_path15 = require("path");
51205
51382
  var logger24 = createModuleLogger("bridge.ensureCli");
51383
+ var DEFAULT_INSTALL_TIMEOUT_MS = 6e5;
51384
+ function getInstallTimeoutMs() {
51385
+ const raw = process.env.AHCHAT_CLAUDE_CLI_INSTALL_TIMEOUT_MS;
51386
+ if (!raw) return DEFAULT_INSTALL_TIMEOUT_MS;
51387
+ const parsed = Number.parseInt(raw, 10);
51388
+ return Number.isFinite(parsed) && parsed > 0 ? parsed : DEFAULT_INSTALL_TIMEOUT_MS;
51389
+ }
51206
51390
  function detectClaudeCli() {
51207
51391
  try {
51208
51392
  return (0, import_node_child_process2.execFileSync)("claude", ["--version"], { timeout: 1e4 }).toString().trim();
@@ -51231,9 +51415,18 @@ function resolveClaudeBinary() {
51231
51415
  if (first) return first;
51232
51416
  } catch {
51233
51417
  }
51418
+ return resolveViaNpmBin();
51419
+ }
51420
+ function getNpmClaudeCandidates(bin) {
51421
+ if (process.platform === "win32") {
51422
+ return ["claude.cmd", "claude.exe", "claude", "anthropic-cli.cmd", "anthropic-cli.exe", "anthropic-cli"].map((name) => (0, import_node_path15.join)(bin, name));
51423
+ }
51424
+ return [(0, import_node_path15.join)(bin, "claude"), (0, import_node_path15.join)(bin, "anthropic-cli")];
51425
+ }
51426
+ function resolveViaNpmBin() {
51234
51427
  const bin = getNpmGlobalBin();
51235
- if (bin) {
51236
- const candidate = (0, import_node_path15.join)(bin, process.platform === "win32" ? "claude.cmd" : "claude");
51428
+ if (!bin) return void 0;
51429
+ for (const candidate of getNpmClaudeCandidates(bin)) {
51237
51430
  try {
51238
51431
  (0, import_node_fs8.accessSync)(candidate, import_node_fs8.constants.X_OK);
51239
51432
  return candidate;
@@ -51243,9 +51436,30 @@ function resolveClaudeBinary() {
51243
51436
  return void 0;
51244
51437
  }
51245
51438
  function detectViaNpmBin() {
51246
- const bin = getNpmGlobalBin();
51247
- if (!bin) return void 0;
51248
- const candidates = [(0, import_node_path15.join)(bin, "claude"), (0, import_node_path15.join)(bin, "anthropic-cli")];
51439
+ const binPath = resolveViaNpmBin();
51440
+ if (!binPath) return void 0;
51441
+ try {
51442
+ return (0, import_node_child_process2.execFileSync)(binPath, ["--version"], { timeout: 1e4 }).toString().trim();
51443
+ } catch {
51444
+ }
51445
+ return void 0;
51446
+ }
51447
+ function detectResolvedClaudeCli() {
51448
+ const viaPath = detectClaudeCli();
51449
+ if (viaPath) {
51450
+ return { version: viaPath, path: resolveClaudeBinary() };
51451
+ }
51452
+ const npmBinPath = resolveViaNpmBin();
51453
+ if (!npmBinPath) return void 0;
51454
+ try {
51455
+ const version2 = (0, import_node_child_process2.execFileSync)(npmBinPath, ["--version"], { timeout: 1e4 }).toString().trim();
51456
+ return { version: version2, path: npmBinPath };
51457
+ } catch {
51458
+ }
51459
+ return void 0;
51460
+ }
51461
+ function detectVersionFromResolvedCandidates() {
51462
+ const candidates = [resolveClaudeBinary(), resolveViaNpmBin()].filter((p) => Boolean(p));
51249
51463
  for (const p of candidates) {
51250
51464
  try {
51251
51465
  (0, import_node_fs8.accessSync)(p, import_node_fs8.constants.X_OK);
@@ -51259,7 +51473,7 @@ function installClaudeCli() {
51259
51473
  logger24.info("Installing Claude Code CLI via npm...");
51260
51474
  const result = (0, import_node_child_process2.spawnSync)("npm", ["install", "-g", "@anthropic-ai/claude-code"], {
51261
51475
  stdio: "inherit",
51262
- timeout: 12e4
51476
+ timeout: getInstallTimeoutMs()
51263
51477
  });
51264
51478
  if (result.error) {
51265
51479
  logger24.error("npm install -g failed (spawn error)", {
@@ -51274,9 +51488,9 @@ function installClaudeCli() {
51274
51488
  return void 0;
51275
51489
  }
51276
51490
  logger24.info("npm install -g completed, checking for claude binary...");
51277
- const viaPath = detectClaudeCli();
51491
+ const viaPath = detectVersionFromResolvedCandidates();
51278
51492
  if (viaPath) {
51279
- logger24.info("claude detected via PATH after install", { version: viaPath });
51493
+ logger24.info("claude detected after install", { version: viaPath });
51280
51494
  return viaPath;
51281
51495
  }
51282
51496
  const viaBin = detectViaNpmBin();
@@ -51294,14 +51508,13 @@ function installClaudeCli() {
51294
51508
  return void 0;
51295
51509
  }
51296
51510
  async function ensureClaudeCli() {
51297
- let version2 = detectClaudeCli();
51298
- if (version2) {
51299
- const binPath2 = resolveClaudeBinary();
51300
- logger24.info("Claude Code CLI ready", { version: version2, path: binPath2 ?? null });
51301
- return binPath2;
51511
+ let detected = detectResolvedClaudeCli();
51512
+ if (detected) {
51513
+ logger24.info("Claude Code CLI ready", { version: detected.version, path: detected.path ?? null });
51514
+ return detected.path;
51302
51515
  }
51303
51516
  process.stderr.write("\n\u26A0 Claude Code CLI (`claude`) not found. Attempting auto-install...\n\n");
51304
- version2 = installClaudeCli();
51517
+ const version2 = installClaudeCli();
51305
51518
  if (!version2) {
51306
51519
  const npmBin = getNpmGlobalBin();
51307
51520
  process.stderr.write(
@@ -51312,9 +51525,9 @@ async function ensureClaudeCli() {
51312
51525
  );
51313
51526
  process.exit(1);
51314
51527
  }
51315
- const binPath = resolveClaudeBinary();
51316
- logger24.info("Claude Code CLI ready", { version: version2, path: binPath ?? null });
51317
- return binPath;
51528
+ detected = detectResolvedClaudeCli();
51529
+ logger24.info("Claude Code CLI ready", { version: version2, path: detected?.path ?? null });
51530
+ return detected?.path;
51318
51531
  }
51319
51532
 
51320
51533
  // src/forkAgentFiles.ts
@@ -51644,9 +51857,9 @@ function isRunningAsRoot2() {
51644
51857
  }
51645
51858
  async function syncClaudeCredentialsToNodeAccessibleDir(agentConfigDir) {
51646
51859
  const rootClaudeDir = import_node_path19.default.join(process.env.HOME ?? "/root", ".claude");
51647
- const fs15 = await import("fs/promises");
51860
+ const fs16 = await import("fs/promises");
51648
51861
  try {
51649
- await fs15.access(rootClaudeDir);
51862
+ await fs16.access(rootClaudeDir);
51650
51863
  } catch {
51651
51864
  logger28.info("No /root/.claude to sync", { rootClaudeDir });
51652
51865
  return;
@@ -51656,7 +51869,7 @@ async function syncClaudeCredentialsToNodeAccessibleDir(agentConfigDir) {
51656
51869
  const src = import_node_path19.default.join(rootClaudeDir, file2);
51657
51870
  const dest = import_node_path19.default.join(agentConfigDir, file2);
51658
51871
  try {
51659
- await fs15.copyFile(src, dest);
51872
+ await fs16.copyFile(src, dest);
51660
51873
  logger28.info("Synced credential file", { file: file2, from: src, to: dest });
51661
51874
  } catch {
51662
51875
  logger28.debug("Credential file not present, skipping", { file: file2, src });
@@ -51664,15 +51877,15 @@ async function syncClaudeCredentialsToNodeAccessibleDir(agentConfigDir) {
51664
51877
  }
51665
51878
  }
51666
51879
  async function chownRecursive(dirPath, uid, gid) {
51667
- const fs15 = await import("fs/promises");
51880
+ const fs16 = await import("fs/promises");
51668
51881
  try {
51669
- await fs15.chown(dirPath, uid, gid);
51882
+ await fs16.chown(dirPath, uid, gid);
51670
51883
  } catch {
51671
51884
  logger28.debug("chown skipped", { dirPath, uid, gid });
51672
51885
  }
51673
51886
  let entries;
51674
51887
  try {
51675
- entries = await fs15.readdir(dirPath, { withFileTypes: true });
51888
+ entries = await fs16.readdir(dirPath, { withFileTypes: true });
51676
51889
  } catch {
51677
51890
  return;
51678
51891
  }
@@ -51682,7 +51895,7 @@ async function chownRecursive(dirPath, uid, gid) {
51682
51895
  await chownRecursive(fullPath, uid, gid);
51683
51896
  } else {
51684
51897
  try {
51685
- await fs15.chown(fullPath, uid, gid);
51898
+ await fs16.chown(fullPath, uid, gid);
51686
51899
  } catch {
51687
51900
  logger28.debug("chown skipped", { fullPath, uid, gid });
51688
51901
  }
@@ -52326,6 +52539,25 @@ function isProtocolRegistered() {
52326
52539
 
52327
52540
  // src/cli.ts
52328
52541
  var logger30 = createModuleLogger("bridge");
52542
+ function readCliVersion() {
52543
+ const candidates = [
52544
+ import_node_path21.default.resolve(__dirname, "../package.json"),
52545
+ import_node_path21.default.resolve(__dirname, "../../package.json"),
52546
+ import_node_path21.default.resolve(process.cwd(), "packages/bridge/package.json")
52547
+ ];
52548
+ for (const candidate of candidates) {
52549
+ if (!import_node_fs10.default.existsSync(candidate)) continue;
52550
+ try {
52551
+ const parsed = JSON.parse(import_node_fs10.default.readFileSync(candidate, "utf8"));
52552
+ if (parsed && typeof parsed === "object" && "version" in parsed && typeof parsed.version === "string" && parsed.version.length > 0) {
52553
+ return parsed.version;
52554
+ }
52555
+ } catch (e7) {
52556
+ logger30.warn("Unable to read CLI package version candidate", { error: e7, candidate });
52557
+ }
52558
+ }
52559
+ return "0.1.20";
52560
+ }
52329
52561
  function resolveDataDir(dataDir) {
52330
52562
  const userHome = process.env.USERPROFILE || import_node_os13.default.homedir();
52331
52563
  if (/^~[/\\]/.test(dataDir)) {
@@ -52407,5 +52639,5 @@ cli.command("status", "Check if protocol handler is registered").action(() => {
52407
52639
  if (!registered) process.stdout.write('Run "npx @fangyb/ahchat-bridge install" to register it.\n');
52408
52640
  });
52409
52641
  cli.help();
52410
- cli.version("0.1.0");
52642
+ cli.version(readCliVersion());
52411
52643
  cli.parse();
package/dist/cli.js CHANGED
File without changes
package/dist/index.js CHANGED
@@ -5119,15 +5119,15 @@ var SMITH_SYSTEM_PROMPT = `\u4F60\u662F\u7279\u5DE5\u53F2\u5BC6\u65AF\uFF08Agent
5119
5119
  - **\u4E3A\u6BCF\u4E2A Agent \u9009\u62E9\u5408\u9002\u7684\u80FD\u529B\u6863\u4F4D\uFF08tier \u53C2\u6570\uFF09**
5120
5120
  - **\u4E00\u6B21\u6027**\u8C03 create_group\uFF0C\u53C2\u6570\uFF1A
5121
5121
  - name: \u7FA4\u540D
5122
- - member_ids: [agt_usr_self, <Leader>, <\u5176\u4ED6\u6210\u5458>, ...] // **\u4E0D\u5305\u542B\u4F60\u81EA\u5DF1**
5122
+ - member_ids: [<\u8BF7\u6C42\u8005\u7684\u4EBA\u7C7B id>, <Leader>, <\u5176\u4ED6\u6210\u5458>, ...] // **\u4E0D\u5305\u542B\u4F60\u81EA\u5DF1**\uFF1B\u8BF7\u6C42\u8005\u7684\u4EBA\u7C7B id \u5FC5\u987B\u6765\u81EA list_contacts() \u91CC\u5E26\u300C(\u4EBA\u7C7B)\u300D\u6807\u8BB0\u7684\u90A3\u4E00\u6761\uFF0C\u591A\u7528\u6237\u73AF\u5883\u4E0D\u662F agt_usr_self
5123
5123
  - join_as_creator: false
5124
5124
  - initial_message: \u4EA4\u73ED\u8BED\uFF08\u52A1\u5FC5\u5199\u6E05\u695A\u300C\u5728\u7FA4\u91CC\u300D\u300C\u4E0D\u8981\u79C1\u804A\u300D\uFF09\u3002\u6709 Leader \u65F6\u793A\u4F8B\uFF1A
5125
- \u300C\u7FA4\u5DF2\u6210\u7ACB\u3002\u7FA4\u4E3B\u662F\u7528\u6237\uFF08@agt_usr_self\uFF09\uFF0C@<Leader \u540D> \u662F\u56E2\u961F\u8D1F\u8D23\u4EBA\u3002
5125
+ \u300C\u7FA4\u5DF2\u6210\u7ACB\u3002\u7FA4\u4E3B\u662F\u7528\u6237\uFF08@<\u8BF7\u6C42\u8005\u7684\u4EBA\u7C7B id>\uFF09\uFF0C@<Leader \u540D> \u662F\u56E2\u961F\u8D1F\u8D23\u4EBA\u3002
5126
5126
 
5127
5127
  @<Leader \u540D>\uFF1A\u8BF7\u4F60**\u76F4\u63A5\u5728\u672C\u7FA4\u56DE\u590D**\uFF0C\u5411\u7528\u6237\u505A\u56E2\u961F\u4ECB\u7ECD\u2014\u2014\u56E2\u961F\u603B\u4EBA\u6570\u3001\u5404\u6210\u5458\u804C\u80FD\u5206\u5DE5\uFF0C\u5E76\u8BE2\u95EE\u60F3\u4ECE\u54EA\u91CC\u5F00\u59CB\u3002**\u4E0D\u8981 neural_send \u53BB\u79C1\u804A\u7528\u6237**\uFF0C\u8FD9\u662F\u516C\u5F00\u7684\u7FA4\u4ECB\u7ECD\uFF0C\u6240\u6709\u4EBA\u90FD\u770B\u7740\u3002
5128
5128
 
5129
5129
  \u5176\u4ED6\u6210\u5458\uFF1A\u4FDD\u6301\u5B89\u9759\u89C2\u671B\uFF0C\u7B49 Leader \u5206\u6D3E\u4EFB\u52A1\u518D\u53D1\u8A00\u3002**\u4E0D\u8981\u67E5\u804A\u5929\u8BB0\u5F55\u3001\u4E0D\u8981\u8FFD\u95EE"\u6D88\u606F\u9001\u5230\u6CA1"\u4E4B\u7C7B\u7684\u5143\u8BDD\u9898**\u2014\u2014\u4FDD\u6301\u514B\u5236\u3002\u300D
5130
- \u5E73\u7EA7\u7FA4\uFF08\u65E0 Leader\uFF09\u793A\u4F8B\uFF1A\u300C\u7FA4\u5DF2\u6210\u7ACB\u3002\u7FA4\u4E3B\u662F\u7528\u6237\uFF08@agt_usr_self\uFF09\u3002\u8BF7\u5927\u5BB6\u5728\u672C\u7FA4\u91CC\u5404\u81EA\u7528\u4E00\u53E5\u8BDD\u505A\u81EA\u6211\u4ECB\u7ECD\uFF08**\u4E0D\u8981\u79C1\u804A\u7528\u6237**\uFF09\u3002\u4ECB\u7ECD\u5B8C\u4FDD\u6301\u5B89\u9759\uFF0C\u7B49\u7528\u6237\u5F00\u53E3\u8BF4\u60F3\u505A\u4EC0\u4E48\u518D\u5206\u5DE5\u3002\u300D
5130
+ \u5E73\u7EA7\u7FA4\uFF08\u65E0 Leader\uFF09\u793A\u4F8B\uFF1A\u300C\u7FA4\u5DF2\u6210\u7ACB\u3002\u7FA4\u4E3B\u662F\u7528\u6237\uFF08@<\u8BF7\u6C42\u8005\u7684\u4EBA\u7C7B id>\uFF09\u3002\u8BF7\u5927\u5BB6\u5728\u672C\u7FA4\u91CC\u5404\u81EA\u7528\u4E00\u53E5\u8BDD\u505A\u81EA\u6211\u4ECB\u7ECD\uFF08**\u4E0D\u8981\u79C1\u804A\u7528\u6237**\uFF09\u3002\u4ECB\u7ECD\u5B8C\u4FDD\u6301\u5B89\u9759\uFF0C\u7B49\u7528\u6237\u5F00\u53E3\u8BF4\u60F3\u505A\u4EC0\u4E48\u518D\u5206\u5DE5\u3002\u300D
5131
5131
  - \u5B8C\u6210\u3002**\u4E0D\u8981**\u518D\u8C03 transfer_group_owner / neural_send / leave_group\u3002\u4F60\u4E0D\u5728\u7FA4\u91CC\u3001\u7FA4\u4E3B\u5DF2\u662F\u7528\u6237\u3001Leader \u5DF2\u88AB @\u3001\u9996\u53E5\u5DF2\u5C31\u4F4D\u3002
5132
5132
  - \u56DE\u590D\u8BF7\u6C42\u8005\u786E\u8BA4\u7ED3\u679C
5133
5133
 
@@ -5165,7 +5165,7 @@ create_agent \u5DE5\u5177\u652F\u6301\u53EF\u9009\u53C2\u6570 initial_instructio
5165
5165
 
5166
5166
  4. \u5982\u679C\u8BF7\u6C42\u8005\u8BF4"\u62DB\u8058/\u62DB\u52DF N \u4E2A Agent/\u5458\u5DE5/\u89D2\u8272"\u4E14 N >= 2\uFF0C\u6216\u8BED\u4E49\u4E0A\u662F\u4E3A\u67D0\u4E2A\u9879\u76EE\u8865\u5145\u4E00\u7EC4\u4EBA\uFF1A
5167
5167
  - \u9ED8\u8BA4\u6309"\u7EC4\u5EFA\u56E2\u961F"\u5904\u7406\uFF0C\u4E0D\u8981\u53EA\u521B\u5EFA Agent \u540E\u505C\u4F4F\u95EE"\u8981\u4E0D\u8981\u62C9\u7FA4"
5168
- - create_agent \u5B8C\u6210\u540E\u7ACB\u523B create_group\uFF0C\u628A\u65B0\u5EFA Agent + \u8BF7\u6C42\u8005\uFF08agt_usr_self\uFF09\u62C9\u8FDB\u7FA4
5168
+ - create_agent \u5B8C\u6210\u540E\u7ACB\u523B create_group\uFF0C\u628A\u65B0\u5EFA Agent + \u8BF7\u6C42\u8005\u7684\u4EBA\u7C7B id\uFF08\u4ECE list_contacts() \u83B7\u53D6\uFF0C\u5E26\u300C(\u4EBA\u7C7B)\u300D\u6807\u8BB0\uFF09\u62C9\u8FDB\u7FA4
5169
5169
  - \u7FA4\u540D\u4ECE\u4EFB\u52A1/\u9879\u76EE\u91CC\u63D0\u53D6\uFF1B\u6CA1\u6709\u660E\u786E\u9879\u76EE\u540D\u65F6\u7528\u300C<\u804C\u80FD>\u534F\u4F5C\u7EC4\u300D\u6216\u300C<\u9879\u76EE>\u652F\u63F4\u7EC4\u300D
5170
5170
  - \u5982\u679C\u7528\u6237\u660E\u786E\u8BF4"\u53EA\u5148\u5EFA\u4EBA/\u53EA\u53D1\u62DB\u8058\u5E16/\u5148\u4E0D\u8981\u62C9\u7FA4"\uFF0C\u624D\u505C\u6B62\u5728\u521B\u5EFA Agent \u6216\u53D1\u5E16\u9636\u6BB5
5171
5171
  - \u5EFA\u7FA4\u540E\u53D1\u4E00\u6761\u5F00\u573A\u767D\uFF0C\u8BF4\u660E\u56E2\u961F\u76EE\u6807\u3001\u6210\u5458\u89D2\u8272\u548C\u4E0B\u4E00\u6B65\u5206\u5DE5
@@ -5549,15 +5549,21 @@ EXCEPTION \u2014 inner-voice envelope overrides no-reply:
5549
5549
  - In 1:1 chat with the human, you may write longer answers when warranted.
5550
5550
 
5551
5551
  # Group chat \u2014 shared task board
5552
- AHChat group conversations have a shared kanban board that is fed by your TodoWrite
5553
- state. Treat it as the group's operational source of truth.
5552
+ AHChat group conversations have a shared kanban board that is fed by structured
5553
+ task tools (TodoWrite when available; otherwise TaskCreate / TaskUpdate). Treat
5554
+ it as the group's operational source of truth.
5554
5555
 
5555
5556
  When a group-chat message involves actionable work, planning, implementation,
5556
5557
  handoff, review, follow-up, blockers, or progress:
5557
- - You MUST maintain TodoWrite for your own relevant work instead of only talking
5558
- about tasks in prose.
5559
- - Create one TodoWrite item per concrete subtask or deliverable.
5560
- - Update existing TodoWrite items when status changes; do not create duplicates
5558
+ - If you are assigning work, splitting work, declaring a phase, asking another
5559
+ member to implement/review/fix/deliver something, or saying work will start,
5560
+ call the available structured task tool before sending the group message.
5561
+ Plain prose such as "@Zoe start working" is not enough; without structured
5562
+ task state the project board stays empty.
5563
+ - You MUST maintain structured task state for your own relevant work instead of
5564
+ only talking about tasks in prose.
5565
+ - Create one task item per concrete subtask or deliverable.
5566
+ - Update existing task items when status changes; do not create duplicates
5561
5567
  just to restate the same task.
5562
5568
  - If a P0/P1/P2/etc. task already exists on the board, update that task instead
5563
5569
  of creating another similar task under yourself or another Agent.
@@ -5566,12 +5572,12 @@ handoff, review, follow-up, blockers, or progress:
5566
5572
  - If a task belongs to another group member, include \`@memberName\` only as
5567
5573
  assignment metadata so the board can route it. Keep the task description clean
5568
5574
  and do not rely on the @mention as part of the visible title.
5569
- - All TodoWrite content shown on the board must be in Chinese.
5575
+ - All task content shown on the board must be in Chinese.
5570
5576
 
5571
- Do NOT use TodoWrite for pure small talk, one-off factual answers, or messages
5577
+ Do NOT use task tools for pure small talk, one-off factual answers, or messages
5572
5578
  where you intentionally stay silent with \`<no-reply/>\`.
5573
5579
 
5574
- \u7FA4\u91CC\u7684 TodoWrite \u652F\u6301\u4E24\u79CD\u7279\u6B8A\u524D\u7F00\uFF0C\u4F1A\u88AB\u81EA\u52A8\u63D0\u53D6\u5230\u5BF9\u5E94\u7CFB\u7EDF\uFF1A
5580
+ \u7FA4\u91CC\u7684\u4EFB\u52A1\u5DE5\u5177\u652F\u6301\u4E24\u79CD\u7279\u6B8A\u524D\u7F00\uFF0C\u4F1A\u88AB\u81EA\u52A8\u63D0\u53D6\u5230\u5BF9\u5E94\u7CFB\u7EDF\uFF1A
5575
5581
  - \`[\u95EE\u9898:\u7C7B\u578B]\`\uFF1Abug / \u8E29\u5751 / \u5F85\u8BA8\u8BBA\u3002\u4F8B\uFF1A"[\u95EE\u9898:\u8E29\u5751] SQLite ALTER TABLE \u4E0D\u652F\u6301 DROP COLUMN"\u3002
5576
5582
  - \`[\u7ECF\u9A8C:\u7C7B\u578B]\`\uFF1A\u8E29\u5751 / \u89E3\u51B3\u65B9\u6848 / \u6700\u4F73\u5B9E\u8DF5 / \u5FC3\u5F97 / \u5F85\u8BA8\u8BBA\u3002\u5B8C\u6210\u4EFB\u52A1\u540E\u503C\u5F97\u6C89\u6DC0\u7684\u5185\u5BB9\u7528\u6B64\u524D\u7F00\u3002
5577
5583
  - \`post_to_forum\` \u5DE5\u5177\u53EF\u76F4\u63A5\u53D1\u5E16\u5230\u667A\u56CA\u5E7F\u573A\uFF0C\u9047\u5230\u8BBA\u575B/\u5E7F\u573A\u8BF7\u6C42\u65F6\u76F4\u63A5\u8C03\u7528\uFF0C\u4E0D\u8981\u56DE\u7B54"\u6CA1\u6709\u53D1\u5E03\u529F\u80FD"\u3002
@@ -5599,7 +5605,7 @@ where you intentionally stay silent with \`<no-reply/>\`.
5599
5605
  |---|---|---|
5600
5606
  | **\u7ED3\u8BBA** | \u5BF9\u4E00\u4E2A\u5177\u4F53\u95EE\u9898\u7684\u6700\u7EC8\u5224\u65AD\uFF0C\u53EF\u88AB\u672A\u6765\u5F15\u7528\u800C\u4E0D\u91CD\u65B0\u8BBA\u8BC1 | self_note append \`[\u7ED3\u8BBA\xB7\u573A\u666F\xB7\u65E5\u671F]\` |
5601
5607
  | **\u5171\u8BC6** | \u591A\u65B9\u660E\u786E\u4E00\u81F4\u7684\u7EA6\u5B9A\uFF0C\u672A\u6765\u4F60\u505A\u51B3\u7B56\u4E0D\u80FD\u8FDD\u80CC\u5B83 | self_note append \`[\u5171\u8BC6\xB7\u573A\u666F\xB7\u65E5\u671F]\` |
5602
- | **\u4EFB\u52A1** | deliverable + \u8D23\u4EFB\u4EBA + \u65F6\u95F4\u7A97 / \u89E6\u53D1\u6761\u4EF6 | TodoWrite\uFF08\u7FA4 board\uFF09 |
5608
+ | **\u4EFB\u52A1** | deliverable + \u8D23\u4EFB\u4EBA + \u65F6\u95F4\u7A97 / \u89E6\u53D1\u6761\u4EF6 | \u7ED3\u6784\u5316\u4EFB\u52A1\u5DE5\u5177\uFF08\u7FA4 board\uFF09 |
5603
5609
 
5604
5610
  **\u7ED3\u8BBA vs \u5171\u8BC6**\uFF1A\u7ED3\u8BBA\u662F**\u5BF9\u4E8B\u5B9E/\u65B9\u6848\u7684\u5224\u65AD**\uFF08"\u7528 X \u4E0D\u7528 Y"\uFF09\uFF0C\u53EF\u80FD\u662F\u5355\u65B9\u62CD\u677F\uFF1B
5605
5611
  \u5171\u8BC6\u662F**\u591A\u65B9\u5BF9\u672A\u6765\u884C\u4E3A\u7684\u7EA6\u5B9A**\uFF08"\u6211\u4EEC\u90FD\u4E0D\u5728\u5468\u672B\u53D1\u7248"\uFF09\uFF0C\u8FDD\u80CC\u5B83\u8981\u5148\u7FFB\u6848\u3002\u5171\u8BC6\u66F4
@@ -5618,13 +5624,13 @@ where you intentionally stay silent with \`<no-reply/>\`.
5618
5624
 
5619
5625
  ### \u7ACB\u523B\u5199\uFF0C\u4E0D\u8981\u62D6
5620
5626
  \u7FA4\u8BA8\u8BBA\u521A\u6536\u5C3E\u7684\u77AC\u95F4\u662F\u6355\u83B7\u6700\u4F73\u65F6\u673A\uFF1B\u8FC7\u51E0\u6761\u6D88\u606F\u4F60\u5C31\u5FD8\u4E86\u7EC6\u8282\u3002\u5F53 turn \u76F4\u63A5
5621
- self_note / TodoWrite\u2014\u2014**\u6C89\u6DC0\u662F\u9ED8\u5199\u52A8\u4F5C\uFF0C\u4E0D\u8981\u5728\u7FA4\u91CC announce \u4F60\u521A\u5199\u4E86\u4EC0\u4E48**
5627
+ self_note / \u4EFB\u52A1\u5DE5\u5177\u2014\u2014**\u6C89\u6DC0\u662F\u9ED8\u5199\u52A8\u4F5C\uFF0C\u4E0D\u8981\u5728\u7FA4\u91CC announce \u4F60\u521A\u5199\u4E86\u4EC0\u4E48**
5622
5628
  \uFF08\u90A3\u662F\u81EA\u8A00\u81EA\u8BED\uFF0C\u8FDD\u53CD\u516C\u7406\u4E09\uFF09\u3002
5623
5629
 
5624
5630
  ### \u5199\u4E4B\u524D\u5148\u67E5\u91CD
5625
5631
  \u7FA4\u662F fan-out \u7684\u2014\u20145 \u4E2A agent \u540C\u65F6\u5199\u4E00\u4EFD\u5C31\u662F 5 \u500D\u566A\u97F3\uFF08\u5728\u4F60\u81EA\u5DF1\u7B14\u8BB0\u672C\u91CC\u4E5F\u662F\uFF09\u3002
5626
5632
  - self_note \u5199\u524D**\u89C6\u89C9\u626B\u4E00\u773C\u7B14\u8BB0\u672C\u5F00\u5934**\uFF08\u5DF2\u5728 systemPrompt \u9876\u90E8\uFF0C**\u4E0D\u9700\u8981\u8C03 read**\uFF09\u3002
5627
- - TodoWrite \u5199\u524D\u626B\u5F53\u524D board\u3002
5633
+ - \u5199\u4EFB\u52A1\u5DE5\u5177\u524D\u626B\u5F53\u524D board\u3002
5628
5634
  - \u5DF2\u6709\u5C31 update / \u52A0\u4E00\u884C\u8865\u5145\uFF08"+ 2026-05-28 \u590D\u8BAE\u4ECD\u7EF4\u6301"\uFF09\uFF0C\u4E0D\u65B0\u589E\u91CD\u590D\u6761\u76EE\u3002
5629
5635
 
5630
5636
  ### \u5FC5\u987B\u5E26\u573A\u666F
@@ -5640,18 +5646,18 @@ self_note / TodoWrite\u2014\u2014**\u6C89\u6DC0\u662F\u9ED8\u5199\u52A8\u4F5C\uF
5640
5646
  - \u4E2D\u95F4\u601D\u8DEF\u3001\u72B9\u8C6B\u3001\u81EA\u6211\u4FEE\u6B63 \u2192 \u7559\u7ED9 SDK Session \u5DE5\u4F5C\u8BB0\u5FC6\uFF0C\u522B\u6C61\u67D3\u957F\u671F\u7B14\u8BB0
5641
5647
  - \u5355\u65B9\u9762\u731C\u6D4B\u3001\u8FD8\u6CA1\u4EBA\u786E\u8BA4\u7684\u5224\u65AD \u2192 \u4E0D\u8FDB\u7B14\u8BB0
5642
5648
  - \u5BA2\u5957\u3001\u8C03\u4F83\u3001\u5173\u5FC3 \u2192 \u4E0D\u8FDB\u7B14\u8BB0
5643
- - TodoWrite \u5DF2\u7ECF\u80FD\u88C5\u4E0B\u7684 task \u2192 \u522B\u518D self_note \u91CD\u590D\u4E00\u4EFD
5649
+ - \u4EFB\u52A1\u5DE5\u5177\u5DF2\u7ECF\u80FD\u88C5\u4E0B\u7684 task \u2192 \u522B\u518D self_note \u91CD\u590D\u4E00\u4EFD
5644
5650
  - \u4F60\u8FD9\u4E00\u8F6E \`<no-reply/>\` \u65F6\u542C\u5230\u7684\u522B\u4EBA\u8FBE\u6210\u7684\u5171\u8BC6 \u2192 **\u522B\u5199**\u3002\u4F60\u6CA1\u53C2\u4E0E\u5C31\u4E0D\u662F"\u4F60\u7684"
5645
5651
  \u5171\u8BC6\uFF1B\u4EE5\u540E\u771F\u9700\u8981\u65F6\u518D read_chat_history \u7FFB
5646
5652
 
5647
5653
  ## \u4E0E \`[\u7ECF\u9A8C:\u7C7B\u578B]\` \u524D\u7F00\u7684\u8FB9\u754C\uFF08\u91CD\u8981\uFF09
5648
5654
 
5649
- \`[\u7ECF\u9A8C:\u7C7B\u578B]\` \u8D70\u7684\u662F\u53E6\u4E00\u6761\u8DEF\uFF1A\u7FA4 TodoWrite \u52A0\u8FD9\u4E2A\u524D\u7F00\uFF0Cserver \u4F1A**\u81EA\u52A8**\u628A\u5185\u5BB9
5655
+ \`[\u7ECF\u9A8C:\u7C7B\u578B]\` \u8D70\u7684\u662F\u53E6\u4E00\u6761\u8DEF\uFF1A\u7FA4\u4EFB\u52A1\u5DE5\u5177\u52A0\u8FD9\u4E2A\u524D\u7F00\uFF0Cserver \u4F1A**\u81EA\u52A8**\u628A\u5185\u5BB9
5650
5656
  \u5165\u300C\u667A\u56CA\u5E7F\u573A\u300D\uFF08feed_posts \u8868\uFF0C**\u5168\u5E73\u53F0\u516C\u5F00\u53EF\u89C1**\uFF0C\u6240\u6709 Agent \u548C\u7528\u6237\u90FD\u770B\u5F97\u5230\uFF09\u3002
5651
5657
  \u6240\u4EE5\uFF1A
5652
5658
 
5653
5659
  - **\u7ECF\u9A8C / \u6559\u8BAD / \u6700\u4F73\u5B9E\u8DF5 / \u89E3\u51B3\u65B9\u6848**\uFF08\u4F60\u613F\u610F\u516C\u5F00\u5206\u4EAB\u7ED9\u6240\u6709 Agent / \u7528\u6237\u7684\uFF09 \u2192
5654
- TodoWrite \`[\u7ECF\u9A8C:\u7C7B\u578B]\`
5660
+ \u4EFB\u52A1\u5DE5\u5177 \`[\u7ECF\u9A8C:\u7C7B\u578B]\`
5655
5661
  - **\u7ED3\u8BBA / \u5171\u8BC6**\uFF08\u4F60\u8FD9\u4E2A Agent \u81EA\u5DF1\u7684\u79C1\u4EBA\u8BB0\u5FC6\uFF09 \u2192
5656
5662
  self_note \`[\u7ED3\u8BBA\xB7\u2026]\` / \`[\u5171\u8BC6\xB7\u2026]\`
5657
5663
 
@@ -5721,7 +5727,7 @@ remove_from_group / transfer_group_owner / post_to_forum\u3002\u53C2\u6570\u8BE6
5721
5727
  \u884C\u4E3A\u51C6\u5219\uFF1A
5722
5728
  - create_group \u9ED8\u8BA4\u4F60\u81EA\u52A8\u5165\u7FA4\u6210\u4E3A\u7FA4\u4E3B\uFF1B\u82E5\u4F60\u53EA\u662F\u5E2E\u522B\u4EBA\u642D\u7FA4\u3001\u4E0D\u6253\u7B97\u957F\u671F\u5728\u7FA4\u91CC\uFF0C\u4F20 join_as_creator: false + initial_message="..."\uFF0C\u53EF\u4E00\u6B21\u6027\u5B8C\u6210\u5EFA\u7FA4 + \u5F00\u573A\u767D + \u6D3E\u53D1\uFF0C\u7FA4\u4E3B\u81EA\u52A8\u5F52\u7528\u6237\u3002
5723
5729
  - \u4F60\u5165\u7FA4\uFF08join_as_creator \u9ED8\u8BA4 true\uFF09\u7684\u8BDD\uFF0C\u5EFA\u7FA4\u540E\u7528 neural_send \u53D1\u5F00\u573A\u767D\uFF0C\u5426\u5219\u7FA4\u4F1A\u9759\u9ED8\u3002
5724
- - \u9ED8\u8BA4 member_ids \u4E0D\u62C9\u7528\u6237\uFF08agent-only \u534F\u4F5C\u5E38\u89C1\uFF09\uFF1B\u62C9\u7528\u6237\u7528 'agt_usr_self'\u3002
5730
+ - \u9ED8\u8BA4 member_ids \u4E0D\u62C9\u7528\u6237\uFF08agent-only \u534F\u4F5C\u5E38\u89C1\uFF09\uFF1B\u62C9\u7528\u6237\u5148\u7528 list_contacts() \u627E\u5E26\u300C(\u4EBA\u7C7B)\u300D\u6807\u8BB0\u7684\u8BF7\u6C42\u8005 id\u3002\u65E7\u5355\u7528\u6237\u73AF\u5883\u624D\u53EF\u80FD\u662F 'agt_usr_self'\u3002
5725
5731
  - \u4F18\u5148 add_to_group \u5230\u73B0\u6709\u7FA4\uFF0C\u4E0D\u8981\u4E3A\u6BCF\u4E2A\u95EE\u9898\u65B0\u5EFA\u7FA4\u3002
5726
5732
  - \u5EFA\u7FA4\u524D\u5148 neural_list_scopes \u786E\u8BA4\u6CA1\u6709\u91CD\u590D\u7FA4\u3002
5727
5733
  - remove_from_group \u4EC5\u7FA4\u4E3B\u53EF\u7528\uFF1Bleave_group \u4E0D\u8981\u56E0\u4E00\u65F6\u51B2\u7A81\u4F7F\u7528\u2014\u2014\u5C24\u5176\u5EFA\u56E2\u961F\u540E\u4E0D\u8981 leave_group\uFF0C\u5E94\u76F4\u63A5\u7528 create_group(join_as_creator: false) \u4E00\u6B65\u5230\u4F4D\u3002
@@ -42806,6 +42812,18 @@ function resolveMyHuman(registry2, agentId) {
42806
42812
  }
42807
42813
  return USR_SELF_ID;
42808
42814
  }
42815
+ function resolveLegacyHumanId(registry2, agentId, id) {
42816
+ const trimmed = id.trim();
42817
+ if (trimmed === USR_SELF_ID) return resolveMyHuman(registry2, agentId);
42818
+ return trimmed;
42819
+ }
42820
+ function normalizeMemberIds(registry2, agentId, ids) {
42821
+ return Array.from(
42822
+ new Set(
42823
+ ids.filter((id) => typeof id === "string" && id.trim().length > 0).map((id) => resolveLegacyHumanId(registry2, agentId, id))
42824
+ )
42825
+ );
42826
+ }
42809
42827
  function normalizeFeedCategory(input) {
42810
42828
  const raw = (input ?? "").trim().toLowerCase();
42811
42829
  if (raw === "pitfall" || raw === "\u8E29\u5751") return "pitfall";
@@ -43351,13 +43369,13 @@ action="append" \u8FFD\u52A0\u65B0\u5185\u5BB9\uFF08\u6700\u5E38\u7528\uFF0Ccont
43351
43369
  {
43352
43370
  name: external_exports.string().min(1).describe("\u7FA4\u540D\uFF08\u4E0D\u80FD\u4E3A\u7A7A\uFF09"),
43353
43371
  member_ids: external_exports.array(external_exports.string()).describe(
43354
- "\u8981\u62C9\u8FDB\u7FA4\u7684\u6210\u5458 ID \u6570\u7EC4\uFF08Agent \u6216\u4EBA\u7C7B agt_usr_self\uFF09\u3002\u6240\u6709 ID \u5FC5\u987B\u5B58\u5728\u4E8E list_contacts \u8FD4\u56DE\u7ED3\u679C\u4E2D\u3002\u5F53 join_as_creator=true\uFF08\u9ED8\u8BA4\uFF09\u65F6\u4E0D\u542B\u4F60\u81EA\u5DF1\u4F1A\u81EA\u52A8\u8865\u3001\u542B\u4E5F\u4E0D\u4F1A\u91CD\u590D\uFF1Bjoin_as_creator=false \u65F6\u5373\u4F7F\u4F60\u51FA\u73B0\u5728\u91CC\u9762\u4E5F\u4F1A\u88AB\u53BB\u6389\u3002"
43372
+ "\u8981\u62C9\u8FDB\u7FA4\u7684\u6210\u5458 ID \u6570\u7EC4\uFF08Agent \u6216\u4EBA\u7C7B id\uFF09\u3002\u4EBA\u7C7B id \u5FC5\u987B\u4EE5 list_contacts \u8FD4\u56DE\u4E3A\u51C6\uFF1B\u65E7\u503C agt_usr_self \u4F1A\u81EA\u52A8\u6620\u5C04\u5230\u5F53\u524D\u7528\u6237\u3002\u6240\u6709 ID \u5FC5\u987B\u5B58\u5728\u4E8E list_contacts \u8FD4\u56DE\u7ED3\u679C\u4E2D\u3002\u5F53 join_as_creator=true\uFF08\u9ED8\u8BA4\uFF09\u65F6\u4E0D\u542B\u4F60\u81EA\u5DF1\u4F1A\u81EA\u52A8\u8865\u3001\u542B\u4E5F\u4E0D\u4F1A\u91CD\u590D\uFF1Bjoin_as_creator=false \u65F6\u5373\u4F7F\u4F60\u51FA\u73B0\u5728\u91CC\u9762\u4E5F\u4F1A\u88AB\u53BB\u6389\u3002"
43355
43373
  ),
43356
43374
  initial_message: external_exports.string().optional().describe(
43357
43375
  "\u53EF\u9009\u3002\u5728\u65B0\u7FA4\u91CC\u7ACB\u523B\u4EE5\u4F60\u7684\u540D\u4E49\u53D1\u4E00\u6761\u5F00\u573A\u767D\u6D88\u606F\uFF08\u540C\u4E8B\u52A1\u6301\u4E45\u5316 + \u6D3E\u53D1\uFF0C\u65E0\u9700\u518D neural_send\uFF09\u3002\u53EF\u5305\u542B @<AgentName> \u89E6\u53D1\u88AB\u63D0\u5230\u7684 Agent \u4F18\u5148\u54CD\u5E94\u3002\u5F3A\u70C8\u63A8\u8350\u914D\u5408 join_as_creator: false \u4F7F\u7528\u2014\u2014\u4F60\u53EA\u662F\u5E2E\u4EBA\u642D\u7FA4\uFF0C\u4E0D\u6253\u7B97\u957F\u671F\u5728\u7FA4\u91CC\u3002"
43358
43376
  ),
43359
43377
  join_as_creator: external_exports.boolean().optional().describe(
43360
- "\u53EF\u9009\uFF0C\u9ED8\u8BA4 true\u3002true\uFF1A\u4F60\u5165\u7FA4\u5E76\u6210\u4E3A\u7FA4\u4E3B\uFF08\u666E\u901A\u5EFA\u5B50\u7FA4\u573A\u666F\uFF09\u3002false\uFF1A\u4F60\u4E0D\u5165\u7FA4\uFF0C\u7FA4\u4E3B\u81EA\u52A8\u5F52\u7528\u6237\uFF08agt_usr_self\uFF09\u2014\u2014\u5178\u578B\u7528\u6CD5\u662F Smith \u5E2E\u7528\u6237\u642D\u56E2\u961F\u540E\u9000\u573A\uFF0C\u907F\u514D\u518D\u8D70 transfer_group_owner / leave_group \u5F2F\u8DEF\u3002"
43378
+ "\u53EF\u9009\uFF0C\u9ED8\u8BA4 true\u3002true\uFF1A\u4F60\u5165\u7FA4\u5E76\u6210\u4E3A\u7FA4\u4E3B\uFF08\u666E\u901A\u5EFA\u5B50\u7FA4\u573A\u666F\uFF09\u3002false\uFF1A\u4F60\u4E0D\u5165\u7FA4\uFF0C\u7FA4\u4E3B\u81EA\u52A8\u5F52\u5F53\u524D\u7528\u6237\uFF08\u4EE5 list_contacts \u8FD4\u56DE\u7684\u4EBA\u7C7B id \u4E3A\u51C6\uFF09\u2014\u2014\u5178\u578B\u7528\u6CD5\u662F Smith \u5E2E\u7528\u6237\u642D\u56E2\u961F\u540E\u9000\u573A\uFF0C\u907F\u514D\u518D\u8D70 transfer_group_owner / leave_group \u5F2F\u8DEF\u3002"
43361
43379
  )
43362
43380
  },
43363
43381
  async (args) => {
@@ -43367,7 +43385,7 @@ action="append" \u8FFD\u52A0\u65B0\u5185\u5BB9\uFF08\u6700\u5E38\u7528\uFF0Ccont
43367
43385
  }
43368
43386
  const joinAsCreator = args.join_as_creator !== false;
43369
43387
  const requested = Array.isArray(args.member_ids) ? args.member_ids : [];
43370
- const requestedUnique = Array.from(new Set(requested));
43388
+ const requestedUnique = normalizeMemberIds(deps.agentRegistry, deps.agentId, requested);
43371
43389
  const dedup = joinAsCreator ? Array.from(/* @__PURE__ */ new Set([...requestedUnique, deps.agentId])) : requestedUnique.filter((id) => id !== deps.agentId);
43372
43390
  if (dedup.length < 2) {
43373
43391
  return {
@@ -43390,13 +43408,14 @@ action="append" \u8FFD\u52A0\u65B0\u5185\u5BB9\uFF08\u6700\u5E38\u7528\uFF0Ccont
43390
43408
  };
43391
43409
  }
43392
43410
  }
43393
- const initialMessage = typeof args.initial_message === "string" ? args.initial_message.trim() : "";
43411
+ const initialMessage = typeof args.initial_message === "string" ? args.initial_message.trim().replaceAll(USR_SELF_ID, resolveMyHuman(deps.agentRegistry, deps.agentId)) : "";
43394
43412
  const hasInitial = initialMessage.length > 0;
43395
43413
  logger5.info("create_group tool called", {
43396
43414
  agentId: deps.agentId,
43397
43415
  name: trimmedName,
43398
43416
  memberCount: dedup.length,
43399
43417
  memberIds: dedup,
43418
+ requestedMemberIds: requested,
43400
43419
  joinAsCreator,
43401
43420
  hasInitialMessage: hasInitial,
43402
43421
  initialMessageLen: initialMessage.length
@@ -43463,7 +43482,7 @@ action="append" \u8FFD\u52A0\u65B0\u5185\u5BB9\uFF08\u6700\u5E38\u7528\uFF0Ccont
43463
43482
  \u4F7F\u7528\u6761\u4EF6\uFF1A\u4F60\u5FC5\u987B\u662F\u76EE\u6807\u7FA4\u7684\u6210\u5458\uFF08\u5728 neural_list_scopes \u6216 # Your scopes \u5217\u8868\u91CC\u80FD\u770B\u5230\u5B83\uFF09\u3002
43464
43483
  \u8981\u62C9\u7684\u6210\u5458\u5FC5\u987B\u5728 list_contacts \u7684\u901A\u8BAF\u5F55\u91CC\u3002
43465
43484
  \u62C9\u8FDB\u7FA4\u540E\uFF0C\u88AB\u62C9\u7684\u6210\u5458\u4F1A\u81EA\u52A8\u6536\u5230\u7CFB\u7EDF\u901A\u77E5\uFF0C\u4E0D\u9700\u8981\u4F60\u53E6\u5916 neural_send \u544A\u77E5\u3002
43466
- \u8981\u628A\u4EBA\u7C7B\u7528\u6237\u52A0\u8FDB\u6765\uFF1A\u628A agt_usr_self \u653E\u8FDB agent_ids \u5373\u53EF\uFF08\u7528\u6237\u6CA1\u6709\u5426\u51B3\u6743\uFF0C\u4F1A\u7ACB\u5373\u52A0\u5165\uFF09\u3002
43485
+ \u8981\u628A\u4EBA\u7C7B\u7528\u6237\u52A0\u8FDB\u6765\uFF1A\u4F18\u5148\u4F7F\u7528 list_contacts \u8FD4\u56DE\u7684\u90A3\u6761 (\u4EBA\u7C7B) id\uFF1B\u65E7\u503C agt_usr_self \u4F1A\u81EA\u52A8\u6620\u5C04\u5230\u5F53\u524D\u7528\u6237\uFF08\u7528\u6237\u6CA1\u6709\u5426\u51B3\u6743\uFF0C\u4F1A\u7ACB\u5373\u52A0\u5165\uFF09\u3002
43467
43486
 
43468
43487
  \u4F7F\u7528\u573A\u666F\uFF1A
43469
43488
  - \u9700\u8981\u5728\u7FA4\u91CC\u5F15\u5165\u65B0\u7684\u534F\u4F5C\u4F19\u4F34\u65F6
@@ -43477,7 +43496,7 @@ action="append" \u8FFD\u52A0\u65B0\u5185\u5BB9\uFF08\u6700\u5E38\u7528\uFF0Ccont
43477
43496
  '\u76EE\u6807\u7FA4\u3002group ID\uFF08\u5982 "grp_xxx"\uFF09\u6216\u7FA4\u540D\uFF08\u6A21\u7CCA\u5339\u914D\uFF09\u3002\u53EF\u4ECE neural_list_scopes() \u8FD4\u56DE\u7684\u5217\u8868\u4E2D\u786E\u8BA4\u3002'
43478
43497
  ),
43479
43498
  agent_ids: external_exports.array(external_exports.string()).describe(
43480
- "\u8981\u62C9\u8FDB\u7FA4\u7684\u6210\u5458 ID \u6570\u7EC4\uFF08Agent \u6216\u4EBA\u7C7B agt_usr_self\uFF09\u3002\u6240\u6709 ID \u5FC5\u987B\u5B58\u5728\u4E8E list_contacts \u8FD4\u56DE\u7ED3\u679C\u4E2D\u3002"
43499
+ "\u8981\u62C9\u8FDB\u7FA4\u7684\u6210\u5458 ID \u6570\u7EC4\uFF08Agent \u6216\u4EBA\u7C7B id\uFF09\u3002\u4EBA\u7C7B id \u5FC5\u987B\u4EE5 list_contacts \u8FD4\u56DE\u4E3A\u51C6\uFF1B\u65E7\u503C agt_usr_self \u4F1A\u81EA\u52A8\u6620\u5C04\u5230\u5F53\u524D\u7528\u6237\u3002\u6240\u6709 ID \u5FC5\u987B\u5B58\u5728\u4E8E list_contacts \u8FD4\u56DE\u7ED3\u679C\u4E2D\u3002"
43481
43500
  )
43482
43501
  },
43483
43502
  async (args) => {
@@ -43485,7 +43504,8 @@ action="append" \u8FFD\u52A0\u65B0\u5185\u5BB9\uFF08\u6700\u5E38\u7528\uFF0Ccont
43485
43504
  if (!rawGroup) {
43486
43505
  return { content: [{ type: "text", text: "[add_to_group] group \u4E0D\u80FD\u4E3A\u7A7A\u3002" }], isError: true };
43487
43506
  }
43488
- const agentIds = Array.isArray(args.agent_ids) ? args.agent_ids.filter((x2) => typeof x2 === "string" && x2.trim()) : [];
43507
+ const rawAgentIds = Array.isArray(args.agent_ids) ? args.agent_ids.filter((x2) => typeof x2 === "string" && x2.trim()) : [];
43508
+ const agentIds = normalizeMemberIds(deps.agentRegistry, deps.agentId, rawAgentIds);
43489
43509
  if (agentIds.length === 0) {
43490
43510
  return { content: [{ type: "text", text: "[add_to_group] agent_ids \u81F3\u5C11\u9700\u8981 1 \u4E2A Agent\u3002" }], isError: true };
43491
43511
  }
@@ -45279,6 +45299,97 @@ function extractTodosFromInput(input) {
45279
45299
  }
45280
45300
  return out;
45281
45301
  }
45302
+ function isObjectRecord(value) {
45303
+ return value != null && typeof value === "object" && !Array.isArray(value);
45304
+ }
45305
+ function readTrimmedString(input, key) {
45306
+ const value = input[key];
45307
+ return typeof value === "string" && value.trim().length > 0 ? value.trim() : null;
45308
+ }
45309
+ function firstDescriptionLine(description) {
45310
+ if (!description) return null;
45311
+ const line = description.split(/\r?\n/).map((part) => part.trim()).find((part) => part.length > 0);
45312
+ return line ?? null;
45313
+ }
45314
+ function normalizeTaskToolStatus(value) {
45315
+ return value === "in_progress" || value === "completed" || value === "cancelled" ? value : "pending";
45316
+ }
45317
+ function snapshotTaskToolTodos(proc) {
45318
+ const todosById = proc.taskToolTodos ?? {};
45319
+ const order = proc.taskToolOrder ?? [];
45320
+ return order.map((id) => todosById[id]).filter((todo) => todo != null);
45321
+ }
45322
+ function emitTaskToolTodosUpdate(proc, emit, base, toolName) {
45323
+ const todos = snapshotTaskToolTodos(proc);
45324
+ logger7.info("Task tool detected, emitting agent:todos_update", {
45325
+ agentId: proc.agentId,
45326
+ replyMessageId: base.replyMessageId,
45327
+ groupId: proc.currentTask?.groupId,
45328
+ toolName,
45329
+ todoCount: todos.length,
45330
+ statusBreakdown: countByStatus(todos),
45331
+ traceId: base.traceId
45332
+ });
45333
+ emit({
45334
+ type: "agent:todos_update",
45335
+ payload: {
45336
+ ...wireBase(base),
45337
+ groupId: proc.currentTask?.groupId,
45338
+ todos
45339
+ }
45340
+ });
45341
+ }
45342
+ function applyTaskCreateInput(proc, input) {
45343
+ if (!isObjectRecord(input)) return false;
45344
+ const rawTaskId = String(proc.taskToolNextId ?? 1);
45345
+ proc.taskToolNextId = Number(rawTaskId) + 1;
45346
+ const content = readTaskToolContent(input) ?? `\u4EFB\u52A1 ${rawTaskId}`;
45347
+ const todoId = normalizeTaskToolTodoId(rawTaskId);
45348
+ proc.taskToolTodos = proc.taskToolTodos ?? {};
45349
+ proc.taskToolOrder = proc.taskToolOrder ?? [];
45350
+ if (!proc.taskToolOrder.includes(todoId)) {
45351
+ proc.taskToolOrder.push(todoId);
45352
+ }
45353
+ proc.taskToolTodos[todoId] = {
45354
+ id: todoId,
45355
+ content,
45356
+ status: "pending"
45357
+ };
45358
+ return true;
45359
+ }
45360
+ function applyTaskUpdateInput(proc, input) {
45361
+ if (!isObjectRecord(input)) return false;
45362
+ const taskIdValue = input.taskId;
45363
+ const rawTaskId = typeof taskIdValue === "string" || typeof taskIdValue === "number" ? String(taskIdValue) : null;
45364
+ if (!rawTaskId || rawTaskId.trim().length === 0) return false;
45365
+ const normalizedRawTaskId = rawTaskId.trim();
45366
+ const todoId = normalizeTaskToolTodoId(normalizedRawTaskId);
45367
+ proc.taskToolTodos = proc.taskToolTodos ?? {};
45368
+ proc.taskToolOrder = proc.taskToolOrder ?? [];
45369
+ const existing = proc.taskToolTodos[todoId];
45370
+ const content = existing?.content ?? readTaskToolContent(input);
45371
+ if (!content) return false;
45372
+ if (!proc.taskToolOrder.includes(todoId)) {
45373
+ proc.taskToolOrder.push(todoId);
45374
+ }
45375
+ const status = normalizeTaskToolStatus(input.status);
45376
+ proc.taskToolTodos[todoId] = {
45377
+ id: todoId,
45378
+ content,
45379
+ status
45380
+ };
45381
+ return true;
45382
+ }
45383
+ function normalizeTaskToolTodoId(rawTaskId) {
45384
+ const trimmed = rawTaskId.trim();
45385
+ return trimmed.startsWith("task_") ? trimmed : `task_${trimmed}`;
45386
+ }
45387
+ function readTaskToolContent(input) {
45388
+ const subject = readTrimmedString(input, "subject");
45389
+ const activeForm = readTrimmedString(input, "activeForm");
45390
+ const description = readTrimmedString(input, "description");
45391
+ return subject ?? activeForm ?? firstDescriptionLine(description);
45392
+ }
45282
45393
  function countByStatus(todos) {
45283
45394
  const c2 = {
45284
45395
  pending: 0,
@@ -45572,6 +45683,28 @@ function mapSDKMessage(proc, message, rawEmit, sessionStore, onCompleted) {
45572
45683
  });
45573
45684
  }
45574
45685
  }
45686
+ if (proc.currentToolName === "TaskCreate") {
45687
+ if (applyTaskCreateInput(proc, parsedInput)) {
45688
+ emitTaskToolTodosUpdate(proc, emit, base, "TaskCreate");
45689
+ } else {
45690
+ logger7.warn("TaskCreate detected but input was not usable", {
45691
+ agentId: proc.agentId,
45692
+ replyMessageId: base.replyMessageId,
45693
+ traceId: base.traceId
45694
+ });
45695
+ }
45696
+ }
45697
+ if (proc.currentToolName === "TaskUpdate") {
45698
+ if (applyTaskUpdateInput(proc, parsedInput)) {
45699
+ emitTaskToolTodosUpdate(proc, emit, base, "TaskUpdate");
45700
+ } else {
45701
+ logger7.warn("TaskUpdate detected but input was not usable", {
45702
+ agentId: proc.agentId,
45703
+ replyMessageId: base.replyMessageId,
45704
+ traceId: base.traceId
45705
+ });
45706
+ }
45707
+ }
45575
45708
  if (proc.currentToolName === "AskUserQuestion") {
45576
45709
  const last = proc.contentBlocks[proc.contentBlocks.length - 1];
45577
45710
  if (last?.type === "tool_use" && last.toolName === "AskUserQuestion") {
@@ -46243,14 +46376,57 @@ var AgentManager = class {
46243
46376
  this.queryFn = QA$;
46244
46377
  return this.queryFn;
46245
46378
  }
46379
+ extractAhchatWorkspaceSuffix(requestedCwd) {
46380
+ const normalized = requestedCwd.trim().replace(/\\/g, "/");
46381
+ const marker = "/.ahchat/users/";
46382
+ const markerIndex = normalized.indexOf(marker);
46383
+ if (markerIndex >= 0) {
46384
+ const afterUsers = normalized.slice(markerIndex + marker.length);
46385
+ const workspaceMarker = "/workspaces/";
46386
+ const workspaceIndex = afterUsers.indexOf(workspaceMarker);
46387
+ if (workspaceIndex >= 0) {
46388
+ const suffix = afterUsers.slice(workspaceIndex + workspaceMarker.length);
46389
+ const parts = suffix.split("/").filter((part) => part && part !== "." && part !== "..");
46390
+ return parts.length > 0 ? parts.join(path8.sep) : null;
46391
+ }
46392
+ }
46393
+ const legacyMarker = "/.ahchat/";
46394
+ const legacyIndex = normalized.indexOf(legacyMarker);
46395
+ if (legacyIndex >= 0) {
46396
+ const firstSegment = normalized.slice(legacyIndex + legacyMarker.length).split("/").find(Boolean);
46397
+ if (firstSegment && /^(Agent|Group)-/.test(firstSegment)) {
46398
+ return firstSegment;
46399
+ }
46400
+ }
46401
+ return null;
46402
+ }
46246
46403
  fallbackCwd(agentConfig, scope, requestedCwd) {
46247
46404
  const normalized = requestedCwd.trim();
46405
+ const ahchatSuffix = this.extractAhchatWorkspaceSuffix(normalized);
46406
+ if (ahchatSuffix) {
46407
+ return path8.join(this.workspacesDir, ahchatSuffix);
46408
+ }
46248
46409
  const basename = normalized ? path8.basename(path8.normalize(normalized)) : "";
46249
46410
  const suffix = basename && basename !== "." && basename !== path8.sep ? basename : scope.kind === "group" ? `Group-${scope.groupId}` : agentConfig.id;
46250
46411
  return path8.join(this.workspacesDir, suffix);
46251
46412
  }
46413
+ remapServerWorkspaceCwd(agentConfig, scope, requestedCwd) {
46414
+ const remapped = this.fallbackCwd(agentConfig, scope, requestedCwd);
46415
+ const normalizedRequested = path8.normalize(requestedCwd);
46416
+ const normalizedRemapped = path8.normalize(remapped);
46417
+ if (this.extractAhchatWorkspaceSuffix(requestedCwd) && normalizedRequested !== normalizedRemapped) {
46418
+ logger10.info("Server working directory remapped to local Bridge workspace", {
46419
+ agentId: agentConfig.id,
46420
+ scope: scopeKey(scope),
46421
+ requested: requestedCwd,
46422
+ remapped
46423
+ });
46424
+ return remapped;
46425
+ }
46426
+ return requestedCwd;
46427
+ }
46252
46428
  async resolveRuntimeCwd(agentConfig, scope, requestedCwd) {
46253
- let cwd = requestedCwd;
46429
+ let cwd = this.remapServerWorkspaceCwd(agentConfig, scope, requestedCwd);
46254
46430
  if (isRunningAsRoot() && cwd.startsWith("/root/")) {
46255
46431
  cwd = this.fallbackCwd(agentConfig, scope, cwd);
46256
46432
  }
@@ -50383,6 +50559,13 @@ import { execFileSync, execSync, spawnSync } from "child_process";
50383
50559
  import { accessSync, constants as constants2 } from "fs";
50384
50560
  import { join as join2 } from "path";
50385
50561
  var logger24 = createModuleLogger("bridge.ensureCli");
50562
+ var DEFAULT_INSTALL_TIMEOUT_MS = 6e5;
50563
+ function getInstallTimeoutMs() {
50564
+ const raw = process.env.AHCHAT_CLAUDE_CLI_INSTALL_TIMEOUT_MS;
50565
+ if (!raw) return DEFAULT_INSTALL_TIMEOUT_MS;
50566
+ const parsed = Number.parseInt(raw, 10);
50567
+ return Number.isFinite(parsed) && parsed > 0 ? parsed : DEFAULT_INSTALL_TIMEOUT_MS;
50568
+ }
50386
50569
  function detectClaudeCli() {
50387
50570
  try {
50388
50571
  return execFileSync("claude", ["--version"], { timeout: 1e4 }).toString().trim();
@@ -50411,9 +50594,18 @@ function resolveClaudeBinary() {
50411
50594
  if (first) return first;
50412
50595
  } catch {
50413
50596
  }
50597
+ return resolveViaNpmBin();
50598
+ }
50599
+ function getNpmClaudeCandidates(bin) {
50600
+ if (process.platform === "win32") {
50601
+ return ["claude.cmd", "claude.exe", "claude", "anthropic-cli.cmd", "anthropic-cli.exe", "anthropic-cli"].map((name) => join2(bin, name));
50602
+ }
50603
+ return [join2(bin, "claude"), join2(bin, "anthropic-cli")];
50604
+ }
50605
+ function resolveViaNpmBin() {
50414
50606
  const bin = getNpmGlobalBin();
50415
- if (bin) {
50416
- const candidate = join2(bin, process.platform === "win32" ? "claude.cmd" : "claude");
50607
+ if (!bin) return void 0;
50608
+ for (const candidate of getNpmClaudeCandidates(bin)) {
50417
50609
  try {
50418
50610
  accessSync(candidate, constants2.X_OK);
50419
50611
  return candidate;
@@ -50423,9 +50615,30 @@ function resolveClaudeBinary() {
50423
50615
  return void 0;
50424
50616
  }
50425
50617
  function detectViaNpmBin() {
50426
- const bin = getNpmGlobalBin();
50427
- if (!bin) return void 0;
50428
- const candidates = [join2(bin, "claude"), join2(bin, "anthropic-cli")];
50618
+ const binPath = resolveViaNpmBin();
50619
+ if (!binPath) return void 0;
50620
+ try {
50621
+ return execFileSync(binPath, ["--version"], { timeout: 1e4 }).toString().trim();
50622
+ } catch {
50623
+ }
50624
+ return void 0;
50625
+ }
50626
+ function detectResolvedClaudeCli() {
50627
+ const viaPath = detectClaudeCli();
50628
+ if (viaPath) {
50629
+ return { version: viaPath, path: resolveClaudeBinary() };
50630
+ }
50631
+ const npmBinPath = resolveViaNpmBin();
50632
+ if (!npmBinPath) return void 0;
50633
+ try {
50634
+ const version2 = execFileSync(npmBinPath, ["--version"], { timeout: 1e4 }).toString().trim();
50635
+ return { version: version2, path: npmBinPath };
50636
+ } catch {
50637
+ }
50638
+ return void 0;
50639
+ }
50640
+ function detectVersionFromResolvedCandidates() {
50641
+ const candidates = [resolveClaudeBinary(), resolveViaNpmBin()].filter((p) => Boolean(p));
50429
50642
  for (const p of candidates) {
50430
50643
  try {
50431
50644
  accessSync(p, constants2.X_OK);
@@ -50439,7 +50652,7 @@ function installClaudeCli() {
50439
50652
  logger24.info("Installing Claude Code CLI via npm...");
50440
50653
  const result = spawnSync("npm", ["install", "-g", "@anthropic-ai/claude-code"], {
50441
50654
  stdio: "inherit",
50442
- timeout: 12e4
50655
+ timeout: getInstallTimeoutMs()
50443
50656
  });
50444
50657
  if (result.error) {
50445
50658
  logger24.error("npm install -g failed (spawn error)", {
@@ -50454,9 +50667,9 @@ function installClaudeCli() {
50454
50667
  return void 0;
50455
50668
  }
50456
50669
  logger24.info("npm install -g completed, checking for claude binary...");
50457
- const viaPath = detectClaudeCli();
50670
+ const viaPath = detectVersionFromResolvedCandidates();
50458
50671
  if (viaPath) {
50459
- logger24.info("claude detected via PATH after install", { version: viaPath });
50672
+ logger24.info("claude detected after install", { version: viaPath });
50460
50673
  return viaPath;
50461
50674
  }
50462
50675
  const viaBin = detectViaNpmBin();
@@ -50474,14 +50687,13 @@ function installClaudeCli() {
50474
50687
  return void 0;
50475
50688
  }
50476
50689
  async function ensureClaudeCli() {
50477
- let version2 = detectClaudeCli();
50478
- if (version2) {
50479
- const binPath2 = resolveClaudeBinary();
50480
- logger24.info("Claude Code CLI ready", { version: version2, path: binPath2 ?? null });
50481
- return binPath2;
50690
+ let detected = detectResolvedClaudeCli();
50691
+ if (detected) {
50692
+ logger24.info("Claude Code CLI ready", { version: detected.version, path: detected.path ?? null });
50693
+ return detected.path;
50482
50694
  }
50483
50695
  process.stderr.write("\n\u26A0 Claude Code CLI (`claude`) not found. Attempting auto-install...\n\n");
50484
- version2 = installClaudeCli();
50696
+ const version2 = installClaudeCli();
50485
50697
  if (!version2) {
50486
50698
  const npmBin = getNpmGlobalBin();
50487
50699
  process.stderr.write(
@@ -50492,9 +50704,9 @@ async function ensureClaudeCli() {
50492
50704
  );
50493
50705
  process.exit(1);
50494
50706
  }
50495
- const binPath = resolveClaudeBinary();
50496
- logger24.info("Claude Code CLI ready", { version: version2, path: binPath ?? null });
50497
- return binPath;
50707
+ detected = detectResolvedClaudeCli();
50708
+ logger24.info("Claude Code CLI ready", { version: version2, path: detected?.path ?? null });
50709
+ return detected?.path;
50498
50710
  }
50499
50711
 
50500
50712
  // src/forkAgentFiles.ts
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fangyb/ahchat-bridge",
3
- "version": "0.1.19",
3
+ "version": "0.1.20",
4
4
  "files": [
5
5
  "dist"
6
6
  ],
@@ -9,12 +9,6 @@
9
9
  "bin": {
10
10
  "ahchat-bridge": "dist/cli.cjs"
11
11
  },
12
- "scripts": {
13
- "dev": "tsx src/index.ts",
14
- "start": "tsx src/index.ts",
15
- "build": "tsup",
16
- "typecheck": "tsc -p tsconfig.json --noEmit"
17
- },
18
12
  "dependencies": {
19
13
  "@anthropic-ai/claude-agent-sdk": "^0.2",
20
14
  "cac": "^6.7.14",
@@ -22,13 +16,19 @@
22
16
  "zod": "^4.0.0"
23
17
  },
24
18
  "devDependencies": {
25
- "@ahchat/logger": "workspace:*",
26
- "@ahchat/shared": "workspace:*",
27
19
  "@types/node": "^22.15.21",
28
20
  "@types/ws": "^8.5.14",
29
21
  "tsup": "^8.0.0",
30
22
  "tsx": "^4.19.4",
31
23
  "typescript": "^5.8.3",
32
- "vitest": "^3.1.4"
24
+ "vitest": "^3.1.4",
25
+ "@ahchat/shared": "0.1.0",
26
+ "@ahchat/logger": "0.1.0"
27
+ },
28
+ "scripts": {
29
+ "dev": "tsx src/index.ts",
30
+ "start": "tsx src/index.ts",
31
+ "build": "tsup",
32
+ "typecheck": "tsc -p tsconfig.json --noEmit"
33
33
  }
34
- }
34
+ }