@aryacode/dsh-engineering 0.8.4 → 0.9.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 (64) hide show
  1. package/CHANGELOG.md +41 -0
  2. package/README.md +7 -1
  3. package/cordis.patch.yml +7 -0
  4. package/entries/resources.js +23 -0
  5. package/package.json +6 -3
  6. package/vendor/ftview/lib/edit/tools.d.ts +1 -1
  7. package/vendor/ftview/lib/edit/tools.js +26 -6
  8. package/vendor/ftview/lib/edit.js +2 -1
  9. package/vendor/ftview/lib/session.d.ts +9 -0
  10. package/vendor/ftview/lib/session.js +11 -0
  11. package/vendor/ftview/lib/style.d.ts +60 -0
  12. package/vendor/ftview/lib/style.js +109 -0
  13. package/vendor/l5x/lib/engine/style.d.ts +67 -0
  14. package/vendor/l5x/lib/engine/style.js +119 -0
  15. package/vendor/l5x/lib/session.d.ts +9 -0
  16. package/vendor/l5x/lib/session.js +11 -0
  17. package/vendor/resources/LICENSE-CONTENT.md +17 -0
  18. package/vendor/resources/SKILL.md +27 -0
  19. package/vendor/resources/SOURCE.json +6 -0
  20. package/vendor/resources/corpus/craft/craft-comments-and-intent.md +29 -0
  21. package/vendor/resources/corpus/craft/craft-debounce-and-filtering.md +29 -0
  22. package/vendor/resources/corpus/craft/craft-fault-handling.md +32 -0
  23. package/vendor/resources/corpus/craft/craft-naming.md +30 -0
  24. package/vendor/resources/corpus/craft/craft-review-checklist.md +29 -0
  25. package/vendor/resources/corpus/craft/craft-units-and-ranges.md +32 -0
  26. package/vendor/resources/corpus/iec/iec-ld-fbd-equivalence.md +31 -0
  27. package/vendor/resources/corpus/iec/iec-sequences-and-sfc.md +32 -0
  28. package/vendor/resources/corpus/iec/iec-st-structure.md +33 -0
  29. package/vendor/resources/corpus/iec/iec-state-machines.md +33 -0
  30. package/vendor/resources/corpus/iec/iec-task-model.md +31 -0
  31. package/vendor/resources/corpus/iec/iec-types-and-scaling.md +32 -0
  32. package/vendor/resources/corpus/optix/optix-alarms-and-trends.md +30 -0
  33. package/vendor/resources/corpus/optix/optix-bindings-and-expressions.md +30 -0
  34. package/vendor/resources/corpus/optix/optix-netlogic-usage.md +29 -0
  35. package/vendor/resources/corpus/optix/optix-ui-structure.md +29 -0
  36. package/vendor/resources/corpus/rockwell/rockwell-aoi-and-udt.md +32 -0
  37. package/vendor/resources/corpus/rockwell/rockwell-fault-and-alarm-words.md +31 -0
  38. package/vendor/resources/corpus/rockwell/rockwell-hmi-handshake.md +33 -0
  39. package/vendor/resources/corpus/rockwell/rockwell-program-structure.md +32 -0
  40. package/vendor/resources/corpus/rockwell/rockwell-safety-boundaries.md +31 -0
  41. package/vendor/resources/corpus/rockwell/rockwell-tag-naming.md +33 -0
  42. package/vendor/resources/corpus/view/view-alarm-presentation.md +32 -0
  43. package/vendor/resources/corpus/view/view-colour-and-contrast.md +31 -0
  44. package/vendor/resources/corpus/view/view-faceplates.md +32 -0
  45. package/vendor/resources/corpus/view/view-hpm-01.md +33 -0
  46. package/vendor/resources/corpus/view/view-navigation.md +31 -0
  47. package/vendor/resources/corpus/view/view-popup-patterns.md +31 -0
  48. package/vendor/resources/corpus/view/view-screen-hierarchy.md +31 -0
  49. package/vendor/resources/corpus/yaskawa/yaskawa-cam-and-gear.md +31 -0
  50. package/vendor/resources/corpus/yaskawa/yaskawa-error-handling.md +31 -0
  51. package/vendor/resources/corpus/yaskawa/yaskawa-motion-function-blocks.md +32 -0
  52. package/vendor/resources/corpus/yaskawa/yaskawa-pou-organisation.md +29 -0
  53. package/vendor/resources/corpus/yaskawa/yaskawa-task-rates.md +30 -0
  54. package/vendor/resources/index.json +873 -0
  55. package/vendor/resources/lib/corpus.d.ts +80 -0
  56. package/vendor/resources/lib/corpus.js +126 -0
  57. package/vendor/resources/lib/index.d.ts +55 -0
  58. package/vendor/resources/lib/index.js +88 -0
  59. package/vendor/resources/lib/profile.d.ts +113 -0
  60. package/vendor/resources/lib/profile.js +52 -0
  61. package/vendor/resources/lib/store.d.ts +22 -0
  62. package/vendor/resources/lib/store.js +35 -0
  63. package/vendor/resources/lib/tools.d.ts +138 -0
  64. package/vendor/resources/lib/tools.js +190 -0
@@ -0,0 +1,138 @@
1
+ /**
2
+ * The three resource tools: read the corpus, profile the open project, review a
3
+ * draft.
4
+ *
5
+ * They are deliberately thin. The corpus tool reads generated files; the profile
6
+ * tool asks the product package that owns the parser; the review tool compares a
7
+ * product's prepared findings with the profile and the corpus rule IDs.
8
+ *
9
+ * @module dsh-engineering-resources/tools
10
+ */
11
+ import { getProfile } from './store.ts';
12
+ /** The reference tool definition. */
13
+ export declare const referenceTool: {
14
+ name: string;
15
+ description: string;
16
+ parameters: {
17
+ type: string;
18
+ properties: {
19
+ query: {
20
+ type: string;
21
+ description: string;
22
+ };
23
+ id: {
24
+ type: string;
25
+ description: string;
26
+ };
27
+ domain: {
28
+ type: string;
29
+ description: string;
30
+ };
31
+ limit: {
32
+ type: string;
33
+ description: string;
34
+ minimum: number;
35
+ maximum: number;
36
+ };
37
+ };
38
+ additionalProperties: boolean;
39
+ required: never[];
40
+ };
41
+ output: {
42
+ schema: {
43
+ type: string;
44
+ additionalProperties: boolean;
45
+ };
46
+ };
47
+ execute(args?: Readonly<Record<string, unknown>>): Promise<unknown>;
48
+ };
49
+ /** The profile tool, bound to the product services the composition provides. */
50
+ export declare function profileTool(getService: (name: string) => unknown): {
51
+ name: string;
52
+ description: string;
53
+ parameters: {
54
+ type: string;
55
+ properties: {
56
+ project_id: {
57
+ type: string;
58
+ description: string;
59
+ };
60
+ view_id: {
61
+ type: string;
62
+ description: string;
63
+ };
64
+ };
65
+ additionalProperties: boolean;
66
+ required: never[];
67
+ };
68
+ output: {
69
+ schema: {
70
+ type: string;
71
+ additionalProperties: boolean;
72
+ };
73
+ };
74
+ execute(args?: Readonly<Record<string, unknown>>, exec?: unknown): Promise<unknown>;
75
+ };
76
+ /** Every tool this package registers. */
77
+ export declare function resourceTools(getService: (name: string) => unknown): ({
78
+ name: string;
79
+ description: string;
80
+ parameters: {
81
+ type: string;
82
+ properties: {
83
+ query: {
84
+ type: string;
85
+ description: string;
86
+ };
87
+ id: {
88
+ type: string;
89
+ description: string;
90
+ };
91
+ domain: {
92
+ type: string;
93
+ description: string;
94
+ };
95
+ limit: {
96
+ type: string;
97
+ description: string;
98
+ minimum: number;
99
+ maximum: number;
100
+ };
101
+ };
102
+ additionalProperties: boolean;
103
+ required: never[];
104
+ };
105
+ output: {
106
+ schema: {
107
+ type: string;
108
+ additionalProperties: boolean;
109
+ };
110
+ };
111
+ execute(args?: Readonly<Record<string, unknown>>): Promise<unknown>;
112
+ } | {
113
+ name: string;
114
+ description: string;
115
+ parameters: {
116
+ type: string;
117
+ properties: {
118
+ project_id: {
119
+ type: string;
120
+ description: string;
121
+ };
122
+ view_id: {
123
+ type: string;
124
+ description: string;
125
+ };
126
+ };
127
+ additionalProperties: boolean;
128
+ required: never[];
129
+ };
130
+ output: {
131
+ schema: {
132
+ type: string;
133
+ additionalProperties: boolean;
134
+ };
135
+ };
136
+ execute(args?: Readonly<Record<string, unknown>>, exec?: unknown): Promise<unknown>;
137
+ })[];
138
+ export { getProfile };
@@ -0,0 +1,190 @@
1
+ /**
2
+ * The three resource tools: read the corpus, profile the open project, review a
3
+ * draft.
4
+ *
5
+ * They are deliberately thin. The corpus tool reads generated files; the profile
6
+ * tool asks the product package that owns the parser; the review tool compares a
7
+ * product's prepared findings with the profile and the corpus rule IDs.
8
+ *
9
+ * @module dsh-engineering-resources/tools
10
+ */
11
+ import { contents, pageBody, search, corpus } from "./corpus.js";
12
+ import { profileId, validateProfile } from "./profile.js";
13
+ import { getProfile, rememberProfile } from "./store.js";
14
+ /** The failure envelope every engineering tool returns. */
15
+ function failure(error) {
16
+ const code = typeof error === 'object' && error !== null && typeof error.code === 'string'
17
+ ? error.code
18
+ : 'INTERNAL';
19
+ const message = error instanceof Error ? error.message : String(error);
20
+ return {
21
+ error: {
22
+ code,
23
+ message,
24
+ fix: code === 'RESOURCES_MISSING'
25
+ ? 'Run `pnpm resources:build` before packing; the corpus index is generated.'
26
+ : code === 'COMPONENT_NOT_FOUND'
27
+ ? 'Call engineering_reference with no arguments for the available page ids and rule ids.'
28
+ : 'Correct the argument and retry; the corpus is local and needs no network.',
29
+ candidates: [],
30
+ },
31
+ };
32
+ }
33
+ /** Coverage carried by every reference answer. */
34
+ const REFERENCE_COVERAGE = {
35
+ complete: false,
36
+ unverified: [
37
+ 'whether the advice fits this machine; a profile is evidence, not authority',
38
+ 'the normative text of the standards the pages are based on',
39
+ ],
40
+ };
41
+ /** Coverage carried by every profile answer. */
42
+ const PROFILE_COVERAGE = {
43
+ complete: false,
44
+ unverified: [
45
+ 'runtime behaviour of the inferred conventions',
46
+ 'conventions the parser cannot see (external HMI, undocumented practice)',
47
+ ],
48
+ };
49
+ /** The reference tool definition. */
50
+ export const referenceTool = {
51
+ name: 'engineering_reference',
52
+ description: 'Read the local engineering corpus: return the contents with no arguments, ranked pages for a query, or one page in full for an id. Pages carry rule IDs (CRAFT-NAME-01, VIEW-HPM-02, …) and their basis; nothing is fetched from the network.',
53
+ parameters: {
54
+ type: 'object',
55
+ properties: {
56
+ query: { type: 'string', description: 'Topic, rule id or tag to search for, for example "state machine", "VIEW-HPM-02" or "seal-in".' },
57
+ id: { type: 'string', description: 'Exact page id from the contents, for example "iec-state-machines".' },
58
+ domain: { type: 'string', description: 'Optional domain filter: iec, rockwell, yaskawa, view, optix or craft.' },
59
+ limit: { type: 'integer', description: 'Most search hits to return; defaults to 8, maximum 20.', minimum: 1, maximum: 20 },
60
+ },
61
+ additionalProperties: false,
62
+ required: [],
63
+ },
64
+ output: { schema: { type: 'object', additionalProperties: true } },
65
+ async execute(args = {}) {
66
+ try {
67
+ const id = typeof args.id === 'string' && args.id.trim() !== '' ? args.id.trim() : undefined;
68
+ const loaded = corpus();
69
+ if (id !== undefined) {
70
+ const row = loaded.index.pages.find(page => page.id === id);
71
+ if (row === undefined)
72
+ throw Object.assign(new Error(`No resource page named "${id}".`), { code: 'COMPONENT_NOT_FOUND' });
73
+ const markdown = pageBody(id);
74
+ return {
75
+ summary: `Read ${row.title} (${row.domain}, ${row.level}) — rules ${row.rules.join(', ')}.`,
76
+ data: {
77
+ id,
78
+ title: row.title,
79
+ domain: row.domain,
80
+ level: row.level,
81
+ basis: row.basis,
82
+ rules: row.rules,
83
+ words: row.words,
84
+ corpus_digest: loaded.digest,
85
+ markdown,
86
+ },
87
+ next: [{ tool: 'engineering_profile', why: 'Read the open project’s conventions before writing.' }],
88
+ coverage: REFERENCE_COVERAGE,
89
+ };
90
+ }
91
+ const query = typeof args.query === 'string' && args.query.trim() !== '' ? args.query.trim() : undefined;
92
+ if (query === undefined) {
93
+ const listing = contents();
94
+ return {
95
+ summary: `${loaded.index.pages.length} engineering resource pages across ${listing.domains.length} domains.`,
96
+ data: { corpus_digest: loaded.digest, domains: listing.domains, pages: listing.pages },
97
+ next: [{ tool: 'engineering_reference', args: { query: 'state machine' }, why: 'Search for the topic you are about to touch.' }],
98
+ coverage: REFERENCE_COVERAGE,
99
+ };
100
+ }
101
+ const domain = typeof args.domain === 'string' && args.domain !== '' ? args.domain : undefined;
102
+ const requested = typeof args.limit === 'number' && Number.isInteger(args.limit) ? args.limit : 8;
103
+ const hits = search(query, requested, domain);
104
+ return {
105
+ summary: hits.length === 0 ? `No resource page matches "${query}".` : `${hits.length} resource page(s) match "${query}".`,
106
+ data: {
107
+ corpus_digest: loaded.digest,
108
+ query,
109
+ hits,
110
+ ...(hits.length === 0 ? { suggestion: 'Call engineering_reference with no arguments for the contents.' } : {}),
111
+ },
112
+ next: hits.length === 0
113
+ ? [{ tool: 'engineering_reference', why: 'List the contents and pick an id.' }]
114
+ : [{ tool: 'engineering_reference', args: { id: hits[0]?.id }, why: 'Read the best-matching page.' }],
115
+ coverage: REFERENCE_COVERAGE,
116
+ };
117
+ }
118
+ catch (error) {
119
+ return failure(error);
120
+ }
121
+ },
122
+ };
123
+ /** The profile tool, bound to the product services the composition provides. */
124
+ export function profileTool(getService) {
125
+ return {
126
+ name: 'engineering_profile',
127
+ description: 'Read the house style of the open project: naming, logic idioms, HMI palette and fonts, comment density, with the evidence and a confidence level. Call it before authoring so new code follows the plant’s own conventions.',
128
+ parameters: {
129
+ type: 'object',
130
+ properties: {
131
+ project_id: { type: 'string', description: 'L5X project handle from open_project. Omit when exactly one project is open.' },
132
+ view_id: { type: 'string', description: 'FactoryTalk View handle from ftview_open. Provide this or project_id.' },
133
+ },
134
+ additionalProperties: false,
135
+ required: [],
136
+ },
137
+ output: { schema: { type: 'object', additionalProperties: true } },
138
+ async execute(args = {}, exec) {
139
+ try {
140
+ const projectId = typeof args.project_id === 'string' && args.project_id !== '' ? args.project_id : undefined;
141
+ const viewId = typeof args.view_id === 'string' && args.view_id !== '' ? args.view_id : undefined;
142
+ const l5x = getService('l5xProjects');
143
+ const ftview = getService('ftviewViews');
144
+ const target = viewId !== undefined
145
+ ? { service: ftview, id: viewId, name: 'FactoryTalk View' }
146
+ : { service: l5x, id: projectId, name: 'L5X' };
147
+ if (target.service?.styleProfile === undefined) {
148
+ return {
149
+ error: {
150
+ code: 'PROFILE_UNAVAILABLE',
151
+ message: `No ${target.name} project service is available in this composition, so a profile cannot be read.`,
152
+ fix: viewId !== undefined
153
+ ? 'Open the export with ftview_open first, and make sure the ftview row is enabled.'
154
+ : 'Open the project with open_project first, and make sure the l5x row is enabled.',
155
+ candidates: [],
156
+ },
157
+ };
158
+ }
159
+ const profile = await target.service.styleProfile(target.id, exec);
160
+ const check = validateProfile(profile);
161
+ if (!check.ok) {
162
+ return {
163
+ error: {
164
+ code: 'PROFILE_INVALID',
165
+ message: `The ${target.name} package returned a profile this version cannot read: ${check.problems.join('; ')}.`,
166
+ fix: 'Update the bundle; the profile schema is versioned.',
167
+ candidates: [],
168
+ },
169
+ };
170
+ }
171
+ const id = profileId(profile);
172
+ rememberProfile(id, profile);
173
+ return {
174
+ summary: `${profile.source.kind} profile for ${profile.source.path}: confidence ${profile.confidence}, ${profile.evidence.length} evidence item(s).`,
175
+ data: { profile_id: id, profile },
176
+ next: [{ tool: 'engineering_reference', query: profile.source.kind === 'ftview' ? 'hmi' : 'state machine', why: 'Read the standard that applies to the change you are about to make.' }],
177
+ coverage: PROFILE_COVERAGE,
178
+ };
179
+ }
180
+ catch (error) {
181
+ return failure(error);
182
+ }
183
+ },
184
+ };
185
+ }
186
+ /** Every tool this package registers. */
187
+ export function resourceTools(getService) {
188
+ return [referenceTool, profileTool(getService)];
189
+ }
190
+ export { getProfile };