toolcraft 0.0.232 → 0.0.233

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 (180) hide show
  1. package/composition.json +3 -3
  2. package/dist/applied-default.d.ts +3 -0
  3. package/dist/applied-default.js +16 -0
  4. package/dist/cli.js +508 -204
  5. package/dist/composition.json +3 -3
  6. package/dist/discriminator.d.ts +9 -0
  7. package/dist/discriminator.js +32 -0
  8. package/dist/error-report.d.ts +2 -18
  9. package/dist/error-report.js +12 -14
  10. package/dist/http.js +8 -1
  11. package/dist/human-in-loop/gate.js +6 -0
  12. package/dist/index.compile-check.js +22 -5
  13. package/dist/index.d.ts +12 -5
  14. package/dist/index.js +50 -0
  15. package/dist/json-schema-converter.d.ts +14 -6
  16. package/dist/json-schema-converter.js +150 -20
  17. package/dist/mcp-proxy-metadata.d.ts +2 -0
  18. package/dist/mcp-proxy-metadata.js +13 -0
  19. package/dist/mcp-proxy.d.ts +1 -0
  20. package/dist/mcp-proxy.js +65 -47
  21. package/dist/mcp-result.d.ts +3 -0
  22. package/dist/mcp-result.js +10 -0
  23. package/dist/mcp.js +211 -153
  24. package/dist/redaction.js +26 -17
  25. package/dist/renderer.js +40 -29
  26. package/dist/schema-member-names.d.ts +2 -0
  27. package/dist/schema-member-names.js +39 -0
  28. package/dist/schema-scope.d.ts +1 -0
  29. package/dist/schema-scope.js +29 -16
  30. package/dist/schema.d.ts +1 -1
  31. package/dist/sdk.d.ts +2 -1
  32. package/dist/sdk.js +164 -50
  33. package/dist/stream.js +24 -23
  34. package/dist/testing/diagnostic-value.d.ts +1 -0
  35. package/dist/testing/diagnostic-value.js +57 -0
  36. package/dist/testing/fakes.js +2 -1
  37. package/dist/testing/harness.js +1 -0
  38. package/dist/testing/memory-fs.js +42 -1
  39. package/dist/testing/parity.js +50 -6
  40. package/dist/union-validation.d.ts +5 -0
  41. package/dist/union-validation.js +36 -0
  42. package/node_modules/@poe-code/process-runner/dist/types.d.ts +2 -0
  43. package/node_modules/mcp-oauth-server/dist/index.js +47 -6
  44. package/node_modules/tiny-http-mcp-server/dist/cli.js +14 -2
  45. package/node_modules/tiny-http-mcp-server/dist/composition.json +1 -1
  46. package/node_modules/tiny-http-mcp-server/dist/http-server.d.ts +7 -5
  47. package/node_modules/tiny-http-mcp-server/dist/http-server.js +3 -11
  48. package/node_modules/tiny-http-mcp-server/dist/http-transport.d.ts +6 -1
  49. package/node_modules/tiny-http-mcp-server/dist/http-transport.js +196 -15
  50. package/node_modules/tiny-http-mcp-server/dist/index.d.ts +2 -2
  51. package/node_modules/tiny-http-mcp-server/dist/modern-headers.d.ts +3 -0
  52. package/node_modules/tiny-http-mcp-server/dist/modern-headers.js +35 -0
  53. package/node_modules/tiny-http-mcp-server/dist/parse-body.d.ts +1 -0
  54. package/node_modules/tiny-http-mcp-server/dist/parse-body.js +9 -5
  55. package/node_modules/tiny-http-mcp-server/dist/test-support.js +17 -0
  56. package/node_modules/tiny-http-mcp-server/dist/testing.d.ts +1 -1
  57. package/node_modules/tiny-http-mcp-server/dist/testing.js +3 -2
  58. package/node_modules/tiny-http-mcp-server/node_modules/mcp-oauth/dist/client/default-oauth-client-provider.js +21 -4
  59. package/node_modules/tiny-http-mcp-server/node_modules/mcp-oauth/dist/client/token-endpoint.d.ts +1 -1
  60. package/node_modules/tiny-http-mcp-server/node_modules/mcp-oauth/dist/client/token-endpoint.js +14 -6
  61. package/node_modules/tiny-http-mcp-server/node_modules/mcp-oauth/dist/http-fetch.d.ts +1 -0
  62. package/node_modules/tiny-http-mcp-server/node_modules/mcp-oauth/dist/http-fetch.js +8 -0
  63. package/node_modules/tiny-http-mcp-server/node_modules/mcp-oauth/dist/http-response.d.ts +1 -0
  64. package/node_modules/tiny-http-mcp-server/node_modules/mcp-oauth/dist/http-response.js +50 -0
  65. package/node_modules/tiny-http-mcp-server/node_modules/mcp-oauth/dist/index.d.ts +2 -0
  66. package/node_modules/tiny-http-mcp-server/node_modules/mcp-oauth/dist/index.js +2 -0
  67. package/node_modules/tiny-http-mcp-server/node_modules/mcp-oauth/dist/server/jwks-token-verifier.js +21 -3
  68. package/node_modules/tiny-http-mcp-server/package.json +1 -1
  69. package/node_modules/tiny-mcp-client/README.md +1 -0
  70. package/node_modules/tiny-mcp-client/dist/index.d.ts +178 -101
  71. package/node_modules/tiny-mcp-client/dist/index.js +4696 -291
  72. package/node_modules/tiny-mcp-client/package.json +2 -1
  73. package/node_modules/tiny-stdio-mcp-server/dist/base64.d.ts +1 -0
  74. package/node_modules/tiny-stdio-mcp-server/dist/base64.js +5 -0
  75. package/node_modules/tiny-stdio-mcp-server/dist/composition.json +1 -1
  76. package/node_modules/tiny-stdio-mcp-server/dist/content/audio.d.ts +3 -0
  77. package/node_modules/tiny-stdio-mcp-server/dist/content/convert.d.ts +5 -1
  78. package/node_modules/tiny-stdio-mcp-server/dist/content/convert.js +41 -6
  79. package/node_modules/tiny-stdio-mcp-server/dist/content/file.d.ts +5 -0
  80. package/node_modules/tiny-stdio-mcp-server/dist/content/image.d.ts +3 -0
  81. package/node_modules/tiny-stdio-mcp-server/dist/headers.d.ts +10 -0
  82. package/node_modules/tiny-stdio-mcp-server/dist/headers.js +180 -0
  83. package/node_modules/tiny-stdio-mcp-server/dist/index.d.ts +5 -5
  84. package/node_modules/tiny-stdio-mcp-server/dist/index.js +1 -1
  85. package/node_modules/tiny-stdio-mcp-server/dist/input-request-schema.d.ts +220 -0
  86. package/node_modules/tiny-stdio-mcp-server/dist/input-request-schema.js +1995 -0
  87. package/node_modules/tiny-stdio-mcp-server/dist/jsonrpc.d.ts +1 -0
  88. package/node_modules/tiny-stdio-mcp-server/dist/jsonrpc.js +38 -25
  89. package/node_modules/tiny-stdio-mcp-server/dist/metadata.d.ts +2 -0
  90. package/node_modules/tiny-stdio-mcp-server/dist/metadata.js +37 -0
  91. package/node_modules/tiny-stdio-mcp-server/dist/protocol-validation.d.ts +4 -0
  92. package/node_modules/tiny-stdio-mcp-server/dist/protocol-validation.js +53 -0
  93. package/node_modules/tiny-stdio-mcp-server/dist/protocol.d.ts +17 -0
  94. package/node_modules/tiny-stdio-mcp-server/dist/protocol.js +228 -0
  95. package/node_modules/tiny-stdio-mcp-server/dist/request-cancellation.d.ts +1 -0
  96. package/node_modules/tiny-stdio-mcp-server/dist/request-cancellation.js +18 -0
  97. package/node_modules/tiny-stdio-mcp-server/dist/sampling-messages.d.ts +18 -0
  98. package/node_modules/tiny-stdio-mcp-server/dist/sampling-messages.js +34 -0
  99. package/node_modules/tiny-stdio-mcp-server/dist/schema.d.ts +4 -1
  100. package/node_modules/tiny-stdio-mcp-server/dist/server.d.ts +9 -4
  101. package/node_modules/tiny-stdio-mcp-server/dist/server.js +334 -135
  102. package/node_modules/tiny-stdio-mcp-server/dist/stdio-input.d.ts +3 -0
  103. package/node_modules/tiny-stdio-mcp-server/dist/stdio-input.js +50 -28
  104. package/node_modules/tiny-stdio-mcp-server/dist/subscriptions.d.ts +11 -0
  105. package/node_modules/tiny-stdio-mcp-server/dist/subscriptions.js +128 -0
  106. package/node_modules/tiny-stdio-mcp-server/dist/types.d.ts +58 -18
  107. package/node_modules/tiny-stdio-mcp-server/dist/types.js +2 -1
  108. package/node_modules/tiny-stdio-mcp-server/dist/uri.d.ts +1 -0
  109. package/node_modules/tiny-stdio-mcp-server/dist/uri.js +41 -0
  110. package/node_modules/tiny-stdio-mcp-server/package.json +8 -0
  111. package/node_modules/toolcraft-design/dist/command-registry.d.ts +11 -0
  112. package/node_modules/toolcraft-design/dist/command-registry.js +24 -0
  113. package/node_modules/toolcraft-design/dist/dashboard/ansi.d.ts +2 -0
  114. package/node_modules/toolcraft-design/dist/dashboard/ansi.js +81 -27
  115. package/node_modules/toolcraft-design/dist/dashboard/buffer.js +39 -25
  116. package/node_modules/toolcraft-design/dist/dashboard/components/border.js +6 -5
  117. package/node_modules/toolcraft-design/dist/dashboard/components/footer.js +26 -21
  118. package/node_modules/toolcraft-design/dist/dashboard/components/output-pane.d.ts +1 -1
  119. package/node_modules/toolcraft-design/dist/dashboard/components/output-pane.js +12 -6
  120. package/node_modules/toolcraft-design/dist/dashboard/components/stats-pane.d.ts +2 -1
  121. package/node_modules/toolcraft-design/dist/dashboard/components/stats-pane.js +51 -10
  122. package/node_modules/toolcraft-design/dist/dashboard/dashboard.d.ts +4 -0
  123. package/node_modules/toolcraft-design/dist/dashboard/dashboard.js +77 -4
  124. package/node_modules/toolcraft-design/dist/dashboard/index.d.ts +2 -0
  125. package/node_modules/toolcraft-design/dist/dashboard/index.js +2 -0
  126. package/node_modules/toolcraft-design/dist/dashboard/keymap.js +26 -6
  127. package/node_modules/toolcraft-design/dist/dashboard/layout.d.ts +1 -0
  128. package/node_modules/toolcraft-design/dist/dashboard/layout.js +19 -3
  129. package/node_modules/toolcraft-design/dist/dashboard/line-buffer.d.ts +9 -0
  130. package/node_modules/toolcraft-design/dist/dashboard/line-buffer.js +63 -0
  131. package/node_modules/toolcraft-design/dist/dashboard/output-preview.d.ts +9 -0
  132. package/node_modules/toolcraft-design/dist/dashboard/output-preview.js +70 -0
  133. package/node_modules/toolcraft-design/dist/dashboard/snapshot.js +3 -1
  134. package/node_modules/toolcraft-design/dist/dashboard/store.js +9 -3
  135. package/node_modules/toolcraft-design/dist/dashboard/terminal-strings.d.ts +6 -0
  136. package/node_modules/toolcraft-design/dist/dashboard/terminal-strings.js +108 -0
  137. package/node_modules/toolcraft-design/dist/dashboard/terminal-width.js +3 -1
  138. package/node_modules/toolcraft-design/dist/dashboard/terminal.js +11 -1
  139. package/node_modules/toolcraft-design/dist/dashboard/testing/pipeline-scenario.d.ts +1 -0
  140. package/node_modules/toolcraft-design/dist/dashboard/testing/pipeline-scenario.js +126 -0
  141. package/node_modules/toolcraft-design/dist/dashboard/types.d.ts +3 -1
  142. package/node_modules/toolcraft-design/dist/event-groups.d.ts +19 -0
  143. package/node_modules/toolcraft-design/dist/event-groups.js +49 -0
  144. package/node_modules/toolcraft-design/dist/index.d.ts +6 -1
  145. package/node_modules/toolcraft-design/dist/index.js +5 -1
  146. package/node_modules/toolcraft-design/dist/inline-notice.d.ts +14 -0
  147. package/node_modules/toolcraft-design/dist/inline-notice.js +28 -0
  148. package/node_modules/toolcraft-design/dist/metric.d.ts +8 -0
  149. package/node_modules/toolcraft-design/dist/metric.js +21 -0
  150. package/node_modules/toolcraft-design/dist/overlay-manager.d.ts +6 -0
  151. package/node_modules/toolcraft-design/dist/overlay-manager.js +10 -0
  152. package/node_modules/toolcraft-design/dist/primitives.d.ts +12 -0
  153. package/node_modules/toolcraft-design/dist/primitives.js +7 -0
  154. package/node_modules/toolcraft-design/dist/progress-group.d.ts +7 -0
  155. package/node_modules/toolcraft-design/dist/progress-group.js +10 -0
  156. package/node_modules/toolcraft-design/dist/render-performance.d.ts +33 -0
  157. package/node_modules/toolcraft-design/dist/render-performance.js +71 -0
  158. package/node_modules/toolcraft-design/dist/task-tree.d.ts +22 -0
  159. package/node_modules/toolcraft-design/dist/task-tree.js +79 -0
  160. package/node_modules/toolcraft-design/dist/viewport.d.ts +18 -0
  161. package/node_modules/toolcraft-design/dist/viewport.js +56 -0
  162. package/node_modules/toolcraft-schema/dist/clone-default.d.ts +1 -0
  163. package/node_modules/toolcraft-schema/dist/clone-default.js +26 -0
  164. package/node_modules/toolcraft-schema/dist/index.compile-check.js +1 -0
  165. package/node_modules/toolcraft-schema/dist/index.d.ts +18 -9
  166. package/node_modules/toolcraft-schema/dist/index.js +46 -8
  167. package/node_modules/toolcraft-schema/dist/json-schema/compiler.d.ts +1 -0
  168. package/node_modules/toolcraft-schema/dist/json-schema/compiler.js +6 -0
  169. package/node_modules/toolcraft-schema/dist/json-schema/evaluate.js +6 -3
  170. package/node_modules/toolcraft-schema/dist/json-schema/normalize-nullability.d.ts +1 -0
  171. package/node_modules/toolcraft-schema/dist/json-schema/normalize-nullability.js +69 -0
  172. package/node_modules/toolcraft-schema/dist/json-schema/types.d.ts +1 -0
  173. package/node_modules/toolcraft-schema/dist/json.d.ts +4 -1
  174. package/node_modules/toolcraft-schema/dist/json.js +57 -1
  175. package/node_modules/toolcraft-schema/dist/native-json-schema.d.ts +10 -0
  176. package/node_modules/toolcraft-schema/dist/native-json-schema.js +11 -0
  177. package/node_modules/toolcraft-schema/dist/validate.d.ts +5 -1
  178. package/node_modules/toolcraft-schema/dist/validate.js +61 -47
  179. package/node_modules/toolcraft-schema/package.json +1 -1
  180. package/package.json +6 -3
package/dist/redaction.js CHANGED
@@ -12,28 +12,37 @@ export function isSensitiveName(name) {
12
12
  const normalized = normalizeName(name);
13
13
  return SENSITIVE_NAME_PARTS.some((candidate) => normalized.includes(candidate));
14
14
  }
15
- function redactSecretLikeFieldsValue(value, name, seen) {
15
+ function redactSecretLikeFieldsValue(value, name, seen, applyToJSON = true) {
16
16
  if (name.length > 0 && isSensitiveName(name)) {
17
17
  return REDACTED_VALUE;
18
18
  }
19
- if (Array.isArray(value)) {
20
- if (seen.has(value)) {
21
- return "[Circular]";
22
- }
23
- seen.add(value);
24
- return value.map((entry) => redactSecretLikeFieldsValue(entry, name, seen));
19
+ if ((typeof value !== "object" || value === null) && typeof value !== "function") {
20
+ return value;
21
+ }
22
+ if (seen.has(value)) {
23
+ return "[Circular]";
25
24
  }
26
- if (isPlainObject(value)) {
27
- if (seen.has(value)) {
28
- return "[Circular]";
25
+ seen.add(value);
26
+ const toJSON = applyToJSON ? value.toJSON : undefined;
27
+ if (typeof toJSON === "function") {
28
+ const serialized = toJSON.call(value, name);
29
+ if (serialized !== value) {
30
+ const redacted = redactSecretLikeFieldsValue(serialized, name, seen, false);
31
+ seen.delete(value);
32
+ return redacted;
29
33
  }
30
- seen.add(value);
31
- return Object.fromEntries(Object.entries(value).map(([key, entry]) => [
32
- key,
33
- redactSecretLikeFieldsValue(entry, key, seen)
34
- ]));
35
34
  }
36
- return value;
35
+ if (typeof value === "function") {
36
+ seen.delete(value);
37
+ return undefined;
38
+ }
39
+ const redacted = Array.isArray(value)
40
+ ? value.map((entry, index) => redactSecretLikeFieldsValue(entry, String(index), seen))
41
+ : Object.fromEntries(Object.entries(value)
42
+ .filter(([key, entry]) => key !== "toJSON" || typeof entry !== "function")
43
+ .map(([key, entry]) => [key, redactSecretLikeFieldsValue(entry, key, seen)]));
44
+ seen.delete(value);
45
+ return redacted;
37
46
  }
38
47
  export function redactSecretLikeFields(value, name = "") {
39
48
  return redactSecretLikeFieldsValue(value, name, new WeakSet());
@@ -61,7 +70,7 @@ export function redactHttpBody(body) {
61
70
  export function redactHttpHeaderValue(name, value) {
62
71
  const normalized = normalizeName(name);
63
72
  if (AUTHORIZATION_HEADER_NAMES.has(normalized)) {
64
- return "Bearer ****";
73
+ return value.startsWith("Bearer ") ? "Bearer ****" : "****";
65
74
  }
66
75
  if (SECRET_HEADER_NAMES.has(normalized) || isSensitiveName(name)) {
67
76
  return REDACTED_VALUE;
package/dist/renderer.js CHANGED
@@ -1,26 +1,19 @@
1
1
  import YAML from "yaml";
2
2
  import { renderDetailCard } from "toolcraft-design";
3
+ import { isMCPResult } from "./mcp-result.js";
3
4
  function isObject(value) {
4
5
  return value !== null && typeof value === "object" && !Array.isArray(value);
5
6
  }
6
- function isMcpCallToolResult(value) {
7
- if (!isObject(value)) {
8
- return false;
9
- }
10
- const hasContent = Array.isArray(value.content);
11
- const hasStructured = value.structuredContent !== undefined;
12
- if (!hasContent && !hasStructured) {
13
- return false;
14
- }
15
- return Object.keys(value).every((key) => key === "content" || key === "structuredContent" || key === "isError" || key === "_meta");
16
- }
17
7
  function isMcpTextContent(value) {
18
8
  return isObject(value) && value.type === "text" && typeof value.text === "string";
19
9
  }
20
10
  function extractMcpPayload(envelope) {
21
11
  const structuredContent = envelope.structuredContent;
22
- if (isObject(structuredContent) && "result" in structuredContent) {
23
- return structuredContent.result;
12
+ if (isObject(structuredContent)) {
13
+ const keys = Object.keys(structuredContent);
14
+ if (keys.length === 1 && keys[0] === "result") {
15
+ return structuredContent.result;
16
+ }
24
17
  }
25
18
  if (structuredContent !== undefined) {
26
19
  return structuredContent;
@@ -30,12 +23,15 @@ function extractMcpPayload(envelope) {
30
23
  .filter(isMcpTextContent)
31
24
  .map((block) => block.text)
32
25
  .join("\n");
33
- return text.length > 0 ? text : undefined;
26
+ if (text.length > 0) {
27
+ return text;
28
+ }
29
+ return envelope.isError === true ? "Upstream tool failed." : undefined;
34
30
  }
35
31
  return undefined;
36
32
  }
37
33
  function unwrapMcpEnvelope(result) {
38
- if (!isMcpCallToolResult(result)) {
34
+ if (!isMCPResult(result)) {
39
35
  return { result, mcpError: false };
40
36
  }
41
37
  return {
@@ -87,10 +83,25 @@ function humanizeKey(key) {
87
83
  }
88
84
  return output;
89
85
  }
86
+ function getResultLabels(result) {
87
+ const labels = new Map();
88
+ const counts = new Map();
89
+ for (const key of Object.keys(result)) {
90
+ const label = humanizeKey(key);
91
+ labels.set(key, label);
92
+ counts.set(label, (counts.get(label) ?? 0) + 1);
93
+ }
94
+ for (const [key, label] of labels) {
95
+ if (counts.get(label) > 1)
96
+ labels.set(key, key);
97
+ }
98
+ return labels;
99
+ }
90
100
  function detailRows(result, depth = 0) {
91
101
  const rows = [];
102
+ const labels = getResultLabels(result);
92
103
  for (const [key, value] of Object.entries(result)) {
93
- const label = `${" ".repeat(depth)}${humanizeKey(key)}`;
104
+ const label = `${" ".repeat(depth)}${labels.get(key)}`;
94
105
  if (isObject(value)) {
95
106
  if (Object.keys(value).length === 0) {
96
107
  rows.push({ label, value: "{}" });
@@ -135,23 +146,23 @@ function stackedList(value) {
135
146
  function displayRowValue(value) {
136
147
  return displayScalar(value);
137
148
  }
138
- function directScalarRows(result) {
149
+ function directScalarRows(result, labels) {
139
150
  return Object.entries(result)
140
151
  .filter(([, value]) => !isObject(value) && !Array.isArray(value))
141
- .map(([key, value]) => ({ label: humanizeKey(key), value: displayRowValue(value) }));
152
+ .map(([key, value]) => ({ label: labels.get(key), value: displayRowValue(value) }));
142
153
  }
143
- function directObjectSections(result) {
154
+ function directObjectSections(result, labels) {
144
155
  return Object.entries(result)
145
156
  .filter(([, value]) => isObject(value))
146
- .map(([key, value]) => ({ title: humanizeKey(key), rows: detailRows(value) }))
157
+ .map(([key, value]) => ({ title: labels.get(key), rows: detailRows(value) }))
147
158
  .filter((section) => section.rows.length > 0);
148
159
  }
149
- function directArrayObjectSections(result) {
160
+ function directArrayObjectSections(result, labels) {
150
161
  return Object.entries(result).flatMap(([key, value]) => {
151
162
  if (!isNonEmptyArrayOfObjects(value)) {
152
163
  return [];
153
164
  }
154
- const title = humanizeKey(key);
165
+ const title = labels.get(key);
155
166
  return value
156
167
  .map((entry, index) => ({
157
168
  title: value.length === 1 ? title : `${title} ${index + 1}`,
@@ -161,12 +172,13 @@ function directArrayObjectSections(result) {
161
172
  });
162
173
  }
163
174
  function renderObjectCard(result, primitives, title) {
164
- const scalarRows = directScalarRows(result);
165
- const nestedSections = directObjectSections(result);
166
- const arrayObjectSections = directArrayObjectSections(result);
175
+ const labels = getResultLabels(result);
176
+ const scalarRows = directScalarRows(result, labels);
177
+ const nestedSections = directObjectSections(result, labels);
178
+ const arrayObjectSections = directArrayObjectSections(result, labels);
167
179
  const listRows = Object.entries(result)
168
180
  .filter(([, value]) => Array.isArray(value) && !isNonEmptyArrayOfObjects(value))
169
- .map(([key, value]) => ({ label: humanizeKey(key), value: stackedList(value) }));
181
+ .map(([key, value]) => ({ label: labels.get(key), value: stackedList(value) }));
170
182
  return renderDetailCard({
171
183
  theme: primitives.getTheme(),
172
184
  title,
@@ -304,9 +316,8 @@ export function renderResult(command, result, output, primitives, write = (chunk
304
316
  process.stdout.write(chunk);
305
317
  }) {
306
318
  const unwrapped = unwrapMcpEnvelope(result);
307
- result = unwrapped.result;
308
319
  if (unwrapped.mcpError) {
309
- const payload = autoRender(command, result, output, primitives);
320
+ const payload = autoRender(command, unwrapped.result, output, primitives);
310
321
  if (payload.length > 0) {
311
322
  write(`${payload}\n`, "stderr");
312
323
  }
@@ -330,7 +341,7 @@ export function renderResult(command, result, output, primitives, write = (chunk
330
341
  command.render.rich(result, primitives);
331
342
  return { mcpError: false };
332
343
  }
333
- const payload = autoRender(command, result, output, primitives);
344
+ const payload = autoRender(command, unwrapped.result, output, primitives);
334
345
  if (payload.length > 0) {
335
346
  write(`${payload}\n`);
336
347
  }
@@ -0,0 +1,2 @@
1
+ import type { AnySchema } from "toolcraft-schema";
2
+ export declare function validateCasedSchemaMembers(schema: AnySchema, formatMember: (key: string) => string, surface: "SDK member" | "MCP field", discriminator?: string): void;
@@ -0,0 +1,39 @@
1
+ import { UserError } from "./user-error.js";
2
+ export function validateCasedSchemaMembers(schema, formatMember, surface, discriminator) {
3
+ switch (schema.kind) {
4
+ case "optional":
5
+ validateCasedSchemaMembers(schema.inner, formatMember, surface, discriminator);
6
+ return;
7
+ case "array":
8
+ validateCasedSchemaMembers(schema.item, formatMember, surface);
9
+ return;
10
+ case "record":
11
+ validateCasedSchemaMembers(schema.value, formatMember, surface);
12
+ return;
13
+ case "union":
14
+ for (const branch of schema.branches) {
15
+ validateCasedSchemaMembers(branch, formatMember, surface);
16
+ }
17
+ return;
18
+ case "oneOf":
19
+ for (const branch of Object.values(schema.branches)) {
20
+ validateCasedSchemaMembers(branch, formatMember, surface, schema.discriminator);
21
+ }
22
+ return;
23
+ case "object": {
24
+ const sourceKeysByMember = new Map();
25
+ if (discriminator !== undefined) {
26
+ sourceKeysByMember.set(formatMember(discriminator), discriminator);
27
+ }
28
+ for (const [key, child] of Object.entries(schema.shape)) {
29
+ const member = formatMember(key);
30
+ const existingKey = sourceKeysByMember.get(member);
31
+ if (existingKey !== undefined) {
32
+ throw new UserError(`Parameters "${existingKey}" and "${key}" use conflicting ${surface} "${member}".`);
33
+ }
34
+ sourceKeysByMember.set(member, key);
35
+ validateCasedSchemaMembers(child, formatMember, surface);
36
+ }
37
+ }
38
+ }
39
+ }
@@ -1,4 +1,5 @@
1
1
  import type { AnySchema } from "toolcraft-schema";
2
2
  type SchemaScope = "cli" | "mcp" | "sdk";
3
3
  export declare function filterSchemaForScope(schema: AnySchema, scope: SchemaScope): AnySchema | undefined;
4
+ export declare function getUnfilteredSchema(schema: AnySchema): AnySchema;
4
5
  export {};
@@ -1,4 +1,15 @@
1
+ const unfilteredSchemas = new WeakMap();
1
2
  export function filterSchemaForScope(schema, scope) {
3
+ const filtered = filterScopedSchema(schema, scope);
4
+ if (filtered !== undefined && filtered !== schema && schema.kind !== "optional") {
5
+ unfilteredSchemas.set(filtered, unfilteredSchemas.get(schema) ?? schema);
6
+ }
7
+ return filtered;
8
+ }
9
+ export function getUnfilteredSchema(schema) {
10
+ return unfilteredSchemas.get(schema) ?? schema;
11
+ }
12
+ function filterScopedSchema(schema, scope) {
2
13
  if (schema.scope !== undefined && !schema.scope.includes(scope)) {
3
14
  return undefined;
4
15
  }
@@ -27,22 +38,24 @@ export function filterSchemaForScope(schema, scope) {
27
38
  const value = filterSchemaForScope(schema.value, scope);
28
39
  return value === undefined ? undefined : { ...schema, value };
29
40
  }
30
- case "oneOf":
31
- return {
32
- ...schema,
33
- branches: Object.fromEntries(Object.entries(schema.branches).flatMap(([name, branch]) => {
34
- const filtered = filterSchemaForScope(branch, scope);
35
- return filtered?.kind === "object" ? [[name, filtered]] : [];
36
- }))
37
- };
38
- case "union":
39
- return {
40
- ...schema,
41
- branches: schema.branches.flatMap((branch) => {
42
- const filtered = filterSchemaForScope(branch, scope);
43
- return filtered?.kind === "object" ? [filtered] : [];
44
- })
45
- };
41
+ case "oneOf": {
42
+ const branches = Object.fromEntries(Object.entries(schema.branches).flatMap(([name, branch]) => {
43
+ const filtered = filterSchemaForScope(branch, scope);
44
+ return filtered?.kind === "object" ? [[name, filtered]] : [];
45
+ }));
46
+ return Object.keys(branches).length === 0 && schema.nullable !== true
47
+ ? undefined
48
+ : { ...schema, branches };
49
+ }
50
+ case "union": {
51
+ const branches = schema.branches.flatMap((branch) => {
52
+ const filtered = filterSchemaForScope(branch, scope);
53
+ return filtered?.kind === "object" ? [filtered] : [];
54
+ });
55
+ return branches.length === 0 && schema.nullable !== true
56
+ ? undefined
57
+ : { ...schema, branches };
58
+ }
46
59
  case "object":
47
60
  return {
48
61
  ...schema,
package/dist/schema.d.ts CHANGED
@@ -1,2 +1,2 @@
1
1
  export { Json, OneOf, Record, S, Union, toJsonSchema, toJsonSchemaDocument, validate } from "toolcraft-schema";
2
- export type { AnySchema, ArraySchema, BooleanSchema, CliMissingParameterChoice, CliMissingParameterContext, CliMissingParameterResolution, CliOutputMode, CliSchemaOptions, EnumSchema, JsonSchema, JsonSchemaDocument, JsonSchemaDocumentOptions, JsonValue, JsonValueSchema, NumberSchema, ObjectSchema, OneOfSchema, OptionalSchema, RecordSchema, SchemaBase, Static, StringSchema, UnionSchema, ValidationIssue, ValidationResult } from "toolcraft-schema";
2
+ export type { AnySchema, ArraySchema, BooleanSchema, CliMissingParameterChoice, CliMissingParameterContext, CliMissingParameterResolution, CliOutputMode, CliSchemaOptions, EnumSchema, JsonSchema, JsonSchemaDocument, JsonSchemaDocumentOptions, JsonValue, JsonValueSchema, NumberSchema, ObjectSchema, OneOfSchema, OptionalSchema, RecordSchema, SchemaBase, Static, StringSchema, UnionSchema, ValidationIssue, ValidationOptions, ValidationResult } from "toolcraft-schema";
package/dist/sdk.d.ts CHANGED
@@ -3,8 +3,10 @@ import type { ObjectSchema, Static } from "toolcraft-schema";
3
3
  import type { Group, HandlerFs, LogLevel, RuntimeLoggerInput, Scope } from "./index.js";
4
4
  import { type ErrorReportsOption } from "./error-report.js";
5
5
  import type { HumanInLoopPending, HumanInLoopRuntime } from "./human-in-loop/types.js";
6
+ import { mergeApprovalsRoot } from "./human-in-loop/wiring.js";
6
7
  import { type ValidationError } from "./validation-errors.js";
7
8
  import type { StreamConsumerOptions, ToolcraftStream } from "./stream.js";
9
+ export { mergeApprovalsRoot };
8
10
  type ScopeInput = readonly Scope[] | undefined;
9
11
  type HumanInLoopMode = "sync" | "async";
10
12
  type HumanInLoopModeInput = HumanInLoopMode | null | undefined;
@@ -86,4 +88,3 @@ type SDKRootShape<TRoot> = TRoot extends {
86
88
  };
87
89
  } ? SDKChildrenShape<TChildren, undefined, undefined> : Record<string, unknown>;
88
90
  export declare function createSDK<TRoot extends Group<any>, TServices extends object = Record<string, unknown>>(root: TRoot, options?: CreateSDKOptions<TServices>): SDKRootShape<TRoot>;
89
- export {};