pmx-canvas 0.7.3 → 0.8.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (244) hide show
  1. package/.github/extensions/pmx-canvas/THIRD_PARTY_LICENSES.txt +331 -0
  2. package/.github/extensions/pmx-canvas/extension.mjs +25 -172
  3. package/.github/extensions/pmx-canvas/mcp-bootstrap.ts +198 -0
  4. package/.github/extensions/pmx-canvas/runtime.d.mts +41 -0
  5. package/.github/extensions/pmx-canvas/runtime.json +3 -0
  6. package/.github/extensions/pmx-canvas/runtime.mjs +194 -0
  7. package/.github/extensions/pmx-canvas/start-mcp.mjs +51 -0
  8. package/.github/extensions/pmx-canvas/tools.json +2560 -0
  9. package/CHANGELOG.md +64 -0
  10. package/Readme.md +21 -7
  11. package/dist/canvas/fonts/OFL.txt +93 -0
  12. package/dist/canvas/fonts/ibm-plex-mono-latin-400-normal.woff2 +0 -0
  13. package/dist/canvas/fonts/ibm-plex-mono-latin-500-normal.woff2 +0 -0
  14. package/dist/canvas/fonts/ibm-plex-mono-latin-ext-400-normal.woff2 +0 -0
  15. package/dist/canvas/fonts/ibm-plex-mono-latin-ext-500-normal.woff2 +0 -0
  16. package/dist/canvas/fonts/ibm-plex-sans-latin-400-normal.woff2 +0 -0
  17. package/dist/canvas/fonts/ibm-plex-sans-latin-500-normal.woff2 +0 -0
  18. package/dist/canvas/fonts/ibm-plex-sans-latin-600-normal.woff2 +0 -0
  19. package/dist/canvas/fonts/ibm-plex-sans-latin-ext-400-normal.woff2 +0 -0
  20. package/dist/canvas/fonts/ibm-plex-sans-latin-ext-500-normal.woff2 +0 -0
  21. package/dist/canvas/fonts/ibm-plex-sans-latin-ext-600-normal.woff2 +0 -0
  22. package/dist/canvas/global.css +726 -674
  23. package/dist/canvas/index.js +90 -88
  24. package/dist/canvas/mcp-app.html +7879 -0
  25. package/dist/canvas/mermaid-entry.js +1 -1
  26. package/dist/canvas/surface-theme.css +151 -46
  27. package/dist/json-render/index.css +81 -1
  28. package/dist/json-render/index.js +1 -1
  29. package/dist/types/cli/commands/record.d.ts +1 -1
  30. package/dist/types/client/canvas/NodeContextMark.d.ts +24 -0
  31. package/dist/types/client/canvas/SessionReceipt.d.ts +3 -1
  32. package/dist/types/client/icons.d.ts +1 -2
  33. package/dist/types/client/mcp-app/index.d.ts +1 -0
  34. package/dist/types/client/nodes/HtmlNode.d.ts +1 -0
  35. package/dist/types/client/nodes/ax-node-actions.d.ts +2 -2
  36. package/dist/types/client/nodes/markdown-sanitize.d.ts +2 -0
  37. package/dist/types/client/nodes/use-workbench-asset.d.ts +2 -0
  38. package/dist/types/client/state/attention-store.d.ts +0 -5
  39. package/dist/types/client/state/context-status-store.d.ts +53 -0
  40. package/dist/types/client/state/intent-bridge.d.ts +3 -0
  41. package/dist/types/client/state/near-pin-store.d.ts +16 -0
  42. package/dist/types/client/state/presence-store.d.ts +5 -0
  43. package/dist/types/client/state/session-store.d.ts +33 -3
  44. package/dist/types/client/state/workbench-transport.d.ts +16 -0
  45. package/dist/types/client/theme/tokens.d.ts +1 -3
  46. package/dist/types/client/types.d.ts +9 -0
  47. package/dist/types/json-render/server.d.ts +1 -1
  48. package/dist/types/mcp/app-server.d.ts +3 -0
  49. package/dist/types/mcp/canvas-access.d.ts +1 -1
  50. package/dist/types/mcp/canvas-app.d.ts +4 -0
  51. package/dist/types/mcp/workbench-app.d.ts +4 -0
  52. package/dist/types/server/agent-presence.d.ts +1 -1
  53. package/dist/types/server/ax-state.d.ts +1 -1
  54. package/dist/types/server/canvas-db.d.ts +8 -0
  55. package/dist/types/server/canvas-geometry.d.ts +25 -0
  56. package/dist/types/server/canvas-operations.d.ts +1 -11
  57. package/dist/types/server/canvas-state.d.ts +25 -3
  58. package/dist/types/server/context-brief.d.ts +8 -1
  59. package/dist/types/server/context-reads.d.ts +30 -7
  60. package/dist/types/server/index.d.ts +6 -1
  61. package/dist/types/server/mcp-app-runtime.d.ts +1 -0
  62. package/dist/types/server/operations/http.d.ts +2 -0
  63. package/dist/types/server/operations/invoker.d.ts +4 -2
  64. package/dist/types/server/operations/ops/nodes.d.ts +0 -6
  65. package/dist/types/server/server.d.ts +1 -0
  66. package/dist/types/server/spatial-analysis.d.ts +2 -0
  67. package/dist/types/shared/agent-context.d.ts +22 -0
  68. package/dist/types/shared/agent-presence.d.ts +3 -10
  69. package/dist/types/shared/canvas-app.d.ts +54 -0
  70. package/dist/types/shared/themes.d.ts +1 -1
  71. package/docs/RELEASE.md +7 -3
  72. package/docs/agent-plugin.md +123 -0
  73. package/docs/ax-state-contract.md +40 -0
  74. package/docs/cli.md +7 -2
  75. package/docs/design/AgentContext.dc.html +186 -0
  76. package/docs/design/Before.dc.html +208 -0
  77. package/docs/design/BoardPins.dc.html +151 -0
  78. package/docs/design/Chrome.dc.html +211 -0
  79. package/docs/design/Context.dc.html +239 -0
  80. package/docs/design/Flows.dc.html +181 -0
  81. package/docs/design/Home.dc.html +209 -0
  82. package/docs/design/HomeGraph.dc.html +211 -0
  83. package/docs/design/HomeMap.dc.html +117 -0
  84. package/docs/design/HomeTeam.dc.html +176 -0
  85. package/docs/design/Light.dc.html +28 -0
  86. package/docs/design/Main.dc.html +280 -0
  87. package/docs/design/NearPin.dc.html +260 -0
  88. package/docs/design/Pane600.dc.html +120 -0
  89. package/docs/design/Relations.dc.html +297 -0
  90. package/docs/design/Themes.dc.html +121 -0
  91. package/docs/design/TokenSystem.dc.html +136 -0
  92. package/docs/design/Tokens.dc.html +163 -0
  93. package/docs/design/Types1.dc.html +177 -0
  94. package/docs/design/Types2.dc.html +226 -0
  95. package/docs/design/Types3.dc.html +195 -0
  96. package/docs/design/Uses.dc.html +152 -0
  97. package/docs/design/Vision.dc.html +116 -0
  98. package/docs/design/Zoom.dc.html +82 -0
  99. package/docs/design/canvas.json +274 -0
  100. package/docs/design.md +217 -0
  101. package/docs/environment.md +1 -1
  102. package/docs/http-api.md +86 -16
  103. package/docs/mcp.md +202 -4
  104. package/docs/node-types.md +34 -10
  105. package/docs/plans/plan-009-tech-debt-backlog.md +1 -1
  106. package/docs/plans/plan-015-design-foundation-wave-0.md +177 -0
  107. package/docs/plans/plan-016-context-made-visible-wave-1.md +148 -0
  108. package/docs/product-vision-2026-09.md +47 -7
  109. package/docs/screenshot.png +0 -0
  110. package/docs/sdk.md +1 -0
  111. package/package.json +10 -4
  112. package/plugins/pmx-canvas/LICENSE +21 -0
  113. package/plugins/pmx-canvas/THIRD_PARTY_LICENSES.txt +331 -0
  114. package/plugins/pmx-canvas/assets/preview.png +0 -0
  115. package/plugins/pmx-canvas/com.github.copilot/extensions/pmx-canvas/extension.mjs +930 -0
  116. package/plugins/pmx-canvas/com.github.copilot/extensions/pmx-canvas/runtime.json +3 -0
  117. package/plugins/pmx-canvas/com.github.copilot/extensions/pmx-canvas/runtime.mjs +194 -0
  118. package/plugins/pmx-canvas/com.github.copilot/extensions/pmx-canvas/steering-delivery.mjs +79 -0
  119. package/plugins/pmx-canvas/mcp.json +12 -0
  120. package/plugins/pmx-canvas/plugin.json +24 -0
  121. package/plugins/pmx-canvas/runtime.json +3 -0
  122. package/plugins/pmx-canvas/runtime.mjs +194 -0
  123. package/plugins/pmx-canvas/start-mcp.mjs +51 -0
  124. package/plugins/pmx-canvas/tools.json +2560 -0
  125. package/skills/pmx-canvas/SKILL.md +29 -9
  126. package/skills/pmx-canvas/evals/evals.json +62 -0
  127. package/skills/pmx-canvas/references/ax-html-control-surface.md +6 -0
  128. package/skills/pmx-canvas/references/full-reference.md +11 -7
  129. package/skills/pmx-canvas/references/github-copilot-app-adapter.md +20 -8
  130. package/skills/pmx-canvas/references/installing-pmx-canvas.md +6 -6
  131. package/skills/pmx-canvas-testing/SKILL.md +5 -4
  132. package/src/cli/commands/copilot.ts +5 -0
  133. package/src/cli/commands/nodes.ts +3 -2
  134. package/src/cli/commands/view.ts +1 -1
  135. package/src/cli/index.ts +10 -4
  136. package/src/client/App.tsx +6 -1
  137. package/src/client/canvas/AgentPresenceLayer.tsx +3 -3
  138. package/src/client/canvas/AnnotationLayer.tsx +1 -1
  139. package/src/client/canvas/CanvasNode.tsx +32 -49
  140. package/src/client/canvas/CanvasViewport.tsx +0 -2
  141. package/src/client/canvas/CommandPalette.tsx +3 -2
  142. package/src/client/canvas/ContextMenu.tsx +11 -0
  143. package/src/client/canvas/EdgeLayer.tsx +1 -1
  144. package/src/client/canvas/ExportDialog.tsx +33 -6
  145. package/src/client/canvas/IntentLayer.tsx +2 -2
  146. package/src/client/canvas/Minimap.tsx +12 -7
  147. package/src/client/canvas/NodeContextMark.tsx +156 -0
  148. package/src/client/canvas/SessionPanel.tsx +4 -7
  149. package/src/client/canvas/SessionReceipt.tsx +114 -17
  150. package/src/client/canvas/ShortcutOverlay.tsx +6 -1
  151. package/src/client/canvas/SnapshotPanel.tsx +11 -2
  152. package/src/client/canvas/ToolRail.tsx +12 -9
  153. package/src/client/canvas/TopBar.tsx +16 -11
  154. package/src/client/icons.tsx +2 -12
  155. package/src/client/mcp-app/index.tsx +137 -0
  156. package/src/client/mcp-app/style.css +10 -0
  157. package/src/client/nodes/AttachmentNode.tsx +8 -1
  158. package/src/client/nodes/AxStepControls.tsx +1 -1
  159. package/src/client/nodes/ContextNode.tsx +9 -9
  160. package/src/client/nodes/ExtAppFrame.tsx +13 -8
  161. package/src/client/nodes/FileNode.tsx +8 -5
  162. package/src/client/nodes/HtmlNode.tsx +12 -2
  163. package/src/client/nodes/ImageNode.tsx +4 -2
  164. package/src/client/nodes/InlineMarkdownEditor.tsx +2 -1
  165. package/src/client/nodes/LedgerNode.tsx +2 -2
  166. package/src/client/nodes/MarkdownNode.tsx +44 -9
  167. package/src/client/nodes/McpAppNode.tsx +6 -4
  168. package/src/client/nodes/PromptNode.tsx +5 -17
  169. package/src/client/nodes/ResponseNode.tsx +3 -15
  170. package/src/client/nodes/StatusNode.tsx +2 -2
  171. package/src/client/nodes/StatusSummary.tsx +3 -1
  172. package/src/client/nodes/TraceNode.tsx +6 -4
  173. package/src/client/nodes/WebpageNode.tsx +1 -1
  174. package/src/client/nodes/ax-node-actions.ts +2 -2
  175. package/src/client/nodes/iframe-document-url.ts +3 -2
  176. package/src/client/nodes/markdown-sanitize.ts +10 -0
  177. package/src/client/nodes/surface-url.ts +10 -0
  178. package/src/client/nodes/use-surface-frame.ts +3 -1
  179. package/src/client/nodes/use-workbench-asset.ts +26 -0
  180. package/src/client/state/attention-bridge.ts +0 -8
  181. package/src/client/state/attention-store.ts +0 -17
  182. package/src/client/state/canvas-store.ts +4 -2
  183. package/src/client/state/context-status-store.ts +66 -0
  184. package/src/client/state/human-store.ts +2 -0
  185. package/src/client/state/iframe-mode.ts +5 -0
  186. package/src/client/state/intent-bridge.ts +10 -4
  187. package/src/client/state/near-pin-store.ts +53 -0
  188. package/src/client/state/presence-store.ts +5 -10
  189. package/src/client/state/session-store.ts +106 -9
  190. package/src/client/state/sse-bridge.ts +26 -7
  191. package/src/client/state/theme-override.ts +1 -1
  192. package/src/client/state/workbench-transport.ts +36 -0
  193. package/src/client/theme/global.css +726 -674
  194. package/src/client/theme/surface-theme.css +151 -46
  195. package/src/client/theme/tokens.ts +7 -11
  196. package/src/client/types.ts +10 -0
  197. package/src/json-render/renderer/index.css +6 -1
  198. package/src/json-render/renderer/index.tsx +0 -1
  199. package/src/json-render/server.ts +71 -14
  200. package/src/mcp/app-server.ts +64 -0
  201. package/src/mcp/canvas-access.ts +14 -11
  202. package/src/mcp/canvas-app.ts +318 -0
  203. package/src/mcp/server.ts +1 -1
  204. package/src/mcp/workbench-app.ts +211 -0
  205. package/src/server/agent-presence.ts +45 -6
  206. package/src/server/ax-context.ts +1 -1
  207. package/src/server/ax-state.ts +1 -1
  208. package/src/server/board-export.ts +5 -2
  209. package/src/server/canvas-db.ts +46 -12
  210. package/src/server/canvas-geometry.ts +64 -0
  211. package/src/server/canvas-operations.ts +7 -25
  212. package/src/server/canvas-state.ts +105 -15
  213. package/src/server/canvas-validation.ts +19 -4
  214. package/src/server/context-brief.ts +39 -2
  215. package/src/server/context-reads.ts +87 -15
  216. package/src/server/demo-state.json +31 -31
  217. package/src/server/html-surface.ts +4 -5
  218. package/src/server/index.ts +41 -5
  219. package/src/server/mcp-app-runtime.ts +11 -0
  220. package/src/server/operations/composites.ts +4 -3
  221. package/src/server/operations/http.ts +4 -4
  222. package/src/server/operations/invoker.ts +13 -4
  223. package/src/server/operations/mcp.ts +6 -0
  224. package/src/server/operations/ops/ax-read.ts +1 -1
  225. package/src/server/operations/ops/ax-timeline.ts +37 -0
  226. package/src/server/operations/ops/boards.ts +1 -1
  227. package/src/server/operations/ops/canvas-wire.ts +3 -6
  228. package/src/server/operations/ops/intent.ts +31 -2
  229. package/src/server/operations/ops/json-render.ts +6 -2
  230. package/src/server/operations/ops/nodes.ts +8 -76
  231. package/src/server/operations/ops/query.ts +8 -2
  232. package/src/server/operations/ops/snapshots.ts +4 -1
  233. package/src/server/operations/ops/viewport.ts +29 -5
  234. package/src/server/operations/registry.ts +41 -5
  235. package/src/server/scope-fence.ts +55 -10
  236. package/src/server/server.ts +83 -5
  237. package/src/server/spatial-analysis.ts +2 -2
  238. package/src/server/workboard.ts +6 -1
  239. package/src/{server → shared}/agent-context.ts +2 -2
  240. package/src/shared/agent-presence.ts +3 -15
  241. package/src/shared/canvas-app.ts +62 -0
  242. package/src/shared/themes.ts +5 -5
  243. package/src/client/canvas/FocusFieldLayer.tsx +0 -116
  244. package/src/client/canvas/kind-colors.ts +0 -23
@@ -0,0 +1,331 @@
1
+ @modelcontextprotocol/sdk@1.28.0
2
+
3
+ MIT License
4
+
5
+ Copyright (c) 2024 Anthropic, PBC
6
+
7
+ Permission is hereby granted, free of charge, to any person obtaining a copy
8
+ of this software and associated documentation files (the "Software"), to deal
9
+ in the Software without restriction, including without limitation the rights
10
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11
+ copies of the Software, and to permit persons to whom the Software is
12
+ furnished to do so, subject to the following conditions:
13
+
14
+ The above copyright notice and this permission notice shall be included in all
15
+ copies or substantial portions of the Software.
16
+
17
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23
+ SOFTWARE.
24
+
25
+
26
+ ---
27
+
28
+ ajv@8.18.0
29
+
30
+ The MIT License (MIT)
31
+
32
+ Copyright (c) 2015-2021 Evgeny Poberezkin
33
+
34
+ Permission is hereby granted, free of charge, to any person obtaining a copy
35
+ of this software and associated documentation files (the "Software"), to deal
36
+ in the Software without restriction, including without limitation the rights
37
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
38
+ copies of the Software, and to permit persons to whom the Software is
39
+ furnished to do so, subject to the following conditions:
40
+
41
+ The above copyright notice and this permission notice shall be included in all
42
+ copies or substantial portions of the Software.
43
+
44
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
45
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
46
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
47
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
48
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
49
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
50
+ SOFTWARE.
51
+
52
+
53
+
54
+ ---
55
+
56
+ ajv-formats@3.0.1
57
+
58
+ MIT License
59
+
60
+ Copyright (c) 2020 Evgeny Poberezkin
61
+
62
+ Permission is hereby granted, free of charge, to any person obtaining a copy
63
+ of this software and associated documentation files (the "Software"), to deal
64
+ in the Software without restriction, including without limitation the rights
65
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
66
+ copies of the Software, and to permit persons to whom the Software is
67
+ furnished to do so, subject to the following conditions:
68
+
69
+ The above copyright notice and this permission notice shall be included in all
70
+ copies or substantial portions of the Software.
71
+
72
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
73
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
74
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
75
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
76
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
77
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
78
+ SOFTWARE.
79
+
80
+
81
+ ---
82
+
83
+ cross-spawn@7.0.6
84
+
85
+ The MIT License (MIT)
86
+
87
+ Copyright (c) 2018 Made With MOXY Lda <hello@moxy.studio>
88
+
89
+ Permission is hereby granted, free of charge, to any person obtaining a copy
90
+ of this software and associated documentation files (the "Software"), to deal
91
+ in the Software without restriction, including without limitation the rights
92
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
93
+ copies of the Software, and to permit persons to whom the Software is
94
+ furnished to do so, subject to the following conditions:
95
+
96
+ The above copyright notice and this permission notice shall be included in
97
+ all copies or substantial portions of the Software.
98
+
99
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
100
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
101
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
102
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
103
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
104
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
105
+ THE SOFTWARE.
106
+
107
+
108
+ ---
109
+
110
+ fast-deep-equal@3.1.3
111
+
112
+ MIT License
113
+
114
+ Copyright (c) 2017 Evgeny Poberezkin
115
+
116
+ Permission is hereby granted, free of charge, to any person obtaining a copy
117
+ of this software and associated documentation files (the "Software"), to deal
118
+ in the Software without restriction, including without limitation the rights
119
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
120
+ copies of the Software, and to permit persons to whom the Software is
121
+ furnished to do so, subject to the following conditions:
122
+
123
+ The above copyright notice and this permission notice shall be included in all
124
+ copies or substantial portions of the Software.
125
+
126
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
127
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
128
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
129
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
130
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
131
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
132
+ SOFTWARE.
133
+
134
+
135
+ ---
136
+
137
+ fast-uri@3.1.0
138
+
139
+ Copyright (c) 2011-2021, Gary Court until https://github.com/garycourt/uri-js/commit/a1acf730b4bba3f1097c9f52e7d9d3aba8cdcaae
140
+ Copyright (c) 2021-present The Fastify team
141
+ All rights reserved.
142
+
143
+ The Fastify team members are listed at https://github.com/fastify/fastify#team.
144
+
145
+ Redistribution and use in source and binary forms, with or without
146
+ modification, are permitted provided that the following conditions are met:
147
+ * Redistributions of source code must retain the above copyright
148
+ notice, this list of conditions and the following disclaimer.
149
+ * Redistributions in binary form must reproduce the above copyright
150
+ notice, this list of conditions and the following disclaimer in the
151
+ documentation and/or other materials provided with the distribution.
152
+ * The names of any contributors may not be used to endorse or promote
153
+ products derived from this software without specific prior written
154
+ permission.
155
+
156
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
157
+ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
158
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
159
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY
160
+ DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
161
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
162
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
163
+ ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
164
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
165
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
166
+
167
+ * * *
168
+
169
+ The complete list of contributors can be found at:
170
+ - https://github.com/garycourt/uri-js/graphs/contributors
171
+
172
+ ---
173
+
174
+ isexe@2.0.0
175
+
176
+ The ISC License
177
+
178
+ Copyright (c) Isaac Z. Schlueter and Contributors
179
+
180
+ Permission to use, copy, modify, and/or distribute this software for any
181
+ purpose with or without fee is hereby granted, provided that the above
182
+ copyright notice and this permission notice appear in all copies.
183
+
184
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
185
+ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
186
+ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
187
+ ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
188
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
189
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
190
+ IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
191
+
192
+
193
+ ---
194
+
195
+ json-schema-traverse@1.0.0
196
+
197
+ MIT License
198
+
199
+ Copyright (c) 2017 Evgeny Poberezkin
200
+
201
+ Permission is hereby granted, free of charge, to any person obtaining a copy
202
+ of this software and associated documentation files (the "Software"), to deal
203
+ in the Software without restriction, including without limitation the rights
204
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
205
+ copies of the Software, and to permit persons to whom the Software is
206
+ furnished to do so, subject to the following conditions:
207
+
208
+ The above copyright notice and this permission notice shall be included in all
209
+ copies or substantial portions of the Software.
210
+
211
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
212
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
213
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
214
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
215
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
216
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
217
+ SOFTWARE.
218
+
219
+
220
+ ---
221
+
222
+ path-key@3.1.1
223
+
224
+ MIT License
225
+
226
+ Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (sindresorhus.com)
227
+
228
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
229
+
230
+ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
231
+
232
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
233
+
234
+
235
+ ---
236
+
237
+ shebang-command@2.0.0
238
+
239
+ MIT License
240
+
241
+ Copyright (c) Kevin Mårtensson <kevinmartensson@gmail.com> (github.com/kevva)
242
+
243
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
244
+
245
+ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
246
+
247
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
248
+
249
+
250
+ ---
251
+
252
+ shebang-regex@3.0.0
253
+
254
+ MIT License
255
+
256
+ Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (sindresorhus.com)
257
+
258
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
259
+
260
+ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
261
+
262
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
263
+
264
+
265
+ ---
266
+
267
+ which@2.0.2
268
+
269
+ The ISC License
270
+
271
+ Copyright (c) Isaac Z. Schlueter and Contributors
272
+
273
+ Permission to use, copy, modify, and/or distribute this software for any
274
+ purpose with or without fee is hereby granted, provided that the above
275
+ copyright notice and this permission notice appear in all copies.
276
+
277
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
278
+ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
279
+ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
280
+ ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
281
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
282
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
283
+ IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
284
+
285
+
286
+ ---
287
+
288
+ zod@4.3.6
289
+
290
+ MIT License
291
+
292
+ Copyright (c) 2025 Colin McDonnell
293
+
294
+ Permission is hereby granted, free of charge, to any person obtaining a copy
295
+ of this software and associated documentation files (the "Software"), to deal
296
+ in the Software without restriction, including without limitation the rights
297
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
298
+ copies of the Software, and to permit persons to whom the Software is
299
+ furnished to do so, subject to the following conditions:
300
+
301
+ The above copyright notice and this permission notice shall be included in all
302
+ copies or substantial portions of the Software.
303
+
304
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
305
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
306
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
307
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
308
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
309
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
310
+ SOFTWARE.
311
+
312
+
313
+ ---
314
+
315
+ zod-to-json-schema@3.25.1
316
+
317
+ ISC License
318
+
319
+ Copyright (c) 2020, Stefan Terdell
320
+
321
+ Permission to use, copy, modify, and/or distribute this software for any
322
+ purpose with or without fee is hereby granted, provided that the above
323
+ copyright notice and this permission notice appear in all copies.
324
+
325
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
326
+ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
327
+ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
328
+ ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
329
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
330
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
331
+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
@@ -1,63 +1,28 @@
1
- import { spawn } from "node:child_process";
2
1
  import { existsSync } from "node:fs";
3
2
  import { createServer as createHttpServer } from "node:http";
4
- import { createServer as createNetServer } from "node:net";
5
3
  import { dirname, resolve } from "node:path";
6
4
  import { fileURLToPath } from "node:url";
7
5
  import { CanvasError, createCanvas, joinSession } from "@github/copilot-sdk/extension";
8
6
  import { createSteeringDeliveryPump } from "./steering-delivery.mjs";
7
+ import { canonicalWorkspace, ensurePmxServer, explicitServerUrl, findPmxServer, preferredPort, runtimeCommand } from "./runtime.mjs";
9
8
 
10
9
  const EXTENSION_DIR = dirname(fileURLToPath(import.meta.url));
11
10
  const PROJECT_ROOT = resolve(EXTENSION_DIR, "../../..");
12
- const DEFAULT_PORT = 4313;
13
11
  const MAX_AX_CONTEXT_CHARS = 16_000;
14
- const MANAGED_START_TIMEOUT_MS = 10_000;
15
12
  const HEALTH_TIMEOUT_MS = 500;
16
13
  const STEERING_WAIT_MS = 30_000;
17
14
 
18
15
  let copilotSession;
19
16
  let steeringDeliveryPump;
20
- let managedProcess = null;
21
- let managedBaseUrl = null;
22
- let managedWorkspaceRoot = null;
23
- let managedPort = null;
24
- const managedLogs = [];
17
+ let sessionWorkspaceRoot = resolve(process.env.PMX_CANVAS_WORKSPACE_ROOT || process.cwd());
25
18
  const panelServers = new Map();
26
19
  // Canvas actions are invoked separately from `open`, and their context can
27
20
  // omit the canvas input. Keep the server selected for each visible instance so
28
21
  // an action cannot fall back to the process/default port behind the panel.
29
22
  const panelTargets = new Map();
30
23
 
31
- function normalizeBaseUrl(value) {
32
- if (typeof value !== "string" || value.trim() === "") return null;
33
- try {
34
- const url = new URL(value.trim());
35
- if (url.protocol !== "http:" && url.protocol !== "https:") return null;
36
- url.pathname = url.pathname.replace(/\/$/, "");
37
- url.search = "";
38
- url.hash = "";
39
- return url.toString().replace(/\/$/, "");
40
- } catch {
41
- return null;
42
- }
43
- }
44
-
45
- function normalizePort(value) {
46
- if (typeof value !== "string" && typeof value !== "number") return null;
47
- const parsed = Number(value);
48
- if (!Number.isFinite(parsed) || parsed <= 0) return null;
49
- return Math.floor(parsed);
50
- }
51
-
52
- function preferredPort(input) {
53
- return normalizePort(input?.port) ??
54
- normalizePort(process.env.PMX_CANVAS_PORT) ??
55
- normalizePort(process.env.PMX_WEB_CANVAS_PORT) ??
56
- DEFAULT_PORT;
57
- }
58
-
59
24
  function candidateBaseUrls(input) {
60
- const explicit = normalizeBaseUrl(input?.serverUrl) ?? normalizeBaseUrl(process.env.PMX_CANVAS_URL);
25
+ const explicit = explicitServerUrl(input);
61
26
  if (explicit) return [{ baseUrl: explicit, explicit: true }];
62
27
 
63
28
  const port = preferredPort(input);
@@ -70,13 +35,12 @@ function candidateBaseUrls(input) {
70
35
  function workspaceRootFrom(ctxOrInput) {
71
36
  const inputWorkspace = typeof ctxOrInput?.input?.workspaceRoot === "string" ? ctxOrInput.input.workspaceRoot : null;
72
37
  const sessionWorkspace = typeof ctxOrInput?.session?.workingDirectory === "string" ? ctxOrInput.session.workingDirectory : null;
73
- const currentWorkspace = typeof copilotSession?.workspacePath === "string" ? copilotSession.workspacePath : null;
74
- return resolve(inputWorkspace ?? sessionWorkspace ?? currentWorkspace ?? PROJECT_ROOT);
38
+ return resolve(inputWorkspace ?? sessionWorkspace ?? sessionWorkspaceRoot);
75
39
  }
76
40
 
77
41
  function workspaceMatches(health, workspaceRoot) {
78
42
  if (!health || typeof health.workspace !== "string") return false;
79
- return resolve(health.workspace) === resolve(workspaceRoot);
43
+ return canonicalWorkspace(health.workspace) === canonicalWorkspace(workspaceRoot);
80
44
  }
81
45
 
82
46
  function delay(ms) {
@@ -116,137 +80,24 @@ async function probeServer(baseUrl, workspaceRoot, options = {}) {
116
80
  }
117
81
  }
118
82
 
119
- async function isPortAvailable(port) {
120
- return await new Promise((resolveAvailable) => {
121
- const server = createNetServer();
122
- server.once("error", () => resolveAvailable(false));
123
- server.once("listening", () => {
124
- server.close(() => resolveAvailable(true));
125
- });
126
- server.listen(port, "127.0.0.1");
127
- });
128
- }
129
-
130
- async function pickManagedPort(startPort) {
131
- for (let port = startPort; port < startPort + 20; port += 1) {
132
- if (await isPortAvailable(port)) return port;
133
- }
134
- throw new Error(`No available PMX Canvas port found near ${startPort}`);
135
- }
136
-
137
- function captureManagedLog(chunk) {
138
- const text = chunk.toString("utf8").trim();
139
- if (!text) return;
140
- managedLogs.push(text);
141
- while (managedLogs.length > 20) managedLogs.shift();
142
- }
143
-
144
- function stopManagedServer() {
145
- if (managedProcess && managedProcess.exitCode === null && !managedProcess.killed) {
146
- managedProcess.kill("SIGTERM");
147
- }
148
- managedProcess = null;
149
- managedBaseUrl = null;
150
- managedWorkspaceRoot = null;
151
- managedPort = null;
152
- }
153
-
154
- function managedCommand(workspaceRoot, port) {
83
+ function managedCommand(workspaceRoot) {
155
84
  const sourceEntry = resolve(workspaceRoot, "src/cli/index.ts");
156
- const localBin = resolve(workspaceRoot, "node_modules/.bin/pmx-canvas");
157
- if (existsSync(sourceEntry)) {
85
+ if (workspaceRoot === PROJECT_ROOT && existsSync(sourceEntry)) {
158
86
  return {
159
87
  command: "bun",
160
- args: ["run", "src/cli/index.ts", "--no-open", `--port=${port}`],
161
- };
162
- }
163
- if (existsSync(localBin)) {
164
- return {
165
- command: localBin,
166
- args: ["--no-open", `--port=${port}`],
88
+ args: ["run", sourceEntry],
167
89
  };
168
90
  }
169
- return {
170
- command: "pmx-canvas",
171
- args: ["--no-open", `--port=${port}`],
172
- };
173
- }
174
-
175
- async function startManagedServer(workspaceRoot, input) {
176
- if (managedProcess && managedBaseUrl && managedWorkspaceRoot === workspaceRoot) {
177
- const probe = await probeServer(managedBaseUrl, workspaceRoot, { allowWorkspaceMismatch: false });
178
- if (probe.ok) return probe;
179
- }
180
-
181
- stopManagedServer();
182
- const port = await pickManagedPort(preferredPort(input));
183
- const baseUrl = `http://127.0.0.1:${port}`;
184
- const managed = managedCommand(workspaceRoot, port);
185
- let managedError = null;
186
- managedLogs.length = 0;
187
- managedProcess = spawn(managed.command, managed.args, {
188
- cwd: workspaceRoot,
189
- env: {
190
- ...process.env,
191
- PMX_CANVAS_DISABLE_BROWSER_OPEN: "1",
192
- PMX_WEB_CANVAS_PORT: String(port),
193
- },
194
- stdio: ["ignore", "pipe", "pipe"],
195
- });
196
- managedBaseUrl = baseUrl;
197
- managedWorkspaceRoot = workspaceRoot;
198
- managedPort = port;
199
- managedProcess.stdout?.on("data", captureManagedLog);
200
- managedProcess.stderr?.on("data", captureManagedLog);
201
- managedProcess.once("error", (error) => {
202
- managedError = error;
203
- captureManagedLog(Buffer.from(error.message));
204
- });
205
- managedProcess.once("exit", () => {
206
- managedProcess = null;
207
- managedBaseUrl = null;
208
- managedWorkspaceRoot = null;
209
- managedPort = null;
210
- });
211
-
212
- const startedAt = Date.now();
213
- while (Date.now() - startedAt < MANAGED_START_TIMEOUT_MS) {
214
- const probe = await probeServer(baseUrl, workspaceRoot, {
215
- allowWorkspaceMismatch: false,
216
- timeoutMs: HEALTH_TIMEOUT_MS,
217
- });
218
- if (probe.ok) return probe;
219
- if (managedError) throw managedError;
220
- if (!managedProcess || managedProcess.exitCode !== null) break;
221
- await delay(250);
222
- }
223
-
224
- const tail = managedLogs.slice(-4).join("\n");
225
- throw new Error(`PMX Canvas did not become healthy on port ${port}.${tail ? `\n${tail}` : ""}`);
91
+ return runtimeCommand();
226
92
  }
227
93
 
228
94
  async function resolvePmxServer(ctxOrInput, options = {}) {
229
95
  const workspaceRoot = workspaceRootFrom(ctxOrInput);
230
96
  const input = ctxOrInput?.input ?? ctxOrInput ?? {};
231
- const allowWorkspaceMismatch = input?.allowWorkspaceMismatch === true;
232
- for (const candidate of candidateBaseUrls(input)) {
233
- const probe = await probeServer(candidate.baseUrl, workspaceRoot, {
234
- allowWorkspaceMismatch,
235
- });
236
- if (probe.ok) return probe;
237
- }
238
-
239
97
  if (options.autoStart === false || input?.autoStart === false) {
240
- return {
241
- ok: false,
242
- baseUrl: null,
243
- health: null,
244
- workspaceOk: false,
245
- error: "No matching PMX Canvas server is running.",
246
- };
98
+ return await findPmxServer(workspaceRoot, input);
247
99
  }
248
-
249
- return await startManagedServer(workspaceRoot, input);
100
+ return await ensurePmxServer(workspaceRoot, input, managedCommand(workspaceRoot));
250
101
  }
251
102
 
252
103
  async function resolvePanelTarget(ctx, options = {}) {
@@ -372,7 +223,7 @@ function renderShell(entry) {
372
223
  if (response.ok && target.ok && target.baseUrl) {
373
224
  // Load the real workbench at its own origin, including its token,
374
225
  // Home, boards, and relative API paths. The shell is not a proxy.
375
- window.location.replace(target.baseUrl + '/workbench?theme=light');
226
+ window.location.replace(target.baseUrl + '/workbench?theme=daylight');
376
227
  return;
377
228
  }
378
229
  status.textContent = target.error || 'No matching PMX Canvas server is running.';
@@ -627,7 +478,7 @@ async function postPresence(workspaceRoot, payload, options = {}) {
627
478
  async function getCopilotPresence() {
628
479
  try {
629
480
  const resolved = await resolvePmxServer(
630
- { input: {}, session: { workingDirectory: PROJECT_ROOT } },
481
+ { input: {}, session: { workingDirectory: sessionWorkspaceRoot } },
631
482
  { autoStart: false },
632
483
  );
633
484
  if (!resolved.ok || !resolved.baseUrl) return null;
@@ -652,7 +503,7 @@ function recordCopilotSteering(ctx, message) {
652
503
  }
653
504
 
654
505
  async function claimCopilotSteering(consumer) {
655
- const workspaceRoot = PROJECT_ROOT;
506
+ const workspaceRoot = sessionWorkspaceRoot;
656
507
  const resolved = await resolvePmxServer(
657
508
  { input: {}, session: { workingDirectory: workspaceRoot } },
658
509
  { autoStart: false },
@@ -669,7 +520,7 @@ async function claimCopilotSteering(consumer) {
669
520
  }
670
521
 
671
522
  async function markCopilotSteering(id, consumer) {
672
- const workspaceRoot = PROJECT_ROOT;
523
+ const workspaceRoot = sessionWorkspaceRoot;
673
524
  const resolved = await resolvePmxServer(
674
525
  { input: {}, session: { workingDirectory: workspaceRoot } },
675
526
  { autoStart: false },
@@ -962,7 +813,7 @@ const pmxCanvas = createCanvas({
962
813
  return {
963
814
  title: "PMX Canvas",
964
815
  status: "Connected",
965
- url: `${pmx.baseUrl}/workbench?theme=light`,
816
+ url: `${pmx.baseUrl}/workbench?theme=daylight`,
966
817
  };
967
818
  }
968
819
 
@@ -995,7 +846,8 @@ copilotSession = await joinSession({
995
846
  canvases: [pmxCanvas],
996
847
  hooks: {
997
848
  onUserPromptSubmitted: async (input) => {
998
- const workspaceRoot = resolve(input?.workingDirectory ?? copilotSession?.workspacePath ?? PROJECT_ROOT);
849
+ const workspaceRoot = resolve(input?.workingDirectory ?? sessionWorkspaceRoot);
850
+ sessionWorkspaceRoot = workspaceRoot;
999
851
  // A submitted prompt means the agent is about to think: attach (idempotent)
1000
852
  // and flip the phase. The agent's subsequent canvas writes reach the server
1001
853
  // as MCP/HTTP tool calls and are attributed to this session.
@@ -1010,13 +862,15 @@ copilotSession = await joinSession({
1010
862
  },
1011
863
  });
1012
864
 
865
+ sessionWorkspaceRoot = resolve((await copilotSession.rpc.metadata.snapshot()).workingDirectory);
866
+
1013
867
  steeringDeliveryPump = createSteeringDeliveryPump({
1014
868
  consumer: "copilot",
1015
869
  claim: claimCopilotSteering,
1016
870
  send: async (message) => await copilotSession.send({ prompt: message }),
1017
871
  mark: markCopilotSteering,
1018
872
  getPresence: getCopilotPresence,
1019
- setPresence: async (patch) => await postPresence(PROJECT_ROOT, patch),
873
+ setPresence: async (patch) => await postPresence(sessionWorkspaceRoot, patch),
1020
874
  shouldSend: (() => {
1021
875
  const startedAt = Date.now();
1022
876
  return (steering) => Date.parse(steering.createdAt) >= startedAt;
@@ -1028,7 +882,7 @@ void steeringDeliveryPump.start();
1028
882
 
1029
883
  // Attach the session as soon as the host joins (the canvas may not be running
1030
884
  // yet — the prompt hook above re-attaches lazily in that case).
1031
- void postPresence(resolve(copilotSession?.workspacePath ?? PROJECT_ROOT), { attached: true });
885
+ void postPresence(sessionWorkspaceRoot, { attached: true });
1032
886
 
1033
887
  // Real context window (rail-chrome-v2): Copilot emits `session.usage_info`
1034
888
  // with the live token count and the model's window after each turn. Report it
@@ -1049,7 +903,7 @@ function reportContextUsage(event) {
1049
903
  usageFlush = null;
1050
904
  const usage = pendingUsage;
1051
905
  pendingUsage = null;
1052
- if (usage) void postPresence(resolve(copilotSession?.workspacePath ?? PROJECT_ROOT), { contextUsage: usage });
906
+ if (usage) void postPresence(sessionWorkspaceRoot, { contextUsage: usage });
1053
907
  }, 500);
1054
908
  }
1055
909
  if (typeof copilotSession?.on === "function") {
@@ -1063,14 +917,13 @@ if (typeof copilotSession?.on === "function") {
1063
917
  async function shutdown() {
1064
918
  steeringDeliveryPump?.stop();
1065
919
  // Detach the presence first so the canvas returns to the quiet board the
1066
- // moment the host goes away, then stop any managed server. The whole
920
+ // moment the host goes away. The shared daemon belongs to the workspace. The whole
1067
921
  // detach is capped at 800ms (server probing + the POST) so a host with a
1068
922
  // short SIGTERM grace window can never be held past it.
1069
923
  await Promise.race([
1070
- postPresence(resolve(copilotSession?.workspacePath ?? PROJECT_ROOT), { attached: false }, { timeoutMs: 500 }),
924
+ postPresence(sessionWorkspaceRoot, { attached: false }, { timeoutMs: 500 }),
1071
925
  delay(800),
1072
926
  ]);
1073
- stopManagedServer();
1074
927
  process.exit(0);
1075
928
  }
1076
929
  process.once("SIGTERM", () => void shutdown());