@tiwater/office-mcp 0.21.5 → 0.21.6

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.
@@ -1,6 +1,6 @@
1
1
  import { createHash } from 'node:crypto';
2
2
  import { createReadStream } from 'node:fs';
3
- import { mkdir, stat, writeFile } from 'node:fs/promises';
3
+ import { mkdir, readFile, stat, writeFile } from 'node:fs/promises';
4
4
  import path from 'node:path';
5
5
 
6
6
  import { requireString } from './tool-runtime.mjs';
@@ -31,7 +31,7 @@ export async function deliverLargeJsonResult({ tool, args, runtime, payload, sou
31
31
  runtime,
32
32
  sources: await Promise.all(sourcePaths.map(fileArtifact)),
33
33
  returnContent: channels.returnContent,
34
- artifact: channels.output === null ? null : await writeJsonArtifact(channels.output, payload),
34
+ artifact: channels.output === null ? null : await writeIdempotentJsonArtifact(channels.output, payload),
35
35
  receipt: {
36
36
  contentBytes,
37
37
  contentReturned,
@@ -47,6 +47,28 @@ export async function writeJsonArtifact(output, payload) {
47
47
  const bytes = Buffer.from(`${JSON.stringify(payload, null, 2)}\n`, 'utf8');
48
48
  await mkdir(path.dirname(fullPath), { recursive: true });
49
49
  await writeFile(fullPath, bytes, { flag: 'wx' });
50
+ return describeJsonArtifact(fullPath, bytes);
51
+ }
52
+
53
+ export async function writeIdempotentJsonArtifact(output, payload) {
54
+ const fullPath = path.resolve(output);
55
+ const bytes = Buffer.from(`${JSON.stringify(payload, null, 2)}\n`, 'utf8');
56
+ await mkdir(path.dirname(fullPath), { recursive: true });
57
+ try {
58
+ await writeFile(fullPath, bytes, { flag: 'wx' });
59
+ } catch (error) {
60
+ if (error?.code !== 'EEXIST') throw error;
61
+ const existing = await readFile(fullPath);
62
+ if (!existing.equals(bytes)) {
63
+ throw Object.assign(new Error(`artifact-path-already-exists-with-different-content:${fullPath}`), {
64
+ code: 'EEXIST',
65
+ });
66
+ }
67
+ }
68
+ return describeJsonArtifact(fullPath, bytes);
69
+ }
70
+
71
+ function describeJsonArtifact(fullPath, bytes) {
50
72
  return {
51
73
  path: fullPath,
52
74
  sha256: createHash('sha256').update(bytes).digest('hex'),
@@ -2,7 +2,7 @@
2
2
  "schema": "tiwater.office-provider-contract-manifest/v1",
3
3
  "provider": {
4
4
  "id": "@tiwater/office-mcp",
5
- "version": "0.21.5"
5
+ "version": "0.21.6"
6
6
  },
7
7
  "tools": [
8
8
  {
package/office/index.mjs CHANGED
@@ -19,6 +19,7 @@ import {
19
19
  fileArtifact,
20
20
  resultChannels,
21
21
  returnedContentBudgetBytes,
22
+ writeIdempotentJsonArtifact,
22
23
  writeJsonArtifact,
23
24
  } from '../_shared/large-json-result.mjs';
24
25
  import { withOutputWriteLock } from '../_shared/output-write-lock.mjs';
@@ -746,7 +747,7 @@ async function docxInspect(args) {
746
747
  returnContent: delivery.returnContent,
747
748
  artifact: delivery.output === null
748
749
  ? null
749
- : await writeJsonArtifact(delivery.output, result.json),
750
+ : await writeIdempotentJsonArtifact(delivery.output, result.json),
750
751
  ...(delivery.returnContent ? compactDocxInspection(result.json) : {}),
751
752
  };
752
753
  }
@@ -770,7 +771,7 @@ async function docxObservation(tool, args) {
770
771
  const offset = Math.min(args.offset ?? 0, totalCount);
771
772
  const withArtifact = delivery.output === null ? retained : {
772
773
  ...retained,
773
- artifact: await writeJsonArtifact(delivery.output, result.json),
774
+ artifact: await writeIdempotentJsonArtifact(delivery.output, result.json),
774
775
  };
775
776
  if (!delivery.returnContent) {
776
777
  return {
@@ -805,7 +806,7 @@ async function docxObservation(tool, args) {
805
806
  const totalCount = payload.tables.length;
806
807
  const withArtifact = delivery.output === null ? retained : {
807
808
  ...retained,
808
- artifact: await writeJsonArtifact(delivery.output, result.json),
809
+ artifact: await writeIdempotentJsonArtifact(delivery.output, result.json),
809
810
  };
810
811
  if (!delivery.returnContent) {
811
812
  return {
@@ -872,7 +873,7 @@ async function docxObservation(tool, args) {
872
873
  };
873
874
  const withArtifact = delivery.output === null ? retained : {
874
875
  ...retained,
875
- artifact: await writeJsonArtifact(delivery.output, detailPage),
876
+ artifact: await writeIdempotentJsonArtifact(delivery.output, detailPage),
876
877
  };
877
878
  if (!delivery.returnContent) {
878
879
  return {
@@ -964,7 +965,7 @@ async function docxReadObject(args) {
964
965
  returnContent: delivery.returnContent,
965
966
  artifact: delivery.output === null
966
967
  ? null
967
- : await writeJsonArtifact(delivery.output, result.json),
968
+ : await writeIdempotentJsonArtifact(delivery.output, result.json),
968
969
  receipt: {
969
970
  schema: 'tiwater.docx-read-object-receipt/v1',
970
971
  observationCount: observations.length,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tiwater/office-mcp",
3
- "version": "0.21.5",
3
+ "version": "0.21.6",
4
4
  "description": "Published MCP server for Tiwater Office document capabilities",
5
5
  "type": "module",
6
6
  "license": "MIT",