openwork-server 0.18.61 → 0.18.62

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 (71) hide show
  1. package/dist/{opencode-plugin-deps-1.18.30.tgz → opencode-plugin-deps-1.18.33.tgz} +0 -0
  2. package/dist/opencode-plugins/drive-file-tools.js +10 -8
  3. package/dist/opencode-plugins/openwork-extensions-preview.js +9 -7
  4. package/dist/openwork-server.mjs +317 -40
  5. package/package.json +1 -1
  6. package/web/assets/{abnfDiagram-VCTEODGH-DGCabXot.js → abnfDiagram-VCTEODGH-DJzrT8Ql.js} +1 -1
  7. package/web/assets/{app-Cy3sY2K8.js → app-_2KkkZIM.js} +10 -10
  8. package/web/assets/{arc-OJTfUP9L.js → arc-KehB1xN5.js} +1 -1
  9. package/web/assets/{architectureDiagram-5GKGNRK7-Ch0Zt81S.js → architectureDiagram-5GKGNRK7-C_GL2639.js} +1 -1
  10. package/web/assets/{artifact-code-view-CSo8dBet.js → artifact-code-view-CYn_58gV.js} +1 -1
  11. package/web/assets/{artifact-spreadsheet-editor-DG2AL4aO.js → artifact-spreadsheet-editor-f6V-tYvi.js} +1 -1
  12. package/web/assets/{artifact-text-editor-BKs1cI6V.js → artifact-text-editor-CiSlW3kl.js} +1 -1
  13. package/web/assets/{blockDiagram-OSKFZWR5-Dur4PitI.js → blockDiagram-OSKFZWR5-DErH-7gY.js} +1 -1
  14. package/web/assets/{c4Diagram-7LVT6UL2-DN-qrh5o.js → c4Diagram-7LVT6UL2-aML4z_n9.js} +1 -1
  15. package/web/assets/channel-7oM0ncHI.js +1 -0
  16. package/web/assets/{chunk-2Q5K7J3B-BSmk0dam.js → chunk-2Q5K7J3B-Dw_IH9rW.js} +1 -1
  17. package/web/assets/{chunk-5VM5RSS4-BwAmjLhK.js → chunk-5VM5RSS4-aeJEQ945.js} +1 -1
  18. package/web/assets/{chunk-F27PBJKO-DLKbY_DS.js → chunk-F27PBJKO-hZwti-Oc.js} +1 -1
  19. package/web/assets/{chunk-HLEWEB6X-s4I3BuHN.js → chunk-HLEWEB6X-JFNzm3Ge.js} +1 -1
  20. package/web/assets/{chunk-JWPE2WC7-LslAnaQK.js → chunk-JWPE2WC7-B34hvYk7.js} +1 -1
  21. package/web/assets/{chunk-POPQ4Y6H-e0_lKBGk.js → chunk-POPQ4Y6H-CDqgEp-q.js} +1 -1
  22. package/web/assets/{chunk-SVP7TREG-CBKOSsQl.js → chunk-SVP7TREG-B65ta9aQ.js} +1 -1
  23. package/web/assets/{chunk-XXDRQBXY-Bwqkh7ZD.js → chunk-XXDRQBXY-DjTi6c9m.js} +1 -1
  24. package/web/assets/{chunk-ZLD2IHE6-anLhhsDd.js → chunk-ZLD2IHE6-CbviXFvb.js} +1 -1
  25. package/web/assets/classDiagram-CYGNFDIV-BkidFauP.js +1 -0
  26. package/web/assets/classDiagram-v2-TLXNO2FR-BkidFauP.js +1 -0
  27. package/web/assets/{cose-bilkent-JH36ORCC-CCj043X5.js → cose-bilkent-JH36ORCC-Cl9SO5zd.js} +1 -1
  28. package/web/assets/{cynefin-OW5HDTMX-BGWD-i0N.js → cynefin-OW5HDTMX-CAcz2tHt.js} +1 -1
  29. package/web/assets/{cynefinDiagram-5FMLGOSQ-ZWq_C5SK.js → cynefinDiagram-5FMLGOSQ-BJHft4FO.js} +1 -1
  30. package/web/assets/{dagre-OS7QT2EB-In3Mah_T.js → dagre-OS7QT2EB-DbdnY1uS.js} +1 -1
  31. package/web/assets/{diagram-S7CK7UJ4-DaTd6oXD.js → diagram-S7CK7UJ4-C07WD5Lc.js} +1 -1
  32. package/web/assets/{diagram-UQ7AKVKN-D3jwCd_v.js → diagram-UQ7AKVKN-D8VCjq9x.js} +1 -1
  33. package/web/assets/{diagram-VSXAHHWV-CsK-_hfn.js → diagram-VSXAHHWV-D1XSfMnK.js} +1 -1
  34. package/web/assets/{diagram-VX7I27RA-BBLQ2mL7.js → diagram-VX7I27RA-3GZe-yrf.js} +1 -1
  35. package/web/assets/{diagram-Z3DM3KII-CUM2PN0X.js → diagram-Z3DM3KII-CI43WcIB.js} +1 -1
  36. package/web/assets/{ebnfDiagram-PWID7BFC-BjJTJ9Vr.js → ebnfDiagram-PWID7BFC-CTzouade.js} +1 -1
  37. package/web/assets/{erDiagram-2YWLMYGG-BhjMQMDs.js → erDiagram-2YWLMYGG-CNcqsnqx.js} +1 -1
  38. package/web/assets/{flowDiagram-T62WH6J4-KrGbrW-t.js → flowDiagram-T62WH6J4-pomAqjgF.js} +1 -1
  39. package/web/assets/{ganttDiagram-EL5Y4UJY-Co_OE6ls.js → ganttDiagram-EL5Y4UJY-C1dNaxxj.js} +1 -1
  40. package/web/assets/{gitGraphDiagram-WWUBYQGX-BxM4C4Ti.js → gitGraphDiagram-WWUBYQGX-Ni8GECg1.js} +1 -1
  41. package/web/assets/{infoDiagram-FKFFQAWI-C8YaW3a6.js → infoDiagram-FKFFQAWI-C0kvE7Zu.js} +1 -1
  42. package/web/assets/{ishikawaDiagram-5VMMS53U-MPTb2C9Y.js → ishikawaDiagram-5VMMS53U-CxmP_irp.js} +1 -1
  43. package/web/assets/{journeyDiagram-EYS64GPL-Dzq-vllP.js → journeyDiagram-EYS64GPL-60GkPgH5.js} +1 -1
  44. package/web/assets/{kanban-definition-UXKFOSKX-DWhE5bnH.js → kanban-definition-UXKFOSKX-ByxcB0T_.js} +1 -1
  45. package/web/assets/{layout-CMyIV62W.js → layout-BD9ef90s.js} +1 -1
  46. package/web/assets/{linear-CX-tWibZ.js → linear-Dp9l0lBr.js} +1 -1
  47. package/web/assets/{mermaid.core-DcgS6fFC.js → mermaid.core-FKm3Akes.js} +6 -6
  48. package/web/assets/{mindmap-definition-THT77NOG-CJzNRYpk.js → mindmap-definition-THT77NOG-i7WJlWHV.js} +1 -1
  49. package/web/assets/{pegDiagram-XKGWAZYB-BSIi724T.js → pegDiagram-XKGWAZYB-DfI-LsJq.js} +1 -1
  50. package/web/assets/{pieDiagram-E7YTZNPT-CoArMhZD.js → pieDiagram-E7YTZNPT-kcgWYBSb.js} +1 -1
  51. package/web/assets/{quadrantDiagram-AXDQQJYC-B9HoxOyK.js → quadrantDiagram-AXDQQJYC-DVyziZnc.js} +1 -1
  52. package/web/assets/{railroadDiagram-O6MQD6OU-C-aYV4dU.js → railroadDiagram-O6MQD6OU-CWgHq9nv.js} +1 -1
  53. package/web/assets/{requirementDiagram-IS5BZ75X-DHPnVlti.js → requirementDiagram-IS5BZ75X-B7fgi4lz.js} +1 -1
  54. package/web/assets/{sankeyDiagram-P5KCCOFB-DlxAwgv1.js → sankeyDiagram-P5KCCOFB-D1-pD_qh.js} +1 -1
  55. package/web/assets/{sequenceDiagram-WJ2MYXX4-DzVPZb2m.js → sequenceDiagram-WJ2MYXX4-B6oeRmVj.js} +1 -1
  56. package/web/assets/{sizeCapture-INFHLROL-BkwjaMAx.js → sizeCapture-INFHLROL-BTpKGFt5.js} +1 -1
  57. package/web/assets/{stateDiagram-XQSTLZYL-DIeNtdWj.js → stateDiagram-XQSTLZYL-zXJRxE6h.js} +1 -1
  58. package/web/assets/stateDiagram-v2-IH3M54BS-CmwZ6tXj.js +1 -0
  59. package/web/assets/{swimlanes-V6O3JKXN-CPUSs3Tj.js → swimlanes-V6O3JKXN-Dc7MXPb3.js} +1 -1
  60. package/web/assets/swimlanesDiagram-JKAHXJPX-BXoJEx2b.js +8 -0
  61. package/web/assets/{timeline-definition-24CTP7MA-CjBwDFJH.js → timeline-definition-24CTP7MA-DYhgbnjW.js} +1 -1
  62. package/web/assets/{vennDiagram-4TSXK5OY-DOsoEsMT.js → vennDiagram-4TSXK5OY-DRnme7za.js} +1 -1
  63. package/web/assets/{wardleyDiagram-VM6X3IG4-_fhLZdvF.js → wardleyDiagram-VM6X3IG4-wAoo4GsZ.js} +1 -1
  64. package/web/assets/{workspace-file-tree-CTzNl5A5.js → workspace-file-tree-DmAwvqtx.js} +1 -1
  65. package/web/assets/{xychartDiagram-S5SC5T6Z-D4Kz81TF.js → xychartDiagram-S5SC5T6Z-_Z_TOWBn.js} +1 -1
  66. package/web/index.html +1 -1
  67. package/web/assets/channel-68fpiRG4.js +0 -1
  68. package/web/assets/classDiagram-CYGNFDIV-Z4CG2h2d.js +0 -1
  69. package/web/assets/classDiagram-v2-TLXNO2FR-Z4CG2h2d.js +0 -1
  70. package/web/assets/stateDiagram-v2-IH3M54BS-CZR_2wND.js +0 -1
  71. package/web/assets/swimlanesDiagram-JKAHXJPX-C1Sms2Ey.js +0 -8
@@ -310371,6 +310371,14 @@ import { createHash as createHash16, randomBytes as randomBytes6 } from "node:cr
310371
310371
  import { constants as constants3, realpathSync } from "node:fs";
310372
310372
  import { lstat as lstat3, mkdir as mkdir13, open as open4, readFile as readFile24, realpath as realpath5, rename as rename7, rm as rm12, stat as stat6, writeFile as writeFile17 } from "node:fs/promises";
310373
310373
  import { basename as basename10, dirname as dirname15, extname as extname2, isAbsolute as isAbsolute3, join as join25, relative as relative5, resolve as resolve16 } from "node:path";
310374
+
310375
+ // ../../packages/types/src/microsoft-drive-transfer.ts
310376
+ var MICROSOFT_DRIVE_TRANSFER_MAX_BYTES = 250 * 1024 * 1024;
310377
+ var MICROSOFT_DRIVE_PULL_CHUNK_BYTES = 8 * 1024 * 1024;
310378
+ var MICROSOFT_DRIVE_UPLOAD_CHUNK_BYTES = 32 * 320 * 1024;
310379
+ var MICROSOFT_DRIVE_UPLOAD_MAX_BYTES = 250 * 1000 ** 3;
310380
+
310381
+ // src/extensions/drive-files.ts
310374
310382
  init_errors5();
310375
310383
  init_runtime_db();
310376
310384
 
@@ -310461,7 +310469,11 @@ var LINKS_FILE = "drive-links.json";
310461
310469
  var DEN_TIMEOUT_MS = 2 * 60 * 1000;
310462
310470
  var MAX_STATUS_FILES = 50;
310463
310471
  var CONNECTION_ID = /^(google-workspace|emc_[A-Za-z0-9]+)$/;
310472
+ var MICROSOFT_CONNECTION_ID = /^(microsoft-365|emc_[A-Za-z0-9]+)$/;
310464
310473
  var DRIVE_ID = /^[A-Za-z0-9_-]{1,512}$/;
310474
+ var MICROSOFT_ID = /^[^\s/\\?#]{1,512}$/;
310475
+ var MICROSOFT_LINK_HOST = /(^|\.)(sharepoint\.(com|us|cn|de)|sharepoint-mil\.us|onedrive\.(com|live\.com)|1drv\.ms)$/;
310476
+ var SERVICE_NAME = { "google-workspace": "Drive", "microsoft-365": "OneDrive or SharePoint" };
310465
310477
  var CONVERTIBLE_FORMATS = {
310466
310478
  "application/vnd.google-apps.spreadsheet": ["xlsx", "csv"],
310467
310479
  "application/vnd.google-apps.document": ["docx", "md", "txt"],
@@ -310487,14 +310499,47 @@ function readArgString(args2, key2) {
310487
310499
  const value3 = args2[key2];
310488
310500
  return typeof value3 === "string" ? value3.trim() : "";
310489
310501
  }
310490
- function optionalConnectionId(args2) {
310502
+ function optionalConnectionId(args2, provider = "google-workspace") {
310491
310503
  if (args2.connectionId === undefined)
310492
310504
  return;
310493
- if (typeof args2.connectionId !== "string" || !CONNECTION_ID.test(args2.connectionId)) {
310494
- throw new ApiError(400, "invalid_payload", "connectionId must identify a native Google Workspace connection.");
310505
+ const pattern = provider === "microsoft-365" ? MICROSOFT_CONNECTION_ID : CONNECTION_ID;
310506
+ if (typeof args2.connectionId !== "string" || !pattern.test(args2.connectionId)) {
310507
+ throw new ApiError(400, "invalid_payload", provider === "microsoft-365" ? "connectionId must identify a Microsoft 365 connection." : "connectionId must identify a native Google Workspace connection.");
310495
310508
  }
310496
310509
  return args2.connectionId;
310497
310510
  }
310511
+ function isMicrosoftLink(value3) {
310512
+ try {
310513
+ const url2 = new URL(value3);
310514
+ return url2.protocol === "https:" && MICROSOFT_LINK_HOST.test(url2.hostname);
310515
+ } catch {
310516
+ return false;
310517
+ }
310518
+ }
310519
+ function providerFor(args2) {
310520
+ if (args2.provider !== undefined) {
310521
+ if (args2.provider !== "google-workspace" && args2.provider !== "microsoft-365")
310522
+ throw new ApiError(400, "invalid_payload", "provider must be google-workspace or microsoft-365.");
310523
+ return args2.provider;
310524
+ }
310525
+ if (args2.driveId !== undefined || args2.connectionId === "microsoft-365")
310526
+ return "microsoft-365";
310527
+ return isMicrosoftLink(readArgString(args2, "fileId")) ? "microsoft-365" : "google-workspace";
310528
+ }
310529
+ function microsoftTarget(args2) {
310530
+ const fileId = readArgString(args2, "fileId");
310531
+ const driveId = args2.driveId === undefined ? undefined : readArgString(args2, "driveId");
310532
+ if (driveId !== undefined && !MICROSOFT_ID.test(driveId))
310533
+ throw new ApiError(400, "invalid_payload", "driveId must be a Microsoft drive id.");
310534
+ if (isMicrosoftLink(fileId)) {
310535
+ if (driveId !== undefined)
310536
+ throw new ApiError(400, "invalid_payload", "Pass a OneDrive or SharePoint link, or an item id with its driveId, not both.");
310537
+ return { url: fileId };
310538
+ }
310539
+ if (!MICROSOFT_ID.test(fileId))
310540
+ throw new ApiError(400, "invalid_payload", "fileId must be a OneDrive or SharePoint item id or file link.");
310541
+ return { itemId: fileId, ...driveId ? { driveId } : {} };
310542
+ }
310498
310543
  function parseDriveFileId(value3) {
310499
310544
  const trimmed = value3.trim();
310500
310545
  if (DRIVE_ID.test(trimmed))
@@ -310738,9 +310783,11 @@ async function denRequest(config2, dependencies, suffix, init = {}) {
310738
310783
  headers: {
310739
310784
  authorization: endpoint.authorization,
310740
310785
  ...init.body !== undefined ? { "content-type": "application/json" } : {},
310786
+ ...init.bytes ? { "content-type": "application/octet-stream" } : {},
310741
310787
  ...init.headers
310742
310788
  },
310743
310789
  ...init.body !== undefined ? { body: JSON.stringify(init.body) } : {},
310790
+ ...init.bytes ? { body: init.bytes } : {},
310744
310791
  signal: dependencies.signal ? AbortSignal.any([dependencies.signal, AbortSignal.timeout(DEN_TIMEOUT_MS)]) : AbortSignal.timeout(DEN_TIMEOUT_MS)
310745
310792
  });
310746
310793
  } catch (error48) {
@@ -310774,6 +310821,7 @@ function parseDownloadInfo(payload) {
310774
310821
  return {
310775
310822
  file: {
310776
310823
  id: file2.id,
310824
+ driveId: "",
310777
310825
  name: file2.name,
310778
310826
  mimeType: file2.mimeType,
310779
310827
  native: file2.native === true,
@@ -310793,12 +310841,55 @@ function parseDownloadInfo(payload) {
310793
310841
  }
310794
310842
  };
310795
310843
  }
310796
- async function describe4(config2, dependencies, fileId, format4, connectionId) {
310797
- return parseDownloadInfo(await denJson(config2, dependencies, `/v1/direct-downloads/google-workspace/drive-files/${fileId}`, { query: { format: format4, connectionId } }));
310844
+ function parseMicrosoftDownloadInfo(payload) {
310845
+ const file2 = payload.file;
310846
+ const download = payload.download;
310847
+ if (!isRecord28(file2) || !isRecord28(download) || typeof file2.id !== "string" || !MICROSOFT_ID.test(file2.id) || typeof file2.name !== "string" || typeof file2.mimeType !== "string" || typeof download.mimeType !== "string" || file2.driveId !== "" && (typeof file2.driveId !== "string" || !MICROSOFT_ID.test(file2.driveId))) {
310848
+ throw new ApiError(502, "cloud_drive_failed", "OpenWork Cloud returned an invalid OneDrive or SharePoint file description.");
310849
+ }
310850
+ const size6 = typeof download.size === "number" && Number.isSafeInteger(download.size) ? download.size : null;
310851
+ return {
310852
+ file: {
310853
+ id: file2.id,
310854
+ driveId: file2.driveId,
310855
+ name: file2.name,
310856
+ mimeType: file2.mimeType,
310857
+ native: false,
310858
+ revision: stringOrNull(file2.revision),
310859
+ md5Checksum: null,
310860
+ size: typeof file2.size === "number" ? file2.size : null,
310861
+ webViewLink: stringOrNull(file2.webUrl),
310862
+ parents: typeof file2.parentId === "string" && file2.parentId ? [file2.parentId] : []
310863
+ },
310864
+ download: {
310865
+ format: download.format === "pdf" ? "pdf" : null,
310866
+ mimeType: download.mimeType,
310867
+ extension: stringOrNull(download.extension),
310868
+ size: size6,
310869
+ exported: download.exported === true,
310870
+ maxBytes: typeof download.maxBytes === "number" ? Math.min(download.maxBytes, MICROSOFT_DRIVE_TRANSFER_MAX_BYTES) : MICROSOFT_DRIVE_TRANSFER_MAX_BYTES
310871
+ }
310872
+ };
310873
+ }
310874
+ async function describe4(config2, dependencies, target, format4, connectionId) {
310875
+ if ("fileId" in target) {
310876
+ return parseDownloadInfo(await denJson(config2, dependencies, `/v1/direct-downloads/google-workspace/drive-files/${target.fileId}`, { query: { format: format4, connectionId } }));
310877
+ }
310878
+ const query = "url" in target ? { url: target.url } : { itemId: target.itemId, driveId: target.driveId };
310879
+ return parseMicrosoftDownloadInfo(await denJson(config2, dependencies, "/v1/direct-downloads/microsoft-365/drive-files", { query: { ...query, format: format4, connectionId } }));
310880
+ }
310881
+ function describedTarget(provider, info) {
310882
+ return provider === "microsoft-365" ? { itemId: info.file.id, ...info.file.driveId ? { driveId: info.file.driveId } : {} } : { fileId: info.file.id };
310798
310883
  }
310799
- async function download(config2, dependencies, info, connectionId, handle) {
310800
- const suffix = `/v1/direct-downloads/google-workspace/drive-files/${info.file.id}/content`;
310801
- const query = { format: info.download.exported ? info.download.format ?? undefined : undefined, connectionId };
310884
+ function linkTarget(link2) {
310885
+ return link2.provider === "microsoft-365" ? { itemId: link2.fileId, ...link2.driveId ? { driveId: link2.driveId } : {} } : { fileId: link2.fileId };
310886
+ }
310887
+ async function download(config2, dependencies, provider, info, connectionId, handle) {
310888
+ const format4 = info.download.exported ? info.download.format ?? undefined : undefined;
310889
+ const microsoft = provider === "microsoft-365";
310890
+ const suffix = microsoft ? "/v1/direct-downloads/microsoft-365/drive-files/content" : `/v1/direct-downloads/google-workspace/drive-files/${info.file.id}/content`;
310891
+ const query = microsoft ? { itemId: info.file.id, driveId: info.file.driveId || undefined, format: format4, connectionId } : { format: format4, connectionId };
310892
+ const chunkBytes = microsoft ? MICROSOFT_DRIVE_PULL_CHUNK_BYTES : GOOGLE_DRIVE_PULL_CHUNK_BYTES;
310802
310893
  const sha256 = createHash16("sha256");
310803
310894
  const md5 = createHash16("md5");
310804
310895
  let written = 0;
@@ -310812,14 +310903,14 @@ async function download(config2, dependencies, info, connectionId, handle) {
310812
310903
  };
310813
310904
  const size6 = info.download.size;
310814
310905
  if (!info.download.exported && size6 !== null) {
310815
- for (let start = 0;start < size6; start += GOOGLE_DRIVE_PULL_CHUNK_BYTES) {
310816
- const end = Math.min(size6, start + GOOGLE_DRIVE_PULL_CHUNK_BYTES) - 1;
310906
+ for (let start = 0;start < size6; start += chunkBytes) {
310907
+ const end = Math.min(size6, start + chunkBytes) - 1;
310817
310908
  const response = await denRequest(config2, dependencies, suffix, { query, headers: { range: `bytes=${start}-${end}` } });
310818
310909
  if (!response.ok)
310819
310910
  await denFailure(response);
310820
310911
  if (response.status !== 206 && !(response.status === 200 && start === 0 && end === size6 - 1)) {
310821
310912
  await response.body?.cancel();
310822
- throw new ApiError(502, "drive_download_incomplete", "Google did not return the requested part of the file. Try the pull again.");
310913
+ throw new ApiError(502, "drive_download_incomplete", "The requested part of the file did not arrive. Try the pull again.");
310823
310914
  }
310824
310915
  const bytes = new Uint8Array(await response.arrayBuffer().catch(() => {
310825
310916
  throw new ApiError(502, "drive_download_incomplete", "The download stopped early. Try the pull again.");
@@ -310833,7 +310924,7 @@ async function download(config2, dependencies, info, connectionId, handle) {
310833
310924
  if (!response.ok)
310834
310925
  await denFailure(response);
310835
310926
  if (!response.body)
310836
- throw new ApiError(502, "drive_download_incomplete", "Google returned no file content.");
310927
+ throw new ApiError(502, "drive_download_incomplete", "No file content arrived.");
310837
310928
  try {
310838
310929
  for await (const chunk of response.body)
310839
310930
  await write(chunk);
@@ -310849,21 +310940,28 @@ function verified(info, saved) {
310849
310940
  return (info.download.size === null || saved.size === info.download.size) && (info.download.exported || !info.file.md5Checksum || saved.md5 === info.file.md5Checksum);
310850
310941
  }
310851
310942
  async function pullDriveFile(config2, args2, context4, dependencies) {
310852
- const fileId = parseDriveFileId(readArgString(args2, "fileId"));
310943
+ const provider = providerFor(args2);
310944
+ let fileTarget = provider === "microsoft-365" ? microsoftTarget(args2) : { fileId: parseDriveFileId(readArgString(args2, "fileId")) };
310853
310945
  const format4 = readArgString(args2, "format") || undefined;
310946
+ if (provider === "microsoft-365" && format4 && format4 !== "pdf")
310947
+ throw new ApiError(400, "invalid_payload", "OneDrive and SharePoint files can only be converted to pdf; omit format to pull the file as it is.");
310854
310948
  if (format4 && !/^[a-z]{2,5}$/.test(format4))
310855
310949
  throw new ApiError(400, "invalid_payload", "format must be an export format such as xlsx, csv, docx, md, txt, pptx or pdf.");
310856
- const connectionId = optionalConnectionId(args2);
310950
+ const connectionId = optionalConnectionId(args2, provider);
310857
310951
  const overwrite = args2.overwrite === true;
310858
310952
  const requested = readArgString(args2, "path") || null;
310859
- let info = await describe4(config2, dependencies, fileId, format4, connectionId);
310860
- const name = safeFileName(info.file.name, info.download.exported ? info.download.extension : null);
310953
+ const service3 = SERVICE_NAME[provider];
310954
+ let info = await describe4(config2, dependencies, fileTarget, format4, connectionId);
310955
+ fileTarget = describedTarget(provider, info);
310956
+ const converted = provider === "microsoft-365" && info.download.exported;
310957
+ const sourceName = converted ? info.file.name.slice(0, info.file.name.length - extname2(info.file.name).length) || info.file.name : info.file.name;
310958
+ const name = safeFileName(sourceName, info.download.exported ? info.download.extension : null);
310861
310959
  const links = await readLinks(config2);
310862
310960
  let target = await resolvePullTarget(config2, context4, requested, name);
310863
310961
  if (!requested) {
310864
310962
  const extension = extname2(name);
310865
310963
  const stem = name.slice(0, name.length - extension.length);
310866
- for (let copy2 = 2;await exists2(target) && links.links[target]?.fileId !== info.file.id; copy2 += 1) {
310964
+ for (let copy2 = 2;await exists2(target) && !sameDriveFile(links.links[target], provider, info); copy2 += 1) {
310867
310965
  if (copy2 > 50)
310868
310966
  throw new ApiError(409, "path_exists", "Choose a path for this file; the default names are taken.");
310869
310967
  target = await resolvePullTarget(config2, context4, null, `${stem} (${copy2})${extension}`);
@@ -310872,24 +310970,24 @@ async function pullDriveFile(config2, args2, context4, dependencies) {
310872
310970
  const before = await lstat3(target).catch(() => null);
310873
310971
  if (before) {
310874
310972
  const link3 = links.links[target];
310875
- if (link3?.fileId === info.file.id) {
310973
+ if (sameDriveFile(link3, provider, info)) {
310876
310974
  const local = await hashFile(target);
310877
310975
  if (local.sha256 === link3.sha256 && link3.revision !== null && link3.revision === info.file.revision && link3.format === info.download.format) {
310878
310976
  return pullResult(config2, context4, target, info, local.size, true);
310879
310977
  }
310880
310978
  if (!overwrite && local.sha256 !== link3.sha256) {
310881
- throw new ApiError(409, "local_changes", "The local copy has edits that are not in Drive. Push them first, or pull with overwrite: true to discard them.", { path: displayPath(config2, context4, target) });
310979
+ throw new ApiError(409, "local_changes", `The local copy has edits that are not in ${service3}. Push them first, or pull with overwrite: true to discard them.`, { path: displayPath(config2, context4, target) });
310882
310980
  }
310883
310981
  } else if (!overwrite) {
310884
310982
  throw new ApiError(409, "path_exists", "A different file already exists at that path. Choose another path, or pass overwrite: true to replace it.");
310885
310983
  }
310886
310984
  }
310887
310985
  let saved = null;
310888
- await confirmDriveTransfer(config2, { action: before && overwrite ? "overwrite" : "pull", path: target, fileId: info.file.id, name: info.file.name, webViewLink: info.file.webViewLink }, dependencies.signal);
310986
+ await confirmDriveTransfer(config2, { provider, action: before && overwrite ? "overwrite" : "pull", path: target, fileId: info.file.id, name: info.file.name, webViewLink: info.file.webViewLink }, dependencies.signal);
310889
310987
  for (let attempt = 1;attempt <= 2 && !saved; attempt += 1) {
310890
310988
  const temporary = await privateDriveFile(config2);
310891
310989
  try {
310892
- const result3 = await download(config2, dependencies, info, connectionId, temporary);
310990
+ const result3 = await download(config2, dependencies, provider, info, connectionId, temporary);
310893
310991
  if (verified(info, result3)) {
310894
310992
  if (!sameState(before, await lstat3(target).catch(() => null))) {
310895
310993
  throw new ApiError(409, "local_changes", "The file at that path changed while pulling, so it was not replaced. Pull again once it is saved or pushed.", { path: displayPath(config2, context4, target) });
@@ -310919,10 +311017,10 @@ async function pullDriveFile(config2, args2, context4, dependencies) {
310919
311017
  }
310920
311018
  }
310921
311019
  } catch (error48) {
310922
- const transient = error48 instanceof ApiError && ["drive_download_incomplete", "google_api_error", "cloud_drive_failed"].includes(error48.code);
311020
+ const transient = error48 instanceof ApiError && ["drive_download_incomplete", "google_api_error", "microsoft_graph_error", "cloud_drive_failed"].includes(error48.code);
310923
311021
  if (!transient || attempt === 2)
310924
311022
  throw error48;
310925
- const fresh = await describe4(config2, dependencies, fileId, format4, connectionId);
311023
+ const fresh = await describe4(config2, dependencies, fileTarget, format4, connectionId);
310926
311024
  if (fresh.file.revision === info.file.revision)
310927
311025
  throw error48;
310928
311026
  info = fresh;
@@ -310931,11 +311029,12 @@ async function pullDriveFile(config2, args2, context4, dependencies) {
310931
311029
  await temporary.close();
310932
311030
  }
310933
311031
  if (!saved && attempt === 1)
310934
- info = await describe4(config2, dependencies, fileId, format4, connectionId);
311032
+ info = await describe4(config2, dependencies, fileTarget, format4, connectionId);
310935
311033
  }
310936
311034
  if (!saved)
310937
- throw new ApiError(409, "drive_changed_during_download", "The file kept changing in Drive while downloading. Try again later.");
311035
+ throw new ApiError(409, "drive_changed_during_download", `The file kept changing in ${service3} while downloading. Try again later.`);
310938
311036
  const link2 = {
311037
+ ...provider === "microsoft-365" ? { provider, driveId: info.file.driveId } : {},
310939
311038
  fileId: info.file.id,
310940
311039
  connectionId: connectionId ?? null,
310941
311040
  name: info.file.name,
@@ -310964,9 +311063,21 @@ function pullResult(config2, context4, target, info, size6, upToDate) {
310964
311063
  mimeType: info.download.mimeType,
310965
311064
  ...info.download.exported ? { exportedAs: info.download.format } : {},
310966
311065
  ...upToDate ? { upToDate: true } : {},
310967
- file: { id: info.file.id, name: info.file.name, mimeType: info.file.mimeType, webViewLink: info.file.webViewLink, revision: info.file.revision }
311066
+ file: {
311067
+ id: info.file.id,
311068
+ ...info.file.driveId ? { driveId: info.file.driveId } : {},
311069
+ name: info.file.name,
311070
+ mimeType: info.file.mimeType,
311071
+ webViewLink: info.file.webViewLink,
311072
+ revision: info.file.revision
311073
+ }
310968
311074
  };
310969
311075
  }
311076
+ function sameDriveFile(link2, provider, info) {
311077
+ if (!link2 || (link2.provider ?? "google-workspace") !== provider || link2.fileId !== info.file.id)
311078
+ return false;
311079
+ return provider !== "microsoft-365" || (link2.driveId ?? "") === info.file.driveId;
311080
+ }
310970
311081
  async function linkedEntries(config2, context4, requested) {
310971
311082
  const links = await readLinks(config2);
310972
311083
  const roots = [...allowedRoots(config2), ...await realRoots(config2)];
@@ -310986,6 +311097,9 @@ async function linkedEntries(config2, context4, requested) {
310986
311097
  }
310987
311098
  return entries3;
310988
311099
  }
311100
+ function linkFormat(link2) {
311101
+ return link2.provider === "microsoft-365" || link2.native ? link2.format ?? undefined : undefined;
311102
+ }
310989
311103
  async function driveFileStatus(config2, args2, context4, dependencies) {
310990
311104
  const entries3 = await linkedEntries(config2, context4, readArgString(args2, "path"));
310991
311105
  const files = [];
@@ -310997,7 +311111,7 @@ async function driveFileStatus(config2, args2, context4, dependencies) {
310997
311111
  let currentRevision = null;
310998
311112
  let note;
310999
311113
  try {
311000
- const info = await describe4(config2, dependencies, link2.fileId, link2.native ? link2.format ?? undefined : undefined, link2.connectionId ?? undefined);
311114
+ const info = await describe4(config2, dependencies, linkTarget(link2), linkFormat(link2), link2.connectionId ?? undefined);
311001
311115
  currentRevision = info.file.revision;
311002
311116
  drive = currentRevision === link2.revision ? "unchanged" : "changed";
311003
311117
  } catch (error48) {
@@ -311008,7 +311122,9 @@ async function driveFileStatus(config2, args2, context4, dependencies) {
311008
311122
  }
311009
311123
  files.push({
311010
311124
  path: displayPath(config2, context4, path3),
311125
+ provider: link2.provider ?? "google-workspace",
311011
311126
  fileId: link2.fileId,
311127
+ ...link2.driveId ? { driveId: link2.driveId } : {},
311012
311128
  name: link2.name,
311013
311129
  webViewLink: link2.webViewLink,
311014
311130
  local,
@@ -311059,6 +311175,8 @@ async function pushOpenFile(config2, args2, context4, dependencies, path3, handl
311059
311175
  const link2 = (await readLinks(config2)).links[path3];
311060
311176
  if (!link2)
311061
311177
  throw new ApiError(409, "not_linked", "That file was not pulled from Drive. Upload it as a new file with drive_upload_file instead.");
311178
+ if (link2.provider === "microsoft-365")
311179
+ return pushMicrosoftFile(config2, args2, context4, dependencies, path3, handle, link2);
311062
311180
  if (!DRIVE_ID.test(link2.fileId) || link2.connectionId !== null && !CONNECTION_ID.test(link2.connectionId)) {
311063
311181
  throw new ApiError(409, "invalid_link", "The saved Drive link is invalid. Pull the file again before saving.");
311064
311182
  }
@@ -311078,14 +311196,14 @@ async function pushOpenFile(config2, args2, context4, dependencies, path3, handl
311078
311196
  }
311079
311197
  const snapshot = await snapshotForPush(config2, handle, local, dependencies.signal);
311080
311198
  try {
311081
- const remote = await describe4(config2, dependencies, link2.fileId, link2.native ? link2.format ?? undefined : undefined, link2.connectionId ?? undefined);
311199
+ const remote = await describe4(config2, dependencies, linkTarget(link2), linkFormat(link2), link2.connectionId ?? undefined);
311082
311200
  if (remote.file.id !== link2.fileId)
311083
311201
  throw new ApiError(409, "drive_conflict", "The Drive target changed. Pull it again before saving.");
311084
311202
  if (mode === "replace" && remote.file.native)
311085
311203
  throw new ApiError(400, "native_file_replace_unsupported", "Save this Google file as a copy instead.");
311086
311204
  const target = { ...link2, name: remote.file.name, driveMimeType: remote.file.mimeType, native: remote.file.native, parents: remote.file.parents };
311087
311205
  const convert = mode === "copy" && target.native && (CONVERTIBLE_FORMATS[target.driveMimeType] ?? []).includes(link2.format ?? "");
311088
- await confirmDriveTransfer(config2, { action: "push", path: path3, fileId: remote.file.id, name: remote.file.name, webViewLink: remote.file.webViewLink, mode: mode === "copy" ? "copy" : "replace" }, dependencies.signal);
311206
+ await confirmDriveTransfer(config2, { provider: "google-workspace", action: "push", path: path3, fileId: remote.file.id, name: remote.file.name, webViewLink: remote.file.webViewLink, mode: mode === "copy" ? "copy" : "replace" }, dependencies.signal);
311089
311207
  await assertStableFolder(config2, dirname15(path3));
311090
311208
  await assertSameFile(path3, await handle.stat());
311091
311209
  if ((await hashHandle(handle)).sha256 !== local.sha256) {
@@ -311141,6 +311259,163 @@ async function pushOpenFile(config2, args2, context4, dependencies, path3, handl
311141
311259
  await snapshot.close();
311142
311260
  }
311143
311261
  }
311262
+ async function relayProgress(response) {
311263
+ const payload = await response.json().catch(() => null);
311264
+ if (!response.ok) {
311265
+ const code = isRecord28(payload) && typeof payload.error === "string" ? payload.error : "";
311266
+ if (response.status >= 500 || code === "upload_out_of_order")
311267
+ return "uncertain";
311268
+ const message = isRecord28(payload) && typeof payload.message === "string" ? payload.message : `OpenWork Cloud returned HTTP ${response.status}.`;
311269
+ const details = isRecord28(payload) ? Object.fromEntries(Object.entries(payload).filter(([key2]) => key2 === "currentRevision" || key2 === "modifiedTime")) : {};
311270
+ throw new ApiError(response.status, code || "cloud_drive_failed", message, Object.keys(details).length ? details : undefined);
311271
+ }
311272
+ if (isRecord28(payload) && payload.status === "partial" && typeof payload.nextOffset === "number" && Number.isSafeInteger(payload.nextOffset)) {
311273
+ return { status: "partial", nextOffset: payload.nextOffset };
311274
+ }
311275
+ if (isRecord28(payload) && payload.status === "complete" && isRecord28(payload.file) && typeof payload.file.id === "string" && MICROSOFT_ID.test(payload.file.id)) {
311276
+ return { status: "complete", file: payload.file };
311277
+ }
311278
+ return "uncertain";
311279
+ }
311280
+ async function uploadMicrosoftRelayFile(config2, dependencies, input) {
311281
+ const suffix = "/v1/direct-uploads/microsoft-365/drive-upload-sessions/content";
311282
+ const query = { token: input.token };
311283
+ const unconfirmed = () => new ApiError(502, "drive_upload_unconfirmed", "Microsoft did not confirm the upload. Check the file before retrying; no new upload was started.");
311284
+ let offset2 = 0;
311285
+ let recoveries = 0;
311286
+ while (true) {
311287
+ dependencies.signal?.throwIfAborted();
311288
+ const length = Math.min(input.chunkBytes, input.size - offset2);
311289
+ const bytes = new Uint8Array(length);
311290
+ for (let read2 = 0;read2 < length; ) {
311291
+ const part = await input.file.read(bytes, read2, length - read2, offset2 + read2);
311292
+ if (!part.bytesRead)
311293
+ throw new ApiError(409, "file_changed", "The file was truncated during upload.");
311294
+ read2 += part.bytesRead;
311295
+ }
311296
+ let result3;
311297
+ try {
311298
+ result3 = await relayProgress(await denRequest(config2, dependencies, suffix, {
311299
+ method: "PUT",
311300
+ query,
311301
+ headers: { "content-range": `bytes ${offset2}-${offset2 + length - 1}/${input.size}` },
311302
+ bytes
311303
+ }));
311304
+ } catch (error48) {
311305
+ if (!(error48 instanceof ApiError) || error48.code !== "cloud_unreachable")
311306
+ throw error48;
311307
+ result3 = "uncertain";
311308
+ }
311309
+ if (result3 === "uncertain") {
311310
+ if (++recoveries > 2)
311311
+ throw unconfirmed();
311312
+ try {
311313
+ result3 = await relayProgress(await denRequest(config2, dependencies, suffix, { query }));
311314
+ } catch (error48) {
311315
+ if (error48 instanceof ApiError && error48.code === "cloud_unreachable")
311316
+ throw unconfirmed();
311317
+ throw error48;
311318
+ }
311319
+ if (result3 === "uncertain")
311320
+ throw unconfirmed();
311321
+ }
311322
+ if (result3.status === "complete")
311323
+ return result3.file;
311324
+ if (result3.nextOffset < 0 || result3.nextOffset >= input.size)
311325
+ throw unconfirmed();
311326
+ if (result3.nextOffset <= offset2 && ++recoveries > 2)
311327
+ throw new ApiError(502, "drive_upload_unconfirmed", "Microsoft's upload made no progress. Completion is not confirmed; check the file before retrying.");
311328
+ offset2 = result3.nextOffset;
311329
+ }
311330
+ }
311331
+ async function pushMicrosoftFile(config2, args2, context4, dependencies, path3, handle, link2) {
311332
+ if (!MICROSOFT_ID.test(link2.fileId) || link2.driveId && !MICROSOFT_ID.test(link2.driveId) || link2.connectionId !== null && !MICROSOFT_CONNECTION_ID.test(link2.connectionId)) {
311333
+ throw new ApiError(409, "invalid_link", "The saved OneDrive or SharePoint link is invalid. Pull the file again before saving.");
311334
+ }
311335
+ const modeArg = readArgString(args2, "mode");
311336
+ if (modeArg && modeArg !== "replace" && modeArg !== "copy")
311337
+ throw new ApiError(400, "invalid_payload", "mode must be replace or copy.");
311338
+ const converted = link2.format !== null;
311339
+ const mode = modeArg || (converted ? "copy" : "replace");
311340
+ if (mode === "replace" && converted) {
311341
+ throw new ApiError(400, "converted_file_replace_unsupported", "A PDF made from this file cannot replace the original. Push with mode copy to save the PDF next to it.");
311342
+ }
311343
+ if (mode === "replace" && !link2.revision) {
311344
+ throw new ApiError(409, "revision_unknown", "Microsoft reported no revision when this file was pulled, so newer changes could not be detected. Pull it again, or save the edits as a copy.");
311345
+ }
311346
+ const local = await hashHandle(handle);
311347
+ if (local.size > MICROSOFT_DRIVE_TRANSFER_MAX_BYTES) {
311348
+ throw new ApiError(413, "file_too_large", `Saving to OneDrive or SharePoint supports files up to ${MICROSOFT_DRIVE_TRANSFER_MAX_BYTES} bytes.`);
311349
+ }
311350
+ if (mode === "replace" && local.sha256 === link2.sha256) {
311351
+ return { ok: true, unchanged: true, path: displayPath(config2, context4, path3), file: { id: link2.fileId, driveId: link2.driveId ?? "", name: link2.name, webViewLink: link2.webViewLink, revision: link2.revision } };
311352
+ }
311353
+ const snapshot = await snapshotForPush(config2, handle, local, dependencies.signal);
311354
+ try {
311355
+ const remote = await describe4(config2, dependencies, linkTarget(link2), undefined, link2.connectionId ?? undefined);
311356
+ if (remote.file.id !== link2.fileId)
311357
+ throw new ApiError(409, "drive_conflict", "The OneDrive or SharePoint target changed. Pull it again before saving.");
311358
+ await confirmDriveTransfer(config2, { provider: "microsoft-365", action: "push", path: path3, fileId: remote.file.id, name: remote.file.name, webViewLink: remote.file.webViewLink, mode: mode === "copy" ? "copy" : "replace" }, dependencies.signal);
311359
+ await assertStableFolder(config2, dirname15(path3));
311360
+ await assertSameFile(path3, await handle.stat());
311361
+ if ((await hashHandle(handle)).sha256 !== local.sha256) {
311362
+ throw new ApiError(409, "local_changes", "The local file changed while confirmation was open. Nothing was uploaded; review the edits and save again.");
311363
+ }
311364
+ const extension = converted ? ".pdf" : extname2(remote.file.name);
311365
+ const stem = remote.file.name.slice(0, remote.file.name.length - extname2(remote.file.name).length);
311366
+ const requestedName = readArgString(args2, "name").replace(/[/\\\x00-\x1f\x7f]/g, "_").slice(0, 255);
311367
+ const name = requestedName || `${stem} (edited)${extension}`;
311368
+ const driveId = remote.file.driveId || link2.driveId;
311369
+ const session2 = await denJson(config2, dependencies, "/v1/direct-uploads/microsoft-365/drive-upload-sessions", {
311370
+ method: "POST",
311371
+ body: {
311372
+ size: local.size,
311373
+ ...link2.connectionId ? { connectionId: link2.connectionId } : {},
311374
+ ...driveId ? { driveId } : {},
311375
+ ...mode === "replace" ? { itemId: link2.fileId, baseRevision: link2.revision } : { name, conflictBehavior: "rename", ...remote.file.parents[0] ? { folderId: remote.file.parents[0] } : {} }
311376
+ }
311377
+ });
311378
+ const chunkBytes = session2.chunkSize;
311379
+ if (typeof session2.uploadToken !== "string" || session2.size !== local.size || typeof chunkBytes !== "number" || !Number.isSafeInteger(chunkBytes) || chunkBytes < 1 || chunkBytes > MICROSOFT_DRIVE_UPLOAD_CHUNK_BYTES || chunkBytes % (320 * 1024) !== 0) {
311380
+ throw new ApiError(502, "invalid_upload_session", "OpenWork Cloud returned an invalid upload session.");
311381
+ }
311382
+ const file2 = await uploadMicrosoftRelayFile(config2, dependencies, { token: session2.uploadToken, file: snapshot, size: local.size, chunkBytes });
311383
+ const revision = stringOrNull(file2.eTag);
311384
+ const savedName = typeof file2.name === "string" && file2.name ? file2.name : name;
311385
+ const savedDriveId = typeof file2.driveId === "string" && MICROSOFT_ID.test(file2.driveId) ? file2.driveId : driveId ?? "";
311386
+ const webViewLink = typeof file2.webUrl === "string" && file2.webUrl ? file2.webUrl : mode === "replace" ? link2.webViewLink : null;
311387
+ const driveMimeType = typeof file2.mimeType === "string" && file2.mimeType ? file2.mimeType : link2.driveMimeType;
311388
+ await withLinks(config2, (current2) => {
311389
+ current2.links[path3] = {
311390
+ ...link2,
311391
+ provider: "microsoft-365",
311392
+ fileId: file2.id,
311393
+ driveId: savedDriveId,
311394
+ name: savedName,
311395
+ driveMimeType,
311396
+ native: false,
311397
+ format: null,
311398
+ revision,
311399
+ md5Checksum: null,
311400
+ sha256: local.sha256,
311401
+ size: local.size,
311402
+ webViewLink,
311403
+ pushedAt: new Date().toISOString()
311404
+ };
311405
+ });
311406
+ const replaces = isRecord28(session2.replaces) ? session2.replaces : null;
311407
+ return {
311408
+ ok: true,
311409
+ mode,
311410
+ path: displayPath(config2, context4, path3),
311411
+ size: local.size,
311412
+ file: { id: file2.id, driveId: savedDriveId, name: savedName, mimeType: driveMimeType, webViewLink, revision },
311413
+ ...mode === "replace" ? { previousRevision: stringOrNull(replaces?.previousRevision) } : { copiedFrom: link2.fileId }
311414
+ };
311415
+ } finally {
311416
+ await snapshot.close();
311417
+ }
311418
+ }
311144
311419
  async function callDriveFileAction(config2, action, args2, context4, dependencies = {}) {
311145
311420
  if (action === "drive_pull_file")
311146
311421
  return pullDriveFile(config2, args2, context4, dependencies);
@@ -318752,12 +319027,14 @@ async function uiBridgeRequest(path3, options = {}) {
318752
319027
  // src/opencode-plugins/drive-file-tools.ts
318753
319028
  init_zod();
318754
319029
  var DRIVE_FILE_ACTIONS = ["drive_pull_file", "drive_file_status", "drive_push_file"];
318755
- var connectionId = exports_external.string().regex(/^(google-workspace|emc_[A-Za-z0-9]+)$/).optional().describe("Selected Google Workspace connection; omit for the default. Unavailable selections never fall back to another account.");
319030
+ var connectionId = exports_external.string().regex(/^(google-workspace|microsoft-365|emc_[A-Za-z0-9]+)$/).optional().describe("Selected Google Workspace or Microsoft 365 connection; omit for the default. Unavailable selections never fall back to another account.");
318756
319031
  var workspacePath = exports_external.string().min(1).max(4096);
318757
319032
  var drivePullFileArgs = exports_external.object({
318758
- fileId: exports_external.string().min(1).max(2048).describe("Drive file ID or link."),
319033
+ fileId: exports_external.string().min(1).max(2048).describe("Google Drive file ID or link, or a OneDrive, SharePoint or Teams file link or item id."),
319034
+ driveId: exports_external.string().min(1).max(512).optional().describe("Microsoft 365 only: the driveId that came with the item id from a search or folder listing."),
319035
+ provider: exports_external.enum(["google-workspace", "microsoft-365"]).optional().describe("Only needed for a Microsoft item id without driveId; links and driveId identify Microsoft 365 files."),
318759
319036
  path: workspacePath.optional().describe("Workspace path to save to. Defaults to drive/<file name>."),
318760
- format: exports_external.string().regex(/^[a-z]{2,5}$/).optional().describe("Docs, Sheets, Slides and Drawings only: xlsx, csv (first tab only), docx, md, txt, pptx, pdf, png or svg."),
319037
+ format: exports_external.string().regex(/^[a-z]{2,5}$/).optional().describe("Docs, Sheets, Slides and Drawings: xlsx, csv (first tab only), docx, md, txt, pptx, pdf, png or svg. OneDrive and SharePoint: pdf converts an Office file."),
318761
319038
  connectionId,
318762
319039
  overwrite: exports_external.boolean().optional().describe("Replace a local copy even if it has edits not in Drive. Asks the person first.")
318763
319040
  }).strict();
@@ -318766,7 +319043,7 @@ var driveFileStatusArgs = exports_external.object({
318766
319043
  }).strict();
318767
319044
  var drivePushFileArgs = exports_external.object({
318768
319045
  path: workspacePath.describe("Workspace path of a pulled file."),
318769
- mode: exports_external.enum(["replace", "copy"]).optional().describe("replace (default for stored files) updates the same Drive file; copy saves a new file next to it."),
319046
+ mode: exports_external.enum(["replace", "copy"]).optional().describe("replace (default for stored files) updates the same file; copy saves a new file next to it."),
318770
319047
  name: exports_external.string().min(1).max(255).optional().describe("Name for a copy.")
318771
319048
  }).strict();
318772
319049
  function isRecord41(value3) {
@@ -318781,7 +319058,7 @@ async function askPermission(context4, permission, patterns, metadata) {
318781
319058
  function createDriveFileTools(call) {
318782
319059
  return {
318783
319060
  drive_pull_file: {
318784
- description: "Save a Google Drive file into the workspace and return its path and revision, never its content. Use it to analyze or edit Office, PDF, CSV or any large file with shell tools. Docs, Sheets and Slides arrive as docx, xlsx and pptx unless format says otherwise.",
319061
+ description: "Save a Google Drive, OneDrive or SharePoint file into the workspace and return its path and revision, never its content. Use it to analyze or edit Office, PDF, CSV or any large file with shell tools. Docs, Sheets and Slides arrive as docx, xlsx and pptx unless format says otherwise.",
318785
319062
  args: drivePullFileArgs.shape,
318786
319063
  async execute(rawArgs, context4) {
318787
319064
  const args2 = drivePullFileArgs.parse(rawArgs ?? {});
@@ -318791,14 +319068,14 @@ function createDriveFileTools(call) {
318791
319068
  }
318792
319069
  },
318793
319070
  drive_file_status: {
318794
- description: "For files pulled with drive_pull_file, report whether the local copy has edits not saved to Drive and whether the file changed in Drive since the pull.",
319071
+ description: "For files pulled with drive_pull_file, report whether the local copy has edits not saved back and whether the file changed in Drive, OneDrive or SharePoint since the pull.",
318795
319072
  args: driveFileStatusArgs.shape,
318796
319073
  async execute(rawArgs, context4) {
318797
319074
  return JSON.stringify(await call("drive_file_status", driveFileStatusArgs.parse(rawArgs ?? {}), context4), null, 2);
318798
319075
  }
318799
319076
  },
318800
319077
  drive_push_file: {
318801
- description: "Save a pulled file back to Google Drive when the person asks. Asks the person first. Stored files are replaced in place as a new Drive version; Docs, Sheets and Slides are saved as a new Google file next to the original. Returns drive_conflict, and changes nothing, when someone changed the file in Drive since the pull: pull it again and reapply the edits, or save a copy.",
319078
+ description: "Save a pulled file back to where it came from when the person asks. Asks the person first. Stored files, including Office files in OneDrive and SharePoint, are replaced in place as a new version; Google Docs, Sheets and Slides and PDF conversions are saved as a new file next to the original. Returns drive_conflict, and changes nothing, when someone changed the file since the pull: pull it again and reapply the edits, or save a copy.",
318802
319079
  args: drivePushFileArgs.shape,
318803
319080
  async execute(rawArgs, context4) {
318804
319081
  const args2 = drivePushFileArgs.parse(rawArgs ?? {});
@@ -323877,7 +324154,7 @@ import { mkdir as mkdir19, rename as rename13, rm as rm18, writeFile as writeFil
323877
324154
  import { join as join36 } from "node:path";
323878
324155
  // ../../constants.json
323879
324156
  var constants_default = {
323880
- opencodeVersion: "v1.18.30",
324157
+ opencodeVersion: "v1.18.33",
323881
324158
  opencodeV2Version: "2.0.26"
323882
324159
  };
323883
324160
 
@@ -325254,7 +325531,7 @@ function createEngineV2Preview(options) {
325254
325531
  // package.json
325255
325532
  var package_default = {
325256
325533
  name: "openwork-server",
325257
- version: "0.18.61",
325534
+ version: "0.18.62",
325258
325535
  description: "Filesystem-backed API for OpenWork remote clients",
325259
325536
  type: "module",
325260
325537
  bin: {
@@ -332809,7 +333086,7 @@ function readInstalledOpencodeVersion() {
332809
333086
  // package.json
332810
333087
  var package_default2 = {
332811
333088
  name: "openwork-server",
332812
- version: "0.18.61",
333089
+ version: "0.18.62",
332813
333090
  description: "Filesystem-backed API for OpenWork remote clients",
332814
333091
  type: "module",
332815
333092
  bin: {
@@ -332900,7 +333177,7 @@ var package_default2 = {
332900
333177
  };
332901
333178
  // ../../constants.json
332902
333179
  var constants_default2 = {
332903
- opencodeVersion: "v1.18.30",
333180
+ opencodeVersion: "v1.18.33",
332904
333181
  opencodeV2Version: "2.0.26"
332905
333182
  };
332906
333183
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "openwork-server",
3
- "version": "0.18.61",
3
+ "version": "0.18.62",
4
4
  "description": "Filesystem-backed API for OpenWork remote clients",
5
5
  "type": "module",
6
6
  "bin": {
@@ -1 +1 @@
1
- import{g as p,r as u,d as a}from"./chunk-SVP7TREG-CBKOSsQl.js";import{p as f}from"./chunk-JWPE2WC7-LslAnaQK.js";import{_ as n,l as o}from"./mermaid.core-DcgS6fFC.js";import{M as c,b as d}from"./cynefin-OW5HDTMX-BGWD-i0N.js";import"./app-Cy3sY2K8.js";var v=d().RailroadAbnf.parser.LangiumParser,i=n(e=>{const r=e.alternatives.map(g);return r.length===1?r[0]:{type:"choice",alternatives:r}},"transformAlternation"),g=n(e=>{const r=e.elements.map(y);return r.length===1?r[0]:{type:"sequence",elements:r}},"transformConcatenation"),b=n(e=>{if(e.includes("*")){const[t,s]=e.split("*"),l=t?parseInt(t,10):0,m=s?parseInt(s,10):1/0;return{min:l,max:m}}const r=parseInt(e,10);return{min:r,max:r}},"parseRepeat"),y=n(e=>{const r=A(e.primary);if(!e.repeat)return r;const{min:t,max:s}=b(e.repeat);return t===0&&s===1?{type:"optional",element:r}:{type:"repetition",element:r,min:t,max:s}},"transformElement"),A=n(e=>{switch(e.$type){case"AbnfStringLiteral":return{type:"terminal",value:e.value};case"AbnfNumVal":return{type:"terminal",value:e.value};case"AbnfRuleName":return{type:"nonterminal",name:e.name};case"AbnfGroup":return i(e.element);case"AbnfOptionalGroup":return{type:"optional",element:i(e.element)};default:throw new Error(`Unsupported ABNF primary node: ${e.$type}`)}},"transformPrimary"),P=n(e=>({name:e.name,definition:i(e.definition)}),"transformRule"),h=n(e=>{f(e,a),e.title&&a.setTitle(e.title),e.rules.map(r=>a.addRule(P(r)))},"populateDb"),R={parse:n(e=>{a.clear(),o.debug("[ABNF Parser] Starting Langium parse");const r=v.parse(e);if(r.lexerErrors.length>0||r.parserErrors.length>0)throw new c(r);const t=r.value;o.debug("[ABNF Parser] Parsed rules:",t.rules.length),h(t),o.debug("[ABNF Parser] Parse complete")},"parse"),parser:{yy:a}},B={parser:R,db:a,renderer:u,styles:p};export{B as diagram};
1
+ import{g as p,r as u,d as a}from"./chunk-SVP7TREG-B65ta9aQ.js";import{p as f}from"./chunk-JWPE2WC7-B34hvYk7.js";import{_ as n,l as o}from"./mermaid.core-FKm3Akes.js";import{M as c,b as d}from"./cynefin-OW5HDTMX-CAcz2tHt.js";import"./app-_2KkkZIM.js";var v=d().RailroadAbnf.parser.LangiumParser,i=n(e=>{const r=e.alternatives.map(g);return r.length===1?r[0]:{type:"choice",alternatives:r}},"transformAlternation"),g=n(e=>{const r=e.elements.map(y);return r.length===1?r[0]:{type:"sequence",elements:r}},"transformConcatenation"),b=n(e=>{if(e.includes("*")){const[t,s]=e.split("*"),l=t?parseInt(t,10):0,m=s?parseInt(s,10):1/0;return{min:l,max:m}}const r=parseInt(e,10);return{min:r,max:r}},"parseRepeat"),y=n(e=>{const r=A(e.primary);if(!e.repeat)return r;const{min:t,max:s}=b(e.repeat);return t===0&&s===1?{type:"optional",element:r}:{type:"repetition",element:r,min:t,max:s}},"transformElement"),A=n(e=>{switch(e.$type){case"AbnfStringLiteral":return{type:"terminal",value:e.value};case"AbnfNumVal":return{type:"terminal",value:e.value};case"AbnfRuleName":return{type:"nonterminal",name:e.name};case"AbnfGroup":return i(e.element);case"AbnfOptionalGroup":return{type:"optional",element:i(e.element)};default:throw new Error(`Unsupported ABNF primary node: ${e.$type}`)}},"transformPrimary"),P=n(e=>({name:e.name,definition:i(e.definition)}),"transformRule"),h=n(e=>{f(e,a),e.title&&a.setTitle(e.title),e.rules.map(r=>a.addRule(P(r)))},"populateDb"),R={parse:n(e=>{a.clear(),o.debug("[ABNF Parser] Starting Langium parse");const r=v.parse(e);if(r.lexerErrors.length>0||r.parserErrors.length>0)throw new c(r);const t=r.value;o.debug("[ABNF Parser] Parsed rules:",t.rules.length),h(t),o.debug("[ABNF Parser] Parse complete")},"parse"),parser:{yy:a}},B={parser:R,db:a,renderer:u,styles:p};export{B as diagram};