@oscharko-dev/keiko-server 0.2.7 → 0.2.9

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 (302) hide show
  1. package/dist/.tsbuildinfo +1 -1
  2. package/dist/chat-handlers.d.ts +18 -2
  3. package/dist/chat-handlers.d.ts.map +1 -1
  4. package/dist/chat-handlers.js +185 -3
  5. package/dist/command-runner-errors.d.ts +17 -0
  6. package/dist/command-runner-errors.d.ts.map +1 -0
  7. package/dist/command-runner-errors.js +37 -0
  8. package/dist/command-runner-evidence.d.ts +23 -0
  9. package/dist/command-runner-evidence.d.ts.map +1 -0
  10. package/dist/command-runner-evidence.js +69 -0
  11. package/dist/command-runner-routes.d.ts +7 -0
  12. package/dist/command-runner-routes.d.ts.map +1 -0
  13. package/dist/command-runner-routes.js +175 -0
  14. package/dist/command-runner.d.ts +29 -0
  15. package/dist/command-runner.d.ts.map +1 -0
  16. package/dist/command-runner.js +348 -0
  17. package/dist/conversation-prompt.d.ts +2 -2
  18. package/dist/conversation-prompt.d.ts.map +1 -1
  19. package/dist/conversation-prompt.js +17 -1
  20. package/dist/csp.d.ts.map +1 -1
  21. package/dist/csp.js +3 -0
  22. package/dist/deps.d.ts +28 -1
  23. package/dist/deps.d.ts.map +1 -1
  24. package/dist/deps.js +288 -13
  25. package/dist/discussion-prompt.d.ts +4 -0
  26. package/dist/discussion-prompt.d.ts.map +1 -0
  27. package/dist/discussion-prompt.js +19 -0
  28. package/dist/editor/agentActionAudit.d.ts +18 -0
  29. package/dist/editor/agentActionAudit.d.ts.map +1 -0
  30. package/dist/editor/agentActionAudit.js +80 -0
  31. package/dist/editor/agentRoutes.d.ts +1 -0
  32. package/dist/editor/agentRoutes.d.ts.map +1 -1
  33. package/dist/editor/agentRoutes.js +292 -55
  34. package/dist/editor/agentSessionRegistry.d.ts +35 -0
  35. package/dist/editor/agentSessionRegistry.d.ts.map +1 -0
  36. package/dist/editor/agentSessionRegistry.js +243 -0
  37. package/dist/editor/completionRoutes.d.ts.map +1 -1
  38. package/dist/editor/completionRoutes.js +5 -10
  39. package/dist/editor/languageRoutes.d.ts +12 -1
  40. package/dist/editor/languageRoutes.d.ts.map +1 -1
  41. package/dist/editor/languageRoutes.js +71 -8
  42. package/dist/editor/languageService.d.ts +3 -2
  43. package/dist/editor/languageService.d.ts.map +1 -1
  44. package/dist/editor/languageService.js +41 -3
  45. package/dist/editor/languageServiceHost.d.ts.map +1 -1
  46. package/dist/editor/languageServiceHost.js +2 -2
  47. package/dist/editor/lsp/hostLanguageOperation.d.ts +17 -0
  48. package/dist/editor/lsp/hostLanguageOperation.d.ts.map +1 -0
  49. package/dist/editor/lsp/hostLanguageOperation.js +436 -0
  50. package/dist/editor/lsp/hostLanguageProviders.d.ts +26 -0
  51. package/dist/editor/lsp/hostLanguageProviders.d.ts.map +1 -0
  52. package/dist/editor/lsp/hostLanguageProviders.js +161 -0
  53. package/dist/editor/lsp/lspFrameCodec.d.ts +13 -0
  54. package/dist/editor/lsp/lspFrameCodec.d.ts.map +1 -0
  55. package/dist/editor/lsp/lspFrameCodec.js +164 -0
  56. package/dist/editor/lsp/lspJsonRpcClient.d.ts +34 -0
  57. package/dist/editor/lsp/lspJsonRpcClient.d.ts.map +1 -0
  58. package/dist/editor/lsp/lspJsonRpcClient.js +173 -0
  59. package/dist/editor/lsp/lspLanguageProvider.d.ts +7 -0
  60. package/dist/editor/lsp/lspLanguageProvider.d.ts.map +1 -0
  61. package/dist/editor/lsp/lspLanguageProvider.js +29 -0
  62. package/dist/editor/lsp/lspLifecycleLedger.d.ts +5 -0
  63. package/dist/editor/lsp/lspLifecycleLedger.d.ts.map +1 -0
  64. package/dist/editor/lsp/lspLifecycleLedger.js +37 -0
  65. package/dist/editor/lsp/lspNodeAdapter.d.ts +31 -0
  66. package/dist/editor/lsp/lspNodeAdapter.d.ts.map +1 -0
  67. package/dist/editor/lsp/lspNodeAdapter.js +230 -0
  68. package/dist/editor/lsp/lspProcessManager.d.ts +24 -0
  69. package/dist/editor/lsp/lspProcessManager.d.ts.map +1 -0
  70. package/dist/editor/lsp/lspProcessManager.js +255 -0
  71. package/dist/editor/lsp/lspRestartThrottle.d.ts +6 -0
  72. package/dist/editor/lsp/lspRestartThrottle.d.ts.map +1 -0
  73. package/dist/editor/lsp/lspRestartThrottle.js +24 -0
  74. package/dist/editor/lsp/lspStatusRoute.d.ts +8 -0
  75. package/dist/editor/lsp/lspStatusRoute.d.ts.map +1 -0
  76. package/dist/editor/lsp/lspStatusRoute.js +22 -0
  77. package/dist/editor/lsp/lspTransport.d.ts +19 -0
  78. package/dist/editor/lsp/lspTransport.d.ts.map +1 -0
  79. package/dist/editor/lsp/lspTransport.js +55 -0
  80. package/dist/editor/lsp/testing/fakeLspProcess.d.ts +23 -0
  81. package/dist/editor/lsp/testing/fakeLspProcess.d.ts.map +1 -0
  82. package/dist/editor/lsp/testing/fakeLspProcess.js +132 -0
  83. package/dist/files.d.ts +63 -0
  84. package/dist/files.d.ts.map +1 -1
  85. package/dist/files.js +799 -1
  86. package/dist/gateway-readiness.d.ts +6 -0
  87. package/dist/gateway-readiness.d.ts.map +1 -0
  88. package/dist/gateway-readiness.js +624 -0
  89. package/dist/gateway-setup.d.ts +2 -0
  90. package/dist/gateway-setup.d.ts.map +1 -1
  91. package/dist/gateway-setup.js +275 -11
  92. package/dist/gitDelivery/actionSheetProjection.d.ts +30 -0
  93. package/dist/gitDelivery/actionSheetProjection.d.ts.map +1 -0
  94. package/dist/gitDelivery/actionSheetProjection.js +206 -0
  95. package/dist/gitDelivery/actionSheetRoutes.d.ts +29 -0
  96. package/dist/gitDelivery/actionSheetRoutes.d.ts.map +1 -0
  97. package/dist/gitDelivery/actionSheetRoutes.js +293 -0
  98. package/dist/gitDelivery/agentOperationsRoutes.d.ts +33 -0
  99. package/dist/gitDelivery/agentOperationsRoutes.d.ts.map +1 -0
  100. package/dist/gitDelivery/agentOperationsRoutes.js +405 -0
  101. package/dist/gitDelivery/commitRoutes.d.ts +23 -0
  102. package/dist/gitDelivery/commitRoutes.d.ts.map +1 -0
  103. package/dist/gitDelivery/commitRoutes.js +204 -0
  104. package/dist/gitDelivery/evidenceRoutes.d.ts +9 -0
  105. package/dist/gitDelivery/evidenceRoutes.d.ts.map +1 -0
  106. package/dist/gitDelivery/evidenceRoutes.js +101 -0
  107. package/dist/gitDelivery/execution.d.ts +38 -0
  108. package/dist/gitDelivery/execution.d.ts.map +1 -0
  109. package/dist/gitDelivery/execution.js +117 -0
  110. package/dist/gitDelivery/localMutationRoutes.d.ts +30 -0
  111. package/dist/gitDelivery/localMutationRoutes.d.ts.map +1 -0
  112. package/dist/gitDelivery/localMutationRoutes.js +165 -0
  113. package/dist/gitDelivery/mergeExecution.d.ts +63 -0
  114. package/dist/gitDelivery/mergeExecution.d.ts.map +1 -0
  115. package/dist/gitDelivery/mergeExecution.js +168 -0
  116. package/dist/gitDelivery/mergeRoutes.d.ts +12 -0
  117. package/dist/gitDelivery/mergeRoutes.d.ts.map +1 -0
  118. package/dist/gitDelivery/mergeRoutes.js +218 -0
  119. package/dist/gitDelivery/mutationEvidenceLedger.d.ts +23 -0
  120. package/dist/gitDelivery/mutationEvidenceLedger.d.ts.map +1 -0
  121. package/dist/gitDelivery/mutationEvidenceLedger.js +87 -0
  122. package/dist/gitDelivery/prExecution.d.ts +54 -0
  123. package/dist/gitDelivery/prExecution.d.ts.map +1 -0
  124. package/dist/gitDelivery/prExecution.js +192 -0
  125. package/dist/gitDelivery/prRoutes.d.ts +12 -0
  126. package/dist/gitDelivery/prRoutes.d.ts.map +1 -0
  127. package/dist/gitDelivery/prRoutes.js +256 -0
  128. package/dist/gitDelivery/pushExecution.d.ts +43 -0
  129. package/dist/gitDelivery/pushExecution.d.ts.map +1 -0
  130. package/dist/gitDelivery/pushExecution.js +124 -0
  131. package/dist/gitDelivery/pushRoutes.d.ts +12 -0
  132. package/dist/gitDelivery/pushRoutes.d.ts.map +1 -0
  133. package/dist/gitDelivery/pushRoutes.js +200 -0
  134. package/dist/gitDelivery/requestGuards.d.ts +15 -0
  135. package/dist/gitDelivery/requestGuards.d.ts.map +1 -0
  136. package/dist/gitDelivery/requestGuards.js +97 -0
  137. package/dist/gitDelivery/syncEvidence.d.ts +37 -0
  138. package/dist/gitDelivery/syncEvidence.d.ts.map +1 -0
  139. package/dist/gitDelivery/syncEvidence.js +85 -0
  140. package/dist/gitDelivery/syncExecution.d.ts +30 -0
  141. package/dist/gitDelivery/syncExecution.d.ts.map +1 -0
  142. package/dist/gitDelivery/syncExecution.js +266 -0
  143. package/dist/gitDelivery/syncRoutes.d.ts +13 -0
  144. package/dist/gitDelivery/syncRoutes.d.ts.map +1 -0
  145. package/dist/gitDelivery/syncRoutes.js +200 -0
  146. package/dist/gitPorcelainStatus.d.ts +15 -0
  147. package/dist/gitPorcelainStatus.d.ts.map +1 -0
  148. package/dist/gitPorcelainStatus.js +104 -0
  149. package/dist/gitRepositoryReads.d.ts +10 -0
  150. package/dist/gitRepositoryReads.d.ts.map +1 -0
  151. package/dist/gitRepositoryReads.js +314 -0
  152. package/dist/gitRepositoryRoutes.d.ts +7 -0
  153. package/dist/gitRepositoryRoutes.d.ts.map +1 -0
  154. package/dist/gitRepositoryRoutes.js +221 -0
  155. package/dist/gitRoutes.d.ts +66 -0
  156. package/dist/gitRoutes.d.ts.map +1 -0
  157. package/dist/gitRoutes.js +543 -0
  158. package/dist/governed-workflow.d.ts +2 -0
  159. package/dist/governed-workflow.d.ts.map +1 -1
  160. package/dist/governed-workflow.js +4 -0
  161. package/dist/grounded-qa-hybrid.d.ts.map +1 -1
  162. package/dist/grounded-qa-hybrid.js +2 -0
  163. package/dist/grounded-qa-multi-source.d.ts.map +1 -1
  164. package/dist/grounded-qa-multi-source.js +1 -0
  165. package/dist/grounded-qa.d.ts +11 -0
  166. package/dist/grounded-qa.d.ts.map +1 -1
  167. package/dist/grounded-qa.js +14 -4
  168. package/dist/headers.d.ts +4 -1
  169. package/dist/headers.d.ts.map +1 -1
  170. package/dist/headers.js +11 -4
  171. package/dist/index.d.ts +8 -1
  172. package/dist/index.d.ts.map +1 -1
  173. package/dist/index.js +9 -1
  174. package/dist/local-knowledge-grounded-qa.d.ts.map +1 -1
  175. package/dist/local-knowledge-grounded-qa.js +11 -2
  176. package/dist/qualityIntelligence/figmaSnapshotRoutes.d.ts +1 -1
  177. package/dist/qualityIntelligence/figmaSnapshotRoutes.d.ts.map +1 -1
  178. package/dist/qualityIntelligence/figmaSnapshotRoutes.js +1 -1
  179. package/dist/read-handlers.d.ts +5 -0
  180. package/dist/read-handlers.d.ts.map +1 -1
  181. package/dist/read-handlers.js +57 -1
  182. package/dist/routes.d.ts.map +1 -1
  183. package/dist/routes.js +260 -12
  184. package/dist/run-engine.d.ts.map +1 -1
  185. package/dist/run-engine.js +3 -0
  186. package/dist/run-handlers.d.ts +0 -1
  187. package/dist/run-handlers.d.ts.map +1 -1
  188. package/dist/run-handlers.js +64 -211
  189. package/dist/run-request.d.ts +11 -0
  190. package/dist/run-request.d.ts.map +1 -1
  191. package/dist/run-request.js +158 -10
  192. package/dist/runtime/capabilityDetector.d.ts +38 -0
  193. package/dist/runtime/capabilityDetector.d.ts.map +1 -0
  194. package/dist/runtime/capabilityDetector.js +443 -0
  195. package/dist/runtime/capabilityRoutes.d.ts +9 -0
  196. package/dist/runtime/capabilityRoutes.d.ts.map +1 -0
  197. package/dist/runtime/capabilityRoutes.js +45 -0
  198. package/dist/runtime/containerEngineDetector.d.ts +17 -0
  199. package/dist/runtime/containerEngineDetector.d.ts.map +1 -0
  200. package/dist/runtime/containerEngineDetector.js +222 -0
  201. package/dist/runtime/containerRoutes.d.ts +8 -0
  202. package/dist/runtime/containerRoutes.d.ts.map +1 -0
  203. package/dist/runtime/containerRoutes.js +207 -0
  204. package/dist/runtime/containerRunner-errors.d.ts +18 -0
  205. package/dist/runtime/containerRunner-errors.d.ts.map +1 -0
  206. package/dist/runtime/containerRunner-errors.js +42 -0
  207. package/dist/runtime/containerRunner-evidence.d.ts +24 -0
  208. package/dist/runtime/containerRunner-evidence.d.ts.map +1 -0
  209. package/dist/runtime/containerRunner-evidence.js +74 -0
  210. package/dist/runtime/containerRunner.d.ts +37 -0
  211. package/dist/runtime/containerRunner.d.ts.map +1 -0
  212. package/dist/runtime/containerRunner.js +443 -0
  213. package/dist/server.d.ts.map +1 -1
  214. package/dist/server.js +24 -4
  215. package/dist/store/db.d.ts.map +1 -1
  216. package/dist/store/db.js +2 -1
  217. package/dist/store/index.d.ts +1 -1
  218. package/dist/store/index.d.ts.map +1 -1
  219. package/dist/store/messages.d.ts +2 -1
  220. package/dist/store/messages.d.ts.map +1 -1
  221. package/dist/store/messages.js +46 -4
  222. package/dist/store/schema.d.ts +1 -1
  223. package/dist/store/schema.d.ts.map +1 -1
  224. package/dist/store/schema.js +68 -1
  225. package/dist/store/types.d.ts +3 -2
  226. package/dist/store/types.d.ts.map +1 -1
  227. package/dist/task-workspace/active-store.d.ts +21 -0
  228. package/dist/task-workspace/active-store.d.ts.map +1 -0
  229. package/dist/task-workspace/active-store.js +55 -0
  230. package/dist/task-workspace/authorization.d.ts +7 -0
  231. package/dist/task-workspace/authorization.d.ts.map +1 -0
  232. package/dist/task-workspace/authorization.js +54 -0
  233. package/dist/task-workspace/binding.d.ts +3 -0
  234. package/dist/task-workspace/binding.d.ts.map +1 -0
  235. package/dist/task-workspace/binding.js +22 -0
  236. package/dist/task-workspace/cleanup.d.ts +4 -0
  237. package/dist/task-workspace/cleanup.d.ts.map +1 -0
  238. package/dist/task-workspace/cleanup.js +428 -0
  239. package/dist/task-workspace/errors.d.ts +14 -0
  240. package/dist/task-workspace/errors.d.ts.map +1 -0
  241. package/dist/task-workspace/errors.js +81 -0
  242. package/dist/task-workspace/evidence.d.ts +32 -0
  243. package/dist/task-workspace/evidence.d.ts.map +1 -0
  244. package/dist/task-workspace/evidence.js +52 -0
  245. package/dist/task-workspace/field-safety.d.ts +3 -0
  246. package/dist/task-workspace/field-safety.d.ts.map +1 -0
  247. package/dist/task-workspace/field-safety.js +42 -0
  248. package/dist/task-workspace/health.d.ts +4 -0
  249. package/dist/task-workspace/health.d.ts.map +1 -0
  250. package/dist/task-workspace/health.js +163 -0
  251. package/dist/task-workspace/lifecycle.d.ts +3 -0
  252. package/dist/task-workspace/lifecycle.d.ts.map +1 -0
  253. package/dist/task-workspace/lifecycle.js +248 -0
  254. package/dist/task-workspace/locks.d.ts +13 -0
  255. package/dist/task-workspace/locks.d.ts.map +1 -0
  256. package/dist/task-workspace/locks.js +44 -0
  257. package/dist/task-workspace/managed-root.d.ts +7 -0
  258. package/dist/task-workspace/managed-root.d.ts.map +1 -0
  259. package/dist/task-workspace/managed-root.js +98 -0
  260. package/dist/task-workspace/mutex.d.ts +8 -0
  261. package/dist/task-workspace/mutex.d.ts.map +1 -0
  262. package/dist/task-workspace/mutex.js +82 -0
  263. package/dist/task-workspace/naming.d.ts +15 -0
  264. package/dist/task-workspace/naming.d.ts.map +1 -0
  265. package/dist/task-workspace/naming.js +0 -0
  266. package/dist/task-workspace/provisioning.d.ts +3 -0
  267. package/dist/task-workspace/provisioning.d.ts.map +1 -0
  268. package/dist/task-workspace/provisioning.js +528 -0
  269. package/dist/task-workspace/reconciliation.d.ts +15 -0
  270. package/dist/task-workspace/reconciliation.d.ts.map +1 -0
  271. package/dist/task-workspace/reconciliation.js +274 -0
  272. package/dist/task-workspace/repair.d.ts +3 -0
  273. package/dist/task-workspace/repair.d.ts.map +1 -0
  274. package/dist/task-workspace/repair.js +286 -0
  275. package/dist/task-workspace/routes.d.ts +19 -0
  276. package/dist/task-workspace/routes.d.ts.map +1 -0
  277. package/dist/task-workspace/routes.js +481 -0
  278. package/dist/task-workspace/store.d.ts +12 -0
  279. package/dist/task-workspace/store.d.ts.map +1 -0
  280. package/dist/task-workspace/store.js +128 -0
  281. package/dist/task-workspace/types.d.ts +170 -0
  282. package/dist/task-workspace/types.d.ts.map +1 -0
  283. package/dist/task-workspace/types.js +5 -0
  284. package/dist/voice-action-governance.d.ts +23 -0
  285. package/dist/voice-action-governance.d.ts.map +1 -0
  286. package/dist/voice-action-governance.js +126 -0
  287. package/dist/voice-handlers.d.ts +6 -0
  288. package/dist/voice-handlers.d.ts.map +1 -0
  289. package/dist/voice-handlers.js +570 -0
  290. package/dist/voice-realtime-grounded-tool.d.ts +31 -0
  291. package/dist/voice-realtime-grounded-tool.d.ts.map +1 -0
  292. package/dist/voice-realtime-grounded-tool.js +322 -0
  293. package/dist/voice-realtime.d.ts +69 -0
  294. package/dist/voice-realtime.d.ts.map +1 -0
  295. package/dist/voice-realtime.js +787 -0
  296. package/dist/workspace-state-handlers.d.ts +5 -0
  297. package/dist/workspace-state-handlers.d.ts.map +1 -0
  298. package/dist/workspace-state-handlers.js +106 -0
  299. package/package.json +20 -19
  300. package/dist/grounded-handoff.d.ts +0 -4
  301. package/dist/grounded-handoff.d.ts.map +0 -1
  302. package/dist/grounded-handoff.js +0 -445
@@ -0,0 +1,443 @@
1
+ // Local runtime capability detector (Issue #1385, Epic #1491). This module is metadata-only:
2
+ // production detection never spawns host executables, never reads Git config, never calls package
3
+ // managers, and never talks to container daemons. It reports coarse, content-free capability states
4
+ // so editor/runtime epics can degrade gracefully without duplicating tool discovery.
5
+ import { accessSync, constants, statSync } from "node:fs";
6
+ import { delimiter, dirname, parse, relative, resolve } from "node:path";
7
+ import { RUNTIME_CAPABILITY_SCHEMA_VERSION, } from "@oscharko-dev/keiko-contracts";
8
+ import { readWorkspaceFile } from "@oscharko-dev/keiko-workspace";
9
+ import { isWithinWorkspace } from "@oscharko-dev/keiko-workspace";
10
+ import { nodeWorkspaceFs } from "@oscharko-dev/keiko-workspace/internal/fs";
11
+ export const DEFAULT_RUNTIME_CAPABILITY_DEADLINE_MS = 250;
12
+ const PACKAGE_READ_BYTES = 262_144;
13
+ export const RUNTIME_HOST_EXECUTABLE_SPECS = Object.freeze([
14
+ {
15
+ id: "git",
16
+ kind: "git",
17
+ executable: "git",
18
+ label: "Git",
19
+ remediationHint: "Install Git or make it available on PATH.",
20
+ },
21
+ {
22
+ id: "node",
23
+ kind: "node",
24
+ executable: "node",
25
+ label: "Node.js",
26
+ remediationHint: "Install Node.js or make it available on PATH.",
27
+ },
28
+ {
29
+ id: "npm",
30
+ kind: "package-manager",
31
+ executable: "npm",
32
+ label: "npm",
33
+ remediationHint: "Install npm with Node.js or make it available on PATH.",
34
+ },
35
+ {
36
+ id: "pnpm",
37
+ kind: "package-manager",
38
+ executable: "pnpm",
39
+ label: "pnpm",
40
+ remediationHint: "Install pnpm or make it available on PATH.",
41
+ },
42
+ {
43
+ id: "yarn",
44
+ kind: "package-manager",
45
+ executable: "yarn",
46
+ label: "Yarn",
47
+ remediationHint: "Install Yarn or make it available on PATH.",
48
+ },
49
+ {
50
+ id: "python",
51
+ kind: "language-toolchain",
52
+ executable: "python3",
53
+ label: "Python",
54
+ remediationHint: "Install Python or make python3 available on PATH.",
55
+ },
56
+ {
57
+ id: "java",
58
+ kind: "language-toolchain",
59
+ executable: "java",
60
+ label: "Java",
61
+ remediationHint: "Install a JDK/JRE or make java available on PATH.",
62
+ },
63
+ {
64
+ id: "go",
65
+ kind: "language-toolchain",
66
+ executable: "go",
67
+ label: "Go",
68
+ remediationHint: "Install Go or make go available on PATH.",
69
+ },
70
+ {
71
+ id: "rust",
72
+ kind: "language-toolchain",
73
+ executable: "rustc",
74
+ label: "Rust",
75
+ remediationHint: "Install Rust or make rustc available on PATH.",
76
+ },
77
+ {
78
+ id: "cargo",
79
+ kind: "language-toolchain",
80
+ executable: "cargo",
81
+ label: "Cargo",
82
+ remediationHint: "Install Cargo or make cargo available on PATH.",
83
+ },
84
+ {
85
+ id: "shellcheck",
86
+ kind: "language-toolchain",
87
+ executable: "shellcheck",
88
+ label: "ShellCheck",
89
+ remediationHint: "Install ShellCheck or make shellcheck available on PATH.",
90
+ },
91
+ {
92
+ id: "docker",
93
+ kind: "container-engine",
94
+ executable: "docker",
95
+ label: "Docker",
96
+ remediationHint: "Install Docker or make docker available on PATH.",
97
+ },
98
+ {
99
+ id: "podman",
100
+ kind: "container-engine",
101
+ executable: "podman",
102
+ label: "Podman",
103
+ remediationHint: "Install Podman or make podman available on PATH.",
104
+ },
105
+ ]);
106
+ function hasUnsafeExecutableName(name) {
107
+ return (name.length === 0 ||
108
+ name.includes("\u0000") ||
109
+ name.includes("/") ||
110
+ name.includes("\\") ||
111
+ name.includes(" "));
112
+ }
113
+ function executableExtensions(platform, pathext) {
114
+ if (platform !== "win32") {
115
+ return [""];
116
+ }
117
+ return (pathext ?? ".EXE;.CMD;.BAT;.COM").split(";").filter((value) => value.length > 0);
118
+ }
119
+ function writableByGroupOrOther(mode) {
120
+ return (mode & 0o022) !== 0;
121
+ }
122
+ function trustedPath(candidate, platform) {
123
+ if (platform === "win32") {
124
+ return true;
125
+ }
126
+ const file = statSync(candidate);
127
+ if (!file.isFile() || writableByGroupOrOther(file.mode)) {
128
+ return false;
129
+ }
130
+ const root = parse(candidate).root;
131
+ let current = dirname(candidate);
132
+ for (;;) {
133
+ const info = statSync(current);
134
+ if (!info.isDirectory() || writableByGroupOrOther(info.mode)) {
135
+ return false;
136
+ }
137
+ if (current === root) {
138
+ return true;
139
+ }
140
+ current = dirname(current);
141
+ }
142
+ }
143
+ function insideWorkspace(candidate, workspaceRoot, realCandidate) {
144
+ if (workspaceRoot === undefined) {
145
+ return false;
146
+ }
147
+ let realRoot = workspaceRoot;
148
+ try {
149
+ realRoot = nodeWorkspaceFs.realPath(workspaceRoot);
150
+ }
151
+ catch {
152
+ // Fall back to lexical root; missing roots are handled by the route before detector entry.
153
+ }
154
+ return isWithinWorkspace(workspaceRoot, candidate) || isWithinWorkspace(realRoot, realCandidate);
155
+ }
156
+ function candidateProbeOutcome(candidate, workspaceRoot, platform) {
157
+ try {
158
+ accessSync(candidate, constants.X_OK);
159
+ const realCandidate = nodeWorkspaceFs.realPath(candidate);
160
+ if (insideWorkspace(candidate, workspaceRoot, realCandidate) ||
161
+ !trustedPath(candidate, platform)) {
162
+ return { found: false, unsafePath: true, permissionDenied: false };
163
+ }
164
+ return { found: true, unsafePath: false, permissionDenied: false };
165
+ }
166
+ catch (error) {
167
+ const code = error.code;
168
+ return {
169
+ found: false,
170
+ unsafePath: false,
171
+ permissionDenied: code === "EACCES" || code === "EPERM",
172
+ };
173
+ }
174
+ }
175
+ function unavailableProbeResult(sawUnsafePath, sawPermissionDenied) {
176
+ if (sawUnsafePath) {
177
+ return { state: "policy-blocked", unavailableReason: "unsafe-path" };
178
+ }
179
+ if (sawPermissionDenied) {
180
+ return { state: "permission-denied", unavailableReason: "executable-not-runnable" };
181
+ }
182
+ return { state: "missing", unavailableReason: "executable-not-found" };
183
+ }
184
+ export class PathHostExecutableProbe {
185
+ env;
186
+ platform;
187
+ constructor(env = process.env, platform = process.platform) {
188
+ this.env = env;
189
+ this.platform = platform;
190
+ }
191
+ probe(executable, workspaceRoot) {
192
+ if (hasUnsafeExecutableName(executable)) {
193
+ return { state: "policy-blocked", unavailableReason: "policy-blocked" };
194
+ }
195
+ const pathValue = this.env.PATH ?? "";
196
+ const extensions = executableExtensions(this.platform, this.env.PATHEXT);
197
+ let sawPermissionDenied = false;
198
+ let sawUnsafePath = false;
199
+ for (const dir of pathValue.split(delimiter).filter(Boolean)) {
200
+ for (const ext of extensions) {
201
+ const candidate = resolve(resolve(dir), executable + ext);
202
+ const outcome = candidateProbeOutcome(candidate, workspaceRoot, this.platform);
203
+ if (outcome.found) {
204
+ return { state: "available" };
205
+ }
206
+ sawUnsafePath ||= outcome.unsafePath;
207
+ sawPermissionDenied ||= outcome.permissionDenied;
208
+ }
209
+ }
210
+ return unavailableProbeResult(sawUnsafePath, sawPermissionDenied);
211
+ }
212
+ }
213
+ function capabilityFromProbe(spec, result) {
214
+ const base = {
215
+ id: spec.id,
216
+ kind: spec.kind,
217
+ label: spec.label,
218
+ ...(result.version === undefined ? {} : { version: result.version }),
219
+ ...(result.state === "available" ? {} : { remediationHint: spec.remediationHint }),
220
+ };
221
+ return {
222
+ ...base,
223
+ state: result.state,
224
+ ...(result.unavailableReason === undefined
225
+ ? {}
226
+ : { unavailableReason: result.unavailableReason }),
227
+ };
228
+ }
229
+ function parseJsonObject(text) {
230
+ try {
231
+ const parsed = JSON.parse(text);
232
+ return typeof parsed === "object" && parsed !== null && !Array.isArray(parsed)
233
+ ? parsed
234
+ : undefined;
235
+ }
236
+ catch {
237
+ return undefined;
238
+ }
239
+ }
240
+ function readPackageJson(workspace, fs) {
241
+ try {
242
+ return parseJsonObject(readWorkspaceFile(workspace, "package.json", { maxBytes: PACKAGE_READ_BYTES }, fs).text);
243
+ }
244
+ catch {
245
+ return undefined;
246
+ }
247
+ }
248
+ function packageManagerFromPackageJson(record) {
249
+ const value = record?.packageManager;
250
+ if (typeof value !== "string" || value.length === 0 || value.length > 80) {
251
+ return undefined;
252
+ }
253
+ return value.split("@", 1)[0];
254
+ }
255
+ function scriptNames(record) {
256
+ const scripts = record?.scripts;
257
+ if (typeof scripts !== "object" || scripts === null || Array.isArray(scripts)) {
258
+ return [];
259
+ }
260
+ return Object.entries(scripts)
261
+ .filter(([, value]) => typeof value === "string")
262
+ .map(([name]) => name)
263
+ .filter((name) => name.length > 0 && name.length <= 120)
264
+ .sort();
265
+ }
266
+ function isLifecycleWrapper(lowerName, needle) {
267
+ return (lowerName === `pre${needle}` ||
268
+ lowerName === `post${needle}` ||
269
+ lowerName.startsWith(`pre${needle}:`) ||
270
+ lowerName.startsWith(`post${needle}:`));
271
+ }
272
+ function pickScript(names, exact, contains) {
273
+ for (const name of names) {
274
+ if (exact.includes(name.toLowerCase())) {
275
+ return name;
276
+ }
277
+ }
278
+ for (const name of names) {
279
+ const lower = name.toLowerCase();
280
+ if (contains.some((needle) => lower.includes(needle)) &&
281
+ !contains.some((needle) => isLifecycleWrapper(lower, needle))) {
282
+ return name;
283
+ }
284
+ }
285
+ return undefined;
286
+ }
287
+ function packageScriptSources(record) {
288
+ const names = scriptNames(record);
289
+ const packageManager = packageManagerFromPackageJson(record);
290
+ const mapping = {
291
+ test: pickScript(names, ["test"], ["test"]),
292
+ build: pickScript(names, ["build"], ["build"]),
293
+ lint: pickScript(names, ["lint"], ["lint", "eslint"]),
294
+ typecheck: pickScript(names, ["typecheck", "type-check", "tsc"], ["typecheck", "type-check"]),
295
+ };
296
+ return Object.entries(mapping)
297
+ .filter((entry) => entry[1] !== undefined)
298
+ .map(([commandKind, scriptName]) => ({
299
+ type: "package-json-script",
300
+ path: "package.json",
301
+ commandKind,
302
+ scriptName,
303
+ ...(packageManager === undefined ? {} : { packageManager }),
304
+ }));
305
+ }
306
+ function commandSourceCapability(source) {
307
+ const label = source.commandKind === undefined
308
+ ? "Command source"
309
+ : `${source.commandKind[0]?.toUpperCase() ?? ""}${source.commandKind.slice(1)} command source`;
310
+ return {
311
+ id: `command-source:${source.path}:${source.commandKind ?? source.scriptName ?? "manifest"}`,
312
+ kind: "command-source",
313
+ label,
314
+ state: "available",
315
+ source,
316
+ };
317
+ }
318
+ function packageManifestCapability(record) {
319
+ if (record === undefined) {
320
+ return {
321
+ id: "manifest:package-json",
322
+ kind: "command-source",
323
+ label: "package.json command source",
324
+ state: "missing",
325
+ unavailableReason: "manifest-not-found",
326
+ remediationHint: "Add package.json when Node package scripts should be discoverable.",
327
+ source: { type: "package-json-script", path: "package.json" },
328
+ };
329
+ }
330
+ return {
331
+ id: "manifest:package-json",
332
+ kind: "command-source",
333
+ label: "package.json command source",
334
+ state: "available",
335
+ source: { type: "package-json-script", path: "package.json" },
336
+ };
337
+ }
338
+ function relativeWorkspacePath(root, absolutePath) {
339
+ return relative(root, absolutePath).split("\\").join("/");
340
+ }
341
+ function addManifestCapability(capabilities, workspace, fs, path, label) {
342
+ const absolute = resolve(workspace.root, path);
343
+ try {
344
+ if (fs.exists(absolute) && fs.stat(absolute).isFile) {
345
+ capabilities.push({
346
+ id: `manifest:${path}`,
347
+ kind: "command-source",
348
+ label,
349
+ state: "available",
350
+ source: {
351
+ type: path.endsWith(".lock") || path.endsWith("lockfile") ? "lockfile" : "ecosystem-manifest",
352
+ path: relativeWorkspacePath(workspace.root, absolute),
353
+ },
354
+ });
355
+ }
356
+ }
357
+ catch {
358
+ // Manifest discovery is best-effort and never blocks the endpoint.
359
+ }
360
+ }
361
+ function workspaceCapabilities(workspace, fs) {
362
+ if (workspace === undefined) {
363
+ return [];
364
+ }
365
+ const capabilities = [];
366
+ const packageJson = readPackageJson(workspace, fs);
367
+ capabilities.push(packageManifestCapability(packageJson));
368
+ for (const source of packageScriptSources(packageJson)) {
369
+ capabilities.push(commandSourceCapability(source));
370
+ }
371
+ if (packageJson !== undefined && typeof packageJson.packageManager === "string") {
372
+ capabilities.push({
373
+ id: "manifest:package-manager",
374
+ kind: "command-source",
375
+ label: "package manager declaration",
376
+ state: "available",
377
+ source: { type: "ecosystem-manifest", path: "package.json" },
378
+ });
379
+ }
380
+ addManifestCapability(capabilities, workspace, fs, "pnpm-lock.yaml", "pnpm lockfile");
381
+ addManifestCapability(capabilities, workspace, fs, "yarn.lock", "Yarn lockfile");
382
+ addManifestCapability(capabilities, workspace, fs, "package-lock.json", "npm lockfile");
383
+ addManifestCapability(capabilities, workspace, fs, "Cargo.toml", "Rust manifest");
384
+ addManifestCapability(capabilities, workspace, fs, "go.mod", "Go module manifest");
385
+ addManifestCapability(capabilities, workspace, fs, "pyproject.toml", "Python project manifest");
386
+ addManifestCapability(capabilities, workspace, fs, "pom.xml", "Maven manifest");
387
+ addManifestCapability(capabilities, workspace, fs, "build.gradle", "Gradle manifest");
388
+ addManifestCapability(capabilities, workspace, fs, "build.gradle.kts", "Gradle Kotlin manifest");
389
+ addManifestCapability(capabilities, workspace, fs, "Dockerfile", "Dockerfile");
390
+ return capabilities;
391
+ }
392
+ function deadlineExpired(startedAt, now, deadlineMs) {
393
+ return now() - startedAt >= deadlineMs;
394
+ }
395
+ function deadlineCapability() {
396
+ return {
397
+ id: "runtime-detection:deadline",
398
+ kind: "command-source",
399
+ label: "Runtime detection deadline",
400
+ state: "missing",
401
+ unavailableReason: "probe-timed-out",
402
+ remediationHint: "Retry runtime detection or reduce host PATH size.",
403
+ };
404
+ }
405
+ function detectHostCapabilities(specs, probe, workspaceRoot, generatedAtMs, now, deadlineMs) {
406
+ const capabilities = [];
407
+ for (const spec of specs) {
408
+ if (deadlineExpired(generatedAtMs, now, deadlineMs)) {
409
+ capabilities.push(deadlineCapability());
410
+ break;
411
+ }
412
+ capabilities.push(capabilityFromProbe(spec, probe.probe(spec.executable, workspaceRoot)));
413
+ }
414
+ return capabilities;
415
+ }
416
+ function runtimeProbe(options) {
417
+ if (options.probe !== undefined) {
418
+ return options.probe;
419
+ }
420
+ return new PathHostExecutableProbe(options.env ?? process.env, options.platform ?? process.platform);
421
+ }
422
+ function appendWorkspaceCapabilities(capabilities, options, fs, generatedAtMs, now, deadlineMs) {
423
+ if (deadlineExpired(generatedAtMs, now, deadlineMs)) {
424
+ return;
425
+ }
426
+ capabilities.push(...workspaceCapabilities(options.workspace, fs));
427
+ }
428
+ export function detectRuntimeCapabilities(options = {}) {
429
+ const now = options.now ?? Date.now;
430
+ const generatedAtMs = now();
431
+ const deadlineMs = options.deadlineMs ?? DEFAULT_RUNTIME_CAPABILITY_DEADLINE_MS;
432
+ const fs = options.fs ?? nodeWorkspaceFs;
433
+ const workspaceRoot = options.workspace?.root;
434
+ const probe = runtimeProbe(options);
435
+ const capabilities = detectHostCapabilities(options.specs ?? RUNTIME_HOST_EXECUTABLE_SPECS, probe, workspaceRoot, generatedAtMs, now, deadlineMs);
436
+ appendWorkspaceCapabilities(capabilities, options, fs, generatedAtMs, now, deadlineMs);
437
+ return {
438
+ schemaVersion: RUNTIME_CAPABILITY_SCHEMA_VERSION,
439
+ generatedAtMs,
440
+ deadlineMs,
441
+ capabilities,
442
+ };
443
+ }
@@ -0,0 +1,9 @@
1
+ import { type WorkspaceInfo } from "@oscharko-dev/keiko-workspace";
2
+ import { type RouteContext, type RouteResult } from "../routes.js";
3
+ import type { UiHandlerDeps } from "../deps.js";
4
+ import { type RuntimeCapabilityDetectorOptions } from "./capabilityDetector.js";
5
+ export type RuntimeCapabilityRouteOptions = Omit<RuntimeCapabilityDetectorOptions, "workspace"> & {
6
+ readonly detectWorkspace?: ((root: string) => WorkspaceInfo) | undefined;
7
+ };
8
+ export declare function handleRuntimeCapabilities(ctx: RouteContext, deps: UiHandlerDeps, options?: RuntimeCapabilityRouteOptions): Promise<RouteResult>;
9
+ //# sourceMappingURL=capabilityRoutes.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"capabilityRoutes.d.ts","sourceRoot":"","sources":["../../src/runtime/capabilityRoutes.ts"],"names":[],"mappings":"AAAA,OAAO,EAAqB,KAAK,aAAa,EAAE,MAAM,+BAA+B,CAAC;AACtF,OAAO,EAAa,KAAK,YAAY,EAAE,KAAK,WAAW,EAAE,MAAM,cAAc,CAAC;AAC9E,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAEhD,OAAO,EAEL,KAAK,gCAAgC,EACtC,MAAM,yBAAyB,CAAC;AAEjC,MAAM,MAAM,6BAA6B,GAAG,IAAI,CAAC,gCAAgC,EAAE,WAAW,CAAC,GAAG;IAChG,QAAQ,CAAC,eAAe,CAAC,EAAE,CAAC,CAAC,IAAI,EAAE,MAAM,KAAK,aAAa,CAAC,GAAG,SAAS,CAAC;CAC1E,CAAC;AAmBF,wBAAsB,yBAAyB,CAC7C,GAAG,EAAE,YAAY,EACjB,IAAI,EAAE,aAAa,EACnB,OAAO,GAAE,6BAAkC,GAC1C,OAAO,CAAC,WAAW,CAAC,CA8BtB"}
@@ -0,0 +1,45 @@
1
+ import { detectWorkspaceAt } from "@oscharko-dev/keiko-workspace";
2
+ import { errorBody } from "../routes.js";
3
+ import { resolveRoot, runFilesHandler } from "../files.js";
4
+ import { detectRuntimeCapabilities, } from "./capabilityDetector.js";
5
+ function badRoot() {
6
+ return {
7
+ status: 400,
8
+ body: errorBody("BAD_REQUEST", "The root query parameter must be a non-empty local path."),
9
+ };
10
+ }
11
+ function workspaceNotRegistered() {
12
+ return {
13
+ status: 403,
14
+ body: errorBody("WORKSPACE_NOT_REGISTERED", "The workspace directory is not a registered project."),
15
+ };
16
+ }
17
+ export async function handleRuntimeCapabilities(ctx, deps, options = {}) {
18
+ const rawRoot = ctx.url.searchParams.get("root");
19
+ if (rawRoot === null) {
20
+ return {
21
+ status: 200,
22
+ body: deps.redactor(detectRuntimeCapabilities({
23
+ env: deps.env,
24
+ ...options,
25
+ })),
26
+ };
27
+ }
28
+ const root = rawRoot.trim();
29
+ if (root.length === 0) {
30
+ return badRoot();
31
+ }
32
+ if (!deps.store.listProjects().some((project) => project.path === root)) {
33
+ return workspaceNotRegistered();
34
+ }
35
+ return runFilesHandler(async () => {
36
+ const resolved = await resolveRoot(deps.store, root, deps.redactor);
37
+ const workspace = (options.detectWorkspace ?? detectWorkspaceAt)(resolved.realRoot);
38
+ const body = detectRuntimeCapabilities({
39
+ env: deps.env,
40
+ ...options,
41
+ workspace,
42
+ });
43
+ return { status: 200, body: deps.redactor(body) };
44
+ });
45
+ }
@@ -0,0 +1,17 @@
1
+ import { runCommand, type SandboxPolicy } from "@oscharko-dev/keiko-tools";
2
+ import type { WorkspaceInfo } from "@oscharko-dev/keiko-workspace";
3
+ import { type ContainerCapabilityResponse, type ContainerEngineId } from "@oscharko-dev/keiko-contracts";
4
+ export declare const DEFAULT_CONTAINER_PROBE_DEADLINE_MS: 4000;
5
+ export declare const SUPPORTED_DOCKER_MAJOR: 20;
6
+ export declare const KEIKO_CONTAINERS_DISABLED_ENV: "KEIKO_CONTAINERS_DISABLED";
7
+ export interface ContainerProbeDeps {
8
+ readonly runCommand: typeof runCommand;
9
+ readonly workspace?: WorkspaceInfo | undefined;
10
+ readonly policy?: SandboxPolicy | undefined;
11
+ readonly processEnv: NodeJS.ProcessEnv;
12
+ readonly now: () => number;
13
+ readonly deadlineMs?: number | undefined;
14
+ readonly engines?: readonly ContainerEngineId[] | undefined;
15
+ }
16
+ export declare function detectContainerEngines(deps: ContainerProbeDeps): Promise<ContainerCapabilityResponse>;
17
+ //# sourceMappingURL=containerEngineDetector.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"containerEngineDetector.d.ts","sourceRoot":"","sources":["../../src/runtime/containerEngineDetector.ts"],"names":[],"mappings":"AAYA,OAAO,EAIL,UAAU,EAGV,KAAK,aAAa,EACnB,MAAM,2BAA2B,CAAC;AAEnC,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAC;AACnE,OAAO,EAIL,KAAK,2BAA2B,EAChC,KAAK,iBAAiB,EAIvB,MAAM,+BAA+B,CAAC;AAEvC,eAAO,MAAM,mCAAmC,EAAG,IAAc,CAAC;AAClE,eAAO,MAAM,sBAAsB,EAAG,EAAW,CAAC;AAElD,eAAO,MAAM,6BAA6B,EAAG,2BAAoC,CAAC;AAqBlF,MAAM,WAAW,kBAAkB;IAEjC,QAAQ,CAAC,UAAU,EAAE,OAAO,UAAU,CAAC;IACvC,QAAQ,CAAC,SAAS,CAAC,EAAE,aAAa,GAAG,SAAS,CAAC;IAC/C,QAAQ,CAAC,MAAM,CAAC,EAAE,aAAa,GAAG,SAAS,CAAC;IAC5C,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC,UAAU,CAAC;IACvC,QAAQ,CAAC,GAAG,EAAE,MAAM,MAAM,CAAC;IAC3B,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACzC,QAAQ,CAAC,OAAO,CAAC,EAAE,SAAS,iBAAiB,EAAE,GAAG,SAAS,CAAC;CAC7D;AAqMD,wBAAsB,sBAAsB,CAC1C,IAAI,EAAE,kBAAkB,GACvB,OAAO,CAAC,2BAA2B,CAAC,CA2BtC"}