@jungjaehoon/mama-os 0.75.0 → 0.77.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 (260) hide show
  1. package/CHANGELOG.md +112 -0
  2. package/README.md +1 -1
  3. package/dist/api/attachment-actions.d.ts.map +1 -1
  4. package/dist/api/attachment-actions.js +8 -7
  5. package/dist/api/attachment-actions.js.map +1 -1
  6. package/dist/api/code-act-actions.d.ts +3 -1
  7. package/dist/api/code-act-actions.d.ts.map +1 -1
  8. package/dist/api/code-act-actions.js +21 -9
  9. package/dist/api/code-act-actions.js.map +1 -1
  10. package/dist/api/document-actions.d.ts +13 -0
  11. package/dist/api/document-actions.d.ts.map +1 -0
  12. package/dist/api/document-actions.js +55 -0
  13. package/dist/api/document-actions.js.map +1 -0
  14. package/dist/api/drive-actions.d.ts +4 -0
  15. package/dist/api/drive-actions.d.ts.map +1 -1
  16. package/dist/api/drive-actions.js +15 -7
  17. package/dist/api/drive-actions.js.map +1 -1
  18. package/dist/api/drive-delivery.d.ts.map +1 -1
  19. package/dist/api/drive-delivery.js +8 -3
  20. package/dist/api/drive-delivery.js.map +1 -1
  21. package/dist/api/member-enrollment.d.ts +9 -3
  22. package/dist/api/member-enrollment.d.ts.map +1 -1
  23. package/dist/api/member-enrollment.js +64 -16
  24. package/dist/api/member-enrollment.js.map +1 -1
  25. package/dist/api/member-export.d.ts.map +1 -1
  26. package/dist/api/member-export.js +14 -6
  27. package/dist/api/member-export.js.map +1 -1
  28. package/dist/api/member-lifecycle.d.ts +25 -4
  29. package/dist/api/member-lifecycle.d.ts.map +1 -1
  30. package/dist/api/member-lifecycle.js +88 -21
  31. package/dist/api/member-lifecycle.js.map +1 -1
  32. package/dist/api/member-notice-actions.d.ts +18 -0
  33. package/dist/api/member-notice-actions.d.ts.map +1 -0
  34. package/dist/api/member-notice-actions.js +184 -0
  35. package/dist/api/member-notice-actions.js.map +1 -0
  36. package/dist/api/member-records.d.ts +17 -2
  37. package/dist/api/member-records.d.ts.map +1 -1
  38. package/dist/api/member-records.js +440 -82
  39. package/dist/api/member-records.js.map +1 -1
  40. package/dist/api/member-share-actions.d.ts +3 -3
  41. package/dist/api/member-share-actions.d.ts.map +1 -1
  42. package/dist/api/member-share-actions.js +47 -20
  43. package/dist/api/member-share-actions.js.map +1 -1
  44. package/dist/api/owner-policy-actions.d.ts +1 -0
  45. package/dist/api/owner-policy-actions.d.ts.map +1 -1
  46. package/dist/api/owner-policy-actions.js +8 -4
  47. package/dist/api/owner-policy-actions.js.map +1 -1
  48. package/dist/api/owner-timezone-actions.d.ts +5 -2
  49. package/dist/api/owner-timezone-actions.d.ts.map +1 -1
  50. package/dist/api/owner-timezone-actions.js +4 -6
  51. package/dist/api/owner-timezone-actions.js.map +1 -1
  52. package/dist/api/personal-job-actions.d.ts +6 -0
  53. package/dist/api/personal-job-actions.d.ts.map +1 -0
  54. package/dist/api/personal-job-actions.js +72 -0
  55. package/dist/api/personal-job-actions.js.map +1 -0
  56. package/dist/api/security-events.d.ts +6 -1
  57. package/dist/api/security-events.d.ts.map +1 -1
  58. package/dist/api/security-events.js +34 -15
  59. package/dist/api/security-events.js.map +1 -1
  60. package/dist/api/skill-actions.d.ts +5 -0
  61. package/dist/api/skill-actions.d.ts.map +1 -0
  62. package/dist/api/skill-actions.js +66 -0
  63. package/dist/api/skill-actions.js.map +1 -0
  64. package/dist/api/source-actions.d.ts.map +1 -1
  65. package/dist/api/source-actions.js +4 -2
  66. package/dist/api/source-actions.js.map +1 -1
  67. package/dist/api/stored-source-reader.d.ts.map +1 -1
  68. package/dist/api/stored-source-reader.js +9 -2
  69. package/dist/api/stored-source-reader.js.map +1 -1
  70. package/dist/api/trello-actions.d.ts.map +1 -1
  71. package/dist/api/trello-actions.js +8 -2
  72. package/dist/api/trello-actions.js.map +1 -1
  73. package/dist/api/work-actions.d.ts +12 -2
  74. package/dist/api/work-actions.d.ts.map +1 -1
  75. package/dist/api/work-actions.js +57 -10
  76. package/dist/api/work-actions.js.map +1 -1
  77. package/dist/cli/commands/daemon.d.ts +12 -2
  78. package/dist/cli/commands/daemon.d.ts.map +1 -1
  79. package/dist/cli/commands/daemon.js +85 -13
  80. package/dist/cli/commands/daemon.js.map +1 -1
  81. package/dist/cli/commands/init.d.ts +4 -0
  82. package/dist/cli/commands/init.d.ts.map +1 -1
  83. package/dist/cli/commands/init.js +23 -0
  84. package/dist/cli/commands/init.js.map +1 -1
  85. package/dist/cli/commands/tools.d.ts +12 -0
  86. package/dist/cli/commands/tools.d.ts.map +1 -0
  87. package/dist/cli/commands/tools.js +109 -0
  88. package/dist/cli/commands/tools.js.map +1 -0
  89. package/dist/cli/index.js +6 -1
  90. package/dist/cli/index.js.map +1 -1
  91. package/dist/cli/runtime/claude-caller-config.d.ts +3 -1
  92. package/dist/cli/runtime/claude-caller-config.d.ts.map +1 -1
  93. package/dist/cli/runtime/claude-caller-config.js +14 -2
  94. package/dist/cli/runtime/claude-caller-config.js.map +1 -1
  95. package/dist/connectors/framework/polling-scheduler.d.ts +6 -1
  96. package/dist/connectors/framework/polling-scheduler.d.ts.map +1 -1
  97. package/dist/connectors/framework/polling-scheduler.js +25 -3
  98. package/dist/connectors/framework/polling-scheduler.js.map +1 -1
  99. package/dist/connectors/framework/stored-index-read.d.ts +2 -2
  100. package/dist/connectors/framework/stored-index-read.d.ts.map +1 -1
  101. package/dist/connectors/framework/stored-index-read.js +10 -3
  102. package/dist/connectors/framework/stored-index-read.js.map +1 -1
  103. package/dist/gateways/base-gateway.d.ts +7 -0
  104. package/dist/gateways/base-gateway.d.ts.map +1 -1
  105. package/dist/gateways/base-gateway.js +24 -0
  106. package/dist/gateways/base-gateway.js.map +1 -1
  107. package/dist/gateways/discord.d.ts +4 -0
  108. package/dist/gateways/discord.d.ts.map +1 -1
  109. package/dist/gateways/discord.js +24 -6
  110. package/dist/gateways/discord.js.map +1 -1
  111. package/dist/gateways/slack.d.ts +3 -0
  112. package/dist/gateways/slack.d.ts.map +1 -1
  113. package/dist/gateways/slack.js +15 -2
  114. package/dist/gateways/slack.js.map +1 -1
  115. package/dist/gateways/telegram-errors.d.ts +3 -0
  116. package/dist/gateways/telegram-errors.d.ts.map +1 -1
  117. package/dist/gateways/telegram-errors.js +5 -0
  118. package/dist/gateways/telegram-errors.js.map +1 -1
  119. package/dist/gateways/telegram-message-ledger.d.ts +7 -0
  120. package/dist/gateways/telegram-message-ledger.d.ts.map +1 -1
  121. package/dist/gateways/telegram-message-ledger.js +27 -2
  122. package/dist/gateways/telegram-message-ledger.js.map +1 -1
  123. package/dist/gateways/telegram.d.ts +24 -6
  124. package/dist/gateways/telegram.d.ts.map +1 -1
  125. package/dist/gateways/telegram.js +258 -44
  126. package/dist/gateways/telegram.js.map +1 -1
  127. package/dist/gateways/turn-contract.d.ts +6 -0
  128. package/dist/gateways/turn-contract.d.ts.map +1 -1
  129. package/dist/runtime/action-surface.d.ts +28 -3
  130. package/dist/runtime/action-surface.d.ts.map +1 -1
  131. package/dist/runtime/action-surface.js +316 -34
  132. package/dist/runtime/action-surface.js.map +1 -1
  133. package/dist/runtime/backend-security.d.ts +4 -0
  134. package/dist/runtime/backend-security.d.ts.map +1 -1
  135. package/dist/runtime/backend-security.js +8 -1
  136. package/dist/runtime/backend-security.js.map +1 -1
  137. package/dist/runtime/claude-caller-hook.d.ts +14 -0
  138. package/dist/runtime/claude-caller-hook.d.ts.map +1 -1
  139. package/dist/runtime/claude-caller-hook.js +21 -1
  140. package/dist/runtime/claude-caller-hook.js.map +1 -1
  141. package/dist/runtime/config.d.ts +6 -0
  142. package/dist/runtime/config.d.ts.map +1 -1
  143. package/dist/runtime/config.js +24 -0
  144. package/dist/runtime/config.js.map +1 -1
  145. package/dist/runtime/connectors.js +1 -1
  146. package/dist/runtime/connectors.js.map +1 -1
  147. package/dist/runtime/egress-proxy.d.ts +3 -3
  148. package/dist/runtime/egress-proxy.d.ts.map +1 -1
  149. package/dist/runtime/egress-proxy.js +16 -3
  150. package/dist/runtime/egress-proxy.js.map +1 -1
  151. package/dist/runtime/member-paths.d.ts +9 -1
  152. package/dist/runtime/member-paths.d.ts.map +1 -1
  153. package/dist/runtime/member-paths.js +67 -5
  154. package/dist/runtime/member-paths.js.map +1 -1
  155. package/dist/runtime/member-session.d.ts +21 -21
  156. package/dist/runtime/member-session.d.ts.map +1 -1
  157. package/dist/runtime/member-session.js +297 -34
  158. package/dist/runtime/member-session.js.map +1 -1
  159. package/dist/runtime/member-system-prompt.d.ts +3 -0
  160. package/dist/runtime/member-system-prompt.d.ts.map +1 -1
  161. package/dist/runtime/member-system-prompt.js +30 -4
  162. package/dist/runtime/member-system-prompt.js.map +1 -1
  163. package/dist/runtime/native-session.d.ts +8 -0
  164. package/dist/runtime/native-session.d.ts.map +1 -1
  165. package/dist/runtime/native-session.js +105 -17
  166. package/dist/runtime/native-session.js.map +1 -1
  167. package/dist/runtime/outbound-attempts.d.ts +5 -2
  168. package/dist/runtime/outbound-attempts.d.ts.map +1 -1
  169. package/dist/runtime/outbound-attempts.js +3 -2
  170. package/dist/runtime/outbound-attempts.js.map +1 -1
  171. package/dist/runtime/owner-authority.d.ts +16 -14
  172. package/dist/runtime/owner-authority.d.ts.map +1 -1
  173. package/dist/runtime/owner-authority.js +163 -7
  174. package/dist/runtime/owner-authority.js.map +1 -1
  175. package/dist/runtime/owner-runtime.d.ts +18 -5
  176. package/dist/runtime/owner-runtime.d.ts.map +1 -1
  177. package/dist/runtime/owner-runtime.js +429 -43
  178. package/dist/runtime/owner-runtime.js.map +1 -1
  179. package/dist/runtime/owner-system-prompt.d.ts +3 -1
  180. package/dist/runtime/owner-system-prompt.d.ts.map +1 -1
  181. package/dist/runtime/owner-system-prompt.js +16 -6
  182. package/dist/runtime/owner-system-prompt.js.map +1 -1
  183. package/dist/runtime/personal-job-cron.d.ts +6 -0
  184. package/dist/runtime/personal-job-cron.d.ts.map +1 -0
  185. package/dist/runtime/personal-job-cron.js +154 -0
  186. package/dist/runtime/personal-job-cron.js.map +1 -0
  187. package/dist/runtime/personal-jobs.d.ts +107 -0
  188. package/dist/runtime/personal-jobs.d.ts.map +1 -0
  189. package/dist/runtime/personal-jobs.js +353 -0
  190. package/dist/runtime/personal-jobs.js.map +1 -0
  191. package/dist/runtime/personal-notices.d.ts +38 -0
  192. package/dist/runtime/personal-notices.d.ts.map +1 -0
  193. package/dist/runtime/personal-notices.js +137 -0
  194. package/dist/runtime/personal-notices.js.map +1 -0
  195. package/dist/runtime/personal-turns.d.ts +23 -0
  196. package/dist/runtime/personal-turns.d.ts.map +1 -0
  197. package/dist/runtime/personal-turns.js +51 -0
  198. package/dist/runtime/personal-turns.js.map +1 -0
  199. package/dist/runtime/principal-access.d.ts +8 -0
  200. package/dist/runtime/principal-access.d.ts.map +1 -1
  201. package/dist/runtime/principal-access.js +70 -2
  202. package/dist/runtime/principal-access.js.map +1 -1
  203. package/dist/runtime/principal-sessions.d.ts +16 -2
  204. package/dist/runtime/principal-sessions.d.ts.map +1 -1
  205. package/dist/runtime/principal-sessions.js +104 -21
  206. package/dist/runtime/principal-sessions.js.map +1 -1
  207. package/dist/runtime/skills.d.ts +86 -0
  208. package/dist/runtime/skills.d.ts.map +1 -0
  209. package/dist/runtime/skills.js +560 -0
  210. package/dist/runtime/skills.js.map +1 -0
  211. package/dist/runtime/stimulus-delivery.d.ts +21 -1
  212. package/dist/runtime/stimulus-delivery.d.ts.map +1 -1
  213. package/dist/runtime/stimulus-delivery.js +185 -18
  214. package/dist/runtime/stimulus-delivery.js.map +1 -1
  215. package/dist/runtime/tools-paths.d.ts +9 -0
  216. package/dist/runtime/tools-paths.d.ts.map +1 -0
  217. package/dist/runtime/tools-paths.js +98 -0
  218. package/dist/runtime/tools-paths.js.map +1 -0
  219. package/dist/runtime/turn-orders.d.ts +22 -2
  220. package/dist/runtime/turn-orders.d.ts.map +1 -1
  221. package/dist/runtime/turn-orders.js +60 -6
  222. package/dist/runtime/turn-orders.js.map +1 -1
  223. package/dist/runtime/web-fetch-scope.d.ts +20 -0
  224. package/dist/runtime/web-fetch-scope.d.ts.map +1 -0
  225. package/dist/runtime/web-fetch-scope.js +68 -0
  226. package/dist/runtime/web-fetch-scope.js.map +1 -0
  227. package/dist/storage/chat-sources.d.ts +21 -0
  228. package/dist/storage/chat-sources.d.ts.map +1 -1
  229. package/dist/storage/chat-sources.js +65 -3
  230. package/dist/storage/chat-sources.js.map +1 -1
  231. package/dist/tools/command-runner.d.ts +12 -0
  232. package/dist/tools/command-runner.d.ts.map +1 -0
  233. package/dist/tools/command-runner.js +65 -0
  234. package/dist/tools/command-runner.js.map +1 -0
  235. package/dist/tools/document-render.d.ts +24 -0
  236. package/dist/tools/document-render.d.ts.map +1 -0
  237. package/dist/tools/document-render.js +208 -0
  238. package/dist/tools/document-render.js.map +1 -0
  239. package/dist/tools/document-toolkit.d.ts +15 -0
  240. package/dist/tools/document-toolkit.d.ts.map +1 -0
  241. package/dist/tools/document-toolkit.js +501 -0
  242. package/dist/tools/document-toolkit.js.map +1 -0
  243. package/dist/tools/office-render.d.ts +28 -0
  244. package/dist/tools/office-render.d.ts.map +1 -0
  245. package/dist/tools/office-render.js +101 -0
  246. package/dist/tools/office-render.js.map +1 -0
  247. package/dist/tools/toolkit-process.d.ts +9 -0
  248. package/dist/tools/toolkit-process.d.ts.map +1 -0
  249. package/dist/tools/toolkit-process.js +148 -0
  250. package/dist/tools/toolkit-process.js.map +1 -0
  251. package/dist/tools/toolkit-state.d.ts +22 -0
  252. package/dist/tools/toolkit-state.d.ts.map +1 -0
  253. package/dist/tools/toolkit-state.js +116 -0
  254. package/dist/tools/toolkit-state.js.map +1 -0
  255. package/package.json +3 -2
  256. package/toolkit/inspect-office-zip.py +16 -0
  257. package/toolkit/rasterize.py +29 -0
  258. package/toolkit/requirements.in +11 -0
  259. package/toolkit/requirements.lock +1643 -0
  260. package/toolkit/smoke.py +32 -0
@@ -0,0 +1,101 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.requireOfficeSandbox = requireOfficeSandbox;
4
+ exports.officeSandboxProfile = officeSandboxProfile;
5
+ exports.renderEnvironment = renderEnvironment;
6
+ exports.sandboxedCommand = sandboxedCommand;
7
+ exports.renderOffice = renderOffice;
8
+ const node_fs_1 = require("node:fs");
9
+ const node_path_1 = require("node:path");
10
+ const node_url_1 = require("node:url");
11
+ const backend_security_js_1 = require("../runtime/backend-security.js");
12
+ const command_runner_js_1 = require("./command-runner.js");
13
+ function requireOfficeSandbox(platform = process.platform) {
14
+ if (platform !== 'darwin')
15
+ throw new Error(`document.render requires macOS sandbox-exec to enforce read denies and the network deny; rendering is unavailable on ${platform}`);
16
+ }
17
+ /** Office needs an AF_UNIX bind in /tmp; that grants no outbound network. */
18
+ function officeSandboxProfile(temp, output, deniedReadPaths) {
19
+ const quoted = (path) => JSON.stringify(path);
20
+ return [
21
+ '(version 1)',
22
+ '(allow default)',
23
+ '(deny network*)',
24
+ '(allow network-bind network-inbound (local unix-socket))',
25
+ '(deny appleevent-send)',
26
+ '(deny file-write*)',
27
+ // LibreOffice checks that /tmp is writable, then binds its single-instance socket there
28
+ // (/tmp/OSL_PIPE_<uid>_SingleOfficeIPC_<hash>) whatever TMPDIR says; measured 2026-10-14.
29
+ `(allow file-write* ${[temp, output].map((path) => `(subpath ${quoted(path)})`).join(' ')} (literal "/private/tmp") (regex #"^/private/tmp/OSL_PIPE_[0-9]+_SingleOfficeIPC_[0-9a-f]+$"))`,
30
+ ...(deniedReadPaths.length
31
+ ? [
32
+ `(deny file-read* ${(0, backend_security_js_1.normalizeReadPaths)(deniedReadPaths)
33
+ .map((path) => `(subpath ${quoted(path)})`)
34
+ .join(' ')})`,
35
+ ]
36
+ : []),
37
+ // Every agent denies the host render root. Only this renderer may read its private child.
38
+ `(allow file-read* (subpath ${quoted(temp)}))`,
39
+ // LibreOffice stats that child's parent, the render root; denied, it waits until the timeout
40
+ // (measured 2026-10-15). Metadata of the root alone lists no other render.
41
+ `(allow file-read-metadata (literal ${quoted((0, node_path_1.dirname)(temp))}))`,
42
+ ].join('\n');
43
+ }
44
+ function renderEnvironment(versionDir, fontconfig, temp) {
45
+ return {
46
+ ...(0, backend_security_js_1.backendEnvironment)(),
47
+ HOME: temp,
48
+ TMPDIR: temp,
49
+ XDG_CACHE_HOME: (0, node_path_1.join)(temp, 'cache'),
50
+ XDG_CONFIG_HOME: (0, node_path_1.join)(temp, 'config'),
51
+ FONTCONFIG_FILE: fontconfig,
52
+ FONTCONFIG_PATH: versionDir,
53
+ // LibreOffice's bundled Python would write __pycache__ into the app and break its seal.
54
+ PYTHONDONTWRITEBYTECODE: '1',
55
+ PATH: `${(0, node_path_1.join)(versionDir, 'bin')}:${process.env.PATH ?? '/usr/bin:/bin'}`,
56
+ };
57
+ }
58
+ async function sandboxedCommand(options) {
59
+ requireOfficeSandbox(options.platform);
60
+ const run = options.run ?? command_runner_js_1.runCommand;
61
+ return run('/usr/bin/sandbox-exec', [
62
+ '-p',
63
+ officeSandboxProfile(options.temp, options.output, options.deniedReadPaths),
64
+ options.command,
65
+ ...options.args,
66
+ ], { env: options.env, cwd: options.temp, timeoutMs: options.timeoutMs });
67
+ }
68
+ async function renderOffice(options) {
69
+ const profile = (0, node_path_1.join)(options.temp, 'profile');
70
+ (0, node_fs_1.mkdirSync)((0, node_path_1.join)(profile, 'user'), { recursive: true });
71
+ (0, node_fs_1.writeFileSync)((0, node_path_1.join)(profile, 'user', 'registrymodifications.xcu'), '<?xml version="1.0" encoding="UTF-8"?>\n' +
72
+ '<oor:items xmlns:oor="http://openoffice.org/2001/registry">' +
73
+ '<item oor:path="/org.openoffice.Office.Common/Security/Scripting">' +
74
+ '<prop oor:name="MacroSecurityLevel" oor:op="fuse"><value>3</value></prop>' +
75
+ '<prop oor:name="DisableMacrosExecution" oor:op="fuse"><value>true</value></prop>' +
76
+ '<prop oor:name="BlockUntrustedRefererLinks" oor:op="fuse"><value>true</value></prop>' +
77
+ '</item>' +
78
+ // Writer's Link: 2 is Never (1 is On Request); Calc's Link: 1 is Never.
79
+ '<item oor:path="/org.openoffice.Office.Writer/Content/Update">' +
80
+ '<prop oor:name="Link" oor:op="fuse"><value>2</value></prop></item>' +
81
+ '<item oor:path="/org.openoffice.Office.Calc/Content/Update">' +
82
+ '<prop oor:name="Link" oor:op="fuse"><value>1</value></prop></item>' +
83
+ '</oor:items>\n', { mode: 0o600 });
84
+ await sandboxedCommand({
85
+ ...options,
86
+ command: options.soffice,
87
+ args: [
88
+ '--headless',
89
+ '--nologo',
90
+ '--nodefault',
91
+ '--norestore',
92
+ `-env:UserInstallation=${(0, node_url_1.pathToFileURL)(profile).href}`,
93
+ '--convert-to',
94
+ 'pdf',
95
+ '--outdir',
96
+ options.output,
97
+ options.input,
98
+ ],
99
+ });
100
+ }
101
+ //# sourceMappingURL=office-render.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"office-render.js","sourceRoot":"","sources":["../../src/tools/office-render.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ /** Kill command groups before releasing their locks, even when no finally can run. */
2
+ export declare function onToolkitSignal(cleanup: () => void, options?: {
3
+ exit?: boolean;
4
+ }): () => void;
5
+ export declare function pidIsAlive(pid: number): boolean;
6
+ export declare function liveToolkitLease(path: string): boolean;
7
+ /** Publish a nonempty lock atomically; unique owner files make concurrent stale recovery safe. */
8
+ export declare function tryToolkitLock(path: string): (() => void) | null;
9
+ //# sourceMappingURL=toolkit-process.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"toolkit-process.d.ts","sourceRoot":"","sources":["../../src/tools/toolkit-process.ts"],"names":[],"mappings":"AAkBA,sFAAsF;AACtF,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,IAAI,EAAE,OAAO,GAAE;IAAE,IAAI,CAAC,EAAE,OAAO,CAAA;CAAO,GAAG,MAAM,IAAI,CA4BjG;AAED,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAW/C;AAED,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAUtD;AAED,kGAAkG;AAClG,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,CAAC,MAAM,IAAI,CAAC,GAAG,IAAI,CA6DhE"}
@@ -0,0 +1,148 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.onToolkitSignal = onToolkitSignal;
4
+ exports.pidIsAlive = pidIsAlive;
5
+ exports.liveToolkitLease = liveToolkitLease;
6
+ exports.tryToolkitLock = tryToolkitLock;
7
+ const node_fs_1 = require("node:fs");
8
+ const node_crypto_1 = require("node:crypto");
9
+ const node_path_1 = require("node:path");
10
+ const signals = { SIGINT: 130, SIGHUP: 129, SIGTERM: 143 };
11
+ const cleanups = new Map();
12
+ const handlers = new Map();
13
+ /** Kill command groups before releasing their locks, even when no finally can run. */
14
+ function onToolkitSignal(cleanup, options = {}) {
15
+ if (!cleanups.size) {
16
+ for (const [signal, code] of Object.entries(signals)) {
17
+ const handler = () => {
18
+ let exit = false;
19
+ for (const [release, exitOnSignal] of [...cleanups].reverse()) {
20
+ exit ||= exitOnSignal;
21
+ try {
22
+ release();
23
+ }
24
+ catch (error) {
25
+ process.stderr.write(`Document toolkit cleanup failed: ${String(error)}\n`);
26
+ }
27
+ }
28
+ // Daemon shutdown owns its async stop. Only the host install CLI requests exit.
29
+ if (exit)
30
+ process.exit(code);
31
+ };
32
+ handlers.set(signal, handler);
33
+ process.on(signal, handler);
34
+ }
35
+ }
36
+ cleanups.set(cleanup, options.exit === true);
37
+ return () => {
38
+ cleanups.delete(cleanup);
39
+ if (!cleanups.size) {
40
+ for (const [signal, handler] of handlers)
41
+ process.removeListener(signal, handler);
42
+ handlers.clear();
43
+ }
44
+ };
45
+ }
46
+ function pidIsAlive(pid) {
47
+ if (!Number.isSafeInteger(pid) || pid <= 0)
48
+ return false;
49
+ try {
50
+ process.kill(pid, 0);
51
+ return true;
52
+ }
53
+ catch (error) {
54
+ if (error.code === 'ESRCH')
55
+ return false;
56
+ // EPERM still proves that the process exists. Other errors must be visible.
57
+ if (error.code === 'EPERM')
58
+ return true;
59
+ throw error;
60
+ }
61
+ }
62
+ function liveToolkitLease(path) {
63
+ let owner;
64
+ try {
65
+ owner = (0, node_fs_1.readFileSync)(path, 'utf8');
66
+ }
67
+ catch (error) {
68
+ // A render released its lease between the directory scan and this read.
69
+ if (error.code === 'ENOENT')
70
+ return false;
71
+ throw error;
72
+ }
73
+ return pidIsAlive(Number(owner.trim()));
74
+ }
75
+ /** Publish a nonempty lock atomically; unique owner files make concurrent stale recovery safe. */
76
+ function tryToolkitLock(path) {
77
+ const candidate = (0, node_fs_1.mkdtempSync)(`${path}.`);
78
+ const owner = `${process.pid}-${(0, node_crypto_1.randomUUID)()}`;
79
+ (0, node_fs_1.writeFileSync)((0, node_path_1.join)(candidate, owner), String(process.pid), { mode: 0o600 });
80
+ const removeEmpty = () => {
81
+ try {
82
+ (0, node_fs_1.rmdirSync)(path);
83
+ }
84
+ catch (error) {
85
+ if (!['ENOENT', 'ENOTEMPTY', 'EEXIST'].includes(error.code ?? ''))
86
+ throw error;
87
+ }
88
+ };
89
+ try {
90
+ for (;;) {
91
+ try {
92
+ (0, node_fs_1.renameSync)(candidate, path);
93
+ const release = () => {
94
+ (0, node_fs_1.rmSync)((0, node_path_1.join)(path, owner), { force: true });
95
+ removeEmpty();
96
+ };
97
+ const unregister = onToolkitSignal(release);
98
+ return () => {
99
+ try {
100
+ release();
101
+ }
102
+ finally {
103
+ unregister();
104
+ }
105
+ };
106
+ }
107
+ catch (error) {
108
+ if (!['EEXIST', 'ENOTEMPTY', 'ENOTDIR'].includes(error.code ?? ''))
109
+ throw error;
110
+ try {
111
+ if (!(0, node_fs_1.lstatSync)(path).isDirectory()) {
112
+ // Recover an earlier PID-file lock, without removing a replacement directory.
113
+ if (liveToolkitLease(path))
114
+ return null;
115
+ try {
116
+ (0, node_fs_1.unlinkSync)(path);
117
+ }
118
+ catch (error) {
119
+ const code = error.code;
120
+ if (code === 'EPERM' && (0, node_fs_1.lstatSync)(path).isDirectory())
121
+ continue;
122
+ if (!['ENOENT', 'EISDIR'].includes(code ?? ''))
123
+ throw error;
124
+ }
125
+ }
126
+ else {
127
+ for (const name of (0, node_fs_1.readdirSync)(path)) {
128
+ const entry = (0, node_path_1.join)(path, name);
129
+ if (liveToolkitLease(entry))
130
+ return null;
131
+ // A newly published lock always has a different owner filename.
132
+ (0, node_fs_1.rmSync)(entry, { force: true });
133
+ }
134
+ removeEmpty();
135
+ }
136
+ }
137
+ catch (error) {
138
+ if (error.code !== 'ENOENT')
139
+ throw error;
140
+ }
141
+ }
142
+ }
143
+ }
144
+ finally {
145
+ (0, node_fs_1.rmSync)(candidate, { recursive: true, force: true });
146
+ }
147
+ }
148
+ //# sourceMappingURL=toolkit-process.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"toolkit-process.js","sourceRoot":"","sources":["../../src/tools/toolkit-process.ts"],"names":[],"mappings":";;AAmBA,0CA4BC;AAED,gCAWC;AAED,4CAUC;AAGD,wCA6DC;AAxID,qCAUiB;AACjB,6CAAyC;AACzC,yCAAiC;AAEjC,MAAM,OAAO,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,OAAO,EAAE,GAAG,EAAW,CAAC;AACpE,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAuB,CAAC;AAChD,MAAM,QAAQ,GAAG,IAAI,GAAG,EAA8B,CAAC;AAEvD,sFAAsF;AACtF,SAAgB,eAAe,CAAC,OAAmB,EAAE,UAA8B,EAAE;IACnF,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC;QACnB,KAAK,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;YACrD,MAAM,OAAO,GAAG,GAAG,EAAE;gBACnB,IAAI,IAAI,GAAG,KAAK,CAAC;gBACjB,KAAK,MAAM,CAAC,OAAO,EAAE,YAAY,CAAC,IAAI,CAAC,GAAG,QAAQ,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC;oBAC9D,IAAI,KAAK,YAAY,CAAC;oBACtB,IAAI,CAAC;wBACH,OAAO,EAAE,CAAC;oBACZ,CAAC;oBAAC,OAAO,KAAK,EAAE,CAAC;wBACf,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,oCAAoC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;oBAC9E,CAAC;gBACH,CAAC;gBACD,gFAAgF;gBAChF,IAAI,IAAI;oBAAE,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAC/B,CAAC,CAAC;YACF,QAAQ,CAAC,GAAG,CAAC,MAAwB,EAAE,OAAO,CAAC,CAAC;YAChD,OAAO,CAAC,EAAE,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QAC9B,CAAC;IACH,CAAC;IACD,QAAQ,CAAC,GAAG,CAAC,OAAO,EAAE,OAAO,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC;IAC7C,OAAO,GAAG,EAAE;QACV,QAAQ,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;QACzB,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC;YACnB,KAAK,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,IAAI,QAAQ;gBAAE,OAAO,CAAC,cAAc,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;YAClF,QAAQ,CAAC,KAAK,EAAE,CAAC;QACnB,CAAC;IACH,CAAC,CAAC;AACJ,CAAC;AAED,SAAgB,UAAU,CAAC,GAAW;IACpC,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,GAAG,CAAC,IAAI,GAAG,IAAI,CAAC;QAAE,OAAO,KAAK,CAAC;IACzD,IAAI,CAAC;QACH,OAAO,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;QACrB,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAK,KAA+B,CAAC,IAAI,KAAK,OAAO;YAAE,OAAO,KAAK,CAAC;QACpE,4EAA4E;QAC5E,IAAK,KAA+B,CAAC,IAAI,KAAK,OAAO;YAAE,OAAO,IAAI,CAAC;QACnE,MAAM,KAAK,CAAC;IACd,CAAC;AACH,CAAC;AAED,SAAgB,gBAAgB,CAAC,IAAY;IAC3C,IAAI,KAAa,CAAC;IAClB,IAAI,CAAC;QACH,KAAK,GAAG,IAAA,sBAAY,EAAC,IAAI,EAAE,MAAM,CAAC,CAAC;IACrC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,wEAAwE;QACxE,IAAK,KAA+B,CAAC,IAAI,KAAK,QAAQ;YAAE,OAAO,KAAK,CAAC;QACrE,MAAM,KAAK,CAAC;IACd,CAAC;IACD,OAAO,UAAU,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;AAC1C,CAAC;AAED,kGAAkG;AAClG,SAAgB,cAAc,CAAC,IAAY;IACzC,MAAM,SAAS,GAAG,IAAA,qBAAW,EAAC,GAAG,IAAI,GAAG,CAAC,CAAC;IAC1C,MAAM,KAAK,GAAG,GAAG,OAAO,CAAC,GAAG,IAAI,IAAA,wBAAU,GAAE,EAAE,CAAC;IAC/C,IAAA,uBAAa,EAAC,IAAA,gBAAI,EAAC,SAAS,EAAE,KAAK,CAAC,EAAE,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;IAC5E,MAAM,WAAW,GAAG,GAAG,EAAE;QACvB,IAAI,CAAC;YACH,IAAA,mBAAS,EAAC,IAAI,CAAC,CAAC;QAClB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,CAAC,CAAC,QAAQ,EAAE,WAAW,EAAE,QAAQ,CAAC,CAAC,QAAQ,CAAE,KAA+B,CAAC,IAAI,IAAI,EAAE,CAAC;gBAC1F,MAAM,KAAK,CAAC;QAChB,CAAC;IACH,CAAC,CAAC;IACF,IAAI,CAAC;QACH,SAAS,CAAC;YACR,IAAI,CAAC;gBACH,IAAA,oBAAU,EAAC,SAAS,EAAE,IAAI,CAAC,CAAC;gBAC5B,MAAM,OAAO,GAAG,GAAG,EAAE;oBACnB,IAAA,gBAAM,EAAC,IAAA,gBAAI,EAAC,IAAI,EAAE,KAAK,CAAC,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;oBAC3C,WAAW,EAAE,CAAC;gBAChB,CAAC,CAAC;gBACF,MAAM,UAAU,GAAG,eAAe,CAAC,OAAO,CAAC,CAAC;gBAC5C,OAAO,GAAG,EAAE;oBACV,IAAI,CAAC;wBACH,OAAO,EAAE,CAAC;oBACZ,CAAC;4BAAS,CAAC;wBACT,UAAU,EAAE,CAAC;oBACf,CAAC;gBACH,CAAC,CAAC;YACJ,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,IACE,CAAC,CAAC,QAAQ,EAAE,WAAW,EAAE,SAAS,CAAC,CAAC,QAAQ,CAAE,KAA+B,CAAC,IAAI,IAAI,EAAE,CAAC;oBAEzF,MAAM,KAAK,CAAC;gBACd,IAAI,CAAC;oBACH,IAAI,CAAC,IAAA,mBAAS,EAAC,IAAI,CAAC,CAAC,WAAW,EAAE,EAAE,CAAC;wBACnC,8EAA8E;wBAC9E,IAAI,gBAAgB,CAAC,IAAI,CAAC;4BAAE,OAAO,IAAI,CAAC;wBACxC,IAAI,CAAC;4BACH,IAAA,oBAAU,EAAC,IAAI,CAAC,CAAC;wBACnB,CAAC;wBAAC,OAAO,KAAK,EAAE,CAAC;4BACf,MAAM,IAAI,GAAI,KAA+B,CAAC,IAAI,CAAC;4BACnD,IAAI,IAAI,KAAK,OAAO,IAAI,IAAA,mBAAS,EAAC,IAAI,CAAC,CAAC,WAAW,EAAE;gCAAE,SAAS;4BAChE,IAAI,CAAC,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC,QAAQ,CAAC,IAAI,IAAI,EAAE,CAAC;gCAAE,MAAM,KAAK,CAAC;wBAC9D,CAAC;oBACH,CAAC;yBAAM,CAAC;wBACN,KAAK,MAAM,IAAI,IAAI,IAAA,qBAAW,EAAC,IAAI,CAAC,EAAE,CAAC;4BACrC,MAAM,KAAK,GAAG,IAAA,gBAAI,EAAC,IAAI,EAAE,IAAI,CAAC,CAAC;4BAC/B,IAAI,gBAAgB,CAAC,KAAK,CAAC;gCAAE,OAAO,IAAI,CAAC;4BACzC,gEAAgE;4BAChE,IAAA,gBAAM,EAAC,KAAK,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;wBACjC,CAAC;wBACD,WAAW,EAAE,CAAC;oBAChB,CAAC;gBACH,CAAC;gBAAC,OAAO,KAAK,EAAE,CAAC;oBACf,IAAK,KAA+B,CAAC,IAAI,KAAK,QAAQ;wBAAE,MAAM,KAAK,CAAC;gBACtE,CAAC;YACH,CAAC;QACH,CAAC;IACH,CAAC;YAAS,CAAC;QACT,IAAA,gBAAM,EAAC,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IACtD,CAAC;AACH,CAAC"}
@@ -0,0 +1,22 @@
1
+ export declare const TOOLKIT_INSTALL_COMMAND = "mama tools install";
2
+ export declare const TOOLKIT_ASSETS: string;
3
+ export declare const TOOLKIT_VERSION_NAME: RegExp;
4
+ export declare const TOOLKIT_LEASE_NAME: RegExp;
5
+ /** Never follow a shared lease directory link, at either installation or rendering. */
6
+ export declare function toolkitLeaseDirectory(root: string, create?: boolean): string | null;
7
+ export interface DocumentToolkit {
8
+ versionDir: string;
9
+ python: string;
10
+ soffice: string;
11
+ fontconfig: string;
12
+ }
13
+ /** Broken/absent installations disable the toolkit; unsafe ownership remains a hard error. */
14
+ export declare function readDocumentToolkit(root?: string, onBroken?: (error: Error) => void): DocumentToolkit | null;
15
+ export declare function requireDocumentToolkit(root?: string): DocumentToolkit;
16
+ /** Switch/prune and render leasing are mutually exclusive, across installer/daemon processes. */
17
+ export declare function withToolkitState<T>(root: string, work: () => T): Promise<T>;
18
+ export declare function leaseDocumentToolkit(root?: string): Promise<{
19
+ toolkit: DocumentToolkit;
20
+ release: () => void;
21
+ }>;
22
+ //# sourceMappingURL=toolkit-state.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"toolkit-state.d.ts","sourceRoot":"","sources":["../../src/tools/toolkit-state.ts"],"names":[],"mappings":"AAeA,eAAO,MAAM,uBAAuB,uBAAuB,CAAC;AAC5D,eAAO,MAAM,cAAc,QAAmC,CAAC;AAE/D,eAAO,MAAM,oBAAoB,QAAiC,CAAC;AACnE,eAAO,MAAM,kBAAkB,QAA2C,CAAC;AAE3E,uFAAuF;AACvF,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,UAAQ,GAAG,MAAM,GAAG,IAAI,CAiBjF;AAED,MAAM,WAAW,eAAe;IAC9B,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,8FAA8F;AAC9F,wBAAgB,mBAAmB,CACjC,IAAI,CAAC,EAAE,MAAM,EACb,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,GAChC,eAAe,GAAG,IAAI,CA+BxB;AAED,wBAAgB,sBAAsB,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,eAAe,CAOrE;AAED,iGAAiG;AACjG,wBAAsB,gBAAgB,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAkBjF;AAED,wBAAsB,oBAAoB,CACxC,IAAI,CAAC,EAAE,MAAM,GACZ,OAAO,CAAC;IAAE,OAAO,EAAE,eAAe,CAAC;IAAC,OAAO,EAAE,MAAM,IAAI,CAAA;CAAE,CAAC,CAwB5D"}
@@ -0,0 +1,116 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.TOOLKIT_LEASE_NAME = exports.TOOLKIT_VERSION_NAME = exports.TOOLKIT_ASSETS = exports.TOOLKIT_INSTALL_COMMAND = void 0;
4
+ exports.toolkitLeaseDirectory = toolkitLeaseDirectory;
5
+ exports.readDocumentToolkit = readDocumentToolkit;
6
+ exports.requireDocumentToolkit = requireDocumentToolkit;
7
+ exports.withToolkitState = withToolkitState;
8
+ exports.leaseDocumentToolkit = leaseDocumentToolkit;
9
+ const node_fs_1 = require("node:fs");
10
+ const node_crypto_1 = require("node:crypto");
11
+ const node_path_1 = require("node:path");
12
+ const tools_paths_js_1 = require("../runtime/tools-paths.js");
13
+ const toolkit_process_js_1 = require("./toolkit-process.js");
14
+ exports.TOOLKIT_INSTALL_COMMAND = 'mama tools install';
15
+ exports.TOOLKIT_ASSETS = (0, node_path_1.join)(__dirname, '../../toolkit');
16
+ const uuid = '[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}';
17
+ exports.TOOLKIT_VERSION_NAME = new RegExp(`^v-\\d+-${uuid}$`);
18
+ exports.TOOLKIT_LEASE_NAME = new RegExp(`^v-\\d+-${uuid}\\.${uuid}$`);
19
+ /** Never follow a shared lease directory link, at either installation or rendering. */
20
+ function toolkitLeaseDirectory(root, create = false) {
21
+ const path = (0, node_path_1.join)(root, '.leases');
22
+ let meta;
23
+ try {
24
+ meta = (0, node_fs_1.lstatSync)(path);
25
+ }
26
+ catch (error) {
27
+ if (error.code !== 'ENOENT')
28
+ throw error;
29
+ if (!create)
30
+ return null;
31
+ (0, node_fs_1.mkdirSync)(path, { mode: 0o700 });
32
+ meta = (0, node_fs_1.lstatSync)(path);
33
+ }
34
+ const uid = process.getuid?.();
35
+ if (!meta.isDirectory() || uid === undefined || meta.uid !== uid)
36
+ throw new Error(`Document toolkit: left ${path} untouched; require a real directory owned by uid ${uid}`);
37
+ return path;
38
+ }
39
+ /** Broken/absent installations disable the toolkit; unsafe ownership remains a hard error. */
40
+ function readDocumentToolkit(root, onBroken) {
41
+ if (root)
42
+ (0, tools_paths_js_1.assertToolsOwnership)(root);
43
+ try {
44
+ if (!root || !(0, node_fs_1.existsSync)((0, node_path_1.join)(root, 'current')))
45
+ return null;
46
+ const versionDir = (0, node_fs_1.realpathSync)((0, node_path_1.join)(root, 'current'));
47
+ const offset = (0, node_path_1.relative)((0, node_fs_1.realpathSync)(root), versionDir);
48
+ if (offset !== (0, node_path_1.basename)(versionDir) || offset.includes(node_path_1.sep) || !offset.startsWith('v-'))
49
+ throw new Error(`Invalid document toolkit current link; run ${exports.TOOLKIT_INSTALL_COMMAND}`);
50
+ const manifest = JSON.parse((0, node_fs_1.readFileSync)((0, node_path_1.join)(versionDir, 'manifest.json'), 'utf8'));
51
+ const python = (0, node_path_1.join)(versionDir, 'bin', 'python3');
52
+ const fontconfig = (0, node_path_1.join)(versionDir, 'fonts.conf');
53
+ if (manifest.version !== 1 ||
54
+ typeof manifest.soffice !== 'string' ||
55
+ ![python, fontconfig, (0, node_path_1.join)(versionDir, 'pyvenv.cfg'), manifest.soffice].every((path) => (0, node_fs_1.existsSync)(path) && (0, node_fs_1.statSync)(path).isFile()))
56
+ throw new Error(`Incomplete document toolkit; run ${exports.TOOLKIT_INSTALL_COMMAND}`);
57
+ return { versionDir, python, soffice: manifest.soffice, fontconfig };
58
+ }
59
+ catch (error) {
60
+ onBroken?.(new Error(`Document toolkit unavailable: ${error instanceof Error ? error.message : String(error)}; run ${exports.TOOLKIT_INSTALL_COMMAND}`));
61
+ return null;
62
+ }
63
+ }
64
+ function requireDocumentToolkit(root) {
65
+ const toolkit = readDocumentToolkit(root);
66
+ if (!toolkit)
67
+ throw new Error(`Document toolkit is missing; ask the owner to run ${exports.TOOLKIT_INSTALL_COMMAND} on the host`);
68
+ return toolkit;
69
+ }
70
+ /** Switch/prune and render leasing are mutually exclusive, across installer/daemon processes. */
71
+ async function withToolkitState(root, work) {
72
+ const lock = (0, node_path_1.join)(root, '.state-lock');
73
+ const deadline = Date.now() + 30_000;
74
+ let release;
75
+ for (;;) {
76
+ release = (0, toolkit_process_js_1.tryToolkitLock)(lock);
77
+ if (release)
78
+ break;
79
+ if (Date.now() >= deadline)
80
+ throw new Error(`Document toolkit state is busy at ${lock}; retry after the host install finishes`);
81
+ await new Promise((resolve) => setTimeout(resolve, 25));
82
+ }
83
+ try {
84
+ return work();
85
+ }
86
+ finally {
87
+ release();
88
+ }
89
+ }
90
+ async function leaseDocumentToolkit(root) {
91
+ // An absent tools_root never attempts filesystem writes.
92
+ if (!root || !(0, node_fs_1.existsSync)(root)) {
93
+ requireDocumentToolkit(root);
94
+ }
95
+ (0, tools_paths_js_1.assertToolsOwnership)(root);
96
+ return withToolkitState(root, () => {
97
+ const toolkit = requireDocumentToolkit(root);
98
+ const directory = toolkitLeaseDirectory(root, true);
99
+ const lease = (0, node_path_1.join)(directory, `${(0, node_path_1.basename)(toolkit.versionDir)}.${(0, node_crypto_1.randomUUID)()}`);
100
+ (0, node_fs_1.writeFileSync)(lease, String(process.pid), { flag: 'wx', mode: 0o600 });
101
+ const release = () => (0, node_fs_1.rmSync)(lease, { force: true });
102
+ const unregister = (0, toolkit_process_js_1.onToolkitSignal)(release);
103
+ return {
104
+ toolkit,
105
+ release: () => {
106
+ try {
107
+ release();
108
+ }
109
+ finally {
110
+ unregister();
111
+ }
112
+ },
113
+ };
114
+ });
115
+ }
116
+ //# sourceMappingURL=toolkit-state.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"toolkit-state.js","sourceRoot":"","sources":["../../src/tools/toolkit-state.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jungjaehoon/mama-os",
3
- "version": "0.75.0",
3
+ "version": "0.77.0",
4
4
  "description": "MAMA OS - The local work agent behind your messenger.",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",
@@ -42,6 +42,7 @@
42
42
  "dist",
43
43
  "public",
44
44
  "db",
45
+ "toolkit",
45
46
  "README.md",
46
47
  "CHANGELOG.md"
47
48
  ],
@@ -49,7 +50,7 @@
49
50
  "access": "public"
50
51
  },
51
52
  "dependencies": {
52
- "@jungjaehoon/mama-core": "^8.6.0",
53
+ "@jungjaehoon/mama-core": "^8.7.0",
53
54
  "@slack/socket-mode": "^2.0.5",
54
55
  "@slack/web-api": "^7.13.0",
55
56
  "better-sqlite3": "^12.8.0",
@@ -0,0 +1,16 @@
1
+ """Bound office ZIP expansion using only the central directory, without extracting entries."""
2
+ import sys
3
+ import zipfile
4
+
5
+ with zipfile.ZipFile(sys.argv[1]) as archive:
6
+ entries = archive.infolist()
7
+ if len(entries) > 10_000:
8
+ raise ValueError("Office ZIP exceeds the 10,000 entries limit")
9
+ total = sum(entry.file_size for entry in entries)
10
+ if total > 512 * 1024 ** 2:
11
+ raise ValueError("Office ZIP exceeds the 512 MiB total uncompressed size limit")
12
+ if any(entry.file_size > 256 * 1024 ** 2 for entry in entries):
13
+ raise ValueError("Office ZIP exceeds the 256 MiB entry uncompressed size limit")
14
+ compressed = sum(entry.compress_size for entry in entries)
15
+ if total > 100 * compressed:
16
+ raise ValueError("Office ZIP exceeds the 100:1 expansion ratio limit")
@@ -0,0 +1,29 @@
1
+ """Trusted host helper. Input PDF remains untrusted; caller applies time and OS sandbox limits."""
2
+ import json
3
+ import pathlib
4
+ import sys
5
+ import pymupdf
6
+
7
+ source, output, limit = sys.argv[1], pathlib.Path(sys.argv[2]), int(sys.argv[3])
8
+ # A small PDF can repeat one large image on every page; bound the whole render, not only a page.
9
+ TOTAL_PIXELS = 200_000_000
10
+ pages, fonts, total = [], [], 0
11
+ with pymupdf.open(source) as pdf:
12
+ if pdf.is_encrypted:
13
+ raise ValueError("Encrypted PDFs cannot be rendered")
14
+ if not 0 < len(pdf) <= limit:
15
+ raise ValueError(f"Document must contain 1 to {limit} pages")
16
+ for number, page in enumerate(pdf, 1):
17
+ # 144 dpi, bounded before allocating the pixmap.
18
+ pixels = page.rect.width * page.rect.height * 4
19
+ if pixels > 20_000_000:
20
+ raise ValueError("Page exceeds the 20 megapixel render limit")
21
+ total += pixels
22
+ if total > TOTAL_PIXELS:
23
+ raise ValueError("Document exceeds the 200 megapixel render limit")
24
+ name = f"page-{number:03d}.png"
25
+ page.get_pixmap(matrix=pymupdf.Matrix(2, 2), alpha=False).save(output / name)
26
+ pages.append(name)
27
+ fonts.append(sorted({font[3] for font in page.get_fonts(full=True)
28
+ if font[1] != "n/a"}))
29
+ print(json.dumps({"pageCount": len(pages), "pages": pages, "fonts": fonts}))
@@ -0,0 +1,11 @@
1
+ python-pptx
2
+ python-docx
3
+ openpyxl
4
+ xlsxwriter
5
+ pymupdf
6
+ pdfplumber
7
+ reportlab
8
+ pillow
9
+ numpy
10
+ pandas
11
+ matplotlib