@roaming-ai/dsh-group-chat 0.2.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 (136) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +56 -0
  3. package/cordis.patch.yml +12 -0
  4. package/lib/client.js +3308 -0
  5. package/lib/client.js.map +1 -0
  6. package/lib/index.js +2583 -0
  7. package/lib/types/client/Bubble.d.ts +10 -0
  8. package/lib/types/client/Glyph.d.ts +12 -0
  9. package/lib/types/client/GroupChatPanel.d.ts +10 -0
  10. package/lib/types/client/GroupChatPanel.old.d.ts +10 -0
  11. package/lib/types/client/GroupChatSettingsSection.d.ts +15 -0
  12. package/lib/types/client/PermissionSelect.d.ts +13 -0
  13. package/lib/types/client/RoleDrawer.d.ts +17 -0
  14. package/lib/types/client/ThinkRow.d.ts +9 -0
  15. package/lib/types/client/ToolRow.d.ts +9 -0
  16. package/lib/types/client/api.d.ts +8 -0
  17. package/lib/types/client/components/AsidePanel.d.ts +31 -0
  18. package/lib/types/client/components/Bubble.d.ts +19 -0
  19. package/lib/types/client/components/ChatPanel.d.ts +57 -0
  20. package/lib/types/client/components/Composer.d.ts +48 -0
  21. package/lib/types/client/components/Glyph.d.ts +12 -0
  22. package/lib/types/client/components/GroupChatSettingsSection.d.ts +15 -0
  23. package/lib/types/client/components/MessageFlow.d.ts +15 -0
  24. package/lib/types/client/components/NavPanel.d.ts +40 -0
  25. package/lib/types/client/components/PermissionSelect.d.ts +13 -0
  26. package/lib/types/client/components/RoleDrawer.d.ts +17 -0
  27. package/lib/types/client/components/ThinkRow.d.ts +9 -0
  28. package/lib/types/client/components/ToolRow.d.ts +9 -0
  29. package/lib/types/client/components/index.d.ts +9 -0
  30. package/lib/types/client/components.d.ts +22 -0
  31. package/lib/types/client/drawer.d.ts +17 -0
  32. package/lib/types/client/glyph.d.ts +12 -0
  33. package/lib/types/client/hooks/index.d.ts +6 -0
  34. package/lib/types/client/hooks/useComposer.d.ts +27 -0
  35. package/lib/types/client/hooks/useFileSearch.d.ts +19 -0
  36. package/lib/types/client/hooks/useGroupChatState.d.ts +95 -0
  37. package/lib/types/client/hooks/useMentionState.d.ts +27 -0
  38. package/lib/types/client/index.d.ts +52 -0
  39. package/lib/types/client/lib/api.d.ts +8 -0
  40. package/lib/types/client/lib/model.d.ts +80 -0
  41. package/lib/types/client/lib/styles.d.ts +10 -0
  42. package/lib/types/client/lib/ui.d.ts +17 -0
  43. package/lib/types/client/model.d.ts +78 -0
  44. package/lib/types/client/panel.d.ts +10 -0
  45. package/lib/types/client/settings.d.ts +15 -0
  46. package/lib/types/client/styles.d.ts +10 -0
  47. package/lib/types/client/ui.d.ts +17 -0
  48. package/lib/types/client/utils/utils.d.ts +29 -0
  49. package/lib/types/client/utils.d.ts +22 -0
  50. package/lib/types/core/json.d.ts +9 -0
  51. package/lib/types/core/status.d.ts +18 -0
  52. package/lib/types/core/tools.d.ts +59 -0
  53. package/lib/types/core/types.d.ts +256 -0
  54. package/lib/types/host/actions.d.ts +34 -0
  55. package/lib/types/host/api/actions.d.ts +36 -0
  56. package/lib/types/host/api/http.d.ts +16 -0
  57. package/lib/types/host/api/index.d.ts +7 -0
  58. package/lib/types/host/api/routes.d.ts +11 -0
  59. package/lib/types/host/broadcast.d.ts +20 -0
  60. package/lib/types/host/conversation.d.ts +25 -0
  61. package/lib/types/host/engine/conversation.d.ts +25 -0
  62. package/lib/types/host/engine/index.d.ts +7 -0
  63. package/lib/types/host/engine/retitle.d.ts +20 -0
  64. package/lib/types/host/http.d.ts +16 -0
  65. package/lib/types/host/index.d.ts +8 -0
  66. package/lib/types/host/materials/index.d.ts +6 -0
  67. package/lib/types/host/materials/materials.d.ts +40 -0
  68. package/lib/types/host/materials.d.ts +32 -0
  69. package/lib/types/host/persistence/index.d.ts +6 -0
  70. package/lib/types/host/persistence/persistence.d.ts +31 -0
  71. package/lib/types/host/persistence/store.d.ts +65 -0
  72. package/lib/types/host/persistence.d.ts +31 -0
  73. package/lib/types/host/routes.d.ts +11 -0
  74. package/lib/types/host/service.d.ts +28 -0
  75. package/lib/types/host/state.d.ts +45 -0
  76. package/lib/types/host/store.d.ts +65 -0
  77. package/lib/types/host/tools/index.d.ts +6 -0
  78. package/lib/types/host/tools/tools.d.ts +28 -0
  79. package/lib/types/host/tools.d.ts +28 -0
  80. package/lib/types/index.d.ts +41 -0
  81. package/lib/types/mount-once.d.ts +9 -0
  82. package/lib/types/shared/file-mention-grammar.d.ts +37 -0
  83. package/lib/types/shared/file-mention-grammar.test.d.ts +5 -0
  84. package/package.json +98 -0
  85. package/src/client/GroupChatPanel.tsx +385 -0
  86. package/src/client/components/AsidePanel.tsx +188 -0
  87. package/src/client/components/Bubble.tsx +76 -0
  88. package/src/client/components/ChatPanel.tsx +214 -0
  89. package/src/client/components/Composer.tsx +238 -0
  90. package/src/client/components/Glyph.tsx +27 -0
  91. package/src/client/components/GroupChatSettingsSection.tsx +74 -0
  92. package/src/client/components/MessageFlow.tsx +97 -0
  93. package/src/client/components/NavPanel.tsx +249 -0
  94. package/src/client/components/PermissionSelect.tsx +159 -0
  95. package/src/client/components/RoleDrawer.tsx +186 -0
  96. package/src/client/components/ThinkRow.tsx +32 -0
  97. package/src/client/components/ToolRow.tsx +51 -0
  98. package/src/client/components/index.ts +10 -0
  99. package/src/client/hooks/index.ts +7 -0
  100. package/src/client/hooks/useComposer.ts +272 -0
  101. package/src/client/hooks/useFileSearch.ts +115 -0
  102. package/src/client/hooks/useGroupChatState.ts +214 -0
  103. package/src/client/hooks/useMentionState.ts +56 -0
  104. package/src/client/index.ts +110 -0
  105. package/src/client/lib/api.ts +23 -0
  106. package/src/client/lib/model.ts +119 -0
  107. package/src/client/lib/styles.ts +317 -0
  108. package/src/client/lib/ui.ts +27 -0
  109. package/src/client/react-dom-shim.d.ts +13 -0
  110. package/src/client/utils/utils.ts +104 -0
  111. package/src/core/json.ts +28 -0
  112. package/src/core/status.ts +33 -0
  113. package/src/core/tools.ts +41 -0
  114. package/src/core/types.ts +222 -0
  115. package/src/host/api/actions.ts +335 -0
  116. package/src/host/api/http.ts +80 -0
  117. package/src/host/api/index.ts +8 -0
  118. package/src/host/api/routes.ts +95 -0
  119. package/src/host/broadcast.ts +65 -0
  120. package/src/host/engine/conversation.ts +331 -0
  121. package/src/host/engine/index.ts +8 -0
  122. package/src/host/engine/retitle.ts +135 -0
  123. package/src/host/index.ts +9 -0
  124. package/src/host/materials/index.ts +7 -0
  125. package/src/host/materials/materials.ts +193 -0
  126. package/src/host/persistence/index.ts +7 -0
  127. package/src/host/persistence/persistence.ts +311 -0
  128. package/src/host/persistence/store.ts +375 -0
  129. package/src/host/service.ts +78 -0
  130. package/src/host/state.ts +85 -0
  131. package/src/host/tools/index.ts +7 -0
  132. package/src/host/tools/tools.ts +194 -0
  133. package/src/index.ts +99 -0
  134. package/src/mount-once.ts +49 -0
  135. package/src/shared/file-mention-grammar.test.ts +77 -0
  136. package/src/shared/file-mention-grammar.ts +82 -0
@@ -0,0 +1,65 @@
1
+ /**
2
+ * 持久化(PERSISTENCE.md v2.1:会话级文件隔离)。
3
+ *
4
+ * 目录布局(每群组一目录,一会话一文件):
5
+ * <dir>/ledger.json 群组/会话清单(schema 3,纯清单,pretty;群组含 permissionTier)
6
+ * <dir>/<group-id>/workspaceDir 工作区目录设置(纯文本一行)
7
+ * <dir>/<group-id>/roles.json 群组角色(schema 1,紧凑)
8
+ * <dir>/<group-id>/sessions/session-<uuid>.json 会话(schema 1,自包含,紧凑)
9
+ *
10
+ * 原子写 tmp+fsync+rename(每目录一次 fsync);单实例 .lock;损坏隔离重建;
11
+ * 写失败保留脏标记;v1 自动迁移。
12
+ * @module dsh-group-chat/host/persistence/store
13
+ */
14
+ import type { GroupRecord } from '../../core/types.ts';
15
+ /** DSH 主目录;DSH_GROUP_CHAT_STORE 供测试覆盖存储位置。 */
16
+ export declare const DSH_HOME: string;
17
+ /** 存储根目录。 */
18
+ export declare const STORE_DIR: string;
19
+ /** 会话文件名 → 会话 id。 */
20
+ export declare function sessionFileMatch(name: string): string | null;
21
+ export declare class Store {
22
+ readonly dir: string;
23
+ readonly ledgerFile: string;
24
+ private readonly lockFile;
25
+ private lockFd;
26
+ constructor(dir: string);
27
+ groupDir(groupId: string): string;
28
+ sessionsDir(groupId: string): string;
29
+ sessionFile(groupId: string, sessionId: string): string;
30
+ rolesFile(groupId: string): string;
31
+ workspaceFile(groupId: string): string;
32
+ private acquireLock;
33
+ release(): void;
34
+ fsyncDir(dir: string): void;
35
+ /** 原子写:tmp+fsync+rename;目录 fsync 由调用方按 flush 批量执行(每目录一次)。 */
36
+ atomicWrite(file: string, text: string): void;
37
+ quarantine(file: string): void;
38
+ /** 读 JSON;缺失返回 null;损坏则隔离后返回 null。 */
39
+ loadJson(file: string): unknown;
40
+ readWorkspace(groupId: string): string;
41
+ /** hydrate 残留清理:.tmp-* 删除;同前缀 .corrupt-* 只保留最近 1 份。 */
42
+ cleanup(): void;
43
+ /** v1(ledger+messages 双文件)→ v2 一次性迁移;幂等,messages.json 只归档从不删除。 */
44
+ migrateV1(): void;
45
+ }
46
+ /** ledger 清单的读取形态(hydrate 用;allowCommands 为 v2 遗留字段,读取时经 migrateTier 迁移)。 */
47
+ export interface LedgerDocument {
48
+ schema?: number;
49
+ groups?: {
50
+ id: string;
51
+ name?: string;
52
+ permissionTier?: string;
53
+ allowCommands?: boolean;
54
+ }[];
55
+ sessions?: {
56
+ id: string;
57
+ groupId: string;
58
+ }[];
59
+ }
60
+ /** 从磁盘目录回收群组 id 列表(ledger 缺失/损坏时的兜底路径)。 */
61
+ export declare function scanGroupIds(dir: string): string[];
62
+ /** 扫描群组目录下的会话文件(ledger 缺失/损坏时的兜底路径)。 */
63
+ export declare function scanSessionIds(store: Store, groupId: string): string[];
64
+ /** 空群组记录构造(hydrate 兜底路径用)。 */
65
+ export declare function emptyGroup(id: string, name: string): GroupRecord;
@@ -0,0 +1,31 @@
1
+ /**
2
+ * 持久化(PERSISTENCE.md v2.1):事件驱动脏标记合并落盘 + 启动恢复。
3
+ * 锁失败/写失败时降级为内存态运行(console 告警)。
4
+ * @module dsh-group-chat/host/persistence
5
+ */
6
+ import type { HostState } from './state.ts';
7
+ /** 持久化面。 */
8
+ export interface Persistence {
9
+ /** 事件驱动落盘;同一 tick 内多次变更合并为一次写。 */
10
+ schedulePersist: (targets?: {
11
+ ledger?: boolean;
12
+ session?: string | null;
13
+ roles?: string | null;
14
+ workspace?: string | null;
15
+ }) => void;
16
+ /** 同步 flush:写全部脏文件(dispose 最终落盘用)。 */
17
+ flushNow: () => void;
18
+ /** 删除群组/会话后摘除脏标记(对应文件已删/将删,flush 跳过)。 */
19
+ dropDirty: (targets: {
20
+ session?: string | null;
21
+ roles?: string | null;
22
+ workspace?: string | null;
23
+ }) => void;
24
+ /** dispose:同步最终 flush → 释放锁 → 摘除句柄。 */
25
+ release: () => void;
26
+ }
27
+ /**
28
+ * 创建持久化面:构造即完成 store 初始化 + hydrate(v1 迁移 → 残留清理 →
29
+ * 清单 → 群组数据 → 会话文件;缺文件空重建;补建默认会话/群组立即落盘)。
30
+ */
31
+ export declare function createPersistence(core: HostState): Persistence;
@@ -0,0 +1,11 @@
1
+ /**
2
+ * HTTP 路由(经 webServer 暴露):
3
+ * GET /api/group-chat/state 全量快照
4
+ * POST /api/group-chat/action { kind: mutate|send|stop|models|preview, ... }
5
+ * GET /api/group-chat/events SSE,状态变化时推送节流后的全量快照
6
+ * @module dsh-group-chat/host/routes
7
+ */
8
+ import type { WebRoute } from '@deepseek-ai/dsh-host-webserver';
9
+ import type { GroupChatService } from './service.ts';
10
+ /** 构建群聊的三条 HTTP 路由。 */
11
+ export declare function makeGroupChatRoutes(service: GroupChatService): WebRoute[];
@@ -0,0 +1,28 @@
1
+ /**
2
+ * 群聊宿主服务(组合根):装配各层模块并暴露对路由/入口的面。
3
+ * 目录分层(对齐 src/client 的分层模式:每层一目录 + index.ts barrel):
4
+ * state.ts 共享状态容器(四张表 + run + 可变槽位;kernel,根级)
5
+ * broadcast.ts SSE 广播(节流)+ touch + 全量快照(kernel 读模型,根级)
6
+ * persistence/ 持久化(store 文件原语 + 脏标记合并落盘 + 启动恢复)
7
+ * materials/ 资料读取与路径解析 + 目录浏览器
8
+ * tools/ 工具执行(沙箱 + 确认闸门)
9
+ * engine/ 对话引擎(conversation:speak/runLoop;retitle:标题整理)
10
+ * api/ HTTP 传输(http 护栏 + routes 路由)与动作分发(actions)
11
+ * @module dsh-group-chat/host/service
12
+ */
13
+ import type { Context } from '@deepseek-ai/cordis';
14
+ import type { Snapshot } from '../core/types.ts';
15
+ /** 服务对路由/入口暴露的面。 */
16
+ export interface GroupChatService {
17
+ snapshot(): Snapshot;
18
+ handleAction(body: unknown): Promise<unknown>;
19
+ subscribePush(push: () => void): () => void;
20
+ /** 设置停用时中止正在进行的群聊。 */
21
+ stopAll(): void;
22
+ /** 卸载/热重载:唤醒确认等待 + kill 子进程 → 同步最终 flush → 释放锁。 */
23
+ dispose(): void;
24
+ }
25
+ /**
26
+ * 创建群聊宿主服务(装配各模块;持久化锁失败时降级内存态运行)。
27
+ */
28
+ export declare function createGroupChatService(ctx: Context): GroupChatService;
@@ -0,0 +1,45 @@
1
+ /**
2
+ * 群聊宿主服务共享状态容器:四张表 + run(对话进行时状态)+ 可变槽位
3
+ * (store / revision / idSeq / lastCreated)。各功能模块(persistence /
4
+ * broadcast / materials / tools / conversation / actions)以工厂装配到同一
5
+ * 容器上,模块间只经显式依赖传递;容器本身只含数据与稳定引用,不含行为。
6
+ * @module dsh-group-chat/host/state
7
+ */
8
+ import type { Context } from '@deepseek-ai/cordis';
9
+ import type { Store } from './persistence/store.ts';
10
+ import type { GroupRecord, LastCreated, MessageRecord, RoleRecord, RunState, SessionRecord } from '../core/types.ts';
11
+ declare module '@deepseek-ai/cordis' {
12
+ interface Context {
13
+ agentDefaultModel?: {
14
+ currentSelection(): {
15
+ provider: string;
16
+ model: string;
17
+ };
18
+ };
19
+ }
20
+ }
21
+ /** 角色标识色板(新增角色依序取色)。 */
22
+ export declare const PALETTE: string[];
23
+ /** 宿主服务共享状态容器(见模块注释;可变原始值一律经 core.* 访问)。 */
24
+ export interface HostState {
25
+ ctx: Context;
26
+ llm: Context['llm'];
27
+ fs: Context['fs'];
28
+ groups: Map<string, GroupRecord>;
29
+ sessions: Map<string, SessionRecord>;
30
+ roles: Map<string, RoleRecord>;
31
+ messages: Map<string, MessageRecord>;
32
+ run: RunState;
33
+ /** 持久化句柄;锁失败降级内存态为 null,dispose 后置 null。 */
34
+ store: Store | null;
35
+ /** 快照版本号:touch() 递增。 */
36
+ revision: number;
37
+ /** id 序号(hydrate 后推进到历史最大值 + 1)。 */
38
+ idSeq: number;
39
+ nid: (p: string) => string;
40
+ /** 最近一次创建的群组/会话,供客户端定位选中项。 */
41
+ lastCreated: LastCreated | null;
42
+ newSession: (groupId: string, name?: string) => SessionRecord;
43
+ }
44
+ /** 创建共享状态容器(仅数据与稳定引用,不含行为)。 */
45
+ export declare function createHostState(ctx: Context): HostState;
@@ -0,0 +1,65 @@
1
+ /**
2
+ * 持久化(PERSISTENCE.md v2.1:会话级文件隔离)。
3
+ *
4
+ * 目录布局(每群组一目录,一会话一文件):
5
+ * <dir>/ledger.json 群组/会话清单(schema 3,纯清单,pretty;群组含 permissionTier)
6
+ * <dir>/<group-id>/workspaceDir 工作区目录设置(纯文本一行)
7
+ * <dir>/<group-id>/roles.json 群组角色(schema 1,紧凑)
8
+ * <dir>/<group-id>/sessions/session-<uuid>.json 会话(schema 1,自包含,紧凑)
9
+ *
10
+ * 原子写 tmp+fsync+rename(每目录一次 fsync);单实例 .lock;损坏隔离重建;
11
+ * 写失败保留脏标记;v1 自动迁移。
12
+ * @module dsh-group-chat/host/store
13
+ */
14
+ import type { GroupRecord } from '../core/types.ts';
15
+ /** DSH 主目录;DSH_GROUP_CHAT_STORE 供测试覆盖存储位置。 */
16
+ export declare const DSH_HOME: string;
17
+ /** 存储根目录。 */
18
+ export declare const STORE_DIR: string;
19
+ /** 会话文件名 → 会话 id。 */
20
+ export declare function sessionFileMatch(name: string): string | null;
21
+ export declare class Store {
22
+ readonly dir: string;
23
+ readonly ledgerFile: string;
24
+ private readonly lockFile;
25
+ private lockFd;
26
+ constructor(dir: string);
27
+ groupDir(groupId: string): string;
28
+ sessionsDir(groupId: string): string;
29
+ sessionFile(groupId: string, sessionId: string): string;
30
+ rolesFile(groupId: string): string;
31
+ workspaceFile(groupId: string): string;
32
+ private acquireLock;
33
+ release(): void;
34
+ fsyncDir(dir: string): void;
35
+ /** 原子写:tmp+fsync+rename;目录 fsync 由调用方按 flush 批量执行(每目录一次)。 */
36
+ atomicWrite(file: string, text: string): void;
37
+ quarantine(file: string): void;
38
+ /** 读 JSON;缺失返回 null;损坏则隔离后返回 null。 */
39
+ loadJson(file: string): unknown;
40
+ readWorkspace(groupId: string): string;
41
+ /** hydrate 残留清理:.tmp-* 删除;同前缀 .corrupt-* 只保留最近 1 份。 */
42
+ cleanup(): void;
43
+ /** v1(ledger+messages 双文件)→ v2 一次性迁移;幂等,messages.json 只归档从不删除。 */
44
+ migrateV1(): void;
45
+ }
46
+ /** ledger 清单的读取形态(hydrate 用;allowCommands 为 v2 遗留字段,读取时经 migrateTier 迁移)。 */
47
+ export interface LedgerDocument {
48
+ schema?: number;
49
+ groups?: {
50
+ id: string;
51
+ name?: string;
52
+ permissionTier?: string;
53
+ allowCommands?: boolean;
54
+ }[];
55
+ sessions?: {
56
+ id: string;
57
+ groupId: string;
58
+ }[];
59
+ }
60
+ /** 从磁盘目录回收群组 id 列表(ledger 缺失/损坏时的兜底路径)。 */
61
+ export declare function scanGroupIds(dir: string): string[];
62
+ /** 扫描群组目录下的会话文件(ledger 缺失/损坏时的兜底路径)。 */
63
+ export declare function scanSessionIds(store: Store, groupId: string): string[];
64
+ /** 空群组记录构造(hydrate 兜底路径用)。 */
65
+ export declare function emptyGroup(id: string, name: string): GroupRecord;
@@ -0,0 +1,6 @@
1
+ /**
2
+ * 工具执行层统一导出
3
+ * @module dsh-group-chat/host/tools
4
+ */
5
+ export { createTools } from './tools.ts';
6
+ export type { Tools } from './tools.ts';
@@ -0,0 +1,28 @@
1
+ /**
2
+ * 工具执行(TOOLS.md §2:沙箱 / §3:确认闸门):read_file / list_dir /
3
+ * run_command 三件套;realpath 硬边界 + 分隔符比较;run_command 按群组
4
+ * 权限档位走逐条确认或直接执行。
5
+ * @module dsh-group-chat/host/tools
6
+ */
7
+ import { TOOL_SCHEMAS } from '../../core/tools.ts';
8
+ import type { GroupRecord, ToolExecution } from '../../core/types.ts';
9
+ import type { HostState } from '../state.ts';
10
+ /** 工具面。 */
11
+ export interface Tools {
12
+ /** 执行一次工具调用(args 解析 + 分发 + 计时;确认闸门在 run_command 内)。 */
13
+ executeTool: (g: GroupRecord, root: string, tc: {
14
+ id: string;
15
+ name: string;
16
+ args: string;
17
+ }) => Promise<ToolExecution>;
18
+ /** 工具 schema(view_only 档剔除 run_command)。 */
19
+ buildToolSchemas: (g: GroupRecord) => (typeof TOOL_SCHEMAS)[number][];
20
+ /** 置 pendingConfirm 后无限等待,confirmCommand/stop/dispose 唤醒。 */
21
+ requestConfirmation: (toolCallId: string, args: Record<string, unknown>) => Promise<boolean>;
22
+ /** 唤醒确认等待(以拒绝放行;置空 pendingConfirm)。 */
23
+ wakeConfirm: () => void;
24
+ /** kill 正在执行的命令子进程。 */
25
+ killChild: () => void;
26
+ }
27
+ /** 创建工具面。 */
28
+ export declare function createTools(core: HostState, touch: () => void): Tools;
@@ -0,0 +1,28 @@
1
+ /**
2
+ * 工具执行(TOOLS.md §2:沙箱 / §3:确认闸门):read_file / list_dir /
3
+ * run_command 三件套;realpath 硬边界 + 分隔符比较;run_command 按群组
4
+ * 权限档位走逐条确认或直接执行。
5
+ * @module dsh-group-chat/host/tools
6
+ */
7
+ import { TOOL_SCHEMAS } from '../core/tools.ts';
8
+ import type { GroupRecord, ToolExecution } from '../core/types.ts';
9
+ import type { HostState } from './state.ts';
10
+ /** 工具面。 */
11
+ export interface Tools {
12
+ /** 执行一次工具调用(args 解析 + 分发 + 计时;确认闸门在 run_command 内)。 */
13
+ executeTool: (g: GroupRecord, root: string, tc: {
14
+ id: string;
15
+ name: string;
16
+ args: string;
17
+ }) => Promise<ToolExecution>;
18
+ /** 工具 schema(view_only 档剔除 run_command)。 */
19
+ buildToolSchemas: (g: GroupRecord) => (typeof TOOL_SCHEMAS)[number][];
20
+ /** 置 pendingConfirm 后无限等待,confirmCommand/stop/dispose 唤醒。 */
21
+ requestConfirmation: (toolCallId: string, args: Record<string, unknown>) => Promise<boolean>;
22
+ /** 唤醒确认等待(以拒绝放行;置空 pendingConfirm)。 */
23
+ wakeConfirm: () => void;
24
+ /** kill 正在执行的命令子进程。 */
25
+ killChild: () => void;
26
+ }
27
+ /** 创建工具面。 */
28
+ export declare function createTools(core: HostState, touch: () => void): Tools;
@@ -0,0 +1,41 @@
1
+ /**
2
+ * dsh-group-chat — DSH 模型群聊(host 平面组合插件,host + client 双半)。
3
+ *
4
+ * Host 半职责:
5
+ * - 群组 / 会话 / 角色 / 消息的状态机,会话级文件持久化于
6
+ * ~/.dsh/storages/group-chat/(PERSISTENCE.md v2.1:每群组一目录,
7
+ * sessions/session-<uuid>.json 一会话一文件;roles.json 与 workspaceDir
8
+ * 随群组目录;ledger.json 纯清单;原子写 tmp+fsync+rename(每目录一次
9
+ * fsync);单实例 .lock;损坏隔离重建;写失败保留脏标记;v1 自动迁移)
10
+ * 数据模型:Group 1..N Session,消息挂在会话上;角色与工作区目录挂在群组上
11
+ * - 群组与会话的增删改;群组/会话检索由客户端在快照上过滤
12
+ * - 角色发言经 `llm` 服务流式生成,按角色绑定的 provider/model 路由
13
+ * - 群组工作区目录经 `fs` 服务读取(根下一层文本文件,最多 20 个),
14
+ * 以「共享资料」块注入每个角色的 system 提示词;无独立笔记/文件清单
15
+ * - 经 `webServer` 暴露 HTTP API:
16
+ * GET /api/group-chat/state 全量快照
17
+ * POST /api/group-chat/action { kind: mutate|send|stop|confirmCommand|models|efforts|browse|fileSearch, ... }
18
+ * GET /api/group-chat/events SSE,状态变化时推送节流后的全量快照
19
+ *
20
+ * 设置命名空间 `group-chat`(settings.yaml 持久化):`enabled` 控制浏览器半
21
+ * 的侧边栏入口与主面板挂载;关闭时会中止正在进行的群聊。
22
+ *
23
+ * @module dsh-group-chat
24
+ */
25
+ import type { Context } from '@deepseek-ai/cordis';
26
+ import type { SettingsNamespace } from '@deepseek-ai/dsh-settings';
27
+ import z from 'schemastery';
28
+ export declare const name = "group-chat";
29
+ export declare const inject: string[];
30
+ /** 设置命名空间;浏览器半拼写同一值,两边不共享代码。 */
31
+ export declare const SETTINGS_NAMESPACE: SettingsNamespace;
32
+ export interface Config {
33
+ enabled?: boolean;
34
+ }
35
+ /** 设置 schema:目前只有启停一个开关。 */
36
+ export declare const Config: z<Config>;
37
+ /**
38
+ * Host 半插件体:状态机服务 + HTTP 路由 + 设置接入。
39
+ * mountOnce 保证同名包每进程至多挂载一次(bundle 聚合与独立安装并存场景)。
40
+ */
41
+ export declare const apply: (ctx: Context, config?: Config) => void;
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Wrap a cordis plugin apply so the package runs at most once per process.
3
+ * The first mount registers normally and unmarks when its fiber disposes;
4
+ * any later mount of the same package name is a no-op.
5
+ * @param packageName - npm package identity shared by every install source.
6
+ * @param fn - the original plugin apply.
7
+ * @returns an apply of the same shape.
8
+ */
9
+ export declare function mountOnce<T extends (...args: any[]) => unknown>(packageName: string, fn: T): T;
@@ -0,0 +1,37 @@
1
+ /**
2
+ * Vendored @file token grammar from dsh-file-reference (browser-safe, zero Node API).
3
+ *
4
+ * Sourced from @deepseek-ai/dsh-file-reference/lib/types/grammar.js
5
+ * Cannot import directly due to client bundle purity gate (dsh-client-bundle-purity).
6
+ *
7
+ * @module dsh-group-chat/shared
8
+ */
9
+ export interface AtToken {
10
+ /** Full matched prefix including @ and optional quotes */
11
+ prefix: string;
12
+ /** Query fragment after @ (unquoted content) */
13
+ query: string;
14
+ /** Whether the token uses quoted form @"..." */
15
+ quoted: boolean;
16
+ }
17
+ export interface FileCandidate {
18
+ kind: 'file' | 'directory';
19
+ path: string;
20
+ }
21
+ /**
22
+ * Extract active @token at cursor position.
23
+ * Matches @ at word boundary (line start or after whitespace).
24
+ *
25
+ * @param line - Current line text
26
+ * @param cursor - Cursor offset in line
27
+ * @returns Token or undefined if no active @token at cursor
28
+ */
29
+ export declare function activeAtToken(line: string, cursor: number): AtToken | undefined;
30
+ /**
31
+ * Format file/directory candidate as @mention text.
32
+ *
33
+ * @param candidate - File or directory to format
34
+ * @param preserveQuote - Keep quotes even when unnecessary (for drill-down continuity)
35
+ * @returns Formatted @path or undefined for invalid paths
36
+ */
37
+ export declare function formatFileMention(candidate: FileCandidate, preserveQuote: boolean): string | undefined;
@@ -0,0 +1,5 @@
1
+ /**
2
+ * @file Tests for vendored @file token grammar.
3
+ * @vitest-environment node
4
+ */
5
+ export {};
package/package.json ADDED
@@ -0,0 +1,98 @@
1
+ {
2
+ "name": "@roaming-ai/dsh-group-chat",
3
+ "description": "DSH 模型群聊:多模型角色群组对话面板。角色绑定不同 provider/model,群内共享对话记录;设置页支持启用/停用。",
4
+ "version": "0.2.0",
5
+ "type": "module",
6
+ "engines": {
7
+ "node": "^22.19.0 || >=24.0.0"
8
+ },
9
+ "main": "lib/index.js",
10
+ "types": "lib/types/index.d.ts",
11
+ "exports": {
12
+ ".": {
13
+ "types": "./lib/types/index.d.ts",
14
+ "default": "./lib/index.js"
15
+ },
16
+ "./client": {
17
+ "types": "./lib/types/client/index.d.ts",
18
+ "default": "./lib/client.js"
19
+ },
20
+ "./src/*": "./src/*",
21
+ "./package.json": "./package.json"
22
+ },
23
+ "files": [
24
+ "lib/**/*.js",
25
+ "lib/**/*.js.map",
26
+ "lib/**/*.d.ts",
27
+ "lib/**/*.d.ts.map",
28
+ "src",
29
+ "cordis.patch.yml",
30
+ "README.md"
31
+ ],
32
+ "license": "MIT",
33
+ "repository": {
34
+ "type": "git",
35
+ "url": "https://github.com/localSummer/dsh-group-chat"
36
+ },
37
+ "keywords": [
38
+ "dsh-plugin",
39
+ "deepseek-harness"
40
+ ],
41
+ "dsh": {
42
+ "engines": {
43
+ "dsh": ">=0.1.5-rc.1"
44
+ },
45
+ "bundle": {
46
+ "patch": "./cordis.patch.yml"
47
+ },
48
+ "client": {
49
+ "platform": "web",
50
+ "inject": [
51
+ "@deepseek-ai/dsh-client-ui-settings",
52
+ "@deepseek-ai/dsh-client-ui-slots",
53
+ "@deepseek-ai/dsh-client-ui-renderer"
54
+ ]
55
+ }
56
+ },
57
+ "dependencies": {
58
+ "@deepseek-ai/dsh-file-reference": "0.1.5-rc.2",
59
+ "@deepseek-ai/dsh-file-reference-local": "0.1.5-rc.2",
60
+ "schemastery": "^3.18.0"
61
+ },
62
+ "peerDependencies": {
63
+ "@deepseek-ai/cordis": "*",
64
+ "react": "^18.2.0"
65
+ },
66
+ "peerDependenciesMeta": {
67
+ "@deepseek-ai/cordis": {
68
+ "optional": true
69
+ }
70
+ },
71
+ "devDependencies": {
72
+ "@deepseek-ai/cordis": "^4.0.2",
73
+ "@deepseek-ai/dsh-client-ui-primitives": "^0.1.5-rc.1",
74
+ "@deepseek-ai/dsh-client-ui-renderer": "^0.1.5-rc.1",
75
+ "@deepseek-ai/dsh-client-ui-settings": "^0.1.5-rc.1",
76
+ "@deepseek-ai/dsh-client-ui-slots": "^0.1.5-rc.1",
77
+ "@deepseek-ai/dsh-fs": "^0.1.5-rc.1",
78
+ "@deepseek-ai/dsh-host-webserver": "^0.1.5-rc.1",
79
+ "@deepseek-ai/dsh-llm": "^0.1.5-rc.1",
80
+ "@deepseek-ai/dsh-settings": "^0.1.5-rc.1",
81
+ "@deepseek-ai/dsh-workspace": "^0.1.5-rc.1",
82
+ "@types/node": "^22.20.0",
83
+ "@types/react": "~18.3.1",
84
+ "lightningcss": "^1.32.0",
85
+ "react": "^18.2.0",
86
+ "tsdown": "^0.22.2",
87
+ "typescript": "^6.0.3",
88
+ "vite-tsconfig-paths": "^6.1.1",
89
+ "vitest": "^4.1.8"
90
+ },
91
+ "scripts": {
92
+ "build": "tsc -p tsconfig.build.json && tsdown",
93
+ "watch": "tsdown --watch",
94
+ "test": "vitest run",
95
+ "typecheck": "tsc --noEmit && tsc -p tsconfig.test.json --pretty false",
96
+ "pack:check": "pnpm build && pnpm pack --dry-run"
97
+ }
98
+ }