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.
- package/CHANGELOG.md +19 -0
- package/LICENSE +201 -0
- package/README.es.md +175 -0
- package/README.hi.md +175 -0
- package/README.md +175 -0
- package/README.pt.md +175 -0
- package/README.zh.md +175 -0
- package/THIRD_PARTY_NOTICES.md +21 -0
- package/cordis.patch.yml +44 -0
- package/lib/index.js +2080 -0
- package/lib/types/chain.d.ts +68 -0
- package/lib/types/chain.d.ts.map +1 -0
- package/lib/types/chain.js +88 -0
- package/lib/types/chain.js.map +1 -0
- package/lib/types/company.d.ts +121 -0
- package/lib/types/company.d.ts.map +1 -0
- package/lib/types/company.js +170 -0
- package/lib/types/company.js.map +1 -0
- package/lib/types/config.d.ts +72 -0
- package/lib/types/config.d.ts.map +1 -0
- package/lib/types/config.js +86 -0
- package/lib/types/config.js.map +1 -0
- package/lib/types/engine-bridge.d.ts +68 -0
- package/lib/types/engine-bridge.d.ts.map +1 -0
- package/lib/types/engine-bridge.js +18 -0
- package/lib/types/engine-bridge.js.map +1 -0
- package/lib/types/events.d.ts +79 -0
- package/lib/types/events.d.ts.map +1 -0
- package/lib/types/events.js +13 -0
- package/lib/types/events.js.map +1 -0
- package/lib/types/index.d.ts +58 -0
- package/lib/types/index.d.ts.map +1 -0
- package/lib/types/index.js +111 -0
- package/lib/types/index.js.map +1 -0
- package/lib/types/paths.d.ts +45 -0
- package/lib/types/paths.d.ts.map +1 -0
- package/lib/types/paths.js +93 -0
- package/lib/types/paths.js.map +1 -0
- package/lib/types/report.d.ts +134 -0
- package/lib/types/report.d.ts.map +1 -0
- package/lib/types/report.js +278 -0
- package/lib/types/report.js.map +1 -0
- package/lib/types/sources.d.ts +55 -0
- package/lib/types/sources.d.ts.map +1 -0
- package/lib/types/sources.js +73 -0
- package/lib/types/sources.js.map +1 -0
- package/lib/types/timeline.d.ts +78 -0
- package/lib/types/timeline.d.ts.map +1 -0
- package/lib/types/timeline.js +129 -0
- package/lib/types/timeline.js.map +1 -0
- package/lib/types/toolkit.d.ts +61 -0
- package/lib/types/toolkit.d.ts.map +1 -0
- package/lib/types/toolkit.js +77 -0
- package/lib/types/toolkit.js.map +1 -0
- package/lib/types/tools/company.d.ts +36 -0
- package/lib/types/tools/company.d.ts.map +1 -0
- package/lib/types/tools/company.js +139 -0
- package/lib/types/tools/company.js.map +1 -0
- package/lib/types/tools/map.d.ts +44 -0
- package/lib/types/tools/map.d.ts.map +1 -0
- package/lib/types/tools/map.js +211 -0
- package/lib/types/tools/map.js.map +1 -0
- package/lib/types/tools/report.d.ts +61 -0
- package/lib/types/tools/report.d.ts.map +1 -0
- package/lib/types/tools/report.js +277 -0
- package/lib/types/tools/report.js.map +1 -0
- package/lib/types/tools/track.d.ts +46 -0
- package/lib/types/tools/track.d.ts.map +1 -0
- package/lib/types/tools/track.js +188 -0
- package/lib/types/tools/track.js.map +1 -0
- package/lib/types/version.d.ts +8 -0
- package/lib/types/version.d.ts.map +1 -0
- package/lib/types/version.js +8 -0
- package/lib/types/version.js.map +1 -0
- package/lib/types/web.d.ts +74 -0
- package/lib/types/web.d.ts.map +1 -0
- package/lib/types/web.js +60 -0
- package/lib/types/web.js.map +1 -0
- package/package.json +143 -0
- package/skills/company-research-method/SKILL.md +50 -0
- package/skills/industry-research-method/SKILL.md +57 -0
- package/skills/industry-research-method/references/frameworks.md +42 -0
- package/src/chain.ts +132 -0
- package/src/company.ts +238 -0
- package/src/config.ts +154 -0
- package/src/engine-bridge.ts +62 -0
- package/src/events.ts +82 -0
- package/src/index.ts +139 -0
- package/src/paths.ts +96 -0
- package/src/report.ts +326 -0
- package/src/sources.ts +95 -0
- package/src/timeline.ts +155 -0
- package/src/toolkit.ts +87 -0
- package/src/tools/company.ts +157 -0
- package/src/tools/map.ts +241 -0
- package/src/tools/report.ts +304 -0
- package/src/tools/track.ts +223 -0
- package/src/version.ts +8 -0
- package/src/web.ts +94 -0
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The industry-chain structure model (`ChainMap`) and its validation. This is
|
|
3
|
+
* a pure data module: no I/O, no clock. A metric is either a sourced value
|
|
4
|
+
* (`value` + `sourceRef`, optionally `unit`/`asOf`) or an explicit gap slot
|
|
5
|
+
* (no `value`), so an unsourced number is a validation error by construction
|
|
6
|
+
* and a missing number is an honest, listable gap.
|
|
7
|
+
* @module dsh-industry-research/chain
|
|
8
|
+
*/
|
|
9
|
+
/** Chain tiers, upstream → downstream. */
|
|
10
|
+
export declare const CHAIN_TIERS: readonly ["upstream", "midstream", "downstream"];
|
|
11
|
+
/** One chain tier. */
|
|
12
|
+
export type ChainTier = (typeof CHAIN_TIERS)[number];
|
|
13
|
+
/** One metric slot on a chain node. */
|
|
14
|
+
export type ChainMetric = {
|
|
15
|
+
/** Metric name (e.g. `市场规模`, `毛利率`). */
|
|
16
|
+
key: string;
|
|
17
|
+
/** The numeric value; absent means the slot is an explicit gap (待补). */
|
|
18
|
+
value?: number;
|
|
19
|
+
/** Unit of the value (e.g. `亿元`, `%`). */
|
|
20
|
+
unit?: string;
|
|
21
|
+
/** ISO-8601 date the value is current as of. */
|
|
22
|
+
asOf?: string;
|
|
23
|
+
/** Source reference: a sources.json ref (`S1`), a URL, or a workspace path. Required whenever `value` is present. */
|
|
24
|
+
sourceRef?: string;
|
|
25
|
+
};
|
|
26
|
+
/** One node in the industry chain. */
|
|
27
|
+
export type ChainNode = {
|
|
28
|
+
/** Stable node id referenced by edges (unique within the map). */
|
|
29
|
+
id: string;
|
|
30
|
+
/** Display name (e.g. `高粱种植`, `白酒酿造`). */
|
|
31
|
+
name: string;
|
|
32
|
+
tier: ChainTier;
|
|
33
|
+
/** Metric slots; each is a sourced value or an explicit gap. */
|
|
34
|
+
metrics: ChainMetric[];
|
|
35
|
+
};
|
|
36
|
+
/** One directed relation between two nodes. */
|
|
37
|
+
export type ChainEdge = {
|
|
38
|
+
/** Source node id. */
|
|
39
|
+
from: string;
|
|
40
|
+
/** Target node id. */
|
|
41
|
+
to: string;
|
|
42
|
+
/** Optional relation note (e.g. `原料供应`). */
|
|
43
|
+
note?: string;
|
|
44
|
+
};
|
|
45
|
+
/** The industry-chain map persisted as `<industryRoot>/<industry>/chain.json`. */
|
|
46
|
+
export type ChainMap = {
|
|
47
|
+
/** Industry display name. */
|
|
48
|
+
industry: string;
|
|
49
|
+
nodes: ChainNode[];
|
|
50
|
+
edges: ChainEdge[];
|
|
51
|
+
};
|
|
52
|
+
/**
|
|
53
|
+
* Validate a chain map. Pure: returns the list of problems (empty when the
|
|
54
|
+
* map is well-formed). Rules: unique node ids, legal tiers, edges reference
|
|
55
|
+
* existing nodes, and every metric carrying a `value` also carries a
|
|
56
|
+
* `sourceRef` (gap slots without a value are always legal).
|
|
57
|
+
* @param map - the candidate chain map.
|
|
58
|
+
* @returns human-readable validation problems, in encounter order.
|
|
59
|
+
*/
|
|
60
|
+
export declare function validateChainMap(map: ChainMap): string[];
|
|
61
|
+
/**
|
|
62
|
+
* List the explicit gaps of a well-formed chain map: metric slots without a
|
|
63
|
+
* value, nodes without any metric slot, and tiers with no node at all.
|
|
64
|
+
* @param map - the chain map (already validated).
|
|
65
|
+
* @returns human-readable gap lines, in encounter order.
|
|
66
|
+
*/
|
|
67
|
+
export declare function chainGaps(map: ChainMap): string[];
|
|
68
|
+
//# sourceMappingURL=chain.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chain.d.ts","sourceRoot":"","sources":["../../src/chain.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,0CAA0C;AAC1C,eAAO,MAAM,WAAW,kDAAmD,CAAA;AAE3E,sBAAsB;AACtB,MAAM,MAAM,SAAS,GAAG,CAAC,OAAO,WAAW,CAAC,CAAC,MAAM,CAAC,CAAA;AAEpD,uCAAuC;AACvC,MAAM,MAAM,WAAW,GAAG;IACxB,wCAAwC;IACxC,GAAG,EAAE,MAAM,CAAA;IACX,wEAAwE;IACxE,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,0CAA0C;IAC1C,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,gDAAgD;IAChD,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,qHAAqH;IACrH,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB,CAAA;AAED,sCAAsC;AACtC,MAAM,MAAM,SAAS,GAAG;IACtB,kEAAkE;IAClE,EAAE,EAAE,MAAM,CAAA;IACV,0CAA0C;IAC1C,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,SAAS,CAAA;IACf,gEAAgE;IAChE,OAAO,EAAE,WAAW,EAAE,CAAA;CACvB,CAAA;AAED,+CAA+C;AAC/C,MAAM,MAAM,SAAS,GAAG;IACtB,sBAAsB;IACtB,IAAI,EAAE,MAAM,CAAA;IACZ,sBAAsB;IACtB,EAAE,EAAE,MAAM,CAAA;IACV,4CAA4C;IAC5C,IAAI,CAAC,EAAE,MAAM,CAAA;CACd,CAAA;AAED,kFAAkF;AAClF,MAAM,MAAM,QAAQ,GAAG;IACrB,6BAA6B;IAC7B,QAAQ,EAAE,MAAM,CAAA;IAChB,KAAK,EAAE,SAAS,EAAE,CAAA;IAClB,KAAK,EAAE,SAAS,EAAE,CAAA;CACnB,CAAA;AAED;;;;;;;GAOG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,QAAQ,GAAG,MAAM,EAAE,CAuCxD;AAED;;;;;GAKG;AACH,wBAAgB,SAAS,CAAC,GAAG,EAAE,QAAQ,GAAG,MAAM,EAAE,CAkBjD"}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The industry-chain structure model (`ChainMap`) and its validation. This is
|
|
3
|
+
* a pure data module: no I/O, no clock. A metric is either a sourced value
|
|
4
|
+
* (`value` + `sourceRef`, optionally `unit`/`asOf`) or an explicit gap slot
|
|
5
|
+
* (no `value`), so an unsourced number is a validation error by construction
|
|
6
|
+
* and a missing number is an honest, listable gap.
|
|
7
|
+
* @module dsh-industry-research/chain
|
|
8
|
+
*/
|
|
9
|
+
/** Chain tiers, upstream → downstream. */
|
|
10
|
+
export const CHAIN_TIERS = ['upstream', 'midstream', 'downstream'];
|
|
11
|
+
/**
|
|
12
|
+
* Validate a chain map. Pure: returns the list of problems (empty when the
|
|
13
|
+
* map is well-formed). Rules: unique node ids, legal tiers, edges reference
|
|
14
|
+
* existing nodes, and every metric carrying a `value` also carries a
|
|
15
|
+
* `sourceRef` (gap slots without a value are always legal).
|
|
16
|
+
* @param map - the candidate chain map.
|
|
17
|
+
* @returns human-readable validation problems, in encounter order.
|
|
18
|
+
*/
|
|
19
|
+
export function validateChainMap(map) {
|
|
20
|
+
const problems = [];
|
|
21
|
+
if (typeof map.industry !== 'string' || map.industry.trim().length === 0) {
|
|
22
|
+
problems.push('chain.industry must be a non-empty name');
|
|
23
|
+
}
|
|
24
|
+
const ids = new Set();
|
|
25
|
+
for (const node of map.nodes) {
|
|
26
|
+
if (typeof node.id !== 'string' || node.id.trim().length === 0) {
|
|
27
|
+
problems.push(`node ${JSON.stringify(node.id)} has an empty id`);
|
|
28
|
+
continue;
|
|
29
|
+
}
|
|
30
|
+
if (ids.has(node.id))
|
|
31
|
+
problems.push(`duplicate node id "${node.id}"`);
|
|
32
|
+
ids.add(node.id);
|
|
33
|
+
if (typeof node.name !== 'string' || node.name.trim().length === 0) {
|
|
34
|
+
problems.push(`node "${node.id}" has an empty name`);
|
|
35
|
+
}
|
|
36
|
+
if (!CHAIN_TIERS.includes(node.tier)) {
|
|
37
|
+
problems.push(`node "${node.id}" has an illegal tier ${JSON.stringify(node.tier)} (expected upstream|midstream|downstream)`);
|
|
38
|
+
}
|
|
39
|
+
for (const metric of node.metrics) {
|
|
40
|
+
if (typeof metric.key !== 'string' || metric.key.trim().length === 0) {
|
|
41
|
+
problems.push(`node "${node.id}" has a metric with an empty key`);
|
|
42
|
+
continue;
|
|
43
|
+
}
|
|
44
|
+
if (metric.value !== undefined) {
|
|
45
|
+
if (typeof metric.value !== 'number' || !Number.isFinite(metric.value)) {
|
|
46
|
+
problems.push(`node "${node.id}" metric "${metric.key}" carries a non-finite value`);
|
|
47
|
+
}
|
|
48
|
+
if (typeof metric.sourceRef !== 'string' || metric.sourceRef.trim().length === 0) {
|
|
49
|
+
problems.push(`node "${node.id}" metric "${metric.key}" carries a value without a sourceRef — register the source or mark the slot 待补 (omit value)`);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
for (const edge of map.edges) {
|
|
55
|
+
if (!ids.has(edge.from))
|
|
56
|
+
problems.push(`edge references unknown node "${edge.from}" (from)`);
|
|
57
|
+
if (!ids.has(edge.to))
|
|
58
|
+
problems.push(`edge references unknown node "${edge.to}" (to)`);
|
|
59
|
+
}
|
|
60
|
+
return problems;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* List the explicit gaps of a well-formed chain map: metric slots without a
|
|
64
|
+
* value, nodes without any metric slot, and tiers with no node at all.
|
|
65
|
+
* @param map - the chain map (already validated).
|
|
66
|
+
* @returns human-readable gap lines, in encounter order.
|
|
67
|
+
*/
|
|
68
|
+
export function chainGaps(map) {
|
|
69
|
+
const gaps = [];
|
|
70
|
+
const tiers = new Set();
|
|
71
|
+
for (const node of map.nodes) {
|
|
72
|
+
tiers.add(node.tier);
|
|
73
|
+
if (node.metrics.length === 0) {
|
|
74
|
+
gaps.push(`节点「${node.name}」(${node.id}) 没有任何指标槽位`);
|
|
75
|
+
}
|
|
76
|
+
for (const metric of node.metrics) {
|
|
77
|
+
if (metric.value === undefined) {
|
|
78
|
+
gaps.push(`节点「${node.name}」(${node.id}) 的指标「${metric.key}」待补(无来源数值)`);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
for (const tier of CHAIN_TIERS) {
|
|
83
|
+
if (!tiers.has(tier))
|
|
84
|
+
gaps.push(`产业链缺少 ${tier} 层节点`);
|
|
85
|
+
}
|
|
86
|
+
return gaps;
|
|
87
|
+
}
|
|
88
|
+
//# sourceMappingURL=chain.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chain.js","sourceRoot":"","sources":["../../src/chain.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Company scan support: read user-supplied data files from the workspace,
|
|
3
|
+
* hash them, extract a lightweight outline (Markdown headings) and
|
|
4
|
+
* figure-candidate lines (lines carrying digits, so every number the model
|
|
5
|
+
* cites can point at a file and a line), and persist the scan card
|
|
6
|
+
* (`card.json` + `card.md`). v1 reads text formats only — no PDF.
|
|
7
|
+
* @module dsh-industry-research/company
|
|
8
|
+
*/
|
|
9
|
+
import type { ResolvedConfig } from './config.js';
|
|
10
|
+
/** File extensions v1 can read as text. PDF and office formats are out of scope. */
|
|
11
|
+
export declare const READABLE_EXTENSIONS: Set<string>;
|
|
12
|
+
/** One registered data-file source on a card. */
|
|
13
|
+
export type CardSource = {
|
|
14
|
+
/** Absolute workspace path of the data file. */
|
|
15
|
+
path: string;
|
|
16
|
+
/** SHA-256 of the file content at scan time. */
|
|
17
|
+
sha256: string;
|
|
18
|
+
/** File size in bytes at scan time. */
|
|
19
|
+
bytes: number;
|
|
20
|
+
/** Line count at scan time. */
|
|
21
|
+
lines: number;
|
|
22
|
+
};
|
|
23
|
+
/** One line carrying a digit — a citation anchor for every figure the model quotes. */
|
|
24
|
+
export type FigureCandidate = {
|
|
25
|
+
/** Absolute workspace path of the data file. */
|
|
26
|
+
path: string;
|
|
27
|
+
/** 1-based line number. */
|
|
28
|
+
line: number;
|
|
29
|
+
/** The verbatim line text (trimmed, capped). */
|
|
30
|
+
text: string;
|
|
31
|
+
};
|
|
32
|
+
/** Markdown heading outline of one data file. */
|
|
33
|
+
export type FileOutline = {
|
|
34
|
+
/** Absolute workspace path of the data file. */
|
|
35
|
+
path: string;
|
|
36
|
+
/** Heading texts in document order (`#`/`##`/`###`). */
|
|
37
|
+
headings: string[];
|
|
38
|
+
};
|
|
39
|
+
/** One web citation attached to the card (public-source complement). */
|
|
40
|
+
export type CardWebSource = {
|
|
41
|
+
url: string;
|
|
42
|
+
title?: string;
|
|
43
|
+
snippet?: string;
|
|
44
|
+
publishedAt?: string;
|
|
45
|
+
};
|
|
46
|
+
/** The structured company scan card persisted as `card.json`. */
|
|
47
|
+
export type CompanyCard = {
|
|
48
|
+
/** Company display name. */
|
|
49
|
+
name: string;
|
|
50
|
+
/** Directory slug (validated path segment). */
|
|
51
|
+
slug: string;
|
|
52
|
+
/** ISO-8601 scan time. */
|
|
53
|
+
asOf: string;
|
|
54
|
+
/** Data-file sources with hashes. */
|
|
55
|
+
sources: CardSource[];
|
|
56
|
+
/** Per-file Markdown outlines. */
|
|
57
|
+
outline: FileOutline[];
|
|
58
|
+
/** Lines carrying digits, for precise figure citation. */
|
|
59
|
+
figureCandidates: FigureCandidate[];
|
|
60
|
+
/** Public-source citations from ctx.web; null when the web complement did not run. */
|
|
61
|
+
webSources: CardWebSource[] | null;
|
|
62
|
+
/** Honest gap declarations (what the card could not establish). */
|
|
63
|
+
gaps: string[];
|
|
64
|
+
/** Research-only disclaimer carried into every rendering. */
|
|
65
|
+
disclaimer: string;
|
|
66
|
+
};
|
|
67
|
+
/** The research-only disclaimer text shared by cards and reports. */
|
|
68
|
+
export declare const DISCLAIMER = "\u4EC5\u4F9B\u7814\u7A76\uFF0C\u4E0D\u6784\u6210\u6295\u8D44\u5EFA\u8BAE";
|
|
69
|
+
/** The outcome of reading and extracting one data file. */
|
|
70
|
+
export interface ScannedFile {
|
|
71
|
+
source: CardSource;
|
|
72
|
+
outline: FileOutline | undefined;
|
|
73
|
+
figures: FigureCandidate[];
|
|
74
|
+
/** Verbatim content (for downstream evidence registration). */
|
|
75
|
+
content: string;
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Read one containment-verified data file and extract its outline and figure
|
|
79
|
+
* candidates. Unsupported extensions and unreadable entries throw — the tool
|
|
80
|
+
* wraps them into the card's gap list where the contract allows skipping.
|
|
81
|
+
* @param path - absolute, containment-verified file path.
|
|
82
|
+
* @param maxBytes - per-file read cap.
|
|
83
|
+
* @returns the scanned file.
|
|
84
|
+
*/
|
|
85
|
+
export declare function scanFile(path: string, maxBytes: number): Promise<ScannedFile>;
|
|
86
|
+
/**
|
|
87
|
+
* Persist a company card as `card.json` + `card.md` inside its directory.
|
|
88
|
+
* The Markdown card is a template whose analytical sections stay explicitly
|
|
89
|
+
* 待补 — the tool surfaces evidence (sources, outline, figure candidates); it
|
|
90
|
+
* never invents business structure, financials, or risks.
|
|
91
|
+
* @param dir - absolute company card directory.
|
|
92
|
+
* @param card - the card to persist.
|
|
93
|
+
* @returns the written file paths.
|
|
94
|
+
*/
|
|
95
|
+
export declare function writeCard(dir: string, card: CompanyCard): Promise<{
|
|
96
|
+
cardJsonPath: string;
|
|
97
|
+
cardPath: string;
|
|
98
|
+
}>;
|
|
99
|
+
/**
|
|
100
|
+
* Render the human-facing Markdown card. Every section that the scan could
|
|
101
|
+
* not fill from evidence is an explicit 待补 line, never prose.
|
|
102
|
+
* @param card - the card to render.
|
|
103
|
+
* @returns the Markdown text.
|
|
104
|
+
*/
|
|
105
|
+
export declare function renderCardMarkdown(card: CompanyCard): string;
|
|
106
|
+
/**
|
|
107
|
+
* Load a persisted card (for report assembly). Missing/corrupt cards fail
|
|
108
|
+
* loud to the caller, which decides per-card tolerance.
|
|
109
|
+
* @param cardJsonPath - absolute path of `card.json`.
|
|
110
|
+
* @returns the parsed card.
|
|
111
|
+
*/
|
|
112
|
+
export declare function readCard(cardJsonPath: string): Promise<CompanyCard>;
|
|
113
|
+
/**
|
|
114
|
+
* Apply the figure-candidate budget to a scan result set, keeping files in
|
|
115
|
+
* scan order and noting the cut in the card gaps when it applies.
|
|
116
|
+
* @param figures - all candidates, in scan order.
|
|
117
|
+
* @param config - resolved config (budget source).
|
|
118
|
+
* @returns the bounded candidate list.
|
|
119
|
+
*/
|
|
120
|
+
export declare function boundFigures(figures: readonly FigureCandidate[], config: ResolvedConfig): FigureCandidate[];
|
|
121
|
+
//# sourceMappingURL=company.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"company.d.ts","sourceRoot":"","sources":["../../src/company.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAKH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAA;AAEjD,oFAAoF;AACpF,eAAO,MAAM,mBAAmB,aAAoD,CAAA;AAEpF,iDAAiD;AACjD,MAAM,MAAM,UAAU,GAAG;IACvB,gDAAgD;IAChD,IAAI,EAAE,MAAM,CAAA;IACZ,gDAAgD;IAChD,MAAM,EAAE,MAAM,CAAA;IACd,uCAAuC;IACvC,KAAK,EAAE,MAAM,CAAA;IACb,+BAA+B;IAC/B,KAAK,EAAE,MAAM,CAAA;CACd,CAAA;AAED,uFAAuF;AACvF,MAAM,MAAM,eAAe,GAAG;IAC5B,gDAAgD;IAChD,IAAI,EAAE,MAAM,CAAA;IACZ,2BAA2B;IAC3B,IAAI,EAAE,MAAM,CAAA;IACZ,gDAAgD;IAChD,IAAI,EAAE,MAAM,CAAA;CACb,CAAA;AAED,iDAAiD;AACjD,MAAM,MAAM,WAAW,GAAG;IACxB,gDAAgD;IAChD,IAAI,EAAE,MAAM,CAAA;IACZ,wDAAwD;IACxD,QAAQ,EAAE,MAAM,EAAE,CAAA;CACnB,CAAA;AAED,wEAAwE;AACxE,MAAM,MAAM,aAAa,GAAG;IAC1B,GAAG,EAAE,MAAM,CAAA;IACX,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,WAAW,CAAC,EAAE,MAAM,CAAA;CACrB,CAAA;AAED,iEAAiE;AACjE,MAAM,MAAM,WAAW,GAAG;IACxB,4BAA4B;IAC5B,IAAI,EAAE,MAAM,CAAA;IACZ,+CAA+C;IAC/C,IAAI,EAAE,MAAM,CAAA;IACZ,0BAA0B;IAC1B,IAAI,EAAE,MAAM,CAAA;IACZ,qCAAqC;IACrC,OAAO,EAAE,UAAU,EAAE,CAAA;IACrB,kCAAkC;IAClC,OAAO,EAAE,WAAW,EAAE,CAAA;IACtB,0DAA0D;IAC1D,gBAAgB,EAAE,eAAe,EAAE,CAAA;IACnC,sFAAsF;IACtF,UAAU,EAAE,aAAa,EAAE,GAAG,IAAI,CAAA;IAClC,mEAAmE;IACnE,IAAI,EAAE,MAAM,EAAE,CAAA;IACd,6DAA6D;IAC7D,UAAU,EAAE,MAAM,CAAA;CACnB,CAAA;AAED,qEAAqE;AACrE,eAAO,MAAM,UAAU,6EAAiB,CAAA;AAOxC,2DAA2D;AAC3D,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,UAAU,CAAA;IAClB,OAAO,EAAE,WAAW,GAAG,SAAS,CAAA;IAChC,OAAO,EAAE,eAAe,EAAE,CAAA;IAC1B,+DAA+D;IAC/D,OAAO,EAAE,MAAM,CAAA;CAChB;AAED;;;;;;;GAOG;AACH,wBAAsB,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,CA+BnF;AAED;;;;;;;;GAQG;AACH,wBAAsB,SAAS,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,WAAW,GAAG,OAAO,CAAC;IAAE,YAAY,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,CAAC,CAOnH;AAED;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,WAAW,GAAG,MAAM,CAoD5D;AAED;;;;;GAKG;AACH,wBAAsB,QAAQ,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,CAOzE;AAED;;;;;;GAMG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,SAAS,eAAe,EAAE,EAAE,MAAM,EAAE,cAAc,GAAG,eAAe,EAAE,CAE3G"}
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Company scan support: read user-supplied data files from the workspace,
|
|
3
|
+
* hash them, extract a lightweight outline (Markdown headings) and
|
|
4
|
+
* figure-candidate lines (lines carrying digits, so every number the model
|
|
5
|
+
* cites can point at a file and a line), and persist the scan card
|
|
6
|
+
* (`card.json` + `card.md`). v1 reads text formats only — no PDF.
|
|
7
|
+
* @module dsh-industry-research/company
|
|
8
|
+
*/
|
|
9
|
+
import { readFile, writeFile, mkdir, stat } from 'node:fs/promises';
|
|
10
|
+
import { extname, join } from 'node:path';
|
|
11
|
+
import { sha256Of } from "./sources.js";
|
|
12
|
+
/** File extensions v1 can read as text. PDF and office formats are out of scope. */
|
|
13
|
+
export const READABLE_EXTENSIONS = new Set(['.md', '.txt', '.csv', '.tsv', '.json']);
|
|
14
|
+
/** The research-only disclaimer text shared by cards and reports. */
|
|
15
|
+
export const DISCLAIMER = '仅供研究,不构成投资建议';
|
|
16
|
+
/** Maximum length of one surfaced figure-candidate line. */
|
|
17
|
+
const FIGURE_LINE_CAP = 200;
|
|
18
|
+
/** Maximum headings surfaced per file. */
|
|
19
|
+
const OUTLINE_CAP = 50;
|
|
20
|
+
/**
|
|
21
|
+
* Read one containment-verified data file and extract its outline and figure
|
|
22
|
+
* candidates. Unsupported extensions and unreadable entries throw — the tool
|
|
23
|
+
* wraps them into the card's gap list where the contract allows skipping.
|
|
24
|
+
* @param path - absolute, containment-verified file path.
|
|
25
|
+
* @param maxBytes - per-file read cap.
|
|
26
|
+
* @returns the scanned file.
|
|
27
|
+
*/
|
|
28
|
+
export async function scanFile(path, maxBytes) {
|
|
29
|
+
const ext = extname(path).toLowerCase();
|
|
30
|
+
if (!READABLE_EXTENSIONS.has(ext)) {
|
|
31
|
+
throw new Error(`unsupported data-file extension ${JSON.stringify(ext)} (v1 reads ${[...READABLE_EXTENSIONS].join(', ')}; PDF is out of scope)`);
|
|
32
|
+
}
|
|
33
|
+
const info = await stat(path);
|
|
34
|
+
if (!info.isFile())
|
|
35
|
+
throw new Error(`not a regular file: ${path}`);
|
|
36
|
+
if (info.size > maxBytes) {
|
|
37
|
+
throw new Error(`file exceeds scan.maxFileBytes (${info.size} > ${maxBytes}): ${path}`);
|
|
38
|
+
}
|
|
39
|
+
const content = await readFile(path, 'utf8');
|
|
40
|
+
const lines = content.split('\n');
|
|
41
|
+
const headings = [];
|
|
42
|
+
const figures = [];
|
|
43
|
+
if (ext === '.md') {
|
|
44
|
+
for (const line of lines) {
|
|
45
|
+
const match = /^#{1,3}\s+(.+?)\s*$/u.exec(line);
|
|
46
|
+
if (match?.[1] !== undefined && headings.length < OUTLINE_CAP)
|
|
47
|
+
headings.push(match[1]);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
lines.forEach((raw, index) => {
|
|
51
|
+
const text = raw.trim();
|
|
52
|
+
if (text.length === 0 || !/\d/u.test(text))
|
|
53
|
+
return;
|
|
54
|
+
figures.push({ path, line: index + 1, text: text.length > FIGURE_LINE_CAP ? `${text.slice(0, FIGURE_LINE_CAP)}…` : text });
|
|
55
|
+
});
|
|
56
|
+
return {
|
|
57
|
+
source: { path, sha256: sha256Of(content), bytes: info.size, lines: lines.length },
|
|
58
|
+
outline: headings.length > 0 ? { path, headings } : undefined,
|
|
59
|
+
figures,
|
|
60
|
+
content,
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Persist a company card as `card.json` + `card.md` inside its directory.
|
|
65
|
+
* The Markdown card is a template whose analytical sections stay explicitly
|
|
66
|
+
* 待补 — the tool surfaces evidence (sources, outline, figure candidates); it
|
|
67
|
+
* never invents business structure, financials, or risks.
|
|
68
|
+
* @param dir - absolute company card directory.
|
|
69
|
+
* @param card - the card to persist.
|
|
70
|
+
* @returns the written file paths.
|
|
71
|
+
*/
|
|
72
|
+
export async function writeCard(dir, card) {
|
|
73
|
+
await mkdir(dir, { recursive: true });
|
|
74
|
+
const cardJsonPath = join(dir, 'card.json');
|
|
75
|
+
const cardPath = join(dir, 'card.md');
|
|
76
|
+
await writeFile(cardJsonPath, `${JSON.stringify(card, null, 2)}\n`, 'utf8');
|
|
77
|
+
await writeFile(cardPath, renderCardMarkdown(card), 'utf8');
|
|
78
|
+
return { cardJsonPath, cardPath };
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Render the human-facing Markdown card. Every section that the scan could
|
|
82
|
+
* not fill from evidence is an explicit 待补 line, never prose.
|
|
83
|
+
* @param card - the card to render.
|
|
84
|
+
* @returns the Markdown text.
|
|
85
|
+
*/
|
|
86
|
+
export function renderCardMarkdown(card) {
|
|
87
|
+
const lines = [
|
|
88
|
+
`# 公司速览卡:${card.name}`,
|
|
89
|
+
'',
|
|
90
|
+
`> ${card.disclaimer}。扫描时间(asOf):${card.asOf}`,
|
|
91
|
+
'',
|
|
92
|
+
'## 业务结构',
|
|
93
|
+
'',
|
|
94
|
+
];
|
|
95
|
+
if (card.outline.length > 0) {
|
|
96
|
+
lines.push('数据文件目录结构(供研究定位,非分析结论):');
|
|
97
|
+
for (const outline of card.outline) {
|
|
98
|
+
lines.push(`- \`${outline.path}\``);
|
|
99
|
+
for (const heading of outline.headings)
|
|
100
|
+
lines.push(` - ${heading}`);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
else {
|
|
104
|
+
lines.push('待补:未从数据文件中提取到目录结构。');
|
|
105
|
+
}
|
|
106
|
+
lines.push('', '## 财务要点', '');
|
|
107
|
+
if (card.figureCandidates.length > 0) {
|
|
108
|
+
lines.push(`数字候选行(共 ${card.figureCandidates.length} 行,引用时必须标注文件与行号):`);
|
|
109
|
+
for (const figure of card.figureCandidates.slice(0, 20)) {
|
|
110
|
+
lines.push(`- \`${figure.path}\`:${figure.line} — ${figure.text}`);
|
|
111
|
+
}
|
|
112
|
+
if (card.figureCandidates.length > 20)
|
|
113
|
+
lines.push(`- ……其余 ${card.figureCandidates.length - 20} 行见 card.json`);
|
|
114
|
+
}
|
|
115
|
+
else {
|
|
116
|
+
lines.push('待补:数据文件中未发现数字行。');
|
|
117
|
+
}
|
|
118
|
+
lines.push('', '## 风险点', '', '待补:由研究者基于来源材料归纳;不得凭空列举。', '', '## 来源清单', '');
|
|
119
|
+
if (card.sources.length > 0) {
|
|
120
|
+
for (const source of card.sources) {
|
|
121
|
+
lines.push(`- \`${source.path}\` — SHA-256 \`${source.sha256}\`,${source.bytes} 字节,${source.lines} 行`);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
else {
|
|
125
|
+
lines.push('无用户提供的数据文件。');
|
|
126
|
+
}
|
|
127
|
+
if (card.webSources !== null) {
|
|
128
|
+
lines.push('', '公开源检索(ctx.web):');
|
|
129
|
+
for (const source of card.webSources) {
|
|
130
|
+
const label = source.title ?? source.url;
|
|
131
|
+
const when = source.publishedAt !== undefined ? `(${source.publishedAt})` : '';
|
|
132
|
+
lines.push(`- [${label}](${source.url})${when}`);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
lines.push('', '## 缺口声明', '');
|
|
136
|
+
if (card.gaps.length > 0) {
|
|
137
|
+
for (const gap of card.gaps)
|
|
138
|
+
lines.push(`- ${gap}`);
|
|
139
|
+
}
|
|
140
|
+
else {
|
|
141
|
+
lines.push('无。');
|
|
142
|
+
}
|
|
143
|
+
lines.push('');
|
|
144
|
+
return lines.join('\n');
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* Load a persisted card (for report assembly). Missing/corrupt cards fail
|
|
148
|
+
* loud to the caller, which decides per-card tolerance.
|
|
149
|
+
* @param cardJsonPath - absolute path of `card.json`.
|
|
150
|
+
* @returns the parsed card.
|
|
151
|
+
*/
|
|
152
|
+
export async function readCard(cardJsonPath) {
|
|
153
|
+
const text = await readFile(cardJsonPath, 'utf8');
|
|
154
|
+
const parsed = JSON.parse(text);
|
|
155
|
+
if (typeof parsed.name !== 'string' || !Array.isArray(parsed.sources) || !Array.isArray(parsed.gaps)) {
|
|
156
|
+
throw new Error(`company card at ${cardJsonPath} is malformed`);
|
|
157
|
+
}
|
|
158
|
+
return parsed;
|
|
159
|
+
}
|
|
160
|
+
/**
|
|
161
|
+
* Apply the figure-candidate budget to a scan result set, keeping files in
|
|
162
|
+
* scan order and noting the cut in the card gaps when it applies.
|
|
163
|
+
* @param figures - all candidates, in scan order.
|
|
164
|
+
* @param config - resolved config (budget source).
|
|
165
|
+
* @returns the bounded candidate list.
|
|
166
|
+
*/
|
|
167
|
+
export function boundFigures(figures, config) {
|
|
168
|
+
return figures.slice(0, config.scan.maxFigureCandidates);
|
|
169
|
+
}
|
|
170
|
+
//# sourceMappingURL=company.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"company.js","sourceRoot":"","sources":["../../src/company.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAA;AACnE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;AACzC,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAA;AAGvC,oFAAoF;AACpF,MAAM,CAAC,MAAM,mBAAmB,GAAG,IAAI,GAAG,CAAC,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC,CAAA;AA8DpF,qEAAqE;AACrE,MAAM,CAAC,MAAM,UAAU,GAAG,cAAc,CAAA;AAExC,4DAA4D;AAC5D,MAAM,eAAe,GAAG,GAAG,CAAA;AAC3B,0CAA0C;AAC1C,MAAM,WAAW,GAAG,EAAE,CAAA;AAWtB;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,QAAQ,CAAC,IAAY,EAAE,QAAgB;IAC3D,MAAM,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,WAAW,EAAE,CAAA;IACvC,IAAI,CAAC,mBAAmB,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;QAClC,MAAM,IAAI,KAAK,CAAC,mCAAmC,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,cAAc,CAAC,GAAG,mBAAmB,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,wBAAwB,CAAC,CAAA;IAClJ,CAAC;IACD,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,CAAA;IAC7B,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE;QAAE,MAAM,IAAI,KAAK,CAAC,uBAAuB,IAAI,EAAE,CAAC,CAAA;IAClE,IAAI,IAAI,CAAC,IAAI,GAAG,QAAQ,EAAE,CAAC;QACzB,MAAM,IAAI,KAAK,CAAC,mCAAmC,IAAI,CAAC,IAAI,MAAM,QAAQ,MAAM,IAAI,EAAE,CAAC,CAAA;IACzF,CAAC;IACD,MAAM,OAAO,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC,CAAA;IAC5C,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAA;IACjC,MAAM,QAAQ,GAAa,EAAE,CAAA;IAC7B,MAAM,OAAO,GAAsB,EAAE,CAAA;IACrC,IAAI,GAAG,KAAK,KAAK,EAAE,CAAC;QAClB,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACzB,MAAM,KAAK,GAAG,sBAAsB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;YAC/C,IAAI,KAAK,EAAE,CAAC,CAAC,CAAC,KAAK,SAAS,IAAI,QAAQ,CAAC,MAAM,GAAG,WAAW;gBAAE,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAA;QACxF,CAAC;IACH,CAAC;IACD,KAAK,CAAC,OAAO,CAAC,CAAC,GAAG,EAAE,KAAK,EAAE,EAAE;QAC3B,MAAM,IAAI,GAAG,GAAG,CAAC,IAAI,EAAE,CAAA;QACvB,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC;YAAE,OAAM;QAClD,OAAO,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,GAAG,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,MAAM,GAAG,eAAe,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,eAAe,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAA;IAC5H,CAAC,CAAC,CAAA;IACF,OAAO;QACL,MAAM,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,CAAC,OAAO,CAAC,EAAE,KAAK,EAAE,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE,KAAK,CAAC,MAAM,EAAE;QAClF,OAAO,EAAE,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC,CAAC,CAAC,SAAS;QAC7D,OAAO;QACP,OAAO;KACR,CAAA;AACH,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,GAAW,EAAE,IAAiB;IAC5D,MAAM,KAAK,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAA;IACrC,MAAM,YAAY,GAAG,IAAI,CAAC,GAAG,EAAE,WAAW,CAAC,CAAA;IAC3C,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,EAAE,SAAS,CAAC,CAAA;IACrC,MAAM,SAAS,CAAC,YAAY,EAAE,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,MAAM,CAAC,CAAA;IAC3E,MAAM,SAAS,CAAC,QAAQ,EAAE,kBAAkB,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC,CAAA;IAC3D,OAAO,EAAE,YAAY,EAAE,QAAQ,EAAE,CAAA;AACnC,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,kBAAkB,CAAC,IAAiB;IAClD,MAAM,KAAK,GAAa;QACtB,WAAW,IAAI,CAAC,IAAI,EAAE;QACtB,EAAE;QACF,KAAK,IAAI,CAAC,UAAU,eAAe,IAAI,CAAC,IAAI,EAAE;QAC9C,EAAE;QACF,SAAS;QACT,EAAE;KACH,CAAA;IACD,IAAI,IAAI,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC5B,KAAK,CAAC,IAAI,CAAC,wBAAwB,CAAC,CAAA;QACpC,KAAK,MAAM,OAAO,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;YACnC,KAAK,CAAC,IAAI,CAAC,OAAO,OAAO,CAAC,IAAI,IAAI,CAAC,CAAA;YACnC,KAAK,MAAM,OAAO,IAAI,OAAO,CAAC,QAAQ;gBAAE,KAAK,CAAC,IAAI,CAAC,OAAO,OAAO,EAAE,CAAC,CAAA;QACtE,CAAC;IACH,CAAC;SAAM,CAAC;QACN,KAAK,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAA;IAClC,CAAC;IACD,KAAK,CAAC,IAAI,CAAC,EAAE,EAAE,SAAS,EAAE,EAAE,CAAC,CAAA;IAC7B,IAAI,IAAI,CAAC,gBAAgB,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACrC,KAAK,CAAC,IAAI,CAAC,WAAW,IAAI,CAAC,gBAAgB,CAAC,MAAM,mBAAmB,CAAC,CAAA;QACtE,KAAK,MAAM,MAAM,IAAI,IAAI,CAAC,gBAAgB,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC;YACxD,KAAK,CAAC,IAAI,CAAC,OAAO,MAAM,CAAC,IAAI,MAAM,MAAM,CAAC,IAAI,MAAM,MAAM,CAAC,IAAI,EAAE,CAAC,CAAA;QACpE,CAAC;QACD,IAAI,IAAI,CAAC,gBAAgB,CAAC,MAAM,GAAG,EAAE;YAAE,KAAK,CAAC,IAAI,CAAC,UAAU,IAAI,CAAC,gBAAgB,CAAC,MAAM,GAAG,EAAE,eAAe,CAAC,CAAA;IAC/G,CAAC;SAAM,CAAC;QACN,KAAK,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAA;IAC/B,CAAC;IACD,KAAK,CAAC,IAAI,CAAC,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,yBAAyB,EAAE,EAAE,EAAE,SAAS,EAAE,EAAE,CAAC,CAAA;IAC1E,IAAI,IAAI,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC5B,KAAK,MAAM,MAAM,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;YAClC,KAAK,CAAC,IAAI,CAAC,OAAO,MAAM,CAAC,IAAI,kBAAkB,MAAM,CAAC,MAAM,MAAM,MAAM,CAAC,KAAK,OAAO,MAAM,CAAC,KAAK,IAAI,CAAC,CAAA;QACxG,CAAC;IACH,CAAC;SAAM,CAAC;QACN,KAAK,CAAC,IAAI,CAAC,aAAa,CAAC,CAAA;IAC3B,CAAC;IACD,IAAI,IAAI,CAAC,UAAU,KAAK,IAAI,EAAE,CAAC;QAC7B,KAAK,CAAC,IAAI,CAAC,EAAE,EAAE,iBAAiB,CAAC,CAAA;QACjC,KAAK,MAAM,MAAM,IAAI,IAAI,CAAC,UAAU,EAAE,CAAC;YACrC,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,IAAI,MAAM,CAAC,GAAG,CAAA;YACxC,MAAM,IAAI,GAAG,MAAM,CAAC,WAAW,KAAK,SAAS,CAAC,CAAC,CAAC,IAAI,MAAM,CAAC,WAAW,GAAG,CAAC,CAAC,CAAC,EAAE,CAAA;YAC9E,KAAK,CAAC,IAAI,CAAC,MAAM,KAAK,KAAK,MAAM,CAAC,GAAG,IAAI,IAAI,EAAE,CAAC,CAAA;QAClD,CAAC;IACH,CAAC;IACD,KAAK,CAAC,IAAI,CAAC,EAAE,EAAE,SAAS,EAAE,EAAE,CAAC,CAAA;IAC7B,IAAI,IAAI,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACzB,KAAK,MAAM,GAAG,IAAI,IAAI,CAAC,IAAI;YAAE,KAAK,CAAC,IAAI,CAAC,KAAK,GAAG,EAAE,CAAC,CAAA;IACrD,CAAC;SAAM,CAAC;QACN,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;IAClB,CAAC;IACD,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;IACd,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;AACzB,CAAC;AAED;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,QAAQ,CAAC,YAAoB;IACjD,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC,CAAA;IACjD,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAgB,CAAA;IAC9C,IAAI,OAAO,MAAM,CAAC,IAAI,KAAK,QAAQ,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC;QACrG,MAAM,IAAI,KAAK,CAAC,mBAAmB,YAAY,eAAe,CAAC,CAAA;IACjE,CAAC;IACD,OAAO,MAAM,CAAA;AACf,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,YAAY,CAAC,OAAmC,EAAE,MAAsB;IACtF,OAAO,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,MAAM,CAAC,IAAI,CAAC,mBAAmB,CAAC,CAAA;AAC1D,CAAC"}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Config schema and resolution for `dsh-industry-research`. Every tunable is a
|
|
3
|
+
* validated {@link Config} field changeable from cordis.yml; the resolution
|
|
4
|
+
* step validates bounds so misconfiguration fails loud at mount. With
|
|
5
|
+
* `enabled: false` the plugin registers nothing and stays inert.
|
|
6
|
+
* @module dsh-industry-research/config
|
|
7
|
+
*/
|
|
8
|
+
import z from '@deepseek-ai/schemastery';
|
|
9
|
+
/** Public-source tracking bounds. */
|
|
10
|
+
export interface TrackConfig {
|
|
11
|
+
/** `web_search` maxResults per topic. */
|
|
12
|
+
maxResultsPerTopic?: number;
|
|
13
|
+
/** Maximum snapshot fetches per `industry_track` call; sources beyond the budget stay citation-only entries. */
|
|
14
|
+
maxFetchesPerCall?: number;
|
|
15
|
+
}
|
|
16
|
+
/** Company scan bounds. */
|
|
17
|
+
export interface ScanConfig {
|
|
18
|
+
/** Maximum bytes read per user-supplied data file. */
|
|
19
|
+
maxFileBytes?: number;
|
|
20
|
+
/** Maximum figure-candidate lines surfaced per company scan. */
|
|
21
|
+
maxFigureCandidates?: number;
|
|
22
|
+
}
|
|
23
|
+
/** Raw plugin config — every field optional; {@link resolveConfig} supplies the defaults. */
|
|
24
|
+
export interface Config {
|
|
25
|
+
/** Master switch; `false` mounts nothing. */
|
|
26
|
+
enabled?: boolean;
|
|
27
|
+
/** Root directory (relative to the session workspace, or absolute) holding every industry artifact. */
|
|
28
|
+
industryRoot?: string;
|
|
29
|
+
/** Per-request timeout (ms) applied to `ctx.web` search/fetch calls. */
|
|
30
|
+
fetchTimeoutMs?: number;
|
|
31
|
+
/** Maximum entries retained per industry `timeline.jsonl` (oldest dropped). */
|
|
32
|
+
timelineMaxEntries?: number;
|
|
33
|
+
/** Host allowlist for tracked sources (empty = all hosts allowed). Entries are host suffixes (`gov.cn`) or URL prefixes (`https://www.gov.cn/`). */
|
|
34
|
+
sourceAllowlist?: string[];
|
|
35
|
+
/** Host blocklist for tracked sources; wins over the allowlist. */
|
|
36
|
+
sourceBlocklist?: string[];
|
|
37
|
+
/** Offline mode: never touch `ctx.web`; only local workspace data is used. */
|
|
38
|
+
offline?: boolean;
|
|
39
|
+
/** Explicit skills root override; defaults to the packaged `skills/` edition. */
|
|
40
|
+
skillsDir?: string;
|
|
41
|
+
track?: TrackConfig;
|
|
42
|
+
scan?: ScanConfig;
|
|
43
|
+
}
|
|
44
|
+
/** Fully resolved config handed to the runtime. */
|
|
45
|
+
export interface ResolvedConfig {
|
|
46
|
+
readonly enabled: boolean;
|
|
47
|
+
readonly industryRoot: string;
|
|
48
|
+
readonly fetchTimeoutMs: number;
|
|
49
|
+
readonly timelineMaxEntries: number;
|
|
50
|
+
readonly sourceAllowlist: readonly string[];
|
|
51
|
+
readonly sourceBlocklist: readonly string[];
|
|
52
|
+
readonly offline: boolean;
|
|
53
|
+
readonly skillsDir: string | undefined;
|
|
54
|
+
readonly track: {
|
|
55
|
+
readonly maxResultsPerTopic: number;
|
|
56
|
+
readonly maxFetchesPerCall: number;
|
|
57
|
+
};
|
|
58
|
+
readonly scan: {
|
|
59
|
+
readonly maxFileBytes: number;
|
|
60
|
+
readonly maxFigureCandidates: number;
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
/** Schemastery schema: the loader validates and fills defaults before `apply`. */
|
|
64
|
+
export declare const Config: z<Config>;
|
|
65
|
+
/**
|
|
66
|
+
* Validate raw values and fill explicit defaults. Invalid bounds throw here —
|
|
67
|
+
* misconfiguration fails loud at mount even without the Schemastery loader.
|
|
68
|
+
* @param config - raw (possibly partial) plugin config.
|
|
69
|
+
* @returns the fully resolved config.
|
|
70
|
+
*/
|
|
71
|
+
export declare function resolveConfig(config?: Config): ResolvedConfig;
|
|
72
|
+
//# sourceMappingURL=config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/config.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,CAAC,MAAM,0BAA0B,CAAA;AAExC,qCAAqC;AACrC,MAAM,WAAW,WAAW;IAC1B,yCAAyC;IACzC,kBAAkB,CAAC,EAAE,MAAM,CAAA;IAC3B,gHAAgH;IAChH,iBAAiB,CAAC,EAAE,MAAM,CAAA;CAC3B;AAED,2BAA2B;AAC3B,MAAM,WAAW,UAAU;IACzB,sDAAsD;IACtD,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,gEAAgE;IAChE,mBAAmB,CAAC,EAAE,MAAM,CAAA;CAC7B;AAED,6FAA6F;AAC7F,MAAM,WAAW,MAAM;IACrB,6CAA6C;IAC7C,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,uGAAuG;IACvG,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,wEAAwE;IACxE,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,+EAA+E;IAC/E,kBAAkB,CAAC,EAAE,MAAM,CAAA;IAC3B,oJAAoJ;IACpJ,eAAe,CAAC,EAAE,MAAM,EAAE,CAAA;IAC1B,mEAAmE;IACnE,eAAe,CAAC,EAAE,MAAM,EAAE,CAAA;IAC1B,8EAA8E;IAC9E,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,iFAAiF;IACjF,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,KAAK,CAAC,EAAE,WAAW,CAAA;IACnB,IAAI,CAAC,EAAE,UAAU,CAAA;CAClB;AAED,mDAAmD;AACnD,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAA;IACzB,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAA;IAC7B,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAA;IAC/B,QAAQ,CAAC,kBAAkB,EAAE,MAAM,CAAA;IACnC,QAAQ,CAAC,eAAe,EAAE,SAAS,MAAM,EAAE,CAAA;IAC3C,QAAQ,CAAC,eAAe,EAAE,SAAS,MAAM,EAAE,CAAA;IAC3C,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAA;IACzB,QAAQ,CAAC,SAAS,EAAE,MAAM,GAAG,SAAS,CAAA;IACtC,QAAQ,CAAC,KAAK,EAAE;QACd,QAAQ,CAAC,kBAAkB,EAAE,MAAM,CAAA;QACnC,QAAQ,CAAC,iBAAiB,EAAE,MAAM,CAAA;KACnC,CAAA;IACD,QAAQ,CAAC,IAAI,EAAE;QACb,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAA;QAC7B,QAAQ,CAAC,mBAAmB,EAAE,MAAM,CAAA;KACrC,CAAA;CACF;AAED,kFAAkF;AAClF,eAAO,MAAM,MAAM,EAAE,CAAC,CAAC,MAAM,CAiB3B,CAAA;AAkBF;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,MAAM,GAAE,MAAW,GAAG,cAAc,CA2CjE"}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Config schema and resolution for `dsh-industry-research`. Every tunable is a
|
|
3
|
+
* validated {@link Config} field changeable from cordis.yml; the resolution
|
|
4
|
+
* step validates bounds so misconfiguration fails loud at mount. With
|
|
5
|
+
* `enabled: false` the plugin registers nothing and stays inert.
|
|
6
|
+
* @module dsh-industry-research/config
|
|
7
|
+
*/
|
|
8
|
+
import z from '@deepseek-ai/schemastery';
|
|
9
|
+
/** Schemastery schema: the loader validates and fills defaults before `apply`. */
|
|
10
|
+
export const Config = z.object({
|
|
11
|
+
enabled: z.boolean().default(true),
|
|
12
|
+
industryRoot: z.string().default('industry-research'),
|
|
13
|
+
fetchTimeoutMs: z.number().default(20_000),
|
|
14
|
+
timelineMaxEntries: z.number().default(500),
|
|
15
|
+
sourceAllowlist: z.array(z.string()).default([]),
|
|
16
|
+
sourceBlocklist: z.array(z.string()).default([]),
|
|
17
|
+
offline: z.boolean().default(false),
|
|
18
|
+
skillsDir: z.string(),
|
|
19
|
+
track: z.object({
|
|
20
|
+
maxResultsPerTopic: z.number().default(10),
|
|
21
|
+
maxFetchesPerCall: z.number().default(10),
|
|
22
|
+
}).default({ maxResultsPerTopic: 10, maxFetchesPerCall: 10 }),
|
|
23
|
+
scan: z.object({
|
|
24
|
+
maxFileBytes: z.number().default(1_048_576),
|
|
25
|
+
maxFigureCandidates: z.number().default(100),
|
|
26
|
+
}).default({ maxFileBytes: 1_048_576, maxFigureCandidates: 100 }),
|
|
27
|
+
});
|
|
28
|
+
/** Throw unless `value` is a positive safe integer. */
|
|
29
|
+
function assertPositiveInt(name, value) {
|
|
30
|
+
if (!Number.isSafeInteger(value) || value <= 0) {
|
|
31
|
+
throw new TypeError(`${name} must be a positive safe integer, got ${String(value)}`);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
/** Throw unless every entry is a non-empty string. */
|
|
35
|
+
function assertStringList(name, value) {
|
|
36
|
+
for (const entry of value) {
|
|
37
|
+
if (typeof entry !== 'string' || entry.trim().length === 0) {
|
|
38
|
+
throw new TypeError(`${name} entries must be non-empty strings, got ${JSON.stringify(entry)}`);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Validate raw values and fill explicit defaults. Invalid bounds throw here —
|
|
44
|
+
* misconfiguration fails loud at mount even without the Schemastery loader.
|
|
45
|
+
* @param config - raw (possibly partial) plugin config.
|
|
46
|
+
* @returns the fully resolved config.
|
|
47
|
+
*/
|
|
48
|
+
export function resolveConfig(config = {}) {
|
|
49
|
+
const industryRoot = config.industryRoot ?? 'industry-research';
|
|
50
|
+
if (typeof industryRoot !== 'string' || industryRoot.trim().length === 0) {
|
|
51
|
+
throw new TypeError('industryRoot must be a non-empty path');
|
|
52
|
+
}
|
|
53
|
+
const fetchTimeoutMs = config.fetchTimeoutMs ?? 20_000;
|
|
54
|
+
assertPositiveInt('fetchTimeoutMs', fetchTimeoutMs);
|
|
55
|
+
const timelineMaxEntries = config.timelineMaxEntries ?? 500;
|
|
56
|
+
assertPositiveInt('timelineMaxEntries', timelineMaxEntries);
|
|
57
|
+
const sourceAllowlist = config.sourceAllowlist ?? [];
|
|
58
|
+
assertStringList('sourceAllowlist', sourceAllowlist);
|
|
59
|
+
const sourceBlocklist = config.sourceBlocklist ?? [];
|
|
60
|
+
assertStringList('sourceBlocklist', sourceBlocklist);
|
|
61
|
+
const skillsDir = config.skillsDir;
|
|
62
|
+
if (skillsDir !== undefined && (typeof skillsDir !== 'string' || skillsDir.trim().length === 0)) {
|
|
63
|
+
throw new TypeError('skillsDir must be a non-empty path when set');
|
|
64
|
+
}
|
|
65
|
+
const maxResultsPerTopic = config.track?.maxResultsPerTopic ?? 10;
|
|
66
|
+
assertPositiveInt('track.maxResultsPerTopic', maxResultsPerTopic);
|
|
67
|
+
const maxFetchesPerCall = config.track?.maxFetchesPerCall ?? 10;
|
|
68
|
+
assertPositiveInt('track.maxFetchesPerCall', maxFetchesPerCall);
|
|
69
|
+
const maxFileBytes = config.scan?.maxFileBytes ?? 1_048_576;
|
|
70
|
+
assertPositiveInt('scan.maxFileBytes', maxFileBytes);
|
|
71
|
+
const maxFigureCandidates = config.scan?.maxFigureCandidates ?? 100;
|
|
72
|
+
assertPositiveInt('scan.maxFigureCandidates', maxFigureCandidates);
|
|
73
|
+
return {
|
|
74
|
+
enabled: config.enabled ?? true,
|
|
75
|
+
industryRoot,
|
|
76
|
+
fetchTimeoutMs,
|
|
77
|
+
timelineMaxEntries,
|
|
78
|
+
sourceAllowlist,
|
|
79
|
+
sourceBlocklist,
|
|
80
|
+
offline: config.offline ?? false,
|
|
81
|
+
skillsDir,
|
|
82
|
+
track: { maxResultsPerTopic, maxFetchesPerCall },
|
|
83
|
+
scan: { maxFileBytes, maxFigureCandidates },
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/config.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,CAAC,MAAM,0BAA0B,CAAA;AA4DxC,kFAAkF;AAClF,MAAM,CAAC,MAAM,MAAM,GAAc,CAAC,CAAC,MAAM,CAAC;IACxC,OAAO,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC;IAClC,YAAY,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,mBAAmB,CAAC;IACrD,cAAc,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC;IAC1C,kBAAkB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC;IAC3C,eAAe,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC;IAChD,eAAe,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC;IAChD,OAAO,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC;IACnC,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE;IACrB,KAAK,EAAE,CAAC,CAAC,MAAM,CAAC;QACd,kBAAkB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC;QAC1C,iBAAiB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC;KAC1C,CAAC,CAAC,OAAO,CAAC,EAAE,kBAAkB,EAAE,EAAE,EAAE,iBAAiB,EAAE,EAAE,EAAE,CAAC;IAC7D,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC;QACb,YAAY,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,SAAS,CAAC;QAC3C,mBAAmB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC;KAC7C,CAAC,CAAC,OAAO,CAAC,EAAE,YAAY,EAAE,SAAS,EAAE,mBAAmB,EAAE,GAAG,EAAE,CAAC;CAClE,CAAC,CAAA;AAEF,uDAAuD;AACvD,SAAS,iBAAiB,CAAC,IAAY,EAAE,KAAa;IACpD,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,KAAK,CAAC,IAAI,KAAK,IAAI,CAAC,EAAE,CAAC;QAC/C,MAAM,IAAI,SAAS,CAAC,GAAG,IAAI,yCAAyC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAA;IACtF,CAAC;AACH,CAAC;AAED,sDAAsD;AACtD,SAAS,gBAAgB,CAAC,IAAY,EAAE,KAAwB;IAC9D,KAAK,MAAM,KAAK,IAAI,KAAK,EAAE,CAAC;QAC1B,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,IAAI,EAAE,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC3D,MAAM,IAAI,SAAS,CAAC,GAAG,IAAI,2CAA2C,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,CAAC,CAAA;QAChG,CAAC;IACH,CAAC;AACH,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,aAAa,CAAC,SAAiB,EAAE;IAC/C,MAAM,YAAY,GAAG,MAAM,CAAC,YAAY,IAAI,mBAAmB,CAAA;IAC/D,IAAI,OAAO,YAAY,KAAK,QAAQ,IAAI,YAAY,CAAC,IAAI,EAAE,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACzE,MAAM,IAAI,SAAS,CAAC,uCAAuC,CAAC,CAAA;IAC9D,CAAC;IAED,MAAM,cAAc,GAAG,MAAM,CAAC,cAAc,IAAI,MAAM,CAAA;IACtD,iBAAiB,CAAC,gBAAgB,EAAE,cAAc,CAAC,CAAA;IACnD,MAAM,kBAAkB,GAAG,MAAM,CAAC,kBAAkB,IAAI,GAAG,CAAA;IAC3D,iBAAiB,CAAC,oBAAoB,EAAE,kBAAkB,CAAC,CAAA;IAE3D,MAAM,eAAe,GAAG,MAAM,CAAC,eAAe,IAAI,EAAE,CAAA;IACpD,gBAAgB,CAAC,iBAAiB,EAAE,eAAe,CAAC,CAAA;IACpD,MAAM,eAAe,GAAG,MAAM,CAAC,eAAe,IAAI,EAAE,CAAA;IACpD,gBAAgB,CAAC,iBAAiB,EAAE,eAAe,CAAC,CAAA;IAEpD,MAAM,SAAS,GAAG,MAAM,CAAC,SAAS,CAAA;IAClC,IAAI,SAAS,KAAK,SAAS,IAAI,CAAC,OAAO,SAAS,KAAK,QAAQ,IAAI,SAAS,CAAC,IAAI,EAAE,CAAC,MAAM,KAAK,CAAC,CAAC,EAAE,CAAC;QAChG,MAAM,IAAI,SAAS,CAAC,6CAA6C,CAAC,CAAA;IACpE,CAAC;IAED,MAAM,kBAAkB,GAAG,MAAM,CAAC,KAAK,EAAE,kBAAkB,IAAI,EAAE,CAAA;IACjE,iBAAiB,CAAC,0BAA0B,EAAE,kBAAkB,CAAC,CAAA;IACjE,MAAM,iBAAiB,GAAG,MAAM,CAAC,KAAK,EAAE,iBAAiB,IAAI,EAAE,CAAA;IAC/D,iBAAiB,CAAC,yBAAyB,EAAE,iBAAiB,CAAC,CAAA;IAE/D,MAAM,YAAY,GAAG,MAAM,CAAC,IAAI,EAAE,YAAY,IAAI,SAAS,CAAA;IAC3D,iBAAiB,CAAC,mBAAmB,EAAE,YAAY,CAAC,CAAA;IACpD,MAAM,mBAAmB,GAAG,MAAM,CAAC,IAAI,EAAE,mBAAmB,IAAI,GAAG,CAAA;IACnE,iBAAiB,CAAC,0BAA0B,EAAE,mBAAmB,CAAC,CAAA;IAElE,OAAO;QACL,OAAO,EAAE,MAAM,CAAC,OAAO,IAAI,IAAI;QAC/B,YAAY;QACZ,cAAc;QACd,kBAAkB;QAClB,eAAe;QACf,eAAe;QACf,OAAO,EAAE,MAAM,CAAC,OAAO,IAAI,KAAK;QAChC,SAAS;QACT,KAAK,EAAE,EAAE,kBAAkB,EAAE,iBAAiB,EAAE;QAChD,IAAI,EAAE,EAAE,YAAY,EAAE,mBAAmB,EAAE;KAC5C,CAAA;AACH,CAAC"}
|