@zackbart/connecta 0.16.1 → 0.17.0

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 (42) hide show
  1. package/CHANGELOG.md +102 -0
  2. package/dist/catalog-service.d.ts +4 -0
  3. package/dist/catalog-service.js +8 -1
  4. package/dist/catalog.js +114 -12
  5. package/dist/errors.d.ts +4 -6
  6. package/dist/execute.d.ts +5 -0
  7. package/dist/execute.js +229 -161
  8. package/dist/invocation.js +3 -1
  9. package/dist/meta-tools.d.ts +4 -0
  10. package/dist/meta-tools.js +46 -14
  11. package/dist/operator-ui/generated.d.ts +1 -1
  12. package/dist/operator-ui/generated.js +1 -1
  13. package/dist/operator-ui/model.d.ts +3 -1
  14. package/dist/providers/mixpanel.d.ts +3 -5
  15. package/dist/providers/mixpanel.js +73 -5
  16. package/dist/providers/stripe.d.ts +2 -2
  17. package/dist/providers/stripe.js +13 -11
  18. package/dist/registry.d.ts +32 -9
  19. package/dist/registry.js +217 -33
  20. package/dist/routes/mcp.js +6 -0
  21. package/dist/skills.d.ts +4 -0
  22. package/dist/skills.js +157 -18
  23. package/dist/types.d.ts +14 -2
  24. package/dist/ui.js +4 -1
  25. package/dist/version.d.ts +1 -1
  26. package/dist/version.js +1 -1
  27. package/documentation/architecture.md +7 -4
  28. package/documentation/code-mode.md +45 -53
  29. package/documentation/connector-guides.md +24 -19
  30. package/documentation/connectors.md +13 -1
  31. package/documentation/meta-tools.md +26 -17
  32. package/documentation/mixpanel.md +20 -0
  33. package/documentation/operations.md +21 -18
  34. package/documentation/operator-ui.md +12 -2
  35. package/documentation/provider-audit.md +3 -3
  36. package/documentation/provider-conventions.md +26 -13
  37. package/documentation/stripe.md +45 -14
  38. package/documentation/upgrading.md +28 -4
  39. package/ethos.md +3 -3
  40. package/examples/worker/README.md +4 -3
  41. package/package.json +1 -1
  42. package/templates/node/package.json +1 -1
@@ -282,7 +282,9 @@ export class InvocationService {
282
282
  context.beforeDispatch?.();
283
283
  }
284
284
  catch (error) {
285
- return failed(classifyCallError(error));
285
+ return failed(error instanceof InvocationFailure
286
+ ? error.details
287
+ : classifyCallError(error));
286
288
  }
287
289
  const maxRetries = Math.min(2, Math.max(0, Math.trunc(context.maxRetries ?? 0)));
288
290
  let result;
@@ -1,6 +1,7 @@
1
1
  import type { McpServer } from "@modelcontextprotocol/server";
2
2
  import type { ActivityRequestContext } from "./activity.js";
3
3
  import { MAX_DESCRIBE_ADDRESSES, MAX_DISCOVERY_RESULT_BYTES, MAX_SEARCH_LIMIT } from "./catalog-service.js";
4
+ import type { DeferredWork } from "./connector-scope.js";
4
5
  import { MAX_RETRY_BACKOFF_MS, retryBackoffMs } from "./invocation.js";
5
6
  import { type RegistryView } from "./registry.js";
6
7
  export { MAX_DESCRIBE_ADDRESSES, MAX_DISCOVERY_RESULT_BYTES, MAX_RETRY_BACKOFF_MS, MAX_SEARCH_LIMIT, retryBackoffMs, };
@@ -112,6 +113,8 @@ export declare function createMetaTools(registry: RegistryView, baseUrl: string,
112
113
  activity?: ActivityRequestContext;
113
114
  /** Inbound request cancellation shared by every call this request makes. */
114
115
  requestSignal?: AbortSignal;
116
+ /** Runtime-owned tail for stale catalog refreshes. */
117
+ defer?: DeferredWork;
115
118
  }): {
116
119
  skills(args?: SkillArgs): Promise<ToolResult>;
117
120
  searchTools(args: SearchArgs): Promise<ToolResult>;
@@ -135,4 +138,5 @@ export declare function registerMetaTools(server: McpServer, registry: RegistryV
135
138
  discoveryConcurrency?: number;
136
139
  activity?: ActivityRequestContext;
137
140
  requestSignal?: AbortSignal;
141
+ defer?: DeferredWork;
138
142
  }): void;
@@ -125,25 +125,41 @@ export function alignEndToCharBoundary(bytes, offset, end, total) {
125
125
  }
126
126
  return e;
127
127
  }
128
- // --- fields selection (feature 2) -----------------------------------------
129
- /** Resolve a dot-path (segments) against a value; `key[]` maps the tail over an array. */
128
+ /** Resolve a dot-path and retain misses below every `[]` boundary. */
130
129
  function resolvePath(value, segments) {
131
130
  const seg = segments[0];
132
- if (seg === undefined)
133
- return value;
131
+ if (seg === undefined) {
132
+ return value === undefined
133
+ ? { status: "unmatched" }
134
+ : { status: "matched", value };
135
+ }
134
136
  const rest = segments.slice(1);
135
137
  const isArr = seg.endsWith("[]");
136
138
  const key = isArr ? seg.slice(0, -2) : seg;
137
139
  let next = value;
138
140
  if (key !== "") {
139
- if (value === null || typeof value !== "object")
140
- return undefined;
141
+ if (value === null || typeof value !== "object") {
142
+ return { status: "unmatched" };
143
+ }
141
144
  next = value[key];
142
145
  }
143
146
  if (isArr) {
144
147
  if (!Array.isArray(next))
145
- return undefined;
146
- return next.map((el) => resolvePath(el, rest));
148
+ return { status: "unmatched" };
149
+ if (next.length === 0)
150
+ return { status: "matched", value: [] };
151
+ const elements = next.map((el) => resolvePath(el, rest));
152
+ const matched = elements.some((element) => element.status !== "unmatched");
153
+ const missed = elements.some((element) => element.status !== "matched");
154
+ if (!matched)
155
+ return { status: "unmatched" };
156
+ return {
157
+ status: missed ? "partial" : "matched",
158
+ // Undefined placeholders retain the historical array positions in the
159
+ // partial value. JSON renders them as null; partialFields says they are
160
+ // unresolved rather than genuine downstream nulls.
161
+ value: elements.map((element) => element.status === "unmatched" ? undefined : element.value),
162
+ };
147
163
  }
148
164
  return resolvePath(next, rest);
149
165
  }
@@ -517,14 +533,19 @@ function schemaProjectionFeedback(outputSchema, unmatchedFields) {
517
533
  function applyFields(value, fields) {
518
534
  const out = {};
519
535
  const unmatchedFields = [];
536
+ const partialFields = [];
520
537
  for (const path of fields) {
521
538
  const resolved = resolvePath(value, path.split("."));
522
- if (resolved === undefined)
539
+ if (resolved.status === "unmatched") {
523
540
  unmatchedFields.push(path);
524
- else
525
- out[path] = resolved;
541
+ }
542
+ else {
543
+ out[path] = resolved.value;
544
+ if (resolved.status === "partial")
545
+ partialFields.push(path);
546
+ }
526
547
  }
527
- return { data: out, unmatchedFields };
548
+ return { data: out, unmatchedFields, partialFields };
528
549
  }
529
550
  /**
530
551
  * Keep the historical flat projection when every path resolves. A miss gets a
@@ -537,16 +558,25 @@ function projectionValue(value, fields, outputSchema) {
537
558
  // matched downstream field with that exact name is escaped below `data`, so
538
559
  // no user-controlled value can impersonate Connecta's discriminator.
539
560
  const reservedCollision = Object.prototype.hasOwnProperty.call(projected.data, "$connecta");
540
- if (projected.unmatchedFields.length === 0 && !reservedCollision) {
561
+ if (projected.unmatchedFields.length === 0 &&
562
+ projected.partialFields.length === 0 &&
563
+ !reservedCollision) {
541
564
  return projected.data;
542
565
  }
566
+ const problemFields = [
567
+ ...projected.unmatchedFields,
568
+ ...projected.partialFields,
569
+ ];
543
570
  return {
544
571
  data: projected.data,
545
572
  $connecta: {
546
573
  type: "field_projection",
547
574
  unmatchedFields: projected.unmatchedFields,
575
+ ...(projected.partialFields.length > 0
576
+ ? { partialFields: projected.partialFields }
577
+ : {}),
548
578
  ...(outputSchema
549
- ? schemaProjectionFeedback(outputSchema, projected.unmatchedFields)
579
+ ? schemaProjectionFeedback(outputSchema, problemFields)
550
580
  : {}),
551
581
  },
552
582
  };
@@ -731,6 +761,7 @@ export function createMetaTools(registry, baseUrl, opts = {}) {
731
761
  requestScope,
732
762
  probeTimeoutMs,
733
763
  concurrency: discoveryConcurrency,
764
+ ...(opts.defer ? { defer: opts.defer } : {}),
734
765
  // searchRoute keeps its top-level default. In-program callers use a
735
766
  // separate CatalogService configured for connecta.search.
736
767
  });
@@ -1089,6 +1120,7 @@ export function registerMetaTools(server, registry, ctx) {
1089
1120
  ...(ctx.requestSignal !== undefined
1090
1121
  ? { requestSignal: ctx.requestSignal }
1091
1122
  : {}),
1123
+ ...(ctx.defer !== undefined ? { defer: ctx.defer } : {}),
1092
1124
  });
1093
1125
  server.registerTool("skills", {
1094
1126
  description: describedFor(registry, SKILLS_DESC, "skills"),