@rubytech/create-maxy-code 0.1.458 → 0.1.459

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 (116) hide show
  1. package/package.json +1 -1
  2. package/payload/platform/lib/storage-broker/dist/__tests__/cf-exec.test.js +188 -3
  3. package/payload/platform/lib/storage-broker/dist/__tests__/cf-exec.test.js.map +1 -1
  4. package/payload/platform/lib/storage-broker/dist/__tests__/object-limits.test.d.ts +2 -0
  5. package/payload/platform/lib/storage-broker/dist/__tests__/object-limits.test.d.ts.map +1 -0
  6. package/payload/platform/lib/storage-broker/dist/__tests__/object-limits.test.js +59 -0
  7. package/payload/platform/lib/storage-broker/dist/__tests__/object-limits.test.js.map +1 -0
  8. package/payload/platform/lib/storage-broker/dist/cf-exec.d.ts +12 -1
  9. package/payload/platform/lib/storage-broker/dist/cf-exec.d.ts.map +1 -1
  10. package/payload/platform/lib/storage-broker/dist/cf-exec.js +97 -0
  11. package/payload/platform/lib/storage-broker/dist/cf-exec.js.map +1 -1
  12. package/payload/platform/lib/storage-broker/dist/house-credential.d.ts.map +1 -1
  13. package/payload/platform/lib/storage-broker/dist/house-credential.js +4 -2
  14. package/payload/platform/lib/storage-broker/dist/house-credential.js.map +1 -1
  15. package/payload/platform/lib/storage-broker/dist/index.d.ts +1 -0
  16. package/payload/platform/lib/storage-broker/dist/index.d.ts.map +1 -1
  17. package/payload/platform/lib/storage-broker/dist/index.js +1 -0
  18. package/payload/platform/lib/storage-broker/dist/index.js.map +1 -1
  19. package/payload/platform/lib/storage-broker/dist/object-limits.d.ts +53 -0
  20. package/payload/platform/lib/storage-broker/dist/object-limits.d.ts.map +1 -0
  21. package/payload/platform/lib/storage-broker/dist/object-limits.js +72 -0
  22. package/payload/platform/lib/storage-broker/dist/object-limits.js.map +1 -0
  23. package/payload/platform/lib/storage-broker/src/__tests__/cf-exec.test.ts +211 -5
  24. package/payload/platform/lib/storage-broker/src/__tests__/object-limits.test.ts +76 -0
  25. package/payload/platform/lib/storage-broker/src/cf-exec.ts +148 -6
  26. package/payload/platform/lib/storage-broker/src/house-credential.ts +4 -2
  27. package/payload/platform/lib/storage-broker/src/index.ts +1 -0
  28. package/payload/platform/lib/storage-broker/src/object-limits.ts +75 -0
  29. package/payload/platform/plugins/admin/skills/platform-architecture/SKILL.md +5 -5
  30. package/payload/platform/plugins/cloudflare/bin/cf-token.sh +4 -3
  31. package/payload/platform/plugins/cloudflare/references/api.md +1 -1
  32. package/payload/platform/plugins/docs/references/outlook-guide.md +4 -4
  33. package/payload/platform/plugins/outlook/.claude-plugin/plugin.json +1 -1
  34. package/payload/platform/plugins/outlook/PLUGIN.md +2 -2
  35. package/payload/platform/plugins/outlook/mcp/dist/__tests__/attach.test.d.ts +2 -0
  36. package/payload/platform/plugins/outlook/mcp/dist/__tests__/attach.test.d.ts.map +1 -0
  37. package/payload/platform/plugins/outlook/mcp/dist/__tests__/attach.test.js +138 -0
  38. package/payload/platform/plugins/outlook/mcp/dist/__tests__/attach.test.js.map +1 -0
  39. package/payload/platform/plugins/outlook/mcp/dist/__tests__/draft-attachments.test.d.ts +2 -0
  40. package/payload/platform/plugins/outlook/mcp/dist/__tests__/draft-attachments.test.d.ts.map +1 -0
  41. package/payload/platform/plugins/outlook/mcp/dist/__tests__/draft-attachments.test.js +121 -0
  42. package/payload/platform/plugins/outlook/mcp/dist/__tests__/draft-attachments.test.js.map +1 -0
  43. package/payload/platform/plugins/outlook/mcp/dist/__tests__/draft-edit-attachments.test.d.ts +2 -0
  44. package/payload/platform/plugins/outlook/mcp/dist/__tests__/draft-edit-attachments.test.d.ts.map +1 -0
  45. package/payload/platform/plugins/outlook/mcp/dist/__tests__/draft-edit-attachments.test.js +102 -0
  46. package/payload/platform/plugins/outlook/mcp/dist/__tests__/draft-edit-attachments.test.js.map +1 -0
  47. package/payload/platform/plugins/outlook/mcp/dist/__tests__/draft-edit.test.js +1 -1
  48. package/payload/platform/plugins/outlook/mcp/dist/__tests__/draft-edit.test.js.map +1 -1
  49. package/payload/platform/plugins/outlook/mcp/dist/__tests__/mail-send-attachments.test.d.ts +2 -0
  50. package/payload/platform/plugins/outlook/mcp/dist/__tests__/mail-send-attachments.test.d.ts.map +1 -0
  51. package/payload/platform/plugins/outlook/mcp/dist/__tests__/mail-send-attachments.test.js +209 -0
  52. package/payload/platform/plugins/outlook/mcp/dist/__tests__/mail-send-attachments.test.js.map +1 -0
  53. package/payload/platform/plugins/outlook/mcp/dist/index.js +10 -7
  54. package/payload/platform/plugins/outlook/mcp/dist/index.js.map +1 -1
  55. package/payload/platform/plugins/outlook/mcp/dist/lib/attach.d.ts +37 -0
  56. package/payload/platform/plugins/outlook/mcp/dist/lib/attach.d.ts.map +1 -0
  57. package/payload/platform/plugins/outlook/mcp/dist/lib/attach.js +79 -0
  58. package/payload/platform/plugins/outlook/mcp/dist/lib/attach.js.map +1 -0
  59. package/payload/platform/plugins/outlook/mcp/dist/lib/message.d.ts +8 -0
  60. package/payload/platform/plugins/outlook/mcp/dist/lib/message.d.ts.map +1 -1
  61. package/payload/platform/plugins/outlook/mcp/dist/lib/message.js +4 -0
  62. package/payload/platform/plugins/outlook/mcp/dist/lib/message.js.map +1 -1
  63. package/payload/platform/plugins/outlook/mcp/dist/lib/outbound-attachments.d.ts +31 -8
  64. package/payload/platform/plugins/outlook/mcp/dist/lib/outbound-attachments.d.ts.map +1 -1
  65. package/payload/platform/plugins/outlook/mcp/dist/lib/outbound-attachments.js +40 -13
  66. package/payload/platform/plugins/outlook/mcp/dist/lib/outbound-attachments.js.map +1 -1
  67. package/payload/platform/plugins/outlook/mcp/dist/lib/upload-session.d.ts +9 -5
  68. package/payload/platform/plugins/outlook/mcp/dist/lib/upload-session.d.ts.map +1 -1
  69. package/payload/platform/plugins/outlook/mcp/dist/lib/upload-session.js +12 -8
  70. package/payload/platform/plugins/outlook/mcp/dist/lib/upload-session.js.map +1 -1
  71. package/payload/platform/plugins/outlook/mcp/dist/tools/draft-edit.d.ts +29 -4
  72. package/payload/platform/plugins/outlook/mcp/dist/tools/draft-edit.d.ts.map +1 -1
  73. package/payload/platform/plugins/outlook/mcp/dist/tools/draft-edit.js +46 -13
  74. package/payload/platform/plugins/outlook/mcp/dist/tools/draft-edit.js.map +1 -1
  75. package/payload/platform/plugins/outlook/mcp/dist/tools/draft.d.ts +8 -2
  76. package/payload/platform/plugins/outlook/mcp/dist/tools/draft.d.ts.map +1 -1
  77. package/payload/platform/plugins/outlook/mcp/dist/tools/draft.js +13 -4
  78. package/payload/platform/plugins/outlook/mcp/dist/tools/draft.js.map +1 -1
  79. package/payload/platform/plugins/outlook/mcp/dist/tools/mail-reply.d.ts.map +1 -1
  80. package/payload/platform/plugins/outlook/mcp/dist/tools/mail-reply.js +3 -20
  81. package/payload/platform/plugins/outlook/mcp/dist/tools/mail-reply.js.map +1 -1
  82. package/payload/platform/plugins/outlook/mcp/dist/tools/mail-send.d.ts +27 -3
  83. package/payload/platform/plugins/outlook/mcp/dist/tools/mail-send.d.ts.map +1 -1
  84. package/payload/platform/plugins/outlook/mcp/dist/tools/mail-send.js +53 -8
  85. package/payload/platform/plugins/outlook/mcp/dist/tools/mail-send.js.map +1 -1
  86. package/payload/platform/plugins/outlook/references/graph-surfaces.md +29 -6
  87. package/payload/platform/plugins/outlook/skills/outlook/SKILL.md +22 -5
  88. package/payload/platform/plugins/storage-broker/PLUGIN.md +41 -2
  89. package/payload/platform/plugins/storage-broker/mcp/dist/__tests__/confine-path.test.d.ts +2 -0
  90. package/payload/platform/plugins/storage-broker/mcp/dist/__tests__/confine-path.test.d.ts.map +1 -0
  91. package/payload/platform/plugins/storage-broker/mcp/dist/__tests__/confine-path.test.js +85 -0
  92. package/payload/platform/plugins/storage-broker/mcp/dist/__tests__/confine-path.test.js.map +1 -0
  93. package/payload/platform/plugins/storage-broker/mcp/dist/__tests__/put-source.test.d.ts +2 -0
  94. package/payload/platform/plugins/storage-broker/mcp/dist/__tests__/put-source.test.d.ts.map +1 -0
  95. package/payload/platform/plugins/storage-broker/mcp/dist/__tests__/put-source.test.js +77 -0
  96. package/payload/platform/plugins/storage-broker/mcp/dist/__tests__/put-source.test.js.map +1 -0
  97. package/payload/platform/plugins/storage-broker/mcp/dist/confine-path.d.ts +12 -0
  98. package/payload/platform/plugins/storage-broker/mcp/dist/confine-path.d.ts.map +1 -0
  99. package/payload/platform/plugins/storage-broker/mcp/dist/confine-path.js +107 -0
  100. package/payload/platform/plugins/storage-broker/mcp/dist/confine-path.js.map +1 -0
  101. package/payload/platform/plugins/storage-broker/mcp/dist/index.js +86 -0
  102. package/payload/platform/plugins/storage-broker/mcp/dist/index.js.map +1 -1
  103. package/payload/platform/plugins/storage-broker/mcp/dist/put-source.d.ts +11 -0
  104. package/payload/platform/plugins/storage-broker/mcp/dist/put-source.d.ts.map +1 -0
  105. package/payload/platform/plugins/storage-broker/mcp/dist/put-source.js +35 -0
  106. package/payload/platform/plugins/storage-broker/mcp/dist/put-source.js.map +1 -0
  107. package/payload/platform/scripts/logs-read-jsonl.test.sh +118 -0
  108. package/payload/platform/scripts/logs-read.sh +63 -9
  109. package/payload/platform/services/claude-session-manager/dist/canonical-tool-names.generated.d.ts.map +1 -1
  110. package/payload/platform/services/claude-session-manager/dist/canonical-tool-names.generated.js +4 -0
  111. package/payload/platform/services/claude-session-manager/dist/canonical-tool-names.generated.js.map +1 -1
  112. package/payload/server/{chunk-F4D35LKL.js → chunk-POBXIHOF.js} +34 -0
  113. package/payload/server/{chunk-64FGYKNZ.js → chunk-Q6W4U6HL.js} +104 -0
  114. package/payload/server/maxy-edge.js +1 -1
  115. package/payload/server/server.js +206 -6
  116. package/payload/server/{src-S7C4P6TT.js → src-3I2RYZFB.js} +9 -1
@@ -0,0 +1,77 @@
1
+ import { describe, it, expect, vi, beforeEach, afterEach } from "vitest";
2
+ import { mkdtempSync, realpathSync, rmSync, writeFileSync, truncateSync } from "node:fs";
3
+ import { tmpdir } from "node:os";
4
+ import { join } from "node:path";
5
+ import { R2_OBJECT_MAX_BYTES } from "../../../../../lib/storage-broker/dist/object-limits.js";
6
+ // Task 1695 — the property under test is an ordering: the cap must fire BEFORE
7
+ // the file is read. Spying on readFileSync is what makes that observable. An
8
+ // assertion that only checked the error message would pass just as happily on an
9
+ // implementation that slurps a 3 GB file into memory and then measures its
10
+ // length, which is the bug this exists to prevent.
11
+ //
12
+ // node:fs is mocked partially so confine-path's realpathSync/statSync stay real
13
+ // and the confinement predicate is still exercised for what it is.
14
+ const readFileSpy = vi.fn();
15
+ vi.mock("node:fs", async (importOriginal) => {
16
+ const actual = await importOriginal();
17
+ return {
18
+ ...actual,
19
+ readFileSync: (...args) => readFileSpy(...args),
20
+ };
21
+ });
22
+ const { readPutSource } = await import("../put-source.js");
23
+ let dir;
24
+ beforeEach(() => {
25
+ // realpath'd at creation: on macOS mkdtemp hands back /var/folders/… which
26
+ // canonicalises to /private/var/folders/…, and confineToAccountDir realpaths
27
+ // both sides. Without this the paths under test differ from the paths asserted
28
+ // for a reason that has nothing to do with the cap.
29
+ dir = realpathSync(mkdtempSync(join(tmpdir(), "put-source-")));
30
+ process.env.ACCOUNT_DIR = dir;
31
+ readFileSpy.mockReset();
32
+ readFileSpy.mockReturnValue(Buffer.from([1, 2, 3]));
33
+ });
34
+ afterEach(() => {
35
+ rmSync(dir, { recursive: true, force: true });
36
+ delete process.env.ACCOUNT_DIR;
37
+ });
38
+ /** A sparse file of `size` bytes: statSync reports the size, no disk is used and
39
+ * nothing is ever written. A real 100 MiB fixture would make this suite the
40
+ * thing that thrashes the machine. */
41
+ function sparseFile(name, size) {
42
+ const p = join(dir, name);
43
+ writeFileSync(p, "");
44
+ truncateSync(p, size);
45
+ return p;
46
+ }
47
+ describe("readPutSource", () => {
48
+ it("rejects an over-cap file before reading it", () => {
49
+ const p = sparseFile("huge.bin", R2_OBJECT_MAX_BYTES + 1);
50
+ expect(() => readPutSource(p)).toThrow(/huge\.bin/);
51
+ // The assertion that matters. Without it this test would pass on an
52
+ // implementation that reads the whole file and then checks its length.
53
+ expect(readFileSpy).not.toHaveBeenCalled();
54
+ });
55
+ it("names the file and the limit when it rejects", () => {
56
+ const p = sparseFile("huge.bin", 150 * 1024 * 1024);
57
+ expect(() => readPutSource(p)).toThrow(/huge\.bin is 150\.0 MiB.*100\.0 MiB/);
58
+ });
59
+ it("reads a file at exactly the cap — the cap is a bound, not a wall", () => {
60
+ const p = sparseFile("atcap.bin", R2_OBJECT_MAX_BYTES);
61
+ const out = readPutSource(p);
62
+ expect(readFileSpy).toHaveBeenCalledWith(p);
63
+ expect(out.path).toBe(p);
64
+ });
65
+ it("reads an ordinary file", () => {
66
+ const p = join(dir, "small.bin");
67
+ writeFileSync(p, Buffer.from([1, 2, 3]));
68
+ const out = readPutSource(p);
69
+ expect(out.bytes).toEqual(Buffer.from([1, 2, 3]));
70
+ expect(readFileSpy).toHaveBeenCalledWith(p);
71
+ });
72
+ it("still rejects a path outside the account directory, before any size check", () => {
73
+ expect(() => readPutSource("/etc/hosts")).toThrow(/outside the account directory/);
74
+ expect(readFileSpy).not.toHaveBeenCalled();
75
+ });
76
+ });
77
+ //# sourceMappingURL=put-source.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"put-source.test.js","sourceRoot":"","sources":["../../src/__tests__/put-source.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Resolve `p` and require it inside the caller's account directory.
3
+ *
4
+ * `mustExist` true (a source to read): the path itself is realpathed and must
5
+ * be a regular file. False (a destination to write): the path does not exist
6
+ * yet and cannot be realpathed, so its *parent* is — which is exactly what a
7
+ * symlinked parent directory would otherwise subvert.
8
+ *
9
+ * Returns the resolved absolute path. Throws naming the offending path.
10
+ */
11
+ export declare function confineToAccountDir(p: string, mustExist: boolean): string;
12
+ //# sourceMappingURL=confine-path.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"confine-path.d.ts","sourceRoot":"","sources":["../src/confine-path.ts"],"names":[],"mappings":"AAyCA;;;;;;;;;GASG;AACH,wBAAgB,mBAAmB,CAAC,CAAC,EAAE,MAAM,EAAE,SAAS,EAAE,OAAO,GAAG,MAAM,CA4DzE"}
@@ -0,0 +1,107 @@
1
+ /**
2
+ * Confine an agent-supplied file path to the caller's own account directory.
3
+ *
4
+ * Mirrors the predicate proven in the email plugin's resolveOutboundAttachments
5
+ * (platform/plugins/email/mcp/src/lib/attachment-resolve.ts): realpath the
6
+ * candidate and require the result under the realpathed account directory, so a
7
+ * symlink cannot escape a plain string prefix check. Copied rather than
8
+ * imported because platform/lib/* is the only cross-plugin-importable surface
9
+ * and this predicate does not live there; consolidating the duplicates is its
10
+ * own concern, not this tool's.
11
+ *
12
+ * This is a correctness guardrail, not a security boundary, and the difference
13
+ * matters. Every account shares one unix user and the agent holds Bash, so it
14
+ * can already read anything this process can (Task 1690). What actually
15
+ * contains the blast radius is that the house-level broker route touches no
16
+ * filesystem at all: file I/O stays here, in a process running at the agent's
17
+ * own privilege, so it grants nothing the agent did not already have. Moving
18
+ * this check server-side would not harden it — it would create the very
19
+ * house-privileged arbitrary read/write it appears to prevent.
20
+ */
21
+ import { realpathSync, statSync } from "node:fs";
22
+ import { basename, dirname, join, resolve } from "node:path";
23
+ /** The caller's account directory. ACCOUNT_DIR is the canonical spawn-set var;
24
+ * fall back to PLATFORM_ROOT + ACCOUNT_ID exactly as the email and url-get
25
+ * tools do. Throws rather than returning a default: with no account context
26
+ * there is nothing to validate against, and failing closed is the only safe
27
+ * answer. */
28
+ function accountDir() {
29
+ const direct = process.env.ACCOUNT_DIR;
30
+ if (direct && direct.trim())
31
+ return direct;
32
+ const platformRoot = process.env.PLATFORM_ROOT;
33
+ const accountId = process.env.ACCOUNT_ID;
34
+ if (platformRoot && accountId && !accountId.includes("/") && !accountId.includes("..")) {
35
+ return join(platformRoot, "..", "data", "accounts", accountId);
36
+ }
37
+ throw new Error("No account context (ACCOUNT_DIR unset and PLATFORM_ROOT+ACCOUNT_ID unavailable) to validate paths against.");
38
+ }
39
+ /**
40
+ * Resolve `p` and require it inside the caller's account directory.
41
+ *
42
+ * `mustExist` true (a source to read): the path itself is realpathed and must
43
+ * be a regular file. False (a destination to write): the path does not exist
44
+ * yet and cannot be realpathed, so its *parent* is — which is exactly what a
45
+ * symlinked parent directory would otherwise subvert.
46
+ *
47
+ * Returns the resolved absolute path. Throws naming the offending path.
48
+ */
49
+ export function confineToAccountDir(p, mustExist) {
50
+ let base;
51
+ try {
52
+ base = realpathSync(accountDir());
53
+ }
54
+ catch (err) {
55
+ throw new Error(`Account directory is not accessible: ${err instanceof Error ? err.message : String(err)}`);
56
+ }
57
+ let resolved;
58
+ if (mustExist) {
59
+ try {
60
+ resolved = realpathSync(p);
61
+ }
62
+ catch (err) {
63
+ if (err.code === "ENOENT") {
64
+ throw new Error(`File not found: ${p}`);
65
+ }
66
+ throw new Error(`Cannot read ${p}: ${err instanceof Error ? err.message : String(err)}`);
67
+ }
68
+ if (!statSync(resolved).isFile()) {
69
+ throw new Error(`${p} is not a regular file.`);
70
+ }
71
+ }
72
+ else {
73
+ const absolute = resolve(p);
74
+ // A destination that already exists must be realpathed like any source: if
75
+ // the final component is a symlink pointing out of the account directory, a
76
+ // write to it follows the link out, and resolving only the parent would let
77
+ // that through. The source branch rejects exactly this escape, so the two
78
+ // branches would otherwise disagree about what "confined" means.
79
+ try {
80
+ resolved = realpathSync(absolute);
81
+ }
82
+ catch (err) {
83
+ if (err.code !== "ENOENT") {
84
+ throw new Error(`Cannot resolve destination ${p}: ${err instanceof Error ? err.message : String(err)}`);
85
+ }
86
+ // It does not exist yet, so it cannot be realpathed. Resolve its parent —
87
+ // which is what a symlinked parent directory would otherwise subvert —
88
+ // and re-attach the final name.
89
+ let parent;
90
+ try {
91
+ parent = realpathSync(dirname(absolute));
92
+ }
93
+ catch (perr) {
94
+ if (perr.code === "ENOENT") {
95
+ throw new Error(`Destination directory does not exist: ${dirname(absolute)}`);
96
+ }
97
+ throw new Error(`Cannot resolve destination ${p}: ${perr instanceof Error ? perr.message : String(perr)}`);
98
+ }
99
+ resolved = join(parent, basename(absolute));
100
+ }
101
+ }
102
+ if (resolved !== base && !resolved.startsWith(base + "/")) {
103
+ throw new Error(`${p} is outside the account directory and cannot be used.`);
104
+ }
105
+ return resolved;
106
+ }
107
+ //# sourceMappingURL=confine-path.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"confine-path.js","sourceRoot":"","sources":["../src/confine-path.ts"],"names":[],"mappings":"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"}
@@ -6,10 +6,14 @@
6
6
  */
7
7
  import { initStderrTee } from "../../../../lib/mcp-stderr-tee/dist/index.js";
8
8
  initStderrTee("storage-broker");
9
+ import { writeFileSync } from "node:fs";
9
10
  import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
10
11
  import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
11
12
  import { z } from "zod";
12
13
  import { callApi as rawCallApi } from "./call-api.js";
14
+ import { confineToAccountDir } from "./confine-path.js";
15
+ import { readPutSource } from "./put-source.js";
16
+ import { R2_OBJECT_MAX_BYTES } from "../../../../lib/storage-broker/dist/object-limits.js";
13
17
  import { callerScopeHeaders } from "./caller-scope-headers.js";
14
18
  import { requirePortEnv } from "../../../../lib/require-port-env/dist/index.js";
15
19
  import { lifelineTool } from "../../../../lib/mcp-lifeline/dist/index.js";
@@ -87,6 +91,88 @@ lifelineTool(server, "storage-r2-bucket-create", "Create a Cloudflare R2 bucket
87
91
  return textResult(`R2 create failed: ${err}`, true);
88
92
  return textResult(`Created R2 bucket ${name}.`);
89
93
  });
94
+ // ─── R2 objects (Task 1691) ───────────────────────────────────────────────
95
+ //
96
+ // get/put move bytes through a file rather than the tool result: these objects
97
+ // are photos and scans, and base64 in a tool result would push megabytes into
98
+ // the agent's context window. The file I/O lives here, in this account-scoped
99
+ // process, and never in the house-level route that holds the credential — see
100
+ // confine-path.ts for why that split is the part that matters.
101
+ // ─── storage-r2-object-list ───────────────────────────────────────────────
102
+ lifelineTool(server, "storage-r2-object-list", "List the objects in an R2 bucket your account owns.", {
103
+ bucket: z.string().describe("Bucket name"),
104
+ prefix: z.string().optional().describe("Only list keys starting with this prefix"),
105
+ }, async ({ bucket, prefix }) => {
106
+ const result = await callApi("storage-r2-object-list", "/api/storage/r2/object/list", "POST", { bucket, prefix });
107
+ const err = errorOf(result);
108
+ if (err)
109
+ return textResult(`R2 object list failed: ${err}`, true);
110
+ const objects = result.objects ?? [];
111
+ return textResult(objects.length ? objects.map((o) => `${o.key}\t${o.size}`).join("\n") : "No objects.");
112
+ });
113
+ // ─── storage-r2-object-get ────────────────────────────────────────────────
114
+ lifelineTool(server, "storage-r2-object-get", `Download an object from an R2 bucket your account owns to a file in your account directory. Objects larger than ${R2_OBJECT_MAX_BYTES / 1024 / 1024} MiB are rejected.`, {
115
+ bucket: z.string().describe("Bucket name"),
116
+ key: z.string().describe("Object key"),
117
+ destPath: z.string().describe("Destination file path, inside your account directory"),
118
+ }, async ({ bucket, key, destPath }) => {
119
+ // Confine before the fetch: a rejected destination should cost no download.
120
+ let dest;
121
+ try {
122
+ dest = confineToAccountDir(destPath, false);
123
+ }
124
+ catch (e) {
125
+ return textResult(`R2 object get failed: ${e instanceof Error ? e.message : String(e)}`, true);
126
+ }
127
+ const result = await callApi("storage-r2-object-get", "/api/storage/r2/object/get", "POST", { bucket, key });
128
+ const err = errorOf(result);
129
+ if (err)
130
+ return textResult(`R2 object get failed: ${err}`, true);
131
+ const b64 = result.contentBase64;
132
+ if (typeof b64 !== "string")
133
+ return textResult("R2 object get failed: no content in response", true);
134
+ const bytes = Buffer.from(b64, "base64");
135
+ try {
136
+ writeFileSync(dest, bytes);
137
+ }
138
+ catch (e) {
139
+ return textResult(`R2 object get failed: ${e instanceof Error ? e.message : String(e)}`, true);
140
+ }
141
+ return textResult(`Wrote ${bytes.length} bytes to ${dest}`);
142
+ });
143
+ // ─── storage-r2-object-put ────────────────────────────────────────────────
144
+ lifelineTool(server, "storage-r2-object-put", `Upload a file from your account directory to an R2 bucket your account owns. Files larger than ${R2_OBJECT_MAX_BYTES / 1024 / 1024} MiB are rejected.`, {
145
+ bucket: z.string().describe("Bucket name"),
146
+ key: z.string().describe("Object key"),
147
+ srcPath: z.string().describe("Source file path, inside your account directory"),
148
+ }, async ({ bucket, key, srcPath }) => {
149
+ let bytes;
150
+ try {
151
+ // Confined and size-checked before the read: an over-cap file costs no
152
+ // buffer here and never reaches the house process.
153
+ ({ bytes } = readPutSource(srcPath));
154
+ }
155
+ catch (e) {
156
+ return textResult(`R2 object put failed: ${e instanceof Error ? e.message : String(e)}`, true);
157
+ }
158
+ const result = await callApi("storage-r2-object-put", "/api/storage/r2/object/put", "POST", {
159
+ bucket,
160
+ key,
161
+ contentBase64: bytes.toString("base64"),
162
+ });
163
+ const err = errorOf(result);
164
+ if (err)
165
+ return textResult(`R2 object put failed: ${err}`, true);
166
+ return textResult(`Uploaded ${bytes.length} bytes to ${bucket}/${key}.`);
167
+ });
168
+ // ─── storage-r2-object-delete ─────────────────────────────────────────────
169
+ lifelineTool(server, "storage-r2-object-delete", "Delete an object from an R2 bucket your account owns.", { bucket: z.string().describe("Bucket name"), key: z.string().describe("Object key") }, async ({ bucket, key }) => {
170
+ const result = await callApi("storage-r2-object-delete", "/api/storage/r2/object/delete", "POST", { bucket, key });
171
+ const err = errorOf(result);
172
+ if (err)
173
+ return textResult(`R2 object delete failed: ${err}`, true);
174
+ return textResult(`Deleted ${bucket}/${key}.`);
175
+ });
90
176
  async function main() {
91
177
  const transport = new StdioServerTransport();
92
178
  await server.connect(transport);
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Returns the confined absolute path and the file's bytes.
3
+ *
4
+ * Throws naming the offending file and the limit when the file is over the cap,
5
+ * and naming the path when it is outside the account directory or unreadable.
6
+ */
7
+ export declare function readPutSource(srcPath: string): {
8
+ path: string;
9
+ bytes: Buffer;
10
+ };
11
+ //# sourceMappingURL=put-source.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"put-source.d.ts","sourceRoot":"","sources":["../src/put-source.ts"],"names":[],"mappings":"AAuBA;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAQ9E"}
@@ -0,0 +1,35 @@
1
+ /**
2
+ * Resolve a put's source file: confine it to the caller's account directory,
3
+ * size it, reject it if it is over the cap, and only then read it.
4
+ *
5
+ * The order is the point (Task 1695). An over-cap file must cost no buffer, in
6
+ * this process or the house one, so the size is checked before the read rather
7
+ * than after — the same pre-read statSync rule the email plugin's
8
+ * resolveOutboundAttachments already proves for the same class of payload.
9
+ * Checking after the read would bound the upload while leaving the local OOM
10
+ * exactly where it was.
11
+ *
12
+ * This lives in its own module rather than inline in the put tool because the
13
+ * ordering is the behaviour worth testing, and index.ts constructs an MCP server
14
+ * on import.
15
+ */
16
+ import { readFileSync, statSync } from "node:fs";
17
+ import { basename } from "node:path";
18
+ import { confineToAccountDir } from "./confine-path.js";
19
+ import { R2_OBJECT_MAX_BYTES, tooLargeMessage, } from "../../../../lib/storage-broker/dist/object-limits.js";
20
+ /**
21
+ * Returns the confined absolute path and the file's bytes.
22
+ *
23
+ * Throws naming the offending file and the limit when the file is over the cap,
24
+ * and naming the path when it is outside the account directory or unreadable.
25
+ */
26
+ export function readPutSource(srcPath) {
27
+ const path = confineToAccountDir(srcPath, true);
28
+ // confineToAccountDir has already proven this is a regular file.
29
+ const { size } = statSync(path);
30
+ if (size > R2_OBJECT_MAX_BYTES) {
31
+ throw new Error(tooLargeMessage(basename(path), size));
32
+ }
33
+ return { path, bytes: readFileSync(path) };
34
+ }
35
+ //# sourceMappingURL=put-source.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"put-source.js","sourceRoot":"","sources":["../src/put-source.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AACH,OAAO,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AACjD,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AACrC,OAAO,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AACxD,OAAO,EACL,mBAAmB,EACnB,eAAe,GAChB,MAAM,sDAAsD,CAAC;AAE9D;;;;;GAKG;AACH,MAAM,UAAU,aAAa,CAAC,OAAe;IAC3C,MAAM,IAAI,GAAG,mBAAmB,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;IAChD,iEAAiE;IACjE,MAAM,EAAE,IAAI,EAAE,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC;IAChC,IAAI,IAAI,GAAG,mBAAmB,EAAE,CAAC;QAC/B,MAAM,IAAI,KAAK,CAAC,eAAe,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC;IACzD,CAAC;IACD,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,YAAY,CAAC,IAAI,CAAC,EAAE,CAAC;AAC7C,CAAC"}
@@ -87,6 +87,52 @@ write_parent_with_error() {
87
87
  } > "$f"
88
88
  }
89
89
 
90
+ # Write a parent JSONL carrying BOTH harness rejections and the classes that
91
+ # must NOT be treated as rejections. A rejection is a call the CLI refused to
92
+ # dispatch, so the tool never ran; everything else here either ran and failed or
93
+ # is a different fault. Both InputValidationError sub-classes are covered:
94
+ # unparseable JSON (carries __unparsedToolInput) and schema-valid JSON that
95
+ # failed validation (no such marker, and the majority class in practice).
96
+ write_parent_with_rejections() {
97
+ local cfg="$1" uuid="$2"
98
+ local f="$cfg/projects/-fake-cwd/${uuid}.jsonl"
99
+ {
100
+ printf '%s\n' '{"type":"user","timestamp":"2026-07-16T15:59:00.000Z","uuid":"r0","message":{"role":"user","content":"send it"}}'
101
+ # 2 x rejection sub-class A (unparseable JSON) on ONE tool -> census x2
102
+ printf '%s\n' '{"type":"assistant","timestamp":"2026-07-16T15:59:01.000Z","uuid":"r1","message":{"role":"assistant","content":[{"type":"tool_use","id":"toolu_R1","name":"outlook-mail-send","input":{"__unparsedToolInput":"{\"to\": bare@x.co}"}}]}}'
103
+ printf '%s\n' '{"type":"user","timestamp":"2026-07-16T15:59:02.000Z","uuid":"r2","message":{"role":"user","content":[{"type":"tool_result","tool_use_id":"toolu_R1","is_error":true,"content":"<tool_use_error>InputValidationError: outlook-mail-send was called with input that could not be parsed as JSON.\nYou sent (first 200 of 670 bytes): {\"to\": bare@x.co} REJECT_A_ONE</tool_use_error>"}]}}'
104
+ printf '%s\n' '{"type":"assistant","timestamp":"2026-07-16T15:59:03.000Z","uuid":"r3","message":{"role":"assistant","content":[{"type":"tool_use","id":"toolu_R2","name":"outlook-mail-send","input":{"__unparsedToolInput":"{\"to\": bare@x.co}"}}]}}'
105
+ printf '%s\n' '{"type":"user","timestamp":"2026-07-16T15:59:04.000Z","uuid":"r4","message":{"role":"user","content":[{"type":"tool_result","tool_use_id":"toolu_R2","is_error":true,"content":"<tool_use_error>InputValidationError: outlook-mail-send was called with input that could not be parsed as JSON.\nYou sent (first 200 of 670 bytes): {\"to\": bare@x.co} REJECT_A_TWO</tool_use_error>"}]}}'
106
+ # rejection sub-class B: JSON parsed fine, schema validation failed
107
+ printf '%s\n' '{"type":"assistant","timestamp":"2026-07-16T15:59:05.000Z","uuid":"r5","message":{"role":"assistant","content":[{"type":"tool_use","id":"toolu_R3","name":"Read","input":{"offset":"x"}}]}}'
108
+ printf '%s\n' '{"type":"user","timestamp":"2026-07-16T15:59:06.000Z","uuid":"r6","message":{"role":"user","content":[{"type":"tool_result","tool_use_id":"toolu_R3","is_error":true,"content":"<tool_use_error>InputValidationError: Read failed due to the following issue: The parameter `offset` type is expected as `number` REJECT_B_ONE</tool_use_error>"}]}}'
109
+ # NOT a rejection: unknown tool (different fault, has its own PostToolUse hook)
110
+ printf '%s\n' '{"type":"assistant","timestamp":"2026-07-16T15:59:07.000Z","uuid":"r7","message":{"role":"assistant","content":[{"type":"tool_use","id":"toolu_N1","name":"work-create","input":{}}]}}'
111
+ printf '%s\n' '{"type":"user","timestamp":"2026-07-16T15:59:08.000Z","uuid":"r8","message":{"role":"user","content":[{"type":"tool_result","tool_use_id":"toolu_N1","is_error":true,"content":"<tool_use_error>Error: No such tool available: work-create NOTREJ_NOTOOL</tool_use_error>"}]}}'
112
+ # NOT a rejection: MCP server-side validation (the call DID reach the server)
113
+ printf '%s\n' '{"type":"assistant","timestamp":"2026-07-16T15:59:09.000Z","uuid":"r9","message":{"role":"assistant","content":[{"type":"tool_use","id":"toolu_N2","name":"outlook-mail-fetch-body","input":{}}]}}'
114
+ printf '%s\n' '{"type":"user","timestamp":"2026-07-16T15:59:10.000Z","uuid":"rA","message":{"role":"user","content":[{"type":"tool_result","tool_use_id":"toolu_N2","is_error":true,"content":"MCP error -32602: Input validation error: id: Required NOTREJ_32602"}]}}'
115
+ # NOT a rejection: built-in tool that RAN and failed its precondition
116
+ printf '%s\n' '{"type":"assistant","timestamp":"2026-07-16T15:59:11.000Z","uuid":"rB","message":{"role":"assistant","content":[{"type":"tool_use","id":"toolu_N3","name":"Edit","input":{}}]}}'
117
+ printf '%s\n' '{"type":"user","timestamp":"2026-07-16T15:59:12.000Z","uuid":"rC","message":{"role":"user","content":[{"type":"tool_result","tool_use_id":"toolu_N3","is_error":true,"content":"<tool_use_error>File has not been read yet. Read it first before writing to it. NOTREJ_UNREAD</tool_use_error>"}]}}'
118
+ } > "$f"
119
+ }
120
+
121
+ # Write a subagent transcript whose ONLY error is a harness rejection. Used to
122
+ # prove --scan-subagent-errors does not report a rejection-only subagent as an
123
+ # error-carrying one: the subagent did not fail, a call was never dispatched.
124
+ write_subagent_rejection_only() {
125
+ local cfg="$1" parent_uuid="$2" agent="$3" atype="$4"
126
+ local d="$cfg/projects/-fake-cwd/${parent_uuid}/subagents"
127
+ mkdir -p "$d"
128
+ {
129
+ printf '%s\n' '{"type":"user","timestamp":"2026-07-16T16:00:00.000Z","uuid":"j1","message":{"role":"user","content":"read it"}}'
130
+ printf '%s\n' '{"type":"assistant","timestamp":"2026-07-16T16:00:01.000Z","uuid":"j2","message":{"role":"assistant","content":[{"type":"tool_use","id":"toolu_SR","name":"Read","input":{"__unparsedToolInput":"{\"file_path\": /x}"}}]}}'
131
+ printf '%s\n' '{"type":"user","timestamp":"2026-07-16T16:00:02.000Z","uuid":"j3","message":{"role":"user","content":[{"type":"tool_result","tool_use_id":"toolu_SR","is_error":true,"content":"<tool_use_error>InputValidationError: Read was called with input that could not be parsed as JSON.\nYou sent (first 200 of 30 bytes): {\"file_path\": /x} SUBREJ_ONLY</tool_use_error>"}]}}'
132
+ } > "$d/${agent}.jsonl"
133
+ printf '{"agentType":"%s","description":"read a file"}\n' "$atype" > "$d/${agent}.meta.json"
134
+ }
135
+
90
136
  # Write a CLEAN subagent transcript (no errors) + its meta.
91
137
  write_subagent_clean() {
92
138
  local cfg="$1" parent_uuid="$2" agent="$3" atype="$4"
@@ -248,6 +294,75 @@ case_parent_error_not_subagent() {
248
294
  return 0
249
295
  }
250
296
 
297
+ # --- Case J: harness rejection is distinguished from a tool that RAN and failed ---
298
+ # The 1692 defect: a call the CLI refused to dispatch rendered identically to a
299
+ # tool that ran and returned a failure, so a rejection loop read as "the tool is
300
+ # broken" while the tool was healthy. Only InputValidationError may be relabelled.
301
+ case_rejection_classified_and_counted() {
302
+ local root="/tmp/maxy-1692-J-$$"; local out
303
+ out=$(setup_tree "$root"); local script="${out% *}"; local cfg="${out#* }"
304
+ write_parent_with_rejections "$cfg" "$UUID_A"
305
+ write_pidfile "$cfg" 4255 "$UUID_A" "$BRIDGE"
306
+
307
+ invoke "$script" "$cfg" "session_${BRIDGE}"
308
+ cleanup_tree "$root"
309
+
310
+ [[ $RC -eq 0 ]] || { echo " expected exit 0, got $RC; err=$ERR"; return 1; }
311
+
312
+ # Both InputValidationError sub-classes are rejections (neither dispatched).
313
+ [[ "$OUT" == *"REJECTED"*"REJECT_A_ONE"* ]] || { echo " sub-class A (unparseable) not flagged REJECTED"; return 1; }
314
+ [[ "$OUT" == *"REJECTED"*"REJECT_B_ONE"* ]] || { echo " sub-class B (schema-invalid) not flagged REJECTED"; return 1; }
315
+
316
+ # The exclusions MUST keep the plain tool-error rendering. Widening the
317
+ # predicate to the bare <tool_use_error> wrapper is the regression this pins.
318
+ local l
319
+ for l in NOTREJ_NOTOOL NOTREJ_32602 NOTREJ_UNREAD; do
320
+ grep -q "tool error.*$l" <<<"$OUT" || { echo " $l lost its '‼ tool error' rendering"; return 1; }
321
+ grep -q "REJECTED.*$l" <<<"$OUT" && { echo " $l wrongly flagged REJECTED"; return 1; }
322
+ done
323
+
324
+ # Repetition is the diagnostic fact: 2 identical calls on one tool, counted.
325
+ [[ "$OUT" == *"rejections: 3"* ]] || { echo " census missing or miscounted (want 3)"; return 1; }
326
+ [[ "$OUT" == *"outlook-mail-send x2"* ]] || { echo " census does not count the repeat per tool"; return 1; }
327
+ return 0
328
+ }
329
+
330
+ # --- Case K: a clean session emits NO census line (non-regression) ---
331
+ case_no_rejections_no_census() {
332
+ local root="/tmp/maxy-1692-K-$$"; local out
333
+ out=$(setup_tree "$root"); local script="${out% *}"; local cfg="${out#* }"
334
+ write_parent_with_error "$cfg" "$UUID_A"
335
+ write_pidfile "$cfg" 4256 "$UUID_A" "$BRIDGE"
336
+
337
+ invoke "$script" "$cfg" "session_${BRIDGE}"
338
+ cleanup_tree "$root"
339
+
340
+ [[ $RC -eq 0 ]] || { echo " expected exit 0, got $RC"; return 1; }
341
+ [[ "$OUT" != *"rejections:"* ]] || { echo " census line emitted for a session with no rejections"; return 1; }
342
+ [[ "$OUT" != *"REJECTED"* ]] || { echo " genuine tool error wrongly flagged REJECTED"; return 1; }
343
+ return 0
344
+ }
345
+
346
+ # --- Case L: --scan-subagent-errors does not report a rejection-only subagent ---
347
+ # A rejection is not a subagent failure: the subagent did not fail, a call was
348
+ # never dispatched. Counting it re-creates the 1692 conflation one mode over.
349
+ case_scan_ignores_rejection_only_subagent() {
350
+ local root="/tmp/maxy-1692-L-$$"; local out
351
+ out=$(setup_tree "$root"); local script="${out% *}"; local cfg="${out#* }"
352
+ write_parent "$cfg" "$UUID_A"
353
+ write_subagent_rejection_only "$cfg" "$UUID_A" "agent-aREJ00001" "content-producer"
354
+ write_subagent_failed "$cfg" "$UUID_A" "agent-aFAIL0001" "pdf-renderer"
355
+
356
+ invoke "$script" "$cfg" --scan-subagent-errors
357
+ cleanup_tree "$root"
358
+
359
+ [[ $RC -eq 0 ]] || { echo " expected exit 0, got $RC; err=$ERR"; return 1; }
360
+ [[ "$OUT" == *"aFAIL0001"* ]] || { echo " genuinely failed subagent missing from scan"; return 1; }
361
+ [[ "$OUT" != *"SUBREJ_ONLY"* ]] || { echo " rejection-only subagent reported as error-carrying"; return 1; }
362
+ [[ "$OUT" != *"aREJ00001"* ]] || { echo " rejection-only subagent listed by scan"; return 1; }
363
+ return 0
364
+ }
365
+
251
366
  # --- Case I: content-grep resolves a unique body match (last-resort tier) ---
252
367
  case_content_grep_single() {
253
368
  local root="/tmp/maxy-585-I-$$"; local out
@@ -299,6 +414,9 @@ run_case "parent's own tool error not mislabelled SUBAGENT ERROR" case_pare
299
414
  run_case "content-grep resolves a unique body match" case_content_grep_single
300
415
  run_case "content-grep refuses an ambiguous (multi) body match" case_content_grep_ambiguous_refuses
301
416
  run_case "unresolvable key → exit 1" case_unresolvable_miss
417
+ run_case "harness rejection classified + counted, exclusions intact" case_rejection_classified_and_counted
418
+ run_case "no rejections → no census line" case_no_rejections_no_census
419
+ run_case "scan ignores a rejection-only subagent" case_scan_ignores_rejection_only_subagent
302
420
 
303
421
  echo ""
304
422
  echo "================================================"