@deepseek-ai/dsh-client-ui-reference 0.1.6-alpha.1 → 0.1.7-alpha.1

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/README.i18n.yaml CHANGED
@@ -2,5 +2,5 @@
2
2
  # side as of the last confirmed-consistent state. Both languages carry equal authority;
3
3
  # after editing either side, bring the other along and re-record with:
4
4
  # pnpm run verify-translation-pairing --write packages/client/ui-reference/README.md
5
- README.md: 1a79a22425fff1c7323a3bcb55afd324decbe5e8
6
- README.zh.md: 7cde5e46e69f008e9fcfffeb3920184d90bddb60
5
+ README.md: 57b5ae2440cf3dd4512cf44361b334dc7f3a58c9
6
+ README.zh.md: fa5af63c939f2bb71f371262dbbf137180c63f8e
package/README.md CHANGED
@@ -51,7 +51,9 @@ The source keeps candidate encoding internal to the registration effect: the `/c
51
51
 
52
52
  ### Candidate flow
53
53
 
54
- For an unquoted token, the browser starts the `fileReferences/list` and `sessionReferenceResolver/candidates` Remote calls together, then deterministically orders files before sessions with locale-registered folder/file/session labels. Rows render under non-selectable file and session section headings without a redundant raw `reference` source title. A session row is dated from the Host session list's `updatedAt` through the same relative-time bucket that list uses, so one session reads the same age on both surfaces; a session the list does not carry falls back to the candidate's creation time. A drilled query publishes a breadcrumb from the workspace root to the directory being listed; each crumb carries the drill payload a folder row would, so returning to a step and descending into one are one outcome.
54
+ For an unquoted token, the browser starts the `fileReferences/list` and `sessionReferenceResolver/candidates` Remote calls together, then deterministically orders files, direct subagents of the current Session, and other Sessions. Rows use the resolver's display title, which prefers a subagent's creation label while ordinary Sessions retain their projected title, and render under locale-owned group headings without a redundant raw `reference` source title. A session row is dated from the Host session list's `updatedAt` through the same relative-time bucket that list uses, so one session reads the same age on both surfaces; a session the list does not carry falls back to the candidate's creation time. A drilled query publishes a breadcrumb from the workspace root to the current directory; each crumb carries the drill payload a folder row would, so returning to a step and descending into one are one outcome.
55
+
56
+ Candidate requests require an existing retained Client Session and share one temporary `referenceCandidates` reference. Both discovery calls wait for that Session's initial history open to succeed; an unretained Session or failed open prevents both RPCs. The candidate request's cancellation signal covers the history wait and both calls, and the temporary reference is released when the lookup settles.
55
57
 
56
58
  ### Serialization
57
59
 
package/README.zh.md CHANGED
@@ -51,7 +51,9 @@ Web 用户需要从同一个 `@` 补全菜单提及文件、文件夹或会话
51
51
 
52
52
  ### 候选流程
53
53
 
54
- 对于未加引号的 token,浏览器会同时启动 `fileReferences/list` 与 `sessionReferenceResolver/candidates` Remote 调用,再以确定性顺序把文件排在会话之前,并使用注册在 locale 字典中的文件夹、文件与会话标签。各行分别渲染在不可选择的文件与会话分组标题下,不显示重复的原始 `reference` source 标题。会话行用宿主会话列表的 `updatedAt` 经该列表相同的相对时间分档标注时间,因此同一个会话在两处读到的时长一致;列表中没有的会话回落到候选自带的创建时间。下钻后的查询会发布一条从工作区根目录到当前所列目录的面包屑;每一节携带的下钻载荷与文件夹行相同,因此「回到某一步」与「进入某一层」是同一个结果。
54
+ 对于未加引号的 token,浏览器会同时启动 `fileReferences/list` 与 `sessionReferenceResolver/candidates` Remote 调用,再按文件、当前 Session 的直接 subagent、其他 Session 的确定性顺序排列。各行使用 resolver 的显示标题;subagent 优先使用创建标签,普通 Session 保持投影标题,并渲染在 locale 管理的分组标题下,不显示重复的原始 `reference` source 标题。会话行用宿主会话列表的 `updatedAt` 经该列表相同的相对时间分档标注时间,因此同一个会话在两处读到的时长一致;列表中没有的会话回落到候选自带的创建时间。下钻后的查询会发布一条从工作区根目录到当前目录的面包屑;每一节携带的下钻载荷与文件夹行相同,因此「回到某一步」与「进入某一层」是同一个结果。
55
+
56
+ 候选请求要求客户端已持有该会话,并共用一个临时的 `referenceCandidates` 引用。两个发现调用都等待该会话首次历史打开成功;未持有会话或打开失败时,均不发送 RPC。候选请求的取消信号同时覆盖历史等待和两个调用,查询结束时释放临时引用。
55
57
 
56
58
  ### 序列化
57
59
 
package/lib/client.js CHANGED
@@ -108,6 +108,7 @@ window.__ModuleLoader__.load({
108
108
  */
109
109
  const zh = {
110
110
  "section.files": "文件与文件夹",
111
+ "section.subagents": "子智能体",
111
112
  "section.sessions": "对话",
112
113
  "candidate.noCwd": "(无工作目录)",
113
114
  "crumb.root": "工作区",
@@ -121,6 +122,7 @@ window.__ModuleLoader__.load({
121
122
  /** English dictionary, checked complete against the zh key set. */
122
123
  const en = {
123
124
  "section.files": "Files & folders",
125
+ "section.subagents": "Subagents",
124
126
  "section.sessions": "Sessions",
125
127
  "candidate.noCwd": "(no cwd)",
126
128
  "crumb.root": "Workspace",
@@ -159,15 +161,36 @@ window.__ModuleLoader__.load({
159
161
  name: "reference",
160
162
  showGroupTitle: false,
161
163
  async candidates(session, { query, quoted, drilled, signal }) {
162
- const fileLookup = ctx.remote.fileReferences.list(session.sessionId, query, signal).then((result) => result.ok ? result.value : []);
163
- const sessionLookup = quoted === true ? Promise.resolve([]) : ctx.remote.sessionReferenceResolver.candidates(session.sessionId, query, signal).then((result) => result.ok ? result.value : []);
164
- const [fileItems, sessionItems] = await Promise.all([fileLookup, sessionLookup]);
164
+ if (sessions.binding(session.sessionId) === void 0) throw new Error(`reference candidates require a retained session "${session.sessionId}"`);
165
+ const [fileItems, sessionItems] = await sessions.using(session.sessionId, {
166
+ source: "referenceCandidates",
167
+ signal
168
+ }, async (reference) => {
169
+ signal.throwIfAborted();
170
+ const state = reference.binding.session.getSnapshot();
171
+ if (state.openState !== "open") throw state.openError ?? /* @__PURE__ */ new Error(`session "${session.sessionId}" is not open`);
172
+ const fileLookup = ctx.remote.fileReferences.list(session.sessionId, query, signal).then((result) => result.ok ? result.value : []);
173
+ const sessionLookup = quoted === true ? Promise.resolve([]) : ctx.remote.sessionReferenceResolver.candidates(session.sessionId, query, signal).then((result) => result.ok ? result.value : []);
174
+ return Promise.all([fileLookup, sessionLookup]);
175
+ });
165
176
  if (signal.aborted) return [];
166
177
  const withLocation = crumbsFor(query, quoted === true, drilled, t) === void 0;
167
178
  const now = Date.now();
168
179
  const home = ctx.remote.$host.home;
169
180
  const listed = sessions.list.getSnapshot().byId;
170
- return [...fileItems.flatMap((candidate) => fileCandidate(candidate, quoted === true, withLocation, t)), ...sessionItems.map((candidate) => sessionCandidate(candidate, listed[candidate.sessionId]?.updatedAt ?? candidate.createdAt, now, home, t))];
181
+ const sessionRows = sessionItems.map((candidate) => {
182
+ const summary = listed[candidate.sessionId];
183
+ const child = summary?.origin === "subagent" && summary.parentId === session.sessionId;
184
+ return {
185
+ child,
186
+ row: sessionCandidate(candidate, candidate.displayTitle ?? candidate.label, summary?.updatedAt ?? candidate.createdAt, now, home, t(child ? "section.subagents" : "section.sessions"), t)
187
+ };
188
+ });
189
+ return [
190
+ ...fileItems.flatMap((candidate) => fileCandidate(candidate, quoted === true, withLocation, t)),
191
+ ...sessionRows.filter((item) => item.child).map((item) => item.row),
192
+ ...sessionRows.filter((item) => !item.child).map((item) => item.row)
193
+ ];
171
194
  },
172
195
  header(_session, req) {
173
196
  return crumbsFor(req.query, req.quoted === true, req.drilled, t);
@@ -277,20 +300,20 @@ window.__ModuleLoader__.load({
277
300
  ...directory ? { drill: true } : {}
278
301
  }];
279
302
  }
280
- function sessionCandidate(candidate, updatedAt, now, home, t) {
303
+ function sessionCandidate(candidate, label, updatedAt, now, home, section, t) {
281
304
  const { unit, n } = (0, _deepseek_ai_dsh_client_ui_primitives.relativeTime)(updatedAt, now);
282
305
  const age = unit === "now" ? t("time.now") : t(`time.${unit}`, { n });
283
306
  const location = candidate.sameWorkspace ? void 0 : candidate.cwd === void 0 ? t("candidate.noCwd") : abbreviateHomePath(candidate.cwd, home);
284
307
  const value = {
285
308
  kind: "session",
286
- label: candidate.label,
309
+ label,
287
310
  mention: candidate.mention
288
311
  };
289
312
  return {
290
- name: candidate.label,
313
+ name: label,
291
314
  description: location === void 0 ? age : `${location} · ${age}`,
292
315
  icon: "session",
293
- section: t("section.sessions"),
316
+ section,
294
317
  value: JSON.stringify(value)
295
318
  };
296
319
  }
@@ -1,4 +1,10 @@
1
1
  import type { Context as ClientContext } from '@deepseek-ai/cordis';
2
+ declare module '@deepseek-ai/dsh-api-session-controller/client' {
3
+ interface SessionReferenceSourceMap {
4
+ /** File and Session candidates waiting for initial history and their RPC results. */
5
+ referenceCandidates: unknown;
6
+ }
7
+ }
2
8
  /** Required services: the trigger registry, the Remote namespaces, and the copy. */
3
9
  export declare const inject: string[];
4
10
  /**
@@ -10,6 +10,7 @@ export declare const NS = "reference";
10
10
  */
11
11
  export declare const zh: {
12
12
  'section.files': string;
13
+ 'section.subagents': string;
13
14
  'section.sessions': string;
14
15
  'candidate.noCwd': string;
15
16
  'crumb.root': string;
@@ -31,6 +32,7 @@ declare module '@deepseek-ai/dsh-client-ui-slots' {
31
32
  /** English dictionary, checked complete against the zh key set. */
32
33
  export declare const en: {
33
34
  'section.files': string;
35
+ 'section.subagents': string;
34
36
  'section.sessions': string;
35
37
  'candidate.noCwd': string;
36
38
  'crumb.root': string;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@deepseek-ai/dsh-client-ui-reference",
3
3
  "description": "Unified Web @file and @session reference source",
4
- "version": "0.1.6-alpha.1",
4
+ "version": "0.1.7-alpha.1",
5
5
  "publishConfig": {
6
6
  "access": "public"
7
7
  },
@@ -40,23 +40,23 @@
40
40
  },
41
41
  "license": "MIT",
42
42
  "peerDependencies": {
43
- "@deepseek-ai/cordis": "^4.0.2"
43
+ "@deepseek-ai/cordis": "^4.0.3"
44
44
  },
45
45
  "devDependencies": {
46
- "@deepseek-ai/dsh-api-remotes": "^0.1.6-alpha.1",
47
- "@deepseek-ai/dsh-api-session-controller": "^0.1.6-alpha.1",
48
- "@deepseek-ai/dsh-client-locale": "^0.1.6-alpha.1",
49
- "@deepseek-ai/dsh-client-connection": "^0.1.6-alpha.1",
50
- "@deepseek-ai/dsh-client-test-runtime": "^0.1.6-alpha.1",
51
- "@deepseek-ai/dsh-client-ui-input-trigger": "^0.1.6-alpha.1",
52
- "@deepseek-ai/dsh-client-ui-slots": "^0.1.6-alpha.1",
53
- "@deepseek-ai/dsh-client-ui-primitives": "^0.1.6-alpha.1",
54
- "@deepseek-ai/dsh-file-reference": "^0.1.6-alpha.1",
55
- "@deepseek-ai/dsh-session-reference": "^0.1.6-alpha.1",
56
- "@deepseek-ai/dsh-typert-protocol": "^0.1.6-alpha.1",
57
- "@deepseek-ai/dsh-util-workspace-path": "^0.1.6-alpha.1",
58
- "@deepseek-ai/cordis": "^4.0.2",
59
- "@deepseek-ai/dsh-client-ui-sidebar-right": "^0.1.6-alpha.1"
46
+ "@deepseek-ai/dsh-api-remotes": "^0.1.7-alpha.1",
47
+ "@deepseek-ai/dsh-api-session-controller": "^0.1.7-alpha.1",
48
+ "@deepseek-ai/dsh-client-connection": "^0.1.7-alpha.1",
49
+ "@deepseek-ai/dsh-client-locale": "^0.1.7-alpha.1",
50
+ "@deepseek-ai/dsh-client-test-runtime": "^0.1.7-alpha.1",
51
+ "@deepseek-ai/dsh-client-ui-input-trigger": "^0.1.7-alpha.1",
52
+ "@deepseek-ai/dsh-client-ui-slots": "^0.1.7-alpha.1",
53
+ "@deepseek-ai/dsh-client-ui-primitives": "^0.1.7-alpha.1",
54
+ "@deepseek-ai/dsh-file-reference": "^0.1.7-alpha.1",
55
+ "@deepseek-ai/dsh-typert-protocol": "^0.1.7-alpha.1",
56
+ "@deepseek-ai/dsh-session-reference": "^0.1.7-alpha.1",
57
+ "@deepseek-ai/cordis": "^4.0.3",
58
+ "@deepseek-ai/dsh-util-workspace-path": "^0.1.7-alpha.1",
59
+ "@deepseek-ai/dsh-client-ui-sidebar-right": "^0.1.7-alpha.1"
60
60
  },
61
61
  "files": [
62
62
  "lib/index.js",