stitchkit 0.90.2 → 0.90.4

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 (57) hide show
  1. package/CHANGELOG.md +129 -0
  2. package/dist/agent-runtime-coding-tools.js +3 -3
  3. package/dist/agent-runtime-harness.js +4 -4
  4. package/dist/agent-runtime-sandbox.js +3 -3
  5. package/dist/agent-runtime.js +7 -7
  6. package/dist/cli.d.ts +14 -1
  7. package/dist/cli.d.ts.map +1 -1
  8. package/dist/cli.js +359 -11
  9. package/dist/{index-gbqjt8jz.js → index-19ryv24q.js} +3 -3
  10. package/dist/{index-2hrfpw2c.js → index-32vjke6q.js} +2 -2
  11. package/dist/{index-f475yj00.js → index-6atvfjc1.js} +1 -1
  12. package/dist/{index-79hb1wyh.js → index-7t0wq6j5.js} +3 -3
  13. package/dist/{index-j7q0xj6d.js → index-8crm1srv.js} +1 -1
  14. package/dist/{index-kc6h6hg0.js → index-8z9we758.js} +1 -1
  15. package/dist/{index-r159gjwy.js → index-fenaekmk.js} +94 -8
  16. package/dist/{index-wb15909q.js → index-kzxpsf8y.js} +3 -3
  17. package/dist/{index-44ht2790.js → index-vcnfwrtr.js} +1 -1
  18. package/dist/{index-8dph3pw6.js → index-y47z614h.js} +405 -35
  19. package/dist/testing.js +1 -1
  20. package/dist/tool-invoker.js +4 -4
  21. package/dist/tools/cli-args.d.ts +49 -0
  22. package/dist/tools/cli-args.d.ts.map +1 -1
  23. package/dist/tools/cli-command.d.ts +8 -1
  24. package/dist/tools/cli-command.d.ts.map +1 -1
  25. package/dist/tools/cli-installer.d.ts +29 -0
  26. package/dist/tools/cli-installer.d.ts.map +1 -0
  27. package/dist/tools/cli-manifest.d.ts +83 -0
  28. package/dist/tools/cli-manifest.d.ts.map +1 -0
  29. package/dist/tools/cli-policy.d.ts +6 -1
  30. package/dist/tools/cli-policy.d.ts.map +1 -1
  31. package/dist/tools/cli-profile.d.ts +40 -0
  32. package/dist/tools/cli-profile.d.ts.map +1 -0
  33. package/dist/tools/cli-update.d.ts +64 -0
  34. package/dist/tools/cli-update.d.ts.map +1 -0
  35. package/dist/tools/cli-view.d.ts +12 -0
  36. package/dist/tools/cli-view.d.ts.map +1 -0
  37. package/dist/tools/cli.d.ts +20 -5
  38. package/dist/tools/cli.d.ts.map +1 -1
  39. package/dist/tools/connections/index.d.ts +2 -1
  40. package/dist/tools/connections/index.d.ts.map +1 -1
  41. package/dist/tools/connections/index.js +37 -10
  42. package/dist/tools/connections/mcp.d.ts +2 -1
  43. package/dist/tools/connections/mcp.d.ts.map +1 -1
  44. package/dist/tools/connections/mount.d.ts.map +1 -1
  45. package/dist/tools/connections/openapi.d.ts +2 -1
  46. package/dist/tools/connections/openapi.d.ts.map +1 -1
  47. package/dist/tools/connections/runtime.d.ts +17 -0
  48. package/dist/tools/connections/runtime.d.ts.map +1 -1
  49. package/dist/tools/connections/types.d.ts +18 -1
  50. package/dist/tools/connections/types.d.ts.map +1 -1
  51. package/dist/tools/json-schema-dialect.d.ts +17 -0
  52. package/dist/tools/json-schema-dialect.d.ts.map +1 -0
  53. package/dist/tools/presentation.d.ts +8 -1
  54. package/dist/tools/presentation.d.ts.map +1 -1
  55. package/dist/tools.js +8 -8
  56. package/llms-full.txt +293 -7
  57. package/package.json +1 -1
@@ -1,5 +1,6 @@
1
1
  import { type RuntimeToolDefinition } from '../runtime-tool.js';
2
+ import { type ConnectionToolSkipReporter } from './runtime.js';
2
3
  import type { McpClientConnection } from './types.js';
3
4
  /** Discover and mount every tool one MCP connection exposes. */
4
- export declare function mountMcpConnection(connection: McpClientConnection, instanceId: string): Promise<RuntimeToolDefinition[]>;
5
+ export declare function mountMcpConnection(connection: McpClientConnection, instanceId: string, onSkipped: ConnectionToolSkipReporter): Promise<RuntimeToolDefinition[]>;
5
6
  //# sourceMappingURL=mcp.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"mcp.d.ts","sourceRoot":"","sources":["../../../src/tools/connections/mcp.ts"],"names":[],"mappings":"AAEA,OAAO,EAAqB,KAAK,qBAAqB,EAAE,MAAM,iBAAiB,CAAC;AAMhF,OAAO,KAAK,EAAE,mBAAmB,EAAiB,MAAM,SAAS,CAAC;AAQlE,gEAAgE;AAChE,wBAAsB,kBAAkB,CACtC,UAAU,EAAE,mBAAmB,EAC/B,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC,qBAAqB,EAAE,CAAC,CAyDlC"}
1
+ {"version":3,"file":"mcp.d.ts","sourceRoot":"","sources":["../../../src/tools/connections/mcp.ts"],"names":[],"mappings":"AAEA,OAAO,EAAqB,KAAK,qBAAqB,EAAE,MAAM,iBAAiB,CAAC;AAGhF,OAAO,EACL,KAAK,0BAA0B,EAIhC,MAAM,WAAW,CAAC;AAGnB,OAAO,KAAK,EAAE,mBAAmB,EAAiB,MAAM,SAAS,CAAC;AAQlE,gEAAgE;AAChE,wBAAsB,kBAAkB,CACtC,UAAU,EAAE,mBAAmB,EAC/B,UAAU,EAAE,MAAM,EAClB,SAAS,EAAE,0BAA0B,GACpC,OAAO,CAAC,qBAAqB,EAAE,CAAC,CAgElC"}
@@ -1 +1 @@
1
- {"version":3,"file":"mount.d.ts","sourceRoot":"","sources":["../../../src/tools/connections/mount.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,iBAAiB,CAAC;AAM7D,OAAO,KAAK,EAAE,oBAAoB,EAAE,sBAAsB,EAAE,MAAM,SAAS,CAAC;AAE5E;;;;;;;GAOG;AACH,wBAAsB,gBAAgB,CACpC,WAAW,EAAE,SAAS,oBAAoB,EAAE,EAC5C,OAAO,GAAE,sBAA2B,GACnC,OAAO,CAAC,SAAS,qBAAqB,EAAE,CAAC,CAsB3C"}
1
+ {"version":3,"file":"mount.d.ts","sourceRoot":"","sources":["../../../src/tools/connections/mount.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,iBAAiB,CAAC;AAO7D,OAAO,KAAK,EAAE,oBAAoB,EAAE,sBAAsB,EAAE,MAAM,SAAS,CAAC;AAE5E;;;;;;;GAOG;AACH,wBAAsB,gBAAgB,CACpC,WAAW,EAAE,SAAS,oBAAoB,EAAE,EAC5C,OAAO,GAAE,sBAA2B,GACnC,OAAO,CAAC,SAAS,qBAAqB,EAAE,CAAC,CAuB3C"}
@@ -1,5 +1,6 @@
1
1
  import { type RuntimeToolDefinition } from '../runtime-tool.js';
2
+ import { type ConnectionToolSkipReporter } from './runtime.js';
2
3
  import type { OpenApiConnection } from './types.js';
3
4
  /** Load and mount every operation of one OpenAPI document. */
4
- export declare function mountOpenApiConnection(connection: OpenApiConnection, instanceId: string): Promise<RuntimeToolDefinition[]>;
5
+ export declare function mountOpenApiConnection(connection: OpenApiConnection, instanceId: string, onSkipped: ConnectionToolSkipReporter): Promise<RuntimeToolDefinition[]>;
5
6
  //# sourceMappingURL=openapi.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"openapi.d.ts","sourceRoot":"","sources":["../../../src/tools/connections/openapi.ts"],"names":[],"mappings":"AAGA,OAAO,EAAqB,KAAK,qBAAqB,EAAE,MAAM,iBAAiB,CAAC;AAchF,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAC;AAgBjD,8DAA8D;AAC9D,wBAAsB,sBAAsB,CAC1C,UAAU,EAAE,iBAAiB,EAC7B,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC,qBAAqB,EAAE,CAAC,CAkGlC"}
1
+ {"version":3,"file":"openapi.d.ts","sourceRoot":"","sources":["../../../src/tools/connections/openapi.ts"],"names":[],"mappings":"AAGA,OAAO,EAAqB,KAAK,qBAAqB,EAAE,MAAM,iBAAiB,CAAC;AAWhF,OAAO,EACL,KAAK,0BAA0B,EAKhC,MAAM,WAAW,CAAC;AAGnB,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAC;AAgBjD,8DAA8D;AAC9D,wBAAsB,sBAAsB,CAC1C,UAAU,EAAE,iBAAiB,EAC7B,UAAU,EAAE,MAAM,EAClB,SAAS,EAAE,0BAA0B,GACpC,OAAO,CAAC,qBAAqB,EAAE,CAAC,CA4GlC"}
@@ -1,5 +1,6 @@
1
1
  import { type ZodObject } from 'zod';
2
2
  import type { RuntimeContext } from '../../contract/index.js';
3
+ import type { RuntimeToolDefinition } from '../runtime-tool.js';
3
4
  /** A connection's optional principal-scoped credential resolver. */
4
5
  export type ConnectionTokenProvider = (context?: RuntimeContext) => string | undefined | Promise<string | undefined>;
5
6
  interface TeardownTarget {
@@ -25,5 +26,21 @@ export declare function withConnectionToken<T>(params: {
25
26
  export declare function zodObjectFromJsonSchema(schema: Record<string, unknown> | undefined): ZodObject;
26
27
  /** Normalise a tool name into the characters every provider accepts. */
27
28
  export declare function sanitizeToolName(value: string): string;
29
+ /** One discovered tool the mount could not turn into a definition. */
30
+ export interface SkippedConnectionTool {
31
+ connection: string;
32
+ tool: string;
33
+ reason: string;
34
+ }
35
+ export type ConnectionToolSkipReporter = (skipped: SkippedConnectionTool) => void;
36
+ /** Default report: name the tool and the reason, and keep the connection. */
37
+ export declare function reportSkippedConnectionTool(skipped: SkippedConnectionTool): void;
38
+ /**
39
+ * Build one definition per discovered entry, surviving the ones that cannot be
40
+ * built. A mount is all-or-nothing only if it is written that way, and a foreign
41
+ * surface of two hundred tools should not be lost to one unconvertible schema —
42
+ * the refusal is reported and named, which is what a caller can act on.
43
+ */
44
+ export declare function mountToolsTolerantly<TEntry>(entries: readonly TEntry[], connection: string, nameOf: (entry: TEntry) => string, build: (entry: TEntry) => RuntimeToolDefinition, onSkipped: ConnectionToolSkipReporter): RuntimeToolDefinition[];
28
45
  export {};
29
46
  //# sourceMappingURL=runtime.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../../../src/tools/connections/runtime.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,SAAS,EAAK,MAAM,KAAK,CAAC;AACxC,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAGrD,oEAAoE;AACpE,MAAM,MAAM,uBAAuB,GAAG,CACpC,OAAO,CAAC,EAAE,cAAc,KACrB,MAAM,GAAG,SAAS,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAAC;AAEtD,UAAU,cAAc;IACtB,QAAQ,IAAI,IAAI,CAAC;CAClB;AAED;;;;GAIG;AACH,wBAAsB,mBAAmB,CAAC,CAAC,EACzC,MAAM,EAAE;IACN,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,uBAAuB,CAAC;IACnC,MAAM,CAAC,EAAE,cAAc,CAAC;IACxB,OAAO,CAAC,EAAE,cAAc,CAAC;CAC1B,EACD,IAAI,EAAE,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,KAAK,OAAO,CAAC,CAAC,CAAC,GAC9C,OAAO,CAAC,CAAC,CAAC,CAUZ;AAED;;;;;GAKG;AACH,wBAAgB,uBAAuB,CACrC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,GAC1C,SAAS,CAKX;AAED,wEAAwE;AACxE,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAEtD"}
1
+ {"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../../../src/tools/connections/runtime.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,SAAS,EAAK,MAAM,KAAK,CAAC;AACxC,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAErD,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,iBAAiB,CAAC;AAG7D,oEAAoE;AACpE,MAAM,MAAM,uBAAuB,GAAG,CACpC,OAAO,CAAC,EAAE,cAAc,KACrB,MAAM,GAAG,SAAS,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAAC;AAEtD,UAAU,cAAc;IACtB,QAAQ,IAAI,IAAI,CAAC;CAClB;AAED;;;;GAIG;AACH,wBAAsB,mBAAmB,CAAC,CAAC,EACzC,MAAM,EAAE;IACN,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,uBAAuB,CAAC;IACnC,MAAM,CAAC,EAAE,cAAc,CAAC;IACxB,OAAO,CAAC,EAAE,cAAc,CAAC;CAC1B,EACD,IAAI,EAAE,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,KAAK,OAAO,CAAC,CAAC,CAAC,GAC9C,OAAO,CAAC,CAAC,CAAC,CAUZ;AAED;;;;;GAKG;AACH,wBAAgB,uBAAuB,CACrC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,GAC1C,SAAS,CAKX;AAcD,wEAAwE;AACxE,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAEtD;AAED,sEAAsE;AACtE,MAAM,WAAW,qBAAqB;IACpC,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,MAAM,0BAA0B,GAAG,CAAC,OAAO,EAAE,qBAAqB,KAAK,IAAI,CAAC;AAElF,6EAA6E;AAC7E,wBAAgB,2BAA2B,CAAC,OAAO,EAAE,qBAAqB,GAAG,IAAI,CAIhF;AAED;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EACzC,OAAO,EAAE,SAAS,MAAM,EAAE,EAC1B,UAAU,EAAE,MAAM,EAClB,MAAM,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,EACjC,KAAK,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,qBAAqB,EAC/C,SAAS,EAAE,0BAA0B,GACpC,qBAAqB,EAAE,CAczB"}
@@ -1,4 +1,5 @@
1
- import type { ConnectionTokenProvider } from './runtime.js';
1
+ import type { RuntimeToolTransport } from '../runtime-tool.js';
2
+ import type { ConnectionTokenProvider, ConnectionToolSkipReporter } from './runtime.js';
2
3
  /** Where one external MCP server lives, plus static request headers. */
3
4
  export interface McpConnectionTransport {
4
5
  url: string;
@@ -23,6 +24,14 @@ export interface McpClientConnectionConfig {
23
24
  timeoutMs?: number;
24
25
  /** Response body ceiling in bytes; defaults to 1 MiB. */
25
26
  maxResponseBytes?: number;
27
+ /**
28
+ * Which surfaces this server's discovered tools appear on; default MCP and
29
+ * AGENT. Naming `['CLI']` is how a whole server becomes a set of commands,
30
+ * without the consumer rebuilding each discovered definition — and a
31
+ * connection without it contributes nothing to the CLI, because CLI exposure
32
+ * is explicit everywhere else in the framework too.
33
+ */
34
+ transports?: readonly RuntimeToolTransport[];
26
35
  }
27
36
  /** A defined MCP connection. */
28
37
  export interface McpClientConnection extends McpClientConnectionConfig {
@@ -40,6 +49,8 @@ export interface OpenApiConnectionConfig {
40
49
  timeoutMs?: number;
41
50
  /** Response body ceiling in bytes; defaults to 1 MiB. */
42
51
  maxResponseBytes?: number;
52
+ /** Which surfaces every mounted operation appears on; default MCP and AGENT. */
53
+ transports?: readonly RuntimeToolTransport[];
43
54
  }
44
55
  /** A defined OpenAPI connection. */
45
56
  export interface OpenApiConnection extends OpenApiConnectionConfig {
@@ -56,5 +67,11 @@ export interface ConnectionBudget {
56
67
  /** Shared mount policy for every connection in one call. */
57
68
  export interface ConnectionMountOptions {
58
69
  budget?: ConnectionBudget;
70
+ /**
71
+ * Called for each discovered tool that could not be mounted. Defaults to a
72
+ * stderr line naming the connection, the tool and the reason; the rest of the
73
+ * surface is mounted either way.
74
+ */
75
+ onSkippedTool?: ConnectionToolSkipReporter;
59
76
  }
60
77
  //# sourceMappingURL=types.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/tools/connections/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,WAAW,CAAC;AAEzD,wEAAwE;AACxE,MAAM,WAAW,sBAAsB;IACrC,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAClC;AAED,+EAA+E;AAC/E,MAAM,WAAW,aAAa;IAC5B,KAAK,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC1B,KAAK,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CAC3B;AAED,+DAA+D;AAC/D,MAAM,WAAW,yBAAyB;IACxC,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,sBAAsB,CAAC;IAClC,KAAK,CAAC,EAAE,aAAa,CAAC;IACtB,KAAK,CAAC,EAAE,uBAAuB,CAAC;IAChC,mFAAmF;IACnF,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,4EAA4E;IAC5E,UAAU,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC/B,gEAAgE;IAChE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,yDAAyD;IACzD,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED,gCAAgC;AAChC,MAAM,WAAW,mBAAoB,SAAQ,yBAAyB;IACpE,IAAI,EAAE,KAAK,CAAC;CACb;AAED,kFAAkF;AAClF,MAAM,WAAW,uBAAuB;IACtC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC;IACtB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,uBAAuB,CAAC;IAChC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC/B,gEAAgE;IAChE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,yDAAyD;IACzD,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED,oCAAoC;AACpC,MAAM,WAAW,iBAAkB,SAAQ,uBAAuB;IAChE,IAAI,EAAE,SAAS,CAAC;CACjB;AAED,mEAAmE;AACnE,MAAM,MAAM,oBAAoB,GAAG,mBAAmB,GAAG,iBAAiB,CAAC;AAE3E,wEAAwE;AACxE,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,6EAA6E;IAC7E,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,4DAA4D;AAC5D,MAAM,WAAW,sBAAsB;IACrC,MAAM,CAAC,EAAE,gBAAgB,CAAC;CAC3B"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/tools/connections/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,iBAAiB,CAAC;AAC5D,OAAO,KAAK,EAAE,uBAAuB,EAAE,0BAA0B,EAAE,MAAM,WAAW,CAAC;AAErF,wEAAwE;AACxE,MAAM,WAAW,sBAAsB;IACrC,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAClC;AAED,+EAA+E;AAC/E,MAAM,WAAW,aAAa;IAC5B,KAAK,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC1B,KAAK,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CAC3B;AAED,+DAA+D;AAC/D,MAAM,WAAW,yBAAyB;IACxC,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,sBAAsB,CAAC;IAClC,KAAK,CAAC,EAAE,aAAa,CAAC;IACtB,KAAK,CAAC,EAAE,uBAAuB,CAAC;IAChC,mFAAmF;IACnF,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,4EAA4E;IAC5E,UAAU,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC/B,gEAAgE;IAChE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,yDAAyD;IACzD,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B;;;;;;OAMG;IACH,UAAU,CAAC,EAAE,SAAS,oBAAoB,EAAE,CAAC;CAC9C;AAED,gCAAgC;AAChC,MAAM,WAAW,mBAAoB,SAAQ,yBAAyB;IACpE,IAAI,EAAE,KAAK,CAAC;CACb;AAED,kFAAkF;AAClF,MAAM,WAAW,uBAAuB;IACtC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC;IACtB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,uBAAuB,CAAC;IAChC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC/B,gEAAgE;IAChE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,yDAAyD;IACzD,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,gFAAgF;IAChF,UAAU,CAAC,EAAE,SAAS,oBAAoB,EAAE,CAAC;CAC9C;AAED,oCAAoC;AACpC,MAAM,WAAW,iBAAkB,SAAQ,uBAAuB;IAChE,IAAI,EAAE,SAAS,CAAC;CACjB;AAED,mEAAmE;AACnE,MAAM,MAAM,oBAAoB,GAAG,mBAAmB,GAAG,iBAAiB,CAAC;AAE3E,wEAAwE;AACxE,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,6EAA6E;IAC7E,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,4DAA4D;AAC5D,MAAM,WAAW,sBAAsB;IACrC,MAAM,CAAC,EAAE,gBAAgB,CAAC;IAC1B;;;;OAIG;IACH,aAAa,CAAC,EAAE,0BAA0B,CAAC;CAC5C"}
@@ -0,0 +1,17 @@
1
+ /** True when a document says, in its own `$schema`, that it is draft-07. */
2
+ export declare function declaresDraft07(dialect: unknown): boolean;
3
+ /**
4
+ * Move a document's top-level `definitions` to `$defs`, carrying its pointers.
5
+ *
6
+ * A JSON Schema document that names one dialect and uses another's keyword is
7
+ * not a style question: a reader registers reusable subschemas from the keyword
8
+ * the dialect declares and then cannot resolve `#/definitions/x` at all. Both
9
+ * halves of this framework met that document — the MCP SDK stamps 2020-12 onto
10
+ * the metadata it is handed, and our own MCP client obeyed the stamp.
11
+ *
12
+ * Only the top level moves. A `definitions` deeper in the document may be a
13
+ * property literally called "definitions", and guessing which is worse than
14
+ * leaving it where the author put it.
15
+ */
16
+ export declare function withDefsDialect(schema: Record<string, unknown>): Record<string, unknown>;
17
+ //# sourceMappingURL=json-schema-dialect.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"json-schema-dialect.d.ts","sourceRoot":"","sources":["../../src/tools/json-schema-dialect.ts"],"names":[],"mappings":"AAQA,4EAA4E;AAC5E,wBAAgB,eAAe,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAEzD;AAeD;;;;;;;;;;;;GAYG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAUxF"}
@@ -10,6 +10,13 @@ export interface ToolPresentationConfig {
10
10
  /** Build the one model-facing document shared by MCP, agents and manifests. */
11
11
  export declare function buildToolPresentationSchema(config: ToolPresentationConfig): ToolPresentationSchema;
12
12
  export declare function isObjectPresentationSchema(schema: ToolPresentationSchema): boolean;
13
- /** Metadata passed to the Zod identity carrier; the SDK supplies its own dialect. */
13
+ /**
14
+ * Metadata passed to the Zod identity carrier.
15
+ *
16
+ * The SDK supplies its own dialect and it is 2020-12, so the document has to
17
+ * speak 2020-12: a draft-07 `definitions` block under a 2020-12 `$schema` is a
18
+ * document that says one thing and does another, and a client that believes the
19
+ * stamp cannot resolve a single `#/definitions/...` pointer in it.
20
+ */
14
21
  export declare function presentationMetadata(schema: ToolPresentationSchema): ToolPresentationSchema;
15
22
  //# sourceMappingURL=presentation.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"presentation.d.ts","sourceRoot":"","sources":["../../src/tools/presentation.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAGL,KAAK,sBAAsB,EAC5B,MAAM,WAAW,CAAC;AAGnB,MAAM,WAAW,sBAAsB;IACrC,YAAY,CAAC,EAAE,CAAC,CAAC,OAAO,CAAC;IACzB,WAAW,CAAC,EAAE,CAAC,CAAC,OAAO,CAAC;IACxB,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC;IACzC,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,eAAe,CAAC,EAAE,OAAO,GAAG,KAAK,CAAC;CACnC;AA+FD,+EAA+E;AAC/E,wBAAgB,2BAA2B,CACzC,MAAM,EAAE,sBAAsB,GAC7B,sBAAsB,CAgDxB;AAED,wBAAgB,0BAA0B,CAAC,MAAM,EAAE,sBAAsB,GAAG,OAAO,CAElF;AAED,qFAAqF;AACrF,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,sBAAsB,GAAG,sBAAsB,CAE3F"}
1
+ {"version":3,"file":"presentation.d.ts","sourceRoot":"","sources":["../../src/tools/presentation.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAGL,KAAK,sBAAsB,EAC5B,MAAM,WAAW,CAAC;AAInB,MAAM,WAAW,sBAAsB;IACrC,YAAY,CAAC,EAAE,CAAC,CAAC,OAAO,CAAC;IACzB,WAAW,CAAC,EAAE,CAAC,CAAC,OAAO,CAAC;IACxB,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC;IACzC,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,eAAe,CAAC,EAAE,OAAO,GAAG,KAAK,CAAC;CACnC;AA+KD,+EAA+E;AAC/E,wBAAgB,2BAA2B,CACzC,MAAM,EAAE,sBAAsB,GAC7B,sBAAsB,CAgDxB;AAED,wBAAgB,0BAA0B,CAAC,MAAM,EAAE,sBAAsB,GAAG,OAAO,CAElF;AAED;;;;;;;GAOG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,sBAAsB,GAAG,sBAAsB,CAE3F"}
package/dist/tools.js CHANGED
@@ -21,7 +21,7 @@ import {
21
21
  buildToolManifest,
22
22
  describeToolCatalog,
23
23
  mountAgent
24
- } from "./index-gbqjt8jz.js";
24
+ } from "./index-19ryv24q.js";
25
25
  import"./index-7rkhw9ec.js";
26
26
  import {
27
27
  argumentsDigest
@@ -37,7 +37,7 @@ import {
37
37
  } from "./index-4fpa9dy2.js";
38
38
  import {
39
39
  createToolInvoker
40
- } from "./index-79hb1wyh.js";
40
+ } from "./index-7t0wq6j5.js";
41
41
  import {
42
42
  WaitTimeoutError,
43
43
  createCli,
@@ -46,22 +46,22 @@ import {
46
46
  fetchPinnedDocument,
47
47
  readCapped,
48
48
  runWaitOperation
49
- } from "./index-8dph3pw6.js";
49
+ } from "./index-y47z614h.js";
50
50
  import"./index-sbdmyz75.js";
51
51
  import {
52
52
  collectToolSurface
53
- } from "./index-wb15909q.js";
53
+ } from "./index-kzxpsf8y.js";
54
54
  import {
55
55
  collectTools,
56
56
  createToolRunner,
57
57
  formatToolError
58
- } from "./index-2hrfpw2c.js";
58
+ } from "./index-32vjke6q.js";
59
59
  import {
60
60
  ToolExecutionControlError,
61
61
  executeToolMethod,
62
62
  isToolExecutionControlError,
63
63
  toolResultFromError
64
- } from "./index-44ht2790.js";
64
+ } from "./index-vcnfwrtr.js";
65
65
  import {
66
66
  getRequestContext,
67
67
  getTraceId,
@@ -92,7 +92,7 @@ import"./index-kzfs85xp.js";
92
92
  import {
93
93
  createRuntimeToolFactory,
94
94
  defineRuntimeTool
95
- } from "./index-kc6h6hg0.js";
95
+ } from "./index-8z9we758.js";
96
96
  import {
97
97
  PORTABLE_JSON_SCHEMA_FORMATS,
98
98
  assertToolName,
@@ -103,7 +103,7 @@ import {
103
103
  prepareProjectedMcpTools,
104
104
  presentationMetadata,
105
105
  validateMcpRoundPolicy
106
- } from "./index-r159gjwy.js";
106
+ } from "./index-fenaekmk.js";
107
107
  import"./index-cby4ar3v.js";
108
108
  import {
109
109
  isRecord
package/llms-full.txt CHANGED
@@ -7443,6 +7443,30 @@ command schema. `-f` / `-f=false` are boolean forms; values accept `-n 100` and
7443
7443
  bundles such as `-fn`, attached values such as `-n100`, `--no-f` and unknown
7444
7444
  short flags are rejected. Canonical `--no-follow` remains available.
7445
7445
 
7446
+ ### A trailing list
7447
+
7448
+ When the LAST declared positional is an array field, it takes every remaining
7449
+ token, each coerced by the array's element type:
7450
+
7451
+ ```ts
7452
+ positionals: { handoff: ['to', 'files'] } // files: z.array(z.string())
7453
+ ```
7454
+
7455
+ ```
7456
+ myapp handoff proj a.md b.md → { to: 'proj', files: ['a.md', 'b.md'] }
7457
+ myapp handoff proj a.md → { to: 'proj', files: ['a.md'] }
7458
+ ```
7459
+
7460
+ One token is a one-element list, not a scalar, so the parsed shape never depends
7461
+ on how many a caller happened to pass. Command help marks it:
7462
+ `Usage: myapp handoff <to> <files...>`. The flag form still works
7463
+ (`--files '["a.md","b.md"]'`, or a repeated `--files`) — but passing both forms
7464
+ in one call is an argument error rather than a silent merge.
7465
+
7466
+ Only the trailing position is variadic. An array declared anywhere else in the
7467
+ list keeps taking exactly one token (a JSON array), and its help stays `<tags>`,
7468
+ so the usage line always says which field is the list.
7469
+
7446
7470
  `positionals` replaces automatic schema-order selection only for the named
7447
7471
  command. An empty array disables argv positionals. Fields remain available as
7448
7472
  long/short options and stdin still fills the first required unset field with the
@@ -7465,6 +7489,10 @@ same Zod schema an HTTP or MCP call does.
7465
7489
  | `--quiet` | Suppress non-essential stderr output |
7466
7490
  | `--dry-run` | Print the resolved call without executing |
7467
7491
  | `--help`, `-h` | Usage — top-level or per-command flag table |
7492
+ | `--count-by <field>` | Count records per distinct value — see [Aggregate views](#aggregate-views) |
7493
+ | `--sum <f> [--by <g>]`| Total a numeric field, optionally grouped |
7494
+ | `--top <n> --by <f>` | Keep only the n largest groups |
7495
+ | `--table <a,b>` | Render named fields as an aligned table |
7468
7496
 
7469
7497
  stdout carries the result; structured errors and progress go to stderr. With
7470
7498
  `--json`, a success or structured failure is exactly one compact,
@@ -7474,6 +7502,68 @@ diagnostics remain ordinary stderr text. This keeps stdout pipeable and
7474
7502
  `VALIDATION_ERROR → 1`, `UNAUTHORIZED → 2`, `FORBIDDEN → 3`, `NOT_FOUND → 4`,
7475
7503
  …) — override per app with `exitCodes`.
7476
7504
 
7505
+ ## Application global options
7506
+
7507
+ `--json` and friends above are the framework's. An application usually has
7508
+ globals of its own — which identity key to use, which checkout a call speaks
7509
+ for, which profile — and they belong to no single operation:
7510
+
7511
+ ```ts
7512
+ await createCli({
7513
+ name: 'myapp',
7514
+ version: '1.0.0',
7515
+ globalOptions: z.object({
7516
+ caller: z.string().optional().describe('Identity key file'),
7517
+ root: z.string().optional().describe('Checkout the call speaks for'),
7518
+ }),
7519
+ resolveAuth: (globals) => loadIdentity(globals.caller),
7520
+ context: (auth, globals) => ({ auth, root: globals.root }),
7521
+ runtimeTools: (auth) => catalogFor(auth),
7522
+ })
7523
+ ```
7524
+
7525
+ ```
7526
+ myapp --root /srv/app handoff_read --handoffId u
7527
+ myapp handoff_read --root /srv/app --handoffId u # the same call
7528
+ ```
7529
+
7530
+ These flags are lifted out of argv wherever they stand — before or after the
7531
+ command name — validated against the declared schema, and kept out of every
7532
+ operation's arguments: `handoff_read` above receives `{ handoffId: 'u' }` and
7533
+ nothing else. The values reach `resolveAuth(globals)`, `context(auth, globals)`
7534
+ and a native command's `globals`. An invalid value is an argument error naming
7535
+ the flag; a name that collides with a framework option, or with a field of any
7536
+ command, is refused at startup rather than shadowing it silently. Past a bare
7537
+ `--` every token is a literal, so a positional value that reads like a global
7538
+ survives intact.
7539
+
7540
+ Both help levels list them under `Application options:`.
7541
+
7542
+ ## When the managed surface cannot resolve
7543
+
7544
+ A CLI whose commands come from a running server declares them with a factory,
7545
+ and that factory needs an identity. When `resolveAuth` fails — the server is
7546
+ down, the key file is missing — the commands it would have named are unknown to
7547
+ the CLI, but the native ones are not:
7548
+
7549
+ ```
7550
+ $ myapp --help
7551
+ myapp 1.0.0
7552
+ ...
7553
+ Commands:
7554
+ serve Run the server
7555
+
7556
+ Managed commands are unavailable: UNREACHABLE: socket closed
7557
+ ```
7558
+
7559
+ Help still lists what does not depend on identity and says, in one line, why the
7560
+ rest is missing. Calling a name the CLI cannot resolve answers with that same
7561
+ refusal and the exit code its error class declares through `exitCodes` — never
7562
+ `Unknown command`, which would claim the name does not exist when the truth is
7563
+ that it could not be looked up. A native command and its help still run: they
7564
+ never needed an identity. Identity is still resolved at most once per
7565
+ invocation, failure included.
7566
+
7477
7567
  Per-command help derives the positional form from the same resolved policy as
7478
7568
  the argv parser. For example, a required `action` and optional `profile` render as
7479
7569
  `Usage: myapp skill <action> [profile] [--flags]`; the argument table also shows
@@ -7517,6 +7607,172 @@ myapp generate "a fox" --wait --output-dir ./out
7517
7607
  myapp generate "a fox" --wait --json > result.json &
7518
7608
  ```
7519
7609
 
7610
+ ## Aggregate views
7611
+
7612
+ The CLI's audience is agents, scripts and `jq`, so output is JSON. That settles
7613
+ the *encoding*; it does not settle whether the answer to "how many items per
7614
+ status" should be every item. Measured on a live server, one ordinary question:
7615
+
7616
+ | call | characters returned |
7617
+ |---|---|
7618
+ | the listing (98 records) | 34 750 |
7619
+ | `--count-by status` | ~90 |
7620
+
7621
+ An agent pays for every one of those characters in its context window, and `|
7622
+ jq` does not help: the bytes have been read into the conversation by the time
7623
+ `jq` sees them. So the aggregate is computed on the result, before anything is
7624
+ written.
7625
+
7626
+ ```bash
7627
+ myapp item_list --count-by status # { "active": 33, "idle": 33, "stopped": 32 }
7628
+ myapp item_list --count-by status --top 2 # the two largest groups
7629
+ myapp item_list --sum messages # 4753
7630
+ myapp item_list --sum messages --by status # one total per status
7631
+ myapp item_list --top 5 --by status # same view, written the other way round
7632
+ myapp item_list --table id,status # the one human-facing shape
7633
+ ```
7634
+
7635
+ `--by` always names the **grouping** field, in every form it appears in, so the
7636
+ grammar has one meaning rather than two. Groups are ordered largest first, which
7637
+ is what makes `--top` a defined slice rather than an arbitrary one.
7638
+
7639
+ Three rules worth knowing before you rely on them:
7640
+
7641
+ - **A field the result does not carry is an argument error.** A group of zero
7642
+ over a misspelled field is indistinguishable from a true empty answer, and the
7643
+ caller reads it as data. The message names the fields that *are* there.
7644
+ - **An aggregate needs a collection** — the result itself when it is an array,
7645
+ or the single array field of a result object. An aggregate over a scalar, or
7646
+ over an object with two array fields, is refused rather than guessed.
7647
+ - **Without a view flag the output is byte-for-byte what it was.** The flags are
7648
+ reserved CLI behaviour like `--json`; they never reach a tool argument.
7649
+
7650
+ A failed call still reports its own error and exit code. An aggregate over an
7651
+ error is not an answer to the question that was asked.
7652
+
7653
+ ## Named profiles
7654
+
7655
+ A CLI that talks to a deployed server needs an address and a credential per
7656
+ environment, and the way a person picks one is a name: `--profile prod`.
7657
+ `globalOptions` gives the flag a home and `resolveAuth(globals)` gives it a
7658
+ resolution point. The rule that makes the mechanism safe is easy to write the
7659
+ wrong way round, because the unsafe version reads as kindness:
7660
+
7661
+ > the named profile does not exist, but exactly one profile is configured — use it.
7662
+
7663
+ That is correct exactly while a single profile exists. The day a second appears
7664
+ it is a command run against the wrong deployment, with nothing in the output to
7665
+ say so. **A profile named explicitly and not found is a refusal, never a
7666
+ substitution.** Substitution survives only where it cannot be wrong: no name was
7667
+ given at all and exactly one profile exists — and even then it is announced on
7668
+ stderr. The distinction has to be drawn at resolution; one step later, "prod" and
7669
+ "prod by default" are the same string.
7670
+
7671
+ `createCliProfileStore` is that rule, plus the twenty lines every consumer of
7672
+ this shape writes:
7673
+
7674
+ ```ts
7675
+ import { createCliProfileStore } from 'stitchkit/cli'
7676
+ import { homedir } from 'node:os'
7677
+ import { join } from 'node:path'
7678
+ import { z } from 'zod'
7679
+
7680
+ const profiles = createCliProfileStore({
7681
+ directory: join(homedir(), '.config/myapp/profiles'),
7682
+ schema: z.object({ url: z.url(), token: z.string().min(1) }),
7683
+ createHint: (name, path) => `write ${path} with {"url","token"} for "${name}"`,
7684
+ })
7685
+
7686
+ await createCli({
7687
+ name: 'myapp',
7688
+ version,
7689
+ globalOptions: z.object({ profile: z.string().optional() }),
7690
+ resolveAuth: (globals) => profiles.resolve(globals.profile).value,
7691
+ services,
7692
+ })
7693
+ ```
7694
+
7695
+ Files are written `0600` in a `0700` directory — and a profile file other users
7696
+ can read is refused with the `chmod` that fixes it, because it holds a
7697
+ credential.
7698
+
7699
+ ## Distribution and self-update
7700
+
7701
+ `createCli` ships no executable, and that is right — but the step after the
7702
+ executable is not application logic either. It is the same problem for every
7703
+ consumer, with the same three traps:
7704
+
7705
+ 1. **The installer cannot parse the manifest.** A `curl … | sh` runs on a
7706
+ machine where nothing is installed yet, including `jq`. So the installer is
7707
+ generated *from* the manifest, server-side, with the URL and digest already
7708
+ substituted — it parses no JSON at all.
7709
+ 2. **Replacing a running binary is a rename, not a write.** Anything else can
7710
+ leave a half-written executable on someone's PATH when the connection drops.
7711
+ 3. **The digest covers the decompressed bytes** — the file that will actually be
7712
+ executed, not the archive that was transferred.
7713
+
7714
+ The framework owns the manifest shape, the installer generation and the update
7715
+ primitive. The application owns where the assets live, which platforms it
7716
+ publishes and who may download them.
7717
+
7718
+ ```ts
7719
+ import {
7720
+ CliBuildManifestSchema, assertCliPublishable, renderCliInstaller,
7721
+ selectCliBuildAsset, checkCliUpdate, applyCliUpdate,
7722
+ } from 'stitchkit/cli'
7723
+
7724
+ // Publishing: refuse to republish one version from a different commit —
7725
+ // otherwise everyone who already installed it never receives the fix.
7726
+ assertCliPublishable(previous, next)
7727
+
7728
+ // Serving: one generated script per target, no JSON on the wire.
7729
+ renderCliInstaller({ manifest, asset: selectCliBuildAsset(manifest, target)!, binaryName: 'myapp' })
7730
+
7731
+ // Checking: bounded, at most once per interval, silent on any failure.
7732
+ const check = await checkCliUpdate({ manifestUrl, currentVersion, lastCheckedAt })
7733
+ if (check.status === 'outdated' && check.asset) {
7734
+ // Replacing is always an explicit command, never a side effect of a check.
7735
+ await applyCliUpdate({ asset: check.asset })
7736
+ }
7737
+ ```
7738
+
7739
+ `checkCliUpdate` has **four** answers, not three: `skipped`, `current`,
7740
+ `outdated` and `unknown`. "Could not ask" is not "up to date" — collapsing them
7741
+ is how a tool goes quiet about its own staleness for months. It never throws,
7742
+ and a command still exits with the code it earned.
7743
+
7744
+ Carry the build stamp inside the binary (`CliBuildStampSchema`,
7745
+ `formatCliBuildStamp`) so the tool can say what it is rather than leaving the
7746
+ reader to infer it from behaviour.
7747
+
7748
+ ## Commands discovered from a running server
7749
+
7750
+ A CLI compiled from contracts carries the surface of the build it was compiled
7751
+ from. One built from discovery carries the surface the server has *right now* —
7752
+ which matters, because a long-lived MCP client freezes schemas at connect time
7753
+ and then refuses the server's own newer fields:
7754
+
7755
+ ```ts
7756
+ const discovered = await mountConnections([
7757
+ defineMcpClientConnection({
7758
+ name: 'api',
7759
+ transport: { url },
7760
+ token: () => key,
7761
+ transports: ['CLI'], // the opt-in: this server's tools are commands
7762
+ }),
7763
+ ])
7764
+ await createCli({ name: 'myapp', version, runtimeTools: discovered, commands: [...] })
7765
+ ```
7766
+
7767
+ `transports` is where the opt-in belongs: a whole server becomes a set of
7768
+ commands, and a connection without it still contributes nothing to the CLI —
7769
+ exposure stays explicit, as it is everywhere else in the framework.
7770
+
7771
+ One unconvertible schema no longer takes the connection down with it. The tool
7772
+ is skipped and **named** (`onSkippedTool`, or a stderr line by default), so a
7773
+ surface of two hundred tools is not lost to one.
7774
+
7775
+
7520
7776
  ## Auth parity
7521
7777
 
7522
7778
  A scoped command is guarded by the same `createAuthHook` your HTTP server uses —
@@ -16443,14 +16699,14 @@ payload.
16443
16699
  | `AgentToolRegistry` / `AgentToolRegistryBuilder` / `AgentToolRegistryInput` | _type_ | the composed runtime surface and its builder: declared defaults, `replace`/`disable` by name, and the exact `{ tools, names }` a mount receives |
16444
16700
  | `defineToolRegistry` | function | compose runtime tools over one declared default set; an unknown `replace`/`disable` name is refused instead of silently leaving the default in place |
16445
16701
  | `AgentContext` | _type_ | the context merged into agent tool handlers |
16446
- | `CliConfig` | _type_ | config for `createCli`, including program-level `defaultCommand` selection and command-scoped `optionAliases` / `positionals` policy |
16702
+ | `CliConfig` | _type_ | config for `createCli`, including program-level `defaultCommand` selection, application-wide `globalOptions` and command-scoped `optionAliases` / `positionals` policy |
16447
16703
  | `CliPresentationPolicyConfig` | _type_ | reusable default-command, short-alias and explicit-positional policy inherited by `CliConfig` |
16448
16704
  | `CliSurfaceSource` | _type_ | static managed surface or identity-dependent surface factory for `createCli` |
16449
16705
  | `CliCommandDefinition` | _type_ | Zod-first CLI-only command union |
16450
16706
  | `CliCommandDefinitionBase` | _type_ | native command name, description and input schema |
16451
16707
  | `CliCommandDefinitionWithOutput` | _type_ | native command with declared output schema, validated handler result and typed optional `present` / `exitCode` callbacks |
16452
16708
  | `CliCommandDefinitionWithoutOutput` | _type_ | void native command with no output schema |
16453
- | `CliCommandContext` | _type_ | parsed native command input, global options and injected writers |
16709
+ | `CliCommandContext` | _type_ | parsed native command input, framework run options, the application's `globals` and injected writers |
16454
16710
  | `CliWaitConfig` | _type_ | `--wait` polling config |
16455
16711
  | `ExitCodeMap` | _type_ | `ToolResult.code` → process exit code |
16456
16712
  | `Toolkit` | _type_ | the context-pinned tool surface from `createToolkit` |
@@ -16624,13 +16880,16 @@ and approval path.
16624
16880
  | `ConnectionTokenProvider` | _type_ | `() => string \| undefined \| Promise<string \| undefined>` — the lazily resolved credential |
16625
16881
  | `ConnectionBudget` | _type_ | `{ maxTools? }` ceiling on one `mountConnections` call |
16626
16882
  | `ConnectionDefinition` | _type_ | either a defined MCP client or OpenAPI connection |
16627
- | `ConnectionMountOptions` | _type_ | shared `{ lifecycle?, budget? }` mount policy |
16883
+ | `ConnectionMountOptions` | _type_ | shared `{ lifecycle?, budget?, onSkippedTool? }` mount policy |
16884
+ | `ConnectionToolSkipReporter` | _type_ | `(skipped) => void` — called per discovered tool the mount could not build; defaults to a stderr line, and the rest of the surface still mounts |
16885
+ | `SkippedConnectionTool` | _type_ | `{ connection, tool, reason }` — which tool was not mounted, and why |
16886
+ | `RuntimeToolTransport` | _type_ | `'MCP' \| 'AGENT' \| 'CLI'` — the surfaces a connection's `transports` may name |
16628
16887
  | `McpClientConnection` | _type_ | a defined MCP client connection |
16629
- | `McpClientConnectionConfig` | _type_ | name, transport, tool filter, token provider, instance key and allowed hosts |
16888
+ | `McpClientConnectionConfig` | _type_ | name, transport, tool filter, token provider, instance key, allowed hosts and `transports` — naming `['CLI']` makes the whole server's discovered tools commands, with no per-definition rewriting |
16630
16889
  | `McpConnectionTransport` | _type_ | `{ url, headers? }` for one MCP endpoint |
16631
16890
  | `McpToolFilter` | _type_ | `{ allow?, block? }` discovered-tool filter |
16632
16891
  | `OpenApiConnection` | _type_ | a defined OpenAPI connection |
16633
- | `OpenApiConnectionConfig` | _type_ | name, spec, base URL, token provider, instance key and allowed hosts |
16892
+ | `OpenApiConnectionConfig` | _type_ | name, spec, base URL, token provider, instance key, allowed hosts and `transports` |
16634
16893
 
16635
16894
  ---
16636
16895
 
@@ -16946,17 +17205,44 @@ SDK nor the `ai` peer.
16946
17205
  | `createCli` | function | build and run a CLI from contracts — [guide](../guide/cli.md) |
16947
17206
  | `defineCliCommand` | function | define one Zod-typed CLI-only executable command with optional validated-result presentation/exit policy |
16948
17207
  | `parseCliArgs` | function | argv → typed tool args against a schema (advanced) |
17208
+ | `routeCliArgv` | function | select the command out of argv without duplicating the global-option grammar (advanced) |
17209
+ | `extractCliGlobalOptions` | function | lift the application's own global options out of argv before routing (advanced) |
17210
+ | `coerceJsonArgs` | function | the second half of `parseCliArgs` — parse array/object values a consumer sends itself, without the `stitchkit/tools` barrel |
17211
+ | `CliArgumentError` | class | the refusal `parseCliArgs` and the view flags raise; a CLI reports it and exits `2` |
17212
+ | `renderCliView` | function | compute an aggregate over a result (`--count-by`, `--sum`, `--top`, `--table`) — [guide](../guide/cli.md#aggregate-views) |
17213
+ | `createCliProfileStore` | function | named `0600` credential profiles resolved by name, with the never-substitute rule built in — [guide](../guide/cli.md#named-profiles) |
17214
+ | `CliProfileError` | class | an `AppError` refusing a named profile that is missing, unreadable or shared between users |
17215
+ | `renderCliInstaller` | function | generate the one-line installer from a build manifest, with the URL and digest substituted — [guide](../guide/cli.md#distribution-and-self-update) |
17216
+ | `checkCliUpdate` | function | bounded, interval-limited, never-throwing check for a newer published build |
17217
+ | `applyCliUpdate` | function | download, verify the decompressed digest and replace the binary by rename |
17218
+ | `assertCliPublishable` | function | refuse republishing one version from a different commit |
17219
+ | `selectCliBuildAsset` | function | the asset for one target, or `undefined` |
17220
+ | `currentCliBuildTarget` | function | `{ platform, arch }` of the running process |
17221
+ | `formatCliBuildStamp` | function | one line saying what the running build is |
17222
+ | `compareCliVersions` | function | compare two versions, or `undefined` when they are not comparable |
17223
+ | `CliBuildManifestSchema` / `CliBuildManifest` | schema / _type_ | name, version, commit, build time and assets |
17224
+ | `CliBuildAssetSchema` / `CliBuildAsset` | schema / _type_ | one download; `size` and `sha256` describe the **decompressed** bytes |
17225
+ | `CliBuildTargetSchema` / `CliBuildTarget` | schema / _type_ | `{ platform, arch }` |
17226
+ | `CliBuildStampSchema` / `CliBuildStamp` | schema / _type_ | the version/commit/build time carried inside a binary |
17227
+ | `CliInstallerConfig` | _type_ | manifest, asset, binary name and default install directory |
17228
+ | `CliUpdateCheckConfig` / `CliUpdateCheck` | _type_ | check inputs, and its four answers — `skipped`, `current`, `outdated`, `unknown` |
17229
+ | `CliUpdateApplyConfig` / `AppliedCliUpdate` | _type_ | apply inputs and the replaced path, byte count and digest |
17230
+ | `CliProfileStore` / `CliProfileStoreConfig` / `ResolvedCliProfile` | _type_ | the profile store, its directory/schema/hint config, and one resolution |
17231
+ | `CliResultView` | _type_ | the requested aggregate — `count`, `sum` or `table` |
17232
+ | `CliViewOutput` | _type_ | a JSON value, or the one human-facing text shape |
17233
+ | `CliGlobalOptionsParse` | _type_ | `{ argv, globals }` returned by `extractCliGlobalOptions` |
17234
+ | `CliArgvRoute` | _type_ | `{ command, commandArgv, topLevelHelp, version, error? }` returned by `routeCliArgv` |
16949
17235
  | `pollUntilDone` | function | the generic `--wait` poller (advanced) |
16950
17236
  | `emitResult` | function | write a pretty or compact `ToolResult` record to stdout/stderr + exit code (advanced) |
16951
17237
  | `DEFAULT_EXIT_CODES` | const | the default `ToolResult.code` → exit-code map |
16952
- | `CliConfig` | _type_ | config for `createCli`; `defaultCommand`, `optionAliases` and `positionals` define the shared command presentation policy |
17238
+ | `CliConfig` | _type_ | config for `createCli`; `defaultCommand`, `globalOptions`, `optionAliases` and `positionals` define the shared command presentation policy |
16953
17239
  | `CliPresentationPolicyConfig` | _type_ | shared command presentation-policy subset of `CliConfig` |
16954
17240
  | `CliSurfaceSource` | _type_ | static service/runtime array or identity-dependent factory |
16955
17241
  | `CliCommandDefinition` | _type_ | native command definition union |
16956
17242
  | `CliCommandDefinitionBase` | _type_ | native command name, description and input schema |
16957
17243
  | `CliCommandDefinitionWithOutput` | _type_ | native command with validated declared output and typed optional `present` / successful `exitCode` callbacks |
16958
17244
  | `CliCommandDefinitionWithoutOutput` | _type_ | native void command without an output contract |
16959
- | `CliCommandContext` | _type_ | parsed input, global options and stdout/stderr writers |
17245
+ | `CliCommandContext` | _type_ | parsed input, framework run options, the application's `globals` and stdout/stderr writers |
16960
17246
  | `CliRunOptions` | _type_ | parsed global flags (`--json` compacts success/error records, `--wait`, …) |
16961
17247
  | `ParsedCliArgs` | _type_ | result of `parseCliArgs` |
16962
17248
  | `CliWaitConfig` | _type_ | per-command `--wait` polling config; optional `failed(result)` maps a terminal domain failure to `WAIT_FAILED` and a non-zero exit |
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "stitchkit",
3
- "version": "0.90.2",
3
+ "version": "0.90.4",
4
4
  "description": "Contract-first backend framework — one defineContract() into an HTTP API, MCP tools, AI-agent tools and a typed client. Bun and Node.",
5
5
  "keywords": [
6
6
  "bun",