@suifei/dsh-ai-team 0.3.11 → 0.3.12

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/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.3.12 — 2026-11-10
4
+
5
+ - 点击成员名字直接打开该 Agent 的 DSH 原生 Session,可与它直接对话;
6
+ - 没有 session 的空闲成员会先激活再打开;
7
+ - 「⋯」仍打开成员资料,资料内也增加「直接对话」按钮。
8
+
3
9
  ## 0.3.11 — 2026-11-10
4
10
 
5
11
  - 修复空闲默认成员不接收 Main stream:owner 无 session 时先自动激活,再记录 `wake/delivered`;
package/README.md CHANGED
@@ -103,7 +103,7 @@ dsh --profile ai-team --no-open --port 33271
103
103
  | 收件箱 | Human/Agent 各自拉取;跨 Project 聚合与项目内 ack |
104
104
  | 关注 | 关注 Task;完成后收到 `followed_task_update` |
105
105
  | 默认成员 | 新 Project 初始化墨渊 / 青岚 / 白砚;可改名、改职责、改个性、改模型 |
106
- | 成员 | 持久 session;名字/角色/personality/notes/skills;空闲 owner 收到 Main stream 会自动激活 |
106
+ | 成员 | 持久 session;点击名字直接打开该 Agent 的 DSH Session 对话;「⋯」编辑资料 |
107
107
  | 模型 | Provider / Model 下拉读取 DSH `llm` 目录;可跟随系统默认 |
108
108
  | 进化 | `team.evolve` 只改自己的 personality;验收后 reflection wake |
109
109
  | 人才库 | leave/rejoin;遗留 Task 可被接管(taken-over) |
package/client.js CHANGED
@@ -178,8 +178,11 @@ window.__ModuleLoader__.load({
178
178
  projectSwitchMock: 'spike:项目切换只更新视图标题;按项目读取账本在 M1 接入。',
179
179
  archivedMock: 'spike:归档项目只读;取消归档在 M3 接入。',
180
180
  agentMock: 'spike:成员详情(打开会话 / 发消息 / 记忆与技能)在 M3 接入。',
181
- agentOpen: '查看 {name} 的详情',
181
+ agentOpen: '与 {name} 对话',
182
182
  moreActions: '更多操作',
183
+ agentChat: '直接对话',
184
+ agentChatOpening: '正在打开对话…',
185
+ agentChatUnavailable: '宿主没有可用的 Session 打开能力。',
183
186
  newProject: '新建项目',
184
187
  addAgent: '添加成员',
185
188
  newProjectMock: 'spike:新建项目属于 S-01 流程,M1 之后接入。',
@@ -465,8 +468,11 @@ window.__ModuleLoader__.load({
465
468
  projectSwitchMock: 'spike: switching projects only updates the header; per-project ledger reads land with M1.',
466
469
  archivedMock: 'spike: archived projects are read-only; unarchive lands with M3.',
467
470
  agentMock: 'spike: member detail (open session / message / memory & skills) lands with M3.',
468
- agentOpen: 'Open details for {name}',
471
+ agentOpen: 'Chat with {name}',
469
472
  moreActions: 'More actions',
473
+ agentChat: 'Direct chat',
474
+ agentChatOpening: 'Opening conversation…',
475
+ agentChatUnavailable: 'This host cannot open a Session.',
470
476
  newProject: 'New project',
471
477
  addAgent: 'Add member',
472
478
  newProjectMock: 'spike: project creation belongs to S-01 and lands after M1.',
@@ -1482,7 +1488,7 @@ window.__ModuleLoader__.load({
1482
1488
  h('span', { className: 'at-prowtitle' }, project.name));
1483
1489
  }
1484
1490
 
1485
- function AgentRow({ t, agent, onAgent }) {
1491
+ function AgentRow({ t, agent, onAgent, onAgentMore }) {
1486
1492
  const statusText = t(AGENT_STATUS[agent.status] ?? 'agentIdle');
1487
1493
  const config = agent.config ?? null;
1488
1494
  const model = config?.model ? config.model : t('agentDefaultModel');
@@ -1510,11 +1516,11 @@ window.__ModuleLoader__.load({
1510
1516
  type: 'button',
1511
1517
  'aria-label': tf(t, 'agentOpen', { name: agent.name }),
1512
1518
  title: t('moreActions'),
1513
- onClick: () => onAgent(agent),
1519
+ onClick: () => onAgentMore(agent),
1514
1520
  }, '⋯'));
1515
1521
  }
1516
1522
 
1517
- function LeftPanel({ t, data, projectId, scope, tab, inboxUnread, onBack, onInbox, onBoard, onProject, onNewProject, onAgent, onAddAgent, onRecruit }) {
1523
+ function LeftPanel({ t, data, projectId, scope, tab, inboxUnread, onBack, onInbox, onBoard, onProject, onNewProject, onAgent, onAgentMore, onAddAgent, onRecruit }) {
1518
1524
  const projects = data.projects.filter((project) => !project.archived);
1519
1525
  const activeAgents = data.agents.filter((agent) => agent.status !== 'retired');
1520
1526
  const talentAgents = data.agents.filter((agent) => agent.status === 'retired');
@@ -1564,7 +1570,7 @@ window.__ModuleLoader__.load({
1564
1570
  h('button', { className: 'at-mini', type: 'button', 'aria-label': t('addAgent'), title: t('addAgent'), onClick: onAddAgent }, h(Ico, { name: 'plus', size: 12 })),
1565
1571
  ),
1566
1572
  activeAgents.length
1567
- ? h('div', { role: 'list', 'aria-label': t('agentsAria') }, activeAgents.map((agent) => h(AgentRow, { key: agent.id, t, agent, onAgent })))
1573
+ ? h('div', { role: 'list', 'aria-label': t('agentsAria') }, activeAgents.map((agent) => h(AgentRow, { key: agent.id, t, agent, onAgent, onAgentMore })))
1568
1574
  : h('div', { className: 'at-colempty' }, t('emptyColumn')),
1569
1575
  talentAgents.length ? h('details', { className: 'at-archived' },
1570
1576
  h('summary', null, tf(t, 'talentPoolCount', { n: talentAgents.length })),
@@ -2389,6 +2395,30 @@ window.__ModuleLoader__.load({
2389
2395
  setMBusy(false);
2390
2396
  }
2391
2397
  }
2398
+ async function openAgentChat(agent) {
2399
+ closeMobile();
2400
+ if (ctx?.uiWorkspace?.openSession === undefined) {
2401
+ say(t('agentChatUnavailable'));
2402
+ openProfile(agent);
2403
+ return;
2404
+ }
2405
+ if (agent.sessionId) {
2406
+ ctx.uiWorkspace.openSession(agent.sessionId);
2407
+ return;
2408
+ }
2409
+ try {
2410
+ say(t('agentChatOpening'));
2411
+ const activated = await runCommand('member.activate', {
2412
+ memberId: agent.id,
2413
+ prompt: '你正在与 Human 直接对话。先简要说明你是谁、当前负责什么;不要创建 Task,除非 Human 明确要求。',
2414
+ });
2415
+ await reloadData();
2416
+ if (activated?.sessionId) ctx.uiWorkspace.openSession(activated.sessionId);
2417
+ } catch (error) {
2418
+ say(tf(t, 'sendFailed', { message: error?.message ?? String(error) }));
2419
+ openProfile(agent);
2420
+ }
2421
+ }
2392
2422
  function openProfile(agent) {
2393
2423
  setProfileAgent(agent);
2394
2424
  setPName(agent.name ?? '');
@@ -2753,7 +2783,8 @@ window.__ModuleLoader__.load({
2753
2783
  onBoard: switchBoard,
2754
2784
  onProject: switchProject,
2755
2785
  onNewProject: () => { closeMobile(); openNewProject(); },
2756
- onAgent: (agent) => { closeMobile(); openProfile(agent); },
2786
+ onAgent: (agent) => { closeMobile(); void openAgentChat(agent); },
2787
+ onAgentMore: (agent) => { closeMobile(); openProfile(agent); },
2757
2788
  onAddAgent: () => { closeMobile(); openAddAgent(); },
2758
2789
  onRecruit: (agent) => { closeMobile(); recruit(agent); },
2759
2790
  };
@@ -3030,6 +3061,7 @@ window.__ModuleLoader__.load({
3030
3061
  pError ? h('div', { className: 'at-modalerror', role: 'alert' }, pError) : null,
3031
3062
  h('div', { className: 'at-modalactions' },
3032
3063
  h('button', { className: 'at-btn', type: 'button', onClick: () => setProfileAgent(null), disabled: pBusy }, t('cancel')),
3064
+ h('button', { className: 'at-btn', type: 'button', onClick: () => { const target = profileAgent; setProfileAgent(null); void openAgentChat(target); } }, t('agentChat')),
3033
3065
  h('button', { className: 'at-btn', type: 'button', onClick: leaveProfile, disabled: pBusy }, t('leaveTeam')),
3034
3066
  profileAgent.status === 'failed' ? h('button', { className: 'at-btn', type: 'button', onClick: retryProfile, disabled: pBusy }, t('retry')) : null,
3035
3067
  h('button', { className: 'at-btn', type: 'button', onClick: distillProfile, disabled: pBusy }, t('redistill')),
package/index.js CHANGED
@@ -33,7 +33,7 @@ export const name = 'ai-team';
33
33
  /** The workbench only makes sense where the Web carrier exists. */
34
34
  export const inject = ['webServer', 'permissionPresets', 'sandboxPolicy'];
35
35
 
36
- const VERSION = '0.3.11';
36
+ const VERSION = '0.3.12';
37
37
  const PROJECT_ID = 'prj_main';
38
38
  const HUMAN_ID = 'mem_human';
39
39
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@suifei/dsh-ai-team",
3
- "version": "0.3.11",
3
+ "version": "0.3.12",
4
4
  "type": "module",
5
5
  "description": "文渊阁 (Wenyuan Pavilion) — AI Team mode for DeepSeek Harness: concurrent projects, owned tasks, threads, inbox and an append-only team ledger",
6
6
  "license": "MIT",