dsh-office-kit 0.1.0 → 0.3.0

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 (198) hide show
  1. package/CAPABILITY.md +147 -68
  2. package/LICENSE.md +21 -21
  3. package/README.md +108 -106
  4. package/assets/skills/excel-live-control/SKILL.md +234 -0
  5. package/assets/skills/excel-live-control/container_tools/live_excel.py +1589 -0
  6. package/assets/skills/excel-live-control/domain_guidance/financial_models.md +86 -0
  7. package/assets/skills/excel-live-control/domain_guidance/healthcare.md +58 -0
  8. package/assets/skills/excel-live-control/domain_guidance/marketing_advertising.md +53 -0
  9. package/assets/skills/excel-live-control/domain_guidance/scientific_research.md +53 -0
  10. package/assets/skills/excel-live-control/references/office-automation.md +207 -0
  11. package/assets/skills/excel-live-control/references/read_only_qna.md +59 -0
  12. package/assets/skills/excel-live-control/style_guidelines.md +87 -0
  13. package/assets/skills/excel-live-control/workflows/create_workflows.md +78 -0
  14. package/assets/skills/excel-live-control/workflows/edit_workflows.md +72 -0
  15. package/assets/skills/office-documents/SKILL.md +90 -77
  16. package/assets/skills/office-documents/examples/end_to_end_smoke_test.md +86 -0
  17. package/assets/skills/office-documents/ooxml/comments.md +40 -0
  18. package/assets/skills/office-documents/ooxml/hyperlinks_and_fields.md +66 -0
  19. package/assets/skills/office-documents/ooxml/rels_and_content_types.md +62 -0
  20. package/assets/skills/office-documents/ooxml/tracked_changes.md +53 -0
  21. package/assets/skills/office-documents/references/docx-structure.md +83 -0
  22. package/assets/skills/office-documents/references/template-elicitation.md +49 -0
  23. package/assets/skills/office-documents/references/writing-quality.md +49 -0
  24. package/assets/skills/office-documents/render_docx.py +92 -0
  25. package/assets/skills/office-documents/scripts/a11y_audit.py +194 -0
  26. package/assets/skills/office-documents/scripts/accept_tracked_changes.py +151 -0
  27. package/assets/skills/office-documents/scripts/add_tracked_replacements.py +148 -0
  28. package/assets/skills/office-documents/scripts/append_blocks.py +108 -0
  29. package/assets/skills/office-documents/scripts/apply_template_styles.py +104 -0
  30. package/assets/skills/office-documents/scripts/captions_and_crossrefs.py +102 -0
  31. package/assets/skills/office-documents/scripts/comments_add.py +136 -0
  32. package/assets/skills/office-documents/scripts/comments_apply_patch.py +114 -0
  33. package/assets/skills/office-documents/scripts/comments_extract.py +85 -0
  34. package/assets/skills/office-documents/scripts/comments_strip.py +74 -0
  35. package/assets/skills/office-documents/scripts/content_controls.py +192 -0
  36. package/assets/skills/office-documents/scripts/core_properties.py +124 -0
  37. package/assets/skills/office-documents/scripts/docx_kit.py +587 -0
  38. package/assets/skills/office-documents/scripts/docx_ooxml_patch.py +225 -0
  39. package/assets/skills/office-documents/scripts/docx_table_to_csv.py +99 -0
  40. package/assets/skills/office-documents/scripts/fields_materialize.py +66 -0
  41. package/assets/skills/office-documents/scripts/fields_report.py +59 -0
  42. package/assets/skills/office-documents/scripts/flatten_ref_fields.py +62 -0
  43. package/assets/skills/office-documents/scripts/footnotes_report.py +77 -0
  44. package/assets/skills/office-documents/scripts/google_docs_title_sanitize.py +96 -0
  45. package/assets/skills/office-documents/scripts/heading_audit.py +81 -0
  46. package/assets/skills/office-documents/scripts/images_audit.py +80 -0
  47. package/assets/skills/office-documents/scripts/insert_note.py +126 -0
  48. package/assets/skills/office-documents/scripts/insert_ref_fields.py +90 -0
  49. package/assets/skills/office-documents/scripts/insert_toc.py +84 -0
  50. package/assets/skills/office-documents/scripts/internal_nav.py +146 -0
  51. package/assets/skills/office-documents/scripts/make_fixtures.py +169 -0
  52. package/assets/skills/office-documents/scripts/merge_docx_append.py +239 -0
  53. package/assets/skills/office-documents/scripts/privacy_scrub.py +131 -0
  54. package/assets/skills/office-documents/scripts/redact_docx.py +113 -0
  55. package/assets/skills/office-documents/scripts/render_and_diff.py +101 -0
  56. package/assets/skills/office-documents/scripts/replace_text.py +154 -0
  57. package/assets/skills/office-documents/scripts/section_audit.py +91 -0
  58. package/assets/skills/office-documents/scripts/set_protection.py +92 -0
  59. package/assets/skills/office-documents/scripts/style_lint.py +111 -0
  60. package/assets/skills/office-documents/scripts/style_normalize.py +103 -0
  61. package/assets/skills/office-documents/scripts/table_geometry.py +167 -0
  62. package/assets/skills/office-documents/scripts/watermark_add.py +48 -0
  63. package/assets/skills/office-documents/scripts/watermark_audit_remove.py +67 -0
  64. package/assets/skills/office-documents/scripts/xlsx_to_docx_table.py +117 -0
  65. package/assets/skills/office-documents/tasks/accessibility_a11y.md +45 -0
  66. package/assets/skills/office-documents/tasks/captions_crossrefs.md +49 -0
  67. package/assets/skills/office-documents/tasks/clean_tracked_changes.md +49 -0
  68. package/assets/skills/office-documents/tasks/comments_manage.md +59 -0
  69. package/assets/skills/office-documents/tasks/compare_diff.md +40 -0
  70. package/assets/skills/office-documents/tasks/create_edit.md +107 -0
  71. package/assets/skills/office-documents/tasks/equations.md +59 -0
  72. package/assets/skills/office-documents/tasks/fields_update.md +44 -0
  73. package/assets/skills/office-documents/tasks/fixtures_edge_cases.md +50 -0
  74. package/assets/skills/office-documents/tasks/footnotes_endnotes.md +38 -0
  75. package/assets/skills/office-documents/tasks/forms_content_controls.md +48 -0
  76. package/assets/skills/office-documents/tasks/headings_numbering.md +55 -0
  77. package/assets/skills/office-documents/tasks/images_figures.md +63 -0
  78. package/assets/skills/office-documents/tasks/multi_doc_merge.md +43 -0
  79. package/assets/skills/office-documents/tasks/navigation_internal_links.md +38 -0
  80. package/assets/skills/office-documents/tasks/privacy_scrub_metadata.md +45 -0
  81. package/assets/skills/office-documents/tasks/protection_restrict_editing.md +41 -0
  82. package/assets/skills/office-documents/tasks/read_review.md +50 -0
  83. package/assets/skills/office-documents/tasks/redaction_anonymization.md +42 -0
  84. package/assets/skills/office-documents/tasks/sections_layout.md +54 -0
  85. package/assets/skills/office-documents/tasks/style_lint_normalize.md +44 -0
  86. package/assets/skills/office-documents/tasks/tables_spreadsheets.md +64 -0
  87. package/assets/skills/office-documents/tasks/templates_style_packs.md +53 -0
  88. package/assets/skills/office-documents/tasks/toc_workflow.md +39 -0
  89. package/assets/skills/office-documents/tasks/verify_render.md +50 -0
  90. package/assets/skills/office-documents/tasks/watermarks_background.md +35 -0
  91. package/assets/skills/office-documents/troubleshooting/libreoffice_headless.md +47 -0
  92. package/assets/skills/office-documents/troubleshooting/run_splitting.md +36 -0
  93. package/assets/skills/office-pdf/SKILL.md +73 -56
  94. package/assets/skills/office-pdf/references/form-fields.md +56 -0
  95. package/assets/skills/office-pdf/references/geometry.md +44 -0
  96. package/assets/skills/office-pdf/references/layout-quality.md +41 -0
  97. package/assets/skills/office-pdf/references/limits.md +58 -0
  98. package/assets/skills/office-pdf/scripts/extract_text.py +172 -0
  99. package/assets/skills/office-pdf/scripts/forms.py +556 -0
  100. package/assets/skills/office-pdf/scripts/metadata.py +161 -0
  101. package/assets/skills/office-pdf/scripts/page_ops.py +198 -0
  102. package/assets/skills/office-pdf/scripts/redact_region.py +347 -0
  103. package/assets/skills/office-pdf/scripts/render_pages.py +207 -0
  104. package/assets/skills/office-pdf/scripts/split_pages.py +155 -0
  105. package/assets/skills/office-pdf/scripts/stamp_overlay.py +199 -0
  106. package/assets/skills/office-pdf/tasks/annotations.md +98 -0
  107. package/assets/skills/office-pdf/tasks/create.md +75 -0
  108. package/assets/skills/office-pdf/tasks/edit-pages.md +71 -0
  109. package/assets/skills/office-pdf/tasks/forms.md +67 -0
  110. package/assets/skills/office-pdf/tasks/read.md +62 -0
  111. package/assets/skills/office-pdf/tasks/redact.md +72 -0
  112. package/assets/skills/office-pdf/tasks/stamp.md +60 -0
  113. package/assets/skills/office-presentations/SKILL.md +141 -87
  114. package/assets/skills/office-presentations/container_tools/add_slides.py +136 -0
  115. package/assets/skills/office-presentations/container_tools/core_properties.py +120 -0
  116. package/assets/skills/office-presentations/container_tools/create_montage.py +126 -0
  117. package/assets/skills/office-presentations/container_tools/inspect_presentation_layout_geometry.py +285 -0
  118. package/assets/skills/office-presentations/container_tools/inspect_presentation_package_integrity.py +157 -0
  119. package/assets/skills/office-presentations/container_tools/native_chart_title_gate.py +144 -0
  120. package/assets/skills/office-presentations/container_tools/native_quantitative_chart_gate.py +199 -0
  121. package/assets/skills/office-presentations/container_tools/native_table_arithmetic_gate.py +212 -0
  122. package/assets/skills/office-presentations/container_tools/ooxml_helpers.py +345 -0
  123. package/assets/skills/office-presentations/container_tools/preview_render.py +375 -0
  124. package/assets/skills/office-presentations/container_tools/render_slides.py +139 -0
  125. package/assets/skills/office-presentations/container_tools/replace_text.py +168 -0
  126. package/assets/skills/office-presentations/container_tools/template_source_fidelity_gate.py +229 -0
  127. package/assets/skills/office-presentations/domain_guidance/finance.md +66 -0
  128. package/assets/skills/office-presentations/recipes/README.md +71 -0
  129. package/assets/skills/office-presentations/recipes/autolayout.md +88 -0
  130. package/assets/skills/office-presentations/recipes/connectors.md +83 -0
  131. package/assets/skills/office-presentations/recipes/images.md +80 -0
  132. package/assets/skills/office-presentations/recipes/master-and-layouts.md +127 -0
  133. package/assets/skills/office-presentations/recipes/native-charts.md +87 -0
  134. package/assets/skills/office-presentations/recipes/rich-text-runs.md +86 -0
  135. package/assets/skills/office-presentations/recipes/speaker-notes.md +65 -0
  136. package/assets/skills/office-presentations/recipes/tables.md +88 -0
  137. package/assets/skills/office-presentations/recipes/textbox-at-coordinate.md +71 -0
  138. package/assets/skills/office-presentations/recipes/theme-tokens.md +87 -0
  139. package/assets/skills/office-presentations/references/authoring-workflow.md +65 -0
  140. package/assets/skills/office-presentations/references/finalization.md +63 -0
  141. package/assets/skills/office-presentations/references/native-bullets.md +78 -0
  142. package/assets/skills/office-presentations/references/native-evidence.md +67 -0
  143. package/assets/skills/office-presentations/references/style-guidelines.md +66 -0
  144. package/assets/skills/office-presentations/references/templates.md +76 -0
  145. package/assets/skills/office-presentations/routing/google_slides.md +45 -0
  146. package/assets/skills/office-presentations/tasks/apply-annotations.md +83 -0
  147. package/assets/skills/office-presentations/tasks/charts-tables-notes.md +79 -0
  148. package/assets/skills/office-presentations/tasks/create-deck.md +106 -0
  149. package/assets/skills/office-presentations/tasks/edit-deck.md +93 -0
  150. package/assets/skills/office-presentations/tasks/inspect-and-verify.md +107 -0
  151. package/assets/skills/office-presentations/tasks/template-following.md +132 -0
  152. package/assets/skills/office-presentations/template_following_scripts/check_template_fidelity.py +176 -0
  153. package/assets/skills/office-presentations/template_following_scripts/inspect_template_deck.py +154 -0
  154. package/assets/skills/office-presentations/template_following_scripts/make_contact_sheet.py +111 -0
  155. package/assets/skills/office-presentations/template_following_scripts/prepare_template_starter_deck.py +239 -0
  156. package/assets/skills/office-presentations/template_following_scripts/validate_template_plan.py +185 -0
  157. package/assets/skills/office-spreadsheets/SKILL.md +105 -101
  158. package/assets/skills/office-spreadsheets/container_tools/add_chart.py +236 -0
  159. package/assets/skills/office-spreadsheets/container_tools/add_image.py +107 -0
  160. package/assets/skills/office-spreadsheets/container_tools/append_rows.py +122 -0
  161. package/assets/skills/office-spreadsheets/container_tools/diff_workbooks.py +306 -0
  162. package/assets/skills/office-spreadsheets/container_tools/inspect_workbook.py +398 -0
  163. package/assets/skills/office-spreadsheets/container_tools/recalc_gate.py +275 -0
  164. package/assets/skills/office-spreadsheets/container_tools/set_cells.py +135 -0
  165. package/assets/skills/office-spreadsheets/container_tools/sheet_ops.py +134 -0
  166. package/assets/skills/office-spreadsheets/container_tools/style_cells.py +133 -0
  167. package/assets/skills/office-spreadsheets/recipes/charts.md +66 -0
  168. package/assets/skills/office-spreadsheets/recipes/conditional-formats.md +69 -0
  169. package/assets/skills/office-spreadsheets/recipes/data-tables.md +58 -0
  170. package/assets/skills/office-spreadsheets/recipes/named-ranges.md +41 -0
  171. package/assets/skills/office-spreadsheets/recipes/number-formats.md +72 -0
  172. package/assets/skills/office-spreadsheets/recipes/sparklines.md +43 -0
  173. package/assets/skills/office-spreadsheets/references/charts.md +63 -0
  174. package/assets/skills/office-spreadsheets/references/domain/financial-models.md +40 -0
  175. package/assets/skills/office-spreadsheets/references/domain/healthcare.md +22 -0
  176. package/assets/skills/office-spreadsheets/references/domain/marketing.md +28 -0
  177. package/assets/skills/office-spreadsheets/references/domain/research.md +22 -0
  178. package/assets/skills/office-spreadsheets/references/formula-patterns.md +78 -0
  179. package/assets/skills/office-spreadsheets/references/style-guidelines.md +69 -0
  180. package/assets/skills/office-spreadsheets/references/workbook-structure.md +60 -0
  181. package/assets/skills/office-spreadsheets/routing/google-sheets.md +36 -0
  182. package/assets/skills/office-spreadsheets/tasks/analyze-workbook.md +37 -0
  183. package/assets/skills/office-spreadsheets/tasks/annotations.md +51 -0
  184. package/assets/skills/office-spreadsheets/tasks/create-workbook.md +66 -0
  185. package/assets/skills/office-spreadsheets/tasks/diff-workbooks.md +38 -0
  186. package/assets/skills/office-spreadsheets/tasks/edit-workbook.md +69 -0
  187. package/assets/skills/office-spreadsheets/tasks/inspect-workbook.md +38 -0
  188. package/assets/skills/office-spreadsheets/tasks/recalc-and-check.md +57 -0
  189. package/assets/skills/shared/annotation-recipes.md +252 -0
  190. package/assets/skills/shared/check_runtime.py +253 -0
  191. package/assets/skills/shared/common-workflow.md +139 -0
  192. package/assets/skills/shared/scripts/ensure_raster_image.py +187 -0
  193. package/dist/client.js +4 -4
  194. package/dist/client.js.map +1 -1
  195. package/dist/index.js +239 -89
  196. package/package.json +146 -149
  197. package/postinstall.mjs +92 -82
  198. package/python/office_cli.py +171 -246
package/package.json CHANGED
@@ -1,149 +1,146 @@
1
- {
2
- "name": "dsh-office-kit",
3
- "type": "module",
4
- "version": "0.1.0",
5
- "packageManager": "pnpm@11.15.1",
6
- "description": "Office documents, PDF, presentations, and spreadsheets for DeepSeek Harness",
7
- "author": "Hairy",
8
- "license": "MIT",
9
- "homepage": "https://github.com/hairyf/dsh-office-kit#readme",
10
- "repository": {
11
- "type": "git",
12
- "url": "git+https://github.com/hairyf/dsh-office-kit.git"
13
- },
14
- "bugs": "https://github.com/hairyf/dsh-office-kit/issues",
15
- "keywords": [
16
- "dsh-plugin",
17
- "deepseek-harness",
18
- "office",
19
- "docx",
20
- "pdf",
21
- "pptx",
22
- "xlsx"
23
- ],
24
- "sideEffects": false,
25
- "exports": {
26
- ".": "./dist/index.js",
27
- "./client": "./dist/client.js",
28
- "./package.json": "./package.json"
29
- },
30
- "main": "./dist/index.js",
31
- "module": "./dist/index.js",
32
- "types": "./dist/index.d.ts",
33
- "files": [
34
- "CAPABILITY.md",
35
- "README.md",
36
- "assets",
37
- "cordis.patch.yml",
38
- "dist",
39
- "postinstall.mjs",
40
- "python"
41
- ],
42
- "dsh": {
43
- "client": {
44
- "inject": [
45
- "@deepseek-ai/dsh-api-session-controller",
46
- "@deepseek-ai/dsh-client-locale",
47
- "@deepseek-ai/dsh-client-ui-layout",
48
- "@deepseek-ai/dsh-client-ui-conversation",
49
- "@deepseek-ai/dsh-client-ui-input-trigger",
50
- "@deepseek-ai/dsh-client-ui-sidebar-right",
51
- "@deepseek-ai/dsh-api-remotes"
52
- ],
53
- "platform": "web"
54
- },
55
- "bundle": {
56
- "patch": "./cordis.patch.yml"
57
- }
58
- },
59
- "scripts": {
60
- "build": "tsdown",
61
- "dev": "tsdown --watch",
62
- "lint": "eslint",
63
- "prepack": "nr build",
64
- "release": "bumpp",
65
- "start": "tsx src/index.ts",
66
- "test": "pnpm run build && vitest",
67
- "typecheck": "tsc",
68
- "prepare": "git config core.hooksPath .githooks && simple-git-hooks",
69
- "postinstall": "node postinstall.mjs"
70
- },
71
- "scripts-info": {
72
- "build": "Build the library for publishing",
73
- "dev": "Rebuild on change during development",
74
- "lint": "Check for code style issues",
75
- "prepack": "Build before publishing",
76
- "release": "Bump version and publish a release",
77
- "start": "Run the entry file",
78
- "test": "Run the test suite",
79
- "typecheck": "Check types",
80
- "prepare": "Set up git hooks and skills"
81
- },
82
- "devDependencies": {
83
- "@antfu/eslint-config": "catalog:cli",
84
- "@antfu/ni": "catalog:cli",
85
- "@antfu/utils": "catalog:inlined",
86
- "@deepseek-ai/cordis": "catalog:dsh",
87
- "@deepseek-ai/cordis-plugin-group": "catalog:dsh",
88
- "@deepseek-ai/cordis-plugin-include": "catalog:dsh",
89
- "@deepseek-ai/cordis-plugin-loader": "catalog:dsh",
90
- "@deepseek-ai/dsh-agent": "catalog:dsh",
91
- "@deepseek-ai/dsh-agent-default-model": "catalog:dsh",
92
- "@deepseek-ai/dsh-agent-loop": "catalog:dsh",
93
- "@deepseek-ai/dsh-agent-preset": "catalog:dsh",
94
- "@deepseek-ai/dsh-agent-preset-registry": "catalog:dsh",
95
- "@deepseek-ai/dsh-api-remotes": "catalog:dsh",
96
- "@deepseek-ai/dsh-api-session-controller": "catalog:dsh",
97
- "@deepseek-ai/dsh-api-workspace-controller": "catalog:dsh",
98
- "@deepseek-ai/dsh-client-connection": "catalog:dsh",
99
- "@deepseek-ai/dsh-client-locale": "catalog:dsh",
100
- "@deepseek-ai/dsh-client-store": "catalog:dsh",
101
- "@deepseek-ai/dsh-client-ui-conversation": "catalog:dsh",
102
- "@deepseek-ai/dsh-client-ui-input-trigger": "catalog:dsh",
103
- "@deepseek-ai/dsh-client-ui-layout": "catalog:dsh",
104
- "@deepseek-ai/dsh-client-ui-primitives": "catalog:dsh",
105
- "@deepseek-ai/dsh-client-ui-renderer": "catalog:dsh",
106
- "@deepseek-ai/dsh-client-ui-session": "catalog:dsh",
107
- "@deepseek-ai/dsh-client-ui-settings": "catalog:dsh",
108
- "@deepseek-ai/dsh-client-ui-sidebar-right": "catalog:dsh",
109
- "@deepseek-ai/dsh-client-ui-slots": "catalog:dsh",
110
- "@deepseek-ai/dsh-client-ui-theme": "catalog:dsh",
111
- "@deepseek-ai/dsh-client-ui-workspace": "catalog:dsh",
112
- "@deepseek-ai/dsh-host-webserver": "catalog:dsh",
113
- "@deepseek-ai/dsh-llm": "catalog:dsh",
114
- "@deepseek-ai/dsh-permission-presets": "catalog:dsh",
115
- "@deepseek-ai/dsh-session": "catalog:dsh",
116
- "@deepseek-ai/dsh-session-persistence": "catalog:dsh",
117
- "@deepseek-ai/dsh-session-projection": "catalog:dsh",
118
- "@deepseek-ai/dsh-skill": "catalog:dsh",
119
- "@deepseek-ai/dsh-skill-filesystem": "catalog:dsh",
120
- "@deepseek-ai/dsh-tools": "catalog:dsh",
121
- "@deepseek-ai/dsh-user-approval": "catalog:dsh",
122
- "@deepseek-ai/dsh-user-questions": "catalog:dsh",
123
- "@deepseek-ai/dsh-util-code-language": "catalog:dsh",
124
- "@deepseek-ai/dsh-util-values": "catalog:dsh",
125
- "@deepseek-ai/dsh-workspace": "catalog:dsh",
126
- "@types/node": "catalog:types",
127
- "@types/react": "catalog:react",
128
- "@types/react-dom": "catalog:react",
129
- "bumpp": "catalog:cli",
130
- "eslint": "catalog:cli",
131
- "nano-staged": "catalog:cli",
132
- "publint": "catalog:cli",
133
- "react": "catalog:react",
134
- "simple-git-hooks": "catalog:cli",
135
- "skills-npm": "catalog:cli",
136
- "tsdown": "catalog:cli",
137
- "tsnapi": "catalog:testing",
138
- "tsx": "catalog:cli",
139
- "typescript": "catalog:cli",
140
- "vite": "catalog:cli",
141
- "vitest": "catalog:testing"
142
- },
143
- "simple-git-hooks": {
144
- "pre-commit": "pnpm i --frozen-lockfile --ignore-scripts --offline && pnpm run build && npx nano-staged"
145
- },
146
- "nano-staged": {
147
- "*": "eslint --fix"
148
- }
149
- }
1
+ {
2
+ "name": "dsh-office-kit",
3
+ "type": "module",
4
+ "version": "0.3.0",
5
+ "description": "Office documents, PDF, presentations, and spreadsheets for DeepSeek Harness",
6
+ "author": "Hairy",
7
+ "license": "MIT",
8
+ "homepage": "https://github.com/hairyf/dsh-office-kit#readme",
9
+ "repository": {
10
+ "type": "git",
11
+ "url": "git+https://github.com/hairyf/dsh-office-kit.git"
12
+ },
13
+ "bugs": "https://github.com/hairyf/dsh-office-kit/issues",
14
+ "keywords": [
15
+ "dsh-plugin",
16
+ "deepseek-harness",
17
+ "office",
18
+ "docx",
19
+ "pdf",
20
+ "pptx",
21
+ "xlsx"
22
+ ],
23
+ "sideEffects": false,
24
+ "exports": {
25
+ ".": "./dist/index.js",
26
+ "./client": "./dist/client.js",
27
+ "./package.json": "./package.json"
28
+ },
29
+ "main": "./dist/index.js",
30
+ "module": "./dist/index.js",
31
+ "types": "./dist/index.d.ts",
32
+ "files": [
33
+ "CAPABILITY.md",
34
+ "README.md",
35
+ "assets",
36
+ "cordis.patch.yml",
37
+ "dist",
38
+ "postinstall.mjs",
39
+ "python"
40
+ ],
41
+ "dsh": {
42
+ "client": {
43
+ "inject": [
44
+ "@deepseek-ai/dsh-api-session-controller",
45
+ "@deepseek-ai/dsh-client-locale",
46
+ "@deepseek-ai/dsh-client-ui-layout",
47
+ "@deepseek-ai/dsh-client-ui-conversation",
48
+ "@deepseek-ai/dsh-client-ui-input-trigger",
49
+ "@deepseek-ai/dsh-client-ui-sidebar-right",
50
+ "@deepseek-ai/dsh-api-remotes"
51
+ ],
52
+ "platform": "web"
53
+ },
54
+ "bundle": {
55
+ "patch": "./cordis.patch.yml"
56
+ }
57
+ },
58
+ "scripts-info": {
59
+ "build": "Build the library for publishing",
60
+ "dev": "Rebuild on change during development",
61
+ "lint": "Check for code style issues",
62
+ "prepack": "Build before publishing",
63
+ "release": "Bump version and publish a release",
64
+ "start": "Run the entry file",
65
+ "test": "Run the test suite",
66
+ "typecheck": "Check types",
67
+ "prepare": "Set up git hooks and skills"
68
+ },
69
+ "devDependencies": {
70
+ "@antfu/eslint-config": "^9.1.0",
71
+ "@antfu/ni": "^30.2.0",
72
+ "@antfu/utils": "^9.3.0",
73
+ "@deepseek-ai/cordis": "4.0.5",
74
+ "@deepseek-ai/cordis-plugin-group": "1.0.5",
75
+ "@deepseek-ai/cordis-plugin-include": "1.0.10",
76
+ "@deepseek-ai/cordis-plugin-loader": "1.0.6",
77
+ "@deepseek-ai/dsh-agent": "0.2.1-rc.2",
78
+ "@deepseek-ai/dsh-agent-default-model": "0.2.1-rc.2",
79
+ "@deepseek-ai/dsh-agent-loop": "0.2.1-rc.2",
80
+ "@deepseek-ai/dsh-agent-preset": "0.2.1-rc.2",
81
+ "@deepseek-ai/dsh-agent-preset-registry": "0.2.1-rc.2",
82
+ "@deepseek-ai/dsh-api-remotes": "0.2.1-rc.2",
83
+ "@deepseek-ai/dsh-api-session-controller": "0.2.1-rc.2",
84
+ "@deepseek-ai/dsh-api-workspace-controller": "0.2.1-rc.2",
85
+ "@deepseek-ai/dsh-client-connection": "0.2.1-rc.2",
86
+ "@deepseek-ai/dsh-client-locale": "0.2.1-rc.2",
87
+ "@deepseek-ai/dsh-client-store": "0.2.1-rc.2",
88
+ "@deepseek-ai/dsh-client-ui-conversation": "0.2.1-rc.2",
89
+ "@deepseek-ai/dsh-client-ui-input-trigger": "0.2.1-rc.2",
90
+ "@deepseek-ai/dsh-client-ui-layout": "0.2.1-rc.2",
91
+ "@deepseek-ai/dsh-client-ui-primitives": "0.2.1-rc.2",
92
+ "@deepseek-ai/dsh-client-ui-renderer": "0.2.1-rc.2",
93
+ "@deepseek-ai/dsh-client-ui-session": "0.2.1-rc.2",
94
+ "@deepseek-ai/dsh-client-ui-settings": "0.2.1-rc.2",
95
+ "@deepseek-ai/dsh-client-ui-sidebar-right": "0.2.1-rc.2",
96
+ "@deepseek-ai/dsh-client-ui-slots": "0.2.1-rc.2",
97
+ "@deepseek-ai/dsh-client-ui-theme": "0.2.1-rc.2",
98
+ "@deepseek-ai/dsh-client-ui-workspace": "0.2.1-rc.2",
99
+ "@deepseek-ai/dsh-host-webserver": "0.2.1-rc.2",
100
+ "@deepseek-ai/dsh-llm": "0.2.1-rc.2",
101
+ "@deepseek-ai/dsh-permission-presets": "0.2.1-rc.2",
102
+ "@deepseek-ai/dsh-session": "0.2.1-rc.2",
103
+ "@deepseek-ai/dsh-session-persistence": "0.2.1-rc.2",
104
+ "@deepseek-ai/dsh-session-projection": "0.2.1-rc.2",
105
+ "@deepseek-ai/dsh-skill": "0.2.1-rc.2",
106
+ "@deepseek-ai/dsh-skill-filesystem": "0.2.1-rc.2",
107
+ "@deepseek-ai/dsh-tools": "0.2.1-rc.2",
108
+ "@deepseek-ai/dsh-user-approval": "0.2.1-rc.2",
109
+ "@deepseek-ai/dsh-user-questions": "0.2.1-rc.2",
110
+ "@deepseek-ai/dsh-util-code-language": "0.2.1-rc.2",
111
+ "@deepseek-ai/dsh-util-values": "0.2.1-rc.2",
112
+ "@deepseek-ai/dsh-workspace": "0.2.1-rc.2",
113
+ "@types/node": "^26.1.1",
114
+ "@types/react": "^18.2.0",
115
+ "@types/react-dom": "^18.2.0",
116
+ "bumpp": "^12.0.0",
117
+ "eslint": "^10.7.0",
118
+ "nano-staged": "^1.0.2",
119
+ "publint": "^0.3.21",
120
+ "react": "^18.2.0",
121
+ "simple-git-hooks": "^2.13.1",
122
+ "skills-npm": "^1.2.0",
123
+ "tsdown": "^0.22.12",
124
+ "tsnapi": "^1.0.0",
125
+ "tsx": "^4.23.1",
126
+ "typescript": "^6.0.3",
127
+ "vite": "^8.1.5",
128
+ "vitest": "^4.1.10"
129
+ },
130
+ "simple-git-hooks": {
131
+ "pre-commit": "pnpm i --frozen-lockfile --ignore-scripts --offline && pnpm run build && npx nano-staged"
132
+ },
133
+ "nano-staged": {
134
+ "*": "eslint --fix"
135
+ },
136
+ "scripts": {
137
+ "build": "tsdown",
138
+ "dev": "tsdown --watch",
139
+ "lint": "eslint",
140
+ "release": "bumpp",
141
+ "start": "tsx src/index.ts",
142
+ "test": "pnpm run build && vitest",
143
+ "typecheck": "tsc",
144
+ "postinstall": "node postinstall.mjs"
145
+ }
146
+ }
package/postinstall.mjs CHANGED
@@ -1,16 +1,18 @@
1
1
  #!/usr/bin/env node
2
2
  /* eslint-disable no-console */
3
3
  /**
4
- * dsh-office-kit postinstall.
4
+ * dsh-office-kit runtime bootstrap.
5
5
  *
6
6
  * Ensures a compatible Python (3.10–3.13) with the Office helper libraries is
7
- * available. On Windows a missing Python is downloaded from python.org,
8
- * signature-checked, installed silently into the per-user standard directory,
9
- * then isolated in a plugin-owned virtual environment.
7
+ * available. The virtual environment lives in `~/.dsh/office/runtime/venv` on
8
+ * every platform. On Windows a missing Python is downloaded from python.org,
9
+ * signature-checked and installed silently into the installer's own per-user
10
+ * location (AppendPath=1, no TargetDir, no manual registry edits).
10
11
  *
11
- * The plugin itself resolves the absolute interpreter path from its config
12
- * file; the user PATH is updated only as a convenience and never replaces
13
- * existing entries.
12
+ * The host half runs this file itself when the runtime is missing, so pnpm's
13
+ * lifecycle-script policy can never leave the plugin with a bare interpreter.
14
+ * The script is idempotent: a venv that already imports every dependency
15
+ * returns immediately. PATH is maintained by the Python installer, never here.
14
16
  */
15
17
 
16
18
  import { spawnSync } from 'node:child_process'
@@ -23,11 +25,17 @@ import { fileURLToPath } from 'node:url'
23
25
  const PACKAGE_ROOT = dirname(fileURLToPath(import.meta.url))
24
26
  const IS_WINDOWS = process.platform === 'win32'
25
27
  const PYTHON_VERSION = '3.12.10'
26
- const PYTHON_INSTALL_DIR = join(process.env.LOCALAPPDATA || join(homedir(), 'AppData', 'Local'), 'Programs', 'Python', 'Python312')
27
- const DATA_DIR = join(process.env.LOCALAPPDATA || join(homedir(), 'AppData', 'Local'), 'dsh-office-kit')
28
- const CONFIG_DIR = join(process.env.APPDATA || join(homedir(), 'AppData', 'Roaming'), 'dsh-office-kit')
29
- const VENV_DIR = join(DATA_DIR, 'venv')
28
+ const RUNTIME_DIR = join(homedir(), '.dsh', 'office', 'runtime')
29
+ const VENV_DIR = join(RUNTIME_DIR, 'venv')
30
30
  const VENV_PYTHON = join(VENV_DIR, IS_WINDOWS ? 'Scripts/python.exe' : 'bin/python')
31
+ const LEGACY_DATA_DIR = IS_WINDOWS
32
+ ? join(process.env.LOCALAPPDATA || join(homedir(), 'AppData', 'Local'), 'dsh-office-kit')
33
+ : process.platform === 'darwin'
34
+ ? join(homedir(), 'Library', 'Application Support', 'dsh-office-kit')
35
+ : join(process.env.XDG_DATA_HOME || join(homedir(), '.local', 'share'), 'dsh-office-kit')
36
+ const LEGACY_VENV_DIR = join(LEGACY_DATA_DIR, 'venv')
37
+ const LEGACY_VENV_PYTHON = join(LEGACY_VENV_DIR, IS_WINDOWS ? 'Scripts/python.exe' : 'bin/python')
38
+ const CONFIG_DIR = join(process.env.APPDATA || join(homedir(), 'AppData', 'Roaming'), 'dsh-office-kit')
31
39
  const CONFIG_FILE = join(CONFIG_DIR, 'config.json')
32
40
  const REQUIREMENTS = join(PACKAGE_ROOT, 'python', 'requirements.txt')
33
41
  const LOG_PREFIX = '[dsh-office-kit]'
@@ -118,10 +126,26 @@ function findCompatiblePython() {
118
126
  }
119
127
 
120
128
  // A ready virtual environment still works even if its base interpreter was removed.
121
- if (existsSync(VENV_PYTHON)) {
122
- const info = pythonInfo(VENV_PYTHON)
129
+ for (const venvPython of [VENV_PYTHON, LEGACY_VENV_PYTHON]) {
130
+ if (existsSync(venvPython)) {
131
+ const info = pythonInfo(venvPython)
132
+ if (info) {
133
+ return { executable: venvPython, args: [], info }
134
+ }
135
+ }
136
+ }
137
+ return null
138
+ }
139
+
140
+ /** The first existing virtual environment that still runs, new layout first. */
141
+ function workingVenv() {
142
+ for (const [python, directory] of [[VENV_PYTHON, VENV_DIR], [LEGACY_VENV_PYTHON, LEGACY_VENV_DIR]]) {
143
+ if (!existsSync(python)) {
144
+ continue
145
+ }
146
+ const info = pythonInfo(python)
123
147
  if (info) {
124
- return { executable: VENV_PYTHON, args: [], info }
148
+ return { python, directory, info }
125
149
  }
126
150
  }
127
151
  return null
@@ -159,20 +183,19 @@ function verifySignature(file) {
159
183
 
160
184
  function installPython() {
161
185
  if (!IS_WINDOWS) {
162
- return null
186
+ return false
163
187
  }
164
188
  // Unique per process: a stale installer from an interrupted run must not lock this download.
165
189
  const installer = join(tmpdir(), `python-${PYTHON_VERSION}-amd64-${process.pid}-${Date.now()}.exe`)
166
190
  const url = `https://www.python.org/ftp/python/${PYTHON_VERSION}/python-${PYTHON_VERSION}-amd64.exe`
167
191
  download(url, installer)
168
192
  verifySignature(installer)
169
- log(`installing Python ${PYTHON_VERSION} into ${PYTHON_INSTALL_DIR}`)
193
+ log(`installing Python ${PYTHON_VERSION} into the installer default per-user location`)
170
194
  const args = [
171
195
  '/quiet',
172
196
  'InstallAllUsers=0',
173
- `TargetDir=${PYTHON_INSTALL_DIR}`,
174
- 'PrependPath=0',
175
- 'Include_launcher=0',
197
+ 'AppendPath=1',
198
+ 'CompileAll=0',
176
199
  'Include_test=0',
177
200
  'Include_doc=0',
178
201
  'Include_pip=1',
@@ -183,17 +206,16 @@ function installPython() {
183
206
  if (result.status !== 0) {
184
207
  throw new Error(`Python installer exited with status ${result.status}`)
185
208
  }
186
- const target = join(PYTHON_INSTALL_DIR, 'python.exe')
187
- if (!existsSync(target)) {
188
- throw new Error(`Python installer finished but ${target} is missing`)
189
- }
190
- return target
209
+ return true
191
210
  }
192
211
 
193
212
  function ensureVenv(base) {
194
- const existing = pythonInfo(VENV_PYTHON)
213
+ const existing = workingVenv()
195
214
  if (existing) {
196
- return existing
215
+ if (existing.directory === LEGACY_VENV_DIR) {
216
+ log(`using the existing virtual environment at ${LEGACY_VENV_DIR} (legacy layout)`)
217
+ }
218
+ return existing.python
197
219
  }
198
220
  if (existsSync(VENV_DIR)) {
199
221
  warn(`replacing incomplete virtual environment at ${VENV_DIR}`)
@@ -209,15 +231,15 @@ function ensureVenv(base) {
209
231
  if (!info) {
210
232
  throw new Error('virtual environment interpreter is not executable')
211
233
  }
212
- return info
234
+ return VENV_PYTHON
213
235
  }
214
236
 
215
- function installRequirements() {
237
+ function installRequirements(python) {
216
238
  if (!existsSync(REQUIREMENTS)) {
217
239
  throw new Error(`requirements file missing: ${REQUIREMENTS}`)
218
240
  }
219
241
  log('installing Python packages (this may take a few minutes)')
220
- const result = spawnSync(VENV_PYTHON, ['-m', 'pip', 'install', '--disable-pip-version-check', '--no-input', '--upgrade', '-r', REQUIREMENTS], {
242
+ const result = spawnSync(python, ['-m', 'pip', 'install', '--disable-pip-version-check', '--no-input', '--upgrade', '-r', REQUIREMENTS], {
221
243
  stdio: 'inherit',
222
244
  timeout: 30 * 60 * 1000,
223
245
  })
@@ -226,10 +248,10 @@ function installRequirements() {
226
248
  }
227
249
  }
228
250
 
229
- function verifyImports() {
251
+ function verifyImports(python) {
230
252
  const modules = ['docx', 'openpyxl', 'pptx', 'pypdf', 'reportlab', 'pdfplumber', 'pymupdf', 'PIL', 'latex2mathml', 'mathml2omml']
231
253
  const script = `import importlib, json\nmissing = []\nfor name in ${JSON.stringify(modules)}:\n try:\n importlib.import_module(name)\n except Exception as exc:\n missing.append({"module": name, "error": f"{type(exc).__name__}: {exc}"})\nprint(json.dumps({"ok": not missing, "missing": missing}))`
232
- const result = spawnSync(VENV_PYTHON, ['-c', script], { encoding: 'utf8', timeout: 120000 })
254
+ const result = spawnSync(python, ['-c', script], { encoding: 'utf8', timeout: 120000 })
233
255
  if (result.status !== 0) {
234
256
  throw new Error(`import verification failed: ${(result.stderr || '').trim()}`)
235
257
  }
@@ -257,31 +279,17 @@ function writeConfig(config) {
257
279
  writeFileSync(CONFIG_FILE, `${JSON.stringify(config, null, 2)}\n`, 'utf8')
258
280
  }
259
281
 
260
- function addToUserPath(entries) {
261
- if (!IS_WINDOWS) {
262
- return
263
- }
264
- const script = [
265
- '$key = "HKCU:\\Environment"',
266
- '$item = Get-Item $key',
267
- '$current = [string]$item.GetValue("Path", "", "DoNotExpandEnvironmentNames")',
268
- '$parts = @($current -split ";" | Where-Object { $_ -ne "" })',
269
- '$changed = $false',
270
- 'foreach ($entry in ($env:DSH_PATH_ENTRIES -split ";")) { if ($entry -and ($parts -notcontains $entry)) { $parts += $entry; $changed = $true } }',
271
- 'if ($changed) { try { $item.SetValue("Path", ($parts -join ";"), "ExpandString"); Write-Output "updated" } catch { Write-Output "failed: $($_.Exception.Message)"; exit 3 } } else { Write-Output "unchanged" }',
272
- ].join('; ')
273
- const result = spawnSync('powershell', ['-NoProfile', '-NonInteractive', '-ExecutionPolicy', 'Bypass', '-Command', script], {
274
- encoding: 'utf8',
275
- env: { ...process.env, DSH_PATH_ENTRIES: entries.join(';') },
276
- timeout: 60000,
282
+ function writeReadyConfig(existingConfig, python, basePython, report) {
283
+ const info = pythonInfo(python)
284
+ writeConfig({
285
+ ...existingConfig,
286
+ python,
287
+ ...(basePython ? { basePython } : {}),
288
+ ...(info ? { pythonVersion: info.version.join('.') } : {}),
289
+ pluginVersion: readPackageVersion(),
290
+ updatedAt: new Date().toISOString(),
291
+ imports: report,
277
292
  })
278
- if (result.status !== 0) {
279
- warn(`could not update the user PATH: ${(result.stdout || result.stderr || '').trim()}`)
280
- warn('The plugin still resolves the verified interpreter by absolute path; reopen the terminal only after a successful PATH update.')
281
- }
282
- else {
283
- log(`user PATH ${(result.stdout || '').trim()}`)
284
- }
285
293
  }
286
294
 
287
295
  function main() {
@@ -295,17 +303,31 @@ function main() {
295
303
  }
296
304
 
297
305
  const existingConfig = readConfig()
298
- let base = findCompatiblePython()
299
306
 
307
+ // Fast path: an installed venv that already imports everything needs no network and no pip.
308
+ const ready = workingVenv()
309
+ if (ready) {
310
+ try {
311
+ const report = verifyImports(ready.python)
312
+ writeReadyConfig(existingConfig, ready.python, existingConfig.basePython, report)
313
+ log('Python environment is ready.')
314
+ log(`interpreter: ${ready.python}`)
315
+ return
316
+ }
317
+ catch (error) {
318
+ warn(`existing virtual environment needs repair: ${error.message}`)
319
+ }
320
+ }
321
+
322
+ let base = findCompatiblePython()
300
323
  if (!base) {
301
324
  if (!IS_WINDOWS) {
302
325
  warn('no compatible Python 3.10–3.13 was found. Install one and rerun `node postinstall.mjs`.')
326
+ process.exitCode = 1
303
327
  return
304
328
  }
305
329
  try {
306
- const installed = installPython()
307
- const info = installed ? pythonInfo(installed) : null
308
- base = installed && info ? { executable: installed, args: [], info } : null
330
+ installPython()
309
331
  }
310
332
  catch (error) {
311
333
  warn(`automatic Python installation failed: ${error.message}`)
@@ -313,34 +335,22 @@ function main() {
313
335
  process.exitCode = 1
314
336
  return
315
337
  }
316
- }
317
-
318
- if (!base) {
319
- warn('no compatible Python interpreter could be established.')
320
- process.exitCode = 1
321
- return
338
+ base = findCompatiblePython()
339
+ if (!base) {
340
+ warn('the Python installer finished but no compatible interpreter was found in the default per-user location.')
341
+ process.exitCode = 1
342
+ return
343
+ }
322
344
  }
323
345
 
324
346
  log(`using Python ${base.info.version.join('.')} at ${base.info.executable}`)
325
347
  try {
326
- ensureVenv(base)
327
- installRequirements()
328
- const report = verifyImports()
329
- const config = {
330
- ...existingConfig,
331
- python: VENV_PYTHON,
332
- basePython: base.info.executable,
333
- pythonVersion: base.info.version.join('.'),
334
- pluginVersion: readPackageVersion(),
335
- updatedAt: new Date().toISOString(),
336
- imports: report,
337
- }
338
- writeConfig(config)
339
- const pathEntries = IS_WINDOWS ? [dirname(base.info.executable), join(dirname(base.info.executable), 'Scripts')] : []
340
- addToUserPath(pathEntries)
348
+ const python = ensureVenv(base)
349
+ installRequirements(python)
350
+ const report = verifyImports(python)
351
+ writeReadyConfig(existingConfig, python, base.info.executable, report)
341
352
  log('Python environment is ready.')
342
- log(`interpreter: ${VENV_PYTHON}`)
343
- log('Open a new terminal for PATH changes to apply to new shells.')
353
+ log(`interpreter: ${python}`)
344
354
  }
345
355
  catch (error) {
346
356
  warn(`Python environment setup failed: ${error.message}`)