@fangyb/ahchat-bridge 0.1.19 → 0.1.21

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.
Files changed (3) hide show
  1. package/dist/cli.cjs +441 -179
  2. package/dist/index.js +386 -145
  3. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -4460,11 +4460,11 @@ var RotatingFileStream = class extends Writable {
4460
4460
  timeout;
4461
4461
  timeoutPromise;
4462
4462
  constructor(generator, options) {
4463
- const { encoding, history, maxFiles, maxSize, path: path20 } = options;
4463
+ const { encoding, history, maxFiles, maxSize, path: path21 } = options;
4464
4464
  super({ decodeStrings: true, defaultEncoding: encoding });
4465
4465
  this.createGzip = createGzip;
4466
4466
  this.exec = exec;
4467
- this.filename = path20 + generator(null);
4467
+ this.filename = path21 + generator(null);
4468
4468
  this.fsCreateReadStream = createReadStream;
4469
4469
  this.fsCreateWriteStream = createWriteStream;
4470
4470
  this.fsOpen = open;
@@ -4476,7 +4476,7 @@ var RotatingFileStream = class extends Writable {
4476
4476
  this.options = options;
4477
4477
  this.stdout = process.stdout;
4478
4478
  if (maxFiles || maxSize)
4479
- options.history = path20 + (history ? history : this.generator(null) + ".txt");
4479
+ options.history = path21 + (history ? history : this.generator(null) + ".txt");
4480
4480
  this.on("close", () => this.finished ? null : this.emit("finish"));
4481
4481
  this.on("finish", () => this.finished = this.clear());
4482
4482
  (async () => {
@@ -4604,9 +4604,9 @@ var RotatingFileStream = class extends Writable {
4604
4604
  return this.move();
4605
4605
  }
4606
4606
  async findName() {
4607
- const { interval, path: path20, intervalBoundary } = this.options;
4607
+ const { interval, path: path21, intervalBoundary } = this.options;
4608
4608
  for (let index = 1; index < 1e3; ++index) {
4609
- const filename = path20 + this.generator(interval && intervalBoundary ? new Date(this.prev) : this.rotation, index);
4609
+ const filename = path21 + this.generator(interval && intervalBoundary ? new Date(this.prev) : this.rotation, index);
4610
4610
  if (!await exists(filename))
4611
4611
  return filename;
4612
4612
  }
@@ -4636,11 +4636,11 @@ var RotatingFileStream = class extends Writable {
4636
4636
  return this.unlink(filename);
4637
4637
  }
4638
4638
  async classical() {
4639
- const { compress, path: path20, rotate } = this.options;
4639
+ const { compress, path: path21, rotate } = this.options;
4640
4640
  let rotatedName = "";
4641
4641
  for (let count = rotate; count > 0; --count) {
4642
- const currName = path20 + this.generator(count);
4643
- const prevName = count === 1 ? this.filename : path20 + this.generator(count - 1);
4642
+ const currName = path21 + this.generator(count);
4643
+ const prevName = count === 1 ? this.filename : path21 + this.generator(count - 1);
4644
4644
  if (!await exists(prevName))
4645
4645
  continue;
4646
4646
  if (!rotatedName)
@@ -5077,7 +5077,7 @@ function createModuleLogger(module) {
5077
5077
  }
5078
5078
 
5079
5079
  // src/start.ts
5080
- import path19 from "path";
5080
+ import path20 from "path";
5081
5081
 
5082
5082
  // ../shared/src/smithContent.ts
5083
5083
  var SMITH_SYSTEM_PROMPT = `\u4F60\u662F\u7279\u5DE5\u53F2\u5BC6\u65AF\uFF08Agent Smith\uFF09\uFF0CAHChat \u7CFB\u7EDF\u7684\u7EC4\u7EC7\u5DE5\u5177\u3002
@@ -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
@@ -6234,7 +6240,7 @@ import { createHash } from "crypto";
6234
6240
  import fsSync from "fs";
6235
6241
  import fs4 from "fs/promises";
6236
6242
  import os5 from "os";
6237
- import path8 from "path";
6243
+ import path9 from "path";
6238
6244
 
6239
6245
  // ../../node_modules/.pnpm/@anthropic-ai+claude-agent-sdk@0.2.141_zod@4.4.3/node_modules/@anthropic-ai/claude-agent-sdk/sdk.mjs
6240
6246
  import { createRequire as $S } from "module";
@@ -29031,10 +29037,10 @@ function mergeDefs(...defs) {
29031
29037
  function cloneDef(schema) {
29032
29038
  return mergeDefs(schema._zod.def);
29033
29039
  }
29034
- function getElementAtPath(obj, path20) {
29035
- if (!path20)
29040
+ function getElementAtPath(obj, path21) {
29041
+ if (!path21)
29036
29042
  return obj;
29037
- return path20.reduce((acc, key) => acc?.[key], obj);
29043
+ return path21.reduce((acc, key) => acc?.[key], obj);
29038
29044
  }
29039
29045
  function promiseAllObject(promisesObj) {
29040
29046
  const keys = Object.keys(promisesObj);
@@ -29443,11 +29449,11 @@ function explicitlyAborted(x2, startIndex = 0) {
29443
29449
  }
29444
29450
  return false;
29445
29451
  }
29446
- function prefixIssues(path20, issues) {
29452
+ function prefixIssues(path21, issues) {
29447
29453
  return issues.map((iss) => {
29448
29454
  var _a3;
29449
29455
  (_a3 = iss).path ?? (_a3.path = []);
29450
- iss.path.unshift(path20);
29456
+ iss.path.unshift(path21);
29451
29457
  return iss;
29452
29458
  });
29453
29459
  }
@@ -29594,16 +29600,16 @@ function flattenError(error51, mapper = (issue2) => issue2.message) {
29594
29600
  }
29595
29601
  function formatError(error51, mapper = (issue2) => issue2.message) {
29596
29602
  const fieldErrors = { _errors: [] };
29597
- const processError = (error52, path20 = []) => {
29603
+ const processError = (error52, path21 = []) => {
29598
29604
  for (const issue2 of error52.issues) {
29599
29605
  if (issue2.code === "invalid_union" && issue2.errors.length) {
29600
- issue2.errors.map((issues) => processError({ issues }, [...path20, ...issue2.path]));
29606
+ issue2.errors.map((issues) => processError({ issues }, [...path21, ...issue2.path]));
29601
29607
  } else if (issue2.code === "invalid_key") {
29602
- processError({ issues: issue2.issues }, [...path20, ...issue2.path]);
29608
+ processError({ issues: issue2.issues }, [...path21, ...issue2.path]);
29603
29609
  } else if (issue2.code === "invalid_element") {
29604
- processError({ issues: issue2.issues }, [...path20, ...issue2.path]);
29610
+ processError({ issues: issue2.issues }, [...path21, ...issue2.path]);
29605
29611
  } else {
29606
- const fullpath = [...path20, ...issue2.path];
29612
+ const fullpath = [...path21, ...issue2.path];
29607
29613
  if (fullpath.length === 0) {
29608
29614
  fieldErrors._errors.push(mapper(issue2));
29609
29615
  } else {
@@ -29630,17 +29636,17 @@ function formatError(error51, mapper = (issue2) => issue2.message) {
29630
29636
  }
29631
29637
  function treeifyError(error51, mapper = (issue2) => issue2.message) {
29632
29638
  const result = { errors: [] };
29633
- const processError = (error52, path20 = []) => {
29639
+ const processError = (error52, path21 = []) => {
29634
29640
  var _a3, _b2;
29635
29641
  for (const issue2 of error52.issues) {
29636
29642
  if (issue2.code === "invalid_union" && issue2.errors.length) {
29637
- issue2.errors.map((issues) => processError({ issues }, [...path20, ...issue2.path]));
29643
+ issue2.errors.map((issues) => processError({ issues }, [...path21, ...issue2.path]));
29638
29644
  } else if (issue2.code === "invalid_key") {
29639
- processError({ issues: issue2.issues }, [...path20, ...issue2.path]);
29645
+ processError({ issues: issue2.issues }, [...path21, ...issue2.path]);
29640
29646
  } else if (issue2.code === "invalid_element") {
29641
- processError({ issues: issue2.issues }, [...path20, ...issue2.path]);
29647
+ processError({ issues: issue2.issues }, [...path21, ...issue2.path]);
29642
29648
  } else {
29643
- const fullpath = [...path20, ...issue2.path];
29649
+ const fullpath = [...path21, ...issue2.path];
29644
29650
  if (fullpath.length === 0) {
29645
29651
  result.errors.push(mapper(issue2));
29646
29652
  continue;
@@ -29672,8 +29678,8 @@ function treeifyError(error51, mapper = (issue2) => issue2.message) {
29672
29678
  }
29673
29679
  function toDotPath(_path) {
29674
29680
  const segs = [];
29675
- const path20 = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
29676
- for (const seg of path20) {
29681
+ const path21 = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
29682
+ for (const seg of path21) {
29677
29683
  if (typeof seg === "number")
29678
29684
  segs.push(`[${seg}]`);
29679
29685
  else if (typeof seg === "symbol")
@@ -42365,13 +42371,13 @@ function resolveRef(ref, ctx) {
42365
42371
  if (!ref.startsWith("#")) {
42366
42372
  throw new Error("External $ref is not supported, only local refs (#/...) are allowed");
42367
42373
  }
42368
- const path20 = ref.slice(1).split("/").filter(Boolean);
42369
- if (path20.length === 0) {
42374
+ const path21 = ref.slice(1).split("/").filter(Boolean);
42375
+ if (path21.length === 0) {
42370
42376
  return ctx.rootSchema;
42371
42377
  }
42372
42378
  const defsKey = ctx.version === "draft-2020-12" ? "$defs" : "definitions";
42373
- if (path20[0] === defsKey) {
42374
- const key = path20[1];
42379
+ if (path21[0] === defsKey) {
42380
+ const key = path21[1];
42375
42381
  if (!key || !ctx.defs[key]) {
42376
42382
  throw new Error(`Reference not found: ${ref}`);
42377
42383
  }
@@ -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") {
@@ -46044,6 +46177,52 @@ function buildForkHistorySection(messages) {
46044
46177
  return lines.join("\n");
46045
46178
  }
46046
46179
 
46180
+ // src/workdirMapper.ts
46181
+ import path8 from "path";
46182
+ function extractAhchatWorkspaceParts(requestedPath) {
46183
+ const normalized = requestedPath.trim().replace(/\\/g, "/");
46184
+ const marker = "/.ahchat/users/";
46185
+ const markerIndex = normalized.indexOf(marker);
46186
+ if (markerIndex >= 0) {
46187
+ const afterUsers = normalized.slice(markerIndex + marker.length);
46188
+ const workspaceMarker = "/workspaces/";
46189
+ const workspaceIndex = afterUsers.indexOf(workspaceMarker);
46190
+ if (workspaceIndex >= 0) {
46191
+ const suffix = afterUsers.slice(workspaceIndex + workspaceMarker.length);
46192
+ const parts = suffix.split("/").filter((part) => part && part !== "." && part !== "..");
46193
+ return parts;
46194
+ }
46195
+ const workspacesRootMarker = "/workspaces";
46196
+ const rootIndex = afterUsers.indexOf(workspacesRootMarker);
46197
+ if (rootIndex >= 0 && afterUsers.slice(rootIndex + workspacesRootMarker.length).length === 0) {
46198
+ return [];
46199
+ }
46200
+ }
46201
+ const legacyMarker = "/.ahchat/";
46202
+ const legacyIndex = normalized.indexOf(legacyMarker);
46203
+ if (legacyIndex >= 0) {
46204
+ const firstSegment = normalized.slice(legacyIndex + legacyMarker.length).split("/").find(Boolean);
46205
+ if (firstSegment && /^(Agent|Group)-/.test(firstSegment)) {
46206
+ return [firstSegment];
46207
+ }
46208
+ }
46209
+ return null;
46210
+ }
46211
+ function extractAhchatWorkspaceSuffix(requestedPath) {
46212
+ const parts = extractAhchatWorkspaceParts(requestedPath);
46213
+ if (!parts || parts.length === 0) return null;
46214
+ return path8.join(...parts);
46215
+ }
46216
+ function remapServerWorkspacePath(requestedPath, workspacesDir) {
46217
+ const parts = extractAhchatWorkspaceParts(requestedPath);
46218
+ if (!parts) return { path: requestedPath, remapped: false };
46219
+ const remappedPath = parts.length > 0 ? path8.join(workspacesDir, ...parts) : workspacesDir;
46220
+ return {
46221
+ path: remappedPath,
46222
+ remapped: path8.normalize(requestedPath) !== path8.normalize(remappedPath)
46223
+ };
46224
+ }
46225
+
46047
46226
  // src/wsMetrics.ts
46048
46227
  import { monitorEventLoopDelay } from "perf_hooks";
46049
46228
  var logger9 = createModuleLogger("ws.metrics");
@@ -46137,7 +46316,7 @@ async function chownForRootSpawn(targetPath, target) {
46137
46316
  }
46138
46317
  function readCronLockSnapshot() {
46139
46318
  try {
46140
- const lockPath2 = path8.join(os5.homedir(), ".claude", "scheduled_tasks.lock");
46319
+ const lockPath2 = path9.join(os5.homedir(), ".claude", "scheduled_tasks.lock");
46141
46320
  if (!fsSync.existsSync(lockPath2)) {
46142
46321
  return { exists: false, sessionId: null, pid: null };
46143
46322
  }
@@ -46205,8 +46384,8 @@ var AgentManager = class {
46205
46384
  this.emit = emit;
46206
46385
  if (typeof options === "function") {
46207
46386
  this.queryFn = options;
46208
- this.workspacesDir = path8.join(os5.homedir(), ".ahchat", "workspaces");
46209
- this.agentConfigDir = path8.join(os5.homedir(), ".ahchat", "agent-config");
46387
+ this.workspacesDir = path9.join(os5.homedir(), ".ahchat", "workspaces");
46388
+ this.agentConfigDir = path9.join(os5.homedir(), ".ahchat", "agent-config");
46210
46389
  this.queryConfig = DEFAULT_QUERY_CONFIG;
46211
46390
  this.askQuestionRegistry = new AskQuestionRegistry();
46212
46391
  this.groupRegistry = null;
@@ -46217,11 +46396,11 @@ var AgentManager = class {
46217
46396
  this.serverApiUrl = null;
46218
46397
  this.bridgeToken = null;
46219
46398
  this.defaultModel = null;
46220
- this.dataDir = path8.join(os5.homedir(), ".ahchat");
46399
+ this.dataDir = path9.join(os5.homedir(), ".ahchat");
46221
46400
  } else {
46222
46401
  this.queryFn = options?.queryFn ?? null;
46223
- this.workspacesDir = options?.workspacesDir ?? path8.join(os5.homedir(), ".ahchat", "workspaces");
46224
- this.agentConfigDir = options?.agentConfigDir ?? path8.join(os5.homedir(), ".ahchat", "agent-config");
46402
+ this.workspacesDir = options?.workspacesDir ?? path9.join(os5.homedir(), ".ahchat", "workspaces");
46403
+ this.agentConfigDir = options?.agentConfigDir ?? path9.join(os5.homedir(), ".ahchat", "agent-config");
46225
46404
  this.queryConfig = options?.queryConfig ?? DEFAULT_QUERY_CONFIG;
46226
46405
  this.askQuestionRegistry = options?.askQuestionRegistry ?? new AskQuestionRegistry();
46227
46406
  this.groupRegistry = options?.groupRegistry ?? null;
@@ -46232,7 +46411,7 @@ var AgentManager = class {
46232
46411
  this.serverApiUrl = options?.serverApiUrl ?? null;
46233
46412
  this.bridgeToken = options?.bridgeToken ?? null;
46234
46413
  this.defaultModel = options?.defaultModel ?? null;
46235
- this.dataDir = options?.dataDir ?? path8.join(os5.homedir(), ".ahchat");
46414
+ this.dataDir = options?.dataDir ?? path9.join(os5.homedir(), ".ahchat");
46236
46415
  }
46237
46416
  this.evictionTimer = setInterval(() => {
46238
46417
  void this.evictIdle();
@@ -46245,12 +46424,29 @@ var AgentManager = class {
46245
46424
  }
46246
46425
  fallbackCwd(agentConfig, scope, requestedCwd) {
46247
46426
  const normalized = requestedCwd.trim();
46248
- const basename = normalized ? path8.basename(path8.normalize(normalized)) : "";
46249
- const suffix = basename && basename !== "." && basename !== path8.sep ? basename : scope.kind === "group" ? `Group-${scope.groupId}` : agentConfig.id;
46250
- return path8.join(this.workspacesDir, suffix);
46427
+ const ahchatSuffix = extractAhchatWorkspaceSuffix(normalized);
46428
+ if (ahchatSuffix) {
46429
+ return path9.join(this.workspacesDir, ahchatSuffix);
46430
+ }
46431
+ const basename = normalized ? path9.basename(path9.normalize(normalized)) : "";
46432
+ const suffix = basename && basename !== "." && basename !== path9.sep ? basename : scope.kind === "group" ? `Group-${scope.groupId}` : agentConfig.id;
46433
+ return path9.join(this.workspacesDir, suffix);
46434
+ }
46435
+ remapServerWorkspaceCwd(agentConfig, scope, requestedCwd) {
46436
+ const remapped = remapServerWorkspacePath(requestedCwd, this.workspacesDir);
46437
+ if (remapped.remapped) {
46438
+ logger10.info("Server working directory remapped to local Bridge workspace", {
46439
+ agentId: agentConfig.id,
46440
+ scope: scopeKey(scope),
46441
+ requested: requestedCwd,
46442
+ remapped: remapped.path
46443
+ });
46444
+ return remapped.path;
46445
+ }
46446
+ return requestedCwd;
46251
46447
  }
46252
46448
  async resolveRuntimeCwd(agentConfig, scope, requestedCwd) {
46253
- let cwd = requestedCwd;
46449
+ let cwd = this.remapServerWorkspaceCwd(agentConfig, scope, requestedCwd);
46254
46450
  if (isRunningAsRoot() && cwd.startsWith("/root/")) {
46255
46451
  cwd = this.fallbackCwd(agentConfig, scope, cwd);
46256
46452
  }
@@ -46486,12 +46682,12 @@ var AgentManager = class {
46486
46682
  const agentCwd = await this.resolveRuntimeCwd(agentConfig, scope, cwd);
46487
46683
  const cfg = await this.resolveAgentConfig(agentConfig);
46488
46684
  if (cfg.instructions?.trim()) {
46489
- await fs4.writeFile(path8.join(agentCwd, "CLAUDE.md"), cfg.instructions.trim(), "utf-8");
46685
+ await fs4.writeFile(path9.join(agentCwd, "CLAUDE.md"), cfg.instructions.trim(), "utf-8");
46490
46686
  logger10.info("CLAUDE.md written", { agentId: agentConfig.id, bytes: cfg.instructions.trim().length });
46491
46687
  }
46492
46688
  let effectiveConfigDir = this.agentConfigDir;
46493
46689
  if (cfg.subscriptionType !== "system" && cfg.apiKey) {
46494
- effectiveConfigDir = path8.join(this.agentConfigDir, "api-key-agents", agentConfig.id);
46690
+ effectiveConfigDir = path9.join(this.agentConfigDir, "api-key-agents", agentConfig.id);
46495
46691
  let isNew = false;
46496
46692
  try {
46497
46693
  await fs4.access(effectiveConfigDir);
@@ -46504,7 +46700,7 @@ var AgentManager = class {
46504
46700
  this.dispatchMemory.deleteScope(agentConfig.id, scope);
46505
46701
  logger10.info("New API-key agent config dir; cleared stale session", { agentId: agentConfig.id });
46506
46702
  }
46507
- const settingsPath = path8.join(effectiveConfigDir, "settings.json");
46703
+ const settingsPath = path9.join(effectiveConfigDir, "settings.json");
46508
46704
  const envEntries = {};
46509
46705
  if (cfg.apiKey) envEntries.ANTHROPIC_API_KEY = cfg.apiKey;
46510
46706
  if (cfg.apiBaseUrl) envEntries.ANTHROPIC_BASE_URL = cfg.apiBaseUrl;
@@ -46811,7 +47007,7 @@ Do NOT use "..." as content \u2014 write specific, project-relevant content.`;
46811
47007
  settings: (() => {
46812
47008
  const isolated = cfg.subscriptionType === "project" && Boolean(cfg.apiKey ?? cfg.apiBaseUrl);
46813
47009
  if (!isolated) return void 0;
46814
- return path8.join(effectiveConfigDir, "settings.json");
47010
+ return path9.join(effectiveConfigDir, "settings.json");
46815
47011
  })(),
46816
47012
  canUseTool: async (toolName, input) => {
46817
47013
  if (toolName === "AskUserQuestion") {
@@ -46885,7 +47081,7 @@ Do NOT use "..." as content \u2014 write specific, project-relevant content.`;
46885
47081
  if (isRunningAsRoot()) {
46886
47082
  await chownForRootSpawn(effectiveConfigDir, "configDir");
46887
47083
  await chownForRootSpawn(agentCwd, "agentCwd");
46888
- const settingsFilePath = path8.join(effectiveConfigDir, "settings.json");
47084
+ const settingsFilePath = path9.join(effectiveConfigDir, "settings.json");
46889
47085
  await chownForRootSpawn(settingsFilePath, "settingsFile");
46890
47086
  options.spawnClaudeCodeProcess = (spawnOptions) => {
46891
47087
  const env2 = { ...spawnOptions.env, HOME: "/home/node" };
@@ -47052,7 +47248,7 @@ ${trimmed}`;
47052
47248
  lines.push(` workdir: ${currentCwd}`);
47053
47249
  } else {
47054
47250
  const a = this.agentRegistry?.getById(agentId);
47055
- const singleCwd = a?.workingDirectory || path8.join(this.workspacesDir, agentId);
47251
+ const singleCwd = a?.workingDirectory || path9.join(this.workspacesDir, agentId);
47056
47252
  lines.push(` workdir: ${singleCwd}`);
47057
47253
  }
47058
47254
  let rosterCount = 0;
@@ -47064,7 +47260,7 @@ ${trimmed}`;
47064
47260
  if (key === curKey) {
47065
47261
  lines.push(` workdir: ${currentCwd}`);
47066
47262
  } else {
47067
- const groupCwd = g2.workingDirectory || path8.join(this.workspacesDir, g2.groupId);
47263
+ const groupCwd = g2.workingDirectory || path9.join(this.workspacesDir, g2.groupId);
47068
47264
  lines.push(` workdir: ${groupCwd}`);
47069
47265
  }
47070
47266
  const others = g2.members.filter((id) => id !== agentId).map((id) => {
@@ -47515,14 +47711,14 @@ ${lines.join("\n")}`;
47515
47711
  }
47516
47712
  async materializeAttachment(runtime, attachment, buffer) {
47517
47713
  const safeFileName = this.safeAttachmentFileName(attachment.fileName);
47518
- const dir = path8.join(runtime.cwd, ".ahchat-attachments", attachment.id);
47714
+ const dir = path9.join(runtime.cwd, ".ahchat-attachments", attachment.id);
47519
47715
  await fs4.mkdir(dir, { recursive: true });
47520
- const filePath = path8.join(dir, safeFileName);
47716
+ const filePath = path9.join(dir, safeFileName);
47521
47717
  await fs4.writeFile(filePath, buffer);
47522
47718
  return filePath;
47523
47719
  }
47524
47720
  safeAttachmentFileName(fileName) {
47525
- const baseName = path8.basename(fileName).replace(/[\0/:\\]/g, "_").trim();
47721
+ const baseName = path9.basename(fileName).replace(/[\0/:\\]/g, "_").trim();
47526
47722
  return baseName || "attachment";
47527
47723
  }
47528
47724
  /**
@@ -47537,7 +47733,7 @@ ${lines.join("\n")}`;
47537
47733
  async detectVisionSupport() {
47538
47734
  if (process.env.ANTHROPIC_BASE_URL) return false;
47539
47735
  try {
47540
- const settingsPath = path8.join(os5.homedir(), ".claude", "settings.json");
47736
+ const settingsPath = path9.join(os5.homedir(), ".claude", "settings.json");
47541
47737
  const raw = await fs4.readFile(settingsPath, "utf-8");
47542
47738
  const parsed = JSON.parse(raw);
47543
47739
  if (parsed.env?.ANTHROPIC_BASE_URL) return false;
@@ -47903,7 +48099,7 @@ ${lines.join("\n")}`;
47903
48099
  }
47904
48100
  cwd = payload.targetCwd;
47905
48101
  } else {
47906
- cwd = agentConfig.workingDirectory || path8.join(this.workspacesDir, agentConfig.id);
48102
+ cwd = agentConfig.workingDirectory || path9.join(this.workspacesDir, agentConfig.id);
47907
48103
  }
47908
48104
  void this.acquire(agentConfig, targetScope, cwd).then(() => {
47909
48105
  logger10.info("Neural send new runtime acquired", {
@@ -48009,7 +48205,7 @@ ${lines.join("\n")}`;
48009
48205
  conversationId,
48010
48206
  traceId
48011
48207
  });
48012
- const cwd = newAgent.workingDirectory || path8.join(this.workspacesDir, newAgent.id);
48208
+ const cwd = newAgent.workingDirectory || path9.join(this.workspacesDir, newAgent.id);
48013
48209
  const scope = { kind: "single" };
48014
48210
  try {
48015
48211
  await this.acquire(newAgent, scope, cwd);
@@ -48291,12 +48487,12 @@ ${lines.join("\n")}`;
48291
48487
  break;
48292
48488
  }
48293
48489
  try {
48294
- let cwd = agent.workingDirectory || path8.join(this.workspacesDir, agent.id);
48490
+ let cwd = agent.workingDirectory || path9.join(this.workspacesDir, agent.id);
48295
48491
  if (agent.workingDirectory) {
48296
48492
  try {
48297
48493
  await fs4.mkdir(cwd, { recursive: true });
48298
48494
  } catch {
48299
- cwd = path8.join(this.workspacesDir, agent.id);
48495
+ cwd = path9.join(this.workspacesDir, agent.id);
48300
48496
  logger10.warn("Stored workingDirectory inaccessible, falling back", {
48301
48497
  agentId: agent.id,
48302
48498
  stored: agent.workingDirectory,
@@ -48769,8 +48965,8 @@ var HttpAgentRegistry = class {
48769
48965
  agents = /* @__PURE__ */ new Map();
48770
48966
  apiUrl(suffix) {
48771
48967
  const base = this.serverApiUrl.replace(/\/$/, "");
48772
- const path20 = suffix.startsWith("/") ? suffix : `/${suffix}`;
48773
- return `${base}${path20}`;
48968
+ const path21 = suffix.startsWith("/") ? suffix : `/${suffix}`;
48969
+ return `${base}${path21}`;
48774
48970
  }
48775
48971
  async refresh() {
48776
48972
  const attempt = async () => {
@@ -48861,8 +49057,8 @@ var HttpSubscriptionRegistry = class {
48861
49057
  subscriptions = /* @__PURE__ */ new Map();
48862
49058
  apiUrl(suffix) {
48863
49059
  const base = this.serverApiUrl.replace(/\/$/, "");
48864
- const path20 = suffix.startsWith("/") ? suffix : `/${suffix}`;
48865
- return `${base}${path20}`;
49060
+ const path21 = suffix.startsWith("/") ? suffix : `/${suffix}`;
49061
+ return `${base}${path21}`;
48866
49062
  }
48867
49063
  async refresh() {
48868
49064
  const attempt = async () => {
@@ -49345,7 +49541,7 @@ var ServerConnector = class {
49345
49541
  // src/contextDumper.ts
49346
49542
  import fs5 from "fs/promises";
49347
49543
  import os7 from "os";
49348
- import path9 from "path";
49544
+ import path10 from "path";
49349
49545
  var logger16 = createModuleLogger("bridge.contextDumper");
49350
49546
  var TRUNCATE_THRESHOLD = 5e4;
49351
49547
  var TRUNCATE_HEAD = 8e3;
@@ -49374,7 +49570,7 @@ function cwdToProjectSlug(cwd) {
49374
49570
  }
49375
49571
  function resolveJsonlPath(sessionId, cwd) {
49376
49572
  const slug = cwdToProjectSlug(cwd);
49377
- return path9.join(os7.homedir(), ".claude", "projects", slug, `${sessionId}.jsonl`);
49573
+ return path10.join(os7.homedir(), ".claude", "projects", slug, `${sessionId}.jsonl`);
49378
49574
  }
49379
49575
  var RENDERABLE_TYPES = /* @__PURE__ */ new Set(["user", "assistant", "system", "attachment"]);
49380
49576
  async function readJsonlEntries(filePath) {
@@ -49634,7 +49830,7 @@ async function dumpAgentContext(agentId, deps) {
49634
49830
  if (!workdir) {
49635
49831
  return { ok: false, files: [], scopeErrors: [], error: "agent has no working directory" };
49636
49832
  }
49637
- const dumpDir = path9.join(workdir, "sessioninfo");
49833
+ const dumpDir = path10.join(workdir, "sessioninfo");
49638
49834
  await fs5.mkdir(dumpDir, { recursive: true });
49639
49835
  const prefix = `${agentId}::`;
49640
49836
  const scopeEntries = [];
@@ -49704,7 +49900,7 @@ async function dumpAgentContext(agentId, deps) {
49704
49900
  jsonlPath
49705
49901
  });
49706
49902
  const filename = scopeFilename(agent.name, scopeKey2, groupName);
49707
- const filePath = path9.join(dumpDir, filename);
49903
+ const filePath = path10.join(dumpDir, filename);
49708
49904
  await fs5.writeFile(filePath, html, "utf-8");
49709
49905
  dumpedFiles.push(filename);
49710
49906
  const stat3 = await fs5.stat(filePath);
@@ -49745,7 +49941,7 @@ async function dumpAgentContext(agentId, deps) {
49745
49941
 
49746
49942
  // src/listDir.ts
49747
49943
  import fs6 from "fs/promises";
49748
- import path10 from "path";
49944
+ import path11 from "path";
49749
49945
  var logger17 = createModuleLogger("bridge.listDir");
49750
49946
  function shouldIncludeEntry(name) {
49751
49947
  if (!name.startsWith(".")) return true;
@@ -49757,7 +49953,7 @@ async function listDirectoryEntries(dirPath) {
49757
49953
  const entries = [];
49758
49954
  for (const entry of raw) {
49759
49955
  if (!shouldIncludeEntry(entry.name)) continue;
49760
- const fullPath = path10.join(dirPath, entry.name);
49956
+ const fullPath = path11.join(dirPath, entry.name);
49761
49957
  const isDir = entry.isDirectory();
49762
49958
  let size;
49763
49959
  let mtime;
@@ -49785,7 +49981,7 @@ async function listDirectoryEntries(dirPath) {
49785
49981
 
49786
49982
  // src/logScanner.ts
49787
49983
  import fs7 from "fs";
49788
- import path11 from "path";
49984
+ import path12 from "path";
49789
49985
  import os8 from "os";
49790
49986
  import readline from "readline";
49791
49987
  var logger18 = createModuleLogger("bridge.logScanner");
@@ -49800,10 +49996,10 @@ function listLogFiles(logsDir, baseName) {
49800
49996
  return [];
49801
49997
  }
49802
49998
  const pattern = new RegExp(`^${baseName.replace(".", "\\.")}(\\.\\d+)?$`);
49803
- return names.filter((n2) => pattern.test(n2)).map((n2) => path11.join(logsDir, n2));
49999
+ return names.filter((n2) => pattern.test(n2)).map((n2) => path12.join(logsDir, n2));
49804
50000
  }
49805
50001
  async function scanFile(filePath, source, filter, limit, state) {
49806
- const file2 = path11.basename(filePath);
50002
+ const file2 = path12.basename(filePath);
49807
50003
  const stream = fs7.createReadStream(filePath, { encoding: "utf-8" });
49808
50004
  const rl2 = readline.createInterface({ input: stream, crlfDelay: Infinity });
49809
50005
  let lineNum = 0;
@@ -49842,7 +50038,7 @@ async function scanLocalLogs(logsDir, baseName, filter) {
49842
50038
  };
49843
50039
  }
49844
50040
  async function scanBridgeLogs(filter) {
49845
- const logDir = path11.join(os8.homedir(), ".ahchat", "logs");
50041
+ const logDir = path12.join(os8.homedir(), ".ahchat", "logs");
49846
50042
  logger18.info("scanBridgeLogs start", {
49847
50043
  logDir,
49848
50044
  startIso: filter.startIso,
@@ -49860,13 +50056,13 @@ async function scanBridgeLogs(filter) {
49860
50056
 
49861
50057
  // src/skillStore.ts
49862
50058
  import fs8 from "fs";
49863
- import path12 from "path";
50059
+ import path13 from "path";
49864
50060
  var logger19 = createModuleLogger("bridge.skillStore");
49865
50061
  var ALLOWED_NAMES = /* @__PURE__ */ new Set(["log-analysis"]);
49866
50062
  var SkillStore = class {
49867
50063
  skillsDir;
49868
50064
  constructor(dataDir) {
49869
- this.skillsDir = path12.join(dataDir, "skills");
50065
+ this.skillsDir = path13.join(dataDir, "skills");
49870
50066
  fs8.mkdirSync(this.skillsDir, { recursive: true });
49871
50067
  logger19.info("SkillStore initialized", { skillsDir: this.skillsDir });
49872
50068
  }
@@ -49875,7 +50071,7 @@ var SkillStore = class {
49875
50071
  logger19.warn("Skill read: unknown name", { name, allowed: [...ALLOWED_NAMES] });
49876
50072
  return "";
49877
50073
  }
49878
- const filePath = path12.join(this.skillsDir, `${name}.md`);
50074
+ const filePath = path13.join(this.skillsDir, `${name}.md`);
49879
50075
  try {
49880
50076
  const content = fs8.readFileSync(filePath, "utf-8");
49881
50077
  logger19.info("Skill read", { name, bytes: content.length });
@@ -49890,7 +50086,7 @@ var SkillStore = class {
49890
50086
  if (!ALLOWED_NAMES.has(name)) {
49891
50087
  throw new Error(`Unknown skill name: ${name}`);
49892
50088
  }
49893
- const filePath = path12.join(this.skillsDir, `${name}.md`);
50089
+ const filePath = path13.join(this.skillsDir, `${name}.md`);
49894
50090
  const tmpPath = `${filePath}.tmp`;
49895
50091
  let existing = "";
49896
50092
  try {
@@ -49913,7 +50109,7 @@ var SkillStore = class {
49913
50109
 
49914
50110
  // src/lockfile.ts
49915
50111
  import fs9 from "fs";
49916
- import path13 from "path";
50112
+ import path14 from "path";
49917
50113
  var logger20 = createModuleLogger("bridge.lockfile");
49918
50114
  var lockPath = null;
49919
50115
  function isProcessAlive(pid) {
@@ -49927,7 +50123,7 @@ function isProcessAlive(pid) {
49927
50123
  }
49928
50124
  }
49929
50125
  function acquireLock(dataDir) {
49930
- const file2 = path13.join(dataDir, "bridge.lock");
50126
+ const file2 = path14.join(dataDir, "bridge.lock");
49931
50127
  lockPath = file2;
49932
50128
  if (fs9.existsSync(file2)) {
49933
50129
  const raw = fs9.readFileSync(file2, "utf-8").trim();
@@ -49939,7 +50135,7 @@ function acquireLock(dataDir) {
49939
50135
  logger20.warn("Removing stale bridge.lock (process not found)", { pid, path: file2 });
49940
50136
  }
49941
50137
  }
49942
- fs9.mkdirSync(path13.dirname(file2), { recursive: true });
50138
+ fs9.mkdirSync(path14.dirname(file2), { recursive: true });
49943
50139
  fs9.writeFileSync(file2, String(process.pid), "utf-8");
49944
50140
  logger20.info("Acquired bridge lock", { path: file2, pid: process.pid });
49945
50141
  const release = () => {
@@ -50303,13 +50499,13 @@ async function handleGroupArchivedPush(deps, payload) {
50303
50499
 
50304
50500
  // src/sessionStore.ts
50305
50501
  import fs10 from "fs";
50306
- import path14 from "path";
50502
+ import path15 from "path";
50307
50503
  var logger23 = createModuleLogger("session.store");
50308
50504
  var SessionStore = class {
50309
50505
  filePath;
50310
50506
  cache;
50311
50507
  constructor(dataDir) {
50312
- this.filePath = path14.join(dataDir, "sessions.json");
50508
+ this.filePath = path15.join(dataDir, "sessions.json");
50313
50509
  this.cache = this.loadFromDisk();
50314
50510
  }
50315
50511
  cacheKey(agentId, scope) {
@@ -50369,7 +50565,7 @@ var SessionStore = class {
50369
50565
  }
50370
50566
  saveToDisk() {
50371
50567
  try {
50372
- const dir = path14.dirname(this.filePath);
50568
+ const dir = path15.dirname(this.filePath);
50373
50569
  fs10.mkdirSync(dir, { recursive: true });
50374
50570
  fs10.writeFileSync(this.filePath, JSON.stringify(this.cache, null, 2), "utf-8");
50375
50571
  } catch (e7) {
@@ -50383,6 +50579,13 @@ import { execFileSync, execSync, spawnSync } from "child_process";
50383
50579
  import { accessSync, constants as constants2 } from "fs";
50384
50580
  import { join as join2 } from "path";
50385
50581
  var logger24 = createModuleLogger("bridge.ensureCli");
50582
+ var DEFAULT_INSTALL_TIMEOUT_MS = 6e5;
50583
+ function getInstallTimeoutMs() {
50584
+ const raw = process.env.AHCHAT_CLAUDE_CLI_INSTALL_TIMEOUT_MS;
50585
+ if (!raw) return DEFAULT_INSTALL_TIMEOUT_MS;
50586
+ const parsed = Number.parseInt(raw, 10);
50587
+ return Number.isFinite(parsed) && parsed > 0 ? parsed : DEFAULT_INSTALL_TIMEOUT_MS;
50588
+ }
50386
50589
  function detectClaudeCli() {
50387
50590
  try {
50388
50591
  return execFileSync("claude", ["--version"], { timeout: 1e4 }).toString().trim();
@@ -50411,9 +50614,18 @@ function resolveClaudeBinary() {
50411
50614
  if (first) return first;
50412
50615
  } catch {
50413
50616
  }
50617
+ return resolveViaNpmBin();
50618
+ }
50619
+ function getNpmClaudeCandidates(bin) {
50620
+ if (process.platform === "win32") {
50621
+ return ["claude.cmd", "claude.exe", "claude", "anthropic-cli.cmd", "anthropic-cli.exe", "anthropic-cli"].map((name) => join2(bin, name));
50622
+ }
50623
+ return [join2(bin, "claude"), join2(bin, "anthropic-cli")];
50624
+ }
50625
+ function resolveViaNpmBin() {
50414
50626
  const bin = getNpmGlobalBin();
50415
- if (bin) {
50416
- const candidate = join2(bin, process.platform === "win32" ? "claude.cmd" : "claude");
50627
+ if (!bin) return void 0;
50628
+ for (const candidate of getNpmClaudeCandidates(bin)) {
50417
50629
  try {
50418
50630
  accessSync(candidate, constants2.X_OK);
50419
50631
  return candidate;
@@ -50423,9 +50635,30 @@ function resolveClaudeBinary() {
50423
50635
  return void 0;
50424
50636
  }
50425
50637
  function detectViaNpmBin() {
50426
- const bin = getNpmGlobalBin();
50427
- if (!bin) return void 0;
50428
- const candidates = [join2(bin, "claude"), join2(bin, "anthropic-cli")];
50638
+ const binPath = resolveViaNpmBin();
50639
+ if (!binPath) return void 0;
50640
+ try {
50641
+ return execFileSync(binPath, ["--version"], { timeout: 1e4 }).toString().trim();
50642
+ } catch {
50643
+ }
50644
+ return void 0;
50645
+ }
50646
+ function detectResolvedClaudeCli() {
50647
+ const viaPath = detectClaudeCli();
50648
+ if (viaPath) {
50649
+ return { version: viaPath, path: resolveClaudeBinary() };
50650
+ }
50651
+ const npmBinPath = resolveViaNpmBin();
50652
+ if (!npmBinPath) return void 0;
50653
+ try {
50654
+ const version2 = execFileSync(npmBinPath, ["--version"], { timeout: 1e4 }).toString().trim();
50655
+ return { version: version2, path: npmBinPath };
50656
+ } catch {
50657
+ }
50658
+ return void 0;
50659
+ }
50660
+ function detectVersionFromResolvedCandidates() {
50661
+ const candidates = [resolveClaudeBinary(), resolveViaNpmBin()].filter((p) => Boolean(p));
50429
50662
  for (const p of candidates) {
50430
50663
  try {
50431
50664
  accessSync(p, constants2.X_OK);
@@ -50439,7 +50672,7 @@ function installClaudeCli() {
50439
50672
  logger24.info("Installing Claude Code CLI via npm...");
50440
50673
  const result = spawnSync("npm", ["install", "-g", "@anthropic-ai/claude-code"], {
50441
50674
  stdio: "inherit",
50442
- timeout: 12e4
50675
+ timeout: getInstallTimeoutMs()
50443
50676
  });
50444
50677
  if (result.error) {
50445
50678
  logger24.error("npm install -g failed (spawn error)", {
@@ -50454,9 +50687,9 @@ function installClaudeCli() {
50454
50687
  return void 0;
50455
50688
  }
50456
50689
  logger24.info("npm install -g completed, checking for claude binary...");
50457
- const viaPath = detectClaudeCli();
50690
+ const viaPath = detectVersionFromResolvedCandidates();
50458
50691
  if (viaPath) {
50459
- logger24.info("claude detected via PATH after install", { version: viaPath });
50692
+ logger24.info("claude detected after install", { version: viaPath });
50460
50693
  return viaPath;
50461
50694
  }
50462
50695
  const viaBin = detectViaNpmBin();
@@ -50474,14 +50707,13 @@ function installClaudeCli() {
50474
50707
  return void 0;
50475
50708
  }
50476
50709
  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;
50710
+ let detected = detectResolvedClaudeCli();
50711
+ if (detected) {
50712
+ logger24.info("Claude Code CLI ready", { version: detected.version, path: detected.path ?? null });
50713
+ return detected.path;
50482
50714
  }
50483
50715
  process.stderr.write("\n\u26A0 Claude Code CLI (`claude`) not found. Attempting auto-install...\n\n");
50484
- version2 = installClaudeCli();
50716
+ const version2 = installClaudeCli();
50485
50717
  if (!version2) {
50486
50718
  const npmBin = getNpmGlobalBin();
50487
50719
  process.stderr.write(
@@ -50492,27 +50724,27 @@ async function ensureClaudeCli() {
50492
50724
  );
50493
50725
  process.exit(1);
50494
50726
  }
50495
- const binPath = resolveClaudeBinary();
50496
- logger24.info("Claude Code CLI ready", { version: version2, path: binPath ?? null });
50497
- return binPath;
50727
+ detected = detectResolvedClaudeCli();
50728
+ logger24.info("Claude Code CLI ready", { version: version2, path: detected?.path ?? null });
50729
+ return detected?.path;
50498
50730
  }
50499
50731
 
50500
50732
  // src/forkAgentFiles.ts
50501
50733
  import * as fs11 from "fs/promises";
50502
- import * as path16 from "path";
50734
+ import * as path17 from "path";
50503
50735
 
50504
50736
  // src/sessionSlug.ts
50505
50737
  import os9 from "os";
50506
- import path15 from "path";
50507
- var CLAUDE_PROJECTS_DIR = path15.join(os9.homedir(), ".claude", "projects");
50738
+ import path16 from "path";
50739
+ var CLAUDE_PROJECTS_DIR = path16.join(os9.homedir(), ".claude", "projects");
50508
50740
  function cwdToSlug(cwd) {
50509
50741
  return cwd.replace(/[^a-zA-Z0-9-]/g, "-");
50510
50742
  }
50511
50743
  function sessionDirForCwd(cwd) {
50512
- return path15.join(CLAUDE_PROJECTS_DIR, cwdToSlug(cwd));
50744
+ return path16.join(CLAUDE_PROJECTS_DIR, cwdToSlug(cwd));
50513
50745
  }
50514
50746
  function sessionFilePath(cwd, sessionId) {
50515
- return path15.join(sessionDirForCwd(cwd), `${sessionId}.jsonl`);
50747
+ return path16.join(sessionDirForCwd(cwd), `${sessionId}.jsonl`);
50516
50748
  }
50517
50749
 
50518
50750
  // src/forkAgentFiles.ts
@@ -50544,9 +50776,9 @@ async function forkAgentFiles(sourceAgentId, newAgentId, sourceWorkdir, newWorkd
50544
50776
  logger25.error("Workdir copy failed", { error: e7 });
50545
50777
  throw e7;
50546
50778
  }
50547
- const srcNotebook = path16.join(dataDir, "agent-memory", sourceAgentId, "notebook.md");
50548
- const dstNotebookDir = path16.join(dataDir, "agent-memory", newAgentId);
50549
- const dstNotebook = path16.join(dstNotebookDir, "notebook.md");
50779
+ const srcNotebook = path17.join(dataDir, "agent-memory", sourceAgentId, "notebook.md");
50780
+ const dstNotebookDir = path17.join(dataDir, "agent-memory", newAgentId);
50781
+ const dstNotebook = path17.join(dstNotebookDir, "notebook.md");
50550
50782
  try {
50551
50783
  const nbStat = await fs11.stat(srcNotebook).catch(() => null);
50552
50784
  if (nbStat?.isFile()) {
@@ -50573,7 +50805,7 @@ async function forkAgentFiles(sourceAgentId, newAgentId, sourceWorkdir, newWorkd
50573
50805
  if (srcStat?.isFile()) {
50574
50806
  const dstDir = sessionDirForCwd(newWorkdir);
50575
50807
  await fs11.mkdir(dstDir, { recursive: true });
50576
- const dstPath = path16.join(dstDir, `${sourceSessionId}.jsonl`);
50808
+ const dstPath = path17.join(dstDir, `${sourceSessionId}.jsonl`);
50577
50809
  await fs11.copyFile(srcPath, dstPath);
50578
50810
  sessionStore.set(newAgentId, { kind: "single" }, sourceSessionId);
50579
50811
  sessionCopied = true;
@@ -50621,11 +50853,11 @@ async function forkAgentFiles(sourceAgentId, newAgentId, sourceWorkdir, newWorkd
50621
50853
  // src/modelQuerier.ts
50622
50854
  import fs12 from "fs/promises";
50623
50855
  import os10 from "os";
50624
- import path17 from "path";
50856
+ import path18 from "path";
50625
50857
  var logger26 = createModuleLogger("bridge.modelQuerier");
50626
50858
  async function listModels(queryFn, opts = {}) {
50627
50859
  const t0 = Date.now();
50628
- const cwd = opts.cwd ?? path17.join(os10.homedir(), ".ahchat", "workspaces", "_list_models");
50860
+ const cwd = opts.cwd ?? path18.join(os10.homedir(), ".ahchat", "workspaces", "_list_models");
50629
50861
  await fs12.mkdir(cwd, { recursive: true });
50630
50862
  const fn = queryFn ?? QA$;
50631
50863
  const ic2 = new InputController();
@@ -50688,7 +50920,7 @@ async function listModels(queryFn, opts = {}) {
50688
50920
  // src/promptOptimizer.ts
50689
50921
  import fs13 from "fs/promises";
50690
50922
  import os11 from "os";
50691
- import path18 from "path";
50923
+ import path19 from "path";
50692
50924
  var logger27 = createModuleLogger("bridge.promptOptimizer");
50693
50925
  var OPTIMIZER_SYSTEM_PROMPT = `You are an expert prompt editor for AHChat Agent creation.
50694
50926
 
@@ -50731,7 +50963,7 @@ async function optimizePrompt(queryFn, opts) {
50731
50963
  const prompt = opts.systemPrompt.trim();
50732
50964
  if (!prompt) throw new Error("systemPrompt is required");
50733
50965
  const t0 = Date.now();
50734
- const cwd = opts.cwd ?? path18.join(os11.homedir(), ".ahchat", "workspaces", "_prompt_optimizer");
50966
+ const cwd = opts.cwd ?? path19.join(os11.homedir(), ".ahchat", "workspaces", "_prompt_optimizer");
50735
50967
  await fs13.mkdir(cwd, { recursive: true });
50736
50968
  const fn = queryFn ?? QA$;
50737
50969
  const ic2 = new InputController();
@@ -50819,7 +51051,7 @@ function isRunningAsRoot2() {
50819
51051
  }
50820
51052
  }
50821
51053
  async function syncClaudeCredentialsToNodeAccessibleDir(agentConfigDir) {
50822
- const rootClaudeDir = path19.join(process.env.HOME ?? "/root", ".claude");
51054
+ const rootClaudeDir = path20.join(process.env.HOME ?? "/root", ".claude");
50823
51055
  const fs14 = await import("fs/promises");
50824
51056
  try {
50825
51057
  await fs14.access(rootClaudeDir);
@@ -50829,8 +51061,8 @@ async function syncClaudeCredentialsToNodeAccessibleDir(agentConfigDir) {
50829
51061
  }
50830
51062
  const filesToSync = [".credentials.json", "settings.json", ".credentials.backup.json"];
50831
51063
  for (const file2 of filesToSync) {
50832
- const src = path19.join(rootClaudeDir, file2);
50833
- const dest = path19.join(agentConfigDir, file2);
51064
+ const src = path20.join(rootClaudeDir, file2);
51065
+ const dest = path20.join(agentConfigDir, file2);
50834
51066
  try {
50835
51067
  await fs14.copyFile(src, dest);
50836
51068
  logger28.info("Synced credential file", { file: file2, from: src, to: dest });
@@ -50853,7 +51085,7 @@ async function chownRecursive(dirPath, uid, gid) {
50853
51085
  return;
50854
51086
  }
50855
51087
  for (const entry of entries) {
50856
- const fullPath = path19.join(dirPath, entry.name);
51088
+ const fullPath = path20.join(dirPath, entry.name);
50857
51089
  if (entry.isDirectory()) {
50858
51090
  await chownRecursive(fullPath, uid, gid);
50859
51091
  } else {
@@ -50868,7 +51100,7 @@ async function chownRecursive(dirPath, uid, gid) {
50868
51100
  async function startBridge(config2) {
50869
51101
  ensureDir(config2.dataDir);
50870
51102
  ensureDir(config2.agentConfigDir);
50871
- const workspacesDir = path19.join(config2.dataDir, "workspaces");
51103
+ const workspacesDir = path20.join(config2.dataDir, "workspaces");
50872
51104
  ensureDir(workspacesDir);
50873
51105
  process.env.CLAUDE_CONFIG_DIR = config2.agentConfigDir;
50874
51106
  installBridgeFetchAuth(config2.serverApiUrl, config2.bridgeToken);
@@ -50897,7 +51129,7 @@ Bridge token (register this machine at Settings \u2192 \u5DF2\u8FDE\u63A5\u7684\
50897
51129
  `);
50898
51130
  wsMetrics.start(5e3);
50899
51131
  const sessionStore = new SessionStore(config2.dataDir);
50900
- const memoryRoot = path19.join(config2.dataDir, "agent-memory");
51132
+ const memoryRoot = path20.join(config2.dataDir, "agent-memory");
50901
51133
  const memoryStore = new AgentMemoryStore(memoryRoot);
50902
51134
  logger28.info("Agent memory store initialized", { rootDir: memoryRoot });
50903
51135
  const smithNotebook = memoryStore.read(SMITH_AGENT_ID);
@@ -51074,7 +51306,16 @@ Bridge token (register this machine at Settings \u2192 \u5DF2\u8FDE\u63A5\u7684\
51074
51306
  const { requestId, path: dirPath } = msg.payload;
51075
51307
  logger28.info("list_dir request received", { requestId, path: dirPath });
51076
51308
  try {
51077
- const entries = await listDirectoryEntries(dirPath);
51309
+ const resolved = remapServerWorkspacePath(dirPath, workspacesDir);
51310
+ if (resolved.remapped) {
51311
+ ensureDir(resolved.path);
51312
+ logger28.info("list_dir path remapped to local Bridge workspace", {
51313
+ requestId,
51314
+ requested: dirPath,
51315
+ remapped: resolved.path
51316
+ });
51317
+ }
51318
+ const entries = await listDirectoryEntries(resolved.path);
51078
51319
  connector?.send({
51079
51320
  type: "bridge:list_dir_response",
51080
51321
  payload: { requestId, entries }