@dshtrading/base 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 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,121 @@
1
+ # @dshtrading/base —— 市场无关共享行的唯一拥有者(README 设计铁律 #1)。
2
+ #
3
+ # 本文件只允许 insert(patch 非 insert 语义是按 id 整行替换,多市场并存会互相
4
+ # 覆盖);共享行一律只在本层定义一次,市场 bundle 不得 replace。
5
+ #
6
+ # 当前两层语义(2026-08-29 web 宿主实测修正,vendor/loader + vendor/include 源码为准):
7
+ # 1. insert 行:dsh-trading-base-gate —— 本包的统一审批监听器插件(见 src/index.ts):
8
+ # 对 <market>_(place|cancel)_order 且 dryRun!==true 的工具调用返回 ask 交宿主
9
+ # 审批面;headless 无应答者时宿主降级为 deny(fail-closed 特性)。
10
+ # 该 id 全仓唯一,insert 在任何宿主都安全。
11
+ # 2. 同 id 覆盖行:agent-presets —— 统一 preset root 配置(S3 机制)。
12
+ # **为什么不能 insert**:web 宿主的 web-app 层已有 agent-presets 行,insert 无 id
13
+ # 条目一律 append 新行,loader.update 对重复 id 直接抛
14
+ # 「duplicate loader entry id」——web profile 会启动崩溃(trading-web 实测)。
15
+ # 覆盖条目语义:行存在 → 按 key 覆盖(config 全键 restate,不合并——所以 default/
16
+ # includeShippedRoot/includeUserRoot 必须全带);行不存在(headless)→ 仅 Loader
17
+ # 警告并跳过,不致命。headless 部署需要该 root 时,由部署方在 profile 级
18
+ # cordis.patch.yml 自行 insert 同一行(见 README 开发期安装节;trading-dev 即如此)。
19
+ # roots 用市场自有目录 ~/.dsh-trading-presets(bundle 安装器自安装目的地,
20
+ # 不混入 ~/.dsh/.agent-presets 用户创作区);default 保持官方 standard,
21
+ # 多市场会话并存时不劫持默认 preset。包名解析依赖本包 dependencies 里的
22
+ # @deepseek-ai/dsh-agent-presets(进 profile 安装闭包,S3 坑 3)。
23
+ #
24
+ # 脚手架阶段遗留的 insert-only 约定不变:后续共享行(组合管理/风控工具行、
25
+ # credentials 引用约定行 [S4])继续追加到本文件的 insert 列表。
26
+ - insert:
27
+ - id: dsh-trading-base-gate
28
+ name: '@dshtrading/base'
29
+
30
+ # 市场/数据源路由(2026-08-29 设置驱动单预设重构,docs/exchange-routing.md):
31
+ # host 面常驻,注册 dshtrading settings namespace + provide tradingMarketRouter;
32
+ # 连接器 apply 时 consult activeProvider(market)——用户设置选谁谁激活。
33
+ # 市场无关共享行(四市场共用),只由 base 拥有(铁律 #1/#4)。
34
+ - id: dsh-trading-market-router
35
+ name: '@dshtrading/router'
36
+
37
+ # 交易设置一级菜单(2026-08-29 浏览器半包,docs/exchange-routing.md §6):
38
+ # dsh.client 双面包(node 半空 apply + 浏览器半注册 settings.section id=trading)。
39
+ # 浏览器侧由 web 宿主的 dsh-client-modules 扫描 loader entries 进 __DSH_BOOT__;
40
+ # headless 宿主无 modules 行,此包被解析为普通 host 行(空 apply 无害)。
41
+ - id: dsh-trading-client-ui-settings
42
+ name: '@dshtrading/client-ui-settings'
43
+
44
+ # 失效信号事件总线(issue #30 / P1):provide tradingEvents 服务(emit/subscribe/
45
+ # per-store revision,零 HTTP 零业务数据);能力包工具与桥写入状态后 emit,
46
+ # /dshtrading/api/events(SSE)以本服务为数据源出浏览器。
47
+ - id: dsh-trading-eventbus
48
+ name: '@dshtrading/eventbus'
49
+
50
+ # 策略 Agent 产出管线(issue #31 / P2,dataplane 行同款 subpath 插件先例):
51
+ # strategy_author + strategy_backtest host 平面工具(全会话可见,owner 裁决 D4),
52
+ # 自定义策略 file store 落 ~/.dsh/strategies/custom.json;写后 emit tradingEvents('strategies')。
53
+ - id: dsh-trading-strategies
54
+ name: '@dshtrading/strategies/plugin'
55
+
56
+ # 自选股升位(issue #32 / P3,subpath 插件先例):watchlist_list/add/remove/select
57
+ # host 平面工具(跨市场、全会话可见),file store 落 ~/.dsh/watchlists.json +
58
+ # ~/.dsh/selection.json;写后 emit tradingEvents('watchlists'|'selection')。
59
+ - id: dsh-trading-watchlist
60
+ name: '@dshtrading/watchlist/plugin'
61
+
62
+ # 指标能力收口(issue #33 / P4):provide tradingCustomIndicators 单实例 store 服务
63
+ # (桥与工具共享缓存),indicator_author/indicator_delete host 平面注册;
64
+ # 写后 emit tradingEvents('indicators')。
65
+ - id: dsh-trading-indicators
66
+ name: '@dshtrading/indicators/plugin'
67
+
68
+ # dsh-tool-cordis 动态包能力开放(issue #35 / P6,owner 裁决 D5,硬前置 P0 服务缝
69
+ # 闸门已落地):cordis_inspect_* / cordis_define / cordis_run / cordis_stop /
70
+ # cordis_undefine 7 工具进 trading profile。信任级 = bash(官方声明);动态包
71
+ # session-scoped、重启即散、浏览器半需人工审批;服务缝闸门兜底实盘边界。
72
+ - id: dsh-trading-dynamic-capabilities
73
+ name: '@deepseek-ai/dsh-tool-cordis'
74
+
75
+ # 知识能力收口(issue #33 / P4):provide tradingKnowledgeCards 单实例 store 服务,
76
+ # knowledge_ingest/search/graph host 平面注册;写后 emit tradingEvents('knowledge')。
77
+ - id: dsh-trading-knowledge
78
+ name: '@dshtrading/knowledge/plugin'
79
+
80
+ # 中心化 i18n 语言包(feat/i18n-zh-cn):注册「简体中文」(zh-CN) 进宿主
81
+ # Settings → General 语言目录,并为全部 dshtrading.* 命名空间注册 zh-CN
82
+ # 词典(构建期 import 各 UI 包 locales.ts 纯数据模块,zh-CN ≡ zh 零漂移)。
83
+ # 纯浏览器半语言包(dsh-web dsh-i18n 范式),headless 宿主空 apply 无害。
84
+ - id: dsh-trading-dsh-i18n
85
+ name: '@dshtrading/dsh-i18n'
86
+
87
+ # 交易 GUI 壳(第二阶段富途式三栏,2026-08-30):左栏市场/自选遮蔽
88
+ # sidebar.workspaces、中栏 conversation.view 加行情 tab、右栏 shell.overlay
89
+ # 会话面板;node 半注册 /dshtrading/api 行情桥(web 宿主,headless 挂起无害)。
90
+ - id: dsh-trading-client-ui-trading
91
+ name: '@dshtrading/client-ui-trading'
92
+
93
+ # 预置指标提供插件(2026-08-30 指标插件化):client 半 provide
94
+ # tradingIndicators 服务(IndicatorRegistry,预置 MA/EMA/BOLL/MACD/RSI/KDJ);
95
+ # 社区/自定义指标插件 inject 该服务 register definition 即可上榜。
96
+ # headless 宿主解析为空 apply host 行,无害。
97
+ - id: dsh-trading-client-ui-indicators
98
+ name: '@dshtrading/client-ui-indicators'
99
+
100
+ # 策略中栏视图(issue #34 / P5 拆包):client 半 inject tradingStageViews
101
+ # 注册「策略」tab + tool.call.toolview 富卡片(strategy_backtest/author);
102
+ # 引擎经 @dshtrading/strategies 纯库 import,桥走 shell 的 tradingBridge
103
+ # 服务。headless 宿主解析为空 apply host 行,无害。
104
+ - id: dsh-trading-client-ui-strategies
105
+ name: '@dshtrading/client-ui-strategies'
106
+
107
+ # 知识库中栏视图(issue #34 / P5 拆包):client 半 inject tradingStageViews
108
+ # 注册「知识库」tab;force-graph 力导图谱随本包打包(shell 已卸下该依赖)。
109
+ # headless 宿主解析为空 apply host 行,无害。
110
+ - id: dsh-trading-client-ui-knowledge
111
+ name: '@dshtrading/client-ui-knowledge'
112
+
113
+ - id: agent-presets
114
+ name: '@deepseek-ai/dsh-agent-presets'
115
+ config:
116
+ default: standard
117
+ roots:
118
+ - path: ~/.dsh-trading-presets
119
+ trust: user
120
+ includeShippedRoot: true
121
+ includeUserRoot: true
package/lib/index.d.ts ADDED
@@ -0,0 +1,44 @@
1
+ import Schema from "@deepseek-ai/schemastery";
2
+ import { Context } from "@deepseek-ai/cordis";
3
+ import { PreToolDecision, ToolExecution } from "@deepseek-ai/dsh-tools";
4
+ //#region src/index.d.ts
5
+ /**
6
+ * Cordis 插件名 = patch 行 id(TEMPLATES §8)。base 是共享行唯一拥有者,
7
+ * 行 id 用 `dsh-trading-base-gate` 市场无关命名空间,绝不与市场行冲突。
8
+ */
9
+ declare const name = "dsh-trading-base-gate";
10
+ interface Config {
11
+ /** 统一审批闸门开关;false 时完全不挂监听器(仅测试/显式降级用)。 */
12
+ enabled: boolean;
13
+ }
14
+ declare const Config: Schema<Config>;
15
+ /**
16
+ * 下单/撤单工具名模式(跨市场统一词汇:`<market>_<action>_order`,如
17
+ * `crypto_place_order`)。工具名是模型面向词汇,用短市场前缀(crypto/us/cn/hk);
18
+ * `dsh-trading-` 前缀只属于插件名/patch 行 id,不进工具名(与 crypto_get_ticker
19
+ * 等只读工具一致)。锚定首尾 + 市场段枚举,避免误拦同名他方工具。
20
+ */
21
+ declare const ORDER_GATE_PATTERN: RegExp;
22
+ declare function isOrderGateTool(toolName: string): boolean;
23
+ /**
24
+ * 纯判定:这次工具调用是否需要用户审批。
25
+ *
26
+ * - 非下单/撤单工具 → undefined(不拦截);
27
+ * - 下单/撤单且 `dryRun === true` → undefined(模拟单无需审批);
28
+ * - 其余(dryRun 缺省/false/形状异常)→ `{kind:'ask'}`。
29
+ * 缺省也 ask 是故意的保守面:工具 schema 的 dryRun 默认 true 在工具层生效,
30
+ * 闸门层只认显式 `true`;宁可在交互形态多问一次,不在实盘形态漏拦一次。
31
+ *
32
+ * 返回 undefined 时调用方必须 `next()` 继续 waterfall —— 本监听器永不直接
33
+ * 返回 allow,避免越过宿主其他策略层。
34
+ */
35
+ declare function decideOrderGate(toolName: string, args: unknown): PreToolDecision | undefined;
36
+ /**
37
+ * waterfall 监听器工厂(独立导出便于单测直接驱动 next() 契约,
38
+ * 官方参照:packages/hooks/hooks-codex 的 pre-execute 桥)。
39
+ */
40
+ declare function createGateListener(): (this: unknown, exec: ToolExecution, next: () => Promise<PreToolDecision>) => Promise<PreToolDecision>;
41
+ /** 插件入口:按配置挂统一审批监听器(不声明 inject —— 事件面无需 tools 服务)。 */
42
+ declare function apply(ctx: Context, config: Config): void;
43
+ //#endregion
44
+ export { Config, ORDER_GATE_PATTERN, apply, createGateListener, decideOrderGate, isOrderGateTool, name };
package/lib/index.js ADDED
@@ -0,0 +1,54 @@
1
+ import Schema from "@deepseek-ai/schemastery";
2
+ //#region src/index.ts
3
+ /**
4
+ * Cordis 插件名 = patch 行 id(TEMPLATES §8)。base 是共享行唯一拥有者,
5
+ * 行 id 用 `dsh-trading-base-gate` 市场无关命名空间,绝不与市场行冲突。
6
+ */
7
+ const name = "dsh-trading-base-gate";
8
+ const Config = Schema.object({ enabled: Schema.boolean().default(true) });
9
+ /**
10
+ * 下单/撤单工具名模式(跨市场统一词汇:`<market>_<action>_order`,如
11
+ * `crypto_place_order`)。工具名是模型面向词汇,用短市场前缀(crypto/us/cn/hk);
12
+ * `dsh-trading-` 前缀只属于插件名/patch 行 id,不进工具名(与 crypto_get_ticker
13
+ * 等只读工具一致)。锚定首尾 + 市场段枚举,避免误拦同名他方工具。
14
+ */
15
+ const ORDER_GATE_PATTERN = /^(?:crypto|us|cn|hk)_(?:place|cancel)_order$/;
16
+ function isOrderGateTool(toolName) {
17
+ return ORDER_GATE_PATTERN.test(toolName);
18
+ }
19
+ /**
20
+ * 纯判定:这次工具调用是否需要用户审批。
21
+ *
22
+ * - 非下单/撤单工具 → undefined(不拦截);
23
+ * - 下单/撤单且 `dryRun === true` → undefined(模拟单无需审批);
24
+ * - 其余(dryRun 缺省/false/形状异常)→ `{kind:'ask'}`。
25
+ * 缺省也 ask 是故意的保守面:工具 schema 的 dryRun 默认 true 在工具层生效,
26
+ * 闸门层只认显式 `true`;宁可在交互形态多问一次,不在实盘形态漏拦一次。
27
+ *
28
+ * 返回 undefined 时调用方必须 `next()` 继续 waterfall —— 本监听器永不直接
29
+ * 返回 allow,避免越过宿主其他策略层。
30
+ */
31
+ function decideOrderGate(toolName, args) {
32
+ if (!isOrderGateTool(toolName)) return void 0;
33
+ if (args?.dryRun === true) return void 0;
34
+ return {
35
+ kind: "ask",
36
+ reason: `order tool "${toolName}" was called without explicit dryRun=true (live trading intent); the dsh-trading safety gate requires user approval (README iron rule #3). Note: headless deployments with no approver will deny this call — fail closed by design.`
37
+ };
38
+ }
39
+ /**
40
+ * waterfall 监听器工厂(独立导出便于单测直接驱动 next() 契约,
41
+ * 官方参照:packages/hooks/hooks-codex 的 pre-execute 桥)。
42
+ */
43
+ function createGateListener() {
44
+ return async (exec, next) => {
45
+ return decideOrderGate(exec.name, exec.arguments) ?? next();
46
+ };
47
+ }
48
+ /** 插件入口:按配置挂统一审批监听器(不声明 inject —— 事件面无需 tools 服务)。 */
49
+ function apply(ctx, config) {
50
+ if (!config.enabled) return;
51
+ ctx.on("tools/pre-execute", createGateListener());
52
+ }
53
+ //#endregion
54
+ export { Config, ORDER_GATE_PATTERN, apply, createGateListener, decideOrderGate, isOrderGateTool, name };
package/package.json ADDED
@@ -0,0 +1,55 @@
1
+ {
2
+ "name": "@dshtrading/base",
3
+ "description": "Market-agnostic core bundle for dsh-trading: sole owner of shared cordis rows — unified order/cancel approval gate plugin and the agent-presets row (unified preset root ~/.dsh-trading-presets)",
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
+ "cordis.patch.yml"
19
+ ],
20
+ "license": "PolyForm-Noncommercial-1.0.0",
21
+ "dsh": {
22
+ "bundle": {
23
+ "patch": "./cordis.patch.yml"
24
+ }
25
+ },
26
+ "dependencies": {
27
+ "@deepseek-ai/dsh-agent-presets": ">=0.1.2-alpha.1",
28
+ "@deepseek-ai/dsh-tool-cordis": ">=0.1.2-alpha.3",
29
+ "@dshtrading/client-ui-indicators": "^0.1.0",
30
+ "@dshtrading/api": "^0.1.0",
31
+ "@dshtrading/client-ui-knowledge": "^0.1.0",
32
+ "@dshtrading/client-ui-settings": "^0.1.0",
33
+ "@dshtrading/client-ui-strategies": "^0.1.0",
34
+ "@dshtrading/client-ui-trading": "^0.1.0",
35
+ "@dshtrading/eventbus": "^0.1.0",
36
+ "@dshtrading/strategies": "^0.1.0",
37
+ "@dshtrading/indicators": "^0.1.0",
38
+ "@dshtrading/knowledge": "^0.1.0",
39
+ "@dshtrading/router": "^0.1.0",
40
+ "@dshtrading/watchlist": "^0.1.0"
41
+ },
42
+ "peerDependencies": {
43
+ "@deepseek-ai/cordis": ">=4.0.0",
44
+ "@deepseek-ai/dsh-tools": ">=0.1.2-alpha.1",
45
+ "@deepseek-ai/schemastery": ">=3.18.0"
46
+ },
47
+ "devDependencies": {
48
+ "tsdown": "^0.22.0",
49
+ "vitest": "^3.0.0"
50
+ },
51
+ "scripts": {
52
+ "build": "tsdown",
53
+ "test": "vitest run"
54
+ }
55
+ }