@zackbart/connecta 0.16.0 → 0.16.1
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.
- package/AGENTS.md +12 -5
- package/CHANGELOG.md +187 -0
- package/README.md +6 -1
- package/dist/catalog-service.js +41 -4
- package/dist/catalog.d.ts +11 -0
- package/dist/catalog.js +20 -0
- package/dist/errors.d.ts +30 -2
- package/dist/errors.js +1 -0
- package/dist/providers/cloudflare.js +13 -25
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/documentation/cloudflare.md +40 -8
- package/documentation/code-first-exploration.md +2 -2
- package/documentation/code-mode.md +2 -2
- package/documentation/meta-tools.md +7 -1
- package/documentation/notion.md +7 -2
- package/documentation/operations.md +53 -11
- package/documentation/provider-audit.md +1 -1
- package/documentation/provider-conventions.md +42 -6
- package/documentation/upgrading.md +454 -0
- package/ethos.md +1 -1
- package/examples/worker/README.md +9 -3
- package/package.json +7 -2
- package/templates/node/AGENTS.md +5 -0
- package/templates/node/package.json +1 -1
|
@@ -229,7 +229,13 @@ results explain that no single tool covered every term and recommend splitting
|
|
|
229
229
|
distinct intents. A true negative says that no matching capability is
|
|
230
230
|
configured and recommends refining, connector-scoping, or browsing; when a
|
|
231
231
|
connector catalog was unavailable, the response includes
|
|
232
|
-
`unavailableConnectorCount` instead of making that stronger claim. A
|
|
232
|
+
`unavailableConnectorCount` instead of making that stronger claim. A no-match
|
|
233
|
+
query whose terms name a configured connector's `id` or `title` never makes it
|
|
234
|
+
either: connector identity is not in the lexical index — indexing it would move
|
|
235
|
+
ranking for every query that already matches tools — so instead the guidance on
|
|
236
|
+
an unscoped miss names up to three such connectors by ID and sends the caller
|
|
237
|
+
to a scoped browse. Identity affects that one sentence and nothing else: no
|
|
238
|
+
ranking, no result, and no new field. A search
|
|
233
239
|
explicitly scoped to that unavailable connector also receives `catalogError` —
|
|
234
240
|
the bounded classified failure (`code`, `message`, `retryable`, and any
|
|
235
241
|
`retryAfterMs`) so the caller can tell a transient outage from one a deployment
|
package/documentation/notion.md
CHANGED
|
@@ -166,7 +166,7 @@ should do next, and two of Notion's are easy to mistranslate.
|
|
|
166
166
|
| 400 (`validation_error`, `invalid_json`, `invalid_request`, `missing_version`, …) | `invalid_args` | every documented 400 is a malformed request |
|
|
167
167
|
| 401 `unauthorized` | `auth_required` | the token is missing or invalid |
|
|
168
168
|
| 403 `restricted_resource` | `connector_call_failed`, non-retryable | **not** `auth_required` |
|
|
169
|
-
| 404 `object_not_found` | `connector_call_failed`, non-retryable | overloaded
|
|
169
|
+
| 404 `object_not_found` | `connector_call_failed`, non-retryable | overloaded — deliberately **not** `not_found`; see below |
|
|
170
170
|
| 409 `conflict_error` | `unavailable`, retryable | Notion says to retry |
|
|
171
171
|
| 429 `rate_limited` | `rate_limited` + `retryAfterMs` | `Retry-After` seconds → ms |
|
|
172
172
|
| 529 `service_overload` | `unavailable` + `retryAfterMs` | back off like a 429 |
|
|
@@ -184,7 +184,12 @@ whose message says an operator must change it in Notion.
|
|
|
184
184
|
object that does not exist and for one that exists but has not been shared with
|
|
185
185
|
the integration, and it will not say which. The message says both, because
|
|
186
186
|
treating it as deletion is exactly how an agent concludes a page is gone when
|
|
187
|
-
it was simply never shared.
|
|
187
|
+
it was simply never shared. This is why the row above does not use `not_found`,
|
|
188
|
+
which exists precisely to say "it is not there": the qualifier on that code
|
|
189
|
+
([H11](./provider-conventions.md#h11--errors-are-mapped-to-what-the-caller-does-next))
|
|
190
|
+
is that the provider must tell absence apart from a permission gap, and Notion
|
|
191
|
+
does not. A program that skipped this id as missing would be right about half
|
|
192
|
+
the time, which is the half that matters.
|
|
188
193
|
|
|
189
194
|
## Rate limiting
|
|
190
195
|
|
|
@@ -18,6 +18,15 @@ rather than serving a smaller surface
|
|
|
18
18
|
`new DynamicWorkerExecutor({ loader: env.LOADER })` from
|
|
19
19
|
`@cloudflare/codemode`.
|
|
20
20
|
|
|
21
|
+
Both executor packages are optional peers: they never install with connecta,
|
|
22
|
+
and a deployment installs the one its runtime needs. The manifest publishes the
|
|
23
|
+
range each release supports — `^0.32.0` for `quickjs-emscripten`,
|
|
24
|
+
`^0.4.4 || ^0.5.0` for `@cloudflare/codemode` — so npm answers the version
|
|
25
|
+
question at install time rather than leaving a deployment to discover the skew
|
|
26
|
+
when a program runs ([#376](https://github.com/zackbart/connecta/issues/376)).
|
|
27
|
+
The version this repository tests against is one the published range admits,
|
|
28
|
+
and `test/package-surface.test.ts` fails if the two ever drift apart.
|
|
29
|
+
|
|
21
30
|
There are exactly two deployment shapes.
|
|
22
31
|
[`templates/node/`](../templates/node/) is what `connecta init` copies — the
|
|
23
32
|
one standalone Node project, Docker-ready rather than Docker-only — and
|
|
@@ -108,9 +117,13 @@ deployment repository
|
|
|
108
117
|
```
|
|
109
118
|
|
|
110
119
|
An upgrade is an intentional dependency change followed by a normal build.
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
120
|
+
Doing it to a deployment somebody else generated — reading its pin, diffing it
|
|
121
|
+
against the template generation it came from, and crossing the version
|
|
122
|
+
boundaries that break construction — is [upgrading](./upgrading.md), which is
|
|
123
|
+
written for the agent sitting inside that deployment rather than inside this
|
|
124
|
+
repository. Instances must not share KV namespaces, D1 databases, secrets, or
|
|
125
|
+
encryption keys. Keeping deployment configuration private is sensible even
|
|
126
|
+
though this package is public.
|
|
114
127
|
|
|
115
128
|
## Verification
|
|
116
129
|
|
|
@@ -118,7 +131,7 @@ package is public.
|
|
|
118
131
|
|
|
119
132
|
| Script | What it gates |
|
|
120
133
|
| --- | --- |
|
|
121
|
-
| `check:docs` | local Markdown targets and fragments
|
|
134
|
+
| `check:docs` | local Markdown targets and fragments — including the `github.com` and `raw.githubusercontent.com` URLs that point back into this repository — guide and ethos size caps, duplicate heading anchors, a resurrected `docs/`, stale manual references |
|
|
122
135
|
| `check:operator-ui` | the committed browser bundle matches its source, byte for byte |
|
|
123
136
|
| `check:lint` | Oxlint's correctness category only — style is authored, not enforced |
|
|
124
137
|
| `check:unused` | Knip's unused-export and dependency gate |
|
|
@@ -130,11 +143,38 @@ package is public.
|
|
|
130
143
|
`npm run release:check` adds `check:security` (`npm audit --omit=dev
|
|
131
144
|
--audit-level=moderate`) and `check:package`, and is what CI runs on every push
|
|
132
145
|
and pull request. `check:package` packs the tarball, asserts the required files
|
|
133
|
-
are in it and that no
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
146
|
+
are in it and that no unshippable path leaked in — including any
|
|
147
|
+
Cloudflare-named connector or storage path (`connectors/cloudflare`,
|
|
148
|
+
`storage/cloudflare`) anywhere in the artifact, `dist/` and `examples/` alike —
|
|
149
|
+
derives the shipped guide list from which guides still carry a stub marker,
|
|
150
|
+
hands the packed path list to `scripts/check-packed-links.mjs`, and then runs
|
|
151
|
+
`connecta init` and builds and runs the generated deployment's own container.
|
|
152
|
+
|
|
153
|
+
That last step enforces the packed-link policy, which is one sentence: **every
|
|
154
|
+
relative link in shipped Markdown must resolve to a path the tarball carries,
|
|
155
|
+
and a target that is repository-only is cited as an absolute
|
|
156
|
+
`https://github.com/zackbart/connecta/blob/main/...` URL** (the
|
|
157
|
+
`raw.githubusercontent.com` form for an image, which is how the README hero
|
|
158
|
+
still renders on npmjs.com). The tarball is built output, not a checkout: it
|
|
159
|
+
carries no `eval/`, `test/`, `scripts/`, or `assets/`, so a relative pointer
|
|
160
|
+
into any of them is a dead end for the reader who installed the package, and
|
|
161
|
+
the fix is never to ship those directories — that would undo the trim of
|
|
162
|
+
[#346](https://github.com/zackbart/connecta/issues/346). A repository URL keeps
|
|
163
|
+
the citation verifiable in both directions: an outside reader can follow it, and
|
|
164
|
+
`check:docs` resolves it back to the checkout and fails when the cited file
|
|
165
|
+
moves ([#378](https://github.com/zackbart/connecta/issues/378)). `CHANGELOG.md`
|
|
166
|
+
is exempt from both gates, because release notes quote the paths that existed
|
|
167
|
+
when they shipped.
|
|
168
|
+
|
|
169
|
+
The Worker example ships in the tarball, its Cloudflare KV and D1 adapters
|
|
170
|
+
included: it is the Workers starting template a consumer copies. That is not a
|
|
171
|
+
hole in the published surface, because nothing under `examples/` appears in the
|
|
172
|
+
`exports` map — every export target resolves into `dist/`, so those adapters
|
|
173
|
+
are reference source rather than an importable subpath. They also clear the
|
|
174
|
+
platform-specific gate above on their names (`cloudflare-kv.ts`,
|
|
175
|
+
`d1-activity.ts`) rather than by exemption: that gate is a blunt pattern over
|
|
176
|
+
the whole artifact, so an example file renamed into `storage/cloudflare` would
|
|
177
|
+
fail the pack even though nothing about the published surface had changed.
|
|
138
178
|
|
|
139
179
|
Two more runners are deliberately outside `check`:
|
|
140
180
|
|
|
@@ -221,13 +261,14 @@ justification for *not* re-running it in workerd, so "it was easier" is not one.
|
|
|
221
261
|
| Suite | Covers | Why Node |
|
|
222
262
|
| --- | --- | --- |
|
|
223
263
|
| `deployment-shapes.test.ts` | the Worker as the only example, one Node template that is also its own container, the same source running locally and in the container, the full operator surface in both, a template that cannot start on its own `.env.example`, a Worker README naming every optional peer its entrypoint imports, and the initializer's `.gitignore` staying in step | walks the template and example trees with Node filesystem APIs |
|
|
224
|
-
| `doc-links.test.ts` | the documentation checker itself — local file and fragment resolution, duplicate heading slugs, fenced-code exclusion, and useful failures | spawns the Node checker against filesystem fixtures |
|
|
264
|
+
| `doc-links.test.ts` | the documentation checker itself — local file and fragment resolution, repository URLs resolved back to the checkout, duplicate heading slugs, fenced-code exclusion, and useful failures | spawns the Node checker against filesystem fixtures |
|
|
225
265
|
| `doctor-cli.test.ts` | `connecta doctor`'s executor line end to end — the sandbox the deployment reports is the one named, an unidentifiable executor gets an executor-neutral line, and a hostile name is bounded and stripped before it reaches a terminal | spawns the CLI against a Node HTTP deployment over real sockets |
|
|
226
266
|
| `drift-check.test.ts` | the maintainer drift checker — recorded touched endpoints, a quiet revision bump, clear failures for an unavailable spec/manifest/credential, `$ref` traversal, and one well-formed row per endpoint | spawns the Node checker against filesystem fixtures |
|
|
227
267
|
| `file-storage.test.ts` | `fileStorage()` across instances, logical TTL plus physical pruning without clobbering a newer value, and corrupt-file quarantine | exercises the Node filesystem storage adapter |
|
|
228
268
|
| `guest-api-contract-quickjs.test.ts` | the shared guest-contract cases on the real QuickJS executor | runs the contract cases on the Node QuickJS executor |
|
|
229
269
|
| `node.test.ts` | the `listen()` adapter propagating an HTTP client disconnect through the Web `Request` and the MCP handler into a program's connector call, releasing both admission permits | exercises the Node HTTP adapter over real TCP sockets |
|
|
230
|
-
| `
|
|
270
|
+
| `packed-links.test.ts` | the packed-link gate itself — shipped targets and repository URLs accepted, relative links into unshipped paths and directories rejected with the citation to write instead, reference definitions seen, fenced examples ignored, the changelog exempt | spawns the Node packed-link gate against filesystem fixtures |
|
|
271
|
+
| `package-surface.test.ts` | the published boundary — built output shipped, the `exports` map carrying exactly the documented subpaths plus `./package.json`, only generic factories, platform storage kept in examples, Clerk and QuickJS behind optional subpaths, every provider independently importable, and the Cloudflare provider free of bare specifiers | walks the package tree with Node filesystem APIs |
|
|
231
272
|
| `purity.test.ts` | the import-graph guardrail ([architecture](./architecture.md#import-graph-purity)) — the core stays Workers-clean | walks the source import graph with Node filesystem APIs |
|
|
232
273
|
| `quickjs-child-entry.test.ts` | a missing QuickJS child entry failing before `fork()`, with the expected path and the bundler-externalization constraint | mocks Node child-process and filesystem APIs |
|
|
233
274
|
| `quickjs-child-stderr.test.ts` | abnormal child exits retaining only an 8 KiB stderr tail, included in the parent-side diagnostic | mocks Node child-process streams |
|
|
@@ -235,6 +276,7 @@ justification for *not* re-running it in workerd, so "it was easier" is not one.
|
|
|
235
276
|
| `quickjs-log-limits.test.ts` | bounded `console.*` capture — per-entry cut, cumulative character and transport budgets, escape-heavy floods preserving the guest result | runs the Node QuickJS child-process executor |
|
|
236
277
|
| `suite-partition.test.ts` | this partition, including itself: every `*.test.ts` in exactly one list, stale entries and empty reasons refused | walks the test directory to guard the partition |
|
|
237
278
|
| `template-file-activity.test.ts` | the Node template's own activity store — persistence across restart, torn-line repair, newest-first paging, and compaction past the slack window | runs it against real files |
|
|
279
|
+
| `upgrade-guide.test.ts` | the [upgrade guide](./upgrading.md)'s claims about somebody else's deployment — the generated file inventory, the seven tool names doctor demands, version boundaries that actually shipped, a bump target that is this release, and the three places a reader finds it | reads the guide, the template tree, and the CLI with Node filesystem APIs |
|
|
238
280
|
| `version.test.ts` | `CONNECTA_VERSION` matching `package.json` | reads `package.json` with Node filesystem APIs |
|
|
239
281
|
|
|
240
282
|
### Outside `npm run check`
|
|
@@ -14,7 +14,7 @@ error, not a finding, so the proxy reports have no H rows.
|
|
|
14
14
|
Every miss below is fixed in the same change that recorded it
|
|
15
15
|
([#342](https://github.com/zackbart/connecta/issues/342)), except where the row
|
|
16
16
|
says otherwise. The mechanically checkable half of the hand-written bar is now
|
|
17
|
-
a test — [`test/provider-conventions.test.ts`](
|
|
17
|
+
a test — [`test/provider-conventions.test.ts`](https://github.com/zackbart/connecta/blob/main/test/provider-conventions.test.ts)
|
|
18
18
|
walks the shipped surface of both `api()` providers on every run, so these
|
|
19
19
|
verdicts cannot rot quietly back into prose. The proxies' mechanical rows live
|
|
20
20
|
in their own suites, because what they assert is the wrapper's identity,
|
|
@@ -64,7 +64,9 @@ floor. From `src/catalog.ts` and `src/catalog-service.ts`:
|
|
|
64
64
|
fallback summary for a guide with no usable body line. Routing facts belong
|
|
65
65
|
in the title and the guide's first line; a routing fact that lives only in
|
|
66
66
|
the connector description has been written into a field the model does not
|
|
67
|
-
read.
|
|
67
|
+
read. Neither the `id` nor the `title` is a lexical document, so a term drawn
|
|
68
|
+
from one of them is not a search hit — it is a no-match whose guidance names
|
|
69
|
+
the connector and points at a scoped browse.
|
|
68
70
|
|
|
69
71
|
Two construction-time checks enforce the floor beneath all of this. The hard
|
|
70
72
|
one is `api()` itself: since
|
|
@@ -108,7 +110,10 @@ write never hides behind a neutral one. Escape hatches are named
|
|
|
108
110
|
`<provider>_api_<class>` so they sort together and read as generic.
|
|
109
111
|
|
|
110
112
|
*Why:* the name is the only thing lexical search indexes besides the
|
|
111
|
-
description, and it is what an agent skims first.
|
|
113
|
+
description, and it is what an agent skims first. A connector's `id` and
|
|
114
|
+
`title` are displayed, not indexed — a search for one of them matches no tool,
|
|
115
|
+
and the miss is answered by guidance naming that connector rather than by a
|
|
116
|
+
ranked result. *Cost:* wrong-tool selection.
|
|
112
117
|
|
|
113
118
|
### H3 — The selection sentence fits in 160 characters; the whole description in 240
|
|
114
119
|
|
|
@@ -217,6 +222,37 @@ convenient reading. A call that can only fail is refused locally as
|
|
|
217
222
|
`invalid_args` before the round trip. Provider error prose is never parsed to
|
|
218
223
|
invent a classification.
|
|
219
224
|
|
|
225
|
+
**A downstream 404 is `not_found` — when the provider means it.** The code
|
|
226
|
+
exists because the next move is none of the others': you do not wait, you do
|
|
227
|
+
not send the agent to `authorize_connector`, you do not repair the argument
|
|
228
|
+
object. You re-address — look the id up again, or accept the absence and carry
|
|
229
|
+
on — and a program looping over ids inside `execute_code` can continue past
|
|
230
|
+
`not_found` where `connector_call_failed` would have to abort the run, reading
|
|
231
|
+
the code off a `connecta.batch` entry's `errorDetails` rather than off a caught
|
|
232
|
+
error, which the guest bridge has already stripped to prose. That
|
|
233
|
+
control-flow difference is the H11 test being met; it is not a label for the
|
|
234
|
+
cause.
|
|
235
|
+
|
|
236
|
+
The qualifier is the whole rule. Map a status to `not_found` only where the
|
|
237
|
+
provider distinguishes absence from a permission gap. Where it does not —
|
|
238
|
+
Notion returns `object_not_found` both for an object that is gone and for one
|
|
239
|
+
that was never shared with the integration, and will not say which — the honest
|
|
240
|
+
code stays `connector_call_failed` (or `auth_required`, where a credential
|
|
241
|
+
really is the fix) and the message states the ambiguity, exactly as the
|
|
242
|
+
paragraph above requires. Cloudflare is the other side of the pair: a token
|
|
243
|
+
that may not touch a resource is refused with 401 or 403, so its 404 is an
|
|
244
|
+
absence and maps to `not_found`. Neither connector's mapping changed shape when
|
|
245
|
+
the code arrived; one of them changed codes.
|
|
246
|
+
|
|
247
|
+
Two boundaries. `not_found` is about a resource the *downstream* owns: an
|
|
248
|
+
address connecta cannot resolve is already framed as `unknown_address` or
|
|
249
|
+
`unknown_tool` and never reaches a connector. And it never appears on the
|
|
250
|
+
hosted-MCP proxy path, because `P1` forbids re-shaping downstream framing and
|
|
251
|
+
prose is never parsed to invent a classification — a proxied server's own
|
|
252
|
+
missing-resource error arrives as that server wrote it. The two paths do not
|
|
253
|
+
diverge on the rule; they diverge on who is entitled to apply it, which is the
|
|
254
|
+
same split every other code already has.
|
|
255
|
+
|
|
220
256
|
*Why:* a misrouted error sends an agent down a recovery path that cannot
|
|
221
257
|
succeed. *Cost:* argument retries.
|
|
222
258
|
|
|
@@ -508,7 +544,7 @@ whether or not anybody noticed it arrived.
|
|
|
508
544
|
([#351](https://github.com/zackbart/connecta/issues/351)): a human at a laptop,
|
|
509
545
|
before a release, with local credentials and the published specifications in
|
|
510
546
|
front of them. It lives in
|
|
511
|
-
[`scripts/drift-check.mjs`](
|
|
547
|
+
[`scripts/drift-check.mjs`](https://github.com/zackbart/connecta/blob/main/scripts/drift-check.mjs) and ships nowhere —
|
|
512
548
|
`scripts/` is outside the package, no runtime module imports it, and nothing it
|
|
513
549
|
reads becomes a runtime input.
|
|
514
550
|
|
|
@@ -528,7 +564,7 @@ message naming it rather than reporting an empty catalog as mass removal.
|
|
|
528
564
|
|
|
529
565
|
**Touched endpoints.** A hand-written provider is written against a published
|
|
530
566
|
OpenAPI document and calls a few dozen of its operations, so
|
|
531
|
-
[`scripts/drift/`](
|
|
567
|
+
[`scripts/drift/`](https://github.com/zackbart/connecta/tree/main/scripts/drift) commits exactly those: method, path, the
|
|
532
568
|
specification revision a release reviewed the endpoint at, whether the
|
|
533
569
|
operation was deprecated at that revision, and a digest of that endpoint's
|
|
534
570
|
contract. `--specs` fetches each provider's published document and reports four
|
|
@@ -580,7 +616,7 @@ the reason). A convention is never quietly skipped, and an accepted miss is
|
|
|
580
616
|
recorded as a provider-specific exception with its argument, not left blank.
|
|
581
617
|
Its five reports live in [provider-audit.md](./provider-audit.md), and the
|
|
582
618
|
mechanically checkable half of the hand-written bar runs on every test run in
|
|
583
|
-
[`test/provider-conventions.test.ts`](
|
|
619
|
+
[`test/provider-conventions.test.ts`](https://github.com/zackbart/connecta/blob/main/test/provider-conventions.test.ts) —
|
|
584
620
|
so a convention that was met once stays met, or fails loudly.
|
|
585
621
|
|
|
586
622
|
Hand-written providers are audited against H1–H14; hosted-MCP proxies against
|
|
@@ -620,7 +656,7 @@ beats the escape hatch — is a reading, and the audit reports it as one. The
|
|
|
620
656
|
Cloudflare keep/prune half of that judgment was made in
|
|
621
657
|
[#350](https://github.com/zackbart/connecta/issues/350): 30 keep, 18 improve,
|
|
622
658
|
3 prune, measured per tool in
|
|
623
|
-
[`eval/current-version/results/issue-350-evidence.md`](
|
|
659
|
+
[`eval/current-version/results/issue-350-evidence.md`](https://github.com/zackbart/connecta/blob/main/eval/current-version/results/issue-350-evidence.md).
|
|
624
660
|
Its eighteen `improve` rows are H8 and H9 misses on tools that clearly earn
|
|
625
661
|
their place, so they are this audit's work, not a second removal argument.
|
|
626
662
|
|