@v587d/capital-generation 2.11.0 → 2.12.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.
- package/CHANGELOG.md +31 -0
- package/README.md +4 -4
- package/chart-ui/package.json +1 -1
- package/config/package.json +1 -1
- package/lib/sources/fuyao-rest.js +1 -1
- package/lib/web-retriever/local-fetch.d.ts +1 -1
- package/lib/web-retriever/local-fetch.js +1 -1
- package/lib/web-retriever/sources.d.ts +4 -0
- package/lib/web-retriever/sources.js +21 -7
- package/lib/web-retriever/wind-client.d.ts +1 -1
- package/lib/web-retriever/wind-client.js +1 -1
- package/package.json +6 -6
- package/preset/capital-generation/README.md +1 -1
- package/watchlist/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,37 @@
|
|
|
7
7
|
- **第三位(patch)**:不破坏既有工具 / 配置 / 会话的新增与修复(如 2.1.1、2.1.2)。
|
|
8
8
|
- **第二位(minor)**:有需要用户知晓的行为变更,且段内附迁移说明(如 2.1.0 的图表呈现通道重做、2.2.0 的数据源与检索来源扩容、2.4.0 的**必须换宿主版本**、2.9.0 的选择器收敛与质检前置——本插件自己的工具与数据契约没变,所以只抬第二位)。
|
|
9
9
|
|
|
10
|
+
## [2.12.0] - 2026-10-26
|
|
11
|
+
|
|
12
|
+
宿主基线从 `0.2.1-rc.2` 抬到 `0.2.1-rc.3`。rc.3 只改客户端界面与 DeepSeek 模型列表,本插件消费的
|
|
13
|
+
扩展面(配置卡片、自选股弹窗、图表卡片、交付事件)逐条核对后没有形状变化,工具与数据契约不变。
|
|
14
|
+
|
|
15
|
+
### Changed
|
|
16
|
+
|
|
17
|
+
- **`peerDependencies` 的 `dsh-skill` / `dsh-skill-filesystem` 改成精确 pin `0.2.1-rc.3`**:
|
|
18
|
+
这两颗是运行时导入(`FileSystemSkillProvider`),与宿主同版才不会有"插件带 rc.3 的 provider
|
|
19
|
+
接 rc.2 的 skill 服务"这种跨版本组合。`devDependencies` 与 lockfile 同步到 rc.3。
|
|
20
|
+
- README 基线徽章、CONTRIBUTING、CI 安装版本、preset 维护文档同步到 rc.3。
|
|
21
|
+
|
|
22
|
+
### Migration
|
|
23
|
+
|
|
24
|
+
- **本次必须换宿主版本**:先 `dsh --version` 确认为 `0.2.1-rc.3`,再安装或更新本插件。在 rc.2 上
|
|
25
|
+
安装本版会被宿主的插件兼容预检直接拒绝;反过来,若先升宿主而插件仍是 2.11.1,启动时该插件行
|
|
26
|
+
会被禁用(stderr 一行 `disabling profile plugin ...`,界面上模式与工具整体消失),执行
|
|
27
|
+
`dsh plugin --profile <profile> update @v587d/capital-generation` 后重启即可恢复。
|
|
28
|
+
- rc.3 的 New Session 会复用 Workspace 里的空白会话:**更新插件后先重启宿主再新建会话**,
|
|
29
|
+
否则复用到的空白会话仍保留创建时的 preset 组合。
|
|
30
|
+
|
|
31
|
+
## [2.11.1] - 2026-10-26
|
|
32
|
+
|
|
33
|
+
### Fixed
|
|
34
|
+
|
|
35
|
+
- **财联社快讯在 50 条时必然解析失败**:具名来源沿用了 HTML 回退的 10 万字符上限,
|
|
36
|
+
`cls_telegraph limit=50` 的真实响应 106,106 字符被截断后报 `Unterminated string`。
|
|
37
|
+
具名来源改用独立上限(262,144 字符 / 1 MiB),截断时点名体积原因而不是 JSON 语法错误。
|
|
38
|
+
- **5003 被当成可重试失败**:`financial_indicators` 描述补明该码是报告期尚未入库的数据缺口
|
|
39
|
+
(实测 2026-3 全市场均如此),不要 `force_refresh` 重试。
|
|
40
|
+
|
|
10
41
|
## [2.11.0] - 2026-10-26
|
|
11
42
|
|
|
12
43
|
精选 Skills 收敛为「运行时只带 Markdown」:取数方式从 70 颗正文里移出,改由角色系统提示的
|
package/README.md
CHANGED
|
@@ -13,12 +13,12 @@
|
|
|
13
13
|
<a href="https://github.com/deepseek-ai"><img src="https://img.shields.io/badge/DeepSeek_Harness-plugin-blue" alt="DSH Plugin"></a>
|
|
14
14
|
<a href="https://github.com/deepseek-ai"><img src="https://img.shields.io/badge/DeepSeek_Harness-web-orange" alt="DSH Web"></a>
|
|
15
15
|
<a href="https://github.com/deepseek-ai"><img src="https://img.shields.io/badge/DeepSeek_Harness-desktop-brightgreen" alt="DSH Desktop · 已实机验证"></a>
|
|
16
|
-
<a href="https://github.com/deepseek-ai"><img src="https://img.shields.io/badge/DSH%20Baseline-0.2.1--rc.
|
|
16
|
+
<a href="https://github.com/deepseek-ai"><img src="https://img.shields.io/badge/DSH%20Baseline-0.2.1--rc.3-blue" alt="DSH@0.2.1-rc.3"></a>
|
|
17
17
|
</p>
|
|
18
18
|
<p align="center">
|
|
19
19
|
<a href="https://awesome-dsh-plugin.com"><img src="https://awesome-dsh-plugin.com/badge.svg" alt="awesome · DSH plugin"></a>
|
|
20
20
|
<a href="LICENSE"><img src="https://img.shields.io/badge/License-MIT-green" alt="License"></a>
|
|
21
|
-
<a href="https://github.com/v587d/capital-generation/releases"><img src="https://img.shields.io/badge/version-2.
|
|
21
|
+
<a href="https://github.com/v587d/capital-generation/releases"><img src="https://img.shields.io/badge/version-2.12.0-9cf" alt="Version"></a>
|
|
22
22
|
<a href="https://www.npmjs.com/package/@v587d/capital-generation"><img src="https://img.shields.io/npm/v/%40v587d%2Fcapital-generation" alt="npm version"></a>
|
|
23
23
|
<a href="https://github.com/deepseek-ai/deepseek-harness"><img src="https://img.shields.io/badge/powered_by-dsh-4D6BFE?style=flat-square&logo=deepseek&logoColor=white" alt="powered-by-dsh"></a>
|
|
24
24
|
</p>
|
|
@@ -37,7 +37,7 @@ Capital Generation 是运行在 [DeepSeek Harness(DSH)](https://github.com/d
|
|
|
37
37
|
## 快速上手
|
|
38
38
|
|
|
39
39
|
> [!NOTE]
|
|
40
|
-
> 适配 DSH`@0.2.1-rc.
|
|
40
|
+
> 适配 DSH`@0.2.1-rc.3`。已在 Linux 的 Web profile 和 Windows 桌面端验证;其他环境尚未充分测试。建议使用 `Deepseek/deepseek-flash` ,思考推理能力为 High ;GPT / Claude 尚未充分测试。
|
|
41
41
|
|
|
42
42
|
1. **安装插件。**
|
|
43
43
|
|
|
@@ -202,7 +202,7 @@ https://github.com/v587d/capital-generation
|
|
|
202
202
|
- **安装后找不到模式?** 确认插件出现在「插件」→ 已安装列表;Web / CLI profile 安装后要重启该 profile,并在新会话选择模式。选择器里应看到自动模式、行情专家、资讯专员;分析师和绘图专员是自动模式的内部角色,不会出现在这里。
|
|
203
203
|
- **配置在哪?** 打开「插件」→ 已安装的 **Capital Generation**,页面顶部就是「数据源 / 精选 Skills / 包含的组件」三格,五把密钥都在第一格;不在 DSH 的普通「设置」页面,也不用点进任何一行组件。保存密钥后新建会话再试。
|
|
204
204
|
- **升级到 2.9.0 后,分析师和绘图专员去哪了?** 这一版把它们收进自动模式内部,不再出现在选择器与预设管理里,避免误开一个没有取数入口的空会话。旧会话仍能按原身份恢复;新任务直接用自动模式提出即可。
|
|
205
|
-
- **桌面端升级后仍是旧版?** 桌面端安装时会固定所解析的版本,不会自动升级。卸载后重新安装,再到插件详情查看版本号;如需指定版本,可在地址末尾加 `#v2.
|
|
205
|
+
- **桌面端升级后仍是旧版?** 桌面端安装时会固定所解析的版本,不会自动升级。卸载后重新安装,再到插件详情查看版本号;如需指定版本,可在地址末尾加 `#v2.12.0` 或 `@2.12.0`。
|
|
206
206
|
- **刚发布的新版本装不到?** 桌面端取包时会跳过**刚发布不久**的版本(宿主侧包管理器的发布冷却策略,实测会静默装成上一个版本),国内镜像的同步也可能滞后一段时间。急着用最新代码,改用仓库地址安装最直接。
|
|
207
207
|
- **网页抓取失败?** 配置卡片中的「允许启动本地提取网页内容」默认开启:AnySearch 提取失败时可尝试本机直连。关闭后,本机直连的具名来源查询也不可用;请检查该开关和网络连接。
|
|
208
208
|
- **Wind 那部分会消耗积分?** 会。公告与新闻检索、宏观 / 行业 / 汇率指标、按日期区间取的历史 K 线都按次消耗你在 Wind 侧的额度;额度与条款以 Wind 为准,插件不做用量封顶。没配 `WIND_API_KEY` 时这几类不可用,其余功能照常。
|
package/chart-ui/package.json
CHANGED
package/config/package.json
CHANGED
|
@@ -999,7 +999,7 @@ function endpointDefinitions() {
|
|
|
999
999
|
name: 'get_a_share_financials_indicators',
|
|
1000
1000
|
capability: 'financial_indicators',
|
|
1001
1001
|
summary: '单期五类财务指标(成长/盈利/偿债/营运/现金流)',
|
|
1002
|
-
description: '获取单只标的指定报告期的五类财务指标(growth/profitability/solvency/operation/cash-flow)。thscode 不接受逗号;report 格式 yyyy-1..yyyy-4(1 一季报/2 中报/3 三季报/4 年报)。返回 data.abilities[].indicators[],每项含 index_id 与 value:value 是数据源原始数值**字符串**(保留精度与尾随小数位,不转 number),缺失为 null;百分比类指标按百分数原值表达(如 89.12000000 表示 89.12%),周转率按次、已获利息倍数按倍,展示时按 index_id
|
|
1002
|
+
description: '获取单只标的指定报告期的五类财务指标(growth/profitability/solvency/operation/cash-flow)。thscode 不接受逗号;report 格式 yyyy-1..yyyy-4(1 一季报/2 中报/3 三季报/4 年报)。返回 data.abilities[].indicators[],每项含 index_id 与 value:value 是数据源原始数值**字符串**(保留精度与尾随小数位,不转 number),缺失为 null;百分比类指标按百分数原值表达(如 89.12000000 表示 89.12%),周转率按次、已获利息倍数按倍,展示时按 index_id 识别单位。⚠️ 上游返回 code=5003 表示该报告期数据尚未入库(财报披露前常见,实测 2026-3 全市场均为 5003),属数据缺口而非参数错误:**不要 force_refresh 重试**,改用更早报告期或等披露后再取。',
|
|
1003
1003
|
path: '/api/a-share/financials/indicators',
|
|
1004
1004
|
inputSchema: objectSchema({
|
|
1005
1005
|
thscode: { type: 'string', description: '单只标的完整代码(如 300033.SZ),不接受逗号' },
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* Known limit: DNS resolves per request but the IP is not pinned to the connection,
|
|
4
4
|
* so a rebinding window remains (same trade-off as dsh-search-first).
|
|
5
5
|
*/
|
|
6
|
-
export declare const LOCAL_FETCH_CLIENT_VERSION = "2.
|
|
6
|
+
export declare const LOCAL_FETCH_CLIENT_VERSION = "2.12.0";
|
|
7
7
|
export declare const LOCAL_FETCH_MAX_URL_LENGTH = 2048;
|
|
8
8
|
export type LocalFetchErrorCode = 'ABORTED' | 'TIMEOUT' | 'INVALID_URL' | 'BLOCKED_URL' | 'DNS' | 'REDIRECT' | 'HTTP' | 'TOO_LARGE' | 'UNSUPPORTED_CONTENT_TYPE';
|
|
9
9
|
export declare class LocalFetchError extends Error {
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* so a rebinding window remains (same trade-off as dsh-search-first).
|
|
5
5
|
*/
|
|
6
6
|
import { htmlToMarkdown, stripInvisibleText } from './html-markdown.js';
|
|
7
|
-
export const LOCAL_FETCH_CLIENT_VERSION = '2.
|
|
7
|
+
export const LOCAL_FETCH_CLIENT_VERSION = '2.12.0';
|
|
8
8
|
export const LOCAL_FETCH_MAX_URL_LENGTH = 2048;
|
|
9
9
|
export class LocalFetchError extends Error {
|
|
10
10
|
code;
|
|
@@ -30,6 +30,10 @@ export declare class SourceError extends Error {
|
|
|
30
30
|
readonly code: string;
|
|
31
31
|
constructor(source: SourceId, code: string, message: string);
|
|
32
32
|
}
|
|
33
|
+
/** Named sources return API payloads, not web pages: the 100k-char HTML cap cuts a 50-item
|
|
34
|
+
* CLS telegraph body (measured 106,106 chars) into invalid JSON. Size for JSON, not HTML. */
|
|
35
|
+
export declare const SOURCE_MAX_BYTES = 1048576;
|
|
36
|
+
export declare const SOURCE_MAX_CHARS = 262144;
|
|
33
37
|
type Requester = ReturnType<typeof createHttpRequester>;
|
|
34
38
|
/** Built per source-tool call; lazy transport, configured timeout. */
|
|
35
39
|
export declare function createSourceTransport(options: LocalFetchOptions): Requester;
|
|
@@ -21,13 +21,23 @@ export class SourceError extends Error {
|
|
|
21
21
|
}
|
|
22
22
|
}
|
|
23
23
|
const REQUEST_TIMEOUT_MS = 20_000;
|
|
24
|
+
/** Named sources return API payloads, not web pages: the 100k-char HTML cap cuts a 50-item
|
|
25
|
+
* CLS telegraph body (measured 106,106 chars) into invalid JSON. Size for JSON, not HTML. */
|
|
26
|
+
export const SOURCE_MAX_BYTES = 1_048_576;
|
|
27
|
+
export const SOURCE_MAX_CHARS = 262_144;
|
|
24
28
|
function createHash(algorithm) {
|
|
25
29
|
const processLike = globalThis.process;
|
|
26
30
|
return processLike?.getBuiltinModule?.('node:crypto')?.createHash?.(algorithm);
|
|
27
31
|
}
|
|
28
32
|
/** Built per source-tool call; lazy transport, configured timeout. */
|
|
29
33
|
export function createSourceTransport(options) {
|
|
30
|
-
return createHttpRequester({
|
|
34
|
+
return createHttpRequester({
|
|
35
|
+
...options,
|
|
36
|
+
timeoutMs: options.timeoutMs || REQUEST_TIMEOUT_MS,
|
|
37
|
+
// Never lower the JSON ceiling to the HTML setting: a truncated body cannot be parsed.
|
|
38
|
+
maxBytes: Math.max(options.maxBytes, SOURCE_MAX_BYTES),
|
|
39
|
+
maxContentChars: Math.max(options.maxContentChars, SOURCE_MAX_CHARS),
|
|
40
|
+
});
|
|
31
41
|
}
|
|
32
42
|
/**
|
|
33
43
|
* Eastmoney shares the other sources' egress gate; throttling stays process-wide.
|
|
@@ -89,7 +99,11 @@ function asRecord(value) {
|
|
|
89
99
|
? value
|
|
90
100
|
: undefined;
|
|
91
101
|
}
|
|
92
|
-
function parseJson(text, source, what) {
|
|
102
|
+
function parseJson(text, source, what, truncated = false) {
|
|
103
|
+
// A truncated body always fails JSON.parse with a syntax error; name the real cause instead.
|
|
104
|
+
if (truncated) {
|
|
105
|
+
throw new SourceError(source, 'INVALID_RESPONSE', `${what} 超过本机响应体上限被截断,无法解析;请降低 limit 或缩小查询范围`);
|
|
106
|
+
}
|
|
93
107
|
try {
|
|
94
108
|
return JSON.parse(text);
|
|
95
109
|
}
|
|
@@ -137,7 +151,7 @@ export async function clsTelegraph(transport, input) {
|
|
|
137
151
|
};
|
|
138
152
|
const query = Object.keys(params).sort().map((key) => `${key}=${params[key]}`).join('&');
|
|
139
153
|
const outcome = await transport.request({ url: `${CLS_URL}?${query}&sign=${clsSign(params)}`, headers: { referer: CLS_REFERER } }, input.signal);
|
|
140
|
-
const body = asRecord(parseJson(outcome.text, 'cls', '财联社响应'));
|
|
154
|
+
const body = asRecord(parseJson(outcome.text, 'cls', '财联社响应', outcome.truncated));
|
|
141
155
|
if (!body)
|
|
142
156
|
throw new SourceError('cls', 'INVALID_RESPONSE', '财联社响应不是对象');
|
|
143
157
|
if (body.errno !== 0) {
|
|
@@ -179,7 +193,7 @@ export async function wscnLives(transport, input) {
|
|
|
179
193
|
if (input.cursor !== undefined)
|
|
180
194
|
params.set('cursor', input.cursor);
|
|
181
195
|
const outcome = await transport.request({ url: `${WSCN_URL}?${params.toString()}` }, input.signal);
|
|
182
|
-
const body = asRecord(parseJson(outcome.text, 'wscn', '华尔街见闻响应'));
|
|
196
|
+
const body = asRecord(parseJson(outcome.text, 'wscn', '华尔街见闻响应', outcome.truncated));
|
|
183
197
|
if (!body)
|
|
184
198
|
throw new SourceError('wscn', 'INVALID_RESPONSE', '华尔街见闻响应不是对象');
|
|
185
199
|
if (body.code !== 20000) {
|
|
@@ -225,7 +239,7 @@ function formBody(fields) {
|
|
|
225
239
|
*/
|
|
226
240
|
export async function cninfoIrm(transport, input) {
|
|
227
241
|
const keyword = await transport.request({ url: IRM_KEYWORD_URL, method: 'POST', body: formBody({ keyWord: input.code }) }, input.signal);
|
|
228
|
-
const keywordBody = asRecord(parseJson(keyword.text, 'cninfo_irm', '互动易代码查询响应'));
|
|
242
|
+
const keywordBody = asRecord(parseJson(keyword.text, 'cninfo_irm', '互动易代码查询响应', keyword.truncated));
|
|
229
243
|
const matches = Array.isArray(keywordBody?.data) ? keywordBody.data : [];
|
|
230
244
|
const first = asRecord(matches[0]);
|
|
231
245
|
const orgId = typeof first?.secid === 'string' ? first.secid : undefined;
|
|
@@ -243,7 +257,7 @@ export async function cninfoIrm(transport, input) {
|
|
|
243
257
|
endDay: '',
|
|
244
258
|
});
|
|
245
259
|
const page = await transport.request({ url: `${IRM_QUESTION_URL}?${params.toString()}`, method: 'POST', body: '' }, input.signal);
|
|
246
|
-
const pageBody = asRecord(parseJson(page.text, 'cninfo_irm', '互动易问答响应'));
|
|
260
|
+
const pageBody = asRecord(parseJson(page.text, 'cninfo_irm', '互动易问答响应', page.truncated));
|
|
247
261
|
const rows = requireRows(pageBody?.rows, 'cninfo_irm', '互动易 rows');
|
|
248
262
|
const total = typeof pageBody?.total === 'number' ? pageBody.total : undefined;
|
|
249
263
|
const items = [];
|
|
@@ -311,7 +325,7 @@ async function sseCompanyPage(transport, page, signal) {
|
|
|
311
325
|
if (cached !== undefined)
|
|
312
326
|
return cached;
|
|
313
327
|
const outcome = await transport.request({ url: `${SSE_BASE}/allcompany.do`, method: 'POST', body: formBody({ code: '0', order: '2', areaId: '0', page: String(page) }), headers: { referer: SSE_REFERER } }, signal);
|
|
314
|
-
const body = asRecord(parseJson(outcome.text, 'sseinfo', '上证e互动公司列表响应'));
|
|
328
|
+
const body = asRecord(parseJson(outcome.text, 'sseinfo', '上证e互动公司列表响应', outcome.truncated));
|
|
315
329
|
const content = typeof body?.content === 'string' ? body.content : undefined;
|
|
316
330
|
if (content === undefined) {
|
|
317
331
|
throw new SourceError('sseinfo', 'INVALID_RESPONSE', `上证e互动公司列表第 ${page} 页没有 content 字符串(页面结构可能已变)`);
|
|
@@ -35,7 +35,7 @@ export interface WindCallResult {
|
|
|
35
35
|
code?: WindErrorCode;
|
|
36
36
|
}
|
|
37
37
|
/** Must match `package.json` version; a test pins the two together. */
|
|
38
|
-
export declare const WIND_CLIENT_VERSION = "2.
|
|
38
|
+
export declare const WIND_CLIENT_VERSION = "2.12.0";
|
|
39
39
|
export interface WindClient {
|
|
40
40
|
callTool(toolName: string, args: Record<string, unknown>, signal?: AbortSignal): Promise<WindCallResult>;
|
|
41
41
|
}
|
|
@@ -19,7 +19,7 @@ export const WIND_SERVER_ENDPOINTS = {
|
|
|
19
19
|
analytics_data: 'https://mcp.wind.com.cn/vserver_analytics_data/mcp/',
|
|
20
20
|
};
|
|
21
21
|
/** Must match `package.json` version; a test pins the two together. */
|
|
22
|
-
export const WIND_CLIENT_VERSION = '2.
|
|
22
|
+
export const WIND_CLIENT_VERSION = '2.12.0';
|
|
23
23
|
function errorText(error) {
|
|
24
24
|
return error instanceof Error ? error.message : String(error);
|
|
25
25
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@v587d/capital-generation",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.12.0",
|
|
4
4
|
"description": "Capital Generation:面向中国散户的 AI 投资助手插件(自动模式 Agent Preset)",
|
|
5
5
|
"icon": "assets/cg-icon.png",
|
|
6
6
|
"author": "v587d",
|
|
@@ -159,14 +159,14 @@
|
|
|
159
159
|
},
|
|
160
160
|
"peerDependencies": {
|
|
161
161
|
"@deepseek-ai/cordis": "^4.0.2",
|
|
162
|
-
"@deepseek-ai/dsh-skill": "0.2.1-rc.
|
|
163
|
-
"@deepseek-ai/dsh-skill-filesystem": "0.2.1-rc.
|
|
162
|
+
"@deepseek-ai/dsh-skill": "0.2.1-rc.3",
|
|
163
|
+
"@deepseek-ai/dsh-skill-filesystem": "0.2.1-rc.3"
|
|
164
164
|
},
|
|
165
165
|
"devDependencies": {
|
|
166
166
|
"@deepseek-ai/cordis": "^4.0.2",
|
|
167
|
-
"@deepseek-ai/dsh-skill": "^0.2.1-rc.
|
|
168
|
-
"@deepseek-ai/dsh-skill-filesystem": "^0.2.1-rc.
|
|
169
|
-
"@deepseek-ai/dsh-system-prompt": "^0.2.1-rc.
|
|
167
|
+
"@deepseek-ai/dsh-skill": "^0.2.1-rc.3",
|
|
168
|
+
"@deepseek-ai/dsh-skill-filesystem": "^0.2.1-rc.3",
|
|
169
|
+
"@deepseek-ai/dsh-system-prompt": "^0.2.1-rc.3",
|
|
170
170
|
"@deepseek-ai/schemastery": "^3.18.4",
|
|
171
171
|
"esbuild": "^0.28.2",
|
|
172
172
|
"js-yaml": "^5.4.1",
|
package/watchlist/package.json
CHANGED