@wowyuarm/dsh-agent-team 0.1.0

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 (125) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +103 -0
  3. package/README.zh.md +103 -0
  4. package/cordis.patch.yml +36 -0
  5. package/package.json +152 -0
  6. package/packages/agent-team/README.md +58 -0
  7. package/packages/agent-team/README.zh.md +57 -0
  8. package/packages/agent-team/lib/index.js +841 -0
  9. package/packages/agent-team/lib/invariant.js +24 -0
  10. package/packages/agent-team/lib/ledger.js +2161 -0
  11. package/packages/agent-team/lib/member-context.js +69 -0
  12. package/packages/agent-team/lib/preset-roster.js +14 -0
  13. package/packages/agent-team/lib/spec.js +347 -0
  14. package/packages/agent-team/lib/typert.host.d.ts +3 -0
  15. package/packages/agent-team/lib/typert.host.js +2084 -0
  16. package/packages/agent-team/lib/typert.remote-client.d.ts +54 -0
  17. package/packages/agent-team/lib/typert.remote-client.d.ts.map +1 -0
  18. package/packages/agent-team/lib/typert.remote-client.js +1218 -0
  19. package/packages/agent-team/lib/types/index.d.ts +156 -0
  20. package/packages/agent-team/lib/types/index.d.ts.map +1 -0
  21. package/packages/agent-team/lib/types/invariant.d.ts +13 -0
  22. package/packages/agent-team/lib/types/invariant.d.ts.map +1 -0
  23. package/packages/agent-team/lib/types/ledger.d.ts +271 -0
  24. package/packages/agent-team/lib/types/ledger.d.ts.map +1 -0
  25. package/packages/agent-team/lib/types/member-context.d.ts +7 -0
  26. package/packages/agent-team/lib/types/member-context.d.ts.map +1 -0
  27. package/packages/agent-team/lib/types/preset-roster.d.ts +5 -0
  28. package/packages/agent-team/lib/types/preset-roster.d.ts.map +1 -0
  29. package/packages/agent-team/lib/types/spec.d.ts +13 -0
  30. package/packages/agent-team/lib/types/spec.d.ts.map +1 -0
  31. package/packages/agent-team/lib/types/types.d.ts +818 -0
  32. package/packages/agent-team/lib/types/types.d.ts.map +1 -0
  33. package/packages/agent-team/lib/types.js +1 -0
  34. package/packages/agent-team/preset/team-member/agent.cordis.yml +89 -0
  35. package/packages/client-agent-team/README.md +39 -0
  36. package/packages/client-agent-team/README.zh.md +39 -0
  37. package/packages/client-agent-team/lib/client.js +9633 -0
  38. package/packages/client-agent-team/lib/client.js.map +1 -0
  39. package/packages/client-agent-team/lib/index.js +5 -0
  40. package/packages/client-agent-team/lib/types/client/TeamAgentsPanel.d.ts +20 -0
  41. package/packages/client-agent-team/lib/types/client/TeamAgentsPanel.d.ts.map +1 -0
  42. package/packages/client-agent-team/lib/types/client/TeamAgentsPanel.js +274 -0
  43. package/packages/client-agent-team/lib/types/client/TeamChannelPage.d.ts +19 -0
  44. package/packages/client-agent-team/lib/types/client/TeamChannelPage.d.ts.map +1 -0
  45. package/packages/client-agent-team/lib/types/client/TeamChannelPage.js +243 -0
  46. package/packages/client-agent-team/lib/types/client/TeamChannelsPanel.d.ts +21 -0
  47. package/packages/client-agent-team/lib/types/client/TeamChannelsPanel.d.ts.map +1 -0
  48. package/packages/client-agent-team/lib/types/client/TeamChannelsPanel.js +196 -0
  49. package/packages/client-agent-team/lib/types/client/TeamComposer.d.ts +15 -0
  50. package/packages/client-agent-team/lib/types/client/TeamComposer.d.ts.map +1 -0
  51. package/packages/client-agent-team/lib/types/client/TeamComposer.js +144 -0
  52. package/packages/client-agent-team/lib/types/client/TeamConversation.d.ts +3 -0
  53. package/packages/client-agent-team/lib/types/client/TeamConversation.d.ts.map +1 -0
  54. package/packages/client-agent-team/lib/types/client/TeamConversation.js +20 -0
  55. package/packages/client-agent-team/lib/types/client/TeamFooterAction.d.ts +3 -0
  56. package/packages/client-agent-team/lib/types/client/TeamFooterAction.d.ts.map +1 -0
  57. package/packages/client-agent-team/lib/types/client/TeamFooterAction.js +19 -0
  58. package/packages/client-agent-team/lib/types/client/TeamInboxPanel.d.ts +13 -0
  59. package/packages/client-agent-team/lib/types/client/TeamInboxPanel.d.ts.map +1 -0
  60. package/packages/client-agent-team/lib/types/client/TeamInboxPanel.js +90 -0
  61. package/packages/client-agent-team/lib/types/client/TeamMemberAvatar.d.ts +12 -0
  62. package/packages/client-agent-team/lib/types/client/TeamMemberAvatar.d.ts.map +1 -0
  63. package/packages/client-agent-team/lib/types/client/TeamMemberAvatar.js +15 -0
  64. package/packages/client-agent-team/lib/types/client/TeamMembersAction.d.ts +5 -0
  65. package/packages/client-agent-team/lib/types/client/TeamMembersAction.d.ts.map +1 -0
  66. package/packages/client-agent-team/lib/types/client/TeamMembersAction.js +32 -0
  67. package/packages/client-agent-team/lib/types/client/TeamMessage.d.ts +19 -0
  68. package/packages/client-agent-team/lib/types/client/TeamMessage.d.ts.map +1 -0
  69. package/packages/client-agent-team/lib/types/client/TeamMessage.js +24 -0
  70. package/packages/client-agent-team/lib/types/client/TeamPresenceDot.d.ts +11 -0
  71. package/packages/client-agent-team/lib/types/client/TeamPresenceDot.d.ts.map +1 -0
  72. package/packages/client-agent-team/lib/types/client/TeamPresenceDot.js +20 -0
  73. package/packages/client-agent-team/lib/types/client/TeamRowMenu.d.ts +15 -0
  74. package/packages/client-agent-team/lib/types/client/TeamRowMenu.d.ts.map +1 -0
  75. package/packages/client-agent-team/lib/types/client/TeamRowMenu.js +23 -0
  76. package/packages/client-agent-team/lib/types/client/TeamSettings.d.ts +3 -0
  77. package/packages/client-agent-team/lib/types/client/TeamSettings.d.ts.map +1 -0
  78. package/packages/client-agent-team/lib/types/client/TeamSettings.js +5 -0
  79. package/packages/client-agent-team/lib/types/client/TeamSidebarSection.d.ts +9 -0
  80. package/packages/client-agent-team/lib/types/client/TeamSidebarSection.d.ts.map +1 -0
  81. package/packages/client-agent-team/lib/types/client/TeamSidebarSection.js +9 -0
  82. package/packages/client-agent-team/lib/types/client/TeamThreadPage.d.ts +22 -0
  83. package/packages/client-agent-team/lib/types/client/TeamThreadPage.d.ts.map +1 -0
  84. package/packages/client-agent-team/lib/types/client/TeamThreadPage.js +464 -0
  85. package/packages/client-agent-team/lib/types/client/TeamWorkspaceBrowser.d.ts +3 -0
  86. package/packages/client-agent-team/lib/types/client/TeamWorkspaceBrowser.d.ts.map +1 -0
  87. package/packages/client-agent-team/lib/types/client/TeamWorkspaceBrowser.js +39 -0
  88. package/packages/client-agent-team/lib/types/client/TeamWorkspaceRow.d.ts +11 -0
  89. package/packages/client-agent-team/lib/types/client/TeamWorkspaceRow.d.ts.map +1 -0
  90. package/packages/client-agent-team/lib/types/client/TeamWorkspaceRow.js +6 -0
  91. package/packages/client-agent-team/lib/types/client/index.d.ts +19 -0
  92. package/packages/client-agent-team/lib/types/client/index.d.ts.map +1 -0
  93. package/packages/client-agent-team/lib/types/client/index.js +113 -0
  94. package/packages/client-agent-team/lib/types/client/locales.d.ts +224 -0
  95. package/packages/client-agent-team/lib/types/client/locales.d.ts.map +1 -0
  96. package/packages/client-agent-team/lib/types/client/locales.js +222 -0
  97. package/packages/client-agent-team/lib/types/client/navigation.d.ts +39 -0
  98. package/packages/client-agent-team/lib/types/client/navigation.d.ts.map +1 -0
  99. package/packages/client-agent-team/lib/types/client/navigation.js +96 -0
  100. package/packages/client-agent-team/lib/types/client/slots.d.ts +74 -0
  101. package/packages/client-agent-team/lib/types/client/slots.d.ts.map +1 -0
  102. package/packages/client-agent-team/lib/types/client/slots.js +1 -0
  103. package/packages/client-agent-team/lib/types/client/team-changes.d.ts +28 -0
  104. package/packages/client-agent-team/lib/types/client/team-changes.d.ts.map +1 -0
  105. package/packages/client-agent-team/lib/types/client/team-changes.js +70 -0
  106. package/packages/client-agent-team/lib/types/client/team-formatters.d.ts +53 -0
  107. package/packages/client-agent-team/lib/types/client/team-formatters.d.ts.map +1 -0
  108. package/packages/client-agent-team/lib/types/client/team-formatters.js +128 -0
  109. package/packages/client-agent-team/lib/types/client/team-membership.d.ts +25 -0
  110. package/packages/client-agent-team/lib/types/client/team-membership.d.ts.map +1 -0
  111. package/packages/client-agent-team/lib/types/client/team-membership.js +39 -0
  112. package/packages/client-agent-team/lib/types/client/team-separators.d.ts +23 -0
  113. package/packages/client-agent-team/lib/types/client/team-separators.d.ts.map +1 -0
  114. package/packages/client-agent-team/lib/types/client/team-separators.js +52 -0
  115. package/packages/client-agent-team/lib/types/client/timeline-scroll.d.ts +18 -0
  116. package/packages/client-agent-team/lib/types/client/timeline-scroll.d.ts.map +1 -0
  117. package/packages/client-agent-team/lib/types/client/timeline-scroll.js +54 -0
  118. package/packages/client-agent-team/lib/types/index.d.ts +3 -0
  119. package/packages/client-agent-team/lib/types/index.d.ts.map +1 -0
  120. package/packages/client-agent-team/lib/types/index.js +2 -0
  121. package/packages/tool-agent-team/README.md +23 -0
  122. package/packages/tool-agent-team/README.zh.md +23 -0
  123. package/packages/tool-agent-team/lib/index.js +294 -0
  124. package/packages/tool-agent-team/lib/types/index.d.ts +5 -0
  125. package/packages/tool-agent-team/lib/types/index.d.ts.map +1 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"timeline-scroll.d.ts","sourceRoot":"","sources":["../../../src/client/timeline-scroll.ts"],"names":[],"mappings":"AAKA,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,GAAG,EAAE,KAAK,CAAC,SAAS,CAAC,WAAW,CAAC,CAAA;IAC1C,QAAQ,EAAE,MAAM,IAAI,CAAA;IACpB,gFAAgF;IAChF,QAAQ,EAAE,MAAM,OAAO,CAAA;IACvB,qEAAqE;IACrE,cAAc,EAAE,MAAM,IAAI,CAAA;IAC1B,0DAA0D;IAC1D,YAAY,EAAE,MAAM,IAAI,CAAA;CACzB;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,UAAU,EAAE,MAAM,GAAG,cAAc,CA+CpE"}
@@ -0,0 +1,54 @@
1
+ import { useCallback, useEffect, useRef } from 'react';
2
+ const BOTTOM_MARGIN_PX = 48;
3
+ const BOUNDARY_OFFSET_PX = 12;
4
+ /**
5
+ * Chat-timeline scroll policy shared by the Channel and Thread pages: follow
6
+ * new facts only while the reader stays pinned to the bottom, keep prepended
7
+ * history visually stable, and honor explicit jump requests exactly once per
8
+ * content commit. The content key must change whenever rendered facts change.
9
+ */
10
+ export function useTimelineScroll(contentKey) {
11
+ const ref = useRef(null);
12
+ const pinnedRef = useRef(true);
13
+ const heightRef = useRef(0);
14
+ const jumpRef = useRef();
15
+ const onScroll = useCallback(() => {
16
+ const element = ref.current;
17
+ if (element === null)
18
+ return;
19
+ pinnedRef.current = element.scrollHeight - element.scrollTop - element.clientHeight < BOTTOM_MARGIN_PX;
20
+ }, []);
21
+ const jumpToBoundary = useCallback(() => {
22
+ jumpRef.current = 'boundary';
23
+ pinnedRef.current = false;
24
+ }, []);
25
+ const jumpToLatest = useCallback(() => {
26
+ jumpRef.current = 'latest';
27
+ pinnedRef.current = true;
28
+ }, []);
29
+ useEffect(() => {
30
+ const element = ref.current;
31
+ if (element === null)
32
+ return;
33
+ const previousHeight = heightRef.current;
34
+ heightRef.current = element.scrollHeight;
35
+ const jump = jumpRef.current;
36
+ jumpRef.current = undefined;
37
+ if (jump === 'boundary') {
38
+ const marker = element.querySelector('[data-thread-boundary]');
39
+ if (marker !== null) {
40
+ element.scrollTop += marker.getBoundingClientRect().top - element.getBoundingClientRect().top - BOUNDARY_OFFSET_PX;
41
+ return;
42
+ }
43
+ }
44
+ if (jump === 'latest' || pinnedRef.current) {
45
+ element.scrollTop = element.scrollHeight;
46
+ return;
47
+ }
48
+ // Prepended older history must not shift the content the reader is on.
49
+ if (previousHeight > 0 && element.scrollHeight > previousHeight) {
50
+ element.scrollTop += element.scrollHeight - previousHeight;
51
+ }
52
+ }, [contentKey]);
53
+ return { ref, onScroll, isPinned: () => pinnedRef.current, jumpToBoundary, jumpToLatest };
54
+ }
@@ -0,0 +1,3 @@
1
+ /** Host half: the Team UI has no Node-side behavior. */
2
+ export declare function apply(): void;
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,wDAAwD;AACxD,wBAAgB,KAAK,IAAI,IAAI,CAAG"}
@@ -0,0 +1,2 @@
1
+ /** Host half: the Team UI has no Node-side behavior. */
2
+ export function apply() { }
@@ -0,0 +1,23 @@
1
+ # @wowyuarm/dsh-agent-team/tools
2
+
3
+ English | [中文](README.zh.md)
4
+
5
+ Model-facing tools for Agent Team Members. The package registers tools in the calling Agent preset scope and does not provide or replace Host services.
6
+
7
+ ## Tools
8
+
9
+ - `team_inbox` lists bounded unread Thread summaries for the calling Member, ordered by direct work and then recency.
10
+ - `team_thread` reads a Thread, pages history, follows, or unfollows. `read` atomically returns the Task anchor, current Task and Claim snapshot, bounded orientation facts, and one contiguous unread batch while advancing the durable watermark; `history` never changes read state.
11
+ - `team_message` starts a top-level Task or replies to an existing Thread. Replies require the exact `baseRevision` and reject unread work before checking revision freshness.
12
+ - `team_claim` lists or mutates the calling Member's Direction Claims through `list`, `claim`, `done`, and `release`. Direction exclusion uses Unicode NFKC normalization, trim, whitespace compression, and deterministic case folding.
13
+ - `team_view` discovers bounded, membership-authorized Channel, Task, and Member summaries. It does not return Thread messages or activities.
14
+
15
+ An Agent cannot silently enroll an unfollowed Agent through a mention; the Host returns `member_not_following`. Human confirmation is a separate Host/Client flow. Closed Tasks reject replies, Claims, and new Attention until a Human reopens them.
16
+
17
+ Canonical results expose stable refs, current Task status, Thread revision, Claim history, Attention, and unread facts. Typed `unread_required` and `stale_revision` results include the fields needed to reread and retry deliberately. Tool execution resolves the exact live `exec.agent`; arguments cannot select or impersonate the actor or Workspace. Write request identity derives from sessionId plus tool callId. Team tools return to the model loop and never conclude the turn.
18
+
19
+ The complete implemented protocol is documented in [`../../docs/team-collaboration.md`](../../docs/team-collaboration.md).
20
+
21
+ ## Composition
22
+
23
+ Mount this plugin inside a team-enabled Agent preset after `dsh-tools`. It statically injects only `tools`; execution resolves `agentTeam` from the live Agent context. This avoids a dependency cycle while the Host restores member sessions.
@@ -0,0 +1,23 @@
1
+ # @wowyuarm/dsh-agent-team/tools
2
+
3
+ [English](README.md) | 中文
4
+
5
+ 面向 Agent Team Member 的模型工具。本包在调用方 Agent preset scope 内注册工具,不提供或替换 Host service。
6
+
7
+ ## 工具
8
+
9
+ - `team_inbox` 列出调用方 Member 的有界未读 Thread 摘要,先按 direct work、再按最近活动排序。
10
+ - `team_thread` 读取 Thread、分页历史、follow 或 unfollow。`read` 原子返回 Task anchor、当前 Task 与 Claim 快照、有界背景和一批连续未读事实,并推进持久 watermark;`history` 不改变 read 状态。
11
+ - `team_message` 创建顶层 Task,或回复已有 Thread。Reply 必须携带准确的 `baseRevision`,并在检查 revision 前先处理未读门禁。
12
+ - `team_claim` 通过 `list`、`claim`、`done`、`release` 读取或修改调用方 Member 的 Direction Claim。Direction 互斥键执行 Unicode NFKC normalization、trim、空白压缩和确定性大小写折叠。
13
+ - `team_view` 发现有界、按 membership 授权的 Channel、Task 和 Member 摘要,不返回 Thread Message 或 Activity。
14
+
15
+ Agent 不能通过 mention 静默把另一个 unfollowed Agent 加入 Thread;Host 返回 `member_not_following`。Human confirmation 属于单独的 Host/Client 流程。Closed Task 在 Human reopen 前拒绝 reply、Claim 和新的 Attention。
16
+
17
+ Canonical result 包含稳定 refs、当前 Task status、Thread revision、Claim history、Attention 和未读 facts。类型化的 `unread_required` 与 `stale_revision` 结果包含重新读取和审慎重试所需字段。工具执行通过准确的 live `exec.agent` 解析 actor;参数不能选择或冒充 actor 或 Workspace。写操作的 request identity 由 sessionId 与 tool callId 派生。Team tools 将结果返回模型循环,不主动结束 turn。
18
+
19
+ 完整的已实现协议见 [`../../docs/team-collaboration.md`](../../docs/team-collaboration.md)。
20
+
21
+ ## Composition
22
+
23
+ 在 team-enabled Agent preset 内、`dsh-tools` 之后挂载本插件。插件只静态 inject `tools`;执行时从 live Agent context 读取 `agentTeam`,避免 Host 恢复 Member session 时形成依赖环。
@@ -0,0 +1,294 @@
1
+ import { markAgentTeamPreset } from '@wowyuarm/dsh-agent-team/host';
2
+ import { defineTool } from '@deepseek-ai/dsh-tools';
3
+ export const name = 'wowyuarm-agent-team-tools';
4
+ export const inject = ['tools'];
5
+ function service(agent) {
6
+ const host = agent.ctx.get('agentTeam');
7
+ if (host === undefined)
8
+ throw new Error('Agent Team Host is unavailable');
9
+ return host;
10
+ }
11
+ function member(agent) {
12
+ const current = service(agent).memberForAgent(agent);
13
+ if (current === undefined)
14
+ throw new Error('team tool requires an active Team Member');
15
+ return current;
16
+ }
17
+ function requestId(agentId, callId) {
18
+ return `agent-team:tool:${agentId}:${callId}`;
19
+ }
20
+ const teamInbox = defineTool({
21
+ name: 'team_inbox',
22
+ description: 'List your bounded Team Inbox. It returns Thread summaries without message bodies and does not mark anything read.',
23
+ parameters: { limit: { type: 'number' } },
24
+ output: {
25
+ schema: { type: 'object', additionalProperties: false, properties: {
26
+ totalUnreadCount: { type: 'number', required: true }, totalDirectCount: { type: 'number', required: true },
27
+ items: { type: 'array', required: true, items: { type: 'object', additionalProperties: false, properties: {
28
+ taskRef: { type: 'string', required: true }, threadRef: { type: 'string', required: true }, channelRef: { type: 'string', required: true },
29
+ status: { type: 'string', required: true }, revision: { type: 'number', required: true }, unreadCount: { type: 'number', required: true }, directCount: { type: 'number', required: true },
30
+ taskNumber: { type: 'number' },
31
+ } } },
32
+ } },
33
+ render: (_args, value) => [{ type: 'text', text: value.items.length === 0 ? 'No unread Team work.'
34
+ : value.items.map(item => `${item.taskRef}${item.taskNumber === undefined ? '' : ` (#${item.taskNumber})`} · ${item.directCount > 0 ? 'direct' : 'unread'}, ${item.unreadCount} update(s), revision ${item.revision}`).join('\n') }],
35
+ },
36
+ async execute(args, exec) {
37
+ const agent = exec.agent;
38
+ if (agent === undefined)
39
+ throw new Error('team_inbox requires an Agent session');
40
+ const current = member(agent);
41
+ const host = service(agent);
42
+ const inbox = host.inboxForAgent(agent, { workspaceId: current.workspaceId, ...(args.limit === undefined ? {} : { limit: args.limit }) });
43
+ const taskNumbers = new Map(host.viewForAgent(agent, { workspaceId: current.workspaceId, topLevelOnly: true, includeActivities: false })
44
+ .taskNumbers.map(entry => [entry.taskRef, entry.taskNumber]));
45
+ return {
46
+ totalUnreadCount: inbox.totalUnreadCount, totalDirectCount: inbox.totalDirectCount,
47
+ items: inbox.items.map(item => {
48
+ const taskNumber = taskNumbers.get(item.task.taskRef);
49
+ return { taskRef: item.task.taskRef, threadRef: item.thread.threadRef, channelRef: item.channelRef,
50
+ status: item.task.status, revision: item.thread.revision, unreadCount: item.unreadCount, directCount: item.directCount,
51
+ ...(taskNumber === undefined ? {} : { taskNumber }) };
52
+ }),
53
+ };
54
+ },
55
+ });
56
+ const teamThread = defineTool({
57
+ name: 'team_thread',
58
+ description: 'Read or manage your Attention on one Task Thread. read acknowledges one chronological batch; history does not change read state.',
59
+ parameters: {
60
+ action: { type: 'string', required: true, enum: ['status', 'follow', 'unfollow', 'read', 'history'] },
61
+ taskRef: { type: 'string', required: true, description: "Full branded Task ref exactly as returned by Team tools, including the 'task:' prefix." },
62
+ beforeSequence: { type: 'number' }, limit: { type: 'number' },
63
+ },
64
+ output: {
65
+ schema: { type: 'object', additionalProperties: false, properties: {
66
+ kind: { type: 'string', required: true }, taskRef: { type: 'string', required: true }, threadRef: { type: 'string', required: true },
67
+ revision: { type: 'number', required: true }, status: { type: 'string', required: true }, resolution: { type: 'string', required: true },
68
+ following: { type: 'boolean', required: true }, readThroughSequence: { type: 'number' }, remainingUnreadCount: { type: 'number' }, cursor: { type: 'number' }, hasMore: { type: 'boolean' },
69
+ anchor: { type: 'object', required: true, additionalProperties: false, properties: {
70
+ messageRef: { type: 'string', required: true }, sender: { type: 'string', required: true }, body: { type: 'string', required: true }, sequence: { type: 'number', required: true },
71
+ } },
72
+ claims: { type: 'array', required: true, items: { type: 'object', additionalProperties: false, properties: {
73
+ claimRef: { type: 'string', required: true }, direction: { type: 'string', required: true }, state: { type: 'string', required: true }, owner: { type: 'string', required: true },
74
+ } } },
75
+ facts: { type: 'array', required: true, items: { type: 'object', additionalProperties: false, properties: {
76
+ sequence: { type: 'number', required: true }, kind: { type: 'string', required: true }, body: { type: 'string' }, sender: { type: 'string' }, mentions: { type: 'array', items: { type: 'string' } }, activity: { type: 'string' }, unread: { type: 'boolean' }, direct: { type: 'boolean' },
77
+ } } },
78
+ } },
79
+ render: (_args, value) => [{ type: 'text', text: value.facts.length === 0
80
+ ? `${value.threadRef} · revision ${value.revision}, following=${value.following}`
81
+ : [`revision ${value.revision}`, ...value.facts.map(fact => fact.kind === 'message'
82
+ ? `${fact.sequence} [${fact.sender ?? 'unknown sender'}] ${fact.body}`
83
+ : `${fact.sequence} ${fact.activity}`)].join('\n') }],
84
+ },
85
+ async execute(args, exec) {
86
+ const agent = exec.agent;
87
+ if (agent === undefined)
88
+ throw new Error('team_thread requires an Agent session');
89
+ const current = member(agent);
90
+ const host = service(agent);
91
+ const base = { workspaceId: current.workspaceId, taskRef: args.taskRef };
92
+ if (args.action === 'status') {
93
+ if (args.beforeSequence !== undefined || args.limit !== undefined)
94
+ throw new Error('status does not accept history arguments');
95
+ const status = host.attentionStatusForAgent(agent, base);
96
+ const snapshot = host.threadHistoryForAgent(agent, { ...base, beforeSequence: 1, limit: 1 });
97
+ return threadResult('status', snapshot, status.attention, []);
98
+ }
99
+ if (args.action === 'follow' || args.action === 'unfollow') {
100
+ if (args.beforeSequence !== undefined || args.limit !== undefined)
101
+ throw new Error(`${args.action} does not accept history arguments`);
102
+ const result = await host.changeAttentionForAgent(agent, { requestId: requestId(agent.id, exec.callId), ...base, action: args.action });
103
+ const snapshot = host.threadHistoryForAgent(agent, { ...base, beforeSequence: 1, limit: 1 });
104
+ return threadResult(args.action, snapshot, result.attention, []);
105
+ }
106
+ if (args.action === 'history') {
107
+ const history = host.threadHistoryForAgent(agent, { ...base, ...(args.beforeSequence === undefined ? {} : { beforeSequence: args.beforeSequence }), ...(args.limit === undefined ? {} : { limit: args.limit }) });
108
+ const status = host.attentionStatusForAgent(agent, base);
109
+ return threadResult('history', history, status.attention, history.facts.map(fact => fact.kind === 'message'
110
+ ? { sequence: fact.sequence, kind: 'message', body: fact.message.body, sender: fact.message.sender, mentions: [...fact.mentions] }
111
+ : { sequence: fact.sequence, kind: 'activity', activity: fact.activity.kind }), { cursor: history.cursor, hasMore: history.hasMore });
112
+ }
113
+ if (args.beforeSequence !== undefined || args.limit !== undefined)
114
+ throw new Error('read does not accept history arguments');
115
+ const read = await host.readThreadForAgent(agent, { requestId: requestId(agent.id, exec.callId), ...base });
116
+ return threadResult('read', read, read.attention, read.facts.map(entry => entry.fact.kind === 'message'
117
+ ? { sequence: entry.fact.sequence, kind: 'message', body: entry.fact.message.body, sender: entry.fact.message.sender, mentions: [...entry.fact.mentions], unread: entry.unread, direct: entry.direct }
118
+ : { sequence: entry.fact.sequence, kind: 'activity', activity: entry.fact.activity.kind, unread: entry.unread, direct: entry.direct }), { readThroughSequence: read.readThroughSequence, remainingUnreadCount: read.remainingUnreadCount });
119
+ },
120
+ });
121
+ function threadResult(kind, snapshot, attention, facts, extra = {}) {
122
+ return {
123
+ kind, taskRef: snapshot.task.taskRef, threadRef: snapshot.thread.threadRef, revision: snapshot.thread.revision,
124
+ status: snapshot.task.status, resolution: snapshot.task.resolution, following: attention !== undefined,
125
+ ...extra,
126
+ ...(attention === undefined || extra.readThroughSequence !== undefined ? {} : { readThroughSequence: attention.readThroughSequence }),
127
+ anchor: { messageRef: snapshot.anchor.messageRef, sender: snapshot.anchor.sender, body: snapshot.anchor.body, sequence: snapshot.anchor.sequence },
128
+ claims: snapshot.claims.map(claim => ({ claimRef: claim.claimRef, direction: claim.direction, state: claim.state, owner: claim.owner })),
129
+ facts,
130
+ };
131
+ }
132
+ const teamMessage = markAgentTeamPreset(defineTool({
133
+ name: 'team_message',
134
+ description: 'Create a top-level Task or reply to one existing Task Thread. Read the Thread first; replies require its current revision. A top-level start may mention related Agents directly; in replies, only a Human can invite an unfollowed Agent. Pass Member refs in mentions and spell their handles inside the body; only mentioned Members render as mention chips.',
135
+ parameters: {
136
+ action: { type: 'string', required: true, enum: ['start', 'reply'] },
137
+ channelRef: { type: 'string', description: "Full branded Channel ref exactly as returned by Team tools, including the 'channel:' prefix." },
138
+ taskRef: { type: 'string', description: "Full branded Task ref exactly as returned by Team tools, including the 'task:' prefix." },
139
+ body: { type: 'string', required: true }, baseRevision: { type: 'number', description: "Positive integer; use the current Thread revision as shown by the latest team_inbox or team_thread result for this Task." },
140
+ mentions: { type: 'array', items: { type: 'string' }, description: 'Member refs to mention. Mentioned Agents receive the Message directly; write their handles in the body (any casing, optional @) so the mention renders inline.' },
141
+ },
142
+ output: {
143
+ schema: { type: 'object', additionalProperties: false, properties: {
144
+ kind: { type: 'string', required: true }, taskRef: { type: 'string' }, threadRef: { type: 'string' }, revision: { type: 'number' },
145
+ expectedRevision: { type: 'number' }, messageRef: { type: 'string' }, memberIds: { type: 'array', items: { type: 'string' } }, unreadCount: { type: 'number' }, directCount: { type: 'number' },
146
+ } },
147
+ render: (_args, value) => [{ type: 'text', text: value.kind === 'committed' ? `Message ${value.messageRef} committed at revision ${value.revision}.`
148
+ : `${value.kind}: ${value.memberIds?.join(', ') ?? `Task ${value.taskRef ?? ''} revision ${value.revision ?? ''}`}` }],
149
+ },
150
+ async execute(args, exec) {
151
+ const agent = exec.agent;
152
+ if (agent === undefined)
153
+ throw new Error('team_message requires an Agent session');
154
+ const current = member(agent);
155
+ const host = service(agent);
156
+ const mentions = args.mentions;
157
+ if (args.action === 'start') {
158
+ if (args.channelRef === undefined || args.taskRef !== undefined || args.baseRevision !== undefined)
159
+ throw new Error('start requires channelRef and does not accept taskRef or baseRevision');
160
+ const result = await host.sendMessageForAgent(agent, { requestId: requestId(agent.id, exec.callId), workspaceId: current.workspaceId,
161
+ channelRef: args.channelRef, body: args.body, ...(mentions === undefined ? {} : { recipients: mentions }) });
162
+ return messageOutcome(result);
163
+ }
164
+ const baseRevision = args.baseRevision;
165
+ if (args.taskRef === undefined || args.channelRef !== undefined || typeof baseRevision !== 'number' || !Number.isSafeInteger(baseRevision) || baseRevision < 1) {
166
+ throw new Error("reply requires taskRef and a positive baseRevision, and does not accept channelRef; use the current Thread 'revision' returned by team_inbox or team_thread for this Task");
167
+ }
168
+ const result = await host.replyForAgent(agent, { requestId: requestId(agent.id, exec.callId), workspaceId: current.workspaceId,
169
+ taskRef: args.taskRef, body: args.body, baseRevision,
170
+ ...(mentions === undefined ? {} : { recipients: mentions }) });
171
+ return messageOutcome(result);
172
+ },
173
+ }));
174
+ function messageOutcome(result) {
175
+ if (result.kind === 'committed')
176
+ return { kind: result.kind, taskRef: result.task.taskRef, threadRef: result.thread.threadRef,
177
+ revision: result.thread.revision, messageRef: result.message.messageRef };
178
+ if (result.kind === 'member_not_following')
179
+ return { kind: result.kind, memberIds: [...result.memberIds],
180
+ ...(result.taskRef === undefined ? {} : { taskRef: result.taskRef }), ...(result.threadRef === undefined ? {} : { threadRef: result.threadRef, revision: result.revision }) };
181
+ if (result.kind === 'unread_required')
182
+ return { kind: result.kind, taskRef: result.taskRef, threadRef: result.threadRef,
183
+ revision: result.revision, unreadCount: result.unreadCount, directCount: result.directCount };
184
+ if (result.kind === 'stale_revision')
185
+ return { kind: result.kind, taskRef: result.taskRef, threadRef: result.threadRef,
186
+ expectedRevision: result.expectedRevision, revision: result.revision };
187
+ throw new Error('Agents cannot receive invitation confirmations');
188
+ }
189
+ const teamClaim = defineTool({
190
+ name: 'team_claim',
191
+ description: 'List or mutate your Direction Claims. Read the Thread first; every mutation uses the current Thread revision.',
192
+ parameters: {
193
+ action: { type: 'string', required: true, enum: ['list', 'claim', 'done', 'release'] },
194
+ taskRef: { type: 'string', required: true, description: "Full branded Task ref exactly as returned by Team tools, including the 'task:' prefix." },
195
+ baseRevision: { type: 'number', description: "Positive integer; use the current Thread revision as shown by the latest team_inbox or team_thread result for this Task." }, direction: { type: 'string' },
196
+ claimRef: { type: 'string', description: "Full branded Claim ref exactly as returned by team_claim, including the 'claim:' prefix." },
197
+ },
198
+ output: {
199
+ schema: { type: 'object', additionalProperties: false, properties: {
200
+ kind: { type: 'string', required: true }, taskRef: { type: 'string', required: true }, threadRef: { type: 'string', required: true },
201
+ revision: { type: 'number', required: true }, expectedRevision: { type: 'number' }, status: { type: 'string', required: true },
202
+ unreadCount: { type: 'number' }, directCount: { type: 'number' },
203
+ claims: { type: 'array', required: true, items: { type: 'object', additionalProperties: false, properties: { claimRef: { type: 'string', required: true }, direction: { type: 'string', required: true }, state: { type: 'string', required: true }, owner: { type: 'string', required: true } } } },
204
+ } },
205
+ render: (_args, value) => [{ type: 'text', text: [`${value.kind}: ${value.taskRef} · ${value.status}, revision ${value.revision}`,
206
+ ...value.claims.map(claim => `${claim.claimRef} · ${claim.state} — ${claim.owner}: ${claim.direction}`)].join('\n') }],
207
+ },
208
+ async execute(args, exec) {
209
+ const agent = exec.agent;
210
+ if (agent === undefined)
211
+ throw new Error('team_claim requires an Agent session');
212
+ const current = member(agent);
213
+ const host = service(agent);
214
+ const base = { workspaceId: current.workspaceId, taskRef: args.taskRef };
215
+ if (args.action === 'list') {
216
+ if (args.baseRevision !== undefined || args.direction !== undefined || args.claimRef !== undefined)
217
+ throw new Error('list accepts only taskRef');
218
+ const listed = host.listClaimsForAgent(agent, base);
219
+ return { kind: 'listed', taskRef: listed.task.taskRef, threadRef: listed.thread.threadRef, revision: listed.thread.revision, status: listed.task.status,
220
+ claims: listed.claims.map(claim => ({ claimRef: claim.claimRef, owner: claim.owner, direction: claim.direction, state: claim.state })) };
221
+ }
222
+ const baseRevision = args.baseRevision;
223
+ if (typeof baseRevision !== 'number' || !Number.isSafeInteger(baseRevision) || baseRevision < 1)
224
+ throw new Error("claim mutation requires a positive baseRevision; use the current Thread 'revision' returned by team_inbox or team_thread for this Task");
225
+ if (args.action === 'claim' && (args.direction === undefined || args.claimRef !== undefined))
226
+ throw new Error('claim requires direction and does not accept claimRef');
227
+ if ((args.action === 'done' || args.action === 'release') && (args.claimRef === undefined || args.direction !== undefined))
228
+ throw new Error(`${args.action} requires claimRef and does not accept direction`);
229
+ const result = await host.changeClaimForAgent(agent, { requestId: requestId(agent.id, exec.callId), ...base, action: args.action,
230
+ baseRevision, ...(args.direction === undefined ? {} : { direction: args.direction }), ...(args.claimRef === undefined ? {} : { claimRef: args.claimRef }) });
231
+ const listed = host.listClaimsForAgent(agent, base);
232
+ const claims = listed.claims.map(claim => ({ claimRef: claim.claimRef, owner: claim.owner, direction: claim.direction, state: claim.state }));
233
+ if (result.kind === 'committed')
234
+ return { kind: result.kind, taskRef: result.task.taskRef, threadRef: result.thread.threadRef,
235
+ revision: result.thread.revision, status: result.task.status, claims };
236
+ if (result.kind === 'unread_required')
237
+ return { kind: result.kind, taskRef: result.taskRef, threadRef: result.threadRef,
238
+ revision: result.revision, status: listed.task.status, unreadCount: result.unreadCount, directCount: result.directCount, claims };
239
+ return { kind: result.kind, taskRef: result.taskRef, threadRef: result.threadRef, expectedRevision: result.expectedRevision,
240
+ revision: result.revision, status: listed.task.status, claims };
241
+ },
242
+ });
243
+ const teamView = defineTool({
244
+ name: 'team_view',
245
+ description: 'Discover authorized Team Channels, Tasks, and Members. It is not a substitute for team_thread reading.',
246
+ parameters: {
247
+ channelRef: { type: 'string', description: "Full branded Channel ref exactly as returned by Team tools, including the 'channel:' prefix." },
248
+ limit: { type: 'number' }, cursor: { type: 'number' },
249
+ },
250
+ output: {
251
+ schema: { type: 'object', additionalProperties: false, properties: {
252
+ channels: { type: 'array', required: true, items: { type: 'object', additionalProperties: false, properties: { channelRef: { type: 'string', required: true }, name: { type: 'string', required: true } } } },
253
+ members: { type: 'array', required: true, items: { type: 'object', additionalProperties: false, properties: {
254
+ memberId: { type: 'string', required: true }, kind: { type: 'string', required: true }, handle: { type: 'string', required: true }, description: { type: 'string', required: true }, presence: { type: 'string', required: true },
255
+ } } },
256
+ tasks: { type: 'array', required: true, items: { type: 'object', additionalProperties: false, properties: { taskRef: { type: 'string', required: true }, threadRef: { type: 'string', required: true }, channelRef: { type: 'string', required: true }, status: { type: 'string', required: true }, revision: { type: 'number', required: true } } } },
257
+ cursor: { type: 'number', required: true }, hasMore: { type: 'boolean', required: true },
258
+ } },
259
+ render: (_args, value) => [{ type: 'text', text: [
260
+ ...value.channels.map(channel => `${channel.channelRef} · ${channel.name}`),
261
+ ...value.members.map(m => `${m.memberId} · ${m.handle} (${m.kind}, ${m.presence})${m.description === '' ? '' : ` — ${m.description}`}`),
262
+ ...(value.tasks.length > 0
263
+ ? value.tasks.map(task => `${task.taskRef} · ${task.status}`)
264
+ : ['No Team Tasks.']),
265
+ ].join('\n') }],
266
+ },
267
+ async execute(args, exec) {
268
+ const agent = exec.agent;
269
+ if (agent === undefined)
270
+ throw new Error('team_view requires an Agent session');
271
+ const current = member(agent);
272
+ const host = service(agent);
273
+ const view = host.viewForAgent(agent, { workspaceId: current.workspaceId, ...(args.channelRef === undefined ? {} : { channelRef: args.channelRef }), ...(args.limit === undefined ? {} : { limit: args.limit }), ...(args.cursor === undefined ? {} : { cursor: args.cursor }), topLevelOnly: true, includeActivities: false });
274
+ const visibleMemberIds = new Set(view.members.map(membership => membership.memberId));
275
+ return {
276
+ channels: view.channels.map(channel => ({ channelRef: channel.channelRef, name: channel.name })),
277
+ members: [
278
+ { memberId: view.humanMemberId, kind: 'human', handle: 'human', description: 'Human Team Member', presence: 'available' },
279
+ ...host.members().filter(status => visibleMemberIds.has(status.member.memberId)).map(status => ({ memberId: status.member.memberId,
280
+ kind: 'agent', handle: status.member.handle, description: status.member.description, presence: status.presence })),
281
+ ],
282
+ tasks: view.tasks.map(task => ({ taskRef: task.taskRef, threadRef: task.threadRef, channelRef: task.channelRef,
283
+ status: task.status, revision: view.threads.find(thread => thread.threadRef === task.threadRef)?.revision ?? 0 })),
284
+ cursor: view.cursor, hasMore: view.hasMore,
285
+ };
286
+ },
287
+ });
288
+ export function apply(ctx) {
289
+ ctx.tools.register(teamInbox);
290
+ ctx.tools.register(teamThread);
291
+ ctx.tools.register(teamMessage);
292
+ ctx.tools.register(teamClaim);
293
+ ctx.tools.register(teamView);
294
+ }
@@ -0,0 +1,5 @@
1
+ import type { Context } from '@deepseek-ai/cordis';
2
+ export declare const name = "wowyuarm-agent-team-tools";
3
+ export declare const inject: string[];
4
+ export declare function apply(ctx: Context): void;
5
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AAUlD,eAAO,MAAM,IAAI,8BAA8B,CAAA;AAC/C,eAAO,MAAM,MAAM,UAAY,CAAA;AAwR/B,wBAAgB,KAAK,CAAC,GAAG,EAAE,OAAO,GAAG,IAAI,CAMxC"}