toolcraft 0.0.27 → 0.0.34

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 (243) hide show
  1. package/README.md +2 -2
  2. package/dist/cli.compile-check.js +7 -1
  3. package/dist/cli.d.ts +9 -1
  4. package/dist/cli.js +134 -62
  5. package/dist/design.d.ts +1 -0
  6. package/dist/design.js +1 -0
  7. package/dist/error-codes.d.ts +1 -0
  8. package/dist/error-codes.js +6 -0
  9. package/dist/human-in-loop/approvals-commands.js +2 -1
  10. package/dist/human-in-loop/runner.js +2 -2
  11. package/dist/index.d.ts +6 -2
  12. package/dist/json-schema-converter.js +12 -1
  13. package/dist/mcp-proxy.js +26 -9
  14. package/dist/mcp.js +55 -4
  15. package/dist/renderer.js +1 -1
  16. package/dist/schema-scope.js +22 -1
  17. package/dist/sdk.js +51 -3
  18. package/dist/source-snippet.js +1 -1
  19. package/node_modules/@poe-code/agent-defs/dist/agents/claude-code.js +5 -0
  20. package/node_modules/@poe-code/agent-defs/dist/agents/codex.js +10 -0
  21. package/node_modules/@poe-code/agent-defs/dist/agents/cursor.d.ts +2 -0
  22. package/node_modules/@poe-code/agent-defs/dist/agents/cursor.js +15 -0
  23. package/node_modules/@poe-code/agent-defs/dist/agents/goose.js +1 -0
  24. package/node_modules/@poe-code/agent-defs/dist/agents/index.d.ts +1 -0
  25. package/node_modules/@poe-code/agent-defs/dist/agents/index.js +1 -0
  26. package/node_modules/@poe-code/agent-defs/dist/agents/opencode.js +5 -0
  27. package/node_modules/@poe-code/agent-defs/dist/index.d.ts +2 -2
  28. package/node_modules/@poe-code/agent-defs/dist/index.js +1 -1
  29. package/node_modules/@poe-code/agent-defs/dist/registry.js +8 -1
  30. package/node_modules/@poe-code/agent-defs/dist/specifier.js +7 -3
  31. package/node_modules/@poe-code/agent-defs/dist/types.d.ts +5 -0
  32. package/node_modules/@poe-code/agent-human-in-loop/dist/providers/osascript.js +7 -1
  33. package/node_modules/@poe-code/agent-mcp-config/dist/configs.js +6 -0
  34. package/node_modules/@poe-code/config-mutations/dist/error-codes.d.ts +1 -0
  35. package/node_modules/@poe-code/config-mutations/dist/error-codes.js +6 -0
  36. package/node_modules/@poe-code/config-mutations/dist/execution/apply-mutation.js +25 -15
  37. package/node_modules/@poe-code/config-mutations/dist/formats/json.js +1 -1
  38. package/node_modules/@poe-code/config-mutations/dist/formats/toml.js +1 -1
  39. package/node_modules/@poe-code/config-mutations/dist/formats/yaml.js +1 -1
  40. package/node_modules/@poe-code/config-mutations/dist/fs-utils.js +2 -4
  41. package/node_modules/@poe-code/config-mutations/dist/template/render.js +1 -1
  42. package/node_modules/@poe-code/config-mutations/package.json +1 -1
  43. package/node_modules/@poe-code/process-runner/dist/host/host-execution-env.js +18 -5
  44. package/node_modules/@poe-code/process-runner/dist/host/host-runner.js +38 -4
  45. package/node_modules/@poe-code/process-runner/dist/workspace-transfer.js +8 -2
  46. package/node_modules/@poe-code/task-list/dist/backends/gh-issues-sync.js +10 -7
  47. package/node_modules/@poe-code/task-list/dist/backends/markdown-dir.js +13 -6
  48. package/node_modules/@poe-code/task-list/dist/backends/utils.js +15 -10
  49. package/node_modules/@poe-code/task-list/dist/backends/yaml-file.js +39 -22
  50. package/node_modules/@poe-code/task-list/dist/move.js +4 -1
  51. package/node_modules/@poe-code/task-list/dist/open.js +42 -20
  52. package/node_modules/@poe-code/task-list/dist/state-machine.js +8 -5
  53. package/node_modules/auth-store/dist/create-secret-store.js +6 -1
  54. package/node_modules/auth-store/dist/encrypted-file-store.d.ts +1 -1
  55. package/node_modules/auth-store/dist/encrypted-file-store.js +32 -28
  56. package/node_modules/auth-store/dist/error-codes.d.ts +1 -0
  57. package/node_modules/auth-store/dist/error-codes.js +5 -0
  58. package/node_modules/auth-store/dist/keychain-store.js +23 -8
  59. package/node_modules/mcp-oauth/dist/client/auth-store-session-store.js +17 -5
  60. package/node_modules/mcp-oauth/dist/client/authorization-state.js +21 -8
  61. package/node_modules/mcp-oauth/dist/client/default-oauth-client-provider.js +128 -55
  62. package/node_modules/mcp-oauth/dist/client/token-endpoint.js +27 -17
  63. package/node_modules/mcp-oauth/dist/server/jwks-token-verifier.js +43 -22
  64. package/node_modules/toolcraft-design/README.md +148 -0
  65. package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/acp/components.d.ts +1 -0
  66. package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/acp/components.js +12 -0
  67. package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/acp/index.d.ts +1 -1
  68. package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/acp/index.js +1 -1
  69. package/node_modules/toolcraft-design/dist/components/catalog.d.ts +26 -0
  70. package/node_modules/toolcraft-design/dist/components/catalog.js +94 -0
  71. package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/components/index.d.ts +2 -0
  72. package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/components/index.js +1 -0
  73. package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/dashboard/components/footer.js +1 -2
  74. package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/dashboard/components/output-pane.js +16 -19
  75. package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/dashboard/components/stats-pane.js +1 -15
  76. package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/explorer/demo.js +2 -2
  77. package/node_modules/toolcraft-design/dist/explorer/theme.js +29 -0
  78. package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/index.d.ts +7 -1
  79. package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/index.js +4 -0
  80. package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/internal/theme-detect.d.ts +1 -0
  81. package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/internal/theme-detect.js +28 -6
  82. package/node_modules/toolcraft-design/dist/internal/theme-state.d.ts +12 -0
  83. package/node_modules/toolcraft-design/dist/internal/theme-state.js +35 -0
  84. package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/prompts/theme.d.ts +1 -1
  85. package/node_modules/toolcraft-design/dist/prompts/theme.js +15 -0
  86. package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/terminal-markdown/parser/frontmatter.js +50 -0
  87. package/node_modules/toolcraft-design/dist/tokens/brand.d.ts +5 -0
  88. package/node_modules/toolcraft-design/dist/tokens/brand.js +5 -0
  89. package/node_modules/toolcraft-design/dist/tokens/colors.d.ts +37 -0
  90. package/node_modules/toolcraft-design/dist/tokens/colors.js +85 -0
  91. package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/tokens/index.d.ts +2 -0
  92. package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/tokens/index.js +1 -0
  93. package/node_modules/toolcraft-design/package.json +42 -0
  94. package/package.json +10 -6
  95. package/node_modules/@poe-code/design-system/dist/explorer/theme.js +0 -97
  96. package/node_modules/@poe-code/design-system/dist/prompts/theme.js +0 -12
  97. package/node_modules/@poe-code/design-system/dist/tokens/colors.d.ts +0 -35
  98. package/node_modules/@poe-code/design-system/dist/tokens/colors.js +0 -34
  99. package/node_modules/@poe-code/design-system/package.json +0 -29
  100. /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/acp/writer.d.ts +0 -0
  101. /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/acp/writer.js +0 -0
  102. /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/components/browser.d.ts +0 -0
  103. /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/components/browser.js +0 -0
  104. /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/components/color.d.ts +0 -0
  105. /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/components/color.js +0 -0
  106. /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/components/command-errors.d.ts +0 -0
  107. /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/components/command-errors.js +0 -0
  108. /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/components/detail-card.d.ts +0 -0
  109. /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/components/detail-card.js +0 -0
  110. /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/components/help-formatter-plain.d.ts +0 -0
  111. /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/components/help-formatter-plain.js +0 -0
  112. /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/components/help-formatter.d.ts +0 -0
  113. /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/components/help-formatter.js +0 -0
  114. /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/components/logger.d.ts +0 -0
  115. /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/components/logger.js +0 -0
  116. /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/components/symbols.d.ts +0 -0
  117. /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/components/symbols.js +0 -0
  118. /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/components/table.d.ts +0 -0
  119. /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/components/table.js +0 -0
  120. /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/components/template.d.ts +0 -0
  121. /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/components/template.js +0 -0
  122. /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/components/text.d.ts +0 -0
  123. /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/components/text.js +0 -0
  124. /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/dashboard/ansi.d.ts +0 -0
  125. /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/dashboard/ansi.js +0 -0
  126. /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/dashboard/buffer.d.ts +0 -0
  127. /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/dashboard/buffer.js +0 -0
  128. /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/dashboard/components/border.d.ts +0 -0
  129. /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/dashboard/components/border.js +0 -0
  130. /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/dashboard/components/footer.d.ts +0 -0
  131. /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/dashboard/components/output-pane.d.ts +0 -0
  132. /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/dashboard/components/stats-pane.d.ts +0 -0
  133. /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/dashboard/dashboard.d.ts +0 -0
  134. /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/dashboard/dashboard.js +0 -0
  135. /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/dashboard/demo.d.ts +0 -0
  136. /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/dashboard/demo.js +0 -0
  137. /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/dashboard/index.d.ts +0 -0
  138. /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/dashboard/index.js +0 -0
  139. /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/dashboard/keymap.d.ts +0 -0
  140. /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/dashboard/keymap.js +0 -0
  141. /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/dashboard/layout.d.ts +0 -0
  142. /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/dashboard/layout.js +0 -0
  143. /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/dashboard/should-use-dashboard.d.ts +0 -0
  144. /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/dashboard/should-use-dashboard.js +0 -0
  145. /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/dashboard/snapshot.d.ts +0 -0
  146. /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/dashboard/snapshot.js +0 -0
  147. /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/dashboard/store.d.ts +0 -0
  148. /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/dashboard/store.js +0 -0
  149. /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/dashboard/terminal-width.d.ts +0 -0
  150. /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/dashboard/terminal-width.js +0 -0
  151. /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/dashboard/terminal.d.ts +0 -0
  152. /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/dashboard/terminal.js +0 -0
  153. /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/dashboard/types.d.ts +0 -0
  154. /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/dashboard/types.js +0 -0
  155. /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/explorer/actions.d.ts +0 -0
  156. /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/explorer/actions.js +0 -0
  157. /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/explorer/demo.d.ts +0 -0
  158. /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/explorer/events.d.ts +0 -0
  159. /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/explorer/events.js +0 -0
  160. /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/explorer/filter.d.ts +0 -0
  161. /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/explorer/filter.js +0 -0
  162. /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/explorer/index.d.ts +0 -0
  163. /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/explorer/index.js +0 -0
  164. /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/explorer/jobs.d.ts +0 -0
  165. /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/explorer/jobs.js +0 -0
  166. /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/explorer/keymap.d.ts +0 -0
  167. /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/explorer/keymap.js +0 -0
  168. /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/explorer/layout.d.ts +0 -0
  169. /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/explorer/layout.js +0 -0
  170. /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/explorer/reducer.d.ts +0 -0
  171. /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/explorer/reducer.js +0 -0
  172. /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/explorer/render/detail.d.ts +0 -0
  173. /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/explorer/render/detail.js +0 -0
  174. /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/explorer/render/footer.d.ts +0 -0
  175. /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/explorer/render/footer.js +0 -0
  176. /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/explorer/render/header.d.ts +0 -0
  177. /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/explorer/render/header.js +0 -0
  178. /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/explorer/render/index.d.ts +0 -0
  179. /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/explorer/render/index.js +0 -0
  180. /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/explorer/render/list.d.ts +0 -0
  181. /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/explorer/render/list.js +0 -0
  182. /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/explorer/render/modal.d.ts +0 -0
  183. /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/explorer/render/modal.js +0 -0
  184. /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/explorer/render/test-fixtures.d.ts +0 -0
  185. /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/explorer/render/test-fixtures.js +0 -0
  186. /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/explorer/render/text.d.ts +0 -0
  187. /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/explorer/render/text.js +0 -0
  188. /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/explorer/runtime.d.ts +0 -0
  189. /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/explorer/runtime.js +0 -0
  190. /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/explorer/runtime.test-helpers.d.ts +0 -0
  191. /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/explorer/runtime.test-helpers.js +0 -0
  192. /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/explorer/state.d.ts +0 -0
  193. /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/explorer/state.js +0 -0
  194. /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/explorer/theme.d.ts +0 -0
  195. /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/internal/color-support.d.ts +0 -0
  196. /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/internal/color-support.js +0 -0
  197. /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/internal/output-format.d.ts +0 -0
  198. /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/internal/output-format.js +0 -0
  199. /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/internal/strip-ansi.d.ts +0 -0
  200. /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/internal/strip-ansi.js +0 -0
  201. /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/prompts/index.d.ts +0 -0
  202. /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/prompts/index.js +0 -0
  203. /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/prompts/primitives/cancel.d.ts +0 -0
  204. /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/prompts/primitives/cancel.js +0 -0
  205. /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/prompts/primitives/intro.d.ts +0 -0
  206. /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/prompts/primitives/intro.js +0 -0
  207. /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/prompts/primitives/log.d.ts +0 -0
  208. /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/prompts/primitives/log.js +0 -0
  209. /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/prompts/primitives/note.d.ts +0 -0
  210. /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/prompts/primitives/note.js +0 -0
  211. /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/prompts/primitives/outro.d.ts +0 -0
  212. /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/prompts/primitives/outro.js +0 -0
  213. /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/prompts/primitives/spinner.d.ts +0 -0
  214. /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/prompts/primitives/spinner.js +0 -0
  215. /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/static/index.d.ts +0 -0
  216. /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/static/index.js +0 -0
  217. /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/static/menu.d.ts +0 -0
  218. /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/static/menu.js +0 -0
  219. /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/static/spinner.d.ts +0 -0
  220. /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/static/spinner.js +0 -0
  221. /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/terminal-markdown/ast.d.ts +0 -0
  222. /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/terminal-markdown/ast.js +0 -0
  223. /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/terminal-markdown/demo-content.d.ts +0 -0
  224. /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/terminal-markdown/demo-content.js +0 -0
  225. /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/terminal-markdown/index.d.ts +0 -0
  226. /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/terminal-markdown/index.js +0 -0
  227. /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/terminal-markdown/parser/block.d.ts +0 -0
  228. /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/terminal-markdown/parser/block.js +0 -0
  229. /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/terminal-markdown/parser/frontmatter.d.ts +0 -0
  230. /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/terminal-markdown/parser/inline.d.ts +0 -0
  231. /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/terminal-markdown/parser/inline.js +0 -0
  232. /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/terminal-markdown/parser.d.ts +0 -0
  233. /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/terminal-markdown/parser.js +0 -0
  234. /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/terminal-markdown/renderer.d.ts +0 -0
  235. /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/terminal-markdown/renderer.js +0 -0
  236. /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/terminal-markdown/testing/theme-render-fixture.d.ts +0 -0
  237. /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/terminal-markdown/testing/theme-render-fixture.js +0 -0
  238. /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/tokens/spacing.d.ts +0 -0
  239. /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/tokens/spacing.js +0 -0
  240. /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/tokens/typography.d.ts +0 -0
  241. /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/tokens/typography.js +0 -0
  242. /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/tokens/widths.d.ts +0 -0
  243. /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/tokens/widths.js +0 -0
package/dist/mcp-proxy.js CHANGED
@@ -1,9 +1,10 @@
1
1
  import { existsSync } from "node:fs";
2
- import { lstat, mkdir, readFile, rename, writeFile } from "node:fs/promises";
2
+ import { lstat, mkdir, readFile, rename, unlink, writeFile } from "node:fs/promises";
3
3
  import path from "node:path";
4
4
  import { createHash, randomUUID } from "node:crypto";
5
- import { createLogger } from "@poe-code/design-system";
5
+ import { createLogger } from "toolcraft-design";
6
6
  import { HttpTransport, McpClient, StdioTransport } from "tiny-mcp-client";
7
+ import { hasOwnErrorCode } from "./error-codes.js";
7
8
  import { convertJsonSchema } from "./json-schema-converter.js";
8
9
  const GROUP_CONFIG_SYMBOL_DESCRIPTION = "toolcraft.group.config";
9
10
  const MCP_PROXY_SCHEMA_URL = "https://poe-platform.github.io/poe-code/schemas/toolcraft/mcp-proxy.schema.json";
@@ -175,8 +176,7 @@ async function readCache(cachePath) {
175
176
  };
176
177
  }
177
178
  catch (error) {
178
- const code = error.code;
179
- if (code === "ENOENT" || error instanceof SyntaxError) {
179
+ if (hasOwnErrorCode(error, "ENOENT") || error instanceof SyntaxError) {
180
180
  return undefined;
181
181
  }
182
182
  return undefined;
@@ -185,14 +185,31 @@ async function readCache(cachePath) {
185
185
  async function writeCache(cachePath, cache) {
186
186
  const directory = path.dirname(cachePath);
187
187
  const tempPath = `${cachePath}.tmp-${randomUUID()}`;
188
+ let tempCreated = false;
188
189
  await assertCachePathHasNoSymlinks(cachePath);
189
190
  await assertCachePathHasNoSymlinks(tempPath);
190
191
  await mkdir(directory, { recursive: true });
191
192
  await assertCachePathHasNoSymlinks(directory);
192
- await writeFile(tempPath, `${JSON.stringify(cache, null, 2)}\n`);
193
- await assertCachePathHasNoSymlinks(tempPath);
194
- await assertCachePathHasNoSymlinks(cachePath);
195
- await rename(tempPath, cachePath);
193
+ try {
194
+ await writeFile(tempPath, `${JSON.stringify(cache, null, 2)}\n`, {
195
+ encoding: "utf8",
196
+ flag: "wx"
197
+ });
198
+ tempCreated = true;
199
+ await assertCachePathHasNoSymlinks(tempPath);
200
+ await assertCachePathHasNoSymlinks(cachePath);
201
+ await rename(tempPath, cachePath);
202
+ tempCreated = false;
203
+ }
204
+ catch (error) {
205
+ if (tempCreated || !isAlreadyExistsError(error)) {
206
+ await unlink(tempPath).catch(() => undefined);
207
+ }
208
+ throw error;
209
+ }
210
+ }
211
+ function isAlreadyExistsError(error) {
212
+ return hasOwnErrorCode(error, "EEXIST");
196
213
  }
197
214
  async function fetchCache(name, config) {
198
215
  const logger = createLogger((message) => {
@@ -402,7 +419,7 @@ async function assertCachePathHasNoSymlinks(filePath) {
402
419
  }
403
420
  }
404
421
  catch (error) {
405
- if (error.code !== "ENOENT") {
422
+ if (!hasOwnErrorCode(error, "ENOENT")) {
406
423
  throw error;
407
424
  }
408
425
  }
package/dist/mcp.js CHANGED
@@ -93,8 +93,8 @@ function isPlainObject(value) {
93
93
  function createFs() {
94
94
  return {
95
95
  readFile: async (path, encoding = "utf8") => readFile(path, { encoding }),
96
- writeFile: async (path, contents) => {
97
- await writeFile(path, contents);
96
+ writeFile: async (path, contents, options) => {
97
+ await writeFile(path, contents, options);
98
98
  },
99
99
  exists: async (path) => {
100
100
  try {
@@ -356,6 +356,48 @@ function validateSchemaValue(schema, value, casing, label, errors) {
356
356
  return value.map((item, index) => validateSchemaValue(unwrappedSchema.item, item, casing, `${label}[${index}]`, errors));
357
357
  case "object":
358
358
  return validateObjectSchema(unwrappedSchema, value, casing, label, errors);
359
+ case "json":
360
+ return value;
361
+ case "record": {
362
+ if (!isPlainObject(value)) {
363
+ errors.push({
364
+ path: label,
365
+ message: `Invalid value for "${label}". Expected an object, got ${describeReceived(value)}.`
366
+ });
367
+ return value;
368
+ }
369
+ return Object.fromEntries(Object.entries(value).map(([key, item]) => [
370
+ key,
371
+ validateSchemaValue(unwrappedSchema.value, item, casing, `${label}.${key}`, errors)
372
+ ]));
373
+ }
374
+ case "oneOf": {
375
+ if (!isPlainObject(value)) {
376
+ return value;
377
+ }
378
+ const discriminatorKey = formatSegment(unwrappedSchema.discriminator, casing);
379
+ const discriminator = value[discriminatorKey];
380
+ const branch = typeof discriminator === "string" ? unwrappedSchema.branches[discriminator] : undefined;
381
+ if (branch === undefined) {
382
+ return value;
383
+ }
384
+ const { [discriminatorKey]: ignoredDiscriminator, ...branchValue } = value;
385
+ void ignoredDiscriminator;
386
+ return {
387
+ [unwrappedSchema.discriminator]: discriminator,
388
+ ...validateObjectSchema(branch, branchValue, casing, label, errors)
389
+ };
390
+ }
391
+ case "union": {
392
+ if (!isPlainObject(value)) {
393
+ return value;
394
+ }
395
+ const branch = unwrappedSchema.branches.find((candidate) => Object.keys(candidate.shape).every((key) => candidate.shape[key]?.kind === "optional" ||
396
+ Object.prototype.hasOwnProperty.call(value, formatSegment(key, casing))));
397
+ return branch === undefined
398
+ ? value
399
+ : validateObjectSchema(branch, value, casing, label, errors);
400
+ }
359
401
  }
360
402
  }
361
403
  function validateObjectSchema(schema, value, casing, label, errors) {
@@ -373,6 +415,15 @@ function validateObjectSchema(schema, value, casing, label, errors) {
373
415
  }
374
416
  for (const key of Object.keys(value)) {
375
417
  if (!expectedKeys.has(key)) {
418
+ if (schema.additionalProperties === true) {
419
+ Object.defineProperty(result, key, {
420
+ value: value[key],
421
+ enumerable: true,
422
+ configurable: true,
423
+ writable: true
424
+ });
425
+ continue;
426
+ }
376
427
  const fieldLabel = label.length === 0 ? key : `${label}.${key}`;
377
428
  errors.push({
378
429
  path: fieldLabel,
@@ -557,7 +608,7 @@ function createDeferredMCPServer(root, options) {
557
608
  }
558
609
  export function createMCPServer(roots, options) {
559
610
  const normalizedRoot = normalizeRoots(roots);
560
- const root = options.approvals === false ? normalizedRoot : mergeApprovalsGroup(normalizedRoot);
611
+ const root = options.approvals === true ? mergeApprovalsGroup(normalizedRoot) : normalizedRoot;
561
612
  if (!hasMcpProxyGroups(root)) {
562
613
  return createResolvedMCPServer(root, options);
563
614
  }
@@ -566,7 +617,7 @@ export function createMCPServer(roots, options) {
566
617
  export async function runMCP(roots, options) {
567
618
  enableSourceMaps();
568
619
  const normalizedRoot = normalizeRoots(roots);
569
- const root = options.approvals === false ? normalizedRoot : mergeApprovalsGroup(normalizedRoot);
620
+ const root = options.approvals === true ? mergeApprovalsGroup(normalizedRoot) : normalizedRoot;
570
621
  await resolveMcpProxies(root, { projectRoot: options.projectRoot });
571
622
  const server = createResolvedMCPServer(root, options);
572
623
  await server.listen();
package/dist/renderer.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import YAML from "yaml";
2
- import { renderDetailCard } from "@poe-code/design-system";
2
+ import { renderDetailCard } from "toolcraft-design";
3
3
  function isObject(value) {
4
4
  return value !== null && typeof value === "object" && !Array.isArray(value);
5
5
  }
@@ -21,14 +21,35 @@ export function filterSchemaForScope(schema, scope) {
21
21
  case "number":
22
22
  case "boolean":
23
23
  case "enum":
24
+ case "json":
24
25
  return schema;
26
+ case "record": {
27
+ const value = filterSchemaForScope(schema.value, scope);
28
+ return value === undefined ? undefined : { ...schema, value };
29
+ }
30
+ case "oneOf":
31
+ return {
32
+ ...schema,
33
+ branches: Object.fromEntries(Object.entries(schema.branches).flatMap(([name, branch]) => {
34
+ const filtered = filterSchemaForScope(branch, scope);
35
+ return filtered?.kind === "object" ? [[name, filtered]] : [];
36
+ }))
37
+ };
38
+ case "union":
39
+ return {
40
+ ...schema,
41
+ branches: schema.branches.flatMap((branch) => {
42
+ const filtered = filterSchemaForScope(branch, scope);
43
+ return filtered?.kind === "object" ? [filtered] : [];
44
+ })
45
+ };
25
46
  case "object":
26
47
  return {
27
48
  ...schema,
28
49
  shape: Object.fromEntries(Object.entries(schema.shape).flatMap(([key, childSchema]) => {
29
50
  const filtered = filterSchemaForScope(childSchema, scope);
30
51
  return filtered === undefined ? [] : [[key, filtered]];
31
- })),
52
+ }))
32
53
  };
33
54
  }
34
55
  }
package/dist/sdk.js CHANGED
@@ -74,8 +74,8 @@ function isPlainObject(value) {
74
74
  function createFs() {
75
75
  return {
76
76
  readFile: async (path, encoding = "utf8") => readFile(path, { encoding }),
77
- writeFile: async (path, contents) => {
78
- await writeFile(path, contents);
77
+ writeFile: async (path, contents, options) => {
78
+ await writeFile(path, contents, options);
79
79
  },
80
80
  exists: async (path) => {
81
81
  try {
@@ -179,6 +179,45 @@ function validateSchemaValue(schema, value, label, errors) {
179
179
  return value.map((item, index) => validateSchemaValue(unwrappedSchema.item, item, `${label}[${index}]`, errors));
180
180
  case "object":
181
181
  return validateObjectSchema(unwrappedSchema, value, label, errors);
182
+ case "json":
183
+ return value;
184
+ case "record": {
185
+ if (!isPlainObject(value)) {
186
+ errors.push({
187
+ path: label,
188
+ message: `Invalid value for "${label}". Expected an object, got ${describeReceived(value)}.`
189
+ });
190
+ return value;
191
+ }
192
+ return Object.fromEntries(Object.entries(value).map(([key, item]) => [
193
+ key,
194
+ validateSchemaValue(unwrappedSchema.value, item, `${label}.${key}`, errors)
195
+ ]));
196
+ }
197
+ case "oneOf": {
198
+ if (!isPlainObject(value)) {
199
+ return value;
200
+ }
201
+ const discriminator = value[unwrappedSchema.discriminator];
202
+ const branch = typeof discriminator === "string" ? unwrappedSchema.branches[discriminator] : undefined;
203
+ if (branch === undefined) {
204
+ return value;
205
+ }
206
+ const { [unwrappedSchema.discriminator]: ignoredDiscriminator, ...branchValue } = value;
207
+ void ignoredDiscriminator;
208
+ return {
209
+ [unwrappedSchema.discriminator]: discriminator,
210
+ ...validateObjectSchema(branch, branchValue, label, errors)
211
+ };
212
+ }
213
+ case "union": {
214
+ if (!isPlainObject(value)) {
215
+ return value;
216
+ }
217
+ const branch = unwrappedSchema.branches.find((candidate) => Object.keys(candidate.shape).every((key) => candidate.shape[key]?.kind === "optional" ||
218
+ Object.prototype.hasOwnProperty.call(value, formatSegment(key))));
219
+ return branch === undefined ? value : validateObjectSchema(branch, value, label, errors);
220
+ }
182
221
  }
183
222
  }
184
223
  function validateObjectSchema(schema, value, label, errors) {
@@ -196,6 +235,15 @@ function validateObjectSchema(schema, value, label, errors) {
196
235
  }
197
236
  for (const key of Object.keys(value)) {
198
237
  if (!expectedKeys.has(key)) {
238
+ if (schema.additionalProperties === true) {
239
+ Object.defineProperty(result, key, {
240
+ value: value[key],
241
+ enumerable: true,
242
+ configurable: true,
243
+ writable: true
244
+ });
245
+ continue;
246
+ }
199
247
  const fieldLabel = label.length === 0 ? key : `${label}.${key}`;
200
248
  errors.push({
201
249
  path: fieldLabel,
@@ -266,7 +314,7 @@ function defineMember(target, key, value) {
266
314
  }
267
315
  export function createSDK(root, options = {}) {
268
316
  enableSourceMaps();
269
- const mergedRoot = options.approvals === false ? root : mergeApprovalsGroup(root);
317
+ const mergedRoot = options.approvals === true ? mergeApprovalsGroup(root) : root;
270
318
  if (!hasMcpProxyGroups(mergedRoot)) {
271
319
  return createResolvedSDK(mergedRoot, options);
272
320
  }
@@ -1,4 +1,4 @@
1
- import { text } from "@poe-code/design-system";
1
+ import { text } from "toolcraft-design";
2
2
  export function renderSourceSnippet(opts) {
3
3
  const lines = opts.source.replaceAll("\r\n", "\n").replaceAll("\r", "\n").split("\n");
4
4
  const line = clampInteger(opts.line, 1, Math.max(lines.length, 1));
@@ -6,6 +6,11 @@ export const claudeCodeAgent = {
6
6
  aliases: ["claude"],
7
7
  binaryName: "claude",
8
8
  apiShapes: ["anthropic-messages"],
9
+ otelCapture: {
10
+ env: {
11
+ CLAUDE_CODE_ENABLE_TELEMETRY: "1"
12
+ }
13
+ },
9
14
  configPath: "~/.claude/settings.json",
10
15
  branding: {
11
16
  colors: {
@@ -5,6 +5,16 @@ export const codexAgent = {
5
5
  summary: "Configure Codex to use Poe as the model provider.",
6
6
  binaryName: "codex",
7
7
  apiShapes: ["openai-responses"],
8
+ otelCapture: {
9
+ args: (endpoint, content) => [
10
+ "-c",
11
+ `otel.trace_exporter={"otlp-http"={endpoint=${JSON.stringify(`${endpoint}/v1/traces`)},protocol="json"}}`,
12
+ "-c",
13
+ `otel.exporter={"otlp-http"={endpoint=${JSON.stringify(`${endpoint}/v1/logs`)},protocol="json"}}`,
14
+ "-c",
15
+ `otel.log_user_prompt=${content}`
16
+ ]
17
+ },
8
18
  configPath: "~/.codex/config.toml",
9
19
  branding: {
10
20
  colors: {
@@ -0,0 +1,2 @@
1
+ import type { AgentDefinition } from "../types.js";
2
+ export declare const cursorAgent: AgentDefinition;
@@ -0,0 +1,15 @@
1
+ export const cursorAgent = {
2
+ id: "cursor",
3
+ name: "cursor",
4
+ aliases: ["cursor-agent"],
5
+ label: "Cursor",
6
+ summary: "Cursor's CLI coding agent.",
7
+ binaryName: "cursor-agent",
8
+ configPath: "~/.cursor/cli-config.json",
9
+ branding: {
10
+ colors: {
11
+ dark: "#FFFFFF",
12
+ light: "#000000"
13
+ }
14
+ }
15
+ };
@@ -5,6 +5,7 @@ export const gooseAgent = {
5
5
  summary: "Block's open-source AI agent with ACP support.",
6
6
  binaryName: "goose",
7
7
  apiShapes: ["openai-chat-completions"],
8
+ otelCapture: {},
8
9
  configPath: "~/.config/goose/config.yaml",
9
10
  branding: {
10
11
  colors: {
@@ -1,6 +1,7 @@
1
1
  export { claudeCodeAgent } from "./claude-code.js";
2
2
  export { claudeDesktopAgent } from "./claude-desktop.js";
3
3
  export { codexAgent } from "./codex.js";
4
+ export { cursorAgent } from "./cursor.js";
4
5
  export { geminiCliAgent } from "./gemini-cli.js";
5
6
  export { openCodeAgent } from "./opencode.js";
6
7
  export { kimiAgent } from "./kimi.js";
@@ -1,6 +1,7 @@
1
1
  export { claudeCodeAgent } from "./claude-code.js";
2
2
  export { claudeDesktopAgent } from "./claude-desktop.js";
3
3
  export { codexAgent } from "./codex.js";
4
+ export { cursorAgent } from "./cursor.js";
4
5
  export { geminiCliAgent } from "./gemini-cli.js";
5
6
  export { openCodeAgent } from "./opencode.js";
6
7
  export { kimiAgent } from "./kimi.js";
@@ -5,6 +5,11 @@ export const openCodeAgent = {
5
5
  summary: "Configure OpenCode CLI to use the Poe API.",
6
6
  binaryName: "opencode",
7
7
  apiShapes: ["openai-chat-completions"],
8
+ otelCapture: {
9
+ env: {
10
+ OPENCODE_CONFIG_CONTENT: '{"experimental":{"openTelemetry":true}}'
11
+ }
12
+ },
8
13
  configPath: "~/.config/opencode/config.json",
9
14
  branding: {
10
15
  colors: {
@@ -1,5 +1,5 @@
1
- export type { AgentDefinition, ApiShapeId } from "./types.js";
1
+ export type { AgentDefinition, ApiShapeId, OtelCaptureDefinition } from "./types.js";
2
2
  export type { AgentSpecifier } from "./specifier.js";
3
- export { claudeCodeAgent, claudeDesktopAgent, codexAgent, geminiCliAgent, openCodeAgent, kimiAgent, gooseAgent, poeAgentAgent } from "./agents/index.js";
3
+ export { claudeCodeAgent, claudeDesktopAgent, codexAgent, cursorAgent, geminiCliAgent, openCodeAgent, kimiAgent, gooseAgent, poeAgentAgent } from "./agents/index.js";
4
4
  export { allAgents, resolveAgentId } from "./registry.js";
5
5
  export { parseAgentSpecifier, formatAgentSpecifier, normalizeAgentId } from "./specifier.js";
@@ -1,3 +1,3 @@
1
- export { claudeCodeAgent, claudeDesktopAgent, codexAgent, geminiCliAgent, openCodeAgent, kimiAgent, gooseAgent, poeAgentAgent } from "./agents/index.js";
1
+ export { claudeCodeAgent, claudeDesktopAgent, codexAgent, cursorAgent, geminiCliAgent, openCodeAgent, kimiAgent, gooseAgent, poeAgentAgent } from "./agents/index.js";
2
2
  export { allAgents, resolveAgentId } from "./registry.js";
3
3
  export { parseAgentSpecifier, formatAgentSpecifier, normalizeAgentId } from "./specifier.js";
@@ -1,4 +1,4 @@
1
- import { claudeCodeAgent, claudeDesktopAgent, codexAgent, geminiCliAgent, openCodeAgent, kimiAgent, gooseAgent, poeAgentAgent } from "./agents/index.js";
1
+ import { claudeCodeAgent, claudeDesktopAgent, codexAgent, cursorAgent, geminiCliAgent, openCodeAgent, kimiAgent, gooseAgent, poeAgentAgent } from "./agents/index.js";
2
2
  function freezeAgent(agent) {
3
3
  if (agent.aliases !== undefined) {
4
4
  Object.freeze(agent.aliases);
@@ -6,6 +6,12 @@ function freezeAgent(agent) {
6
6
  if (agent.apiShapes !== undefined) {
7
7
  Object.freeze(agent.apiShapes);
8
8
  }
9
+ if (agent.otelCapture?.env !== undefined) {
10
+ Object.freeze(agent.otelCapture.env);
11
+ }
12
+ if (agent.otelCapture !== undefined) {
13
+ Object.freeze(agent.otelCapture);
14
+ }
9
15
  Object.freeze(agent.branding.colors);
10
16
  Object.freeze(agent.branding);
11
17
  return Object.freeze(agent);
@@ -14,6 +20,7 @@ export const allAgents = Object.freeze([
14
20
  freezeAgent(claudeCodeAgent),
15
21
  freezeAgent(claudeDesktopAgent),
16
22
  freezeAgent(codexAgent),
23
+ freezeAgent(cursorAgent),
17
24
  freezeAgent(geminiCliAgent),
18
25
  freezeAgent(openCodeAgent),
19
26
  freezeAgent(kimiAgent),
@@ -1,4 +1,7 @@
1
1
  import { resolveAgentId } from "./registry.js";
2
+ function getOwnModel(specifier) {
3
+ return Object.prototype.hasOwnProperty.call(specifier, "model") ? specifier.model : undefined;
4
+ }
2
5
  export function parseAgentSpecifier(input) {
3
6
  const colonIndex = input.indexOf(":");
4
7
  if (colonIndex === -1) {
@@ -12,8 +15,9 @@ export function parseAgentSpecifier(input) {
12
15
  };
13
16
  }
14
17
  export function formatAgentSpecifier(specifier) {
15
- if (specifier.model) {
16
- return `${specifier.agent}:${specifier.model}`;
18
+ const model = getOwnModel(specifier);
19
+ if (model) {
20
+ return `${specifier.agent}:${model}`;
17
21
  }
18
22
  return specifier.agent;
19
23
  }
@@ -22,6 +26,6 @@ export function normalizeAgentId(input) {
22
26
  const agent = resolveAgentId(specifier.agent) ?? specifier.agent;
23
27
  return formatAgentSpecifier({
24
28
  agent,
25
- model: specifier.model
29
+ model: getOwnModel(specifier)
26
30
  });
27
31
  }
@@ -1,4 +1,8 @@
1
1
  export type ApiShapeId = "openai-chat-completions" | "openai-responses" | "anthropic-messages" | "google-generations";
2
+ export interface OtelCaptureDefinition {
3
+ env?: Record<string, string>;
4
+ args?: (endpoint: string, content: boolean) => string[];
5
+ }
2
6
  export interface AgentDefinition {
3
7
  id: string;
4
8
  name: string;
@@ -8,6 +12,7 @@ export interface AgentDefinition {
8
12
  /** Binary name for CLI agents. Optional for GUI-only apps like Claude Desktop. */
9
13
  binaryName?: string;
10
14
  readonly apiShapes?: readonly ApiShapeId[];
15
+ readonly otelCapture?: OtelCaptureDefinition;
11
16
  configPath: string;
12
17
  branding: {
13
18
  colors: {
@@ -19,7 +19,7 @@ export function osascriptProvider(options = {}) {
19
19
  return parseStdout(stdout);
20
20
  }
21
21
  catch (error) {
22
- if (error.code === "ENOENT") {
22
+ if (hasOwnErrorCode(error, "ENOENT")) {
23
23
  throw new Error("osascript not found — provide a different provider on this platform");
24
24
  }
25
25
  if (isUserCanceled(error)) {
@@ -31,3 +31,9 @@ export function osascriptProvider(options = {}) {
31
31
  }
32
32
  };
33
33
  }
34
+ function hasOwnErrorCode(error, code) {
35
+ return (typeof error === "object" &&
36
+ error !== null &&
37
+ Object.prototype.hasOwnProperty.call(error, "code") &&
38
+ error.code === code);
39
+ }
@@ -31,6 +31,12 @@ const agentMcpConfigs = {
31
31
  format: "toml",
32
32
  shape: "standard"
33
33
  },
34
+ cursor: {
35
+ configFile: "~/.cursor/mcp.json",
36
+ configKey: "mcpServers",
37
+ format: "json",
38
+ shape: "standard"
39
+ },
34
40
  opencode: {
35
41
  configFile: "~/.config/opencode/opencode.json",
36
42
  configKey: "mcp",
@@ -0,0 +1 @@
1
+ export declare function hasOwnErrorCode(error: unknown, code: string): error is NodeJS.ErrnoException;
@@ -0,0 +1,6 @@
1
+ export function hasOwnErrorCode(error, code) {
2
+ return (typeof error === "object" &&
3
+ error !== null &&
4
+ Object.prototype.hasOwnProperty.call(error, "code") &&
5
+ error.code === code);
6
+ }
@@ -1,9 +1,11 @@
1
+ import { randomUUID } from "node:crypto";
1
2
  import path from "node:path";
2
- import { renderTemplate } from "@poe-code/design-system";
3
+ import { renderTemplate } from "toolcraft-design";
3
4
  import { getConfigFormat, detectFormat } from "../formats/index.js";
4
5
  import { cloneConfigObject, setConfigEntry } from "../formats/object.js";
5
6
  import { resolvePath } from "./path-utils.js";
6
7
  import { isNotFound, readFileIfExists, pathExists, createTimestamp } from "../fs-utils.js";
8
+ import { hasOwnErrorCode } from "../error-codes.js";
7
9
  // ============================================================================
8
10
  // Helper Functions
9
11
  // ============================================================================
@@ -29,6 +31,7 @@ async function backupInvalidDocument(context, targetPath, content) {
29
31
  }
30
32
  catch (error) {
31
33
  if (!isAlreadyExists(error)) {
34
+ await context.fs.unlink(backupPath).catch(() => undefined);
32
35
  throw error;
33
36
  }
34
37
  attempt += 1;
@@ -36,7 +39,7 @@ async function backupInvalidDocument(context, targetPath, content) {
36
39
  }
37
40
  }
38
41
  function isAlreadyExists(error) {
39
- return Boolean(error && typeof error === "object" && "code" in error && error.code === "EEXIST");
42
+ return hasOwnErrorCode(error, "EEXIST");
40
43
  }
41
44
  async function assertRegularWriteTarget(context, targetPath) {
42
45
  // Symlinks inside the managed home directory are untrusted: an attacker could
@@ -65,30 +68,36 @@ async function assertRegularWriteTarget(context, targetPath) {
65
68
  }
66
69
  async function writeAtomically(context, targetPath, content) {
67
70
  await assertRegularWriteTarget(context, targetPath);
68
- let attempt = 0;
69
- while (true) {
70
- const tempPath = `${targetPath}.mutation-tmp-${attempt}`;
71
+ for (let attempt = 0; attempt < 10; attempt += 1) {
72
+ const tempPath = `${targetPath}.mutation-tmp-${process.pid}-${randomUUID()}`;
73
+ let tempCreated = false;
71
74
  try {
75
+ await assertRegularWriteTarget(context, tempPath);
72
76
  await context.fs.writeFile(tempPath, content, { encoding: "utf8", flag: "wx" });
77
+ tempCreated = true;
73
78
  await context.fs.rename(tempPath, targetPath);
79
+ tempCreated = false;
74
80
  return;
75
81
  }
76
82
  catch (error) {
77
- if (isAlreadyExists(error)) {
78
- attempt += 1;
79
- continue;
80
- }
81
- try {
82
- await context.fs.unlink(tempPath);
83
- }
84
- catch (cleanupError) {
85
- if (!isNotFound(cleanupError)) {
86
- void cleanupError;
83
+ const alreadyExists = isAlreadyExists(error);
84
+ if (tempCreated || !alreadyExists) {
85
+ try {
86
+ await context.fs.unlink(tempPath);
87
+ }
88
+ catch (cleanupError) {
89
+ if (!isNotFound(cleanupError)) {
90
+ void cleanupError;
91
+ }
87
92
  }
88
93
  }
94
+ if (alreadyExists) {
95
+ continue;
96
+ }
89
97
  throw error;
90
98
  }
91
99
  }
100
+ throw new Error(`Unable to create temporary mutation file for ${targetPath}.`);
92
101
  }
93
102
  function describeMutation(kind, targetPath) {
94
103
  const displayPath = targetPath ?? "target";
@@ -392,6 +401,7 @@ async function applyBackup(mutation, context, options) {
392
401
  }
393
402
  catch (error) {
394
403
  if (!isAlreadyExists(error)) {
404
+ await context.fs.unlink(backupPath).catch(() => undefined);
395
405
  throw error;
396
406
  }
397
407
  attempt += 1;
@@ -39,7 +39,7 @@ function merge(base, patch) {
39
39
  if (value === undefined) {
40
40
  continue;
41
41
  }
42
- const existing = result[key];
42
+ const existing = hasConfigEntry(result, key) ? result[key] : undefined;
43
43
  if (isConfigObject(existing) && isConfigObject(value)) {
44
44
  setConfigEntry(result, key, merge(existing, value));
45
45
  continue;
@@ -23,7 +23,7 @@ function merge(base, patch) {
23
23
  if (value === undefined) {
24
24
  continue;
25
25
  }
26
- const existing = result[key];
26
+ const existing = hasConfigEntry(result, key) ? result[key] : undefined;
27
27
  if (isConfigObject(existing) && isConfigObject(value)) {
28
28
  setConfigEntry(result, key, merge(existing, value));
29
29
  continue;
@@ -26,7 +26,7 @@ function merge(base, patch) {
26
26
  if (value === undefined) {
27
27
  continue;
28
28
  }
29
- const existing = result[key];
29
+ const existing = hasConfigEntry(result, key) ? result[key] : undefined;
30
30
  if (isConfigObject(existing) && isConfigObject(value)) {
31
31
  setConfigEntry(result, key, merge(existing, value));
32
32
  continue;
@@ -1,11 +1,9 @@
1
+ import { hasOwnErrorCode } from "./error-codes.js";
1
2
  /**
2
3
  * Check if an error is a "file not found" (ENOENT) error.
3
4
  */
4
5
  export function isNotFound(error) {
5
- return (typeof error === "object" &&
6
- error !== null &&
7
- "code" in error &&
8
- error.code === "ENOENT");
6
+ return hasOwnErrorCode(error, "ENOENT");
9
7
  }
10
8
  /**
11
9
  * Read a file if it exists, returning null if not found.