@mondaydotcomorg/atp-server 0.17.14

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 (307) hide show
  1. package/README.md +489 -0
  2. package/dist/aggregator/index.d.ts +59 -0
  3. package/dist/aggregator/index.d.ts.map +1 -0
  4. package/dist/aggregator/index.js +171 -0
  5. package/dist/aggregator/index.js.map +1 -0
  6. package/dist/callback/index.d.ts +98 -0
  7. package/dist/callback/index.d.ts.map +1 -0
  8. package/dist/callback/index.js +136 -0
  9. package/dist/callback/index.js.map +1 -0
  10. package/dist/client-sessions.d.ts +82 -0
  11. package/dist/client-sessions.d.ts.map +1 -0
  12. package/dist/client-sessions.js +174 -0
  13. package/dist/client-sessions.js.map +1 -0
  14. package/dist/controllers/definitions.controller.d.ts +4 -0
  15. package/dist/controllers/definitions.controller.d.ts.map +1 -0
  16. package/dist/controllers/definitions.controller.js +11 -0
  17. package/dist/controllers/definitions.controller.js.map +1 -0
  18. package/dist/controllers/execute.controller.d.ts +18 -0
  19. package/dist/controllers/execute.controller.d.ts.map +1 -0
  20. package/dist/controllers/execute.controller.js +122 -0
  21. package/dist/controllers/execute.controller.js.map +1 -0
  22. package/dist/controllers/info.controller.d.ts +3 -0
  23. package/dist/controllers/info.controller.d.ts.map +1 -0
  24. package/dist/controllers/info.controller.js +13 -0
  25. package/dist/controllers/info.controller.js.map +1 -0
  26. package/dist/controllers/resume.controller.d.ts +11 -0
  27. package/dist/controllers/resume.controller.d.ts.map +1 -0
  28. package/dist/controllers/resume.controller.js +61 -0
  29. package/dist/controllers/resume.controller.js.map +1 -0
  30. package/dist/controllers/search.controller.d.ts +4 -0
  31. package/dist/controllers/search.controller.d.ts.map +1 -0
  32. package/dist/controllers/search.controller.js +7 -0
  33. package/dist/controllers/search.controller.js.map +1 -0
  34. package/dist/controllers/stream.controller.d.ts +19 -0
  35. package/dist/controllers/stream.controller.d.ts.map +1 -0
  36. package/dist/controllers/stream.controller.js +141 -0
  37. package/dist/controllers/stream.controller.js.map +1 -0
  38. package/dist/core/config.d.ts +161 -0
  39. package/dist/core/config.d.ts.map +1 -0
  40. package/dist/core/config.js +7 -0
  41. package/dist/core/config.js.map +1 -0
  42. package/dist/core/http.d.ts +4 -0
  43. package/dist/core/http.d.ts.map +1 -0
  44. package/dist/core/http.js +17 -0
  45. package/dist/core/http.js.map +1 -0
  46. package/dist/create-server.d.ts +120 -0
  47. package/dist/create-server.d.ts.map +1 -0
  48. package/dist/create-server.js +423 -0
  49. package/dist/create-server.js.map +1 -0
  50. package/dist/execution-state/index.d.ts +95 -0
  51. package/dist/execution-state/index.d.ts.map +1 -0
  52. package/dist/execution-state/index.js +128 -0
  53. package/dist/execution-state/index.js.map +1 -0
  54. package/dist/executor/ast-provenance-bridge.d.ts +12 -0
  55. package/dist/executor/ast-provenance-bridge.d.ts.map +1 -0
  56. package/dist/executor/ast-provenance-bridge.js +66 -0
  57. package/dist/executor/ast-provenance-bridge.js.map +1 -0
  58. package/dist/executor/ast-tracking-runtime.d.ts +7 -0
  59. package/dist/executor/ast-tracking-runtime.d.ts.map +1 -0
  60. package/dist/executor/ast-tracking-runtime.js +559 -0
  61. package/dist/executor/ast-tracking-runtime.js.map +1 -0
  62. package/dist/executor/bootstrap-generated.d.ts +32 -0
  63. package/dist/executor/bootstrap-generated.d.ts.map +1 -0
  64. package/dist/executor/bootstrap-generated.js +90 -0
  65. package/dist/executor/bootstrap-generated.js.map +1 -0
  66. package/dist/executor/compiler-config.d.ts +32 -0
  67. package/dist/executor/compiler-config.d.ts.map +1 -0
  68. package/dist/executor/compiler-config.js +99 -0
  69. package/dist/executor/compiler-config.js.map +1 -0
  70. package/dist/executor/constants.d.ts +4 -0
  71. package/dist/executor/constants.d.ts.map +1 -0
  72. package/dist/executor/constants.js +4 -0
  73. package/dist/executor/constants.js.map +1 -0
  74. package/dist/executor/error-handler.d.ts +9 -0
  75. package/dist/executor/error-handler.d.ts.map +1 -0
  76. package/dist/executor/error-handler.js +95 -0
  77. package/dist/executor/error-handler.js.map +1 -0
  78. package/dist/executor/execution-error-handler.d.ts +7 -0
  79. package/dist/executor/execution-error-handler.d.ts.map +1 -0
  80. package/dist/executor/execution-error-handler.js +136 -0
  81. package/dist/executor/execution-error-handler.js.map +1 -0
  82. package/dist/executor/executor.d.ts +20 -0
  83. package/dist/executor/executor.d.ts.map +1 -0
  84. package/dist/executor/executor.js +452 -0
  85. package/dist/executor/executor.js.map +1 -0
  86. package/dist/executor/index.d.ts +4 -0
  87. package/dist/executor/index.d.ts.map +1 -0
  88. package/dist/executor/index.js +3 -0
  89. package/dist/executor/index.js.map +1 -0
  90. package/dist/executor/resume-handler.d.ts +9 -0
  91. package/dist/executor/resume-handler.d.ts.map +1 -0
  92. package/dist/executor/resume-handler.js +22 -0
  93. package/dist/executor/resume-handler.js.map +1 -0
  94. package/dist/executor/sandbox-builder.d.ts +29 -0
  95. package/dist/executor/sandbox-builder.d.ts.map +1 -0
  96. package/dist/executor/sandbox-builder.js +538 -0
  97. package/dist/executor/sandbox-builder.js.map +1 -0
  98. package/dist/executor/sandbox-injector.d.ts +7 -0
  99. package/dist/executor/sandbox-injector.d.ts.map +1 -0
  100. package/dist/executor/sandbox-injector.js +293 -0
  101. package/dist/executor/sandbox-injector.js.map +1 -0
  102. package/dist/executor/types.d.ts +21 -0
  103. package/dist/executor/types.d.ts.map +1 -0
  104. package/dist/executor/types.js +2 -0
  105. package/dist/executor/types.js.map +1 -0
  106. package/dist/explorer/index.d.ts +69 -0
  107. package/dist/explorer/index.d.ts.map +1 -0
  108. package/dist/explorer/index.js +228 -0
  109. package/dist/explorer/index.js.map +1 -0
  110. package/dist/handlers/definitions.handler.d.ts +3 -0
  111. package/dist/handlers/definitions.handler.d.ts.map +1 -0
  112. package/dist/handlers/definitions.handler.js +11 -0
  113. package/dist/handlers/definitions.handler.js.map +1 -0
  114. package/dist/handlers/execute.handler.d.ts +7 -0
  115. package/dist/handlers/execute.handler.d.ts.map +1 -0
  116. package/dist/handlers/execute.handler.js +225 -0
  117. package/dist/handlers/execute.handler.js.map +1 -0
  118. package/dist/handlers/explorer.handler.d.ts +4 -0
  119. package/dist/handlers/explorer.handler.d.ts.map +1 -0
  120. package/dist/handlers/explorer.handler.js +10 -0
  121. package/dist/handlers/explorer.handler.js.map +1 -0
  122. package/dist/handlers/init.handler.d.ts +5 -0
  123. package/dist/handlers/init.handler.d.ts.map +1 -0
  124. package/dist/handlers/init.handler.js +41 -0
  125. package/dist/handlers/init.handler.js.map +1 -0
  126. package/dist/handlers/resume.handler.d.ts +6 -0
  127. package/dist/handlers/resume.handler.d.ts.map +1 -0
  128. package/dist/handlers/resume.handler.js +256 -0
  129. package/dist/handlers/resume.handler.js.map +1 -0
  130. package/dist/handlers/search.handler.d.ts +5 -0
  131. package/dist/handlers/search.handler.d.ts.map +1 -0
  132. package/dist/handlers/search.handler.js +11 -0
  133. package/dist/handlers/search.handler.js.map +1 -0
  134. package/dist/http/request-handler.d.ts +15 -0
  135. package/dist/http/request-handler.d.ts.map +1 -0
  136. package/dist/http/request-handler.js +94 -0
  137. package/dist/http/request-handler.js.map +1 -0
  138. package/dist/http/router.d.ts +4 -0
  139. package/dist/http/router.d.ts.map +1 -0
  140. package/dist/http/router.js +32 -0
  141. package/dist/http/router.js.map +1 -0
  142. package/dist/index.d.ts +10 -0
  143. package/dist/index.d.ts.map +1 -0
  144. package/dist/index.js +8 -0
  145. package/dist/index.js.map +1 -0
  146. package/dist/instrumentation/index.d.ts +5 -0
  147. package/dist/instrumentation/index.d.ts.map +1 -0
  148. package/dist/instrumentation/index.js +5 -0
  149. package/dist/instrumentation/index.js.map +1 -0
  150. package/dist/instrumentation/serializer.d.ts +61 -0
  151. package/dist/instrumentation/serializer.d.ts.map +1 -0
  152. package/dist/instrumentation/serializer.js +334 -0
  153. package/dist/instrumentation/serializer.js.map +1 -0
  154. package/dist/instrumentation/state-manager.d.ts +61 -0
  155. package/dist/instrumentation/state-manager.d.ts.map +1 -0
  156. package/dist/instrumentation/state-manager.js +205 -0
  157. package/dist/instrumentation/state-manager.js.map +1 -0
  158. package/dist/instrumentation/transformer.d.ts +9 -0
  159. package/dist/instrumentation/transformer.d.ts.map +1 -0
  160. package/dist/instrumentation/transformer.js +70 -0
  161. package/dist/instrumentation/transformer.js.map +1 -0
  162. package/dist/instrumentation/types.d.ts +59 -0
  163. package/dist/instrumentation/types.d.ts.map +1 -0
  164. package/dist/instrumentation/types.js +5 -0
  165. package/dist/instrumentation/types.js.map +1 -0
  166. package/dist/middleware/audit.d.ts +18 -0
  167. package/dist/middleware/audit.d.ts.map +1 -0
  168. package/dist/middleware/audit.js +76 -0
  169. package/dist/middleware/audit.js.map +1 -0
  170. package/dist/openapi/index.d.ts +133 -0
  171. package/dist/openapi/index.d.ts.map +1 -0
  172. package/dist/openapi/index.js +235 -0
  173. package/dist/openapi/index.js.map +1 -0
  174. package/dist/openapi-loader.d.ts +87 -0
  175. package/dist/openapi-loader.d.ts.map +1 -0
  176. package/dist/openapi-loader.js +491 -0
  177. package/dist/openapi-loader.js.map +1 -0
  178. package/dist/routes/index.d.ts +21 -0
  179. package/dist/routes/index.d.ts.map +1 -0
  180. package/dist/routes/index.js +47 -0
  181. package/dist/routes/index.js.map +1 -0
  182. package/dist/search/index.d.ts +48 -0
  183. package/dist/search/index.d.ts.map +1 -0
  184. package/dist/search/index.js +156 -0
  185. package/dist/search/index.js.map +1 -0
  186. package/dist/security/index.d.ts +2 -0
  187. package/dist/security/index.d.ts.map +1 -0
  188. package/dist/security/index.js +2 -0
  189. package/dist/security/index.js.map +1 -0
  190. package/dist/shutdown.d.ts +19 -0
  191. package/dist/shutdown.d.ts.map +1 -0
  192. package/dist/shutdown.js +87 -0
  193. package/dist/shutdown.js.map +1 -0
  194. package/dist/utils/banner.d.ts +12 -0
  195. package/dist/utils/banner.d.ts.map +1 -0
  196. package/dist/utils/banner.js +18 -0
  197. package/dist/utils/banner.js.map +1 -0
  198. package/dist/utils/context.d.ts +16 -0
  199. package/dist/utils/context.d.ts.map +1 -0
  200. package/dist/utils/context.js +44 -0
  201. package/dist/utils/context.js.map +1 -0
  202. package/dist/utils/error.d.ts +8 -0
  203. package/dist/utils/error.d.ts.map +1 -0
  204. package/dist/utils/error.js +17 -0
  205. package/dist/utils/error.js.map +1 -0
  206. package/dist/utils/hint-based-instrumentation.d.ts +14 -0
  207. package/dist/utils/hint-based-instrumentation.d.ts.map +1 -0
  208. package/dist/utils/hint-based-instrumentation.js +84 -0
  209. package/dist/utils/hint-based-instrumentation.js.map +1 -0
  210. package/dist/utils/index.d.ts +8 -0
  211. package/dist/utils/index.d.ts.map +1 -0
  212. package/dist/utils/index.js +8 -0
  213. package/dist/utils/index.js.map +1 -0
  214. package/dist/utils/info.d.ts +20 -0
  215. package/dist/utils/info.d.ts.map +1 -0
  216. package/dist/utils/info.js +15 -0
  217. package/dist/utils/info.js.map +1 -0
  218. package/dist/utils/provenance-reattachment.d.ts +32 -0
  219. package/dist/utils/provenance-reattachment.d.ts.map +1 -0
  220. package/dist/utils/provenance-reattachment.js +115 -0
  221. package/dist/utils/provenance-reattachment.js.map +1 -0
  222. package/dist/utils/request.d.ts +21 -0
  223. package/dist/utils/request.d.ts.map +1 -0
  224. package/dist/utils/request.js +44 -0
  225. package/dist/utils/request.js.map +1 -0
  226. package/dist/utils/response.d.ts +30 -0
  227. package/dist/utils/response.d.ts.map +1 -0
  228. package/dist/utils/response.js +53 -0
  229. package/dist/utils/response.js.map +1 -0
  230. package/dist/utils/runtime-types.d.ts +6 -0
  231. package/dist/utils/runtime-types.d.ts.map +1 -0
  232. package/dist/utils/runtime-types.js +14 -0
  233. package/dist/utils/runtime-types.js.map +1 -0
  234. package/dist/utils/schema.d.ts +9 -0
  235. package/dist/utils/schema.d.ts.map +1 -0
  236. package/dist/utils/schema.js +13 -0
  237. package/dist/utils/schema.js.map +1 -0
  238. package/dist/utils/token-emitter.d.ts +21 -0
  239. package/dist/utils/token-emitter.d.ts.map +1 -0
  240. package/dist/utils/token-emitter.js +129 -0
  241. package/dist/utils/token-emitter.js.map +1 -0
  242. package/dist/validator/index.d.ts +36 -0
  243. package/dist/validator/index.d.ts.map +1 -0
  244. package/dist/validator/index.js +224 -0
  245. package/dist/validator/index.js.map +1 -0
  246. package/package.json +68 -0
  247. package/src/aggregator/index.ts +207 -0
  248. package/src/callback/index.ts +191 -0
  249. package/src/client-sessions.ts +234 -0
  250. package/src/controllers/definitions.controller.ts +19 -0
  251. package/src/controllers/execute.controller.ts +166 -0
  252. package/src/controllers/info.controller.ts +14 -0
  253. package/src/controllers/resume.controller.ts +92 -0
  254. package/src/controllers/search.controller.ts +16 -0
  255. package/src/controllers/stream.controller.ts +190 -0
  256. package/src/core/config.ts +180 -0
  257. package/src/core/http.ts +21 -0
  258. package/src/create-server.ts +536 -0
  259. package/src/execution-state/index.ts +204 -0
  260. package/src/executor/ast-provenance-bridge.ts +80 -0
  261. package/src/executor/ast-tracking-runtime.ts +558 -0
  262. package/src/executor/bootstrap-generated.ts +90 -0
  263. package/src/executor/compiler-config.ts +146 -0
  264. package/src/executor/constants.ts +5 -0
  265. package/src/executor/error-handler.ts +118 -0
  266. package/src/executor/execution-error-handler.ts +178 -0
  267. package/src/executor/executor.ts +631 -0
  268. package/src/executor/index.ts +3 -0
  269. package/src/executor/resume-handler.ts +39 -0
  270. package/src/executor/sandbox-builder.ts +684 -0
  271. package/src/executor/sandbox-injector.ts +345 -0
  272. package/src/executor/types.ts +22 -0
  273. package/src/explorer/index.ts +297 -0
  274. package/src/handlers/definitions.handler.ts +13 -0
  275. package/src/handlers/execute.handler.ts +286 -0
  276. package/src/handlers/explorer.handler.ts +18 -0
  277. package/src/handlers/init.handler.ts +53 -0
  278. package/src/handlers/resume.handler.ts +316 -0
  279. package/src/handlers/search.handler.ts +32 -0
  280. package/src/http/request-handler.ts +117 -0
  281. package/src/http/router.ts +29 -0
  282. package/src/index.ts +60 -0
  283. package/src/instrumentation/index.ts +4 -0
  284. package/src/instrumentation/serializer.ts +421 -0
  285. package/src/instrumentation/state-manager.ts +237 -0
  286. package/src/instrumentation/transformer.ts +84 -0
  287. package/src/instrumentation/types.ts +76 -0
  288. package/src/middleware/audit.ts +101 -0
  289. package/src/openapi/index.ts +378 -0
  290. package/src/openapi-loader.ts +744 -0
  291. package/src/routes/index.ts +93 -0
  292. package/src/search/index.ts +216 -0
  293. package/src/security/index.ts +1 -0
  294. package/src/shutdown.ts +108 -0
  295. package/src/utils/banner.ts +25 -0
  296. package/src/utils/context.ts +58 -0
  297. package/src/utils/error.ts +25 -0
  298. package/src/utils/hint-based-instrumentation.ts +99 -0
  299. package/src/utils/index.ts +15 -0
  300. package/src/utils/info.ts +31 -0
  301. package/src/utils/provenance-reattachment.ts +144 -0
  302. package/src/utils/request.ts +53 -0
  303. package/src/utils/response.ts +69 -0
  304. package/src/utils/runtime-types.ts +14 -0
  305. package/src/utils/schema.ts +18 -0
  306. package/src/utils/token-emitter.ts +182 -0
  307. package/src/validator/index.ts +253 -0
@@ -0,0 +1,93 @@
1
+ import type { IncomingMessage, ServerResponse } from 'node:http';
2
+ import type { log } from '@mondaydotcomorg/atp-runtime';
3
+ import { handleInfo } from '../controllers/info.controller.js';
4
+ import { handleDefinitions } from '../controllers/definitions.controller.js';
5
+ import { handleSearch } from '../controllers/search.controller.js';
6
+ import { handleExecute } from '../controllers/execute.controller.js';
7
+ import { handleExecuteStream } from '../controllers/stream.controller.js';
8
+ import { handleResume } from '../controllers/resume.controller.js';
9
+ import type { APIAggregator } from '../aggregator/index.js';
10
+ import type { SearchEngine } from '../search/index.js';
11
+ import type { CodeValidator } from '../validator/index.js';
12
+ import type { SandboxExecutor } from '../executor/index.js';
13
+ import type { ExecutionStateManager } from '../execution-state/index.js';
14
+ import type { AuditConfig } from '../middleware/audit.js';
15
+ import { readBody } from '../utils/index.js';
16
+
17
+ export interface RouteContext {
18
+ aggregator: APIAggregator;
19
+ searchEngine: SearchEngine;
20
+ validator: CodeValidator;
21
+ executor: SandboxExecutor;
22
+ stateManager: ExecutionStateManager;
23
+ auditConfig?: AuditConfig;
24
+ defaultTimeout: number;
25
+ defaultMemoryLimit: number;
26
+ defaultLLMCallLimit: number;
27
+ }
28
+
29
+ export async function handleRoute(
30
+ req: IncomingMessage,
31
+ res: ServerResponse,
32
+ context: RouteContext,
33
+ logger: ReturnType<typeof log.child>
34
+ ): Promise<boolean> {
35
+ const clientId = req.headers['x-client-id'] as string | undefined;
36
+ const url = new URL(req.url ?? '/', `http://${req.headers.host}`);
37
+
38
+ if (url.pathname === '/api/info' && req.method === 'GET') {
39
+ logger.debug('Serving API info');
40
+ await handleInfo(req, res);
41
+ return true;
42
+ }
43
+
44
+ if (url.pathname === '/api/definitions' && req.method === 'GET') {
45
+ logger.debug('Serving API definitions');
46
+ await handleDefinitions(req, res, context.aggregator, url);
47
+ return true;
48
+ }
49
+
50
+ if (url.pathname === '/api/search' && req.method === 'POST') {
51
+ logger.debug('Searching API functions');
52
+ const body = await readBody(req);
53
+ await handleSearch(req, res, context.searchEngine, body);
54
+ return true;
55
+ }
56
+
57
+ if (url.pathname.match(/^\/api\/resume\/[^/]+$/) && req.method === 'POST') {
58
+ const executionId = url.pathname.split('/').pop()!;
59
+ const body = await readBody(req);
60
+ await handleResume(
61
+ req,
62
+ res,
63
+ { executor: context.executor, stateManager: context.stateManager },
64
+ executionId,
65
+ body,
66
+ logger
67
+ );
68
+ return true;
69
+ }
70
+
71
+ if (url.pathname === '/api/execute' && req.method === 'POST') {
72
+ const body = await readBody(req);
73
+ await handleExecuteStream(
74
+ req,
75
+ res,
76
+ {
77
+ validator: context.validator,
78
+ executor: context.executor,
79
+ stateManager: context.stateManager,
80
+ auditConfig: context.auditConfig,
81
+ defaultTimeout: context.defaultTimeout,
82
+ defaultMemoryLimit: context.defaultMemoryLimit,
83
+ defaultLLMCallLimit: context.defaultLLMCallLimit,
84
+ },
85
+ body,
86
+ clientId,
87
+ logger
88
+ );
89
+ return true;
90
+ }
91
+
92
+ return false;
93
+ }
@@ -0,0 +1,216 @@
1
+ import type {
2
+ SearchOptions,
3
+ SearchResult,
4
+ APIGroupConfig,
5
+ AuthProvider,
6
+ ScopeFilteringConfig,
7
+ } from '@mondaydotcomorg/atp-protocol';
8
+
9
+ interface IndexedFunction {
10
+ apiGroup: string;
11
+ functionName: string;
12
+ description: string;
13
+ signature: string;
14
+ keywords: string[];
15
+ metadata?: {
16
+ requiredScopes?: string[];
17
+ provider?: string;
18
+ source?: 'server' | 'user';
19
+ };
20
+ }
21
+
22
+ /**
23
+ * SearchEngine provides semantic and keyword-based search over available API functions.
24
+ */
25
+ export class SearchEngine {
26
+ private index: IndexedFunction[] = [];
27
+
28
+ /**
29
+ * Creates a new SearchEngine instance.
30
+ * @param apiGroups - Array of API group configurations to index
31
+ */
32
+ constructor(apiGroups?: APIGroupConfig[]) {
33
+ if (apiGroups) {
34
+ this.buildIndex(apiGroups);
35
+ }
36
+ }
37
+
38
+ /**
39
+ * Builds the search index from API group configurations.
40
+ * @param apiGroups - API groups to index
41
+ */
42
+ private buildIndex(apiGroups: APIGroupConfig[]): void {
43
+ this.index = [];
44
+
45
+ for (const group of apiGroups) {
46
+ if (group.functions) {
47
+ for (const func of group.functions) {
48
+ const keywords = this.extractKeywords(func.description);
49
+ const signature = this.generateSignature(func);
50
+
51
+ this.index.push({
52
+ apiGroup: group.name,
53
+ functionName: func.name,
54
+ description: func.description,
55
+ signature,
56
+ keywords,
57
+ metadata: {
58
+ requiredScopes: func.requiredScopes,
59
+ provider: func.auth?.oauthProvider,
60
+ source: func.auth?.source,
61
+ },
62
+ });
63
+ }
64
+ }
65
+ }
66
+ }
67
+
68
+ /**
69
+ * Searches for API functions matching the query.
70
+ * @param options - Search options including query and filters
71
+ * @param userId - Optional user ID for scope filtering
72
+ * @param authProvider - Optional auth provider for checking user scopes
73
+ * @param scopeFilteringConfig - Optional scope filtering configuration
74
+ * @returns Array of search results sorted by relevance
75
+ */
76
+ async search(
77
+ options: SearchOptions,
78
+ userId?: string,
79
+ authProvider?: AuthProvider,
80
+ scopeFilteringConfig?: ScopeFilteringConfig
81
+ ): Promise<SearchResult[]> {
82
+ const queryWords = this.extractKeywords(options.query);
83
+ const results: Array<{ result: SearchResult; score: number }> = [];
84
+
85
+ for (const item of this.index) {
86
+ if (options.apiGroups && !options.apiGroups.includes(item.apiGroup)) {
87
+ continue;
88
+ }
89
+
90
+ if (scopeFilteringConfig?.enabled && item.metadata?.source === 'user') {
91
+ const shouldInclude = await this.checkScopes(
92
+ item,
93
+ userId,
94
+ authProvider,
95
+ scopeFilteringConfig
96
+ );
97
+ if (!shouldInclude) {
98
+ continue;
99
+ }
100
+ }
101
+
102
+ let score = 0;
103
+
104
+ if (item.description.toLowerCase().includes(options.query.toLowerCase())) {
105
+ score += 100;
106
+ }
107
+
108
+ if (item.functionName.toLowerCase().includes(options.query.toLowerCase())) {
109
+ score += 50;
110
+ }
111
+
112
+ for (const word of queryWords) {
113
+ if (item.keywords.includes(word)) {
114
+ score += 10;
115
+ }
116
+ if (item.functionName.toLowerCase().includes(word)) {
117
+ score += 5;
118
+ }
119
+ if (item.description.toLowerCase().includes(word)) {
120
+ score += 3;
121
+ }
122
+ }
123
+
124
+ if (score > 0) {
125
+ results.push({
126
+ result: {
127
+ apiGroup: item.apiGroup,
128
+ functionName: item.functionName,
129
+ description: item.description,
130
+ signature: item.signature,
131
+ relevanceScore: score,
132
+ },
133
+ score,
134
+ });
135
+ }
136
+ }
137
+
138
+ results.sort((a, b) => b.score - a.score);
139
+
140
+ const limit = options.maxResults ?? 10;
141
+ return results.slice(0, limit).map((r) => r.result);
142
+ }
143
+
144
+ /**
145
+ * Checks if a user has the required scopes for a function.
146
+ * @param item - Indexed function to check
147
+ * @param userId - User ID
148
+ * @param authProvider - Auth provider for looking up credentials
149
+ * @param config - Scope filtering configuration
150
+ * @returns True if function should be included in results
151
+ */
152
+ private async checkScopes(
153
+ item: IndexedFunction,
154
+ userId: string | undefined,
155
+ authProvider: AuthProvider | undefined,
156
+ config: ScopeFilteringConfig
157
+ ): Promise<boolean> {
158
+ const requiredScopes = item.metadata?.requiredScopes;
159
+ const provider = item.metadata?.provider;
160
+
161
+ if (!requiredScopes || requiredScopes.length === 0) {
162
+ return true;
163
+ }
164
+
165
+ if (!userId || !authProvider || !provider) {
166
+ return config.fallback === 'allow';
167
+ }
168
+
169
+ try {
170
+ const userCreds = await authProvider.getUserCredential?.(userId, provider);
171
+
172
+ if (!userCreds) {
173
+ return config.fallback === 'allow';
174
+ }
175
+
176
+ const userScopes = userCreds.scopes ?? [];
177
+ const hasAllScopes = requiredScopes.every((required) => userScopes.includes(required));
178
+
179
+ return hasAllScopes;
180
+ } catch (error) {
181
+ return config.fallback === 'allow';
182
+ }
183
+ }
184
+
185
+ /**
186
+ * Extracts keywords from a text string.
187
+ * @param text - Text to extract keywords from
188
+ * @returns Array of lowercase keywords
189
+ */
190
+ private extractKeywords(text: string): string[] {
191
+ return text
192
+ .toLowerCase()
193
+ .replace(/[^\w\s]/g, ' ')
194
+ .split(/\s+/)
195
+ .filter((word) => word.length > 2);
196
+ }
197
+
198
+ /**
199
+ * Generates a function signature string.
200
+ * @param func - Function definition
201
+ * @returns Signature string
202
+ */
203
+ private generateSignature(func: {
204
+ name: string;
205
+ inputSchema?: { properties?: Record<string, unknown> };
206
+ }): string {
207
+ const params: string[] = [];
208
+ if (func.inputSchema?.properties) {
209
+ for (const [key, value] of Object.entries(func.inputSchema.properties)) {
210
+ const prop = value as { type?: string };
211
+ params.push(`${key}: ${prop.type ?? 'any'}`);
212
+ }
213
+ }
214
+ return `${func.name}({ ${params.join(', ')} })`;
215
+ }
216
+ }
@@ -0,0 +1 @@
1
+ export * from '@mondaydotcomorg/atp-provenance';
@@ -0,0 +1,108 @@
1
+ import { log } from '@mondaydotcomorg/atp-runtime';
2
+ import type { Server } from 'node:http';
3
+ import { flushAuditQueue, shutdownAudit } from './middleware/audit.js';
4
+ import type { ExecutionStateManager } from './execution-state/index.js';
5
+ import type { ClientCallbackManager } from './callback/index.js';
6
+
7
+ interface ShutdownHandlers {
8
+ server?: Server;
9
+ stateManager?: ExecutionStateManager;
10
+ callbackManager?: ClientCallbackManager;
11
+ customHandlers?: Array<() => Promise<void>>;
12
+ }
13
+
14
+ let isShuttingDown = false;
15
+ let shutdownHandlers: ShutdownHandlers = {};
16
+
17
+ /**
18
+ * Registers handlers for graceful shutdown
19
+ */
20
+ export function registerShutdownHandlers(handlers: ShutdownHandlers): void {
21
+ shutdownHandlers = handlers;
22
+
23
+ process.on('SIGTERM', handleShutdown);
24
+ process.on('SIGINT', handleShutdown);
25
+
26
+ process.on('uncaughtException', (error) => {
27
+ log.error('Uncaught exception', { error: error.message, stack: error.stack });
28
+ handleShutdown();
29
+ });
30
+
31
+ process.on('unhandledRejection', (reason) => {
32
+ log.error('Unhandled promise rejection', { reason });
33
+ handleShutdown();
34
+ });
35
+ }
36
+
37
+ /**
38
+ * Performs graceful shutdown
39
+ */
40
+ async function handleShutdown(): Promise<void> {
41
+ if (isShuttingDown) {
42
+ log.warn('Shutdown already in progress');
43
+ return;
44
+ }
45
+
46
+ isShuttingDown = true;
47
+ log.info('Starting graceful shutdown...');
48
+
49
+ const shutdownTimeout = setTimeout(() => {
50
+ log.error('Shutdown timeout exceeded, forcing exit');
51
+ process.exit(1);
52
+ }, 30000);
53
+
54
+ try {
55
+ if (shutdownHandlers.server) {
56
+ log.info('Closing HTTP server...');
57
+ await new Promise<void>((resolve, reject) => {
58
+ shutdownHandlers.server!.close((err) => {
59
+ if (err) reject(err);
60
+ else resolve();
61
+ });
62
+ });
63
+ log.info('HTTP server closed');
64
+ }
65
+
66
+ log.info('Flushing audit queue...');
67
+ await flushAuditQueue();
68
+ shutdownAudit();
69
+ log.info('Audit system stopped');
70
+
71
+ if (shutdownHandlers.stateManager) {
72
+ log.info('Closing state manager...');
73
+ await shutdownHandlers.stateManager.close();
74
+ log.info('State manager closed');
75
+ }
76
+
77
+ if (shutdownHandlers.callbackManager) {
78
+ log.info('Cleaning up callback manager...');
79
+ shutdownHandlers.callbackManager.destroy();
80
+ log.info('Callback manager cleaned up');
81
+ }
82
+
83
+ if (shutdownHandlers.customHandlers) {
84
+ log.info('Running custom shutdown handlers...');
85
+ for (const handler of shutdownHandlers.customHandlers) {
86
+ await handler();
87
+ }
88
+ log.info('Custom handlers completed');
89
+ }
90
+
91
+ clearTimeout(shutdownTimeout);
92
+ log.info('Graceful shutdown completed');
93
+ process.exit(0);
94
+ } catch (error) {
95
+ clearTimeout(shutdownTimeout);
96
+ log.error('Error during shutdown', {
97
+ error: error instanceof Error ? error.message : 'Unknown error',
98
+ });
99
+ process.exit(1);
100
+ }
101
+ }
102
+
103
+ /**
104
+ * Triggers graceful shutdown programmatically
105
+ */
106
+ export function shutdown(): void {
107
+ handleShutdown();
108
+ }
@@ -0,0 +1,25 @@
1
+ import type { CacheProvider, AuthProvider, AuditSink } from '@mondaydotcomorg/atp-protocol';
2
+
3
+ export interface BannerOptions {
4
+ port: number;
5
+ cacheProvider?: CacheProvider;
6
+ authProvider?: AuthProvider;
7
+ auditSink?: AuditSink;
8
+ }
9
+
10
+ /**
11
+ * Prints a startup banner with server information
12
+ */
13
+ export function printBanner(options: BannerOptions): void {
14
+ const { port, cacheProvider, authProvider, auditSink } = options;
15
+
16
+ console.log('\n✨ ATP Server ready!');
17
+ console.log(`📍 http://localhost:${port}/`);
18
+ console.log(`📚 Type definitions: http://localhost:${port}/openapi.json`);
19
+ console.log(`🔍 API search: http://localhost:${port}/explorer`);
20
+
21
+ if (cacheProvider) console.log(`💾 Cache: ${cacheProvider.name}`);
22
+ if (authProvider) console.log(`🔒 Auth: ${authProvider.name}`);
23
+ if (auditSink) console.log(`📝 Audit: ${auditSink.name}`);
24
+ console.log();
25
+ }
@@ -0,0 +1,58 @@
1
+ import { IncomingMessage } from 'node:http';
2
+ import type { CacheProvider, AuthProvider, AuditSink } from '@mondaydotcomorg/atp-protocol';
3
+ import { log } from '@mondaydotcomorg/atp-runtime';
4
+ import type { RequestContext } from '../core/config.js';
5
+ import { parseQuery } from '../core/http.js';
6
+
7
+ export interface CreateContextOptions {
8
+ req: IncomingMessage;
9
+ cacheProvider?: CacheProvider;
10
+ authProvider?: AuthProvider;
11
+ auditSink?: AuditSink;
12
+ customLogger?: any;
13
+ responseHeaders: Map<IncomingMessage, Map<string, string>>;
14
+ }
15
+
16
+ /**
17
+ * Creates a request context object with all necessary helpers and providers
18
+ */
19
+ export function createContext(options: CreateContextOptions): RequestContext {
20
+ const { req, cacheProvider, authProvider, auditSink, customLogger, responseHeaders } = options;
21
+
22
+ const clientId = (req.headers['x-client-id'] as string) || undefined;
23
+ const userId = (req.headers['x-user-id'] as string) || undefined;
24
+
25
+ return {
26
+ method: req.method || 'GET',
27
+ path: req.url || '/',
28
+ query: parseQuery(req.url || '/'),
29
+ headers: req.headers as Record<string, string>,
30
+ body: null,
31
+ status: 200,
32
+ responseBody: null,
33
+ clientId,
34
+ userId,
35
+ cache: cacheProvider,
36
+ auth: authProvider,
37
+ audit: auditSink,
38
+ logger: customLogger || log,
39
+ throw: (status, message) => {
40
+ const error = new Error(message) as any;
41
+ error.status = status;
42
+ throw error;
43
+ },
44
+ assert: (condition, message) => {
45
+ if (!condition) {
46
+ const error = new Error(message) as any;
47
+ error.status = 400;
48
+ throw error;
49
+ }
50
+ },
51
+ set: (header, value) => {
52
+ if (!responseHeaders.has(req)) {
53
+ responseHeaders.set(req, new Map());
54
+ }
55
+ responseHeaders.get(req)!.set(header, value);
56
+ },
57
+ };
58
+ }
@@ -0,0 +1,25 @@
1
+ import { ServerResponse } from 'node:http';
2
+ import { log } from '@mondaydotcomorg/atp-runtime';
3
+
4
+ /**
5
+ * Handles HTTP request errors and sends appropriate responses
6
+ */
7
+ export function handleError(
8
+ res: ServerResponse,
9
+ error: Error & { status?: number },
10
+ requestId: string,
11
+ additionalHeaders?: Map<string, string>
12
+ ): void {
13
+ const status = error.status || 500;
14
+ log.error('Request failed', { requestId, error: error.message, stack: error.stack });
15
+
16
+ const headers: Record<string, string> = { 'Content-Type': 'application/json' };
17
+ if (additionalHeaders) {
18
+ for (const [key, value] of additionalHeaders.entries()) {
19
+ headers[key] = value;
20
+ }
21
+ }
22
+
23
+ res.writeHead(status, headers);
24
+ res.end(JSON.stringify({ error: error.message, requestId }));
25
+ }
@@ -0,0 +1,99 @@
1
+ /**
2
+ * Pre-process code to mark string literals that match provenance hints as tainted
3
+ * This enables cross-execution provenance tracking
4
+ */
5
+
6
+ import * as acorn from 'acorn';
7
+ import * as walk from 'acorn-walk';
8
+ import * as escodegen from 'escodegen';
9
+ import type { ProvenanceMetadata } from '@mondaydotcomorg/atp-provenance';
10
+ import { computeDigest } from '@mondaydotcomorg/atp-provenance';
11
+
12
+ /**
13
+ * Instrument string literals in code that match hint digests
14
+ * Wraps them in __mark_tainted(value, hintId) calls
15
+ */
16
+ export function instrumentLiteralsFromHints(
17
+ code: string,
18
+ hintMetadata: Map<string, ProvenanceMetadata>
19
+ ): { code: string; taintedCount: number } {
20
+ if (!hintMetadata || hintMetadata.size === 0) {
21
+ return { code, taintedCount: 0 };
22
+ }
23
+
24
+ let taintedCount = 0;
25
+
26
+ const valueMap = (hintMetadata as any).__valueMap as Map<string, ProvenanceMetadata> | undefined;
27
+
28
+ try {
29
+ const isAlreadyWrapped = code.trim().startsWith('(async function');
30
+
31
+ const wrappedCode = isAlreadyWrapped ? code : `(async function() {\n${code}\n})`;
32
+
33
+ const ast = acorn.parse(wrappedCode, {
34
+ ecmaVersion: 2022,
35
+ sourceType: 'script',
36
+ }) as any;
37
+
38
+ walk.simple(ast, {
39
+ Literal(node: any) {
40
+ if (typeof node.value === 'string') {
41
+ let shouldTaint = false;
42
+
43
+ const digest = computeDigest(node.value);
44
+ if (digest && hintMetadata.has(digest)) {
45
+ shouldTaint = true;
46
+ }
47
+
48
+ if (!shouldTaint && valueMap && valueMap.size > 0) {
49
+ for (const hintValue of valueMap.keys()) {
50
+ if (node.value.includes(hintValue)) {
51
+ shouldTaint = true;
52
+ break;
53
+ }
54
+ }
55
+ }
56
+
57
+ if (shouldTaint) {
58
+ const originalValue = node.value;
59
+ const originalRaw = (node as any).raw || JSON.stringify(originalValue);
60
+ (node as any).type = 'CallExpression';
61
+ (node as any).callee = {
62
+ type: 'Identifier',
63
+ name: '__mark_tainted',
64
+ };
65
+ (node as any).arguments = [
66
+ {
67
+ type: 'Literal',
68
+ value: originalValue,
69
+ raw: originalRaw,
70
+ },
71
+ ];
72
+ delete (node as any).value;
73
+ delete (node as any).raw;
74
+ taintedCount++;
75
+ }
76
+ }
77
+ },
78
+ });
79
+
80
+ let instrumentedCode = escodegen.generate(ast);
81
+
82
+ if (!isAlreadyWrapped) {
83
+ const unwrapPrefix = '(async function () {\n';
84
+ const unwrapSuffix = '\n})';
85
+ if (instrumentedCode.startsWith(unwrapPrefix) && instrumentedCode.endsWith(unwrapSuffix)) {
86
+ instrumentedCode = instrumentedCode.slice(unwrapPrefix.length, -unwrapSuffix.length);
87
+ }
88
+ } else {
89
+ if (instrumentedCode.endsWith(');')) {
90
+ instrumentedCode = instrumentedCode.slice(0, -1);
91
+ }
92
+ }
93
+
94
+ return { code: instrumentedCode, taintedCount };
95
+ } catch (error) {
96
+ console.error('Failed to instrument literals from hints:', error);
97
+ return { code, taintedCount: 0 };
98
+ }
99
+ }
@@ -0,0 +1,15 @@
1
+ export { toJSONSchema } from './schema.js';
2
+ export { printBanner, type BannerOptions } from './banner.js';
3
+ export { handleError } from './error.js';
4
+ export { createContext, type CreateContextOptions } from './context.js';
5
+ export { getServerInfo, type ServerInfo, type ServerLimits } from './info.js';
6
+ export { readBody, readJsonBody, DEFAULT_MAX_BODY_SIZE } from './request.js';
7
+ export {
8
+ sendJson,
9
+ sendError,
10
+ send404,
11
+ sendBadRequest,
12
+ sendServiceUnavailable,
13
+ setCorsHeaders,
14
+ handleOptions,
15
+ } from './response.js';
@@ -0,0 +1,31 @@
1
+ export interface ServerLimits {
2
+ maxTimeout: number;
3
+ maxMemory: number;
4
+ maxLLMCalls: number;
5
+ }
6
+
7
+ export interface ServerInfo {
8
+ version: string;
9
+ capabilities: {
10
+ execution: boolean;
11
+ search: boolean;
12
+ streaming: boolean;
13
+ llmCalls: boolean;
14
+ };
15
+ limits: ServerLimits;
16
+ }
17
+
18
+ /**
19
+ * Generates server information object
20
+ */
21
+ export function getServerInfo(limits: ServerLimits): ServerInfo {
22
+ return {
23
+ version: '1.0.0',
24
+ capabilities: { execution: true, search: true, streaming: false, llmCalls: true },
25
+ limits: {
26
+ maxTimeout: limits.maxTimeout,
27
+ maxMemory: limits.maxMemory,
28
+ maxLLMCalls: limits.maxLLMCalls,
29
+ },
30
+ };
31
+ }