@hpmicro-tools/hpmmfgctl 0.0.0-stage → 0.0.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.
Files changed (67) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +197 -2
  3. package/README.zh-CN.md +197 -0
  4. package/dist/command/arguments.d.ts +3 -0
  5. package/dist/command/arguments.js +18 -0
  6. package/dist/command/arguments.js.map +1 -0
  7. package/dist/command/runner.d.ts +22 -0
  8. package/dist/command/runner.js +119 -0
  9. package/dist/command/runner.js.map +1 -0
  10. package/dist/command/types.d.ts +37 -0
  11. package/dist/command/types.js +2 -0
  12. package/dist/command/types.js.map +1 -0
  13. package/dist/command/validate.d.ts +4 -0
  14. package/dist/command/validate.js +48 -0
  15. package/dist/command/validate.js.map +1 -0
  16. package/dist/config/config-path.d.ts +8 -0
  17. package/dist/config/config-path.js +27 -0
  18. package/dist/config/config-path.js.map +1 -0
  19. package/dist/config/config-store.d.ts +13 -0
  20. package/dist/config/config-store.js +61 -0
  21. package/dist/config/config-store.js.map +1 -0
  22. package/dist/config/config-type.d.ts +5 -0
  23. package/dist/config/config-type.js +2 -0
  24. package/dist/config/config-type.js.map +1 -0
  25. package/dist/device/enumerator.d.ts +12 -0
  26. package/dist/device/enumerator.js +65 -0
  27. package/dist/device/enumerator.js.map +1 -0
  28. package/dist/device/types.d.ts +22 -0
  29. package/dist/device/types.js +2 -0
  30. package/dist/device/types.js.map +1 -0
  31. package/dist/hpm-mfg-service.d.ts +37 -0
  32. package/dist/hpm-mfg-service.js +155 -0
  33. package/dist/hpm-mfg-service.js.map +1 -0
  34. package/dist/main.d.ts +2 -0
  35. package/dist/main.js +23 -0
  36. package/dist/main.js.map +1 -0
  37. package/dist/mcp/configuration.d.ts +4 -0
  38. package/dist/mcp/configuration.js +30 -0
  39. package/dist/mcp/configuration.js.map +1 -0
  40. package/dist/mcp/discovery.d.ts +4 -0
  41. package/dist/mcp/discovery.js +30 -0
  42. package/dist/mcp/discovery.js.map +1 -0
  43. package/dist/mcp/mcp-type.d.ts +11 -0
  44. package/dist/mcp/mcp-type.js +2 -0
  45. package/dist/mcp/mcp-type.js.map +1 -0
  46. package/dist/mcp/operations.d.ts +4 -0
  47. package/dist/mcp/operations.js +17 -0
  48. package/dist/mcp/operations.js.map +1 -0
  49. package/dist/mcp/registration.d.ts +15 -0
  50. package/dist/mcp/registration.js +23 -0
  51. package/dist/mcp/registration.js.map +1 -0
  52. package/dist/mcp/responses.d.ts +5 -0
  53. package/dist/mcp/responses.js +20 -0
  54. package/dist/mcp/responses.js.map +1 -0
  55. package/dist/mcp/schemas.d.ts +155 -0
  56. package/dist/mcp/schemas.js +253 -0
  57. package/dist/mcp/schemas.js.map +1 -0
  58. package/dist/mcp/server.d.ts +4 -0
  59. package/dist/mcp/server.js +16 -0
  60. package/dist/mcp/server.js.map +1 -0
  61. package/dist/operations/rom.d.ts +5 -0
  62. package/dist/operations/rom.js +81 -0
  63. package/dist/operations/rom.js.map +1 -0
  64. package/dist/service-type.d.ts +13 -0
  65. package/dist/service-type.js +2 -0
  66. package/dist/service-type.js.map +1 -0
  67. package/package.json +51 -4
@@ -0,0 +1,48 @@
1
+ import { basename, isAbsolute } from "node:path";
2
+ import { stat } from "node:fs/promises";
3
+ /** Checks the installed CMD name, version, failure exit behavior, and required options. */
4
+ export async function validatePath(path, runner, signal) {
5
+ if (!isAbsolute(path)) {
6
+ return {
7
+ compatible: false,
8
+ message: "manufacturing command path must be absolute",
9
+ };
10
+ }
11
+ const expected = `hpm_manufacturing_cmd${process.platform === "win32" ? ".exe" : ""}`;
12
+ if (basename(path).toLowerCase() !== expected) {
13
+ return {
14
+ compatible: false,
15
+ message: `command file name must be ${expected}`,
16
+ };
17
+ }
18
+ try {
19
+ const info = await stat(path);
20
+ if (!info.isFile() || (process.platform !== "win32" && !(info.mode & 0o111))) {
21
+ throw new Error("command must be an executable file");
22
+ }
23
+ const version = await runner.run(path, ["--version"], 10000, signal);
24
+ if (!version.success) {
25
+ return { compatible: false, message: "--version failed: " + version.log };
26
+ }
27
+ const noArgs = await runner.run(path, [], 10000, signal);
28
+ if (noArgs.exitCode <= 0 || noArgs.timedOut || signal?.aborted) {
29
+ return {
30
+ compatible: false,
31
+ message: "command must fail with a nonzero exit code when called without arguments",
32
+ };
33
+ }
34
+ const help = await runner.run(path, ["--help"], 10000, signal);
35
+ if (!help.success ||
36
+ !["-p", "-u", "-r", "-t", "-f"].every((option) => help.log.includes(option))) {
37
+ return { compatible: false, message: "missing required command options" };
38
+ }
39
+ return { compatible: true, version: version.log.trim() };
40
+ }
41
+ catch (error) {
42
+ if (signal?.aborted) {
43
+ throw error;
44
+ }
45
+ return { compatible: false, message: String(error) };
46
+ }
47
+ }
48
+ //# sourceMappingURL=validate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validate.js","sourceRoot":"","sources":["../../src/command/validate.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AACjD,OAAO,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAIxC,2FAA2F;AAC3F,MAAM,CAAC,KAAK,UAAU,YAAY,CAChC,IAAY,EACZ,MAAc,EACd,MAAoB;IAEpB,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;QACtB,OAAO;YACL,UAAU,EAAE,KAAK;YACjB,OAAO,EAAE,6CAA6C;SACvD,CAAC;IACJ,CAAC;IACD,MAAM,QAAQ,GAAG,wBAAwB,OAAO,CAAC,QAAQ,KAAK,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;IACtF,IAAI,QAAQ,CAAC,IAAI,CAAC,CAAC,WAAW,EAAE,KAAK,QAAQ,EAAE,CAAC;QAC9C,OAAO;YACL,UAAU,EAAE,KAAK;YACjB,OAAO,EAAE,6BAA6B,QAAQ,EAAE;SACjD,CAAC;IACJ,CAAC;IACD,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,CAAC;QAC9B,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,OAAO,CAAC,QAAQ,KAAK,OAAO,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,GAAG,KAAK,CAAC,CAAC,EAAE,CAAC;YAC7E,MAAM,IAAI,KAAK,CAAC,oCAAoC,CAAC,CAAC;QACxD,CAAC;QACD,MAAM,OAAO,GAAG,MAAM,MAAM,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,WAAW,CAAC,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC;QACrE,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC;YACrB,OAAO,EAAE,UAAU,EAAE,KAAK,EAAE,OAAO,EAAE,oBAAoB,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC;QAC5E,CAAC;QACD,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,GAAG,CAAC,IAAI,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC;QACzD,IAAI,MAAM,CAAC,QAAQ,IAAI,CAAC,IAAI,MAAM,CAAC,QAAQ,IAAI,MAAM,EAAE,OAAO,EAAE,CAAC;YAC/D,OAAO;gBACL,UAAU,EAAE,KAAK;gBACjB,OAAO,EAAE,0EAA0E;aACpF,CAAC;QACJ,CAAC;QACD,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,QAAQ,CAAC,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC;QAC/D,IACE,CAAC,IAAI,CAAC,OAAO;YACb,CAAC,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC,KAAK,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,EAC5E,CAAC;YACD,OAAO,EAAE,UAAU,EAAE,KAAK,EAAE,OAAO,EAAE,kCAAkC,EAAE,CAAC;QAC5E,CAAC;QACD,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,CAAC,GAAG,CAAC,IAAI,EAAE,EAAE,CAAC;IAC3D,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,MAAM,EAAE,OAAO,EAAE,CAAC;YACpB,MAAM,KAAK,CAAC;QACd,CAAC;QACD,OAAO,EAAE,UAAU,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC;IACvD,CAAC;AACH,CAAC"}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Resolves a stable user configuration path, preferring HPMMFGCTL_CONFIG.
3
+ * @param environmentVariables Environment providing the override and APPDATA/XDG_CONFIG_HOME.
4
+ * @param platform Target OS; defaults to the current OS and is injectable for tests.
5
+ * @param home User home directory for platform-specific fallback paths.
6
+ * @returns File path; does not create files.
7
+ */
8
+ export declare function defaultPath(environmentVariables?: NodeJS.ProcessEnv, platform?: NodeJS.Platform, home?: string): string;
@@ -0,0 +1,27 @@
1
+ import * as os from "node:os";
2
+ import * as path from "node:path";
3
+ /**
4
+ * Resolves a stable user configuration path, preferring HPMMFGCTL_CONFIG.
5
+ * @param environmentVariables Environment providing the override and APPDATA/XDG_CONFIG_HOME.
6
+ * @param platform Target OS; defaults to the current OS and is injectable for tests.
7
+ * @param home User home directory for platform-specific fallback paths.
8
+ * @returns File path; does not create files.
9
+ */
10
+ export function defaultPath(environmentVariables = process.env, platform = process.platform, home = os.homedir()) {
11
+ if (environmentVariables.HPMMFGCTL_CONFIG) {
12
+ return environmentVariables.HPMMFGCTL_CONFIG;
13
+ }
14
+ let configDirectory;
15
+ switch (platform) {
16
+ case "win32":
17
+ configDirectory = environmentVariables.APPDATA || path.join(home, "AppData", "Roaming");
18
+ break;
19
+ case "darwin":
20
+ configDirectory = path.join(home, "Library", "Application Support");
21
+ break;
22
+ default:
23
+ configDirectory = environmentVariables.XDG_CONFIG_HOME || path.join(home, ".config");
24
+ }
25
+ return path.join(configDirectory, "hpmicro", "hpmmfgctl", "config.json");
26
+ }
27
+ //# sourceMappingURL=config-path.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config-path.js","sourceRoot":"","sources":["../../src/config/config-path.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAC9B,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAElC;;;;;;GAMG;AACH,MAAM,UAAU,WAAW,CACzB,oBAAoB,GAAG,OAAO,CAAC,GAAG,EAClC,QAAQ,GAAG,OAAO,CAAC,QAAQ,EAC3B,IAAI,GAAG,EAAE,CAAC,OAAO,EAAE;IAEnB,IAAI,oBAAoB,CAAC,gBAAgB,EAAE,CAAC;QAC1C,OAAO,oBAAoB,CAAC,gBAAgB,CAAC;IAC/C,CAAC;IACD,IAAI,eAAuB,CAAC;IAC5B,QAAQ,QAAQ,EAAE,CAAC;QACjB,KAAK,OAAO;YACV,eAAe,GAAG,oBAAoB,CAAC,OAAO,IAAI,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,SAAS,EAAE,SAAS,CAAC,CAAC;YACxF,MAAM;QACR,KAAK,QAAQ;YACX,eAAe,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,SAAS,EAAE,qBAAqB,CAAC,CAAC;YACpE,MAAM;QACR;YACE,eAAe,GAAG,oBAAoB,CAAC,eAAe,IAAI,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC;IACzF,CAAC;IACD,OAAO,IAAI,CAAC,IAAI,CAAC,eAAe,EAAE,SAAS,EAAE,WAAW,EAAE,aAAa,CAAC,CAAC;AAC3E,CAAC"}
@@ -0,0 +1,13 @@
1
+ import type { Config } from "./config-type.js";
2
+ /** Persists configuration at a stable per-user path without caching file contents. */
3
+ export declare class Store {
4
+ readonly filePath: string;
5
+ /** Uses the supplied file path or the platform default resolved by defaultPath. */
6
+ constructor(filePath?: string);
7
+ /** Returns the resolved configuration file path. */
8
+ path(): string;
9
+ /** Reads the latest configuration; a missing file returns an empty configuration. */
10
+ load(): Promise<Config>;
11
+ /** Flushes a temporary file and replaces configuration in the same directory. */
12
+ save(config: Config): Promise<void>;
13
+ }
@@ -0,0 +1,61 @@
1
+ import { mkdir, readFile, rename, unlink, open } from "node:fs/promises";
2
+ import { dirname, join } from "node:path";
3
+ import { randomUUID } from "node:crypto";
4
+ import { defaultPath } from "./config-path.js";
5
+ /** Persists configuration at a stable per-user path without caching file contents. */
6
+ export class Store {
7
+ filePath;
8
+ /** Uses the supplied file path or the platform default resolved by defaultPath. */
9
+ constructor(filePath = defaultPath()) {
10
+ this.filePath = filePath;
11
+ }
12
+ /** Returns the resolved configuration file path. */
13
+ path() {
14
+ return this.filePath;
15
+ }
16
+ /** Reads the latest configuration; a missing file returns an empty configuration. */
17
+ async load() {
18
+ const path = this.path();
19
+ let text;
20
+ try {
21
+ text = await readFile(path, "utf8");
22
+ }
23
+ catch (error) {
24
+ if (error.code === "ENOENT") {
25
+ return {};
26
+ }
27
+ throw error;
28
+ }
29
+ const value = JSON.parse(text);
30
+ if (!value || typeof value !== "object" || Array.isArray(value)) {
31
+ throw new Error("Invalid config object");
32
+ }
33
+ const cfg = value;
34
+ if (cfg.mfgCmdPath !== undefined && typeof cfg.mfgCmdPath !== "string") {
35
+ throw new Error("Invalid mfgCmdPath");
36
+ }
37
+ return cfg;
38
+ }
39
+ /** Flushes a temporary file and replaces configuration in the same directory. */
40
+ async save(config) {
41
+ const path = this.path();
42
+ const directory = dirname(path);
43
+ await mkdir(directory, { recursive: true, mode: 0o700 });
44
+ const tmp = join(directory, `.config-${randomUUID()}.tmp`);
45
+ try {
46
+ const file = await open(tmp, "wx", 0o600);
47
+ try {
48
+ await file.writeFile(JSON.stringify(config, null, 2) + "\n");
49
+ await file.sync();
50
+ }
51
+ finally {
52
+ await file.close();
53
+ }
54
+ await rename(tmp, path);
55
+ }
56
+ finally {
57
+ await unlink(tmp).catch(() => { });
58
+ }
59
+ }
60
+ }
61
+ //# sourceMappingURL=config-store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config-store.js","sourceRoot":"","sources":["../../src/config/config-store.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AACzE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAGzC,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAE/C,sFAAsF;AACtF,MAAM,OAAO,KAAK;IAEK;IADrB,mFAAmF;IACnF,YAAqB,WAAW,WAAW,EAAE;QAAxB,aAAQ,GAAR,QAAQ,CAAgB;IAAG,CAAC;IAEjD,oDAAoD;IACpD,IAAI;QACF,OAAO,IAAI,CAAC,QAAQ,CAAC;IACvB,CAAC;IAED,qFAAqF;IACrF,KAAK,CAAC,IAAI;QACR,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;QACzB,IAAI,IAAY,CAAC;QACjB,IAAI,CAAC;YACH,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;QACtC,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAK,KAA+B,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;gBACvD,OAAO,EAAE,CAAC;YACZ,CAAC;YACD,MAAM,KAAK,CAAC;QACd,CAAC;QACD,MAAM,KAAK,GAAY,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QACxC,IAAI,CAAC,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;YAChE,MAAM,IAAI,KAAK,CAAC,uBAAuB,CAAC,CAAC;QAC3C,CAAC;QACD,MAAM,GAAG,GAAG,KAAe,CAAC;QAC5B,IAAI,GAAG,CAAC,UAAU,KAAK,SAAS,IAAI,OAAO,GAAG,CAAC,UAAU,KAAK,QAAQ,EAAE,CAAC;YACvE,MAAM,IAAI,KAAK,CAAC,oBAAoB,CAAC,CAAC;QACxC,CAAC;QACD,OAAO,GAAG,CAAC;IACb,CAAC;IAED,iFAAiF;IACjF,KAAK,CAAC,IAAI,CAAC,MAAc;QACvB,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;QACzB,MAAM,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;QAChC,MAAM,KAAK,CAAC,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;QACzD,MAAM,GAAG,GAAG,IAAI,CAAC,SAAS,EAAE,WAAW,UAAU,EAAE,MAAM,CAAC,CAAC;QAC3D,IAAI,CAAC;YACH,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,GAAG,EAAE,IAAI,EAAE,KAAK,CAAC,CAAC;YAC1C,IAAI,CAAC;gBACH,MAAM,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;gBAC7D,MAAM,IAAI,CAAC,IAAI,EAAE,CAAC;YACpB,CAAC;oBAAS,CAAC;gBACT,MAAM,IAAI,CAAC,KAAK,EAAE,CAAC;YACrB,CAAC;YACD,MAAM,MAAM,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;QAC1B,CAAC;gBAAS,CAAC;YACT,MAAM,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;QACpC,CAAC;IACH,CAAC;CACF"}
@@ -0,0 +1,5 @@
1
+ /** Serialized configuration compatible with the Go manufacturing server. */
2
+ export interface Config {
3
+ /** Absolute installed CMD executable path; omitted when not configured. */
4
+ mfgCmdPath?: string;
5
+ }
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=config-type.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config-type.js","sourceRoot":"","sources":["../../src/config/config-type.ts"],"names":[],"mappings":""}
@@ -0,0 +1,12 @@
1
+ import type { DeviceInfo, Enumerator } from "./types.js";
2
+ /** HPMicro USB vendor ID used when the caller omits a HID vendor filter. */
3
+ export declare const defaultVID = 13495;
4
+ /** Discovers devices using native OS bindings on supported manufacturing platforms. */
5
+ export declare class SystemEnumerator implements Enumerator {
6
+ /** Rejects platforms outside the Manufacturing CMD support matrix. */
7
+ private supported;
8
+ /** Lists serial ports; Windows accessibility is verified later by the CMD probe. */
9
+ listSerial(): Promise<DeviceInfo[]>;
10
+ /** Lists matching HID interfaces and checks whether each can be opened. */
11
+ listHID(vid: number, pid: number): Promise<DeviceInfo[]>;
12
+ }
@@ -0,0 +1,65 @@
1
+ import { access } from "node:fs/promises";
2
+ import { constants } from "node:fs";
3
+ /** HPMicro USB vendor ID used when the caller omits a HID vendor filter. */
4
+ export const defaultVID = 0x34b7;
5
+ /** Discovers devices using native OS bindings on supported manufacturing platforms. */
6
+ export class SystemEnumerator {
7
+ /** Rejects platforms outside the Manufacturing CMD support matrix. */
8
+ supported() {
9
+ if (!["win32", "linux"].includes(process.platform) || process.arch !== "x64") {
10
+ throw new Error("Supported platforms: Windows x64 and Linux x86_64");
11
+ }
12
+ }
13
+ /** Lists serial ports; Windows accessibility is verified later by the CMD probe. */
14
+ async listSerial() {
15
+ this.supported();
16
+ const { autoDetect } = await import("@serialport/bindings-cpp");
17
+ const ports = await autoDetect().list();
18
+ return Promise.all(ports.map(async (port) => {
19
+ const accessible = process.platform === "win32" ||
20
+ (await access(port.path, constants.R_OK | constants.W_OK).then(() => true, () => false));
21
+ return {
22
+ path: port.path,
23
+ description: port.manufacturer ?? "",
24
+ accessible,
25
+ ...(accessible ? {} : { hint: "Check device permissions and group membership" }),
26
+ };
27
+ }));
28
+ }
29
+ /** Lists matching HID interfaces and checks whether each can be opened. */
30
+ async listHID(vid, pid) {
31
+ this.supported();
32
+ const hid = await import("node-hid");
33
+ // Linux CMD expects hidraw paths rather than libusb bus identifiers.
34
+ if (process.platform === "linux") {
35
+ hid.setDriverType("hidraw");
36
+ }
37
+ const devices = (await hid.devicesAsync()).filter((device) => device.path && (!vid || device.vendorId === vid) && (!pid || device.productId === pid));
38
+ const result = [];
39
+ for (const device of devices) {
40
+ let accessible = false;
41
+ try {
42
+ const handle = await hid.HIDAsync.open(device.path);
43
+ await handle.close();
44
+ accessible = true;
45
+ }
46
+ catch {
47
+ /* Permission or exclusive-access failure. */
48
+ }
49
+ result.push({
50
+ path: device.path,
51
+ vid: device.vendorId,
52
+ pid: device.productId,
53
+ description: device.product ?? "",
54
+ accessible,
55
+ ...(accessible
56
+ ? {}
57
+ : {
58
+ hint: "Check HID permissions or another application's exclusive access",
59
+ }),
60
+ });
61
+ }
62
+ return result.sort((left, right) => left.path.localeCompare(right.path));
63
+ }
64
+ }
65
+ //# sourceMappingURL=enumerator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"enumerator.js","sourceRoot":"","sources":["../../src/device/enumerator.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,22 @@
1
+ /** Operating-system device information returned by discovery. */
2
+ export interface DeviceInfo {
3
+ /** Serial device or HID interface path used to create a target. */
4
+ path: string;
5
+ /** USB vendor ID, when available. */
6
+ vid?: number;
7
+ /** USB product ID, when available. */
8
+ pid?: number;
9
+ /** Human-readable device description reported by the operating system. */
10
+ description: string;
11
+ /** Discovery accessibility hint; actual CMD access is verified during target creation. */
12
+ accessible: boolean;
13
+ /** Permission or exclusive-access guidance for unavailable devices. */
14
+ hint?: string;
15
+ }
16
+ /** Device discovery boundary, replaceable for service tests. */
17
+ export interface Enumerator {
18
+ /** Lists serial devices without performing ROM communication. */
19
+ listSerial(): Promise<DeviceInfo[]>;
20
+ /** Lists HID devices filtered by vendor and product; zero disables that filter. */
21
+ listHID(vid: number, pid: number): Promise<DeviceInfo[]>;
22
+ }
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/device/types.ts"],"names":[],"mappings":""}
@@ -0,0 +1,37 @@
1
+ import { Store } from "./config/config-store.js";
2
+ import { Runner } from "./command/runner.js";
3
+ import type { Validation } from "./command/types.js";
4
+ import type { Enumerator } from "./device/types.js";
5
+ import type { ROMName } from "./mcp/mcp-type.js";
6
+ import type { TargetCreateInput } from "./service-type.js";
7
+ /** Coordinates configuration, device probing, and serialized ROM operations. */
8
+ export declare class Service {
9
+ readonly store: Store;
10
+ readonly runner: Runner;
11
+ readonly devices: Enumerator;
12
+ private targets;
13
+ private next;
14
+ private cached?;
15
+ /** Injects storage, process execution, and discovery without accessing hardware. */
16
+ constructor(store?: Store, runner?: Runner, devices?: Enumerator);
17
+ /** Caches successful compatibility checks by file identity; forced checks invalidate stale success. */
18
+ validate(path: string, signal?: AbortSignal, force?: boolean): Promise<Validation>;
19
+ /** Refreshes compatibility and reports the active plugin configuration. */
20
+ doctor(signal?: AbortSignal): Promise<Record<string, unknown>>;
21
+ /** Persists an absolute CMD path only after a successful compatibility check. */
22
+ set(path: string, signal?: AbortSignal): Promise<Validation>;
23
+ /** Clears persisted CMD settings and cached compatibility. */
24
+ clear(): Promise<Record<string, unknown>>;
25
+ /** Discovers devices without registering targets or issuing ROM commands. */
26
+ discover(transport: "serial" | "hid", vid?: number, pid?: number): Promise<Record<string, unknown>>;
27
+ /** Probes query-rte 0 and registers the target only when CMD reports success. */
28
+ create(input: TargetCreateInput, signal?: AbortSignal): Promise<Record<string, unknown>>;
29
+ /** Returns connection settings for targets registered in this process. */
30
+ list(): Record<string, unknown>;
31
+ /** Deletes a registered target and rejects unknown IDs. */
32
+ delete(targetId: string): Record<string, unknown>;
33
+ /** Validates a ROM request and executes it against a registered target. */
34
+ rom(name: ROMName, raw: unknown, signal?: AbortSignal): Promise<Record<string, unknown>>;
35
+ /** Resolves a compatible CMD and executes the transport-specific ROM arguments. */
36
+ private run;
37
+ }
@@ -0,0 +1,155 @@
1
+ import { normalize } from "node:path";
2
+ import { stat } from "node:fs/promises";
3
+ import { Store } from "./config/config-store.js";
4
+ import { Runner } from "./command/runner.js";
5
+ import { buildArgs } from "./command/arguments.js";
6
+ import { validatePath } from "./command/validate.js";
7
+ import { SystemEnumerator, defaultVID } from "./device/enumerator.js";
8
+ import { buildROM, defaultTimeout } from "./operations/rom.js";
9
+ /** Coordinates configuration, device probing, and serialized ROM operations. */
10
+ export class Service {
11
+ store;
12
+ runner;
13
+ devices;
14
+ targets = new Map();
15
+ next = 0;
16
+ cached;
17
+ /** Injects storage, process execution, and discovery without accessing hardware. */
18
+ constructor(store = new Store(), runner = new Runner(), devices = new SystemEnumerator()) {
19
+ this.store = store;
20
+ this.runner = runner;
21
+ this.devices = devices;
22
+ }
23
+ /** Caches successful compatibility checks by file identity; forced checks invalidate stale success. */
24
+ async validate(path, signal, force = false) {
25
+ let key = "";
26
+ try {
27
+ const info = await stat(path);
28
+ key = `${normalize(path)}:${info.size}:${info.mtimeMs}:${info.ctimeMs}`;
29
+ }
30
+ catch {
31
+ /* Invalid paths are not cached. */
32
+ }
33
+ if (!force && key && this.cached?.key === key) {
34
+ return this.cached.validation;
35
+ }
36
+ const validation = await validatePath(path, this.runner, signal);
37
+ if (validation.compatible && key) {
38
+ this.cached = { key, validation };
39
+ }
40
+ else if (this.cached?.key === key) {
41
+ this.cached = undefined;
42
+ }
43
+ return validation;
44
+ }
45
+ /** Refreshes compatibility and reports the active plugin configuration. */
46
+ async doctor(signal) {
47
+ const config = await this.store.load();
48
+ const validation = await this.validate(config.mfgCmdPath ?? "", signal, true);
49
+ return {
50
+ mcpVersion: "0.1.0",
51
+ os: process.platform,
52
+ arch: process.arch,
53
+ configPath: this.store.path(),
54
+ configuredPath: config.mfgCmdPath ?? "",
55
+ validation,
56
+ pathWhitespaceUnsupported: true,
57
+ };
58
+ }
59
+ /** Persists an absolute CMD path only after a successful compatibility check. */
60
+ async set(path, signal) {
61
+ const validation = await this.validate(path, signal, true);
62
+ if (!validation.compatible) {
63
+ throw new Error(validation.message);
64
+ }
65
+ await this.store.save({ mfgCmdPath: normalize(path) });
66
+ return validation;
67
+ }
68
+ /** Clears persisted CMD settings and cached compatibility. */
69
+ async clear() {
70
+ await this.store.save({});
71
+ this.cached = undefined;
72
+ return { cleared: true };
73
+ }
74
+ /** Discovers devices without registering targets or issuing ROM commands. */
75
+ async discover(transport, vid = defaultVID, pid = 0) {
76
+ return {
77
+ transport,
78
+ devices: transport === "serial"
79
+ ? await this.devices.listSerial()
80
+ : await this.devices.listHID(vid || defaultVID, pid),
81
+ };
82
+ }
83
+ /** Probes query-rte 0 and registers the target only when CMD reports success. */
84
+ async create(input, signal) {
85
+ const target = { ...input };
86
+ delete target.timeoutMs;
87
+ if (target.transport === "serial") {
88
+ target.baudRate ||= 115200;
89
+ if (!target.port) {
90
+ const list = await this.devices.listSerial();
91
+ if (list.length !== 1) {
92
+ throw new Error(`Exactly one serial device required; found ${list.length}`);
93
+ }
94
+ target.port = list[0].path;
95
+ }
96
+ }
97
+ else {
98
+ target.vid ||= defaultVID;
99
+ if (!target.path) {
100
+ const list = await this.devices.listHID(target.vid, target.pid ?? 0);
101
+ if (list.length !== 1) {
102
+ throw new Error(`Exactly one HID device required; found ${list.length}`);
103
+ }
104
+ if (!list[0].accessible) {
105
+ throw new Error("HID device is not accessible");
106
+ }
107
+ target.path = list[0].path;
108
+ }
109
+ }
110
+ const probe = await this.run(target, input.timeoutMs ?? 10000, "query-rte 0", signal);
111
+ if (!probe.success) {
112
+ return { ...probe };
113
+ }
114
+ const targetId = `target-${++this.next}`;
115
+ this.targets.set(targetId, target);
116
+ return { target: { targetId, ...target }, probe };
117
+ }
118
+ /** Returns connection settings for targets registered in this process. */
119
+ list() {
120
+ return {
121
+ targets: [...this.targets].map(([targetId, target]) => ({
122
+ targetId,
123
+ ...target,
124
+ })),
125
+ };
126
+ }
127
+ /** Deletes a registered target and rejects unknown IDs. */
128
+ delete(targetId) {
129
+ if (!this.targets.delete(targetId)) {
130
+ throw new Error("unknown targetId");
131
+ }
132
+ return { targetId, deleted: true };
133
+ }
134
+ /** Validates a ROM request and executes it against a registered target. */
135
+ async rom(name, raw, signal) {
136
+ const { input, command } = await buildROM(name, raw);
137
+ const target = this.targets.get(input.targetId);
138
+ if (!target) {
139
+ throw new Error("unknown targetId");
140
+ }
141
+ return {
142
+ ...(await this.run(target, input.timeoutMs ?? defaultTimeout(name), command, signal)),
143
+ };
144
+ }
145
+ /** Resolves a compatible CMD and executes the transport-specific ROM arguments. */
146
+ async run(target, timeout, command, signal) {
147
+ const { mfgCmdPath = "" } = await this.store.load();
148
+ const validation = await this.validate(mfgCmdPath, signal);
149
+ if (!validation.compatible) {
150
+ throw new Error(`Manufacturing command is not ready: ${validation.message}`);
151
+ }
152
+ return this.runner.run(mfgCmdPath, buildArgs(target, timeout, command), timeout + 5000, signal);
153
+ }
154
+ }
155
+ //# sourceMappingURL=hpm-mfg-service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hpm-mfg-service.js","sourceRoot":"","sources":["../src/hpm-mfg-service.ts"],"names":[],"mappings":"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"}
package/dist/main.d.ts ADDED
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
package/dist/main.js ADDED
@@ -0,0 +1,23 @@
1
+ #!/usr/bin/env node
2
+ import { StdioServerTransport } from "@modelcontextprotocol/server/stdio";
3
+ import { createServer } from "./mcp/server.js";
4
+ /** CLI arguments select the stdio transport; stdout remains reserved for MCP. */
5
+ const args = process.argv.slice(2);
6
+ if (args.length === 0 || args.includes("--help")) {
7
+ console.error("Usage: hpmmfgctl mcp | hpmmfgctl serve --stdio");
8
+ }
9
+ else if ((args.length === 1 && args[0] === "mcp") ||
10
+ (args.length === 2 && args[0] === "serve" && args[1] === "--stdio")) {
11
+ const server = createServer();
12
+ for (const signal of ["SIGINT", "SIGTERM"]) {
13
+ process.once(signal, () => {
14
+ void server.close();
15
+ });
16
+ }
17
+ await server.connect(new StdioServerTransport());
18
+ }
19
+ else {
20
+ console.error("Usage: hpmmfgctl mcp | hpmmfgctl serve --stdio");
21
+ process.exitCode = 1;
22
+ }
23
+ //# sourceMappingURL=main.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"main.js","sourceRoot":"","sources":["../src/main.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,oBAAoB,EAAE,MAAM,oCAAoC,CAAC;AAC1E,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAE/C,iFAAiF;AACjF,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AACnC,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC;IACjD,OAAO,CAAC,KAAK,CAAC,gDAAgD,CAAC,CAAC;AAClE,CAAC;KAAM,IACL,CAAC,IAAI,CAAC,MAAM,KAAK,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC,KAAK,KAAK,CAAC;IACxC,CAAC,IAAI,CAAC,MAAM,KAAK,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC,KAAK,OAAO,IAAI,IAAI,CAAC,CAAC,CAAC,KAAK,SAAS,CAAC,EACnE,CAAC;IACD,MAAM,MAAM,GAAG,YAAY,EAAE,CAAC;IAC9B,KAAK,MAAM,MAAM,IAAI,CAAC,QAAQ,EAAE,SAAS,CAAU,EAAE,CAAC;QACpD,OAAO,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,EAAE;YACxB,KAAK,MAAM,CAAC,KAAK,EAAE,CAAC;QACtB,CAAC,CAAC,CAAC;IACL,CAAC;IACD,MAAM,MAAM,CAAC,OAAO,CAAC,IAAI,oBAAoB,EAAE,CAAC,CAAC;AACnD,CAAC;KAAM,CAAC;IACN,OAAO,CAAC,KAAK,CAAC,gDAAgD,CAAC,CAAC;IAChE,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;AACvB,CAAC"}
@@ -0,0 +1,4 @@
1
+ import type { McpServer } from "@modelcontextprotocol/server";
2
+ import type { Service } from "../hpm-mfg-service.js";
3
+ /** Registers configuration tools without accessing files or starting CMD processes. */
4
+ export declare function registerConfigurationTools(server: McpServer, service: Service): void;
@@ -0,0 +1,30 @@
1
+ import { cmdSetSchema, emptyInputSchema } from "./schemas.js";
2
+ import { registerTool } from "./registration.js";
3
+ /** Registers configuration tools without accessing files or starting CMD processes. */
4
+ export function registerConfigurationTools(server, service) {
5
+ registerTool(server, "mfg.doctor", {
6
+ description: "Refresh manufacturing command compatibility and report configuration",
7
+ inputSchema: emptyInputSchema,
8
+ readOnly: true,
9
+ destructive: false,
10
+ }, (_input, signal) => service.doctor(signal));
11
+ registerTool(server, "mfg.get", {
12
+ description: "Get configured CMD path",
13
+ inputSchema: emptyInputSchema,
14
+ readOnly: true,
15
+ destructive: false,
16
+ }, async () => ({ ...(await service.store.load()) }));
17
+ registerTool(server, "mfg.set", {
18
+ description: "Validate and save the installed CMD absolute path",
19
+ inputSchema: cmdSetSchema,
20
+ readOnly: false,
21
+ destructive: false,
22
+ }, async (input, signal) => ({ ...(await service.set(input.path, signal)) }));
23
+ registerTool(server, "mfg.clear", {
24
+ description: "Clear configured CMD path",
25
+ inputSchema: emptyInputSchema,
26
+ readOnly: false,
27
+ destructive: false,
28
+ }, () => service.clear());
29
+ }
30
+ //# sourceMappingURL=configuration.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"configuration.js","sourceRoot":"","sources":["../../src/mcp/configuration.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAC9D,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAEjD,uFAAuF;AACvF,MAAM,UAAU,0BAA0B,CAAC,MAAiB,EAAE,OAAgB;IAC5E,YAAY,CACV,MAAM,EACN,YAAY,EACZ;QACE,WAAW,EAAE,sEAAsE;QACnF,WAAW,EAAE,gBAAgB;QAC7B,QAAQ,EAAE,IAAI;QACd,WAAW,EAAE,KAAK;KACnB,EACD,CAAC,MAAM,EAAE,MAAM,EAAE,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,CAC3C,CAAC;IAEF,YAAY,CACV,MAAM,EACN,SAAS,EACT;QACE,WAAW,EAAE,yBAAyB;QACtC,WAAW,EAAE,gBAAgB;QAC7B,QAAQ,EAAE,IAAI;QACd,WAAW,EAAE,KAAK;KACnB,EACD,KAAK,IAAI,EAAE,CAAC,CAAC,EAAE,GAAG,CAAC,MAAM,OAAO,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,EAAE,CAAC,CAClD,CAAC;IAEF,YAAY,CACV,MAAM,EACN,SAAS,EACT;QACE,WAAW,EAAE,mDAAmD;QAChE,WAAW,EAAE,YAAY;QACzB,QAAQ,EAAE,KAAK;QACf,WAAW,EAAE,KAAK;KACnB,EACD,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE,CAAC,CAAC,EAAE,GAAG,CAAC,MAAM,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,EAAE,CAAC,CAC1E,CAAC;IAEF,YAAY,CACV,MAAM,EACN,WAAW,EACX;QACE,WAAW,EAAE,2BAA2B;QACxC,WAAW,EAAE,gBAAgB;QAC7B,QAAQ,EAAE,KAAK;QACf,WAAW,EAAE,KAAK;KACnB,EACD,GAAG,EAAE,CAAC,OAAO,CAAC,KAAK,EAAE,CACtB,CAAC;AACJ,CAAC"}
@@ -0,0 +1,4 @@
1
+ import type { McpServer } from "@modelcontextprotocol/server";
2
+ import type { Service } from "../hpm-mfg-service.js";
3
+ /** Registers OS discovery and process-local target management tools. */
4
+ export declare function registerDiscoveryTools(server: McpServer, service: Service): void;
@@ -0,0 +1,30 @@
1
+ import { deviceDiscoverSchema, emptyInputSchema, targetCreateSchema, targetDeleteSchema, } from "./schemas.js";
2
+ import { registerTool } from "./registration.js";
3
+ /** Registers OS discovery and process-local target management tools. */
4
+ export function registerDiscoveryTools(server, service) {
5
+ registerTool(server, "device.discover", {
6
+ description: "Discover serial or HID devices using OS interfaces",
7
+ inputSchema: deviceDiscoverSchema,
8
+ readOnly: true,
9
+ destructive: false,
10
+ }, (input) => service.discover(input.transport, input.vid, input.pid));
11
+ registerTool(server, "device.create", {
12
+ description: "Probe with query-rte 0 and register an in-process ROM target",
13
+ inputSchema: targetCreateSchema,
14
+ readOnly: false,
15
+ destructive: false,
16
+ }, (input, signal) => service.create(input, signal));
17
+ registerTool(server, "device.list", {
18
+ description: "List registered targets",
19
+ inputSchema: emptyInputSchema,
20
+ readOnly: true,
21
+ destructive: false,
22
+ }, () => service.list());
23
+ registerTool(server, "device.delete", {
24
+ description: "Delete registered target",
25
+ inputSchema: targetDeleteSchema,
26
+ readOnly: false,
27
+ destructive: false,
28
+ }, (input) => service.delete(input.targetId));
29
+ }
30
+ //# sourceMappingURL=discovery.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"discovery.js","sourceRoot":"","sources":["../../src/mcp/discovery.ts"],"names":[],"mappings":"AAEA,OAAO,EACL,oBAAoB,EACpB,gBAAgB,EAChB,kBAAkB,EAClB,kBAAkB,GACnB,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAEjD,wEAAwE;AACxE,MAAM,UAAU,sBAAsB,CAAC,MAAiB,EAAE,OAAgB;IACxE,YAAY,CACV,MAAM,EACN,iBAAiB,EACjB;QACE,WAAW,EAAE,oDAAoD;QACjE,WAAW,EAAE,oBAAoB;QACjC,QAAQ,EAAE,IAAI;QACd,WAAW,EAAE,KAAK;KACnB,EACD,CAAC,KAAK,EAAE,EAAE,CAAC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAC,SAAS,EAAE,KAAK,CAAC,GAAG,EAAE,KAAK,CAAC,GAAG,CAAC,CACnE,CAAC;IAEF,YAAY,CACV,MAAM,EACN,eAAe,EACf;QACE,WAAW,EAAE,8DAA8D;QAC3E,WAAW,EAAE,kBAAkB;QAC/B,QAAQ,EAAE,KAAK;QACf,WAAW,EAAE,KAAK;KACnB,EACD,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,CACjD,CAAC;IAEF,YAAY,CACV,MAAM,EACN,aAAa,EACb;QACE,WAAW,EAAE,yBAAyB;QACtC,WAAW,EAAE,gBAAgB;QAC7B,QAAQ,EAAE,IAAI;QACd,WAAW,EAAE,KAAK;KACnB,EACD,GAAG,EAAE,CAAC,OAAO,CAAC,IAAI,EAAE,CACrB,CAAC;IAEF,YAAY,CACV,MAAM,EACN,eAAe,EACf;QACE,WAAW,EAAE,0BAA0B;QACvC,WAAW,EAAE,kBAAkB;QAC/B,QAAQ,EAAE,KAAK;QACf,WAAW,EAAE,KAAK;KACnB,EACD,CAAC,KAAK,EAAE,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,CAC1C,CAAC;AACJ,CAAC"}