@dshtrading/us 0.1.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/LICENSE +75 -0
- package/assets/preset/us-trader/agent.cordis.yml +125 -0
- package/assets/preset/us-trader/preset.yml +3 -0
- package/cordis.patch.yml +48 -0
- package/lib/index.d.ts +47 -0
- package/lib/index.js +106 -0
- package/package.json +46 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
Copyright (c) 2026 zhu1090093659 (dsh-trading)
|
|
2
|
+
|
|
3
|
+
# PolyForm Noncommercial License 1.0.0
|
|
4
|
+
|
|
5
|
+
<https://polyformproject.org/licenses/noncommercial/1.0.0>
|
|
6
|
+
|
|
7
|
+
## Acceptance
|
|
8
|
+
|
|
9
|
+
In order to get any license under these terms, you must agree to them as both strict obligations and conditions to all your licenses.
|
|
10
|
+
|
|
11
|
+
## Copyright License
|
|
12
|
+
|
|
13
|
+
The licensor grants you a copyright license for the software to do everything you might do with the software that would otherwise infringe the licensor's copyright in it for any permitted purpose. However, you may only distribute the software according to [Distribution License](#distribution-license) and make changes or new works based on the software according to [Changes and New Works License](#changes-and-new-works-license).
|
|
14
|
+
|
|
15
|
+
## Distribution License
|
|
16
|
+
|
|
17
|
+
The licensor grants you an additional copyright license to distribute copies of the software. Your license to distribute covers distributing the software with changes and new works permitted by [Changes and New Works License](#changes-and-new-works-license).
|
|
18
|
+
|
|
19
|
+
## Notices
|
|
20
|
+
|
|
21
|
+
You must ensure that anyone who gets a copy of any part of the software from you also gets a copy of these terms or the URL for them above, as well as copies of any plain-text lines beginning with `Required Notice:` that the licensor provided with the software. For example:
|
|
22
|
+
|
|
23
|
+
> Required Notice: Copyright Yoyodyne, Inc. (http://example.com)
|
|
24
|
+
|
|
25
|
+
## Changes and New Works License
|
|
26
|
+
|
|
27
|
+
The licensor grants you an additional copyright license to make changes and new works based on the software for any permitted purpose.
|
|
28
|
+
|
|
29
|
+
## Patent License
|
|
30
|
+
|
|
31
|
+
The licensor grants you a patent license for the software that covers patent claims the licensor can license, or becomes able to license, that you would infringe by using the software.
|
|
32
|
+
|
|
33
|
+
## Noncommercial Purposes
|
|
34
|
+
|
|
35
|
+
Any noncommercial purpose is a permitted purpose.
|
|
36
|
+
|
|
37
|
+
## Personal Uses
|
|
38
|
+
|
|
39
|
+
Personal use for research, experiment, and testing for the benefit of public knowledge, personal study, private entertainment, hobby projects, amateur pursuits, or religious observance, without any anticipated commercial application, is use for a permitted purpose.
|
|
40
|
+
|
|
41
|
+
## Noncommercial Organizations
|
|
42
|
+
|
|
43
|
+
Use by any charitable organization, educational institution, public research organization, public safety or health organization, environmental protection organization, or government institution is use for a permitted purpose regardless of the source of funding or obligations resulting from the funding.
|
|
44
|
+
|
|
45
|
+
## Fair Use
|
|
46
|
+
|
|
47
|
+
You may have "fair use" rights for the software under the law. These terms do not limit them.
|
|
48
|
+
|
|
49
|
+
## No Other Rights
|
|
50
|
+
|
|
51
|
+
These terms do not allow you to sublicense or transfer any of your licenses to anyone else, or prevent the licensor from granting licenses to anyone else. These terms do not imply any other licenses.
|
|
52
|
+
|
|
53
|
+
## Patent Defense
|
|
54
|
+
|
|
55
|
+
If you make any written claim that the software infringes or contributes to infringement of any patent, your patent license for the software granted under these terms ends immediately. If your company makes such a claim, your patent license ends immediately for work on behalf of your company.
|
|
56
|
+
|
|
57
|
+
## Violations
|
|
58
|
+
|
|
59
|
+
The first time you are notified in writing that you have violated any of these terms, or done anything with the software not covered by your licenses, your licenses can nonetheless continue if you come into full compliance with these terms, and take practical steps to correct past violations, within 32 days of receiving notice. Otherwise, all your licenses end immediately.
|
|
60
|
+
|
|
61
|
+
## No Liability
|
|
62
|
+
|
|
63
|
+
***As far as the law allows, the software comes as is, without any warranty or condition, and the licensor will not be liable to you for any damages arising out of these terms or the use or nature of the software, under any kind of legal claim.***
|
|
64
|
+
|
|
65
|
+
## Definitions
|
|
66
|
+
|
|
67
|
+
The **licensor** is the individual or entity offering these terms, and the **software** is the software the licensor makes available under these terms.
|
|
68
|
+
|
|
69
|
+
**You** refers to the individual or entity agreeing to these terms.
|
|
70
|
+
|
|
71
|
+
**Your company** is any legal entity, sole proprietorship, or other kind of organization that you work for, plus all organizations that have control over, are under the control of, or are under common control with that organization. **Control** means ownership of substantially all the assets of an entity, or the power to direct its management and policies by vote, contract, or otherwise. Control can be direct or indirect.
|
|
72
|
+
|
|
73
|
+
**Your licenses** are all the licenses granted to you for the software under these terms.
|
|
74
|
+
|
|
75
|
+
**Use** means anything you do with the software requiring one of your licenses.
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
# us-trader agent preset —— dsh-trading us 切片(实装形态抄 crypto-trader)。
|
|
2
|
+
#
|
|
3
|
+
# 本文件由 @dshtrading/us 的 dsh-trading-us-installer 插件(bundle host 面常驻行)在
|
|
4
|
+
# apply() 时幂等自安装到市场自有 preset root(默认 ~/.dsh-trading-presets/us-trader;
|
|
5
|
+
# agent-presets 行需把该 root 配进 roots,统一配置归 @dshtrading/base)。插件卸载不
|
|
6
|
+
# 删除已安装目录;升级/重装后再次 apply 即恢复一致,行不可解析时只会得到带原因的
|
|
7
|
+
# broken 行,无进程崩溃(S3 REPORT broken 语义)。
|
|
8
|
+
#
|
|
9
|
+
# 组合形态对照官方 standard preset(@deepseek-ai/dsh-agent-presets 内 standard/):
|
|
10
|
+
# - 本文件是 AGENT-PLANE 组合:roster 每个 preset 常驻挂载一次,会话按 scope 父子加入;
|
|
11
|
+
# preset 不持有审批/沙箱/模型路由(host 面职责,官方注释明确)。
|
|
12
|
+
# - persona 行:@deepseek-ai/dsh-persona 的 config.text,{{model}}/{{cwd}} 由 agent 的
|
|
13
|
+
# 路由与工作区解析(官方同款写法)。
|
|
14
|
+
# - isolate realm:kit 行只向宿主 scope 分层注册表(ctx.skills)注册、不 provide 任何
|
|
15
|
+
# 服务,与官方 standard 的 tool-fs/tool-bash 等同类,无需 realm。
|
|
16
|
+
- id: persona
|
|
17
|
+
name: '@deepseek-ai/dsh-persona'
|
|
18
|
+
config:
|
|
19
|
+
text: >-
|
|
20
|
+
你是一名严谨的美股交易员,由 {{model}} 模型驱动,工作目录为 {{cwd}}。基于 Yahoo
|
|
21
|
+
Finance 公开行情(regular-market 快照;不反映盘前盘后价)做客观、量化的分析;下单类操作一律默认
|
|
22
|
+
dry-run 模拟,liveTrading 关闭时直接拒绝实盘,未经用户明确确认绝不触碰真实资金;
|
|
23
|
+
涉及盘前盘后、熔断、做空、T+1 与 PDT 日内限制时逐项核对 us-risk-checklist 风控
|
|
24
|
+
清单,并明确提示跳空与流动性风险;你给出的任何内容都不构成投资建议。每次会话开始时,
|
|
25
|
+
先检查工作目录下是否已有交易日志目录 .trading-journal/:没有则提醒用户本工作区尚未
|
|
26
|
+
建立交易日志,并调用 trading-notes-setup 技能创建骨架;已有则把本会话的重要操作按
|
|
27
|
+
trading-notes-setup 的规范记入日志——agent 自己的操作入 agent 轨,用户的决定与手工
|
|
28
|
+
操作代记入 human 轨,dry-run 一律标注。
|
|
29
|
+
|
|
30
|
+
# connector 行 provide 服务(tradingUsMarketData),按官方 standard preset 的硬性规则
|
|
31
|
+
# 必须包进 cordis:group + isolate(entry-local realm),且 isolate 键 = 服务名:否则
|
|
32
|
+
# 服务发布进 root realm,与其他 preset 冲突,dsh-agent-presets 挂载时直接拒绝。
|
|
33
|
+
# (实装同 crypto-trader:commit 8f75804 + acceptance「修复 1」)
|
|
34
|
+
- id: dsh-trading-us-connector
|
|
35
|
+
name: cordis:group
|
|
36
|
+
group: true
|
|
37
|
+
isolate:
|
|
38
|
+
tradingUsMarketData: true
|
|
39
|
+
config:
|
|
40
|
+
- id: dsh-trading-us-connector-yahoo
|
|
41
|
+
name: '@dshtrading/connector-yahoo'
|
|
42
|
+
config:
|
|
43
|
+
enabled: true
|
|
44
|
+
dryRun: true
|
|
45
|
+
liveTrading: false
|
|
46
|
+
|
|
47
|
+
- id: dsh-trading-us-connector-alpaca-group
|
|
48
|
+
name: cordis:group
|
|
49
|
+
group: true
|
|
50
|
+
isolate:
|
|
51
|
+
tradingUsMarketData: true
|
|
52
|
+
tradingUsTrade: true
|
|
53
|
+
config:
|
|
54
|
+
- id: dsh-trading-us-connector-alpaca
|
|
55
|
+
name: '@dshtrading/connector-alpaca'
|
|
56
|
+
config:
|
|
57
|
+
enabled: true
|
|
58
|
+
env: demo
|
|
59
|
+
dryRun: true
|
|
60
|
+
liveTrading: false
|
|
61
|
+
|
|
62
|
+
- id: dsh-trading-us-connector-fmp-group
|
|
63
|
+
name: cordis:group
|
|
64
|
+
group: true
|
|
65
|
+
isolate:
|
|
66
|
+
tradingUsMarketData: true
|
|
67
|
+
tradingUsTrade: true
|
|
68
|
+
config:
|
|
69
|
+
- id: dsh-trading-us-connector-fmp
|
|
70
|
+
name: '@dshtrading/connector-fmp'
|
|
71
|
+
config:
|
|
72
|
+
enabled: true
|
|
73
|
+
dryRun: true
|
|
74
|
+
liveTrading: false
|
|
75
|
+
|
|
76
|
+
- id: dsh-trading-us-connector-finnhub-group
|
|
77
|
+
name: cordis:group
|
|
78
|
+
group: true
|
|
79
|
+
isolate:
|
|
80
|
+
tradingUsMarketData: true
|
|
81
|
+
tradingUsTrade: true
|
|
82
|
+
config:
|
|
83
|
+
- id: dsh-trading-us-connector-finnhub
|
|
84
|
+
name: '@dshtrading/connector-finnhub'
|
|
85
|
+
config:
|
|
86
|
+
enabled: true
|
|
87
|
+
dryRun: true
|
|
88
|
+
liveTrading: false
|
|
89
|
+
|
|
90
|
+
- id: dsh-trading-us-connector-polygon-group
|
|
91
|
+
name: cordis:group
|
|
92
|
+
group: true
|
|
93
|
+
isolate:
|
|
94
|
+
tradingUsMarketData: true
|
|
95
|
+
tradingUsTrade: true
|
|
96
|
+
config:
|
|
97
|
+
- id: dsh-trading-us-connector-polygon
|
|
98
|
+
name: '@dshtrading/connector-polygon'
|
|
99
|
+
config:
|
|
100
|
+
enabled: true
|
|
101
|
+
dryRun: true
|
|
102
|
+
liveTrading: false
|
|
103
|
+
|
|
104
|
+
- id: dsh-trading-us-connector-ibkr-group
|
|
105
|
+
name: cordis:group
|
|
106
|
+
group: true
|
|
107
|
+
isolate:
|
|
108
|
+
tradingUsMarketData: true
|
|
109
|
+
tradingUsTrade: true
|
|
110
|
+
config:
|
|
111
|
+
- id: dsh-trading-us-connector-ibkr
|
|
112
|
+
name: '@dshtrading/connector-ibkr'
|
|
113
|
+
config:
|
|
114
|
+
enabled: true
|
|
115
|
+
dryRun: true
|
|
116
|
+
liveTrading: false
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
- id: dsh-trading-us-kit
|
|
122
|
+
name: '@dshtrading/kit-us'
|
|
123
|
+
config:
|
|
124
|
+
dryRun: true
|
|
125
|
+
liveTrading: false
|
package/cordis.patch.yml
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# @dshtrading/us —— us 市场 bundle 的 patch 层(insert-only,README 设计铁律 #1)。
|
|
2
|
+
#
|
|
3
|
+
# 实装形态抄 @dshtrading/crypto(架构修订 2026-08-29 主 agent 决策):connector/kit 的
|
|
4
|
+
# 插件行在 preset 的 agent.cordis.yml(preset 级会话隔离——tools/skills 注册表按 scope
|
|
5
|
+
# 分层,preset scope 内注册的工具不进入 standard 会话)。本 bundle 的职责:
|
|
6
|
+
# 1. dsh-trading-us-installer —— host 面常驻安装器插件(src/index.ts):boot 时幂等
|
|
7
|
+
# 自安装 us-trader preset 到 ~/.dsh-trading-presets。自安装必须在 bundle 层而非
|
|
8
|
+
# kit 插件(kit 行在 preset 平面,preset 不存在则 kit.apply() 永不运行);
|
|
9
|
+
# 2. 依赖安装载体:preset 行按 bare 包名从 profile node_modules 解析(S3 坑 3),本包
|
|
10
|
+
# dependencies 实装 @dshtrading/connector-yahoo(2026-08-29 数据面切换:Stooq 本出口
|
|
11
|
+
# 被反爬拒止,见其 README)与 @dshtrading/kit-us,保证
|
|
12
|
+
# preset 行可解析、不 broken;
|
|
13
|
+
# 3. agent-presets root 行归 base 层所有(~/.dsh-trading-presets),本层不得重复配置。
|
|
14
|
+
#
|
|
15
|
+
# 注意:patch 文件必须保持「顶层 YAML 数组」形状(loadProfile → parsePatchList 对非数组
|
|
16
|
+
# 直接抛错);只允许 insert(按 id 打已存在行 = 整行替换,多市场并存会互相覆盖)。
|
|
17
|
+
- insert:
|
|
18
|
+
- id: dsh-trading-us-installer
|
|
19
|
+
name: '@dshtrading/us'
|
|
20
|
+
|
|
21
|
+
# host 面数据行(2026-08-30 GUI 行情桥配套):只 provide tradingUsMarketData。
|
|
22
|
+
- id: dsh-trading-us-dataplane-yahoo
|
|
23
|
+
name: '@dshtrading/connector-yahoo/dataplane'
|
|
24
|
+
config:
|
|
25
|
+
enabled: true
|
|
26
|
+
- id: dsh-trading-us-dataplane-alpaca
|
|
27
|
+
name: '@dshtrading/connector-alpaca/dataplane'
|
|
28
|
+
config:
|
|
29
|
+
enabled: true
|
|
30
|
+
- id: dsh-trading-us-dataplane-fmp
|
|
31
|
+
name: '@dshtrading/connector-fmp/dataplane'
|
|
32
|
+
config:
|
|
33
|
+
enabled: true
|
|
34
|
+
- id: dsh-trading-us-dataplane-finnhub
|
|
35
|
+
name: '@dshtrading/connector-finnhub/dataplane'
|
|
36
|
+
config:
|
|
37
|
+
enabled: true
|
|
38
|
+
- id: dsh-trading-us-dataplane-polygon
|
|
39
|
+
name: '@dshtrading/connector-polygon/dataplane'
|
|
40
|
+
config:
|
|
41
|
+
enabled: true
|
|
42
|
+
- id: dsh-trading-us-dataplane-ibkr
|
|
43
|
+
name: '@dshtrading/connector-ibkr/dataplane'
|
|
44
|
+
config:
|
|
45
|
+
enabled: true
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
|
package/lib/index.d.ts
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import Schema from "@deepseek-ai/schemastery";
|
|
2
|
+
import { Context } from "@deepseek-ai/cordis";
|
|
3
|
+
//#region src/index.d.ts
|
|
4
|
+
/**
|
|
5
|
+
* Cordis 插件名 = patch 行 id(TEMPLATES §8):`dsh-trading-us-*` 市场命名空间,
|
|
6
|
+
* 全仓唯一(insert-only 铁律 #1)。
|
|
7
|
+
*/
|
|
8
|
+
declare const name = "dsh-trading-us-installer";
|
|
9
|
+
interface Config {
|
|
10
|
+
/** preset 自安装 root 覆盖;默认 ~/.dsh-trading-presets(须与 base 层 agent-presets 行的 roots 一致)。 */
|
|
11
|
+
presetRoot?: string;
|
|
12
|
+
}
|
|
13
|
+
declare const Config: Schema<Config>;
|
|
14
|
+
declare const PRESET_ID = "us-trader";
|
|
15
|
+
/** 默认安装 root:市场自有目录(S3 建议——绝不写进 ~/.dsh/.agent-presets 用户创作区)。 */
|
|
16
|
+
declare const DEFAULT_PRESET_ROOT: string;
|
|
17
|
+
interface SelfInstallResult {
|
|
18
|
+
/** 安装目录(preset 目录名即 roster id)。 */
|
|
19
|
+
dir: string;
|
|
20
|
+
/** 本次实际写入的文件名;空数组 = 内容已是当前代际。 */
|
|
21
|
+
wrote: string[];
|
|
22
|
+
/** 被跳过的文件与原因(用户改过/无管理戳)。 */
|
|
23
|
+
skipped: string[];
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* 幂等自安装 preset(S3 机制 + 2026-08-29 代际管理戳升级):mkdir -p + 逐文件按管理戳
|
|
27
|
+
* 三代裁决——
|
|
28
|
+
*
|
|
29
|
+
* 1. 目标不存在 → 写入(头行 = `# dsh-trading-managed: <内容sha前8>` + shipped 内容);
|
|
30
|
+
* 2. 目标存在且带本包可识别的管理戳(托管文件)→ 正文与 shipped 内容不同则整文件更新
|
|
31
|
+
* (以新代际覆盖——戳即「本文件归安装器托管」的约定);
|
|
32
|
+
* 3. 目标存在但无管理戳(用户改过/前代安装器所装)→ 跳过并记录提示(删除该文件即可
|
|
33
|
+
* 让安装器重新提供)。
|
|
34
|
+
*
|
|
35
|
+
* 迁移注意:代际升级前由旧安装器写入的已装文件没有管理戳,按第 3 条处理(跳过 + log
|
|
36
|
+
* 提示)——宁可不更新,绝不覆盖用户改动。
|
|
37
|
+
*
|
|
38
|
+
* 卸载本 bundle 不删除已安装目录(有意为之):升级/重装后再次 apply 即恢复一致;本包
|
|
39
|
+
* 被移除后 preset 行不可解析只会得到带原因的 broken 行,无进程崩溃(S3 REPORT broken 语义)。
|
|
40
|
+
* preset 引用的插件包必须进本 bundle 的 dependencies(S3 坑 3),见 package.json。
|
|
41
|
+
*/
|
|
42
|
+
declare function installPreset(options?: {
|
|
43
|
+
presetRoot?: string;
|
|
44
|
+
}): Promise<SelfInstallResult>;
|
|
45
|
+
declare function apply(ctx: Context, config: Config): void;
|
|
46
|
+
//#endregion
|
|
47
|
+
export { Config, DEFAULT_PRESET_ROOT, PRESET_ID, SelfInstallResult, apply, installPreset, name };
|
package/lib/index.js
ADDED
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
2
|
+
import { mkdir, readFile, writeFile } from "node:fs/promises";
|
|
3
|
+
import { homedir } from "node:os";
|
|
4
|
+
import { join } from "node:path";
|
|
5
|
+
import { fileURLToPath } from "node:url";
|
|
6
|
+
import Schema from "@deepseek-ai/schemastery";
|
|
7
|
+
//#region src/index.ts
|
|
8
|
+
/**
|
|
9
|
+
* @dshtrading/us — us 市场 bundle。包承载两块实质内容(实装形态抄 @dshtrading/crypto):
|
|
10
|
+
*
|
|
11
|
+
* 1. `cordis.patch.yml`(由 package.json 的 `dsh.bundle.patch` 声明):insert-only
|
|
12
|
+
* 聚合本 bundle 的 host 面常驻行(铁律 #1)。connector/kit 两行在 preset 的
|
|
13
|
+
* agent.cordis.yml(preset 级会话隔离,见 assets/preset/us-trader/)。
|
|
14
|
+
* 2. `dsh-trading-us-installer` 插件(本模块):us-trader preset 幂等自安装(S3 机制)。
|
|
15
|
+
* **自安装职责必须在 bundle(host 面常驻)而非 kit 插件**——kit 行在 preset 平面,
|
|
16
|
+
* preset 不存在时 kit.apply() 永不运行,鸡生蛋(2026-08-29 主 agent 结构性修复);
|
|
17
|
+
* bundle 行常驻,boot 即自安装,与会话无关。
|
|
18
|
+
*
|
|
19
|
+
* @module @dshtrading/us
|
|
20
|
+
*/
|
|
21
|
+
/**
|
|
22
|
+
* Cordis 插件名 = patch 行 id(TEMPLATES §8):`dsh-trading-us-*` 市场命名空间,
|
|
23
|
+
* 全仓唯一(insert-only 铁律 #1)。
|
|
24
|
+
*/
|
|
25
|
+
const name = "dsh-trading-us-installer";
|
|
26
|
+
const Config = Schema.object({ presetRoot: Schema.string() });
|
|
27
|
+
const PRESET_ID = "us-trader";
|
|
28
|
+
/** 默认安装 root:市场自有目录(S3 建议——绝不写进 ~/.dsh/.agent-presets 用户创作区)。 */
|
|
29
|
+
const DEFAULT_PRESET_ROOT = join(homedir(), ".dsh-trading-presets");
|
|
30
|
+
/** 预置资产随本包分发(bundle 是市场组装点,preset 资产归 bundle 所有)。 */
|
|
31
|
+
const PRESET_ASSET_DIR = fileURLToPath(new URL("../assets/preset/", import.meta.url));
|
|
32
|
+
const PRESET_FILES = ["agent.cordis.yml", "preset.yml"];
|
|
33
|
+
/** 管理戳注释行前缀:托管安装文件的头行,值 = shipped 内容(不含戳行)的 SHA-256 前 8 位。 */
|
|
34
|
+
const MANAGED_STAMP_PREFIX = "# dsh-trading-managed: ";
|
|
35
|
+
function contentSha8(content) {
|
|
36
|
+
return createHash("sha256").update(content, "utf8").digest("hex").slice(0, 8);
|
|
37
|
+
}
|
|
38
|
+
/** 提取已安装文件头行的管理戳;null = 无戳(文件视为用户所有)。 */
|
|
39
|
+
function readManagedStamp(current) {
|
|
40
|
+
if (!current.startsWith(MANAGED_STAMP_PREFIX)) return null;
|
|
41
|
+
const stamp = (current.includes("\n") ? current.slice(0, current.indexOf("\n")) : current).slice(23).trim();
|
|
42
|
+
return /^[0-9a-f]{8}$/.test(stamp) ? stamp : null;
|
|
43
|
+
}
|
|
44
|
+
/** 已安装文件去掉管理戳头行后的正文。 */
|
|
45
|
+
function bodyAfterStamp(current) {
|
|
46
|
+
return current.includes("\n") ? current.slice(current.indexOf("\n") + 1) : "";
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* 幂等自安装 preset(S3 机制 + 2026-08-29 代际管理戳升级):mkdir -p + 逐文件按管理戳
|
|
50
|
+
* 三代裁决——
|
|
51
|
+
*
|
|
52
|
+
* 1. 目标不存在 → 写入(头行 = `# dsh-trading-managed: <内容sha前8>` + shipped 内容);
|
|
53
|
+
* 2. 目标存在且带本包可识别的管理戳(托管文件)→ 正文与 shipped 内容不同则整文件更新
|
|
54
|
+
* (以新代际覆盖——戳即「本文件归安装器托管」的约定);
|
|
55
|
+
* 3. 目标存在但无管理戳(用户改过/前代安装器所装)→ 跳过并记录提示(删除该文件即可
|
|
56
|
+
* 让安装器重新提供)。
|
|
57
|
+
*
|
|
58
|
+
* 迁移注意:代际升级前由旧安装器写入的已装文件没有管理戳,按第 3 条处理(跳过 + log
|
|
59
|
+
* 提示)——宁可不更新,绝不覆盖用户改动。
|
|
60
|
+
*
|
|
61
|
+
* 卸载本 bundle 不删除已安装目录(有意为之):升级/重装后再次 apply 即恢复一致;本包
|
|
62
|
+
* 被移除后 preset 行不可解析只会得到带原因的 broken 行,无进程崩溃(S3 REPORT broken 语义)。
|
|
63
|
+
* preset 引用的插件包必须进本 bundle 的 dependencies(S3 坑 3),见 package.json。
|
|
64
|
+
*/
|
|
65
|
+
async function installPreset(options = {}) {
|
|
66
|
+
const dir = join(options.presetRoot ?? DEFAULT_PRESET_ROOT, PRESET_ID);
|
|
67
|
+
await mkdir(dir, { recursive: true });
|
|
68
|
+
const wrote = [];
|
|
69
|
+
const skipped = [];
|
|
70
|
+
for (const file of PRESET_FILES) {
|
|
71
|
+
const content = await readFile(join(PRESET_ASSET_DIR, PRESET_ID, file), "utf8");
|
|
72
|
+
const stamped = `${MANAGED_STAMP_PREFIX}${contentSha8(content)}\n${content}`;
|
|
73
|
+
const target = join(dir, file);
|
|
74
|
+
let current = null;
|
|
75
|
+
try {
|
|
76
|
+
current = await readFile(target, "utf8");
|
|
77
|
+
} catch {}
|
|
78
|
+
if (current === null) {
|
|
79
|
+
await writeFile(target, stamped);
|
|
80
|
+
wrote.push(file);
|
|
81
|
+
continue;
|
|
82
|
+
}
|
|
83
|
+
if (readManagedStamp(current) === null) {
|
|
84
|
+
skipped.push(`${file} (no management stamp — user-modified file left untouched; delete it to let the installer re-provision it)`);
|
|
85
|
+
continue;
|
|
86
|
+
}
|
|
87
|
+
if (bodyAfterStamp(current) !== content) {
|
|
88
|
+
await writeFile(target, stamped);
|
|
89
|
+
wrote.push(file);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
return {
|
|
93
|
+
dir,
|
|
94
|
+
wrote,
|
|
95
|
+
skipped
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
function logger(ctx) {
|
|
99
|
+
const service = ctx.logger;
|
|
100
|
+
return typeof service === "function" ? service(name) : console;
|
|
101
|
+
}
|
|
102
|
+
function apply(ctx, config) {
|
|
103
|
+
installPreset({ presetRoot: config?.presetRoot }).then((result) => logger(ctx).info("[dsh-trading-us-installer] self-install %s preset at %s wrote=[%s] skipped=[%s]", PRESET_ID, result.dir, result.wrote.join(",") || "nothing — already current", result.skipped.join("; ") || "none"), (error) => logger(ctx).warn("[dsh-trading-us-installer] us-trader preset self-install failed: %s", error));
|
|
104
|
+
}
|
|
105
|
+
//#endregion
|
|
106
|
+
export { Config, DEFAULT_PRESET_ROOT, PRESET_ID, apply, installPreset, name };
|
package/package.json
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@dshtrading/us",
|
|
3
|
+
"description": "US market bundle for dsh-trading: host-plane us-trader preset installer + insert-only aggregation of the yahoo connector and us kit rows (design rule #1)",
|
|
4
|
+
"version": "0.1.0",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "lib/index.js",
|
|
7
|
+
"types": "./lib/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./lib/index.d.ts",
|
|
11
|
+
"default": "./lib/index.js"
|
|
12
|
+
},
|
|
13
|
+
"./cordis.patch.yml": "./cordis.patch.yml",
|
|
14
|
+
"./package.json": "./package.json"
|
|
15
|
+
},
|
|
16
|
+
"files": [
|
|
17
|
+
"lib",
|
|
18
|
+
"assets",
|
|
19
|
+
"cordis.patch.yml"
|
|
20
|
+
],
|
|
21
|
+
"license": "PolyForm-Noncommercial-1.0.0",
|
|
22
|
+
"dsh": {
|
|
23
|
+
"bundle": {
|
|
24
|
+
"patch": "./cordis.patch.yml"
|
|
25
|
+
}
|
|
26
|
+
},
|
|
27
|
+
"dependencies": {
|
|
28
|
+
"@dshtrading/connector-alpaca": "0.1.0",
|
|
29
|
+
"@dshtrading/connector-finnhub": "0.1.0",
|
|
30
|
+
"@dshtrading/connector-fmp": "0.1.0",
|
|
31
|
+
"@dshtrading/connector-ibkr": "0.1.0",
|
|
32
|
+
"@dshtrading/connector-polygon": "0.1.0",
|
|
33
|
+
"@dshtrading/connector-yahoo": "0.1.0",
|
|
34
|
+
"@dshtrading/kit-us": "0.1.0"
|
|
35
|
+
},
|
|
36
|
+
"peerDependencies": {
|
|
37
|
+
"@deepseek-ai/cordis": ">=4.0.0",
|
|
38
|
+
"@deepseek-ai/schemastery": ">=3.18.0"
|
|
39
|
+
},
|
|
40
|
+
"devDependencies": {
|
|
41
|
+
"tsdown": "^0.22.0"
|
|
42
|
+
},
|
|
43
|
+
"scripts": {
|
|
44
|
+
"build": "tsdown"
|
|
45
|
+
}
|
|
46
|
+
}
|