@dsh-ft/dsh-fft-settings 0.0.0-stage → 0.5.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 +21 -0
- package/README.md +392 -2
- package/cordis.patch.yml +18 -0
- package/docs/compatibility-dsh-0.1.6-alpha.1.md +58 -0
- package/docs/extension-service-design.md +351 -0
- package/docs/extension-service-sequences.html +545 -0
- package/docs/ftshare-settings-er.html +139 -0
- package/docs/ftshare-settings-er.svg +113 -0
- package/docs/ftshare-settings-results-er.html +148 -0
- package/docs/ftshare-settings-results-er.svg +122 -0
- package/docs/kline-integration.md +258 -0
- package/lib/agent.d.ts +24 -0
- package/lib/agent.js +26 -0
- package/lib/brand.d.ts +53 -0
- package/lib/brand.js +50 -0
- package/lib/client.d.ts +8 -0
- package/lib/client.js +822 -0
- package/lib/client.js.map +1 -0
- package/lib/contract.d.ts +14 -0
- package/lib/contract.js +14 -0
- package/lib/core/client-transport.d.ts +15 -0
- package/lib/core/client-transport.js +31 -0
- package/lib/core/contract.d.ts +62 -0
- package/lib/core/contract.js +28 -0
- package/lib/core/module-registry.d.ts +54 -0
- package/lib/core/module-registry.js +68 -0
- package/lib/core/rpc-core.d.ts +69 -0
- package/lib/core/rpc-core.js +88 -0
- package/lib/core/shell.d.ts +59 -0
- package/lib/core/shell.js +28 -0
- package/lib/core/styles.d.ts +31 -0
- package/lib/core/styles.js +43 -0
- package/lib/core/transport.d.ts +19 -0
- package/lib/core/transport.js +80 -0
- package/lib/default-preset.d.ts +52 -0
- package/lib/default-preset.js +121 -0
- package/lib/features/api-key/card.d.ts +24 -0
- package/lib/features/api-key/card.js +39 -0
- package/lib/features/api-key/client-api.d.ts +4 -0
- package/lib/features/api-key/client-api.js +11 -0
- package/lib/features/api-key/contract.d.ts +69 -0
- package/lib/features/api-key/contract.js +24 -0
- package/lib/features/api-key/host.d.ts +17 -0
- package/lib/features/api-key/host.js +32 -0
- package/lib/features/api-key/index.d.ts +13 -0
- package/lib/features/api-key/index.js +12 -0
- package/lib/features/api-key/logging.d.ts +15 -0
- package/lib/features/api-key/logging.js +1 -0
- package/lib/features/api-key/model.d.ts +24 -0
- package/lib/features/api-key/model.js +105 -0
- package/lib/features/api-key/probe.d.ts +11 -0
- package/lib/features/api-key/probe.js +142 -0
- package/lib/features/api-key/rpc.d.ts +4 -0
- package/lib/features/api-key/rpc.js +17 -0
- package/lib/features/api-key/service.d.ts +21 -0
- package/lib/features/api-key/service.js +181 -0
- package/lib/features/api-key/styles.d.ts +9 -0
- package/lib/features/api-key/styles.js +24 -0
- package/lib/features/logs/archive.d.ts +87 -0
- package/lib/features/logs/archive.js +156 -0
- package/lib/features/logs/card.d.ts +22 -0
- package/lib/features/logs/card.js +107 -0
- package/lib/features/logs/client-api.d.ts +4 -0
- package/lib/features/logs/client-api.js +11 -0
- package/lib/features/logs/collector.d.ts +91 -0
- package/lib/features/logs/collector.js +258 -0
- package/lib/features/logs/config.d.ts +70 -0
- package/lib/features/logs/config.js +97 -0
- package/lib/features/logs/contract.d.ts +130 -0
- package/lib/features/logs/contract.js +67 -0
- package/lib/features/logs/export.d.ts +92 -0
- package/lib/features/logs/export.js +212 -0
- package/lib/features/logs/format.d.ts +42 -0
- package/lib/features/logs/format.js +172 -0
- package/lib/features/logs/home.d.ts +18 -0
- package/lib/features/logs/home.js +39 -0
- package/lib/features/logs/host.d.ts +19 -0
- package/lib/features/logs/host.js +139 -0
- package/lib/features/logs/index.d.ts +12 -0
- package/lib/features/logs/index.js +12 -0
- package/lib/features/logs/rpc.d.ts +6 -0
- package/lib/features/logs/rpc.js +27 -0
- package/lib/features/logs/styles.d.ts +9 -0
- package/lib/features/logs/styles.js +13 -0
- package/lib/guidance.d.ts +41 -0
- package/lib/guidance.js +88 -0
- package/lib/index.d.ts +67 -0
- package/lib/index.js +50 -0
- package/lib/rpc.d.ts +10 -0
- package/lib/rpc.js +10 -0
- package/package.json +86 -4
- package/src/agent.ts +31 -0
- package/src/brand.ts +79 -0
- package/src/client.tsx +21 -0
- package/src/contract.ts +14 -0
- package/src/core/client-transport.ts +37 -0
- package/src/core/contract.ts +57 -0
- package/src/core/module-registry.ts +102 -0
- package/src/core/rpc-core.ts +107 -0
- package/src/core/shell.tsx +81 -0
- package/src/core/styles.ts +43 -0
- package/src/core/transport.ts +82 -0
- package/src/default-preset.ts +151 -0
- package/src/features/api-key/card.tsx +77 -0
- package/src/features/api-key/client-api.ts +12 -0
- package/src/features/api-key/contract.ts +63 -0
- package/src/features/api-key/host.ts +36 -0
- package/src/features/api-key/index.ts +13 -0
- package/src/features/api-key/logging.ts +15 -0
- package/src/features/api-key/model.ts +63 -0
- package/src/features/api-key/probe.ts +116 -0
- package/src/features/api-key/rpc.ts +18 -0
- package/src/features/api-key/service.ts +157 -0
- package/src/features/api-key/styles.ts +24 -0
- package/src/features/logs/archive.ts +230 -0
- package/src/features/logs/card.tsx +169 -0
- package/src/features/logs/client-api.ts +20 -0
- package/src/features/logs/collector.ts +313 -0
- package/src/features/logs/config.ts +115 -0
- package/src/features/logs/contract.ts +149 -0
- package/src/features/logs/export.ts +274 -0
- package/src/features/logs/format.ts +188 -0
- package/src/features/logs/home.ts +43 -0
- package/src/features/logs/host.ts +153 -0
- package/src/features/logs/index.ts +12 -0
- package/src/features/logs/rpc.ts +29 -0
- package/src/features/logs/styles.ts +13 -0
- package/src/guidance.ts +114 -0
- package/src/index.ts +59 -0
- package/src/rpc.ts +10 -0
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `logs` 命名空间的 RPC 方法:只暴露显式登记的三个只读方法,沿用严格 payload 校验。
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { LOGS_DEFAULT_PREVIEW_LINES, LOGS_MAX_PREVIEW_LINES, type LogsSettings } from './contract.js'
|
|
6
|
+
import type { SettingsRpcMethods } from '../../core/rpc-core.js'
|
|
7
|
+
|
|
8
|
+
const record = (value: unknown): value is Record<string, unknown> =>
|
|
9
|
+
typeof value === 'object' && value !== null && !Array.isArray(value)
|
|
10
|
+
const empty = (value: unknown): boolean => record(value) && Object.keys(value).length === 0
|
|
11
|
+
/** 只允许 `{ lines?: number }`,且值必须落在预览上限内。 */
|
|
12
|
+
const previewPayload = (value: unknown): boolean => {
|
|
13
|
+
if (!record(value)) return false
|
|
14
|
+
const keys = Object.keys(value)
|
|
15
|
+
if (keys.some(key => key !== 'lines')) return false
|
|
16
|
+
if (value.lines === undefined) return true
|
|
17
|
+
return typeof value.lines === 'number' && Number.isInteger(value.lines) && value.lines >= 1 && value.lines <= LOGS_MAX_PREVIEW_LINES
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export function createLogsRpcMethods(service: LogsSettings): SettingsRpcMethods {
|
|
21
|
+
return {
|
|
22
|
+
stats: { validate: empty, invoke: () => service.stats() },
|
|
23
|
+
preview: {
|
|
24
|
+
validate: previewPayload,
|
|
25
|
+
invoke: payload => service.preview((payload as { lines?: number }).lines ?? LOGS_DEFAULT_PREVIEW_LINES),
|
|
26
|
+
},
|
|
27
|
+
export: { validate: empty, invoke: () => service.export() },
|
|
28
|
+
}
|
|
29
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The `logs` card's own styles, rendered by the card component's `<style>`.
|
|
3
|
+
*
|
|
4
|
+
* These two rules used to live in the core section stylesheet; a card owns
|
|
5
|
+
* everything past the section shell, so they moved here with the card. Every
|
|
6
|
+
* selector stays scoped under `.ftshare-settings`, so a card never styles
|
|
7
|
+
* another card's markup.
|
|
8
|
+
*/
|
|
9
|
+
export const LOGS_CARD_CSS = `
|
|
10
|
+
.ftshare-settings select { height:32px; border:0.5px solid var(--ftshare-control); border-radius:var(--dsw-radius-md); padding:0 10px; background:var(--ftshare-input); color:inherit; font:inherit; }
|
|
11
|
+
.ftshare-settings .ftshare-download { display:inline-flex; align-items:center; min-height:32px; padding:0 14px; border:0.5px solid var(--ftshare-control); border-radius:var(--dsw-radius-md); color:inherit; text-decoration:none; cursor:pointer; }
|
|
12
|
+
.ftshare-settings .ftshare-log-preview { max-height:320px; overflow:auto; margin:0 0 12px; padding:12px; background:var(--ftshare-input); border:0.5px solid var(--ftshare-border); border-radius:var(--dsw-radius-lg); font-family:ui-monospace,SFMono-Regular,Menlo,monospace; font-size:12px; line-height:1.5; white-space:pre-wrap; overflow-wrap:anywhere; }
|
|
13
|
+
`
|
package/src/guidance.ts
ADDED
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The FT prompt contract: two ordered system sections and one runtime fact.
|
|
3
|
+
*
|
|
4
|
+
* The identity is not here: the preset that mounts this entry states it in its own
|
|
5
|
+
* `persona` row (order 0), and repeating it as a section would render it twice.
|
|
6
|
+
*
|
|
7
|
+
* Registration is a single {@link installGuidance} call so the text and the
|
|
8
|
+
* mount point stay independent — moving these registrations into an agent preset
|
|
9
|
+
* later changes only the row that calls this module.
|
|
10
|
+
*
|
|
11
|
+
* A section is paid for on every request and any edit invalidates the prompt's
|
|
12
|
+
* KV-cache prefix, so the contract stays short; methodology that needs examples,
|
|
13
|
+
* checklists, or branch flow belongs in a skill instead.
|
|
14
|
+
* @module @dsh-ft/dsh-fft-settings/guidance
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
import type { Context } from '@deepseek-ai/cordis'
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* The prompt-registry calls this module makes, declared structurally: the host
|
|
21
|
+
* owns `systemPrompt`, and `inject` guarantees the service exists before `apply`
|
|
22
|
+
* runs, so the package keeps no harness dependency just to name the type.
|
|
23
|
+
*/
|
|
24
|
+
interface PromptRegistry {
|
|
25
|
+
section(section: { readonly name: string; readonly order: number; readonly text: string }): () => void
|
|
26
|
+
context(entry: { readonly name: string; readonly order: number; readonly text: () => string }): () => void
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/** Section name of the capability list. */
|
|
30
|
+
export const FT_SERVICES_SECTION = 'ft:services'
|
|
31
|
+
|
|
32
|
+
/** Section name of the financial-data discipline. */
|
|
33
|
+
export const FT_DATA_POLICY_SECTION = 'ft:data-policy'
|
|
34
|
+
|
|
35
|
+
/** Runtime-context name of the FTShare credential fact. */
|
|
36
|
+
export const FT_CREDENTIALS_CONTEXT = 'ft:credentials'
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Section orders. Consecutive integers keep a third-party section from sorting
|
|
40
|
+
* between two of ours (`1`–`499` is the shared free band), while `6` still lands
|
|
41
|
+
* after the deployment persona (`0`) and before core's plan policy (`500`).
|
|
42
|
+
*/
|
|
43
|
+
export const FT_SECTION_ORDERS = { services: 6, dataPolicy: 7 } as const
|
|
44
|
+
|
|
45
|
+
/** Order of the credential fact — `getContextOrder` owns only three named positions. */
|
|
46
|
+
export const FT_CREDENTIALS_ORDER = 130
|
|
47
|
+
|
|
48
|
+
export const FT_SERVICES_TEXT = '行情、K线与指标用 dsh-kline 工具(代码先用 search_symbols 解析);投研报告与组合推荐用 cockpit_* 工具;因子入库与评价用 factor-intake-standard 技能;FTShare API Key 在设置页维护。'
|
|
49
|
+
|
|
50
|
+
export const FT_DATA_POLICY_TEXT = '金融数据优先取 FTShare,其次才用联网检索补充;引用必须给出处与时点;严格区分已披露事实、机构判断与待验证信息;不编造数字,也不构成投资建议。'
|
|
51
|
+
|
|
52
|
+
export const FT_CREDENTIALS_MISSING_TEXT = 'FTShare 凭据未配置:行情可能退化为免费兜底源,覆盖有限,引用时必须标明来源;需要完整数据时引导用户在设置页填写 API Key。'
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Resolve the host prompt registry.
|
|
56
|
+
* @param ctx - the plugin context whose `inject` declared `systemPrompt`.
|
|
57
|
+
* @returns the registry, typed by this module's structural declaration.
|
|
58
|
+
*/
|
|
59
|
+
function promptRegistry(ctx: Context): PromptRegistry {
|
|
60
|
+
const registry = ctx.get('systemPrompt') as PromptRegistry | undefined
|
|
61
|
+
if (registry === undefined) {
|
|
62
|
+
throw new Error('dsh-fft-settings: the systemPrompt service is missing although inject declared it')
|
|
63
|
+
}
|
|
64
|
+
return registry
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Keep one boolean for the credential fact, because a prompt provider is
|
|
69
|
+
* synchronous while the settings service answers asynchronously.
|
|
70
|
+
* @param ctx - the plugin context.
|
|
71
|
+
*/
|
|
72
|
+
function installCredentialFact(ctx: Context): void {
|
|
73
|
+
const apiKey = ctx.ftshareSettings.apiKey
|
|
74
|
+
// `undefined` is "not known yet" and renders nothing: an unresolved fact must
|
|
75
|
+
// not tell the model the credential is missing.
|
|
76
|
+
let configured: boolean | undefined
|
|
77
|
+
const refresh = (): void => {
|
|
78
|
+
void apiKey.describe().then(
|
|
79
|
+
(status) => { configured = status.configured },
|
|
80
|
+
(error: unknown) => {
|
|
81
|
+
configured = undefined
|
|
82
|
+
ctx.logger.debug('dsh-fft-settings: credential status unavailable', error)
|
|
83
|
+
},
|
|
84
|
+
)
|
|
85
|
+
}
|
|
86
|
+
refresh()
|
|
87
|
+
ctx.effect(() => apiKey.subscribe(refresh), 'dsh-fft-settings: credential fact refresh')
|
|
88
|
+
ctx.effect(() => promptRegistry(ctx).context({
|
|
89
|
+
name: FT_CREDENTIALS_CONTEXT,
|
|
90
|
+
order: FT_CREDENTIALS_ORDER,
|
|
91
|
+
text: () => configured === false ? FT_CREDENTIALS_MISSING_TEXT : '',
|
|
92
|
+
}), 'dsh-fft-settings: ft:credentials')
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Register the FT prompt contract for every agent the calling context reaches.
|
|
97
|
+
* @param ctx - the plugin's host context; an unscoped context registers globally.
|
|
98
|
+
*/
|
|
99
|
+
export function installGuidance(ctx: Context): void {
|
|
100
|
+
const prompt = promptRegistry(ctx)
|
|
101
|
+
ctx.effect(() => prompt.section({
|
|
102
|
+
name: FT_SERVICES_SECTION,
|
|
103
|
+
order: FT_SECTION_ORDERS.services,
|
|
104
|
+
text: FT_SERVICES_TEXT,
|
|
105
|
+
}), 'dsh-fft-settings: ft:services')
|
|
106
|
+
ctx.effect(() => prompt.section({
|
|
107
|
+
name: FT_DATA_POLICY_SECTION,
|
|
108
|
+
order: FT_SECTION_ORDERS.dataPolicy,
|
|
109
|
+
text: FT_DATA_POLICY_TEXT,
|
|
110
|
+
}), 'dsh-fft-settings: ft:data-policy')
|
|
111
|
+
// Optional service: the three sections never depend on the settings row, and
|
|
112
|
+
// a missing provider only means the credential fact renders nothing.
|
|
113
|
+
ctx.inject(['ftshareSettings'], scope => installCredentialFact(scope))
|
|
114
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import type { Context } from '@deepseek-ai/cordis'
|
|
2
|
+
import z from '@deepseek-ai/schemastery'
|
|
3
|
+
import { type FtshareSettingsService } from './contract.js'
|
|
4
|
+
import { createSettingsHost } from './core/module-registry.js'
|
|
5
|
+
import { createApiKeyModule } from './features/api-key/index.js'
|
|
6
|
+
import { DEFAULT_LOGS_CONFIG, logsConfigSchema, resolveLogsConfig, type LogsConfig } from './features/logs/config.js'
|
|
7
|
+
import { createLogsModule } from './features/logs/index.js'
|
|
8
|
+
import type { HostFetch } from './core/rpc-core.js'
|
|
9
|
+
import { createSettingsRoute } from './core/transport.js'
|
|
10
|
+
import { installDefaultPresetOnce } from './default-preset.js'
|
|
11
|
+
export * from './contract.js'
|
|
12
|
+
export { defineSettingsModule } from './core/module-registry.js'
|
|
13
|
+
export const name = '@dsh-ft/dsh-fft-settings'
|
|
14
|
+
/**
|
|
15
|
+
* Host services this plugin's own built-in modules resolve at registration.
|
|
16
|
+
* A consuming plugin declares its own requirement; settings never declares
|
|
17
|
+
* services on a module's behalf. The FT prompt contract lives in the `./agent`
|
|
18
|
+
* entry, which only an agent preset mounts.
|
|
19
|
+
*/
|
|
20
|
+
export const inject = ['credentials']
|
|
21
|
+
export const provide = ['ftshareSettings']
|
|
22
|
+
/** Plugin config, assembled from each feature's own slice schema. */
|
|
23
|
+
export interface FtshareSettingsConfig { logs: LogsConfig }
|
|
24
|
+
/**
|
|
25
|
+
* Native Schemastery schema of the whole plugin config: the features own their
|
|
26
|
+
* slices, this entry only composes them. DSH's config collector accepts
|
|
27
|
+
* nothing but a native Schemastery schema.
|
|
28
|
+
*/
|
|
29
|
+
export const Config = z.object({ logs: logsConfigSchema })
|
|
30
|
+
export { DEFAULT_LOGS_CONFIG }
|
|
31
|
+
export type { LogsConfig }
|
|
32
|
+
declare module '@deepseek-ai/cordis' {
|
|
33
|
+
interface Context { ftshareSettings: FtshareSettingsService }
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* @param config - validated plugin config. Each built-in module is registered
|
|
37
|
+
* eagerly, so the log collector starts here, unconditionally, instead of
|
|
38
|
+
* waiting for a settings-page render.
|
|
39
|
+
*
|
|
40
|
+
* The parameter default is deliberately **not** relied on: cordis validates the
|
|
41
|
+
* raw row through {@link Config} before this call, and a direct `apply(ctx)`
|
|
42
|
+
* call (tests, hand-built contexts) never triggers one — so the fallback parse
|
|
43
|
+
* happens in the body and every feature slice is always defined.
|
|
44
|
+
*/
|
|
45
|
+
export function apply(ctx: Context, config?: FtshareSettingsConfig): void {
|
|
46
|
+
const { service, handler } = createSettingsHost()
|
|
47
|
+
ctx.provide('ftshareSettings', service)
|
|
48
|
+
// 具名 logger:`ctx.logger()` 无参调用时 logger name = 插件名(cordis 既有语义),
|
|
49
|
+
// 采集器据此把「是哪个包打的」自动带上。feature 不接受模块级单例。
|
|
50
|
+
const logger = ctx.logger()
|
|
51
|
+
// Built-in namespaces take the same path a third-party module would take.
|
|
52
|
+
service.modules.register(createApiKeyModule(logger), ctx)
|
|
53
|
+
service.modules.register(createLogsModule(resolveLogsConfig(config)), ctx)
|
|
54
|
+
installDefaultPresetOnce(ctx)
|
|
55
|
+
ctx.inject(['connection'], scoped => {
|
|
56
|
+
const connection = scoped.get('connection') as { fetch: HostFetch }
|
|
57
|
+
scoped.effect(() => connection.fetch.register(createSettingsRoute({ handler })), 'dsh-fft-settings: /api route')
|
|
58
|
+
})
|
|
59
|
+
}
|
package/src/rpc.ts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `@dsh-ft/dsh-fft-settings/client-api` — the generic browser caller entry.
|
|
3
|
+
*
|
|
4
|
+
* Transport plus envelope helpers and their types, nothing feature-specific: a
|
|
5
|
+
* card for any namespace uses `callSettingsRpc` against the namespace and
|
|
6
|
+
* method its own host module registered. A feature's browser adapter lives
|
|
7
|
+
* beside that feature instead of growing this entry.
|
|
8
|
+
*/
|
|
9
|
+
export * from './core/rpc-core.js'
|
|
10
|
+
export { createSettingsTransport } from './core/client-transport.js'
|