dsh-industry-research 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.
Files changed (99) hide show
  1. package/CHANGELOG.md +19 -0
  2. package/LICENSE +201 -0
  3. package/README.es.md +175 -0
  4. package/README.hi.md +175 -0
  5. package/README.md +175 -0
  6. package/README.pt.md +175 -0
  7. package/README.zh.md +175 -0
  8. package/THIRD_PARTY_NOTICES.md +21 -0
  9. package/cordis.patch.yml +44 -0
  10. package/lib/index.js +2080 -0
  11. package/lib/types/chain.d.ts +68 -0
  12. package/lib/types/chain.d.ts.map +1 -0
  13. package/lib/types/chain.js +88 -0
  14. package/lib/types/chain.js.map +1 -0
  15. package/lib/types/company.d.ts +121 -0
  16. package/lib/types/company.d.ts.map +1 -0
  17. package/lib/types/company.js +170 -0
  18. package/lib/types/company.js.map +1 -0
  19. package/lib/types/config.d.ts +72 -0
  20. package/lib/types/config.d.ts.map +1 -0
  21. package/lib/types/config.js +86 -0
  22. package/lib/types/config.js.map +1 -0
  23. package/lib/types/engine-bridge.d.ts +68 -0
  24. package/lib/types/engine-bridge.d.ts.map +1 -0
  25. package/lib/types/engine-bridge.js +18 -0
  26. package/lib/types/engine-bridge.js.map +1 -0
  27. package/lib/types/events.d.ts +79 -0
  28. package/lib/types/events.d.ts.map +1 -0
  29. package/lib/types/events.js +13 -0
  30. package/lib/types/events.js.map +1 -0
  31. package/lib/types/index.d.ts +58 -0
  32. package/lib/types/index.d.ts.map +1 -0
  33. package/lib/types/index.js +111 -0
  34. package/lib/types/index.js.map +1 -0
  35. package/lib/types/paths.d.ts +45 -0
  36. package/lib/types/paths.d.ts.map +1 -0
  37. package/lib/types/paths.js +93 -0
  38. package/lib/types/paths.js.map +1 -0
  39. package/lib/types/report.d.ts +134 -0
  40. package/lib/types/report.d.ts.map +1 -0
  41. package/lib/types/report.js +278 -0
  42. package/lib/types/report.js.map +1 -0
  43. package/lib/types/sources.d.ts +55 -0
  44. package/lib/types/sources.d.ts.map +1 -0
  45. package/lib/types/sources.js +73 -0
  46. package/lib/types/sources.js.map +1 -0
  47. package/lib/types/timeline.d.ts +78 -0
  48. package/lib/types/timeline.d.ts.map +1 -0
  49. package/lib/types/timeline.js +129 -0
  50. package/lib/types/timeline.js.map +1 -0
  51. package/lib/types/toolkit.d.ts +61 -0
  52. package/lib/types/toolkit.d.ts.map +1 -0
  53. package/lib/types/toolkit.js +77 -0
  54. package/lib/types/toolkit.js.map +1 -0
  55. package/lib/types/tools/company.d.ts +36 -0
  56. package/lib/types/tools/company.d.ts.map +1 -0
  57. package/lib/types/tools/company.js +139 -0
  58. package/lib/types/tools/company.js.map +1 -0
  59. package/lib/types/tools/map.d.ts +44 -0
  60. package/lib/types/tools/map.d.ts.map +1 -0
  61. package/lib/types/tools/map.js +211 -0
  62. package/lib/types/tools/map.js.map +1 -0
  63. package/lib/types/tools/report.d.ts +61 -0
  64. package/lib/types/tools/report.d.ts.map +1 -0
  65. package/lib/types/tools/report.js +277 -0
  66. package/lib/types/tools/report.js.map +1 -0
  67. package/lib/types/tools/track.d.ts +46 -0
  68. package/lib/types/tools/track.d.ts.map +1 -0
  69. package/lib/types/tools/track.js +188 -0
  70. package/lib/types/tools/track.js.map +1 -0
  71. package/lib/types/version.d.ts +8 -0
  72. package/lib/types/version.d.ts.map +1 -0
  73. package/lib/types/version.js +8 -0
  74. package/lib/types/version.js.map +1 -0
  75. package/lib/types/web.d.ts +74 -0
  76. package/lib/types/web.d.ts.map +1 -0
  77. package/lib/types/web.js +60 -0
  78. package/lib/types/web.js.map +1 -0
  79. package/package.json +143 -0
  80. package/skills/company-research-method/SKILL.md +50 -0
  81. package/skills/industry-research-method/SKILL.md +57 -0
  82. package/skills/industry-research-method/references/frameworks.md +42 -0
  83. package/src/chain.ts +132 -0
  84. package/src/company.ts +238 -0
  85. package/src/config.ts +154 -0
  86. package/src/engine-bridge.ts +62 -0
  87. package/src/events.ts +82 -0
  88. package/src/index.ts +139 -0
  89. package/src/paths.ts +96 -0
  90. package/src/report.ts +326 -0
  91. package/src/sources.ts +95 -0
  92. package/src/timeline.ts +155 -0
  93. package/src/toolkit.ts +87 -0
  94. package/src/tools/company.ts +157 -0
  95. package/src/tools/map.ts +241 -0
  96. package/src/tools/report.ts +304 -0
  97. package/src/tools/track.ts +223 -0
  98. package/src/version.ts +8 -0
  99. package/src/web.ts +94 -0
@@ -0,0 +1,188 @@
1
+ /**
2
+ * The `industry_track` tool: track public-source policy and news for one
3
+ * industry through `ctx.web` (never a hand-rolled fetch). Searches per topic,
4
+ * applies the host allow/block lists and the `since` filter, fetches page
5
+ * snapshots for a SHA-256 provenance hash within the configured fetch budget,
6
+ * and merges the surviving entries into `timeline.jsonl` (dedupe by
7
+ * normalized URL, capped by `timelineMaxEntries`). Fails loud when the web
8
+ * capability is unreachable; never fabricates an entry.
9
+ * @module dsh-industry-research/tools/track
10
+ */
11
+ import { defineTool } from '@deepseek-ai/dsh-tools';
12
+ import { mergeTimeline, readTimeline, sourceAllowed } from "../timeline.js";
13
+ import { sha256Of } from "../sources.js";
14
+ import { requestSignal, requireWeb, webErrorMessage } from "../web.js";
15
+ import { industryDirOf, timelinePathOf, workspaceOf } from "../toolkit.js";
16
+ /** How many snapshot fetches may run concurrently. */
17
+ const FETCH_CONCURRENCY = 4;
18
+ /**
19
+ * Run `limit`-bounded concurrent workers over `items`.
20
+ * @param items - the work items.
21
+ * @param limit - concurrency bound.
22
+ * @param worker - the per-item async worker.
23
+ */
24
+ async function pool(items, limit, worker) {
25
+ let next = 0;
26
+ const runners = Array.from({ length: Math.min(limit, items.length) }, async () => {
27
+ while (next < items.length) {
28
+ const item = items[next];
29
+ next += 1;
30
+ if (item !== undefined)
31
+ await worker(item);
32
+ }
33
+ });
34
+ await Promise.all(runners);
35
+ }
36
+ /**
37
+ * Build the `industry_track` tool definition.
38
+ * @param ctx - the plugin context (event emission + optional web lookup).
39
+ * @param config - the resolved plugin config.
40
+ * @returns the tool definition to register.
41
+ */
42
+ export function buildIndustryTrackTool(ctx, config) {
43
+ return defineTool({
44
+ name: 'industry_track',
45
+ description: '行业研究员的政策与动态跟踪工具:经官方 ctx.web 检索行业政策/要闻,产出带日期、标题、来源 URL、摘要与抓取快照哈希的结构化时间线条目,追加去重写入 timeline.jsonl。只使用公开源;来源不可达或数据缺口会显式列出,禁止编造。仅供研究,不构成投资建议。',
46
+ parameters: {
47
+ industry: { type: 'string', required: true, description: '行业名(作为目录段,如「白酒」)' },
48
+ topics: { type: 'array', items: { type: 'string' }, description: '检索主题列表;缺省用「<行业> 行业 政策」与「<行业> 行业 动态 要闻」' },
49
+ since: { type: 'string', description: '只保留该日期(ISO-8601)及之后的条目(按来源发布日期过滤;无日期的来源保留)' },
50
+ },
51
+ output: {
52
+ schema: {
53
+ type: 'object',
54
+ properties: {
55
+ industry: { type: 'string', required: true },
56
+ path: { type: 'string', required: true },
57
+ added: { type: 'array', items: { type: 'json' }, required: true },
58
+ duplicates: { type: 'number', required: true },
59
+ blocked: { type: 'number', required: true },
60
+ tooOld: { type: 'number', required: true },
61
+ fetchFailed: { type: 'array', items: { type: 'json' }, required: true },
62
+ total: { type: 'number', required: true },
63
+ truncated: { type: 'boolean', required: true },
64
+ corruptSkipped: { type: 'number', required: true },
65
+ },
66
+ additionalProperties: false,
67
+ },
68
+ render: (_args, value) => {
69
+ const current = value;
70
+ const lines = [
71
+ `行业「${current.industry}」政策与动态:新增 ${current.added.length} 条(去重 ${current.duplicates},拦截 ${current.blocked},过早 ${current.tooOld}),时间线共 ${current.total} 条 → ${current.path}`,
72
+ ];
73
+ for (const entry of current.added.slice(0, 10)) {
74
+ lines.push(`- ${entry.date ?? '日期未知'} — ${entry.title}(${entry.url})`);
75
+ }
76
+ if (current.added.length > 10)
77
+ lines.push(`- ……其余 ${current.added.length - 10} 条见 timeline.jsonl`);
78
+ if (current.fetchFailed.length > 0) {
79
+ lines.push(`快照抓取失败 ${current.fetchFailed.length} 条(仍以纯引用条目记录):${current.fetchFailed.map(failure => failure.url).join(';')}`);
80
+ }
81
+ if (current.truncated)
82
+ lines.push('已达 retention 上限,最旧条目已被裁剪。');
83
+ if (current.corruptSkipped > 0)
84
+ lines.push(`警告:跳过 ${current.corruptSkipped} 行损坏的既有时间线记录。`);
85
+ return [{ type: 'text', text: lines.join('\n') }];
86
+ },
87
+ },
88
+ timeoutMs: Math.max(60_000, config.fetchTimeoutMs * config.track.maxFetchesPerCall),
89
+ async execute(args, exec) {
90
+ const web = requireWeb(ctx, config, 'industry_track');
91
+ const cwd = workspaceOf(exec);
92
+ const { dir, name } = industryDirOf(config, cwd, args.industry);
93
+ const path = timelinePathOf(dir);
94
+ const topics = (args.topics ?? [`${name} 行业 政策`, `${name} 行业 动态 要闻`]).map(topic => topic.trim()).filter(topic => topic.length > 0);
95
+ if (topics.length === 0)
96
+ throw new Error('topics must contain at least one non-empty topic');
97
+ const since = args.since?.trim();
98
+ if (since !== undefined && Number.isNaN(Date.parse(since))) {
99
+ throw new Error(`since must be an ISO-8601 date, got ${JSON.stringify(args.since)}`);
100
+ }
101
+ const byUrl = new Map();
102
+ for (const topic of topics) {
103
+ const outcome = await web.search({ query: topic, maxResults: config.track.maxResultsPerTopic }, requestSignal(exec.signal, config.fetchTimeoutMs));
104
+ for (const source of outcome.sources) {
105
+ const existing = byUrl.get(source.url);
106
+ if (existing !== undefined) {
107
+ if (!existing.topics.includes(topic))
108
+ existing.topics.push(topic);
109
+ continue;
110
+ }
111
+ byUrl.set(source.url, {
112
+ url: source.url,
113
+ title: source.title ?? null,
114
+ snippet: source.snippet ?? null,
115
+ publishedAt: source.publishedAt ?? null,
116
+ topics: [topic],
117
+ });
118
+ }
119
+ }
120
+ // Filter phase: allow/block lists, then the since filter.
121
+ let blocked = 0;
122
+ let tooOld = 0;
123
+ const candidates = [];
124
+ for (const candidate of byUrl.values()) {
125
+ if (!sourceAllowed(candidate.url, config.sourceAllowlist, config.sourceBlocklist)) {
126
+ blocked += 1;
127
+ continue;
128
+ }
129
+ if (since !== undefined && candidate.publishedAt !== null) {
130
+ const published = Date.parse(candidate.publishedAt);
131
+ if (!Number.isNaN(published) && published < Date.parse(since)) {
132
+ tooOld += 1;
133
+ continue;
134
+ }
135
+ }
136
+ candidates.push(candidate);
137
+ }
138
+ // Snapshot phase: bounded concurrent fetches within the call budget.
139
+ const now = new Date().toISOString();
140
+ const fetchFailed = [];
141
+ const snapshots = new Map();
142
+ const fetchable = candidates.slice(0, config.track.maxFetchesPerCall);
143
+ await pool(fetchable, FETCH_CONCURRENCY, async (candidate) => {
144
+ try {
145
+ const outcome = await web.fetch({ url: candidate.url }, requestSignal(exec.signal, config.fetchTimeoutMs));
146
+ snapshots.set(candidate.url, sha256Of(outcome.body.content));
147
+ }
148
+ catch (error) {
149
+ fetchFailed.push({ url: candidate.url, note: webErrorMessage(error) });
150
+ }
151
+ });
152
+ const batch = candidates.map(candidate => {
153
+ const snapshotHash = snapshots.get(candidate.url) ?? null;
154
+ const failure = fetchFailed.find(entry => entry.url === candidate.url);
155
+ const beyondBudget = !fetchable.includes(candidate);
156
+ return {
157
+ date: candidate.publishedAt,
158
+ title: candidate.title ?? candidate.url,
159
+ url: candidate.url,
160
+ summary: candidate.snippet,
161
+ snapshotHash,
162
+ capturedAt: now,
163
+ topics: candidate.topics,
164
+ ...(snapshotHash === null
165
+ ? { note: failure !== undefined ? `快照抓取失败:${failure.note}` : beyondBudget ? '超出本次抓取预算,未抓取快照' : '无快照' }
166
+ : {}),
167
+ };
168
+ });
169
+ const { corrupt } = await readTimeline(path);
170
+ const merge = await mergeTimeline(path, batch, config.timelineMaxEntries);
171
+ const payload = { industry: name, path, added: merge.added.length, duplicates: merge.duplicates, total: merge.total };
172
+ ctx.emit('industry-research/track', payload);
173
+ return {
174
+ industry: name,
175
+ path,
176
+ added: merge.added,
177
+ duplicates: merge.duplicates,
178
+ blocked,
179
+ tooOld,
180
+ fetchFailed,
181
+ total: merge.total,
182
+ truncated: merge.truncated,
183
+ corruptSkipped: corrupt,
184
+ };
185
+ },
186
+ });
187
+ }
188
+ //# sourceMappingURL=track.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"track.js","sourceRoot":"","sources":["../../../src/tools/track.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Single source of truth for the package version (stamped by the release
3
+ * script together with package.json and CHANGELOG.md).
4
+ * @module dsh-industry-research/version
5
+ */
6
+ /** The package version. */
7
+ export declare const VERSION = "0.1.0";
8
+ //# sourceMappingURL=version.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"version.d.ts","sourceRoot":"","sources":["../../src/version.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,2BAA2B;AAC3B,eAAO,MAAM,OAAO,UAAU,CAAA"}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Single source of truth for the package version (stamped by the release
3
+ * script together with package.json and CHANGELOG.md).
4
+ * @module dsh-industry-research/version
5
+ */
6
+ /** The package version. */
7
+ export const VERSION = '0.1.0';
8
+ //# sourceMappingURL=version.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"version.js","sourceRoot":"","sources":["../../src/version.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,2BAA2B;AAC3B,MAAM,CAAC,MAAM,OAAO,GAAG,OAAO,CAAA"}
@@ -0,0 +1,74 @@
1
+ /**
2
+ * Optional access to the `ctx.web` capability. The service is never injected
3
+ * (a deployment without web providers must still mount this plugin); it is
4
+ * looked up structurally at execution time, and `industry_track` fails loud
5
+ * with mount guidance when the capability or the deployment's `offline` mode
6
+ * says the web is out of reach.
7
+ * @module dsh-industry-research/web
8
+ */
9
+ import type { Context } from '@deepseek-ai/cordis';
10
+ import type { ResolvedConfig } from './config.js';
11
+ /** One citeable search source (structural mirror of `WebSearchSource`). */
12
+ export type WebSource = {
13
+ readonly url: string;
14
+ readonly title?: string;
15
+ readonly snippet?: string;
16
+ readonly publishedAt?: string;
17
+ };
18
+ /** Structural mirror of `WebSearchResult`. */
19
+ export interface WebSearchOutcome {
20
+ readonly content?: string;
21
+ readonly sources: readonly WebSource[];
22
+ readonly truncated: boolean;
23
+ }
24
+ /** Structural mirror of `WebFetchResult`. */
25
+ export interface WebFetchOutcome {
26
+ readonly url: string;
27
+ readonly statusCode: number;
28
+ readonly body: {
29
+ readonly kind: string;
30
+ readonly content: string;
31
+ };
32
+ readonly truncated: boolean;
33
+ }
34
+ /** The structural surface of the optional `ctx.web` service this plugin uses. */
35
+ export interface WebLike {
36
+ search(request: {
37
+ query: string;
38
+ maxResults?: number;
39
+ }, signal?: AbortSignal): Promise<WebSearchOutcome>;
40
+ fetch(request: {
41
+ url: string;
42
+ }, signal?: AbortSignal): Promise<WebFetchOutcome>;
43
+ }
44
+ /**
45
+ * Look up the optional web capability.
46
+ * @param ctx - the plugin context.
47
+ * @returns the web service surface, or undefined when no web seam is mounted.
48
+ */
49
+ export declare function lookupWeb(ctx: Context): WebLike | undefined;
50
+ /**
51
+ * Resolve the web capability or throw the actionable reason it cannot run:
52
+ * `offline: true` (deployment choice) or no mounted web seam (mount guidance
53
+ * naming the missing pieces). Used by tools whose work is impossible offline.
54
+ * @param ctx - the plugin context.
55
+ * @param config - the resolved plugin config.
56
+ * @param tool - the calling tool name (for the error message).
57
+ * @returns the web service surface.
58
+ */
59
+ export declare function requireWeb(ctx: Context, config: ResolvedConfig, tool: string): WebLike;
60
+ /**
61
+ * Combine the tool's caller signal with the configured per-request timeout.
62
+ * @param signal - the tool execution signal (`exec.signal`).
63
+ * @param timeoutMs - per-request timeout in milliseconds.
64
+ * @returns a signal that fires on either cancellation or timeout.
65
+ */
66
+ export declare function requestSignal(signal: AbortSignal, timeoutMs: number): AbortSignal;
67
+ /**
68
+ * Render a thrown web failure with its machine-routable code when one exists
69
+ * (`WebError` carries a stable `code`; plain errors degrade to the message).
70
+ * @param error - the thrown value.
71
+ * @returns a single-line diagnostic.
72
+ */
73
+ export declare function webErrorMessage(error: unknown): string;
74
+ //# sourceMappingURL=web.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"web.d.ts","sourceRoot":"","sources":["../../src/web.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AAClD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAA;AAEjD,2EAA2E;AAC3E,MAAM,MAAM,SAAS,GAAG;IACtB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;IACpB,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAA;IACvB,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAA;IACzB,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAA;CAC9B,CAAA;AAED,8CAA8C;AAC9C,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAA;IACzB,QAAQ,CAAC,OAAO,EAAE,SAAS,SAAS,EAAE,CAAA;IACtC,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAA;CAC5B;AAED,6CAA6C;AAC7C,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;IACpB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAA;IAC3B,QAAQ,CAAC,IAAI,EAAE;QAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAA;IAClE,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAA;CAC5B;AAED,iFAAiF;AACjF,MAAM,WAAW,OAAO;IACtB,MAAM,CAAC,OAAO,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,UAAU,CAAC,EAAE,MAAM,CAAA;KAAE,EAAE,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAAA;IACxG,KAAK,CAAC,OAAO,EAAE;QAAE,GAAG,EAAE,MAAM,CAAA;KAAE,EAAE,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,eAAe,CAAC,CAAA;CAChF;AAED;;;;GAIG;AACH,wBAAgB,SAAS,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,GAAG,SAAS,CAE3D;AAED;;;;;;;;GAQG;AACH,wBAAgB,UAAU,CAAC,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,cAAc,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAStF;AAED;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,GAAG,WAAW,CAEjF;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAOtD"}
@@ -0,0 +1,60 @@
1
+ /**
2
+ * Optional access to the `ctx.web` capability. The service is never injected
3
+ * (a deployment without web providers must still mount this plugin); it is
4
+ * looked up structurally at execution time, and `industry_track` fails loud
5
+ * with mount guidance when the capability or the deployment's `offline` mode
6
+ * says the web is out of reach.
7
+ * @module dsh-industry-research/web
8
+ */
9
+ /**
10
+ * Look up the optional web capability.
11
+ * @param ctx - the plugin context.
12
+ * @returns the web service surface, or undefined when no web seam is mounted.
13
+ */
14
+ export function lookupWeb(ctx) {
15
+ return ctx.get('web');
16
+ }
17
+ /**
18
+ * Resolve the web capability or throw the actionable reason it cannot run:
19
+ * `offline: true` (deployment choice) or no mounted web seam (mount guidance
20
+ * naming the missing pieces). Used by tools whose work is impossible offline.
21
+ * @param ctx - the plugin context.
22
+ * @param config - the resolved plugin config.
23
+ * @param tool - the calling tool name (for the error message).
24
+ * @returns the web service surface.
25
+ */
26
+ export function requireWeb(ctx, config, tool) {
27
+ if (config.offline) {
28
+ throw new Error(`${tool} cannot run while config.offline is true — public-source tracking requires the web; set offline: false or work from local artifacts only`);
29
+ }
30
+ const web = lookupWeb(ctx);
31
+ if (web === undefined) {
32
+ throw new Error(`${tool} requires the ctx.web capability, which is not mounted in this profile — mount @deepseek-ai/dsh-web plus a search provider (e.g. @deepseek-ai/dsh-web-search-deepseek) and a fetch provider (e.g. @deepseek-ai/dsh-web-fetch-http); the official dsh-base bundle already composes them`);
33
+ }
34
+ return web;
35
+ }
36
+ /**
37
+ * Combine the tool's caller signal with the configured per-request timeout.
38
+ * @param signal - the tool execution signal (`exec.signal`).
39
+ * @param timeoutMs - per-request timeout in milliseconds.
40
+ * @returns a signal that fires on either cancellation or timeout.
41
+ */
42
+ export function requestSignal(signal, timeoutMs) {
43
+ return AbortSignal.any([signal, AbortSignal.timeout(timeoutMs)]);
44
+ }
45
+ /**
46
+ * Render a thrown web failure with its machine-routable code when one exists
47
+ * (`WebError` carries a stable `code`; plain errors degrade to the message).
48
+ * @param error - the thrown value.
49
+ * @returns a single-line diagnostic.
50
+ */
51
+ export function webErrorMessage(error) {
52
+ if (error instanceof Error) {
53
+ const code = error.code;
54
+ if (typeof code === 'string' && code.length > 0)
55
+ return `${code}: ${error.message}`;
56
+ return error.message;
57
+ }
58
+ return String(error);
59
+ }
60
+ //# sourceMappingURL=web.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"web.js","sourceRoot":"","sources":["../../src/web.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAkCH;;;;GAIG;AACH,MAAM,UAAU,SAAS,CAAC,GAAY;IACpC,OAAO,GAAG,CAAC,GAAG,CAAC,KAAK,CAAmC,CAAA;AACzD,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,UAAU,CAAC,GAAY,EAAE,MAAsB,EAAE,IAAY;IAC3E,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;QACnB,MAAM,IAAI,KAAK,CAAC,GAAG,IAAI,0IAA0I,CAAC,CAAA;IACpK,CAAC;IACD,MAAM,GAAG,GAAG,SAAS,CAAC,GAAG,CAAC,CAAA;IAC1B,IAAI,GAAG,KAAK,SAAS,EAAE,CAAC;QACtB,MAAM,IAAI,KAAK,CAAC,GAAG,IAAI,wRAAwR,CAAC,CAAA;IAClT,CAAC;IACD,OAAO,GAAG,CAAA;AACZ,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,aAAa,CAAC,MAAmB,EAAE,SAAiB;IAClE,OAAO,WAAW,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,WAAW,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,CAAA;AAClE,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,eAAe,CAAC,KAAc;IAC5C,IAAI,KAAK,YAAY,KAAK,EAAE,CAAC;QAC3B,MAAM,IAAI,GAAI,KAA4B,CAAC,IAAI,CAAA;QAC/C,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC;YAAE,OAAO,GAAG,IAAI,KAAK,KAAK,CAAC,OAAO,EAAE,CAAA;QACnF,OAAO,KAAK,CAAC,OAAO,CAAA;IACtB,CAAC;IACD,OAAO,MAAM,CAAC,KAAK,CAAC,CAAA;AACtB,CAAC"}
package/package.json ADDED
@@ -0,0 +1,143 @@
1
+ {
2
+ "name": "dsh-industry-research",
3
+ "version": "0.1.0",
4
+ "description": "Industry and company research domain pack for DeepSeek Harness: methodology skills, an industry-chain structure model (industry_map), public-source policy/news tracking over ctx.web (industry_track), company scan cards (company_scan), and auditable research reports with an optional ctx.researchReport sealing bridge and a builtin Markdown fallback (industry_report). Research only — not investment advice.",
5
+ "author": "dsh-industry-research contributors",
6
+ "repository": {
7
+ "type": "git",
8
+ "url": "git+https://github.com/PerryLink/dsh-industry-research.git"
9
+ },
10
+ "homepage": "https://github.com/PerryLink/dsh-industry-research#readme",
11
+ "bugs": {
12
+ "url": "https://github.com/PerryLink/dsh-industry-research/issues"
13
+ },
14
+ "private": false,
15
+ "type": "module",
16
+ "main": "./lib/index.js",
17
+ "types": "./lib/types/index.d.ts",
18
+ "exports": {
19
+ ".": {
20
+ "types": "./lib/types/index.d.ts",
21
+ "default": "./lib/index.js"
22
+ },
23
+ "./package.json": "./package.json"
24
+ },
25
+ "files": [
26
+ "lib",
27
+ "src",
28
+ "skills",
29
+ "cordis.patch.yml",
30
+ "CHANGELOG.md",
31
+ "THIRD_PARTY_NOTICES.md",
32
+ "README.md",
33
+ "README.zh.md",
34
+ "README.es.md",
35
+ "README.pt.md",
36
+ "README.hi.md",
37
+ "LICENSE"
38
+ ],
39
+ "sideEffects": false,
40
+ "dsh": {
41
+ "bundle": {
42
+ "patch": "./cordis.patch.yml"
43
+ }
44
+ },
45
+ "dshWorkshop": {
46
+ "schema": "omdsh-workshop-package/v1",
47
+ "type": "plugin",
48
+ "integration": {
49
+ "protocol": "harness-profile",
50
+ "artifact": "cordis.patch.yml"
51
+ },
52
+ "install": {
53
+ "mode": "transactional",
54
+ "adapter": "profile-bundle",
55
+ "failurePolicy": "generation-rollback",
56
+ "touchesCurrentBeforeActivation": false
57
+ },
58
+ "lifecycle": {
59
+ "activation": "restart-profile",
60
+ "dispose": "supported"
61
+ },
62
+ "permissions": [
63
+ "files:read",
64
+ "files:write",
65
+ "network:fetch",
66
+ "native-code:none"
67
+ ],
68
+ "compatibility": {
69
+ "dshVersions": [
70
+ "0.1.0-rc.6"
71
+ ]
72
+ },
73
+ "capability": {
74
+ "id": "industry-research",
75
+ "kind": "research-domain-pack",
76
+ "invocation": "mount the dsh-industry-research bundle row, then call industry_map / industry_track / company_scan / industry_report or load the industry-research-method / company-research-method skills",
77
+ "expected": "ctx.tools gains the four research tools, ctx.skills lists the two methodology skills, artifacts land under the configured industryRoot, and reports carry the research-only disclaimer with a source-traceability appendix"
78
+ },
79
+ "evidence": {
80
+ "install": null,
81
+ "failureIsolation": null,
82
+ "hotReload": null,
83
+ "remove": null
84
+ }
85
+ },
86
+ "keywords": [
87
+ "dsh",
88
+ "dsh-plugin",
89
+ "deepseek-harness",
90
+ "cordis",
91
+ "industry-research",
92
+ "company-research",
93
+ "research",
94
+ "report"
95
+ ],
96
+ "engines": {
97
+ "node": "^22.19.0 || >=24.0.0"
98
+ },
99
+ "packageManager": "pnpm@11.7.0",
100
+ "peerDependencies": {
101
+ "@deepseek-ai/cordis": "^4.0.1",
102
+ "@deepseek-ai/dsh-skill": "0.1.0-rc.6",
103
+ "@deepseek-ai/dsh-skill-filesystem": "0.1.0-rc.6",
104
+ "@deepseek-ai/dsh-tools": "0.1.0-rc.6",
105
+ "@deepseek-ai/schemastery": "^3.18.0"
106
+ },
107
+ "dependencies": {
108
+ "tsdown": "^0.22.14",
109
+ "typescript": "^5.9.0"
110
+ },
111
+ "devDependencies": {
112
+ "@deepseek-ai/cordis": "^4.0.1",
113
+ "@deepseek-ai/cordis-plugin-include": "1.0.6",
114
+ "@deepseek-ai/cordis-plugin-loader": "1.0.2",
115
+ "@deepseek-ai/dsh-agent": "0.1.0-rc.6",
116
+ "@deepseek-ai/dsh-llm": "0.1.0-rc.6",
117
+ "@deepseek-ai/dsh-session": "0.1.0-rc.6",
118
+ "@deepseek-ai/dsh-skill": "0.1.0-rc.6",
119
+ "@deepseek-ai/dsh-skill-filesystem": "0.1.0-rc.6",
120
+ "@deepseek-ai/dsh-system-prompt": "0.1.0-rc.6",
121
+ "@deepseek-ai/dsh-tools": "0.1.0-rc.6",
122
+ "@deepseek-ai/dsh-web": "0.1.0-rc.6",
123
+ "@deepseek-ai/schemastery": "^3.18.0",
124
+ "@types/node": "^22.19.0",
125
+ "@vitest/coverage-v8": "^3.2.0",
126
+ "oxlint": "0.18.1",
127
+ "vitest": "^3.2.0"
128
+ },
129
+ "scripts": {
130
+ "build": "node scripts/prepare.mjs",
131
+ "typecheck": "tsc -p tsconfig.json --noEmit && tsc -p tsconfig.test.json --noEmit",
132
+ "typecheck:ci": "tsc -p tsconfig.ci.json --noEmit",
133
+ "test": "vitest run",
134
+ "test:coverage": "vitest run --coverage",
135
+ "lint": "oxlint",
136
+ "prepare": "node scripts/prepare.mjs",
137
+ "verify:self-contained": "node scripts/verify-self-contained.mjs",
138
+ "verify:artifacts": "node scripts/verify-artifacts.mjs",
139
+ "verify:readme-sync": "node scripts/check-readme-sync.mjs",
140
+ "pack:check": "node scripts/prepare.mjs && pnpm pack"
141
+ },
142
+ "license": "Apache-2.0"
143
+ }
@@ -0,0 +1,50 @@
1
+ ---
2
+ name: company-research-method
3
+ description: '公司研究方法论:公司研究框架(业务结构/财务要点/风险点)、公开源清单与用户数据文件的使用纪律、数字标注纪律(来源文件+行号+asOf)、合规话术。做单个公司的速览、对比或深度研究时使用;行业层面研究用 industry-research-method。'
4
+ whenToUse: '用户要求研究一个具体公司(速览卡、年报摘录解读、风险梳理)时使用本技能;配合 company_scan 工具落盘卡片。只做行业层面研究时改用 industry-research-method。'
5
+ metadata:
6
+ pack: dsh-industry-research
7
+ version: '0.1.0'
8
+ ---
9
+
10
+ # 公司研究方法论(company-research-method)
11
+
12
+ 本技能规范一次公司研究的流程与纪律,产出**每个数字都能标注来源文件与行号**的公司速览卡。合规底线:**仅供研究,不构成投资建议**;不接付费/需登录数据源(企查查、Wind 等留给用户自行导出后作为 `dataFiles` 传入)。
13
+
14
+ ## 工具配合关系
15
+
16
+ - `company_scan({ name, dataFiles? })`:读用户数据文件(主)+ `ctx.web` 公开检索(辅),落盘 `<industryRoot>/companies/<公司>/card.json` + `card.md`。
17
+ - 卡片落盘后由研究者(模型)在对话中基于 `figureCandidates`(数字候选行,带文件与行号)完成分析段;`industry_report` 会把卡片纳入行业报告。
18
+
19
+ ## 阶段 1:材料归集
20
+
21
+ 1. **用户提供数据为主**:年报/公告摘录、数据表(.md/.txt/.csv/.tsv/.json;v1 不解析 PDF——请用户先转成文本)。文件必须在会话工作区内,`company_scan` 会拒绝越界路径并列出未采纳原因。
22
+ 2. **公开源为辅**:`ctx.web` 检索公司简介/业务(官网、公告、权威媒体报道);`ctx.web` 未挂载或 offline 时记入缺口,不得用记忆充数。
23
+ 3. 付费/需登录来源(企查查、Wind、Choice 等):请用户自行导出摘录后放入工作区,作为 `dataFiles` 传入即可——本插件不直接对接。
24
+
25
+ ## 阶段 2:速览卡框架(company_scan)
26
+
27
+ 卡片三节框架,**每节只写能回溯的内容**:
28
+
29
+ 1. **业务结构**:主营构成、收入分部、上下游位置;从数据文件的目录结构与正文归纳,引用时标注文件。
30
+ 2. **财务要点**:只引用 `figureCandidates` 命中的数字行,格式「指标:数值 单位(截至 asOf,来源 文件:行号)」;跨期比较注明口径。
31
+ 3. **风险点**:只列来源材料中明示的风险(年报「风险提示」章节、公告、监管文书);**不得凭空列举**;无材料时保留「待补」。
32
+
33
+ ## 阶段 3:深化与并入行业研究
34
+
35
+ - 需要行业坐标时,用 `industry_map` 把公司放入产业链节点(指标槽位同样遵守来源纪律)。
36
+ - `industry_report` 会把 `companies/` 下的卡片汇总进行业报告的公司速览一节;卡片的缺口会并入报告缺口清单。
37
+
38
+ ## 公开源清单(按优先级)
39
+
40
+ 1. 公司披露:官网投资者关系页、定期报告与公告原文。
41
+ 2. 监管与政务:证监会/交易所披露、行业主管部门政策原文(`gov.cn`)。
42
+ 3. 权威媒体与行业协会发布;搜索引擎摘要只作线索,引用前尽量抓取原文核对。
43
+ 4. 不采用:匿名论坛帖、无署名转载、无法定位发布时间的页面(可作线索,不进证据)。
44
+
45
+ ## 口径纪律与合规话术
46
+
47
+ - 每个数字三要素:数值、单位、来源(文件:行号 或 URL),尽量带 asOf;缺来源一律待补。
48
+ - 财务数据优先「公司披露口径」;媒体二手数据必须标注为二手。
49
+ - 结论性表述以「仅供研究,不构成投资建议」收尾;不预测股价、不评价买卖时点、不作评级。
50
+ - 缺口声明优于完整假象:查不到的写进缺口清单。
@@ -0,0 +1,57 @@
1
+ ---
2
+ name: industry-research-method
3
+ description: '行业研究方法论:产业链上中下游拆分法、供需分析框架、政策跟踪口径、数据口径纪律(每个数字必须有来源与 asOf)、缺口声明纪律(宁标缺口不编造)。做行业梳理、产业链建图、政策动态跟踪或行业报告撰写时使用;只查单一公司时用 company-research-method。'
4
+ whenToUse: '用户要求研究一个行业(梳理产业链、跟踪政策动态、写行业研究报告)时使用本技能;配合 industry_map / industry_track / industry_report 工具落盘可核查产物。只做公司层面研究时改用 company-research-method。'
5
+ metadata:
6
+ pack: dsh-industry-research
7
+ version: '0.1.0'
8
+ ---
9
+
10
+ # 行业研究方法论(industry-research-method)
11
+
12
+ 本技能规范一次行业研究的全流程,产出**每个数字都能回溯到来源**的可核查产物。合规底线:**仅供研究,不构成投资建议**;不接交易、不做实时告警、不使用需登录/付费/绕反爬的数据源。
13
+
14
+ ## 工具配合关系
15
+
16
+ | 阶段 | 工具 | 产物 |
17
+ |---|---|---|
18
+ | 建图 | `industry_map` | `<industryRoot>/<行业>/chain.json`(校验过的产业链结构图) |
19
+ | 跟踪 | `industry_track` | `<industryRoot>/<行业>/timeline.jsonl`(政策/动态时间线) |
20
+ | 成文 | `industry_report` | `reports/<时间戳>/report.md` + `manifest.json`(引擎缺席时为 builtin-fallback) |
21
+
22
+ 工作区默认根为 `industry-research/`(可用 `industryRoot` 配置)。方法论细节见 `references/frameworks.md`(供需框架与常见拆分模板),需要时再用 read 工具加载。
23
+
24
+ ## 阶段 1:产业链拆分(industry_map)
25
+
26
+ 1. 先调用 `industry_map({ industry })`(不带 chain)读取当前图与已登记来源;有用户笔记/文件时经 `seed`/`seedFiles` 登记为来源(得 ref,如 `S1`)。
27
+ 2. 按上/中/下游拆分撰写 ChainMap:
28
+ - **上游**:原材料、关键投入品、设备与基础设施。
29
+ - **中游**:生产制造、核心工艺环节、主要参与者类型。
30
+ - **下游**:分销渠道、终端应用、消费者/客户类型。
31
+ - 边表示投入→产出关系,`note` 写明关系性质(如「原料供应」「渠道分销」)。
32
+ 3. 每个节点挂指标槽位:**有 `value` 必须带 `sourceRef`**(sources.json 的 ref、URL 或工作区路径)并尽量带 `asOf`;暂时没有来源的指标**只写 `key` 不写 `value`**——这就是显式待补槽位,禁止填估计值。
33
+ 4. 带 `chain` 再次调用 `industry_map`;校验失败(悬空边、无来源数值、非法 tier)按返回的问题清单修正后重试。
34
+ 5. 工具返回的 `gaps` 是后续工作的清单,不是失败:逐项决定是补充来源还是保留待补。
35
+
36
+ ## 阶段 2:政策与动态跟踪(industry_track)
37
+
38
+ 1. 默认主题为「<行业> 行业 政策」与「<行业> 行业 动态 要闻」;用户给定点时经 `topics` 传入。
39
+ 2. 条目纪律:每条带来源 URL、发布日期(来源无日期则为空,**不得编造日期**)、摘要与快照哈希;抓取失败的条目以纯引用形式记录并在 `note` 中说明。
40
+ 3. 来源治理:部署方可用 `sourceAllowlist`/`sourceBlocklist` 收口(如只信 `gov.cn`);被拦截与去重的计数在结果中如实报告。
41
+ 4. `ctx.web` 未挂载或 `offline: true` 时工具会响亮失败——如实转告用户需要挂载 web provider 或关闭 offline,**不得**用记忆代替检索结果充数。
42
+
43
+ ## 阶段 3:报告成文(industry_report)
44
+
45
+ 1. 默认自动草稿即可成文;需要定制叙述结构时用 `draft` 撰写 sections + claims:
46
+ - 每条 claim 必须登记 `evidenceIds`(`E-chain` / `E-timeline` / `E-company-<slug>`)。
47
+ - claim 文本中的数字必须与证据内容一致——引擎路径会逐条核查,builtin-fallback 路径会把 claims 如实标记为 unverified。
48
+ 2. 报告必须保留:免责声明(仅供研究,不构成投资建议)、来源回溯表、缺口与待补清单。
49
+ 3. 挂载了 `ctx.researchReport` 引擎时报告经其 `assemble` 封存并回传 sealHash 与逐 claim 结论;未挂载时走 `reports/<时间戳>/` 的版本化降级目录,如实标注 `engine: builtin-fallback`。
50
+
51
+ ## 口径纪律(违反即返工)
52
+
53
+ - **每个数字三要素齐全**:数值、单位、来源(+ 尽量 asOf);缺来源的数字降级为待补槽位。
54
+ - **口径一致**:同一指标跨来源使用时注明口径差异(如「出厂口径 vs 零售口径」)。
55
+ - **缺口声明优于完整假象**:找不到的数据写进缺口清单,禁止编造产业链数据、公司数字或政策条文。
56
+ - **区分事实与判断**:检索到的事实带来源;研究者的判断/推测必须明示为判断,不混入证据区。
57
+ - **合规话术**:对用户的任何结论性表述以「仅供研究,不构成投资建议」收尾;不预测价格、不推荐买卖。