@us_momo/dsh-erp-analysis 1.2.2 → 1.3.1
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/README.md +19 -78
- package/client.mjs +8 -1
- package/package.json +47 -47
- package/plugin/client.js +185 -185
- package/plugin/runtime.mjs +97 -97
- package/release.json +1 -1
- package/release.mjs +403 -403
package/plugin/runtime.mjs
CHANGED
|
@@ -1,97 +1,97 @@
|
|
|
1
|
-
import { readFile, mkdir, readdir } from "node:fs/promises";
|
|
2
|
-
import { join, resolve } from "node:path";
|
|
3
|
-
import { homedir } from "node:os";
|
|
4
|
-
import { TeamClient } from "../client.mjs";
|
|
5
|
-
import { installRelease, currentRelease, readJson, atomicJson, trustedErpUrl } from "../release.mjs";
|
|
6
|
-
|
|
7
|
-
export const PRESET = "company-erp-analysis";
|
|
8
|
-
export const defaultRoot = () => join(process.env.LOCALAPPDATA || join(homedir(), ".local", "share"), "CompanyDSH");
|
|
9
|
-
|
|
10
|
-
/** Package code is replaceable; device identity, reports and work stay in the user data directory. */
|
|
11
|
-
export async function prepareCompany({ root = defaultRoot(), packageRoot = resolve(import.meta.dirname, "..") } = {}) {
|
|
12
|
-
const config = await readJson(join(packageRoot, "company-public.json"));
|
|
13
|
-
trustedErpUrl(config.server);
|
|
14
|
-
const existing = await readJson(join(root, "company.json"), null);
|
|
15
|
-
if (existing && new URL(existing.server).origin !== new URL(config.server).origin)
|
|
16
|
-
throw new Error("公司工作资料已关联另一 ERP 地址,请先核对安装包。");
|
|
17
|
-
const manifest = await readJson(join(packageRoot, "release.json"));
|
|
18
|
-
const installed = await installRelease(root, manifest);
|
|
19
|
-
if (!existing) await atomicJson(join(root, "company.json"), { server: config.server });
|
|
20
|
-
for (const name of ["downloads", "test-results", "knowledge-drafts"])
|
|
21
|
-
await mkdir(join(root, "workspace", name), { recursive: true });
|
|
22
|
-
const release = await currentRelease(root);
|
|
23
|
-
return { root, workspace: join(root, "workspace"), release, packageVersion: manifest.version,
|
|
24
|
-
server: config.server, pendingReload: installed.status === "pending-reload" };
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
export async function companyPreset(runtime) {
|
|
28
|
-
const { root, release } = runtime;
|
|
29
|
-
const resourceRoot = join(release.path, "workspace", ".dsh", "skills");
|
|
30
|
-
const rules = await readFile(join(release.path, "workspace", "AGENTS.md"), "utf8");
|
|
31
|
-
return {
|
|
32
|
-
id: PRESET, name: "公司 ERP 分析", description: "选品研究、经营、SKU、备货及财务分析。", order: 2,
|
|
33
|
-
plugins: [
|
|
34
|
-
{ id: "persona", name: "@deepseek-ai/dsh-persona", config: { prefix: rules } },
|
|
35
|
-
{ id: "time-context", name: "@deepseek-ai/dsh-time-context" },
|
|
36
|
-
{ id: "tool-fs", name: "@deepseek-ai/dsh-tool-fs" },
|
|
37
|
-
{ id: "tool-fs-search", name: "@deepseek-ai/dsh-tool-fs-search", config: { sampleOverCapGlobResults: false } },
|
|
38
|
-
{ id: "tool-web", name: "@deepseek-ai/dsh-tool-web" },
|
|
39
|
-
{ id: "tool-pwsh", name: "@deepseek-ai/dsh-tool-pwsh", disabled: process.platform !== "win32" },
|
|
40
|
-
{ id: "tool-bash", name: "@deepseek-ai/dsh-tool-bash", disabled: process.platform === "win32" },
|
|
41
|
-
{ id: "tool-jobs", name: "@deepseek-ai/dsh-tool-jobs" },
|
|
42
|
-
{ id: "skill-filesystem", name: "@deepseek-ai/dsh-skill-filesystem", config: {
|
|
43
|
-
providerName: "company-methods", includeDefaultRoots: false, customSkillDirs: [resourceRoot], watch: false,
|
|
44
|
-
} },
|
|
45
|
-
{ id: "tool-skill", name: "@deepseek-ai/dsh-tool-skill" },
|
|
46
|
-
{ id: "tool-presentation", name: "@deepseek-ai/dsh-agent-tool-presentation", config: { mode: "ptc" } },
|
|
47
|
-
{ id: "tool-ask-user", name: "@deepseek-ai/dsh-tool-ask-user" },
|
|
48
|
-
{ id: "present", name: "@deepseek-ai/dsh-tool-present" },
|
|
49
|
-
{ id: "company-erp-tools", name: "@deepseek-ai/dsh-mcp-client", config: {
|
|
50
|
-
serverName: "erp_read", transport: "stdio", command: process.execPath,
|
|
51
|
-
args: [join(release.path, "app", "cli.mjs"), "bridge", "--root", root, "--version", release.version, "--distribution", "plugin"],
|
|
52
|
-
env: { ELECTRON_RUN_AS_NODE: "1" }, cwd: runtime.workspace, toolCallTimeoutMs: 125000,
|
|
53
|
-
failOnStartupError: true,
|
|
54
|
-
} },
|
|
55
|
-
],
|
|
56
|
-
};
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
export function companyActions(runtime) {
|
|
60
|
-
const client = new TeamClient(runtime.root, { server: runtime.server });
|
|
61
|
-
return async (action, body = {}) => {
|
|
62
|
-
if (action === "status") {
|
|
63
|
-
let connection;
|
|
64
|
-
try { connection = await client.status(); }
|
|
65
|
-
catch (error) { connection = { status: "unavailable", message: error.message }; }
|
|
66
|
-
let pendingReports = 0;
|
|
67
|
-
const queues = join(runtime.root, "private", "reports");
|
|
68
|
-
for (const owner of await readdir(queues, { withFileTypes: true }).catch((e) => {
|
|
69
|
-
if (e.code === "ENOENT") return []; throw e;
|
|
70
|
-
})) {
|
|
71
|
-
if (owner.isDirectory()) pendingReports += (await readdir(join(queues, owner.name)))
|
|
72
|
-
.filter((name) => name.endsWith(".json")).length;
|
|
73
|
-
}
|
|
74
|
-
return { connection, version: runtime.release.version, packageVersion: runtime.packageVersion,
|
|
75
|
-
pendingReload: runtime.pendingReload, workspace: runtime.workspace, pendingReports };
|
|
76
|
-
}
|
|
77
|
-
if (action === "connect") return client.connect();
|
|
78
|
-
if (action === "switch") return client.switchAccount();
|
|
79
|
-
if (action === "logout") return client.logout();
|
|
80
|
-
if (action === "renew") {
|
|
81
|
-
const device = await readJson(join(runtime.root, "private", "device.json"));
|
|
82
|
-
const result = await client.request(`devices/${device.deviceId}/renew`, { method: "POST", body: {} });
|
|
83
|
-
if (trustedErpUrl(result.verificationUrl).origin !== new URL(runtime.server).origin)
|
|
84
|
-
throw new Error("ERP 续期地址不匹配。");
|
|
85
|
-
return result;
|
|
86
|
-
}
|
|
87
|
-
if (action === "devices") return client.request("devices");
|
|
88
|
-
if (action === "revoke") {
|
|
89
|
-
if (!/^[0-9a-f-]{36}$/i.test(body.deviceId || "")) throw new Error("设备编号无效。");
|
|
90
|
-
return client.request(`devices/${body.deviceId}/revoke`, { method: "POST", body: {} });
|
|
91
|
-
}
|
|
92
|
-
if (action === "reports") return client.call("company_reports_list", { request: body });
|
|
93
|
-
if (action === "report") return client.call("company_reports_read", { request: body });
|
|
94
|
-
if (action === "retry") return { receipts: await client.flushReports() };
|
|
95
|
-
throw new Error("公司分析操作不存在。");
|
|
96
|
-
};
|
|
97
|
-
}
|
|
1
|
+
import { readFile, mkdir, readdir } from "node:fs/promises";
|
|
2
|
+
import { join, resolve } from "node:path";
|
|
3
|
+
import { homedir } from "node:os";
|
|
4
|
+
import { TeamClient } from "../client.mjs";
|
|
5
|
+
import { installRelease, currentRelease, readJson, atomicJson, trustedErpUrl } from "../release.mjs";
|
|
6
|
+
|
|
7
|
+
export const PRESET = "company-erp-analysis";
|
|
8
|
+
export const defaultRoot = () => join(process.env.LOCALAPPDATA || join(homedir(), ".local", "share"), "CompanyDSH");
|
|
9
|
+
|
|
10
|
+
/** Package code is replaceable; device identity, reports and work stay in the user data directory. */
|
|
11
|
+
export async function prepareCompany({ root = defaultRoot(), packageRoot = resolve(import.meta.dirname, "..") } = {}) {
|
|
12
|
+
const config = await readJson(join(packageRoot, "company-public.json"));
|
|
13
|
+
trustedErpUrl(config.server);
|
|
14
|
+
const existing = await readJson(join(root, "company.json"), null);
|
|
15
|
+
if (existing && new URL(existing.server).origin !== new URL(config.server).origin)
|
|
16
|
+
throw new Error("公司工作资料已关联另一 ERP 地址,请先核对安装包。");
|
|
17
|
+
const manifest = await readJson(join(packageRoot, "release.json"));
|
|
18
|
+
const installed = await installRelease(root, manifest);
|
|
19
|
+
if (!existing) await atomicJson(join(root, "company.json"), { server: config.server });
|
|
20
|
+
for (const name of ["downloads", "test-results", "knowledge-drafts"])
|
|
21
|
+
await mkdir(join(root, "workspace", name), { recursive: true });
|
|
22
|
+
const release = await currentRelease(root);
|
|
23
|
+
return { root, workspace: join(root, "workspace"), release, packageVersion: manifest.version,
|
|
24
|
+
server: config.server, pendingReload: installed.status === "pending-reload" };
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export async function companyPreset(runtime) {
|
|
28
|
+
const { root, release } = runtime;
|
|
29
|
+
const resourceRoot = join(release.path, "workspace", ".dsh", "skills");
|
|
30
|
+
const rules = await readFile(join(release.path, "workspace", "AGENTS.md"), "utf8");
|
|
31
|
+
return {
|
|
32
|
+
id: PRESET, name: "公司 ERP 分析", description: "选品研究、经营、SKU、备货及财务分析。", order: 2,
|
|
33
|
+
plugins: [
|
|
34
|
+
{ id: "persona", name: "@deepseek-ai/dsh-persona", config: { prefix: rules } },
|
|
35
|
+
{ id: "time-context", name: "@deepseek-ai/dsh-time-context" },
|
|
36
|
+
{ id: "tool-fs", name: "@deepseek-ai/dsh-tool-fs" },
|
|
37
|
+
{ id: "tool-fs-search", name: "@deepseek-ai/dsh-tool-fs-search", config: { sampleOverCapGlobResults: false } },
|
|
38
|
+
{ id: "tool-web", name: "@deepseek-ai/dsh-tool-web" },
|
|
39
|
+
{ id: "tool-pwsh", name: "@deepseek-ai/dsh-tool-pwsh", disabled: process.platform !== "win32" },
|
|
40
|
+
{ id: "tool-bash", name: "@deepseek-ai/dsh-tool-bash", disabled: process.platform === "win32" },
|
|
41
|
+
{ id: "tool-jobs", name: "@deepseek-ai/dsh-tool-jobs" },
|
|
42
|
+
{ id: "skill-filesystem", name: "@deepseek-ai/dsh-skill-filesystem", config: {
|
|
43
|
+
providerName: "company-methods", includeDefaultRoots: false, customSkillDirs: [resourceRoot], watch: false,
|
|
44
|
+
} },
|
|
45
|
+
{ id: "tool-skill", name: "@deepseek-ai/dsh-tool-skill" },
|
|
46
|
+
{ id: "tool-presentation", name: "@deepseek-ai/dsh-agent-tool-presentation", config: { mode: "ptc" } },
|
|
47
|
+
{ id: "tool-ask-user", name: "@deepseek-ai/dsh-tool-ask-user" },
|
|
48
|
+
{ id: "present", name: "@deepseek-ai/dsh-tool-present" },
|
|
49
|
+
{ id: "company-erp-tools", name: "@deepseek-ai/dsh-mcp-client", config: {
|
|
50
|
+
serverName: "erp_read", transport: "stdio", command: process.execPath,
|
|
51
|
+
args: [join(release.path, "app", "cli.mjs"), "bridge", "--root", root, "--version", release.version, "--distribution", "plugin"],
|
|
52
|
+
env: { ELECTRON_RUN_AS_NODE: "1" }, cwd: runtime.workspace, toolCallTimeoutMs: 125000,
|
|
53
|
+
failOnStartupError: true,
|
|
54
|
+
} },
|
|
55
|
+
],
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export function companyActions(runtime) {
|
|
60
|
+
const client = new TeamClient(runtime.root, { server: runtime.server });
|
|
61
|
+
return async (action, body = {}) => {
|
|
62
|
+
if (action === "status") {
|
|
63
|
+
let connection;
|
|
64
|
+
try { connection = await client.status(); }
|
|
65
|
+
catch (error) { connection = { status: "unavailable", message: error.message }; }
|
|
66
|
+
let pendingReports = 0;
|
|
67
|
+
const queues = join(runtime.root, "private", "reports");
|
|
68
|
+
for (const owner of await readdir(queues, { withFileTypes: true }).catch((e) => {
|
|
69
|
+
if (e.code === "ENOENT") return []; throw e;
|
|
70
|
+
})) {
|
|
71
|
+
if (owner.isDirectory()) pendingReports += (await readdir(join(queues, owner.name)))
|
|
72
|
+
.filter((name) => name.endsWith(".json")).length;
|
|
73
|
+
}
|
|
74
|
+
return { connection, version: runtime.release.version, packageVersion: runtime.packageVersion,
|
|
75
|
+
pendingReload: runtime.pendingReload, workspace: runtime.workspace, pendingReports };
|
|
76
|
+
}
|
|
77
|
+
if (action === "connect") return client.connect();
|
|
78
|
+
if (action === "switch") return client.switchAccount();
|
|
79
|
+
if (action === "logout") return client.logout();
|
|
80
|
+
if (action === "renew") {
|
|
81
|
+
const device = await readJson(join(runtime.root, "private", "device.json"));
|
|
82
|
+
const result = await client.request(`devices/${device.deviceId}/renew`, { method: "POST", body: {} });
|
|
83
|
+
if (trustedErpUrl(result.verificationUrl).origin !== new URL(runtime.server).origin)
|
|
84
|
+
throw new Error("ERP 续期地址不匹配。");
|
|
85
|
+
return result;
|
|
86
|
+
}
|
|
87
|
+
if (action === "devices") return client.request("devices");
|
|
88
|
+
if (action === "revoke") {
|
|
89
|
+
if (!/^[0-9a-f-]{36}$/i.test(body.deviceId || "")) throw new Error("设备编号无效。");
|
|
90
|
+
return client.request(`devices/${body.deviceId}/revoke`, { method: "POST", body: {} });
|
|
91
|
+
}
|
|
92
|
+
if (action === "reports") return client.call("company_reports_list", { request: body });
|
|
93
|
+
if (action === "report") return client.call("company_reports_read", { request: body });
|
|
94
|
+
if (action === "retry") return { receipts: await client.flushReports() };
|
|
95
|
+
throw new Error("公司分析操作不存在。");
|
|
96
|
+
};
|
|
97
|
+
}
|