@qilin-agent/client-ui-reference 0.0.0-stage → 3.1.3
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/LICENSE +21 -0
- package/README.i18n.yaml +49 -0
- package/README.md +103 -2
- package/README.zh.md +104 -0
- package/lib/client.js +322 -0
- package/lib/index.js +11 -0
- package/lib/types/client/index.d.ts +9 -0
- package/lib/types/client/locales.d.ts +46 -0
- package/lib/types/index.d.ts +9 -0
- package/package.json +70 -3
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 kkutysllb
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.i18n.yaml
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
# Bilingual-pair consistency record for README.md (docs/i18n/README.md): per heading
|
|
2
|
+
# section, a hash of its English and Chinese blocks outside code blocks and generated regions.
|
|
3
|
+
# After editing either side, bring the other along and re-record with:
|
|
4
|
+
# pnpm run verify-translation-pairing --write packages/client/ui-reference/README.md
|
|
5
|
+
/:
|
|
6
|
+
en: 891fa9f998222b74
|
|
7
|
+
zh: 5eed64a6df09c534
|
|
8
|
+
/qilin-client-ui-reference:
|
|
9
|
+
en: ca103c231ae55c46
|
|
10
|
+
zh: 49521fe0b8b5f1d1
|
|
11
|
+
/qilin-client-ui-reference/summary:
|
|
12
|
+
en: b99e8765f2ead4d0
|
|
13
|
+
zh: 4e45668504acc043
|
|
14
|
+
/qilin-client-ui-reference/table-of-contents:
|
|
15
|
+
en: d152484eb41ac6b4
|
|
16
|
+
zh: 09388d293f9be9cb
|
|
17
|
+
/qilin-client-ui-reference/use-this-package:
|
|
18
|
+
en: 779a9a534eaad38b
|
|
19
|
+
zh: 3dd159a2c35702d6
|
|
20
|
+
/qilin-client-ui-reference/use-this-package/what-a-pick-inserts:
|
|
21
|
+
en: a06b0309e76b743b
|
|
22
|
+
zh: 9b6e62b78093e8d2
|
|
23
|
+
/qilin-client-ui-reference/use-this-package/failure-behavior:
|
|
24
|
+
en: 228ee6f4b81d96a7
|
|
25
|
+
zh: e1c960c3f5b25317
|
|
26
|
+
/qilin-client-ui-reference/understand-the-implementation:
|
|
27
|
+
en: dbfe93987c800112
|
|
28
|
+
zh: 200d477cc8cd8a1a
|
|
29
|
+
/qilin-client-ui-reference/understand-the-implementation/candidate-flow:
|
|
30
|
+
en: ee3a3b095cecc67b
|
|
31
|
+
zh: 6b47c3f0f50cd423
|
|
32
|
+
/qilin-client-ui-reference/understand-the-implementation/serialization:
|
|
33
|
+
en: b9029bd93e628331
|
|
34
|
+
zh: a8635f62b1db85ba
|
|
35
|
+
/qilin-client-ui-reference/further-exploration:
|
|
36
|
+
en: f6080f05ebc9cd5d
|
|
37
|
+
zh: b340184ea23122f4
|
|
38
|
+
/qilin-client-ui-reference/model-experience:
|
|
39
|
+
en: f7fa58a80d82d63a
|
|
40
|
+
zh: 8235157cbbbd18cf
|
|
41
|
+
/qilin-client-ui-reference/model-experience/kv-cache-effect:
|
|
42
|
+
en: ff23f8026f7c6050
|
|
43
|
+
zh: 6b0841800076bcd2
|
|
44
|
+
/qilin-client-ui-reference/known-limitations-and-deferred-work:
|
|
45
|
+
en: e79991a25b11e342
|
|
46
|
+
zh: 15064e8374c8e63d
|
|
47
|
+
/qilin-client-ui-reference/known-limitations-and-deferred-work/dev-note:
|
|
48
|
+
en: e67f633dc6fe7773
|
|
49
|
+
zh: 3bb0c20c93f16f98
|
package/README.md
CHANGED
|
@@ -1,3 +1,104 @@
|
|
|
1
|
-
|
|
1
|
+
---
|
|
2
|
+
description: "Web @file and @session reference source for the composer: candidates, ordering, and atomic inline references (unified file/session picking)."
|
|
3
|
+
kind: "package-reference"
|
|
4
|
+
---
|
|
2
5
|
|
|
3
|
-
|
|
6
|
+
# @qilin-agent/client-ui-reference
|
|
7
|
+
|
|
8
|
+
English | [中文](README.zh.md)
|
|
9
|
+
|
|
10
|
+
## Summary
|
|
11
|
+
|
|
12
|
+
Use `qilin-client-ui-reference` when Web users need to mention files, folders, or sessions from one `@` completion menu. It lists files before sessions and keeps either group available when the other cannot load. Picking a file, folder, or session inserts an atomic reference with a stable clipboard form; folder rows also let users descend without closing completion. File rows omit redundant root locations, and session rows show a workspace only when it differs from the current one. Session mentions are validated before model context is captured, while browsing candidates has no model effect.
|
|
13
|
+
|
|
14
|
+
## Table of Contents
|
|
15
|
+
|
|
16
|
+
- [Use this package](#use-this-package)
|
|
17
|
+
- [Understand the implementation](#understand-the-implementation)
|
|
18
|
+
- [Further Exploration](#further-exploration)
|
|
19
|
+
- [Model Experience](#model-experience)
|
|
20
|
+
- [Known Limitations and Deferred Work](#known-limitations-and-deferred-work)
|
|
21
|
+
- [Dev Note](#dev-note)
|
|
22
|
+
|
|
23
|
+
-----
|
|
24
|
+
|
|
25
|
+
<a id="use-this-package"></a>
|
|
26
|
+
## Use this package
|
|
27
|
+
|
|
28
|
+
The source is active whenever the composition mounts this package and a Host `ctx.fileReferences` provider is available. Type `@` followed by an unquoted token to see files first, then sessions; open `@"…` to search files only. The candidate list is a completion menu, not a search result page: pick once and keep typing.
|
|
29
|
+
|
|
30
|
+
### What a pick inserts
|
|
31
|
+
|
|
32
|
+
A file closes completion as an atomic inline reference displayed with a file glyph and business-color filename. A directory row carries two verbs: the settling pick (row click or Enter) resolves the folder itself as the same kind of atomic reference — folder glyph, trailing-slash label, canonical `@dir/` mention as its serialized form — while the drill action (Tab or the row's chevron) keeps plain editable path text with a folder glyph and the menu active at its trailing slash, so you can descend another level. Paths containing whitespace use `@"path with spaces"`, and a quote the user opened explicitly remains quoted.
|
|
33
|
+
|
|
34
|
+
A session pick inserts an atomic inline reference whose hidden `ref` and clipboard representation is the canonical `@[label](qilin-session:…)` mention returned by the Host; its visible form is a chat-bubble glyph plus the session title. Sending carries the mention through `session.prompt`, and the session-reference service validates it and captures model context at `agent/pre-step`.
|
|
35
|
+
|
|
36
|
+
### Failure behavior
|
|
37
|
+
|
|
38
|
+
One unavailable or failed candidate domain yields no rows for that domain while the other still lists. A session-reference preparation failure occurs after prompt acceptance and terminates that agent turn.
|
|
39
|
+
|
|
40
|
+
Click a file reference in the composer to preview its current contents in the right Sidebar. Quoted paths retain their spaces, and paths resolve in the composer Session. Folder and Session references retain their editing behavior.
|
|
41
|
+
|
|
42
|
+
-----
|
|
43
|
+
|
|
44
|
+
<a id="understand-the-implementation"></a>
|
|
45
|
+
## Understand the implementation
|
|
46
|
+
|
|
47
|
+
<details>
|
|
48
|
+
<summary>Implementation internals — click to expand</summary>
|
|
49
|
+
|
|
50
|
+
The source keeps candidate encoding internal to the registration effect: the `/client` export is the plugin body (`apply`/`inject`) only.
|
|
51
|
+
|
|
52
|
+
### Candidate flow
|
|
53
|
+
|
|
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
|
+
### Serialization
|
|
57
|
+
|
|
58
|
+
File picks preserve the natural text defined by the shared `@path` grammar as the hidden serialized and clipboard form. Session picks use the canonical `@[label](qilin-session:…)` mention; serialization never reconstructs identity from the visible title.
|
|
59
|
+
|
|
60
|
+
</details>
|
|
61
|
+
|
|
62
|
+
-----
|
|
63
|
+
|
|
64
|
+
<a id="further-exploration"></a>
|
|
65
|
+
## Further Exploration
|
|
66
|
+
|
|
67
|
+
These pages cover the suggestion machinery, the reference seams, and the input pipeline.
|
|
68
|
+
|
|
69
|
+
- [ui-input-trigger](../ui-input-trigger/README.md) — the inline suggestion machinery the source registers into.
|
|
70
|
+
- [file-reference](../../context/file-reference/README.md) — the `@file` seam and its provider contract.
|
|
71
|
+
- [session-reference](../../context/session-reference/README.md) — the `@session` seam and prepared snapshot semantics.
|
|
72
|
+
- [Web input machine and slash pipeline](../../../.agents/notes/archived/architecture/2026-07-25-web-input-machine-and-slash-pipeline.md) — how references and commands share the input machine.
|
|
73
|
+
|
|
74
|
+
-----
|
|
75
|
+
|
|
76
|
+
<a id="model-experience"></a>
|
|
77
|
+
## Model Experience
|
|
78
|
+
|
|
79
|
+
Indirectly, through Host-owned providers, which own the file guidance and session snapshot preparation this package's reference selection delegates to them.
|
|
80
|
+
|
|
81
|
+
#### KV Cache effect
|
|
82
|
+
|
|
83
|
+
Candidate browsing has no model effect. A selected file or session changes only the new user-message suffix and any Host-prepared session-reference context that follows that message; earlier target history remains unchanged.
|
|
84
|
+
|
|
85
|
+
## Known Limitations and Deferred Work
|
|
86
|
+
|
|
87
|
+
<a id="known-limitations-and-deferred-work"></a>
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
These limits define when the reference source cannot help; they are current package constraints.
|
|
91
|
+
|
|
92
|
+
- **Candidate failure is intentionally quiet** — one unavailable or failed Remote discovery call yields no rows for that domain. A session-reference preparation failure occurs after prompt acceptance and terminates that agent turn.
|
|
93
|
+
- **No browser-side file scan** — Web completion requires a mounted Host `ctx.fileReferences` provider; the browser cannot fall back to its own filesystem.
|
|
94
|
+
- **Session search remains metadata-only** — discovery filters session id, cwd, and the latest log-backed title through `ctx.sessionReferenceResolver`; message bodies and full transcripts are not searched.
|
|
95
|
+
|
|
96
|
+
<a id="dev-note"></a>
|
|
97
|
+
### Dev Note
|
|
98
|
+
|
|
99
|
+
<details>
|
|
100
|
+
<summary>Working context for maintainers — click to expand</summary>
|
|
101
|
+
|
|
102
|
+
None.
|
|
103
|
+
|
|
104
|
+
</details>
|
package/README.zh.md
ADDED
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: "Web @file 与 @session 引用 source:候选项、排序,以及原子行内引用(统一的文件/会话选取)。"
|
|
3
|
+
kind: "package-reference"
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# @qilin-agent/client-ui-reference
|
|
7
|
+
|
|
8
|
+
[English](README.md) | 中文
|
|
9
|
+
|
|
10
|
+
## 概述
|
|
11
|
+
|
|
12
|
+
Web 用户需要从同一个 `@` 补全菜单提及文件、文件夹或会话时,可以使用 `qilin-client-ui-reference`。菜单先列出文件,再列出会话;其中一组无法加载时,另一组仍然可用。选择文件、文件夹或会话会插入带稳定剪贴板形式的原子引用;文件夹行还允许用户在不关闭补全的情况下继续下钻。文件行省略多余的根目录位置,会话行仅在工作区与当前工作区不同时显示该工作区。会话 mention 会在捕获模型上下文前接受校验,而浏览候选项不会影响模型。
|
|
13
|
+
|
|
14
|
+
## 目录
|
|
15
|
+
|
|
16
|
+
- [使用本包](#use-this-package)
|
|
17
|
+
- [理解实现](#understand-the-implementation)
|
|
18
|
+
- [进一步探索](#further-exploration)
|
|
19
|
+
- [模型体验](#model-experience)
|
|
20
|
+
- [已知限制与延期工作](#known-limitations-and-deferred-work)
|
|
21
|
+
- [开发备注](#dev-note)
|
|
22
|
+
|
|
23
|
+
-----
|
|
24
|
+
|
|
25
|
+
<a id="use-this-package"></a>
|
|
26
|
+
## 使用本包
|
|
27
|
+
|
|
28
|
+
只要组合挂载了本包且存在宿主 `ctx.fileReferences` 提供方,该 source 即处于活动状态。输入 `@` 后跟一个未加引号的 token,会先看到文件、再看到会话;打开 `@"…` 则只搜索文件。候选列表是补全菜单,不是搜索结果页:选一次、继续输入即可。
|
|
29
|
+
|
|
30
|
+
### 选择后会插入什么
|
|
31
|
+
|
|
32
|
+
选择文件会关闭补全,并显示为带文件图标与业务色文件名的原子行内引用。目录行携带两个动词:选定 pick(点击行主体或 Enter)把文件夹本身解析为同类原子引用——文件夹图标、带尾斜杠的标签、以规范 `@dir/` mention 为序列化形式;钻取动作(Tab 或行尾 chevron)则保持带文件夹图标的可编辑路径纯文本,并让菜单在尾部斜杠处保持活跃,用户可以继续进入下一层。包含空白的路径使用 `@"path with spaces"`,用户显式打开的引号会继续保留。
|
|
33
|
+
|
|
34
|
+
选择会话会插入一个原子的行内引用,其隐藏 `ref` 与剪贴板表示均为宿主返回的规范 `@[label](qilin-session:…)` mention;可见形式为聊天气泡图标加会话标题。发送会经 `session.prompt` 携带该 mention,session-reference 服务会在 `agent/pre-step` 校验它并捕获模型上下文。
|
|
35
|
+
|
|
36
|
+
### 失败行为
|
|
37
|
+
|
|
38
|
+
某个候选领域不可用或失败时,该领域不产生任何行,另一领域仍正常列出。会话引用准备失败发生在提示词接受后,并会终止该 agent 轮次。
|
|
39
|
+
|
|
40
|
+
点击输入框中的文件引用,可在右侧栏预览文件当前的内容。带引号路径中的空格会保留,路径按输入框所属 Session 解析。文件夹和 Session 引用保留原有的编辑行为。
|
|
41
|
+
|
|
42
|
+
-----
|
|
43
|
+
|
|
44
|
+
<a id="understand-the-implementation"></a>
|
|
45
|
+
## 理解实现
|
|
46
|
+
|
|
47
|
+
<details>
|
|
48
|
+
<summary>实现细节——点击展开</summary>
|
|
49
|
+
|
|
50
|
+
该 source 把候选编码保留在注册 effect 内部:`/client` 导出接口只包含插件主体(`apply`/`inject`)。
|
|
51
|
+
|
|
52
|
+
### 候选流程
|
|
53
|
+
|
|
54
|
+
对于未加引号的 token,浏览器会同时启动 `fileReferences/list` 与 `sessionReferenceResolver/candidates` Remote 调用,再按文件、当前 Session 的直接 subagent、其他 Session 的确定性顺序排列。各行使用 resolver 的显示标题;subagent 优先使用创建标签,普通 Session 保持投影标题,并渲染在 locale 管理的分组标题下,不显示重复的原始 `reference` source 标题。会话行用宿主会话列表的 `updatedAt` 经该列表相同的相对时间分档标注时间,因此同一个会话在两处读到的时长一致;列表中没有的会话回落到候选自带的创建时间。下钻后的查询会发布一条从工作区根目录到当前目录的面包屑;每一节携带的下钻载荷与文件夹行相同,因此「回到某一步」与「进入某一层」是同一个结果。
|
|
55
|
+
|
|
56
|
+
### 序列化
|
|
57
|
+
|
|
58
|
+
文件选择把共享 `@path` 语法所定义的自然文本保留为隐藏的序列化与剪贴板形式。会话选择使用规范的 `@[label](qilin-session:…)` mention;序列化永远不会根据可见标题重建身份。
|
|
59
|
+
|
|
60
|
+
</details>
|
|
61
|
+
|
|
62
|
+
-----
|
|
63
|
+
|
|
64
|
+
<a id="further-exploration"></a>
|
|
65
|
+
## 进一步探索
|
|
66
|
+
|
|
67
|
+
以下页面覆盖建议机制、引用 seam 与输入流水线。
|
|
68
|
+
|
|
69
|
+
- [ui-input-trigger](../ui-input-trigger/README.zh.md)——该 source 注册进的行内建议机制。
|
|
70
|
+
- [file-reference](../../context/file-reference/README.zh.md)——`@file` seam 及其提供方约定。
|
|
71
|
+
- [session-reference](../../context/session-reference/README.zh.md)——`@session` seam 与准备后快照的语义。
|
|
72
|
+
- [Web 输入机器与 slash 流水线](../../../.agents/notes/archived/architecture/2026-07-25-web-input-machine-and-slash-pipeline.md)——引用与命令如何共享输入机器。
|
|
73
|
+
|
|
74
|
+
-----
|
|
75
|
+
|
|
76
|
+
<a id="model-experience"></a>
|
|
77
|
+
## 模型体验
|
|
78
|
+
|
|
79
|
+
间接影响模型体验:通过宿主拥有的提供方实现,本包的引用选择把文件指引与会话快照准备委托给它们。
|
|
80
|
+
|
|
81
|
+
#### KV Cache 影响
|
|
82
|
+
|
|
83
|
+
浏览候选项不会影响模型。选择文件或会话只会改变新用户消息的后缀,以及紧随该消息、由宿主准备的会话引用上下文;目标会话更早的历史保持不变。
|
|
84
|
+
|
|
85
|
+
## 已知限制与延期工作
|
|
86
|
+
|
|
87
|
+
<a id="known-limitations-and-deferred-work"></a>
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
这些限制说明引用 source 何时帮不上忙;它们是当前包约束。
|
|
91
|
+
|
|
92
|
+
- **候选失败有意保持静默**:Remote 发现调用不可用或失败时,该领域不产生候选行。会话引用准备失败发生在提示词接受后,并会终止该 agent 轮次。
|
|
93
|
+
- **浏览器侧不扫描文件**:Web 补全需要挂载宿主 `ctx.fileReferences` 提供方;浏览器无法回退到自身文件系统。
|
|
94
|
+
- **会话搜索仍仅使用元数据**:发现流程通过 `ctx.sessionReferenceResolver` 筛选 session id、cwd 与以日志为依据的最新标题;不搜索消息主体或完整 transcript。
|
|
95
|
+
|
|
96
|
+
<a id="dev-note"></a>
|
|
97
|
+
### 开发备注
|
|
98
|
+
|
|
99
|
+
<details>
|
|
100
|
+
<summary>维护者的工作上下文——点击展开</summary>
|
|
101
|
+
|
|
102
|
+
无。
|
|
103
|
+
|
|
104
|
+
</details>
|
package/lib/client.js
ADDED
|
@@ -0,0 +1,322 @@
|
|
|
1
|
+
window.__ModuleLoader__.load({
|
|
2
|
+
id: "@qilin-agent/client-ui-reference",
|
|
3
|
+
factory: (require) => {
|
|
4
|
+
var module = { exports: {} };
|
|
5
|
+
var exports = module.exports;
|
|
6
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
7
|
+
let _qilin_agent_client_ui_primitives = require("@qilin-agent/client-ui-primitives");
|
|
8
|
+
//#region ../../context/file-reference/src/grammar.ts
|
|
9
|
+
/**
|
|
10
|
+
* Format a selected path as prompt text. Whitespace uses the quoted
|
|
11
|
+
* `@"path"` grammar; a quoted directory keeps that quote open after its
|
|
12
|
+
* trailing slash so completion can descend another level.
|
|
13
|
+
* @param candidate - selected file or directory.
|
|
14
|
+
* @param preserveQuote - retain an explicitly opened quote even when unnecessary.
|
|
15
|
+
* @returns the insertion value, or `undefined` for a path the editor grammar cannot represent safely.
|
|
16
|
+
*/
|
|
17
|
+
function formatFileMention(candidate, preserveQuote) {
|
|
18
|
+
const path = candidate.kind === "directory" ? `${candidate.path}/` : candidate.path;
|
|
19
|
+
if (/[\u0000-\u001f\u007f-\u009f"]/u.test(path)) return void 0;
|
|
20
|
+
if (!(preserveQuote || /\s/u.test(path))) return `@${path}`;
|
|
21
|
+
if (candidate.kind === "directory") return `@"${path}`;
|
|
22
|
+
return `@"${path}"`;
|
|
23
|
+
}
|
|
24
|
+
//#endregion
|
|
25
|
+
//#region ../../util/workspace-path/src/file-address.ts
|
|
26
|
+
/** The scheme and type every file address opens with. */
|
|
27
|
+
const FILE_ADDRESS_PREFIX = "qilin-resource://file/";
|
|
28
|
+
/** Component-encode one id or path segment, keeping `:` literal for drive letters. */
|
|
29
|
+
function encodeSegment(segment) {
|
|
30
|
+
return encodeURIComponent(segment).replace(/%3A/gi, ":");
|
|
31
|
+
}
|
|
32
|
+
/** Encode a `/`-separated path segment by segment. */
|
|
33
|
+
function encodePath(path) {
|
|
34
|
+
return path.split("/").map(encodeSegment).join("/");
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Build the address of a file read through one Session.
|
|
38
|
+
* @param sessionId - the Session whose Host workspace resolves the path.
|
|
39
|
+
* @param path - absolute or workspace-relative path; backslashes are normalized to `/`, and leading `./` prefixes are dropped.
|
|
40
|
+
* @returns the `qilin-resource://file/session/<sessionId>/<path>` address.
|
|
41
|
+
*/
|
|
42
|
+
function sessionFileAddress(sessionId, path) {
|
|
43
|
+
const normalized = path.replace(/\\/g, "/").replace(/^(?:\.\/)+/, "");
|
|
44
|
+
return `${FILE_ADDRESS_PREFIX}session/${encodeSegment(sessionId)}/${encodePath(normalized)}`;
|
|
45
|
+
}
|
|
46
|
+
//#endregion
|
|
47
|
+
//#region ../../util/workspace-path/src/index.ts
|
|
48
|
+
/**
|
|
49
|
+
* Browser-safe Workspace path and display helpers.
|
|
50
|
+
* @module @qilin-agent/util-workspace-path
|
|
51
|
+
*/
|
|
52
|
+
/** Whether a path uses a Windows drive or UNC prefix. */
|
|
53
|
+
function isWindowsStylePath(value) {
|
|
54
|
+
return /^[A-Za-z]:[/\\]/.test(value) || value.startsWith("\\\\");
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Whether a path is absolute in either spelling the Host accepts: POSIX (`/a/b`) or Windows drive or UNC.
|
|
58
|
+
* @param path - the path to classify.
|
|
59
|
+
* @returns `true` for an absolute path; `false` for a Workspace-relative one.
|
|
60
|
+
*/
|
|
61
|
+
function isAbsoluteWorkspacePath(path) {
|
|
62
|
+
return path.startsWith("/") || isWindowsStylePath(path);
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Abbreviate a POSIX home directory for display.
|
|
66
|
+
* @param path - Absolute or already-short display path.
|
|
67
|
+
* @param home - Host account home; absent skips abbreviation.
|
|
68
|
+
* @returns `~` or `~/…` for the POSIX home and its descendants, otherwise `path`.
|
|
69
|
+
*/
|
|
70
|
+
function abbreviateHomePath(path, home) {
|
|
71
|
+
if (home === void 0 || home === "") return path;
|
|
72
|
+
if (isWindowsStylePath(path) || isWindowsStylePath(home)) return path;
|
|
73
|
+
const root = home.replace(/\/+$/, "");
|
|
74
|
+
if (root === "" || root === "/") return path;
|
|
75
|
+
if (path.replace(/\/+$/, "") === root) return "~";
|
|
76
|
+
if (path.startsWith(`${root}/`)) return `~${path.slice(root.length)}`;
|
|
77
|
+
return path;
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* The address for a path as a caller holds it: a relative path, or an absolute
|
|
81
|
+
* path inside the Session's workspace, becomes a `session`-scoped address; an
|
|
82
|
+
* absolute path outside it, or one whose workspace root is unknown, keeps its
|
|
83
|
+
* absolute path in that Session's address.
|
|
84
|
+
* @param sessionId - the Session the path is read in.
|
|
85
|
+
* @param cwd - that Session's workspace root, when known.
|
|
86
|
+
* @param path - absolute or workspace-relative path, in either separator spelling.
|
|
87
|
+
* @returns the `qilin-resource://file/…` address.
|
|
88
|
+
*/
|
|
89
|
+
function fileAddressFor(sessionId, cwd, path) {
|
|
90
|
+
const normalized = path.replace(/\\/g, "/");
|
|
91
|
+
if (!isAbsoluteWorkspacePath(normalized)) return sessionFileAddress(sessionId, normalized);
|
|
92
|
+
const root = cwd === void 0 ? "" : cwd.replace(/\\/g, "/").replace(/\/+$/, "");
|
|
93
|
+
if (root !== "" && normalized === root) return sessionFileAddress(sessionId, "");
|
|
94
|
+
if (root !== "" && normalized.startsWith(`${root}/`)) return sessionFileAddress(sessionId, normalized.slice(root.length + 1));
|
|
95
|
+
return sessionFileAddress(sessionId, normalized);
|
|
96
|
+
}
|
|
97
|
+
//#endregion
|
|
98
|
+
//#region lib/types/client/locales.js
|
|
99
|
+
/** `reference` namespace dictionaries for the unified `@` source. */
|
|
100
|
+
/** Dictionary namespace owned by this plugin. */
|
|
101
|
+
const NS = "reference";
|
|
102
|
+
/**
|
|
103
|
+
* Simplified Chinese dictionary (the key-set source of truth).
|
|
104
|
+
*
|
|
105
|
+
* The `time.*` bucket words are this namespace's own copy of the session-row
|
|
106
|
+
* vocabulary: locale-owned copy keeps the words per plugin, while the
|
|
107
|
+
* bucketing they name is the one shared {@link relativeTime} in ui-primitives.
|
|
108
|
+
*/
|
|
109
|
+
const zh = {
|
|
110
|
+
"section.files": "文件与文件夹",
|
|
111
|
+
"section.subagents": "子智能体",
|
|
112
|
+
"section.sessions": "对话",
|
|
113
|
+
"candidate.noCwd": "(无工作目录)",
|
|
114
|
+
"crumb.root": "工作区",
|
|
115
|
+
"time.now": "刚刚",
|
|
116
|
+
"time.minutes": "{n}分钟",
|
|
117
|
+
"time.hours": "{n}小时",
|
|
118
|
+
"time.days": "{n}天",
|
|
119
|
+
"time.months": "{n}个月",
|
|
120
|
+
"time.years": "{n}年"
|
|
121
|
+
};
|
|
122
|
+
/** English dictionary, checked complete against the zh key set. */
|
|
123
|
+
const en = {
|
|
124
|
+
"section.files": "Files & folders",
|
|
125
|
+
"section.subagents": "Subagents",
|
|
126
|
+
"section.sessions": "Sessions",
|
|
127
|
+
"candidate.noCwd": "(no cwd)",
|
|
128
|
+
"crumb.root": "Workspace",
|
|
129
|
+
"time.now": "now",
|
|
130
|
+
"time.minutes": "{n}min",
|
|
131
|
+
"time.hours": "{n}h",
|
|
132
|
+
"time.days": "{n}d",
|
|
133
|
+
"time.months": "{n}mo",
|
|
134
|
+
"time.years": "{n}y"
|
|
135
|
+
};
|
|
136
|
+
//#endregion
|
|
137
|
+
//#region lib/types/client/index.js
|
|
138
|
+
/** Required services: the trigger registry, the Remote namespaces, and the copy. */
|
|
139
|
+
const inject = [
|
|
140
|
+
"inputTriggers",
|
|
141
|
+
"locale",
|
|
142
|
+
"sessions",
|
|
143
|
+
"remote",
|
|
144
|
+
"remote.fileReferences",
|
|
145
|
+
"remote.sessionReferenceResolver",
|
|
146
|
+
"sidebarRight"
|
|
147
|
+
];
|
|
148
|
+
/**
|
|
149
|
+
* Register the combined `@file` / `@session` source.
|
|
150
|
+
* @param ctx - client root context.
|
|
151
|
+
*/
|
|
152
|
+
function apply(ctx) {
|
|
153
|
+
ctx.effect(() => ctx.locale.register(NS, {
|
|
154
|
+
zh,
|
|
155
|
+
en
|
|
156
|
+
}), "ui-reference: dictionaries");
|
|
157
|
+
const t = ctx.locale.bind(NS);
|
|
158
|
+
const sessions = ctx.get("sessions");
|
|
159
|
+
const source = {
|
|
160
|
+
trigger: "@",
|
|
161
|
+
name: "reference",
|
|
162
|
+
showGroupTitle: false,
|
|
163
|
+
async candidates(session, { query, quoted, drilled, signal }) {
|
|
164
|
+
const fileLookup = ctx.remote.fileReferences.list(session.sessionId, query, signal).then((result) => result.ok ? result.value : []);
|
|
165
|
+
const sessionLookup = quoted === true ? Promise.resolve([]) : ctx.remote.sessionReferenceResolver.candidates(session.sessionId, query, signal).then((result) => result.ok ? result.value : []);
|
|
166
|
+
const [fileItems, sessionItems] = await Promise.all([fileLookup, sessionLookup]);
|
|
167
|
+
if (signal.aborted) return [];
|
|
168
|
+
const withLocation = crumbsFor(query, quoted === true, drilled, t) === void 0;
|
|
169
|
+
const now = Date.now();
|
|
170
|
+
const home = ctx.remote.$host.home;
|
|
171
|
+
const listed = sessions.list.getSnapshot().byId;
|
|
172
|
+
const sessionRows = sessionItems.map((candidate) => {
|
|
173
|
+
const summary = listed[candidate.sessionId];
|
|
174
|
+
const child = summary?.origin === "subagent" && summary.parentId === session.sessionId;
|
|
175
|
+
return {
|
|
176
|
+
child,
|
|
177
|
+
row: sessionCandidate(candidate, candidate.displayTitle ?? candidate.label, summary?.updatedAt ?? candidate.createdAt, now, home, t(child ? "section.subagents" : "section.sessions"), t)
|
|
178
|
+
};
|
|
179
|
+
});
|
|
180
|
+
return [
|
|
181
|
+
...fileItems.flatMap((candidate) => fileCandidate(candidate, quoted === true, withLocation, t)),
|
|
182
|
+
...sessionRows.filter((item) => item.child).map((item) => item.row),
|
|
183
|
+
...sessionRows.filter((item) => !item.child).map((item) => item.row)
|
|
184
|
+
];
|
|
185
|
+
},
|
|
186
|
+
header(_session, req) {
|
|
187
|
+
return crumbsFor(req.query, req.quoted === true, req.drilled, t);
|
|
188
|
+
},
|
|
189
|
+
onPick({ candidate, action }) {
|
|
190
|
+
const value = parseCandidate(candidate.value);
|
|
191
|
+
if (value?.kind === "file") {
|
|
192
|
+
if (value.fileKind === "directory" && action === "drill") return {
|
|
193
|
+
text: value.mention,
|
|
194
|
+
continue: true
|
|
195
|
+
};
|
|
196
|
+
return { insert: {
|
|
197
|
+
source: "reference",
|
|
198
|
+
ref: value.mention,
|
|
199
|
+
label: value.fileKind === "directory" ? `${value.label}/` : value.label,
|
|
200
|
+
appearance: value.fileKind === "directory" ? "folder" : "file",
|
|
201
|
+
clipboardText: value.mention
|
|
202
|
+
} };
|
|
203
|
+
}
|
|
204
|
+
if (value?.kind === "session") return { insert: {
|
|
205
|
+
source: "reference",
|
|
206
|
+
ref: value.mention,
|
|
207
|
+
label: value.label,
|
|
208
|
+
appearance: "session",
|
|
209
|
+
clipboardText: value.mention
|
|
210
|
+
} };
|
|
211
|
+
},
|
|
212
|
+
openReference(session, { ref, appearance }) {
|
|
213
|
+
if (appearance !== "file") return false;
|
|
214
|
+
const path = ref.startsWith("@\"") ? ref.slice(2, -1) : ref.slice(1);
|
|
215
|
+
const cwd = sessions.list.getSnapshot().byId[session.sessionId]?.cwd;
|
|
216
|
+
ctx.sidebarRight.openResource(fileAddressFor(session.sessionId, cwd, path));
|
|
217
|
+
return true;
|
|
218
|
+
},
|
|
219
|
+
codec: {
|
|
220
|
+
clipboardText: (ref) => ref,
|
|
221
|
+
serialize: (ref) => Promise.resolve(ref)
|
|
222
|
+
}
|
|
223
|
+
};
|
|
224
|
+
const inputTriggers = ctx.get("inputTriggers");
|
|
225
|
+
ctx.effect(() => inputTriggers.registerSource(source), "ui-reference: @ source");
|
|
226
|
+
}
|
|
227
|
+
/**
|
|
228
|
+
* The breadcrumb of a drilled directory listing, from the workspace root down
|
|
229
|
+
* to the directory being listed.
|
|
230
|
+
*
|
|
231
|
+
* Only a drill produces one: a path the user typed carries its own context in
|
|
232
|
+
* the draft, while a drill replaced the text they were reading with a deeper
|
|
233
|
+
* one and owes them the way back.
|
|
234
|
+
* @param query - the live query, path text following `@` or `@"`.
|
|
235
|
+
* @param quoted - whether the active token is an open quoted path.
|
|
236
|
+
* @param drilled - whether a drill pick, rather than typing, produced the query.
|
|
237
|
+
* @param t - the reference dictionary.
|
|
238
|
+
* @returns the crumbs, or undefined when this listing needs no header.
|
|
239
|
+
*/
|
|
240
|
+
function crumbsFor(query, quoted, drilled, t) {
|
|
241
|
+
if (!drilled) return void 0;
|
|
242
|
+
const slash = query.lastIndexOf("/");
|
|
243
|
+
if (slash < 0) return void 0;
|
|
244
|
+
const segments = query.slice(0, slash).split("/").filter((segment) => segment !== "");
|
|
245
|
+
const crumbs = [{
|
|
246
|
+
label: t("crumb.root"),
|
|
247
|
+
value: directoryValue(t("crumb.root"), quoted ? "@\"" : "@")
|
|
248
|
+
}];
|
|
249
|
+
for (const [index, segment] of segments.entries()) {
|
|
250
|
+
const mention = formatFileMention({
|
|
251
|
+
path: segments.slice(0, index + 1).join("/"),
|
|
252
|
+
kind: "directory"
|
|
253
|
+
}, quoted);
|
|
254
|
+
if (mention === void 0) return void 0;
|
|
255
|
+
crumbs.push({
|
|
256
|
+
label: segment,
|
|
257
|
+
value: directoryValue(segment, mention),
|
|
258
|
+
...index === segments.length - 1 ? { current: true } : {}
|
|
259
|
+
});
|
|
260
|
+
}
|
|
261
|
+
return crumbs;
|
|
262
|
+
}
|
|
263
|
+
/** Project one directory destination as the drill payload `onPick` already understands. */
|
|
264
|
+
function directoryValue(label, mention) {
|
|
265
|
+
return JSON.stringify({
|
|
266
|
+
kind: "file",
|
|
267
|
+
fileKind: "directory",
|
|
268
|
+
label,
|
|
269
|
+
mention
|
|
270
|
+
});
|
|
271
|
+
}
|
|
272
|
+
function fileCandidate(candidate, preserveQuote, withLocation, t) {
|
|
273
|
+
const mention = formatFileMention(candidate, preserveQuote);
|
|
274
|
+
if (mention === void 0) return [];
|
|
275
|
+
const slash = candidate.path.lastIndexOf("/");
|
|
276
|
+
const name = candidate.path.slice(slash + 1);
|
|
277
|
+
const parent = slash < 0 ? "" : candidate.path.slice(0, slash);
|
|
278
|
+
const directory = candidate.kind === "directory";
|
|
279
|
+
const value = {
|
|
280
|
+
kind: "file",
|
|
281
|
+
fileKind: candidate.kind,
|
|
282
|
+
label: name,
|
|
283
|
+
mention
|
|
284
|
+
};
|
|
285
|
+
return [{
|
|
286
|
+
name: `${name}${directory ? "/" : ""}`,
|
|
287
|
+
...withLocation && parent !== "" ? { description: parent } : {},
|
|
288
|
+
icon: directory ? "folder" : "file",
|
|
289
|
+
section: t("section.files"),
|
|
290
|
+
value: JSON.stringify(value),
|
|
291
|
+
...directory ? { drill: true } : {}
|
|
292
|
+
}];
|
|
293
|
+
}
|
|
294
|
+
function sessionCandidate(candidate, label, updatedAt, now, home, section, t) {
|
|
295
|
+
const { unit, n } = (0, _qilin_agent_client_ui_primitives.relativeTime)(updatedAt, now);
|
|
296
|
+
const age = unit === "now" ? t("time.now") : t(`time.${unit}`, { n });
|
|
297
|
+
const location = candidate.sameWorkspace ? void 0 : candidate.cwd === void 0 ? t("candidate.noCwd") : abbreviateHomePath(candidate.cwd, home);
|
|
298
|
+
const value = {
|
|
299
|
+
kind: "session",
|
|
300
|
+
label,
|
|
301
|
+
mention: candidate.mention
|
|
302
|
+
};
|
|
303
|
+
return {
|
|
304
|
+
name: label,
|
|
305
|
+
description: location === void 0 ? age : `${location} · ${age}`,
|
|
306
|
+
icon: "session",
|
|
307
|
+
section,
|
|
308
|
+
value: JSON.stringify(value)
|
|
309
|
+
};
|
|
310
|
+
}
|
|
311
|
+
function parseCandidate(value) {
|
|
312
|
+
if (value === void 0) return void 0;
|
|
313
|
+
return JSON.parse(value);
|
|
314
|
+
}
|
|
315
|
+
//#endregion
|
|
316
|
+
exports.apply = apply;
|
|
317
|
+
exports.inject = inject;
|
|
318
|
+
return module.exports;
|
|
319
|
+
}
|
|
320
|
+
});
|
|
321
|
+
|
|
322
|
+
//# sourceMappingURL=client.js.map
|
package/lib/index.js
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
//#region lib/types/index.js
|
|
2
|
+
/**
|
|
3
|
+
* File/session reference plugin, node half. Pure UI plugin: the empty apply
|
|
4
|
+
* exists so the plugin appears in the host cordis.yml / Loader; the browser
|
|
5
|
+
* half ships via exports["./client"], discovered through the package.json
|
|
6
|
+
* `qilin.client` declaration.
|
|
7
|
+
*/
|
|
8
|
+
/** Host plugin body — no host-side behavior for this source plugin. */
|
|
9
|
+
function apply() {}
|
|
10
|
+
//#endregion
|
|
11
|
+
export { apply };
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { Context as ClientContext } from '@qilin-agent/kylin';
|
|
2
|
+
/** Required services: the trigger registry, the Remote namespaces, and the copy. */
|
|
3
|
+
export declare const inject: string[];
|
|
4
|
+
/**
|
|
5
|
+
* Register the combined `@file` / `@session` source.
|
|
6
|
+
* @param ctx - client root context.
|
|
7
|
+
*/
|
|
8
|
+
export declare function apply(ctx: ClientContext): void;
|
|
9
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/** `reference` namespace dictionaries for the unified `@` source. */
|
|
2
|
+
/** Dictionary namespace owned by this plugin. */
|
|
3
|
+
export declare const NS = "reference";
|
|
4
|
+
/**
|
|
5
|
+
* Simplified Chinese dictionary (the key-set source of truth).
|
|
6
|
+
*
|
|
7
|
+
* The `time.*` bucket words are this namespace's own copy of the session-row
|
|
8
|
+
* vocabulary: locale-owned copy keeps the words per plugin, while the
|
|
9
|
+
* bucketing they name is the one shared {@link relativeTime} in ui-primitives.
|
|
10
|
+
*/
|
|
11
|
+
export declare const zh: {
|
|
12
|
+
'section.files': string;
|
|
13
|
+
'section.subagents': string;
|
|
14
|
+
'section.sessions': string;
|
|
15
|
+
'candidate.noCwd': string;
|
|
16
|
+
'crumb.root': string;
|
|
17
|
+
'time.now': string;
|
|
18
|
+
'time.minutes': string;
|
|
19
|
+
'time.hours': string;
|
|
20
|
+
'time.days': string;
|
|
21
|
+
'time.months': string;
|
|
22
|
+
'time.years': string;
|
|
23
|
+
};
|
|
24
|
+
/** The reference namespace key union. */
|
|
25
|
+
export type ReferenceKey = keyof typeof zh;
|
|
26
|
+
declare module '@qilin-agent/client-ui-slots' {
|
|
27
|
+
interface LocaleNamespaceMap {
|
|
28
|
+
/** The unified `@` reference menu's copy. */
|
|
29
|
+
reference: ReferenceKey;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
/** English dictionary, checked complete against the zh key set. */
|
|
33
|
+
export declare const en: {
|
|
34
|
+
'section.files': string;
|
|
35
|
+
'section.subagents': string;
|
|
36
|
+
'section.sessions': string;
|
|
37
|
+
'candidate.noCwd': string;
|
|
38
|
+
'crumb.root': string;
|
|
39
|
+
'time.now': string;
|
|
40
|
+
'time.minutes': string;
|
|
41
|
+
'time.hours': string;
|
|
42
|
+
'time.days': string;
|
|
43
|
+
'time.months': string;
|
|
44
|
+
'time.years': string;
|
|
45
|
+
};
|
|
46
|
+
//# sourceMappingURL=locales.d.ts.map
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* File/session reference plugin, node half. Pure UI plugin: the empty apply
|
|
3
|
+
* exists so the plugin appears in the host cordis.yml / Loader; the browser
|
|
4
|
+
* half ships via exports["./client"], discovered through the package.json
|
|
5
|
+
* `qilin.client` declaration.
|
|
6
|
+
*/
|
|
7
|
+
/** Host plugin body — no host-side behavior for this source plugin. */
|
|
8
|
+
export declare function apply(): void;
|
|
9
|
+
//# sourceMappingURL=index.d.ts.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,73 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@qilin-agent/client-ui-reference",
|
|
3
|
-
"
|
|
4
|
-
"
|
|
5
|
-
"
|
|
3
|
+
"description": "Unified Web @file and @session reference source",
|
|
4
|
+
"version": "3.1.3",
|
|
5
|
+
"publishConfig": {
|
|
6
|
+
"access": "public"
|
|
7
|
+
},
|
|
8
|
+
"repository": {
|
|
9
|
+
"type": "git",
|
|
10
|
+
"url": "git+https://github.com/kkutysllb/QiLin.git",
|
|
11
|
+
"directory": "packages/client/ui-reference"
|
|
12
|
+
},
|
|
13
|
+
"engines": {
|
|
14
|
+
"node": "^22.19.0 || >=24.0.0"
|
|
15
|
+
},
|
|
16
|
+
"type": "module",
|
|
17
|
+
"main": "lib/index.js",
|
|
18
|
+
"types": "lib/types/index.d.ts",
|
|
19
|
+
"exports": {
|
|
20
|
+
".": {
|
|
21
|
+
"types": "./lib/types/index.d.ts",
|
|
22
|
+
"default": "./lib/index.js"
|
|
23
|
+
},
|
|
24
|
+
"./client": {
|
|
25
|
+
"types": "./lib/types/client/index.d.ts",
|
|
26
|
+
"default": "./lib/client.js"
|
|
27
|
+
},
|
|
28
|
+
"./src/*": "./src/*",
|
|
29
|
+
"./package.json": "./package.json"
|
|
30
|
+
},
|
|
31
|
+
"qilin": {
|
|
32
|
+
"client": {
|
|
33
|
+
"inject": [
|
|
34
|
+
"@qilin-agent/api-remotes",
|
|
35
|
+
"@qilin-agent/api-session-controller",
|
|
36
|
+
"@qilin-agent/client-connection",
|
|
37
|
+
"@qilin-agent/client-locale",
|
|
38
|
+
"@qilin-agent/client-ui-input-trigger",
|
|
39
|
+
"@qilin-agent/client-ui-sidebar-right"
|
|
40
|
+
],
|
|
41
|
+
"platform": "web"
|
|
42
|
+
}
|
|
43
|
+
},
|
|
44
|
+
"license": "MIT",
|
|
45
|
+
"peerDependencies": {
|
|
46
|
+
"@qilin-agent/kylin": "~4.0.3"
|
|
47
|
+
},
|
|
48
|
+
"devDependencies": {
|
|
49
|
+
"@qilin-agent/api-remotes": "3.1.3",
|
|
50
|
+
"@qilin-agent/api-session-controller": "3.1.3",
|
|
51
|
+
"@qilin-agent/client-locale": "3.1.3",
|
|
52
|
+
"@qilin-agent/client-ui-input-trigger": "3.1.3",
|
|
53
|
+
"@qilin-agent/client-test-runtime": "3.1.3",
|
|
54
|
+
"@qilin-agent/client-connection": "3.1.3",
|
|
55
|
+
"@qilin-agent/client-ui-primitives": "3.1.3",
|
|
56
|
+
"@qilin-agent/session-reference": "3.1.3",
|
|
57
|
+
"@qilin-agent/file-reference": "3.1.3",
|
|
58
|
+
"@qilin-agent/typert-protocol": "3.1.3",
|
|
59
|
+
"@qilin-agent/util-workspace-path": "3.1.3",
|
|
60
|
+
"@qilin-agent/kylin": "~4.0.3",
|
|
61
|
+
"@qilin-agent/client-ui-sidebar-right": "3.1.3",
|
|
62
|
+
"@qilin-agent/client-ui-slots": "3.1.3"
|
|
63
|
+
},
|
|
64
|
+
"files": [
|
|
65
|
+
"lib/index.js",
|
|
66
|
+
"lib/client.js",
|
|
67
|
+
"lib/types/**/*.d.ts"
|
|
68
|
+
],
|
|
69
|
+
"scripts": {
|
|
70
|
+
"bundle": "tsdown",
|
|
71
|
+
"watch": "tsdown --watch"
|
|
72
|
+
}
|
|
6
73
|
}
|