agentlang 0.0.2

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 (240) hide show
  1. package/LICENSE +83 -0
  2. package/README.md +120 -0
  3. package/bin/cli.js +4 -0
  4. package/out/api/http.d.ts +3 -0
  5. package/out/api/http.d.ts.map +1 -0
  6. package/out/api/http.js +290 -0
  7. package/out/api/http.js.map +1 -0
  8. package/out/cli/cli-util.d.ts +7 -0
  9. package/out/cli/cli-util.d.ts.map +1 -0
  10. package/out/cli/cli-util.js +9 -0
  11. package/out/cli/cli-util.js.map +1 -0
  12. package/out/cli/docs.d.ts +2 -0
  13. package/out/cli/docs.d.ts.map +1 -0
  14. package/out/cli/docs.js +236 -0
  15. package/out/cli/docs.js.map +1 -0
  16. package/out/cli/main.d.ts +288 -0
  17. package/out/cli/main.d.ts.map +1 -0
  18. package/out/cli/main.js +119 -0
  19. package/out/cli/main.js.map +1 -0
  20. package/out/cli/openapi-docs.yml +695 -0
  21. package/out/extension/main.cjs +18093 -0
  22. package/out/extension/main.cjs.map +7 -0
  23. package/out/extension/main.d.ts +4 -0
  24. package/out/extension/main.d.ts.map +1 -0
  25. package/out/extension/main.js +42 -0
  26. package/out/extension/main.js.map +1 -0
  27. package/out/language/agentlang-module.d.ts +42 -0
  28. package/out/language/agentlang-module.d.ts.map +1 -0
  29. package/out/language/agentlang-module.js +42 -0
  30. package/out/language/agentlang-module.js.map +1 -0
  31. package/out/language/agentlang-validator.d.ts +15 -0
  32. package/out/language/agentlang-validator.d.ts.map +1 -0
  33. package/out/language/agentlang-validator.js +50 -0
  34. package/out/language/agentlang-validator.js.map +1 -0
  35. package/out/language/generated/ast.d.ts +491 -0
  36. package/out/language/generated/ast.d.ts.map +1 -0
  37. package/out/language/generated/ast.js +934 -0
  38. package/out/language/generated/ast.js.map +1 -0
  39. package/out/language/generated/grammar.d.ts +7 -0
  40. package/out/language/generated/grammar.d.ts.map +1 -0
  41. package/out/language/generated/grammar.js +4475 -0
  42. package/out/language/generated/grammar.js.map +1 -0
  43. package/out/language/generated/module.d.ts +14 -0
  44. package/out/language/generated/module.d.ts.map +1 -0
  45. package/out/language/generated/module.js +21 -0
  46. package/out/language/generated/module.js.map +1 -0
  47. package/out/language/main-browser.d.ts +2 -0
  48. package/out/language/main-browser.d.ts.map +1 -0
  49. package/out/language/main-browser.js +10 -0
  50. package/out/language/main-browser.js.map +1 -0
  51. package/out/language/main.cjs +36229 -0
  52. package/out/language/main.cjs.map +7 -0
  53. package/out/language/main.d.ts +2 -0
  54. package/out/language/main.d.ts.map +1 -0
  55. package/out/language/main.js +11 -0
  56. package/out/language/main.js.map +1 -0
  57. package/out/language/parser.d.ts +9 -0
  58. package/out/language/parser.d.ts.map +1 -0
  59. package/out/language/parser.js +273 -0
  60. package/out/language/parser.js.map +1 -0
  61. package/out/language/syntax.d.ts +155 -0
  62. package/out/language/syntax.d.ts.map +1 -0
  63. package/out/language/syntax.js +527 -0
  64. package/out/language/syntax.js.map +1 -0
  65. package/out/runtime/agents/common.d.ts +2 -0
  66. package/out/runtime/agents/common.d.ts.map +1 -0
  67. package/out/runtime/agents/common.js +178 -0
  68. package/out/runtime/agents/common.js.map +1 -0
  69. package/out/runtime/agents/impl/openai.d.ts +8 -0
  70. package/out/runtime/agents/impl/openai.d.ts.map +1 -0
  71. package/out/runtime/agents/impl/openai.js +15 -0
  72. package/out/runtime/agents/impl/openai.js.map +1 -0
  73. package/out/runtime/agents/provider.d.ts +21 -0
  74. package/out/runtime/agents/provider.d.ts.map +1 -0
  75. package/out/runtime/agents/provider.js +32 -0
  76. package/out/runtime/agents/provider.js.map +1 -0
  77. package/out/runtime/agents/registry.d.ts +2 -0
  78. package/out/runtime/agents/registry.d.ts.map +1 -0
  79. package/out/runtime/agents/registry.js +10 -0
  80. package/out/runtime/agents/registry.js.map +1 -0
  81. package/out/runtime/auth/cognito.d.ts +16 -0
  82. package/out/runtime/auth/cognito.d.ts.map +1 -0
  83. package/out/runtime/auth/cognito.js +186 -0
  84. package/out/runtime/auth/cognito.js.map +1 -0
  85. package/out/runtime/auth/defs.d.ts +11 -0
  86. package/out/runtime/auth/defs.d.ts.map +1 -0
  87. package/out/runtime/auth/defs.js +24 -0
  88. package/out/runtime/auth/defs.js.map +1 -0
  89. package/out/runtime/auth/interface.d.ts +22 -0
  90. package/out/runtime/auth/interface.d.ts.map +1 -0
  91. package/out/runtime/auth/interface.js +2 -0
  92. package/out/runtime/auth/interface.js.map +1 -0
  93. package/out/runtime/defs.js +24 -0
  94. package/out/runtime/defs.js.map +1 -0
  95. package/out/runtime/interpreter.d.ts +69 -0
  96. package/out/runtime/interpreter.d.ts.map +1 -0
  97. package/out/runtime/interpreter.js +1163 -0
  98. package/out/runtime/interpreter.js.map +1 -0
  99. package/out/runtime/loader.d.ts +25 -0
  100. package/out/runtime/loader.d.ts.map +1 -0
  101. package/out/runtime/loader.js +346 -0
  102. package/out/runtime/loader.js.map +1 -0
  103. package/out/runtime/logger.d.ts +2 -0
  104. package/out/runtime/logger.d.ts.map +1 -0
  105. package/out/runtime/logger.js +44 -0
  106. package/out/runtime/logger.js.map +1 -0
  107. package/out/runtime/module.d.ts +273 -0
  108. package/out/runtime/module.d.ts.map +1 -0
  109. package/out/runtime/module.js +1786 -0
  110. package/out/runtime/module.js.map +1 -0
  111. package/out/runtime/modules/ai.d.ts +26 -0
  112. package/out/runtime/modules/ai.d.ts.map +1 -0
  113. package/out/runtime/modules/ai.js +211 -0
  114. package/out/runtime/modules/ai.js.map +1 -0
  115. package/out/runtime/modules/auth.d.ts +39 -0
  116. package/out/runtime/modules/auth.d.ts.map +1 -0
  117. package/out/runtime/modules/auth.js +359 -0
  118. package/out/runtime/modules/auth.js.map +1 -0
  119. package/out/runtime/modules/core.d.ts +2 -0
  120. package/out/runtime/modules/core.d.ts.map +1 -0
  121. package/out/runtime/modules/core.js +67 -0
  122. package/out/runtime/modules/core.js.map +1 -0
  123. package/out/runtime/relgraph.d.ts +21 -0
  124. package/out/runtime/relgraph.d.ts.map +1 -0
  125. package/out/runtime/relgraph.js +156 -0
  126. package/out/runtime/relgraph.js.map +1 -0
  127. package/out/runtime/resolvers/interface.d.ts +59 -0
  128. package/out/runtime/resolvers/interface.d.ts.map +1 -0
  129. package/out/runtime/resolvers/interface.js +111 -0
  130. package/out/runtime/resolvers/interface.js.map +1 -0
  131. package/out/runtime/resolvers/registry.d.ts +8 -0
  132. package/out/runtime/resolvers/registry.d.ts.map +1 -0
  133. package/out/runtime/resolvers/registry.js +26 -0
  134. package/out/runtime/resolvers/registry.js.map +1 -0
  135. package/out/runtime/resolvers/sqldb/database.d.ts +50 -0
  136. package/out/runtime/resolvers/sqldb/database.d.ts.map +1 -0
  137. package/out/runtime/resolvers/sqldb/database.js +618 -0
  138. package/out/runtime/resolvers/sqldb/database.js.map +1 -0
  139. package/out/runtime/resolvers/sqldb/dbutil.d.ts +18 -0
  140. package/out/runtime/resolvers/sqldb/dbutil.d.ts.map +1 -0
  141. package/out/runtime/resolvers/sqldb/dbutil.js +221 -0
  142. package/out/runtime/resolvers/sqldb/dbutil.js.map +1 -0
  143. package/out/runtime/resolvers/sqldb/impl.d.ts +26 -0
  144. package/out/runtime/resolvers/sqldb/impl.d.ts.map +1 -0
  145. package/out/runtime/resolvers/sqldb/impl.js +300 -0
  146. package/out/runtime/resolvers/sqldb/impl.js.map +1 -0
  147. package/out/runtime/state.js +83 -0
  148. package/out/runtime/state.js.map +1 -0
  149. package/out/runtime/util.d.ts +43 -0
  150. package/out/runtime/util.d.ts.map +1 -0
  151. package/out/runtime/util.js +447 -0
  152. package/out/runtime/util.js.map +1 -0
  153. package/out/setupClassic.d.ts +98 -0
  154. package/out/setupClassic.d.ts.map +1 -0
  155. package/out/setupClassic.js +38 -0
  156. package/out/setupClassic.js.map +1 -0
  157. package/out/setupCommon.d.ts +2 -0
  158. package/out/setupCommon.d.ts.map +1 -0
  159. package/out/setupCommon.js +33 -0
  160. package/out/setupCommon.js.map +1 -0
  161. package/out/setupExtended.d.ts +40 -0
  162. package/out/setupExtended.d.ts.map +1 -0
  163. package/out/setupExtended.js +67 -0
  164. package/out/setupExtended.js.map +1 -0
  165. package/out/syntaxes/agentlang.monarch.d.ts +77 -0
  166. package/out/syntaxes/agentlang.monarch.d.ts.map +1 -0
  167. package/out/syntaxes/agentlang.monarch.js +31 -0
  168. package/out/syntaxes/agentlang.monarch.js.map +1 -0
  169. package/out/utils/fs/index.d.ts +14 -0
  170. package/out/utils/fs/index.d.ts.map +1 -0
  171. package/out/utils/fs/index.js +26 -0
  172. package/out/utils/fs/index.js.map +1 -0
  173. package/out/utils/fs/interfaces.d.ts +105 -0
  174. package/out/utils/fs/interfaces.d.ts.map +1 -0
  175. package/out/utils/fs/interfaces.js +5 -0
  176. package/out/utils/fs/interfaces.js.map +1 -0
  177. package/out/utils/fs/lightning-fs.d.ts +116 -0
  178. package/out/utils/fs/lightning-fs.d.ts.map +1 -0
  179. package/out/utils/fs/lightning-fs.js +243 -0
  180. package/out/utils/fs/lightning-fs.js.map +1 -0
  181. package/out/utils/fs/node-fs.d.ts +93 -0
  182. package/out/utils/fs/node-fs.d.ts.map +1 -0
  183. package/out/utils/fs/node-fs.js +169 -0
  184. package/out/utils/fs/node-fs.js.map +1 -0
  185. package/out/utils/fs-utils.d.ts +153 -0
  186. package/out/utils/fs-utils.d.ts.map +1 -0
  187. package/out/utils/fs-utils.js +271 -0
  188. package/out/utils/fs-utils.js.map +1 -0
  189. package/out/utils/runtime.d.ts +36 -0
  190. package/out/utils/runtime.d.ts.map +1 -0
  191. package/out/utils/runtime.js +39 -0
  192. package/out/utils/runtime.js.map +1 -0
  193. package/package.json +155 -0
  194. package/src/api/http.ts +361 -0
  195. package/src/cli/cli-util.ts +18 -0
  196. package/src/cli/main.ts +146 -0
  197. package/src/extension/main.ts +51 -0
  198. package/src/language/agentlang-module.ts +75 -0
  199. package/src/language/agentlang-validator.ts +60 -0
  200. package/src/language/agentlang.langium +178 -0
  201. package/src/language/generated/ast.ts +1698 -0
  202. package/src/language/generated/grammar.ts +4477 -0
  203. package/src/language/generated/module.ts +25 -0
  204. package/src/language/main-browser.ts +19 -0
  205. package/src/language/main.ts +13 -0
  206. package/src/language/parser.ts +329 -0
  207. package/src/language/syntax.ts +646 -0
  208. package/src/runtime/agents/common.ts +177 -0
  209. package/src/runtime/agents/impl/openai.ts +19 -0
  210. package/src/runtime/agents/provider.ts +58 -0
  211. package/src/runtime/agents/registry.ts +9 -0
  212. package/src/runtime/auth/cognito.ts +225 -0
  213. package/src/runtime/auth/defs.ts +33 -0
  214. package/src/runtime/auth/interface.ts +31 -0
  215. package/src/runtime/defs.ts +33 -0
  216. package/src/runtime/interpreter.ts +1352 -0
  217. package/src/runtime/loader.ts +450 -0
  218. package/src/runtime/logger.ts +51 -0
  219. package/src/runtime/module.ts +2188 -0
  220. package/src/runtime/modules/ai.ts +257 -0
  221. package/src/runtime/modules/auth.ts +489 -0
  222. package/src/runtime/modules/core.ts +95 -0
  223. package/src/runtime/relgraph.ts +195 -0
  224. package/src/runtime/resolvers/interface.ts +160 -0
  225. package/src/runtime/resolvers/registry.ts +30 -0
  226. package/src/runtime/resolvers/sqldb/database.ts +823 -0
  227. package/src/runtime/resolvers/sqldb/dbutil.ts +257 -0
  228. package/src/runtime/resolvers/sqldb/impl.ts +471 -0
  229. package/src/runtime/state.ts +87 -0
  230. package/src/runtime/util.ts +513 -0
  231. package/src/setupClassic.ts +43 -0
  232. package/src/setupCommon.ts +33 -0
  233. package/src/setupExtended.ts +79 -0
  234. package/src/syntaxes/agentlang.monarch.ts +31 -0
  235. package/src/utils/fs/index.ts +28 -0
  236. package/src/utils/fs/interfaces.ts +118 -0
  237. package/src/utils/fs/lightning-fs.ts +284 -0
  238. package/src/utils/fs/node-fs.ts +185 -0
  239. package/src/utils/fs-utils.ts +304 -0
  240. package/src/utils/runtime.ts +43 -0
@@ -0,0 +1,361 @@
1
+ import chalk from 'chalk';
2
+ import express, { Request, Response } from 'express';
3
+ import {
4
+ getAllChildRelationships,
5
+ getAllEntityNames,
6
+ getAllEventNames,
7
+ Instance,
8
+ InstanceAttributes,
9
+ makeInstance,
10
+ objectAsInstanceAttributes,
11
+ Relationship,
12
+ } from '../runtime/module.js';
13
+ import { evaluate, parseAndEvaluateStatement, Result } from '../runtime/interpreter.js';
14
+ import { ApplicationSpec } from '../runtime/loader.js';
15
+ import { logger } from '../runtime/logger.js';
16
+ import { requireAuth, verifySession } from '../runtime/modules/auth.js';
17
+ import { ActiveSessionInfo, BypassSession, isNoSession, NoSession } from '../runtime/auth/defs.js';
18
+ import {
19
+ escapeFqName,
20
+ forceAsEscapedName,
21
+ forceAsFqName,
22
+ isString,
23
+ makeFqName,
24
+ restoreFqName,
25
+ splitFqName,
26
+ walkDownInstancePath,
27
+ } from '../runtime/util.js';
28
+ import { BadRequestError, PathAttributeNameQuery, UnauthorisedError } from '../runtime/defs.js';
29
+
30
+ export function startServer(appSpec: ApplicationSpec, port: number) {
31
+ const app = express();
32
+ app.use(express.json());
33
+
34
+ const appName: string = appSpec.name;
35
+ const appVersion: string = appSpec.version;
36
+
37
+ app.get('/', (req: Request, res: Response) => {
38
+ res.send(appName);
39
+ });
40
+
41
+ getAllEventNames().forEach((eventNames: string[], moduleName: string) => {
42
+ eventNames.forEach((n: string) => {
43
+ app.post(`/${moduleName}/${n}`, (req: Request, res: Response) => {
44
+ handleEventPost(moduleName, n, req, res);
45
+ });
46
+ });
47
+ });
48
+
49
+ getAllEntityNames().forEach((entityNames: string[], moduleName: string) => {
50
+ entityNames.forEach((n: string) => {
51
+ app.get(`/${moduleName}/${n}`, (req: Request, res: Response) => {
52
+ handleEntityGet(moduleName, n, req, res);
53
+ });
54
+ app.get(`/${moduleName}/${n}/*path`, (req: Request, res: Response) => {
55
+ handleEntityGet(moduleName, n, req, res);
56
+ });
57
+ app.post(`/${moduleName}/${n}`, (req: Request, res: Response) => {
58
+ handleEntityPost(moduleName, n, req, res);
59
+ });
60
+ app.post(`/${moduleName}/${n}/*path`, (req: Request, res: Response) => {
61
+ handleEntityPost(moduleName, n, req, res);
62
+ });
63
+ app.put(`/${moduleName}/${n}/*path`, (req: Request, res: Response) => {
64
+ handleEntityPut(moduleName, n, req, res);
65
+ });
66
+ app.delete(`/${moduleName}/${n}/*path`, (req: Request, res: Response) => {
67
+ handleEntityDelete(moduleName, n, req, res);
68
+ });
69
+ });
70
+ });
71
+
72
+ app.listen(port, () => {
73
+ console.log(
74
+ chalk.green(
75
+ `Application ${chalk.bold(appName + ' version ' + appVersion)} started on port ${chalk.bold(port)}`
76
+ )
77
+ );
78
+ });
79
+ }
80
+
81
+ function ok(res: Response) {
82
+ return (value: Result) => {
83
+ const result: Result = normalizedResult(value);
84
+ res.contentType('application/json');
85
+ res.send(JSON.stringify(result));
86
+ };
87
+ }
88
+
89
+ function statusFromErrorType(err: any): number {
90
+ if (err instanceof UnauthorisedError) {
91
+ return 401;
92
+ } else if (err instanceof BadRequestError) {
93
+ return 400;
94
+ } else {
95
+ return 500;
96
+ }
97
+ }
98
+
99
+ function internalError(res: Response) {
100
+ return (reason: any) => {
101
+ logger.error(reason);
102
+ res.status(statusFromErrorType(reason)).send(reason.message);
103
+ };
104
+ }
105
+
106
+ function patternFromAttributes(
107
+ moduleName: string,
108
+ recName: string,
109
+ attrs: InstanceAttributes
110
+ ): string {
111
+ const attrsStrs = new Array<string>();
112
+ attrs.forEach((v: any, n: string) => {
113
+ let av = isString(v) ? `"${v}"` : v;
114
+ if (av instanceof Object) {
115
+ av = JSON.stringify(av);
116
+ }
117
+ attrsStrs.push(`${n} ${av}`);
118
+ });
119
+ return `{${moduleName}/${recName} { ${attrsStrs.join(',\n')} }}`;
120
+ }
121
+
122
+ function normalizeRequestPath(path: string[], moduleName: string): string[] {
123
+ if (path.length <= 1) {
124
+ return path;
125
+ }
126
+ const result = new Array<string>();
127
+ result.push(path[0]);
128
+ for (let i = 1; i < path.length; ++i) {
129
+ const rn = forceAsEscapedName(path[i], moduleName);
130
+ const en = forceAsEscapedName(path[++i], moduleName);
131
+ result.push(rn);
132
+ result.push(en);
133
+ if (i < path.length) {
134
+ result.push(path[++i]);
135
+ }
136
+ }
137
+ return result;
138
+ }
139
+
140
+ function pathFromRequest(moduleName: string, entryName: string, req: Request): string {
141
+ const path: any = req.params.path;
142
+ if (!path) {
143
+ return req.url;
144
+ }
145
+ let p = '';
146
+ if (path instanceof Array) {
147
+ p = normalizeRequestPath(path, moduleName).join('/');
148
+ } else {
149
+ p = path.toString();
150
+ }
151
+ p = p.trim();
152
+ if (p.endsWith('/')) {
153
+ p = p.substring(0, p.length - 1);
154
+ }
155
+ return `${escapeFqName(makeFqName(moduleName, entryName))}/${p}`;
156
+ }
157
+
158
+ async function handleEventPost(
159
+ moduleName: string,
160
+ eventName: string,
161
+ req: Request,
162
+ res: Response
163
+ ): Promise<void> {
164
+ try {
165
+ const sessionInfo = await verifyAuth(moduleName, eventName, req.headers.authorization);
166
+ if (isNoSession(sessionInfo)) {
167
+ res.status(401).send('Authorization required');
168
+ return;
169
+ }
170
+ const inst: Instance = makeInstance(
171
+ moduleName,
172
+ eventName,
173
+ objectAsInstanceAttributes(req.body)
174
+ ).setAuthContext(sessionInfo);
175
+ evaluate(inst, ok(res)).catch(internalError(res));
176
+ } catch (err: any) {
177
+ logger.error(err);
178
+ res.status(500).send(err.toString());
179
+ }
180
+ }
181
+
182
+ async function handleEntityPost(
183
+ moduleName: string,
184
+ entityName: string,
185
+ req: Request,
186
+ res: Response
187
+ ): Promise<void> {
188
+ try {
189
+ const sessionInfo = await verifyAuth(moduleName, entityName, req.headers.authorization);
190
+ if (isNoSession(sessionInfo)) {
191
+ res.status(401).send('Authorization required');
192
+ return;
193
+ }
194
+ const pattern = req.params.path
195
+ ? createChildPattern(moduleName, entityName, req)
196
+ : patternFromAttributes(moduleName, entityName, objectAsInstanceAttributes(req.body));
197
+ parseAndEvaluateStatement(pattern, sessionInfo.userId).then(ok(res)).catch(internalError(res));
198
+ } catch (err: any) {
199
+ logger.error(err);
200
+ res.status(500).send(err.toString());
201
+ }
202
+ }
203
+
204
+ async function handleEntityGet(
205
+ moduleName: string,
206
+ entityName: string,
207
+ req: Request,
208
+ res: Response
209
+ ): Promise<void> {
210
+ try {
211
+ const path = pathFromRequest(moduleName, entityName, req);
212
+ const sessionInfo = await verifyAuth(moduleName, entityName, req.headers.authorization);
213
+ if (isNoSession(sessionInfo)) {
214
+ res.status(401).send('Authorization required');
215
+ return;
216
+ }
217
+ let pattern = '';
218
+ if (req.query.tree) {
219
+ pattern = fetchTreePattern(makeFqName(moduleName, entityName), path);
220
+ } else {
221
+ const r = walkDownInstancePath(path);
222
+ let moduleName = r[0];
223
+ let entityName = r[1];
224
+ const id = r[2];
225
+ const parts = r[3];
226
+ if (parts.length == 2 && id == undefined) {
227
+ pattern = `{${moduleName}/${entityName}? {}}`;
228
+ } else {
229
+ moduleName = restoreFqName(moduleName);
230
+ entityName = restoreFqName(entityName);
231
+ if (id == undefined) {
232
+ pattern = `{${moduleName}/${entityName} {${PathAttributeNameQuery}like "${path}%"}}`;
233
+ } else {
234
+ pattern = `{${moduleName}/${entityName} {${PathAttributeNameQuery} "${path}"}}`;
235
+ }
236
+ }
237
+ }
238
+ parseAndEvaluateStatement(pattern, sessionInfo.userId).then(ok(res)).catch(internalError(res));
239
+ } catch (err: any) {
240
+ logger.error(err);
241
+ res.status(500).send(err.toString());
242
+ }
243
+ }
244
+
245
+ async function handleEntityPut(
246
+ moduleName: string,
247
+ entityName: string,
248
+ req: Request,
249
+ res: Response
250
+ ): Promise<void> {
251
+ try {
252
+ const path = pathFromRequest(moduleName, entityName, req);
253
+ const sessionInfo = await verifyAuth(moduleName, entityName, req.headers.authorization);
254
+ if (isNoSession(sessionInfo)) {
255
+ res.status(401).send('Authorization required');
256
+ return;
257
+ }
258
+ const attrs = objectAsInstanceAttributes(req.body);
259
+ attrs.set(PathAttributeNameQuery, path);
260
+ const pattern = patternFromAttributes(moduleName, entityName, attrs);
261
+ parseAndEvaluateStatement(pattern, sessionInfo.userId).then(ok(res)).catch(internalError(res));
262
+ } catch (err: any) {
263
+ logger.error(err);
264
+ res.status(500).send(err.toString());
265
+ }
266
+ }
267
+
268
+ async function handleEntityDelete(
269
+ moduleName: string,
270
+ entityName: string,
271
+ req: Request,
272
+ res: Response
273
+ ): Promise<void> {
274
+ try {
275
+ const path = pathFromRequest(moduleName, entityName, req);
276
+ const sessionInfo = await verifyAuth(moduleName, entityName, req.headers.authorization);
277
+ if (isNoSession(sessionInfo)) {
278
+ res.status(401).send('Authorization required');
279
+ return;
280
+ }
281
+ const pattern = `delete {${moduleName}/${entityName} {${PathAttributeNameQuery} "${path}"}}`;
282
+ parseAndEvaluateStatement(pattern, sessionInfo.userId).then(ok(res)).catch(internalError(res));
283
+ } catch (err: any) {
284
+ logger.error(err);
285
+ res.status(500).send(err.toString());
286
+ }
287
+ }
288
+
289
+ function fetchTreePattern(fqName: string, path?: string): string {
290
+ let pattern = path ? `{${fqName} {${PathAttributeNameQuery} "${path}"}` : `{${fqName}? {}`;
291
+ const rels = getAllChildRelationships(fqName);
292
+ if (rels.length > 0) {
293
+ const treePats = new Array<string>();
294
+ rels.forEach((rel: Relationship) => {
295
+ treePats.push(`${rel.getFqName()} ${fetchTreePattern(rel.getChildFqName())}`);
296
+ });
297
+ pattern = pattern.concat(',', treePats.join(','));
298
+ }
299
+ return `${pattern}}`;
300
+ }
301
+
302
+ function createChildPattern(moduleName: string, entityName: string, req: Request): string {
303
+ const path = pathFromRequest(moduleName, entityName, req);
304
+ try {
305
+ const parts = path.split('/');
306
+ const pinfo = parts.slice(-4);
307
+ const parentFqname = forceAsFqName(pinfo[0], moduleName);
308
+ const relName = forceAsFqName(pinfo[2], moduleName);
309
+ const parentPath = parts.slice(0, parts.length - 2).join('/');
310
+ const childFqName = forceAsFqName(pinfo[3], moduleName);
311
+ const cparts = splitFqName(childFqName);
312
+ const childModuleName = cparts.getModuleName();
313
+ const childName = cparts.getEntryName();
314
+ const cp = patternFromAttributes(
315
+ childModuleName,
316
+ childName,
317
+ objectAsInstanceAttributes(req.body)
318
+ );
319
+ return `{${parentFqname} {${PathAttributeNameQuery} "${parentPath}"}, ${relName} ${cp}}`;
320
+ } catch (err: any) {
321
+ throw new BadRequestError(err.message);
322
+ }
323
+ }
324
+
325
+ async function verifyAuth(
326
+ moduleName: string,
327
+ eventName: string,
328
+ authValue: string | undefined
329
+ ): Promise<ActiveSessionInfo> {
330
+ if (requireAuth(moduleName, eventName)) {
331
+ if (authValue) {
332
+ const token = authValue.substring(authValue.indexOf(' ')).trim();
333
+ return await verifySession(token);
334
+ } else {
335
+ return NoSession;
336
+ }
337
+ }
338
+ return BypassSession;
339
+ }
340
+
341
+ function normalizedResult(r: Result): Result {
342
+ if (r instanceof Array) {
343
+ return r.map((x: Result) => {
344
+ return normalizedResult(x);
345
+ });
346
+ } else if (r instanceof Instance) {
347
+ r.mergeRelatedInstances();
348
+ Array.from(r.attributes.keys()).forEach(k => {
349
+ const v: Result = r.attributes.get(k);
350
+ if (v instanceof Array || v instanceof Instance) {
351
+ r.attributes.set(k, normalizedResult(v));
352
+ }
353
+ });
354
+ return r.asObject();
355
+ } else {
356
+ if (r instanceof Map) {
357
+ return Object.fromEntries(r.entries());
358
+ }
359
+ return r;
360
+ }
361
+ }
@@ -0,0 +1,18 @@
1
+ import { path } from '../utils/runtime.js';
2
+
3
+ interface FilePathData {
4
+ destination: string;
5
+ name: string;
6
+ }
7
+
8
+ export function extractDestinationAndName(
9
+ filePath: string,
10
+ destination: string | undefined
11
+ ): FilePathData {
12
+ const fileName = path.basename(filePath, path.extname(filePath)).replace(/[.-]/g, '');
13
+
14
+ return {
15
+ destination: destination ?? path.join(path.dirname(filePath), 'generated'),
16
+ name: fileName,
17
+ };
18
+ }
@@ -0,0 +1,146 @@
1
+ import chalk from 'chalk';
2
+ import { Command } from 'commander';
3
+ import { AgentlangLanguageMetaData } from '../language/generated/module.js';
4
+ import { createAgentlangServices } from '../language/agentlang-module.js';
5
+ import {
6
+ ApplicationSpec,
7
+ internModule,
8
+ load,
9
+ loadCoreModules,
10
+ runStandaloneStatements,
11
+ } from '../runtime/loader.js';
12
+ import { NodeFileSystem } from 'langium/node';
13
+ import { extractDocument } from '../runtime/loader.js';
14
+ import * as url from 'node:url';
15
+ import * as fs from 'node:fs/promises';
16
+ import * as path from 'node:path';
17
+ import { startServer } from '../api/http.js';
18
+ import { initDatabase } from '../runtime/resolvers/sqldb/database.js';
19
+ import { logger } from '../runtime/logger.js';
20
+ import { runInitFunctions } from '../runtime/util.js';
21
+ import { Module } from '../runtime/module.js';
22
+ import { ModuleDefinition } from '../language/generated/ast.js';
23
+ import { z } from 'zod';
24
+ import { loadConfig } from 'c12';
25
+ import { Config, ConfigSchema, setAppConfig } from '../runtime/state.js';
26
+
27
+ const __dirname = url.fileURLToPath(new URL('.', import.meta.url));
28
+
29
+ const packagePath = path.resolve(__dirname, '..', '..', 'package.json');
30
+ const packageContent = await fs.readFile(packagePath, 'utf-8');
31
+
32
+ export type GenerateOptions = {
33
+ destination?: string;
34
+ };
35
+
36
+ export default function (): void {
37
+ const program = new Command();
38
+
39
+ program.version(JSON.parse(packageContent).version);
40
+
41
+ const fileExtensions = AgentlangLanguageMetaData.fileExtensions.join(', ');
42
+
43
+ program
44
+ .command('run')
45
+ .argument('<file>', `source file (possible file extensions: ${fileExtensions})`)
46
+ .option('-c, --config <config>', 'configuration file')
47
+ .description('Loads and runs an agentlang module')
48
+ .action(runModule);
49
+
50
+ program
51
+ .command('parseAndValidate')
52
+ .argument('<file>', `source file (possible file extensions: ${fileExtensions})`)
53
+ .option('-d, --destination <dir>', 'destination directory of generating')
54
+ .description('Parses and validates an Agentlang module')
55
+ .action(parseAndValidate);
56
+
57
+ program.parse(process.argv);
58
+ }
59
+
60
+ /**
61
+ * Parse and validate a program written in our language.
62
+ * Verifies that no lexer or parser errors occur.
63
+ * Implicitly also checks for validation errors while extracting the document
64
+ *
65
+ * @param fileName Program to validate
66
+ */
67
+ export const parseAndValidate = async (fileName: string): Promise<void> => {
68
+ // retrieve the services for our language
69
+ const services = createAgentlangServices(NodeFileSystem).Agentlang;
70
+ // extract a document for our program
71
+ const document = await extractDocument(fileName, services);
72
+ // extract the parse result details
73
+ const parseResult = document.parseResult;
74
+ // verify no lexer, parser, or general diagnostic errors show up
75
+ if (parseResult.lexerErrors.length === 0 && parseResult.parserErrors.length === 0) {
76
+ console.log(chalk.green(`Parsed and validated ${fileName} successfully!`));
77
+ } else {
78
+ console.log(chalk.red(`Failed to parse and validate ${fileName}!`));
79
+ }
80
+ };
81
+
82
+ export async function runPreInitTasks(): Promise<boolean> {
83
+ let result: boolean = true;
84
+ await loadCoreModules().catch((reason: any) => {
85
+ const msg = `Failed to load core modules - ${reason.toString()}`;
86
+ logger.error(msg);
87
+ console.log(chalk.red(msg));
88
+ result = false;
89
+ });
90
+ return result;
91
+ }
92
+
93
+ export async function runPostInitTasks(appSpec?: ApplicationSpec, config?: Config) {
94
+ await initDatabase(config?.store);
95
+ await runInitFunctions();
96
+ await runStandaloneStatements();
97
+ if (appSpec) startServer(appSpec, config?.service?.port || 8080);
98
+ }
99
+
100
+ export const runModule = async (fileName: string, options?: { config?: string }): Promise<void> => {
101
+ const configDir =
102
+ path.dirname(fileName) === '.' ? process.cwd() : path.resolve(process.cwd(), fileName);
103
+
104
+ let config: Config | undefined;
105
+
106
+ try {
107
+ const { config: rawConfig } = await loadConfig({
108
+ cwd: configDir,
109
+ name: 'config',
110
+ configFile: options?.config || 'app.config',
111
+ dotenv: true,
112
+ });
113
+
114
+ config = setAppConfig(ConfigSchema.parse(rawConfig));
115
+ } catch (err) {
116
+ if (err instanceof z.ZodError) {
117
+ console.log(chalk.red('Config validation failed:'));
118
+ err.errors.forEach((error, index) => {
119
+ console.log(chalk.red(` ${index + 1}. ${error.path.join('.')}: ${error.message}`));
120
+ });
121
+ } else {
122
+ console.log(`Config loading failed: ${err}`);
123
+ }
124
+ }
125
+
126
+ const r: boolean = await runPreInitTasks();
127
+ if (!r) {
128
+ throw new Error('Failed to initialize runtime');
129
+ }
130
+ await load(fileName, undefined, async (appSpec?: ApplicationSpec) => {
131
+ await runPostInitTasks(appSpec, config);
132
+ });
133
+ };
134
+
135
+ export async function internAndRunModule(
136
+ module: ModuleDefinition,
137
+ appSpec?: ApplicationSpec
138
+ ): Promise<Module> {
139
+ const r: boolean = await runPreInitTasks();
140
+ if (!r) {
141
+ throw new Error('Failed to initialize runtime');
142
+ }
143
+ const rm: Module = internModule(module);
144
+ await runPostInitTasks(appSpec);
145
+ return rm;
146
+ }
@@ -0,0 +1,51 @@
1
+ import type { LanguageClientOptions, ServerOptions } from 'vscode-languageclient/node.js';
2
+ import type * as vscode from 'vscode';
3
+ import * as path from 'node:path';
4
+ import { LanguageClient, TransportKind } from 'vscode-languageclient/node.js';
5
+
6
+ let client: LanguageClient;
7
+
8
+ // This function is called when the extension is activated.
9
+ export function activate(context: vscode.ExtensionContext): void {
10
+ client = startLanguageClient(context);
11
+ }
12
+
13
+ // This function is called when the extension is deactivated.
14
+ export function deactivate(): Thenable<void> | undefined {
15
+ if (client) {
16
+ return client.stop();
17
+ }
18
+ return undefined;
19
+ }
20
+
21
+ function startLanguageClient(context: vscode.ExtensionContext): LanguageClient {
22
+ const serverModule = context.asAbsolutePath(path.join('out', 'language', 'main.cjs'));
23
+ // The debug options for the server
24
+ // --inspect=6009: runs the server in Node's Inspector mode so VS Code can attach to the server for debugging.
25
+ // By setting `process.env.DEBUG_BREAK` to a truthy value, the language server will wait until a debugger is attached.
26
+ const debugOptions = {
27
+ execArgv: [
28
+ '--nolazy',
29
+ `--inspect${process.env.DEBUG_BREAK ? '-brk' : ''}=${process.env.DEBUG_SOCKET || '6009'}`,
30
+ ],
31
+ };
32
+
33
+ // If the extension is launched in debug mode then the debug server options are used
34
+ // Otherwise the run options are used
35
+ const serverOptions: ServerOptions = {
36
+ run: { module: serverModule, transport: TransportKind.ipc },
37
+ debug: { module: serverModule, transport: TransportKind.ipc, options: debugOptions },
38
+ };
39
+
40
+ // Options to control the language client
41
+ const clientOptions: LanguageClientOptions = {
42
+ documentSelector: [{ scheme: '*', language: 'agentlang' }],
43
+ };
44
+
45
+ // Create the language client and start the client.
46
+ const client = new LanguageClient('agentlang', 'Agentlang', serverOptions, clientOptions);
47
+
48
+ // Start the client. This will also launch the server
49
+ client.start();
50
+ return client;
51
+ }
@@ -0,0 +1,75 @@
1
+ import { type Module, inject } from 'langium';
2
+ import {
3
+ createDefaultModule,
4
+ createDefaultSharedModule,
5
+ type DefaultSharedModuleContext,
6
+ type LangiumServices,
7
+ type LangiumSharedServices,
8
+ type PartialLangiumServices,
9
+ } from 'langium/lsp';
10
+ import { AgentlangGeneratedModule, AgentlangGeneratedSharedModule } from './generated/module.js';
11
+ import { AgentlangValidator, registerValidationChecks } from './agentlang-validator.js';
12
+
13
+ /**
14
+ * Declaration of custom services - add your own service classes here.
15
+ */
16
+ export type AgentlangAddedServices = {
17
+ validation: {
18
+ AgentlangValidator: AgentlangValidator;
19
+ };
20
+ };
21
+
22
+ /**
23
+ * Union of Langium default services and your custom services - use this as constructor parameter
24
+ * of custom service classes.
25
+ */
26
+ export type AgentlangServices = LangiumServices & AgentlangAddedServices;
27
+
28
+ /**
29
+ * Dependency injection module that overrides Langium default services and contributes the
30
+ * declared custom services. The Langium defaults can be partially specified to override only
31
+ * selected services, while the custom services must be fully specified.
32
+ */
33
+ export const AgentlangModule: Module<
34
+ AgentlangServices,
35
+ PartialLangiumServices & AgentlangAddedServices
36
+ > = {
37
+ validation: {
38
+ AgentlangValidator: () => new AgentlangValidator(),
39
+ },
40
+ };
41
+
42
+ /**
43
+ * Create the full set of services required by Langium.
44
+ *
45
+ * First inject the shared services by merging two modules:
46
+ * - Langium default shared services
47
+ * - Services generated by langium-cli
48
+ *
49
+ * Then inject the language-specific services by merging three modules:
50
+ * - Langium default language-specific services
51
+ * - Services generated by langium-cli
52
+ * - Services specified in this file
53
+ *
54
+ * @param context Optional module context with the LSP connection
55
+ * @returns An object wrapping the shared services and the language-specific services
56
+ */
57
+ export function createAgentlangServices(context: DefaultSharedModuleContext): {
58
+ shared: LangiumSharedServices;
59
+ Agentlang: AgentlangServices;
60
+ } {
61
+ const shared = inject(createDefaultSharedModule(context), AgentlangGeneratedSharedModule);
62
+ const Agentlang = inject(
63
+ createDefaultModule({ shared }),
64
+ AgentlangGeneratedModule,
65
+ AgentlangModule
66
+ );
67
+ shared.ServiceRegistry.register(Agentlang);
68
+ registerValidationChecks(Agentlang);
69
+ if (!context.connection) {
70
+ // We don't run inside a language server
71
+ // Therefore, initialize the configuration provider instantly
72
+ shared.workspace.ConfigurationProvider.initialized({});
73
+ }
74
+ return { shared, Agentlang };
75
+ }