@zackbart/connecta 0.12.2 → 0.14.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 (75) hide show
  1. package/CHANGELOG.md +324 -0
  2. package/README.md +4 -1
  3. package/dist/catalog-service.d.ts +41 -0
  4. package/dist/catalog-service.d.ts.map +1 -1
  5. package/dist/catalog-service.js +127 -11
  6. package/dist/catalog-service.js.map +1 -1
  7. package/dist/connectors/api.d.ts +5 -4
  8. package/dist/connectors/api.d.ts.map +1 -1
  9. package/dist/connectors/api.js +5 -1
  10. package/dist/connectors/api.js.map +1 -1
  11. package/dist/connectors/remote-mcp.d.ts +5 -4
  12. package/dist/connectors/remote-mcp.d.ts.map +1 -1
  13. package/dist/connectors/remote-mcp.js.map +1 -1
  14. package/dist/execute.d.ts.map +1 -1
  15. package/dist/execute.js +12 -10
  16. package/dist/execute.js.map +1 -1
  17. package/dist/index.d.ts +1 -1
  18. package/dist/index.d.ts.map +1 -1
  19. package/dist/index.js.map +1 -1
  20. package/dist/meta-tools.d.ts.map +1 -1
  21. package/dist/meta-tools.js +5 -4
  22. package/dist/meta-tools.js.map +1 -1
  23. package/dist/providers/cloudflare.d.ts +53 -0
  24. package/dist/providers/cloudflare.d.ts.map +1 -0
  25. package/dist/providers/cloudflare.js +1385 -0
  26. package/dist/providers/cloudflare.js.map +1 -0
  27. package/dist/providers/linear.d.ts +44 -0
  28. package/dist/providers/linear.d.ts.map +1 -0
  29. package/dist/providers/linear.js +243 -0
  30. package/dist/providers/linear.js.map +1 -0
  31. package/dist/providers/mixpanel.d.ts +21 -0
  32. package/dist/providers/mixpanel.d.ts.map +1 -0
  33. package/dist/providers/mixpanel.js +191 -0
  34. package/dist/providers/mixpanel.js.map +1 -0
  35. package/dist/providers/notion.d.ts +39 -0
  36. package/dist/providers/notion.d.ts.map +1 -0
  37. package/dist/providers/notion.js +1625 -0
  38. package/dist/providers/notion.js.map +1 -0
  39. package/dist/providers/stripe.d.ts +37 -0
  40. package/dist/providers/stripe.d.ts.map +1 -0
  41. package/dist/providers/stripe.js +232 -0
  42. package/dist/providers/stripe.js.map +1 -0
  43. package/dist/skills.d.ts +7 -9
  44. package/dist/skills.d.ts.map +1 -1
  45. package/dist/skills.js +58 -24
  46. package/dist/skills.js.map +1 -1
  47. package/dist/types.d.ts +26 -6
  48. package/dist/types.d.ts.map +1 -1
  49. package/dist/version.d.ts +1 -1
  50. package/dist/version.js +1 -1
  51. package/documentation/cloudflare.md +268 -0
  52. package/documentation/code-mode.md +6 -6
  53. package/documentation/connectors.md +122 -4
  54. package/documentation/linear.md +144 -0
  55. package/documentation/meta-tools.md +91 -8
  56. package/documentation/mixpanel.md +77 -0
  57. package/documentation/notion.md +233 -0
  58. package/documentation/stripe.md +202 -0
  59. package/ethos.md +8 -3
  60. package/package.json +21 -1
  61. package/src/catalog-service.ts +174 -10
  62. package/src/connectors/api.ts +10 -4
  63. package/src/connectors/remote-mcp.ts +5 -3
  64. package/src/execute.ts +18 -10
  65. package/src/index.ts +1 -0
  66. package/src/meta-tools.ts +10 -4
  67. package/src/providers/cloudflare.ts +1696 -0
  68. package/src/providers/linear.ts +301 -0
  69. package/src/providers/mixpanel.ts +228 -0
  70. package/src/providers/notion.ts +1879 -0
  71. package/src/providers/stripe.ts +306 -0
  72. package/src/skills.ts +64 -23
  73. package/src/types.ts +27 -6
  74. package/src/version.ts +1 -1
  75. package/templates/node/package.json +1 -1
package/src/execute.ts CHANGED
@@ -28,6 +28,7 @@ import {
28
28
  InvocationService,
29
29
  } from "./invocation.js";
30
30
  import type { RegistryView } from "./registry.js";
31
+ import { hasConnectorGuides } from "./skills.js";
31
32
  import { isExplicitlyReadOnly } from "./tool-safety.js";
32
33
  import type {
33
34
  Executor,
@@ -1272,20 +1273,22 @@ function discardedEmitsText(emitted: EmitCollector): string {
1272
1273
 
1273
1274
  const executeDescription = (
1274
1275
  emitBudgets: { maxBytes: number; maxBlocks: number },
1275
- ) => `The primary surface. Use for discovery beyond one lookup, two or more calls, dependent steps, loops, joins, branching, or reducing large results before they reach the model — connecta.search and connecta.describe browse and expand catalogs in the run, and connecta.batch handles independent calls. The exception is one call at an address already in hand: search_tools then one call_tool is cheaper than a program. Only tools explicitly annotated readOnlyHint: true are available. Each run is limited to ${EXECUTE_MAX_HOST_CALLS} host calls, connecta.batch to at most ${EXECUTE_MAX_BATCH_CALLS}; each host call has a ${EXECUTE_HOST_CALL_TIMEOUT_MS / 1_000}-second deadline.
1276
+ connectorGuides: boolean,
1277
+ ) => `Choose the route before discovery. Exactly one unknown-address read uses top-level search_tools then call_tool; a known address uses call_tool directly. This is the primary surface for everything wider. If any result will be reduced — even from one connector call — or work has dependent/multiple calls, loops, joins, or branches, make exactly one execute_code call that searches, selects, calls, and reduces before returning. A discovery-only program wastes its round trip: finish here, don't return catalog matches for a later call. Only readOnlyHint: true tools are available. Limits: ${EXECUTE_MAX_HOST_CALLS} host calls per run, ${EXECUTE_MAX_BATCH_CALLS} per batch, ${EXECUTE_HOST_CALL_TIMEOUT_MS / 1_000}-second host deadline.
1276
1278
 
1277
1279
  Write an async arrow function. It runs with NO network, filesystem, timers, or imports — the only capabilities are:
1278
- - One global per connector: call every address <connectorId>.<toolName> from search_tools as <connectorId>.<toolName>(args), with a single args object matching the schema from connecta.describe. Names are sanitized to JS identifiers: characters outside [A-Za-z0-9_$] become "_" (my-service.get.thing → my_service.get_thing), leading digits get "_" prefixed, reserved words "_" appended.
1280
+ - Connector globals call <connectorId>.<toolName>(args) with one schema-matching args object. Sanitization: non-[A-Za-z0-9_$] "_" (my-service.get.thing → my_service.get_thing), leading digit "_" prefix, reserved word "_" suffix.
1279
1281
  - connecta.call(address, args) and connecta.batch(calls) — call raw addresses. Every batch entry is { address, ok: true, data } or { address, ok: false, error, errorDetails: { code, retryable } }; destructure that, not a bare result.
1280
- - connecta.search(args) and connecta.describe, taking { address: "<connectorId>.<toolName>" } or { addresses: [...] } — load and inspect request-local catalogs on demand. Use safety: "readOnly" to avoid advertising calls this sandbox cannot execute; it changes results, not authority. Matches carrying schemas also list inputKeys, requiredInputKeys, and outputKeys — the schema's own names, checkable before building args. A missing list means the schema is not a plain object shape, not that the tool has no fields read the schema.
1281
- - connecta.emit(block) — deliver MCP content beside the JSON return: exactly { type: "text", text } or { type: "image" | "audio", data (base64), mimeType }, nothing else. Blocks are appended on success only, spend no host calls, and are budgeted per run (${emitBudgets.maxBlocks} blocks, ${emitBudgets.maxBytes} serialized bytes); an over-budget or invalid emit throws catchably and accepts nothing.
1282
- - connecta.ui(html, options?) — deliver one view. One argument is display-only; for live reads pass { reads: { name: { address, fixedArgs?, viewArgs? } } }, then markup calls connecta.read(name, args). Read-only is validated; fixed keys cannot be overridden, undeclared keys fail, and discovery, writes, and network stay unavailable. Success-only, no binding call cost, and one budget, not two (${emitBudgets.maxBytes} shared emit bytes); a second, over-budget, or invalid call throws catchably. The bytes stay out of context, so the model reads the return value, not the view: return the initial summary from its variables; later reads update only the view.
1282
+ - connecta.search(args) loads catalogs and must be followed by selection and calls in this program; set connector to the obvious id to load one, otherwise it loads all. For distinct operations, make separate short searches here. Require address/description to match the operation, then check requiredInputKeys, truncation, safety, and outputs; never take the first lexical or merely input-compatible match. Choose the best compatible match; do not require it to be the only match. Missing outputKeys means inspect outputSchema, not discard the candidate. Compatible means every required key has a task/prior-result value; do not prefer zero required keys. Put every requiredInputKey in call args. For dependencies, match an earlier outputKey to the later requiredInputKey. Use displayed names; [] means no required keys, not permission to invent args. Describe only a truncated/insufficient compact shape. Reducers use declared outputKeys, never guessed items/results roots. connecta.describe takes { address: "<connectorId>.<toolName>" } or { addresses: [...] }. Use safety: "readOnly" to avoid advertising calls this sandbox cannot execute; it changes results, not authority. A missing key list means a non-object shape, not no fields read the schema.${connectorGuides ? " A match with guideRequired: true is a hard stop: do not call it; describing the exact schema clears only a schema_truncated reason, so for any other reason return the exact guide name, fetch that guide with the top-level skills tool, then write the informed call." : ""}
1283
+ - connecta.emit(block) — emit exactly { type: "text", text } or { type: "image" | "audio", data (base64), mimeType }. Success-only, no host call, ${emitBudgets.maxBlocks} blocks/${emitBudgets.maxBytes} bytes; invalid or over-budget throws before accepting.
1284
+ - connecta.ui(html, options?) — one success-only view. One arg is display-only; live reads use { reads: { name: { address, fixedArgs?, viewArgs? } } }, then markup calls connecta.read(name, args). Read admission is enforced; fixed keys cannot be overridden and undeclared keys fail. It shares the ${emitBudgets.maxBytes}-byte emit budget one budget, not two; a second, over-budget, or invalid call throws catchably. Bytes stay out of context, so the model reads the return value, not the view: return the initial summary from its variables; later reads update only the view.
1283
1285
  - console.log(...) — captured and returned with the result.
1284
1286
 
1285
- Tool calls return plain values (MCP text is JSON-parsed when possible) and throw on downstream errors use try/catch. A thrown error carries only a message, so use connecta.batch when a program must tell a policy refusal from a transient failure. Never retry a failure whose retryable is false, and never retry a rate_limited one immediately the sandbox has no timers. Return a JSON-serializable value; large results are truncated, so reduce data in code rather than return raw payloads.
1287
+ Dependent example (only when the second call requires a value returned by the first): async () => { const { tools } = await connecta.search({ query: "pipeline run job logs", safety: "readOnly", includeSchemas: "compact" }); const pick = (suffix) => { const match = tools.find((t) => t.address.endsWith(suffix)); if (!match) throw new Error("no tool for " + suffix); return match.address; }; const run = await connecta.call(pick(".get_run"), { runId: 42 }); const logs = await connecta.call(pick(".get_job_logs"), { jobId: run.failedJobId }); return [run, logs]; }
1286
1288
 
1287
- Plain JavaScript only no TypeScript syntax. For unknown-address dependent work, use one execute_code call: search inside it, read the compact schemas, continue to the dependent calls; do not return search results for a second execute_code call. Compact schemas are TypeScript-like strings, not JSON Schema objects: write the property names they display, never a positional guess or an invented alias.
1288
- Dependent example (only when the second call requires a value returned by the first): async () => { const { tools } = await connecta.search({ query: "pipeline run job logs", safety: "readOnly", includeSchemas: "compact" }); const pick = (suffix) => { const match = tools.find((t) => t.address.endsWith(suffix)); if (!match) throw new Error("no tool for " + suffix); return match.address; }; const run = await connecta.call(pick(".get_run"), { runId: 42 }); const logs = await connecta.call(pick(".get_job_logs"), { jobId: run.failedJobId }); return [run, logs]; }`;
1289
+ Calls return plain values (JSON-parsing MCP text when possible) and throw; catch errors. A thrown error is only a message; connecta.batch tells a policy refusal from a transient failure. Never retry retryable: false or rate_limited immediately there are no timers. Return JSON; large results truncate, so reduce instead of returning raw payloads.
1290
+
1291
+ Plain JS, no TypeScript. Compact schemas are TypeScript-like, not JSON Schema: write the property names they display; never guess positions or aliases.`;
1289
1292
 
1290
1293
  /** Register the execute_code meta-tool. Only called when an executor is configured. */
1291
1294
  export function registerExecuteTool(
@@ -1340,11 +1343,16 @@ export function registerExecuteTool(
1340
1343
  server.registerTool(
1341
1344
  "execute_code",
1342
1345
  {
1343
- description: executeDescription(emitBudgets),
1346
+ description: executeDescription(
1347
+ emitBudgets,
1348
+ hasConnectorGuides(registry.listConnectors()),
1349
+ ),
1344
1350
  inputSchema: z.object({
1345
1351
  code: z
1346
1352
  .string()
1347
- .describe("A JavaScript async arrow function to execute."),
1353
+ .describe(
1354
+ "One complete JavaScript async arrow function. Consume search/describe results and finish the task inside it; returning catalog data for a later call spends a round trip and buys nothing. So does aborting on a missing tool match or result key — re-search, describe, or read the result's actual keys here instead.",
1355
+ ),
1348
1356
  diagnostics: z
1349
1357
  .boolean()
1350
1358
  .optional()
package/src/index.ts CHANGED
@@ -630,6 +630,7 @@ export type {
630
630
  ConnectorCredentialFieldConfig,
631
631
  ConnectorCredentialValues,
632
632
  ConnectorContext,
633
+ ConnectorUsageGuide,
633
634
  ConnectorStatus,
634
635
  CredentialTestResult,
635
636
  AdmittingExecutor,
package/src/meta-tools.ts CHANGED
@@ -1372,7 +1372,7 @@ export function createMetaTools(
1372
1372
  };
1373
1373
  }
1374
1374
 
1375
- const SEARCH_DESC = `Unknown address: use 2–4 distinctive action/object terms, not the full request; omit limit initially (default ${DEFAULT_SEARCH_LIMIT}) and page only if needed, up to ${MAX_SEARCH_LIMIT}. Partial and no-match searches report term coverage and next-step guidance. safety="readOnly" returns only calls available to call_tool and generated code; "approvalRequired" returns everything else; omitted or "all" preserves the complete catalog. This filters results, not authority. includeSchemas="compact" adds the input and any declared output shape, each bounded; plain-object schemas also expose inputKeys, requiredInputKeys, and outputKeys, while inputSchemaTruncated/outputSchemaTruncated mark shapes that need exact retrieval; matches also carry declared annotations. Call directly when sufficient. Empty query browses all.`;
1375
+ const SEARCH_DESC = `Use top-level search only for exactly one unreduced read, then call_tool, or for write-capable work, then call_destructive_tool. For read-only reduction, dependent or multiple calls, never search here: make one execute_code program that searches and calls. Use 2–4 distinctive action/object terms, not the full request; set connector to the obvious integration id to load one catalog instead of all; omit limit initially (default ${DEFAULT_SEARCH_LIMIT}), page to ${MAX_SEARCH_LIMIT} if needed. safety="readOnly" returns only calls available to call_tool/code; "approvalRequired" returns the rest; omitted/"all" returns all. This filters results, not authority. includeSchemas="compact" adds the input and any declared output shape, bounded; plain objects expose inputKeys, requiredInputKeys, and outputKeys; truncation flags mark incomplete shapes; matches also carry declared annotations. Require purpose/address fit plus compatible inputs, truncation, safety, and outputs — never the first lexical match. Empty query browses all.`;
1376
1376
  const CALL_DESC =
1377
1377
  'Use for ONE tool explicitly annotated readOnlyHint: true — the cheapest path for a single cold call. For two or more calls, dependent steps, loops, joins, or data reduction use execute_code, whose connecta.call and connecta.batch reach the same tools. Unannotated, write-capable, and destructive tools are refused and require call_destructive_tool. fields selects JSON dot-paths; traverse arrays with [] (for example results[].id). Misses return data plus `$connecta` feedback. resultMode "value" unwraps results, timeoutMs sets a deadline, safe maxRetries are annotation-gated, diagnostics adds timing, and large results page through get_result.';
1378
1378
  const CALL_DESTRUCTIVE_DESC =
@@ -1396,9 +1396,11 @@ const SEARCH_WITH_DESCRIBE_DESC = `${SEARCH_DESC} Expand an ambiguous compact sh
1396
1396
  */
1397
1397
  const GUIDE_NOTES = {
1398
1398
  skills:
1399
- ' skills({}) also lists this deployment\'s per-connector usage guides as "connector:<connectorId>"; fetch the guide for a connector before working with it for the first time.',
1399
+ " skills({}) also lists this deployment's scoped connector guides; fetch only an exact name listed there or carried by discovery, never one inferred from a connector id.",
1400
1400
  search:
1401
- " A connector group carrying `guide` has a usage guide; fetch it with skills({ name: <guide> }).",
1401
+ " A result carrying `guide` also carries a bounded `guideSummary`. `guideRequired: true` is a hard stop: fetch that exact guide before calling. `guideRequiredReasons` explains why — `connector_required` and `approval_required` stand however you expand the schema; `schema_truncated` clears once describe returns the exact one. Otherwise fetch only when the summary names a connector convention relevant to the task. A complete, unambiguous read-only schema needs no otherwise-irrelevant guide fetch.",
1402
+ destructive:
1403
+ " Before a consequential call, inspect the address through discovery or describe and fetch any connector guide it names.",
1402
1404
  } as const;
1403
1405
 
1404
1406
  /** `base`, plus its guide note when any VISIBLE connector carries a guide. */
@@ -1533,7 +1535,11 @@ export function registerMetaTools(
1533
1535
  server.registerTool(
1534
1536
  "call_destructive_tool",
1535
1537
  {
1536
- description: CALL_DESTRUCTIVE_DESC,
1538
+ description: describedFor(
1539
+ registry,
1540
+ CALL_DESTRUCTIVE_DESC,
1541
+ "destructive",
1542
+ ),
1537
1543
  inputSchema: z.object({
1538
1544
  ...CALL_INPUT_SCHEMA,
1539
1545
  // Bounded above, but with no lower bound: a model that sends `""` or