@zackbart/connecta 0.22.3 → 0.24.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 (94) hide show
  1. package/AGENTS.md +5 -0
  2. package/CHANGELOG.md +82 -0
  3. package/README.md +19 -11
  4. package/dist/activity-friction.d.ts +3 -0
  5. package/dist/activity-friction.js +19 -0
  6. package/dist/activity.d.ts +11 -2
  7. package/dist/activity.js +15 -19
  8. package/dist/auth/downstream-oauth.d.ts +2 -1
  9. package/dist/auth/downstream-oauth.js +10 -1
  10. package/dist/branding.d.ts +67 -0
  11. package/dist/branding.js +176 -0
  12. package/dist/catalog-service.d.ts +1 -6
  13. package/dist/catalog-service.js +3 -53
  14. package/dist/connectors/remote-mcp.js +3 -5
  15. package/dist/credential-contract.d.ts +24 -0
  16. package/dist/credential-contract.js +1 -0
  17. package/dist/credential-rules.d.ts +85 -0
  18. package/dist/credential-rules.js +107 -0
  19. package/dist/credentials.d.ts +4 -100
  20. package/dist/credentials.js +3 -107
  21. package/dist/errors.d.ts +1 -1
  22. package/dist/execute.d.ts +5 -52
  23. package/dist/execute.js +40 -347
  24. package/dist/executors/quickjs-protocol.d.ts +0 -7
  25. package/dist/executors/quickjs-protocol.js +2 -10
  26. package/dist/executors/quickjs.js +1 -1
  27. package/dist/index.d.ts +23 -56
  28. package/dist/index.js +30 -58
  29. package/dist/invocation.d.ts +0 -33
  30. package/dist/invocation.js +56 -124
  31. package/dist/meta-tools.d.ts +7 -6
  32. package/dist/meta-tools.js +14 -21
  33. package/dist/module-contracts.d.ts +19 -0
  34. package/dist/module-contracts.js +1 -0
  35. package/dist/operator-ui/generated.js +2 -2
  36. package/dist/operator-ui/model.d.ts +6 -3
  37. package/dist/operator-ui/view.d.ts +2 -18
  38. package/dist/operator-ui/view.js +3 -20
  39. package/dist/registry.d.ts +4 -1
  40. package/dist/registry.js +8 -6
  41. package/dist/routes/activity.js +1 -1
  42. package/dist/routes/credentials.js +5 -2
  43. package/dist/routes/mcp.js +7 -51
  44. package/dist/routes/oauth-management.d.ts +2 -0
  45. package/dist/routes/oauth-management.js +108 -0
  46. package/dist/routes/oauth.d.ts +0 -1
  47. package/dist/routes/oauth.js +21 -121
  48. package/dist/routes/shared.d.ts +19 -17
  49. package/dist/routes/shared.js +48 -44
  50. package/dist/routes/ui.js +36 -33
  51. package/dist/server.d.ts +1 -2
  52. package/dist/server.js +7 -45
  53. package/dist/skills.d.ts +1 -1
  54. package/dist/skills.js +55 -19
  55. package/dist/types.d.ts +3 -15
  56. package/dist/ui.d.ts +15 -70
  57. package/dist/ui.js +176 -317
  58. package/dist/version.d.ts +1 -1
  59. package/dist/version.js +1 -1
  60. package/documentation/architecture.md +31 -26
  61. package/documentation/auth.md +65 -111
  62. package/documentation/call-admission.md +10 -11
  63. package/documentation/cloudflare.md +1 -1
  64. package/documentation/code-mode.md +65 -260
  65. package/documentation/connectors.md +8 -6
  66. package/documentation/linear.md +1 -1
  67. package/documentation/meta-tools.md +37 -18
  68. package/documentation/mixpanel.md +1 -1
  69. package/documentation/notion.md +2 -2
  70. package/documentation/operations.md +19 -23
  71. package/documentation/operator-ui.md +82 -104
  72. package/documentation/optional-modules-upgrade.md +243 -0
  73. package/documentation/provider-conventions.md +7 -5
  74. package/documentation/revenuecat.md +1 -1
  75. package/documentation/storage-and-credentials.md +59 -40
  76. package/documentation/stripe.md +1 -1
  77. package/documentation/upgrading.md +83 -8
  78. package/ethos.md +36 -43
  79. package/examples/worker/AGENTS.md +3 -1
  80. package/examples/worker/README.md +68 -84
  81. package/examples/worker/src/d1-activity.ts +1 -1
  82. package/examples/worker/src/index.ts +11 -6
  83. package/package.json +18 -2
  84. package/templates/node/AGENTS.md +8 -6
  85. package/templates/node/README.md +56 -67
  86. package/templates/node/package.json +1 -1
  87. package/templates/node/src/file-activity.ts +1 -1
  88. package/templates/node/src/index.ts +11 -12
  89. package/dist/access-tokens.d.ts +0 -31
  90. package/dist/access-tokens.js +0 -236
  91. package/dist/apps-shell.d.ts +0 -37
  92. package/dist/apps-shell.js +0 -174
  93. package/dist/routes/access-tokens.d.ts +0 -6
  94. package/dist/routes/access-tokens.js +0 -83
@@ -1,174 +0,0 @@
1
- /**
2
- * The one MCP Apps template connecta serves (`U5`, `U6`).
3
- *
4
- * A build-time string constant, not a file read at startup: the core is
5
- * Web-API-only so it runs unchanged on Workers, and the same bytes have to
6
- * serve everywhere. The shell is display-only: it renders whatever HTML a
7
- * program handed `connecta.ui` inside a nested `srcdoc` frame and forwards no
8
- * channel back from that frame to the host, so program-authored markup is
9
- * inert beyond its own pixels.
10
- *
11
- * The address carries a version segment because hosts are permitted to
12
- * prefetch and cache templates by URI: change these bytes, bump the version.
13
- */
14
- /** The only `ui://` URI in the system. No program input reaches it. */
15
- export const PROGRAM_UI_RESOURCE_URI = "ui://connecta/program-ui/v3";
16
- /** The mimeType the Apps spec requires of an HTML template. */
17
- export const PROGRAM_UI_MIME_TYPE = "text/html;profile=mcp-app";
18
- /**
19
- * The result `_meta` key carrying the payload (`U3`). A plain single-label
20
- * prefix rather than the reverse-DNS form MCP's SHOULD prefers: connecta has
21
- * no domain to reverse, and fabricating one to satisfy a SHOULD is a worse
22
- * answer than the shape the key format's MUST already permits.
23
- */
24
- export const PROGRAM_UI_META_KEY = "connecta/ui";
25
- /** The one extension identifier connecta advertises (`U11`). */
26
- export const MCP_APPS_EXTENSION = "io.modelcontextprotocol/ui";
27
- /**
28
- * The shell document. Dependency-free and deliberately small: it speaks the
29
- * Apps postMessage dialect (`ui/initialize`, `ui/notifications/initialized`,
30
- * `ui/notifications/tool-result`, `ui/notifications/size-changed`,
31
- * `ui/resource-teardown`), lifts `_meta["connecta/ui"].html` out of the
32
- * delivered tool result, and puts it in a frame. It declares no CSP domains,
33
- * so the host applies its restrictive default and the `srcdoc` frame inherits
34
- * `default-src 'none'`. The payload gets scripts and local interactivity, and
35
- * no network.
36
- */
37
- export const PROGRAM_UI_SHELL_HTML = `<!doctype html>
38
- <html lang="en">
39
- <head>
40
- <meta charset="utf-8" />
41
- <meta name="viewport" content="width=device-width, initial-scale=1" />
42
- <title>connecta program view</title>
43
- <style>
44
- html,
45
- body {
46
- margin: 0;
47
- padding: 0;
48
- background: transparent;
49
- }
50
- #program-view {
51
- display: block;
52
- width: 100%;
53
- min-height: 480px;
54
- border: 0;
55
- }
56
- </style>
57
- </head>
58
- <body>
59
- <iframe
60
- id="program-view"
61
- title="Program-rendered view"
62
- sandbox="allow-scripts"
63
- srcdoc=""
64
- ></iframe>
65
- <script>
66
- (function () {
67
- "use strict";
68
- // The host frame is the only peer this shell speaks to, in either
69
- // direction. The payload frame below is sandboxed to scripts alone,
70
- // with no same-origin escape, and is never handed a reply path:
71
- // anything it posts fails the source check and is dropped. There is
72
- // no bridge from program HTML to the host, by construction rather
73
- // than by validation.
74
- var host = window.parent;
75
- var view = document.getElementById("program-view");
76
- var initializeId = "connecta-ui-initialize";
77
- var lastWidth = 0;
78
- var lastHeight = 0;
79
-
80
- function send(message) {
81
- if (!host || host === window) return;
82
- host.postMessage(message, "*");
83
- }
84
-
85
- function notify(method, params) {
86
- send({ jsonrpc: "2.0", method: method, params: params });
87
- }
88
-
89
- // Program views are fixed-height by construction. The shell has no
90
- // bridge to the payload frame — that is the security posture, not an
91
- // omission — so it can never learn the payload's content height, and
92
- // what it reports here is its own box: the min-height above, unless
93
- // the host has given it more. Taller content scrolls inside the inner
94
- // frame rather than growing the view. Raising the min-height is the
95
- // only lever; a content-height signal would cost the isolation.
96
- function reportSize() {
97
- var width = Math.ceil(document.documentElement.clientWidth);
98
- var height = Math.ceil(document.documentElement.scrollHeight);
99
- if (width === lastWidth && height === lastHeight) return;
100
- lastWidth = width;
101
- lastHeight = height;
102
- notify("ui/notifications/size-changed", {
103
- width: width,
104
- height: height
105
- });
106
- }
107
-
108
- function payloadHtml(result) {
109
- if (!result || typeof result !== "object") return null;
110
- var meta = result._meta;
111
- if (!meta || typeof meta !== "object") return null;
112
- var payload = meta["connecta/ui"];
113
- if (!payload || typeof payload !== "object") return null;
114
- var html = payload.html;
115
- return typeof html === "string" && html.length > 0 ? html : null;
116
- }
117
-
118
- function render(params) {
119
- var html =
120
- payloadHtml(params) ||
121
- payloadHtml(params && params.result) ||
122
- payloadHtml(params && params.toolResult);
123
- if (html === null) return;
124
- view.srcdoc = html;
125
- reportSize();
126
- }
127
-
128
- window.addEventListener("message", function (event) {
129
- if (event.source !== host) return;
130
- var message = event.data;
131
- if (!message || message.jsonrpc !== "2.0") return;
132
- if (message.method === "ui/notifications/tool-result") {
133
- render(message.params);
134
- return;
135
- }
136
- if (message.method === "ui/resource-teardown") {
137
- // A host->view request, not a notification: the host waits for
138
- // this reply before it tears the view down. There is nothing to
139
- // release, so answer immediately rather than make it time out.
140
- if (message.id !== undefined && message.id !== null) {
141
- send({ jsonrpc: "2.0", id: message.id, result: {} });
142
- }
143
- return;
144
- }
145
- // Only a completed handshake earns "initialized". A JSON-RPC error
146
- // response carries the same id, and announcing initialization on one
147
- // would assert a handshake that never happened.
148
- if (message.id === initializeId && message.result !== undefined) {
149
- notify("ui/notifications/initialized", {});
150
- }
151
- });
152
-
153
- window.addEventListener("resize", reportSize);
154
- view.addEventListener("load", reportSize);
155
-
156
- // Every field here is required by the Apps initialize schema, and a
157
- // conforming host rejects the request outright when one is missing —
158
- // which would strand the shell before any tool result arrives.
159
- send({
160
- jsonrpc: "2.0",
161
- id: initializeId,
162
- method: "ui/initialize",
163
- params: {
164
- appInfo: { name: "connecta program view", version: "1" },
165
- appCapabilities: {},
166
- protocolVersion: "2026-01-26"
167
- }
168
- });
169
- reportSize();
170
- })();
171
- </script>
172
- </body>
173
- </html>
174
- `;
@@ -1,6 +0,0 @@
1
- import { type RouteContext } from "./shared.js";
2
- /**
3
- * Interactive-operator lifecycle for deployment access tokens. The token itself
4
- * is deliberately never an administrator credential and cannot reach here.
5
- */
6
- export declare function routeAccessTokens(context: RouteContext): Promise<Response | null>;
@@ -1,83 +0,0 @@
1
- import { authorizeUiAdmin, isSameOrigin, msg, privateJson, } from "./shared.js";
2
- async function readName(request) {
3
- if (!request.headers
4
- .get("content-type")
5
- ?.toLowerCase()
6
- .startsWith("application/json")) {
7
- return {
8
- ok: false,
9
- response: privateJson({ error: "Content-Type must be application/json" }, { status: 415 }),
10
- };
11
- }
12
- const raw = await request.text();
13
- if (raw.length > 1_000) {
14
- return {
15
- ok: false,
16
- response: privateJson({ error: "request body is too large" }, { status: 413 }),
17
- };
18
- }
19
- try {
20
- const body = JSON.parse(raw);
21
- return { ok: true, name: body.name };
22
- }
23
- catch {
24
- return {
25
- ok: false,
26
- response: privateJson({ error: "invalid JSON body" }, { status: 400 }),
27
- };
28
- }
29
- }
30
- /**
31
- * Interactive-operator lifecycle for deployment access tokens. The token itself
32
- * is deliberately never an administrator credential and cannot reach here.
33
- */
34
- export async function routeAccessTokens(context) {
35
- const match = /^\/ui\/access-tokens(?:\/([0-9a-f-]{36}))?$/.exec(context.path);
36
- if (!match)
37
- return null;
38
- const { request, baseUrl, opts } = context;
39
- if (request.method === "OPTIONS") {
40
- return privateJson({ error: "CORS is not allowed" }, { status: 403 });
41
- }
42
- if (!opts.accessTokens) {
43
- return privateJson({ error: "access token management is not configured" }, { status: 404 });
44
- }
45
- const mutating = request.method !== "GET";
46
- if (mutating && !isSameOrigin(request, baseUrl)) {
47
- return privateJson({ error: "same-origin request required" }, { status: 403 });
48
- }
49
- const admin = await authorizeUiAdmin(request, baseUrl, opts.auth, "access token management", context.runtimeContext, opts.identity);
50
- if (!admin.ok)
51
- return admin.response;
52
- const id = match[1];
53
- try {
54
- if (!id && request.method === "GET") {
55
- return privateJson({ accessTokens: await opts.accessTokens.list() });
56
- }
57
- if (!id && request.method === "POST") {
58
- const input = await readName(request);
59
- if (!input.ok)
60
- return input.response;
61
- return privateJson(await opts.accessTokens.create(input.name, admin.principal ?? admin.userId), { status: 201 });
62
- }
63
- if (id && request.method === "PUT") {
64
- const input = await readName(request);
65
- if (!input.ok)
66
- return input.response;
67
- const accessToken = await opts.accessTokens.rename(id, input.name);
68
- return accessToken
69
- ? privateJson({ accessToken })
70
- : privateJson({ error: "unknown access token" }, { status: 404 });
71
- }
72
- if (id && request.method === "DELETE") {
73
- const accessToken = await opts.accessTokens.revoke(id, admin.userId);
74
- return accessToken
75
- ? privateJson({ accessToken })
76
- : privateJson({ error: "unknown access token" }, { status: 404 });
77
- }
78
- return privateJson({ error: "method not allowed" }, { status: 405 });
79
- }
80
- catch (error) {
81
- return privateJson({ error: msg(error) }, { status: 400 });
82
- }
83
- }