@chengxianglibra/dsh-data-analysis 0.3.0 → 0.3.1
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.
- package/README.en.md +7 -2
- package/README.md +7 -2
- package/assets/logo-horizontal.svg +42 -0
- package/assets/logo-mark.svg +20 -0
- package/lib/bin/environment.js +99 -76
- package/lib/client/analysis-ui/offline-runtime.generated.js +1 -1
- package/lib/client/credentials/install.js +42 -38
- package/lib/client/credentials/model.js +9 -0
- package/lib/client/credentials/report-publishing.js +84 -0
- package/lib/client/credentials/styles.js +2 -0
- package/lib/client/i18n/credentials.js +18 -0
- package/lib/client/i18n/presentation.js +24 -0
- package/lib/client/right-tabs/install.js +9 -1
- package/lib/client/right-tabs/report-actions.js +30 -4
- package/lib/client/right-tabs/report-publishing.js +107 -0
- package/lib/client/right-tabs/styles.js +3 -0
- package/lib/client/ui/styles.generated.js +3 -0
- package/lib/client-composition.js +202 -191
- package/lib/client.js +205 -194
- package/lib/datasource/resolver-program.js +4 -4
- package/lib/environment/binding.js +16 -23
- package/lib/environment/doctor.js +8 -1
- package/lib/environment/identity.js +32 -0
- package/lib/environment/project-preparation.js +5 -5
- package/lib/environment/runtime.js +15 -16
- package/lib/plugin-agents.js +6 -1
- package/lib/plugin.js +18 -0
- package/lib/presentation/rpc.js +19 -0
- package/lib/report-publishing/adapters.js +136 -0
- package/lib/report-publishing/config.js +58 -0
- package/lib/report-publishing/credential-contract.js +25 -0
- package/lib/report-publishing/service.js +133 -0
- package/lib/skill-build.generated.js +2 -2
- package/lib/types/client/credentials/install.d.ts +2 -1
- package/lib/types/client/credentials/model.d.ts +30 -0
- package/lib/types/client/credentials/report-publishing.d.ts +5 -0
- package/lib/types/client/credentials/styles.d.ts +1 -1
- package/lib/types/client/i18n/copy.d.ts +21 -0
- package/lib/types/client/i18n/credentials.d.ts +18 -0
- package/lib/types/client/i18n/presentation.d.ts +24 -0
- package/lib/types/client/right-tabs/report-actions.d.ts +5 -1
- package/lib/types/client/right-tabs/report-publishing.d.ts +21 -0
- package/lib/types/client/right-tabs/styles.d.ts +1 -1
- package/lib/types/environment/identity.d.ts +6 -0
- package/lib/types/plugin-agents.d.ts +2 -0
- package/lib/types/plugin.d.ts +4 -0
- package/lib/types/presentation/rpc.d.ts +1358 -0
- package/lib/types/report-publishing/adapters.d.ts +6 -0
- package/lib/types/report-publishing/config.d.ts +23 -0
- package/lib/types/report-publishing/credential-contract.d.ts +61 -0
- package/lib/types/report-publishing/service.d.ts +31 -0
- package/package.json +4 -1
- package/skills/dsh-data-analysis-files/references/delivery.md +3 -1
package/README.en.md
CHANGED
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
<p align="center">
|
|
2
|
+
<img src="assets/logo-horizontal.svg" alt="DSH Data Analysis" width="520">
|
|
3
|
+
</p>
|
|
4
|
+
|
|
1
5
|
# @chengxianglibra/dsh-data-analysis
|
|
2
6
|
|
|
3
7
|
[简体中文](README.md) | English
|
|
@@ -115,14 +119,15 @@ Analysis views use `marivo_report_write` to present conclusions, charts, exact v
|
|
|
115
119
|
- **Ask a follow-up**: Select a chart point or supported cell in a DataFrame or Frame and add it to the question draft.
|
|
116
120
|
- **Read the view**: The first preview in the foreground session opens and selects a right-hand tab. Reopen it from Chat after closing it; later updates do not repeatedly open the tab. Catalog and history entries also open on the right.
|
|
117
121
|
- **Suggested next steps**: After analysis, Chat offers a row of temporary follow-up buttons. Clicking uses the native Harness composer to submit the question; existing drafts are preserved. Suggestions stay in Chat and disappear on reload, reconnection or session switch.
|
|
118
|
-
- **Export offline**:
|
|
122
|
+
- **Export offline**: With object storage publishing disabled, download the displayed version as a single HTML file from the actions menu. It includes the saved snapshots and supports offline viewing and local interactions; review its data before sharing.
|
|
123
|
+
- **Publish to object storage**: With `reportPublishing` enabled in the Harness plugin configuration, choose Publish to object storage in the actions menu to upload the displayed saved version and get its URL. The menu links to Credential management if credentials are missing. The assistant can also publish an exact saved version with `marivo_publish_report`.
|
|
119
124
|
- **Delete a view**: Confirm deletion in the analysis view tab’s actions menu to permanently remove the view and all its historical versions, or ask the assistant to delete a saved view. Exported HTML and Marivo results are retained.
|
|
120
125
|
|
|
121
126
|
Initial previews, revisions and final saving update the same analysis view. Subtle chart motion indicates generation and updates, then stops after saving; reduced motion preferences use a static indicator. When analysis is ongoing, the assistant shows a draft early, updates it as results become ready, and saves one version at completion. Native generation also displays program candidates. Failures and cancellation preserve the last successful content. When refreshing a saved view, the assistant retains its layout, components and body while replacing component data sources. Static text is preserved, and the layout within an auto chart may adapt to the data. Refresh rejects changes to the chart type.
|
|
122
127
|
|
|
123
128
|
Analysis views support tables, complete single values, Native generation previews, and updates to an exact saved version.
|
|
124
129
|
Updates reuse saved snapshots; failures and cancellation preserve the previous successful version.
|
|
125
|
-
Frame views support charts selected from their structure. Analysis views do not provide global filters
|
|
130
|
+
Frame views support charts selected from their structure. Analysis views do not provide global filters or in-page editing.
|
|
126
131
|
View history requires current v4 pointers, but the saved Catalog build need not match the current one. The current reader validates report contents and reports unsupported content as an error. Successful reading does not guarantee that component defaults or rendering semantics match the original version. Current v2/v3 pointers (including earlier saved views) and Frame v1 are no longer readable or updatable. Files stay on disk; capture a current snapshot and create a new analysis view to continue.
|
|
127
132
|
|
|
128
133
|
## Analysis timeout
|
package/README.md
CHANGED
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
<p align="center">
|
|
2
|
+
<img src="assets/logo-horizontal.svg" alt="DSH Data Analysis" width="520">
|
|
3
|
+
</p>
|
|
4
|
+
|
|
1
5
|
# @chengxianglibra/dsh-data-analysis
|
|
2
6
|
|
|
3
7
|
简体中文 | [English](README.en.md)
|
|
@@ -112,13 +116,14 @@ npx @deepseek-ai/dsh web
|
|
|
112
116
|
- **继续提问**:在 DataFrame 或 Frame 中选择图点或支持的单元格后,将选中数据加入提问草稿。
|
|
113
117
|
- **阅读视图**:前台会话首次展示视图时自动打开并选中右侧标签页。关闭后可从 Chat 入口重开;后续更新不会反复打开标签页。分析视图目录及历史入口也在右侧打开。
|
|
114
118
|
- **下一步推荐**:分析完成后,Chat 中提供一排临时推荐按钮。点击会使用 Harness 原生输入框直接提交对应问题;已有草稿时不会覆盖。推荐保留在 Chat,刷新、重连或切换会话后清除。
|
|
115
|
-
-
|
|
119
|
+
- **离线导出**:关闭对象存储发布时,可通过三点菜单下载当前显示版本的单个 HTML,文件包含已保存快照,可离线查看并使用本地交互;分享前请确认其中的数据。
|
|
120
|
+
- **发布到对象存储**:在 Harness 插件配置中开启 `reportPublishing` 后,三点菜单显示「发布到对象存储」,可上传当前显示的已保存版本并获取访问链接。缺凭据时可直接前往「凭证管理」。也可让助手通过 `marivo_publish_report` 发布指定版本。
|
|
116
121
|
- **删除视图**:在分析视图标签页的操作菜单中确认删除,永久移除该视图及其历史版本;也可让助手删除已保存的视图。已导出的 HTML 和 Marivo 结果不随视图删除。
|
|
117
122
|
|
|
118
123
|
首次预览、后续修订和正式保存始终更新同一个分析视图,用轻量图表动效显示生成与更新进度,保存后停止;开启“减少动态效果”时静态显示。需要持续计算时,助手会尽早展示草稿,并在结果就绪时更新同一草稿,完成后统一保存一个正式版本。Native 生成期间还会展示程序候选;生成失败或取消保留最后成功内容。刷新已保存视图的数据时,助手保留布局、组件和正文,逐组件替换数据源;静态正文保留原文,auto 图形内部布局可随数据变化。刷新会拒绝图表类型变化。
|
|
119
124
|
|
|
120
125
|
分析视图支持表格、完整单值、Native 生成期预览和按准确版本的增量更新。更新复用已保存快照,
|
|
121
|
-
失败或取消保留上一成功版本。Frame
|
|
126
|
+
失败或取消保留上一成功版本。Frame 视图支持按结构选择图表;分析视图不提供全局筛选或页面编辑。视图历史要求 current v4 指针,但不要求保存的 Catalog build 与当前版本相同;当前 reader 会校验报告内容,无法支持时明确报错。可读取不保证组件的默认值或渲染语义与保存时完全一致。current v2/v3(包括此前保存的新格式视图)和 Frame v1 不再读取或更新。文件保留在磁盘,需要继续使用时捕获当前快照并另建分析视图。
|
|
122
127
|
|
|
123
128
|
## 分析超时设置
|
|
124
129
|
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="1460" height="360" viewBox="0 0 1460 360" role="img" aria-labelledby="logo-title logo-desc">
|
|
2
|
+
<title id="logo-title">dsh-data-analysis</title>
|
|
3
|
+
<desc id="logo-desc">A black sea lion with a green M, followed by the words dsh-data-analysis.</desc>
|
|
4
|
+
<!-- Wordmark outlines use Montserrat Medium, Copyright 2024 The Montserrat Project Authors, SIL Open Font License 1.1. -->
|
|
5
|
+
<svg x="0" y="0" width="360" height="360" viewBox="0 0 512 512" aria-hidden="true">
|
|
6
|
+
<defs>
|
|
7
|
+
<mask id="face-cutouts" maskUnits="userSpaceOnUse" x="0" y="0" width="512" height="512">
|
|
8
|
+
<rect width="512" height="512" fill="#fff"/>
|
|
9
|
+
<ellipse cx="214" cy="112" rx="7" ry="9" fill="#000"/>
|
|
10
|
+
<ellipse cx="298" cy="112" rx="7" ry="9" fill="#000"/>
|
|
11
|
+
<ellipse cx="256" cy="149" rx="41" ry="33" fill="#000"/>
|
|
12
|
+
<g fill="none" stroke="#000" stroke-width="4.5" stroke-linecap="round">
|
|
13
|
+
<path d="M220 138c-11 0-21 2-30 6m30 4c-11 1-21 5-29 11"/>
|
|
14
|
+
<path d="M292 138c11 0 21 2 30 6m-30 4c11 1 21 5 29 11"/>
|
|
15
|
+
</g>
|
|
16
|
+
</mask>
|
|
17
|
+
</defs>
|
|
18
|
+
<path d="M256 62c-31 0-55 14-69 42-14 0-24 7-26 15-2 8 7 12 15 5-4 16-4 32-3 48 3 43-49 111-49 185 0 34-4 44-19 54-14 9-49 19-58 32-12 17 13 15 42 14 56-1 73-11 79-25 6-15 8-38 0-89 22 31 22 74 10 94 19 6 43 9 78 9s59-3 78-9c-12-20-12-63 10-94-8 51-6 74 0 89 6 14 23 24 79 25 29 1 54 3 42-14-9-13-44-23-58-32-15-10-19-20-19-54 0-74-52-142-49-185 1-16 1-32-3-48 8 7 17 3 15-5-2-8-12-15-26-15-14-28-38-42-69-42Z" fill="#111" mask="url(#face-cutouts)"/>
|
|
19
|
+
<path d="M241 129c0-5 7-7 15-7s15 2 15 7c0 4-5 6-9 9-3 2-4 5-6 5s-3-3-6-5c-4-3-9-5-9-9Z" fill="#111"/>
|
|
20
|
+
<path d="M256 141c-1 10-6 16-13 17-6 1-11-1-15-5m28-12c1 10 6 16 13 17 6 1 11-1 15-5" fill="none" stroke="#111" stroke-width="5" stroke-linecap="round"/>
|
|
21
|
+
<path d="M210 322v-72h19l27 32 27-32h19v72h-20v-42l-26 31-26-31v42Z" fill="#138462"/>
|
|
22
|
+
</svg>
|
|
23
|
+
<g fill="#111" transform="translate(365 214) scale(0.12 -0.12)" aria-hidden="true">
|
|
24
|
+
<path d="M310 -6Q233 -6 172.5 28Q112 62 77 123Q42 184 42 265Q42 346 77 406.5Q112 467 172.5 501Q233 535 310 535Q377 535 431 505Q485 475 517.5 415Q550 355 550 265Q550 175 518.5 115Q487 55 433 24.5Q379 -6 310 -6ZM318 78Q368 78 408.5 101Q449 124 472.5 166.5Q496 209 496 265Q496 322 472.5 363.5Q449 405 408.5 428Q368 451 318 451Q267 451 227 428Q187 405 163 363.5Q139 322 139 265Q139 209 163 166.5Q187 124 227 101Q267 78 318 78ZM499 0L499 143L505 266L495 389L495 742L591 742L591 0Z" transform="translate(0 0)"/>
|
|
25
|
+
<path d="M243 -6Q177 -6 117.5 12Q58 30 24 56L64 132Q98 109 148 93Q198 77 250 77Q317 77 346.5 96Q376 115 376 149Q376 174 358 188Q340 202 310.5 209Q281 216 245 221.5Q209 227 173 235.5Q137 244 107 259.5Q77 275 59 302.5Q41 330 41 376Q41 424 68 460Q95 496 144.5 515.5Q194 535 262 535Q314 535 367.5 522.5Q421 510 455 487L414 411Q378 435 339 444Q300 453 261 453Q198 453 167 432.5Q136 412 136 380Q136 353 154.5 338.5Q173 324 202.5 316Q232 308 268 302.5Q304 297 340 288.5Q376 280 405.5 265Q435 250 453.5 223Q472 196 472 151Q472 103 444 68Q416 33 365 13.5Q314 -6 243 -6Z" transform="translate(682 0)"/>
|
|
26
|
+
<path d="M91 0L91 742L187 742L187 387L168 425Q194 477 248 506Q302 535 374 535Q439 535 488.5 510Q538 485 566 434Q594 383 594 305L594 0L498 0L498 294Q498 371 460.5 410Q423 449 355 449Q304 449 266 429Q228 409 207.5 370Q187 331 187 273L187 0Z" transform="translate(1183 0)"/>
|
|
27
|
+
<path d="M57 233L57 316L326 316L326 233Z" transform="translate(1864 0)"/>
|
|
28
|
+
<path d="M310 -6Q233 -6 172.5 28Q112 62 77 123Q42 184 42 265Q42 346 77 406.5Q112 467 172.5 501Q233 535 310 535Q377 535 431 505Q485 475 517.5 415Q550 355 550 265Q550 175 518.5 115Q487 55 433 24.5Q379 -6 310 -6ZM318 78Q368 78 408.5 101Q449 124 472.5 166.5Q496 209 496 265Q496 322 472.5 363.5Q449 405 408.5 428Q368 451 318 451Q267 451 227 428Q187 405 163 363.5Q139 322 139 265Q139 209 163 166.5Q187 124 227 101Q267 78 318 78ZM499 0L499 143L505 266L495 389L495 742L591 742L591 0Z" transform="translate(2257 0)"/>
|
|
29
|
+
<path d="M420 0L420 112L415 133L415 324Q415 385 379.5 418.5Q344 452 273 452Q226 452 181 436.5Q136 421 105 395L65 467Q106 500 163.5 517.5Q221 535 284 535Q393 535 452 482Q511 429 511 320L511 0ZM246 -6Q187 -6 142.5 14Q98 34 74 69.5Q50 105 50 150Q50 193 70.5 228Q91 263 137.5 284Q184 305 263 305L431 305L431 236L267 236Q195 236 170 212Q145 188 145 154Q145 115 176 91.5Q207 68 262 68Q316 68 356.5 92Q397 116 415 162L434 96Q415 49 367 21.5Q319 -6 246 -6Z" transform="translate(2939 0)"/>
|
|
30
|
+
<path d="M273 -6Q193 -6 149 37Q105 80 105 160L105 646L201 646L201 164Q201 121 222.5 98Q244 75 284 75Q329 75 359 100L389 31Q367 12 336.5 3Q306 -6 273 -6ZM15 451L15 530L353 530L353 451Z" transform="translate(3537 0)"/>
|
|
31
|
+
<path d="M420 0L420 112L415 133L415 324Q415 385 379.5 418.5Q344 452 273 452Q226 452 181 436.5Q136 421 105 395L65 467Q106 500 163.5 517.5Q221 535 284 535Q393 535 452 482Q511 429 511 320L511 0ZM246 -6Q187 -6 142.5 14Q98 34 74 69.5Q50 105 50 150Q50 193 70.5 228Q91 263 137.5 284Q184 305 263 305L431 305L431 236L267 236Q195 236 170 212Q145 188 145 154Q145 115 176 91.5Q207 68 262 68Q316 68 356.5 92Q397 116 415 162L434 96Q415 49 367 21.5Q319 -6 246 -6Z" transform="translate(3931 0)"/>
|
|
32
|
+
<path d="M57 233L57 316L326 316L326 233Z" transform="translate(4529 0)"/>
|
|
33
|
+
<path d="M420 0L420 112L415 133L415 324Q415 385 379.5 418.5Q344 452 273 452Q226 452 181 436.5Q136 421 105 395L65 467Q106 500 163.5 517.5Q221 535 284 535Q393 535 452 482Q511 429 511 320L511 0ZM246 -6Q187 -6 142.5 14Q98 34 74 69.5Q50 105 50 150Q50 193 70.5 228Q91 263 137.5 284Q184 305 263 305L431 305L431 236L267 236Q195 236 170 212Q145 188 145 154Q145 115 176 91.5Q207 68 262 68Q316 68 356.5 92Q397 116 415 162L434 96Q415 49 367 21.5Q319 -6 246 -6Z" transform="translate(4912 0)"/>
|
|
34
|
+
<path d="M91 0L91 530L183 530L183 387L168 425Q194 477 248 506Q302 535 374 535Q439 535 488.5 510Q538 485 566 434Q594 383 594 305L594 0L498 0L498 294Q498 371 460.5 410Q423 449 355 449Q304 449 266 429Q228 409 207.5 370Q187 331 187 273L187 0Z" transform="translate(5510 0)"/>
|
|
35
|
+
<path d="M420 0L420 112L415 133L415 324Q415 385 379.5 418.5Q344 452 273 452Q226 452 181 436.5Q136 421 105 395L65 467Q106 500 163.5 517.5Q221 535 284 535Q393 535 452 482Q511 429 511 320L511 0ZM246 -6Q187 -6 142.5 14Q98 34 74 69.5Q50 105 50 150Q50 193 70.5 228Q91 263 137.5 284Q184 305 263 305L431 305L431 236L267 236Q195 236 170 212Q145 188 145 154Q145 115 176 91.5Q207 68 262 68Q316 68 356.5 92Q397 116 415 162L434 96Q415 49 367 21.5Q319 -6 246 -6Z" transform="translate(6191 0)"/>
|
|
36
|
+
<path d="M91 0L91 742L187 742L187 0Z" transform="translate(6789 0)"/>
|
|
37
|
+
<path d="M114 -200Q76 -200 40 -187.5Q4 -175 -22 -151L19 -79Q39 -98 63 -108Q87 -118 114 -118Q149 -118 172 -100Q195 -82 215 -36L248 37L258 49L466 530L560 530L303 -53Q280 -109 251.5 -141Q223 -173 189 -186.5Q155 -200 114 -200ZM240 -17L-2 530L98 530L304 58Z" transform="translate(7066 0)"/>
|
|
38
|
+
<path d="M243 -6Q177 -6 117.5 12Q58 30 24 56L64 132Q98 109 148 93Q198 77 250 77Q317 77 346.5 96Q376 115 376 149Q376 174 358 188Q340 202 310.5 209Q281 216 245 221.5Q209 227 173 235.5Q137 244 107 259.5Q77 275 59 302.5Q41 330 41 376Q41 424 68 460Q95 496 144.5 515.5Q194 535 262 535Q314 535 367.5 522.5Q421 510 455 487L414 411Q378 435 339 444Q300 453 261 453Q198 453 167 432.5Q136 412 136 380Q136 353 154.5 338.5Q173 324 202.5 316Q232 308 268 302.5Q304 297 340 288.5Q376 280 405.5 265Q435 250 453.5 223Q472 196 472 151Q472 103 444 68Q416 33 365 13.5Q314 -6 243 -6Z" transform="translate(7618 0)"/>
|
|
39
|
+
<path d="M91 0L91 530L187 530L187 0ZM139 632Q111 632 92.5 650Q74 668 74 694Q74 721 92.5 739Q111 757 139 757Q167 757 185.5 739.5Q204 722 204 696Q204 669 186 650.5Q168 632 139 632Z" transform="translate(8119 0)"/>
|
|
40
|
+
<path d="M243 -6Q177 -6 117.5 12Q58 30 24 56L64 132Q98 109 148 93Q198 77 250 77Q317 77 346.5 96Q376 115 376 149Q376 174 358 188Q340 202 310.5 209Q281 216 245 221.5Q209 227 173 235.5Q137 244 107 259.5Q77 275 59 302.5Q41 330 41 376Q41 424 68 460Q95 496 144.5 515.5Q194 535 262 535Q314 535 367.5 522.5Q421 510 455 487L414 411Q378 435 339 444Q300 453 261 453Q198 453 167 432.5Q136 412 136 380Q136 353 154.5 338.5Q173 324 202.5 316Q232 308 268 302.5Q304 297 340 288.5Q376 280 405.5 265Q435 250 453.5 223Q472 196 472 151Q472 103 444 68Q416 33 365 13.5Q314 -6 243 -6Z" transform="translate(8398 0)"/>
|
|
41
|
+
</g>
|
|
42
|
+
</svg>
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="512" height="512" viewBox="0 0 512 512" role="img" aria-labelledby="title desc">
|
|
2
|
+
<title id="title">DSH Data Analysis</title>
|
|
3
|
+
<desc id="desc">A front-facing black sea lion silhouette with a green M on its chest.</desc>
|
|
4
|
+
<defs>
|
|
5
|
+
<mask id="face-cutouts" maskUnits="userSpaceOnUse" x="0" y="0" width="512" height="512">
|
|
6
|
+
<rect width="512" height="512" fill="#fff"/>
|
|
7
|
+
<ellipse cx="214" cy="112" rx="7" ry="9" fill="#000"/>
|
|
8
|
+
<ellipse cx="298" cy="112" rx="7" ry="9" fill="#000"/>
|
|
9
|
+
<ellipse cx="256" cy="149" rx="41" ry="33" fill="#000"/>
|
|
10
|
+
<g fill="none" stroke="#000" stroke-width="4.5" stroke-linecap="round">
|
|
11
|
+
<path d="M220 138c-11 0-21 2-30 6m30 4c-11 1-21 5-29 11"/>
|
|
12
|
+
<path d="M292 138c11 0 21 2 30 6m-30 4c11 1 21 5 29 11"/>
|
|
13
|
+
</g>
|
|
14
|
+
</mask>
|
|
15
|
+
</defs>
|
|
16
|
+
<path d="M256 62c-31 0-55 14-69 42-14 0-24 7-26 15-2 8 7 12 15 5-4 16-4 32-3 48 3 43-49 111-49 185 0 34-4 44-19 54-14 9-49 19-58 32-12 17 13 15 42 14 56-1 73-11 79-25 6-15 8-38 0-89 22 31 22 74 10 94 19 6 43 9 78 9s59-3 78-9c-12-20-12-63 10-94-8 51-6 74 0 89 6 14 23 24 79 25 29 1 54 3 42-14-9-13-44-23-58-32-15-10-19-20-19-54 0-74-52-142-49-185 1-16 1-32-3-48 8 7 17 3 15-5-2-8-12-15-26-15-14-28-38-42-69-42Z" fill="#111" mask="url(#face-cutouts)"/>
|
|
17
|
+
<path d="M241 129c0-5 7-7 15-7s15 2 15 7c0 4-5 6-9 9-3 2-4 5-6 5s-3-3-6-5c-4-3-9-5-9-9Z" fill="#111"/>
|
|
18
|
+
<path d="M256 141c-1 10-6 16-13 17-6 1-11-1-15-5m28-12c1 10 6 16 13 17 6 1 11-1 15-5" fill="none" stroke="#111" stroke-width="5" stroke-linecap="round"/>
|
|
19
|
+
<path d="M210 322v-72h19l27 32 27-32h19v72h-20v-42l-26 31-26-31v42Z" fill="#138462"/>
|
|
20
|
+
</svg>
|
package/lib/bin/environment.js
CHANGED
|
@@ -33,9 +33,41 @@ var MarivoEnvironmentError = class extends Error {
|
|
|
33
33
|
// lib/environment/binding.js
|
|
34
34
|
import { createHash } from "node:crypto";
|
|
35
35
|
import { access, constants, realpath, stat } from "node:fs/promises";
|
|
36
|
-
import
|
|
36
|
+
import path2 from "node:path";
|
|
37
37
|
import process3 from "node:process";
|
|
38
38
|
|
|
39
|
+
// lib/environment/identity.js
|
|
40
|
+
import { realpathSync } from "node:fs";
|
|
41
|
+
import path from "node:path";
|
|
42
|
+
function canonicalPythonExecutable(executable) {
|
|
43
|
+
const absolute = path.resolve(executable);
|
|
44
|
+
return path.join(realpathSync(path.dirname(absolute)), path.basename(absolute));
|
|
45
|
+
}
|
|
46
|
+
function canonicalImportIdentity(identity) {
|
|
47
|
+
return {
|
|
48
|
+
pythonExecutable: canonicalPythonExecutable(identity.pythonExecutable),
|
|
49
|
+
marivoVersion: identity.marivoVersion,
|
|
50
|
+
packagePath: realpathSync(identity.packagePath)
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
var PYTHON_IMPORT_IDENTITY = String.raw`
|
|
54
|
+
import os.path as _dsh_identity_path
|
|
55
|
+
|
|
56
|
+
def _dsh_python_executable(executable):
|
|
57
|
+
absolute = _dsh_identity_path.abspath(executable)
|
|
58
|
+
return _dsh_identity_path.join(
|
|
59
|
+
_dsh_identity_path.realpath(_dsh_identity_path.dirname(absolute)),
|
|
60
|
+
_dsh_identity_path.basename(absolute),
|
|
61
|
+
)
|
|
62
|
+
|
|
63
|
+
def _dsh_import_identity(executable, version, package_path):
|
|
64
|
+
return {
|
|
65
|
+
"python_executable": _dsh_python_executable(executable),
|
|
66
|
+
"marivo_version": version,
|
|
67
|
+
"package_path": _dsh_identity_path.realpath(package_path),
|
|
68
|
+
}
|
|
69
|
+
`.trim();
|
|
70
|
+
|
|
39
71
|
// lib/environment/subprocess.js
|
|
40
72
|
import { spawn } from "node:child_process";
|
|
41
73
|
import process2 from "node:process";
|
|
@@ -222,30 +254,25 @@ var IDENTITY_LIMITS = Object.freeze({
|
|
|
222
254
|
stdoutMaxBytes: 16384,
|
|
223
255
|
stderrMaxBytes: 16384
|
|
224
256
|
});
|
|
225
|
-
var CHECKED_IDENTITY_PRELUDE =
|
|
257
|
+
var CHECKED_IDENTITY_PRELUDE = `${PYTHON_IMPORT_IDENTITY}
|
|
258
|
+
${String.raw`
|
|
226
259
|
import json as _dsh_json
|
|
227
260
|
import os as _dsh_os
|
|
228
261
|
import sys as _dsh_sys
|
|
229
262
|
try:
|
|
230
263
|
import marivo as _dsh_marivo
|
|
231
|
-
_dsh_actual =
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
"package_path": _dsh_os.path.abspath(_dsh_marivo.__file__ or ""),
|
|
235
|
-
}
|
|
264
|
+
_dsh_actual = _dsh_import_identity(
|
|
265
|
+
_dsh_sys.executable, _dsh_marivo.__version__, _dsh_marivo.__file__,
|
|
266
|
+
)
|
|
236
267
|
except Exception:
|
|
237
268
|
raise SystemExit(78) from None
|
|
238
269
|
|
|
239
|
-
_dsh_expected =
|
|
240
|
-
"python_executable": _dsh_os.path.abspath(_dsh_sys.argv[1]),
|
|
241
|
-
"marivo_version": _dsh_sys.argv[2],
|
|
242
|
-
"package_path": _dsh_os.path.abspath(_dsh_sys.argv[3]),
|
|
243
|
-
}
|
|
270
|
+
_dsh_expected = _dsh_import_identity(*_dsh_sys.argv[1:4])
|
|
244
271
|
if _dsh_actual != _dsh_expected:
|
|
245
272
|
print(_dsh_json.dumps({"kind": "identity-mismatch", "actual": _dsh_actual}), file=_dsh_sys.stderr)
|
|
246
273
|
raise SystemExit(78)
|
|
247
274
|
_dsh_sys.argv = [_dsh_sys.argv[0], *_dsh_sys.argv[4:]]
|
|
248
|
-
`.trim()
|
|
275
|
+
`.trim()}`;
|
|
249
276
|
var IMPORT_IDENTITY_PROGRAM = String.raw`
|
|
250
277
|
print(_dsh_json.dumps(_dsh_actual, sort_keys=True))
|
|
251
278
|
`.trim();
|
|
@@ -303,9 +330,6 @@ function redactSubprocessOutput(result, environmentOverlay, secretValues = []) {
|
|
|
303
330
|
stderr: Buffer.from(redactText(result.stderr.toString("utf8")))
|
|
304
331
|
};
|
|
305
332
|
}
|
|
306
|
-
function normalizeAbsolute(value) {
|
|
307
|
-
return path.normalize(path.resolve(value));
|
|
308
|
-
}
|
|
309
333
|
async function assertExecutable(executable) {
|
|
310
334
|
try {
|
|
311
335
|
const info = await stat(executable);
|
|
@@ -317,12 +341,12 @@ async function assertExecutable(executable) {
|
|
|
317
341
|
}
|
|
318
342
|
}
|
|
319
343
|
async function resolvePythonExecutable(projectRoot, configured) {
|
|
320
|
-
if (configured !== void 0 && !
|
|
344
|
+
if (configured !== void 0 && !path2.isAbsolute(configured)) {
|
|
321
345
|
throw new MarivoEnvironmentError("python-path-relative", `Configured Marivo Python executable must be absolute: ${configured}`, { pythonExecutable: configured });
|
|
322
346
|
}
|
|
323
|
-
const executable = configured === void 0 ?
|
|
347
|
+
const executable = configured === void 0 ? path2.join(projectRoot, process3.platform === "win32" ? ".venv/Scripts/python.exe" : ".venv/bin/python") : path2.normalize(configured);
|
|
324
348
|
await assertExecutable(executable);
|
|
325
|
-
return executable;
|
|
349
|
+
return canonicalPythonExecutable(executable);
|
|
326
350
|
}
|
|
327
351
|
function fingerprint(binding) {
|
|
328
352
|
const payload = [
|
|
@@ -412,8 +436,9 @@ ${request.program}`,
|
|
|
412
436
|
});
|
|
413
437
|
}
|
|
414
438
|
try {
|
|
415
|
-
const identity = parseImportIdentity(result.stdout);
|
|
416
|
-
|
|
439
|
+
const identity = canonicalImportIdentity(parseImportIdentity(result.stdout));
|
|
440
|
+
const expected = this.binding;
|
|
441
|
+
if (identity.pythonExecutable !== expected.pythonExecutable || identity.marivoVersion !== expected.marivoVersion || identity.packagePath !== expected.packagePath)
|
|
417
442
|
throw new Error("identity values differ from binding");
|
|
418
443
|
return identity;
|
|
419
444
|
} catch (cause) {
|
|
@@ -428,9 +453,7 @@ function createRuntimeRunner(projectRoot, identity, environment) {
|
|
|
428
453
|
const subprocessPolicy = new FixedSubprocessPolicy(projectRoot, environment);
|
|
429
454
|
const partialBinding = {
|
|
430
455
|
projectRoot,
|
|
431
|
-
|
|
432
|
-
marivoVersion: identity.marivoVersion,
|
|
433
|
-
packagePath: identity.packagePath,
|
|
456
|
+
...canonicalImportIdentity(identity),
|
|
434
457
|
subprocessPolicyId: subprocessPolicy.id
|
|
435
458
|
};
|
|
436
459
|
return new MarivoEnvironment({ ...partialBinding, fingerprint: fingerprint(partialBinding) }, subprocessPolicy);
|
|
@@ -440,7 +463,7 @@ async function bindSharedMarivoWorkspace(projectRoot, runtime) {
|
|
|
440
463
|
const runner = createRuntimeRunner(projectRoot, {
|
|
441
464
|
pythonExecutable,
|
|
442
465
|
marivoVersion: runtime.marivoVersion,
|
|
443
|
-
packagePath:
|
|
466
|
+
packagePath: runtime.packagePath
|
|
444
467
|
});
|
|
445
468
|
const result = await runner.runChecked({
|
|
446
469
|
program: PROJECT_CONFIG_PROGRAM,
|
|
@@ -461,7 +484,7 @@ async function bindSharedMarivoWorkspace(projectRoot, runtime) {
|
|
|
461
484
|
import { randomUUID } from "node:crypto";
|
|
462
485
|
import { constants as constants2 } from "node:fs";
|
|
463
486
|
import { access as access2, chmod, cp, lstat, mkdir, readFile, realpath as realpath2, rename, rm, stat as stat2, writeFile } from "node:fs/promises";
|
|
464
|
-
import
|
|
487
|
+
import path3 from "node:path";
|
|
465
488
|
import process4 from "node:process";
|
|
466
489
|
|
|
467
490
|
// ../../node_modules/@deepseek-ai/dsh-home-paths/lib/index.js
|
|
@@ -475,10 +498,10 @@ var DEFAULT_AGENTS_HOME_DISPLAY = `~/${AGENTS_HOME_DIR_NAME}`;
|
|
|
475
498
|
function defaultDshHome() {
|
|
476
499
|
return join(homedir(), DSH_HOME_DIR_NAME);
|
|
477
500
|
}
|
|
478
|
-
function expandHomePath(
|
|
479
|
-
if (
|
|
480
|
-
if (
|
|
481
|
-
return
|
|
501
|
+
function expandHomePath(path5) {
|
|
502
|
+
if (path5 === "~") return homedir();
|
|
503
|
+
if (path5.startsWith("~/") || path5.startsWith("~\\")) return join(homedir(), path5.slice(2));
|
|
504
|
+
return path5;
|
|
482
505
|
}
|
|
483
506
|
function resolveRoot(configured, env, envName, fallback) {
|
|
484
507
|
const fromEnv = env[envName];
|
|
@@ -498,7 +521,8 @@ var INSTALLATION_SCHEMA = RUNTIME_INSTALLATION_VERSION;
|
|
|
498
521
|
var INSTALLATION_FILENAME = "installation.json";
|
|
499
522
|
var SKILL_NAMES = ["marivo-analysis", "marivo-semantic"];
|
|
500
523
|
var SERVICE_SKILL = "marivo-service";
|
|
501
|
-
var PROBE_SCRIPT =
|
|
524
|
+
var PROBE_SCRIPT = `${PYTHON_IMPORT_IDENTITY}
|
|
525
|
+
${String.raw`
|
|
502
526
|
import json
|
|
503
527
|
import os
|
|
504
528
|
import sys
|
|
@@ -515,22 +539,21 @@ print(json.dumps({
|
|
|
515
539
|
"marivo_distribution_version": dist.version,
|
|
516
540
|
"marivo_index_install": dist.read_text("direct_url.json") is None,
|
|
517
541
|
"marivo_import_identity": os.path.realpath(marivo.__file__) == os.path.realpath(dist.locate_file("marivo/__init__.py")),
|
|
518
|
-
|
|
519
|
-
"marivo_version": marivo.__version__,
|
|
520
|
-
"package_path": os.path.abspath(marivo.__file__ or ""),
|
|
542
|
+
**_dsh_import_identity(sys.executable, marivo.__version__, marivo.__file__),
|
|
521
543
|
}, sort_keys=True))
|
|
522
|
-
`.trim()
|
|
523
|
-
var PYTHON_VERSION_SCRIPT =
|
|
544
|
+
`.trim()}`;
|
|
545
|
+
var PYTHON_VERSION_SCRIPT = `${PYTHON_IMPORT_IDENTITY}
|
|
546
|
+
${String.raw`
|
|
524
547
|
import json
|
|
525
548
|
import os
|
|
526
549
|
import sys
|
|
527
550
|
|
|
528
551
|
print(json.dumps({
|
|
529
|
-
"python_executable":
|
|
552
|
+
"python_executable": _dsh_python_executable(sys.executable),
|
|
530
553
|
"version": list(sys.version_info[:3]),
|
|
531
554
|
"prefix": os.path.abspath(sys.prefix),
|
|
532
555
|
}, sort_keys=True))
|
|
533
|
-
`.trim()
|
|
556
|
+
`.trim()}`;
|
|
534
557
|
function administratorRepair(executable) {
|
|
535
558
|
const commands = [
|
|
536
559
|
{
|
|
@@ -550,17 +573,17 @@ function positiveTimeout(value) {
|
|
|
550
573
|
}
|
|
551
574
|
return resolved;
|
|
552
575
|
}
|
|
553
|
-
function
|
|
554
|
-
if (!
|
|
576
|
+
function normalizeAbsolute(name, value) {
|
|
577
|
+
if (!path3.isAbsolute(value)) {
|
|
555
578
|
throw new MarivoEnvironmentError("shared-runtime-config-invalid", `${name} must be an absolute path: ${value}`, { [name]: value });
|
|
556
579
|
}
|
|
557
|
-
return
|
|
580
|
+
return path3.normalize(value);
|
|
558
581
|
}
|
|
559
582
|
function defaultRuntimeRoot() {
|
|
560
|
-
return
|
|
583
|
+
return path3.join(resolveDshHome(), "dsh-data-analysis", "runtimes", "marivo");
|
|
561
584
|
}
|
|
562
585
|
function venvPython(runtimeRoot) {
|
|
563
|
-
return
|
|
586
|
+
return path3.join(runtimeRoot, ".venv", process4.platform === "win32" ? "Scripts/python.exe" : "bin/python");
|
|
564
587
|
}
|
|
565
588
|
function boundedText(buffer, max = 4e3) {
|
|
566
589
|
return buffer.toString("utf8").slice(0, max);
|
|
@@ -577,13 +600,13 @@ function requireSuccess(stage, result) {
|
|
|
577
600
|
});
|
|
578
601
|
}
|
|
579
602
|
async function assertExecutable2(executable) {
|
|
580
|
-
const selected =
|
|
603
|
+
const selected = path3.normalize(path3.resolve(executable));
|
|
581
604
|
try {
|
|
582
605
|
const info = await stat2(selected);
|
|
583
606
|
if (!info.isFile())
|
|
584
607
|
throw new Error("not a file");
|
|
585
608
|
await access2(selected, process4.platform === "win32" ? constants2.F_OK : constants2.X_OK);
|
|
586
|
-
return selected;
|
|
609
|
+
return canonicalPythonExecutable(selected);
|
|
587
610
|
} catch (cause) {
|
|
588
611
|
throw new MarivoEnvironmentError("python-unavailable", `Shared Marivo Python executable is missing or not executable: ${selected}`, { pythonExecutable: selected }, { cause });
|
|
589
612
|
}
|
|
@@ -624,8 +647,8 @@ async function probeRuntime(runtimeRoot, executable, environment, timeoutMs, adm
|
|
|
624
647
|
if (probe.marivo_distribution_version !== probe.marivo_version || probe.marivo_import_identity !== true || typeof probe.python_executable !== "string" || typeof probe.marivo_version !== "string" || probe.marivo_version.length === 0 || typeof probe.package_path !== "string" || probe.package_path.length === 0) {
|
|
625
648
|
throw new MarivoEnvironmentError("shared-runtime-identity-mismatch", "Shared Runtime returned an incomplete or mismatched package identity", { probe, ...repair === void 0 ? {} : { repairCommands: repair.commands } });
|
|
626
649
|
}
|
|
627
|
-
const actualPython =
|
|
628
|
-
const selectedPython =
|
|
650
|
+
const actualPython = canonicalPythonExecutable(probe.python_executable);
|
|
651
|
+
const selectedPython = canonicalPythonExecutable(canonical);
|
|
629
652
|
if (expectedMarivoVersion !== void 0 && probe.marivo_version !== expectedMarivoVersion) {
|
|
630
653
|
throw new MarivoEnvironmentError("shared-runtime-version-unsupported", `Shared Marivo runtime version ${probe.marivo_version} is unsupported; install ${expectedMarivoVersion}.${repair === void 0 ? "" : ` ${repair.message}`}`, {
|
|
631
654
|
supportedMarivoVersion: expectedMarivoVersion,
|
|
@@ -647,12 +670,12 @@ async function probeRuntime(runtimeRoot, executable, environment, timeoutMs, adm
|
|
|
647
670
|
marivo_import_identity: true,
|
|
648
671
|
python_executable: canonical,
|
|
649
672
|
marivo_version: probe.marivo_version,
|
|
650
|
-
package_path:
|
|
673
|
+
package_path: await realpath2(probe.package_path)
|
|
651
674
|
};
|
|
652
675
|
}
|
|
653
676
|
async function availableSkills(skillsRoot) {
|
|
654
677
|
try {
|
|
655
|
-
await lstat(
|
|
678
|
+
await lstat(path3.join(skillsRoot, SERVICE_SKILL));
|
|
656
679
|
return [...SKILL_NAMES, SERVICE_SKILL];
|
|
657
680
|
} catch (error) {
|
|
658
681
|
if (error.code === "ENOENT")
|
|
@@ -662,7 +685,7 @@ async function availableSkills(skillsRoot) {
|
|
|
662
685
|
}
|
|
663
686
|
async function validateSkills(skillsRoot, skills) {
|
|
664
687
|
for (const skill of skills) {
|
|
665
|
-
const skillFile =
|
|
688
|
+
const skillFile = path3.join(skillsRoot, skill, "SKILL.md");
|
|
666
689
|
try {
|
|
667
690
|
if (!(await stat2(skillFile)).isFile())
|
|
668
691
|
throw new Error("not a file");
|
|
@@ -682,16 +705,16 @@ async function validateSkills(skillsRoot, skills) {
|
|
|
682
705
|
}
|
|
683
706
|
}
|
|
684
707
|
async function syncSkills(runtimeRoot, packagePath) {
|
|
685
|
-
const sourceRoot =
|
|
708
|
+
const sourceRoot = path3.join(path3.dirname(packagePath), "skills");
|
|
686
709
|
const skills = await availableSkills(sourceRoot);
|
|
687
710
|
await validateSkills(sourceRoot, skills);
|
|
688
|
-
const skillsRoot =
|
|
689
|
-
const staging =
|
|
690
|
-
const previous =
|
|
711
|
+
const skillsRoot = path3.join(runtimeRoot, "skills");
|
|
712
|
+
const staging = path3.join(runtimeRoot, `.skills-staging-${randomUUID()}`);
|
|
713
|
+
const previous = path3.join(runtimeRoot, `.skills-previous-${randomUUID()}`);
|
|
691
714
|
await mkdir(staging, { recursive: true });
|
|
692
715
|
try {
|
|
693
716
|
for (const skill of skills) {
|
|
694
|
-
await cp(
|
|
717
|
+
await cp(path3.join(sourceRoot, skill), path3.join(staging, skill), { recursive: true });
|
|
695
718
|
}
|
|
696
719
|
await validateSkills(staging, skills);
|
|
697
720
|
let hadPrevious = false;
|
|
@@ -718,7 +741,7 @@ async function syncSkills(runtimeRoot, packagePath) {
|
|
|
718
741
|
}
|
|
719
742
|
async function readInstallation(runtimeRoot) {
|
|
720
743
|
try {
|
|
721
|
-
const value = JSON.parse(await readFile(
|
|
744
|
+
const value = JSON.parse(await readFile(path3.join(runtimeRoot, INSTALLATION_FILENAME), "utf8"));
|
|
722
745
|
if (typeof value !== "object" || value === null || Array.isArray(value))
|
|
723
746
|
return void 0;
|
|
724
747
|
const record = value;
|
|
@@ -738,8 +761,8 @@ async function readInstallation(runtimeRoot) {
|
|
|
738
761
|
}
|
|
739
762
|
}
|
|
740
763
|
async function writeInstallation(runtimeRoot, record) {
|
|
741
|
-
const installationPath =
|
|
742
|
-
const temporary =
|
|
764
|
+
const installationPath = path3.join(runtimeRoot, INSTALLATION_FILENAME);
|
|
765
|
+
const temporary = path3.join(runtimeRoot, `.installation-${randomUUID()}.json`);
|
|
743
766
|
await writeFile(temporary, `${JSON.stringify(record, void 0, 2)}
|
|
744
767
|
`, {
|
|
745
768
|
encoding: "utf8",
|
|
@@ -757,17 +780,17 @@ async function validatedExisting(runtimeRoot, configuredPython, environment, tim
|
|
|
757
780
|
if (record.marivoVersion !== PINNED_MARIVO_VERSION)
|
|
758
781
|
return void 0;
|
|
759
782
|
const expectedPython = configuredPython ?? venvPython(runtimeRoot);
|
|
760
|
-
const expectedSkillsRoot =
|
|
761
|
-
if (path2.normalize(record.skillsRoot) !== path2.normalize(expectedSkillsRoot))
|
|
762
|
-
return void 0;
|
|
783
|
+
const expectedSkillsRoot = path3.join(runtimeRoot, "skills");
|
|
763
784
|
try {
|
|
785
|
+
if (await realpath2(record.skillsRoot) !== await realpath2(expectedSkillsRoot))
|
|
786
|
+
return void 0;
|
|
764
787
|
const selectedPython = await assertExecutable2(expectedPython);
|
|
765
|
-
if (
|
|
788
|
+
if (canonicalPythonExecutable(record.pythonExecutable) !== selectedPython)
|
|
766
789
|
return void 0;
|
|
767
790
|
const probe = await probeRuntime(runtimeRoot, selectedPython, environment, timeoutMs, configuredPython !== void 0, record.marivoVersion);
|
|
768
|
-
if (
|
|
791
|
+
if (probe.package_path !== await realpath2(record.packagePath))
|
|
769
792
|
return void 0;
|
|
770
|
-
const sourceRoot =
|
|
793
|
+
const sourceRoot = path3.join(path3.dirname(probe.package_path), "skills");
|
|
771
794
|
await validateSkills(record.skillsRoot, await availableSkills(sourceRoot));
|
|
772
795
|
return {
|
|
773
796
|
runtimeRoot,
|
|
@@ -775,7 +798,7 @@ async function validatedExisting(runtimeRoot, configuredPython, environment, tim
|
|
|
775
798
|
marivoVersion: probe.marivo_version,
|
|
776
799
|
packagePath: probe.package_path,
|
|
777
800
|
skillsRoot: record.skillsRoot,
|
|
778
|
-
installationPath:
|
|
801
|
+
installationPath: path3.join(runtimeRoot, INSTALLATION_FILENAME)
|
|
779
802
|
};
|
|
780
803
|
} catch {
|
|
781
804
|
return void 0;
|
|
@@ -786,7 +809,7 @@ async function acquireLock(lockPath, timeoutMs, waitIntervalMs) {
|
|
|
786
809
|
while (true) {
|
|
787
810
|
try {
|
|
788
811
|
await mkdir(lockPath);
|
|
789
|
-
await writeFile(
|
|
812
|
+
await writeFile(path3.join(lockPath, "owner.json"), `${JSON.stringify({ pid: process4.pid, startedAt: (/* @__PURE__ */ new Date()).toISOString() })}
|
|
790
813
|
`);
|
|
791
814
|
return async () => {
|
|
792
815
|
await rm(lockPath, { recursive: true, force: true });
|
|
@@ -818,7 +841,7 @@ async function acquireLock(lockPath, timeoutMs, waitIntervalMs) {
|
|
|
818
841
|
}
|
|
819
842
|
async function lockOwnerAlive(lockPath) {
|
|
820
843
|
try {
|
|
821
|
-
const owner = JSON.parse(await readFile(
|
|
844
|
+
const owner = JSON.parse(await readFile(path3.join(lockPath, "owner.json"), "utf8"));
|
|
822
845
|
if (!Number.isSafeInteger(owner.pid) || owner.pid < 1)
|
|
823
846
|
return false;
|
|
824
847
|
try {
|
|
@@ -859,13 +882,13 @@ async function installManagedRuntime(runtimeRoot, bootstrapPythonExecutable, env
|
|
|
859
882
|
if (!Array.isArray(version.version) || typeof version.version[0] !== "number" || typeof version.version[1] !== "number" || version.version[0] < 3 || version.version[0] === 3 && version.version[1] < 10) {
|
|
860
883
|
throw new MarivoEnvironmentError("shared-runtime-install-failed", `Local Python does not satisfy Marivo >=${SHARED_PYTHON_SPEC}; detected ${Array.isArray(version.version) ? version.version.join(".") : "unknown"}`, { version: version.version, pythonExecutable: bootstrapPythonExecutable });
|
|
861
884
|
}
|
|
862
|
-
if (typeof version.python_executable !== "string" || !
|
|
885
|
+
if (typeof version.python_executable !== "string" || !path3.isAbsolute(version.python_executable)) {
|
|
863
886
|
throw new MarivoEnvironmentError("shared-runtime-install-failed", "Local Python returned a non-absolute interpreter path");
|
|
864
887
|
}
|
|
865
888
|
const canonicalPython = await assertExecutable2(version.python_executable);
|
|
866
889
|
requireSuccess("create shared virtual environment (requires Python venv/ensurepip; install python3-venv on Debian/Ubuntu)", await policy.run({
|
|
867
890
|
executable: canonicalPython,
|
|
868
|
-
args: ["-m", "venv",
|
|
891
|
+
args: ["-m", "venv", path3.join(runtimeRoot, ".venv")],
|
|
869
892
|
limits
|
|
870
893
|
}));
|
|
871
894
|
const executable = venvPython(runtimeRoot);
|
|
@@ -877,16 +900,16 @@ async function installManagedRuntime(runtimeRoot, bootstrapPythonExecutable, env
|
|
|
877
900
|
return probeRuntime(runtimeRoot, executable, environment, timeoutMs, false, PINNED_MARIVO_VERSION);
|
|
878
901
|
}
|
|
879
902
|
async function ensureSharedMarivoRuntime(config = {}, options = {}) {
|
|
880
|
-
const runtimeRoot = config.runtimeRoot === void 0 ? defaultRuntimeRoot() :
|
|
881
|
-
const configuredPython = config.pythonExecutable === void 0 ? void 0 :
|
|
882
|
-
const bootstrapPythonExecutable = config.bootstrapPythonExecutable === void 0 ? process4.platform === "win32" ? "python" : "python3" :
|
|
903
|
+
const runtimeRoot = config.runtimeRoot === void 0 ? defaultRuntimeRoot() : normalizeAbsolute("runtimeRoot", config.runtimeRoot);
|
|
904
|
+
const configuredPython = config.pythonExecutable === void 0 ? void 0 : normalizeAbsolute("pythonExecutable", config.pythonExecutable);
|
|
905
|
+
const bootstrapPythonExecutable = config.bootstrapPythonExecutable === void 0 ? process4.platform === "win32" ? "python" : "python3" : normalizeAbsolute("bootstrapPythonExecutable", config.bootstrapPythonExecutable);
|
|
883
906
|
const timeoutMs = positiveTimeout(config.installTimeoutMs);
|
|
884
907
|
const existing = await validatedExisting(runtimeRoot, configuredPython, options.environment, timeoutMs);
|
|
885
908
|
if (existing !== void 0)
|
|
886
909
|
return existing;
|
|
887
910
|
if (options.existingOnly)
|
|
888
911
|
throw new MarivoEnvironmentError("shared-runtime-installation-required", "A valid shared Marivo Runtime installation is required");
|
|
889
|
-
await mkdir(
|
|
912
|
+
await mkdir(path3.dirname(runtimeRoot), { recursive: true });
|
|
890
913
|
const lockPath = `${runtimeRoot}.install-lock`;
|
|
891
914
|
const release = await acquireLock(lockPath, timeoutMs, options.waitIntervalMs ?? 100);
|
|
892
915
|
try {
|
|
@@ -920,7 +943,7 @@ async function ensureSharedMarivoRuntime(config = {}, options = {}) {
|
|
|
920
943
|
|
|
921
944
|
// lib/environment/workspace.js
|
|
922
945
|
import { realpath as realpath3, stat as stat3 } from "node:fs/promises";
|
|
923
|
-
import
|
|
946
|
+
import path4 from "node:path";
|
|
924
947
|
|
|
925
948
|
// lib/lifecycle.js
|
|
926
949
|
var PendingTasks = class {
|
|
@@ -968,12 +991,12 @@ async function assertDirectory(target, label) {
|
|
|
968
991
|
async function canonicalWorkspaceRoot(projectRoot) {
|
|
969
992
|
let canonicalRoot;
|
|
970
993
|
try {
|
|
971
|
-
canonicalRoot = await realpath3(
|
|
994
|
+
canonicalRoot = await realpath3(path4.resolve(projectRoot));
|
|
972
995
|
await assertDirectory(canonicalRoot, "root");
|
|
973
996
|
} catch (cause) {
|
|
974
997
|
if (cause instanceof MarivoEnvironmentError)
|
|
975
998
|
throw cause;
|
|
976
|
-
throw new MarivoEnvironmentError("project-root-invalid", `Marivo project root is not an existing directory: ${
|
|
999
|
+
throw new MarivoEnvironmentError("project-root-invalid", `Marivo project root is not an existing directory: ${path4.resolve(projectRoot)}`, { projectRoot: path4.resolve(projectRoot) }, { cause });
|
|
977
1000
|
}
|
|
978
1001
|
return canonicalRoot;
|
|
979
1002
|
}
|