@zackbart/connecta 0.24.4 → 0.25.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 (107) hide show
  1. package/AGENTS.md +40 -10
  2. package/CHANGELOG.md +253 -0
  3. package/dist/advertised-schema.js +53 -0
  4. package/dist/auth/downstream-oauth.js +490 -106
  5. package/dist/call-admission.js +139 -113
  6. package/dist/catalog-service.js +141 -105
  7. package/dist/catalog.js +258 -33
  8. package/dist/concurrency.js +24 -23
  9. package/dist/connector-scope.js +6 -37
  10. package/dist/connectors/api.d.ts +2 -2
  11. package/dist/connectors/remote-mcp.d.ts +6 -5
  12. package/dist/connectors/remote-mcp.js +317 -241
  13. package/dist/credential-contract.d.ts +9 -0
  14. package/dist/credential-rules.js +2 -2
  15. package/dist/credentials.d.ts +6 -1
  16. package/dist/credentials.js +45 -3
  17. package/dist/execute.js +363 -257
  18. package/dist/executor-admission.js +67 -50
  19. package/dist/executors/quickjs-runtime.js +4 -2
  20. package/dist/executors/quickjs.js +251 -210
  21. package/dist/fix-prompt.js +37 -0
  22. package/dist/index.d.ts +10 -1
  23. package/dist/index.js +51 -20
  24. package/dist/invocation.js +324 -285
  25. package/dist/meta-tools.js +206 -92
  26. package/dist/oauth-callback-outcome.js +94 -0
  27. package/dist/oauth-sealing.js +29 -0
  28. package/dist/operator-ui/fix-prompts.js +87 -0
  29. package/dist/operator-ui/generated.js +2 -2
  30. package/dist/operator-ui/model.d.ts +46 -1
  31. package/dist/operator-ui/setup-commands.js +53 -0
  32. package/dist/operator-ui/view.js +38 -2
  33. package/dist/program-source.js +205 -0
  34. package/dist/providers/notion.js +2 -2
  35. package/dist/providers/revenuecat.js +32 -5
  36. package/dist/providers/stripe.d.ts +3 -2
  37. package/dist/providers/vercel.js +1 -1
  38. package/dist/registry.d.ts +1 -1
  39. package/dist/registry.js +305 -260
  40. package/dist/routes/activity.js +120 -137
  41. package/dist/routes/credentials.js +174 -163
  42. package/dist/routes/mcp.js +129 -70
  43. package/dist/routes/oauth-management.js +60 -71
  44. package/dist/routes/oauth.js +44 -16
  45. package/dist/routes/operator.js +82 -0
  46. package/dist/routes/shared.d.ts +2 -0
  47. package/dist/routes/ui-data.js +210 -0
  48. package/dist/routes/ui.js +64 -32
  49. package/dist/runtime/admission.js +43 -0
  50. package/dist/runtime/call-admission.js +67 -0
  51. package/dist/runtime/connector-scope.js +72 -0
  52. package/dist/runtime/run.js +174 -0
  53. package/dist/runtime/services.js +130 -0
  54. package/dist/runtime/storage.js +66 -0
  55. package/dist/server.js +111 -89
  56. package/dist/skills.js +1 -1
  57. package/dist/storage/file.js +39 -2
  58. package/dist/storage/memory.js +28 -16
  59. package/dist/timeout.js +17 -47
  60. package/dist/types.d.ts +27 -7
  61. package/dist/ui.d.ts +16 -2
  62. package/dist/ui.js +50 -166
  63. package/dist/url-safety.js +157 -0
  64. package/dist/version.d.ts +1 -1
  65. package/dist/version.js +1 -1
  66. package/documentation/architecture.md +184 -10
  67. package/documentation/auth.md +80 -0
  68. package/documentation/code-mode.md +69 -24
  69. package/documentation/meta-tools.md +164 -27
  70. package/ethos.md +44 -47
  71. package/examples/worker/README.md +51 -5
  72. package/examples/worker/src/d1-storage.ts +116 -0
  73. package/examples/worker/src/index.ts +6 -6
  74. package/examples/worker/wrangler.jsonc +16 -4
  75. package/package.json +11 -3
  76. package/templates/node/package.json +1 -1
  77. package/dist/auth/downstream-oauth.d.ts +0 -200
  78. package/dist/catalog-fingerprint.d.ts +0 -19
  79. package/dist/catalog-limits.d.ts +0 -9
  80. package/dist/catalog-service.d.ts +0 -263
  81. package/dist/catalog.d.ts +0 -87
  82. package/dist/concurrency.d.ts +0 -3
  83. package/dist/connectors/guarded-fetch.d.ts +0 -96
  84. package/dist/credential-rules.d.ts +0 -85
  85. package/dist/execute.d.ts +0 -154
  86. package/dist/executor-result.d.ts +0 -10
  87. package/dist/executors/quickjs-child.d.ts +0 -1
  88. package/dist/executors/quickjs-protocol.d.ts +0 -67
  89. package/dist/favicon.d.ts +0 -1
  90. package/dist/identity.d.ts +0 -4
  91. package/dist/invocation.d.ts +0 -74
  92. package/dist/mcp-result.d.ts +0 -8
  93. package/dist/meta-tools.d.ts +0 -129
  94. package/dist/operator-ui/generated.d.ts +0 -2
  95. package/dist/operator-ui/view.d.ts +0 -188
  96. package/dist/result-shapes.d.ts +0 -13
  97. package/dist/retired-toolkits.d.ts +0 -2
  98. package/dist/routes/activity.d.ts +0 -2
  99. package/dist/routes/credentials.d.ts +0 -2
  100. package/dist/routes/mcp.d.ts +0 -10
  101. package/dist/routes/oauth-management.d.ts +0 -2
  102. package/dist/routes/oauth.d.ts +0 -2
  103. package/dist/routes/ui.d.ts +0 -2
  104. package/dist/server.d.ts +0 -9
  105. package/dist/skills.d.ts +0 -44
  106. package/dist/timeout.d.ts +0 -21
  107. package/dist/tool-safety.d.ts +0 -9
@@ -1,3 +1,6 @@
1
+ import { Deferred, Duration, Effect } from "effect";
2
+ import { admit, provideAdmissionProgram } from "./runtime/admission.js";
3
+ import { fromSignal, runEdge } from "./runtime/run.js";
1
4
  /**
2
5
  * A stable, machine-readable admission failure. Overload is retryable; caller
3
6
  * cancellation and shutdown are terminal for this invocation.
@@ -98,57 +101,15 @@ export class AdmissionController {
98
101
  };
99
102
  }
100
103
  acquire(options = {}) {
101
- if (this.closed) {
102
- this.closedTotal++;
103
- return Promise.reject(new ExecutorAdmissionError("executor_closed", "Executor is shutting down."));
104
- }
105
- if (options.signal?.aborted) {
106
- this.cancelledTotal++;
107
- return Promise.reject(new ExecutorAdmissionError("executor_cancelled", "Execution was cancelled before admission."));
108
- }
109
- if (this.active < this.concurrency) {
110
- this.active++;
111
- this.admittedTotal++;
112
- return Promise.resolve(this.makeLease(0));
113
- }
114
- if (this.waiters.length >= this.maxQueueSize) {
115
- this.rejectedTotal++;
116
- return Promise.reject(this.overloaded("Executor queue is full."));
117
- }
118
- return new Promise((resolve, reject) => {
119
- const waiter = {
120
- queuedAt: Date.now(),
121
- resolve,
122
- reject,
123
- ...(options.signal ? { signal: options.signal } : {}),
124
- };
125
- waiter.onAbort = () => {
126
- if (!this.remove(waiter))
127
- return;
128
- this.cleanup(waiter);
129
- this.cancelledTotal++;
130
- reject(new ExecutorAdmissionError("executor_cancelled", "Execution was cancelled while queued."));
131
- };
132
- options.signal?.addEventListener("abort", waiter.onAbort, { once: true });
133
- waiter.timer = setTimeout(() => {
134
- if (!this.remove(waiter))
135
- return;
136
- this.cleanup(waiter);
137
- this.rejectedTotal++;
138
- reject(this.overloaded(`Executor admission timed out after ${this.queueTimeoutMs}ms.`));
139
- }, this.queueTimeoutMs);
140
- this.waiters.push(waiter);
141
- this.queuedTotal++;
142
- });
104
+ return runEdge(admit(this, options));
143
105
  }
144
106
  close() {
145
107
  if (this.closed)
146
108
  return;
147
109
  this.closed = true;
148
110
  for (const waiter of this.waiters.splice(0)) {
149
- this.cleanup(waiter);
150
111
  this.closedTotal++;
151
- waiter.reject(new ExecutorAdmissionError("executor_closed", "Executor is shutting down."));
112
+ Deferred.doneUnsafe(waiter.outcome, Effect.fail(new ExecutorAdmissionError("executor_closed", "Executor is shutting down.")));
152
113
  }
153
114
  }
154
115
  overloaded(message) {
@@ -176,14 +137,13 @@ export class AdmissionController {
176
137
  const waiter = this.waiters.shift();
177
138
  if (!waiter)
178
139
  return;
179
- this.cleanup(waiter);
180
140
  const waitMs = Math.max(0, Date.now() - waiter.queuedAt);
181
141
  this.admittedTotal++;
182
142
  this.queueWaitCount++;
183
143
  this.queueWaitTotalMs += waitMs;
184
144
  this.queueWaitMaxMs = Math.max(this.queueWaitMaxMs, waitMs);
185
145
  this.active++;
186
- waiter.resolve(this.makeLease(waitMs));
146
+ Deferred.doneUnsafe(waiter.outcome, Effect.succeed(this.makeLease(waitMs)));
187
147
  }
188
148
  remove(waiter) {
189
149
  const index = this.waiters.indexOf(waiter);
@@ -192,12 +152,69 @@ export class AdmissionController {
192
152
  this.waiters.splice(index, 1);
193
153
  return true;
194
154
  }
155
+ // The waiting fiber was interrupted — an Effect caller's scope closed, not a
156
+ // signal. Withdraw the waiter if it is still queued; if release() handed it
157
+ // a slot in the same breath, give the slot back, because nobody is left to
158
+ // receive the lease. (A line comment, not JSDoc: TypeScript copies a private
159
+ // member's JSDoc into the published declaration.)
195
160
  cleanup(waiter) {
196
- if (waiter.timer !== undefined)
197
- clearTimeout(waiter.timer);
198
- if (waiter.onAbort) {
199
- waiter.signal?.removeEventListener("abort", waiter.onAbort);
161
+ if (this.remove(waiter)) {
162
+ this.cancelledTotal++;
163
+ return Effect.void;
200
164
  }
165
+ if (!Deferred.isDoneUnsafe(waiter.outcome))
166
+ return Effect.void;
167
+ return Deferred.await(waiter.outcome).pipe(Effect.tap((lease) => Effect.sync(() => lease.release())), Effect.ignore);
168
+ }
169
+ // The admission program, handed to src/runtime/admission.ts. It lives in a
170
+ // static block because the class declaration ships, private member names
171
+ // and all: a new method or field would change the published `.d.ts`, and a
172
+ // static block is the one place outside an instance method that may read
173
+ // this bookkeeping while emitting nothing there.
174
+ static {
175
+ provideAdmissionProgram((controller, signal) => Effect.suspend(() => {
176
+ if (controller.closed) {
177
+ controller.closedTotal++;
178
+ return Effect.fail(new ExecutorAdmissionError("executor_closed", "Executor is shutting down."));
179
+ }
180
+ if (signal?.aborted) {
181
+ controller.cancelledTotal++;
182
+ return Effect.fail(new ExecutorAdmissionError("executor_cancelled", "Execution was cancelled before admission."));
183
+ }
184
+ if (controller.active < controller.concurrency) {
185
+ controller.active++;
186
+ controller.admittedTotal++;
187
+ return Effect.succeed(controller.makeLease(0));
188
+ }
189
+ if (controller.waiters.length >= controller.maxQueueSize) {
190
+ controller.rejectedTotal++;
191
+ return Effect.fail(controller.overloaded("Executor queue is full."));
192
+ }
193
+ const waiter = {
194
+ queuedAt: Date.now(),
195
+ outcome: Deferred.makeUnsafe(),
196
+ };
197
+ controller.waiters.push(waiter);
198
+ controller.queuedTotal++;
199
+ // A timeout or abort settles the waiter only if it takes it out of the
200
+ // queue first. Otherwise release() or close() got there in the same
201
+ // tick, and the outcome they recorded is the answer.
202
+ const giveUp = (count, error) => Effect.suspend(() => {
203
+ if (!controller.remove(waiter))
204
+ return Deferred.await(waiter.outcome);
205
+ count();
206
+ return Effect.fail(error());
207
+ });
208
+ // One flat race; each contender is a forked fiber.
209
+ const contenders = [
210
+ Deferred.await(waiter.outcome),
211
+ Effect.sleep(Duration.millis(controller.queueTimeoutMs)).pipe(Effect.andThen(giveUp(() => controller.rejectedTotal++, () => controller.overloaded(`Executor admission timed out after ${controller.queueTimeoutMs}ms.`)))),
212
+ ];
213
+ if (signal) {
214
+ contenders.push(fromSignal(signal).pipe(Effect.catch(() => giveUp(() => controller.cancelledTotal++, () => new ExecutorAdmissionError("executor_cancelled", "Execution was cancelled while queued.")))));
215
+ }
216
+ return Effect.raceAllFirst(contenders).pipe(Effect.onInterrupt(() => controller.cleanup(waiter)));
217
+ }));
201
218
  }
202
219
  }
203
220
  /** Preserve the one-method Workers seam while recognizing richer Node executors. */
@@ -9,6 +9,7 @@
9
9
  // provider args/results must be JSON-serializable.
10
10
  import { getQuickJS, } from "quickjs-emscripten";
11
11
  import { msg } from "../errors.js";
12
+ import { withoutProgramTerminator } from "../program-source.js";
12
13
  import { hostCallLabel, MAX_QUICKJS_LOG_TRANSPORT_BYTES, serializedBytes, } from "./quickjs-protocol.js";
13
14
  /** Load and compile the shared QuickJS WASM module before a run budget starts. */
14
15
  export async function prepareQuickJs() {
@@ -70,8 +71,9 @@ export function normalizeCode(code) {
70
71
  // lines — models routinely prefix their code with a `//` or `/* */` note,
71
72
  // which would otherwise defeat the detection and wrap the whole thing.
72
73
  const head = c.replace(/^(?:\s+|\/\/[^\n]*|\/\*[\s\S]*?\*\/)+/, "");
73
- if (/^async\b/.test(head) || head.startsWith("("))
74
- return c;
74
+ if (/^async\b/.test(head) || head.startsWith("(")) {
75
+ return withoutProgramTerminator(c);
76
+ }
75
77
  return `async () => {\n${c}\n}`;
76
78
  }
77
79
  /**