@code-yeongyu/senpi 2026.7.11 → 2026.7.13

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 (267) hide show
  1. package/CHANGELOG.md +17 -0
  2. package/dist/core/agent-session.d.ts +9 -0
  3. package/dist/core/agent-session.d.ts.map +1 -1
  4. package/dist/core/agent-session.js +56 -15
  5. package/dist/core/agent-session.js.map +1 -1
  6. package/dist/core/extensions/builtin/prompt-preset/gpt-5.6.d.ts.map +1 -1
  7. package/dist/core/extensions/builtin/prompt-preset/gpt-5.6.js +76 -25
  8. package/dist/core/extensions/builtin/prompt-preset/gpt-5.6.js.map +1 -1
  9. package/dist/core/resource-loader.d.ts +1 -0
  10. package/dist/core/resource-loader.d.ts.map +1 -1
  11. package/dist/core/resource-loader.js +20 -2
  12. package/dist/core/resource-loader.js.map +1 -1
  13. package/dist/modes/interactive/compaction-queue-transfer.d.ts +22 -0
  14. package/dist/modes/interactive/compaction-queue-transfer.d.ts.map +1 -0
  15. package/dist/modes/interactive/compaction-queue-transfer.js +82 -0
  16. package/dist/modes/interactive/compaction-queue-transfer.js.map +1 -0
  17. package/dist/modes/interactive/interactive-mode.d.ts +4 -0
  18. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  19. package/dist/modes/interactive/interactive-mode.js +83 -69
  20. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  21. package/node_modules/@babel/helper-string-parser/LICENSE +22 -0
  22. package/node_modules/@babel/helper-string-parser/README.md +19 -0
  23. package/node_modules/@babel/helper-string-parser/lib/index.js +295 -0
  24. package/node_modules/@babel/helper-string-parser/lib/index.js.map +1 -0
  25. package/node_modules/@babel/helper-string-parser/package.json +31 -0
  26. package/node_modules/@babel/helper-validator-identifier/LICENSE +22 -0
  27. package/node_modules/@babel/helper-validator-identifier/README.md +19 -0
  28. package/node_modules/@babel/helper-validator-identifier/lib/identifier.js +70 -0
  29. package/node_modules/@babel/helper-validator-identifier/lib/identifier.js.map +1 -0
  30. package/node_modules/@babel/helper-validator-identifier/lib/index.js +57 -0
  31. package/node_modules/@babel/helper-validator-identifier/lib/index.js.map +1 -0
  32. package/node_modules/@babel/helper-validator-identifier/lib/keyword.js +35 -0
  33. package/node_modules/@babel/helper-validator-identifier/lib/keyword.js.map +1 -0
  34. package/node_modules/@babel/helper-validator-identifier/package.json +31 -0
  35. package/node_modules/@babel/parser/LICENSE +19 -0
  36. package/node_modules/@babel/parser/README.md +19 -0
  37. package/node_modules/@babel/parser/bin/babel-parser.js +15 -0
  38. package/node_modules/@babel/parser/lib/index.js +14599 -0
  39. package/node_modules/@babel/parser/lib/index.js.map +1 -0
  40. package/node_modules/@babel/parser/package.json +50 -0
  41. package/node_modules/@babel/parser/typings/babel-parser.d.ts +262 -0
  42. package/node_modules/@babel/types/LICENSE +22 -0
  43. package/node_modules/@babel/types/README.md +19 -0
  44. package/node_modules/@babel/types/lib/asserts/assertNode.js +16 -0
  45. package/node_modules/@babel/types/lib/asserts/assertNode.js.map +1 -0
  46. package/node_modules/@babel/types/lib/asserts/generated/index.js +1251 -0
  47. package/node_modules/@babel/types/lib/asserts/generated/index.js.map +1 -0
  48. package/node_modules/@babel/types/lib/ast-types/generated/index.js +3 -0
  49. package/node_modules/@babel/types/lib/ast-types/generated/index.js.map +1 -0
  50. package/node_modules/@babel/types/lib/builders/flow/createFlowUnionType.js +18 -0
  51. package/node_modules/@babel/types/lib/builders/flow/createFlowUnionType.js.map +1 -0
  52. package/node_modules/@babel/types/lib/builders/flow/createTypeAnnotationBasedOnTypeof.js +31 -0
  53. package/node_modules/@babel/types/lib/builders/flow/createTypeAnnotationBasedOnTypeof.js.map +1 -0
  54. package/node_modules/@babel/types/lib/builders/generated/index.js +29 -0
  55. package/node_modules/@babel/types/lib/builders/generated/index.js.map +1 -0
  56. package/node_modules/@babel/types/lib/builders/generated/lowercase.js +2902 -0
  57. package/node_modules/@babel/types/lib/builders/generated/lowercase.js.map +1 -0
  58. package/node_modules/@babel/types/lib/builders/generated/uppercase.js +272 -0
  59. package/node_modules/@babel/types/lib/builders/generated/uppercase.js.map +1 -0
  60. package/node_modules/@babel/types/lib/builders/productions.js +12 -0
  61. package/node_modules/@babel/types/lib/builders/productions.js.map +1 -0
  62. package/node_modules/@babel/types/lib/builders/react/buildChildren.js +24 -0
  63. package/node_modules/@babel/types/lib/builders/react/buildChildren.js.map +1 -0
  64. package/node_modules/@babel/types/lib/builders/typescript/createTSUnionType.js +22 -0
  65. package/node_modules/@babel/types/lib/builders/typescript/createTSUnionType.js.map +1 -0
  66. package/node_modules/@babel/types/lib/builders/validateNode.js +21 -0
  67. package/node_modules/@babel/types/lib/builders/validateNode.js.map +1 -0
  68. package/node_modules/@babel/types/lib/clone/clone.js +12 -0
  69. package/node_modules/@babel/types/lib/clone/clone.js.map +1 -0
  70. package/node_modules/@babel/types/lib/clone/cloneDeep.js +12 -0
  71. package/node_modules/@babel/types/lib/clone/cloneDeep.js.map +1 -0
  72. package/node_modules/@babel/types/lib/clone/cloneDeepWithoutLoc.js +12 -0
  73. package/node_modules/@babel/types/lib/clone/cloneDeepWithoutLoc.js.map +1 -0
  74. package/node_modules/@babel/types/lib/clone/cloneNode.js +107 -0
  75. package/node_modules/@babel/types/lib/clone/cloneNode.js.map +1 -0
  76. package/node_modules/@babel/types/lib/clone/cloneWithoutLoc.js +12 -0
  77. package/node_modules/@babel/types/lib/clone/cloneWithoutLoc.js.map +1 -0
  78. package/node_modules/@babel/types/lib/comments/addComment.js +15 -0
  79. package/node_modules/@babel/types/lib/comments/addComment.js.map +1 -0
  80. package/node_modules/@babel/types/lib/comments/addComments.js +22 -0
  81. package/node_modules/@babel/types/lib/comments/addComments.js.map +1 -0
  82. package/node_modules/@babel/types/lib/comments/inheritInnerComments.js +12 -0
  83. package/node_modules/@babel/types/lib/comments/inheritInnerComments.js.map +1 -0
  84. package/node_modules/@babel/types/lib/comments/inheritLeadingComments.js +12 -0
  85. package/node_modules/@babel/types/lib/comments/inheritLeadingComments.js.map +1 -0
  86. package/node_modules/@babel/types/lib/comments/inheritTrailingComments.js +12 -0
  87. package/node_modules/@babel/types/lib/comments/inheritTrailingComments.js.map +1 -0
  88. package/node_modules/@babel/types/lib/comments/inheritsComments.js +17 -0
  89. package/node_modules/@babel/types/lib/comments/inheritsComments.js.map +1 -0
  90. package/node_modules/@babel/types/lib/comments/removeComments.js +15 -0
  91. package/node_modules/@babel/types/lib/comments/removeComments.js.map +1 -0
  92. package/node_modules/@babel/types/lib/constants/generated/index.js +60 -0
  93. package/node_modules/@babel/types/lib/constants/generated/index.js.map +1 -0
  94. package/node_modules/@babel/types/lib/constants/index.js +31 -0
  95. package/node_modules/@babel/types/lib/constants/index.js.map +1 -0
  96. package/node_modules/@babel/types/lib/converters/ensureBlock.js +14 -0
  97. package/node_modules/@babel/types/lib/converters/ensureBlock.js.map +1 -0
  98. package/node_modules/@babel/types/lib/converters/gatherSequenceExpressions.js +65 -0
  99. package/node_modules/@babel/types/lib/converters/gatherSequenceExpressions.js.map +1 -0
  100. package/node_modules/@babel/types/lib/converters/toBindingIdentifierName.js +14 -0
  101. package/node_modules/@babel/types/lib/converters/toBindingIdentifierName.js.map +1 -0
  102. package/node_modules/@babel/types/lib/converters/toBlock.js +29 -0
  103. package/node_modules/@babel/types/lib/converters/toBlock.js.map +1 -0
  104. package/node_modules/@babel/types/lib/converters/toComputedKey.js +14 -0
  105. package/node_modules/@babel/types/lib/converters/toComputedKey.js.map +1 -0
  106. package/node_modules/@babel/types/lib/converters/toExpression.js +28 -0
  107. package/node_modules/@babel/types/lib/converters/toExpression.js.map +1 -0
  108. package/node_modules/@babel/types/lib/converters/toIdentifier.js +25 -0
  109. package/node_modules/@babel/types/lib/converters/toIdentifier.js.map +1 -0
  110. package/node_modules/@babel/types/lib/converters/toKeyAlias.js +38 -0
  111. package/node_modules/@babel/types/lib/converters/toKeyAlias.js.map +1 -0
  112. package/node_modules/@babel/types/lib/converters/toSequenceExpression.js +19 -0
  113. package/node_modules/@babel/types/lib/converters/toSequenceExpression.js.map +1 -0
  114. package/node_modules/@babel/types/lib/converters/toStatement.js +39 -0
  115. package/node_modules/@babel/types/lib/converters/toStatement.js.map +1 -0
  116. package/node_modules/@babel/types/lib/converters/valueToNode.js +89 -0
  117. package/node_modules/@babel/types/lib/converters/valueToNode.js.map +1 -0
  118. package/node_modules/@babel/types/lib/definitions/core.js +1725 -0
  119. package/node_modules/@babel/types/lib/definitions/core.js.map +1 -0
  120. package/node_modules/@babel/types/lib/definitions/deprecated-aliases.js +11 -0
  121. package/node_modules/@babel/types/lib/definitions/deprecated-aliases.js.map +1 -0
  122. package/node_modules/@babel/types/lib/definitions/experimental.js +124 -0
  123. package/node_modules/@babel/types/lib/definitions/experimental.js.map +1 -0
  124. package/node_modules/@babel/types/lib/definitions/flow.js +495 -0
  125. package/node_modules/@babel/types/lib/definitions/flow.js.map +1 -0
  126. package/node_modules/@babel/types/lib/definitions/index.js +106 -0
  127. package/node_modules/@babel/types/lib/definitions/index.js.map +1 -0
  128. package/node_modules/@babel/types/lib/definitions/jsx.js +157 -0
  129. package/node_modules/@babel/types/lib/definitions/jsx.js.map +1 -0
  130. package/node_modules/@babel/types/lib/definitions/misc.js +31 -0
  131. package/node_modules/@babel/types/lib/definitions/misc.js.map +1 -0
  132. package/node_modules/@babel/types/lib/definitions/placeholders.js +27 -0
  133. package/node_modules/@babel/types/lib/definitions/placeholders.js.map +1 -0
  134. package/node_modules/@babel/types/lib/definitions/typescript.js +528 -0
  135. package/node_modules/@babel/types/lib/definitions/typescript.js.map +1 -0
  136. package/node_modules/@babel/types/lib/definitions/utils.js +296 -0
  137. package/node_modules/@babel/types/lib/definitions/utils.js.map +1 -0
  138. package/node_modules/@babel/types/lib/index-legacy.d.ts +2797 -0
  139. package/node_modules/@babel/types/lib/index.d.ts +3617 -0
  140. package/node_modules/@babel/types/lib/index.js +582 -0
  141. package/node_modules/@babel/types/lib/index.js.flow +2650 -0
  142. package/node_modules/@babel/types/lib/index.js.map +1 -0
  143. package/node_modules/@babel/types/lib/modifications/appendToMemberExpression.js +15 -0
  144. package/node_modules/@babel/types/lib/modifications/appendToMemberExpression.js.map +1 -0
  145. package/node_modules/@babel/types/lib/modifications/flow/removeTypeDuplicates.js +65 -0
  146. package/node_modules/@babel/types/lib/modifications/flow/removeTypeDuplicates.js.map +1 -0
  147. package/node_modules/@babel/types/lib/modifications/inherits.js +28 -0
  148. package/node_modules/@babel/types/lib/modifications/inherits.js.map +1 -0
  149. package/node_modules/@babel/types/lib/modifications/prependToMemberExpression.js +17 -0
  150. package/node_modules/@babel/types/lib/modifications/prependToMemberExpression.js.map +1 -0
  151. package/node_modules/@babel/types/lib/modifications/removeProperties.js +24 -0
  152. package/node_modules/@babel/types/lib/modifications/removeProperties.js.map +1 -0
  153. package/node_modules/@babel/types/lib/modifications/removePropertiesDeep.js +14 -0
  154. package/node_modules/@babel/types/lib/modifications/removePropertiesDeep.js.map +1 -0
  155. package/node_modules/@babel/types/lib/modifications/typescript/removeTypeDuplicates.js +66 -0
  156. package/node_modules/@babel/types/lib/modifications/typescript/removeTypeDuplicates.js.map +1 -0
  157. package/node_modules/@babel/types/lib/retrievers/getAssignmentIdentifiers.js +48 -0
  158. package/node_modules/@babel/types/lib/retrievers/getAssignmentIdentifiers.js.map +1 -0
  159. package/node_modules/@babel/types/lib/retrievers/getBindingIdentifiers.js +102 -0
  160. package/node_modules/@babel/types/lib/retrievers/getBindingIdentifiers.js.map +1 -0
  161. package/node_modules/@babel/types/lib/retrievers/getFunctionName.js +63 -0
  162. package/node_modules/@babel/types/lib/retrievers/getFunctionName.js.map +1 -0
  163. package/node_modules/@babel/types/lib/retrievers/getOuterBindingIdentifiers.js +13 -0
  164. package/node_modules/@babel/types/lib/retrievers/getOuterBindingIdentifiers.js.map +1 -0
  165. package/node_modules/@babel/types/lib/traverse/traverse.js +50 -0
  166. package/node_modules/@babel/types/lib/traverse/traverse.js.map +1 -0
  167. package/node_modules/@babel/types/lib/traverse/traverseFast.js +40 -0
  168. package/node_modules/@babel/types/lib/traverse/traverseFast.js.map +1 -0
  169. package/node_modules/@babel/types/lib/utils/deprecationWarning.js +44 -0
  170. package/node_modules/@babel/types/lib/utils/deprecationWarning.js.map +1 -0
  171. package/node_modules/@babel/types/lib/utils/inherit.js +13 -0
  172. package/node_modules/@babel/types/lib/utils/inherit.js.map +1 -0
  173. package/node_modules/@babel/types/lib/utils/react/cleanJSXElementLiteralChild.js +40 -0
  174. package/node_modules/@babel/types/lib/utils/react/cleanJSXElementLiteralChild.js.map +1 -0
  175. package/node_modules/@babel/types/lib/utils/shallowEqual.js +17 -0
  176. package/node_modules/@babel/types/lib/utils/shallowEqual.js.map +1 -0
  177. package/node_modules/@babel/types/lib/validators/buildMatchMemberExpression.js +13 -0
  178. package/node_modules/@babel/types/lib/validators/buildMatchMemberExpression.js.map +1 -0
  179. package/node_modules/@babel/types/lib/validators/generated/index.js +2797 -0
  180. package/node_modules/@babel/types/lib/validators/generated/index.js.map +1 -0
  181. package/node_modules/@babel/types/lib/validators/is.js +27 -0
  182. package/node_modules/@babel/types/lib/validators/is.js.map +1 -0
  183. package/node_modules/@babel/types/lib/validators/isBinding.js +27 -0
  184. package/node_modules/@babel/types/lib/validators/isBinding.js.map +1 -0
  185. package/node_modules/@babel/types/lib/validators/isBlockScoped.js +13 -0
  186. package/node_modules/@babel/types/lib/validators/isBlockScoped.js.map +1 -0
  187. package/node_modules/@babel/types/lib/validators/isImmutable.js +21 -0
  188. package/node_modules/@babel/types/lib/validators/isImmutable.js.map +1 -0
  189. package/node_modules/@babel/types/lib/validators/isLet.js +13 -0
  190. package/node_modules/@babel/types/lib/validators/isLet.js.map +1 -0
  191. package/node_modules/@babel/types/lib/validators/isNode.js +12 -0
  192. package/node_modules/@babel/types/lib/validators/isNode.js.map +1 -0
  193. package/node_modules/@babel/types/lib/validators/isNodesEquivalent.js +57 -0
  194. package/node_modules/@babel/types/lib/validators/isNodesEquivalent.js.map +1 -0
  195. package/node_modules/@babel/types/lib/validators/isPlaceholderType.js +15 -0
  196. package/node_modules/@babel/types/lib/validators/isPlaceholderType.js.map +1 -0
  197. package/node_modules/@babel/types/lib/validators/isReferenced.js +96 -0
  198. package/node_modules/@babel/types/lib/validators/isReferenced.js.map +1 -0
  199. package/node_modules/@babel/types/lib/validators/isScope.js +18 -0
  200. package/node_modules/@babel/types/lib/validators/isScope.js.map +1 -0
  201. package/node_modules/@babel/types/lib/validators/isSpecifierDefault.js +14 -0
  202. package/node_modules/@babel/types/lib/validators/isSpecifierDefault.js.map +1 -0
  203. package/node_modules/@babel/types/lib/validators/isType.js +17 -0
  204. package/node_modules/@babel/types/lib/validators/isType.js.map +1 -0
  205. package/node_modules/@babel/types/lib/validators/isValidES3Identifier.js +13 -0
  206. package/node_modules/@babel/types/lib/validators/isValidES3Identifier.js.map +1 -0
  207. package/node_modules/@babel/types/lib/validators/isValidIdentifier.js +18 -0
  208. package/node_modules/@babel/types/lib/validators/isValidIdentifier.js.map +1 -0
  209. package/node_modules/@babel/types/lib/validators/isVar.js +15 -0
  210. package/node_modules/@babel/types/lib/validators/isVar.js.map +1 -0
  211. package/node_modules/@babel/types/lib/validators/matchesPattern.js +44 -0
  212. package/node_modules/@babel/types/lib/validators/matchesPattern.js.map +1 -0
  213. package/node_modules/@babel/types/lib/validators/react/isCompatTag.js +11 -0
  214. package/node_modules/@babel/types/lib/validators/react/isCompatTag.js.map +1 -0
  215. package/node_modules/@babel/types/lib/validators/react/isReactComponent.js +11 -0
  216. package/node_modules/@babel/types/lib/validators/react/isReactComponent.js.map +1 -0
  217. package/node_modules/@babel/types/lib/validators/validate.js +42 -0
  218. package/node_modules/@babel/types/lib/validators/validate.js.map +1 -0
  219. package/node_modules/@babel/types/package.json +39 -0
  220. package/node_modules/@code-yeongyu/senpi-codemode/CHANGELOG.md +10 -2
  221. package/node_modules/@code-yeongyu/senpi-codemode/README.md +128 -78
  222. package/node_modules/@code-yeongyu/senpi-codemode/package.json +4 -3
  223. package/node_modules/@code-yeongyu/senpi-codemode/src/bridge/protocol.ts +15 -2
  224. package/node_modules/@code-yeongyu/senpi-codemode/src/bridge/reserved.ts +9 -0
  225. package/node_modules/@code-yeongyu/senpi-codemode/src/bridges/agent-bridge.ts +197 -0
  226. package/node_modules/@code-yeongyu/senpi-codemode/src/bridges/output-bridge.ts +96 -0
  227. package/node_modules/@code-yeongyu/senpi-codemode/src/bridges/schema-injection.ts +3 -0
  228. package/node_modules/@code-yeongyu/senpi-codemode/src/completion/handler.ts +95 -26
  229. package/node_modules/@code-yeongyu/senpi-codemode/src/completion/tool-bridge.ts +11 -2
  230. package/node_modules/@code-yeongyu/senpi-codemode/src/config/settings.ts +96 -8
  231. package/node_modules/@code-yeongyu/senpi-codemode/src/extension/session-manager.ts +24 -3
  232. package/node_modules/@code-yeongyu/senpi-codemode/src/index.ts +155 -21
  233. package/node_modules/@code-yeongyu/senpi-codemode/src/interpreters/detect.ts +1 -1
  234. package/node_modules/@code-yeongyu/senpi-codemode/src/kernels/jl/prelude.jl +252 -48
  235. package/node_modules/@code-yeongyu/senpi-codemode/src/kernels/jl/runner.jl +263 -83
  236. package/node_modules/@code-yeongyu/senpi-codemode/src/kernels/js/context-manager.ts +11 -5
  237. package/node_modules/@code-yeongyu/senpi-codemode/src/kernels/js/local-module-loader.ts +108 -0
  238. package/node_modules/@code-yeongyu/senpi-codemode/src/kernels/js/prelude.ts +8 -6
  239. package/node_modules/@code-yeongyu/senpi-codemode/src/kernels/js/rewrite-imports.ts +164 -0
  240. package/node_modules/@code-yeongyu/senpi-codemode/src/kernels/js/worker-core.js +6 -1
  241. package/node_modules/@code-yeongyu/senpi-codemode/src/kernels/js/worker-runtime.js +307 -41
  242. package/node_modules/@code-yeongyu/senpi-codemode/src/kernels/py/kernel.ts +3 -2
  243. package/node_modules/@code-yeongyu/senpi-codemode/src/kernels/py/prelude.py +792 -79
  244. package/node_modules/@code-yeongyu/senpi-codemode/src/kernels/rb/prelude.rb +234 -21
  245. package/node_modules/@code-yeongyu/senpi-codemode/src/kernels/rb/runner.rb +154 -51
  246. package/node_modules/@code-yeongyu/senpi-codemode/src/kernels/shared/subprocess-queue.ts +1 -0
  247. package/node_modules/@code-yeongyu/senpi-codemode/src/output/output-meta.ts +89 -0
  248. package/node_modules/@code-yeongyu/senpi-codemode/src/output/streaming-output.ts +296 -0
  249. package/node_modules/@code-yeongyu/senpi-codemode/src/prompt/eval-prompt.ts +107 -30
  250. package/node_modules/@code-yeongyu/senpi-codemode/src/timeouts/bridge-timeout.ts +2 -0
  251. package/node_modules/@code-yeongyu/senpi-codemode/src/timeouts/idle-timeout.ts +8 -19
  252. package/node_modules/@code-yeongyu/senpi-codemode/src/tool/cell-handler.ts +175 -113
  253. package/node_modules/@code-yeongyu/senpi-codemode/src/tool/eval-tool.ts +130 -120
  254. package/node_modules/@code-yeongyu/senpi-codemode/src/tool/image.ts +274 -0
  255. package/node_modules/@code-yeongyu/senpi-codemode/src/tool/json-tree.ts +247 -0
  256. package/node_modules/@code-yeongyu/senpi-codemode/src/tool/render.ts +641 -38
  257. package/node_modules/@code-yeongyu/senpi-codemode/src/tool/status-events.ts +12 -0
  258. package/node_modules/@code-yeongyu/senpi-codemode/src/tool/types.ts +29 -1
  259. package/node_modules/@earendil-works/pi-agent-core/package.json +2 -2
  260. package/node_modules/@earendil-works/pi-ai/dist/providers/openrouter.models.js +16 -16
  261. package/node_modules/@earendil-works/pi-ai/dist/providers/openrouter.models.js.map +1 -1
  262. package/node_modules/@earendil-works/pi-ai/dist/providers/vercel-ai-gateway.models.js +6 -6
  263. package/node_modules/@earendil-works/pi-ai/dist/providers/vercel-ai-gateway.models.js.map +1 -1
  264. package/node_modules/@earendil-works/pi-ai/package.json +2 -2
  265. package/node_modules/@earendil-works/pi-pty/package.json +1 -1
  266. package/node_modules/@earendil-works/pi-tui/package.json +1 -1
  267. package/package.json +6 -6
@@ -0,0 +1,96 @@
1
+ import type { AgentToolResult } from "@code-yeongyu/senpi";
2
+ import { type Static, Type } from "typebox";
3
+ import { Check, Errors } from "typebox/value";
4
+ import type { ExecuteTool } from "../tool/types.ts";
5
+
6
+ const outputArgsSchema = Type.Object(
7
+ {
8
+ ids: Type.Array(Type.String({ minLength: 1 }), { minItems: 1 }),
9
+ format: Type.Optional(Type.Union([Type.Literal("raw"), Type.Literal("tail")])),
10
+ offset: Type.Optional(Type.Integer({ minimum: 1 })),
11
+ limit: Type.Optional(Type.Integer({ minimum: 1 })),
12
+ },
13
+ { additionalProperties: false },
14
+ );
15
+
16
+ type OutputArgs = Static<typeof outputArgsSchema>;
17
+
18
+ export type OutputExecuteTool = ExecuteTool & {
19
+ readonly isToolAvailable?: (name: string) => boolean;
20
+ };
21
+
22
+ export type MarshalledToolResult = {
23
+ readonly text: string;
24
+ };
25
+
26
+ export interface RunEvalOutputOptions {
27
+ readonly taskOutputToolName: string;
28
+ readonly executeTool: OutputExecuteTool;
29
+ readonly signal?: AbortSignal;
30
+ readonly marshalToolResult: (result: AgentToolResult<unknown>) => MarshalledToolResult;
31
+ }
32
+
33
+ class OutputArgumentsError extends Error {
34
+ readonly name = "OutputArgumentsError";
35
+
36
+ constructor(summary: string) {
37
+ super(`output() received invalid arguments: ${summary}`);
38
+ }
39
+ }
40
+
41
+ class OutputUnavailableError extends Error {
42
+ readonly name = "OutputUnavailableError";
43
+
44
+ constructor(toolName: string) {
45
+ super(`output() unavailable: no "${toolName}" tool is registered in this session`);
46
+ }
47
+ }
48
+
49
+ export async function runEvalOutput(args: unknown, options: RunEvalOutputOptions): Promise<string | readonly string[]> {
50
+ const parsed = parseOutputArgs(args);
51
+ if (options.executeTool.isToolAvailable?.(options.taskOutputToolName) === false) {
52
+ throw new OutputUnavailableError(options.taskOutputToolName);
53
+ }
54
+
55
+ const mode = parsed.format === "tail" ? "tail" : "full";
56
+ const transcripts = await Promise.all(
57
+ parsed.ids.map(async (id) => {
58
+ let result: AgentToolResult<unknown>;
59
+ try {
60
+ result = await options.executeTool(
61
+ options.taskOutputToolName,
62
+ {
63
+ ...(id.startsWith("st_") ? { task_id: id } : { name: id }),
64
+ mode,
65
+ block: true,
66
+ },
67
+ options.signal === undefined ? undefined : { signal: options.signal },
68
+ );
69
+ } catch (error) {
70
+ if (isUnavailableToolError(error)) throw new OutputUnavailableError(options.taskOutputToolName);
71
+ throw error;
72
+ }
73
+
74
+ // ADAPTATION: task_output owns transcripts, so no AgentOutputManager cache or
75
+ // oh-my-pi query/json/stripped formats exist on this bridge.
76
+ const transcript = options.marshalToolResult(result).text;
77
+ const lines = transcript.split(/\r?\n/u);
78
+ const start = (parsed.offset ?? 1) - 1;
79
+ return lines.slice(start, parsed.limit === undefined ? undefined : start + parsed.limit).join("\n");
80
+ }),
81
+ );
82
+ return transcripts.length === 1 ? transcripts[0] : transcripts;
83
+ }
84
+
85
+ function parseOutputArgs(value: unknown): OutputArgs {
86
+ if (Check(outputArgsSchema, value)) return value;
87
+ const summary = Errors(outputArgsSchema, value)
88
+ .map((error) => `${error.instancePath || "/"} ${error.message}`)
89
+ .join("; ");
90
+ throw new OutputArgumentsError(summary || "invalid value");
91
+ }
92
+
93
+ function isUnavailableToolError(error: unknown): boolean {
94
+ if (typeof error !== "object" || error === null || Array.isArray(error)) return false;
95
+ return "code" in error && (error.code === "unknown_tool" || error.code === "inactive_tool");
96
+ }
@@ -0,0 +1,3 @@
1
+ export function injectSchemaInstruction(prompt: string, schema: unknown): string {
2
+ return `${prompt}\n\nRespond ONLY with JSON matching this JSON-Schema:\n${JSON.stringify(schema)}`;
3
+ }
@@ -1,6 +1,7 @@
1
1
  import type { ExtensionContext } from "@code-yeongyu/senpi";
2
2
  import type { Api, AssistantMessage, Context, Model, SimpleStreamOptions } from "@earendil-works/pi-ai/compat";
3
3
  import { completeSimple } from "@earendil-works/pi-ai/compat";
4
+ import { injectSchemaInstruction } from "../bridges/schema-injection.ts";
4
5
 
5
6
  export interface CompletionRequest {
6
7
  readonly prompt: string;
@@ -20,19 +21,27 @@ export type CompleteSimple = (
20
21
  options?: SimpleStreamOptions,
21
22
  ) => Promise<AssistantMessage>;
22
23
 
23
- interface CompletionDetails {
24
+ type CompletionDetails = {
24
25
  readonly model: string;
25
26
  readonly structured: boolean;
27
+ };
28
+
29
+ type CompletionTier = "smol" | "default" | "slow";
30
+
31
+ class CompletionUnknownTierError extends Error {
32
+ readonly name = "CompletionUnknownTierError";
33
+
34
+ constructor(tier: string) {
35
+ super(`completion() could not resolve the "${tier}" model tier; expected "smol", "default", or "slow".`);
36
+ }
26
37
  }
27
38
 
28
- interface ResolvedAuth {
29
- readonly ok: boolean;
30
- readonly apiKey?: string;
31
- readonly headers?: Record<string, string>;
32
- readonly env?: Record<string, string>;
33
- readonly extraBody?: Record<string, unknown>;
34
- readonly upstreamModelId?: string;
35
- readonly error?: string;
39
+ class CompletionTierUnavailableError extends Error {
40
+ readonly name = "CompletionTierUnavailableError";
41
+
42
+ constructor(tier: Exclude<CompletionTier, "default">) {
43
+ super(`completion() could not resolve the "${tier}" model tier: no configured models are available.`);
44
+ }
36
45
  }
37
46
 
38
47
  export function createCompletionHandler(
@@ -46,16 +55,20 @@ async function runCompletion(
46
55
  request: CompletionRequest,
47
56
  complete: CompleteSimple,
48
57
  ): Promise<CompletionResult> {
49
- const model = resolveRequestedModel(ctx.model, request.model);
50
- if (!model) throw noModelCredentialsError();
51
- const auth = (await ctx.modelRegistry.getApiKeyAndHeaders(model)) as ResolvedAuth;
52
- if (!auth.ok || !auth.apiKey) throw noModelCredentialsError(auth.error);
58
+ const tier = resolveCompletionTier(request.model);
59
+ const model = resolveRequestedModel(ctx, tier);
60
+ if (!model) throw unavailableModelError(tier);
61
+ const auth = await ctx.modelRegistry.getApiKeyAndHeaders(model);
62
+ if (!auth.ok) throw noModelCredentialsError(auth.error);
63
+ if (!auth.apiKey) throw noModelCredentialsError();
53
64
  const requestModel = auth.upstreamModelId ? { ...model, id: auth.upstreamModelId } : model;
65
+ const structured = request.schema !== undefined;
66
+ const prompt = structured ? injectSchemaInstruction(request.prompt, request.schema) : request.prompt;
54
67
  const message = await complete(
55
68
  requestModel,
56
69
  {
57
70
  systemPrompt: request.system ?? "You are a helpful assistant.",
58
- messages: [{ role: "user", content: [{ type: "text", text: request.prompt }], timestamp: Date.now() }],
71
+ messages: [{ role: "user", content: [{ type: "text", text: prompt }], timestamp: Date.now() }],
59
72
  },
60
73
  {
61
74
  apiKey: auth.apiKey,
@@ -65,7 +78,7 @@ async function runCompletion(
65
78
  signal: ctx.signal,
66
79
  },
67
80
  );
68
- return formatCompletion(message, model, request.schema !== undefined);
81
+ return formatCompletion(message, model, structured);
69
82
  }
70
83
 
71
84
  function normalizeRequest(request: CompletionRequest): CompletionRequest {
@@ -78,25 +91,77 @@ function normalizeRequest(request: CompletionRequest): CompletionRequest {
78
91
  };
79
92
  }
80
93
 
81
- function resolveRequestedModel(current: Model<Api> | undefined, requested: string | undefined): Model<Api> | undefined {
82
- if (requested === undefined || requested === "default") return current;
83
- if (requested === "smol" || requested === "slow") {
84
- throw new Error('completion() model roles are not supported; use model: "default" or omit model.');
94
+ function resolveCompletionTier(requested: string | undefined): CompletionTier {
95
+ switch (requested) {
96
+ case undefined:
97
+ case "default":
98
+ return "default";
99
+ case "smol":
100
+ return "smol";
101
+ case "slow":
102
+ return "slow";
103
+ default:
104
+ throw new CompletionUnknownTierError(requested);
105
+ }
106
+ }
107
+
108
+ function resolveRequestedModel(ctx: ExtensionContext, tier: CompletionTier): Model<Api> | undefined {
109
+ switch (tier) {
110
+ case "default":
111
+ return ctx.model;
112
+ case "smol":
113
+ return lowestCostModel(ctx.modelRegistry.getAvailable());
114
+ case "slow":
115
+ return highestCostModel(ctx.modelRegistry.getAvailable());
116
+ default:
117
+ return assertNever(tier);
118
+ }
119
+ }
120
+
121
+ function unavailableModelError(tier: CompletionTier): Error {
122
+ switch (tier) {
123
+ case "default":
124
+ return noModelCredentialsError();
125
+ case "smol":
126
+ case "slow":
127
+ return new CompletionTierUnavailableError(tier);
128
+ default:
129
+ return assertNever(tier);
130
+ }
131
+ }
132
+
133
+ function lowestCostModel(models: readonly Model<Api>[]): Model<Api> | undefined {
134
+ let selected: Model<Api> | undefined;
135
+ for (const model of models) {
136
+ if (selected === undefined || promptAndResponseCost(model) < promptAndResponseCost(selected)) selected = model;
85
137
  }
86
- if (!current) return undefined;
87
- if (requested === current.id || requested === `${current.provider}/${current.id}`) return current;
88
- throw new Error(`completion() could not resolve requested model "${requested}" from the current session model.`);
138
+ return selected;
139
+ }
140
+
141
+ function highestCostModel(models: readonly Model<Api>[]): Model<Api> | undefined {
142
+ let selected: Model<Api> | undefined;
143
+ for (const model of models) {
144
+ if (selected === undefined || promptAndResponseCost(model) > promptAndResponseCost(selected)) selected = model;
145
+ }
146
+ return selected;
147
+ }
148
+
149
+ function promptAndResponseCost(model: Model<Api>): number {
150
+ return model.cost.input + model.cost.output;
89
151
  }
90
152
 
91
153
  function formatCompletion(message: AssistantMessage, model: Model<Api>, structured: boolean): CompletionResult {
92
154
  if (message.stopReason === "error") throw new Error(message.errorMessage ?? "completion() request failed.");
93
155
  if (message.stopReason === "aborted") throw new Error("completion() request aborted.");
94
156
  const text = extractText(message);
95
- if (!structured) return { text, details: { model: formatModel(model), structured: false } };
157
+ const details = { model: formatModel(model), structured };
158
+ if (!structured) return { text, details };
96
159
  try {
97
- return { value: JSON.parse(text) as unknown, details: { model: formatModel(model), structured: true } };
98
- } catch {
99
- throw new Error("completion() did not return a structured JSON response.");
160
+ const value: unknown = JSON.parse(text);
161
+ return { value, details };
162
+ } catch (error) {
163
+ if (error instanceof SyntaxError) return { value: { parseError: error.message }, details };
164
+ throw error;
100
165
  }
101
166
  }
102
167
 
@@ -121,3 +186,7 @@ function formatModel(model: Model<Api>): string {
121
186
  function isRecord(value: unknown): value is Record<string, unknown> {
122
187
  return typeof value === "object" && value !== null;
123
188
  }
189
+
190
+ function assertNever(value: never): never {
191
+ throw new CompletionUnknownTierError(String(value));
192
+ }
@@ -15,9 +15,14 @@ export type CompletionToolCallSummary = { readonly ok: true } | { readonly ok: f
15
15
 
16
16
  export async function handleCompletionToolCall(options: CompletionToolCallOptions): Promise<CompletionToolCallSummary> {
17
17
  try {
18
- const value = await options.complete(toCompletionRequest(options.message.args), options.ctx);
18
+ const result = await options.complete(toCompletionRequest(options.message.args), options.ctx);
19
19
  if (!options.isActive()) return { ok: false, error: "completion() result ignored after eval finalization" };
20
- options.kernel.deliverToolReply({ type: "tool-reply", callId: options.message.callId, ok: true, value });
20
+ options.kernel.deliverToolReply({
21
+ type: "tool-reply",
22
+ callId: options.message.callId,
23
+ ok: true,
24
+ value: completionReplyValue(result),
25
+ });
21
26
  return { ok: true };
22
27
  } catch (error) {
23
28
  const message = error instanceof Error ? error.message : String(error);
@@ -44,3 +49,7 @@ function toCompletionRequest(value: unknown): CompletionRequest {
44
49
  }
45
50
  throw new Error("completion() received invalid arguments");
46
51
  }
52
+
53
+ function completionReplyValue(result: CompletionResult): unknown {
54
+ return "value" in result ? result.value : result.text;
55
+ }
@@ -20,12 +20,41 @@ export const codemodeSettingsSchema = Type.Object(
20
20
  ),
21
21
  cellTimeoutSeconds: Type.Optional(Type.Number({ minimum: 1 })),
22
22
  parallelPoolWidth: Type.Optional(Type.Number({ minimum: 1 })),
23
+ taskTools: Type.Optional(
24
+ Type.Object(
25
+ {
26
+ task: Type.Optional(Type.String()),
27
+ output: Type.Optional(Type.String()),
28
+ },
29
+ { additionalProperties: false },
30
+ ),
31
+ ),
32
+ outputSink: Type.Optional(
33
+ Type.Object(
34
+ {
35
+ headBytes: Type.Optional(Type.Number({ minimum: 0 })),
36
+ maxColumns: Type.Optional(Type.Number({ minimum: 0 })),
37
+ },
38
+ { additionalProperties: false },
39
+ ),
40
+ ),
41
+ statusEvents: Type.Optional(Type.Boolean()),
23
42
  },
24
43
  { additionalProperties: false },
25
44
  );
26
45
 
27
46
  export type CodemodeSettingsInput = Static<typeof codemodeSettingsSchema>;
28
47
 
48
+ export interface CodemodeTaskTools {
49
+ readonly task: string;
50
+ readonly output: string;
51
+ }
52
+
53
+ export interface CodemodeOutputSink {
54
+ readonly headBytes: number;
55
+ readonly maxColumns: number;
56
+ }
57
+
29
58
  export interface CodemodeSettings {
30
59
  readonly languages: {
31
60
  readonly py: boolean;
@@ -35,22 +64,31 @@ export interface CodemodeSettings {
35
64
  };
36
65
  readonly cellTimeoutSeconds: number;
37
66
  readonly parallelPoolWidth: number;
67
+ readonly taskTools?: CodemodeTaskTools;
68
+ readonly outputSink?: CodemodeOutputSink;
69
+ readonly statusEvents?: boolean;
38
70
  }
39
71
 
72
+ export type ResolvedCodemodeSettings = CodemodeSettings & {
73
+ readonly taskTools: CodemodeTaskTools;
74
+ readonly outputSink: CodemodeOutputSink;
75
+ readonly statusEvents: boolean;
76
+ };
77
+
40
78
  export interface LoadCodemodeSettingsOptions {
41
79
  readonly cwd?: string;
42
80
  readonly homeDir?: string;
43
81
  }
44
82
 
45
83
  export interface LoadedCodemodeSettings {
46
- readonly settings: CodemodeSettings;
84
+ readonly settings: ResolvedCodemodeSettings;
47
85
  readonly source: string | null;
48
86
  readonly warnings: readonly string[];
49
87
  }
50
88
 
51
89
  // OMP settings-schema.ts:3211-3299 has language/path settings only; eval.ts:427
52
90
  // defaults timeout to 30s, and codemode pins concurrency-bridge.ts:30 width to 4.
53
- export const defaultCodemodeSettings: CodemodeSettings = {
91
+ export const defaultCodemodeSettings: ResolvedCodemodeSettings = {
54
92
  languages: {
55
93
  py: true,
56
94
  js: true,
@@ -59,8 +97,26 @@ export const defaultCodemodeSettings: CodemodeSettings = {
59
97
  },
60
98
  cellTimeoutSeconds: 30,
61
99
  parallelPoolWidth: 4,
100
+ taskTools: {
101
+ task: "task",
102
+ output: "task_output",
103
+ },
104
+ outputSink: {
105
+ headBytes: 20_480,
106
+ maxColumns: 768,
107
+ },
108
+ statusEvents: true,
62
109
  };
63
110
 
111
+ const languageEnvironmentFlags = {
112
+ py: "SENPI_CODEMODE_PY",
113
+ js: "SENPI_CODEMODE_JS",
114
+ rb: "SENPI_CODEMODE_RB",
115
+ jl: "SENPI_CODEMODE_JL",
116
+ } as const;
117
+
118
+ type Environment = Readonly<Record<string, string | undefined>>;
119
+
64
120
  export async function loadCodemodeSettings(options: LoadCodemodeSettingsOptions = {}): Promise<LoadedCodemodeSettings> {
65
121
  const cwd = options.cwd ?? process.cwd();
66
122
  const homeDir = options.homeDir ?? homedir();
@@ -76,16 +132,29 @@ export async function loadCodemodeSettings(options: LoadCodemodeSettingsOptions
76
132
  return { settings: defaultCodemodeSettings, source: null, warnings: [] };
77
133
  }
78
134
 
135
+ export function resolveEnabledLanguages(
136
+ settings: CodemodeSettings,
137
+ env: Environment = process.env,
138
+ ): CodemodeSettings["languages"] {
139
+ return {
140
+ py: resolveLanguage(settings.languages.py, env[languageEnvironmentFlags.py]),
141
+ js: resolveLanguage(settings.languages.js, env[languageEnvironmentFlags.js]),
142
+ rb: resolveLanguage(settings.languages.rb, env[languageEnvironmentFlags.rb]),
143
+ jl: resolveLanguage(settings.languages.jl, env[languageEnvironmentFlags.jl]),
144
+ };
145
+ }
146
+
79
147
  async function loadSettingsFile(path: string): Promise<LoadedCodemodeSettings> {
80
148
  const raw = await readFile(path, "utf8");
81
149
  let parsed: unknown;
82
150
  try {
83
151
  parsed = JSON.parse(raw);
84
152
  } catch (error) {
153
+ const message = error instanceof Error ? error.message : String(error);
85
154
  return {
86
155
  settings: defaultCodemodeSettings,
87
156
  source: path,
88
- warnings: [`Invalid JSON in ${path}: ${errorMessage(error)}. Falling back to codemode defaults.`],
157
+ warnings: [`Invalid JSON in ${path}: ${message}. Falling back to codemode defaults.`],
89
158
  };
90
159
  }
91
160
 
@@ -100,7 +169,7 @@ async function loadSettingsFile(path: string): Promise<LoadedCodemodeSettings> {
100
169
  return { settings: mergeSettings(parsed), source: path, warnings: [] };
101
170
  }
102
171
 
103
- function mergeSettings(input: CodemodeSettingsInput): CodemodeSettings {
172
+ function mergeSettings(input: CodemodeSettingsInput): ResolvedCodemodeSettings {
104
173
  return {
105
174
  languages: {
106
175
  py: input.languages?.py ?? defaultCodemodeSettings.languages.py,
@@ -110,9 +179,32 @@ function mergeSettings(input: CodemodeSettingsInput): CodemodeSettings {
110
179
  },
111
180
  cellTimeoutSeconds: input.cellTimeoutSeconds ?? defaultCodemodeSettings.cellTimeoutSeconds,
112
181
  parallelPoolWidth: input.parallelPoolWidth ?? defaultCodemodeSettings.parallelPoolWidth,
182
+ taskTools: {
183
+ task: input.taskTools?.task ?? defaultCodemodeSettings.taskTools.task,
184
+ output: input.taskTools?.output ?? defaultCodemodeSettings.taskTools.output,
185
+ },
186
+ outputSink: {
187
+ headBytes: input.outputSink?.headBytes ?? defaultCodemodeSettings.outputSink.headBytes,
188
+ maxColumns: input.outputSink?.maxColumns ?? defaultCodemodeSettings.outputSink.maxColumns,
189
+ },
190
+ statusEvents: input.statusEvents ?? defaultCodemodeSettings.statusEvents,
113
191
  };
114
192
  }
115
193
 
194
+ function resolveLanguage(fileSetting: boolean, environmentValue: string | undefined): boolean {
195
+ if (environmentValue === undefined) return fileSetting;
196
+ switch (environmentValue.trim().toLowerCase()) {
197
+ case "0":
198
+ case "false":
199
+ return false;
200
+ case "1":
201
+ case "true":
202
+ return true;
203
+ default:
204
+ return fileSetting;
205
+ }
206
+ }
207
+
116
208
  async function fileExists(path: string): Promise<boolean> {
117
209
  try {
118
210
  await access(path);
@@ -121,7 +213,3 @@ async function fileExists(path: string): Promise<boolean> {
121
213
  return false;
122
214
  }
123
215
  }
124
-
125
- function errorMessage(error: unknown): string {
126
- return error instanceof Error ? error.message : String(error);
127
- }
@@ -1,3 +1,4 @@
1
+ import { join } from "node:path";
1
2
  import type { ExtensionContext } from "@code-yeongyu/senpi";
2
3
  import { type BridgeServerHandle, startBridgeServer } from "../bridge/http-server.ts";
3
4
  import type { KernelToHostMessage } from "../bridge/protocol.ts";
@@ -16,11 +17,20 @@ export interface CodemodeSessionManager extends EvalKernelManager {
16
17
  setContext?(ctx: ExtensionContext): void;
17
18
  }
18
19
 
20
+ export interface EvalExecutionTracker {
21
+ assertEvalExecutionAllowed(): void;
22
+ trackEvalExecution<Result>(execution: Promise<Result>, controller: AbortController): Promise<Result>;
23
+ }
24
+
19
25
  export interface CreateCodemodeSessionManagerOptions {
20
26
  readonly sessionId: string;
21
27
  readonly cwd: string;
22
28
  readonly settings: CodemodeSettings;
23
29
  readonly availability: InterpreterAvailability;
30
+ /** Session-scoped roots exposed to kernel helpers such as local://. */
31
+ readonly localRoots?: Readonly<Record<string, string>>;
32
+ /** Session-adjacent directory used for persisted eval artifacts. */
33
+ readonly artifactsDir?: string;
24
34
  readonly executeTool: ExecuteTool;
25
35
  readonly complete: (request: CompletionRequest, ctx: ExtensionContext) => Promise<CompletionResult>;
26
36
  }
@@ -33,7 +43,7 @@ export async function createCodemodeSessionManager(
33
43
  return manager;
34
44
  }
35
45
 
36
- class CodemodeSessionDisposedError extends Error {
46
+ export class CodemodeSessionDisposedError extends Error {
37
47
  readonly name = "CodemodeSessionDisposedError";
38
48
 
39
49
  constructor() {
@@ -148,17 +158,28 @@ class DefaultCodemodeSessionManager implements CodemodeSessionManager {
148
158
  async #createKernel(language: EvalLanguage, onMessage: (message: KernelToHostMessage) => void): Promise<EvalKernel> {
149
159
  const bridge = this.#bridge;
150
160
  if (!bridge) throw new Error("codemode bridge server is not running");
161
+ const configuredPoolWidth = this.#options.settings.parallelPoolWidth;
162
+ const parallelPoolWidth = Number.isFinite(configuredPoolWidth) ? Math.max(1, Math.trunc(configuredPoolWidth)) : 1;
151
163
  if (language === "js") {
152
164
  return new JavaScriptKernel({
153
165
  sessionId: this.#options.sessionId,
154
166
  cwd: this.#options.cwd,
155
- parallelPoolWidth: this.#options.settings.parallelPoolWidth,
167
+ parallelPoolWidth,
156
168
  onMessage,
157
169
  });
158
170
  }
159
171
  const detected = this.#options.availability[language].detected;
160
172
  if (!detected.ok) throw new Error(`No ${language} interpreter is available`);
161
- const connection = { port: bridge.port, token: bridge.token };
173
+ const localRoots =
174
+ this.#options.localRoots ??
175
+ (this.#options.artifactsDir ? { local: join(this.#options.artifactsDir, "local") } : undefined);
176
+ const connection = {
177
+ port: bridge.port,
178
+ token: bridge.token,
179
+ parallelPoolWidth,
180
+ ...(localRoots ? { localRoots: { ...localRoots } } : {}),
181
+ ...(this.#options.artifactsDir ? { artifactsDir: this.#options.artifactsDir } : {}),
182
+ };
162
183
  if (language === "py") {
163
184
  return await PythonKernel.start({
164
185
  interpreterPath: detected.path,