@fangyb/ahchat-bridge 0.1.18 → 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 +601 -105
- package/dist/cli.js +0 -0
- package/dist/index.js +573 -94
- package/package.json +11 -11
package/dist/index.js
CHANGED
|
@@ -3746,8 +3746,8 @@ function resolveAgentConfigDir(dataDir) {
|
|
|
3746
3746
|
}
|
|
3747
3747
|
return newPath;
|
|
3748
3748
|
}
|
|
3749
|
-
function loadBridgeConfig() {
|
|
3750
|
-
const dataDir = readEnvString(
|
|
3749
|
+
function loadBridgeConfig(opts) {
|
|
3750
|
+
const dataDir = opts?.dataDir ?? readEnvString(
|
|
3751
3751
|
"AHCHAT_DATA_DIR",
|
|
3752
3752
|
path.join(os.homedir(), ".ahchat")
|
|
3753
3753
|
);
|
|
@@ -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: [
|
|
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
|
|
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
|
|
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\
|
|
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
|
|
5553
|
-
|
|
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
|
-
-
|
|
5558
|
-
|
|
5559
|
-
|
|
5560
|
-
|
|
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
|
|
5575
|
+
- All task content shown on the board must be in Chinese.
|
|
5570
5576
|
|
|
5571
|
-
Do NOT use
|
|
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
|
|
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 |
|
|
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 /
|
|
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
|
-
-
|
|
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
|
-
-
|
|
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
|
|
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
|
-
|
|
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
|
|
@@ -5851,6 +5857,11 @@ var LOG_LEVEL_VALUE2 = {
|
|
|
5851
5857
|
FATAL: 5
|
|
5852
5858
|
};
|
|
5853
5859
|
|
|
5860
|
+
// ../shared/src/types/onboarding.ts
|
|
5861
|
+
function isCapabilityTier(v9) {
|
|
5862
|
+
return v9 === "smart" || v9 === "balanced" || v9 === "fast";
|
|
5863
|
+
}
|
|
5864
|
+
|
|
5854
5865
|
// ../../node_modules/.pnpm/nanoid@5.1.11/node_modules/nanoid/index.js
|
|
5855
5866
|
import { webcrypto as crypto2 } from "crypto";
|
|
5856
5867
|
|
|
@@ -5921,20 +5932,6 @@ function parseWSMessage(raw) {
|
|
|
5921
5932
|
return parsed;
|
|
5922
5933
|
}
|
|
5923
5934
|
|
|
5924
|
-
// ../shared/src/utils/workdir.ts
|
|
5925
|
-
var SLUG_MAX_LEN = 32;
|
|
5926
|
-
function slugifyForFs(name) {
|
|
5927
|
-
const trimmed = name.trim();
|
|
5928
|
-
if (!trimmed) return "unnamed";
|
|
5929
|
-
const slug = trimmed.replace(/[^\w\u4e00-\u9fa5 \-]/gu, "_").replace(/\s+/g, "_").replace(/_+/g, "_").replace(/^_|_$/g, "");
|
|
5930
|
-
const base = slug.length > 0 ? slug : "unnamed";
|
|
5931
|
-
return base.length > SLUG_MAX_LEN ? base.slice(0, SLUG_MAX_LEN) : base;
|
|
5932
|
-
}
|
|
5933
|
-
function defaultGroupWorkdir(home, name, id) {
|
|
5934
|
-
const slug = slugifyForFs(name);
|
|
5935
|
-
return `${home}/.ahchat/Group-${slug}-${id}`;
|
|
5936
|
-
}
|
|
5937
|
-
|
|
5938
5935
|
// ../shared/src/utils/subscription.ts
|
|
5939
5936
|
function isSubscriptionType(v9) {
|
|
5940
5937
|
return v9 === "system" || v9 === "project";
|
|
@@ -5949,6 +5946,7 @@ function parseAgentConfig(raw) {
|
|
|
5949
5946
|
const out = {};
|
|
5950
5947
|
const obj = v9;
|
|
5951
5948
|
if (typeof obj.model === "string" && obj.model.trim()) out.model = obj.model.trim();
|
|
5949
|
+
if (isCapabilityTier(obj.capabilityTier)) out.capabilityTier = obj.capabilityTier;
|
|
5952
5950
|
if (typeof obj.subscriptionId === "string") {
|
|
5953
5951
|
const trimmed = obj.subscriptionId.trim();
|
|
5954
5952
|
if (/^sub_[A-Za-z0-9_-]{1,64}$/.test(trimmed)) {
|
|
@@ -42814,6 +42812,18 @@ function resolveMyHuman(registry2, agentId) {
|
|
|
42814
42812
|
}
|
|
42815
42813
|
return USR_SELF_ID;
|
|
42816
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
|
+
}
|
|
42817
42827
|
function normalizeFeedCategory(input) {
|
|
42818
42828
|
const raw = (input ?? "").trim().toLowerCase();
|
|
42819
42829
|
if (raw === "pitfall" || raw === "\u8E29\u5751") return "pitfall";
|
|
@@ -43359,13 +43369,13 @@ action="append" \u8FFD\u52A0\u65B0\u5185\u5BB9\uFF08\u6700\u5E38\u7528\uFF0Ccont
|
|
|
43359
43369
|
{
|
|
43360
43370
|
name: external_exports.string().min(1).describe("\u7FA4\u540D\uFF08\u4E0D\u80FD\u4E3A\u7A7A\uFF09"),
|
|
43361
43371
|
member_ids: external_exports.array(external_exports.string()).describe(
|
|
43362
|
-
"\u8981\u62C9\u8FDB\u7FA4\u7684\u6210\u5458 ID \u6570\u7EC4\uFF08Agent \u6216\u4EBA\u7C7B
|
|
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"
|
|
43363
43373
|
),
|
|
43364
43374
|
initial_message: external_exports.string().optional().describe(
|
|
43365
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"
|
|
43366
43376
|
),
|
|
43367
43377
|
join_as_creator: external_exports.boolean().optional().describe(
|
|
43368
|
-
"\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\
|
|
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"
|
|
43369
43379
|
)
|
|
43370
43380
|
},
|
|
43371
43381
|
async (args) => {
|
|
@@ -43375,7 +43385,7 @@ action="append" \u8FFD\u52A0\u65B0\u5185\u5BB9\uFF08\u6700\u5E38\u7528\uFF0Ccont
|
|
|
43375
43385
|
}
|
|
43376
43386
|
const joinAsCreator = args.join_as_creator !== false;
|
|
43377
43387
|
const requested = Array.isArray(args.member_ids) ? args.member_ids : [];
|
|
43378
|
-
const requestedUnique =
|
|
43388
|
+
const requestedUnique = normalizeMemberIds(deps.agentRegistry, deps.agentId, requested);
|
|
43379
43389
|
const dedup = joinAsCreator ? Array.from(/* @__PURE__ */ new Set([...requestedUnique, deps.agentId])) : requestedUnique.filter((id) => id !== deps.agentId);
|
|
43380
43390
|
if (dedup.length < 2) {
|
|
43381
43391
|
return {
|
|
@@ -43398,13 +43408,14 @@ action="append" \u8FFD\u52A0\u65B0\u5185\u5BB9\uFF08\u6700\u5E38\u7528\uFF0Ccont
|
|
|
43398
43408
|
};
|
|
43399
43409
|
}
|
|
43400
43410
|
}
|
|
43401
|
-
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)) : "";
|
|
43402
43412
|
const hasInitial = initialMessage.length > 0;
|
|
43403
43413
|
logger5.info("create_group tool called", {
|
|
43404
43414
|
agentId: deps.agentId,
|
|
43405
43415
|
name: trimmedName,
|
|
43406
43416
|
memberCount: dedup.length,
|
|
43407
43417
|
memberIds: dedup,
|
|
43418
|
+
requestedMemberIds: requested,
|
|
43408
43419
|
joinAsCreator,
|
|
43409
43420
|
hasInitialMessage: hasInitial,
|
|
43410
43421
|
initialMessageLen: initialMessage.length
|
|
@@ -43471,7 +43482,7 @@ action="append" \u8FFD\u52A0\u65B0\u5185\u5BB9\uFF08\u6700\u5E38\u7528\uFF0Ccont
|
|
|
43471
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
|
|
43472
43483
|
\u8981\u62C9\u7684\u6210\u5458\u5FC5\u987B\u5728 list_contacts \u7684\u901A\u8BAF\u5F55\u91CC\u3002
|
|
43473
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
|
|
43474
|
-
\u8981\u628A\u4EBA\u7C7B\u7528\u6237\u52A0\u8FDB\u6765\uFF1A\
|
|
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
|
|
43475
43486
|
|
|
43476
43487
|
\u4F7F\u7528\u573A\u666F\uFF1A
|
|
43477
43488
|
- \u9700\u8981\u5728\u7FA4\u91CC\u5F15\u5165\u65B0\u7684\u534F\u4F5C\u4F19\u4F34\u65F6
|
|
@@ -43485,7 +43496,7 @@ action="append" \u8FFD\u52A0\u65B0\u5185\u5BB9\uFF08\u6700\u5E38\u7528\uFF0Ccont
|
|
|
43485
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'
|
|
43486
43497
|
),
|
|
43487
43498
|
agent_ids: external_exports.array(external_exports.string()).describe(
|
|
43488
|
-
"\u8981\u62C9\u8FDB\u7FA4\u7684\u6210\u5458 ID \u6570\u7EC4\uFF08Agent \u6216\u4EBA\u7C7B
|
|
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"
|
|
43489
43500
|
)
|
|
43490
43501
|
},
|
|
43491
43502
|
async (args) => {
|
|
@@ -43493,7 +43504,8 @@ action="append" \u8FFD\u52A0\u65B0\u5185\u5BB9\uFF08\u6700\u5E38\u7528\uFF0Ccont
|
|
|
43493
43504
|
if (!rawGroup) {
|
|
43494
43505
|
return { content: [{ type: "text", text: "[add_to_group] group \u4E0D\u80FD\u4E3A\u7A7A\u3002" }], isError: true };
|
|
43495
43506
|
}
|
|
43496
|
-
const
|
|
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);
|
|
43497
43509
|
if (agentIds.length === 0) {
|
|
43498
43510
|
return { content: [{ type: "text", text: "[add_to_group] agent_ids \u81F3\u5C11\u9700\u8981 1 \u4E2A Agent\u3002" }], isError: true };
|
|
43499
43511
|
}
|
|
@@ -44055,9 +44067,12 @@ limit \u9ED8\u8BA4 500\uFF0C\u786C\u4E0A\u9650 2000\u3002\u8FD4\u56DE\u7ED3\u679
|
|
|
44055
44067
|
const tierRes = await fetch(tierUrl);
|
|
44056
44068
|
if (tierRes.ok) {
|
|
44057
44069
|
const tiers = await tierRes.json();
|
|
44058
|
-
const
|
|
44070
|
+
const self2 = deps.agentRegistry?.getById(deps.agentId);
|
|
44071
|
+
const preferredSubscriptionId = parseAgentConfig(self2?.config).subscriptionId;
|
|
44072
|
+
const tierConfig = tiers.find((t2) => t2.tier === tier && t2.subscriptionId === preferredSubscriptionId) ?? tiers.find((t2) => t2.tier === tier);
|
|
44059
44073
|
if (tierConfig) {
|
|
44060
44074
|
agentConfig = JSON.stringify({
|
|
44075
|
+
capabilityTier: tier,
|
|
44061
44076
|
subscriptionId: tierConfig.subscriptionId,
|
|
44062
44077
|
model: tierConfig.modelName
|
|
44063
44078
|
});
|
|
@@ -44209,9 +44224,11 @@ limit \u9ED8\u8BA4 500\uFF0C\u786C\u4E0A\u9650 2000\u3002\u8FD4\u56DE\u7ED3\u679
|
|
|
44209
44224
|
const tierRes = await fetch(tierUrl);
|
|
44210
44225
|
if (tierRes.ok) {
|
|
44211
44226
|
const tiers = await tierRes.json();
|
|
44212
|
-
const
|
|
44227
|
+
const preferredSubscriptionId = parseAgentConfig(existing.config).subscriptionId;
|
|
44228
|
+
const tierConfig = tiers.find((t2) => t2.tier === tier && t2.subscriptionId === preferredSubscriptionId) ?? tiers.find((t2) => t2.tier === tier);
|
|
44213
44229
|
if (tierConfig) {
|
|
44214
44230
|
agentConfig = JSON.stringify({
|
|
44231
|
+
capabilityTier: tier,
|
|
44215
44232
|
subscriptionId: tierConfig.subscriptionId,
|
|
44216
44233
|
model: tierConfig.modelName
|
|
44217
44234
|
});
|
|
@@ -44943,11 +44960,117 @@ function buildGroupInboxPrompt(entries, opts = {}) {
|
|
|
44943
44960
|
var logger7 = createModuleLogger("sdk.mapper");
|
|
44944
44961
|
var HIGH_WATERMARK_INPUT_TOKENS = 12e4;
|
|
44945
44962
|
var WARN_THRESHOLD_INPUT_TOKENS = 1e5;
|
|
44963
|
+
var LIVE_INPUT_PREVIEW_TOOLS = /* @__PURE__ */ new Set(["Write", "Edit"]);
|
|
44946
44964
|
var CONTEXT_OVERFLOW_LOCK_MS = 6e4;
|
|
44947
44965
|
function isContextOverflowText(text) {
|
|
44948
44966
|
const trimmed = text.trim();
|
|
44949
44967
|
return /^prompt is too long\b/i.test(trimmed) || /context length .* exceed/i.test(trimmed);
|
|
44950
44968
|
}
|
|
44969
|
+
function isAuthFailureText(text, sdkError) {
|
|
44970
|
+
return sdkError === "authentication_failed" || /not logged in|please run \/login/i.test(text);
|
|
44971
|
+
}
|
|
44972
|
+
function buildAuthFailureMessage(errorText) {
|
|
44973
|
+
return `Claude Code SDK \u672A\u767B\u5F55\uFF08${errorText}\uFF09\u3002\u8BF7\u5728 bridge \u4E3B\u673A\u4E0A\u914D\u7F6E\u8BA4\u8BC1\uFF1A\u82E5\u8BE5 Agent \u7528 system \u8BA2\u9605\uFF0C\u5C06\u5176 subscriptionType \u8BBE\u4E3A "system"\uFF08\u8D70 ~/.claude\uFF09\uFF1B\u5426\u5219\u5728 ~/.ahchat/claude-config \u4E0B\u767B\u5F55\uFF0C\u6216\u5728 Agent config \u4E2D\u63D0\u4F9B apiKey / apiBaseUrl\u3002`;
|
|
44974
|
+
}
|
|
44975
|
+
function decodeJsonStringFragment(raw) {
|
|
44976
|
+
let out = "";
|
|
44977
|
+
for (let i = 0; i < raw.length; i++) {
|
|
44978
|
+
const ch2 = raw[i];
|
|
44979
|
+
if (ch2 !== "\\") {
|
|
44980
|
+
out += ch2;
|
|
44981
|
+
continue;
|
|
44982
|
+
}
|
|
44983
|
+
const next = raw[i + 1];
|
|
44984
|
+
if (next === void 0) break;
|
|
44985
|
+
i += 1;
|
|
44986
|
+
switch (next) {
|
|
44987
|
+
case '"':
|
|
44988
|
+
case "\\":
|
|
44989
|
+
case "/":
|
|
44990
|
+
out += next;
|
|
44991
|
+
break;
|
|
44992
|
+
case "b":
|
|
44993
|
+
out += "\b";
|
|
44994
|
+
break;
|
|
44995
|
+
case "f":
|
|
44996
|
+
out += "\f";
|
|
44997
|
+
break;
|
|
44998
|
+
case "n":
|
|
44999
|
+
out += "\n";
|
|
45000
|
+
break;
|
|
45001
|
+
case "r":
|
|
45002
|
+
out += "\r";
|
|
45003
|
+
break;
|
|
45004
|
+
case "t":
|
|
45005
|
+
out += " ";
|
|
45006
|
+
break;
|
|
45007
|
+
case "u": {
|
|
45008
|
+
const hex3 = raw.slice(i + 1, i + 5);
|
|
45009
|
+
if (!/^[0-9a-fA-F]{4}$/.test(hex3)) return out;
|
|
45010
|
+
out += String.fromCharCode(Number.parseInt(hex3, 16));
|
|
45011
|
+
i += 4;
|
|
45012
|
+
break;
|
|
45013
|
+
}
|
|
45014
|
+
default:
|
|
45015
|
+
out += next;
|
|
45016
|
+
}
|
|
45017
|
+
}
|
|
45018
|
+
return out;
|
|
45019
|
+
}
|
|
45020
|
+
function extractJsonStringPrefix(source, key) {
|
|
45021
|
+
const keyToken = `"${key}"`;
|
|
45022
|
+
const keyIndex = source.indexOf(keyToken);
|
|
45023
|
+
if (keyIndex < 0) return null;
|
|
45024
|
+
let i = keyIndex + keyToken.length;
|
|
45025
|
+
while (i < source.length && /\s/.test(source[i] ?? "")) i += 1;
|
|
45026
|
+
if (source[i] !== ":") return null;
|
|
45027
|
+
i += 1;
|
|
45028
|
+
while (i < source.length && /\s/.test(source[i] ?? "")) i += 1;
|
|
45029
|
+
if (source[i] !== '"') return null;
|
|
45030
|
+
i += 1;
|
|
45031
|
+
let raw = "";
|
|
45032
|
+
let escaped = false;
|
|
45033
|
+
for (; i < source.length; i++) {
|
|
45034
|
+
const ch2 = source[i];
|
|
45035
|
+
if (ch2 === void 0) break;
|
|
45036
|
+
if (escaped) {
|
|
45037
|
+
raw += `\\${ch2}`;
|
|
45038
|
+
escaped = false;
|
|
45039
|
+
continue;
|
|
45040
|
+
}
|
|
45041
|
+
if (ch2 === "\\") {
|
|
45042
|
+
escaped = true;
|
|
45043
|
+
continue;
|
|
45044
|
+
}
|
|
45045
|
+
if (ch2 === '"') {
|
|
45046
|
+
return decodeJsonStringFragment(raw);
|
|
45047
|
+
}
|
|
45048
|
+
raw += ch2;
|
|
45049
|
+
}
|
|
45050
|
+
if (escaped) raw += "\\";
|
|
45051
|
+
return decodeJsonStringFragment(raw);
|
|
45052
|
+
}
|
|
45053
|
+
function extractLiveToolInput(toolName, inputJson) {
|
|
45054
|
+
if (toolName === "Write") {
|
|
45055
|
+
const content = extractJsonStringPrefix(inputJson, "content");
|
|
45056
|
+
if (content == null) return null;
|
|
45057
|
+
const filePath = extractJsonStringPrefix(inputJson, "file_path");
|
|
45058
|
+
return filePath == null ? { content } : { file_path: filePath, content };
|
|
45059
|
+
}
|
|
45060
|
+
if (toolName === "Edit") {
|
|
45061
|
+
const newString = extractJsonStringPrefix(inputJson, "new_string");
|
|
45062
|
+
if (newString == null) return null;
|
|
45063
|
+
const oldString = extractJsonStringPrefix(inputJson, "old_string");
|
|
45064
|
+
const filePath = extractJsonStringPrefix(inputJson, "file_path");
|
|
45065
|
+
const input = {
|
|
45066
|
+
new_string: newString
|
|
45067
|
+
};
|
|
45068
|
+
if (filePath != null) input.file_path = filePath;
|
|
45069
|
+
if (oldString != null) input.old_string = oldString;
|
|
45070
|
+
return input;
|
|
45071
|
+
}
|
|
45072
|
+
return null;
|
|
45073
|
+
}
|
|
44951
45074
|
function recordAssistantContextUsage(proc, am2) {
|
|
44952
45075
|
const u = am2.message?.usage;
|
|
44953
45076
|
if (!u) return;
|
|
@@ -45015,6 +45138,45 @@ function cleanupPlanMode(proc, emit, base, reason) {
|
|
|
45015
45138
|
});
|
|
45016
45139
|
proc.planModeActive = false;
|
|
45017
45140
|
}
|
|
45141
|
+
function extractAssistantTextParts(content, depth = 0) {
|
|
45142
|
+
if (depth > 4) return [];
|
|
45143
|
+
if (typeof content === "string") return [content];
|
|
45144
|
+
if (Array.isArray(content)) {
|
|
45145
|
+
return content.flatMap((item) => extractAssistantTextParts(item, depth + 1));
|
|
45146
|
+
}
|
|
45147
|
+
if (typeof content !== "object" || content === null) return [];
|
|
45148
|
+
const block = content;
|
|
45149
|
+
const type = typeof block.type === "string" ? block.type : null;
|
|
45150
|
+
if (type === "tool_use" || type === "tool_result") return [];
|
|
45151
|
+
if (type === "text" || type === "output_text" || type == null) {
|
|
45152
|
+
const textParts = extractAssistantTextParts(block.text, depth + 1);
|
|
45153
|
+
if (textParts.length > 0) return textParts;
|
|
45154
|
+
return extractAssistantTextParts(block.content, depth + 1);
|
|
45155
|
+
}
|
|
45156
|
+
return [];
|
|
45157
|
+
}
|
|
45158
|
+
function describeAssistantContent(content) {
|
|
45159
|
+
if (Array.isArray(content)) {
|
|
45160
|
+
return {
|
|
45161
|
+
contentShape: "array",
|
|
45162
|
+
blockTypes: content.map((item) => {
|
|
45163
|
+
if (typeof item !== "object" || item === null) return typeof item;
|
|
45164
|
+
const type = item.type;
|
|
45165
|
+
return typeof type === "string" ? type : "(no-type)";
|
|
45166
|
+
}).slice(0, 12)
|
|
45167
|
+
};
|
|
45168
|
+
}
|
|
45169
|
+
if (typeof content === "object" && content !== null) {
|
|
45170
|
+
return {
|
|
45171
|
+
contentShape: "object",
|
|
45172
|
+
contentKeys: Object.keys(content).slice(0, 12)
|
|
45173
|
+
};
|
|
45174
|
+
}
|
|
45175
|
+
return { contentShape: typeof content };
|
|
45176
|
+
}
|
|
45177
|
+
function scopeLogLabel(scope) {
|
|
45178
|
+
return scope.kind === "single" ? "single" : scope.groupId;
|
|
45179
|
+
}
|
|
45018
45180
|
function getTaskBase(proc) {
|
|
45019
45181
|
if (proc.currentTask) {
|
|
45020
45182
|
return {
|
|
@@ -45024,10 +45186,42 @@ function getTaskBase(proc) {
|
|
|
45024
45186
|
replyMessageId: proc.currentTask.replyMessageId
|
|
45025
45187
|
};
|
|
45026
45188
|
}
|
|
45189
|
+
const continuation = proc.postMergeContinuationTask;
|
|
45190
|
+
const continuationUntil = proc.postMergeContinuationUntil ?? 0;
|
|
45191
|
+
if (continuation) {
|
|
45192
|
+
if (Date.now() <= continuationUntil) {
|
|
45193
|
+
proc.currentTask = continuation;
|
|
45194
|
+
proc.status = "working";
|
|
45195
|
+
proc.currentTaskStartedAt = Date.now();
|
|
45196
|
+
delete proc.postMergeContinuationTask;
|
|
45197
|
+
delete proc.postMergeContinuationUntil;
|
|
45198
|
+
logger7.info("SDK post-merge continuation routed to merged task", {
|
|
45199
|
+
agentId: proc.agentId,
|
|
45200
|
+
scope: scopeLogLabel(proc.scope),
|
|
45201
|
+
replyMessageId: continuation.replyMessageId,
|
|
45202
|
+
conversationId: continuation.conversationId,
|
|
45203
|
+
traceId: continuation.traceId
|
|
45204
|
+
});
|
|
45205
|
+
return {
|
|
45206
|
+
agentId: proc.agentId,
|
|
45207
|
+
conversationId: continuation.conversationId,
|
|
45208
|
+
traceId: continuation.traceId,
|
|
45209
|
+
replyMessageId: continuation.replyMessageId
|
|
45210
|
+
};
|
|
45211
|
+
}
|
|
45212
|
+
logger7.info("SDK post-merge continuation route expired", {
|
|
45213
|
+
agentId: proc.agentId,
|
|
45214
|
+
scope: scopeLogLabel(proc.scope),
|
|
45215
|
+
replyMessageId: continuation.replyMessageId,
|
|
45216
|
+
routeUntil: new Date(continuationUntil).toISOString()
|
|
45217
|
+
});
|
|
45218
|
+
delete proc.postMergeContinuationTask;
|
|
45219
|
+
delete proc.postMergeContinuationUntil;
|
|
45220
|
+
}
|
|
45027
45221
|
if (!proc.cachedConversationId) {
|
|
45028
45222
|
logger7.warn("SDK self-initiated turn without cachedConversationId; dropping", {
|
|
45029
45223
|
agentId: proc.agentId,
|
|
45030
|
-
scope: proc.scope
|
|
45224
|
+
scope: scopeLogLabel(proc.scope)
|
|
45031
45225
|
});
|
|
45032
45226
|
return null;
|
|
45033
45227
|
}
|
|
@@ -45044,7 +45238,7 @@ function getTaskBase(proc) {
|
|
|
45044
45238
|
proc.currentTaskStartedAt = Date.now();
|
|
45045
45239
|
logger7.info("Cron-initiated turn detected, synthesized task", {
|
|
45046
45240
|
agentId: proc.agentId,
|
|
45047
|
-
scope: proc.scope
|
|
45241
|
+
scope: scopeLogLabel(proc.scope),
|
|
45048
45242
|
replyMessageId,
|
|
45049
45243
|
conversationId: proc.cachedConversationId,
|
|
45050
45244
|
traceId
|
|
@@ -45105,6 +45299,97 @@ function extractTodosFromInput(input) {
|
|
|
45105
45299
|
}
|
|
45106
45300
|
return out;
|
|
45107
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
|
+
}
|
|
45108
45393
|
function countByStatus(todos) {
|
|
45109
45394
|
const c2 = {
|
|
45110
45395
|
pending: 0,
|
|
@@ -45288,6 +45573,17 @@ function mapSDKMessage(proc, message, rawEmit, sessionStore, onCompleted) {
|
|
|
45288
45573
|
const partial2 = delta.partial_json;
|
|
45289
45574
|
if (typeof partial2 === "string") {
|
|
45290
45575
|
proc.accumulatedToolInput += partial2;
|
|
45576
|
+
const liveInput = extractLiveToolInput(proc.currentToolName, proc.accumulatedToolInput);
|
|
45577
|
+
if (liveInput && proc.currentToolName != null) {
|
|
45578
|
+
emit({
|
|
45579
|
+
type: "agent:tool_input_update",
|
|
45580
|
+
payload: {
|
|
45581
|
+
...wireBase(base),
|
|
45582
|
+
toolName: proc.currentToolName,
|
|
45583
|
+
input: liveInput
|
|
45584
|
+
}
|
|
45585
|
+
});
|
|
45586
|
+
}
|
|
45291
45587
|
}
|
|
45292
45588
|
} else if (delta.type === "text_delta" && typeof delta.text === "string") {
|
|
45293
45589
|
if (proc.accumulatedText.length === 0) {
|
|
@@ -45342,6 +45638,16 @@ function mapSDKMessage(proc, message, rawEmit, sessionStore, onCompleted) {
|
|
|
45342
45638
|
if (lastToolUse && lastToolUse.type === "tool_use") {
|
|
45343
45639
|
lastToolUse.input = parsedInput;
|
|
45344
45640
|
}
|
|
45641
|
+
if (proc.currentToolName != null && LIVE_INPUT_PREVIEW_TOOLS.has(proc.currentToolName) && Object.keys(parsedInput).length > 0) {
|
|
45642
|
+
emit({
|
|
45643
|
+
type: "agent:tool_input_update",
|
|
45644
|
+
payload: {
|
|
45645
|
+
...wireBase(base),
|
|
45646
|
+
toolName: proc.currentToolName,
|
|
45647
|
+
input: parsedInput
|
|
45648
|
+
}
|
|
45649
|
+
});
|
|
45650
|
+
}
|
|
45345
45651
|
if (proc.currentToolName === "TodoWrite") {
|
|
45346
45652
|
const todos = extractTodosFromInput(parsedInput);
|
|
45347
45653
|
if (todos) {
|
|
@@ -45377,6 +45683,28 @@ function mapSDKMessage(proc, message, rawEmit, sessionStore, onCompleted) {
|
|
|
45377
45683
|
});
|
|
45378
45684
|
}
|
|
45379
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
|
+
}
|
|
45380
45708
|
if (proc.currentToolName === "AskUserQuestion") {
|
|
45381
45709
|
const last = proc.contentBlocks[proc.contentBlocks.length - 1];
|
|
45382
45710
|
if (last?.type === "tool_use" && last.toolName === "AskUserQuestion") {
|
|
@@ -45586,6 +45914,29 @@ function mapSDKMessage(proc, message, rawEmit, sessionStore, onCompleted) {
|
|
|
45586
45914
|
onCompleted();
|
|
45587
45915
|
break;
|
|
45588
45916
|
}
|
|
45917
|
+
if (proc.accumulatedText.length === 0 && proc.contentBlocks.length === 0) {
|
|
45918
|
+
cleanupPlanMode(proc, emit, base, "error");
|
|
45919
|
+
logger7.warn("SDK success produced empty assistant output; emitting agent:error", {
|
|
45920
|
+
agentId: proc.agentId,
|
|
45921
|
+
ackId: base.replyMessageId,
|
|
45922
|
+
tokenCount: usage.tokenCount,
|
|
45923
|
+
inputTokens: usage.inputTokens,
|
|
45924
|
+
cacheReadTokens: usage.cacheReadTokens,
|
|
45925
|
+
cacheCreationTokens: usage.cacheCreationTokens,
|
|
45926
|
+
assistantContent: proc.lastAssistantContentDescription,
|
|
45927
|
+
traceId: base.traceId
|
|
45928
|
+
});
|
|
45929
|
+
emit({
|
|
45930
|
+
type: "agent:error",
|
|
45931
|
+
payload: {
|
|
45932
|
+
...wireBase(base),
|
|
45933
|
+
error: "Agent \u8FD4\u56DE\u4E86\u7A7A\u7ED3\u679C\uFF0C\u5DF2\u963B\u6B62\u7A7A\u6D88\u606F\u8986\u76D6\u601D\u8003\u6C14\u6CE1\u3002\u8BF7\u91CD\u8BD5\uFF1B\u5982\u679C\u53CD\u590D\u51FA\u73B0\uFF0C\u8BF7\u68C0\u67E5 Claude Code \u767B\u5F55\u72B6\u6001\u6216\u6A21\u578B\u914D\u7F6E\u3002"
|
|
45934
|
+
}
|
|
45935
|
+
});
|
|
45936
|
+
resetAccumulators(proc);
|
|
45937
|
+
onCompleted();
|
|
45938
|
+
break;
|
|
45939
|
+
}
|
|
45589
45940
|
if (proc.accumulatedText) {
|
|
45590
45941
|
proc.contentBlocks.push({ type: "text", content: proc.accumulatedText });
|
|
45591
45942
|
}
|
|
@@ -45655,14 +46006,9 @@ function mapSDKMessage(proc, message, rawEmit, sessionStore, onCompleted) {
|
|
|
45655
46006
|
if (am2.isApiErrorMessage === true) {
|
|
45656
46007
|
const base = getTaskBase(proc);
|
|
45657
46008
|
if (!base) break;
|
|
45658
|
-
const errorTexts =
|
|
45659
|
-
for (const block of am2.message?.content ?? []) {
|
|
45660
|
-
if (block?.type === "text" && typeof block.text === "string") {
|
|
45661
|
-
errorTexts.push(block.text);
|
|
45662
|
-
}
|
|
45663
|
-
}
|
|
46009
|
+
const errorTexts = extractAssistantTextParts(am2.message?.content);
|
|
45664
46010
|
const errorText = errorTexts.join("\n").trim() || `SDK ${am2.error ?? "api_error"}`;
|
|
45665
|
-
const isAuthFail = am2.error
|
|
46011
|
+
const isAuthFail = isAuthFailureText(errorText, am2.error);
|
|
45666
46012
|
if (isAuthFail) {
|
|
45667
46013
|
sessionStore.delete(proc.agentId, proc.scope);
|
|
45668
46014
|
}
|
|
@@ -45674,7 +46020,7 @@ function mapSDKMessage(proc, message, rawEmit, sessionStore, onCompleted) {
|
|
|
45674
46020
|
isAuthFail,
|
|
45675
46021
|
traceId: base.traceId
|
|
45676
46022
|
});
|
|
45677
|
-
const friendlyError = isAuthFail ?
|
|
46023
|
+
const friendlyError = isAuthFail ? buildAuthFailureMessage(errorText) : errorText;
|
|
45678
46024
|
emit({
|
|
45679
46025
|
type: "agent:error",
|
|
45680
46026
|
payload: { ...wireBase(base), error: friendlyError }
|
|
@@ -45687,14 +46033,36 @@ function mapSDKMessage(proc, message, rawEmit, sessionStore, onCompleted) {
|
|
|
45687
46033
|
break;
|
|
45688
46034
|
}
|
|
45689
46035
|
if (proc.accumulatedText.length === 0 && proc.contentBlocks.length === 0) {
|
|
45690
|
-
const captured =
|
|
45691
|
-
for (const block of am2.message?.content ?? []) {
|
|
45692
|
-
if (block?.type === "text" && typeof block.text === "string") {
|
|
45693
|
-
captured.push(block.text);
|
|
45694
|
-
}
|
|
45695
|
-
}
|
|
46036
|
+
const captured = extractAssistantTextParts(am2.message?.content);
|
|
45696
46037
|
if (captured.length > 0) {
|
|
45697
46038
|
const text = captured.join("");
|
|
46039
|
+
if (isAuthFailureText(text, am2.error)) {
|
|
46040
|
+
const base = getTaskBase(proc);
|
|
46041
|
+
logger7.warn("SDK auth failure assistant detected without api-error flag, emitting agent:error", {
|
|
46042
|
+
agentId: proc.agentId,
|
|
46043
|
+
scope: proc.scope.kind === "single" ? "single" : proc.scope.groupId,
|
|
46044
|
+
sdkError: am2.error,
|
|
46045
|
+
errorText: text.slice(0, 200),
|
|
46046
|
+
traceId: base?.traceId,
|
|
46047
|
+
hasCurrentTask: base != null
|
|
46048
|
+
});
|
|
46049
|
+
if (base) {
|
|
46050
|
+
sessionStore.delete(proc.agentId, proc.scope);
|
|
46051
|
+
emit({
|
|
46052
|
+
type: "agent:error",
|
|
46053
|
+
payload: {
|
|
46054
|
+
...wireBase(base),
|
|
46055
|
+
error: buildAuthFailureMessage(text)
|
|
46056
|
+
}
|
|
46057
|
+
});
|
|
46058
|
+
proc.apiErrorEmitted = true;
|
|
46059
|
+
}
|
|
46060
|
+
proc.contentBlocks = [];
|
|
46061
|
+
proc.accumulatedText = "";
|
|
46062
|
+
proc.accumulatedThinking = "";
|
|
46063
|
+
proc.segmentBuffer = "";
|
|
46064
|
+
break;
|
|
46065
|
+
}
|
|
45698
46066
|
if (isContextOverflowText(text)) {
|
|
45699
46067
|
const base = getTaskBase(proc);
|
|
45700
46068
|
logger7.warn("SDK reported context overflow; auto-compact already failed inside SDK", {
|
|
@@ -45738,6 +46106,8 @@ function mapSDKMessage(proc, message, rawEmit, sessionStore, onCompleted) {
|
|
|
45738
46106
|
textLen: text.length,
|
|
45739
46107
|
textSample: text.slice(0, 100)
|
|
45740
46108
|
});
|
|
46109
|
+
} else {
|
|
46110
|
+
proc.lastAssistantContentDescription = describeAssistantContent(am2.message?.content);
|
|
45741
46111
|
}
|
|
45742
46112
|
}
|
|
45743
46113
|
break;
|
|
@@ -45761,6 +46131,7 @@ function resetAccumulators(proc) {
|
|
|
45761
46131
|
proc.accumulatedToolInput = "";
|
|
45762
46132
|
proc.apiErrorEmitted = false;
|
|
45763
46133
|
proc.peakContextUsage = void 0;
|
|
46134
|
+
proc.lastAssistantContentDescription = void 0;
|
|
45764
46135
|
}
|
|
45765
46136
|
|
|
45766
46137
|
// src/forkHistoryReplay.ts
|
|
@@ -45873,8 +46244,15 @@ var wsMetrics = new WsMetrics();
|
|
|
45873
46244
|
// src/agentManager.ts
|
|
45874
46245
|
var logger10 = createModuleLogger("agent.manager");
|
|
45875
46246
|
var NODE_USER_UID = 1e3;
|
|
46247
|
+
var POST_MERGE_CONTINUATION_ROUTE_MS = 15e3;
|
|
45876
46248
|
function isSmithAgent(agent) {
|
|
45877
|
-
|
|
46249
|
+
if (agent.id === SMITH_AGENT_ID) return true;
|
|
46250
|
+
if (agent.systemPrompt === SMITH_SYSTEM_PROMPT) return true;
|
|
46251
|
+
const prompt = agent.systemPrompt ?? "";
|
|
46252
|
+
if (prompt.includes("\u4F60\u662F\u7279\u5DE5\u53F2\u5BC6\u65AF") && prompt.includes("create_agent")) return true;
|
|
46253
|
+
const name = agent.name?.toLowerCase() ?? "";
|
|
46254
|
+
const role = agent.role?.toLowerCase() ?? "";
|
|
46255
|
+
return role === "system" && (name.includes("\u53F2\u5BC6\u65AF") || name.includes("smith"));
|
|
45878
46256
|
}
|
|
45879
46257
|
function isRunningAsRoot() {
|
|
45880
46258
|
try {
|
|
@@ -45883,6 +46261,13 @@ function isRunningAsRoot() {
|
|
|
45883
46261
|
return false;
|
|
45884
46262
|
}
|
|
45885
46263
|
}
|
|
46264
|
+
async function chownForRootSpawn(targetPath, target) {
|
|
46265
|
+
try {
|
|
46266
|
+
await fs4.chown(targetPath, NODE_USER_UID, NODE_USER_UID);
|
|
46267
|
+
} catch (error51) {
|
|
46268
|
+
logger10.error("Best-effort root chown failed", { error: error51, target, path: targetPath });
|
|
46269
|
+
}
|
|
46270
|
+
}
|
|
45886
46271
|
function readCronLockSnapshot() {
|
|
45887
46272
|
try {
|
|
45888
46273
|
const lockPath2 = path8.join(os5.homedir(), ".claude", "scheduled_tasks.lock");
|
|
@@ -45991,14 +46376,57 @@ var AgentManager = class {
|
|
|
45991
46376
|
this.queryFn = QA$;
|
|
45992
46377
|
return this.queryFn;
|
|
45993
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
|
+
}
|
|
45994
46403
|
fallbackCwd(agentConfig, scope, requestedCwd) {
|
|
45995
46404
|
const normalized = requestedCwd.trim();
|
|
46405
|
+
const ahchatSuffix = this.extractAhchatWorkspaceSuffix(normalized);
|
|
46406
|
+
if (ahchatSuffix) {
|
|
46407
|
+
return path8.join(this.workspacesDir, ahchatSuffix);
|
|
46408
|
+
}
|
|
45996
46409
|
const basename = normalized ? path8.basename(path8.normalize(normalized)) : "";
|
|
45997
46410
|
const suffix = basename && basename !== "." && basename !== path8.sep ? basename : scope.kind === "group" ? `Group-${scope.groupId}` : agentConfig.id;
|
|
45998
46411
|
return path8.join(this.workspacesDir, suffix);
|
|
45999
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
|
+
}
|
|
46000
46428
|
async resolveRuntimeCwd(agentConfig, scope, requestedCwd) {
|
|
46001
|
-
let cwd = requestedCwd;
|
|
46429
|
+
let cwd = this.remapServerWorkspaceCwd(agentConfig, scope, requestedCwd);
|
|
46002
46430
|
if (isRunningAsRoot() && cwd.startsWith("/root/")) {
|
|
46003
46431
|
cwd = this.fallbackCwd(agentConfig, scope, cwd);
|
|
46004
46432
|
}
|
|
@@ -46631,19 +47059,10 @@ Do NOT use "..." as content \u2014 write specific, project-relevant content.`;
|
|
|
46631
47059
|
options.resume = savedSessionId;
|
|
46632
47060
|
}
|
|
46633
47061
|
if (isRunningAsRoot()) {
|
|
46634
|
-
|
|
46635
|
-
|
|
46636
|
-
} catch {
|
|
46637
|
-
}
|
|
46638
|
-
try {
|
|
46639
|
-
await fs4.chown(agentCwd, NODE_USER_UID, NODE_USER_UID);
|
|
46640
|
-
} catch {
|
|
46641
|
-
}
|
|
47062
|
+
await chownForRootSpawn(effectiveConfigDir, "configDir");
|
|
47063
|
+
await chownForRootSpawn(agentCwd, "agentCwd");
|
|
46642
47064
|
const settingsFilePath = path8.join(effectiveConfigDir, "settings.json");
|
|
46643
|
-
|
|
46644
|
-
await fs4.chown(settingsFilePath, NODE_USER_UID, NODE_USER_UID);
|
|
46645
|
-
} catch {
|
|
46646
|
-
}
|
|
47065
|
+
await chownForRootSpawn(settingsFilePath, "settingsFile");
|
|
46647
47066
|
options.spawnClaudeCodeProcess = (spawnOptions) => {
|
|
46648
47067
|
const env2 = { ...spawnOptions.env, HOME: "/home/node" };
|
|
46649
47068
|
return nodeSpawn(spawnOptions.command, spawnOptions.args, {
|
|
@@ -46809,7 +47228,7 @@ ${trimmed}`;
|
|
|
46809
47228
|
lines.push(` workdir: ${currentCwd}`);
|
|
46810
47229
|
} else {
|
|
46811
47230
|
const a = this.agentRegistry?.getById(agentId);
|
|
46812
|
-
const singleCwd = a?.workingDirectory || path8.join(
|
|
47231
|
+
const singleCwd = a?.workingDirectory || path8.join(this.workspacesDir, agentId);
|
|
46813
47232
|
lines.push(` workdir: ${singleCwd}`);
|
|
46814
47233
|
}
|
|
46815
47234
|
let rosterCount = 0;
|
|
@@ -46821,7 +47240,7 @@ ${trimmed}`;
|
|
|
46821
47240
|
if (key === curKey) {
|
|
46822
47241
|
lines.push(` workdir: ${currentCwd}`);
|
|
46823
47242
|
} else {
|
|
46824
|
-
const groupCwd =
|
|
47243
|
+
const groupCwd = g2.workingDirectory || path8.join(this.workspacesDir, g2.groupId);
|
|
46825
47244
|
lines.push(` workdir: ${groupCwd}`);
|
|
46826
47245
|
}
|
|
46827
47246
|
const others = g2.members.filter((id) => id !== agentId).map((id) => {
|
|
@@ -47168,6 +47587,16 @@ ${lines.join("\n")}`;
|
|
|
47168
47587
|
}
|
|
47169
47588
|
}
|
|
47170
47589
|
async dispatchToSDK(runtime, task) {
|
|
47590
|
+
if (runtime.postMergeContinuationTask) {
|
|
47591
|
+
logger10.info("Clearing stale post-merge continuation route before explicit dispatch", {
|
|
47592
|
+
agentId: runtime.agentId,
|
|
47593
|
+
staleReplyMessageId: runtime.postMergeContinuationTask.replyMessageId,
|
|
47594
|
+
nextReplyMessageId: task.replyMessageId,
|
|
47595
|
+
traceId: task.traceId
|
|
47596
|
+
});
|
|
47597
|
+
delete runtime.postMergeContinuationTask;
|
|
47598
|
+
delete runtime.postMergeContinuationUntil;
|
|
47599
|
+
}
|
|
47171
47600
|
await this.applyEffortMode(runtime, "high", {
|
|
47172
47601
|
source: "dispatchToSDK",
|
|
47173
47602
|
replyMessageId: task.replyMessageId
|
|
@@ -47376,6 +47805,19 @@ ${lines.join("\n")}`;
|
|
|
47376
47805
|
}
|
|
47377
47806
|
});
|
|
47378
47807
|
}
|
|
47808
|
+
const continuationTask = mergedBatch.at(-1);
|
|
47809
|
+
if (continuationTask) {
|
|
47810
|
+
proc.postMergeContinuationTask = continuationTask;
|
|
47811
|
+
proc.postMergeContinuationUntil = Date.now() + POST_MERGE_CONTINUATION_ROUTE_MS;
|
|
47812
|
+
logger10.info("Armed SDK post-merge continuation routing", {
|
|
47813
|
+
agentId: proc.agentId,
|
|
47814
|
+
carrierReplyMessageId: completedTask.replyMessageId,
|
|
47815
|
+
continuationReplyMessageId: continuationTask.replyMessageId,
|
|
47816
|
+
mergedCount: mergedBatch.length,
|
|
47817
|
+
routeUntil: new Date(proc.postMergeContinuationUntil).toISOString(),
|
|
47818
|
+
traceId: completedTask.traceId
|
|
47819
|
+
});
|
|
47820
|
+
}
|
|
47379
47821
|
runtime.mergedTasks = [];
|
|
47380
47822
|
} else if (runtime.mergedTasks.length > 0) {
|
|
47381
47823
|
logger10.warn("mergedTasks non-empty but no currentTask; dropping", {
|
|
@@ -50117,6 +50559,13 @@ import { execFileSync, execSync, spawnSync } from "child_process";
|
|
|
50117
50559
|
import { accessSync, constants as constants2 } from "fs";
|
|
50118
50560
|
import { join as join2 } from "path";
|
|
50119
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
|
+
}
|
|
50120
50569
|
function detectClaudeCli() {
|
|
50121
50570
|
try {
|
|
50122
50571
|
return execFileSync("claude", ["--version"], { timeout: 1e4 }).toString().trim();
|
|
@@ -50145,9 +50594,18 @@ function resolveClaudeBinary() {
|
|
|
50145
50594
|
if (first) return first;
|
|
50146
50595
|
} catch {
|
|
50147
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() {
|
|
50148
50606
|
const bin = getNpmGlobalBin();
|
|
50149
|
-
if (bin)
|
|
50150
|
-
|
|
50607
|
+
if (!bin) return void 0;
|
|
50608
|
+
for (const candidate of getNpmClaudeCandidates(bin)) {
|
|
50151
50609
|
try {
|
|
50152
50610
|
accessSync(candidate, constants2.X_OK);
|
|
50153
50611
|
return candidate;
|
|
@@ -50157,9 +50615,30 @@ function resolveClaudeBinary() {
|
|
|
50157
50615
|
return void 0;
|
|
50158
50616
|
}
|
|
50159
50617
|
function detectViaNpmBin() {
|
|
50160
|
-
const
|
|
50161
|
-
if (!
|
|
50162
|
-
|
|
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));
|
|
50163
50642
|
for (const p of candidates) {
|
|
50164
50643
|
try {
|
|
50165
50644
|
accessSync(p, constants2.X_OK);
|
|
@@ -50173,7 +50652,7 @@ function installClaudeCli() {
|
|
|
50173
50652
|
logger24.info("Installing Claude Code CLI via npm...");
|
|
50174
50653
|
const result = spawnSync("npm", ["install", "-g", "@anthropic-ai/claude-code"], {
|
|
50175
50654
|
stdio: "inherit",
|
|
50176
|
-
timeout:
|
|
50655
|
+
timeout: getInstallTimeoutMs()
|
|
50177
50656
|
});
|
|
50178
50657
|
if (result.error) {
|
|
50179
50658
|
logger24.error("npm install -g failed (spawn error)", {
|
|
@@ -50188,9 +50667,9 @@ function installClaudeCli() {
|
|
|
50188
50667
|
return void 0;
|
|
50189
50668
|
}
|
|
50190
50669
|
logger24.info("npm install -g completed, checking for claude binary...");
|
|
50191
|
-
const viaPath =
|
|
50670
|
+
const viaPath = detectVersionFromResolvedCandidates();
|
|
50192
50671
|
if (viaPath) {
|
|
50193
|
-
logger24.info("claude detected
|
|
50672
|
+
logger24.info("claude detected after install", { version: viaPath });
|
|
50194
50673
|
return viaPath;
|
|
50195
50674
|
}
|
|
50196
50675
|
const viaBin = detectViaNpmBin();
|
|
@@ -50208,14 +50687,13 @@ function installClaudeCli() {
|
|
|
50208
50687
|
return void 0;
|
|
50209
50688
|
}
|
|
50210
50689
|
async function ensureClaudeCli() {
|
|
50211
|
-
let
|
|
50212
|
-
if (
|
|
50213
|
-
|
|
50214
|
-
|
|
50215
|
-
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;
|
|
50216
50694
|
}
|
|
50217
50695
|
process.stderr.write("\n\u26A0 Claude Code CLI (`claude`) not found. Attempting auto-install...\n\n");
|
|
50218
|
-
version2 = installClaudeCli();
|
|
50696
|
+
const version2 = installClaudeCli();
|
|
50219
50697
|
if (!version2) {
|
|
50220
50698
|
const npmBin = getNpmGlobalBin();
|
|
50221
50699
|
process.stderr.write(
|
|
@@ -50226,9 +50704,9 @@ async function ensureClaudeCli() {
|
|
|
50226
50704
|
);
|
|
50227
50705
|
process.exit(1);
|
|
50228
50706
|
}
|
|
50229
|
-
|
|
50230
|
-
logger24.info("Claude Code CLI ready", { version: version2, path:
|
|
50231
|
-
return
|
|
50707
|
+
detected = detectResolvedClaudeCli();
|
|
50708
|
+
logger24.info("Claude Code CLI ready", { version: version2, path: detected?.path ?? null });
|
|
50709
|
+
return detected?.path;
|
|
50232
50710
|
}
|
|
50233
50711
|
|
|
50234
50712
|
// src/forkAgentFiles.ts
|
|
@@ -50665,6 +51143,7 @@ Bridge token (register this machine at Settings \u2192 \u5DF2\u8FDE\u63A5\u7684\
|
|
|
50665
51143
|
agentRegistry,
|
|
50666
51144
|
subscriptionRegistry,
|
|
50667
51145
|
serverApiUrl: config2.serverApiUrl,
|
|
51146
|
+
bridgeToken: config2.bridgeToken,
|
|
50668
51147
|
dataDir: config2.dataDir
|
|
50669
51148
|
});
|
|
50670
51149
|
const taskDispatchHandler = createTaskDispatchHandler(agentManager, agentRegistry, emit);
|