apps 0.0.1-beta.8 → 0.0.1-beta.80
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/README.md +25 -22
- package/framework-reference.json +1 -1
- package/js/chunk-4IN2N5CY.js +348 -0
- package/js/chunk-5FHWNLCI.js +88 -0
- package/js/{chunk-M3B3DE4K.js → chunk-74YVXBKY.js} +463 -218
- package/js/chunk-BIUWK47W.js +49 -0
- package/js/{chunk-RJDDBDSN.js → chunk-C6P3YMHI.js} +789 -171
- package/js/chunk-CDXQDN7W.js +92 -0
- package/js/{chunk-UESPOTUI.js → chunk-CT3QZBWU.js} +861 -231
- package/js/{chunk-UK573G7W.js → chunk-EOPQ727L.js} +87 -51
- package/js/{chunk-RFVIONFX.js → chunk-EZCV4Q4R.js} +123 -44
- package/js/{chunk-27F7W2LG.js → chunk-H2CJWXA3.js} +2 -2
- package/js/{chunk-JU7VHODU.js → chunk-H72MEDMN.js} +65 -10
- package/js/{chunk-CDL5PM2Q.js → chunk-IFJU5SYQ.js} +19082 -18402
- package/js/{chunk-72JNVHPK.js → chunk-IUPDGBBF.js} +4 -3
- package/js/{chunk-VFZKSM3T.js → chunk-JPEUKEV4.js} +3 -3
- package/js/{chunk-5T57N25Q.js → chunk-KGCTYL2S.js} +511 -63
- package/js/{chunk-KUMBKVJD.js → chunk-KLYSEHUD.js} +2 -2
- package/js/{chunk-WLE7WX2U.js → chunk-NG56RPCA.js} +2348 -472
- package/js/chunk-OD3KFKZD.js +1617 -0
- package/js/chunk-OK4MIBPW.js +334 -0
- package/js/{chunk-57RKNWL2.js → chunk-PD6I2SDG.js} +4 -4
- package/js/chunk-PW4S2HP5.js +426 -0
- package/js/chunk-Q4IZAUIF.js +285 -0
- package/js/{chunk-FL2QR3XW.js → chunk-Q5S3SWMO.js} +333 -69
- package/js/{chunk-Z5M2LQOZ.js → chunk-SNKDWIYL.js} +67 -55
- package/js/{chunk-IJX4CYZO.js → chunk-TUMGL2OC.js} +228 -264
- package/js/{chunk-CMYUWAX7.js → chunk-WFCOT6UW.js} +126 -31
- package/js/{chunk-IPI4MFSN.js → chunk-XBG7HHXC.js} +2 -2
- package/js/chunk-ZYXY6JLH.js +171 -0
- package/js/client.js +142 -94
- package/js/contracts.js +127 -26
- package/js/effect.js +19 -19
- package/js/{es-APDZKREY.js → es-DIULA3ZF.js} +62 -1659
- package/js/graphql.js +50 -40
- package/js/host.js +83 -58
- package/js/index.js +131 -46
- package/js/mcp/effect.js +23 -21
- package/js/mcp/stdio.js +44 -34
- package/js/mcp.js +76 -53
- package/js/openapi.js +4071 -1357
- package/js/react.js +2 -3
- package/js/skills/effect.js +6 -3
- package/js/skills.js +208 -81
- package/js/storage/facet.js +1 -540
- package/js/ui/auth/contracts.js +2 -2
- package/js/ui/auth.js +5 -5
- package/js/ui/contracts.js +5 -4
- package/js/ui/serving.js +8604 -223
- package/package.json +3 -4
- package/runtime.json +1 -1
- package/types/app-cache/src/contracts/cache.d.ts +18 -0
- package/types/app-cache/src/index.d.ts +34 -2
- package/types/apps/src/contracts/api-response-error.d.ts +4 -0
- package/types/apps/src/contracts/app.d.ts +7 -3
- package/types/apps/src/contracts/cache.d.ts +20 -0
- package/types/apps/src/contracts/context.d.ts +19 -11
- package/types/apps/src/contracts/elicitation.d.ts +23 -7
- package/types/apps/src/contracts/events.d.ts +93 -0
- package/types/apps/src/contracts/failure.d.ts +30 -1
- package/types/apps/src/contracts/graphql.d.ts +2 -1
- package/types/apps/src/contracts/host.d.ts +649 -17
- package/types/apps/src/contracts/live.d.ts +2 -0
- package/types/apps/src/contracts/mcp.d.ts +80 -10
- package/types/apps/src/contracts/network.d.ts +120 -0
- package/types/apps/src/contracts/openapi-compile.d.ts +82 -3
- package/types/apps/src/contracts/openapi.d.ts +41 -9
- package/types/apps/src/contracts/operations.d.ts +8 -4
- package/types/apps/src/contracts/placement.d.ts +102 -0
- package/types/apps/src/contracts/protocol-version.d.ts +2 -2
- package/types/apps/src/contracts/protocols/1.d.ts +733 -81
- package/types/apps/src/contracts/protocols/10.d.ts +1450 -0
- package/types/apps/src/contracts/protocols/2.d.ts +69 -26
- package/types/apps/src/contracts/protocols/3.d.ts +133 -33
- package/types/apps/src/contracts/protocols/4.d.ts +122 -45
- package/types/apps/src/contracts/protocols/5.d.ts +157 -47
- package/types/apps/src/contracts/protocols/6.d.ts +1629 -0
- package/types/apps/src/contracts/protocols/7.d.ts +1785 -0
- package/types/apps/src/contracts/protocols/8.d.ts +1182 -0
- package/types/apps/src/contracts/protocols/9.d.ts +1104 -0
- package/types/apps/src/contracts/protocols/current.d.ts +3843 -0
- package/types/apps/src/contracts/protocols/oauth-6.d.ts +74 -0
- package/types/apps/src/contracts/protocols/oauth.d.ts +134 -0
- package/types/apps/src/contracts/provider-error.d.ts +9 -0
- package/types/apps/src/contracts/provider.d.ts +90 -6
- package/types/apps/src/contracts/skills.d.ts +50 -13
- package/types/apps/src/contracts/sql.d.ts +63 -0
- package/types/apps/src/contracts/ui.d.ts +37 -3
- package/types/apps/src/contracts/workflows.d.ts +6 -0
- package/types/apps/src/facet.d.ts +4 -5
- package/types/apps/src/host.d.ts +5 -0
- package/types/apps/src/implementation/account-router.d.ts +4 -3
- package/types/apps/src/implementation/authoring.d.ts +25 -5
- package/types/apps/src/implementation/browser-scripts.gen.d.ts +6 -0
- package/types/apps/src/implementation/cache.d.ts +28 -1
- package/types/apps/src/implementation/catalog-cache.d.ts +35 -4
- package/types/apps/src/implementation/elicitation.d.ts +18 -15
- package/types/apps/src/implementation/events.d.ts +59 -0
- package/types/apps/src/implementation/failure-detail.d.ts +25 -3
- package/types/apps/src/implementation/graphql-catalog.d.ts +3 -3
- package/types/apps/src/implementation/graphql.d.ts +4 -3
- package/types/apps/src/implementation/input-problems.d.ts +6 -2
- package/types/apps/src/implementation/invocation-timing.d.ts +18 -0
- package/types/apps/src/implementation/live.d.ts +2 -2
- package/types/apps/src/implementation/mcp-call.d.ts +6 -5
- package/types/apps/src/implementation/mcp-catalog.d.ts +6 -4
- package/types/apps/src/implementation/mcp-client.d.ts +17 -9
- package/types/apps/src/implementation/mcp-stdio.d.ts +1 -1
- package/types/apps/src/implementation/mcp-tools.d.ts +2 -1
- package/types/apps/src/implementation/mcp.d.ts +20 -9
- package/types/apps/src/implementation/network.d.ts +16 -0
- package/types/apps/src/implementation/openapi-compile.d.ts +26 -6
- package/types/apps/src/implementation/openapi-document.d.ts +46 -19
- package/types/apps/src/implementation/openapi-names.d.ts +9 -4
- package/types/apps/src/implementation/openapi-request.d.ts +10 -2
- package/types/apps/src/implementation/openapi-source.d.ts +18 -0
- package/types/apps/src/implementation/openapi-upgrade.d.ts +4 -0
- package/types/apps/src/implementation/operations.d.ts +17 -2
- package/types/apps/src/implementation/optimistic.d.ts +1 -1
- package/types/apps/src/implementation/placement.d.ts +60 -0
- package/types/apps/src/implementation/protocol-operations.d.ts +3 -0
- package/types/apps/src/implementation/provider-error.d.ts +28 -1
- package/types/apps/src/implementation/provider.d.ts +18 -3
- package/types/apps/src/implementation/query-commit.d.ts +1 -1
- package/types/apps/src/implementation/router-catalog.d.ts +11 -13
- package/types/apps/src/implementation/router.d.ts +16 -5
- package/types/apps/src/implementation/runtime-yield.d.ts +7 -0
- package/types/apps/src/implementation/schema.d.ts +90 -10
- package/types/apps/src/implementation/skills.d.ts +18 -24
- package/types/apps/src/implementation/sql.d.ts +71 -0
- package/types/apps/src/implementation/ui-account-notice.d.ts +9 -0
- package/types/apps/src/implementation/ui-auth.d.ts +1 -1
- package/types/apps/src/implementation/ui-client.d.ts +2 -2
- package/types/apps/src/implementation/ui-document.d.ts +5 -0
- package/types/apps/src/implementation/ui-errors.d.ts +1 -1
- package/types/apps/src/implementation/ui-serving.d.ts +28 -9
- package/types/apps/src/implementation/ui-watch.d.ts +1 -1
- package/types/apps/src/implementation/upstream-error.d.ts +7 -0
- package/types/apps/src/implementation/webhooks.d.ts +1 -1
- package/types/apps/src/implementation/workflows.d.ts +1 -1
- package/types/apps/src/index.d.ts +55 -13
- package/types/apps/src/mcp.d.ts +20 -1
- package/types/apps/src/openapi.d.ts +1 -1
- package/types/apps/src/react.d.ts +1 -1
- package/types/apps/src/skills.d.ts +10 -8
- package/types/apps/src/ui-serving.d.ts +1 -1
- package/types/telemetry/src/app-records.d.ts +42 -0
- package/types/telemetry/src/browser-operations.d.ts +2 -2
- package/types/telemetry/src/browser.d.ts +8 -3
- package/types/telemetry/src/config.d.ts +2 -2
- package/types/telemetry/src/index.d.ts +2 -1
- package/types/telemetry/src/layer.d.ts +2 -2
- package/types/telemetry/src/measurements.d.ts +1 -1
- package/types/telemetry/src/ownership.d.ts +60 -0
- package/types/telemetry/src/recorded-failure.d.ts +29 -0
- package/types/telemetry/src/relay.d.ts +16 -6
- package/types/telemetry/src/span-attributes.d.ts +17 -1
- package/types/telemetry/src/transport.d.ts +8 -1
- package/types/utils/src/api-error.d.ts +55 -0
- package/types/utils/src/connection-failure.d.ts +33 -0
- package/types/utils/src/recorded-message.d.ts +18 -0
- package/types/utils/src/user-facing-error.d.ts +83 -0
- package/js/chunk-MKWZPDR6.js +0 -63
- package/js/chunk-N7YDVXYJ.js +0 -186
- package/js/chunk-NKLWZJLE.js +0 -172
- package/js/chunk-OCYUEU47.js +0 -224
- package/js/chunk-PJJ24GU7.js +0 -877
- package/js/chunk-PZB6T6KU.js +0 -19
- package/js/chunk-R3EV5FTO.js +0 -97
- package/js/chunk-YXQHV65J.js +0 -242
- package/js/chunk-ZQINWV4W.js +0 -630
- package/types/app-data/src/implementation/cursor.d.ts +0 -10
- package/types/app-data/src/implementation/index-key.d.ts +0 -7
- package/types/app-data/src/implementation/promise.d.ts +0 -68
- package/types/app-data/src/implementation/range.d.ts +0 -8
- package/types/app-data/src/implementation/schema.d.ts +0 -18
- package/types/app-data/src/implementation/sqlite.d.ts +0 -11
- package/types/app-data/src/index.d.ts +0 -4
- package/types/apps/src/contracts/storage.d.ts +0 -68
- package/types/apps/src/implementation/storage.d.ts +0 -15
|
@@ -1,39 +1,45 @@
|
|
|
1
1
|
import {
|
|
2
|
-
|
|
3
|
-
|
|
2
|
+
authorCache,
|
|
3
|
+
unavailableCache
|
|
4
|
+
} from "./chunk-OK4MIBPW.js";
|
|
4
5
|
import {
|
|
5
6
|
accountSecrets,
|
|
6
7
|
boundFailureMessage,
|
|
7
8
|
describeFailure,
|
|
8
9
|
failureDetail,
|
|
10
|
+
leavingProviderError,
|
|
11
|
+
parseMcpError,
|
|
12
|
+
parseSkillLoadFailed,
|
|
9
13
|
readCatalog,
|
|
10
14
|
routerSkills
|
|
11
|
-
} from "./chunk-
|
|
15
|
+
} from "./chunk-Q5S3SWMO.js";
|
|
16
|
+
import {
|
|
17
|
+
appInvocationFetch
|
|
18
|
+
} from "./chunk-BIUWK47W.js";
|
|
12
19
|
import {
|
|
13
20
|
folderSkillsEffect
|
|
14
|
-
} from "./chunk-
|
|
21
|
+
} from "./chunk-XBG7HHXC.js";
|
|
15
22
|
import {
|
|
16
23
|
ResponseStatusError,
|
|
17
|
-
|
|
24
|
+
declaredEvents,
|
|
18
25
|
isApp,
|
|
26
|
+
makeEmitter,
|
|
19
27
|
toEffectApp,
|
|
20
|
-
|
|
21
|
-
} from "./chunk-
|
|
22
|
-
import {
|
|
23
|
-
parseDatabaseSchema
|
|
24
|
-
} from "./chunk-ZQINWV4W.js";
|
|
28
|
+
withPlacements
|
|
29
|
+
} from "./chunk-PW4S2HP5.js";
|
|
25
30
|
import {
|
|
26
31
|
declaredOperations,
|
|
27
|
-
fromPromise,
|
|
28
32
|
locate,
|
|
29
|
-
nativeOperation
|
|
30
|
-
|
|
31
|
-
} from "./chunk-Z5M2LQOZ.js";
|
|
33
|
+
nativeOperation
|
|
34
|
+
} from "./chunk-SNKDWIYL.js";
|
|
32
35
|
import {
|
|
33
36
|
accountProviderError,
|
|
37
|
+
appCode,
|
|
38
|
+
fromPromise,
|
|
34
39
|
httpProviderError,
|
|
35
|
-
parseProviderError
|
|
36
|
-
|
|
40
|
+
parseProviderError,
|
|
41
|
+
toPromise
|
|
42
|
+
} from "./chunk-ZYXY6JLH.js";
|
|
37
43
|
import {
|
|
38
44
|
AccountCheckResult,
|
|
39
45
|
DeclaredProvider,
|
|
@@ -62,9 +68,9 @@ import {
|
|
|
62
68
|
HostedWebhook,
|
|
63
69
|
HostedWorkflow,
|
|
64
70
|
InvocationDeadline,
|
|
71
|
+
InvocationTimingSink,
|
|
65
72
|
ManualWebhookSetup,
|
|
66
73
|
ManyAccounts,
|
|
67
|
-
McpError,
|
|
68
74
|
NonRetryableError,
|
|
69
75
|
OpenapiResponseError,
|
|
70
76
|
ResolvedAccounts,
|
|
@@ -80,42 +86,84 @@ import {
|
|
|
80
86
|
approvalElicitation,
|
|
81
87
|
defaultWebhookTransportLimits,
|
|
82
88
|
maxInputProblems,
|
|
89
|
+
migrationsDirectory,
|
|
90
|
+
normalizePlacements,
|
|
91
|
+
reservedTablePrefix,
|
|
92
|
+
sqlBindingsLimit,
|
|
83
93
|
workflowDurationMillis
|
|
84
|
-
} from "./chunk-
|
|
85
|
-
import {
|
|
86
|
-
CacheError
|
|
87
|
-
} from "./chunk-R3EV5FTO.js";
|
|
94
|
+
} from "./chunk-NG56RPCA.js";
|
|
88
95
|
import {
|
|
89
96
|
AppSkills,
|
|
90
|
-
SkillFile
|
|
91
|
-
|
|
92
|
-
} from "./chunk-JU7VHODU.js";
|
|
97
|
+
SkillFile
|
|
98
|
+
} from "./chunk-H72MEDMN.js";
|
|
93
99
|
import {
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
} from "./chunk-RJDDBDSN.js";
|
|
97
|
-
import {
|
|
98
|
-
decoderOf,
|
|
100
|
+
allowedValues,
|
|
101
|
+
echoableKey,
|
|
99
102
|
importedJsonSchema,
|
|
103
|
+
importedSchemaKeys,
|
|
100
104
|
jsonSchemaDecoder,
|
|
101
|
-
jsonSchemaDocument
|
|
102
|
-
|
|
105
|
+
jsonSchemaDocument,
|
|
106
|
+
maxAlternativeKeys,
|
|
107
|
+
missingKey,
|
|
108
|
+
missingKeyText,
|
|
109
|
+
objectShape,
|
|
110
|
+
unionShape
|
|
111
|
+
} from "./chunk-KGCTYL2S.js";
|
|
112
|
+
import {
|
|
113
|
+
captureTelemetry,
|
|
114
|
+
makeOwnershipAccounting,
|
|
115
|
+
measuredSpan,
|
|
116
|
+
owned
|
|
117
|
+
} from "./chunk-C6P3YMHI.js";
|
|
103
118
|
import {
|
|
104
119
|
JsonObject,
|
|
105
120
|
JsonValue
|
|
106
|
-
} from "./chunk-
|
|
121
|
+
} from "./chunk-H2CJWXA3.js";
|
|
107
122
|
import {
|
|
123
|
+
Base64_exports,
|
|
108
124
|
Cause_exports,
|
|
109
125
|
Clock_exports,
|
|
110
126
|
Effect_exports,
|
|
111
|
-
Encoding_exports,
|
|
112
127
|
Match_exports,
|
|
113
128
|
Option_exports,
|
|
114
129
|
Redacted_exports,
|
|
130
|
+
SchemaAST_exports,
|
|
115
131
|
SchemaIssue_exports,
|
|
116
132
|
Schema_exports,
|
|
117
133
|
Stream_exports
|
|
118
|
-
} from "./chunk-
|
|
134
|
+
} from "./chunk-IFJU5SYQ.js";
|
|
135
|
+
|
|
136
|
+
// src/implementation/invocation-timing.ts
|
|
137
|
+
var elicitationWaitSpan = "app.elicitation.wait";
|
|
138
|
+
var workflowControlSpan = "app.workflow.control";
|
|
139
|
+
var timedInvocation = (operation) => (effect) => Effect_exports.gen(function* () {
|
|
140
|
+
const report = yield* InvocationTimingSink;
|
|
141
|
+
return yield* effect.pipe(
|
|
142
|
+
measuredSpan(`app.${operation}`, {}, (start) => {
|
|
143
|
+
const accounting = makeOwnershipAccounting(start, "executor");
|
|
144
|
+
return {
|
|
145
|
+
around: accounting.observe,
|
|
146
|
+
end: (end, span) => {
|
|
147
|
+
const spent = accounting.read(end);
|
|
148
|
+
report({
|
|
149
|
+
elapsedMs: Number(end - start) / 1e6,
|
|
150
|
+
upstreamMs: spent.upstream,
|
|
151
|
+
elicitationMs: spent.person,
|
|
152
|
+
authoredMs: spent.app,
|
|
153
|
+
leaseMs: spent.lease,
|
|
154
|
+
backgroundMs: spent.background
|
|
155
|
+
});
|
|
156
|
+
span.attribute("executor.upstream.wait_ms", spent.upstream);
|
|
157
|
+
span.attribute("executor.elicitation.wait_ms", spent.person);
|
|
158
|
+
span.attribute("executor.authored_ms", spent.app);
|
|
159
|
+
span.attribute("executor.lease.wait_ms", spent.lease);
|
|
160
|
+
span.attribute("executor.background_ms", spent.background);
|
|
161
|
+
span.attribute("executor.overhead_ms", spent.executor);
|
|
162
|
+
}
|
|
163
|
+
};
|
|
164
|
+
})
|
|
165
|
+
);
|
|
166
|
+
});
|
|
119
167
|
|
|
120
168
|
// src/implementation/elicitation.ts
|
|
121
169
|
var prepareElicitation = (input) => Effect_exports.gen(function* () {
|
|
@@ -143,13 +191,17 @@ var prepareElicitation = (input) => Effect_exports.gen(function* () {
|
|
|
143
191
|
});
|
|
144
192
|
return { request, respond };
|
|
145
193
|
});
|
|
146
|
-
var makeElicit = (handler, signal) => toPromise(
|
|
194
|
+
var makeElicit = (handler, signal, telemetry) => toPromise(
|
|
147
195
|
(input) => Effect_exports.gen(function* () {
|
|
148
196
|
if (handler === void 0) return yield* new ElicitationFailed({ reason: "unavailable" });
|
|
149
197
|
const form = yield* prepareElicitation(input);
|
|
150
|
-
return yield* handler(form.request, signal).pipe(
|
|
198
|
+
return yield* handler(form.request, signal).pipe(
|
|
199
|
+
owned("person", elicitationWaitSpan),
|
|
200
|
+
Effect_exports.flatMap(form.respond)
|
|
201
|
+
);
|
|
151
202
|
}),
|
|
152
|
-
signal
|
|
203
|
+
signal,
|
|
204
|
+
telemetry
|
|
153
205
|
);
|
|
154
206
|
|
|
155
207
|
// src/contracts/approval.ts
|
|
@@ -235,10 +287,7 @@ var makeWorkflowContext = (execution, definition, fresh, signal) => Effect_expor
|
|
|
235
287
|
);
|
|
236
288
|
const step2 = yield* fresh(stepId, AbortSignal.any([signal, controller.signal]));
|
|
237
289
|
const result = yield* workflowSafe(
|
|
238
|
-
|
|
239
|
-
try: () => callback(step2.context),
|
|
240
|
-
catch: (error) => error
|
|
241
|
-
}),
|
|
290
|
+
fromPromise(callback, "step")(step2.context),
|
|
242
291
|
step2.secrets
|
|
243
292
|
);
|
|
244
293
|
return yield* Schema_exports.decodeUnknownEffect(WorkflowValue)(result).pipe(
|
|
@@ -319,15 +368,144 @@ var makeWorkflowContext = (execution, definition, fresh, signal) => Effect_expor
|
|
|
319
368
|
});
|
|
320
369
|
|
|
321
370
|
// src/implementation/input-problems.ts
|
|
322
|
-
var
|
|
371
|
+
var nativeObjectShape = (ast, limit) => objectShape(
|
|
372
|
+
ast.propertySignatures.flatMap(
|
|
373
|
+
({ name, type }) => typeof name === "string" ? [{ name, optional: SchemaAST_exports.isOptional(SchemaAST_exports.toEncoded(type)) }] : []
|
|
374
|
+
),
|
|
375
|
+
ast.indexSignatures.length > 0,
|
|
376
|
+
limit
|
|
377
|
+
);
|
|
378
|
+
var unionMembers = (ast) => SchemaAST_exports.isUnion(ast) ? ast.types.flatMap(unionMembers) : SchemaAST_exports.isUndefined(ast) || SchemaAST_exports.isVoid(ast) ? [] : [ast];
|
|
379
|
+
var fixedValues = (ast) => {
|
|
380
|
+
if (SchemaAST_exports.isLiteral(ast)) return [ast.literal];
|
|
381
|
+
if (SchemaAST_exports.isEnum(ast)) return ast.enums.map(([, value]) => value);
|
|
382
|
+
if (!SchemaAST_exports.isUnion(ast)) return void 0;
|
|
383
|
+
const members = unionMembers(ast).map(fixedValues);
|
|
384
|
+
return members.length > 0 && members.every((values) => values !== void 0) ? members.flat() : void 0;
|
|
385
|
+
};
|
|
386
|
+
var describeMember = (ast) => Match_exports.value(ast).pipe(
|
|
387
|
+
Match_exports.when(
|
|
388
|
+
SchemaAST_exports.isObjects,
|
|
389
|
+
(objects) => objects.propertySignatures.length > 0 ? nativeObjectShape(objects, maxAlternativeKeys) : "object"
|
|
390
|
+
),
|
|
391
|
+
Match_exports.when(SchemaAST_exports.isArrays, () => "array"),
|
|
392
|
+
Match_exports.when(SchemaAST_exports.isTemplateLiteral, () => "a string matching a template"),
|
|
393
|
+
Match_exports.when(SchemaAST_exports.isString, () => "string"),
|
|
394
|
+
Match_exports.when(SchemaAST_exports.isNumber, () => "number"),
|
|
395
|
+
Match_exports.when(SchemaAST_exports.isBoolean, () => "boolean"),
|
|
396
|
+
Match_exports.when(SchemaAST_exports.isNull, () => "null"),
|
|
397
|
+
Match_exports.orElse(() => "a value with other constraints")
|
|
398
|
+
);
|
|
399
|
+
var memberSelector = (members) => {
|
|
400
|
+
const [first] = members;
|
|
401
|
+
if (members.length < 2 || first === void 0 || !SchemaAST_exports.isObjects(first)) return void 0;
|
|
402
|
+
return first.propertySignatures.map(({ name }) => name).find(
|
|
403
|
+
(name) => typeof name === "string" && members.every(
|
|
404
|
+
(member) => SchemaAST_exports.isObjects(member) && member.propertySignatures.some(
|
|
405
|
+
(property) => property.name === name && fixedValues(SchemaAST_exports.toEncoded(property.type)) !== void 0
|
|
406
|
+
)
|
|
407
|
+
)
|
|
408
|
+
);
|
|
409
|
+
};
|
|
410
|
+
var unionExpectation = (ast) => {
|
|
411
|
+
const members = unionMembers(ast);
|
|
412
|
+
const fixed = members.map(fixedValues);
|
|
413
|
+
const values = fixed.flatMap((memberValues) => memberValues === void 0 ? [] : memberValues);
|
|
414
|
+
const others = members.filter((_, index) => fixed[index] === void 0);
|
|
415
|
+
if (others.length === 0) return allowedValues(values);
|
|
416
|
+
return unionShape(
|
|
417
|
+
[
|
|
418
|
+
...values.length === 0 ? [] : [allowedValues(values)],
|
|
419
|
+
...new Set(others.map(describeMember))
|
|
420
|
+
],
|
|
421
|
+
memberSelector(members)
|
|
422
|
+
);
|
|
423
|
+
};
|
|
424
|
+
var expectedUnion = (ast) => `Expected ${unionExpectation(ast)}`;
|
|
425
|
+
var expectedValue = (ast) => {
|
|
426
|
+
const encoded = SchemaAST_exports.toEncoded(ast);
|
|
427
|
+
const values = fixedValues(encoded);
|
|
428
|
+
if (values !== void 0) return allowedValues(values);
|
|
429
|
+
const members = unionMembers(encoded);
|
|
430
|
+
const [only] = members;
|
|
431
|
+
if (only === void 0) return void 0;
|
|
432
|
+
if (members.length > 1 && SchemaAST_exports.isUnion(encoded)) return unionExpectation(encoded);
|
|
433
|
+
if (SchemaAST_exports.isObjects(only) && only.propertySignatures.length > 0)
|
|
434
|
+
return nativeObjectShape(only);
|
|
435
|
+
const described = describeMember(only);
|
|
436
|
+
return described === "a value with other constraints" ? void 0 : described;
|
|
437
|
+
};
|
|
438
|
+
var leafHook = (issue) => SchemaIssue_exports.hasInput(issue) ? "Invalid value" : Match_exports.value(issue).pipe(
|
|
439
|
+
Match_exports.tag("InvalidType", ({ ast }) => {
|
|
440
|
+
const values = fixedValues(ast);
|
|
441
|
+
return values !== void 0 ? `Expected ${allowedValues(values)}` : SchemaAST_exports.isObjects(ast) && ast.propertySignatures.length > 0 ? `Expected ${nativeObjectShape(ast)}` : SchemaIssue_exports.defaultLeafHook(issue);
|
|
442
|
+
}),
|
|
443
|
+
Match_exports.orElse(SchemaIssue_exports.defaultLeafHook)
|
|
444
|
+
);
|
|
323
445
|
var checkHook = (issue) => SchemaIssue_exports.hasInput(issue) || SchemaIssue_exports.hasInput(issue.issue) ? SchemaIssue_exports.defaultCheckHook(issue) ?? "Invalid value" : SchemaIssue_exports.defaultCheckHook(issue);
|
|
324
446
|
var format = SchemaIssue_exports.makeFormatterStandardSchemaV1({ leafHook, checkHook });
|
|
325
|
-
var
|
|
326
|
-
var
|
|
447
|
+
var declaredKey = (parent, key) => parent !== void 0 && SchemaAST_exports.isObjects(parent) ? parent.propertySignatures.find(({ name }) => name === key)?.type : void 0;
|
|
448
|
+
var nativeKeys = (parent) => (key) => parent.indexSignatures.length > 0 || parent.propertySignatures.some(({ name }) => name === key);
|
|
449
|
+
var located = (issue, path, parent) => Match_exports.value(issue).pipe(
|
|
450
|
+
Match_exports.tag("Pointer", (pointer) => {
|
|
451
|
+
const declared = pointer.issue._tag === "MissingKey" && pointer.path.length === 1 ? declaredKey(parent, pointer.path[0]) : void 0;
|
|
452
|
+
return declared === void 0 || parent === void 0 || !SchemaAST_exports.isObjects(parent) ? located(pointer.issue, [...path, ...pointer.path]) : [
|
|
453
|
+
{
|
|
454
|
+
path: [...path, ...pointer.path],
|
|
455
|
+
message: missingKey(expectedValue(declared)),
|
|
456
|
+
accepts: nativeKeys(parent)
|
|
457
|
+
}
|
|
458
|
+
];
|
|
459
|
+
}),
|
|
460
|
+
Match_exports.tag(
|
|
461
|
+
"Composite",
|
|
462
|
+
({ ast, issues }) => issues.flatMap((issue2) => located(issue2, path, ast))
|
|
463
|
+
),
|
|
464
|
+
Match_exports.tag("Encoding", (encoding) => located(encoding.issue, path)),
|
|
465
|
+
Match_exports.tag(
|
|
466
|
+
"AnyOf",
|
|
467
|
+
({ ast, issues }) => issues.length === 0 ? [{ path, message: expectedUnion(ast) }] : issues.flatMap((issue2) => located(issue2, path))
|
|
468
|
+
),
|
|
469
|
+
Match_exports.orElse((issue2) => {
|
|
470
|
+
const accepts = issue2._tag === "Filter" ? importedSchemaKeys(issue2.filter) : void 0;
|
|
471
|
+
return format(issue2).issues.map((problem) => ({
|
|
472
|
+
path: [
|
|
473
|
+
...path,
|
|
474
|
+
...(problem.path ?? []).map((key) => typeof key === "object" ? key.key : key)
|
|
475
|
+
],
|
|
476
|
+
message: problem.message,
|
|
477
|
+
...accepts === void 0 ? {} : { accepts }
|
|
478
|
+
}));
|
|
479
|
+
})
|
|
480
|
+
);
|
|
481
|
+
var segment = (key) => typeof key === "number" ? `[${key}]` : typeof key === "string" && echoableKey(key) ? `.${key}` : "[key]";
|
|
482
|
+
var rendered = (path) => `input${path.map(segment).join("")}`;
|
|
483
|
+
var isRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
484
|
+
var valueAt = (input, path) => path.reduce(
|
|
485
|
+
(value, key) => Array.isArray(value) && typeof key === "number" ? value[key] : isRecord(value) && typeof key === "string" && Object.hasOwn(value, key) ? value[key] : void 0,
|
|
486
|
+
input
|
|
487
|
+
);
|
|
488
|
+
var spelling = (key) => key.toLowerCase().replace(/[-_]/g, "");
|
|
489
|
+
var suppliedElsewhere = (input, path, accepts) => {
|
|
490
|
+
const key = path.at(-1);
|
|
491
|
+
if (typeof key !== "string" || !echoableKey(key)) return void 0;
|
|
492
|
+
const at = path.slice(0, -1);
|
|
493
|
+
const holder = valueAt(input, at);
|
|
494
|
+
if (!isRecord(holder)) return void 0;
|
|
495
|
+
const candidates = Object.keys(holder).filter((name) => echoableKey(name) && !accepts(name));
|
|
496
|
+
const respelled = candidates.find((name) => name !== key && spelling(name) === spelling(key));
|
|
497
|
+
const deeper = candidates.find((name) => {
|
|
498
|
+
const child = holder[name];
|
|
499
|
+
return isRecord(child) && Object.hasOwn(child, key);
|
|
500
|
+
});
|
|
501
|
+
const found = respelled !== void 0 ? [...at, respelled] : deeper !== void 0 ? [...at, deeper, key] : void 0;
|
|
502
|
+
return found === void 0 ? void 0 : `The input has ${String(found.at(-1))} at ${rendered(found)}; did you mean ${rendered(path)}?`;
|
|
503
|
+
};
|
|
504
|
+
var inputInvalid = (error, input) => {
|
|
327
505
|
if (!Schema_exports.isSchemaError(error)) return new HostInputInvalid();
|
|
328
|
-
const problems =
|
|
329
|
-
const
|
|
330
|
-
return `${
|
|
506
|
+
const problems = located(error.issue, []).slice(0, maxInputProblems).map(({ path, message, accepts }) => {
|
|
507
|
+
const elsewhere = accepts !== void 0 && message.startsWith(missingKeyText) ? suppliedElsewhere(input, path, accepts) : void 0;
|
|
508
|
+
return `${rendered(path)}: ${message}${elsewhere === void 0 ? "" : `. ${elsewhere}`}`.slice(
|
|
331
509
|
0,
|
|
332
510
|
512
|
|
333
511
|
);
|
|
@@ -434,7 +612,7 @@ var dispatchWebhook = (definition, command, context, accounts) => Effect_exports
|
|
|
434
612
|
yield* invoke(hook.unregister, { ...input, state });
|
|
435
613
|
return null;
|
|
436
614
|
}
|
|
437
|
-
const body = yield* Effect_exports.fromResult(
|
|
615
|
+
const body = yield* Effect_exports.fromResult(Base64_exports.decode(command.request.body)).pipe(
|
|
438
616
|
Effect_exports.mapError(() => new HostInputInvalid())
|
|
439
617
|
);
|
|
440
618
|
if (body.byteLength > defaultWebhookTransportLimits.maxBodyBytes)
|
|
@@ -467,7 +645,8 @@ var dispatchWebhook = (definition, command, context, accounts) => Effect_exports
|
|
|
467
645
|
return yield* new HostOutputInvalid();
|
|
468
646
|
chunks.push(chunk);
|
|
469
647
|
})
|
|
470
|
-
)
|
|
648
|
+
),
|
|
649
|
+
appCode("webhook")
|
|
471
650
|
);
|
|
472
651
|
const bytes = new Uint8Array(size);
|
|
473
652
|
let offset = 0;
|
|
@@ -483,79 +662,414 @@ var dispatchWebhook = (definition, command, context, accounts) => Effect_exports
|
|
|
483
662
|
() => Schema_exports.decodeUnknownEffect(WebhookResponseData)({
|
|
484
663
|
status: response.status,
|
|
485
664
|
headers,
|
|
486
|
-
body:
|
|
665
|
+
body: Base64_exports.encode(new Uint8Array(bytes))
|
|
487
666
|
}),
|
|
488
667
|
new HostOutputInvalid()
|
|
489
668
|
);
|
|
490
669
|
});
|
|
491
670
|
|
|
492
|
-
// src/implementation/
|
|
493
|
-
var
|
|
494
|
-
|
|
495
|
-
|
|
671
|
+
// src/implementation/sql.ts
|
|
672
|
+
var receipts = `${reservedTablePrefix}step_receipts`;
|
|
673
|
+
var stepEvents = `${reservedTablePrefix}step_events`;
|
|
674
|
+
var migrationsTable = `${reservedTablePrefix}migrations`;
|
|
675
|
+
var legacyRows = `${reservedTablePrefix}legacy_rows`;
|
|
676
|
+
var materialize = (cursor) => {
|
|
677
|
+
const rows = cursor.toArray();
|
|
678
|
+
return {
|
|
679
|
+
columnNames: cursor.columnNames,
|
|
680
|
+
rowsRead: cursor.rowsRead,
|
|
681
|
+
rowsWritten: cursor.rowsWritten,
|
|
682
|
+
toArray: () => [...rows],
|
|
683
|
+
one: () => {
|
|
684
|
+
if (rows.length !== 1)
|
|
685
|
+
throw new Error(`Expected exactly one row, but the statement returned ${rows.length}.`);
|
|
686
|
+
return rows[0];
|
|
687
|
+
},
|
|
688
|
+
[Symbol.iterator]: () => rows[Symbol.iterator]()
|
|
689
|
+
};
|
|
496
690
|
};
|
|
497
|
-
var
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
691
|
+
var isThenable = (value) => (typeof value === "object" || typeof value === "function") && value !== null && "then" in value && typeof value.then === "function";
|
|
692
|
+
var missingDatabase = () => {
|
|
693
|
+
throw new Error(
|
|
694
|
+
`This app has no database. Add its first migration, such as ${migrationsDirectory}/0001_create_notes.sql with a CREATE TABLE statement, and deploy again.`
|
|
695
|
+
);
|
|
696
|
+
};
|
|
697
|
+
var noDatabase = { exec: missingDatabase, transaction: missingDatabase };
|
|
698
|
+
var settings = [
|
|
699
|
+
"foreign_keys",
|
|
700
|
+
"defer_foreign_keys",
|
|
701
|
+
"ignore_check_constraints",
|
|
702
|
+
"legacy_alter_table",
|
|
703
|
+
"recursive_triggers",
|
|
704
|
+
"reverse_unordered_selects"
|
|
705
|
+
];
|
|
706
|
+
var readSettings = (storage) => new Map(
|
|
707
|
+
settings.map((name) => [name, Number(storage.sql.exec(`PRAGMA ${name}`).toArray()[0]?.[name])])
|
|
708
|
+
);
|
|
709
|
+
var changedSetting = (storage, baseline) => {
|
|
710
|
+
const current = readSettings(storage);
|
|
711
|
+
return settings.find((name) => current.get(name) !== baseline.get(name));
|
|
712
|
+
};
|
|
713
|
+
var restoreSettings = (storage, baseline) => {
|
|
714
|
+
const current = readSettings(storage);
|
|
715
|
+
for (const [name, value] of baseline)
|
|
716
|
+
if (current.get(name) !== value) storage.sql.exec(`PRAGMA ${name} = ${value}`);
|
|
717
|
+
storage.sql.exec("PRAGMA case_sensitive_like = OFF");
|
|
718
|
+
};
|
|
719
|
+
var ReadRolledBack = class extends Error {
|
|
720
|
+
};
|
|
721
|
+
var authorSql = (storage, options) => {
|
|
722
|
+
let closed = false;
|
|
723
|
+
const live = () => {
|
|
724
|
+
if (closed || options.signal.aborted)
|
|
725
|
+
throw new Error("This call has ended, so its ctx.sql no longer runs statements.");
|
|
726
|
+
};
|
|
727
|
+
let open = false;
|
|
728
|
+
let transactions = 0;
|
|
729
|
+
const baseline = readSettings(storage);
|
|
730
|
+
const checkSettings = () => {
|
|
731
|
+
const changed = changedSetting(storage, baseline);
|
|
732
|
+
if (changed !== void 0)
|
|
733
|
+
throw refuse(
|
|
734
|
+
new Error(
|
|
735
|
+
`SQLite connection settings belong to Executor, so app code cannot change PRAGMA ${changed}; the statement was rolled back. Migrations may change settings while they run.`
|
|
736
|
+
)
|
|
737
|
+
);
|
|
738
|
+
};
|
|
739
|
+
const changes = () => Number(storage.sql.exec("SELECT total_changes() AS n").toArray()[0]?.n);
|
|
740
|
+
let violation;
|
|
741
|
+
const refuse = (error) => {
|
|
742
|
+
if (open) violation ??= error;
|
|
743
|
+
return error;
|
|
744
|
+
};
|
|
745
|
+
const run = (query, bindings, mode) => {
|
|
746
|
+
try {
|
|
747
|
+
return runStatement(query, bindings, mode);
|
|
748
|
+
} finally {
|
|
749
|
+
restoreSettings(storage, baseline);
|
|
750
|
+
}
|
|
751
|
+
};
|
|
752
|
+
const runStatement = (query, bindings, mode) => {
|
|
753
|
+
live();
|
|
754
|
+
if (bindings.length > sqlBindingsLimit)
|
|
755
|
+
throw refuse(
|
|
756
|
+
new Error(
|
|
757
|
+
`A statement can bind at most ${sqlBindingsLimit} values, but this one binds ${bindings.length}. Pass a long list as one JSON array and read it with json_each(?), or split the work into batches.`
|
|
758
|
+
)
|
|
759
|
+
);
|
|
760
|
+
if (mode === "write") {
|
|
761
|
+
const statement = () => {
|
|
762
|
+
const cursor = materialize(storage.sql.exec(query, ...bindings));
|
|
763
|
+
checkSettings();
|
|
764
|
+
return cursor;
|
|
765
|
+
};
|
|
766
|
+
if (!open) return storage.transactionSync(statement);
|
|
767
|
+
try {
|
|
768
|
+
return statement();
|
|
769
|
+
} catch (error) {
|
|
770
|
+
refuse(error instanceof Error ? error : new Error(String(error)));
|
|
771
|
+
throw error;
|
|
772
|
+
}
|
|
773
|
+
}
|
|
774
|
+
if (open) {
|
|
775
|
+
return runStatement(query, bindings, "write");
|
|
776
|
+
}
|
|
777
|
+
const before = changes();
|
|
778
|
+
let read;
|
|
779
|
+
let changed = false;
|
|
780
|
+
try {
|
|
781
|
+
storage.transactionSync(() => {
|
|
782
|
+
read = materialize(storage.sql.exec(query, ...bindings));
|
|
783
|
+
changed = changes() !== before;
|
|
784
|
+
checkSettings();
|
|
785
|
+
throw new ReadRolledBack();
|
|
786
|
+
});
|
|
787
|
+
} catch (error) {
|
|
788
|
+
if (!(error instanceof ReadRolledBack)) throw error;
|
|
789
|
+
}
|
|
790
|
+
if (changed || read === void 0)
|
|
791
|
+
throw new Error(
|
|
792
|
+
options.step !== void 0 ? "A workflow step mutation writes only inside ctx.sql.transaction(...), so a retried step applies its writes once." : "Queries are read-only. Change data from a mutation."
|
|
793
|
+
);
|
|
794
|
+
return read;
|
|
795
|
+
};
|
|
796
|
+
const reader = {
|
|
797
|
+
exec: (query, ...bindings) => run(query, bindings, "read")
|
|
798
|
+
};
|
|
799
|
+
const transactionHandle = () => {
|
|
800
|
+
let active = true;
|
|
801
|
+
const tx = {
|
|
802
|
+
exec: (query, ...bindings) => {
|
|
803
|
+
if (!active)
|
|
804
|
+
throw new Error("This transaction has ended, so its tx no longer runs statements.");
|
|
805
|
+
return run(query, bindings, "write");
|
|
806
|
+
}
|
|
807
|
+
};
|
|
519
808
|
return {
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
)
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
809
|
+
tx,
|
|
810
|
+
end: () => {
|
|
811
|
+
active = false;
|
|
812
|
+
}
|
|
813
|
+
};
|
|
814
|
+
};
|
|
815
|
+
const transaction = (work) => {
|
|
816
|
+
live();
|
|
817
|
+
if (open) throw new Error("ctx.sql.transaction(...) cannot be nested.");
|
|
818
|
+
const step = options.step;
|
|
819
|
+
if (step !== void 0 && transactions > 0)
|
|
820
|
+
throw new Error(
|
|
821
|
+
"A workflow step mutation opens at most one ctx.sql.transaction(...), which records the step's result."
|
|
822
|
+
);
|
|
823
|
+
transactions += 1;
|
|
824
|
+
violation = void 0;
|
|
825
|
+
const handle = transactionHandle();
|
|
826
|
+
const emittedBefore = options.emitted?.length;
|
|
827
|
+
const discardEmitted = () => {
|
|
828
|
+
if (options.emitted !== void 0 && emittedBefore !== void 0)
|
|
829
|
+
options.emitted.length = emittedBefore;
|
|
830
|
+
};
|
|
831
|
+
const body = () => {
|
|
832
|
+
open = true;
|
|
833
|
+
try {
|
|
834
|
+
const complete = () => {
|
|
835
|
+
const value = work(handle.tx);
|
|
836
|
+
if (isThenable(value))
|
|
837
|
+
throw new Error(
|
|
838
|
+
"ctx.sql.transaction(...) callbacks are synchronous and cannot await. Call outside services before or after the transaction."
|
|
839
|
+
);
|
|
840
|
+
if (violation !== void 0) throw violation;
|
|
841
|
+
return value;
|
|
842
|
+
};
|
|
843
|
+
if (step === void 0) return complete();
|
|
844
|
+
storage.sql.exec(
|
|
845
|
+
`CREATE TABLE IF NOT EXISTS ${receipts} (id TEXT PRIMARY KEY, fingerprint TEXT NOT NULL, result TEXT NOT NULL) WITHOUT ROWID`
|
|
846
|
+
);
|
|
847
|
+
const saved = storage.sql.exec(`SELECT fingerprint, result FROM ${receipts} WHERE id = ?`, step.key).toArray()[0];
|
|
848
|
+
storage.sql.exec(
|
|
849
|
+
`CREATE TABLE IF NOT EXISTS ${stepEvents} (id TEXT PRIMARY KEY, events TEXT NOT NULL) WITHOUT ROWID`
|
|
850
|
+
);
|
|
851
|
+
if (saved !== void 0) {
|
|
852
|
+
if (saved.fingerprint !== step.fingerprint)
|
|
853
|
+
throw new Error("This workflow step already ran with different input.");
|
|
854
|
+
const replayed = storage.sql.exec(`SELECT events FROM ${stepEvents} WHERE id = ?`, step.key).toArray()[0];
|
|
855
|
+
if (replayed !== void 0 && options.emitted !== void 0)
|
|
856
|
+
options.emitted.push(...JSON.parse(String(replayed.events)));
|
|
857
|
+
return JSON.parse(String(saved.result));
|
|
858
|
+
}
|
|
859
|
+
const encoded = JSON.stringify(complete() ?? null);
|
|
860
|
+
const emitted = options.emitted?.slice(emittedBefore ?? 0) ?? [];
|
|
861
|
+
if (emitted.length > 0)
|
|
862
|
+
storage.sql.exec(
|
|
863
|
+
`INSERT INTO ${stepEvents} (id, events) VALUES (?, ?)`,
|
|
864
|
+
step.key,
|
|
865
|
+
JSON.stringify(emitted)
|
|
866
|
+
);
|
|
867
|
+
storage.sql.exec(
|
|
868
|
+
`INSERT INTO ${receipts} (id, fingerprint, result) VALUES (?, ?, ?)`,
|
|
869
|
+
step.key,
|
|
870
|
+
step.fingerprint,
|
|
871
|
+
encoded
|
|
553
872
|
);
|
|
873
|
+
return JSON.parse(encoded);
|
|
874
|
+
} finally {
|
|
875
|
+
open = false;
|
|
876
|
+
handle.end();
|
|
554
877
|
}
|
|
555
878
|
};
|
|
879
|
+
try {
|
|
880
|
+
return storage.transactionSync(body);
|
|
881
|
+
} catch (error) {
|
|
882
|
+
discardEmitted();
|
|
883
|
+
throw error;
|
|
884
|
+
}
|
|
885
|
+
};
|
|
886
|
+
const writer = {
|
|
887
|
+
// A step's writes go through its one transaction, which also records its receipt.
|
|
888
|
+
exec: (query, ...bindings) => run(query, bindings, options.step ? "read" : "write"),
|
|
889
|
+
transaction
|
|
890
|
+
};
|
|
891
|
+
return {
|
|
892
|
+
reader,
|
|
893
|
+
writer,
|
|
894
|
+
close: () => {
|
|
895
|
+
closed = true;
|
|
896
|
+
}
|
|
556
897
|
};
|
|
557
|
-
return scoped("shared");
|
|
558
898
|
};
|
|
899
|
+
var MigrationFileInvalid = class extends Schema_exports.TaggedError()(
|
|
900
|
+
"MigrationFileInvalid",
|
|
901
|
+
{ path: Schema_exports.String, reason: Schema_exports.String }
|
|
902
|
+
) {
|
|
903
|
+
get message() {
|
|
904
|
+
return `${this.path}: ${this.reason}`;
|
|
905
|
+
}
|
|
906
|
+
};
|
|
907
|
+
var MigrationHistoryChanged = class extends Schema_exports.TaggedError()(
|
|
908
|
+
"MigrationHistoryChanged",
|
|
909
|
+
{ reason: Schema_exports.String }
|
|
910
|
+
) {
|
|
911
|
+
get message() {
|
|
912
|
+
return `${this.reason} Applied migrations cannot change: restore the original file and add a new migration instead. Nothing was applied; the previous deployment is still active.`;
|
|
913
|
+
}
|
|
914
|
+
};
|
|
915
|
+
var MigrationFailed = class extends Schema_exports.TaggedError()("MigrationFailed", {
|
|
916
|
+
path: Schema_exports.String,
|
|
917
|
+
reason: Schema_exports.String
|
|
918
|
+
}) {
|
|
919
|
+
get message() {
|
|
920
|
+
return `${this.path} failed: ${this.reason}. No migrations were applied; the previous deployment is still active.`;
|
|
921
|
+
}
|
|
922
|
+
};
|
|
923
|
+
var migrationName = /^(\d+)_[A-Za-z0-9_-]+\.sql$/;
|
|
924
|
+
var sha256 = (text) => (
|
|
925
|
+
// oxlint-disable-next-line executor/authored-code-through-adapter -- Web Crypto
|
|
926
|
+
Effect_exports.promise(() => crypto.subtle.digest("SHA-256", new TextEncoder().encode(text))).pipe(
|
|
927
|
+
Effect_exports.map(
|
|
928
|
+
(digest) => Array.from(new Uint8Array(digest), (byte) => byte.toString(16).padStart(2, "0")).join("")
|
|
929
|
+
)
|
|
930
|
+
)
|
|
931
|
+
);
|
|
932
|
+
var statementsOf = (script) => {
|
|
933
|
+
let end = 0;
|
|
934
|
+
let index = 0;
|
|
935
|
+
while (index < script.length) {
|
|
936
|
+
const char = script[index];
|
|
937
|
+
const next = script[index + 1];
|
|
938
|
+
if (char === "-" && next === "-") {
|
|
939
|
+
const newline = script.indexOf("\n", index);
|
|
940
|
+
index = newline === -1 ? script.length : newline + 1;
|
|
941
|
+
continue;
|
|
942
|
+
}
|
|
943
|
+
if (char === "/" && next === "*") {
|
|
944
|
+
const close = script.indexOf("*/", index + 2);
|
|
945
|
+
index = close === -1 ? script.length : close + 2;
|
|
946
|
+
continue;
|
|
947
|
+
}
|
|
948
|
+
const closing = char === "'" || char === '"' || char === "`" ? char : char === "[" ? "]" : void 0;
|
|
949
|
+
if (closing !== void 0) {
|
|
950
|
+
let after = index + 1;
|
|
951
|
+
while (true) {
|
|
952
|
+
const found = script.indexOf(closing, after);
|
|
953
|
+
if (found === -1) {
|
|
954
|
+
after = script.length;
|
|
955
|
+
break;
|
|
956
|
+
}
|
|
957
|
+
if (closing !== "]" && script[found + 1] === closing) {
|
|
958
|
+
after = found + 2;
|
|
959
|
+
continue;
|
|
960
|
+
}
|
|
961
|
+
after = found + 1;
|
|
962
|
+
break;
|
|
963
|
+
}
|
|
964
|
+
index = after;
|
|
965
|
+
end = index;
|
|
966
|
+
continue;
|
|
967
|
+
}
|
|
968
|
+
index += 1;
|
|
969
|
+
if (char !== void 0 && !/\s/u.test(char)) end = index;
|
|
970
|
+
}
|
|
971
|
+
return script.slice(0, end);
|
|
972
|
+
};
|
|
973
|
+
var hasMigrations = (files) => files.some(
|
|
974
|
+
(file) => file.path.startsWith(`${migrationsDirectory}/`) && file.path.endsWith(".sql")
|
|
975
|
+
);
|
|
976
|
+
var migrationsOf = (files) => Effect_exports.gen(function* () {
|
|
977
|
+
const found = [];
|
|
978
|
+
for (const file of files) {
|
|
979
|
+
if (!file.path.startsWith(`${migrationsDirectory}/`) || !file.path.endsWith(".sql")) continue;
|
|
980
|
+
const name = file.path.slice(migrationsDirectory.length + 1);
|
|
981
|
+
const match = migrationName.exec(name);
|
|
982
|
+
if (name.includes("/") || match === null)
|
|
983
|
+
return yield* new MigrationFileInvalid({
|
|
984
|
+
path: file.path,
|
|
985
|
+
reason: "migrations are files directly in migrations/ named like 0001_create_notes.sql: a number that orders them, an underscore, then a name."
|
|
986
|
+
});
|
|
987
|
+
const content = file.content.replaceAll("\r\n", "\n");
|
|
988
|
+
found.push({
|
|
989
|
+
path: file.path,
|
|
990
|
+
order: Number(match[1]),
|
|
991
|
+
content,
|
|
992
|
+
hash: yield* sha256(content)
|
|
993
|
+
});
|
|
994
|
+
}
|
|
995
|
+
const ordered = [...found].sort((left, right) => left.order - right.order);
|
|
996
|
+
for (const [index, migration] of ordered.entries()) {
|
|
997
|
+
const previous = ordered[index - 1];
|
|
998
|
+
if (previous !== void 0 && previous.order === migration.order)
|
|
999
|
+
return yield* new MigrationFileInvalid({
|
|
1000
|
+
path: migration.path,
|
|
1001
|
+
reason: `it has the same number as ${previous.path}; give each migration its own number.`
|
|
1002
|
+
});
|
|
1003
|
+
}
|
|
1004
|
+
return ordered;
|
|
1005
|
+
});
|
|
1006
|
+
var History = Schema_exports.Array(
|
|
1007
|
+
Schema_exports.Struct({ id: Schema_exports.Number, path: Schema_exports.String, hash: Schema_exports.String })
|
|
1008
|
+
);
|
|
1009
|
+
var migrate = (storage, files) => Effect_exports.gen(function* () {
|
|
1010
|
+
const migrations = yield* migrationsOf(files);
|
|
1011
|
+
const baseline = readSettings(storage);
|
|
1012
|
+
return yield* Effect_exports.sync(
|
|
1013
|
+
() => storage.transactionSync(() => {
|
|
1014
|
+
storage.sql.exec(
|
|
1015
|
+
`CREATE TABLE IF NOT EXISTS ${migrationsTable} (id INTEGER PRIMARY KEY, path TEXT NOT NULL, hash TEXT NOT NULL, applied_at TEXT NOT NULL)`
|
|
1016
|
+
);
|
|
1017
|
+
const stored = storage.sql.exec("SELECT 1 FROM sqlite_master WHERE type = 'table' AND name = 'app_rows'").toArray().length > 0;
|
|
1018
|
+
storage.sql.exec(`DROP VIEW IF EXISTS ${legacyRows}`);
|
|
1019
|
+
storage.sql.exec(
|
|
1020
|
+
`CREATE VIEW ${legacyRows} (table_name, id, body) AS ${stored ? "SELECT table_name, id, body FROM app_rows" : "SELECT '', '', '' WHERE 0"}`
|
|
1021
|
+
);
|
|
1022
|
+
const history = Schema_exports.decodeUnknownSync(History)(
|
|
1023
|
+
storage.sql.exec(`SELECT id, path, hash FROM ${migrationsTable} ORDER BY id`).toArray()
|
|
1024
|
+
);
|
|
1025
|
+
for (const [index, applied] of history.entries()) {
|
|
1026
|
+
const current = migrations[index];
|
|
1027
|
+
if (current === void 0)
|
|
1028
|
+
throw new MigrationHistoryChanged({
|
|
1029
|
+
reason: `${applied.path} was applied to this app's database but is no longer in migrations/.`
|
|
1030
|
+
});
|
|
1031
|
+
if (current.path !== applied.path)
|
|
1032
|
+
throw new MigrationHistoryChanged({
|
|
1033
|
+
reason: `Migration ${index + 1} was applied as ${applied.path}, but the build has ${current.path} in its place.`
|
|
1034
|
+
});
|
|
1035
|
+
if (current.hash !== applied.hash)
|
|
1036
|
+
throw new MigrationHistoryChanged({
|
|
1037
|
+
reason: `${applied.path} changed after it was applied to this app's database.`
|
|
1038
|
+
});
|
|
1039
|
+
}
|
|
1040
|
+
const pending = migrations.slice(history.length);
|
|
1041
|
+
const appliedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
1042
|
+
for (const [offset, migration] of pending.entries()) {
|
|
1043
|
+
const statements = statementsOf(migration.content);
|
|
1044
|
+
try {
|
|
1045
|
+
if (statements !== "") storage.sql.exec(statements);
|
|
1046
|
+
} catch (error) {
|
|
1047
|
+
throw new MigrationFailed({
|
|
1048
|
+
path: migration.path,
|
|
1049
|
+
reason: error instanceof Error ? error.message : String(error)
|
|
1050
|
+
});
|
|
1051
|
+
}
|
|
1052
|
+
storage.sql.exec(
|
|
1053
|
+
`INSERT INTO ${migrationsTable} (id, path, hash, applied_at) VALUES (?, ?, ?, ?)`,
|
|
1054
|
+
history.length + offset + 1,
|
|
1055
|
+
migration.path,
|
|
1056
|
+
migration.hash,
|
|
1057
|
+
appliedAt
|
|
1058
|
+
);
|
|
1059
|
+
}
|
|
1060
|
+
return pending.map((migration, offset) => ({
|
|
1061
|
+
id: history.length + offset + 1,
|
|
1062
|
+
name: migration.path
|
|
1063
|
+
}));
|
|
1064
|
+
})
|
|
1065
|
+
).pipe(
|
|
1066
|
+
// Both are thrown inside the transaction so that it rolls back; they are expected failures.
|
|
1067
|
+
Effect_exports.catchDefect(
|
|
1068
|
+
(defect) => Schema_exports.is(MigrationFailed)(defect) || Schema_exports.is(MigrationHistoryChanged)(defect) ? Effect_exports.fail(defect) : Effect_exports.die(defect)
|
|
1069
|
+
),
|
|
1070
|
+
Effect_exports.ensuring(Effect_exports.sync(() => restoreSettings(storage, baseline)))
|
|
1071
|
+
);
|
|
1072
|
+
});
|
|
559
1073
|
|
|
560
1074
|
// src/implementation/host.ts
|
|
561
1075
|
var WireCatalog = Schema_exports.Struct({
|
|
@@ -575,9 +1089,9 @@ var evaluationSafe = (work, secrets) => work.pipe(
|
|
|
575
1089
|
const error = Cause_exports.squash(cause);
|
|
576
1090
|
const provider = parseProviderError(error);
|
|
577
1091
|
const skills = parseSkillLoadFailed(error);
|
|
578
|
-
const mcp = parseMcpError(error);
|
|
1092
|
+
const mcp = parseMcpError(error, secrets);
|
|
579
1093
|
return Effect_exports.fail(
|
|
580
|
-
Option_exports.isSome(provider) ? provider.value : Option_exports.isSome(skills) ? skills.value : Option_exports.isSome(mcp) ? mcp.value : new HostEvaluationFailed(failureDetail(error, secrets))
|
|
1094
|
+
Option_exports.isSome(provider) ? leavingProviderError(provider.value, secrets, "discover") : Option_exports.isSome(skills) ? skills.value : Option_exports.isSome(mcp) ? mcp.value : new HostEvaluationFailed(failureDetail(error, secrets))
|
|
581
1095
|
);
|
|
582
1096
|
})
|
|
583
1097
|
);
|
|
@@ -594,6 +1108,15 @@ var declarationSafe = (work, summary) => Effect_exports.suspend(work).pipe(
|
|
|
594
1108
|
(cause) => Cause_exports.hasInterrupts(cause) ? Effect_exports.interrupt : Effect_exports.fail(declarationInvalid(summary, Cause_exports.squash(cause)))
|
|
595
1109
|
)
|
|
596
1110
|
);
|
|
1111
|
+
function declaredExposure(exposure) {
|
|
1112
|
+
const named = (kind) => Object.entries(exposure ?? {}).filter(([, value]) => value === kind).map(([field]) => field).sort();
|
|
1113
|
+
const plain = named("plain");
|
|
1114
|
+
const raw = named("raw");
|
|
1115
|
+
return { ...plain.length === 0 ? {} : { plain }, ...raw.length === 0 ? {} : { raw } };
|
|
1116
|
+
}
|
|
1117
|
+
function declaredPlacements(request) {
|
|
1118
|
+
return request === void 0 || request.length === 0 ? {} : { request: normalizePlacements(request) };
|
|
1119
|
+
}
|
|
597
1120
|
function providerDeclaration(provider) {
|
|
598
1121
|
return declarationSafe(
|
|
599
1122
|
() => Effect_exports.gen(function* () {
|
|
@@ -604,27 +1127,33 @@ function providerDeclaration(provider) {
|
|
|
604
1127
|
auth.set(name, {
|
|
605
1128
|
type: "secrets",
|
|
606
1129
|
label: method.label,
|
|
607
|
-
fields: yield* jsonSchemaDocument(method.fields)
|
|
1130
|
+
fields: yield* jsonSchemaDocument(method.fields),
|
|
1131
|
+
...declaredExposure(method.exposure),
|
|
1132
|
+
...declaredPlacements(method.request)
|
|
608
1133
|
});
|
|
609
1134
|
break;
|
|
610
1135
|
case "oauth2":
|
|
611
1136
|
auth.set(name, {
|
|
612
1137
|
type: "oauth2",
|
|
613
1138
|
...method.config,
|
|
614
|
-
response: yield* jsonSchemaDocument(method.response)
|
|
1139
|
+
response: yield* jsonSchemaDocument(method.response),
|
|
1140
|
+
...declaredExposure(method.exposure),
|
|
1141
|
+
...declaredPlacements(method.request)
|
|
615
1142
|
});
|
|
616
1143
|
break;
|
|
617
1144
|
}
|
|
618
1145
|
}
|
|
619
1146
|
return yield* Schema_exports.decodeUnknownEffect(DeclaredProvider)({
|
|
620
1147
|
name: provider.name,
|
|
621
|
-
auth: Object.fromEntries(auth)
|
|
1148
|
+
auth: Object.fromEntries(auth),
|
|
1149
|
+
// Order and repetition carry no meaning, so neither changes the provider's identity.
|
|
1150
|
+
...provider.hosts === void 0 ? {} : { hosts: [...new Set(provider.hosts)].sort() }
|
|
622
1151
|
});
|
|
623
1152
|
}),
|
|
624
1153
|
`Account provider "${provider.name}" has an invalid declaration`
|
|
625
1154
|
);
|
|
626
1155
|
}
|
|
627
|
-
function requirements(slots,
|
|
1156
|
+
function requirements(slots, sql, events) {
|
|
628
1157
|
return Effect_exports.gen(function* () {
|
|
629
1158
|
const accounts = /* @__PURE__ */ new Map();
|
|
630
1159
|
for (const [slot, selection] of Object.entries(slots)) {
|
|
@@ -638,10 +1167,16 @@ function requirements(slots, database) {
|
|
|
638
1167
|
return yield* Schema_exports.decodeUnknownEffect(DeclaredRequirements)({
|
|
639
1168
|
accounts: Object.fromEntries(accounts),
|
|
640
1169
|
capabilities: { skills: true, toolIndex: true, skillSources: true, scheduledTools: true },
|
|
641
|
-
...
|
|
1170
|
+
...sql ? { sql: true } : {},
|
|
1171
|
+
...events === void 0 || Object.keys(events).length === 0 ? {} : {
|
|
1172
|
+
events: yield* declarationSafe(
|
|
1173
|
+
() => declaredEvents(events),
|
|
1174
|
+
"The app's event declarations are invalid"
|
|
1175
|
+
)
|
|
1176
|
+
}
|
|
642
1177
|
}).pipe(
|
|
643
1178
|
Effect_exports.mapError(
|
|
644
|
-
(cause) => declarationInvalid("The app's account
|
|
1179
|
+
(cause) => declarationInvalid("The app's account declarations are invalid", cause)
|
|
645
1180
|
)
|
|
646
1181
|
);
|
|
647
1182
|
});
|
|
@@ -653,6 +1188,17 @@ function canonical(value) {
|
|
|
653
1188
|
}
|
|
654
1189
|
return JSON.stringify(value);
|
|
655
1190
|
}
|
|
1191
|
+
function withoutGrants({ hosts: _hosts, ...provider }) {
|
|
1192
|
+
return {
|
|
1193
|
+
...provider,
|
|
1194
|
+
auth: Object.fromEntries(
|
|
1195
|
+
Object.entries(provider.auth).map(([name, { request: _request, ...method }]) => [
|
|
1196
|
+
name,
|
|
1197
|
+
method
|
|
1198
|
+
])
|
|
1199
|
+
)
|
|
1200
|
+
};
|
|
1201
|
+
}
|
|
656
1202
|
function bindAccounts(slots, declarations, context) {
|
|
657
1203
|
return safe2(
|
|
658
1204
|
() => Effect_exports.gen(function* () {
|
|
@@ -678,14 +1224,17 @@ function bindAccounts(slots, declarations, context) {
|
|
|
678
1224
|
for (const account of accounts) {
|
|
679
1225
|
if (ids.has(account.id)) return yield* Effect_exports.fail(new HostAccountsInvalid());
|
|
680
1226
|
ids.add(account.id);
|
|
681
|
-
if (canonical(account.provider) !== canonical(requirement.definition) || !Object.hasOwn(provider.auth, account.method))
|
|
1227
|
+
if (canonical(withoutGrants(account.provider)) !== canonical(withoutGrants(requirement.definition)) || !Object.hasOwn(provider.auth, account.method))
|
|
682
1228
|
return yield* Effect_exports.fail(new HostAccountsInvalid());
|
|
683
1229
|
const method = provider.auth[account.method];
|
|
684
1230
|
if (method === void 0) return yield* Effect_exports.fail(new HostAccountsInvalid());
|
|
685
1231
|
const fields = yield* Schema_exports.decodeUnknownEffect(
|
|
686
1232
|
method._tag === "secrets" ? method.fields : method.response
|
|
687
1233
|
)(account.fields);
|
|
688
|
-
|
|
1234
|
+
const granted = Object.hasOwn(account.provider.auth, account.method) ? account.provider.auth[account.method]?.request : void 0;
|
|
1235
|
+
values.push(
|
|
1236
|
+
withPlacements({ id: account.id, method: account.method, fields }, granted)
|
|
1237
|
+
);
|
|
689
1238
|
}
|
|
690
1239
|
if (many) bound.set(slot, values);
|
|
691
1240
|
else {
|
|
@@ -699,7 +1248,42 @@ function bindAccounts(slots, declarations, context) {
|
|
|
699
1248
|
new HostAccountsInvalid()
|
|
700
1249
|
);
|
|
701
1250
|
}
|
|
702
|
-
|
|
1251
|
+
var fetchLifetime = (signal, background) => Effect_exports.acquireRelease(
|
|
1252
|
+
Effect_exports.sync(() => {
|
|
1253
|
+
const controller = new AbortController();
|
|
1254
|
+
let refreshes = 0;
|
|
1255
|
+
let ended = false;
|
|
1256
|
+
const settle = () => {
|
|
1257
|
+
if (ended && refreshes === 0) controller.abort();
|
|
1258
|
+
};
|
|
1259
|
+
const end = () => {
|
|
1260
|
+
ended = true;
|
|
1261
|
+
settle();
|
|
1262
|
+
};
|
|
1263
|
+
signal.addEventListener("abort", end, { once: true });
|
|
1264
|
+
if (signal.aborted) end();
|
|
1265
|
+
const settled = Effect_exports.sync(() => {
|
|
1266
|
+
refreshes -= 1;
|
|
1267
|
+
settle();
|
|
1268
|
+
});
|
|
1269
|
+
return {
|
|
1270
|
+
signal: controller.signal,
|
|
1271
|
+
close: () => {
|
|
1272
|
+
signal.removeEventListener("abort", end);
|
|
1273
|
+
end();
|
|
1274
|
+
},
|
|
1275
|
+
/** Counted from the hand-off, so a refresh that has not started yet keeps the fetch. */
|
|
1276
|
+
background: (task) => Effect_exports.suspend(() => {
|
|
1277
|
+
refreshes += 1;
|
|
1278
|
+
return background(task.pipe(Effect_exports.ensuring(settled))).pipe(
|
|
1279
|
+
Effect_exports.onError(() => settled)
|
|
1280
|
+
);
|
|
1281
|
+
})
|
|
1282
|
+
};
|
|
1283
|
+
}),
|
|
1284
|
+
(lifetime) => Effect_exports.sync(lifetime.close)
|
|
1285
|
+
);
|
|
1286
|
+
function dispatch(app, request, context, signal, emitted) {
|
|
703
1287
|
return Effect_exports.scoped(
|
|
704
1288
|
Effect_exports.gen(function* () {
|
|
705
1289
|
if (!isApp(app))
|
|
@@ -708,28 +1292,52 @@ function dispatch(app, request, context, signal) {
|
|
|
708
1292
|
);
|
|
709
1293
|
const native = toEffectApp(app);
|
|
710
1294
|
const secrets = accountSecrets(context.accounts);
|
|
711
|
-
const
|
|
712
|
-
const declared = yield* requirements(native.accounts, native.
|
|
713
|
-
if (request.operation === "requirements")
|
|
714
|
-
if (native.database !== void 0)
|
|
715
|
-
yield* parseDatabaseSchema(native.database.schema).pipe(
|
|
716
|
-
Effect_exports.catchTag(
|
|
717
|
-
"AppDatabaseError",
|
|
718
|
-
(cause) => Effect_exports.fail(
|
|
719
|
-
declarationInvalid("The app's account or database declarations are invalid", cause)
|
|
720
|
-
)
|
|
721
|
-
)
|
|
722
|
-
);
|
|
1295
|
+
const ownsSql = hasMigrations(context.files ?? []);
|
|
1296
|
+
const declared = yield* requirements(native.accounts, ownsSql, native.events);
|
|
1297
|
+
if (request.operation === "requirements")
|
|
723
1298
|
return yield* safe2(
|
|
724
1299
|
() => Schema_exports.decodeUnknownEffect(JsonValue)(declared),
|
|
725
1300
|
new HostDeclarationInvalid()
|
|
726
1301
|
);
|
|
1302
|
+
if (request.operation === "migrate") {
|
|
1303
|
+
if (!ownsSql) return yield* new HostOperationNotFound();
|
|
1304
|
+
const storage2 = context.storage;
|
|
1305
|
+
if (storage2 === void 0)
|
|
1306
|
+
return yield* new HostOperationFailed(
|
|
1307
|
+
failureDetail(new Error("This host gave the app no SQL storage."), secrets)
|
|
1308
|
+
);
|
|
1309
|
+
const sources = yield* Schema_exports.decodeUnknownEffect(Schema_exports.Array(SkillFile))(
|
|
1310
|
+
context.files ?? []
|
|
1311
|
+
).pipe(Effect_exports.mapError(() => new HostDeclarationInvalid()));
|
|
1312
|
+
const applied = yield* migrate(storage2, sources).pipe(
|
|
1313
|
+
Effect_exports.mapError((error) => new HostOperationFailed(failureDetail(error, secrets))),
|
|
1314
|
+
Effect_exports.withSpan("app.sql.migrate")
|
|
1315
|
+
);
|
|
1316
|
+
return yield* safe2(
|
|
1317
|
+
() => Schema_exports.decodeUnknownEffect(JsonValue)(applied),
|
|
1318
|
+
new HostOutputInvalid()
|
|
1319
|
+
);
|
|
727
1320
|
}
|
|
728
1321
|
const lifetime = yield* Effect_exports.acquireRelease(
|
|
729
1322
|
Effect_exports.sync(() => new AbortController()),
|
|
730
1323
|
(controller) => Effect_exports.sync(() => controller.abort())
|
|
731
1324
|
);
|
|
732
1325
|
const invocationSignal = AbortSignal.any([signal, lifetime.signal]);
|
|
1326
|
+
const storage = context.storage;
|
|
1327
|
+
const sqlSession = (step) => !ownsSql ? Effect_exports.succeed({ reader: noDatabase, writer: noDatabase }) : storage === void 0 ? Effect_exports.fail(
|
|
1328
|
+
new HostOperationFailed(
|
|
1329
|
+
failureDetail(new Error("This host gave the app no SQL storage."), secrets)
|
|
1330
|
+
)
|
|
1331
|
+
) : Effect_exports.acquireRelease(
|
|
1332
|
+
Effect_exports.sync(
|
|
1333
|
+
() => authorSql(storage, {
|
|
1334
|
+
signal: invocationSignal,
|
|
1335
|
+
emitted,
|
|
1336
|
+
...step === void 0 ? {} : { step }
|
|
1337
|
+
})
|
|
1338
|
+
),
|
|
1339
|
+
(session2) => Effect_exports.sync(session2.close)
|
|
1340
|
+
);
|
|
733
1341
|
const deadline = context.deadline === void 0 ? void 0 : yield* safe2(
|
|
734
1342
|
() => Schema_exports.decodeUnknownEffect(InvocationDeadline)(context.deadline),
|
|
735
1343
|
new HostInputInvalid()
|
|
@@ -756,33 +1364,56 @@ function dispatch(app, request, context, signal) {
|
|
|
756
1364
|
declared,
|
|
757
1365
|
request.requirement,
|
|
758
1366
|
context,
|
|
759
|
-
invocationSignal
|
|
1367
|
+
invocationSignal,
|
|
1368
|
+
deadline
|
|
760
1369
|
).pipe(withinDeadline);
|
|
761
1370
|
let running;
|
|
762
|
-
let transactionOpen = false;
|
|
763
1371
|
const delivery = (request2, signal2) => Effect_exports.suspend(
|
|
764
|
-
() =>
|
|
765
|
-
|
|
1372
|
+
() => running !== void 0 && context.elicitation !== void 0 ? context.elicitation(request2, signal2).pipe(
|
|
1373
|
+
// Delivering the question and waiting for its answer is the person's time.
|
|
1374
|
+
owned("person", "app.tool.elicitation"),
|
|
766
1375
|
Effect_exports.provideContext(running.context)
|
|
767
1376
|
) : Effect_exports.fail(new ElicitationFailed({ reason: "unavailable" }))
|
|
768
1377
|
);
|
|
769
1378
|
const unavailableWorkflow = () => Effect_exports.fail(new WorkflowFailure({ reason: "unavailable", retryable: false }));
|
|
1379
|
+
const telemetry = yield* captureTelemetry;
|
|
1380
|
+
const control = (operation, work) => work.pipe(
|
|
1381
|
+
owned("executor", workflowControlSpan, {
|
|
1382
|
+
attributes: { "executor.workflow.operation": operation }
|
|
1383
|
+
})
|
|
1384
|
+
);
|
|
770
1385
|
const workflowControls = {
|
|
771
1386
|
start: toPromise(
|
|
772
|
-
(input2) =>
|
|
773
|
-
|
|
1387
|
+
(input2) => control(
|
|
1388
|
+
"start",
|
|
1389
|
+
context.workflowControls === void 0 ? unavailableWorkflow() : context.workflowControls.start(input2)
|
|
1390
|
+
),
|
|
1391
|
+
invocationSignal,
|
|
1392
|
+
telemetry.context
|
|
774
1393
|
),
|
|
775
1394
|
get: toPromise(
|
|
776
|
-
(input2) =>
|
|
777
|
-
|
|
1395
|
+
(input2) => control(
|
|
1396
|
+
"get",
|
|
1397
|
+
context.workflowControls === void 0 ? unavailableWorkflow() : context.workflowControls.get(input2)
|
|
1398
|
+
),
|
|
1399
|
+
invocationSignal,
|
|
1400
|
+
telemetry.context
|
|
778
1401
|
),
|
|
779
1402
|
list: toPromise(
|
|
780
|
-
(input2) =>
|
|
781
|
-
|
|
1403
|
+
(input2) => control(
|
|
1404
|
+
"list",
|
|
1405
|
+
context.workflowControls === void 0 ? unavailableWorkflow() : context.workflowControls.list(input2)
|
|
1406
|
+
),
|
|
1407
|
+
invocationSignal,
|
|
1408
|
+
telemetry.context
|
|
782
1409
|
),
|
|
783
1410
|
terminate: toPromise(
|
|
784
|
-
(input2) =>
|
|
785
|
-
|
|
1411
|
+
(input2) => control(
|
|
1412
|
+
"terminate",
|
|
1413
|
+
context.workflowControls === void 0 ? unavailableWorkflow() : context.workflowControls.terminate(input2)
|
|
1414
|
+
),
|
|
1415
|
+
invocationSignal,
|
|
1416
|
+
telemetry.context
|
|
786
1417
|
)
|
|
787
1418
|
};
|
|
788
1419
|
const workflowReads = {
|
|
@@ -794,6 +1425,7 @@ function dispatch(app, request, context, signal) {
|
|
|
794
1425
|
).pipe(Effect_exports.mapError(() => new HostDeclarationInvalid()));
|
|
795
1426
|
let cacheCommands = 0;
|
|
796
1427
|
const hostCache = context.cache ?? unavailableCache;
|
|
1428
|
+
const fetching = yield* fetchLifetime(signal, hostCache.background);
|
|
797
1429
|
const bound = {
|
|
798
1430
|
cache: authorCache(
|
|
799
1431
|
{
|
|
@@ -801,10 +1433,12 @@ function dispatch(app, request, context, signal) {
|
|
|
801
1433
|
transport: (command) => {
|
|
802
1434
|
cacheCommands += 1;
|
|
803
1435
|
return hostCache.transport(command);
|
|
804
|
-
}
|
|
1436
|
+
},
|
|
1437
|
+
background: fetching.background
|
|
805
1438
|
},
|
|
806
1439
|
Redacted_exports.value(context.accounts),
|
|
807
1440
|
invocationSignal,
|
|
1441
|
+
telemetry.context,
|
|
808
1442
|
deadline
|
|
809
1443
|
),
|
|
810
1444
|
files,
|
|
@@ -813,9 +1447,20 @@ function dispatch(app, request, context, signal) {
|
|
|
813
1447
|
),
|
|
814
1448
|
workflows: workflowReads,
|
|
815
1449
|
signal: invocationSignal,
|
|
816
|
-
fetch: yield*
|
|
817
|
-
elicit: makeElicit(delivery, invocationSignal)
|
|
1450
|
+
fetch: yield* appInvocationFetch(fetching.signal),
|
|
1451
|
+
elicit: makeElicit(delivery, invocationSignal, telemetry.context)
|
|
818
1452
|
};
|
|
1453
|
+
const accountIds = Object.values(bound.accounts).flatMap(
|
|
1454
|
+
(selected) => (Array.isArray(selected) ? selected : [selected]).map(
|
|
1455
|
+
(account) => account.id
|
|
1456
|
+
)
|
|
1457
|
+
);
|
|
1458
|
+
const emitter = (sourceAccount) => makeEmitter({
|
|
1459
|
+
events: native.events ?? {},
|
|
1460
|
+
accounts: accountIds,
|
|
1461
|
+
...sourceAccount === void 0 ? {} : { sourceAccount },
|
|
1462
|
+
emitted
|
|
1463
|
+
});
|
|
819
1464
|
const definition = yield* evaluationSafe(native.evaluate(bound), secrets).pipe(
|
|
820
1465
|
Effect_exports.withSpan("app.evaluate")
|
|
821
1466
|
);
|
|
@@ -887,10 +1532,11 @@ function dispatch(app, request, context, signal) {
|
|
|
887
1532
|
cache: authorCache(
|
|
888
1533
|
context.cache ?? unavailableCache,
|
|
889
1534
|
Redacted_exports.value(current.accounts),
|
|
890
|
-
signal2
|
|
1535
|
+
signal2,
|
|
1536
|
+
(yield* captureTelemetry).context
|
|
891
1537
|
),
|
|
892
1538
|
files,
|
|
893
|
-
fetch: yield*
|
|
1539
|
+
fetch: yield* appInvocationFetch(signal2),
|
|
894
1540
|
signal: signal2,
|
|
895
1541
|
runId: execution.runId,
|
|
896
1542
|
stepId,
|
|
@@ -938,7 +1584,8 @@ function dispatch(app, request, context, signal) {
|
|
|
938
1584
|
);
|
|
939
1585
|
}
|
|
940
1586
|
if (request.operation === "webhook-complete" || request.operation === "webhook-validate" || request.operation === "webhooks" || request.operation === "webhook-register" || request.operation === "webhook-handle" || request.operation === "webhook-unregister") {
|
|
941
|
-
const
|
|
1587
|
+
const session2 = yield* sqlSession();
|
|
1588
|
+
return yield* dispatchWebhook(
|
|
942
1589
|
definition,
|
|
943
1590
|
request,
|
|
944
1591
|
{
|
|
@@ -948,27 +1595,17 @@ function dispatch(app, request, context, signal) {
|
|
|
948
1595
|
workflows: workflowControls,
|
|
949
1596
|
signal: bound.signal,
|
|
950
1597
|
fetch: bound.fetch,
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
}
|
|
1598
|
+
sql: session2.writer,
|
|
1599
|
+
events: emitter("sourceAccount" in request ? request.sourceAccount : void 0)
|
|
954
1600
|
},
|
|
955
1601
|
Redacted_exports.value(context.accounts)
|
|
956
1602
|
);
|
|
957
|
-
if (native.database === void 0 || !["webhook-register", "webhook-handle", "webhook-unregister"].includes(request.operation))
|
|
958
|
-
return yield* executeWebhook();
|
|
959
|
-
const storage2 = context.storage ?? unavailableStorage;
|
|
960
|
-
return yield* storage2.mutate(native.database.schema, executeWebhook).pipe(
|
|
961
|
-
Effect_exports.catchTags({
|
|
962
|
-
AppDatabaseError: storageFailure,
|
|
963
|
-
DatabaseLimitExceeded: (error) => Effect_exports.fail(error),
|
|
964
|
-
AppStorageUnavailable: storageFailure,
|
|
965
|
-
AppStorageError: storageFailure
|
|
966
|
-
})
|
|
967
|
-
);
|
|
968
1603
|
}
|
|
969
1604
|
const toolName = request.operation === "call" ? request.tool : request.name;
|
|
970
1605
|
const location = locate(definition.tools, toolName);
|
|
971
|
-
const tool = location === void 0 ? void 0 : location.kind === "operation" ? location.operation : yield* evaluationSafe(location.source.resolve(location.name), secrets)
|
|
1606
|
+
const tool = location === void 0 ? void 0 : location.kind === "operation" ? location.operation : yield* evaluationSafe(location.source.resolve(location.name), secrets).pipe(
|
|
1607
|
+
Effect_exports.withSpan("app.tool.resolve")
|
|
1608
|
+
);
|
|
972
1609
|
if (tool === void 0)
|
|
973
1610
|
return yield* request.operation === "call" ? new HostToolNotFound() : new HostOperationNotFound();
|
|
974
1611
|
const requested = request.operation === "call" ? request.kind : request.operation === "query" ? "query" : "mutation";
|
|
@@ -979,7 +1616,7 @@ function dispatch(app, request, context, signal) {
|
|
|
979
1616
|
() => Schema_exports.decodeUnknownEffect(tool.input)(request.input)
|
|
980
1617
|
).pipe(
|
|
981
1618
|
Effect_exports.catchCause(
|
|
982
|
-
(cause) => Cause_exports.hasInterrupts(cause) ? Effect_exports.interrupt : Effect_exports.fail(inputInvalid(Cause_exports.squash(cause)))
|
|
1619
|
+
(cause) => Cause_exports.hasInterrupts(cause) ? Effect_exports.interrupt : Effect_exports.fail(inputInvalid(Cause_exports.squash(cause), request.input))
|
|
983
1620
|
)
|
|
984
1621
|
);
|
|
985
1622
|
if (context.approval !== void 0) {
|
|
@@ -1024,24 +1661,23 @@ function dispatch(app, request, context, signal) {
|
|
|
1024
1661
|
Match_exports.exhaustive
|
|
1025
1662
|
);
|
|
1026
1663
|
}
|
|
1027
|
-
const
|
|
1028
|
-
|
|
1664
|
+
const replay = context.replay === void 0 ? void 0 : yield* safe2(
|
|
1665
|
+
() => Schema_exports.decodeUnknownEffect(WorkflowReplay)(context.replay),
|
|
1666
|
+
new HostInputInvalid()
|
|
1667
|
+
);
|
|
1668
|
+
if (replay !== void 0 && kind !== "mutate") return yield* new HostInputInvalid();
|
|
1669
|
+
const session = yield* sqlSession(replay);
|
|
1670
|
+
const execute = () => Effect_exports.gen(function* () {
|
|
1029
1671
|
const output = yield* Effect_exports.gen(function* () {
|
|
1030
1672
|
running = yield* captureTelemetry;
|
|
1031
|
-
const fetch = yield*
|
|
1673
|
+
const fetch = yield* appInvocationFetch(fetching.signal);
|
|
1032
1674
|
return yield* tool.run(
|
|
1033
1675
|
{
|
|
1034
1676
|
...bound,
|
|
1035
1677
|
fetch,
|
|
1036
1678
|
workflows: kind === "mutate" ? workflowControls : workflowReads,
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
native.database.tables,
|
|
1040
|
-
db,
|
|
1041
|
-
invocationSignal,
|
|
1042
|
-
kind === "mutate"
|
|
1043
|
-
)
|
|
1044
|
-
}
|
|
1679
|
+
sql: kind === "mutate" ? session.writer : session.reader,
|
|
1680
|
+
...kind === "mutate" ? { events: emitter() } : {}
|
|
1045
1681
|
},
|
|
1046
1682
|
input
|
|
1047
1683
|
);
|
|
@@ -1056,14 +1692,15 @@ function dispatch(app, request, context, signal) {
|
|
|
1056
1692
|
const error = Cause_exports.squash(cause);
|
|
1057
1693
|
const provider = parseProviderError(error);
|
|
1058
1694
|
const response = Schema_exports.decodeUnknownOption(OpenapiResponseError)(error);
|
|
1695
|
+
const mcp = parseMcpError(error, secrets);
|
|
1059
1696
|
const failure = Schema_exports.decodeUnknownOption(ElicitationFailed)(error);
|
|
1060
1697
|
return Effect_exports.fail(
|
|
1061
|
-
Option_exports.isSome(provider) ? provider.value : Option_exports.isSome(response) ? new OpenapiResponseError({
|
|
1698
|
+
Option_exports.isSome(provider) ? leavingProviderError(provider.value, secrets, "call") : Option_exports.isSome(response) ? new OpenapiResponseError({
|
|
1062
1699
|
code: response.value.code,
|
|
1063
1700
|
status: response.value.status,
|
|
1064
1701
|
message: response.value.message,
|
|
1065
1702
|
...response.value.recovery === void 0 ? {} : { recovery: response.value.recovery }
|
|
1066
|
-
}) : Option_exports.isSome(failure) ? failure.value : new HostOperationFailed(failureDetail(error, secrets))
|
|
1703
|
+
}) : Option_exports.isSome(mcp) ? mcp.value : Option_exports.isSome(failure) ? failure.value : new HostOperationFailed(failureDetail(error, secrets))
|
|
1067
1704
|
);
|
|
1068
1705
|
}),
|
|
1069
1706
|
Effect_exports.withSpan("app.operation.execute", {
|
|
@@ -1080,30 +1717,11 @@ function dispatch(app, request, context, signal) {
|
|
|
1080
1717
|
new HostOutputInvalid()
|
|
1081
1718
|
);
|
|
1082
1719
|
});
|
|
1083
|
-
|
|
1084
|
-
() => Schema_exports.decodeUnknownEffect(WorkflowReplay)(context.replay),
|
|
1085
|
-
new HostInputInvalid()
|
|
1086
|
-
);
|
|
1087
|
-
if (replay !== void 0 && kind !== "mutate") return yield* new HostInputInvalid();
|
|
1088
|
-
if (native.database === void 0) return yield* withinDeadline(execute());
|
|
1089
|
-
const storage = context.storage ?? unavailableStorage;
|
|
1090
|
-
return yield* storage[kind === "query" ? "read" : "mutate"](
|
|
1091
|
-
native.database.schema,
|
|
1092
|
-
(db) => withinDeadline(
|
|
1093
|
-
replay === void 0 ? execute(db) : db.once(replay.key, replay.fingerprint, () => execute(db))
|
|
1094
|
-
)
|
|
1095
|
-
).pipe(
|
|
1096
|
-
Effect_exports.catchTags({
|
|
1097
|
-
AppDatabaseError: storageFailure,
|
|
1098
|
-
DatabaseLimitExceeded: (error) => Effect_exports.fail(error),
|
|
1099
|
-
AppStorageUnavailable: storageFailure,
|
|
1100
|
-
AppStorageError: storageFailure
|
|
1101
|
-
})
|
|
1102
|
-
);
|
|
1720
|
+
return yield* withinDeadline(execute());
|
|
1103
1721
|
})
|
|
1104
1722
|
);
|
|
1105
1723
|
}
|
|
1106
|
-
function checkAccount(slots, declared, requirement, context, signal) {
|
|
1724
|
+
function checkAccount(slots, declared, requirement, context, signal, deadline) {
|
|
1107
1725
|
return Effect_exports.gen(function* () {
|
|
1108
1726
|
const selection = Object.hasOwn(slots, requirement) ? slots[requirement] : void 0;
|
|
1109
1727
|
const slot = Object.hasOwn(declared.accounts, requirement) ? declared.accounts[requirement] : void 0;
|
|
@@ -1120,7 +1738,12 @@ function checkAccount(slots, declared, requirement, context, signal) {
|
|
|
1120
1738
|
if (account === void 0 || !("id" in account)) return yield* new HostAccountsInvalid();
|
|
1121
1739
|
const result = yield* Effect_exports.suspend(
|
|
1122
1740
|
() => Effect_exports.gen(function* () {
|
|
1123
|
-
return yield* health.run({
|
|
1741
|
+
return yield* health.run({
|
|
1742
|
+
account,
|
|
1743
|
+
fetch: yield* appInvocationFetch(signal),
|
|
1744
|
+
signal,
|
|
1745
|
+
...deadline === void 0 ? {} : { deadline }
|
|
1746
|
+
});
|
|
1124
1747
|
})
|
|
1125
1748
|
).pipe(
|
|
1126
1749
|
Effect_exports.catchCause((cause) => {
|
|
@@ -1128,8 +1751,9 @@ function checkAccount(slots, declared, requirement, context, signal) {
|
|
|
1128
1751
|
const error = Cause_exports.squash(cause);
|
|
1129
1752
|
const status = Schema_exports.decodeUnknownOption(ResponseStatusError)(error);
|
|
1130
1753
|
const classified = Option_exports.isSome(status) ? Option_exports.fromNullishOr(httpProviderError(status.value.status)) : parseProviderError(error);
|
|
1754
|
+
const secrets = accountSecrets(context.accounts);
|
|
1131
1755
|
return Effect_exports.fail(
|
|
1132
|
-
Option_exports.isSome(classified) ? accountProviderError(classified.value, account.id) : new HostOperationFailed()
|
|
1756
|
+
Option_exports.isSome(classified) ? leavingProviderError(accountProviderError(classified.value, account.id), secrets) : new HostOperationFailed(failureDetail(error, secrets))
|
|
1133
1757
|
);
|
|
1134
1758
|
}),
|
|
1135
1759
|
Effect_exports.withSpan("app.account.check")
|
|
@@ -1143,20 +1767,6 @@ function checkAccount(slots, declared, requirement, context, signal) {
|
|
|
1143
1767
|
);
|
|
1144
1768
|
});
|
|
1145
1769
|
}
|
|
1146
|
-
var parseSkillLoadFailed = (error) => Schema_exports.decodeUnknownOption(SkillLoadFailed)(error).pipe(
|
|
1147
|
-
Option_exports.map(
|
|
1148
|
-
({ reason, message, status }) => new SkillLoadFailed({
|
|
1149
|
-
reason,
|
|
1150
|
-
...message ? { message } : {},
|
|
1151
|
-
...status === void 0 ? {} : { status }
|
|
1152
|
-
})
|
|
1153
|
-
)
|
|
1154
|
-
);
|
|
1155
|
-
var parseMcpError = (error) => Schema_exports.decodeUnknownOption(McpError)(error).pipe(
|
|
1156
|
-
Option_exports.map(
|
|
1157
|
-
({ phase, reason, status }) => new McpError({ phase, reason, ...status === void 0 ? {} : { status } })
|
|
1158
|
-
)
|
|
1159
|
-
);
|
|
1160
1770
|
var errorStatus = Match_exports.type().pipe(
|
|
1161
1771
|
Match_exports.tagsExhaustive({
|
|
1162
1772
|
ProviderError: () => 502,
|
|
@@ -1196,20 +1806,37 @@ var createAppHandler = (app) => (request, context) => Effect_exports.gen(functio
|
|
|
1196
1806
|
...command.operation === "call" ? { "executor.tool.name": command.tool } : {}
|
|
1197
1807
|
});
|
|
1198
1808
|
let toolError = false;
|
|
1199
|
-
const
|
|
1809
|
+
const emitted = [];
|
|
1810
|
+
const value = yield* dispatch(app, command, context, request.signal, emitted).pipe(
|
|
1200
1811
|
Effect_exports.provideService(ToolResultObservation, {
|
|
1201
1812
|
failed: () => {
|
|
1202
1813
|
toolError = true;
|
|
1203
1814
|
}
|
|
1204
1815
|
}),
|
|
1205
|
-
|
|
1816
|
+
// Name what failed on the span; the bounded message stays in the reply only. The host
|
|
1817
|
+
// records an app's own error names and codes as `unrecognized` (telemetry `app-records`).
|
|
1818
|
+
Effect_exports.tapError(
|
|
1819
|
+
(error) => (error._tag === "HostEvaluationFailed" || error._tag === "HostOperationFailed" || error._tag === "HostDeclarationInvalid") && error.errorName !== void 0 ? Effect_exports.annotateCurrentSpan({
|
|
1820
|
+
"error.type": error.errorName,
|
|
1821
|
+
...error.source === void 0 ? {} : { "executor.failure.source": error.source },
|
|
1822
|
+
...error.code === void 0 ? {} : { "executor.failure.code": error.code }
|
|
1823
|
+
}) : Effect_exports.void
|
|
1824
|
+
),
|
|
1825
|
+
// Tool operations time themselves, dividing their time by who owned the work in progress.
|
|
1826
|
+
// Other operations do not.
|
|
1827
|
+
command.operation === "call" || command.operation === "query" || command.operation === "mutate" ? timedInvocation(command.operation) : Effect_exports.withSpan(`app.${command.operation}`)
|
|
1206
1828
|
);
|
|
1207
1829
|
if (toolError)
|
|
1208
1830
|
yield* Effect_exports.annotateCurrentSpan({
|
|
1209
1831
|
"executor.outcome": "failed",
|
|
1210
1832
|
"error.type": "McpToolError"
|
|
1211
1833
|
});
|
|
1212
|
-
return Response.json({
|
|
1834
|
+
return Response.json({
|
|
1835
|
+
ok: true,
|
|
1836
|
+
value,
|
|
1837
|
+
...toolError ? { toolError: true } : {},
|
|
1838
|
+
...emitted.length === 0 ? {} : { events: emitted }
|
|
1839
|
+
});
|
|
1213
1840
|
}).pipe(
|
|
1214
1841
|
Effect_exports.catch(
|
|
1215
1842
|
(error) => Schema_exports.encodeEffect(HostError)(error).pipe(
|
|
@@ -1220,18 +1847,21 @@ var createAppHandler = (app) => (request, context) => Effect_exports.gen(functio
|
|
|
1220
1847
|
)
|
|
1221
1848
|
),
|
|
1222
1849
|
Effect_exports.catchCause(
|
|
1223
|
-
(cause) => Cause_exports.hasInterrupts(cause) ? Effect_exports.interrupt :
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1850
|
+
(cause) => Cause_exports.hasInterrupts(cause) ? Effect_exports.interrupt : (
|
|
1851
|
+
// The cause can carry any text the app threw; its caller receives that, not the log.
|
|
1852
|
+
Effect_exports.logError("The app's request failed unexpectedly").pipe(
|
|
1853
|
+
Effect_exports.andThen(
|
|
1854
|
+
Schema_exports.encodeEffect(HostError)(
|
|
1855
|
+
declarationInvalid(
|
|
1856
|
+
"The app failed while it was loaded",
|
|
1857
|
+
Cause_exports.squash(cause),
|
|
1858
|
+
accountSecrets(context.accounts)
|
|
1859
|
+
)
|
|
1230
1860
|
)
|
|
1231
|
-
)
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1861
|
+
),
|
|
1862
|
+
Effect_exports.map((error) => Response.json({ ok: false, error }, { status: 500 })),
|
|
1863
|
+
Effect_exports.orDie
|
|
1864
|
+
)
|
|
1235
1865
|
)
|
|
1236
1866
|
)
|
|
1237
1867
|
);
|