@arnilo/prism-tools 0.0.0-stage → 0.13.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 (331) hide show
  1. package/CHANGELOG.md +410 -0
  2. package/LICENSE +21 -0
  3. package/README.md +44 -2
  4. package/browser/README.md +98 -0
  5. package/browser/skills/browser-automation/SKILL.md +14 -0
  6. package/browser/src/actions/cdp.ts +131 -0
  7. package/browser/src/actions/dialog.ts +25 -0
  8. package/browser/src/actions/download_release.ts +22 -0
  9. package/browser/src/actions/index.ts +37 -0
  10. package/browser/src/actions/locator.ts +70 -0
  11. package/browser/src/actions/navigate.ts +23 -0
  12. package/browser/src/actions/screenshot.ts +27 -0
  13. package/browser/src/actions/scroll.ts +24 -0
  14. package/browser/src/actions/select_page.ts +21 -0
  15. package/browser/src/actions/types.ts +114 -0
  16. package/browser/src/actions/upload.ts +44 -0
  17. package/browser/src/actions/wait.ts +45 -0
  18. package/browser/src/browser.ts +197 -0
  19. package/browser/src/cdp.ts +178 -0
  20. package/browser/src/checkpoint.ts +189 -0
  21. package/browser/src/config.ts +72 -0
  22. package/browser/src/downloads.ts +253 -0
  23. package/browser/src/errors.ts +31 -0
  24. package/browser/src/evaluate.ts +101 -0
  25. package/browser/src/index.ts +129 -0
  26. package/browser/src/limits.ts +271 -0
  27. package/browser/src/manager.ts +730 -0
  28. package/browser/src/network.ts +263 -0
  29. package/browser/src/observe.ts +178 -0
  30. package/browser/src/policy.ts +133 -0
  31. package/browser/src/screenshot.ts +107 -0
  32. package/browser/src/shared-sandbox.ts +53 -0
  33. package/browser/src/snapshot.ts +99 -0
  34. package/browser/src/targets.ts +165 -0
  35. package/browser/src/tools.ts +480 -0
  36. package/browser/src/types.ts +316 -0
  37. package/browser/src/uploads.ts +174 -0
  38. package/coding/README.md +337 -0
  39. package/coding/src/agent/acp-operations.ts +146 -0
  40. package/coding/src/agent/artifacts.ts +38 -0
  41. package/coding/src/agent/ask-user-decision.ts +623 -0
  42. package/coding/src/agent/atomic-write.ts +23 -0
  43. package/coding/src/agent/bounded-file.ts +21 -0
  44. package/coding/src/agent/checks.ts +301 -0
  45. package/coding/src/agent/coding-checkpoint.ts +828 -0
  46. package/coding/src/agent/delete.ts +237 -0
  47. package/coding/src/agent/diagnostics-tool.ts +163 -0
  48. package/coding/src/agent/diagnostics.ts +262 -0
  49. package/coding/src/agent/edit-diff.ts +382 -0
  50. package/coding/src/agent/edit.ts +322 -0
  51. package/coding/src/agent/effects.ts +102 -0
  52. package/coding/src/agent/env.ts +28 -0
  53. package/coding/src/agent/execution-policy.ts +89 -0
  54. package/coding/src/agent/file-mutation-queue.ts +72 -0
  55. package/coding/src/agent/forge/github.ts +603 -0
  56. package/coding/src/agent/forge/index.ts +16 -0
  57. package/coding/src/agent/forge/types.ts +185 -0
  58. package/coding/src/agent/git-aware-repository.ts +305 -0
  59. package/coding/src/agent/git-exec.ts +326 -0
  60. package/coding/src/agent/git-status.ts +177 -0
  61. package/coding/src/agent/git-tools.ts +360 -0
  62. package/coding/src/agent/git.ts +1074 -0
  63. package/coding/src/agent/glob-match.ts +146 -0
  64. package/coding/src/agent/glob.ts +182 -0
  65. package/coding/src/agent/goal-verify.ts +385 -0
  66. package/coding/src/agent/grep-worker.ts +74 -0
  67. package/coding/src/agent/grep.ts +459 -0
  68. package/coding/src/agent/identity.ts +48 -0
  69. package/coding/src/agent/index.ts +676 -0
  70. package/coding/src/agent/language/client.ts +429 -0
  71. package/coding/src/agent/language/framing.ts +190 -0
  72. package/coding/src/agent/language/index.ts +23 -0
  73. package/coding/src/agent/language/intelligence.ts +682 -0
  74. package/coding/src/agent/language/types.ts +187 -0
  75. package/coding/src/agent/lifecycle-events.ts +121 -0
  76. package/coding/src/agent/lifecycle.ts +166 -0
  77. package/coding/src/agent/limits.ts +214 -0
  78. package/coding/src/agent/move.ts +178 -0
  79. package/coding/src/agent/mutation-path.ts +52 -0
  80. package/coding/src/agent/output-accumulator.ts +304 -0
  81. package/coding/src/agent/path-utils.ts +120 -0
  82. package/coding/src/agent/process/index.ts +58 -0
  83. package/coding/src/agent/process/recovery.ts +508 -0
  84. package/coding/src/agent/process/sessions-host.ts +222 -0
  85. package/coding/src/agent/process/sessions-monitor.ts +141 -0
  86. package/coding/src/agent/process/sessions-recovery.ts +241 -0
  87. package/coding/src/agent/process/sessions-spawn.ts +613 -0
  88. package/coding/src/agent/process/sessions-teardown.ts +281 -0
  89. package/coding/src/agent/process/sessions.ts +30 -0
  90. package/coding/src/agent/process/types.ts +358 -0
  91. package/coding/src/agent/read-path-set.ts +126 -0
  92. package/coding/src/agent/read.ts +713 -0
  93. package/coding/src/agent/repository/glob.ts +147 -0
  94. package/coding/src/agent/repository/indexed-search.ts +480 -0
  95. package/coding/src/agent/repository/list.ts +131 -0
  96. package/coding/src/agent/repository/operations.ts +22 -0
  97. package/coding/src/agent/repository/path.ts +98 -0
  98. package/coding/src/agent/repository/search.ts +277 -0
  99. package/coding/src/agent/repository/types.ts +243 -0
  100. package/coding/src/agent/repository/walk.ts +126 -0
  101. package/coding/src/agent/repository.ts +12 -0
  102. package/coding/src/agent/shell-background.ts +264 -0
  103. package/coding/src/agent/shell-output.ts +75 -0
  104. package/coding/src/agent/shell.ts +526 -0
  105. package/coding/src/agent/todo.ts +399 -0
  106. package/coding/src/agent/truncate.ts +251 -0
  107. package/coding/src/agent/write.ts +170 -0
  108. package/coding/src/ask-user-host.ts +48 -0
  109. package/coding/src/config.ts +278 -0
  110. package/coding/src/hard-deny.ts +97 -0
  111. package/coding/src/index.ts +318 -0
  112. package/coding/src/principal-guard.ts +84 -0
  113. package/coding/src/sandbox.ts +92 -0
  114. package/coding/src/security/approval.ts +144 -0
  115. package/coding/src/security/command-rules.ts +57 -0
  116. package/coding/src/security/docker-cli.ts +222 -0
  117. package/coding/src/security/docker-sandbox.ts +1205 -0
  118. package/coding/src/security/e2b-sandbox.ts +853 -0
  119. package/coding/src/security/egress/dns-pin.ts +88 -0
  120. package/coding/src/security/egress/index.ts +32 -0
  121. package/coding/src/security/egress/limits.ts +57 -0
  122. package/coding/src/security/egress/policy.ts +137 -0
  123. package/coding/src/security/egress/proxy.ts +599 -0
  124. package/coding/src/security/egress/types.ts +30 -0
  125. package/coding/src/security/index.ts +199 -0
  126. package/coding/src/security/native-sandbox.ts +639 -0
  127. package/coding/src/security/path-containment.ts +55 -0
  128. package/coding/src/security/sandbox-coding-operations.ts +392 -0
  129. package/coding/src/security/sandbox-fs-operations.ts +644 -0
  130. package/coding/src/security/sandbox-limits.ts +147 -0
  131. package/coding/src/security/sandbox-tar.ts +308 -0
  132. package/coding/src/security/sandbox.ts +179 -0
  133. package/coding/src/security/semaphore.ts +55 -0
  134. package/coding/src/targets.ts +110 -0
  135. package/coding/src/workspace/diff.ts +78 -0
  136. package/coding/src/workspace/errors.ts +28 -0
  137. package/coding/src/workspace/index.ts +5 -0
  138. package/coding/src/workspace/merge.ts +151 -0
  139. package/coding/src/workspace/routing.ts +76 -0
  140. package/coding/src/workspace/service.ts +545 -0
  141. package/computer-use/README.md +105 -0
  142. package/computer-use/skills/computer-use-linux/SKILL.md +17 -0
  143. package/computer-use/src/classify.ts +53 -0
  144. package/computer-use/src/command.ts +29 -0
  145. package/computer-use/src/config.ts +69 -0
  146. package/computer-use/src/create.ts +170 -0
  147. package/computer-use/src/devices.ts +247 -0
  148. package/computer-use/src/env.ts +28 -0
  149. package/computer-use/src/index.ts +157 -0
  150. package/computer-use/src/skill.ts +21 -0
  151. package/openapi/README.md +97 -0
  152. package/openapi/src/compile.ts +386 -0
  153. package/openapi/src/config.ts +73 -0
  154. package/openapi/src/errors.ts +16 -0
  155. package/openapi/src/execute.ts +241 -0
  156. package/openapi/src/index.ts +124 -0
  157. package/openapi/src/limits.ts +63 -0
  158. package/openapi/src/specs.ts +86 -0
  159. package/openapi/src/tools.ts +60 -0
  160. package/openapi/src/types.ts +61 -0
  161. package/package.json +171 -4
  162. package/research/README.md +72 -0
  163. package/research/skills/research-report/SKILL.md +12 -0
  164. package/research/skills/research-scoping/SKILL.md +10 -0
  165. package/research/skills/research-synthesis/SKILL.md +10 -0
  166. package/research/skills/source-triage/SKILL.md +10 -0
  167. package/research/src/check.ts +71 -0
  168. package/research/src/config.ts +41 -0
  169. package/research/src/index.ts +147 -0
  170. package/research/src/ledger.ts +157 -0
  171. package/research/src/urls.ts +21 -0
  172. package/web/README.md +287 -0
  173. package/web/skills/web-research/SKILL.md +17 -0
  174. package/web/src/brave.ts +66 -0
  175. package/web/src/cache.ts +151 -0
  176. package/web/src/config.ts +210 -0
  177. package/web/src/controls.ts +128 -0
  178. package/web/src/domains.ts +114 -0
  179. package/web/src/exa.ts +60 -0
  180. package/web/src/firecrawl.ts +160 -0
  181. package/web/src/index.ts +387 -0
  182. package/web/src/kagi.ts +73 -0
  183. package/web/src/limits.ts +55 -0
  184. package/web/src/native/convert.ts +84 -0
  185. package/web/src/native/fetch.ts +226 -0
  186. package/web/src/normalize.ts +131 -0
  187. package/web/src/obscura/cdp.ts +201 -0
  188. package/web/src/obscura/classify.ts +35 -0
  189. package/web/src/obscura/cli.ts +254 -0
  190. package/web/src/obscura/errors.ts +8 -0
  191. package/web/src/obscura/index.ts +59 -0
  192. package/web/src/obscura/limits.ts +92 -0
  193. package/web/src/obscura/mcp.ts +104 -0
  194. package/web/src/obscura/playwright.ts +133 -0
  195. package/web/src/obscura/process.ts +235 -0
  196. package/web/src/obscura/search-profile.ts +73 -0
  197. package/web/src/obscura/types.ts +48 -0
  198. package/web/src/obscura/web.ts +419 -0
  199. package/web/src/prompt-fetch.ts +88 -0
  200. package/web/src/render.ts +75 -0
  201. package/web/src/searxng.ts +78 -0
  202. package/web/src/slice.ts +139 -0
  203. package/web/src/tavily.ts +77 -0
  204. package/web/src/tools.ts +182 -0
  205. package/web/src/transport.ts +310 -0
  206. package/web/src/types.ts +199 -0
  207. package/work/README.md +77 -0
  208. package/work/THIRD_PARTY_NOTICES +24 -0
  209. package/work/docling/ocr.py +150 -0
  210. package/work/sandbox/Dockerfile +36 -0
  211. package/work/sandbox/soffice.sh +12 -0
  212. package/work/src/command.ts +29 -0
  213. package/work/src/config.ts +138 -0
  214. package/work/src/connectors/cli.ts +343 -0
  215. package/work/src/connectors/drafts.ts +647 -0
  216. package/work/src/connectors/errors.ts +8 -0
  217. package/work/src/connectors/file-bytes.ts +149 -0
  218. package/work/src/connectors/google-workspace-http.ts +399 -0
  219. package/work/src/connectors/google-workspace.ts +465 -0
  220. package/work/src/connectors/gws-tools.ts +378 -0
  221. package/work/src/connectors/http.ts +123 -0
  222. package/work/src/connectors/idempotency.ts +235 -0
  223. package/work/src/connectors/identity.ts +34 -0
  224. package/work/src/connectors/index.ts +93 -0
  225. package/work/src/connectors/limits.ts +50 -0
  226. package/work/src/connectors/m365-tools.ts +308 -0
  227. package/work/src/connectors/microsoft365-http.ts +428 -0
  228. package/work/src/connectors/microsoft365.ts +402 -0
  229. package/work/src/connectors/normalize.ts +120 -0
  230. package/work/src/connectors/tool-helpers.ts +398 -0
  231. package/work/src/connectors/tools.ts +42 -0
  232. package/work/src/connectors/types.ts +399 -0
  233. package/work/src/diagrams/canonicalize.ts +166 -0
  234. package/work/src/diagrams/caps.ts +52 -0
  235. package/work/src/diagrams/embed.ts +340 -0
  236. package/work/src/diagrams/errors.ts +76 -0
  237. package/work/src/diagrams/index.ts +81 -0
  238. package/work/src/diagrams/messages.ts +150 -0
  239. package/work/src/diagrams/origin.ts +52 -0
  240. package/work/src/diagrams/telemetry.ts +34 -0
  241. package/work/src/diagrams/xml.ts +267 -0
  242. package/work/src/document-extraction/index.ts +563 -0
  243. package/work/src/document-reader/ambient.d.ts +2 -0
  244. package/work/src/document-reader/errors.ts +7 -0
  245. package/work/src/document-reader/index.ts +181 -0
  246. package/work/src/document-reader/mistral-ocr.ts +318 -0
  247. package/work/src/document-reader/parsers.ts +171 -0
  248. package/work/src/documents/caps.ts +135 -0
  249. package/work/src/documents/diff.ts +269 -0
  250. package/work/src/documents/errors.ts +44 -0
  251. package/work/src/documents/fidelity.ts +98 -0
  252. package/work/src/documents/generate.ts +96 -0
  253. package/work/src/documents/hash.ts +8 -0
  254. package/work/src/documents/index.ts +14 -0
  255. package/work/src/documents/model-schema.ts +639 -0
  256. package/work/src/documents/parse.ts +252 -0
  257. package/work/src/documents/patch-history.ts +81 -0
  258. package/work/src/documents/patch.ts +476 -0
  259. package/work/src/documents/preview-html.ts +245 -0
  260. package/work/src/documents/preview.ts +227 -0
  261. package/work/src/documents/telemetry.ts +36 -0
  262. package/work/src/documents/translate/docx.ts +292 -0
  263. package/work/src/documents/translate/pptx.ts +304 -0
  264. package/work/src/documents/translate/xlsx.ts +137 -0
  265. package/work/src/documents/types.ts +188 -0
  266. package/work/src/index.ts +311 -0
  267. package/work/src/runtime/worker-pool-entry.ts +102 -0
  268. package/work/src/runtime/worker-pool.ts +267 -0
  269. package/work/src/sandbox/composition.ts +212 -0
  270. package/work/src/sandbox/image.ts +6 -0
  271. package/work/src/sandbox/index.ts +14 -0
  272. package/work/src/sheets/caps.ts +68 -0
  273. package/work/src/sheets/csv.ts +351 -0
  274. package/work/src/sheets/decimal.ts +388 -0
  275. package/work/src/sheets/errors.ts +52 -0
  276. package/work/src/sheets/index.ts +62 -0
  277. package/work/src/sheets/inference.ts +378 -0
  278. package/work/src/sheets/telemetry.ts +34 -0
  279. package/work/src/sheets/types.ts +162 -0
  280. package/work/src/sheets/xlsx.ts +388 -0
  281. package/work/src/skills/index.ts +8 -0
  282. package/work/src/skills/load.ts +43 -0
  283. package/work/src/tools/filesystem.ts +21 -0
  284. package/work/src/tools/index.ts +1 -0
  285. package/work/src/tools/local-filesystem.ts +33 -0
  286. package/work/src/tools/office.ts +311 -0
  287. package/work/vendor/hermes-agent/LICENSE +21 -0
  288. package/work/vendor/hermes-agent/skills/productivity/docx/LICENSE +21 -0
  289. package/work/vendor/hermes-agent/skills/productivity/docx/SKILL.md +196 -0
  290. package/work/vendor/hermes-agent/skills/productivity/docx/scripts/docx_comments.py +289 -0
  291. package/work/vendor/hermes-agent/skills/productivity/docx/scripts/docx_common.py +94 -0
  292. package/work/vendor/hermes-agent/skills/productivity/docx/scripts/docx_create.py +177 -0
  293. package/work/vendor/hermes-agent/skills/productivity/docx/scripts/docx_edit.py +250 -0
  294. package/work/vendor/hermes-agent/skills/productivity/docx/scripts/docx_read.py +149 -0
  295. package/work/vendor/hermes-agent/skills/productivity/docx/scripts/docx_revisions.py +147 -0
  296. package/work/vendor/hermes-agent/skills/productivity/docx/scripts/docx_template.py +70 -0
  297. package/work/vendor/hermes-agent/skills/productivity/docx/scripts/docx_validate.py +156 -0
  298. package/work/vendor/hermes-agent/skills/productivity/pdf/LICENSE +21 -0
  299. package/work/vendor/hermes-agent/skills/productivity/pdf/SKILL.md +125 -0
  300. package/work/vendor/hermes-agent/skills/productivity/pdf/scripts/_raster.py +76 -0
  301. package/work/vendor/hermes-agent/skills/productivity/pdf/scripts/extract_marker.py +88 -0
  302. package/work/vendor/hermes-agent/skills/productivity/pdf/scripts/extract_pymupdf.py +101 -0
  303. package/work/vendor/hermes-agent/skills/productivity/pdf/scripts/pdf_create.py +130 -0
  304. package/work/vendor/hermes-agent/skills/productivity/pdf/scripts/pdf_fill_form.py +97 -0
  305. package/work/vendor/hermes-agent/skills/productivity/pdf/scripts/pdf_form_layout.py +168 -0
  306. package/work/vendor/hermes-agent/skills/productivity/pdf/scripts/pdf_make_form.py +145 -0
  307. package/work/vendor/hermes-agent/skills/productivity/pdf/scripts/pdf_merge.py +50 -0
  308. package/work/vendor/hermes-agent/skills/productivity/pdf/scripts/pdf_meta.py +115 -0
  309. package/work/vendor/hermes-agent/skills/productivity/pdf/scripts/pdf_page_image.py +99 -0
  310. package/work/vendor/hermes-agent/skills/productivity/pdf/scripts/pdf_read.py +153 -0
  311. package/work/vendor/hermes-agent/skills/productivity/pdf/scripts/pdf_secure.py +71 -0
  312. package/work/vendor/hermes-agent/skills/productivity/pdf/scripts/pdf_split.py +84 -0
  313. package/work/vendor/hermes-agent/skills/productivity/pdf/scripts/pdf_stamp.py +143 -0
  314. package/work/vendor/hermes-agent/skills/productivity/pdf/scripts/pdf_watermark.py +51 -0
  315. package/work/vendor/hermes-agent/skills/productivity/powerpoint/LICENSE +21 -0
  316. package/work/vendor/hermes-agent/skills/productivity/powerpoint/SKILL.md +220 -0
  317. package/work/vendor/hermes-agent/skills/productivity/powerpoint/scripts/pptx_create.py +214 -0
  318. package/work/vendor/hermes-agent/skills/productivity/powerpoint/scripts/pptx_edit.py +436 -0
  319. package/work/vendor/hermes-agent/skills/productivity/powerpoint/scripts/pptx_from_template.py +88 -0
  320. package/work/vendor/hermes-agent/skills/productivity/powerpoint/scripts/pptx_read.py +131 -0
  321. package/work/vendor/hermes-agent/skills/productivity/powerpoint/scripts/pptx_render.py +93 -0
  322. package/work/vendor/hermes-agent/skills/productivity/xlsx/LICENSE +21 -0
  323. package/work/vendor/hermes-agent/skills/productivity/xlsx/SKILL.md +196 -0
  324. package/work/vendor/hermes-agent/skills/productivity/xlsx/scripts/csv_to_xlsx.py +104 -0
  325. package/work/vendor/hermes-agent/skills/productivity/xlsx/scripts/xlsx_create.py +259 -0
  326. package/work/vendor/hermes-agent/skills/productivity/xlsx/scripts/xlsx_edit.py +263 -0
  327. package/work/vendor/hermes-agent/skills/productivity/xlsx/scripts/xlsx_read.py +160 -0
  328. package/work/vendor/hermes-agent/skills/productivity/xlsx/scripts/xlsx_recalc.py +111 -0
  329. package/work/vendor/hermes-agent/skills/productivity/xlsx/scripts/xlsx_restructure.py +337 -0
  330. package/work/vendor/hermes-agent/skills/productivity/xlsx/scripts/xlsx_to_csv.py +69 -0
  331. package/work/vendor-lock.json +11 -0
@@ -0,0 +1,428 @@
1
+ import { type JsonObject } from "@arnilo/prism";
2
+ import { type ArtifactBodyStore } from "@arnilo/prism/artifacts";
3
+ import type { CheckpointStore } from "@arnilo/prism-extensions/workflows";
4
+ import { createCheckpointWorkDraftStore, createMemoryWorkDraftStore } from "./drafts.js";
5
+ import { WorkToolError } from "./errors.js";
6
+ import { assertContentHash, readUploadBytes } from "./file-bytes.js";
7
+ import { createWorkHttpClient } from "./http.js";
8
+ import { type AgentIdentity, assertIdentityActive } from "./identity.js";
9
+ import { resolveWorkLimits } from "./limits.js";
10
+ import { DEFAULT_M365_OPS } from "./microsoft365.js";
11
+ import type { Microsoft365Adapter, Microsoft365Op, WorkDraftStore, WorkLimits, WorkTokenProvider } from "./types.js";
12
+
13
+ const GRAPH_ORIGIN = "https://graph.microsoft.com";
14
+
15
+ export interface Microsoft365HttpAdapterOptions {
16
+ readonly identity: AgentIdentity;
17
+ readonly tokenProvider: WorkTokenProvider;
18
+ readonly accessEnvVar: string;
19
+ readonly allowedOps?: readonly Microsoft365Op[];
20
+ readonly limits?: WorkLimits;
21
+ readonly fetch?: typeof globalThis.fetch;
22
+ readonly draftStore?: WorkDraftStore;
23
+ readonly checkpoints?: CheckpointStore;
24
+ readonly bodies?: ArtifactBodyStore;
25
+ readonly ephemeralDrafts?: boolean;
26
+ }
27
+
28
+ /** Microsoft Graph adapter with pinned default fetch and host-owned OAuth tokens. */
29
+ export function createMicrosoft365HttpAdapter(options: Microsoft365HttpAdapterOptions): Microsoft365Adapter {
30
+ if (!options || typeof options.tokenProvider?.tokenEnv !== "function") {
31
+ throw new WorkToolError("ERR_PRISM_WORK_CREDENTIAL", "Microsoft 365 HTTP adapter requires a tokenProvider");
32
+ }
33
+ if (typeof options.accessEnvVar !== "string" || !/^[A-Za-z_][A-Za-z0-9_]*$/.test(options.accessEnvVar)) {
34
+ throw new WorkToolError("ERR_PRISM_WORK_INPUT", "accessEnvVar must be an environment variable name");
35
+ }
36
+ if (options.fetch !== undefined && typeof options.fetch !== "function") {
37
+ throw new WorkToolError("ERR_PRISM_WORK_INPUT", "fetch must be a function");
38
+ }
39
+ assertIdentityActive(options.identity);
40
+ const limits = resolveWorkLimits(options.limits);
41
+ const allowedOps = new Set<Microsoft365Op>(options.allowedOps ?? [...DEFAULT_M365_OPS, "file.get"]);
42
+ const request = createWorkHttpClient({
43
+ identity: options.identity,
44
+ tokenProvider: options.tokenProvider,
45
+ accessEnvVar: options.accessEnvVar,
46
+ allowedOrigins: [GRAPH_ORIGIN],
47
+ limits,
48
+ ...(options.fetch === undefined ? {} : { fetch: options.fetch }),
49
+ });
50
+ const draftStore: WorkDraftStore =
51
+ options.draftStore ??
52
+ (options.checkpoints
53
+ ? createCheckpointWorkDraftStore({ checkpoints: options.checkpoints, bodies: options.bodies, limits: options.limits })
54
+ : createMemoryWorkDraftStore({ ephemeral: options.ephemeralDrafts ?? true }));
55
+ let readyVersion: string | undefined;
56
+
57
+ const assertAllowed = (op: Microsoft365Op) => {
58
+ if (!allowedOps.has(op)) throw new WorkToolError("ERR_PRISM_WORK_CAPABILITY", `Operation ${op} not allowed for this identity`);
59
+ };
60
+ const ensureReady = async (signal?: AbortSignal): Promise<string> => {
61
+ if (readyVersion) return readyVersion;
62
+ assertAllowed("version");
63
+ const profile = asRecord(await request({ url: graphUrl("/me?$select=id,userPrincipalName"), signal }));
64
+ readyVersion = string(profile?.userPrincipalName) ?? string(profile?.id) ?? "microsoft365";
65
+ return readyVersion;
66
+ };
67
+
68
+ return {
69
+ provider: "microsoft365",
70
+ identity: options.identity,
71
+ allowedOps,
72
+ draftStore,
73
+ ensureReady,
74
+ async runOp(op, args, signal) {
75
+ assertAllowed(op);
76
+ switch (op) {
77
+ case "version":
78
+ return ensureReady(signal);
79
+ case "mail.list":
80
+ return request({ url: listUrl(mailPath(args), args, limits.maxItemsPerPage), signal });
81
+ case "mail.get":
82
+ return request({ url: graphUrl(`${userPath(args)}/messages/${encodeURIComponent(reqString(args, "id"))}`), signal });
83
+ case "mail.send":
84
+ return request({
85
+ url: graphUrl("/me/sendMail"),
86
+ method: "POST",
87
+ headers: { "content-type": "application/json" },
88
+ body: JSON.stringify({ message: graphMessage(args), saveToSentItems: true }),
89
+ signal,
90
+ });
91
+ case "calendar.list":
92
+ return request({ url: calendarListUrl(args, limits.maxItemsPerPage), signal });
93
+ case "calendar.add":
94
+ return request({
95
+ url: calendarPath(args),
96
+ method: "POST",
97
+ headers: { "content-type": "application/json" },
98
+ body: JSON.stringify({
99
+ subject: reqString(args, "subject"),
100
+ start: graphDateTime(reqString(args, "start")),
101
+ end: graphDateTime(reqString(args, "end")),
102
+ }),
103
+ signal,
104
+ });
105
+ case "file.list":
106
+ safeResourceUrl(reqString(args, "webUrl"), "webUrl");
107
+ return request({ url: listUrl(`${graphDriveItem(args, "folderUrl").path}/children`, args, limits.maxItemsPerPage), signal });
108
+ case "file.get":
109
+ return request({
110
+ url: graphUrl(`/me/drive/items/${encodeURIComponent(reqString(args, "id"))}/content`),
111
+ responseType: "bytes",
112
+ maxResponseBytes: limits.maxFileBytes,
113
+ signal,
114
+ });
115
+ case "file.add":
116
+ return uploadFile(request, args, limits, options.bodies, signal);
117
+ case "file.copy":
118
+ return copyFile(request, args, signal);
119
+ case "file.share":
120
+ return createOrganizationLink(request, args, signal);
121
+ case "todo.list":
122
+ return request({ url: listUrl(`${todoListPath(args)}/tasks`, args, limits.maxItemsPerPage), signal });
123
+ case "todo.add":
124
+ return request({
125
+ url: graphUrl(`${todoListPath(args)}/tasks`),
126
+ method: "POST",
127
+ headers: { "content-type": "application/json" },
128
+ body: JSON.stringify({ title: reqString(args, "title") }),
129
+ signal,
130
+ });
131
+ case "todo.complete":
132
+ return request({
133
+ url: graphUrl(`${todoListPath(args)}/tasks/${encodeURIComponent(reqString(args, "id"))}`),
134
+ method: "PATCH",
135
+ headers: { "content-type": "application/json" },
136
+ body: JSON.stringify({ status: "completed" }),
137
+ signal,
138
+ });
139
+ case "planner.list":
140
+ return request({
141
+ url: listUrl(`/planner/plans/${encodeURIComponent(reqString(args, "planId"))}/tasks`, args, limits.maxItemsPerPage),
142
+ signal,
143
+ });
144
+ case "planner.add":
145
+ return request({
146
+ url: graphUrl("/planner/tasks"),
147
+ method: "POST",
148
+ headers: { "content-type": "application/json" },
149
+ body: JSON.stringify({
150
+ title: reqString(args, "title"),
151
+ planId: reqString(args, "planId"),
152
+ bucketId: reqString(args, "bucketId"),
153
+ }),
154
+ signal,
155
+ });
156
+ case "planner.complete":
157
+ return request({
158
+ url: graphUrl(`/planner/tasks/${encodeURIComponent(reqString(args, "id"))}`),
159
+ method: "PATCH",
160
+ headers: { "content-type": "application/json", "if-match": "*" },
161
+ body: JSON.stringify({ percentComplete: 100 }),
162
+ signal,
163
+ });
164
+ default: {
165
+ const _exhaustive: never = op;
166
+ throw new WorkToolError("ERR_PRISM_WORK_OP", `Unknown op ${_exhaustive}`);
167
+ }
168
+ }
169
+ },
170
+ createDraft(op, payload, draftOpts) {
171
+ assertAllowed(op);
172
+ return draftStore.createDraft({
173
+ draftId: draftOpts?.draftId,
174
+ provider: "microsoft365",
175
+ op,
176
+ identity: options.identity,
177
+ payload,
178
+ policyRevision: draftOpts?.policyRevision,
179
+ });
180
+ },
181
+ getDraft(draftId) {
182
+ return draftStore.getDraft({ draftId, identity: options.identity, provider: "microsoft365" });
183
+ },
184
+ updateDraft(draftId, payload, draftOpts) {
185
+ return draftStore.updateDraft({
186
+ draftId,
187
+ identity: options.identity,
188
+ payload,
189
+ expectedRevision: draftOpts?.expectedRevision,
190
+ expectedConcurrencyToken: draftOpts?.concurrencyToken,
191
+ });
192
+ },
193
+ approveDraft(approval) {
194
+ return draftStore.approveDraft({ draftId: approval.draftId, identity: options.identity, approval });
195
+ },
196
+ markDraft(draftId, status, concurrencyToken) {
197
+ return draftStore.markDraft({ draftId, identity: options.identity, status, concurrencyToken });
198
+ },
199
+ };
200
+ }
201
+
202
+ function graphUrl(path: string): URL {
203
+ return new URL(`/v1.0${path}`, GRAPH_ORIGIN);
204
+ }
205
+
206
+ function userPath(args: JsonObject): string {
207
+ const userName = optString(args, "userName");
208
+ const userId = optString(args, "userId");
209
+ if (userName && userId) throw new WorkToolError("ERR_PRISM_WORK_INPUT", "Specify userName or userId, not both");
210
+ const user = userName ?? userId;
211
+ return user ? `/users/${encodeURIComponent(user)}` : "/me";
212
+ }
213
+
214
+ function mailPath(args: JsonObject): string {
215
+ const folderName = optString(args, "folderName");
216
+ const folderId = optString(args, "folderId");
217
+ if (folderName && folderId) throw new WorkToolError("ERR_PRISM_WORK_INPUT", "Specify folderName or folderId, not both");
218
+ if (folderName && folderName.toLowerCase() !== "inbox") {
219
+ throw new WorkToolError("ERR_PRISM_WORK_CAPABILITY", "Microsoft Graph HTTP mail.list supports inbox or folderId");
220
+ }
221
+ return `${userPath(args)}/mailFolders/${encodeURIComponent(folderId ?? "inbox")}/messages`;
222
+ }
223
+
224
+ function calendarPath(args: JsonObject): URL {
225
+ const calendarId = optString(args, "calendarId");
226
+ const calendarName = optString(args, "calendarName");
227
+ if (calendarId && calendarName) throw new WorkToolError("ERR_PRISM_WORK_INPUT", "Specify calendarId or calendarName, not both");
228
+ if (calendarName && calendarName.toLowerCase() !== "calendar") {
229
+ throw new WorkToolError("ERR_PRISM_WORK_CAPABILITY", "Microsoft Graph HTTP calendar supports Calendar or calendarId");
230
+ }
231
+ return graphUrl(`${userPath(args)}${calendarId ? `/calendars/${encodeURIComponent(calendarId)}` : "/calendar"}/events`);
232
+ }
233
+
234
+ function calendarListUrl(args: JsonObject, maxItems: number): URL {
235
+ const start = optString(args, "startDateTime");
236
+ const end = optString(args, "endDateTime");
237
+ if ((start === undefined) !== (end === undefined)) {
238
+ throw new WorkToolError("ERR_PRISM_WORK_INPUT", "startDateTime and endDateTime must be supplied together");
239
+ }
240
+ const url = start === undefined ? calendarPath(args) : graphUrl(`${userPath(args)}/calendarView`);
241
+ if (start !== undefined && end !== undefined) {
242
+ url.searchParams.set("startDateTime", start);
243
+ url.searchParams.set("endDateTime", end);
244
+ }
245
+ url.searchParams.set("$top", boundedPageSize(args, maxItems));
246
+ return url;
247
+ }
248
+
249
+ function listUrl(path: string, args: JsonObject, maxItems: number): URL {
250
+ const url = graphUrl(path);
251
+ url.searchParams.set("$top", boundedPageSize(args, maxItems));
252
+ return url;
253
+ }
254
+
255
+ function graphMessage(args: JsonObject): Record<string, unknown> {
256
+ const contentType = optString(args, "bodyContentType") ?? "Text";
257
+ if (contentType !== "Text" && contentType !== "HTML") {
258
+ throw new WorkToolError("ERR_PRISM_WORK_INPUT", "bodyContentType must be Text or HTML");
259
+ }
260
+ const cc = optString(args, "cc");
261
+ const bcc = optString(args, "bcc");
262
+ return {
263
+ subject: reqString(args, "subject"),
264
+ body: { contentType, content: reqString(args, "bodyContents") },
265
+ toRecipients: recipients(reqString(args, "to")),
266
+ ...(cc ? { ccRecipients: recipients(cc) } : {}),
267
+ ...(bcc ? { bccRecipients: recipients(bcc) } : {}),
268
+ };
269
+ }
270
+
271
+ function recipients(value: string): readonly { emailAddress: { address: string } }[] {
272
+ const addresses = value
273
+ .split(",")
274
+ .map((item) => item.trim())
275
+ .filter(Boolean);
276
+ if (addresses.length === 0 || addresses.some((address) => address.includes("\r") || address.includes("\n"))) {
277
+ throw new WorkToolError("ERR_PRISM_WORK_INPUT", "Recipient addresses must be comma-separated single-line values");
278
+ }
279
+ return addresses.map((address) => ({ emailAddress: { address } }));
280
+ }
281
+
282
+ function graphDateTime(value: string): { dateTime: string; timeZone: string } {
283
+ return { dateTime: value, timeZone: "UTC" };
284
+ }
285
+
286
+ async function uploadFile(
287
+ request: ReturnType<typeof createWorkHttpClient>,
288
+ args: JsonObject,
289
+ limits: ReturnType<typeof resolveWorkLimits>,
290
+ bodies: ArtifactBodyStore | undefined,
291
+ signal?: AbortSignal,
292
+ ): Promise<unknown> {
293
+ const source = await readUploadBytes(args, bodies, limits.maxFileBytes, signal);
294
+ assertContentHash(args, source.contentHash);
295
+ const folder = graphDriveItem(args, "folderUrl");
296
+ return request({
297
+ url: graphUrl(`${folder.path}:/${encodeURIComponent(source.name)}:/content`),
298
+ method: "PUT",
299
+ headers: { "content-type": "application/octet-stream" },
300
+ body: source.bytes,
301
+ signal,
302
+ });
303
+ }
304
+
305
+ async function copyFile(request: ReturnType<typeof createWorkHttpClient>, args: JsonObject, signal?: AbortSignal): Promise<unknown> {
306
+ const source = graphDriveItem(args, "sourceUrl", true);
307
+ const target = graphDriveItem(args, "targetUrl", true);
308
+ return request({
309
+ url: graphUrl(`${source.path}/copy`),
310
+ method: "POST",
311
+ headers: { "content-type": "application/json" },
312
+ body: JSON.stringify({ parentReference: { driveId: target.driveId, id: target.itemId } }),
313
+ signal,
314
+ });
315
+ }
316
+
317
+ async function createOrganizationLink(
318
+ request: ReturnType<typeof createWorkHttpClient>,
319
+ args: JsonObject,
320
+ signal?: AbortSignal,
321
+ ): Promise<unknown> {
322
+ safeResourceUrl(reqString(args, "webUrl"), "webUrl");
323
+ const type = reqString(args, "type");
324
+ if (type !== "view" && type !== "edit") throw new WorkToolError("ERR_PRISM_WORK_INPUT", "type must be view or edit");
325
+ const scope = optString(args, "scope") ?? "organization";
326
+ if (scope === "anonymous") throw new WorkToolError("ERR_PRISM_WORK_POLICY", "Anonymous share denied");
327
+ if (scope !== "organization") throw new WorkToolError("ERR_PRISM_WORK_INPUT", "scope must be organization");
328
+ const fileId = optString(args, "fileId");
329
+ const file = fileId ? { path: `/me/drive/items/${encodeURIComponent(fileId)}` } : graphDriveItem(args, "fileUrl");
330
+ return request({
331
+ url: graphUrl(`${file.path}/createLink`),
332
+ method: "POST",
333
+ headers: { "content-type": "application/json" },
334
+ body: JSON.stringify({ type, scope }),
335
+ signal,
336
+ });
337
+ }
338
+
339
+ function todoListPath(args: JsonObject): string {
340
+ const listName = optString(args, "listName");
341
+ const listId = optString(args, "listId");
342
+ if (listName && listId) throw new WorkToolError("ERR_PRISM_WORK_INPUT", "Specify listName or listId, not both");
343
+ if (listName) throw new WorkToolError("ERR_PRISM_WORK_CAPABILITY", "Microsoft Graph HTTP To Do operations require listId");
344
+ if (!listId) throw new WorkToolError("ERR_PRISM_WORK_INPUT", "Specify listName or listId");
345
+ return `/me/todo/lists/${encodeURIComponent(listId)}`;
346
+ }
347
+
348
+ function graphDriveItem(args: JsonObject, key: string): { path: string; driveId?: string; itemId?: string };
349
+ function graphDriveItem(args: JsonObject, key: string, requireDriveId: true): { path: string; driveId: string; itemId: string };
350
+ function graphDriveItem(args: JsonObject, key: string, requireDriveId = false): { path: string; driveId?: string; itemId?: string } {
351
+ const url = safeResourceUrl(reqString(args, key), key);
352
+ if (url.origin !== GRAPH_ORIGIN) {
353
+ throw new WorkToolError("ERR_PRISM_WORK_CAPABILITY", `${key} must be a Microsoft Graph drive item URL for single-request execution`);
354
+ }
355
+ const [version, kind, driveId, itemKeyword, itemId] = url.pathname.split("/").filter(Boolean).map(decodeURIComponent);
356
+ if (
357
+ version === "v1.0" &&
358
+ kind === "drives" &&
359
+ driveId &&
360
+ itemKeyword === "items" &&
361
+ itemId &&
362
+ url.pathname.split("/").filter(Boolean).length === 5
363
+ ) {
364
+ return { path: `/drives/${encodeURIComponent(driveId)}/items/${encodeURIComponent(itemId)}`, driveId, itemId };
365
+ }
366
+ if (
367
+ !requireDriveId &&
368
+ version === "v1.0" &&
369
+ kind === "me" &&
370
+ driveId === "drive" &&
371
+ itemKeyword === "items" &&
372
+ itemId &&
373
+ url.pathname.split("/").filter(Boolean).length === 5
374
+ ) {
375
+ return { path: `/me/drive/items/${encodeURIComponent(itemId)}`, itemId };
376
+ }
377
+ throw new WorkToolError("ERR_PRISM_WORK_CAPABILITY", `${key} must identify a Microsoft Graph drive item`);
378
+ }
379
+
380
+ function safeResourceUrl(value: string, key: string): URL {
381
+ let url: URL;
382
+ try {
383
+ url = new URL(value);
384
+ } catch {
385
+ throw new WorkToolError("ERR_PRISM_WORK_INPUT", `${key} must be an HTTPS Microsoft Graph or SharePoint URL`);
386
+ }
387
+ const hostname = url.hostname.toLowerCase();
388
+ if (
389
+ url.protocol !== "https:" ||
390
+ url.username ||
391
+ url.password ||
392
+ url.hash ||
393
+ (hostname !== "graph.microsoft.com" && !hostname.endsWith(".sharepoint.com"))
394
+ ) {
395
+ throw new WorkToolError("ERR_PRISM_WORK_POLICY", `${key} must be an HTTPS Microsoft Graph or SharePoint URL`);
396
+ }
397
+ return url;
398
+ }
399
+
400
+ function reqString(args: JsonObject, key: string): string {
401
+ const value = args[key];
402
+ if (typeof value !== "string" || !value) throw new WorkToolError("ERR_PRISM_WORK_INPUT", `${key} must be a non-empty string`);
403
+ return value;
404
+ }
405
+
406
+ function optString(args: JsonObject, key: string): string | undefined {
407
+ const value = args[key];
408
+ if (value === undefined) return undefined;
409
+ if (typeof value !== "string" || !value) throw new WorkToolError("ERR_PRISM_WORK_INPUT", `${key} must be a non-empty string`);
410
+ return value;
411
+ }
412
+
413
+ function boundedPageSize(args: JsonObject, maximum: number): string {
414
+ const value = optString(args, "maxResults") ?? String(maximum);
415
+ const number = Number(value);
416
+ if (!Number.isSafeInteger(number) || number < 1 || number > maximum) {
417
+ throw new WorkToolError("ERR_PRISM_WORK_INPUT", `maxResults must be an integer from 1 to ${maximum}`);
418
+ }
419
+ return String(number);
420
+ }
421
+
422
+ function asRecord(value: unknown): Record<string, unknown> | undefined {
423
+ return value !== null && typeof value === "object" && !Array.isArray(value) ? (value as Record<string, unknown>) : undefined;
424
+ }
425
+
426
+ function string(value: unknown): string | undefined {
427
+ return typeof value === "string" && value ? value : undefined;
428
+ }