@codesys/mcp-toolkit 1.5.7 → 2.0.0-alpha.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (109) hide show
  1. package/CHANGELOG.md +153 -183
  2. package/LICENSE +21 -21
  3. package/README.md +224 -107
  4. package/dist/actions.d.ts +28 -0
  5. package/dist/actions.js +98 -0
  6. package/dist/actions.js.map +1 -0
  7. package/dist/bridge/bridge.d.ts +105 -0
  8. package/dist/bridge/bridge.js +400 -0
  9. package/dist/bridge/bridge.js.map +1 -0
  10. package/dist/cli.d.ts +2 -0
  11. package/dist/cli.js +196 -0
  12. package/dist/cli.js.map +1 -0
  13. package/dist/codesys/cache.d.ts +48 -0
  14. package/dist/codesys/cache.js +82 -0
  15. package/dist/codesys/cache.js.map +1 -0
  16. package/dist/codesys/changes.d.ts +57 -0
  17. package/dist/codesys/changes.js +133 -0
  18. package/dist/codesys/changes.js.map +1 -0
  19. package/dist/codesys/decl.d.ts +45 -0
  20. package/dist/codesys/decl.js +251 -0
  21. package/dist/codesys/decl.js.map +1 -0
  22. package/dist/codesys/devices.d.ts +34 -0
  23. package/dist/codesys/devices.js +82 -0
  24. package/dist/codesys/devices.js.map +1 -0
  25. package/dist/codesys/diff.d.ts +13 -0
  26. package/dist/codesys/diff.js +61 -0
  27. package/dist/codesys/diff.js.map +1 -0
  28. package/dist/codesys/install.d.ts +40 -0
  29. package/dist/codesys/install.js +144 -0
  30. package/dist/codesys/install.js.map +1 -0
  31. package/dist/codesys/library-browse.d.ts +19 -0
  32. package/dist/codesys/library-browse.js +57 -0
  33. package/dist/codesys/library-browse.js.map +1 -0
  34. package/dist/codesys/outline.d.ts +32 -0
  35. package/dist/codesys/outline.js +219 -0
  36. package/dist/codesys/outline.js.map +1 -0
  37. package/dist/codesys/simulation.d.ts +34 -0
  38. package/dist/codesys/simulation.js +57 -0
  39. package/dist/codesys/simulation.js.map +1 -0
  40. package/dist/codesys/st.d.ts +36 -0
  41. package/dist/codesys/st.js +69 -0
  42. package/dist/codesys/st.js.map +1 -0
  43. package/dist/daemon.d.ts +46 -0
  44. package/dist/daemon.js +173 -0
  45. package/dist/daemon.js.map +1 -0
  46. package/dist/driver.d.ts +25 -0
  47. package/dist/driver.js +33 -0
  48. package/dist/driver.js.map +1 -0
  49. package/dist/panel/sim-panel.html +357 -0
  50. package/dist/panel/viewer.html +126 -0
  51. package/dist/panel-types.d.ts +20 -0
  52. package/dist/panel-types.js +3 -0
  53. package/dist/panel-types.js.map +1 -0
  54. package/dist/panel.d.ts +27 -0
  55. package/dist/panel.js +208 -0
  56. package/dist/panel.js.map +1 -0
  57. package/dist/server.d.ts +5 -0
  58. package/dist/server.js +33 -941
  59. package/dist/server.js.map +1 -0
  60. package/dist/tools.d.ts +103 -0
  61. package/dist/tools.js +793 -0
  62. package/dist/tools.js.map +1 -0
  63. package/dist/viewer.d.ts +14 -0
  64. package/dist/viewer.js +125 -0
  65. package/dist/viewer.js.map +1 -0
  66. package/package.json +37 -21
  67. package/watcher/mcp_compat.py +147 -0
  68. package/watcher/mcp_ops.py +1178 -0
  69. package/watcher/mcp_sim.py +246 -0
  70. package/watcher/watcher.py +255 -0
  71. package/.claude/settings.local.json +0 -29
  72. package/CLAUDE.md +0 -26
  73. package/CONTRIBUTING.md +0 -72
  74. package/README.md.enhanced +0 -155
  75. package/codesys-mcp-toolkit-1.2.0.tgz +0 -0
  76. package/codesys-mcp-toolkit-1.2.1.tgz +0 -0
  77. package/codesys-mcp-toolkit-1.5.7.tgz +0 -0
  78. package/dist/bin.js +0 -75
  79. package/dist/check_session_paths.js +0 -149
  80. package/dist/codesys_interop.js +0 -435
  81. package/dist/direct_session_command.js +0 -293
  82. package/dist/scriptLoader.js +0 -165
  83. package/dist/scripts/check_status.py +0 -21
  84. package/dist/scripts/compile_project.py +0 -65
  85. package/dist/scripts/create_method.py +0 -80
  86. package/dist/scripts/create_pou.py +0 -102
  87. package/dist/scripts/create_project.py +0 -116
  88. package/dist/scripts/create_property.py +0 -78
  89. package/dist/scripts/ensure_project_open.py +0 -154
  90. package/dist/scripts/find_object_by_path.py +0 -111
  91. package/dist/scripts/get_pou_code.py +0 -91
  92. package/dist/scripts/get_project_structure.py +0 -72
  93. package/dist/scripts/open_project.py +0 -25
  94. package/dist/scripts/save_project.py +0 -29
  95. package/dist/scripts/session_status.py +0 -281
  96. package/dist/scripts/set_pou_code.py +0 -109
  97. package/dist/scripts/start_session.py +0 -809
  98. package/dist/scripts/stop_session.py +0 -324
  99. package/dist/sessionManager.js +0 -798
  100. package/docs/configuration.md +0 -141
  101. package/docs/index.md +0 -26
  102. package/docs/installation.md +0 -84
  103. package/docs/session_management.md +0 -110
  104. package/examples/README.md +0 -78
  105. package/examples/sample_config.json +0 -32
  106. package/replacements_session_status.txt +0 -16
  107. package/scriptDoc.txt +0 -8679
  108. package/scripts/build.js +0 -25
  109. package/scripts/fix_fstrings.py +0 -76
@@ -0,0 +1,48 @@
1
+ /**
2
+ * What the server knows about the open project, for the workspace panel.
3
+ *
4
+ * The panel must never call CODESYS itself: the bridge runs one request at a
5
+ * time, so panel polling would stall the model's tool calls. Instead the
6
+ * tools keep this cache current as a side effect of their own calls (open,
7
+ * export, write, create, delete, rename, compile), and the panel reads it.
8
+ */
9
+ import type { TreeNode } from "./st.js";
10
+ export interface CompileResult {
11
+ at: string;
12
+ errors: number;
13
+ warnings: number;
14
+ messages: {
15
+ severity: string;
16
+ text: string;
17
+ object?: string | null;
18
+ position?: string | null;
19
+ length?: number;
20
+ code?: string;
21
+ }[];
22
+ }
23
+ export interface Focus {
24
+ /** Object path the model last touched. */
25
+ path: string;
26
+ action: "read" | "write" | "create" | "delete" | "rename" | "revert";
27
+ at: string;
28
+ }
29
+ export declare class ProjectCache {
30
+ project?: string;
31
+ nodes?: TreeNode[];
32
+ /** Bumped on every change, so the panel refetches only when needed. */
33
+ version: number;
34
+ compile?: CompileResult;
35
+ focus?: Focus;
36
+ reset(project?: string): void;
37
+ setAll(nodes: TreeNode[]): void;
38
+ /** Replace or add one object (and keep the order: new ones go after their parent's last child). */
39
+ upsert(node: TreeNode): void;
40
+ /** Remove an object and everything under it. */
41
+ remove(path: string): void;
42
+ rename(path: string, newName: string): void;
43
+ /** Something the workspace shows changed without a node change (e.g. the review baseline). */
44
+ bump(): void;
45
+ touch(path: string, action: Focus["action"]): void;
46
+ setCompile(c: CompileResult): void;
47
+ get(path: string): TreeNode | undefined;
48
+ }
@@ -0,0 +1,82 @@
1
+ export class ProjectCache {
2
+ project;
3
+ nodes;
4
+ /** Bumped on every change, so the panel refetches only when needed. */
5
+ version = 0;
6
+ compile;
7
+ focus;
8
+ reset(project) {
9
+ this.project = project;
10
+ this.nodes = undefined;
11
+ this.compile = undefined;
12
+ this.focus = undefined;
13
+ this.version++;
14
+ }
15
+ setAll(nodes) {
16
+ this.nodes = nodes;
17
+ this.version++;
18
+ }
19
+ /** Replace or add one object (and keep the order: new ones go after their parent's last child). */
20
+ upsert(node) {
21
+ if (!this.nodes)
22
+ return;
23
+ const key = node.path.toLowerCase();
24
+ const i = this.nodes.findIndex((n) => n.path.toLowerCase() === key);
25
+ if (i >= 0)
26
+ this.nodes[i] = { ...this.nodes[i], ...node };
27
+ else {
28
+ const parent = node.path.includes("/") ? node.path.slice(0, node.path.lastIndexOf("/")).toLowerCase() : "";
29
+ let at = this.nodes.length;
30
+ for (let k = this.nodes.length - 1; k >= 0; k--) {
31
+ const p = this.nodes[k].path.toLowerCase();
32
+ if (p === parent || p.startsWith(parent ? parent + "/" : "")) {
33
+ at = k + 1;
34
+ break;
35
+ }
36
+ }
37
+ this.nodes.splice(at, 0, node);
38
+ }
39
+ this.version++;
40
+ }
41
+ /** Remove an object and everything under it. */
42
+ remove(path) {
43
+ if (!this.nodes)
44
+ return;
45
+ const key = path.toLowerCase();
46
+ this.nodes = this.nodes.filter((n) => n.path.toLowerCase() !== key && !n.path.toLowerCase().startsWith(key + "/"));
47
+ this.version++;
48
+ }
49
+ rename(path, newName) {
50
+ if (!this.nodes)
51
+ return;
52
+ const key = path.toLowerCase();
53
+ const parent = path.includes("/") ? path.slice(0, path.lastIndexOf("/") + 1) : "";
54
+ const to = parent + newName;
55
+ this.nodes = this.nodes.map((n) => {
56
+ const p = n.path.toLowerCase();
57
+ if (p === key)
58
+ return { ...n, path: to, name: newName };
59
+ if (p.startsWith(key + "/"))
60
+ return { ...n, path: to + n.path.slice(path.length) };
61
+ return n;
62
+ });
63
+ this.version++;
64
+ }
65
+ /** Something the workspace shows changed without a node change (e.g. the review baseline). */
66
+ bump() {
67
+ this.version++;
68
+ }
69
+ touch(path, action) {
70
+ this.focus = { path, action, at: new Date().toISOString() };
71
+ this.version++;
72
+ }
73
+ setCompile(c) {
74
+ this.compile = c;
75
+ this.version++;
76
+ }
77
+ get(path) {
78
+ const key = path.toLowerCase();
79
+ return this.nodes?.find((n) => n.path.toLowerCase() === key);
80
+ }
81
+ }
82
+ //# sourceMappingURL=cache.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cache.js","sourceRoot":"","sources":["../../src/codesys/cache.ts"],"names":[],"mappings":"AAwBA,MAAM,OAAO,YAAY;IACvB,OAAO,CAAU;IACjB,KAAK,CAAc;IACnB,uEAAuE;IACvE,OAAO,GAAG,CAAC,CAAC;IACZ,OAAO,CAAiB;IACxB,KAAK,CAAS;IAEd,KAAK,CAAC,OAAgB;QACpB,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;QACvB,IAAI,CAAC,KAAK,GAAG,SAAS,CAAC;QACvB,IAAI,CAAC,OAAO,GAAG,SAAS,CAAC;QACzB,IAAI,CAAC,KAAK,GAAG,SAAS,CAAC;QACvB,IAAI,CAAC,OAAO,EAAE,CAAC;IACjB,CAAC;IAED,MAAM,CAAC,KAAiB;QACtB,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;QACnB,IAAI,CAAC,OAAO,EAAE,CAAC;IACjB,CAAC;IAED,mGAAmG;IACnG,MAAM,CAAC,IAAc;QACnB,IAAI,CAAC,IAAI,CAAC,KAAK;YAAE,OAAO;QACxB,MAAM,GAAG,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC;QACpC,MAAM,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,WAAW,EAAE,KAAK,GAAG,CAAC,CAAC;QACpE,IAAI,CAAC,IAAI,CAAC;YAAE,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAE,EAAE,GAAG,IAAI,EAAE,CAAC;aACtD,CAAC;YACJ,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YAC3G,IAAI,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC;YAC3B,KAAK,IAAI,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;gBAChD,MAAM,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAE,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC;gBAC5C,IAAI,CAAC,KAAK,MAAM,IAAI,CAAC,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,GAAG,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC;oBAC7D,EAAE,GAAG,CAAC,GAAG,CAAC,CAAC;oBACX,MAAM;gBACR,CAAC;YACH,CAAC;YACD,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,EAAE,CAAC,EAAE,IAAI,CAAC,CAAC;QACjC,CAAC;QACD,IAAI,CAAC,OAAO,EAAE,CAAC;IACjB,CAAC;IAED,gDAAgD;IAChD,MAAM,CAAC,IAAY;QACjB,IAAI,CAAC,IAAI,CAAC,KAAK;YAAE,OAAO;QACxB,MAAM,GAAG,GAAG,IAAI,CAAC,WAAW,EAAE,CAAC;QAC/B,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,WAAW,EAAE,KAAK,GAAG,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,UAAU,CAAC,GAAG,GAAG,GAAG,CAAC,CAAC,CAAC;QACnH,IAAI,CAAC,OAAO,EAAE,CAAC;IACjB,CAAC;IAED,MAAM,CAAC,IAAY,EAAE,OAAe;QAClC,IAAI,CAAC,IAAI,CAAC,KAAK;YAAE,OAAO;QACxB,MAAM,GAAG,GAAG,IAAI,CAAC,WAAW,EAAE,CAAC;QAC/B,MAAM,MAAM,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QAClF,MAAM,EAAE,GAAG,MAAM,GAAG,OAAO,CAAC;QAC5B,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE;YAChC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC;YAC/B,IAAI,CAAC,KAAK,GAAG;gBAAE,OAAO,EAAE,GAAG,CAAC,EAAE,IAAI,EAAE,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC;YACxD,IAAI,CAAC,CAAC,UAAU,CAAC,GAAG,GAAG,GAAG,CAAC;gBAAE,OAAO,EAAE,GAAG,CAAC,EAAE,IAAI,EAAE,EAAE,GAAG,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;YACnF,OAAO,CAAC,CAAC;QACX,CAAC,CAAC,CAAC;QACH,IAAI,CAAC,OAAO,EAAE,CAAC;IACjB,CAAC;IAED,8FAA8F;IAC9F,IAAI;QACF,IAAI,CAAC,OAAO,EAAE,CAAC;IACjB,CAAC;IAED,KAAK,CAAC,IAAY,EAAE,MAAuB;QACzC,IAAI,CAAC,KAAK,GAAG,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,EAAE,CAAC;QAC5D,IAAI,CAAC,OAAO,EAAE,CAAC;IACjB,CAAC;IAED,UAAU,CAAC,CAAgB;QACzB,IAAI,CAAC,OAAO,GAAG,CAAC,CAAC;QACjB,IAAI,CAAC,OAAO,EAAE,CAAC;IACjB,CAAC;IAED,GAAG,CAAC,IAAY;QACd,MAAM,GAAG,GAAG,IAAI,CAAC,WAAW,EAAE,CAAC;QAC/B,OAAO,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,WAAW,EAAE,KAAK,GAAG,CAAC,CAAC;IAC/D,CAAC;CACF"}
@@ -0,0 +1,57 @@
1
+ import type { TreeNode } from "./st.js";
2
+ export { formatDiff, lineDiff, type DiffOp } from "./diff.js";
3
+ export interface SnapObject {
4
+ path: string;
5
+ name: string;
6
+ kind: TreeNode["kind"];
7
+ sub?: string;
8
+ st?: boolean;
9
+ declaration?: string;
10
+ implementation?: string;
11
+ /** PLCopenXML of a graphical body (SFC, CFC, LD, FBD), to recreate it. */
12
+ xml?: string;
13
+ }
14
+ export interface Checkpoint {
15
+ name: string;
16
+ at: string;
17
+ project: string;
18
+ objects: SnapObject[];
19
+ }
20
+ export declare function snapshot(nodes: TreeNode[]): SnapObject[];
21
+ export interface ObjectChange {
22
+ path: string;
23
+ kind: string;
24
+ change: "added" | "removed" | "modified";
25
+ decl?: {
26
+ plus: number;
27
+ minus: number;
28
+ };
29
+ impl?: {
30
+ plus: number;
31
+ minus: number;
32
+ };
33
+ }
34
+ export declare function diffObjects(before: SnapObject[], after: SnapObject[]): ObjectChange[];
35
+ export declare class ChangeStore {
36
+ readonly root: string;
37
+ /** Projects that already have a session-start checkpoint in this process. */
38
+ private started;
39
+ constructor(root: string);
40
+ dir(project: string): string;
41
+ private file;
42
+ save(project: string, name: string, nodes: TreeNode[]): Promise<Checkpoint>;
43
+ load(project: string, name: string): Promise<Checkpoint | undefined>;
44
+ list(project: string): Promise<{
45
+ name: string;
46
+ at: string;
47
+ objects: number;
48
+ }[]>;
49
+ /** Take the session-start checkpoint once per project per process. */
50
+ sessionStart(project: string, exportNodes: () => Promise<TreeNode[]>): Promise<boolean>;
51
+ /** The review baseline (what the user has accepted); falls back to session-start. */
52
+ review(project: string): Promise<Checkpoint | undefined>;
53
+ /** Accept the current state of an object and everything under it into the review baseline. */
54
+ accept(project: string, path: string, now: SnapObject[]): Promise<number>;
55
+ }
56
+ /** Name of the checkpoint the workspace's diffs and badges compare against. */
57
+ export declare const REVIEW = "review";
@@ -0,0 +1,133 @@
1
+ /**
2
+ * Change tracking for CODESYS edits: checkpoints (snapshots of every ST
3
+ * object's text), diffs against them, and what's needed to revert.
4
+ * Checkpoints live on disk per project, so they survive a server restart.
5
+ */
6
+ import { createHash } from "node:crypto";
7
+ import { existsSync } from "node:fs";
8
+ import { mkdir, readdir, readFile, writeFile } from "node:fs/promises";
9
+ import { basename, join } from "node:path";
10
+ import { countDiff as count, lineDiff } from "./diff.js";
11
+ export { formatDiff, lineDiff } from "./diff.js";
12
+ /** Object kinds whose text is tracked (folders are tracked for structure only). */
13
+ const TRACKED = new Set(["pou", "method", "property", "accessor", "action", "dut", "gvl", "interface", "interface_method", "folder"]);
14
+ export function snapshot(nodes) {
15
+ return nodes
16
+ .filter((n) => TRACKED.has(n.kind))
17
+ .map((n) => ({
18
+ path: n.path,
19
+ name: n.name,
20
+ kind: n.kind,
21
+ ...(n.sub ? { sub: n.sub } : {}),
22
+ ...(n.st === false ? { st: false } : {}),
23
+ ...(n.declaration !== undefined ? { declaration: n.declaration } : {}),
24
+ ...(n.implementation !== undefined ? { implementation: n.implementation } : {}),
25
+ ...(n.xml !== undefined ? { xml: n.xml } : {}),
26
+ }));
27
+ }
28
+ const norm = (s) => (s ?? "").replace(/\r\n?/g, "\n").replace(/\s+$/, "");
29
+ export function diffObjects(before, after) {
30
+ const b = new Map(before.map((o) => [o.path.toLowerCase(), o]));
31
+ const a = new Map(after.map((o) => [o.path.toLowerCase(), o]));
32
+ const out = [];
33
+ for (const [k, o] of a) {
34
+ const old = b.get(k);
35
+ if (!old) {
36
+ out.push({ path: o.path, kind: o.kind, change: "added" });
37
+ continue;
38
+ }
39
+ const d = norm(old.declaration) === norm(o.declaration) ? undefined : count(lineDiff(norm(old.declaration), norm(o.declaration)));
40
+ const i = norm(old.implementation) === norm(o.implementation) ? undefined : count(lineDiff(norm(old.implementation), norm(o.implementation)));
41
+ if (d || i)
42
+ out.push({ path: o.path, kind: o.kind, change: "modified", ...(d ? { decl: d } : {}), ...(i ? { impl: i } : {}) });
43
+ }
44
+ for (const [k, o] of b)
45
+ if (!a.has(k))
46
+ out.push({ path: o.path, kind: o.kind, change: "removed" });
47
+ return out.sort((x, y) => x.path.localeCompare(y.path));
48
+ }
49
+ export class ChangeStore {
50
+ root;
51
+ /** Projects that already have a session-start checkpoint in this process. */
52
+ started = new Set();
53
+ constructor(root) {
54
+ this.root = root;
55
+ }
56
+ dir(project) {
57
+ const base = basename(project).replace(/\.project$/i, "").replace(/[^A-Za-z0-9_.-]/g, "_");
58
+ const h = createHash("sha256").update(project.toLowerCase()).digest("hex").slice(0, 8);
59
+ return join(this.root, `${base}-${h}`);
60
+ }
61
+ file(project, name) {
62
+ return join(this.dir(project), `${name.replace(/[^A-Za-z0-9_.-]/g, "_")}.json`);
63
+ }
64
+ async save(project, name, nodes) {
65
+ const cp = { name, at: new Date().toISOString(), project, objects: snapshot(nodes) };
66
+ await mkdir(this.dir(project), { recursive: true });
67
+ await writeFile(this.file(project, name), JSON.stringify(cp), "utf8");
68
+ return cp;
69
+ }
70
+ async load(project, name) {
71
+ const f = this.file(project, name);
72
+ if (!existsSync(f))
73
+ return undefined;
74
+ return JSON.parse(await readFile(f, "utf8"));
75
+ }
76
+ async list(project) {
77
+ const d = this.dir(project);
78
+ if (!existsSync(d))
79
+ return [];
80
+ const out = [];
81
+ for (const f of await readdir(d)) {
82
+ if (!f.endsWith(".json"))
83
+ continue;
84
+ try {
85
+ const cp = JSON.parse(await readFile(join(d, f), "utf8"));
86
+ out.push({ name: cp.name, at: cp.at, objects: cp.objects.length });
87
+ }
88
+ catch {
89
+ /* skip unreadable */
90
+ }
91
+ }
92
+ return out.sort((x, y) => x.at.localeCompare(y.at));
93
+ }
94
+ /** Take the session-start checkpoint once per project per process. */
95
+ async sessionStart(project, exportNodes) {
96
+ const key = project.toLowerCase();
97
+ if (this.started.has(key))
98
+ return false;
99
+ this.started.add(key);
100
+ try {
101
+ const nodes = await exportNodes();
102
+ await this.save(project, "session-start", nodes);
103
+ // The review baseline starts as the session start; Accept moves it per object.
104
+ await this.save(project, REVIEW, nodes);
105
+ return true;
106
+ }
107
+ catch {
108
+ this.started.delete(key);
109
+ return false;
110
+ }
111
+ }
112
+ /** The review baseline (what the user has accepted); falls back to session-start. */
113
+ async review(project) {
114
+ return (await this.load(project, REVIEW)) ?? (await this.load(project, "session-start"));
115
+ }
116
+ /** Accept the current state of an object and everything under it into the review baseline. */
117
+ async accept(project, path, now) {
118
+ const cp = await this.review(project);
119
+ if (!cp)
120
+ throw new Error("No review baseline yet: open the project first.");
121
+ const key = path.replace(/^\/+/, "").toLowerCase();
122
+ const inTree = (o) => o.path.toLowerCase() === key || o.path.toLowerCase().startsWith(key + "/");
123
+ const kept = cp.objects.filter((o) => !inTree(o));
124
+ const taken = now.filter(inTree);
125
+ const objects = [...kept, ...taken];
126
+ await mkdir(this.dir(project), { recursive: true });
127
+ await writeFile(this.file(project, REVIEW), JSON.stringify({ ...cp, name: REVIEW, at: new Date().toISOString(), objects }), "utf8");
128
+ return taken.length;
129
+ }
130
+ }
131
+ /** Name of the checkpoint the workspace's diffs and badges compare against. */
132
+ export const REVIEW = "review";
133
+ //# sourceMappingURL=changes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"changes.js","sourceRoot":"","sources":["../../src/codesys/changes.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,45 @@
1
+ /**
2
+ * A tolerant parser for CODESYS ST declarations: headers (kind, name,
3
+ * EXTENDS / IMPLEMENTS, return type, modifiers), variable sections with
4
+ * names, types, initial values, AT addresses and comments, enum members and
5
+ * struct fields. Used for the outline and the I/O list; it never rejects
6
+ * input, it just extracts what it recognises.
7
+ */
8
+ export type SectionKind = "VAR_INPUT" | "VAR_OUTPUT" | "VAR_IN_OUT" | "VAR" | "VAR_TEMP" | "VAR_STAT" | "VAR_INST" | "VAR_GLOBAL" | "VAR_EXTERNAL" | "VAR_CONFIG";
9
+ export interface VarDecl {
10
+ name: string;
11
+ type: string;
12
+ init?: string;
13
+ at?: string;
14
+ comment?: string;
15
+ section: SectionKind;
16
+ constant?: boolean;
17
+ retain?: boolean;
18
+ persistent?: boolean;
19
+ }
20
+ export interface Header {
21
+ keyword: string;
22
+ name?: string;
23
+ modifiers: string[];
24
+ extends?: string[];
25
+ implements?: string[];
26
+ returnType?: string;
27
+ attributes: string[];
28
+ }
29
+ export interface ParsedDecl {
30
+ header: Header;
31
+ vars: VarDecl[];
32
+ /** Enum members with optional values (DUT enums). */
33
+ enumMembers?: {
34
+ name: string;
35
+ value?: string;
36
+ }[];
37
+ /** Base type of an enum (`(A, B) INT`) or an alias target. */
38
+ baseType?: string;
39
+ /** STRUCT / UNION fields (DUTs). */
40
+ fields?: VarDecl[];
41
+ dutKind?: "enum" | "struct" | "union" | "alias";
42
+ }
43
+ export declare function parseDeclaration(decl: string | undefined): ParsedDecl;
44
+ /** One-line signature, e.g. `METHOD Reset(bHard : BOOL) : BOOL`. */
45
+ export declare function signature(p: ParsedDecl, name?: string): string;
@@ -0,0 +1,251 @@
1
+ /**
2
+ * A tolerant parser for CODESYS ST declarations: headers (kind, name,
3
+ * EXTENDS / IMPLEMENTS, return type, modifiers), variable sections with
4
+ * names, types, initial values, AT addresses and comments, enum members and
5
+ * struct fields. Used for the outline and the I/O list; it never rejects
6
+ * input, it just extracts what it recognises.
7
+ */
8
+ const SECTION_RE = /^(VAR_INPUT|VAR_OUTPUT|VAR_IN_OUT|VAR_GLOBAL|VAR_EXTERNAL|VAR_CONFIG|VAR_TEMP|VAR_STAT|VAR_INST|VAR)\b(.*)$/i;
9
+ const MODIFIERS = new Set(["PUBLIC", "PRIVATE", "PROTECTED", "INTERNAL", "ABSTRACT", "FINAL"]);
10
+ /** Split text into statements ending in `;` outside brackets, strings and comments; keep the trailing line comment. */
11
+ function statements(text) {
12
+ const out = [];
13
+ let cur = "";
14
+ let depth = 0;
15
+ let pendingComment;
16
+ let i = 0;
17
+ const push = () => {
18
+ const body = cur.replace(/\s+/g, " ").trim();
19
+ if (body)
20
+ out.push({ body, ...(pendingComment ? { comment: pendingComment } : {}) });
21
+ cur = "";
22
+ pendingComment = undefined;
23
+ };
24
+ while (i < text.length) {
25
+ const c = text[i];
26
+ const two = text.slice(i, i + 2);
27
+ if (two === "//") {
28
+ const end = text.indexOf("\n", i);
29
+ const comment = text.slice(i + 2, end < 0 ? undefined : end).trim();
30
+ // A comment right after `;` on the same line belongs to the previous statement.
31
+ const last = out.at(-1);
32
+ if (!cur.trim() && last && !last.comment && comment)
33
+ last.comment = comment;
34
+ else if (comment)
35
+ pendingComment ??= comment;
36
+ i = end < 0 ? text.length : end;
37
+ continue;
38
+ }
39
+ if (two === "(*" || two === "/*") {
40
+ const close = two === "(*" ? "*)" : "*/";
41
+ const end = text.indexOf(close, i + 2);
42
+ const comment = text.slice(i + 2, end < 0 ? undefined : end).trim();
43
+ const last = out.at(-1);
44
+ if (!cur.trim() && last && !last.comment && comment && !comment.includes("\n"))
45
+ last.comment = comment;
46
+ i = end < 0 ? text.length : end + 2;
47
+ continue;
48
+ }
49
+ if (c === "{") {
50
+ const end = text.indexOf("}", i);
51
+ cur += text.slice(i, end < 0 ? undefined : end + 1);
52
+ i = end < 0 ? text.length : end + 1;
53
+ continue;
54
+ }
55
+ if (c === "'" || c === '"') {
56
+ let j = i + 1;
57
+ while (j < text.length && text[j] !== c)
58
+ j += text[j] === "$" ? 2 : 1;
59
+ cur += text.slice(i, j + 1);
60
+ i = j + 1;
61
+ continue;
62
+ }
63
+ if (c === "(" || c === "[")
64
+ depth++;
65
+ if (c === ")" || c === "]")
66
+ depth = Math.max(0, depth - 1);
67
+ if (c === ";" && depth === 0) {
68
+ push();
69
+ i++;
70
+ continue;
71
+ }
72
+ if (c === "\n" && depth === 0) {
73
+ // Section keywords and headers have no `;`: end them at the line break.
74
+ const t = cur.trim();
75
+ // `TYPE X :` continues on the next line (the enum list or STRUCT).
76
+ if (/^(\{[^}]*\}\s*)*TYPE\b[^;]*:\s*$/i.test(t))
77
+ cur += " ";
78
+ else if (/^(\{[^}]*\}\s*)*(VAR\w*|END_VAR|END_STRUCT|END_UNION|END_TYPE|STRUCT|UNION|(PROGRAM|FUNCTION_BLOCK|FUNCTION|METHOD|PROPERTY|INTERFACE|TYPE)\b.*)(\s+\w+)*$/i.test(t) && !/:=/.test(t.replace(/^TYPE\b.*/i, "")))
79
+ push();
80
+ else
81
+ cur += " ";
82
+ i++;
83
+ continue;
84
+ }
85
+ cur += c;
86
+ i++;
87
+ }
88
+ push();
89
+ return out;
90
+ }
91
+ const splitList = (s) => s
92
+ .split(",")
93
+ .map((x) => x.trim())
94
+ .filter(Boolean);
95
+ function parseHeader(stmt) {
96
+ const attributes = [...stmt.matchAll(/\{\s*attribute\s+'([^']+)'(?:\s*:=\s*'[^']*')?\s*\}/gi)].map((m) => m[1]);
97
+ const s = stmt.replace(/\{[^}]*\}/g, " ").replace(/\s+/g, " ").trim();
98
+ const m = /^(PROGRAM|FUNCTION_BLOCK|FUNCTION|METHOD|PROPERTY|INTERFACE|TYPE|VAR_GLOBAL|TEST_PROGRAM|TEST_FUNCTION_BLOCK)\b\s*(.*)$/i.exec(s);
99
+ if (!m)
100
+ return { keyword: "", modifiers: [], attributes };
101
+ const keyword = m[1].toUpperCase();
102
+ let rest = m[2];
103
+ const modifiers = [];
104
+ for (;;) {
105
+ const w = /^(\w+)\s*/.exec(rest);
106
+ if (w && MODIFIERS.has(w[1].toUpperCase())) {
107
+ modifiers.push(w[1].toUpperCase());
108
+ rest = rest.slice(w[0].length);
109
+ }
110
+ else
111
+ break;
112
+ }
113
+ const h = { keyword, modifiers, attributes };
114
+ const name = /^([A-Za-z_]\w*)/.exec(rest);
115
+ if (name) {
116
+ h.name = name[1];
117
+ rest = rest.slice(name[0].length).trim();
118
+ }
119
+ const ret = /^:\s*(.+?)(?=\s+(EXTENDS|IMPLEMENTS)\b|$)/i.exec(rest);
120
+ if (ret && keyword !== "TYPE")
121
+ h.returnType = ret[1].trim();
122
+ const ext = /\bEXTENDS\s+(.+?)(?=\s+IMPLEMENTS\b|$)/i.exec(rest);
123
+ if (ext)
124
+ h.extends = splitList(ext[1]);
125
+ const imp = /\bIMPLEMENTS\s+(.+)$/i.exec(rest);
126
+ if (imp)
127
+ h.implements = splitList(imp[1]);
128
+ return h;
129
+ }
130
+ function parseVar(body, section, flags, comment) {
131
+ const s = body.replace(/\{[^}]*\}/g, " ").trim();
132
+ const m = /^([A-Za-z_][\w\s,]*?)(?:\s+AT\s+(%\S+))?\s*:\s*([\s\S]+)$/i.exec(s);
133
+ if (!m)
134
+ return [];
135
+ let type = m[3].trim();
136
+ let init;
137
+ // `:=` at top level separates type and initial value.
138
+ let depth = 0;
139
+ for (let i = 0; i < type.length - 1; i++) {
140
+ const c = type[i];
141
+ if (c === "(" || c === "[")
142
+ depth++;
143
+ else if (c === ")" || c === "]")
144
+ depth--;
145
+ else if (depth === 0 && c === ":" && type[i + 1] === "=") {
146
+ init = type.slice(i + 2).trim();
147
+ type = type.slice(0, i).trim();
148
+ break;
149
+ }
150
+ }
151
+ return splitList(m[1]).map((name) => ({
152
+ name,
153
+ type,
154
+ section,
155
+ ...(init !== undefined ? { init } : {}),
156
+ ...(m[2] ? { at: m[2] } : {}),
157
+ ...(comment ? { comment } : {}),
158
+ ...(flags.constant ? { constant: true } : {}),
159
+ ...(flags.retain ? { retain: true } : {}),
160
+ ...(flags.persistent ? { persistent: true } : {}),
161
+ }));
162
+ }
163
+ export function parseDeclaration(decl) {
164
+ const stmts = statements(decl ?? "");
165
+ const result = { header: { keyword: "", modifiers: [], attributes: [] }, vars: [] };
166
+ let section;
167
+ let flags = { constant: false, retain: false, persistent: false };
168
+ let inStruct;
169
+ for (let k = 0; k < stmts.length; k++) {
170
+ const { body, comment } = stmts[k];
171
+ const plain = body.replace(/\{[^}]*\}/g, " ").trim();
172
+ if (!result.header.keyword) {
173
+ const h = parseHeader(body);
174
+ if (h.keyword) {
175
+ result.header = h;
176
+ if (h.keyword === "VAR_GLOBAL") {
177
+ section = "VAR_GLOBAL";
178
+ flags = { constant: /\bCONSTANT\b/i.test(body), retain: /\bRETAIN\b/i.test(body), persistent: /\bPERSISTENT\b/i.test(body) };
179
+ }
180
+ if (h.keyword === "TYPE") {
181
+ // TYPE Name : (A := 0, B) INT | TYPE Name : STRUCT | TYPE Name : INT
182
+ const t = /^TYPE\s+\w+\s*(?:EXTENDS\s+[\w.]+\s*)?:\s*([\s\S]*)$/i.exec(plain)?.[1]?.trim() ?? "";
183
+ if (t.startsWith("(")) {
184
+ const close = t.lastIndexOf(")");
185
+ result.dutKind = "enum";
186
+ result.enumMembers = splitList(t.slice(1, close)).map((x) => {
187
+ const [n, v] = x.split(":=").map((y) => y.trim());
188
+ return v !== undefined ? { name: n, value: v } : { name: n };
189
+ });
190
+ const base = t.slice(close + 1).trim();
191
+ if (base)
192
+ result.baseType = base;
193
+ }
194
+ else if (/^STRUCT\b/i.test(t)) {
195
+ result.dutKind = "struct";
196
+ inStruct = "struct";
197
+ result.fields = [];
198
+ }
199
+ else if (/^UNION\b/i.test(t)) {
200
+ result.dutKind = "union";
201
+ inStruct = "union";
202
+ result.fields = [];
203
+ }
204
+ else if (t) {
205
+ result.dutKind = "alias";
206
+ result.baseType = t;
207
+ }
208
+ }
209
+ continue;
210
+ }
211
+ }
212
+ const sec = SECTION_RE.exec(plain);
213
+ if (sec) {
214
+ section = sec[1].toUpperCase();
215
+ flags = { constant: /\bCONSTANT\b/i.test(sec[2]), retain: /\bRETAIN\b/i.test(sec[2]), persistent: /\bPERSISTENT\b/i.test(sec[2]) };
216
+ continue;
217
+ }
218
+ if (/^END_VAR\b/i.test(plain)) {
219
+ section = undefined;
220
+ continue;
221
+ }
222
+ if (/^(STRUCT|UNION)\b/i.test(plain) && result.header.keyword === "TYPE") {
223
+ inStruct = /^STRUCT/i.test(plain) ? "struct" : "union";
224
+ result.dutKind ??= inStruct;
225
+ result.fields ??= [];
226
+ continue;
227
+ }
228
+ if (/^END_(STRUCT|UNION|TYPE)\b/i.test(plain)) {
229
+ inStruct = undefined;
230
+ continue;
231
+ }
232
+ if (inStruct) {
233
+ result.fields.push(...parseVar(body, "VAR", { constant: false, retain: false, persistent: false }, comment));
234
+ continue;
235
+ }
236
+ if (section)
237
+ result.vars.push(...parseVar(body, section, flags, comment));
238
+ }
239
+ return result;
240
+ }
241
+ /** One-line signature, e.g. `METHOD Reset(bHard : BOOL) : BOOL`. */
242
+ export function signature(p, name) {
243
+ const h = p.header;
244
+ const ins = p.vars.filter((v) => v.section === "VAR_INPUT" || v.section === "VAR_IN_OUT").map((v) => `${v.section === "VAR_IN_OUT" ? "VAR_IN_OUT " : ""}${v.name} : ${v.type}`);
245
+ const outs = p.vars.filter((v) => v.section === "VAR_OUTPUT").map((v) => `${v.name} : ${v.type}`);
246
+ let s = `${name ?? h.name ?? "?"}(${ins.join(", ")}${outs.length ? `; out ${outs.join(", ")}` : ""})`;
247
+ if (h.returnType)
248
+ s += ` : ${h.returnType}`;
249
+ return s;
250
+ }
251
+ //# sourceMappingURL=decl.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"decl.js","sourceRoot":"","sources":["../../src/codesys/decl.ts"],"names":[],"mappings":"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"}