@wowyuarm/dsh-agent-team 0.1.2 → 0.1.4

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 (90) hide show
  1. package/README.md +8 -1
  2. package/README.zh.md +9 -1
  3. package/package.json +12 -3
  4. package/packages/agent-team/README.md +3 -3
  5. package/packages/agent-team/README.zh.md +3 -3
  6. package/packages/agent-team/lib/attachments.js +11 -12
  7. package/packages/agent-team/lib/auto-compaction.js +163 -0
  8. package/packages/agent-team/lib/index.js +252 -139
  9. package/packages/agent-team/lib/ledger.js +344 -170
  10. package/packages/agent-team/lib/recovery.js +30 -35
  11. package/packages/agent-team/lib/spec.js +27 -11
  12. package/packages/agent-team/lib/typert.host.js +197 -88
  13. package/packages/agent-team/lib/typert.remote-client.d.ts +3 -1
  14. package/packages/agent-team/lib/typert.remote-client.d.ts.map +1 -1
  15. package/packages/agent-team/lib/typert.remote-client.js +139 -59
  16. package/packages/agent-team/lib/types/attachments.d.ts +2 -2
  17. package/packages/agent-team/lib/types/attachments.d.ts.map +1 -1
  18. package/packages/agent-team/lib/types/auto-compaction.d.ts +38 -0
  19. package/packages/agent-team/lib/types/auto-compaction.d.ts.map +1 -0
  20. package/packages/agent-team/lib/types/index.d.ts +52 -19
  21. package/packages/agent-team/lib/types/index.d.ts.map +1 -1
  22. package/packages/agent-team/lib/types/ledger.d.ts +29 -2
  23. package/packages/agent-team/lib/types/ledger.d.ts.map +1 -1
  24. package/packages/agent-team/lib/types/recovery.d.ts +15 -16
  25. package/packages/agent-team/lib/types/recovery.d.ts.map +1 -1
  26. package/packages/agent-team/lib/types/spec.d.ts.map +1 -1
  27. package/packages/agent-team/lib/types/types.d.ts +69 -30
  28. package/packages/agent-team/lib/types/types.d.ts.map +1 -1
  29. package/packages/agent-team/preset/team-member/agent.cordis.yml +7 -2
  30. package/packages/client-agent-team/README.md +2 -1
  31. package/packages/client-agent-team/README.zh.md +2 -1
  32. package/packages/client-agent-team/lib/client.js +1577 -863
  33. package/packages/client-agent-team/lib/client.js.map +1 -1
  34. package/packages/client-agent-team/lib/types/client/TeamAgentsPanel.d.ts.map +1 -1
  35. package/packages/client-agent-team/lib/types/client/TeamAgentsPanel.js +35 -174
  36. package/packages/client-agent-team/lib/types/client/TeamChannelPage.d.ts.map +1 -1
  37. package/packages/client-agent-team/lib/types/client/TeamChannelPage.js +20 -30
  38. package/packages/client-agent-team/lib/types/client/TeamChannelsPanel.d.ts.map +1 -1
  39. package/packages/client-agent-team/lib/types/client/TeamChannelsPanel.js +3 -2
  40. package/packages/client-agent-team/lib/types/client/TeamComposer.d.ts +6 -1
  41. package/packages/client-agent-team/lib/types/client/TeamComposer.d.ts.map +1 -1
  42. package/packages/client-agent-team/lib/types/client/TeamComposer.js +4 -5
  43. package/packages/client-agent-team/lib/types/client/TeamConversation.d.ts +1 -1
  44. package/packages/client-agent-team/lib/types/client/TeamConversation.d.ts.map +1 -1
  45. package/packages/client-agent-team/lib/types/client/TeamConversation.js +3 -3
  46. package/packages/client-agent-team/lib/types/client/TeamMemberEditor.d.ts +34 -0
  47. package/packages/client-agent-team/lib/types/client/TeamMemberEditor.d.ts.map +1 -0
  48. package/packages/client-agent-team/lib/types/client/TeamMemberEditor.js +169 -0
  49. package/packages/client-agent-team/lib/types/client/TeamMemberSessionComposer.d.ts +17 -0
  50. package/packages/client-agent-team/lib/types/client/TeamMemberSessionComposer.d.ts.map +1 -0
  51. package/packages/client-agent-team/lib/types/client/TeamMemberSessionComposer.js +120 -0
  52. package/packages/client-agent-team/lib/types/client/TeamMessage.d.ts +4 -1
  53. package/packages/client-agent-team/lib/types/client/TeamMessage.d.ts.map +1 -1
  54. package/packages/client-agent-team/lib/types/client/TeamMessage.js +94 -47
  55. package/packages/client-agent-team/lib/types/client/TeamThreadPage.d.ts +2 -1
  56. package/packages/client-agent-team/lib/types/client/TeamThreadPage.d.ts.map +1 -1
  57. package/packages/client-agent-team/lib/types/client/TeamThreadPage.js +81 -39
  58. package/packages/client-agent-team/lib/types/client/TeamWorkspaceBrowser.d.ts.map +1 -1
  59. package/packages/client-agent-team/lib/types/client/TeamWorkspaceBrowser.js +2 -1
  60. package/packages/client-agent-team/lib/types/client/index.d.ts.map +1 -1
  61. package/packages/client-agent-team/lib/types/client/index.js +72 -1
  62. package/packages/client-agent-team/lib/types/client/locales.d.ts +24 -0
  63. package/packages/client-agent-team/lib/types/client/locales.d.ts.map +1 -1
  64. package/packages/client-agent-team/lib/types/client/locales.js +24 -0
  65. package/packages/client-agent-team/lib/types/client/member-session-input.d.ts +22 -0
  66. package/packages/client-agent-team/lib/types/client/member-session-input.d.ts.map +1 -0
  67. package/packages/client-agent-team/lib/types/client/member-session-input.js +98 -0
  68. package/packages/client-agent-team/lib/types/client/navigation.d.ts +1 -1
  69. package/packages/client-agent-team/lib/types/client/navigation.d.ts.map +1 -1
  70. package/packages/client-agent-team/lib/types/client/navigation.js +12 -6
  71. package/packages/client-agent-team/lib/types/client/requests.d.ts +16 -0
  72. package/packages/client-agent-team/lib/types/client/requests.d.ts.map +1 -0
  73. package/packages/client-agent-team/lib/types/client/requests.js +22 -0
  74. package/packages/client-agent-team/lib/types/client/slots.d.ts +2 -1
  75. package/packages/client-agent-team/lib/types/client/slots.d.ts.map +1 -1
  76. package/packages/client-agent-team/lib/types/client/task-refs.d.ts +6 -1
  77. package/packages/client-agent-team/lib/types/client/task-refs.d.ts.map +1 -1
  78. package/packages/client-agent-team/lib/types/client/task-refs.js +19 -0
  79. package/packages/client-agent-team/lib/types/client/team-formatters.d.ts +52 -3
  80. package/packages/client-agent-team/lib/types/client/team-formatters.d.ts.map +1 -1
  81. package/packages/client-agent-team/lib/types/client/team-formatters.js +74 -4
  82. package/packages/client-agent-team/lib/types/client/team-membership.d.ts.map +1 -1
  83. package/packages/client-agent-team/lib/types/client/team-membership.js +2 -1
  84. package/packages/tool-agent-team/README.md +7 -7
  85. package/packages/tool-agent-team/README.zh.md +7 -7
  86. package/packages/tool-agent-team/lib/index.js +38 -28
  87. package/packages/tool-agent-team/lib/types/index.d.ts.map +1 -1
  88. package/packages/client-agent-team/lib/types/client/TeamInboxPanel.d.ts +0 -13
  89. package/packages/client-agent-team/lib/types/client/TeamInboxPanel.d.ts.map +0 -1
  90. package/packages/client-agent-team/lib/types/client/TeamInboxPanel.js +0 -90
@@ -6,15 +6,15 @@
6
6
 
7
7
  ## 工具
8
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 授权的 ChannelTask 和 Member 摘要,不返回 Thread Message 或 Activity。
9
+ - `team_inbox` 列出调用方 Member 的有界未读 Thread 摘要,先按 direct work、再按最近活动排序;只有 Thread 存在真实 Task overlay 时才出现 Task status/number。
10
+ - `team_thread` 读取 Thread、分页历史、follow 或 unfollow。`threadRef` 是主身份;`taskRef` 只对 released task-only Client 是 Host alias。`read` 原子返回 Thread anchor、可选的当前 Task 与 Claim 快照、有界背景和一批连续未读事实,并推进持久 watermark;`history` 不改变 read 状态。
11
+ - `team_message` 创建顶层 Thread,或回复已有 Thread。它默认创建 taskless Thread;传入 `asTask: true` 才原子创建 Task。Reply 必须携带准确的 `baseRevision`,并在检查 revision 前先处理未读门禁。
12
+ - `team_claim` 通过 `list`、`claim`、`done`、`release` 读取或修改调用方 Member 的 Direction Claim;它只适用于真实 Task。Direction 互斥键执行 Unicode NFKC normalization、trim、空白压缩和确定性大小写折叠。
13
+ - `team_view` 发现有界、按 membership 授权的 Channel、真实 Task 和 Member 摘要,不返回 Thread Message 或 Activity。
14
14
 
15
- Agent 不能通过 mention 静默把另一个 unfollowed Agent 加入 Thread;Host 返回 `member_not_following`。Human confirmation 属于单独的 Host/Client 流程。Closed Task 在 Human reopen 前拒绝 reply、Claim 和新的 Attention。
15
+ Agent 不能通过 mention 静默把另一个 unfollowed Agent 加入 Thread;Host 返回 `member_not_following`。Human confirmation 属于单独的 Host/Client 流程。Closed Task 在 Human reopen 前拒绝 reply、Claim 和新的 Attention;taskless Thread 没有 Claim 或 Task resolution mutation path
16
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。
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
18
 
19
19
  完整的已实现协议见 [`../../docs/team-collaboration.md`](../../docs/team-collaboration.md)。
20
20
 
@@ -25,13 +25,13 @@ const teamInbox = defineTool({
25
25
  schema: { type: 'object', additionalProperties: false, properties: {
26
26
  totalUnreadCount: { type: 'number', required: true }, totalDirectCount: { type: 'number', required: true },
27
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 },
28
+ threadRef: { type: 'string', required: true }, channelRef: { type: 'string', required: true },
29
+ taskRef: { type: 'string' }, status: { type: 'string' }, revision: { type: 'number', required: true }, unreadCount: { type: 'number', required: true }, directCount: { type: 'number', required: true },
30
30
  taskNumber: { type: 'number' },
31
31
  } } },
32
32
  } },
33
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') }],
34
+ : value.items.map(item => `${item.threadRef}${item.taskRef === undefined ? '' : ` · ${item.taskRef}`}${item.taskNumber === undefined ? '' : ` (#${item.taskNumber})`} · ${item.directCount > 0 ? 'direct' : 'unread'}, ${item.unreadCount} update(s), revision ${item.revision}`).join('\n') }],
35
35
  },
36
36
  async execute(args, exec) {
37
37
  const agent = exec.agent;
@@ -45,9 +45,10 @@ const teamInbox = defineTool({
45
45
  return {
46
46
  totalUnreadCount: inbox.totalUnreadCount, totalDirectCount: inbox.totalDirectCount,
47
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,
48
+ const taskNumber = item.task === undefined ? undefined : taskNumbers.get(item.task.taskRef);
49
+ return { threadRef: item.thread.threadRef, channelRef: item.channelRef,
50
+ ...(item.task === undefined ? {} : { taskRef: item.task.taskRef, status: item.task.status }),
51
+ revision: item.thread.revision, unreadCount: item.unreadCount, directCount: item.directCount,
51
52
  ...(taskNumber === undefined ? {} : { taskNumber }) };
52
53
  }),
53
54
  };
@@ -55,16 +56,17 @@ const teamInbox = defineTool({
55
56
  });
56
57
  const teamThread = defineTool({
57
58
  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
+ description: 'Read or manage your Attention on one Thread. read acknowledges one chronological batch; history does not change read state. Prefer threadRef; taskRef is a compatibility alias when the Thread has a Task.',
59
60
  parameters: {
60
61
  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
+ threadRef: { type: 'string', description: "Full branded Thread ref exactly as returned by Team tools, including the 'thread:' prefix." },
63
+ taskRef: { type: 'string', description: "Optional Task ref alias for released clients. Prefer threadRef; if both are given they must identify the same Thread." },
62
64
  beforeSequence: { type: 'number' }, limit: { type: 'number' },
63
65
  },
64
66
  output: {
65
67
  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
+ kind: { type: 'string', required: true }, threadRef: { type: 'string', required: true }, taskRef: { type: 'string' },
69
+ revision: { type: 'number', required: true }, status: { type: 'string' }, resolution: { type: 'string' },
68
70
  following: { type: 'boolean', required: true }, readThroughSequence: { type: 'number' }, remainingUnreadCount: { type: 'number' }, cursor: { type: 'number' }, hasMore: { type: 'boolean' },
69
71
  anchor: { type: 'object', required: true, additionalProperties: false, properties: {
70
72
  messageRef: { type: 'string', required: true }, sender: { type: 'string', required: true }, body: { type: 'string', required: true }, sequence: { type: 'number', required: true },
@@ -88,7 +90,9 @@ const teamThread = defineTool({
88
90
  throw new Error('team_thread requires an Agent session');
89
91
  const current = member(agent);
90
92
  const host = service(agent);
91
- const base = { workspaceId: current.workspaceId, taskRef: args.taskRef };
93
+ if (args.threadRef === undefined && args.taskRef === undefined)
94
+ throw new Error('team_thread requires threadRef');
95
+ const base = { workspaceId: current.workspaceId, ...(args.threadRef === undefined ? {} : { threadRef: args.threadRef }), ...(args.taskRef === undefined ? {} : { taskRef: args.taskRef }) };
92
96
  if (args.action === 'status') {
93
97
  if (args.beforeSequence !== undefined || args.limit !== undefined)
94
98
  throw new Error('status does not accept history arguments');
@@ -120,8 +124,9 @@ const teamThread = defineTool({
120
124
  });
121
125
  function threadResult(kind, snapshot, attention, facts, extra = {}) {
122
126
  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,
127
+ kind, threadRef: snapshot.thread.threadRef, revision: snapshot.thread.revision,
128
+ ...(snapshot.task === undefined ? {} : { taskRef: snapshot.task.taskRef, status: snapshot.task.status, resolution: snapshot.task.resolution }),
129
+ following: attention !== undefined,
125
130
  ...extra,
126
131
  ...(attention === undefined || extra.readThroughSequence !== undefined ? {} : { readThroughSequence: attention.readThroughSequence }),
127
132
  anchor: { messageRef: snapshot.anchor.messageRef, sender: snapshot.anchor.sender, body: snapshot.anchor.body, sequence: snapshot.anchor.sequence },
@@ -131,12 +136,14 @@ function threadResult(kind, snapshot, attention, facts, extra = {}) {
131
136
  }
132
137
  const teamMessage = markAgentTeamPreset(defineTool({
133
138
  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 (an internal concurrency token carried by baseRevision, never quoted in bodies). 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.',
139
+ description: 'Start a top-level Thread or reply to an existing Thread. start defaults to a taskless Thread; pass asTask true to create a Task in the same send. Read the Thread first; replies require its current revision (an internal concurrency token carried by baseRevision, never quoted in bodies). 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
140
  parameters: {
136
141
  action: { type: 'string', required: true, enum: ['start', 'reply'] },
137
142
  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. The revision is an internal concurrency token, not a citable fact." },
143
+ threadRef: { type: 'string', description: "Full branded Thread ref exactly as returned by Team tools, including the 'thread:' prefix." },
144
+ taskRef: { type: 'string', description: "Optional Task ref alias for reply on a Taskful Thread. Prefer threadRef." },
145
+ asTask: { type: 'boolean', description: 'When true, start creates a Task with the Thread. Default false creates a taskless Thread.' },
146
+ body: { type: 'string', required: true, description: "Markdown body. Cite Team refs exactly as returned, as bare text with one colon (e.g. task:0f0a…) — never a double colon, never inside backticks or quotes. Spell each mentioned Member's handle in the prose so the mention renders inline." }, baseRevision: { type: 'number', description: "Positive integer; use the current Thread revision as shown by the latest team_inbox or team_thread result for this Thread. The revision is an internal concurrency token, not a citable fact." },
140
147
  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
148
  attachments: { type: 'array', items: { type: 'string' }, description: 'Absolute file paths to share, e.g. screenshots or generated artifacts; images render as thumbnails for recipients. The Host validates each path and copies the file into the attachment cache, and members also receive one cached path per attachment; if any path fails validation the whole send is rejected.' },
142
149
  },
@@ -146,7 +153,7 @@ const teamMessage = markAgentTeamPreset(defineTool({
146
153
  expectedRevision: { type: 'number' }, messageRef: { type: 'string' }, memberIds: { type: 'array', items: { type: 'string' } }, unreadCount: { type: 'number' }, directCount: { type: 'number' },
147
154
  } },
148
155
  render: (_args, value) => [{ type: 'text', text: value.kind === 'committed' ? `Message ${value.messageRef} committed at revision ${value.revision}.`
149
- : `${value.kind}: ${value.memberIds?.join(', ') ?? `Task ${value.taskRef ?? ''} revision ${value.revision ?? ''}`}` }],
156
+ : `${value.kind}: ${value.memberIds?.join(', ') ?? `${value.threadRef ?? ''}${value.taskRef === undefined ? '' : ` · Task ${value.taskRef}`} revision ${value.revision ?? ''}`}` }],
150
157
  },
151
158
  async execute(args, exec) {
152
159
  const agent = exec.agent;
@@ -159,34 +166,37 @@ const teamMessage = markAgentTeamPreset(defineTool({
159
166
  const attachmentPaths = Array.isArray(rawPaths) ? rawPaths.filter((entry) => typeof entry === 'string' && entry.trim() !== '') : undefined;
160
167
  const paths = attachmentPaths !== undefined && attachmentPaths.length > 0 ? { attachmentPaths } : {};
161
168
  if (args.action === 'start') {
162
- if (args.channelRef === undefined || args.taskRef !== undefined || args.baseRevision !== undefined)
163
- throw new Error('start requires channelRef and does not accept taskRef or baseRevision');
169
+ if (args.channelRef === undefined || args.taskRef !== undefined || args.threadRef !== undefined || args.baseRevision !== undefined)
170
+ throw new Error('start requires channelRef and does not accept threadRef, taskRef, or baseRevision');
164
171
  const result = await host.sendMessageForAgent(agent, { requestId: requestId(agent.id, exec.callId), workspaceId: current.workspaceId,
165
- channelRef: args.channelRef, body: args.body, ...(mentions === undefined ? {} : { recipients: mentions }), ...paths });
172
+ channelRef: args.channelRef, body: args.body, asTask: args.asTask === true, ...(mentions === undefined ? {} : { recipients: mentions }), ...paths });
166
173
  return messageOutcome(result);
167
174
  }
168
175
  const baseRevision = args.baseRevision;
169
- if (args.taskRef === undefined || args.channelRef !== undefined || typeof baseRevision !== 'number' || !Number.isSafeInteger(baseRevision) || baseRevision < 1) {
170
- 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");
176
+ if ((args.threadRef === undefined && args.taskRef === undefined) || args.channelRef !== undefined || args.asTask !== undefined || typeof baseRevision !== 'number' || !Number.isSafeInteger(baseRevision) || baseRevision < 1) {
177
+ throw new Error("reply requires threadRef and a positive baseRevision, and does not accept channelRef; use the current Thread 'revision' returned by team_inbox or team_thread");
171
178
  }
172
179
  const result = await host.replyForAgent(agent, { requestId: requestId(agent.id, exec.callId), workspaceId: current.workspaceId,
173
- taskRef: args.taskRef, body: args.body, baseRevision,
180
+ ...(args.threadRef === undefined ? {} : { threadRef: args.threadRef }),
181
+ ...(args.taskRef === undefined ? {} : { taskRef: args.taskRef }),
182
+ body: args.body, baseRevision,
174
183
  ...(mentions === undefined ? {} : { recipients: mentions }), ...paths });
175
184
  return messageOutcome(result);
176
185
  },
177
186
  }));
178
187
  function messageOutcome(result) {
179
188
  if (result.kind === 'committed')
180
- return { kind: result.kind, taskRef: result.task.taskRef, threadRef: result.thread.threadRef,
189
+ return { kind: result.kind, threadRef: result.thread.threadRef,
190
+ ...(result.task === undefined ? {} : { taskRef: result.task.taskRef }),
181
191
  revision: result.thread.revision, messageRef: result.message.messageRef };
182
192
  if (result.kind === 'member_not_following')
183
193
  return { kind: result.kind, memberIds: [...result.memberIds],
184
194
  ...(result.taskRef === undefined ? {} : { taskRef: result.taskRef }), ...(result.threadRef === undefined ? {} : { threadRef: result.threadRef, revision: result.revision }) };
185
195
  if (result.kind === 'unread_required')
186
- return { kind: result.kind, taskRef: result.taskRef, threadRef: result.threadRef,
196
+ return { kind: result.kind, ...(result.taskRef === undefined ? {} : { taskRef: result.taskRef }), threadRef: result.threadRef,
187
197
  revision: result.revision, unreadCount: result.unreadCount, directCount: result.directCount };
188
198
  if (result.kind === 'stale_revision')
189
- return { kind: result.kind, taskRef: result.taskRef, threadRef: result.threadRef,
199
+ return { kind: result.kind, ...(result.taskRef === undefined ? {} : { taskRef: result.taskRef }), threadRef: result.threadRef,
190
200
  expectedRevision: result.expectedRevision, revision: result.revision };
191
201
  throw new Error('Agents cannot receive invitation confirmations');
192
202
  }
@@ -238,9 +248,9 @@ const teamClaim = defineTool({
238
248
  return { kind: result.kind, taskRef: result.task.taskRef, threadRef: result.thread.threadRef,
239
249
  revision: result.thread.revision, status: result.task.status, claims };
240
250
  if (result.kind === 'unread_required')
241
- return { kind: result.kind, taskRef: result.taskRef, threadRef: result.threadRef,
251
+ return { kind: result.kind, taskRef: listed.task.taskRef, threadRef: result.threadRef,
242
252
  revision: result.revision, status: listed.task.status, unreadCount: result.unreadCount, directCount: result.directCount, claims };
243
- return { kind: result.kind, taskRef: result.taskRef, threadRef: result.threadRef, expectedRevision: result.expectedRevision,
253
+ return { kind: result.kind, taskRef: listed.task.taskRef, threadRef: result.threadRef, expectedRevision: result.expectedRevision,
244
254
  revision: result.revision, status: listed.task.status, claims };
245
255
  },
246
256
  });
@@ -1 +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;AA4R/B,wBAAgB,KAAK,CAAC,GAAG,EAAE,OAAO,GAAG,IAAI,CAMxC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AAWlD,eAAO,MAAM,IAAI,8BAA8B,CAAA;AAC/C,eAAO,MAAM,MAAM,UAAY,CAAA;AAqS/B,wBAAgB,KAAK,CAAC,GAAG,EAAE,OAAO,GAAG,IAAI,CAMxC"}
@@ -1,13 +0,0 @@
1
- import type { WorkspaceId } from '@deepseek-ai/dsh-client-runtime/client';
2
- import type { TeamConversationProps } from './slots.ts';
3
- interface TeamInboxPanelProps {
4
- readonly workspaceId: WorkspaceId;
5
- readonly loadInbox: TeamConversationProps['loadInbox'];
6
- readonly loadChannels: TeamConversationProps['loadChannels'];
7
- readonly loadChanges: TeamConversationProps['loadChanges'];
8
- readonly selectThread: TeamConversationProps['selectThread'];
9
- readonly t: TeamConversationProps['t'];
10
- }
11
- export declare function TeamInboxPanel({ workspaceId, loadInbox, loadChannels, loadChanges, selectThread, t }: TeamInboxPanelProps): import("react").JSX.Element;
12
- export {};
13
- //# sourceMappingURL=TeamInboxPanel.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"TeamInboxPanel.d.ts","sourceRoot":"","sources":["../../../src/client/TeamInboxPanel.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,wCAAwC,CAAA;AAEzE,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,YAAY,CAAA;AAIvD,UAAU,mBAAmB;IAC3B,QAAQ,CAAC,WAAW,EAAE,WAAW,CAAA;IACjC,QAAQ,CAAC,SAAS,EAAE,qBAAqB,CAAC,WAAW,CAAC,CAAA;IACtD,QAAQ,CAAC,YAAY,EAAE,qBAAqB,CAAC,cAAc,CAAC,CAAA;IAC5D,QAAQ,CAAC,WAAW,EAAE,qBAAqB,CAAC,aAAa,CAAC,CAAA;IAC1D,QAAQ,CAAC,YAAY,EAAE,qBAAqB,CAAC,cAAc,CAAC,CAAA;IAC5D,QAAQ,CAAC,CAAC,EAAE,qBAAqB,CAAC,GAAG,CAAC,CAAA;CACvC;AAED,wBAAgB,cAAc,CAAC,EAAE,WAAW,EAAE,SAAS,EAAE,YAAY,EAAE,WAAW,EAAE,YAAY,EAAE,CAAC,EAAE,EAAE,mBAAmB,+BAkGzH"}
@@ -1,90 +0,0 @@
1
- import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
- import { useEffect, useMemo, useRef, useState } from 'react';
3
- import { Button } from '@deepseek-ai/dsh-client-ui-primitives';
4
- import { formatTaskStatus } from "./team-formatters.js";
5
- import css from './inbox.module.css';
6
- export function TeamInboxPanel({ workspaceId, loadInbox, loadChannels, loadChanges, selectThread, t }) {
7
- const [inbox, setInbox] = useState();
8
- const [view, setView] = useState();
9
- const [error, setError] = useState();
10
- const [loading, setLoading] = useState(true);
11
- const active = useRef(false);
12
- const refreshSequence = useRef(0);
13
- const refresh = async (clearError = false) => {
14
- const sequence = refreshSequence.current + 1;
15
- refreshSequence.current = sequence;
16
- if (clearError)
17
- setError(undefined);
18
- try {
19
- const [nextInbox, nextView] = await Promise.all([
20
- loadInbox({ workspaceId }),
21
- loadChannels({ workspaceId, topLevelOnly: true, includeActivities: false, limit: 100 }),
22
- ]);
23
- if (!active.current || sequence !== refreshSequence.current)
24
- return;
25
- if (!nextInbox.ok) {
26
- setError(nextInbox.error.message);
27
- return;
28
- }
29
- if (!nextView.ok) {
30
- setError(nextView.error.message);
31
- return;
32
- }
33
- setInbox(nextInbox.value);
34
- setView(nextView.value);
35
- setError(undefined);
36
- }
37
- catch (cause) {
38
- if (active.current && sequence === refreshSequence.current)
39
- setError(cause instanceof Error ? cause.message : String(cause));
40
- }
41
- finally {
42
- if (active.current && sequence === refreshSequence.current)
43
- setLoading(false);
44
- }
45
- };
46
- useEffect(() => {
47
- let listening = true;
48
- active.current = true;
49
- setInbox(undefined);
50
- setView(undefined);
51
- setError(undefined);
52
- setLoading(true);
53
- void refresh();
54
- void (async () => {
55
- let version = 0;
56
- while (listening) {
57
- try {
58
- const changed = await loadChanges({ afterVersion: version });
59
- if (!listening)
60
- return;
61
- if (!changed.ok) {
62
- setError(changed.error.message);
63
- return;
64
- }
65
- if (changed.value.version > version) {
66
- version = changed.value.version;
67
- await refresh();
68
- }
69
- }
70
- catch (cause) {
71
- if (listening)
72
- setError(cause instanceof Error ? cause.message : String(cause));
73
- return;
74
- }
75
- }
76
- })();
77
- return () => {
78
- listening = false;
79
- active.current = false;
80
- refreshSequence.current += 1;
81
- };
82
- }, [workspaceId]);
83
- const channels = useMemo(() => new Map(view?.channels.map(channel => [channel.channelRef, channel]) ?? []), [view]);
84
- const taskNumbers = useMemo(() => new Map(view?.taskNumbers.map(item => [item.taskRef, item.taskNumber]) ?? []), [view]);
85
- return _jsxs("main", { className: css.surface, "data-team-inbox": true, children: [_jsxs("header", { className: css.header, children: [_jsxs("div", { children: [_jsx("h1", { children: t('inbox') }), inbox !== undefined && _jsx("p", { children: inbox.totalUnreadCount === 0 ? t('inboxEmpty') : t('inboxUnreadCount', { count: inbox.totalUnreadCount }) })] }), inbox !== undefined && inbox.totalDirectCount > 0 && _jsx("span", { className: css.directTotal, children: t('inboxDirectCount', { count: inbox.totalDirectCount }) })] }), _jsxs("section", { className: css.list, "aria-label": t('inbox'), children: [loading && inbox === undefined && error === undefined && _jsx("p", { className: css.state, children: t('loadingInbox') }), !loading && inbox?.items.length === 0 && error === undefined && _jsx("p", { className: css.state, children: t('inboxEmpty') }), error !== undefined && _jsxs("div", { className: css.error, role: "alert", children: [_jsx("span", { children: error }), _jsx(Button, { size: "sm", variant: "outline", onClick: () => { void refresh(true); }, children: t('retry') })] }), inbox?.items.map(item => {
86
- const channel = channels.get(item.channelRef);
87
- const taskNumber = taskNumbers.get(item.task.taskRef);
88
- return _jsxs("button", { type: "button", className: css.item, onClick: () => { selectThread(item.task.taskRef, item.thread.threadRef, item.channelRef, taskNumber); }, children: [_jsx("span", { className: css.priority, "data-direct": item.directCount > 0, "aria-hidden": "true" }), _jsxs("span", { className: css.copy, children: [_jsx("strong", { children: taskNumber === undefined ? t('task') : `Task #${taskNumber}` }), _jsxs("small", { children: [channel === undefined ? t('channelUnknown') : `# ${channel.name}`, " \u00B7 ", formatTaskStatus(item.task.status, t)] })] }), _jsxs("span", { className: css.count, "aria-label": `${t('inboxUnreadCount', { count: item.unreadCount })}${item.directCount > 0 ? `, ${t('inboxDirectCount', { count: item.directCount })}` : ''}`, children: [t('inboxUnreadCount', { count: item.unreadCount }), item.directCount > 0 && _jsxs(_Fragment, { children: [" \u00B7 ", t('inboxDirectCount', { count: item.directCount })] })] })] }, item.thread.threadRef);
89
- })] })] });
90
- }