@deepseek-ai/dsh-file-reference-local 0.1.1-rc.2 → 0.1.2-alpha.2
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 +2 -2
- package/README.md +108 -14
- package/README.zh.md +110 -16
- package/lib/index.js +85 -14
- package/lib/types/index.js +1 -1
- package/lib/types/search.d.ts +35 -5
- package/lib/types/search.js +94 -12
- package/package.json +14 -14
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/context/file-reference-local/README.md
|
|
5
|
-
README.md:
|
|
6
|
-
README.zh.md:
|
|
5
|
+
README.md: da5db0882e9f4538bdd901a970eca98aac10bbde
|
|
6
|
+
README.zh.md: cea38d335c8b29ddc3c875782cb62df1d0ae6e0d
|
package/README.md
CHANGED
|
@@ -1,24 +1,102 @@
|
|
|
1
|
-
|
|
1
|
+
---
|
|
2
|
+
description: "Local-workspace @file completion provider for users and maintainers enabling, sizing, or debugging ctx.fileReferences discovery."
|
|
3
|
+
kind: "package-reference"
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# @deepseek-ai/dsh-file-reference-local
|
|
2
7
|
|
|
3
8
|
English | [中文](README.zh.md)
|
|
4
9
|
|
|
5
|
-
|
|
10
|
+
## Summary
|
|
11
|
+
|
|
12
|
+
Agents and their host UIs get ranked path candidates for `@file` mentions, scoped to each agent's workspace and bounded so even large repositories stay responsive. `dsh-file-reference-local` implements `ctx.fileReferences` for the local filesystem: it keeps one reusable search index per agent, rebuilds it in the background after tool results so completion reflects workspace changes without stalling, and never follows directory symlinks. When the addressed agent can call `read`, it also installs a stable one-sentence guidance into the system prompt. Choose it when the agent's `read` tool operates on the Harness host filesystem; remote or virtual namespaces need a provider whose discovery matches the tool.
|
|
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
|
+
Mount this provider when `@file` completion should discover the Harness host's own filesystem — the namespace the shipped `read` tool operates on. Each agent's workspace is indexed from its session working directory, falling back to the host process directory when the session has none.
|
|
29
|
+
|
|
30
|
+
### Enabling the provider
|
|
31
|
+
|
|
32
|
+
The defaults suit a typical workspace, so the minimal mount needs no configuration:
|
|
33
|
+
|
|
34
|
+
```yaml
|
|
35
|
+
- name: '@deepseek-ai/dsh-file-reference-local'
|
|
36
|
+
config:
|
|
37
|
+
maxResults: 20
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
### What you get
|
|
41
|
+
|
|
42
|
+
Typing `@` in a host UI returns up to `maxResults` ranked path candidates for the addressed agent. A query containing `/` lists the matching directory's entries directly; a bare query fuzzy-ranks the bounded recursive index. Directory candidates keep the mention open with a trailing slash. After any tool result the agent's index is marked stale: the next query still answers from it and its replacement builds in the background, so a rebuild never sits in front of the caret.
|
|
43
|
+
|
|
44
|
+
### Configuration
|
|
45
|
+
|
|
46
|
+
| Field | Default | Meaning |
|
|
47
|
+
|---|---|---|
|
|
48
|
+
| `maxResults` | `20` | Maximum ranked candidates returned for one query |
|
|
49
|
+
| `maxEntries` | `50000` | Maximum files and directories indexed per agent workspace |
|
|
50
|
+
| `excludedDirectories` | `['.git', 'node_modules', 'dist', 'build', 'out', 'coverage', 'target', '.next', '.nuxt', '.turbo', '.venv', '__pycache__', '.pytest_cache', '.mypy_cache', '.gradle']` | Directory basenames omitted from traversal and candidates |
|
|
51
|
+
|
|
52
|
+
Every numeric value must be a positive safe integer, and every excluded name must be a non-empty basename without `/` or `\`.
|
|
53
|
+
|
|
54
|
+
-----
|
|
55
|
+
|
|
56
|
+
<a id="understand-the-implementation"></a>
|
|
57
|
+
## Understand the implementation
|
|
6
58
|
|
|
7
|
-
|
|
59
|
+
<details>
|
|
60
|
+
<summary>Implementation internals — click to expand</summary>
|
|
8
61
|
|
|
9
|
-
|
|
62
|
+
This section explains the design of the provider; the observable behavior is covered in [Use this package](#use-this-package).
|
|
10
63
|
|
|
11
|
-
|
|
12
|
-
|---|---:|---|
|
|
13
|
-
| `maxResults` | `20` | Maximum ranked candidates returned for one query. |
|
|
14
|
-
| `maxEntries` | `10000` | Maximum files and directories indexed per agent workspace. |
|
|
15
|
-
| `excludedDirectories` | `[".git", "node_modules"]` | Directory basenames omitted from traversal and candidates. |
|
|
64
|
+
### Design concept
|
|
16
65
|
|
|
17
|
-
|
|
66
|
+
The provider maintains one reusable `WorkspaceFileSearch` per agent, rooted at that session's `cwd`. Directory-scoped queries (`a/b/...`) list live directory state, while bare fuzzy queries share one bounded recursive traversal. Only a workspace's first bare query waits for that traversal; a `tool/result` event marks the settled entries stale, and the next bare query serves them while the replacement builds. The model guidance is a per-agent prompt section contributed only while the addressed agent has a `read` tool; agent disposal releases both the index and the prompt fiber.
|
|
18
67
|
|
|
68
|
+
### Source map
|
|
69
|
+
|
|
70
|
+
| File | Role |
|
|
71
|
+
|---|---|
|
|
72
|
+
| [`src/index.ts`](src/index.ts) | `LocalFileReferenceService`: config validation, per-agent searches, prompt install |
|
|
73
|
+
| [`src/search.ts`](src/search.ts) | `WorkspaceFileSearch`: traversal, ranking, exclusion, staleness and background rebuild |
|
|
74
|
+
| [`src/invariant.ts`](src/invariant.ts) | Invariant companion for the discovery contract |
|
|
75
|
+
|
|
76
|
+
### Main flow
|
|
77
|
+
|
|
78
|
+
A `list(agent, query, signal)` call either lists one directory's entries or reads the shared bounded index, ranks the candidates (exact, prefix, substring, then subsequence scores with directory bonuses), and returns at most `maxResults` in deterministic order. `tool/result` events mark the addressed agent's index stale so a later bare query observes a fresh tree. An unreadable or excluded subtree contributes no candidates, while an unreadable root fails its traversal instead: a transient failure must not replace still-good entries with an empty index.
|
|
79
|
+
|
|
80
|
+
</details>
|
|
81
|
+
|
|
82
|
+
-----
|
|
83
|
+
|
|
84
|
+
<a id="further-exploration"></a>
|
|
85
|
+
## Further Exploration
|
|
86
|
+
|
|
87
|
+
Read these pages when the package-level contract is not enough. They move from the seam this provider implements to the tools its candidates point at.
|
|
88
|
+
|
|
89
|
+
- [File-reference seam](../file-reference/README.md) — the service contract and `@file` grammar this provider implements.
|
|
90
|
+
- [Session-reference subsystem](../../../docs/subsystems/session-reference.md) — the shared file-reference contract behind host UIs.
|
|
91
|
+
- [Filesystem tool catalog](../../../docs/tool-catalog.md#deepseek-aidsh-tool-fs) — the `read` tool whose namespace discovery must match.
|
|
92
|
+
- [Context group map](../README.md) — sibling request-context packages.
|
|
93
|
+
|
|
94
|
+
-----
|
|
95
|
+
|
|
96
|
+
<a id="model-experience"></a>
|
|
19
97
|
## Model Experience
|
|
20
98
|
|
|
21
|
-
### File-reference guidance when
|
|
99
|
+
### File-reference guidance when read is available
|
|
22
100
|
|
|
23
101
|
#### What the model sees
|
|
24
102
|
|
|
@@ -27,7 +105,7 @@ When the addressed agent has an effective `read` tool, the provider contributes
|
|
|
27
105
|
##### File-reference instruction
|
|
28
106
|
|
|
29
107
|
```markdown
|
|
30
|
-
|
|
108
|
+
Tokens prefixed with @ are workspace paths the user explicitly referenced, relative to the workspace root. A trailing slash marks a directory: list it when its contents matter. Anything else is a file: use the read tool when its contents are needed, and do not claim to have inspected it before reading. @"..." quotes a path containing spaces.
|
|
31
109
|
```
|
|
32
110
|
|
|
33
111
|
#### Token effect
|
|
@@ -36,10 +114,26 @@ Conditional and fixed: the one sentence is present while `read` is visible to th
|
|
|
36
114
|
|
|
37
115
|
#### KV Cache effect
|
|
38
116
|
|
|
39
|
-
The stable sentence joins the system-prompt prefix. Mounting or removing this provider, or changing whether `read` is visible, changes that prefix; queries, candidates, and index
|
|
117
|
+
The stable sentence joins the system-prompt prefix. Mounting or removing this provider, or changing whether `read` is visible, changes that prefix; queries, candidates, and index staleness do not.
|
|
40
118
|
|
|
41
119
|
## Known Limitations and Deferred Work
|
|
42
120
|
|
|
121
|
+
<a id="known-limitations-and-deferred-work"></a>
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
These limits define when the provider is a poor fit. They are current package constraints.
|
|
125
|
+
|
|
43
126
|
- **Host-local namespace** — the provider scans the Harness host filesystem, so remote or virtual `read` implementations require a provider whose namespace matches the tool.
|
|
44
|
-
- **Bounded advisory index** — very large workspaces may omit paths after `maxEntries`, and excluded or unreadable directories do not appear.
|
|
127
|
+
- **Bounded advisory index** — very large workspaces may omit paths after `maxEntries`, and excluded or unreadable directories do not appear. The default exclusions name only build outputs no ecosystem also uses for sources; `lib` is deliberately absent, so a workspace that builds into it adds that name through `excludedDirectories`.
|
|
128
|
+
- **One invalidation of staleness** — a bare query answered right after a tool result reflects the tree as of the previous traversal; the following query sees the rebuild.
|
|
45
129
|
- **No ignore-file semantics** — `.gitignore` and other project ignore files do not influence discovery; only configured directory basenames are excluded.
|
|
130
|
+
|
|
131
|
+
<a id="dev-note"></a>
|
|
132
|
+
### Dev Note
|
|
133
|
+
|
|
134
|
+
<details>
|
|
135
|
+
<summary>Working context for maintainers — click to expand</summary>
|
|
136
|
+
|
|
137
|
+
None.
|
|
138
|
+
|
|
139
|
+
</details>
|
package/README.zh.md
CHANGED
|
@@ -1,45 +1,139 @@
|
|
|
1
|
-
|
|
1
|
+
---
|
|
2
|
+
description: "面向用户与维护者的本地工作区 @file 补全提供方,用于启用、设置大小或排查 ctx.fileReferences 的发现能力。"
|
|
3
|
+
kind: "package-reference"
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# @deepseek-ai/dsh-file-reference-local
|
|
2
7
|
|
|
3
8
|
[English](README.md) | 中文
|
|
4
9
|
|
|
5
|
-
|
|
10
|
+
## 概述
|
|
11
|
+
|
|
12
|
+
agent(智能体)及其宿主 UI 获得 `@file` mention 的排序路径候选,范围限定在各自 agent 的工作区,并有界以保证大型仓库依然响应迅速。`dsh-file-reference-local` 在本地文件系统上实现 `ctx.fileReferences`:它为每个 agent 维护一个可复用的搜索索引,在工具结果后于后台重建索引,让补全反映工作区变化而不发生停顿,且从不跟随目录符号链接。当指定 agent 可以调用 `read` 时,它还会向系统提示词安装一句稳定指引。当 agent 的 `read` 工具作用于 Harness 宿主文件系统时选择它;远程或虚拟命名空间需要发现能力与工具一致的提供方。
|
|
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
|
+
当 `@file` 补全应发现 Harness 宿主自身的文件系统——即随附 `read` 工具所操作的命名空间——时,挂载此提供方。每个 agent 的工作区从该会话的工作目录开始建立索引;会话没有工作目录时回退到宿主进程目录。
|
|
29
|
+
|
|
30
|
+
### 启用提供方
|
|
31
|
+
|
|
32
|
+
默认设置适合典型工作区,因此最小挂载无需任何配置:
|
|
33
|
+
|
|
34
|
+
```yaml
|
|
35
|
+
- name: '@deepseek-ai/dsh-file-reference-local'
|
|
36
|
+
config:
|
|
37
|
+
maxResults: 20
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
### 你能得到什么
|
|
41
|
+
|
|
42
|
+
在宿主 UI 中输入 `@` 会为指定 agent 返回至多 `maxResults` 个排序路径候选。包含 `/` 的查询直接列出匹配目录的条目;裸查询对有界递归索引做模糊排序。目录候选以尾斜杠保持 mention 开放。任何工具结果之后,该 agent 的索引会被标记为陈旧:下一次查询仍由它作答,其替代品在后台构建,因此重建不会挡在光标前面。
|
|
43
|
+
|
|
44
|
+
### 配置
|
|
45
|
+
|
|
46
|
+
| 字段 | 默认值 | 含义 |
|
|
47
|
+
|---|---|---|
|
|
48
|
+
| `maxResults` | `20` | 单次查询返回的排序候选最大数量 |
|
|
49
|
+
| `maxEntries` | `50000` | 每个 agent 工作区建立索引的文件与目录最大数量 |
|
|
50
|
+
| `excludedDirectories` | `['.git', 'node_modules', 'dist', 'build', 'out', 'coverage', 'target', '.next', '.nuxt', '.turbo', '.venv', '__pycache__', '.pytest_cache', '.mypy_cache', '.gradle']` | 遍历与候选中排除的目录基名 |
|
|
51
|
+
|
|
52
|
+
所有数值都必须是正的安全整数,所有排除名都必须是不含 `/` 或 `\` 的非空基名。
|
|
53
|
+
|
|
54
|
+
-----
|
|
55
|
+
|
|
56
|
+
<a id="understand-the-implementation"></a>
|
|
57
|
+
## 理解实现
|
|
6
58
|
|
|
7
|
-
|
|
59
|
+
<details>
|
|
60
|
+
<summary>实现细节——点击展开</summary>
|
|
8
61
|
|
|
9
|
-
|
|
62
|
+
本节解释提供方的设计;可观察行为见[使用本包](#use-this-package)。
|
|
10
63
|
|
|
11
|
-
|
|
12
|
-
|---|---:|---|
|
|
13
|
-
| `maxResults` | `20` | 单次查询返回的候选项最大数量。 |
|
|
14
|
-
| `maxEntries` | `10000` | 每个 agent 工作区建立索引的文件和目录最大数量。 |
|
|
15
|
-
| `excludedDirectories` | `[".git", "node_modules"]` | 遍历和候选项中排除的目录基名。 |
|
|
64
|
+
### 设计理念
|
|
16
65
|
|
|
17
|
-
|
|
66
|
+
提供方为每个 agent 维护一个可复用的 `WorkspaceFileSearch`,以该会话的 `cwd` 为根。目录范围查询(`a/b/...`)列出实时目录状态,裸模糊查询共享一次有界递归遍历。只有一个工作区的首次裸查询会等待该遍历;`tool/result` 事件把已完成的条目标记为陈旧,下一次裸查询在替代品构建期间继续由它作答。模型指引是按 agent 的提示词段,仅在指定 agent 拥有 `read` 工具时贡献;agent 释放时会同时释放索引与提示词 fiber。
|
|
18
67
|
|
|
68
|
+
### 源码地图
|
|
69
|
+
|
|
70
|
+
| 文件 | 职责 |
|
|
71
|
+
|---|---|
|
|
72
|
+
| [`src/index.ts`](src/index.ts) | `LocalFileReferenceService`:配置校验、按 agent 搜索、提示词安装 |
|
|
73
|
+
| [`src/search.ts`](src/search.ts) | `WorkspaceFileSearch`:遍历、排序、排除、陈旧标记与后台重建 |
|
|
74
|
+
| [`src/invariant.ts`](src/invariant.ts) | 发现约定的不变式伴生插件 |
|
|
75
|
+
|
|
76
|
+
### 主要流程
|
|
77
|
+
|
|
78
|
+
`list(agent, query, signal)` 要么列出某个目录的条目,要么读取共享的有界索引,对候选排序(精确、前缀、子串,再到子序列得分,目录有加成),并按确定性顺序返回至多 `maxResults` 个。`tool/result` 事件把指定 agent 的索引标记为陈旧,之后的裸查询因此观察到全新目录树。不可读或已排除的子目录不贡献候选,而不可读的根目录则让该次遍历失败:一次瞬时故障不得用空索引覆盖仍然有效的条目。
|
|
79
|
+
|
|
80
|
+
</details>
|
|
81
|
+
|
|
82
|
+
-----
|
|
83
|
+
|
|
84
|
+
<a id="further-exploration"></a>
|
|
85
|
+
## 进一步探索
|
|
86
|
+
|
|
87
|
+
包级约定不够用时阅读以下页面。它们从本提供方所实现的 seam 进入其候选所指向的工具。
|
|
88
|
+
|
|
89
|
+
- [文件引用 seam](../file-reference/README.zh.md)——本提供方所实现的服务约定与 `@file` 语法。
|
|
90
|
+
- [会话引用子系统](../../../docs/subsystems/session-reference.zh.md)——宿主 UI 背后的共享文件引用约定。
|
|
91
|
+
- [文件系统工具目录](../../../docs/tool-catalog.zh.md#deepseek-aidsh-tool-fs)——发现能力必须匹配其命名空间的 `read` 工具。
|
|
92
|
+
- [context 组地图](../README.zh.md)——相邻的请求上下文包。
|
|
93
|
+
|
|
94
|
+
-----
|
|
95
|
+
|
|
96
|
+
<a id="model-experience"></a>
|
|
19
97
|
## 模型体验
|
|
20
98
|
|
|
21
99
|
### `read` 可用时的文件引用指引
|
|
22
100
|
|
|
23
|
-
####
|
|
101
|
+
#### 模型看到的内容
|
|
24
102
|
|
|
25
103
|
当指定 agent 有实际生效的 `read` 工具时,提供方会贡献以下稳定的系统提示词段:
|
|
26
104
|
|
|
27
105
|
##### 文件引用指令
|
|
28
106
|
|
|
29
107
|
```markdown
|
|
30
|
-
|
|
108
|
+
Tokens prefixed with @ are workspace paths the user explicitly referenced, relative to the workspace root. A trailing slash marks a directory: list it when its contents matter. Anything else is a file: use the read tool when its contents are needed, and do not claim to have inspected it before reading. @"..." quotes a path containing spaces.
|
|
31
109
|
```
|
|
32
110
|
|
|
33
111
|
#### Token 影响
|
|
34
112
|
|
|
35
113
|
该影响有条件且固定:只要 `read` 对指定 agent 可见,这一句就会存在;候选查询本身不增加 token,所选路径只会贡献普通用户消息中的对应字符。
|
|
36
114
|
|
|
37
|
-
#### KV
|
|
115
|
+
#### KV Cache 影响
|
|
116
|
+
|
|
117
|
+
该稳定句子会加入系统提示词前缀。挂载或移除此提供方,或者改变 `read` 是否可见,都会改变该前缀;查询、候选项和索引陈旧标记不会改变前缀。
|
|
118
|
+
|
|
119
|
+
## 已知限制与延期工作
|
|
120
|
+
|
|
121
|
+
<a id="known-limitations-and-deferred-work"></a>
|
|
38
122
|
|
|
39
|
-
该稳定句子会加入系统提示词前缀。挂载或移除此提供方,或者改变 `read` 是否可见,都会改变该前缀;查询、候选项和索引失效不会改变前缀。
|
|
40
123
|
|
|
41
|
-
|
|
124
|
+
这些限制说明该提供方何时不合适。它们是当前包约束。
|
|
42
125
|
|
|
43
126
|
- **宿主本地命名空间**:提供方扫描 Harness 宿主的文件系统,因此远程或虚拟 `read` 实现需要使用命名空间与该工具一致的提供方。
|
|
44
|
-
- **有界的提示性索引**:超大型工作区可能省略 `maxEntries`
|
|
127
|
+
- **有界的提示性索引**:超大型工作区可能省略 `maxEntries` 之后的路径;被排除或无法读取的目录不会出现。默认排除项只列没有任何生态用作源码目录的构建产物;`lib` 被刻意排除在外,因此构建进 `lib` 的工作区需通过 `excludedDirectories` 自行加上。
|
|
128
|
+
- **一次失效的陈旧窗口**:紧接工具结果之后的模糊查询反映的是上一次遍历时的目录树;下一次查询才看到重建结果。
|
|
45
129
|
- **没有忽略文件语义**:`.gitignore` 和其他项目忽略文件不会影响发现;系统只排除已配置的目录基名。
|
|
130
|
+
|
|
131
|
+
<a id="dev-note"></a>
|
|
132
|
+
### 开发备注
|
|
133
|
+
|
|
134
|
+
<details>
|
|
135
|
+
<summary>维护者的工作上下文——点击展开</summary>
|
|
136
|
+
|
|
137
|
+
无。
|
|
138
|
+
|
|
139
|
+
</details>
|
package/lib/index.js
CHANGED
|
@@ -14,19 +14,51 @@ import { activeAtToken, formatFileMention } from "@deepseek-ai/dsh-file-referenc
|
|
|
14
14
|
/** Default maximum file and directory candidates rendered for one query. */
|
|
15
15
|
const DEFAULT_FILE_SEARCH_MAX_RESULTS = 20;
|
|
16
16
|
/** Default maximum entries retained in one workspace search index. */
|
|
17
|
-
const DEFAULT_FILE_SEARCH_MAX_ENTRIES =
|
|
18
|
-
/**
|
|
19
|
-
|
|
17
|
+
const DEFAULT_FILE_SEARCH_MAX_ENTRIES = 5e4;
|
|
18
|
+
/**
|
|
19
|
+
* Directory basenames omitted from traversal unless the deployment overrides
|
|
20
|
+
* them: version-control and dependency stores plus build-output names that no
|
|
21
|
+
* ecosystem also uses for sources. Generated files carry the basenames of the
|
|
22
|
+
* sources that produced them, so an unfiltered tree both spends the entry
|
|
23
|
+
* budget twice and ranks `dist/x.js` beside `src/x.ts` for every query.
|
|
24
|
+
*
|
|
25
|
+
* `lib` is deliberately absent: Ruby gems and many npm packages keep their
|
|
26
|
+
* sources there, and excluding it would make `@` miss those sources entirely
|
|
27
|
+
* and silently. A workspace that builds into `lib` adds it through
|
|
28
|
+
* `excludedDirectories`.
|
|
29
|
+
*/
|
|
30
|
+
const DEFAULT_FILE_SEARCH_EXCLUDED_DIRECTORIES = [
|
|
31
|
+
".git",
|
|
32
|
+
"node_modules",
|
|
33
|
+
"dist",
|
|
34
|
+
"build",
|
|
35
|
+
"out",
|
|
36
|
+
"coverage",
|
|
37
|
+
"target",
|
|
38
|
+
".next",
|
|
39
|
+
".nuxt",
|
|
40
|
+
".turbo",
|
|
41
|
+
".venv",
|
|
42
|
+
"__pycache__",
|
|
43
|
+
".pytest_cache",
|
|
44
|
+
".mypy_cache",
|
|
45
|
+
".gradle"
|
|
46
|
+
];
|
|
20
47
|
/**
|
|
21
48
|
* Cancellable, reusable fuzzy index rooted at one agent working directory.
|
|
22
49
|
* Directory-scoped queries list live state; bare fuzzy queries share one
|
|
23
|
-
* bounded traversal
|
|
50
|
+
* bounded traversal. Only the first query of a workspace waits for that
|
|
51
|
+
* traversal — an invalidated index keeps answering while its replacement
|
|
52
|
+
* builds behind the caret.
|
|
24
53
|
*/
|
|
25
54
|
var WorkspaceFileSearch = class {
|
|
26
55
|
root;
|
|
27
56
|
config;
|
|
28
57
|
excludedDirectories;
|
|
58
|
+
settled;
|
|
29
59
|
generation;
|
|
60
|
+
/** Monotonic invalidation counter; a settled index below it is stale. */
|
|
61
|
+
invalidations = 0;
|
|
30
62
|
disposed = false;
|
|
31
63
|
constructor(root, config) {
|
|
32
64
|
this.root = root;
|
|
@@ -52,28 +84,61 @@ var WorkspaceFileSearch = class {
|
|
|
52
84
|
const fragment = slash < 0 ? "" : query.slice(slash + 1);
|
|
53
85
|
return this.listDirectory(directory, fragment, signal);
|
|
54
86
|
}
|
|
55
|
-
return rankCandidates((await
|
|
87
|
+
return rankCandidates((await this.indexFor(signal)).filter((candidate) => visibleForGlobalQuery(candidate.path, query)), query, this.config.maxResults);
|
|
56
88
|
}
|
|
57
|
-
/**
|
|
89
|
+
/**
|
|
90
|
+
* Mark the index stale so a later bare query observes a fresh tree.
|
|
91
|
+
*
|
|
92
|
+
* The stale entries are kept and keep answering: a rebuild costs one
|
|
93
|
+
* traversal of the whole workspace, and putting that in front of the caret
|
|
94
|
+
* is what a caller invalidating on every tool result would otherwise pay.
|
|
95
|
+
*/
|
|
58
96
|
invalidate() {
|
|
59
|
-
this.
|
|
60
|
-
this.generation = void 0;
|
|
97
|
+
this.invalidations += 1;
|
|
61
98
|
}
|
|
62
99
|
/** Abort traversal and make later queries return no candidates. */
|
|
63
100
|
dispose() {
|
|
64
101
|
if (this.disposed) return;
|
|
65
102
|
this.disposed = true;
|
|
66
|
-
this.
|
|
103
|
+
this.generation?.controller.abort(/* @__PURE__ */ new Error("file search index disposed"));
|
|
104
|
+
this.generation = void 0;
|
|
105
|
+
this.settled = void 0;
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* The entries a bare fuzzy query ranks. Only the first query of a workspace
|
|
109
|
+
* waits for a traversal; afterwards a stale index answers immediately and
|
|
110
|
+
* its replacement builds in the background.
|
|
111
|
+
* @param signal - cancels this caller's wait without killing a shared traversal.
|
|
112
|
+
* @returns indexed paths, at most one invalidation behind the tree.
|
|
113
|
+
*/
|
|
114
|
+
async indexFor(signal) {
|
|
115
|
+
const settled = this.settled;
|
|
116
|
+
if (settled === void 0) return waitForPromise(this.ensureIndex(), signal);
|
|
117
|
+
if (settled.startedAt < this.invalidations) this.ensureIndex().catch(() => {});
|
|
118
|
+
return settled.entries;
|
|
67
119
|
}
|
|
68
120
|
ensureIndex() {
|
|
69
121
|
if (this.generation !== void 0) return this.generation.promise;
|
|
70
122
|
const controller = new AbortController();
|
|
123
|
+
const startedAt = this.invalidations;
|
|
71
124
|
const generation = {
|
|
72
125
|
controller,
|
|
73
126
|
promise: Promise.resolve([])
|
|
74
127
|
};
|
|
75
|
-
generation.promise = this.scanWorkspace(controller.signal).
|
|
76
|
-
/* v8 ignore next --
|
|
128
|
+
generation.promise = this.scanWorkspace(controller.signal).then((entries) => {
|
|
129
|
+
/* v8 ignore next -- disposal aborts this traversal, so it reaches the
|
|
130
|
+
* rejection handler instead; the guard only covers a scan that finished
|
|
131
|
+
* its last directory in the instant before the abort landed, and must
|
|
132
|
+
* not hand a disposed index its entries back. */
|
|
133
|
+
if (this.disposed) return entries;
|
|
134
|
+
this.generation = void 0;
|
|
135
|
+
this.settled = {
|
|
136
|
+
entries,
|
|
137
|
+
startedAt
|
|
138
|
+
};
|
|
139
|
+
return entries;
|
|
140
|
+
}, (error) => {
|
|
141
|
+
/* v8 ignore next -- dispose clears `generation` synchronously; this only protects an unexpected scan failure */
|
|
77
142
|
if (this.generation === generation) this.generation = void 0;
|
|
78
143
|
throw error;
|
|
79
144
|
});
|
|
@@ -91,7 +156,7 @@ var WorkspaceFileSearch = class {
|
|
|
91
156
|
const directory = directories[cursor];
|
|
92
157
|
/* v8 ignore next 3 -- cursor is bounded by this exact queue's length. */
|
|
93
158
|
if (directory === void 0) throw new Error("file search selected a missing directory");
|
|
94
|
-
const entries = await readDirectory(directory.absolute, signal);
|
|
159
|
+
const entries = cursor === 0 ? await readWorkspaceRoot(directory.absolute, signal) : await readDirectory(directory.absolute, signal);
|
|
95
160
|
for (const entry of entries) {
|
|
96
161
|
signal.throwIfAborted();
|
|
97
162
|
const path = directory.relative === "" ? entry.name : `${directory.relative}/${entry.name}`;
|
|
@@ -158,6 +223,12 @@ async function resolveDisplayDirectory(root, displayDirectory, signal) {
|
|
|
158
223
|
}
|
|
159
224
|
return absolute;
|
|
160
225
|
}
|
|
226
|
+
async function readWorkspaceRoot(absolute, signal) {
|
|
227
|
+
signal.throwIfAborted();
|
|
228
|
+
const entries = await readdir(absolute, { withFileTypes: true });
|
|
229
|
+
signal.throwIfAborted();
|
|
230
|
+
return entries.sort((left, right) => compareText(left.name, right.name));
|
|
231
|
+
}
|
|
161
232
|
async function readDirectory(absolute, signal) {
|
|
162
233
|
signal.throwIfAborted();
|
|
163
234
|
try {
|
|
@@ -260,7 +331,7 @@ var LocalFileReferenceService = class extends FileReferenceService {
|
|
|
260
331
|
super(ctx);
|
|
261
332
|
this.config = {
|
|
262
333
|
maxResults: config.maxResults ?? 20,
|
|
263
|
-
maxEntries: config.maxEntries ??
|
|
334
|
+
maxEntries: config.maxEntries ?? 5e4,
|
|
264
335
|
excludedDirectories: config.excludedDirectories ?? DEFAULT_FILE_SEARCH_EXCLUDED_DIRECTORIES
|
|
265
336
|
};
|
|
266
337
|
validateConfig(this.config);
|
|
@@ -269,7 +340,7 @@ var LocalFileReferenceService = class extends FileReferenceService {
|
|
|
269
340
|
const fiber = agent.ctx.inject(["systemPrompt", "tools"], (scope) => {
|
|
270
341
|
scope.systemPrompt.section({
|
|
271
342
|
name: "context:file-reference",
|
|
272
|
-
order:
|
|
343
|
+
order: scope.systemPrompt.getSectionOrder("FILE_REFERENCE"),
|
|
273
344
|
text: () => agent.ctx.tools.get("read", agent) === void 0 ? "" : FILE_REFERENCE_PROMPT$1
|
|
274
345
|
});
|
|
275
346
|
});
|
package/lib/types/index.js
CHANGED
|
@@ -35,7 +35,7 @@ export class LocalFileReferenceService extends FileReferenceService {
|
|
|
35
35
|
const fiber = agent.ctx.inject(['systemPrompt', 'tools'], (scope) => {
|
|
36
36
|
scope.systemPrompt.section({
|
|
37
37
|
name: 'context:file-reference',
|
|
38
|
-
order:
|
|
38
|
+
order: scope.systemPrompt.getSectionOrder('FILE_REFERENCE'),
|
|
39
39
|
text: () => agent.ctx.tools.get('read', agent) === undefined ? '' : FILE_REFERENCE_PROMPT,
|
|
40
40
|
});
|
|
41
41
|
});
|
package/lib/types/search.d.ts
CHANGED
|
@@ -10,9 +10,20 @@ export { activeAtToken, formatFileMention } from '@deepseek-ai/dsh-file-referenc
|
|
|
10
10
|
/** Default maximum file and directory candidates rendered for one query. */
|
|
11
11
|
export declare const DEFAULT_FILE_SEARCH_MAX_RESULTS = 20;
|
|
12
12
|
/** Default maximum entries retained in one workspace search index. */
|
|
13
|
-
export declare const DEFAULT_FILE_SEARCH_MAX_ENTRIES =
|
|
14
|
-
/**
|
|
15
|
-
|
|
13
|
+
export declare const DEFAULT_FILE_SEARCH_MAX_ENTRIES = 50000;
|
|
14
|
+
/**
|
|
15
|
+
* Directory basenames omitted from traversal unless the deployment overrides
|
|
16
|
+
* them: version-control and dependency stores plus build-output names that no
|
|
17
|
+
* ecosystem also uses for sources. Generated files carry the basenames of the
|
|
18
|
+
* sources that produced them, so an unfiltered tree both spends the entry
|
|
19
|
+
* budget twice and ranks `dist/x.js` beside `src/x.ts` for every query.
|
|
20
|
+
*
|
|
21
|
+
* `lib` is deliberately absent: Ruby gems and many npm packages keep their
|
|
22
|
+
* sources there, and excluding it would make `@` miss those sources entirely
|
|
23
|
+
* and silently. A workspace that builds into `lib` adds it through
|
|
24
|
+
* `excludedDirectories`.
|
|
25
|
+
*/
|
|
26
|
+
export declare const DEFAULT_FILE_SEARCH_EXCLUDED_DIRECTORIES: readonly [".git", "node_modules", "dist", "build", "out", "coverage", "target", ".next", ".nuxt", ".turbo", ".venv", "__pycache__", ".pytest_cache", ".mypy_cache", ".gradle"];
|
|
16
27
|
/** Resolved limits and exclusions for one workspace index. */
|
|
17
28
|
export interface FileSearchConfig {
|
|
18
29
|
/** Maximum ranked candidates returned for one query. */
|
|
@@ -25,13 +36,18 @@ export interface FileSearchConfig {
|
|
|
25
36
|
/**
|
|
26
37
|
* Cancellable, reusable fuzzy index rooted at one agent working directory.
|
|
27
38
|
* Directory-scoped queries list live state; bare fuzzy queries share one
|
|
28
|
-
* bounded traversal
|
|
39
|
+
* bounded traversal. Only the first query of a workspace waits for that
|
|
40
|
+
* traversal — an invalidated index keeps answering while its replacement
|
|
41
|
+
* builds behind the caret.
|
|
29
42
|
*/
|
|
30
43
|
export declare class WorkspaceFileSearch {
|
|
31
44
|
private readonly root;
|
|
32
45
|
private readonly config;
|
|
33
46
|
private readonly excludedDirectories;
|
|
47
|
+
private settled;
|
|
34
48
|
private generation;
|
|
49
|
+
/** Monotonic invalidation counter; a settled index below it is stale. */
|
|
50
|
+
private invalidations;
|
|
35
51
|
private disposed;
|
|
36
52
|
constructor(root: string, config: FileSearchConfig);
|
|
37
53
|
/**
|
|
@@ -41,10 +57,24 @@ export declare class WorkspaceFileSearch {
|
|
|
41
57
|
* @returns at most `maxResults` deterministic candidates.
|
|
42
58
|
*/
|
|
43
59
|
list(rawQuery: string, signal: AbortSignal): Promise<FileReferenceCandidate[]>;
|
|
44
|
-
/**
|
|
60
|
+
/**
|
|
61
|
+
* Mark the index stale so a later bare query observes a fresh tree.
|
|
62
|
+
*
|
|
63
|
+
* The stale entries are kept and keep answering: a rebuild costs one
|
|
64
|
+
* traversal of the whole workspace, and putting that in front of the caret
|
|
65
|
+
* is what a caller invalidating on every tool result would otherwise pay.
|
|
66
|
+
*/
|
|
45
67
|
invalidate(): void;
|
|
46
68
|
/** Abort traversal and make later queries return no candidates. */
|
|
47
69
|
dispose(): void;
|
|
70
|
+
/**
|
|
71
|
+
* The entries a bare fuzzy query ranks. Only the first query of a workspace
|
|
72
|
+
* waits for a traversal; afterwards a stale index answers immediately and
|
|
73
|
+
* its replacement builds in the background.
|
|
74
|
+
* @param signal - cancels this caller's wait without killing a shared traversal.
|
|
75
|
+
* @returns indexed paths, at most one invalidation behind the tree.
|
|
76
|
+
*/
|
|
77
|
+
private indexFor;
|
|
48
78
|
private ensureIndex;
|
|
49
79
|
private scanWorkspace;
|
|
50
80
|
private listDirectory;
|
package/lib/types/search.js
CHANGED
|
@@ -11,19 +11,51 @@ export { activeAtToken, formatFileMention } from '@deepseek-ai/dsh-file-referenc
|
|
|
11
11
|
/** Default maximum file and directory candidates rendered for one query. */
|
|
12
12
|
export const DEFAULT_FILE_SEARCH_MAX_RESULTS = 20;
|
|
13
13
|
/** Default maximum entries retained in one workspace search index. */
|
|
14
|
-
export const DEFAULT_FILE_SEARCH_MAX_ENTRIES =
|
|
15
|
-
/**
|
|
16
|
-
|
|
14
|
+
export const DEFAULT_FILE_SEARCH_MAX_ENTRIES = 50_000;
|
|
15
|
+
/**
|
|
16
|
+
* Directory basenames omitted from traversal unless the deployment overrides
|
|
17
|
+
* them: version-control and dependency stores plus build-output names that no
|
|
18
|
+
* ecosystem also uses for sources. Generated files carry the basenames of the
|
|
19
|
+
* sources that produced them, so an unfiltered tree both spends the entry
|
|
20
|
+
* budget twice and ranks `dist/x.js` beside `src/x.ts` for every query.
|
|
21
|
+
*
|
|
22
|
+
* `lib` is deliberately absent: Ruby gems and many npm packages keep their
|
|
23
|
+
* sources there, and excluding it would make `@` miss those sources entirely
|
|
24
|
+
* and silently. A workspace that builds into `lib` adds it through
|
|
25
|
+
* `excludedDirectories`.
|
|
26
|
+
*/
|
|
27
|
+
export const DEFAULT_FILE_SEARCH_EXCLUDED_DIRECTORIES = [
|
|
28
|
+
'.git',
|
|
29
|
+
'node_modules',
|
|
30
|
+
'dist',
|
|
31
|
+
'build',
|
|
32
|
+
'out',
|
|
33
|
+
'coverage',
|
|
34
|
+
'target',
|
|
35
|
+
'.next',
|
|
36
|
+
'.nuxt',
|
|
37
|
+
'.turbo',
|
|
38
|
+
'.venv',
|
|
39
|
+
'__pycache__',
|
|
40
|
+
'.pytest_cache',
|
|
41
|
+
'.mypy_cache',
|
|
42
|
+
'.gradle',
|
|
43
|
+
];
|
|
17
44
|
/**
|
|
18
45
|
* Cancellable, reusable fuzzy index rooted at one agent working directory.
|
|
19
46
|
* Directory-scoped queries list live state; bare fuzzy queries share one
|
|
20
|
-
* bounded traversal
|
|
47
|
+
* bounded traversal. Only the first query of a workspace waits for that
|
|
48
|
+
* traversal — an invalidated index keeps answering while its replacement
|
|
49
|
+
* builds behind the caret.
|
|
21
50
|
*/
|
|
22
51
|
export class WorkspaceFileSearch {
|
|
23
52
|
root;
|
|
24
53
|
config;
|
|
25
54
|
excludedDirectories;
|
|
55
|
+
settled;
|
|
26
56
|
generation;
|
|
57
|
+
/** Monotonic invalidation counter; a settled index below it is stale. */
|
|
58
|
+
invalidations = 0;
|
|
27
59
|
disposed = false;
|
|
28
60
|
constructor(root, config) {
|
|
29
61
|
this.root = root;
|
|
@@ -56,31 +88,69 @@ export class WorkspaceFileSearch {
|
|
|
56
88
|
const fragment = slash < 0 ? '' : query.slice(slash + 1);
|
|
57
89
|
return this.listDirectory(directory, fragment, signal);
|
|
58
90
|
}
|
|
59
|
-
const indexed = await
|
|
91
|
+
const indexed = await this.indexFor(signal);
|
|
60
92
|
return rankCandidates(indexed.filter(candidate => visibleForGlobalQuery(candidate.path, query)), query, this.config.maxResults);
|
|
61
93
|
}
|
|
62
|
-
/**
|
|
94
|
+
/**
|
|
95
|
+
* Mark the index stale so a later bare query observes a fresh tree.
|
|
96
|
+
*
|
|
97
|
+
* The stale entries are kept and keep answering: a rebuild costs one
|
|
98
|
+
* traversal of the whole workspace, and putting that in front of the caret
|
|
99
|
+
* is what a caller invalidating on every tool result would otherwise pay.
|
|
100
|
+
*/
|
|
63
101
|
invalidate() {
|
|
64
|
-
this.
|
|
65
|
-
this.generation = undefined;
|
|
102
|
+
this.invalidations += 1;
|
|
66
103
|
}
|
|
67
104
|
/** Abort traversal and make later queries return no candidates. */
|
|
68
105
|
dispose() {
|
|
69
106
|
if (this.disposed)
|
|
70
107
|
return;
|
|
71
108
|
this.disposed = true;
|
|
72
|
-
this.
|
|
109
|
+
this.generation?.controller.abort(new Error('file search index disposed'));
|
|
110
|
+
this.generation = undefined;
|
|
111
|
+
this.settled = undefined;
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* The entries a bare fuzzy query ranks. Only the first query of a workspace
|
|
115
|
+
* waits for a traversal; afterwards a stale index answers immediately and
|
|
116
|
+
* its replacement builds in the background.
|
|
117
|
+
* @param signal - cancels this caller's wait without killing a shared traversal.
|
|
118
|
+
* @returns indexed paths, at most one invalidation behind the tree.
|
|
119
|
+
*/
|
|
120
|
+
async indexFor(signal) {
|
|
121
|
+
const settled = this.settled;
|
|
122
|
+
if (settled === undefined)
|
|
123
|
+
return waitForPromise(this.ensureIndex(), signal);
|
|
124
|
+
if (settled.startedAt < this.invalidations) {
|
|
125
|
+
void this.ensureIndex().catch(() => {
|
|
126
|
+
// A background refresh failure is not this caller's error: the stale
|
|
127
|
+
// entries still answer and `settled.startedAt` stays behind, so the
|
|
128
|
+
// next bare query starts a fresh attempt.
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
return settled.entries;
|
|
73
132
|
}
|
|
74
133
|
ensureIndex() {
|
|
75
134
|
if (this.generation !== undefined)
|
|
76
135
|
return this.generation.promise;
|
|
77
136
|
const controller = new AbortController();
|
|
137
|
+
const startedAt = this.invalidations;
|
|
78
138
|
const generation = {
|
|
79
139
|
controller,
|
|
80
140
|
promise: Promise.resolve([]),
|
|
81
141
|
};
|
|
82
|
-
generation.promise = this.scanWorkspace(controller.signal).
|
|
83
|
-
/* v8 ignore next --
|
|
142
|
+
generation.promise = this.scanWorkspace(controller.signal).then((entries) => {
|
|
143
|
+
/* v8 ignore next -- disposal aborts this traversal, so it reaches the
|
|
144
|
+
* rejection handler instead; the guard only covers a scan that finished
|
|
145
|
+
* its last directory in the instant before the abort landed, and must
|
|
146
|
+
* not hand a disposed index its entries back. */
|
|
147
|
+
if (this.disposed)
|
|
148
|
+
return entries;
|
|
149
|
+
this.generation = undefined;
|
|
150
|
+
this.settled = { entries, startedAt };
|
|
151
|
+
return entries;
|
|
152
|
+
}, (error) => {
|
|
153
|
+
/* v8 ignore next -- dispose clears `generation` synchronously; this only protects an unexpected scan failure */
|
|
84
154
|
if (this.generation === generation)
|
|
85
155
|
this.generation = undefined;
|
|
86
156
|
throw error;
|
|
@@ -98,7 +168,13 @@ export class WorkspaceFileSearch {
|
|
|
98
168
|
if (directory === undefined) {
|
|
99
169
|
throw new Error('file search selected a missing directory');
|
|
100
170
|
}
|
|
101
|
-
|
|
171
|
+
// The root is not a subtree: an unreadable branch costs its own
|
|
172
|
+
// candidates, but an unreadable root means the traversal learned
|
|
173
|
+
// nothing. Letting that settle would publish an empty index over
|
|
174
|
+
// entries that are still good and leave no invalidation to retry from.
|
|
175
|
+
const entries = cursor === 0
|
|
176
|
+
? await readWorkspaceRoot(directory.absolute, signal)
|
|
177
|
+
: await readDirectory(directory.absolute, signal);
|
|
102
178
|
for (const entry of entries) {
|
|
103
179
|
signal.throwIfAborted();
|
|
104
180
|
const path = directory.relative === '' ? entry.name : `${directory.relative}/${entry.name}`;
|
|
@@ -166,6 +242,12 @@ async function resolveDisplayDirectory(root, displayDirectory, signal) {
|
|
|
166
242
|
}
|
|
167
243
|
return absolute;
|
|
168
244
|
}
|
|
245
|
+
async function readWorkspaceRoot(absolute, signal) {
|
|
246
|
+
signal.throwIfAborted();
|
|
247
|
+
const entries = await readdir(absolute, { withFileTypes: true });
|
|
248
|
+
signal.throwIfAborted();
|
|
249
|
+
return entries.sort((left, right) => compareText(left.name, right.name));
|
|
250
|
+
}
|
|
169
251
|
async function readDirectory(absolute, signal) {
|
|
170
252
|
signal.throwIfAborted();
|
|
171
253
|
try {
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@deepseek-ai/dsh-file-reference-local",
|
|
3
3
|
"description": "Local-filesystem ctx.fileReferences provider with bounded fuzzy indexes",
|
|
4
|
-
"version": "0.1.
|
|
4
|
+
"version": "0.1.2-alpha.2",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
7
7
|
},
|
|
@@ -37,22 +37,22 @@
|
|
|
37
37
|
],
|
|
38
38
|
"license": "MIT",
|
|
39
39
|
"dependencies": {
|
|
40
|
-
"@deepseek-ai/schemastery": "^3.18.
|
|
40
|
+
"@deepseek-ai/schemastery": "^3.18.2"
|
|
41
41
|
},
|
|
42
42
|
"peerDependencies": {
|
|
43
|
-
"@deepseek-ai/dsh-agent": "^0.1.
|
|
44
|
-
"@deepseek-ai/dsh-
|
|
45
|
-
"@deepseek-ai/dsh-
|
|
46
|
-
"@deepseek-ai/dsh-system-prompt": "^0.1.
|
|
47
|
-
"@deepseek-ai/dsh-tools": "^0.1.
|
|
48
|
-
"@deepseek-ai/cordis": "^4.0.
|
|
43
|
+
"@deepseek-ai/dsh-agent": "^0.1.2-alpha.2",
|
|
44
|
+
"@deepseek-ai/dsh-file-reference": "^0.1.2-alpha.2",
|
|
45
|
+
"@deepseek-ai/dsh-invariants": "^0.1.2-alpha.2",
|
|
46
|
+
"@deepseek-ai/dsh-system-prompt": "^0.1.2-alpha.2",
|
|
47
|
+
"@deepseek-ai/dsh-tools": "^0.1.2-alpha.2",
|
|
48
|
+
"@deepseek-ai/cordis": "^4.0.2"
|
|
49
49
|
},
|
|
50
50
|
"devDependencies": {
|
|
51
|
-
"@deepseek-ai/dsh-agent": "^0.1.
|
|
52
|
-
"@deepseek-ai/dsh-file-reference": "^0.1.
|
|
53
|
-
"@deepseek-ai/dsh-
|
|
54
|
-
"@deepseek-ai/dsh-tools": "^0.1.
|
|
55
|
-
"@deepseek-ai/dsh-
|
|
56
|
-
"@deepseek-ai/cordis": "^4.0.
|
|
51
|
+
"@deepseek-ai/dsh-agent": "^0.1.2-alpha.2",
|
|
52
|
+
"@deepseek-ai/dsh-file-reference": "^0.1.2-alpha.2",
|
|
53
|
+
"@deepseek-ai/dsh-invariants": "^0.1.2-alpha.2",
|
|
54
|
+
"@deepseek-ai/dsh-tools": "^0.1.2-alpha.2",
|
|
55
|
+
"@deepseek-ai/dsh-system-prompt": "^0.1.2-alpha.2",
|
|
56
|
+
"@deepseek-ai/cordis": "^4.0.2"
|
|
57
57
|
}
|
|
58
58
|
}
|